@warlock.js/core 5.30.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 (1374) hide show
  1. package/CHANGELOG.md +165 -36
  2. package/README.md +28 -23
  3. package/bin/source-load-hook.mjs +63 -0
  4. package/bin/warlock.js +102 -42
  5. package/esm/application/app.d.mts +3 -3
  6. package/esm/application/app.d.mts.map +1 -1
  7. package/esm/application/application-config-types.d.mts +1 -2
  8. package/esm/application/application-config-types.d.mts.map +1 -1
  9. package/esm/application/application.d.mts +5 -7
  10. package/esm/application/application.d.mts.map +1 -1
  11. package/esm/application/application.mjs +3 -1
  12. package/esm/application/application.mjs.map +1 -1
  13. package/esm/application/boot-signal.d.mts +14 -12
  14. package/esm/application/boot-signal.d.mts.map +1 -1
  15. package/esm/application/index.d.mts +2 -1
  16. package/esm/application/index.mjs +1 -1
  17. package/esm/application/public-url.d.mts +1 -2
  18. package/esm/application/public-url.d.mts.map +1 -1
  19. package/esm/application/roles.d.mts +10 -11
  20. package/esm/application/roles.d.mts.map +1 -1
  21. package/esm/benchmark/benchmark-snapshots.d.mts +1 -3
  22. package/esm/benchmark/benchmark-snapshots.d.mts.map +1 -1
  23. package/esm/benchmark/benchmark.d.mts +1 -3
  24. package/esm/benchmark/benchmark.d.mts.map +1 -1
  25. package/esm/benchmark/channels/console.channel.d.mts +1 -3
  26. package/esm/benchmark/channels/console.channel.d.mts.map +1 -1
  27. package/esm/benchmark/channels/noop.channel.d.mts +1 -3
  28. package/esm/benchmark/channels/noop.channel.d.mts.map +1 -1
  29. package/esm/benchmark/index.mjs +1 -1
  30. package/esm/benchmark/profiler.d.mts +1 -3
  31. package/esm/benchmark/profiler.d.mts.map +1 -1
  32. package/esm/benchmark/profiler.mjs +2 -1
  33. package/esm/benchmark/profiler.mjs.map +1 -1
  34. package/esm/benchmark/types.d.mts +22 -17
  35. package/esm/benchmark/types.d.mts.map +1 -1
  36. package/esm/bootstrap/setup.d.mts +1 -2
  37. package/esm/bootstrap/setup.d.mts.map +1 -1
  38. package/esm/bootstrap.d.mts +1 -2
  39. package/esm/bootstrap.d.mts.map +1 -1
  40. package/esm/cache/database-cache-driver.d.mts +3 -5
  41. package/esm/cache/database-cache-driver.d.mts.map +1 -1
  42. package/esm/cache/database-cache-driver.mjs +1 -1
  43. package/esm/cache/index.d.mts +2 -1
  44. package/esm/cache/index.mjs +1 -1
  45. package/esm/cli/cli-commands.manager.mjs +6 -3
  46. package/esm/cli/cli-commands.manager.mjs.map +1 -1
  47. package/esm/cli/commands/add.command.mjs +4 -2
  48. package/esm/cli/commands/add.command.mjs.map +1 -1
  49. package/esm/cli/commands/agents-md/agents-md-command.action.mjs +70 -0
  50. package/esm/cli/commands/agents-md/agents-md-command.action.mjs.map +1 -0
  51. package/esm/cli/commands/agents-md.command.mjs +38 -0
  52. package/esm/cli/commands/agents-md.command.mjs.map +1 -0
  53. package/esm/cli/commands/board/board-command.action.mjs +279 -0
  54. package/esm/cli/commands/board/board-command.action.mjs.map +1 -0
  55. package/esm/cli/commands/board.command.mjs +78 -0
  56. package/esm/cli/commands/board.command.mjs.map +1 -0
  57. package/esm/cli/commands/build.command.mjs +6 -1
  58. package/esm/cli/commands/build.command.mjs.map +1 -1
  59. package/esm/cli/commands/check/check-command.action.mjs +57 -0
  60. package/esm/cli/commands/check/check-command.action.mjs.map +1 -0
  61. package/esm/cli/commands/check/child-typecheck.mjs +66 -0
  62. package/esm/cli/commands/check/child-typecheck.mjs.map +1 -0
  63. package/esm/cli/commands/check/format-problems.mjs +43 -0
  64. package/esm/cli/commands/check/format-problems.mjs.map +1 -0
  65. package/esm/cli/commands/check/typecheck-command.action.mjs +61 -0
  66. package/esm/cli/commands/check/typecheck-command.action.mjs.map +1 -0
  67. package/esm/cli/commands/check.command.mjs +50 -0
  68. package/esm/cli/commands/check.command.mjs.map +1 -0
  69. package/esm/cli/commands/dev-server.command.mjs +12 -3
  70. package/esm/cli/commands/dev-server.command.mjs.map +1 -1
  71. package/esm/cli/commands/doctor/boot-for-diagnostics.mjs +8 -3
  72. package/esm/cli/commands/doctor/boot-for-diagnostics.mjs.map +1 -1
  73. package/esm/cli/commands/doctor/check.types.d.mts +89 -0
  74. package/esm/cli/commands/doctor/check.types.d.mts.map +1 -0
  75. package/esm/cli/commands/doctor/checks/config.check.mjs +1 -0
  76. package/esm/cli/commands/doctor/checks/config.check.mjs.map +1 -1
  77. package/esm/cli/commands/doctor/checks/connectors.check.mjs +2 -0
  78. package/esm/cli/commands/doctor/checks/connectors.check.mjs.map +1 -1
  79. package/esm/cli/commands/doctor/checks/handler-signature.check.mjs +1 -0
  80. package/esm/cli/commands/doctor/checks/handler-signature.check.mjs.map +1 -1
  81. package/esm/cli/commands/doctor/checks/health.check.mjs +3 -0
  82. package/esm/cli/commands/doctor/checks/health.check.mjs.map +1 -1
  83. package/esm/cli/commands/doctor/checks/jwt-secret.check.mjs +1 -0
  84. package/esm/cli/commands/doctor/checks/jwt-secret.check.mjs.map +1 -1
  85. package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs +23 -27
  86. package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs.map +1 -1
  87. package/esm/cli/commands/doctor/checks/optional-peers.check.mjs +1 -0
  88. package/esm/cli/commands/doctor/checks/optional-peers.check.mjs.map +1 -1
  89. package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs +4 -0
  90. package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs.map +1 -1
  91. package/esm/cli/commands/doctor/checks/routes.check.mjs +3 -0
  92. package/esm/cli/commands/doctor/checks/routes.check.mjs.map +1 -1
  93. package/esm/cli/commands/doctor/doctor-command.action.mjs +15 -6
  94. package/esm/cli/commands/doctor/doctor-command.action.mjs.map +1 -1
  95. package/esm/cli/commands/doctor/format-report.mjs +30 -2
  96. package/esm/cli/commands/doctor/format-report.mjs.map +1 -1
  97. package/esm/cli/commands/doctor.command.mjs +4 -0
  98. package/esm/cli/commands/doctor.command.mjs.map +1 -1
  99. package/esm/cli/commands/explain/explain-command.action.mjs +64 -0
  100. package/esm/cli/commands/explain/explain-command.action.mjs.map +1 -0
  101. package/esm/cli/commands/explain.command.mjs +23 -0
  102. package/esm/cli/commands/explain.command.mjs.map +1 -0
  103. package/esm/cli/commands/generate/generate.command.mjs +124 -124
  104. package/esm/cli/commands/generate/generate.command.mjs.map +1 -1
  105. package/esm/cli/commands/generate/generators/controller.generator.mjs +5 -2
  106. package/esm/cli/commands/generate/generators/controller.generator.mjs.map +1 -1
  107. package/esm/cli/commands/generate/generators/endpoint.generator.mjs +313 -0
  108. package/esm/cli/commands/generate/generators/endpoint.generator.mjs.map +1 -0
  109. package/esm/cli/commands/generate/generators/migration.generator.mjs +1 -1
  110. package/esm/cli/commands/generate/generators/migration.generator.mjs.map +1 -1
  111. package/esm/cli/commands/generate/generators/model.generator.mjs +4 -3
  112. package/esm/cli/commands/generate/generators/model.generator.mjs.map +1 -1
  113. package/esm/cli/commands/generate/generators/repository.generator.mjs +3 -1
  114. package/esm/cli/commands/generate/generators/repository.generator.mjs.map +1 -1
  115. package/esm/cli/commands/generate/generators/resource.generator.mjs +3 -1
  116. package/esm/cli/commands/generate/generators/resource.generator.mjs.map +1 -1
  117. package/esm/cli/commands/generate/generators/service.generator.mjs +3 -1
  118. package/esm/cli/commands/generate/generators/service.generator.mjs.map +1 -1
  119. package/esm/cli/commands/generate/templates/endpoint-stubs.mjs +341 -0
  120. package/esm/cli/commands/generate/templates/endpoint-stubs.mjs.map +1 -0
  121. package/esm/cli/commands/generate/templates/stubs.mjs +19 -6
  122. package/esm/cli/commands/generate/templates/stubs.mjs.map +1 -1
  123. package/esm/cli/commands/generate/utils/endpoint-schema.mjs +136 -0
  124. package/esm/cli/commands/generate/utils/endpoint-schema.mjs.map +1 -0
  125. package/esm/cli/commands/generate/utils/name-parser.mjs +2 -2
  126. package/esm/cli/commands/generate/utils/name-parser.mjs.map +1 -1
  127. package/esm/cli/commands/generate/utils/path-resolver.mjs +1 -1
  128. package/esm/cli/commands/generate/utils/prompt.mjs.map +1 -1
  129. package/esm/cli/commands/generate/utils/writer.mjs +38 -13
  130. package/esm/cli/commands/generate/utils/writer.mjs.map +1 -1
  131. package/esm/cli/commands/inspect/inspect-command.action.mjs +73 -0
  132. package/esm/cli/commands/inspect/inspect-command.action.mjs.map +1 -0
  133. package/esm/cli/commands/inspect.command.mjs +39 -0
  134. package/esm/cli/commands/inspect.command.mjs.map +1 -0
  135. package/esm/cli/commands/issue/collect-environment.mjs +187 -0
  136. package/esm/cli/commands/issue/collect-environment.mjs.map +1 -0
  137. package/esm/cli/commands/issue/issue-command.action.mjs +70 -0
  138. package/esm/cli/commands/issue/issue-command.action.mjs.map +1 -0
  139. package/esm/cli/commands/issue.command.mjs +31 -0
  140. package/esm/cli/commands/issue.command.mjs.map +1 -0
  141. package/esm/cli/commands/mcp/mcp-command.action.mjs +104 -0
  142. package/esm/cli/commands/mcp/mcp-command.action.mjs.map +1 -0
  143. package/esm/cli/commands/mcp.command.mjs +76 -0
  144. package/esm/cli/commands/mcp.command.mjs.map +1 -0
  145. package/esm/cli/commands/openapi-generator.action.mjs +1 -1
  146. package/esm/cli/commands/openapi-generator.action.mjs.map +1 -1
  147. package/esm/cli/commands/openapi-generator.command.mjs.map +1 -1
  148. package/esm/cli/commands/postman-generator.action.mjs +1 -1
  149. package/esm/cli/commands/postman-generator.action.mjs.map +1 -1
  150. package/esm/cli/commands/postman-generator.command.mjs.map +1 -1
  151. package/esm/cli/commands/routes/format-routes-table.mjs +1 -1
  152. package/esm/cli/commands/routes/route-row.mjs +1 -1
  153. package/esm/cli/commands/routes/routes-diff.action.mjs +3 -3
  154. package/esm/cli/commands/routes/routes-diff.action.mjs.map +1 -1
  155. package/esm/cli/commands/test.command.mjs +131 -0
  156. package/esm/cli/commands/test.command.mjs.map +1 -0
  157. package/esm/cli/commands/trace/trace-command.action.mjs +145 -0
  158. package/esm/cli/commands/trace/trace-command.action.mjs.map +1 -0
  159. package/esm/cli/commands/trace.command.mjs +60 -0
  160. package/esm/cli/commands/trace.command.mjs.map +1 -0
  161. package/esm/cli/commands/typecheck.command.mjs +40 -0
  162. package/esm/cli/commands/typecheck.command.mjs.map +1 -0
  163. package/esm/cli/commands/upgrade.command.mjs +46 -0
  164. package/esm/cli/commands/upgrade.command.mjs.map +1 -0
  165. package/esm/cli/commands-loader.mjs +1 -1
  166. package/esm/cli/flush-and-exit.mjs +34 -0
  167. package/esm/cli/flush-and-exit.mjs.map +1 -0
  168. package/esm/cli/framework-cli-commands.mjs +25 -1
  169. package/esm/cli/framework-cli-commands.mjs.map +1 -1
  170. package/esm/cli/parse-cli-args.mjs +3 -2
  171. package/esm/cli/parse-cli-args.mjs.map +1 -1
  172. package/esm/cli/start.d.mts +1 -1
  173. package/esm/cli/string-similarity.mjs +1 -1
  174. package/esm/commands/cli-command.d.mts +2 -4
  175. package/esm/commands/cli-command.d.mts.map +1 -1
  176. package/esm/commands/index.d.mts +2 -1
  177. package/esm/commands/index.mjs +1 -1
  178. package/esm/commands/types.d.mts +8 -8
  179. package/esm/commands/types.d.mts.map +1 -1
  180. package/esm/config/config-getter.d.mts +2 -3
  181. package/esm/config/config-getter.d.mts.map +1 -1
  182. package/esm/config/config-getter.mjs +5 -5
  183. package/esm/config/config-getter.mjs.map +1 -1
  184. package/esm/config/config-handlers.d.mts +1 -3
  185. package/esm/config/config-handlers.d.mts.map +1 -1
  186. package/esm/config/config-loader.d.mts +1 -2
  187. package/esm/config/config-loader.d.mts.map +1 -1
  188. package/esm/config/config-loader.mjs +35 -14
  189. package/esm/config/config-loader.mjs.map +1 -1
  190. package/esm/config/config-manager.mjs +1 -1
  191. package/esm/config/config-schema.d.mts +70 -0
  192. package/esm/config/config-schema.d.mts.map +1 -0
  193. package/esm/config/config-schema.mjs +77 -0
  194. package/esm/config/config-schema.mjs.map +1 -0
  195. package/esm/config/config-setter.d.mts +2 -4
  196. package/esm/config/config-setter.d.mts.map +1 -1
  197. package/esm/config/config-setter.mjs +2 -2
  198. package/esm/config/config-setter.mjs.map +1 -1
  199. package/esm/config/config-special-handlers.d.mts +2 -4
  200. package/esm/config/config-special-handlers.d.mts.map +1 -1
  201. package/esm/config/index.d.mts +7 -0
  202. package/esm/config/index.mjs +2 -1
  203. package/esm/config/types.d.mts +4 -5
  204. package/esm/config/types.d.mts.map +1 -1
  205. package/esm/connectors/access-connector.d.mts +1 -3
  206. package/esm/connectors/access-connector.d.mts.map +1 -1
  207. package/esm/connectors/access-connector.mjs +2 -2
  208. package/esm/connectors/access-connector.mjs.map +1 -1
  209. package/esm/connectors/ai-connector.d.mts +1 -3
  210. package/esm/connectors/ai-connector.d.mts.map +1 -1
  211. package/esm/connectors/ai-connector.mjs +2 -2
  212. package/esm/connectors/ai-connector.mjs.map +1 -1
  213. package/esm/connectors/assert-no-reserved-connector-names.d.mts +1 -3
  214. package/esm/connectors/assert-no-reserved-connector-names.d.mts.map +1 -1
  215. package/esm/connectors/assert-no-reserved-connector-names.mjs +2 -1
  216. package/esm/connectors/assert-no-reserved-connector-names.mjs.map +1 -1
  217. package/esm/connectors/assert-unique-connector-names.d.mts +1 -3
  218. package/esm/connectors/assert-unique-connector-names.d.mts.map +1 -1
  219. package/esm/connectors/assert-unique-connector-names.mjs +26 -1
  220. package/esm/connectors/assert-unique-connector-names.mjs.map +1 -1
  221. package/esm/connectors/base-connector.d.mts +1 -3
  222. package/esm/connectors/base-connector.d.mts.map +1 -1
  223. package/esm/connectors/cache-connector.d.mts +1 -3
  224. package/esm/connectors/cache-connector.d.mts.map +1 -1
  225. package/esm/connectors/cache-connector.mjs +3 -3
  226. package/esm/connectors/cache-connector.mjs.map +1 -1
  227. package/esm/connectors/connectors-manager.d.mts +2 -4
  228. package/esm/connectors/connectors-manager.d.mts.map +1 -1
  229. package/esm/connectors/connectors-manager.mjs +2 -2
  230. package/esm/connectors/connectors-manager.mjs.map +1 -1
  231. package/esm/connectors/database-connector.d.mts +1 -3
  232. package/esm/connectors/database-connector.d.mts.map +1 -1
  233. package/esm/connectors/database-connector.mjs +2 -2
  234. package/esm/connectors/database-connector.mjs.map +1 -1
  235. package/esm/connectors/describe-server-address.mjs +4 -4
  236. package/esm/connectors/describe-server-address.mjs.map +1 -1
  237. package/esm/connectors/herald-connector.d.mts +1 -3
  238. package/esm/connectors/herald-connector.d.mts.map +1 -1
  239. package/esm/connectors/herald-connector.mjs +2 -2
  240. package/esm/connectors/herald-connector.mjs.map +1 -1
  241. package/esm/connectors/http-connector.d.mts +1 -3
  242. package/esm/connectors/http-connector.d.mts.map +1 -1
  243. package/esm/connectors/http-connector.mjs +11 -9
  244. package/esm/connectors/http-connector.mjs.map +1 -1
  245. package/esm/connectors/index.d.mts +2 -1
  246. package/esm/connectors/index.mjs +1 -1
  247. package/esm/connectors/logger-connector.d.mts +1 -3
  248. package/esm/connectors/logger-connector.d.mts.map +1 -1
  249. package/esm/connectors/logger-connector.mjs +2 -2
  250. package/esm/connectors/logger-connector.mjs.map +1 -1
  251. package/esm/connectors/mail-connector.d.mts +1 -3
  252. package/esm/connectors/mail-connector.d.mts.map +1 -1
  253. package/esm/connectors/mail-connector.mjs +2 -2
  254. package/esm/connectors/mail-connector.mjs.map +1 -1
  255. package/esm/connectors/notifications-connector.d.mts +1 -3
  256. package/esm/connectors/notifications-connector.d.mts.map +1 -1
  257. package/esm/connectors/notifications-connector.mjs +2 -2
  258. package/esm/connectors/notifications-connector.mjs.map +1 -1
  259. package/esm/connectors/register-configured-connectors.d.mts +2 -4
  260. package/esm/connectors/register-configured-connectors.d.mts.map +1 -1
  261. package/esm/connectors/single-server-warnings.mjs.map +1 -1
  262. package/esm/connectors/socket-connector.d.mts +1 -3
  263. package/esm/connectors/socket-connector.d.mts.map +1 -1
  264. package/esm/connectors/socket-connector.mjs +12 -10
  265. package/esm/connectors/socket-connector.mjs.map +1 -1
  266. package/esm/connectors/storage.connector.d.mts +1 -3
  267. package/esm/connectors/storage.connector.d.mts.map +1 -1
  268. package/esm/connectors/storage.connector.mjs +2 -2
  269. package/esm/connectors/storage.connector.mjs.map +1 -1
  270. package/esm/connectors/types.d.mts +17 -14
  271. package/esm/connectors/types.d.mts.map +1 -1
  272. package/esm/container/container-instance-registry.mjs.map +1 -1
  273. package/esm/container/development-app-modules.d.mts +7 -5
  274. package/esm/container/development-app-modules.d.mts.map +1 -1
  275. package/esm/container/development-model-modules.d.mts +6 -5
  276. package/esm/container/development-model-modules.d.mts.map +1 -1
  277. package/esm/container/index.d.mts +4 -4
  278. package/esm/container/index.d.mts.map +1 -1
  279. package/esm/container/index.mjs.map +1 -1
  280. package/esm/database/index.d.mts +3 -1
  281. package/esm/database/index.mjs +1 -1
  282. package/esm/database/migrate-action.mjs +1 -1
  283. package/esm/database/migrate-action.mjs.map +1 -1
  284. package/esm/database/models/database-log/database-log.d.mts +2 -31
  285. package/esm/database/models/database-log/database-log.d.mts.map +1 -1
  286. package/esm/database/models/database-log/index.d.mts +2 -1
  287. package/esm/database/models/database-log/index.mjs +1 -1
  288. package/esm/database/seed-command-action.mjs +1 -1
  289. package/esm/database/seeds/seeder.d.mts +2 -4
  290. package/esm/database/seeds/seeder.d.mts.map +1 -1
  291. package/esm/database/seeds/seeder.errors.d.mts +6 -3
  292. package/esm/database/seeds/seeder.errors.d.mts.map +1 -1
  293. package/esm/database/seeds/seeder.errors.mjs +2 -0
  294. package/esm/database/seeds/seeder.errors.mjs.map +1 -1
  295. package/esm/database/seeds/seeders.manager.mjs +2 -1
  296. package/esm/database/seeds/seeders.manager.mjs.map +1 -1
  297. package/esm/database/seeds/types.d.mts +7 -8
  298. package/esm/database/seeds/types.d.mts.map +1 -1
  299. package/esm/database/utils.d.mts +4 -5
  300. package/esm/database/utils.d.mts.map +1 -1
  301. package/esm/dev-server/app-module-registry.mjs +1 -1
  302. package/esm/dev-server/boot-precondition-error.mjs +1 -0
  303. package/esm/dev-server/boot-precondition-error.mjs.map +1 -1
  304. package/esm/dev-server/create-worker.mjs +17 -9
  305. package/esm/dev-server/create-worker.mjs.map +1 -1
  306. package/esm/dev-server/dependency-graph.d.mts +1 -3
  307. package/esm/dev-server/dependency-graph.d.mts.map +1 -1
  308. package/esm/dev-server/dependency-graph.mjs +1 -1
  309. package/esm/dev-server/dependency-graph.mjs.map +1 -1
  310. package/esm/dev-server/dev-agent-tooling.mjs +135 -0
  311. package/esm/dev-server/dev-agent-tooling.mjs.map +1 -0
  312. package/esm/dev-server/dev-logger.mjs.map +1 -1
  313. package/esm/dev-server/development-server.mjs +8 -0
  314. package/esm/dev-server/development-server.mjs.map +1 -1
  315. package/esm/dev-server/extract-translation-keys.mjs +16 -17
  316. package/esm/dev-server/extract-translation-keys.mjs.map +1 -1
  317. package/esm/dev-server/file-manager.d.mts +3 -7
  318. package/esm/dev-server/file-manager.d.mts.map +1 -1
  319. package/esm/dev-server/file-operations.d.mts +1 -3
  320. package/esm/dev-server/file-operations.d.mts.map +1 -1
  321. package/esm/dev-server/files-orchestrator.mjs +4 -5
  322. package/esm/dev-server/files-orchestrator.mjs.map +1 -1
  323. package/esm/dev-server/files-watcher.mjs +12 -11
  324. package/esm/dev-server/files-watcher.mjs.map +1 -1
  325. package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs +2 -3
  326. package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs.map +1 -1
  327. package/esm/dev-server/health-checker/checkers/oxlint-health-checker.mjs +33 -0
  328. package/esm/dev-server/health-checker/checkers/oxlint-health-checker.mjs.map +1 -0
  329. package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs +36 -115
  330. package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs.map +1 -1
  331. package/esm/dev-server/health-checker/default-health-checkers.mjs +31 -0
  332. package/esm/dev-server/health-checker/default-health-checkers.mjs.map +1 -0
  333. package/esm/dev-server/health-checker/file-health-checker.contract.d.mts +12 -6
  334. package/esm/dev-server/health-checker/file-health-checker.contract.d.mts.map +1 -1
  335. package/esm/dev-server/health-checker/file-health-result.d.mts +2 -2
  336. package/esm/dev-server/health-checker/file-health-result.d.mts.map +1 -1
  337. package/esm/dev-server/health-checker/files-healthcare.manager.mjs +16 -4
  338. package/esm/dev-server/health-checker/files-healthcare.manager.mjs.map +1 -1
  339. package/esm/dev-server/health-checker/oxlint-runner.mjs +303 -0
  340. package/esm/dev-server/health-checker/oxlint-runner.mjs.map +1 -0
  341. package/esm/dev-server/health-checker/workers/eslint-health.worker.d.mts +1 -1
  342. package/esm/dev-server/health-checker/workers/oxlint-health.worker.d.mts +1 -0
  343. package/esm/dev-server/health-checker/workers/oxlint-health.worker.mjs +42 -0
  344. package/esm/dev-server/health-checker/workers/oxlint-health.worker.mjs.map +1 -0
  345. package/esm/dev-server/health-checker/workers/ts-health.worker.d.mts +1 -1
  346. package/esm/dev-server/health-checker/workers/ts-health.worker.mjs +40 -174
  347. package/esm/dev-server/health-checker/workers/ts-health.worker.mjs.map +1 -1
  348. package/esm/dev-server/loader/hook-thread.d.mts +4 -8
  349. package/esm/dev-server/loader/hook-thread.d.mts.map +1 -1
  350. package/esm/dev-server/loader/load-hook.d.mts +10 -6
  351. package/esm/dev-server/loader/load-hook.d.mts.map +1 -1
  352. package/esm/dev-server/loader/load-hook.mjs +4 -3
  353. package/esm/dev-server/loader/load-hook.mjs.map +1 -1
  354. package/esm/dev-server/loader/loader-port-acks.mjs +1 -1
  355. package/esm/dev-server/loader/loader-port-acks.mjs.map +1 -1
  356. package/esm/dev-server/loader/own-resolver.mjs +1 -1
  357. package/esm/dev-server/loader/register-loader.mjs +4 -3
  358. package/esm/dev-server/loader/register-loader.mjs.map +1 -1
  359. package/esm/dev-server/loader/resolve-hook.d.mts +2 -2
  360. package/esm/dev-server/loader/resolve-hook.d.mts.map +1 -1
  361. package/esm/dev-server/loader/resolve-hook.mjs +3 -2
  362. package/esm/dev-server/loader/resolve-hook.mjs.map +1 -1
  363. package/esm/dev-server/loader/transpile-cache.mjs +3 -2
  364. package/esm/dev-server/loader/transpile-cache.mjs.map +1 -1
  365. package/esm/dev-server/manifest-manager.d.mts +1 -3
  366. package/esm/dev-server/manifest-manager.d.mts.map +1 -1
  367. package/esm/dev-server/model-module-registry.mjs +3 -3
  368. package/esm/dev-server/model-module-registry.mjs.map +1 -1
  369. package/esm/dev-server/model-resource-typings.mjs +40 -47
  370. package/esm/dev-server/model-resource-typings.mjs.map +1 -1
  371. package/esm/dev-server/module-loader.mjs +3 -2
  372. package/esm/dev-server/module-loader.mjs.map +1 -1
  373. package/esm/dev-server/package-json-manager.mjs +1 -1
  374. package/esm/dev-server/parse-imports.mjs +7 -39
  375. package/esm/dev-server/parse-imports.mjs.map +1 -1
  376. package/esm/dev-server/read-config-ast.mjs +3 -33
  377. package/esm/dev-server/read-config-ast.mjs.map +1 -1
  378. package/esm/dev-server/ready-block.mjs +1 -1
  379. package/esm/dev-server/route-types-publisher.mjs +1 -1
  380. package/esm/dev-server/shortcuts.mjs +1 -1
  381. package/esm/dev-server/special-files-collector.d.mts +2 -4
  382. package/esm/dev-server/special-files-collector.d.mts.map +1 -1
  383. package/esm/dev-server/start-development-server.mjs.map +1 -1
  384. package/esm/dev-server/supervisor.mjs +1 -1
  385. package/esm/dev-server/translation-keys-sources.mjs +1 -1
  386. package/esm/dev-server/translation-keys-sources.mjs.map +1 -1
  387. package/esm/dev-server/tsconfig-manager.mjs +3 -3
  388. package/esm/dev-server/tsconfig-manager.mjs.map +1 -1
  389. package/esm/dev-server/type-generator.mjs +31 -38
  390. package/esm/dev-server/type-generator.mjs.map +1 -1
  391. package/esm/dev-server/types.d.mts +3 -4
  392. package/esm/dev-server/types.d.mts.map +1 -1
  393. package/esm/dev-server/update-check-cache.mjs +2 -2
  394. package/esm/dev-server/update-check-cache.mjs.map +1 -1
  395. package/esm/encryption/encrypt.d.mts +2 -3
  396. package/esm/encryption/encrypt.d.mts.map +1 -1
  397. package/esm/encryption/hash.d.mts +1 -2
  398. package/esm/encryption/hash.d.mts.map +1 -1
  399. package/esm/encryption/index.mjs +1 -1
  400. package/esm/encryption/password.d.mts +2 -3
  401. package/esm/encryption/password.d.mts.map +1 -1
  402. package/esm/encryption/types.d.mts +2 -3
  403. package/esm/encryption/types.d.mts.map +1 -1
  404. package/esm/errors/container-key-missing-error.mjs +1 -0
  405. package/esm/errors/container-key-missing-error.mjs.map +1 -1
  406. package/esm/errors/error-codes.d.mts +660 -0
  407. package/esm/errors/error-codes.d.mts.map +1 -0
  408. package/esm/errors/error-codes.mjs +634 -0
  409. package/esm/errors/error-codes.mjs.map +1 -0
  410. package/esm/errors/esbuild-binary-missing-error.mjs +1 -0
  411. package/esm/errors/esbuild-binary-missing-error.mjs.map +1 -1
  412. package/esm/errors/index.d.mts +3 -1
  413. package/esm/errors/index.mjs +3 -1
  414. package/esm/errors/unknown-locale-error.mjs +1 -0
  415. package/esm/errors/unknown-locale-error.mjs.map +1 -1
  416. package/esm/errors/warlock-error.d.mts +21 -0
  417. package/esm/errors/warlock-error.d.mts.map +1 -0
  418. package/esm/errors/warlock-error.mjs +22 -0
  419. package/esm/errors/warlock-error.mjs.map +1 -0
  420. package/esm/generations/add-command.action.mjs +22 -5
  421. package/esm/generations/add-command.action.mjs.map +1 -1
  422. package/esm/generations/features/access.feature.mjs +1 -1
  423. package/esm/generations/features/access.feature.mjs.map +1 -1
  424. package/esm/generations/features/bull-board.feature.mjs +3 -2
  425. package/esm/generations/features/bull-board.feature.mjs.map +1 -1
  426. package/esm/generations/features/mysql.feature.mjs.map +1 -1
  427. package/esm/generations/features/notifications.feature.mjs +7 -3
  428. package/esm/generations/features/notifications.feature.mjs.map +1 -1
  429. package/esm/generations/features/queue.feature.mjs +1 -1
  430. package/esm/generations/features/queue.feature.mjs.map +1 -1
  431. package/esm/generations/features/react-email.feature.mjs +1 -1
  432. package/esm/generations/features/react-email.feature.mjs.map +1 -1
  433. package/esm/generations/features/shadcn.feature.mjs +1 -1
  434. package/esm/generations/features/shadcn.feature.mjs.map +1 -1
  435. package/esm/generations/features/shared/link-ai-package-import.mjs +1 -1
  436. package/esm/generations/features/shared/link-ai-package-import.mjs.map +1 -1
  437. package/esm/generations/features/shared/merge-web-sitemap-config.mjs +16 -23
  438. package/esm/generations/features/shared/merge-web-sitemap-config.mjs.map +1 -1
  439. package/esm/generations/features/shared/patch-tsconfig-include.mjs +2 -2
  440. package/esm/generations/features/shared/patch-tsconfig-include.mjs.map +1 -1
  441. package/esm/generations/features/shared/relocate-conflicting-home-route.mjs +2 -2
  442. package/esm/generations/features/shared/relocate-conflicting-home-route.mjs.map +1 -1
  443. package/esm/generations/features/sitemap.feature.mjs +3 -2
  444. package/esm/generations/features/sitemap.feature.mjs.map +1 -1
  445. package/esm/generations/features/tailwind.feature.mjs +1 -1
  446. package/esm/generations/features/tailwind.feature.mjs.map +1 -1
  447. package/esm/generations/features/test.feature.mjs +11 -6
  448. package/esm/generations/features/test.feature.mjs.map +1 -1
  449. package/esm/generations/features/web.feature.mjs +1 -1
  450. package/esm/generations/features/web.feature.mjs.map +1 -1
  451. package/esm/generations/generation-fs.mjs +73 -0
  452. package/esm/generations/generation-fs.mjs.map +1 -0
  453. package/esm/generations/generation-run.mjs +185 -0
  454. package/esm/generations/generation-run.mjs.map +1 -0
  455. package/esm/generations/stubs.mjs +156 -14
  456. package/esm/generations/stubs.mjs.map +1 -1
  457. package/esm/http/boot-port-preflight.d.mts +4 -5
  458. package/esm/http/boot-port-preflight.d.mts.map +1 -1
  459. package/esm/http/boot-port-preflight.mjs +2 -2
  460. package/esm/http/boot-port-preflight.mjs.map +1 -1
  461. package/esm/http/bounded-stream-queue.d.mts +10 -0
  462. package/esm/http/bounded-stream-queue.d.mts.map +1 -0
  463. package/esm/http/bounded-stream-queue.mjs +97 -0
  464. package/esm/http/bounded-stream-queue.mjs.map +1 -0
  465. package/esm/http/build-cors-options.mjs +2 -2
  466. package/esm/http/build-cors-options.mjs.map +1 -1
  467. package/esm/http/build-rate-limit-options.d.mts +15 -3
  468. package/esm/http/build-rate-limit-options.d.mts.map +1 -1
  469. package/esm/http/build-rate-limit-options.mjs +1 -1
  470. package/esm/http/build-rate-limit-options.mjs.map +1 -1
  471. package/esm/http/conditional-request.d.mts +87 -0
  472. package/esm/http/conditional-request.d.mts.map +1 -0
  473. package/esm/http/conditional-request.mjs +121 -0
  474. package/esm/http/conditional-request.mjs.map +1 -0
  475. package/esm/http/config.d.mts +2 -4
  476. package/esm/http/config.d.mts.map +1 -1
  477. package/esm/http/config.mjs +2 -2
  478. package/esm/http/config.mjs.map +1 -1
  479. package/esm/http/context/request-context.d.mts +6 -7
  480. package/esm/http/context/request-context.d.mts.map +1 -1
  481. package/esm/http/context/request-memo.d.mts +1 -2
  482. package/esm/http/context/request-memo.d.mts.map +1 -1
  483. package/esm/http/createHttpApplication.d.mts +2 -3
  484. package/esm/http/createHttpApplication.d.mts.map +1 -1
  485. package/esm/http/createHttpApplication.mjs +2 -2
  486. package/esm/http/createHttpApplication.mjs.map +1 -1
  487. package/esm/http/csp.d.mts +12 -12
  488. package/esm/http/csp.d.mts.map +1 -1
  489. package/esm/http/csp.mjs +3 -2
  490. package/esm/http/csp.mjs.map +1 -1
  491. package/esm/http/csrf-default-guard.d.mts +2 -4
  492. package/esm/http/csrf-default-guard.d.mts.map +1 -1
  493. package/esm/http/csrf-default-guard.mjs +1 -1
  494. package/esm/http/csrf-default-guard.mjs.map +1 -1
  495. package/esm/http/csrf-origin-policy.d.mts +7 -9
  496. package/esm/http/csrf-origin-policy.d.mts.map +1 -1
  497. package/esm/http/csrf-origin-policy.mjs +2 -2
  498. package/esm/http/csrf-origin-policy.mjs.map +1 -1
  499. package/esm/http/database/RequestLog.d.mts +26 -87
  500. package/esm/http/database/RequestLog.d.mts.map +1 -1
  501. package/esm/http/error-codes.d.mts +1 -2
  502. package/esm/http/error-codes.d.mts.map +1 -1
  503. package/esm/http/error-mapper.d.mts +2 -4
  504. package/esm/http/error-mapper.d.mts.map +1 -1
  505. package/esm/http/error-mapper.mjs +2 -2
  506. package/esm/http/error-mapper.mjs.map +1 -1
  507. package/esm/http/errors/errors.d.mts +30 -29
  508. package/esm/http/errors/errors.d.mts.map +1 -1
  509. package/esm/http/errors/errors.mjs +1 -0
  510. package/esm/http/errors/errors.mjs.map +1 -1
  511. package/esm/http/escape-header-value.d.mts +17 -0
  512. package/esm/http/escape-header-value.d.mts.map +1 -0
  513. package/esm/http/escape-header-value.mjs +27 -0
  514. package/esm/http/escape-header-value.mjs.map +1 -0
  515. package/esm/http/events.d.mts +2 -4
  516. package/esm/http/events.d.mts.map +1 -1
  517. package/esm/http/flush-pending-cookies.mjs.map +1 -1
  518. package/esm/http/health.d.mts +4 -4
  519. package/esm/http/health.d.mts.map +1 -1
  520. package/esm/http/index.d.mts +9 -3
  521. package/esm/http/index.mjs +5 -2
  522. package/esm/http/lazy-static.mjs +194 -0
  523. package/esm/http/lazy-static.mjs.map +1 -0
  524. package/esm/http/middleware/cache-response-middleware.d.mts +2 -4
  525. package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
  526. package/esm/http/middleware/concurrency-limit.middleware.d.mts +3 -3
  527. package/esm/http/middleware/concurrency-limit.middleware.d.mts.map +1 -1
  528. package/esm/http/middleware/idempotency.middleware.d.mts +3 -3
  529. package/esm/http/middleware/idempotency.middleware.d.mts.map +1 -1
  530. package/esm/http/middleware/idempotency.middleware.mjs +6 -6
  531. package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
  532. package/esm/http/middleware/index.d.mts +3 -1
  533. package/esm/http/middleware/index.mjs +1 -1
  534. package/esm/http/middleware/inject-request-context.d.mts +2 -4
  535. package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
  536. package/esm/http/middleware/inject-request-context.mjs +3 -3
  537. package/esm/http/middleware/inject-request-context.mjs.map +1 -1
  538. package/esm/http/middleware/ip-filter.middleware.d.mts +3 -3
  539. package/esm/http/middleware/ip-filter.middleware.d.mts.map +1 -1
  540. package/esm/http/middleware/maintenance.middleware.d.mts +3 -3
  541. package/esm/http/middleware/maintenance.middleware.d.mts.map +1 -1
  542. package/esm/http/middleware/maintenance.middleware.mjs +4 -4
  543. package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
  544. package/esm/http/middleware/max-body-size.middleware.d.mts +2 -2
  545. package/esm/http/middleware/max-body-size.middleware.d.mts.map +1 -1
  546. package/esm/http/middleware/middleware-list.d.mts +1 -3
  547. package/esm/http/middleware/middleware-list.d.mts.map +1 -1
  548. package/esm/http/middleware/rate-limit.middleware.d.mts +3 -3
  549. package/esm/http/middleware/rate-limit.middleware.d.mts.map +1 -1
  550. package/esm/http/middleware/rate-limit.middleware.mjs +2 -2
  551. package/esm/http/middleware/rate-limit.middleware.mjs.map +1 -1
  552. package/esm/http/middleware/utils/cidr-match.d.mts +2 -3
  553. package/esm/http/middleware/utils/cidr-match.d.mts.map +1 -1
  554. package/esm/http/middleware/utils/idempotency-key.d.mts +3 -5
  555. package/esm/http/middleware/utils/idempotency-key.d.mts.map +1 -1
  556. package/esm/http/middleware/utils/index.d.mts +2 -1
  557. package/esm/http/middleware/utils/parse-size.d.mts +1 -2
  558. package/esm/http/middleware/utils/parse-size.d.mts.map +1 -1
  559. package/esm/http/middleware/utils/parse-size.mjs +2 -2
  560. package/esm/http/middleware/utils/parse-size.mjs.map +1 -1
  561. package/esm/http/plugins.d.mts +2 -4
  562. package/esm/http/plugins.d.mts.map +1 -1
  563. package/esm/http/plugins.mjs +17 -14
  564. package/esm/http/plugins.mjs.map +1 -1
  565. package/esm/http/port-preflight.d.mts +3 -4
  566. package/esm/http/port-preflight.d.mts.map +1 -1
  567. package/esm/http/rate-limit-cache-store.mjs +6 -4
  568. package/esm/http/rate-limit-cache-store.mjs.map +1 -1
  569. package/esm/http/ready-report.d.mts +15 -10
  570. package/esm/http/ready-report.d.mts.map +1 -1
  571. package/esm/http/request-controller.d.mts +1 -3
  572. package/esm/http/request-controller.d.mts.map +1 -1
  573. package/esm/http/request-log-snapshot.d.mts +26 -15
  574. package/esm/http/request-log-snapshot.d.mts.map +1 -1
  575. package/esm/http/request-log-snapshot.mjs +85 -6
  576. package/esm/http/request-log-snapshot.mjs.map +1 -1
  577. package/esm/http/request.d.mts +6 -5
  578. package/esm/http/request.d.mts.map +1 -1
  579. package/esm/http/request.mjs +13 -11
  580. package/esm/http/request.mjs.map +1 -1
  581. package/esm/http/response.d.mts +23 -12
  582. package/esm/http/response.d.mts.map +1 -1
  583. package/esm/http/response.mjs +169 -81
  584. package/esm/http/response.mjs.map +1 -1
  585. package/esm/http/safe-redirect.d.mts +50 -0
  586. package/esm/http/safe-redirect.d.mts.map +1 -0
  587. package/esm/http/safe-redirect.mjs +80 -0
  588. package/esm/http/safe-redirect.mjs.map +1 -0
  589. package/esm/http/serialized.d.mts +12 -13
  590. package/esm/http/serialized.d.mts.map +1 -1
  591. package/esm/http/server-rebuilt.d.mts +3 -5
  592. package/esm/http/server-rebuilt.d.mts.map +1 -1
  593. package/esm/http/server.d.mts +11 -9
  594. package/esm/http/server.d.mts.map +1 -1
  595. package/esm/http/server.mjs +17 -7
  596. package/esm/http/server.mjs.map +1 -1
  597. package/esm/http/stream-react-response.d.mts +7 -7
  598. package/esm/http/stream-react-response.d.mts.map +1 -1
  599. package/esm/http/stream-transport.mjs +4 -2
  600. package/esm/http/stream-transport.mjs.map +1 -1
  601. package/esm/http/tracing/index.mjs +1 -1
  602. package/esm/http/tracing/trace-id.d.mts +2 -3
  603. package/esm/http/tracing/trace-id.d.mts.map +1 -1
  604. package/esm/http/tracing/tracing-dispatcher.d.mts +10 -11
  605. package/esm/http/tracing/tracing-dispatcher.d.mts.map +1 -1
  606. package/esm/http/tracing/tracing-dispatcher.mjs +2 -2
  607. package/esm/http/tracing/tracing-dispatcher.mjs.map +1 -1
  608. package/esm/http/tracing/tracing.type.d.mts +11 -9
  609. package/esm/http/tracing/tracing.type.d.mts.map +1 -1
  610. package/esm/http/types.d.mts +78 -39
  611. package/esm/http/types.d.mts.map +1 -1
  612. package/esm/http/uploaded-file.d.mts +6 -5
  613. package/esm/http/uploaded-file.d.mts.map +1 -1
  614. package/esm/http/uploads/generate-image-variant.mjs +1 -1
  615. package/esm/http/uploads/generate-image-variants.d.mts +13 -10
  616. package/esm/http/uploads/generate-image-variants.d.mts.map +1 -1
  617. package/esm/http/uploads/generate-image-variants.mjs +62 -25
  618. package/esm/http/uploads/generate-image-variants.mjs.map +1 -1
  619. package/esm/http/uploads/image-variant-cache-entries.mjs +78 -0
  620. package/esm/http/uploads/image-variant-cache-entries.mjs.map +1 -0
  621. package/esm/http/uploads/image-variant-cache.mjs +72 -30
  622. package/esm/http/uploads/image-variant-cache.mjs.map +1 -1
  623. package/esm/http/uploads/image-variant-types.d.mts +9 -9
  624. package/esm/http/uploads/image-variant-types.d.mts.map +1 -1
  625. package/esm/http/uploads/image-variants-config-error.d.mts +4 -3
  626. package/esm/http/uploads/image-variants-config-error.d.mts.map +1 -1
  627. package/esm/http/uploads/image-variants-config-error.mjs +3 -2
  628. package/esm/http/uploads/image-variants-config-error.mjs.map +1 -1
  629. package/esm/http/uploads/index.d.mts +2 -1
  630. package/esm/http/uploads/index.mjs +1 -1
  631. package/esm/http/uploads/load-variant-source.mjs +1 -1
  632. package/esm/http/uploads/load-variant-source.mjs.map +1 -1
  633. package/esm/http/uploads/parse-uploaded-file-query.mjs +1 -1
  634. package/esm/http/uploads/parse-uploaded-file-query.mjs.map +1 -1
  635. package/esm/http/uploads/purge-image-variants.d.mts +9 -6
  636. package/esm/http/uploads/purge-image-variants.d.mts.map +1 -1
  637. package/esm/http/uploads/purge-image-variants.mjs +16 -16
  638. package/esm/http/uploads/purge-image-variants.mjs.map +1 -1
  639. package/esm/http/uploads/remote-variant-source.mjs +115 -0
  640. package/esm/http/uploads/remote-variant-source.mjs.map +1 -0
  641. package/esm/http/uploads/resolve-image-variant.d.mts +6 -9
  642. package/esm/http/uploads/resolve-image-variant.d.mts.map +1 -1
  643. package/esm/http/uploads/resolve-image-variant.mjs +10 -18
  644. package/esm/http/uploads/resolve-image-variant.mjs.map +1 -1
  645. package/esm/http/uploads/resolve-image-variants-config.mjs +7 -5
  646. package/esm/http/uploads/resolve-image-variants-config.mjs.map +1 -1
  647. package/esm/http/uploads/resolve-original-content-type.mjs +1 -1
  648. package/esm/http/uploads/resolve-original-content-type.mjs.map +1 -1
  649. package/esm/http/uploads/resolve-remote-image-variant.mjs +89 -0
  650. package/esm/http/uploads/resolve-remote-image-variant.mjs.map +1 -0
  651. package/esm/http/uploads/trim-image-variant-cache.mjs +193 -0
  652. package/esm/http/uploads/trim-image-variant-cache.mjs.map +1 -0
  653. package/esm/http/uploads/uploaded-file.controller.d.mts +9 -6
  654. package/esm/http/uploads/uploaded-file.controller.d.mts.map +1 -1
  655. package/esm/http/uploads/uploaded-file.controller.mjs +18 -9
  656. package/esm/http/uploads/uploaded-file.controller.mjs.map +1 -1
  657. package/esm/http/uploads/variant-cache-key.mjs +2 -2
  658. package/esm/http/uploads-config.d.mts +2 -4
  659. package/esm/http/uploads-config.d.mts.map +1 -1
  660. package/esm/http/uploads-types.d.mts +22 -16
  661. package/esm/http/uploads-types.d.mts.map +1 -1
  662. package/esm/http/xmlable.d.mts +1 -2
  663. package/esm/http/xmlable.d.mts.map +1 -1
  664. package/esm/image/image.d.mts +6 -7
  665. package/esm/image/image.d.mts.map +1 -1
  666. package/esm/image/image.mjs.map +1 -1
  667. package/esm/image/index.d.mts +2 -1
  668. package/esm/image/index.mjs +1 -1
  669. package/esm/index.d.mts +38 -6
  670. package/esm/index.mjs +14 -3
  671. package/esm/loader/app-module-importer.d.mts +1 -2
  672. package/esm/loader/app-module-importer.d.mts.map +1 -1
  673. package/esm/localization/index.mjs +1 -1
  674. package/esm/localization/parse-locale-dictionary.d.mts +6 -5
  675. package/esm/localization/parse-locale-dictionary.d.mts.map +1 -1
  676. package/esm/localization/parse-locale-dictionary.mjs +2 -1
  677. package/esm/localization/parse-locale-dictionary.mjs.map +1 -1
  678. package/esm/localization/register-locale-dictionary.d.mts +3 -4
  679. package/esm/localization/register-locale-dictionary.d.mts.map +1 -1
  680. package/esm/localization/register-locale-dictionary.mjs +2 -2
  681. package/esm/localization/register-locale-dictionary.mjs.map +1 -1
  682. package/esm/logger/fatal-visibility.d.mts +1 -2
  683. package/esm/logger/fatal-visibility.d.mts.map +1 -1
  684. package/esm/logger/index.d.mts +2 -1
  685. package/esm/logger/index.mjs +1 -1
  686. package/esm/logger/logger.d.mts +1 -3
  687. package/esm/logger/logger.d.mts.map +1 -1
  688. package/esm/logger/types.d.mts +2 -3
  689. package/esm/logger/types.d.mts.map +1 -1
  690. package/esm/mail/config.d.mts +21 -12
  691. package/esm/mail/config.d.mts.map +1 -1
  692. package/esm/mail/config.mjs +16 -1
  693. package/esm/mail/config.mjs.map +1 -1
  694. package/esm/mail/events.d.mts +4 -6
  695. package/esm/mail/events.d.mts.map +1 -1
  696. package/esm/mail/index.d.mts +3 -2
  697. package/esm/mail/index.mjs +2 -2
  698. package/esm/mail/mail.d.mts +1 -3
  699. package/esm/mail/mail.d.mts.map +1 -1
  700. package/esm/mail/mailer-pool.d.mts +5 -7
  701. package/esm/mail/mailer-pool.d.mts.map +1 -1
  702. package/esm/mail/react-mail.d.mts +1 -3
  703. package/esm/mail/react-mail.d.mts.map +1 -1
  704. package/esm/mail/send-mail.d.mts +1 -3
  705. package/esm/mail/send-mail.d.mts.map +1 -1
  706. package/esm/mail/send-mail.mjs +2 -1
  707. package/esm/mail/send-mail.mjs.map +1 -1
  708. package/esm/mail/test-mailbox.d.mts +11 -13
  709. package/esm/mail/test-mailbox.d.mts.map +1 -1
  710. package/esm/mail/types.d.mts +17 -18
  711. package/esm/mail/types.d.mts.map +1 -1
  712. package/esm/manifest/manifest-manager.mjs +1 -1
  713. package/esm/net/index.d.mts +2 -0
  714. package/esm/net/index.mjs +3 -0
  715. package/esm/openapi/build-openapi-document.d.mts +2 -4
  716. package/esm/openapi/build-openapi-document.d.mts.map +1 -1
  717. package/esm/openapi/build-openapi-document.mjs +8 -5
  718. package/esm/openapi/build-openapi-document.mjs.map +1 -1
  719. package/esm/openapi/cast-schema.mjs +1 -1
  720. package/esm/openapi/development-openapi-provider.d.mts +5 -6
  721. package/esm/openapi/development-openapi-provider.d.mts.map +1 -1
  722. package/esm/openapi/error-responses.mjs +28 -2
  723. package/esm/openapi/error-responses.mjs.map +1 -1
  724. package/esm/openapi/index.d.mts +3 -1
  725. package/esm/openapi/index.mjs +1 -1
  726. package/esm/openapi/openapi-child-output.mjs +2 -2
  727. package/esm/openapi/openapi-child-output.mjs.map +1 -1
  728. package/esm/openapi/postman/build-request-body.mjs.map +1 -1
  729. package/esm/openapi/postman/build-request-url.mjs +1 -1
  730. package/esm/openapi/postman/build-request-url.mjs.map +1 -1
  731. package/esm/openapi/postman/build-saved-responses.mjs.map +1 -1
  732. package/esm/openapi/postman/example-from-schema.d.mts +1 -3
  733. package/esm/openapi/postman/example-from-schema.d.mts.map +1 -1
  734. package/esm/openapi/postman/example-from-schema.mjs.map +1 -1
  735. package/esm/openapi/postman/index.d.mts +2 -1
  736. package/esm/openapi/postman/openapi-to-postman-collection.d.mts +3 -5
  737. package/esm/openapi/postman/openapi-to-postman-collection.d.mts.map +1 -1
  738. package/esm/openapi/postman/openapi-to-postman-collection.mjs.map +1 -1
  739. package/esm/openapi/postman/postman-types.d.mts +19 -18
  740. package/esm/openapi/postman/postman-types.d.mts.map +1 -1
  741. package/esm/openapi/postman/schema-refs.d.mts +1 -3
  742. package/esm/openapi/postman/schema-refs.d.mts.map +1 -1
  743. package/esm/openapi/postman/schema-refs.mjs.map +1 -1
  744. package/esm/openapi/postman/uuid-v5.mjs +1 -1
  745. package/esm/openapi/postman/uuid-v5.mjs.map +1 -1
  746. package/esm/openapi/request-schemas.mjs.map +1 -1
  747. package/esm/openapi/response-schemas.mjs.map +1 -1
  748. package/esm/openapi/schema-registry.d.mts +1 -0
  749. package/esm/openapi/schema-registry.mjs.map +1 -1
  750. package/esm/openapi/security.mjs +1 -1
  751. package/esm/openapi/security.mjs.map +1 -1
  752. package/esm/openapi/types.d.mts +23 -20
  753. package/esm/openapi/types.d.mts.map +1 -1
  754. package/esm/production/assert-generated-imports.mjs +2 -1
  755. package/esm/production/assert-generated-imports.mjs.map +1 -1
  756. package/esm/production/build-contributions.mjs +1 -1
  757. package/esm/production/bundle-framework-dependencies.mjs +1 -1
  758. package/esm/production/dist-build-manifest.mjs +1 -1
  759. package/esm/production/esbuild-plugins.mjs.map +1 -1
  760. package/esm/production/esbuild-preflight.mjs +1 -1
  761. package/esm/production/production-builder.mjs +14 -5
  762. package/esm/production/production-builder.mjs.map +1 -1
  763. package/esm/production/production-supervisor.mjs +1 -1
  764. package/esm/production/registration-child-runner.mjs +4 -3
  765. package/esm/production/registration-child-runner.mjs.map +1 -1
  766. package/esm/production/resolve-build-config.d.mts +4 -4
  767. package/esm/production/resolve-build-config.d.mts.map +1 -1
  768. package/esm/production/resolve-build-config.mjs +2 -1
  769. package/esm/production/resolve-build-config.mjs.map +1 -1
  770. package/esm/production/route-registration-child.d.mts +1 -1
  771. package/esm/production/route-registration-child.mjs +8 -7
  772. package/esm/production/route-registration-child.mjs.map +1 -1
  773. package/esm/production/route-registration-snapshot.mjs.map +1 -1
  774. package/esm/production/tsconfig-path-aliases.mjs +1 -1
  775. package/esm/react/index.d.mts +1 -3
  776. package/esm/react/index.d.mts.map +1 -1
  777. package/esm/react/index.mjs.map +1 -1
  778. package/esm/repositories/adapters/cascade/cascade-adapter.d.mts +3 -4
  779. package/esm/repositories/adapters/cascade/cascade-adapter.d.mts.map +1 -1
  780. package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +2 -3
  781. package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts.map +1 -1
  782. package/esm/repositories/adapters/cascade/filter-applicator.mjs +10 -9
  783. package/esm/repositories/adapters/cascade/filter-applicator.mjs.map +1 -1
  784. package/esm/repositories/adapters/cascade/index.d.mts +2 -1
  785. package/esm/repositories/adapters/cascade/index.mjs +1 -1
  786. package/esm/repositories/contracts/index.d.mts +2 -1
  787. package/esm/repositories/contracts/query-builder.contract.d.mts +4 -6
  788. package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
  789. package/esm/repositories/contracts/repository-adapter.contract.d.mts +1 -3
  790. package/esm/repositories/contracts/repository-adapter.contract.d.mts.map +1 -1
  791. package/esm/repositories/contracts/types.d.mts +23 -25
  792. package/esm/repositories/contracts/types.d.mts.map +1 -1
  793. package/esm/repositories/index.d.mts +4 -1
  794. package/esm/repositories/index.mjs +1 -1
  795. package/esm/repositories/repository.manager.d.mts +2 -3
  796. package/esm/repositories/repository.manager.d.mts.map +1 -1
  797. package/esm/repositories/repository.manager.mjs +2 -2
  798. package/esm/repositories/repository.manager.mjs.map +1 -1
  799. package/esm/resource/define-resource.d.mts +3 -5
  800. package/esm/resource/define-resource.d.mts.map +1 -1
  801. package/esm/resource/index.d.mts +2 -1
  802. package/esm/resource/index.mjs +1 -1
  803. package/esm/resource/nullable-resource.d.mts +5 -7
  804. package/esm/resource/nullable-resource.d.mts.map +1 -1
  805. package/esm/resource/register-resource.d.mts +1 -3
  806. package/esm/resource/register-resource.d.mts.map +1 -1
  807. package/esm/resource/resource-field-builder.d.mts +1 -3
  808. package/esm/resource/resource-field-builder.d.mts.map +1 -1
  809. package/esm/resource/resource.d.mts +3 -5
  810. package/esm/resource/resource.d.mts.map +1 -1
  811. package/esm/resource/resource.mjs +4 -2
  812. package/esm/resource/resource.mjs.map +1 -1
  813. package/esm/resource/types.d.mts +21 -21
  814. package/esm/resource/types.d.mts.map +1 -1
  815. package/esm/restful/index.d.mts +2 -1
  816. package/esm/restful/index.mjs +1 -1
  817. package/esm/restful/restful.d.mts +11 -31
  818. package/esm/restful/restful.d.mts.map +1 -1
  819. package/esm/restful/restful.mjs.map +1 -1
  820. package/esm/router/build-route-rate-limit.mjs.map +1 -1
  821. package/esm/router/dev-dispatch.mjs +31 -12
  822. package/esm/router/dev-dispatch.mjs.map +1 -1
  823. package/esm/router/index.d.mts +5 -2
  824. package/esm/router/index.mjs +3 -1
  825. package/esm/router/log-request-lifecycle.mjs.map +1 -1
  826. package/esm/router/named-api-routes-with-responses.mjs +2 -1
  827. package/esm/router/named-api-routes-with-responses.mjs.map +1 -1
  828. package/esm/router/normalize-request-path.d.mts +1 -2
  829. package/esm/router/normalize-request-path.d.mts.map +1 -1
  830. package/esm/router/normalize-route-path.d.mts +1 -2
  831. package/esm/router/normalize-route-path.d.mts.map +1 -1
  832. package/esm/router/positional-handler-diagnostics.d.mts +15 -13
  833. package/esm/router/positional-handler-diagnostics.d.mts.map +1 -1
  834. package/esm/router/positional-handler-diagnostics.mjs.map +1 -1
  835. package/esm/router/resolve-route-rate-limit.mjs +47 -0
  836. package/esm/router/resolve-route-rate-limit.mjs.map +1 -0
  837. package/esm/router/resolve-route-validation.mjs +19 -0
  838. package/esm/router/resolve-route-validation.mjs.map +1 -0
  839. package/esm/router/route-builder.d.mts +1 -3
  840. package/esm/router/route-builder.d.mts.map +1 -1
  841. package/esm/router/route-guard-names.mjs +30 -0
  842. package/esm/router/route-guard-names.mjs.map +1 -0
  843. package/esm/router/route-name-method-suffix.d.mts +2 -3
  844. package/esm/router/route-name-method-suffix.d.mts.map +1 -1
  845. package/esm/router/route-name-taken-error.d.mts +12 -0
  846. package/esm/router/route-name-taken-error.d.mts.map +1 -0
  847. package/esm/router/route-name-taken-error.mjs +18 -0
  848. package/esm/router/route-name-taken-error.mjs.map +1 -0
  849. package/esm/router/route-registry.d.mts +1 -3
  850. package/esm/router/route-registry.d.mts.map +1 -1
  851. package/esm/router/router.d.mts +34 -17
  852. package/esm/router/router.d.mts.map +1 -1
  853. package/esm/router/router.mjs +74 -39
  854. package/esm/router/router.mjs.map +1 -1
  855. package/esm/router/types.d.mts +156 -37
  856. package/esm/router/types.d.mts.map +1 -1
  857. package/esm/router/unguarded-route-diagnostics.d.mts +38 -0
  858. package/esm/router/unguarded-route-diagnostics.d.mts.map +1 -0
  859. package/esm/router/unguarded-route-diagnostics.mjs +95 -0
  860. package/esm/router/unguarded-route-diagnostics.mjs.map +1 -0
  861. package/esm/socket/index.d.mts +2 -1
  862. package/esm/socket/index.mjs +1 -1
  863. package/esm/socket/types.d.mts +2 -4
  864. package/esm/socket/types.d.mts.map +1 -1
  865. package/esm/socket/utils.d.mts +1 -3
  866. package/esm/socket/utils.d.mts.map +1 -1
  867. package/esm/storage/config.d.mts +4 -6
  868. package/esm/storage/config.d.mts.map +1 -1
  869. package/esm/storage/context/storage-driver-context.d.mts +3 -4
  870. package/esm/storage/context/storage-driver-context.d.mts.map +1 -1
  871. package/esm/storage/drivers/cloud-driver.d.mts +2 -4
  872. package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
  873. package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
  874. package/esm/storage/drivers/do-spaces-driver.d.mts +1 -3
  875. package/esm/storage/drivers/do-spaces-driver.d.mts.map +1 -1
  876. package/esm/storage/drivers/local-driver.d.mts +2 -3
  877. package/esm/storage/drivers/local-driver.d.mts.map +1 -1
  878. package/esm/storage/drivers/local-driver.mjs +8 -3
  879. package/esm/storage/drivers/local-driver.mjs.map +1 -1
  880. package/esm/storage/drivers/r2-driver.d.mts +1 -3
  881. package/esm/storage/drivers/r2-driver.d.mts.map +1 -1
  882. package/esm/storage/drivers/s3-driver.d.mts +1 -3
  883. package/esm/storage/drivers/s3-driver.d.mts.map +1 -1
  884. package/esm/storage/index.d.mts +2 -1
  885. package/esm/storage/index.mjs +1 -1
  886. package/esm/storage/local-disk-roots.mjs +24 -0
  887. package/esm/storage/local-disk-roots.mjs.map +1 -0
  888. package/esm/storage/scoped-storage.d.mts +2 -3
  889. package/esm/storage/scoped-storage.d.mts.map +1 -1
  890. package/esm/storage/storage-file.d.mts +1 -3
  891. package/esm/storage/storage-file.d.mts.map +1 -1
  892. package/esm/storage/storage.d.mts +17 -4
  893. package/esm/storage/storage.d.mts.map +1 -1
  894. package/esm/storage/storage.mjs +22 -0
  895. package/esm/storage/storage.mjs.map +1 -1
  896. package/esm/storage/types.d.mts +36 -36
  897. package/esm/storage/types.d.mts.map +1 -1
  898. package/esm/storage/utils/classify-ip-address.d.mts +1 -2
  899. package/esm/storage/utils/classify-ip-address.d.mts.map +1 -1
  900. package/esm/storage/utils/contain-path.d.mts +1 -2
  901. package/esm/storage/utils/contain-path.d.mts.map +1 -1
  902. package/esm/storage/utils/mime.d.mts +2 -3
  903. package/esm/storage/utils/mime.d.mts.map +1 -1
  904. package/esm/storage/utils/safe-fetch.d.mts +6 -6
  905. package/esm/storage/utils/safe-fetch.d.mts.map +1 -1
  906. package/esm/storage/utils/safe-fetch.mjs +3 -3
  907. package/esm/storage/utils/safe-fetch.mjs.map +1 -1
  908. package/esm/storage/utils/storage-capability-error.d.mts +1 -3
  909. package/esm/storage/utils/storage-capability-error.d.mts.map +1 -1
  910. package/esm/storage/utils/storage-error.d.mts +2 -3
  911. package/esm/storage/utils/storage-error.d.mts.map +1 -1
  912. package/esm/storage/utils/storage-not-initialized-error.d.mts +3 -2
  913. package/esm/storage/utils/storage-not-initialized-error.d.mts.map +1 -1
  914. package/esm/storage/utils/storage-not-initialized-error.mjs +1 -0
  915. package/esm/storage/utils/storage-not-initialized-error.mjs.map +1 -1
  916. package/esm/tests/authenticated-test-client.d.mts +31 -0
  917. package/esm/tests/authenticated-test-client.d.mts.map +1 -0
  918. package/esm/tests/authenticated-test-client.mjs +40 -0
  919. package/esm/tests/authenticated-test-client.mjs.map +1 -0
  920. package/esm/tests/factories.d.mts +74 -0
  921. package/esm/tests/factories.d.mts.map +1 -0
  922. package/esm/tests/factories.mjs +105 -0
  923. package/esm/tests/factories.mjs.map +1 -0
  924. package/esm/tests/fakes/cache-fake.d.mts +34 -0
  925. package/esm/tests/fakes/cache-fake.d.mts.map +1 -0
  926. package/esm/tests/fakes/cache-fake.mjs +79 -0
  927. package/esm/tests/fakes/cache-fake.mjs.map +1 -0
  928. package/esm/tests/fakes/clock-fake.d.mts +37 -0
  929. package/esm/tests/fakes/clock-fake.d.mts.map +1 -0
  930. package/esm/tests/fakes/clock-fake.mjs +69 -0
  931. package/esm/tests/fakes/clock-fake.mjs.map +1 -0
  932. package/esm/tests/fakes/fake-assertion-error.d.mts +12 -0
  933. package/esm/tests/fakes/fake-assertion-error.d.mts.map +1 -0
  934. package/esm/tests/fakes/fake-assertion-error.mjs +20 -0
  935. package/esm/tests/fakes/fake-assertion-error.mjs.map +1 -0
  936. package/esm/tests/fakes/ids-fake.d.mts +23 -0
  937. package/esm/tests/fakes/ids-fake.d.mts.map +1 -0
  938. package/esm/tests/fakes/ids-fake.mjs +57 -0
  939. package/esm/tests/fakes/ids-fake.mjs.map +1 -0
  940. package/esm/tests/fakes/index.d.mts +9 -0
  941. package/esm/tests/fakes/index.mjs +10 -0
  942. package/esm/tests/fakes/mail-fake.d.mts +49 -0
  943. package/esm/tests/fakes/mail-fake.d.mts.map +1 -0
  944. package/esm/tests/fakes/mail-fake.mjs +111 -0
  945. package/esm/tests/fakes/mail-fake.mjs.map +1 -0
  946. package/esm/tests/fakes/queue-fake.d.mts +56 -0
  947. package/esm/tests/fakes/queue-fake.d.mts.map +1 -0
  948. package/esm/tests/fakes/queue-fake.mjs +134 -0
  949. package/esm/tests/fakes/queue-fake.mjs.map +1 -0
  950. package/esm/tests/fakes/storage-fake.d.mts +35 -0
  951. package/esm/tests/fakes/storage-fake.d.mts.map +1 -0
  952. package/esm/tests/fakes/storage-fake.mjs +122 -0
  953. package/esm/tests/fakes/storage-fake.mjs.map +1 -0
  954. package/esm/tests/fakes/test-fakes.d.mts +38 -0
  955. package/esm/tests/fakes/test-fakes.d.mts.map +1 -0
  956. package/esm/tests/fakes/test-fakes.mjs +90 -0
  957. package/esm/tests/fakes/test-fakes.mjs.map +1 -0
  958. package/esm/tests/index.d.mts +15 -2
  959. package/esm/tests/index.mjs +15 -2
  960. package/esm/tests/snapshot-response.d.mts +33 -0
  961. package/esm/tests/snapshot-response.d.mts.map +1 -0
  962. package/esm/tests/snapshot-response.mjs +42 -0
  963. package/esm/tests/snapshot-response.mjs.map +1 -0
  964. package/esm/tests/start-http-development-server.d.mts +25 -5
  965. package/esm/tests/start-http-development-server.d.mts.map +1 -1
  966. package/esm/tests/start-http-development-server.mjs +41 -8
  967. package/esm/tests/start-http-development-server.mjs.map +1 -1
  968. package/esm/tests/test-connectors-selection.d.mts +2 -2
  969. package/esm/tests/test-connectors-selection.d.mts.map +1 -1
  970. package/esm/tests/test-connectors-selection.mjs +1 -1
  971. package/esm/tests/test-helpers.d.mts +28 -10
  972. package/esm/tests/test-helpers.d.mts.map +1 -1
  973. package/esm/tests/test-helpers.mjs +40 -27
  974. package/esm/tests/test-helpers.mjs.map +1 -1
  975. package/esm/tests/test-http-server.d.mts +66 -0
  976. package/esm/tests/test-http-server.d.mts.map +1 -0
  977. package/esm/tests/test-http-server.mjs +119 -0
  978. package/esm/tests/test-http-server.mjs.map +1 -0
  979. package/esm/tests/test-lifecycle-state.mjs +1 -1
  980. package/esm/tests/vitest-setup.d.mts +17 -7
  981. package/esm/tests/vitest-setup.d.mts.map +1 -1
  982. package/esm/tests/vitest-setup.mjs +12 -4
  983. package/esm/tests/vitest-setup.mjs.map +1 -1
  984. package/esm/tooling/agents-md/agents-md-markers.d.mts +26 -0
  985. package/esm/tooling/agents-md/agents-md-markers.d.mts.map +1 -0
  986. package/esm/tooling/agents-md/agents-md-markers.mjs +60 -0
  987. package/esm/tooling/agents-md/agents-md-markers.mjs.map +1 -0
  988. package/esm/tooling/agents-md/agents-md-refresher.d.mts +43 -0
  989. package/esm/tooling/agents-md/agents-md-refresher.d.mts.map +1 -0
  990. package/esm/tooling/agents-md/agents-md-refresher.mjs +72 -0
  991. package/esm/tooling/agents-md/agents-md-refresher.mjs.map +1 -0
  992. package/esm/tooling/agents-md/index.mjs +7 -0
  993. package/esm/tooling/agents-md/installed-skills.d.mts +34 -0
  994. package/esm/tooling/agents-md/installed-skills.d.mts.map +1 -0
  995. package/esm/tooling/agents-md/installed-skills.mjs +74 -0
  996. package/esm/tooling/agents-md/installed-skills.mjs.map +1 -0
  997. package/esm/tooling/agents-md/render-agents-md.d.mts +34 -0
  998. package/esm/tooling/agents-md/render-agents-md.d.mts.map +1 -0
  999. package/esm/tooling/agents-md/render-agents-md.mjs +195 -0
  1000. package/esm/tooling/agents-md/render-agents-md.mjs.map +1 -0
  1001. package/esm/tooling/agents-md/write-agents-md.d.mts +38 -0
  1002. package/esm/tooling/agents-md/write-agents-md.d.mts.map +1 -0
  1003. package/esm/tooling/agents-md/write-agents-md.mjs +49 -0
  1004. package/esm/tooling/agents-md/write-agents-md.mjs.map +1 -0
  1005. package/esm/tooling/board/board-message.d.mts +29 -0
  1006. package/esm/tooling/board/board-message.d.mts.map +1 -0
  1007. package/esm/tooling/board/board-message.mjs +86 -0
  1008. package/esm/tooling/board/board-message.mjs.map +1 -0
  1009. package/esm/tooling/board/board.d.mts +121 -0
  1010. package/esm/tooling/board/board.d.mts.map +1 -0
  1011. package/esm/tooling/board/board.mjs +407 -0
  1012. package/esm/tooling/board/board.mjs.map +1 -0
  1013. package/esm/tooling/board/board.types.d.mts +81 -0
  1014. package/esm/tooling/board/board.types.d.mts.map +1 -0
  1015. package/esm/tooling/board/board.types.mjs +54 -0
  1016. package/esm/tooling/board/board.types.mjs.map +1 -0
  1017. package/esm/tooling/check/changed-files.d.mts +31 -0
  1018. package/esm/tooling/check/changed-files.d.mts.map +1 -0
  1019. package/esm/tooling/check/changed-files.mjs +73 -0
  1020. package/esm/tooling/check/changed-files.mjs.map +1 -0
  1021. package/esm/tooling/check/check-report.types.d.mts +67 -0
  1022. package/esm/tooling/check/check-report.types.d.mts.map +1 -0
  1023. package/esm/tooling/check/check-report.types.mjs +37 -0
  1024. package/esm/tooling/check/check-report.types.mjs.map +1 -0
  1025. package/esm/tooling/check/code-style-conventions.mjs +106 -0
  1026. package/esm/tooling/check/code-style-conventions.mjs.map +1 -0
  1027. package/esm/tooling/check/conventions-step.d.mts +32 -0
  1028. package/esm/tooling/check/conventions-step.d.mts.map +1 -0
  1029. package/esm/tooling/check/conventions-step.mjs +173 -0
  1030. package/esm/tooling/check/conventions-step.mjs.map +1 -0
  1031. package/esm/tooling/check/environment-step.d.mts +16 -0
  1032. package/esm/tooling/check/environment-step.d.mts.map +1 -0
  1033. package/esm/tooling/check/environment-step.mjs +78 -0
  1034. package/esm/tooling/check/environment-step.mjs.map +1 -0
  1035. package/esm/tooling/check/index.mjs +10 -0
  1036. package/esm/tooling/check/lint-step.d.mts +18 -0
  1037. package/esm/tooling/check/lint-step.d.mts.map +1 -0
  1038. package/esm/tooling/check/lint-step.mjs +112 -0
  1039. package/esm/tooling/check/lint-step.mjs.map +1 -0
  1040. package/esm/tooling/check/request-input.mjs +132 -0
  1041. package/esm/tooling/check/request-input.mjs.map +1 -0
  1042. package/esm/tooling/check/run-check.d.mts +43 -0
  1043. package/esm/tooling/check/run-check.d.mts.map +1 -0
  1044. package/esm/tooling/check/run-check.mjs +192 -0
  1045. package/esm/tooling/check/run-check.mjs.map +1 -0
  1046. package/esm/tooling/check/run-tests.d.mts +55 -0
  1047. package/esm/tooling/check/run-tests.d.mts.map +1 -0
  1048. package/esm/tooling/check/run-tests.mjs +93 -0
  1049. package/esm/tooling/check/run-tests.mjs.map +1 -0
  1050. package/esm/tooling/check/security-conventions.mjs +650 -0
  1051. package/esm/tooling/check/security-conventions.mjs.map +1 -0
  1052. package/esm/tooling/check/source-ast.mjs +155 -0
  1053. package/esm/tooling/check/source-ast.mjs.map +1 -0
  1054. package/esm/tooling/check/source-files.mjs +27 -0
  1055. package/esm/tooling/check/source-files.mjs.map +1 -0
  1056. package/esm/tooling/check/tests-step.d.mts +33 -0
  1057. package/esm/tooling/check/tests-step.d.mts.map +1 -0
  1058. package/esm/tooling/check/tests-step.mjs +177 -0
  1059. package/esm/tooling/check/tests-step.mjs.map +1 -0
  1060. package/esm/tooling/dev-state/dev-server-state.d.mts +43 -0
  1061. package/esm/tooling/dev-state/dev-server-state.d.mts.map +1 -0
  1062. package/esm/tooling/dev-state/dev-server-state.mjs +67 -0
  1063. package/esm/tooling/dev-state/dev-server-state.mjs.map +1 -0
  1064. package/esm/tooling/devtools/devtools-client.d.mts +100 -0
  1065. package/esm/tooling/devtools/devtools-client.d.mts.map +1 -0
  1066. package/esm/tooling/devtools/devtools-client.mjs +155 -0
  1067. package/esm/tooling/devtools/devtools-client.mjs.map +1 -0
  1068. package/esm/tooling/generate/generation.d.mts +90 -0
  1069. package/esm/tooling/generate/generation.d.mts.map +1 -0
  1070. package/esm/tooling/generate/generation.mjs +127 -0
  1071. package/esm/tooling/generate/generation.mjs.map +1 -0
  1072. package/esm/tooling/generate/generator-spec.d.mts +57 -0
  1073. package/esm/tooling/generate/generator-spec.d.mts.map +1 -0
  1074. package/esm/tooling/generate/generator-spec.mjs +102 -0
  1075. package/esm/tooling/generate/generator-spec.mjs.map +1 -0
  1076. package/esm/tooling/generate/index.mjs +6 -0
  1077. package/esm/tooling/generate/project-files.mjs +121 -0
  1078. package/esm/tooling/generate/project-files.mjs.map +1 -0
  1079. package/esm/tooling/generate/run-cli.d.mts +43 -0
  1080. package/esm/tooling/generate/run-cli.d.mts.map +1 -0
  1081. package/esm/tooling/generate/run-cli.mjs +93 -0
  1082. package/esm/tooling/generate/run-cli.mjs.map +1 -0
  1083. package/esm/tooling/generate/unified-diff.d.mts +40 -0
  1084. package/esm/tooling/generate/unified-diff.d.mts.map +1 -0
  1085. package/esm/tooling/generate/unified-diff.mjs +161 -0
  1086. package/esm/tooling/generate/unified-diff.mjs.map +1 -0
  1087. package/esm/tooling/index.d.mts +42 -0
  1088. package/esm/tooling/index.mjs +45 -0
  1089. package/esm/tooling/inspect/boot-for-inspect.d.mts +23 -0
  1090. package/esm/tooling/inspect/boot-for-inspect.d.mts.map +1 -0
  1091. package/esm/tooling/inspect/boot-for-inspect.mjs +63 -0
  1092. package/esm/tooling/inspect/boot-for-inspect.mjs.map +1 -0
  1093. package/esm/tooling/inspect/collect-config.mjs +77 -0
  1094. package/esm/tooling/inspect/collect-config.mjs.map +1 -0
  1095. package/esm/tooling/inspect/collect-models.d.mts +10 -0
  1096. package/esm/tooling/inspect/collect-models.d.mts.map +1 -0
  1097. package/esm/tooling/inspect/collect-models.mjs +154 -0
  1098. package/esm/tooling/inspect/collect-models.mjs.map +1 -0
  1099. package/esm/tooling/inspect/collect-packages.d.mts +9 -0
  1100. package/esm/tooling/inspect/collect-packages.d.mts.map +1 -0
  1101. package/esm/tooling/inspect/collect-packages.mjs +157 -0
  1102. package/esm/tooling/inspect/collect-packages.mjs.map +1 -0
  1103. package/esm/tooling/inspect/collect-pages.mjs +108 -0
  1104. package/esm/tooling/inspect/collect-pages.mjs.map +1 -0
  1105. package/esm/tooling/inspect/collect-routes.mjs +168 -0
  1106. package/esm/tooling/inspect/collect-routes.mjs.map +1 -0
  1107. package/esm/tooling/inspect/event-recorder.d.mts +37 -0
  1108. package/esm/tooling/inspect/event-recorder.d.mts.map +1 -0
  1109. package/esm/tooling/inspect/event-recorder.mjs +91 -0
  1110. package/esm/tooling/inspect/event-recorder.mjs.map +1 -0
  1111. package/esm/tooling/inspect/index.d.mts +8 -0
  1112. package/esm/tooling/inspect/index.mjs +7 -0
  1113. package/esm/tooling/inspect/inspect-app.d.mts +62 -0
  1114. package/esm/tooling/inspect/inspect-app.d.mts.map +1 -0
  1115. package/esm/tooling/inspect/inspect-app.mjs +92 -0
  1116. package/esm/tooling/inspect/inspect-app.mjs.map +1 -0
  1117. package/esm/tooling/inspect/inspect-report.schema.d.mts +14 -0
  1118. package/esm/tooling/inspect/inspect-report.schema.d.mts.map +1 -0
  1119. package/esm/tooling/inspect/inspect-report.schema.mjs +463 -0
  1120. package/esm/tooling/inspect/inspect-report.schema.mjs.map +1 -0
  1121. package/esm/tooling/inspect/inspect-report.types.d.mts +228 -0
  1122. package/esm/tooling/inspect/inspect-report.types.d.mts.map +1 -0
  1123. package/esm/tooling/inspect/inspect-report.types.mjs +33 -0
  1124. package/esm/tooling/inspect/inspect-report.types.mjs.map +1 -0
  1125. package/esm/tooling/mcp/create-mcp-context.d.mts +29 -0
  1126. package/esm/tooling/mcp/create-mcp-context.d.mts.map +1 -0
  1127. package/esm/tooling/mcp/create-mcp-context.mjs +75 -0
  1128. package/esm/tooling/mcp/create-mcp-context.mjs.map +1 -0
  1129. package/esm/tooling/mcp/db-schema.d.mts +50 -0
  1130. package/esm/tooling/mcp/db-schema.d.mts.map +1 -0
  1131. package/esm/tooling/mcp/db-schema.mjs +56 -0
  1132. package/esm/tooling/mcp/db-schema.mjs.map +1 -0
  1133. package/esm/tooling/mcp/docs-search.d.mts +77 -0
  1134. package/esm/tooling/mcp/docs-search.d.mts.map +1 -0
  1135. package/esm/tooling/mcp/docs-search.mjs +178 -0
  1136. package/esm/tooling/mcp/docs-search.mjs.map +1 -0
  1137. package/esm/tooling/mcp/index.mjs +9 -0
  1138. package/esm/tooling/mcp/load-ai-tools.d.mts +61 -0
  1139. package/esm/tooling/mcp/load-ai-tools.d.mts.map +1 -0
  1140. package/esm/tooling/mcp/load-ai-tools.mjs +45 -0
  1141. package/esm/tooling/mcp/load-ai-tools.mjs.map +1 -0
  1142. package/esm/tooling/mcp/mcp-tools.d.mts +70 -0
  1143. package/esm/tooling/mcp/mcp-tools.d.mts.map +1 -0
  1144. package/esm/tooling/mcp/mcp-tools.mjs +514 -0
  1145. package/esm/tooling/mcp/mcp-tools.mjs.map +1 -0
  1146. package/esm/tooling/mcp/start-mcp-server.d.mts +63 -0
  1147. package/esm/tooling/mcp/start-mcp-server.d.mts.map +1 -0
  1148. package/esm/tooling/mcp/start-mcp-server.mjs +126 -0
  1149. package/esm/tooling/mcp/start-mcp-server.mjs.map +1 -0
  1150. package/esm/tooling/mcp/tool-input.d.mts +75 -0
  1151. package/esm/tooling/mcp/tool-input.d.mts.map +1 -0
  1152. package/esm/tooling/mcp/tool-input.mjs +72 -0
  1153. package/esm/tooling/mcp/tool-input.mjs.map +1 -0
  1154. package/esm/tooling/problem.d.mts +55 -0
  1155. package/esm/tooling/problem.d.mts.map +1 -0
  1156. package/esm/tooling/problem.mjs +28 -0
  1157. package/esm/tooling/problem.mjs.map +1 -0
  1158. package/esm/tooling/syntax/ast.mjs +230 -0
  1159. package/esm/tooling/syntax/ast.mjs.map +1 -0
  1160. package/esm/tooling/syntax/imports.mjs +34 -0
  1161. package/esm/tooling/syntax/imports.mjs.map +1 -0
  1162. package/esm/tooling/trace/trace-report.types.d.mts +85 -0
  1163. package/esm/tooling/trace/trace-report.types.d.mts.map +1 -0
  1164. package/esm/tooling/trace/trace-report.types.mjs +7 -0
  1165. package/esm/tooling/trace/trace-report.types.mjs.map +1 -0
  1166. package/esm/tooling/trace/trace-request.d.mts +90 -0
  1167. package/esm/tooling/trace/trace-request.d.mts.map +1 -0
  1168. package/esm/tooling/trace/trace-request.mjs +241 -0
  1169. package/esm/tooling/trace/trace-request.mjs.map +1 -0
  1170. package/esm/tooling/typecheck/index.mjs +3 -0
  1171. package/esm/tooling/typecheck/run-typecheck.d.mts +26 -0
  1172. package/esm/tooling/typecheck/run-typecheck.d.mts.map +1 -0
  1173. package/esm/tooling/typecheck/run-typecheck.mjs +90 -0
  1174. package/esm/tooling/typecheck/run-typecheck.mjs.map +1 -0
  1175. package/esm/tooling/typescript/compiler.d.mts +31 -0
  1176. package/esm/tooling/typescript/compiler.d.mts.map +1 -0
  1177. package/esm/tooling/typescript/compiler.mjs +120 -0
  1178. package/esm/tooling/typescript/compiler.mjs.map +1 -0
  1179. package/esm/updater/update-warlock-packages.mjs +3 -2
  1180. package/esm/updater/update-warlock-packages.mjs.map +1 -1
  1181. package/esm/upgrade/codemods/head-viewport.mjs +46 -0
  1182. package/esm/upgrade/codemods/head-viewport.mjs.map +1 -0
  1183. package/esm/upgrade/codemods/helpers.mjs +81 -0
  1184. package/esm/upgrade/codemods/helpers.mjs.map +1 -0
  1185. package/esm/upgrade/codemods/index.mjs +34 -0
  1186. package/esm/upgrade/codemods/index.mjs.map +1 -0
  1187. package/esm/upgrade/codemods/logger-sync-calls.mjs +57 -0
  1188. package/esm/upgrade/codemods/logger-sync-calls.mjs.map +1 -0
  1189. package/esm/upgrade/codemods/package-json.mjs +122 -0
  1190. package/esm/upgrade/codemods/package-json.mjs.map +1 -0
  1191. package/esm/upgrade/codemods/request-log-snapshot.mjs +82 -0
  1192. package/esm/upgrade/codemods/request-log-snapshot.mjs.map +1 -0
  1193. package/esm/upgrade/codemods/review-sites.mjs +262 -0
  1194. package/esm/upgrade/codemods/review-sites.mjs.map +1 -0
  1195. package/esm/upgrade/diff.mjs +119 -0
  1196. package/esm/upgrade/diff.mjs.map +1 -0
  1197. package/esm/upgrade/format-upgrade-report.mjs +32 -0
  1198. package/esm/upgrade/format-upgrade-report.mjs.map +1 -0
  1199. package/esm/upgrade/load-ts-morph.mjs +49 -0
  1200. package/esm/upgrade/load-ts-morph.mjs.map +1 -0
  1201. package/esm/upgrade/notes.mjs +16 -0
  1202. package/esm/upgrade/notes.mjs.map +1 -0
  1203. package/esm/upgrade/run-upgrade.mjs +246 -0
  1204. package/esm/upgrade/run-upgrade.mjs.map +1 -0
  1205. package/esm/upgrade/upgrade-command.action.mjs +37 -0
  1206. package/esm/upgrade/upgrade-command.action.mjs.map +1 -0
  1207. package/esm/upgrade/version.mjs +39 -0
  1208. package/esm/upgrade/version.mjs.map +1 -0
  1209. package/esm/use-cases/index.d.mts +2 -1
  1210. package/esm/use-cases/index.mjs +1 -1
  1211. package/esm/use-cases/types.d.mts +116 -63
  1212. package/esm/use-cases/types.d.mts.map +1 -1
  1213. package/esm/use-cases/use-case-broadcast.d.mts +1 -3
  1214. package/esm/use-cases/use-case-broadcast.d.mts.map +1 -1
  1215. package/esm/use-cases/use-case-events.d.mts +3 -5
  1216. package/esm/use-cases/use-case-events.d.mts.map +1 -1
  1217. package/esm/use-cases/use-case-pipeline.d.mts +6 -6
  1218. package/esm/use-cases/use-case-pipeline.d.mts.map +1 -1
  1219. package/esm/use-cases/use-case.d.mts +2 -4
  1220. package/esm/use-cases/use-case.d.mts.map +1 -1
  1221. package/esm/use-cases/use-case.errors.d.mts +1 -3
  1222. package/esm/use-cases/use-case.errors.d.mts.map +1 -1
  1223. package/esm/use-cases/use-cases-registry.d.mts +8 -10
  1224. package/esm/use-cases/use-cases-registry.d.mts.map +1 -1
  1225. package/esm/use-cases/use-cases-registry.mjs.map +1 -1
  1226. package/esm/utils/app-log.d.mts +1 -2
  1227. package/esm/utils/app-log.d.mts.map +1 -1
  1228. package/esm/utils/clock.d.mts +35 -0
  1229. package/esm/utils/clock.d.mts.map +1 -0
  1230. package/esm/utils/clock.mjs +27 -0
  1231. package/esm/utils/clock.mjs.map +1 -0
  1232. package/esm/utils/database-log.d.mts +3 -4
  1233. package/esm/utils/database-log.d.mts.map +1 -1
  1234. package/esm/utils/environment.d.mts +4 -5
  1235. package/esm/utils/environment.d.mts.map +1 -1
  1236. package/esm/utils/framework-vesion.mjs +1 -1
  1237. package/esm/utils/framework-vesion.mjs.map +1 -1
  1238. package/esm/utils/get-localized.d.mts +2 -3
  1239. package/esm/utils/get-localized.d.mts.map +1 -1
  1240. package/esm/utils/ids.d.mts +35 -0
  1241. package/esm/utils/ids.d.mts.map +1 -0
  1242. package/esm/utils/ids.mjs +33 -0
  1243. package/esm/utils/ids.mjs.map +1 -0
  1244. package/esm/utils/index.d.mts +5 -1
  1245. package/esm/utils/index.mjs +4 -1
  1246. package/esm/utils/normalized-path.d.mts +1 -2
  1247. package/esm/utils/normalized-path.d.mts.map +1 -1
  1248. package/esm/utils/npm-registry.d.mts +1 -2
  1249. package/esm/utils/npm-registry.d.mts.map +1 -1
  1250. package/esm/utils/paths.d.mts +13 -14
  1251. package/esm/utils/paths.d.mts.map +1 -1
  1252. package/esm/utils/paths.mjs +2 -2
  1253. package/esm/utils/paths.mjs.map +1 -1
  1254. package/esm/utils/promise-all-object.d.mts +1 -2
  1255. package/esm/utils/promise-all-object.d.mts.map +1 -1
  1256. package/esm/utils/queue.d.mts +1 -2
  1257. package/esm/utils/queue.d.mts.map +1 -1
  1258. package/esm/utils/runtime.d.mts +60 -0
  1259. package/esm/utils/runtime.d.mts.map +1 -0
  1260. package/esm/utils/runtime.mjs +85 -0
  1261. package/esm/utils/runtime.mjs.map +1 -0
  1262. package/esm/utils/sleep.d.mts +1 -2
  1263. package/esm/utils/sleep.d.mts.map +1 -1
  1264. package/esm/utils/sluggable.d.mts +1 -3
  1265. package/esm/utils/sluggable.d.mts.map +1 -1
  1266. package/esm/utils/to-json.d.mts +1 -2
  1267. package/esm/utils/to-json.d.mts.map +1 -1
  1268. package/esm/utils/types.d.mts +1 -2
  1269. package/esm/utils/types.d.mts.map +1 -1
  1270. package/esm/utils/urls.d.mts +5 -6
  1271. package/esm/utils/urls.d.mts.map +1 -1
  1272. package/esm/utils/version-compare.d.mts +1 -2
  1273. package/esm/utils/version-compare.d.mts.map +1 -1
  1274. package/esm/validation/database/exists-except-current-id.d.mts +2 -3
  1275. package/esm/validation/database/exists-except-current-id.d.mts.map +1 -1
  1276. package/esm/validation/database/exists-except-current-user.d.mts +2 -3
  1277. package/esm/validation/database/exists-except-current-user.d.mts.map +1 -1
  1278. package/esm/validation/database/index.d.mts +2 -1
  1279. package/esm/validation/database/index.mjs +1 -1
  1280. package/esm/validation/database/types.d.mts +14 -10
  1281. package/esm/validation/database/types.d.mts.map +1 -1
  1282. package/esm/validation/database/unique-except-current-id.d.mts +2 -3
  1283. package/esm/validation/database/unique-except-current-id.d.mts.map +1 -1
  1284. package/esm/validation/database/unique-except-current-user.d.mts +2 -3
  1285. package/esm/validation/database/unique-except-current-user.d.mts.map +1 -1
  1286. package/esm/validation/file/file.d.mts +4 -6
  1287. package/esm/validation/file/file.d.mts.map +1 -1
  1288. package/esm/validation/file/index.d.mts +2 -1
  1289. package/esm/validation/file/index.mjs +1 -1
  1290. package/esm/validation/index.d.mts +6 -2
  1291. package/esm/validation/index.mjs +1 -1
  1292. package/esm/validation/plugins/index.mjs +1 -1
  1293. package/esm/validation/types.d.mts +61 -4
  1294. package/esm/validation/types.d.mts.map +1 -1
  1295. package/esm/validation/validateAll.mjs +21 -4
  1296. package/esm/validation/validateAll.mjs.map +1 -1
  1297. package/esm/validation/validation-failure-status.mjs +15 -0
  1298. package/esm/validation/validation-failure-status.mjs.map +1 -0
  1299. package/esm/validation/validators/file-validator.d.mts +2 -20
  1300. package/esm/validation/validators/file-validator.d.mts.map +1 -1
  1301. package/esm/validation/validators/index.d.mts +2 -1
  1302. package/esm/validation/validators/index.mjs +1 -1
  1303. package/esm/vite/lower-stage3-decorators.d.mts +2 -3
  1304. package/esm/vite/lower-stage3-decorators.d.mts.map +1 -1
  1305. package/esm/warlock-config/bundle-config.mjs +1 -1
  1306. package/esm/warlock-config/define-config.d.mts +1 -3
  1307. package/esm/warlock-config/define-config.d.mts.map +1 -1
  1308. package/esm/warlock-config/define-config.mjs +3 -2
  1309. package/esm/warlock-config/define-config.mjs.map +1 -1
  1310. package/esm/warlock-config/index.d.mts +2 -1
  1311. package/esm/warlock-config/index.mjs +1 -1
  1312. package/esm/warlock-config/types.d.mts +31 -6
  1313. package/esm/warlock-config/types.d.mts.map +1 -1
  1314. package/esm/warlock-config/warlock-config.manager.d.mts +5 -7
  1315. package/esm/warlock-config/warlock-config.manager.d.mts.map +1 -1
  1316. package/esm/warlock-config/warlock-config.manager.mjs +2 -1
  1317. package/esm/warlock-config/warlock-config.manager.mjs.map +1 -1
  1318. package/esm/warlock-config/warn-deprecated-config.mjs +1 -1
  1319. package/llms-full.txt +3211 -731
  1320. package/llms.txt +16 -6
  1321. package/package.json +47 -15
  1322. package/schemas/inspect-report.schema.json +554 -0
  1323. package/skills/README.md +9 -0
  1324. package/skills/add-connector/SKILL.md +26 -38
  1325. package/skills/benchmark-code/SKILL.md +30 -24
  1326. package/skills/build-restful/SKILL.md +14 -14
  1327. package/skills/build-url/SKILL.md +18 -18
  1328. package/skills/configure-app/SKILL.md +107 -14
  1329. package/skills/create-controller/SKILL.md +25 -12
  1330. package/skills/create-module/SKILL.md +10 -3
  1331. package/skills/define-resource/SKILL.md +32 -29
  1332. package/skills/encrypt-data/SKILL.md +21 -19
  1333. package/skills/generate-openapi/SKILL.md +50 -24
  1334. package/skills/hash-password/SKILL.md +2 -2
  1335. package/skills/health-checks/SKILL.md +24 -7
  1336. package/skills/index.md +11 -4
  1337. package/skills/lower-stage3-decorators/SKILL.md +4 -4
  1338. package/skills/make-endpoint/SKILL.md +110 -0
  1339. package/skills/model-factories/SKILL.md +92 -0
  1340. package/skills/process-image/SKILL.md +32 -30
  1341. package/skills/register-route/SKILL.md +109 -10
  1342. package/skills/report-framework-issue.md +154 -0
  1343. package/skills/request-memo/SKILL.md +1 -1
  1344. package/skills/request-tracing/SKILL.md +4 -1
  1345. package/skills/resolve-path/SKILL.md +45 -44
  1346. package/skills/retry-operation/SKILL.md +20 -11
  1347. package/skills/run-app/SKILL.md +107 -22
  1348. package/skills/send-response/SKILL.md +179 -14
  1349. package/skills/store-file/SKILL.md +93 -53
  1350. package/skills/test-fakes/SKILL.md +123 -0
  1351. package/skills/test-http/SKILL.md +125 -21
  1352. package/skills/test-service/SKILL.md +41 -1
  1353. package/skills/update-packages/SKILL.md +29 -18
  1354. package/skills/upgrade-from-5-29/SKILL.md +454 -0
  1355. package/skills/upload-file/SKILL.md +31 -33
  1356. package/skills/use-app-context/SKILL.md +38 -31
  1357. package/skills/use-middleware/SKILL.md +45 -25
  1358. package/skills/use-model-transformers/SKILL.md +37 -28
  1359. package/skills/use-repository/SKILL.md +2 -2
  1360. package/skills/validate-input/SKILL.md +72 -28
  1361. package/skills/warlock-agents-md/SKILL.md +96 -0
  1362. package/skills/warlock-board/SKILL.md +123 -0
  1363. package/skills/warlock-check/SKILL.md +133 -0
  1364. package/skills/warlock-conventions/SKILL.md +115 -0
  1365. package/skills/warlock-doctor/SKILL.md +55 -22
  1366. package/skills/warlock-inspect/SKILL.md +134 -0
  1367. package/skills/warlock-mcp/SKILL.md +120 -0
  1368. package/skills/warlock-routes/SKILL.md +18 -11
  1369. package/skills/warlock-trace/SKILL.md +81 -0
  1370. package/skills/wire-socket/SKILL.md +8 -8
  1371. package/skills/write-seeder/SKILL.md +46 -32
  1372. package/skills/write-use-case/SKILL.md +40 -27
  1373. package/esm/http/uploads/matches-if-none-match.mjs +0 -13
  1374. package/esm/http/uploads/matches-if-none-match.mjs.map +0 -1
@@ -1,8 +1,9 @@
1
+ import { purgeVariantCacheEntries, variantCacheEntries, variantSourceCacheEntries } from "./image-variant-cache-entries.mjs";
2
+ import { variantSourceDirectory, variantSourceKey } from "./variant-cache-key.mjs";
1
3
  import { purgeImageVariantsOfFile, variantCacheDirectoryFor } from "./image-variant-cache.mjs";
2
- import { ImageVariantsConfigError } from "./image-variants-config-error.mjs";
3
4
  import { localDiskRoot } from "./local-disk-root.mjs";
5
+ import { remoteVariantDisk, remoteVariantPath } from "./remote-variant-source.mjs";
4
6
  import path from "node:path";
5
- import fs from "node:fs/promises";
6
7
 
7
8
  //#region ../../packages/core/src/http/uploads/purge-image-variants.ts
8
9
  /**
@@ -14,29 +15,28 @@ import fs from "node:fs/promises";
14
15
  * `uploads.images.cacheDirectory` is set, that directory is shared by every
15
16
  * local disk, so this clears all of them.
16
17
  *
18
+ * Only recognized derivative, source-manifest and temporary files in the
19
+ * generated cache layout are removed. The cache root, directories, unrelated
20
+ * files and symlinks stay in place. Use a dedicated folder for derivatives.
21
+ *
17
22
  * Deleting or moving a file through local storage (`storage.delete`,
18
23
  * `deleteMany`, `move`) already purges its derivatives; call this for files
19
24
  * removed some other way.
20
25
  *
26
+ * @throws ImageVariantsConfigError when the cache equals or contains any
27
+ * configured local disk root, including through a symlink
21
28
  * @returns `true` when something was removed
22
- * @throws ImageVariantsConfigError when the disk is not a local disk
23
29
  */
24
30
  async function purgeImageVariants(relativePath, options = {}) {
25
31
  const diskRoot = localDiskRoot(options.disk);
26
- if (!diskRoot) throw new ImageVariantsConfigError(options.disk === void 0 ? "purgeImageVariants needs a local storage driver with a root." : `purgeImageVariants needs a local disk; "${options.disk}" is not one.`);
27
- if (relativePath === void 0) {
28
- const directory = variantCacheDirectoryFor(diskRoot);
29
- try {
30
- await fs.access(directory);
31
- } catch {
32
- return false;
33
- }
34
- await fs.rm(directory, {
35
- recursive: true,
36
- force: true
37
- });
38
- return true;
32
+ if (!diskRoot) {
33
+ const disk = remoteVariantDisk(options.disk);
34
+ const location = relativePath === void 0 ? void 0 : remoteVariantPath(relativePath);
35
+ if (relativePath !== void 0 && location === void 0) return false;
36
+ const cache = variantCacheDirectoryFor(disk.cacheRoot);
37
+ return purgeVariantCacheEntries(location === void 0 ? variantCacheEntries(cache) : variantSourceCacheEntries(variantSourceDirectory(cache, variantSourceKey(disk.root, disk.driver.applyPrefix(location)))));
39
38
  }
39
+ if (relativePath === void 0) return purgeVariantCacheEntries(variantCacheEntries(variantCacheDirectoryFor(diskRoot)));
40
40
  const location = relativePath.replace(/\\/g, "/").replace(/^\/+/, "");
41
41
  return purgeImageVariantsOfFile(diskRoot, path.resolve(diskRoot, location));
42
42
  }
@@ -1 +1 @@
1
- {"version":3,"file":"purge-image-variants.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/http/uploads/purge-image-variants.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { StorageDriverName } from \"../../storage/types\";\nimport { purgeImageVariantsOfFile, variantCacheDirectoryFor } from \"./image-variant-cache\";\nimport { ImageVariantsConfigError } from \"./image-variants-config-error\";\nimport { localDiskRoot } from \"./local-disk-root\";\n\n/**\n * Options for {@link purgeImageVariants}\n */\nexport type PurgeImageVariantsOptions = {\n /**\n * Local disk the source lives on; the default disk when omitted\n */\n disk?: StorageDriverName;\n};\n\n/**\n * Remove cached image derivatives.\n *\n * - With a path: every derivative of that file, in every variant and format.\n * The file itself is untouched and does not need to exist.\n * - Without a path: the whole derivative cache of the disk. When\n * `uploads.images.cacheDirectory` is set, that directory is shared by every\n * local disk, so this clears all of them.\n *\n * Deleting or moving a file through local storage (`storage.delete`,\n * `deleteMany`, `move`) already purges its derivatives; call this for files\n * removed some other way.\n *\n * @returns `true` when something was removed\n * @throws ImageVariantsConfigError when the disk is not a local disk\n */\nexport async function purgeImageVariants(\n relativePath?: string,\n options: PurgeImageVariantsOptions = {},\n): Promise<boolean> {\n const diskRoot = localDiskRoot(options.disk);\n\n if (!diskRoot) {\n throw new ImageVariantsConfigError(\n options.disk === undefined\n ? \"purgeImageVariants needs a local storage driver with a root.\"\n : `purgeImageVariants needs a local disk; \"${options.disk}\" is not one.`,\n );\n }\n\n if (relativePath === undefined) {\n const directory = variantCacheDirectoryFor(diskRoot);\n\n try {\n await fs.access(directory);\n } catch {\n return false;\n }\n\n await fs.rm(directory, { recursive: true, force: true });\n\n return true;\n }\n\n const location = relativePath.replace(/\\\\/g, \"/\").replace(/^\\/+/, \"\");\n\n return purgeImageVariantsOfFile(diskRoot, path.resolve(diskRoot, location));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAiCA,eAAsB,mBACpB,cACA,UAAqC,CAAC,GACpB;CAClB,MAAM,WAAW,cAAc,QAAQ,IAAI;CAE3C,IAAI,CAAC,UACH,MAAM,IAAI,yBACR,QAAQ,SAAS,SACb,iEACA,2CAA2C,QAAQ,KAAK,cAC9D;CAGF,IAAI,iBAAiB,QAAW;EAC9B,MAAM,YAAY,yBAAyB,QAAQ;EAEnD,IAAI;GACF,MAAM,GAAG,OAAO,SAAS;EAC3B,QAAQ;GACN,OAAO;EACT;EAEA,MAAM,GAAG,GAAG,WAAW;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;EAEvD,OAAO;CACT;CAEA,MAAM,WAAW,aAAa,QAAQ,OAAO,GAAG,CAAC,CAAC,QAAQ,QAAQ,EAAE;CAEpE,OAAO,yBAAyB,UAAU,KAAK,QAAQ,UAAU,QAAQ,CAAC;AAC5E"}
1
+ {"version":3,"file":"purge-image-variants.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/http/uploads/purge-image-variants.ts"],"sourcesContent":["import path from \"node:path\";\nimport type { StorageDriverName } from \"../../storage/types\";\nimport { purgeImageVariantsOfFile, variantCacheDirectoryFor } from \"./image-variant-cache\";\nimport { remoteVariantDisk, remoteVariantPath } from \"./remote-variant-source\";\nimport { variantSourceDirectory, variantSourceKey } from \"./variant-cache-key\";\nimport { localDiskRoot } from \"./local-disk-root\";\nimport {\n purgeVariantCacheEntries,\n variantCacheEntries,\n variantSourceCacheEntries,\n} from \"./image-variant-cache-entries\";\n\n/**\n * Options for {@link purgeImageVariants}\n */\nexport type PurgeImageVariantsOptions = {\n /**\n * Disk the source lives on; the default disk when omitted\n */\n disk?: StorageDriverName;\n};\n\n/**\n * Remove cached image derivatives.\n *\n * - With a path: every derivative of that file, in every variant and format.\n * The file itself is untouched and does not need to exist.\n * - Without a path: the whole derivative cache of the disk. When\n * `uploads.images.cacheDirectory` is set, that directory is shared by every\n * local disk, so this clears all of them.\n *\n * Only recognized derivative, source-manifest and temporary files in the\n * generated cache layout are removed. The cache root, directories, unrelated\n * files and symlinks stay in place. Use a dedicated folder for derivatives.\n *\n * Deleting or moving a file through local storage (`storage.delete`,\n * `deleteMany`, `move`) already purges its derivatives; call this for files\n * removed some other way.\n *\n * @throws ImageVariantsConfigError when the cache equals or contains any\n * configured local disk root, including through a symlink\n * @returns `true` when something was removed\n */\nexport async function purgeImageVariants(\n relativePath?: string,\n options: PurgeImageVariantsOptions = {},\n): Promise<boolean> {\n const diskRoot = localDiskRoot(options.disk);\n\n if (!diskRoot) {\n const disk = remoteVariantDisk(options.disk);\n const location = relativePath === undefined ? undefined : remoteVariantPath(relativePath);\n if (relativePath !== undefined && location === undefined) return false;\n const cache = variantCacheDirectoryFor(disk.cacheRoot);\n return purgeVariantCacheEntries(\n location === undefined\n ? variantCacheEntries(cache)\n : variantSourceCacheEntries(\n variantSourceDirectory(\n cache,\n variantSourceKey(disk.root, disk.driver.applyPrefix(location)),\n ),\n ),\n );\n }\n\n if (relativePath === undefined) {\n return purgeVariantCacheEntries(variantCacheEntries(variantCacheDirectoryFor(diskRoot)));\n }\n\n const location = relativePath.replace(/\\\\/g, \"/\").replace(/^\\/+/, \"\");\n\n return purgeImageVariantsOfFile(diskRoot, path.resolve(diskRoot, location));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,eAAsB,mBACpB,cACA,UAAqC,CAAC,GACpB;CAClB,MAAM,WAAW,cAAc,QAAQ,IAAI;CAE3C,IAAI,CAAC,UAAU;EACb,MAAM,OAAO,kBAAkB,QAAQ,IAAI;EAC3C,MAAM,WAAW,iBAAiB,SAAY,SAAY,kBAAkB,YAAY;EACxF,IAAI,iBAAiB,UAAa,aAAa,QAAW,OAAO;EACjE,MAAM,QAAQ,yBAAyB,KAAK,SAAS;EACrD,OAAO,yBACL,aAAa,SACT,oBAAoB,KAAK,IACzB,0BACE,uBACE,OACA,iBAAiB,KAAK,MAAM,KAAK,OAAO,YAAY,QAAQ,CAAC,CAC/D,CACF,CACN;CACF;CAEA,IAAI,iBAAiB,QACnB,OAAO,yBAAyB,oBAAoB,yBAAyB,QAAQ,CAAC,CAAC;CAGzF,MAAM,WAAW,aAAa,QAAQ,OAAO,GAAG,CAAC,CAAC,QAAQ,QAAQ,EAAE;CAEpE,OAAO,yBAAyB,UAAU,KAAK,QAAQ,UAAU,QAAQ,CAAC;AAC5E"}
@@ -0,0 +1,115 @@
1
+ import { storagePath } from "../../utils/paths.mjs";
2
+ import { HttpError } from "../errors/errors.mjs";
3
+ import { storage } from "../../storage/storage.mjs";
4
+ import "../../storage/index.mjs";
5
+ import { detectImageFormat, isVariantSourceFormat } from "./detect-image-format.mjs";
6
+ import { loadVariantSource } from "./load-variant-source.mjs";
7
+ import { createHash } from "node:crypto";
8
+ import path from "node:path";
9
+
10
+ //#region ../../packages/core/src/http/uploads/remote-variant-source.ts
11
+ const activeSources = /* @__PURE__ */ new Map();
12
+ function remoteVariantDisk(disk) {
13
+ const driver = disk === void 0 ? storage.activeDriver : storage.getDriver(disk);
14
+ const { bucket, endpoint, region } = driver.options;
15
+ return {
16
+ driver,
17
+ root: JSON.stringify([
18
+ driver.name,
19
+ bucket,
20
+ endpoint,
21
+ region
22
+ ]),
23
+ cacheRoot: storagePath()
24
+ };
25
+ }
26
+ /** Object keys are normalized once, without URL decoding, before prefixing. */
27
+ function remoteVariantPath(location) {
28
+ if (!location || location.includes("\0") || location.includes("\\") || path.posix.isAbsolute(location) || path.win32.isAbsolute(location) || /^[A-Za-z]:/.test(location) || location.split("/").includes("..")) return void 0;
29
+ const normalized = path.posix.normalize(location);
30
+ return normalized === "." ? void 0 : normalized;
31
+ }
32
+ async function remoteVariantSource(location, disk, images) {
33
+ const relativePath = remoteVariantPath(location);
34
+ if (!relativePath) return void 0;
35
+ const objectPath = relativePath;
36
+ let metadata;
37
+ try {
38
+ metadata = await disk.driver.metadata(relativePath);
39
+ } catch (error) {
40
+ const detail = error;
41
+ if ([
42
+ "ENOENT",
43
+ "NoSuchKey",
44
+ "NotFound"
45
+ ].includes(detail.code ?? detail.name ?? "") || detail.$metadata?.httpStatusCode === 404) return void 0;
46
+ throw error;
47
+ }
48
+ if (metadata.isDirectory) return void 0;
49
+ if (metadata.size > images.maxSourceBytes) throw new HttpError(413, "The source image is too large.");
50
+ const sourcePath = disk.driver.applyPrefix(relativePath);
51
+ const metadataGeneration = metadata.etag ? createHash("sha256").update(JSON.stringify([
52
+ metadata.etag,
53
+ metadata.size,
54
+ metadata.lastModified?.getTime()
55
+ ])).digest("hex") : void 0;
56
+ const activeKey = JSON.stringify([
57
+ disk.root,
58
+ sourcePath,
59
+ metadataGeneration,
60
+ images.maxSourceBytes,
61
+ images.maxSourcePixels
62
+ ]);
63
+ const existing = activeSources.get(activeKey);
64
+ if (existing) {
65
+ existing.references++;
66
+ return existing.source;
67
+ }
68
+ let loaded;
69
+ async function load() {
70
+ const stream = await disk.driver.getStream(objectPath);
71
+ const chunks = [];
72
+ let size = 0;
73
+ try {
74
+ for await (const chunk of stream) {
75
+ const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
76
+ size += bytes.length;
77
+ if (size > images.maxSourceBytes) throw new HttpError(413, "The source image is too large.");
78
+ chunks.push(bytes);
79
+ }
80
+ } finally {
81
+ stream.destroy();
82
+ }
83
+ const buffer = Buffer.concat(chunks);
84
+ const sourceFormat = detectImageFormat(buffer);
85
+ if (!isVariantSourceFormat(sourceFormat)) throw new HttpError(415, "Variants are only available for jpeg, png, webp and avif images.");
86
+ return {
87
+ image: await loadVariantSource(buffer, {
88
+ maxSourceBytes: images.maxSourceBytes,
89
+ maxSourcePixels: images.maxSourcePixels,
90
+ expectedFormat: sourceFormat
91
+ }),
92
+ sourceFormat,
93
+ generation: metadataGeneration ?? createHash("sha256").update(buffer).digest("hex")
94
+ };
95
+ }
96
+ const source = {
97
+ relativePath,
98
+ sourcePath,
99
+ metadataGeneration,
100
+ load: () => loaded ??= load(),
101
+ release() {
102
+ const active = activeSources.get(activeKey);
103
+ if (active && --active.references === 0) activeSources.delete(activeKey);
104
+ }
105
+ };
106
+ activeSources.set(activeKey, {
107
+ source,
108
+ references: 1
109
+ });
110
+ return source;
111
+ }
112
+
113
+ //#endregion
114
+ export { remoteVariantDisk, remoteVariantPath, remoteVariantSource };
115
+ //# sourceMappingURL=remote-variant-source.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-variant-source.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/http/uploads/remote-variant-source.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport type { StorageDriverContract, StorageDriverName } from \"../../storage/types\";\nimport { storage } from \"../../storage\";\nimport { storagePath } from \"../../utils/paths\";\nimport { HttpError } from \"../errors\";\nimport { detectImageFormat, isVariantSourceFormat } from \"./detect-image-format\";\nimport type { ResolvedImageVariantsConfig } from \"./image-variant-types\";\nimport { loadVariantSource } from \"./load-variant-source\";\nimport type { Image } from \"../../image\";\nimport type { VariantSourceFormat } from \"./image-variant-types\";\n\ntype LoadedRemoteSource = { image: Image; sourceFormat: VariantSourceFormat; generation: string };\nexport type RemoteVariantSource = {\n relativePath: string;\n sourcePath: string;\n metadataGeneration?: string;\n load(): Promise<LoadedRemoteSource>;\n release(): void;\n};\nconst activeSources = new Map<string, { references: number; source: RemoteVariantSource }>();\n\nexport function remoteVariantDisk(disk?: StorageDriverName): {\n driver: StorageDriverContract;\n root: string;\n cacheRoot: string;\n} {\n const driver = disk === undefined ? storage.activeDriver : storage.getDriver(disk);\n const { bucket, endpoint, region } = driver.options;\n return {\n driver,\n root: JSON.stringify([driver.name, bucket, endpoint, region]),\n cacheRoot: storagePath(),\n };\n}\n\n/** Object keys are normalized once, without URL decoding, before prefixing. */\nexport function remoteVariantPath(location: string): string | undefined {\n if (\n !location ||\n location.includes(\"\\0\") ||\n location.includes(\"\\\\\") ||\n path.posix.isAbsolute(location) ||\n path.win32.isAbsolute(location) ||\n /^[A-Za-z]:/.test(location) ||\n location.split(\"/\").includes(\"..\")\n )\n return undefined;\n const normalized = path.posix.normalize(location);\n return normalized === \".\" ? undefined : normalized;\n}\n\nexport async function remoteVariantSource(\n location: string,\n disk: ReturnType<typeof remoteVariantDisk>,\n images: ResolvedImageVariantsConfig,\n): Promise<RemoteVariantSource | undefined> {\n const relativePath = remoteVariantPath(location);\n if (!relativePath) return undefined;\n const objectPath = relativePath;\n let metadata;\n try {\n metadata = await disk.driver.metadata(relativePath);\n } catch (error) {\n const detail = error as {\n code?: string;\n name?: string;\n $metadata?: { httpStatusCode?: number };\n };\n if (\n [\"ENOENT\", \"NoSuchKey\", \"NotFound\"].includes(detail.code ?? detail.name ?? \"\") ||\n detail.$metadata?.httpStatusCode === 404\n )\n return undefined;\n throw error;\n }\n if (metadata.isDirectory) return undefined;\n if (metadata.size > images.maxSourceBytes)\n throw new HttpError(413, \"The source image is too large.\");\n // The identity includes the effective prefix, including tenant context.\n const sourcePath = disk.driver.applyPrefix(relativePath);\n const metadataGeneration = metadata.etag\n ? createHash(\"sha256\")\n .update(JSON.stringify([metadata.etag, metadata.size, metadata.lastModified?.getTime()]))\n .digest(\"hex\")\n : undefined;\n const activeKey = JSON.stringify([\n disk.root,\n sourcePath,\n metadataGeneration,\n images.maxSourceBytes,\n images.maxSourcePixels,\n ]);\n const existing = activeSources.get(activeKey);\n if (existing) {\n existing.references++;\n return existing.source;\n }\n let loaded: Promise<LoadedRemoteSource> | undefined;\n async function load() {\n const stream = await disk.driver.getStream(objectPath);\n const chunks: Buffer[] = [];\n let size = 0;\n try {\n for await (const chunk of stream) {\n const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n size += bytes.length;\n if (size > images.maxSourceBytes)\n throw new HttpError(413, \"The source image is too large.\");\n chunks.push(bytes);\n }\n } finally {\n stream.destroy();\n }\n const buffer = Buffer.concat(chunks);\n const sourceFormat = detectImageFormat(buffer);\n if (!isVariantSourceFormat(sourceFormat))\n throw new HttpError(415, \"Variants are only available for jpeg, png, webp and avif images.\");\n const image = await loadVariantSource(buffer, {\n maxSourceBytes: images.maxSourceBytes,\n maxSourcePixels: images.maxSourcePixels,\n expectedFormat: sourceFormat,\n });\n return {\n image,\n sourceFormat,\n generation: metadataGeneration ?? createHash(\"sha256\").update(buffer).digest(\"hex\"),\n };\n }\n const source: RemoteVariantSource = {\n relativePath,\n sourcePath,\n metadataGeneration,\n load: () => (loaded ??= load()),\n release() {\n const active = activeSources.get(activeKey);\n if (active && --active.references === 0) activeSources.delete(activeKey);\n },\n };\n activeSources.set(activeKey, { source, references: 1 });\n return source;\n}\n"],"mappings":"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"}
@@ -1,12 +1,11 @@
1
1
  import { StorageDriverName } from "../../storage/types.mjs";
2
2
  import { VariantOutputFormat } from "./image-variant-types.mjs";
3
-
4
3
  //#region ../../packages/core/src/http/uploads/resolve-image-variant.d.ts
5
4
  /**
6
- * What to render: a file on a local disk and a variant named in
5
+ * What to render: a file on a storage disk and a variant named in
7
6
  * `uploads.images.variants`
8
7
  */
9
- type ResolveImageVariantInput = {
8
+ export type ResolveImageVariantInput = {
10
9
  /**
11
10
  * Path of the source, relative to the disk root
12
11
  */
@@ -21,14 +20,14 @@ type ResolveImageVariantInput = {
21
20
  */
22
21
  format?: VariantOutputFormat;
23
22
  /**
24
- * Local disk the source lives on; the default disk when omitted
23
+ * Disk the source lives on; the default disk when omitted
25
24
  */
26
25
  disk?: StorageDriverName;
27
26
  };
28
27
  /**
29
28
  * A derivative on disk, ready to send
30
29
  */
31
- type ResolvedImageVariant = {
30
+ export type ResolvedImageVariant = {
32
31
  /**
33
32
  * Absolute path of the cached derivative
34
33
  */
@@ -41,7 +40,7 @@ type ResolvedImageVariant = {
41
40
  contentType: string;
42
41
  };
43
42
  /**
44
- * Resolve, and render on a cache miss, one variant of an image on a local
43
+ * Resolve, and render on a cache miss, one variant of an image on a storage
45
44
  * disk. This is what `uploadedFileController` serves; call it from your own
46
45
  * route to serve variants of a private disk behind authentication:
47
46
  *
@@ -61,13 +60,11 @@ type ResolvedImageVariant = {
61
60
  * are pruned once a new derivative is written.
62
61
  *
63
62
  * @returns `undefined` when the path does not resolve to a file on the disk
64
- * @throws ImageVariantsConfigError when the disk is not a local disk
65
63
  * @throws HttpError(400) when variants are not configured, or the variant or
66
64
  * format is not allowed
67
65
  * @throws HttpError(413) when the source is over the configured limits
68
66
  * @throws HttpError(415) when the source is not jpeg, png, webp or avif
69
67
  */
70
- declare function resolveImageVariant(input: ResolveImageVariantInput): Promise<ResolvedImageVariant | undefined>;
68
+ export declare function resolveImageVariant(input: ResolveImageVariantInput): Promise<ResolvedImageVariant | undefined>;
71
69
  //#endregion
72
- export { ResolveImageVariantInput, ResolvedImageVariant, resolveImageVariant };
73
70
  //# sourceMappingURL=resolve-image-variant.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-image-variant.d.mts","names":[],"sources":["../../../../../../../../../packages/core/src/http/uploads/resolve-image-variant.ts"],"mappings":";;;;;;AAoCA;;KAAY,wBAAA;EAoBc;;;EAhBxB,IAAA;EAWS;;;EANT,OAAA;EAWwB;AAM1B;;;EAXE,MAAA,GAAS,mBAAA;EAeT;;;EAVA,IAAA,GAAO,iBAAiB;AAAA;;AAmBb;AAwCb;KArDY,oBAAA;;;;EAIV,YAAA;EAmDQ;;;EA9CR,IAAA;EAEA,MAAA,EAAQ,mBAAmB;EAE3B,WAAA;AAAA;AA0C6B;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iBAFT,mBAAA,CACpB,KAAA,EAAO,wBAAA,GACN,OAAA,CAAQ,oBAAA"}
1
+ {"version":3,"file":"resolve-image-variant.d.mts","names":[],"sources":["../../../../../../../../../packages/core/src/http/uploads/resolve-image-variant.ts"],"mappings":";;;;;;;YAoCY;;;;EAIV;;;;EAKA;;;;;EAMA,SAAS;;;;EAKT,OAAO;;;;;YAMG;;;;EAIV;;;;EAKA;EAEA,QAAQ;EAER;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBA6BoB,oBACpB,OAAO,2BACN,QAAQ"}
@@ -2,14 +2,14 @@ import { HttpError } from "../errors/errors.mjs";
2
2
  import { uploadsConfig } from "../uploads-config.mjs";
3
3
  import { variantCacheKey, variantCachePath, variantGenerationTag, variantSourceDirectory, variantSourceKey } from "./variant-cache-key.mjs";
4
4
  import { pruneStaleVariantGenerationsIfCurrent, retryOnVanishedDirectory, warnIfVariantCacheIsPublic } from "./image-variant-cache.mjs";
5
- import { generateImageVariant } from "./generate-image-variant.mjs";
6
- import { ImageVariantsConfigError } from "./image-variants-config-error.mjs";
5
+ import { localDiskRoot } from "./local-disk-root.mjs";
7
6
  import { loadVariantSource } from "./load-variant-source.mjs";
7
+ import { generateImageVariant } from "./generate-image-variant.mjs";
8
8
  import { resolveImageVariantsConfig } from "./resolve-image-variants-config.mjs";
9
- import { resolveVariantCandidate } from "./resolve-variant-candidate.mjs";
9
+ import { freshImageVariant, scheduleImageVariantCacheTrim } from "./trim-image-variant-cache.mjs";
10
10
  import { variantGenerations } from "./variant-generations.mjs";
11
- import { localDiskRoot } from "./local-disk-root.mjs";
12
- import fs from "node:fs/promises";
11
+ import { resolveRemoteImageVariant } from "./resolve-remote-image-variant.mjs";
12
+ import { resolveVariantCandidate } from "./resolve-variant-candidate.mjs";
13
13
 
14
14
  //#region ../../packages/core/src/http/uploads/resolve-image-variant.ts
15
15
  const CONTENT_TYPES = {
@@ -18,16 +18,8 @@ const CONTENT_TYPES = {
18
18
  webp: "image/webp",
19
19
  avif: "image/avif"
20
20
  };
21
- async function exists(target) {
22
- try {
23
- await fs.access(target);
24
- return true;
25
- } catch {
26
- return false;
27
- }
28
- }
29
21
  /**
30
- * Resolve, and render on a cache miss, one variant of an image on a local
22
+ * Resolve, and render on a cache miss, one variant of an image on a storage
31
23
  * disk. This is what `uploadedFileController` serves; call it from your own
32
24
  * route to serve variants of a private disk behind authentication:
33
25
  *
@@ -47,7 +39,6 @@ async function exists(target) {
47
39
  * are pruned once a new derivative is written.
48
40
  *
49
41
  * @returns `undefined` when the path does not resolve to a file on the disk
50
- * @throws ImageVariantsConfigError when the disk is not a local disk
51
42
  * @throws HttpError(400) when variants are not configured, or the variant or
52
43
  * format is not allowed
53
44
  * @throws HttpError(413) when the source is over the configured limits
@@ -55,7 +46,7 @@ async function exists(target) {
55
46
  */
56
47
  async function resolveImageVariant(input) {
57
48
  const diskRoot = localDiskRoot(input.disk);
58
- if (!diskRoot) throw new ImageVariantsConfigError(input.disk === void 0 ? "Image variants need a local storage driver with a root." : `Image variants need a local disk; "${input.disk}" is not one.`);
49
+ if (!diskRoot) return resolveRemoteImageVariant(input);
59
50
  const images = resolveImageVariantsConfig(uploadsConfig("images"), diskRoot);
60
51
  if (!images) throw new HttpError(400, "Image variants are not configured.");
61
52
  const variant = Object.prototype.hasOwnProperty.call(images.variants, input.variant) ? images.variants[input.variant] : void 0;
@@ -79,8 +70,8 @@ async function resolveImageVariant(input) {
79
70
  sourceKey,
80
71
  generation
81
72
  }, hash, format);
82
- if (!await exists(target)) await variantGenerations.run(target, async () => {
83
- if (await exists(target)) return;
73
+ if (!await freshImageVariant(target, images.maxCacheAge)) await variantGenerations.run(target, async () => {
74
+ if (await freshImageVariant(target, images.maxCacheAge)) return;
84
75
  const image = await loadVariantSource(source.absolutePath, {
85
76
  maxSourceBytes: images.maxSourceBytes,
86
77
  maxSourcePixels: images.maxSourcePixels,
@@ -92,6 +83,7 @@ async function resolveImageVariant(input) {
92
83
  format,
93
84
  targetPath: target
94
85
  }));
86
+ scheduleImageVariantCacheTrim(images, target);
95
87
  await pruneStaleVariantGenerationsIfCurrent(source.absolutePath, variantSourceDirectory(images.cacheDirectory, sourceKey), generation);
96
88
  });
97
89
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-image-variant.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/http/uploads/resolve-image-variant.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport type { StorageDriverName } from \"../../storage/types\";\nimport { HttpError } from \"../errors\";\nimport { uploadsConfig } from \"../uploads-config\";\nimport { generateImageVariant } from \"./generate-image-variant\";\nimport {\n pruneStaleVariantGenerationsIfCurrent,\n retryOnVanishedDirectory,\n warnIfVariantCacheIsPublic,\n} from \"./image-variant-cache\";\nimport { ImageVariantsConfigError } from \"./image-variants-config-error\";\nimport type { VariantOutputFormat } from \"./image-variant-types\";\nimport { loadVariantSource } from \"./load-variant-source\";\nimport { localDiskRoot } from \"./local-disk-root\";\nimport { resolveImageVariantsConfig } from \"./resolve-image-variants-config\";\nimport { resolveVariantCandidate } from \"./resolve-variant-candidate\";\nimport {\n variantCacheKey,\n variantCachePath,\n variantGenerationTag,\n variantSourceDirectory,\n variantSourceKey,\n} from \"./variant-cache-key\";\nimport { variantGenerations } from \"./variant-generations\";\n\nconst CONTENT_TYPES: Record<VariantOutputFormat, string> = {\n jpeg: \"image/jpeg\",\n png: \"image/png\",\n webp: \"image/webp\",\n avif: \"image/avif\",\n};\n\n/**\n * What to render: a file on a local disk and a variant named in\n * `uploads.images.variants`\n */\nexport type ResolveImageVariantInput = {\n /**\n * Path of the source, relative to the disk root\n */\n path: string;\n\n /**\n * Variant name from `uploads.images.variants`\n */\n variant: string;\n\n /**\n * Output format; defaults to the source's own format. Must be the source\n * format or one listed in `uploads.images.formats`.\n */\n format?: VariantOutputFormat;\n\n /**\n * Local disk the source lives on; the default disk when omitted\n */\n disk?: StorageDriverName;\n};\n\n/**\n * A derivative on disk, ready to send\n */\nexport type ResolvedImageVariant = {\n /**\n * Absolute path of the cached derivative\n */\n absolutePath: string;\n\n /**\n * sha256 of everything the derivative depends on; a strong ETag value\n */\n hash: string;\n\n format: VariantOutputFormat;\n\n contentType: string;\n};\n\nasync function exists(target: string): Promise<boolean> {\n try {\n await fs.access(target);\n\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Resolve, and render on a cache miss, one variant of an image on a local\n * disk. This is what `uploadedFileController` serves; call it from your own\n * route to serve variants of a private disk behind authentication:\n *\n * ```ts\n * const variant = await resolveImageVariant({ disk: \"private\", path, variant: \"thumb\" });\n * if (!variant) return response.notFound();\n * return response.sendBuffer(await fs.readFile(variant.absolutePath), {\n * contentType: variant.contentType,\n * });\n * ```\n *\n * The same guards apply as on the public route: the path must stay inside\n * the disk root and outside the derivative cache, the source must be a\n * jpeg/png/webp/avif within `maxSourceBytes`/`maxSourcePixels`, and only\n * declared variants and formats render. Derivatives are generated once per\n * key, even under concurrent calls, and older versions of a rewritten source\n * are pruned once a new derivative is written.\n *\n * @returns `undefined` when the path does not resolve to a file on the disk\n * @throws ImageVariantsConfigError when the disk is not a local disk\n * @throws HttpError(400) when variants are not configured, or the variant or\n * format is not allowed\n * @throws HttpError(413) when the source is over the configured limits\n * @throws HttpError(415) when the source is not jpeg, png, webp or avif\n */\nexport async function resolveImageVariant(\n input: ResolveImageVariantInput,\n): Promise<ResolvedImageVariant | undefined> {\n const diskRoot = localDiskRoot(input.disk);\n\n if (!diskRoot) {\n throw new ImageVariantsConfigError(\n input.disk === undefined\n ? \"Image variants need a local storage driver with a root.\"\n : `Image variants need a local disk; \"${input.disk}\" is not one.`,\n );\n }\n\n const images = resolveImageVariantsConfig(uploadsConfig(\"images\"), diskRoot);\n\n if (!images) {\n throw new HttpError(400, \"Image variants are not configured.\");\n }\n\n const variant = Object.prototype.hasOwnProperty.call(images.variants, input.variant)\n ? images.variants[input.variant]\n : undefined;\n\n if (variant === undefined) {\n throw new HttpError(400, `Unknown variant \"${input.variant}\".`);\n }\n\n if (input.format !== undefined && !images.formats.includes(input.format as never)) {\n throw new HttpError(400, `Format \"${input.format}\" is not allowed.`);\n }\n\n warnIfVariantCacheIsPublic(images.cacheDirectory);\n\n const candidate = await resolveVariantCandidate(input.path, diskRoot, images);\n\n if (!candidate) return undefined;\n\n const { source, stats, sourceFormat } = candidate;\n const format: VariantOutputFormat = input.format ?? sourceFormat;\n const hash = variantCacheKey({\n relativePath: source.relativePath,\n sourceSize: stats.size,\n sourceMtimeMs: stats.mtimeMs,\n variant,\n format,\n });\n const sourceKey = variantSourceKey(source.root, source.relativePath);\n const generation = variantGenerationTag(stats.size, stats.mtimeMs);\n const target = variantCachePath(images.cacheDirectory, { sourceKey, generation }, hash, format);\n\n if (!(await exists(target))) {\n // Keyed on the target path, which includes the disk's real root: the\n // same file on two disks (a mirror copied with its mtime) has the same\n // `hash`, and joining the other disk's flight would leave this target\n // unwritten.\n await variantGenerations.run(target, async () => {\n if (await exists(target)) return;\n\n const image = await loadVariantSource(source.absolutePath, {\n maxSourceBytes: images.maxSourceBytes,\n maxSourcePixels: images.maxSourcePixels,\n expectedFormat: sourceFormat,\n });\n\n await retryOnVanishedDirectory(() =>\n generateImageVariant({ image: image.clone(), variant, format, targetPath: target }),\n );\n await pruneStaleVariantGenerationsIfCurrent(\n source.absolutePath,\n variantSourceDirectory(images.cacheDirectory, sourceKey),\n generation,\n );\n });\n }\n\n return { absolutePath: target, hash, format, contentType: CONTENT_TYPES[format] };\n}\n"],"mappings":";;;;;;;;;;;;;;AAyBA,MAAM,gBAAqD;CACzD,MAAM;CACN,KAAK;CACL,MAAM;CACN,MAAM;AACR;AAgDA,eAAe,OAAO,QAAkC;CACtD,IAAI;EACF,MAAM,GAAG,OAAO,MAAM;EAEtB,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,eAAsB,oBACpB,OAC2C;CAC3C,MAAM,WAAW,cAAc,MAAM,IAAI;CAEzC,IAAI,CAAC,UACH,MAAM,IAAI,yBACR,MAAM,SAAS,SACX,4DACA,sCAAsC,MAAM,KAAK,cACvD;CAGF,MAAM,SAAS,2BAA2B,cAAc,QAAQ,GAAG,QAAQ;CAE3E,IAAI,CAAC,QACH,MAAM,IAAI,UAAU,KAAK,oCAAoC;CAG/D,MAAM,UAAU,OAAO,UAAU,eAAe,KAAK,OAAO,UAAU,MAAM,OAAO,IAC/E,OAAO,SAAS,MAAM,WACtB;CAEJ,IAAI,YAAY,QACd,MAAM,IAAI,UAAU,KAAK,oBAAoB,MAAM,QAAQ,GAAG;CAGhE,IAAI,MAAM,WAAW,UAAa,CAAC,OAAO,QAAQ,SAAS,MAAM,MAAe,GAC9E,MAAM,IAAI,UAAU,KAAK,WAAW,MAAM,OAAO,kBAAkB;CAGrE,2BAA2B,OAAO,cAAc;CAEhD,MAAM,YAAY,MAAM,wBAAwB,MAAM,MAAM,UAAU,MAAM;CAE5E,IAAI,CAAC,WAAW,OAAO;CAEvB,MAAM,EAAE,QAAQ,OAAO,iBAAiB;CACxC,MAAM,SAA8B,MAAM,UAAU;CACpD,MAAM,OAAO,gBAAgB;EAC3B,cAAc,OAAO;EACrB,YAAY,MAAM;EAClB,eAAe,MAAM;EACrB;EACA;CACF,CAAC;CACD,MAAM,YAAY,iBAAiB,OAAO,MAAM,OAAO,YAAY;CACnE,MAAM,aAAa,qBAAqB,MAAM,MAAM,MAAM,OAAO;CACjE,MAAM,SAAS,iBAAiB,OAAO,gBAAgB;EAAE;EAAW;CAAW,GAAG,MAAM,MAAM;CAE9F,IAAI,CAAE,MAAM,OAAO,MAAM,GAKvB,MAAM,mBAAmB,IAAI,QAAQ,YAAY;EAC/C,IAAI,MAAM,OAAO,MAAM,GAAG;EAE1B,MAAM,QAAQ,MAAM,kBAAkB,OAAO,cAAc;GACzD,gBAAgB,OAAO;GACvB,iBAAiB,OAAO;GACxB,gBAAgB;EAClB,CAAC;EAED,MAAM,+BACJ,qBAAqB;GAAE,OAAO,MAAM,MAAM;GAAG;GAAS;GAAQ,YAAY;EAAO,CAAC,CACpF;EACA,MAAM,sCACJ,OAAO,cACP,uBAAuB,OAAO,gBAAgB,SAAS,GACvD,UACF;CACF,CAAC;CAGH,OAAO;EAAE,cAAc;EAAQ;EAAM;EAAQ,aAAa,cAAc;CAAQ;AAClF"}
1
+ {"version":3,"file":"resolve-image-variant.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/http/uploads/resolve-image-variant.ts"],"sourcesContent":["import type { StorageDriverName } from \"../../storage/types\";\nimport { HttpError } from \"../errors\";\nimport { uploadsConfig } from \"../uploads-config\";\nimport { generateImageVariant } from \"./generate-image-variant\";\nimport {\n pruneStaleVariantGenerationsIfCurrent,\n retryOnVanishedDirectory,\n warnIfVariantCacheIsPublic,\n} from \"./image-variant-cache\";\nimport { resolveRemoteImageVariant } from \"./resolve-remote-image-variant\";\nimport type { VariantOutputFormat } from \"./image-variant-types\";\nimport { loadVariantSource } from \"./load-variant-source\";\nimport { localDiskRoot } from \"./local-disk-root\";\nimport { resolveImageVariantsConfig } from \"./resolve-image-variants-config\";\nimport { resolveVariantCandidate } from \"./resolve-variant-candidate\";\nimport {\n variantCacheKey,\n variantCachePath,\n variantGenerationTag,\n variantSourceDirectory,\n variantSourceKey,\n} from \"./variant-cache-key\";\nimport { freshImageVariant, scheduleImageVariantCacheTrim } from \"./trim-image-variant-cache\";\nimport { variantGenerations } from \"./variant-generations\";\n\nconst CONTENT_TYPES: Record<VariantOutputFormat, string> = {\n jpeg: \"image/jpeg\",\n png: \"image/png\",\n webp: \"image/webp\",\n avif: \"image/avif\",\n};\n\n/**\n * What to render: a file on a storage disk and a variant named in\n * `uploads.images.variants`\n */\nexport type ResolveImageVariantInput = {\n /**\n * Path of the source, relative to the disk root\n */\n path: string;\n\n /**\n * Variant name from `uploads.images.variants`\n */\n variant: string;\n\n /**\n * Output format; defaults to the source's own format. Must be the source\n * format or one listed in `uploads.images.formats`.\n */\n format?: VariantOutputFormat;\n\n /**\n * Disk the source lives on; the default disk when omitted\n */\n disk?: StorageDriverName;\n};\n\n/**\n * A derivative on disk, ready to send\n */\nexport type ResolvedImageVariant = {\n /**\n * Absolute path of the cached derivative\n */\n absolutePath: string;\n\n /**\n * sha256 of everything the derivative depends on; a strong ETag value\n */\n hash: string;\n\n format: VariantOutputFormat;\n\n contentType: string;\n};\n\n/**\n * Resolve, and render on a cache miss, one variant of an image on a storage\n * disk. This is what `uploadedFileController` serves; call it from your own\n * route to serve variants of a private disk behind authentication:\n *\n * ```ts\n * const variant = await resolveImageVariant({ disk: \"private\", path, variant: \"thumb\" });\n * if (!variant) return response.notFound();\n * return response.sendBuffer(await fs.readFile(variant.absolutePath), {\n * contentType: variant.contentType,\n * });\n * ```\n *\n * The same guards apply as on the public route: the path must stay inside\n * the disk root and outside the derivative cache, the source must be a\n * jpeg/png/webp/avif within `maxSourceBytes`/`maxSourcePixels`, and only\n * declared variants and formats render. Derivatives are generated once per\n * key, even under concurrent calls, and older versions of a rewritten source\n * are pruned once a new derivative is written.\n *\n * @returns `undefined` when the path does not resolve to a file on the disk\n * @throws HttpError(400) when variants are not configured, or the variant or\n * format is not allowed\n * @throws HttpError(413) when the source is over the configured limits\n * @throws HttpError(415) when the source is not jpeg, png, webp or avif\n */\nexport async function resolveImageVariant(\n input: ResolveImageVariantInput,\n): Promise<ResolvedImageVariant | undefined> {\n const diskRoot = localDiskRoot(input.disk);\n\n if (!diskRoot) return resolveRemoteImageVariant(input);\n\n const images = resolveImageVariantsConfig(uploadsConfig(\"images\"), diskRoot);\n\n if (!images) {\n throw new HttpError(400, \"Image variants are not configured.\");\n }\n\n const variant = Object.prototype.hasOwnProperty.call(images.variants, input.variant)\n ? images.variants[input.variant]\n : undefined;\n\n if (variant === undefined) {\n throw new HttpError(400, `Unknown variant \"${input.variant}\".`);\n }\n\n if (input.format !== undefined && !images.formats.includes(input.format as never)) {\n throw new HttpError(400, `Format \"${input.format}\" is not allowed.`);\n }\n\n warnIfVariantCacheIsPublic(images.cacheDirectory);\n\n const candidate = await resolveVariantCandidate(input.path, diskRoot, images);\n\n if (!candidate) return undefined;\n\n const { source, stats, sourceFormat } = candidate;\n const format: VariantOutputFormat = input.format ?? sourceFormat;\n const hash = variantCacheKey({\n relativePath: source.relativePath,\n sourceSize: stats.size,\n sourceMtimeMs: stats.mtimeMs,\n variant,\n format,\n });\n const sourceKey = variantSourceKey(source.root, source.relativePath);\n const generation = variantGenerationTag(stats.size, stats.mtimeMs);\n const target = variantCachePath(images.cacheDirectory, { sourceKey, generation }, hash, format);\n\n if (!(await freshImageVariant(target, images.maxCacheAge))) {\n // Keyed on the target path, which includes the disk's real root: the\n // same file on two disks (a mirror copied with its mtime) has the same\n // `hash`, and joining the other disk's flight would leave this target\n // unwritten.\n await variantGenerations.run(target, async () => {\n if (await freshImageVariant(target, images.maxCacheAge)) return;\n\n const image = await loadVariantSource(source.absolutePath, {\n maxSourceBytes: images.maxSourceBytes,\n maxSourcePixels: images.maxSourcePixels,\n expectedFormat: sourceFormat,\n });\n\n await retryOnVanishedDirectory(() =>\n generateImageVariant({ image: image.clone(), variant, format, targetPath: target }),\n );\n scheduleImageVariantCacheTrim(images, target);\n await pruneStaleVariantGenerationsIfCurrent(\n source.absolutePath,\n variantSourceDirectory(images.cacheDirectory, sourceKey),\n generation,\n );\n });\n }\n\n return { absolutePath: target, hash, format, contentType: CONTENT_TYPES[format] };\n}\n"],"mappings":";;;;;;;;;;;;;;AAyBA,MAAM,gBAAqD;CACzD,MAAM;CACN,KAAK;CACL,MAAM;CACN,MAAM;AACR;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0EA,eAAsB,oBACpB,OAC2C;CAC3C,MAAM,WAAW,cAAc,MAAM,IAAI;CAEzC,IAAI,CAAC,UAAU,OAAO,0BAA0B,KAAK;CAErD,MAAM,SAAS,2BAA2B,cAAc,QAAQ,GAAG,QAAQ;CAE3E,IAAI,CAAC,QACH,MAAM,IAAI,UAAU,KAAK,oCAAoC;CAG/D,MAAM,UAAU,OAAO,UAAU,eAAe,KAAK,OAAO,UAAU,MAAM,OAAO,IAC/E,OAAO,SAAS,MAAM,WACtB;CAEJ,IAAI,YAAY,QACd,MAAM,IAAI,UAAU,KAAK,oBAAoB,MAAM,QAAQ,GAAG;CAGhE,IAAI,MAAM,WAAW,UAAa,CAAC,OAAO,QAAQ,SAAS,MAAM,MAAe,GAC9E,MAAM,IAAI,UAAU,KAAK,WAAW,MAAM,OAAO,kBAAkB;CAGrE,2BAA2B,OAAO,cAAc;CAEhD,MAAM,YAAY,MAAM,wBAAwB,MAAM,MAAM,UAAU,MAAM;CAE5E,IAAI,CAAC,WAAW,OAAO;CAEvB,MAAM,EAAE,QAAQ,OAAO,iBAAiB;CACxC,MAAM,SAA8B,MAAM,UAAU;CACpD,MAAM,OAAO,gBAAgB;EAC3B,cAAc,OAAO;EACrB,YAAY,MAAM;EAClB,eAAe,MAAM;EACrB;EACA;CACF,CAAC;CACD,MAAM,YAAY,iBAAiB,OAAO,MAAM,OAAO,YAAY;CACnE,MAAM,aAAa,qBAAqB,MAAM,MAAM,MAAM,OAAO;CACjE,MAAM,SAAS,iBAAiB,OAAO,gBAAgB;EAAE;EAAW;CAAW,GAAG,MAAM,MAAM;CAE9F,IAAI,CAAE,MAAM,kBAAkB,QAAQ,OAAO,WAAW,GAKtD,MAAM,mBAAmB,IAAI,QAAQ,YAAY;EAC/C,IAAI,MAAM,kBAAkB,QAAQ,OAAO,WAAW,GAAG;EAEzD,MAAM,QAAQ,MAAM,kBAAkB,OAAO,cAAc;GACzD,gBAAgB,OAAO;GACvB,iBAAiB,OAAO;GACxB,gBAAgB;EAClB,CAAC;EAED,MAAM,+BACJ,qBAAqB;GAAE,OAAO,MAAM,MAAM;GAAG;GAAS;GAAQ,YAAY;EAAO,CAAC,CACpF;EACA,8BAA8B,QAAQ,MAAM;EAC5C,MAAM,sCACJ,OAAO,cACP,uBAAuB,OAAO,gBAAgB,SAAS,GACvD,UACF;CACF,CAAC;CAGH,OAAO;EAAE,cAAc;EAAQ;EAAM;EAAQ,aAAa,cAAc;CAAQ;AAClF"}
@@ -1,5 +1,5 @@
1
1
  import { ImageVariantsConfigError } from "./image-variants-config-error.mjs";
2
- import path from "node:path";
2
+ import { variantCacheDirectoryFor } from "./image-variant-cache.mjs";
3
3
 
4
4
  //#region ../../packages/core/src/http/uploads/resolve-image-variants-config.ts
5
5
  /**
@@ -9,7 +9,7 @@ const MAX_VARIANT_DIMENSION = 8192;
9
9
  /**
10
10
  * Default `maxSourceBytes`: 25 MB
11
11
  */
12
- const DEFAULT_MAX_SOURCE_BYTES = 25 * 1024 * 1024;
12
+ const DEFAULT_MAX_SOURCE_BYTES = 26214400;
13
13
  /**
14
14
  * Default `maxSourcePixels`
15
15
  */
@@ -76,16 +76,18 @@ function resolveImageVariantsConfig(images, storageRoot) {
76
76
  if (!rawVariants || typeof rawVariants !== "object" || Object.keys(rawVariants).length === 0) throw new ImageVariantsConfigError("uploads.images.variants must declare at least one variant.");
77
77
  const variants = {};
78
78
  for (const [name, raw] of Object.entries(rawVariants)) variants[name] = resolveVariant(name, raw);
79
- const cacheDirectory = images.cacheDirectory ? path.resolve(images.cacheDirectory) : path.join(storageRoot, ".cache", "image-variants");
79
+ const cacheDirectory = variantCacheDirectoryFor(storageRoot, images);
80
80
  return {
81
81
  variants,
82
82
  formats: resolveFormats(images.formats),
83
83
  maxSourceBytes: resolveLimit("maxSourceBytes", images.maxSourceBytes, DEFAULT_MAX_SOURCE_BYTES),
84
84
  maxSourcePixels: resolveLimit("maxSourcePixels", images.maxSourcePixels, DEFAULT_MAX_SOURCE_PIXELS),
85
- cacheDirectory
85
+ cacheDirectory,
86
+ maxCacheBytes: resolveLimit("maxCacheBytes", images.maxCacheBytes, 536870912),
87
+ maxCacheAge: resolveLimit("maxCacheAge", images.maxCacheAge, 604800)
86
88
  };
87
89
  }
88
90
 
89
91
  //#endregion
90
- export { resolveImageVariantsConfig };
92
+ export { DEFAULT_MAX_SOURCE_BYTES, DEFAULT_MAX_SOURCE_PIXELS, MAX_VARIANT_DIMENSION, resolveImageVariantsConfig };
91
93
  //# sourceMappingURL=resolve-image-variants-config.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-image-variants-config.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/http/uploads/resolve-image-variants-config.ts"],"sourcesContent":["import path from \"node:path\";\nimport type {\n ImageVariantDefinition,\n ImageVariantFit,\n ImageVariantOutputFormat,\n UploadsImagesConfigurations,\n} from \"../uploads-types\";\nimport { ImageVariantsConfigError } from \"./image-variants-config-error\";\nimport type { ResolvedImageVariantsConfig } from \"./image-variant-types\";\n\n/**\n * Largest width or height a variant may declare\n */\nexport const MAX_VARIANT_DIMENSION = 8192;\n\n/**\n * Default `maxSourceBytes`: 25 MB\n */\nexport const DEFAULT_MAX_SOURCE_BYTES = 25 * 1024 * 1024;\n\n/**\n * Default `maxSourcePixels`\n */\nexport const DEFAULT_MAX_SOURCE_PIXELS = 40_000_000;\n\nconst FITS: readonly ImageVariantFit[] = [\"cover\", \"contain\", \"inside\"];\n\nconst OUTPUT_FORMATS: readonly ImageVariantOutputFormat[] = [\"avif\", \"webp\"];\n\nconst VARIANT_NAME = /^[A-Za-z0-9_-]+$/;\n\nfunction isPositiveInteger(value: unknown, max = Number.MAX_SAFE_INTEGER): value is number {\n return typeof value === \"number\" && Number.isInteger(value) && value >= 1 && value <= max;\n}\n\nfunction resolveVariant(name: string, raw: unknown): ImageVariantDefinition {\n const key = `uploads.images.variants.${name}`;\n\n if (!VARIANT_NAME.test(name)) {\n throw new ImageVariantsConfigError(\n `${key}: a variant name may only use letters, digits, \"-\" and \"_\".`,\n );\n }\n\n if (!raw || typeof raw !== \"object\") {\n throw new ImageVariantsConfigError(`${key} must be an object with a width.`);\n }\n\n const { width, height, fit, quality, enlarge } = raw as Record<string, unknown>;\n\n if (!isPositiveInteger(width, MAX_VARIANT_DIMENSION)) {\n throw new ImageVariantsConfigError(\n `${key}.width must be an integer from 1 to ${MAX_VARIANT_DIMENSION}, got ${JSON.stringify(width)}.`,\n );\n }\n\n const variant: ImageVariantDefinition = { width };\n\n if (height !== undefined) {\n if (!isPositiveInteger(height, MAX_VARIANT_DIMENSION)) {\n throw new ImageVariantsConfigError(\n `${key}.height must be an integer from 1 to ${MAX_VARIANT_DIMENSION}, got ${JSON.stringify(height)}.`,\n );\n }\n\n variant.height = height;\n }\n\n if (fit !== undefined) {\n if (!FITS.includes(fit as ImageVariantFit)) {\n throw new ImageVariantsConfigError(\n `${key}.fit must be one of ${FITS.join(\", \")}, got ${JSON.stringify(fit)}.`,\n );\n }\n\n variant.fit = fit as ImageVariantFit;\n }\n\n if (quality !== undefined) {\n if (!isPositiveInteger(quality, 100)) {\n throw new ImageVariantsConfigError(\n `${key}.quality must be an integer from 1 to 100, got ${JSON.stringify(quality)}.`,\n );\n }\n\n variant.quality = quality;\n }\n\n if (enlarge !== undefined && typeof enlarge !== \"boolean\") {\n throw new ImageVariantsConfigError(\n `${key}.enlarge must be a boolean, got ${JSON.stringify(enlarge)}.`,\n );\n }\n\n // Always set, never left undefined: the effective flag (default false) is\n // part of the normalized variant, so toggling it changes the cache key.\n variant.enlarge = enlarge === true;\n\n return variant;\n}\n\nfunction resolveFormats(raw: unknown): readonly ImageVariantOutputFormat[] {\n if (raw === undefined) return [];\n\n if (!Array.isArray(raw)) {\n throw new ImageVariantsConfigError(`uploads.images.formats must be an array.`);\n }\n\n for (const format of raw) {\n if (!OUTPUT_FORMATS.includes(format)) {\n throw new ImageVariantsConfigError(\n `uploads.images.formats may only contain ${OUTPUT_FORMATS.join(\", \")}, got ${JSON.stringify(format)}.`,\n );\n }\n }\n\n return [...new Set(raw as ImageVariantOutputFormat[])];\n}\n\nfunction resolveLimit(name: string, raw: unknown, fallback: number): number {\n if (raw === undefined) return fallback;\n\n if (!isPositiveInteger(raw)) {\n throw new ImageVariantsConfigError(\n `uploads.images.${name} must be a positive integer, got ${JSON.stringify(raw)}.`,\n );\n }\n\n return raw;\n}\n\n/**\n * Validate the `uploads.images` config and apply its defaults.\n *\n * Every variant is copied field by field, so an unknown key in the config can\n * never reach sharp, and the result is what the cache key is computed from.\n *\n * @param images - the raw `uploads.images` value\n * @param storageRoot - the local storage root, base of the default cache directory\n * @returns the resolved config, or `undefined` when variants are not configured\n * @throws ImageVariantsConfigError when any value is out of bounds\n */\nexport function resolveImageVariantsConfig(\n images: UploadsImagesConfigurations | undefined,\n storageRoot: string,\n): ResolvedImageVariantsConfig | undefined {\n if (images === undefined || images === null) return undefined;\n\n if (typeof images !== \"object\") {\n throw new ImageVariantsConfigError(\"uploads.images must be an object.\");\n }\n\n const rawVariants = (images as { variants?: unknown }).variants;\n\n if (!rawVariants || typeof rawVariants !== \"object\" || Object.keys(rawVariants).length === 0) {\n throw new ImageVariantsConfigError(\n \"uploads.images.variants must declare at least one variant.\",\n );\n }\n\n const variants: Record<string, ImageVariantDefinition> = {};\n\n for (const [name, raw] of Object.entries(rawVariants)) {\n variants[name] = resolveVariant(name, raw);\n }\n\n const cacheDirectory = images.cacheDirectory\n ? path.resolve(images.cacheDirectory)\n : path.join(storageRoot, \".cache\", \"image-variants\");\n\n return {\n variants,\n formats: resolveFormats(images.formats),\n maxSourceBytes: resolveLimit(\"maxSourceBytes\", images.maxSourceBytes, DEFAULT_MAX_SOURCE_BYTES),\n maxSourcePixels: resolveLimit(\n \"maxSourcePixels\",\n images.maxSourcePixels,\n DEFAULT_MAX_SOURCE_PIXELS,\n ),\n cacheDirectory,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"resolve-image-variants-config.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/http/uploads/resolve-image-variants-config.ts"],"sourcesContent":["import type {\n ImageVariantDefinition,\n ImageVariantFit,\n ImageVariantOutputFormat,\n UploadsImagesConfigurations,\n} from \"../uploads-types\";\nimport { variantCacheDirectoryFor } from \"./image-variant-cache\";\nimport { ImageVariantsConfigError } from \"./image-variants-config-error\";\nimport type { ResolvedImageVariantsConfig } from \"./image-variant-types\";\n\n/**\n * Largest width or height a variant may declare\n */\nexport const MAX_VARIANT_DIMENSION = 8192;\n\n/**\n * Default `maxSourceBytes`: 25 MB\n */\nexport const DEFAULT_MAX_SOURCE_BYTES = 25 * 1024 * 1024;\n\n/**\n * Default `maxSourcePixels`\n */\nexport const DEFAULT_MAX_SOURCE_PIXELS = 40_000_000;\n\nconst FITS: readonly ImageVariantFit[] = [\"cover\", \"contain\", \"inside\"];\n\nconst OUTPUT_FORMATS: readonly ImageVariantOutputFormat[] = [\"avif\", \"webp\"];\n\nconst VARIANT_NAME = /^[A-Za-z0-9_-]+$/;\n\nfunction isPositiveInteger(value: unknown, max = Number.MAX_SAFE_INTEGER): value is number {\n return typeof value === \"number\" && Number.isInteger(value) && value >= 1 && value <= max;\n}\n\nfunction resolveVariant(name: string, raw: unknown): ImageVariantDefinition {\n const key = `uploads.images.variants.${name}`;\n\n if (!VARIANT_NAME.test(name)) {\n throw new ImageVariantsConfigError(\n `${key}: a variant name may only use letters, digits, \"-\" and \"_\".`,\n );\n }\n\n if (!raw || typeof raw !== \"object\") {\n throw new ImageVariantsConfigError(`${key} must be an object with a width.`);\n }\n\n const { width, height, fit, quality, enlarge } = raw as Record<string, unknown>;\n\n if (!isPositiveInteger(width, MAX_VARIANT_DIMENSION)) {\n throw new ImageVariantsConfigError(\n `${key}.width must be an integer from 1 to ${MAX_VARIANT_DIMENSION}, got ${JSON.stringify(width)}.`,\n );\n }\n\n const variant: ImageVariantDefinition = { width };\n\n if (height !== undefined) {\n if (!isPositiveInteger(height, MAX_VARIANT_DIMENSION)) {\n throw new ImageVariantsConfigError(\n `${key}.height must be an integer from 1 to ${MAX_VARIANT_DIMENSION}, got ${JSON.stringify(height)}.`,\n );\n }\n\n variant.height = height;\n }\n\n if (fit !== undefined) {\n if (!FITS.includes(fit as ImageVariantFit)) {\n throw new ImageVariantsConfigError(\n `${key}.fit must be one of ${FITS.join(\", \")}, got ${JSON.stringify(fit)}.`,\n );\n }\n\n variant.fit = fit as ImageVariantFit;\n }\n\n if (quality !== undefined) {\n if (!isPositiveInteger(quality, 100)) {\n throw new ImageVariantsConfigError(\n `${key}.quality must be an integer from 1 to 100, got ${JSON.stringify(quality)}.`,\n );\n }\n\n variant.quality = quality;\n }\n\n if (enlarge !== undefined && typeof enlarge !== \"boolean\") {\n throw new ImageVariantsConfigError(\n `${key}.enlarge must be a boolean, got ${JSON.stringify(enlarge)}.`,\n );\n }\n\n // Always set, never left undefined: the effective flag (default false) is\n // part of the normalized variant, so toggling it changes the cache key.\n variant.enlarge = enlarge === true;\n\n return variant;\n}\n\nfunction resolveFormats(raw: unknown): readonly ImageVariantOutputFormat[] {\n if (raw === undefined) return [];\n\n if (!Array.isArray(raw)) {\n throw new ImageVariantsConfigError(`uploads.images.formats must be an array.`);\n }\n\n for (const format of raw) {\n if (!OUTPUT_FORMATS.includes(format)) {\n throw new ImageVariantsConfigError(\n `uploads.images.formats may only contain ${OUTPUT_FORMATS.join(\", \")}, got ${JSON.stringify(format)}.`,\n );\n }\n }\n\n return [...new Set(raw as ImageVariantOutputFormat[])];\n}\n\nfunction resolveLimit(name: string, raw: unknown, fallback: number): number {\n if (raw === undefined) return fallback;\n\n if (!isPositiveInteger(raw)) {\n throw new ImageVariantsConfigError(\n `uploads.images.${name} must be a positive integer, got ${JSON.stringify(raw)}.`,\n );\n }\n\n return raw;\n}\n\n/**\n * Validate the `uploads.images` config and apply its defaults.\n *\n * Every variant is copied field by field, so an unknown key in the config can\n * never reach sharp, and the result is what the cache key is computed from.\n *\n * @param images - the raw `uploads.images` value\n * @param storageRoot - the local storage root, base of the default cache directory\n * @returns the resolved config, or `undefined` when variants are not configured\n * @throws ImageVariantsConfigError when any value is out of bounds\n */\nexport function resolveImageVariantsConfig(\n images: UploadsImagesConfigurations | undefined,\n storageRoot: string,\n): ResolvedImageVariantsConfig | undefined {\n if (images === undefined || images === null) return undefined;\n\n if (typeof images !== \"object\") {\n throw new ImageVariantsConfigError(\"uploads.images must be an object.\");\n }\n\n const rawVariants = (images as { variants?: unknown }).variants;\n\n if (!rawVariants || typeof rawVariants !== \"object\" || Object.keys(rawVariants).length === 0) {\n throw new ImageVariantsConfigError(\n \"uploads.images.variants must declare at least one variant.\",\n );\n }\n\n const variants: Record<string, ImageVariantDefinition> = {};\n\n for (const [name, raw] of Object.entries(rawVariants)) {\n variants[name] = resolveVariant(name, raw);\n }\n\n const cacheDirectory = variantCacheDirectoryFor(storageRoot, images);\n\n return {\n variants,\n formats: resolveFormats(images.formats),\n maxSourceBytes: resolveLimit(\"maxSourceBytes\", images.maxSourceBytes, DEFAULT_MAX_SOURCE_BYTES),\n maxSourcePixels: resolveLimit(\n \"maxSourcePixels\",\n images.maxSourcePixels,\n DEFAULT_MAX_SOURCE_PIXELS,\n ),\n cacheDirectory,\n maxCacheBytes: resolveLimit(\"maxCacheBytes\", images.maxCacheBytes, 512 * 1024 * 1024),\n maxCacheAge: resolveLimit(\"maxCacheAge\", images.maxCacheAge, 7 * 24 * 60 * 60),\n };\n}\n"],"mappings":"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"}
@@ -8,7 +8,7 @@ import mime from "mime";
8
8
  * upload served under its real type is stored XSS the moment it is fetched
9
9
  * from the app's own origin.
10
10
  */
11
- const INLINE_EXECUTABLE_MIME_TYPES = new Set([
11
+ const INLINE_EXECUTABLE_MIME_TYPES = /* @__PURE__ */ new Set([
12
12
  "image/svg+xml",
13
13
  "text/html",
14
14
  "application/xhtml+xml",
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-original-content-type.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/http/uploads/resolve-original-content-type.ts"],"sourcesContent":["import mime from \"mime\";\n\n/**\n * Extension-derived MIME types that are never safe to advertise as-is: a\n * browser that trusts one of these will parse and execute the response body\n * (inline `<script>` in an svg, markup and script in html/xhtml/xml), so an\n * upload served under its real type is stored XSS the moment it is fetched\n * from the app's own origin.\n */\nconst INLINE_EXECUTABLE_MIME_TYPES = new Set([\n \"image/svg+xml\",\n \"text/html\",\n \"application/xhtml+xml\",\n \"text/xml\",\n \"application/xml\",\n]);\n\n/**\n * Content type for an upload original that is being served as an\n * `attachment` (see `uploaded-file.controller.ts`): the extension-derived\n * type, except the svg/html/xml family, which is downgraded to\n * `application/octet-stream` so a browser never sniffs or renders it.\n */\nexport function resolveOriginalContentType(filePath: string): string {\n const type = mime.getType(filePath) || \"application/octet-stream\";\n\n return INLINE_EXECUTABLE_MIME_TYPES.has(type) ? \"application/octet-stream\" : type;\n}\n"],"mappings":";;;;;;;;;;AASA,MAAM,+BAA+B,IAAI,IAAI;CAC3C;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;AAQD,SAAgB,2BAA2B,UAA0B;CACnE,MAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK;CAEvC,OAAO,6BAA6B,IAAI,IAAI,IAAI,6BAA6B;AAC/E"}
1
+ {"version":3,"file":"resolve-original-content-type.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/http/uploads/resolve-original-content-type.ts"],"sourcesContent":["import mime from \"mime\";\n\n/**\n * Extension-derived MIME types that are never safe to advertise as-is: a\n * browser that trusts one of these will parse and execute the response body\n * (inline `<script>` in an svg, markup and script in html/xhtml/xml), so an\n * upload served under its real type is stored XSS the moment it is fetched\n * from the app's own origin.\n */\nconst INLINE_EXECUTABLE_MIME_TYPES = new Set([\n \"image/svg+xml\",\n \"text/html\",\n \"application/xhtml+xml\",\n \"text/xml\",\n \"application/xml\",\n]);\n\n/**\n * Content type for an upload original that is being served as an\n * `attachment` (see `uploaded-file.controller.ts`): the extension-derived\n * type, except the svg/html/xml family, which is downgraded to\n * `application/octet-stream` so a browser never sniffs or renders it.\n */\nexport function resolveOriginalContentType(filePath: string): string {\n const type = mime.getType(filePath) || \"application/octet-stream\";\n\n return INLINE_EXECUTABLE_MIME_TYPES.has(type) ? \"application/octet-stream\" : type;\n}\n"],"mappings":";;;;;;;;;;AASA,MAAM,+CAA+B,IAAI,IAAI;CAC3C;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;AAQD,SAAgB,2BAA2B,UAA0B;CACnE,MAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK;CAEvC,OAAO,6BAA6B,IAAI,IAAI,IAAI,6BAA6B;AAC/E"}
@@ -0,0 +1,89 @@
1
+ import { HttpError } from "../errors/errors.mjs";
2
+ import { uploadsConfig } from "../uploads-config.mjs";
3
+ import { variantCacheKey, variantCachePath, variantSourceDirectory, variantSourceKey } from "./variant-cache-key.mjs";
4
+ import { retryOnVanishedDirectory, warnIfVariantCacheIsPublic } from "./image-variant-cache.mjs";
5
+ import { isVariantSourceFormat } from "./detect-image-format.mjs";
6
+ import { remoteVariantDisk, remoteVariantSource } from "./remote-variant-source.mjs";
7
+ import { generateImageVariant } from "./generate-image-variant.mjs";
8
+ import { resolveImageVariantsConfig } from "./resolve-image-variants-config.mjs";
9
+ import { freshImageVariant, scheduleImageVariantCacheTrim } from "./trim-image-variant-cache.mjs";
10
+ import { variantGenerations } from "./variant-generations.mjs";
11
+ import path from "node:path";
12
+ import { atomicWriteAsync } from "@warlock.js/fs";
13
+ import fs from "node:fs/promises";
14
+
15
+ //#region ../../packages/core/src/http/uploads/resolve-remote-image-variant.ts
16
+ /** Cloud sources are read through their driver; derivatives remain in a local cache. */
17
+ async function resolveRemoteImageVariant(input) {
18
+ const disk = remoteVariantDisk(input.disk);
19
+ const images = resolveImageVariantsConfig(uploadsConfig("images"), disk.cacheRoot);
20
+ if (!images) throw new HttpError(400, "Image variants are not configured.");
21
+ if (!Object.prototype.hasOwnProperty.call(images.variants, input.variant)) throw new HttpError(400, `Unknown variant "${input.variant}".`);
22
+ if (input.format !== void 0 && !images.formats.includes(input.format)) throw new HttpError(400, `Format "${input.format}" is not allowed.`);
23
+ const source = await remoteVariantSource(input.path, disk, images);
24
+ if (!source) return void 0;
25
+ try {
26
+ return await renderRemoteImageVariant(input, disk, images, source);
27
+ } finally {
28
+ source.release();
29
+ }
30
+ }
31
+ /** Ingest rendering reuses one source handle and its memoized bounded download. */
32
+ async function renderRemoteImageVariant(input, disk, images, source) {
33
+ const variant = Object.prototype.hasOwnProperty.call(images.variants, input.variant) ? images.variants[input.variant] : void 0;
34
+ if (!variant) throw new HttpError(400, `Unknown variant "${input.variant}".`);
35
+ if (input.format !== void 0 && !images.formats.includes(input.format)) throw new HttpError(400, `Format "${input.format}" is not allowed.`);
36
+ const generation = source.metadataGeneration ?? (await source.load()).generation;
37
+ const sourceKey = variantSourceKey(disk.root, source.sourcePath);
38
+ const manifestPath = path.join(variantSourceDirectory(images.cacheDirectory, sourceKey), generation, "source.json");
39
+ let format = input.format;
40
+ if (!format) {
41
+ try {
42
+ const savedFormat = JSON.parse(await fs.readFile(manifestPath, "utf8"))?.format;
43
+ if (isVariantSourceFormat(savedFormat)) format = savedFormat;
44
+ } catch (error) {
45
+ if (error.code !== "ENOENT" && !(error instanceof SyntaxError)) throw error;
46
+ }
47
+ format ??= (await source.load()).sourceFormat;
48
+ }
49
+ const hash = variantCacheKey({
50
+ relativePath: JSON.stringify([
51
+ disk.root,
52
+ source.sourcePath,
53
+ generation
54
+ ]),
55
+ sourceSize: 0,
56
+ sourceMtimeMs: 0,
57
+ variant,
58
+ format
59
+ });
60
+ const target = variantCachePath(images.cacheDirectory, {
61
+ sourceKey,
62
+ generation
63
+ }, hash, format);
64
+ warnIfVariantCacheIsPublic(images.cacheDirectory);
65
+ if (!await freshImageVariant(target, images.maxCacheAge)) await variantGenerations.run(target, async () => {
66
+ if (await freshImageVariant(target, images.maxCacheAge)) return;
67
+ const loaded = await source.load();
68
+ await retryOnVanishedDirectory(async () => {
69
+ await generateImageVariant({
70
+ image: loaded.image.clone(),
71
+ variant,
72
+ format,
73
+ targetPath: target
74
+ });
75
+ await atomicWriteAsync(manifestPath, JSON.stringify({ format: loaded.sourceFormat }));
76
+ });
77
+ scheduleImageVariantCacheTrim(images, target);
78
+ });
79
+ return {
80
+ absolutePath: target,
81
+ hash,
82
+ format,
83
+ contentType: `image/${format}`
84
+ };
85
+ }
86
+
87
+ //#endregion
88
+ export { renderRemoteImageVariant, resolveRemoteImageVariant };
89
+ //# sourceMappingURL=resolve-remote-image-variant.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-remote-image-variant.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/http/uploads/resolve-remote-image-variant.ts"],"sourcesContent":["import { atomicWriteAsync } from \"@warlock.js/fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { HttpError } from \"../errors\";\nimport { uploadsConfig } from \"../uploads-config\";\nimport { isVariantSourceFormat } from \"./detect-image-format\";\nimport { generateImageVariant } from \"./generate-image-variant\";\nimport { retryOnVanishedDirectory, warnIfVariantCacheIsPublic } from \"./image-variant-cache\";\nimport type { ResolvedImageVariantsConfig, VariantOutputFormat } from \"./image-variant-types\";\nimport {\n remoteVariantDisk,\n remoteVariantSource,\n type RemoteVariantSource,\n} from \"./remote-variant-source\";\nimport { resolveImageVariantsConfig } from \"./resolve-image-variants-config\";\nimport type { ResolveImageVariantInput, ResolvedImageVariant } from \"./resolve-image-variant\";\nimport { freshImageVariant, scheduleImageVariantCacheTrim } from \"./trim-image-variant-cache\";\nimport {\n variantCacheKey,\n variantCachePath,\n variantSourceDirectory,\n variantSourceKey,\n} from \"./variant-cache-key\";\nimport { variantGenerations } from \"./variant-generations\";\n\n/** Cloud sources are read through their driver; derivatives remain in a local cache. */\nexport async function resolveRemoteImageVariant(\n input: ResolveImageVariantInput,\n): Promise<ResolvedImageVariant | undefined> {\n const disk = remoteVariantDisk(input.disk);\n const images = resolveImageVariantsConfig(uploadsConfig(\"images\"), disk.cacheRoot);\n if (!images) throw new HttpError(400, \"Image variants are not configured.\");\n if (!Object.prototype.hasOwnProperty.call(images.variants, input.variant))\n throw new HttpError(400, `Unknown variant \"${input.variant}\".`);\n if (input.format !== undefined && !images.formats.includes(input.format as never))\n throw new HttpError(400, `Format \"${input.format}\" is not allowed.`);\n const source = await remoteVariantSource(input.path, disk, images);\n if (!source) return undefined;\n try {\n return await renderRemoteImageVariant(input, disk, images, source);\n } finally {\n source.release();\n }\n}\n\n/** Ingest rendering reuses one source handle and its memoized bounded download. */\nexport async function renderRemoteImageVariant(\n input: ResolveImageVariantInput,\n disk: ReturnType<typeof remoteVariantDisk>,\n images: ResolvedImageVariantsConfig,\n source: RemoteVariantSource,\n): Promise<ResolvedImageVariant> {\n const variant = Object.prototype.hasOwnProperty.call(images.variants, input.variant)\n ? images.variants[input.variant]\n : undefined;\n if (!variant) throw new HttpError(400, `Unknown variant \"${input.variant}\".`);\n if (input.format !== undefined && !images.formats.includes(input.format as never))\n throw new HttpError(400, `Format \"${input.format}\" is not allowed.`);\n const generation = source.metadataGeneration ?? (await source.load()).generation;\n const sourceKey = variantSourceKey(disk.root, source.sourcePath);\n const manifestPath = path.join(\n variantSourceDirectory(images.cacheDirectory, sourceKey),\n generation,\n \"source.json\",\n );\n let format: VariantOutputFormat | undefined = input.format;\n if (!format) {\n try {\n const saved: unknown = JSON.parse(await fs.readFile(manifestPath, \"utf8\"));\n const savedFormat = (saved as { format?: unknown } | null)?.format;\n if (isVariantSourceFormat(savedFormat as never)) format = savedFormat as VariantOutputFormat;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\" && !(error instanceof SyntaxError))\n throw error;\n }\n format ??= (await source.load()).sourceFormat;\n }\n const hash = variantCacheKey({\n relativePath: JSON.stringify([disk.root, source.sourcePath, generation]),\n sourceSize: 0,\n sourceMtimeMs: 0,\n variant,\n format,\n });\n const target = variantCachePath(images.cacheDirectory, { sourceKey, generation }, hash, format);\n warnIfVariantCacheIsPublic(images.cacheDirectory);\n if (!(await freshImageVariant(target, images.maxCacheAge))) {\n await variantGenerations.run(target, async () => {\n if (await freshImageVariant(target, images.maxCacheAge)) return;\n const loaded = await source.load();\n await retryOnVanishedDirectory(async () => {\n await generateImageVariant({\n image: loaded.image.clone(),\n variant,\n format,\n targetPath: target,\n });\n await atomicWriteAsync(manifestPath, JSON.stringify({ format: loaded.sourceFormat }));\n });\n scheduleImageVariantCacheTrim(images, target);\n // Retain other generations: an older concurrent download must not prune\n // a newer object's derivatives. Background eviction reclaims them.\n });\n }\n return { absolutePath: target, hash, format, contentType: `image/${format}` };\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA0BA,eAAsB,0BACpB,OAC2C;CAC3C,MAAM,OAAO,kBAAkB,MAAM,IAAI;CACzC,MAAM,SAAS,2BAA2B,cAAc,QAAQ,GAAG,KAAK,SAAS;CACjF,IAAI,CAAC,QAAQ,MAAM,IAAI,UAAU,KAAK,oCAAoC;CAC1E,IAAI,CAAC,OAAO,UAAU,eAAe,KAAK,OAAO,UAAU,MAAM,OAAO,GACtE,MAAM,IAAI,UAAU,KAAK,oBAAoB,MAAM,QAAQ,GAAG;CAChE,IAAI,MAAM,WAAW,UAAa,CAAC,OAAO,QAAQ,SAAS,MAAM,MAAe,GAC9E,MAAM,IAAI,UAAU,KAAK,WAAW,MAAM,OAAO,kBAAkB;CACrE,MAAM,SAAS,MAAM,oBAAoB,MAAM,MAAM,MAAM,MAAM;CACjE,IAAI,CAAC,QAAQ,OAAO;CACpB,IAAI;EACF,OAAO,MAAM,yBAAyB,OAAO,MAAM,QAAQ,MAAM;CACnE,UAAU;EACR,OAAO,QAAQ;CACjB;AACF;;AAGA,eAAsB,yBACpB,OACA,MACA,QACA,QAC+B;CAC/B,MAAM,UAAU,OAAO,UAAU,eAAe,KAAK,OAAO,UAAU,MAAM,OAAO,IAC/E,OAAO,SAAS,MAAM,WACtB;CACJ,IAAI,CAAC,SAAS,MAAM,IAAI,UAAU,KAAK,oBAAoB,MAAM,QAAQ,GAAG;CAC5E,IAAI,MAAM,WAAW,UAAa,CAAC,OAAO,QAAQ,SAAS,MAAM,MAAe,GAC9E,MAAM,IAAI,UAAU,KAAK,WAAW,MAAM,OAAO,kBAAkB;CACrE,MAAM,aAAa,OAAO,uBAAuB,MAAM,OAAO,KAAK,EAAC,CAAE;CACtE,MAAM,YAAY,iBAAiB,KAAK,MAAM,OAAO,UAAU;CAC/D,MAAM,eAAe,KAAK,KACxB,uBAAuB,OAAO,gBAAgB,SAAS,GACvD,YACA,aACF;CACA,IAAI,SAA0C,MAAM;CACpD,IAAI,CAAC,QAAQ;EACX,IAAI;GAEF,MAAM,cADiB,KAAK,MAAM,MAAM,GAAG,SAAS,cAAc,MAAM,CAC/C,CAAC,EAAkC;GAC5D,IAAI,sBAAsB,WAAoB,GAAG,SAAS;EAC5D,SAAS,OAAO;GACd,IAAK,MAAgC,SAAS,YAAY,EAAE,iBAAiB,cAC3E,MAAM;EACV;EACA,YAAY,MAAM,OAAO,KAAK,EAAC,CAAE;CACnC;CACA,MAAM,OAAO,gBAAgB;EAC3B,cAAc,KAAK,UAAU;GAAC,KAAK;GAAM,OAAO;GAAY;EAAU,CAAC;EACvE,YAAY;EACZ,eAAe;EACf;EACA;CACF,CAAC;CACD,MAAM,SAAS,iBAAiB,OAAO,gBAAgB;EAAE;EAAW;CAAW,GAAG,MAAM,MAAM;CAC9F,2BAA2B,OAAO,cAAc;CAChD,IAAI,CAAE,MAAM,kBAAkB,QAAQ,OAAO,WAAW,GACtD,MAAM,mBAAmB,IAAI,QAAQ,YAAY;EAC/C,IAAI,MAAM,kBAAkB,QAAQ,OAAO,WAAW,GAAG;EACzD,MAAM,SAAS,MAAM,OAAO,KAAK;EACjC,MAAM,yBAAyB,YAAY;GACzC,MAAM,qBAAqB;IACzB,OAAO,OAAO,MAAM,MAAM;IAC1B;IACA;IACA,YAAY;GACd,CAAC;GACD,MAAM,iBAAiB,cAAc,KAAK,UAAU,EAAE,QAAQ,OAAO,aAAa,CAAC,CAAC;EACtF,CAAC;EACD,8BAA8B,QAAQ,MAAM;CAG9C,CAAC;CAEH,OAAO;EAAE,cAAc;EAAQ;EAAM;EAAQ,aAAa,SAAS;CAAS;AAC9E"}