@warlock.js/core 5.29.0 → 5.30.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 (1359) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/esm/application/app.d.mts +1 -1
  3. package/esm/application/app.d.mts.map +1 -1
  4. package/esm/application/app.mjs +1 -1
  5. package/esm/application/app.mjs.map +1 -1
  6. package/esm/application/application-config-types.d.mts +1 -1
  7. package/esm/application/application-config-types.d.mts.map +1 -1
  8. package/esm/application/application.d.mts +1 -1
  9. package/esm/application/application.d.mts.map +1 -1
  10. package/esm/application/application.mjs +1 -1
  11. package/esm/application/application.mjs.map +1 -1
  12. package/esm/application/boot-signal.d.mts +1 -1
  13. package/esm/application/boot-signal.d.mts.map +1 -1
  14. package/esm/application/boot-signal.mjs +1 -1
  15. package/esm/application/boot-signal.mjs.map +1 -1
  16. package/esm/application/public-url.d.mts +1 -1
  17. package/esm/application/public-url.d.mts.map +1 -1
  18. package/esm/application/public-url.mjs +1 -1
  19. package/esm/application/public-url.mjs.map +1 -1
  20. package/esm/application/roles.d.mts +1 -1
  21. package/esm/application/roles.d.mts.map +1 -1
  22. package/esm/application/roles.mjs +1 -1
  23. package/esm/application/roles.mjs.map +1 -1
  24. package/esm/benchmark/benchmark-snapshots.d.mts +1 -1
  25. package/esm/benchmark/benchmark-snapshots.d.mts.map +1 -1
  26. package/esm/benchmark/benchmark-snapshots.mjs +1 -1
  27. package/esm/benchmark/benchmark-snapshots.mjs.map +1 -1
  28. package/esm/benchmark/benchmark.d.mts +1 -1
  29. package/esm/benchmark/benchmark.d.mts.map +1 -1
  30. package/esm/benchmark/benchmark.mjs +1 -1
  31. package/esm/benchmark/benchmark.mjs.map +1 -1
  32. package/esm/benchmark/channels/console.channel.d.mts +1 -1
  33. package/esm/benchmark/channels/console.channel.d.mts.map +1 -1
  34. package/esm/benchmark/channels/console.channel.mjs +1 -1
  35. package/esm/benchmark/channels/console.channel.mjs.map +1 -1
  36. package/esm/benchmark/channels/noop.channel.d.mts +1 -1
  37. package/esm/benchmark/channels/noop.channel.d.mts.map +1 -1
  38. package/esm/benchmark/channels/noop.channel.mjs +1 -1
  39. package/esm/benchmark/channels/noop.channel.mjs.map +1 -1
  40. package/esm/benchmark/profiler.d.mts +1 -1
  41. package/esm/benchmark/profiler.d.mts.map +1 -1
  42. package/esm/benchmark/profiler.mjs +1 -1
  43. package/esm/benchmark/profiler.mjs.map +1 -1
  44. package/esm/benchmark/types.d.mts +1 -1
  45. package/esm/benchmark/types.d.mts.map +1 -1
  46. package/esm/bootstrap/setup.d.mts +1 -1
  47. package/esm/bootstrap/setup.d.mts.map +1 -1
  48. package/esm/bootstrap/setup.mjs +1 -1
  49. package/esm/bootstrap/setup.mjs.map +1 -1
  50. package/esm/bootstrap.d.mts +1 -1
  51. package/esm/bootstrap.d.mts.map +1 -1
  52. package/esm/bootstrap.mjs +1 -1
  53. package/esm/bootstrap.mjs.map +1 -1
  54. package/esm/cache/database-cache-driver.d.mts +1 -1
  55. package/esm/cache/database-cache-driver.d.mts.map +1 -1
  56. package/esm/cache/database-cache-driver.mjs +1 -1
  57. package/esm/cache/database-cache-driver.mjs.map +1 -1
  58. package/esm/cache/index.mjs +1 -1
  59. package/esm/cache/index.mjs.map +1 -1
  60. package/esm/cli/cli-commands.manager.mjs +1 -1
  61. package/esm/cli/cli-commands.manager.mjs.map +1 -1
  62. package/esm/cli/cli-commands.utils.mjs +1 -1
  63. package/esm/cli/cli-commands.utils.mjs.map +1 -1
  64. package/esm/cli/commands/add.command.mjs +1 -1
  65. package/esm/cli/commands/add.command.mjs.map +1 -1
  66. package/esm/cli/commands/build.command.mjs +1 -1
  67. package/esm/cli/commands/build.command.mjs.map +1 -1
  68. package/esm/cli/commands/create-database.command.mjs +1 -1
  69. package/esm/cli/commands/create-database.command.mjs.map +1 -1
  70. package/esm/cli/commands/dev-server.command.mjs +1 -1
  71. package/esm/cli/commands/dev-server.command.mjs.map +1 -1
  72. package/esm/cli/commands/doctor/boot-for-diagnostics.mjs +1 -1
  73. package/esm/cli/commands/doctor/boot-for-diagnostics.mjs.map +1 -1
  74. package/esm/cli/commands/doctor/checks/config.check.mjs +1 -1
  75. package/esm/cli/commands/doctor/checks/config.check.mjs.map +1 -1
  76. package/esm/cli/commands/doctor/checks/connectors.check.mjs +1 -1
  77. package/esm/cli/commands/doctor/checks/connectors.check.mjs.map +1 -1
  78. package/esm/cli/commands/doctor/checks/handler-signature.check.mjs +1 -1
  79. package/esm/cli/commands/doctor/checks/handler-signature.check.mjs.map +1 -1
  80. package/esm/cli/commands/doctor/checks/health.check.mjs +1 -1
  81. package/esm/cli/commands/doctor/checks/health.check.mjs.map +1 -1
  82. package/esm/cli/commands/doctor/checks/index.mjs +1 -1
  83. package/esm/cli/commands/doctor/checks/index.mjs.map +1 -1
  84. package/esm/cli/commands/doctor/checks/jwt-secret.check.mjs +1 -1
  85. package/esm/cli/commands/doctor/checks/jwt-secret.check.mjs.map +1 -1
  86. package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs +1 -1
  87. package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs.map +1 -1
  88. package/esm/cli/commands/doctor/checks/optional-peers.check.mjs +1 -1
  89. package/esm/cli/commands/doctor/checks/optional-peers.check.mjs.map +1 -1
  90. package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs +1 -1
  91. package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs.map +1 -1
  92. package/esm/cli/commands/doctor/checks/routes.check.mjs +1 -1
  93. package/esm/cli/commands/doctor/checks/routes.check.mjs.map +1 -1
  94. package/esm/cli/commands/doctor/doctor-command.action.mjs +1 -1
  95. package/esm/cli/commands/doctor/doctor-command.action.mjs.map +1 -1
  96. package/esm/cli/commands/doctor/format-report.mjs +1 -1
  97. package/esm/cli/commands/doctor/format-report.mjs.map +1 -1
  98. package/esm/cli/commands/doctor/run-checks.mjs +1 -1
  99. package/esm/cli/commands/doctor/run-checks.mjs.map +1 -1
  100. package/esm/cli/commands/doctor.command.mjs +1 -1
  101. package/esm/cli/commands/doctor.command.mjs.map +1 -1
  102. package/esm/cli/commands/drop-tables.command.mjs +1 -1
  103. package/esm/cli/commands/drop-tables.command.mjs.map +1 -1
  104. package/esm/cli/commands/generate/generate.command.mjs +1 -1
  105. package/esm/cli/commands/generate/generate.command.mjs.map +1 -1
  106. package/esm/cli/commands/generate/generators/column-dsl-parser.mjs +1 -1
  107. package/esm/cli/commands/generate/generators/column-dsl-parser.mjs.map +1 -1
  108. package/esm/cli/commands/generate/generators/controller.generator.mjs +1 -1
  109. package/esm/cli/commands/generate/generators/controller.generator.mjs.map +1 -1
  110. package/esm/cli/commands/generate/generators/migration.generator.mjs +1 -1
  111. package/esm/cli/commands/generate/generators/migration.generator.mjs.map +1 -1
  112. package/esm/cli/commands/generate/generators/model.generator.mjs +1 -1
  113. package/esm/cli/commands/generate/generators/model.generator.mjs.map +1 -1
  114. package/esm/cli/commands/generate/generators/module.generator.mjs +1 -1
  115. package/esm/cli/commands/generate/generators/module.generator.mjs.map +1 -1
  116. package/esm/cli/commands/generate/generators/repository.generator.mjs +1 -1
  117. package/esm/cli/commands/generate/generators/repository.generator.mjs.map +1 -1
  118. package/esm/cli/commands/generate/generators/resource.generator.mjs +1 -1
  119. package/esm/cli/commands/generate/generators/resource.generator.mjs.map +1 -1
  120. package/esm/cli/commands/generate/generators/service.generator.mjs +1 -1
  121. package/esm/cli/commands/generate/generators/service.generator.mjs.map +1 -1
  122. package/esm/cli/commands/generate/generators/use-case.generator.mjs +1 -1
  123. package/esm/cli/commands/generate/generators/use-case.generator.mjs.map +1 -1
  124. package/esm/cli/commands/generate/templates/stubs.mjs +1 -1
  125. package/esm/cli/commands/generate/templates/stubs.mjs.map +1 -1
  126. package/esm/cli/commands/generate/utils/name-parser.mjs +1 -1
  127. package/esm/cli/commands/generate/utils/name-parser.mjs.map +1 -1
  128. package/esm/cli/commands/generate/utils/path-resolver.mjs +1 -1
  129. package/esm/cli/commands/generate/utils/path-resolver.mjs.map +1 -1
  130. package/esm/cli/commands/generate/utils/prompt.mjs +1 -1
  131. package/esm/cli/commands/generate/utils/prompt.mjs.map +1 -1
  132. package/esm/cli/commands/generate/utils/writer.mjs +1 -1
  133. package/esm/cli/commands/generate/utils/writer.mjs.map +1 -1
  134. package/esm/cli/commands/migrate.command.mjs +1 -1
  135. package/esm/cli/commands/migrate.command.mjs.map +1 -1
  136. package/esm/cli/commands/openapi-generator.action.mjs +1 -1
  137. package/esm/cli/commands/openapi-generator.action.mjs.map +1 -1
  138. package/esm/cli/commands/openapi-generator.command.mjs +1 -1
  139. package/esm/cli/commands/openapi-generator.command.mjs.map +1 -1
  140. package/esm/cli/commands/postman-generator.action.mjs +1 -1
  141. package/esm/cli/commands/postman-generator.action.mjs.map +1 -1
  142. package/esm/cli/commands/postman-generator.command.mjs +1 -1
  143. package/esm/cli/commands/postman-generator.command.mjs.map +1 -1
  144. package/esm/cli/commands/routes/diff-page-routes.mjs +1 -1
  145. package/esm/cli/commands/routes/diff-page-routes.mjs.map +1 -1
  146. package/esm/cli/commands/routes/format-routes-table.mjs +1 -1
  147. package/esm/cli/commands/routes/format-routes-table.mjs.map +1 -1
  148. package/esm/cli/commands/routes/route-row.mjs +1 -1
  149. package/esm/cli/commands/routes/route-row.mjs.map +1 -1
  150. package/esm/cli/commands/routes/routes-command.action.mjs +1 -1
  151. package/esm/cli/commands/routes/routes-command.action.mjs.map +1 -1
  152. package/esm/cli/commands/routes/routes-diff.action.mjs +1 -1
  153. package/esm/cli/commands/routes/routes-diff.action.mjs.map +1 -1
  154. package/esm/cli/commands/routes/with-console-on-stderr.mjs +1 -1
  155. package/esm/cli/commands/routes/with-console-on-stderr.mjs.map +1 -1
  156. package/esm/cli/commands/routes.command.mjs +1 -1
  157. package/esm/cli/commands/routes.command.mjs.map +1 -1
  158. package/esm/cli/commands/seed.command.mjs +1 -1
  159. package/esm/cli/commands/seed.command.mjs.map +1 -1
  160. package/esm/cli/commands/start-production.command.mjs +1 -1
  161. package/esm/cli/commands/start-production.command.mjs.map +1 -1
  162. package/esm/cli/commands/storage-put.action.mjs +1 -1
  163. package/esm/cli/commands/storage-put.action.mjs.map +1 -1
  164. package/esm/cli/commands/storage-put.command.mjs +1 -1
  165. package/esm/cli/commands/storage-put.command.mjs.map +1 -1
  166. package/esm/cli/commands/typings-generator.command.mjs +1 -1
  167. package/esm/cli/commands/typings-generator.command.mjs.map +1 -1
  168. package/esm/cli/commands/update.command.mjs +1 -1
  169. package/esm/cli/commands/update.command.mjs.map +1 -1
  170. package/esm/cli/commands-loader.mjs +1 -1
  171. package/esm/cli/commands-loader.mjs.map +1 -1
  172. package/esm/cli/framework-cli-commands.mjs +1 -1
  173. package/esm/cli/framework-cli-commands.mjs.map +1 -1
  174. package/esm/cli/parse-cli-args.mjs +1 -1
  175. package/esm/cli/parse-cli-args.mjs.map +1 -1
  176. package/esm/cli/start.mjs +1 -1
  177. package/esm/cli/start.mjs.map +1 -1
  178. package/esm/cli/string-similarity.mjs +1 -1
  179. package/esm/cli/string-similarity.mjs.map +1 -1
  180. package/esm/commands/cli-command.d.mts +1 -1
  181. package/esm/commands/cli-command.d.mts.map +1 -1
  182. package/esm/commands/cli-command.mjs +1 -1
  183. package/esm/commands/cli-command.mjs.map +1 -1
  184. package/esm/commands/types.d.mts +1 -1
  185. package/esm/commands/types.d.mts.map +1 -1
  186. package/esm/config/config-getter.d.mts +1 -1
  187. package/esm/config/config-getter.d.mts.map +1 -1
  188. package/esm/config/config-getter.mjs +1 -1
  189. package/esm/config/config-getter.mjs.map +1 -1
  190. package/esm/config/config-handlers.d.mts +1 -1
  191. package/esm/config/config-handlers.d.mts.map +1 -1
  192. package/esm/config/config-handlers.mjs +1 -1
  193. package/esm/config/config-handlers.mjs.map +1 -1
  194. package/esm/config/config-key-from-path.mjs +1 -1
  195. package/esm/config/config-key-from-path.mjs.map +1 -1
  196. package/esm/config/config-loader.d.mts +1 -1
  197. package/esm/config/config-loader.d.mts.map +1 -1
  198. package/esm/config/config-loader.mjs +1 -1
  199. package/esm/config/config-loader.mjs.map +1 -1
  200. package/esm/config/config-manager.mjs +1 -1
  201. package/esm/config/config-manager.mjs.map +1 -1
  202. package/esm/config/config-setter.d.mts +1 -1
  203. package/esm/config/config-setter.d.mts.map +1 -1
  204. package/esm/config/config-setter.mjs +1 -1
  205. package/esm/config/config-setter.mjs.map +1 -1
  206. package/esm/config/config-special-handlers.d.mts +1 -1
  207. package/esm/config/config-special-handlers.d.mts.map +1 -1
  208. package/esm/config/config-special-handlers.mjs +1 -1
  209. package/esm/config/config-special-handlers.mjs.map +1 -1
  210. package/esm/config/load-config-files.mjs +1 -1
  211. package/esm/config/load-config-files.mjs.map +1 -1
  212. package/esm/config/locale-configuration.mjs +1 -1
  213. package/esm/config/locale-configuration.mjs.map +1 -1
  214. package/esm/config/types.d.mts +1 -1
  215. package/esm/config/types.d.mts.map +1 -1
  216. package/esm/connectors/access-connector.d.mts +1 -1
  217. package/esm/connectors/access-connector.d.mts.map +1 -1
  218. package/esm/connectors/access-connector.mjs +1 -1
  219. package/esm/connectors/access-connector.mjs.map +1 -1
  220. package/esm/connectors/ai-connector.d.mts +1 -1
  221. package/esm/connectors/ai-connector.d.mts.map +1 -1
  222. package/esm/connectors/ai-connector.mjs +1 -1
  223. package/esm/connectors/ai-connector.mjs.map +1 -1
  224. package/esm/connectors/assert-no-reserved-connector-names.d.mts +1 -1
  225. package/esm/connectors/assert-no-reserved-connector-names.d.mts.map +1 -1
  226. package/esm/connectors/assert-no-reserved-connector-names.mjs +1 -1
  227. package/esm/connectors/assert-no-reserved-connector-names.mjs.map +1 -1
  228. package/esm/connectors/assert-unique-connector-names.d.mts +1 -1
  229. package/esm/connectors/assert-unique-connector-names.d.mts.map +1 -1
  230. package/esm/connectors/assert-unique-connector-names.mjs +1 -1
  231. package/esm/connectors/assert-unique-connector-names.mjs.map +1 -1
  232. package/esm/connectors/base-connector.d.mts +1 -1
  233. package/esm/connectors/base-connector.d.mts.map +1 -1
  234. package/esm/connectors/base-connector.mjs +1 -1
  235. package/esm/connectors/base-connector.mjs.map +1 -1
  236. package/esm/connectors/cache-connector.d.mts +1 -1
  237. package/esm/connectors/cache-connector.d.mts.map +1 -1
  238. package/esm/connectors/cache-connector.mjs +1 -1
  239. package/esm/connectors/cache-connector.mjs.map +1 -1
  240. package/esm/connectors/connectors-manager.d.mts +1 -1
  241. package/esm/connectors/connectors-manager.d.mts.map +1 -1
  242. package/esm/connectors/connectors-manager.mjs +2 -2
  243. package/esm/connectors/connectors-manager.mjs.map +1 -1
  244. package/esm/connectors/database-connector.d.mts +1 -1
  245. package/esm/connectors/database-connector.d.mts.map +1 -1
  246. package/esm/connectors/database-connector.mjs +1 -1
  247. package/esm/connectors/database-connector.mjs.map +1 -1
  248. package/esm/connectors/describe-server-address.mjs +1 -1
  249. package/esm/connectors/describe-server-address.mjs.map +1 -1
  250. package/esm/connectors/herald-connector.d.mts +1 -1
  251. package/esm/connectors/herald-connector.d.mts.map +1 -1
  252. package/esm/connectors/herald-connector.mjs +1 -1
  253. package/esm/connectors/herald-connector.mjs.map +1 -1
  254. package/esm/connectors/http-connector.d.mts +1 -1
  255. package/esm/connectors/http-connector.d.mts.map +1 -1
  256. package/esm/connectors/http-connector.mjs +1 -1
  257. package/esm/connectors/http-connector.mjs.map +1 -1
  258. package/esm/connectors/logger-connector.d.mts +1 -1
  259. package/esm/connectors/logger-connector.d.mts.map +1 -1
  260. package/esm/connectors/logger-connector.mjs +1 -1
  261. package/esm/connectors/logger-connector.mjs.map +1 -1
  262. package/esm/connectors/mail-connector.d.mts +1 -1
  263. package/esm/connectors/mail-connector.d.mts.map +1 -1
  264. package/esm/connectors/mail-connector.mjs +1 -1
  265. package/esm/connectors/mail-connector.mjs.map +1 -1
  266. package/esm/connectors/notifications-connector.d.mts +1 -1
  267. package/esm/connectors/notifications-connector.d.mts.map +1 -1
  268. package/esm/connectors/notifications-connector.mjs +1 -1
  269. package/esm/connectors/notifications-connector.mjs.map +1 -1
  270. package/esm/connectors/read-bound-port.mjs +1 -1
  271. package/esm/connectors/read-bound-port.mjs.map +1 -1
  272. package/esm/connectors/register-configured-connectors.d.mts +1 -1
  273. package/esm/connectors/register-configured-connectors.d.mts.map +1 -1
  274. package/esm/connectors/register-configured-connectors.mjs +1 -1
  275. package/esm/connectors/register-configured-connectors.mjs.map +1 -1
  276. package/esm/connectors/single-server-warnings.mjs +1 -1
  277. package/esm/connectors/single-server-warnings.mjs.map +1 -1
  278. package/esm/connectors/socket-connector.d.mts +1 -1
  279. package/esm/connectors/socket-connector.d.mts.map +1 -1
  280. package/esm/connectors/socket-connector.mjs +1 -1
  281. package/esm/connectors/socket-connector.mjs.map +1 -1
  282. package/esm/connectors/storage.connector.d.mts +1 -1
  283. package/esm/connectors/storage.connector.d.mts.map +1 -1
  284. package/esm/connectors/storage.connector.mjs +1 -1
  285. package/esm/connectors/storage.connector.mjs.map +1 -1
  286. package/esm/connectors/types.d.mts +1 -1
  287. package/esm/connectors/types.d.mts.map +1 -1
  288. package/esm/connectors/types.mjs +1 -1
  289. package/esm/connectors/types.mjs.map +1 -1
  290. package/esm/container/container-instance-registry.mjs +1 -1
  291. package/esm/container/container-instance-registry.mjs.map +1 -1
  292. package/esm/container/development-app-modules.d.mts +1 -1
  293. package/esm/container/development-app-modules.d.mts.map +1 -1
  294. package/esm/container/development-model-modules.d.mts +1 -1
  295. package/esm/container/development-model-modules.d.mts.map +1 -1
  296. package/esm/container/index.d.mts +1 -1
  297. package/esm/container/index.d.mts.map +1 -1
  298. package/esm/container/index.mjs +1 -1
  299. package/esm/container/index.mjs.map +1 -1
  300. package/esm/database/create-database-action.mjs +1 -1
  301. package/esm/database/create-database-action.mjs.map +1 -1
  302. package/esm/database/drop-tables-action.mjs +1 -1
  303. package/esm/database/drop-tables-action.mjs.map +1 -1
  304. package/esm/database/migrate-action.mjs +1 -1
  305. package/esm/database/migrate-action.mjs.map +1 -1
  306. package/esm/database/models/database-log/database-log.d.mts +31 -39
  307. package/esm/database/models/database-log/database-log.d.mts.map +1 -1
  308. package/esm/database/models/database-log/database-log.mjs +1 -1
  309. package/esm/database/models/database-log/database-log.mjs.map +1 -1
  310. package/esm/database/pending-exit-code.mjs +1 -1
  311. package/esm/database/pending-exit-code.mjs.map +1 -1
  312. package/esm/database/resolve-pending-migrations.mjs +1 -1
  313. package/esm/database/resolve-pending-migrations.mjs.map +1 -1
  314. package/esm/database/seed-command-action.mjs +1 -1
  315. package/esm/database/seed-command-action.mjs.map +1 -1
  316. package/esm/database/seeds/seed-records-table-migration.mjs +1 -1
  317. package/esm/database/seeds/seed-records-table-migration.mjs.map +1 -1
  318. package/esm/database/seeds/seeder.d.mts +1 -1
  319. package/esm/database/seeds/seeder.d.mts.map +1 -1
  320. package/esm/database/seeds/seeder.errors.d.mts +1 -1
  321. package/esm/database/seeds/seeder.errors.d.mts.map +1 -1
  322. package/esm/database/seeds/seeder.errors.mjs +1 -1
  323. package/esm/database/seeds/seeder.errors.mjs.map +1 -1
  324. package/esm/database/seeds/seeder.mjs +1 -1
  325. package/esm/database/seeds/seeder.mjs.map +1 -1
  326. package/esm/database/seeds/seeders.manager.mjs +1 -1
  327. package/esm/database/seeds/seeders.manager.mjs.map +1 -1
  328. package/esm/database/seeds/seeds-table-migration.mjs +1 -1
  329. package/esm/database/seeds/seeds-table-migration.mjs.map +1 -1
  330. package/esm/database/seeds/types.d.mts +1 -1
  331. package/esm/database/seeds/types.d.mts.map +1 -1
  332. package/esm/database/seeds/utils.mjs +1 -1
  333. package/esm/database/seeds/utils.mjs.map +1 -1
  334. package/esm/database/utils.d.mts +1 -1
  335. package/esm/database/utils.d.mts.map +1 -1
  336. package/esm/database/utils.mjs +1 -1
  337. package/esm/database/utils.mjs.map +1 -1
  338. package/esm/dev-server/app-module-registry.mjs +1 -1
  339. package/esm/dev-server/app-module-registry.mjs.map +1 -1
  340. package/esm/dev-server/boot-precondition-error.mjs +1 -1
  341. package/esm/dev-server/boot-precondition-error.mjs.map +1 -1
  342. package/esm/dev-server/build-development-openapi-document.mjs +1 -1
  343. package/esm/dev-server/build-development-openapi-document.mjs.map +1 -1
  344. package/esm/dev-server/check-for-updates.mjs +1 -1
  345. package/esm/dev-server/check-for-updates.mjs.map +1 -1
  346. package/esm/dev-server/collect-development-api-routes.mjs +1 -1
  347. package/esm/dev-server/collect-development-api-routes.mjs.map +1 -1
  348. package/esm/dev-server/create-worker.mjs +1 -1
  349. package/esm/dev-server/create-worker.mjs.map +1 -1
  350. package/esm/dev-server/dependency-graph.d.mts +1 -1
  351. package/esm/dev-server/dependency-graph.d.mts.map +1 -1
  352. package/esm/dev-server/dependency-graph.mjs +1 -1
  353. package/esm/dev-server/dependency-graph.mjs.map +1 -1
  354. package/esm/dev-server/dev-logger.mjs +1 -1
  355. package/esm/dev-server/dev-logger.mjs.map +1 -1
  356. package/esm/dev-server/development-server.mjs +1 -1
  357. package/esm/dev-server/development-server.mjs.map +1 -1
  358. package/esm/dev-server/events.mjs +1 -1
  359. package/esm/dev-server/events.mjs.map +1 -1
  360. package/esm/dev-server/extract-translation-keys.mjs +1 -1
  361. package/esm/dev-server/extract-translation-keys.mjs.map +1 -1
  362. package/esm/dev-server/file-event-handler.mjs +1 -1
  363. package/esm/dev-server/file-event-handler.mjs.map +1 -1
  364. package/esm/dev-server/file-manager.d.mts +1 -1
  365. package/esm/dev-server/file-manager.d.mts.map +1 -1
  366. package/esm/dev-server/file-manager.mjs +1 -1
  367. package/esm/dev-server/file-manager.mjs.map +1 -1
  368. package/esm/dev-server/file-operations.d.mts +1 -1
  369. package/esm/dev-server/file-operations.d.mts.map +1 -1
  370. package/esm/dev-server/file-operations.mjs +1 -1
  371. package/esm/dev-server/file-operations.mjs.map +1 -1
  372. package/esm/dev-server/files-orchestrator.mjs +20 -17
  373. package/esm/dev-server/files-orchestrator.mjs.map +1 -1
  374. package/esm/dev-server/files-watcher.mjs +1 -1
  375. package/esm/dev-server/files-watcher.mjs.map +1 -1
  376. package/esm/dev-server/flags.mjs +1 -1
  377. package/esm/dev-server/flags.mjs.map +1 -1
  378. package/esm/dev-server/health-checker/checkers/base-health-checker.mjs +1 -1
  379. package/esm/dev-server/health-checker/checkers/base-health-checker.mjs.map +1 -1
  380. package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs +1 -1
  381. package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs.map +1 -1
  382. package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs +1 -1
  383. package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs.map +1 -1
  384. package/esm/dev-server/health-checker/file-health-checker.contract.d.mts +1 -1
  385. package/esm/dev-server/health-checker/file-health-checker.contract.d.mts.map +1 -1
  386. package/esm/dev-server/health-checker/file-health-result.d.mts +1 -1
  387. package/esm/dev-server/health-checker/file-health-result.d.mts.map +1 -1
  388. package/esm/dev-server/health-checker/file-health-result.mjs +1 -1
  389. package/esm/dev-server/health-checker/file-health-result.mjs.map +1 -1
  390. package/esm/dev-server/health-checker/files-healthcare.manager.mjs +1 -1
  391. package/esm/dev-server/health-checker/files-healthcare.manager.mjs.map +1 -1
  392. package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs +1 -1
  393. package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs.map +1 -1
  394. package/esm/dev-server/health-checker/workers/ts-health.worker.mjs +1 -1
  395. package/esm/dev-server/health-checker/workers/ts-health.worker.mjs.map +1 -1
  396. package/esm/dev-server/layer-executor.mjs +1 -1
  397. package/esm/dev-server/layer-executor.mjs.map +1 -1
  398. package/esm/dev-server/legacy-locales-warning.mjs +1 -1
  399. package/esm/dev-server/legacy-locales-warning.mjs.map +1 -1
  400. package/esm/dev-server/loader/build-transpile-init.mjs +1 -1
  401. package/esm/dev-server/loader/build-transpile-init.mjs.map +1 -1
  402. package/esm/dev-server/loader/hook-thread.d.mts +1 -1
  403. package/esm/dev-server/loader/hook-thread.d.mts.map +1 -1
  404. package/esm/dev-server/loader/hook-thread.mjs +1 -1
  405. package/esm/dev-server/loader/hook-thread.mjs.map +1 -1
  406. package/esm/dev-server/loader/load-hook.d.mts +1 -1
  407. package/esm/dev-server/loader/load-hook.d.mts.map +1 -1
  408. package/esm/dev-server/loader/load-hook.mjs +1 -1
  409. package/esm/dev-server/loader/load-hook.mjs.map +1 -1
  410. package/esm/dev-server/loader/loader-port-acks.mjs +34 -0
  411. package/esm/dev-server/loader/loader-port-acks.mjs.map +1 -0
  412. package/esm/dev-server/loader/own-resolver.mjs +1 -1
  413. package/esm/dev-server/loader/own-resolver.mjs.map +1 -1
  414. package/esm/dev-server/loader/register-loader.mjs +1 -1
  415. package/esm/dev-server/loader/register-loader.mjs.map +1 -1
  416. package/esm/dev-server/loader/resolve-capture.mjs +1 -1
  417. package/esm/dev-server/loader/resolve-capture.mjs.map +1 -1
  418. package/esm/dev-server/loader/resolve-hook.d.mts +1 -1
  419. package/esm/dev-server/loader/resolve-hook.d.mts.map +1 -1
  420. package/esm/dev-server/loader/resolve-hook.mjs +2 -2
  421. package/esm/dev-server/loader/resolve-hook.mjs.map +1 -1
  422. package/esm/dev-server/loader/source-slug.mjs +1 -1
  423. package/esm/dev-server/loader/source-slug.mjs.map +1 -1
  424. package/esm/dev-server/loader/transpile-cache.mjs +1 -1
  425. package/esm/dev-server/loader/transpile-cache.mjs.map +1 -1
  426. package/esm/dev-server/loader/version-registry.mjs +1 -1
  427. package/esm/dev-server/loader/version-registry.mjs.map +1 -1
  428. package/esm/dev-server/manifest-manager.d.mts +1 -1
  429. package/esm/dev-server/manifest-manager.d.mts.map +1 -1
  430. package/esm/dev-server/manifest-manager.mjs +1 -1
  431. package/esm/dev-server/manifest-manager.mjs.map +1 -1
  432. package/esm/dev-server/model-module-registry.mjs +1 -1
  433. package/esm/dev-server/model-module-registry.mjs.map +1 -1
  434. package/esm/dev-server/model-resource-typings.mjs +1 -1
  435. package/esm/dev-server/model-resource-typings.mjs.map +1 -1
  436. package/esm/dev-server/module-loader.mjs +1 -1
  437. package/esm/dev-server/module-loader.mjs.map +1 -1
  438. package/esm/dev-server/package-json-manager.mjs +1 -1
  439. package/esm/dev-server/package-json-manager.mjs.map +1 -1
  440. package/esm/dev-server/parse-imports.mjs +73 -6
  441. package/esm/dev-server/parse-imports.mjs.map +1 -1
  442. package/esm/dev-server/read-config-ast.mjs +1 -1
  443. package/esm/dev-server/read-config-ast.mjs.map +1 -1
  444. package/esm/dev-server/ready-block.mjs +1 -1
  445. package/esm/dev-server/ready-block.mjs.map +1 -1
  446. package/esm/dev-server/register-dev-shortcuts.mjs +1 -1
  447. package/esm/dev-server/register-dev-shortcuts.mjs.map +1 -1
  448. package/esm/dev-server/register-installed-devtools.mjs +1 -1
  449. package/esm/dev-server/register-installed-devtools.mjs.map +1 -1
  450. package/esm/dev-server/restart-dev-server.mjs +1 -1
  451. package/esm/dev-server/restart-dev-server.mjs.map +1 -1
  452. package/esm/dev-server/route-types-publisher.mjs +1 -1
  453. package/esm/dev-server/route-types-publisher.mjs.map +1 -1
  454. package/esm/dev-server/run-connector-typings.mjs +1 -1
  455. package/esm/dev-server/run-connector-typings.mjs.map +1 -1
  456. package/esm/dev-server/run-typings-generation.mjs +1 -1
  457. package/esm/dev-server/run-typings-generation.mjs.map +1 -1
  458. package/esm/dev-server/shortcuts.mjs +1 -1
  459. package/esm/dev-server/shortcuts.mjs.map +1 -1
  460. package/esm/dev-server/special-file-patterns.mjs +1 -1
  461. package/esm/dev-server/special-file-patterns.mjs.map +1 -1
  462. package/esm/dev-server/special-files-collector.d.mts +1 -1
  463. package/esm/dev-server/special-files-collector.d.mts.map +1 -1
  464. package/esm/dev-server/special-files-collector.mjs +1 -1
  465. package/esm/dev-server/special-files-collector.mjs.map +1 -1
  466. package/esm/dev-server/start-development-server.mjs +1 -1
  467. package/esm/dev-server/start-development-server.mjs.map +1 -1
  468. package/esm/dev-server/supervisor.mjs +1 -1
  469. package/esm/dev-server/supervisor.mjs.map +1 -1
  470. package/esm/dev-server/translation-keys-sources.mjs +1 -1
  471. package/esm/dev-server/translation-keys-sources.mjs.map +1 -1
  472. package/esm/dev-server/tsconfig-manager.mjs +1 -1
  473. package/esm/dev-server/tsconfig-manager.mjs.map +1 -1
  474. package/esm/dev-server/type-generator.mjs +32 -11
  475. package/esm/dev-server/type-generator.mjs.map +1 -1
  476. package/esm/dev-server/types.d.mts +1 -1
  477. package/esm/dev-server/types.d.mts.map +1 -1
  478. package/esm/dev-server/update-check-cache.mjs +1 -1
  479. package/esm/dev-server/update-check-cache.mjs.map +1 -1
  480. package/esm/dev-server/utils.mjs +1 -1
  481. package/esm/dev-server/utils.mjs.map +1 -1
  482. package/esm/encryption/encrypt.d.mts +1 -1
  483. package/esm/encryption/encrypt.d.mts.map +1 -1
  484. package/esm/encryption/encrypt.mjs +1 -1
  485. package/esm/encryption/encrypt.mjs.map +1 -1
  486. package/esm/encryption/hash.d.mts +1 -1
  487. package/esm/encryption/hash.d.mts.map +1 -1
  488. package/esm/encryption/hash.mjs +1 -1
  489. package/esm/encryption/hash.mjs.map +1 -1
  490. package/esm/encryption/password.d.mts +1 -1
  491. package/esm/encryption/password.d.mts.map +1 -1
  492. package/esm/encryption/password.mjs +1 -1
  493. package/esm/encryption/password.mjs.map +1 -1
  494. package/esm/encryption/types.d.mts +1 -1
  495. package/esm/encryption/types.d.mts.map +1 -1
  496. package/esm/errors/container-key-missing-error.mjs +1 -1
  497. package/esm/errors/container-key-missing-error.mjs.map +1 -1
  498. package/esm/errors/esbuild-binary-missing-error.mjs +1 -1
  499. package/esm/errors/esbuild-binary-missing-error.mjs.map +1 -1
  500. package/esm/errors/index.d.mts +2 -0
  501. package/esm/errors/index.mjs +3 -0
  502. package/esm/errors/unknown-locale-error.mjs +1 -1
  503. package/esm/errors/unknown-locale-error.mjs.map +1 -1
  504. package/esm/generations/add-command.action.mjs +29 -6
  505. package/esm/generations/add-command.action.mjs.map +1 -1
  506. package/esm/generations/features/access.feature.mjs +1 -1
  507. package/esm/generations/features/access.feature.mjs.map +1 -1
  508. package/esm/generations/features/ai-anthropic.feature.mjs +1 -1
  509. package/esm/generations/features/ai-anthropic.feature.mjs.map +1 -1
  510. package/esm/generations/features/ai-bedrock.feature.mjs +1 -1
  511. package/esm/generations/features/ai-bedrock.feature.mjs.map +1 -1
  512. package/esm/generations/features/ai-google.feature.mjs +1 -1
  513. package/esm/generations/features/ai-google.feature.mjs.map +1 -1
  514. package/esm/generations/features/ai-ollama.feature.mjs +1 -1
  515. package/esm/generations/features/ai-ollama.feature.mjs.map +1 -1
  516. package/esm/generations/features/ai-openai.feature.mjs +1 -1
  517. package/esm/generations/features/ai-openai.feature.mjs.map +1 -1
  518. package/esm/generations/features/ai-panoptic.feature.mjs +1 -1
  519. package/esm/generations/features/ai-panoptic.feature.mjs.map +1 -1
  520. package/esm/generations/features/ai-tools.feature.mjs +1 -1
  521. package/esm/generations/features/ai-tools.feature.mjs.map +1 -1
  522. package/esm/generations/features/ai-workspace.feature.mjs +1 -1
  523. package/esm/generations/features/ai-workspace.feature.mjs.map +1 -1
  524. package/esm/generations/features/ai.feature.mjs +1 -1
  525. package/esm/generations/features/ai.feature.mjs.map +1 -1
  526. package/esm/generations/features/auth-google.feature.mjs +1 -1
  527. package/esm/generations/features/auth-google.feature.mjs.map +1 -1
  528. package/esm/generations/features/auth-passkeys.feature.mjs +1 -1
  529. package/esm/generations/features/auth-passkeys.feature.mjs.map +1 -1
  530. package/esm/generations/features/bull-board.feature.mjs +1 -1
  531. package/esm/generations/features/bull-board.feature.mjs.map +1 -1
  532. package/esm/generations/features/devtools.feature.mjs +1 -1
  533. package/esm/generations/features/devtools.feature.mjs.map +1 -1
  534. package/esm/generations/features/herald.feature.mjs +1 -1
  535. package/esm/generations/features/herald.feature.mjs.map +1 -1
  536. package/esm/generations/features/image.feature.mjs +1 -1
  537. package/esm/generations/features/image.feature.mjs.map +1 -1
  538. package/esm/generations/features/index.mjs +1 -1
  539. package/esm/generations/features/index.mjs.map +1 -1
  540. package/esm/generations/features/mail.feature.mjs +1 -1
  541. package/esm/generations/features/mail.feature.mjs.map +1 -1
  542. package/esm/generations/features/mongodb.feature.mjs +1 -1
  543. package/esm/generations/features/mongodb.feature.mjs.map +1 -1
  544. package/esm/generations/features/mysql.feature.mjs +1 -1
  545. package/esm/generations/features/mysql.feature.mjs.map +1 -1
  546. package/esm/generations/features/notifications.feature.mjs +121 -17
  547. package/esm/generations/features/notifications.feature.mjs.map +1 -1
  548. package/esm/generations/features/postgres.feature.mjs +1 -1
  549. package/esm/generations/features/postgres.feature.mjs.map +1 -1
  550. package/esm/generations/features/queue.feature.mjs +1 -1
  551. package/esm/generations/features/queue.feature.mjs.map +1 -1
  552. package/esm/generations/features/react-email.feature.mjs +1 -1
  553. package/esm/generations/features/react-email.feature.mjs.map +1 -1
  554. package/esm/generations/features/react.feature.mjs +1 -1
  555. package/esm/generations/features/react.feature.mjs.map +1 -1
  556. package/esm/generations/features/redis.feature.mjs +1 -1
  557. package/esm/generations/features/redis.feature.mjs.map +1 -1
  558. package/esm/generations/features/s3.feature.mjs +1 -1
  559. package/esm/generations/features/s3.feature.mjs.map +1 -1
  560. package/esm/generations/features/scheduler.feature.mjs +1 -1
  561. package/esm/generations/features/scheduler.feature.mjs.map +1 -1
  562. package/esm/generations/features/ses.feature.mjs +1 -1
  563. package/esm/generations/features/ses.feature.mjs.map +1 -1
  564. package/esm/generations/features/shadcn.feature.mjs +1 -1
  565. package/esm/generations/features/shadcn.feature.mjs.map +1 -1
  566. package/esm/generations/features/shared/insert-connector-entry.mjs +1 -1
  567. package/esm/generations/features/shared/insert-connector-entry.mjs.map +1 -1
  568. package/esm/generations/features/shared/insert-queue-dashboard-block.mjs +1 -1
  569. package/esm/generations/features/shared/insert-queue-dashboard-block.mjs.map +1 -1
  570. package/esm/generations/features/shared/link-ai-package-import.mjs +1 -1
  571. package/esm/generations/features/shared/link-ai-package-import.mjs.map +1 -1
  572. package/esm/generations/features/shared/merge-web-sitemap-config.mjs +1 -1
  573. package/esm/generations/features/shared/merge-web-sitemap-config.mjs.map +1 -1
  574. package/esm/generations/features/shared/migration-timestamp.mjs +1 -1
  575. package/esm/generations/features/shared/migration-timestamp.mjs.map +1 -1
  576. package/esm/generations/features/shared/patch-tsconfig-include.mjs +1 -1
  577. package/esm/generations/features/shared/patch-tsconfig-include.mjs.map +1 -1
  578. package/esm/generations/features/shared/relocate-conflicting-home-route.mjs +1 -1
  579. package/esm/generations/features/shared/relocate-conflicting-home-route.mjs.map +1 -1
  580. package/esm/generations/features/shared/resolve-contact-scaffold.mjs +1 -1
  581. package/esm/generations/features/shared/resolve-contact-scaffold.mjs.map +1 -1
  582. package/esm/generations/features/sitemap.feature.mjs +1 -1
  583. package/esm/generations/features/sitemap.feature.mjs.map +1 -1
  584. package/esm/generations/features/socket.feature.mjs +1 -1
  585. package/esm/generations/features/socket.feature.mjs.map +1 -1
  586. package/esm/generations/features/tailwind.feature.mjs +1 -1
  587. package/esm/generations/features/tailwind.feature.mjs.map +1 -1
  588. package/esm/generations/features/test.feature.mjs +1 -1
  589. package/esm/generations/features/test.feature.mjs.map +1 -1
  590. package/esm/generations/features/types.mjs +1 -1
  591. package/esm/generations/features/types.mjs.map +1 -1
  592. package/esm/generations/features/web.feature.mjs +1 -1
  593. package/esm/generations/features/web.feature.mjs.map +1 -1
  594. package/esm/generations/pnpm-build-approvals.mjs +89 -3
  595. package/esm/generations/pnpm-build-approvals.mjs.map +1 -1
  596. package/esm/generations/stubs.mjs +184 -78
  597. package/esm/generations/stubs.mjs.map +1 -1
  598. package/esm/http/boot-port-preflight.d.mts +1 -1
  599. package/esm/http/boot-port-preflight.d.mts.map +1 -1
  600. package/esm/http/boot-port-preflight.mjs +1 -1
  601. package/esm/http/boot-port-preflight.mjs.map +1 -1
  602. package/esm/http/build-cors-options.mjs +1 -1
  603. package/esm/http/build-cors-options.mjs.map +1 -1
  604. package/esm/http/build-rate-limit-options.d.mts +22 -1
  605. package/esm/http/build-rate-limit-options.d.mts.map +1 -1
  606. package/esm/http/build-rate-limit-options.mjs +7 -1
  607. package/esm/http/build-rate-limit-options.mjs.map +1 -1
  608. package/esm/http/config.d.mts +1 -1
  609. package/esm/http/config.d.mts.map +1 -1
  610. package/esm/http/config.mjs +1 -1
  611. package/esm/http/config.mjs.map +1 -1
  612. package/esm/http/context/request-context.d.mts +1 -1
  613. package/esm/http/context/request-context.d.mts.map +1 -1
  614. package/esm/http/context/request-context.mjs +1 -1
  615. package/esm/http/context/request-context.mjs.map +1 -1
  616. package/esm/http/context/request-memo.d.mts +1 -1
  617. package/esm/http/context/request-memo.d.mts.map +1 -1
  618. package/esm/http/context/request-memo.mjs +1 -1
  619. package/esm/http/context/request-memo.mjs.map +1 -1
  620. package/esm/http/createHttpApplication.d.mts +1 -1
  621. package/esm/http/createHttpApplication.d.mts.map +1 -1
  622. package/esm/http/createHttpApplication.mjs +1 -1
  623. package/esm/http/createHttpApplication.mjs.map +1 -1
  624. package/esm/http/csp.d.mts +1 -1
  625. package/esm/http/csp.d.mts.map +1 -1
  626. package/esm/http/csp.mjs +1 -1
  627. package/esm/http/csp.mjs.map +1 -1
  628. package/esm/http/csrf-default-guard.d.mts +1 -1
  629. package/esm/http/csrf-default-guard.d.mts.map +1 -1
  630. package/esm/http/csrf-default-guard.mjs +1 -1
  631. package/esm/http/csrf-default-guard.mjs.map +1 -1
  632. package/esm/http/csrf-origin-policy.d.mts +1 -1
  633. package/esm/http/csrf-origin-policy.d.mts.map +1 -1
  634. package/esm/http/csrf-origin-policy.mjs +1 -1
  635. package/esm/http/csrf-origin-policy.mjs.map +1 -1
  636. package/esm/http/database/RequestLog.d.mts +63 -111
  637. package/esm/http/database/RequestLog.d.mts.map +1 -1
  638. package/esm/http/database/RequestLog.mjs +1 -1
  639. package/esm/http/database/RequestLog.mjs.map +1 -1
  640. package/esm/http/error-codes.d.mts +1 -1
  641. package/esm/http/error-codes.d.mts.map +1 -1
  642. package/esm/http/error-codes.mjs +1 -1
  643. package/esm/http/error-codes.mjs.map +1 -1
  644. package/esm/http/error-mapper.d.mts +48 -0
  645. package/esm/http/error-mapper.d.mts.map +1 -0
  646. package/esm/http/error-mapper.mjs +48 -0
  647. package/esm/http/error-mapper.mjs.map +1 -0
  648. package/esm/http/errors/errors.d.mts +1 -1
  649. package/esm/http/errors/errors.d.mts.map +1 -1
  650. package/esm/http/errors/errors.mjs +1 -1
  651. package/esm/http/errors/errors.mjs.map +1 -1
  652. package/esm/http/events.d.mts +1 -1
  653. package/esm/http/events.d.mts.map +1 -1
  654. package/esm/http/events.mjs +1 -1
  655. package/esm/http/events.mjs.map +1 -1
  656. package/esm/http/flush-pending-cookies.mjs +1 -1
  657. package/esm/http/flush-pending-cookies.mjs.map +1 -1
  658. package/esm/http/health.d.mts +1 -1
  659. package/esm/http/health.d.mts.map +1 -1
  660. package/esm/http/health.mjs +1 -1
  661. package/esm/http/health.mjs.map +1 -1
  662. package/esm/http/index.d.mts +10 -6
  663. package/esm/http/index.mjs +8 -5
  664. package/esm/http/middleware/cache-response-middleware.d.mts +1 -1
  665. package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
  666. package/esm/http/middleware/cache-response-middleware.mjs +1 -1
  667. package/esm/http/middleware/cache-response-middleware.mjs.map +1 -1
  668. package/esm/http/middleware/concurrency-limit.middleware.d.mts +1 -1
  669. package/esm/http/middleware/concurrency-limit.middleware.d.mts.map +1 -1
  670. package/esm/http/middleware/concurrency-limit.middleware.mjs +1 -1
  671. package/esm/http/middleware/concurrency-limit.middleware.mjs.map +1 -1
  672. package/esm/http/middleware/idempotency.middleware.d.mts +1 -1
  673. package/esm/http/middleware/idempotency.middleware.d.mts.map +1 -1
  674. package/esm/http/middleware/idempotency.middleware.mjs +1 -1
  675. package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
  676. package/esm/http/middleware/inject-request-context.d.mts +1 -1
  677. package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
  678. package/esm/http/middleware/inject-request-context.mjs +4 -2
  679. package/esm/http/middleware/inject-request-context.mjs.map +1 -1
  680. package/esm/http/middleware/ip-filter.middleware.d.mts +1 -1
  681. package/esm/http/middleware/ip-filter.middleware.d.mts.map +1 -1
  682. package/esm/http/middleware/ip-filter.middleware.mjs +1 -1
  683. package/esm/http/middleware/ip-filter.middleware.mjs.map +1 -1
  684. package/esm/http/middleware/maintenance.middleware.d.mts +1 -1
  685. package/esm/http/middleware/maintenance.middleware.d.mts.map +1 -1
  686. package/esm/http/middleware/maintenance.middleware.mjs +1 -1
  687. package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
  688. package/esm/http/middleware/max-body-size.middleware.d.mts +1 -1
  689. package/esm/http/middleware/max-body-size.middleware.d.mts.map +1 -1
  690. package/esm/http/middleware/max-body-size.middleware.mjs +1 -1
  691. package/esm/http/middleware/max-body-size.middleware.mjs.map +1 -1
  692. package/esm/http/middleware/middleware-list.d.mts +1 -1
  693. package/esm/http/middleware/middleware-list.d.mts.map +1 -1
  694. package/esm/http/middleware/middleware-list.mjs +1 -1
  695. package/esm/http/middleware/middleware-list.mjs.map +1 -1
  696. package/esm/http/middleware/rate-limit.middleware.d.mts +20 -5
  697. package/esm/http/middleware/rate-limit.middleware.d.mts.map +1 -1
  698. package/esm/http/middleware/rate-limit.middleware.mjs +34 -12
  699. package/esm/http/middleware/rate-limit.middleware.mjs.map +1 -1
  700. package/esm/http/middleware/utils/cidr-match.d.mts +1 -1
  701. package/esm/http/middleware/utils/cidr-match.d.mts.map +1 -1
  702. package/esm/http/middleware/utils/cidr-match.mjs +1 -1
  703. package/esm/http/middleware/utils/cidr-match.mjs.map +1 -1
  704. package/esm/http/middleware/utils/idempotency-key.d.mts +1 -1
  705. package/esm/http/middleware/utils/idempotency-key.d.mts.map +1 -1
  706. package/esm/http/middleware/utils/idempotency-key.mjs +1 -1
  707. package/esm/http/middleware/utils/idempotency-key.mjs.map +1 -1
  708. package/esm/http/middleware/utils/parse-size.d.mts +1 -1
  709. package/esm/http/middleware/utils/parse-size.d.mts.map +1 -1
  710. package/esm/http/middleware/utils/parse-size.mjs +1 -1
  711. package/esm/http/middleware/utils/parse-size.mjs.map +1 -1
  712. package/esm/http/parse-urlencoded-body.mjs +1 -1
  713. package/esm/http/parse-urlencoded-body.mjs.map +1 -1
  714. package/esm/http/plugins.d.mts +9 -2
  715. package/esm/http/plugins.d.mts.map +1 -1
  716. package/esm/http/plugins.mjs +18 -4
  717. package/esm/http/plugins.mjs.map +1 -1
  718. package/esm/http/port-preflight.d.mts +1 -1
  719. package/esm/http/port-preflight.d.mts.map +1 -1
  720. package/esm/http/port-preflight.mjs +1 -1
  721. package/esm/http/port-preflight.mjs.map +1 -1
  722. package/esm/http/rate-limit-cache-store.mjs +155 -0
  723. package/esm/http/rate-limit-cache-store.mjs.map +1 -0
  724. package/esm/http/ready-report.d.mts +1 -1
  725. package/esm/http/ready-report.d.mts.map +1 -1
  726. package/esm/http/ready-report.mjs +1 -1
  727. package/esm/http/ready-report.mjs.map +1 -1
  728. package/esm/http/request-controller.d.mts +1 -1
  729. package/esm/http/request-controller.d.mts.map +1 -1
  730. package/esm/http/request-controller.mjs +1 -1
  731. package/esm/http/request-controller.mjs.map +1 -1
  732. package/esm/http/request-log-snapshot.d.mts +123 -0
  733. package/esm/http/request-log-snapshot.d.mts.map +1 -0
  734. package/esm/http/request-log-snapshot.mjs +141 -0
  735. package/esm/http/request-log-snapshot.mjs.map +1 -0
  736. package/esm/http/request.d.mts +41 -2
  737. package/esm/http/request.d.mts.map +1 -1
  738. package/esm/http/request.mjs +65 -2
  739. package/esm/http/request.mjs.map +1 -1
  740. package/esm/http/resolve-bind-port.mjs +1 -1
  741. package/esm/http/resolve-bind-port.mjs.map +1 -1
  742. package/esm/http/response.d.mts +40 -8
  743. package/esm/http/response.d.mts.map +1 -1
  744. package/esm/http/response.mjs +173 -61
  745. package/esm/http/response.mjs.map +1 -1
  746. package/esm/http/serialized.d.mts +1 -1
  747. package/esm/http/serialized.d.mts.map +1 -1
  748. package/esm/http/server-rebuilt.d.mts +1 -1
  749. package/esm/http/server-rebuilt.d.mts.map +1 -1
  750. package/esm/http/server-rebuilt.mjs +1 -1
  751. package/esm/http/server-rebuilt.mjs.map +1 -1
  752. package/esm/http/server.d.mts +34 -6
  753. package/esm/http/server.d.mts.map +1 -1
  754. package/esm/http/server.mjs +70 -5
  755. package/esm/http/server.mjs.map +1 -1
  756. package/esm/http/stream-react-response.d.mts +1 -1
  757. package/esm/http/stream-react-response.d.mts.map +1 -1
  758. package/esm/http/stream-react-response.mjs +1 -1
  759. package/esm/http/stream-react-response.mjs.map +1 -1
  760. package/esm/http/stream-transport.mjs +75 -0
  761. package/esm/http/stream-transport.mjs.map +1 -0
  762. package/esm/http/tracing/trace-id.d.mts +1 -1
  763. package/esm/http/tracing/trace-id.d.mts.map +1 -1
  764. package/esm/http/tracing/trace-id.mjs +1 -1
  765. package/esm/http/tracing/trace-id.mjs.map +1 -1
  766. package/esm/http/tracing/tracing-dispatcher.d.mts +1 -1
  767. package/esm/http/tracing/tracing-dispatcher.d.mts.map +1 -1
  768. package/esm/http/tracing/tracing-dispatcher.mjs +1 -1
  769. package/esm/http/tracing/tracing-dispatcher.mjs.map +1 -1
  770. package/esm/http/tracing/tracing.type.d.mts +1 -1
  771. package/esm/http/tracing/tracing.type.d.mts.map +1 -1
  772. package/esm/http/types.d.mts +131 -6
  773. package/esm/http/types.d.mts.map +1 -1
  774. package/esm/http/uploaded-file.d.mts +2 -2
  775. package/esm/http/uploaded-file.d.mts.map +1 -1
  776. package/esm/http/uploaded-file.mjs +2 -2
  777. package/esm/http/uploaded-file.mjs.map +1 -1
  778. package/esm/http/uploads/detect-image-format.mjs +1 -1
  779. package/esm/http/uploads/detect-image-format.mjs.map +1 -1
  780. package/esm/http/uploads/generate-image-variant.mjs +1 -1
  781. package/esm/http/uploads/generate-image-variant.mjs.map +1 -1
  782. package/esm/http/uploads/generate-image-variants.d.mts +1 -1
  783. package/esm/http/uploads/generate-image-variants.d.mts.map +1 -1
  784. package/esm/http/uploads/generate-image-variants.mjs +15 -7
  785. package/esm/http/uploads/generate-image-variants.mjs.map +1 -1
  786. package/esm/http/uploads/image-variant-cache.mjs +143 -0
  787. package/esm/http/uploads/image-variant-cache.mjs.map +1 -0
  788. package/esm/http/uploads/image-variant-types.d.mts +1 -1
  789. package/esm/http/uploads/image-variant-types.d.mts.map +1 -1
  790. package/esm/http/uploads/image-variants-config-error.d.mts +1 -1
  791. package/esm/http/uploads/image-variants-config-error.d.mts.map +1 -1
  792. package/esm/http/uploads/image-variants-config-error.mjs +1 -1
  793. package/esm/http/uploads/image-variants-config-error.mjs.map +1 -1
  794. package/esm/http/uploads/index.d.mts +3 -1
  795. package/esm/http/uploads/index.mjs +3 -1
  796. package/esm/http/uploads/is-path-inside.mjs +1 -1
  797. package/esm/http/uploads/is-path-inside.mjs.map +1 -1
  798. package/esm/http/uploads/load-variant-source.mjs +1 -1
  799. package/esm/http/uploads/load-variant-source.mjs.map +1 -1
  800. package/esm/http/uploads/local-disk-root.mjs +24 -0
  801. package/esm/http/uploads/local-disk-root.mjs.map +1 -0
  802. package/esm/http/uploads/matches-if-none-match.mjs +1 -1
  803. package/esm/http/uploads/matches-if-none-match.mjs.map +1 -1
  804. package/esm/http/uploads/parse-uploaded-file-query.mjs +1 -1
  805. package/esm/http/uploads/parse-uploaded-file-query.mjs.map +1 -1
  806. package/esm/http/uploads/purge-image-variants.d.mts +32 -0
  807. package/esm/http/uploads/purge-image-variants.d.mts.map +1 -0
  808. package/esm/http/uploads/purge-image-variants.mjs +46 -0
  809. package/esm/http/uploads/purge-image-variants.mjs.map +1 -0
  810. package/esm/http/uploads/read-file-head.mjs +1 -1
  811. package/esm/http/uploads/read-file-head.mjs.map +1 -1
  812. package/esm/http/uploads/resolve-image-variant.d.mts +73 -0
  813. package/esm/http/uploads/resolve-image-variant.d.mts.map +1 -0
  814. package/esm/http/uploads/resolve-image-variant.mjs +107 -0
  815. package/esm/http/uploads/resolve-image-variant.mjs.map +1 -0
  816. package/esm/http/uploads/resolve-image-variants-config.mjs +1 -1
  817. package/esm/http/uploads/resolve-image-variants-config.mjs.map +1 -1
  818. package/esm/http/uploads/resolve-inline-image-content-type.mjs +1 -1
  819. package/esm/http/uploads/resolve-inline-image-content-type.mjs.map +1 -1
  820. package/esm/http/uploads/resolve-original-content-type.mjs +1 -1
  821. package/esm/http/uploads/resolve-original-content-type.mjs.map +1 -1
  822. package/esm/http/uploads/resolve-upload-path.mjs +3 -2
  823. package/esm/http/uploads/resolve-upload-path.mjs.map +1 -1
  824. package/esm/http/uploads/resolve-variant-candidate.mjs +1 -1
  825. package/esm/http/uploads/resolve-variant-candidate.mjs.map +1 -1
  826. package/esm/http/uploads/single-flight.mjs +1 -1
  827. package/esm/http/uploads/single-flight.mjs.map +1 -1
  828. package/esm/http/uploads/uploaded-file.controller.d.mts +24 -6
  829. package/esm/http/uploads/uploaded-file.controller.d.mts.map +1 -1
  830. package/esm/http/uploads/uploaded-file.controller.mjs +63 -91
  831. package/esm/http/uploads/uploaded-file.controller.mjs.map +1 -1
  832. package/esm/http/uploads/variant-cache-key.mjs +30 -5
  833. package/esm/http/uploads/variant-cache-key.mjs.map +1 -1
  834. package/esm/http/uploads/variant-generations.mjs +1 -1
  835. package/esm/http/uploads/variant-generations.mjs.map +1 -1
  836. package/esm/http/uploads-config.d.mts +1 -1
  837. package/esm/http/uploads-config.d.mts.map +1 -1
  838. package/esm/http/uploads-config.mjs +1 -1
  839. package/esm/http/uploads-config.mjs.map +1 -1
  840. package/esm/http/uploads-types.d.mts +1 -1
  841. package/esm/http/uploads-types.d.mts.map +1 -1
  842. package/esm/http/xmlable.d.mts +1 -1
  843. package/esm/http/xmlable.d.mts.map +1 -1
  844. package/esm/image/image.d.mts +1 -1
  845. package/esm/image/image.d.mts.map +1 -1
  846. package/esm/image/image.mjs +1 -1
  847. package/esm/image/image.mjs.map +1 -1
  848. package/esm/index.d.mts +13 -9
  849. package/esm/index.mjs +10 -7
  850. package/esm/loader/app-module-importer.d.mts +1 -1
  851. package/esm/loader/app-module-importer.d.mts.map +1 -1
  852. package/esm/loader/app-module-importer.mjs +1 -1
  853. package/esm/loader/app-module-importer.mjs.map +1 -1
  854. package/esm/localization/parse-locale-dictionary.d.mts +1 -1
  855. package/esm/localization/parse-locale-dictionary.d.mts.map +1 -1
  856. package/esm/localization/parse-locale-dictionary.mjs +1 -1
  857. package/esm/localization/parse-locale-dictionary.mjs.map +1 -1
  858. package/esm/localization/register-locale-dictionary.d.mts +1 -1
  859. package/esm/localization/register-locale-dictionary.d.mts.map +1 -1
  860. package/esm/localization/register-locale-dictionary.mjs +1 -1
  861. package/esm/localization/register-locale-dictionary.mjs.map +1 -1
  862. package/esm/logger/fatal-visibility.d.mts +1 -1
  863. package/esm/logger/fatal-visibility.d.mts.map +1 -1
  864. package/esm/logger/fatal-visibility.mjs +1 -1
  865. package/esm/logger/fatal-visibility.mjs.map +1 -1
  866. package/esm/logger/logger.d.mts +1 -1
  867. package/esm/logger/logger.d.mts.map +1 -1
  868. package/esm/logger/logger.mjs +1 -1
  869. package/esm/logger/logger.mjs.map +1 -1
  870. package/esm/logger/types.d.mts +1 -1
  871. package/esm/logger/types.d.mts.map +1 -1
  872. package/esm/mail/config.d.mts +1 -1
  873. package/esm/mail/config.d.mts.map +1 -1
  874. package/esm/mail/config.mjs +1 -1
  875. package/esm/mail/config.mjs.map +1 -1
  876. package/esm/mail/events.d.mts +1 -1
  877. package/esm/mail/events.d.mts.map +1 -1
  878. package/esm/mail/events.mjs +1 -1
  879. package/esm/mail/events.mjs.map +1 -1
  880. package/esm/mail/mail.d.mts +1 -1
  881. package/esm/mail/mail.d.mts.map +1 -1
  882. package/esm/mail/mail.mjs +1 -1
  883. package/esm/mail/mail.mjs.map +1 -1
  884. package/esm/mail/mailer-pool.d.mts +1 -1
  885. package/esm/mail/mailer-pool.d.mts.map +1 -1
  886. package/esm/mail/mailer-pool.mjs +1 -1
  887. package/esm/mail/mailer-pool.mjs.map +1 -1
  888. package/esm/mail/react-mail.d.mts +1 -1
  889. package/esm/mail/react-mail.d.mts.map +1 -1
  890. package/esm/mail/react-mail.mjs +1 -1
  891. package/esm/mail/react-mail.mjs.map +1 -1
  892. package/esm/mail/send-mail.d.mts +1 -1
  893. package/esm/mail/send-mail.d.mts.map +1 -1
  894. package/esm/mail/send-mail.mjs +7 -7
  895. package/esm/mail/send-mail.mjs.map +1 -1
  896. package/esm/mail/test-mailbox.d.mts +1 -1
  897. package/esm/mail/test-mailbox.d.mts.map +1 -1
  898. package/esm/mail/test-mailbox.mjs +1 -1
  899. package/esm/mail/test-mailbox.mjs.map +1 -1
  900. package/esm/mail/types.d.mts +1 -1
  901. package/esm/mail/types.d.mts.map +1 -1
  902. package/esm/mail/types.mjs +1 -1
  903. package/esm/mail/types.mjs.map +1 -1
  904. package/esm/manifest/manifest-manager.mjs +1 -1
  905. package/esm/manifest/manifest-manager.mjs.map +1 -1
  906. package/esm/openapi/build-openapi-document.d.mts +1 -1
  907. package/esm/openapi/build-openapi-document.d.mts.map +1 -1
  908. package/esm/openapi/build-openapi-document.mjs +1 -1
  909. package/esm/openapi/build-openapi-document.mjs.map +1 -1
  910. package/esm/openapi/cast-schema.mjs +1 -1
  911. package/esm/openapi/cast-schema.mjs.map +1 -1
  912. package/esm/openapi/collect-openapi-document.mjs +1 -1
  913. package/esm/openapi/collect-openapi-document.mjs.map +1 -1
  914. package/esm/openapi/development-openapi-provider.d.mts +1 -1
  915. package/esm/openapi/development-openapi-provider.d.mts.map +1 -1
  916. package/esm/openapi/development-openapi-provider.mjs +1 -1
  917. package/esm/openapi/development-openapi-provider.mjs.map +1 -1
  918. package/esm/openapi/error-responses.mjs +1 -1
  919. package/esm/openapi/error-responses.mjs.map +1 -1
  920. package/esm/openapi/openapi-child-output.mjs +1 -1
  921. package/esm/openapi/openapi-child-output.mjs.map +1 -1
  922. package/esm/openapi/openapi-protocol.mjs +1 -1
  923. package/esm/openapi/openapi-protocol.mjs.map +1 -1
  924. package/esm/openapi/paths.mjs +1 -1
  925. package/esm/openapi/paths.mjs.map +1 -1
  926. package/esm/openapi/postman/build-request-body.mjs +1 -1
  927. package/esm/openapi/postman/build-request-body.mjs.map +1 -1
  928. package/esm/openapi/postman/build-request-url.mjs +1 -1
  929. package/esm/openapi/postman/build-request-url.mjs.map +1 -1
  930. package/esm/openapi/postman/build-saved-responses.mjs +1 -1
  931. package/esm/openapi/postman/build-saved-responses.mjs.map +1 -1
  932. package/esm/openapi/postman/example-from-schema.d.mts +1 -1
  933. package/esm/openapi/postman/example-from-schema.d.mts.map +1 -1
  934. package/esm/openapi/postman/example-from-schema.mjs +1 -1
  935. package/esm/openapi/postman/example-from-schema.mjs.map +1 -1
  936. package/esm/openapi/postman/http-status-text.mjs +1 -1
  937. package/esm/openapi/postman/http-status-text.mjs.map +1 -1
  938. package/esm/openapi/postman/openapi-to-postman-collection.d.mts +1 -1
  939. package/esm/openapi/postman/openapi-to-postman-collection.d.mts.map +1 -1
  940. package/esm/openapi/postman/openapi-to-postman-collection.mjs +1 -1
  941. package/esm/openapi/postman/openapi-to-postman-collection.mjs.map +1 -1
  942. package/esm/openapi/postman/postman-types.d.mts +1 -1
  943. package/esm/openapi/postman/postman-types.d.mts.map +1 -1
  944. package/esm/openapi/postman/resolve-operation-auth.mjs +1 -1
  945. package/esm/openapi/postman/resolve-operation-auth.mjs.map +1 -1
  946. package/esm/openapi/postman/schema-refs.d.mts +1 -1
  947. package/esm/openapi/postman/schema-refs.d.mts.map +1 -1
  948. package/esm/openapi/postman/schema-refs.mjs +1 -1
  949. package/esm/openapi/postman/schema-refs.mjs.map +1 -1
  950. package/esm/openapi/postman/uuid-v5.mjs +1 -1
  951. package/esm/openapi/postman/uuid-v5.mjs.map +1 -1
  952. package/esm/openapi/request-schemas.mjs +1 -1
  953. package/esm/openapi/request-schemas.mjs.map +1 -1
  954. package/esm/openapi/response-schemas.mjs +1 -1
  955. package/esm/openapi/response-schemas.mjs.map +1 -1
  956. package/esm/openapi/schema-registry.mjs +1 -1
  957. package/esm/openapi/schema-registry.mjs.map +1 -1
  958. package/esm/openapi/security.mjs +1 -1
  959. package/esm/openapi/security.mjs.map +1 -1
  960. package/esm/openapi/types.d.mts +1 -1
  961. package/esm/openapi/types.d.mts.map +1 -1
  962. package/esm/production/assert-dist-ready-to-start.mjs +1 -1
  963. package/esm/production/assert-dist-ready-to-start.mjs.map +1 -1
  964. package/esm/production/assert-generated-imports.mjs +1 -1
  965. package/esm/production/assert-generated-imports.mjs.map +1 -1
  966. package/esm/production/build-app-production.mjs +1 -1
  967. package/esm/production/build-app-production.mjs.map +1 -1
  968. package/esm/production/build-contributions.mjs +1 -1
  969. package/esm/production/build-contributions.mjs.map +1 -1
  970. package/esm/production/bundle-framework-dependencies.mjs +1 -1
  971. package/esm/production/bundle-framework-dependencies.mjs.map +1 -1
  972. package/esm/production/dist-build-manifest.mjs +1 -1
  973. package/esm/production/dist-build-manifest.mjs.map +1 -1
  974. package/esm/production/esbuild-plugins.mjs +1 -1
  975. package/esm/production/esbuild-plugins.mjs.map +1 -1
  976. package/esm/production/esbuild-preflight.mjs +1 -1
  977. package/esm/production/esbuild-preflight.mjs.map +1 -1
  978. package/esm/production/production-builder.mjs +1 -1
  979. package/esm/production/production-builder.mjs.map +1 -1
  980. package/esm/production/production-supervisor.mjs +1 -1
  981. package/esm/production/production-supervisor.mjs.map +1 -1
  982. package/esm/production/promote-dist.mjs +1 -1
  983. package/esm/production/promote-dist.mjs.map +1 -1
  984. package/esm/production/registration-child-runner.mjs +1 -1
  985. package/esm/production/registration-child-runner.mjs.map +1 -1
  986. package/esm/production/resolve-build-config.d.mts +1 -1
  987. package/esm/production/resolve-build-config.d.mts.map +1 -1
  988. package/esm/production/resolve-build-config.mjs +1 -1
  989. package/esm/production/resolve-build-config.mjs.map +1 -1
  990. package/esm/production/route-registration-child.mjs +1 -1
  991. package/esm/production/route-registration-child.mjs.map +1 -1
  992. package/esm/production/route-registration-snapshot.mjs +1 -1
  993. package/esm/production/route-registration-snapshot.mjs.map +1 -1
  994. package/esm/production/tsconfig-path-aliases.mjs +1 -1
  995. package/esm/production/tsconfig-path-aliases.mjs.map +1 -1
  996. package/esm/react/index.d.mts +1 -1
  997. package/esm/react/index.d.mts.map +1 -1
  998. package/esm/react/index.mjs +1 -1
  999. package/esm/react/index.mjs.map +1 -1
  1000. package/esm/repositories/adapters/cascade/cascade-adapter.d.mts +1 -1
  1001. package/esm/repositories/adapters/cascade/cascade-adapter.d.mts.map +1 -1
  1002. package/esm/repositories/adapters/cascade/cascade-adapter.mjs +1 -1
  1003. package/esm/repositories/adapters/cascade/cascade-adapter.mjs.map +1 -1
  1004. package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +1 -1
  1005. package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts.map +1 -1
  1006. package/esm/repositories/adapters/cascade/cascade-query-builder.mjs +1 -1
  1007. package/esm/repositories/adapters/cascade/cascade-query-builder.mjs.map +1 -1
  1008. package/esm/repositories/adapters/cascade/filter-applicator.mjs +1 -1
  1009. package/esm/repositories/adapters/cascade/filter-applicator.mjs.map +1 -1
  1010. package/esm/repositories/contracts/query-builder.contract.d.mts +1 -1
  1011. package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
  1012. package/esm/repositories/contracts/repository-adapter.contract.d.mts +1 -1
  1013. package/esm/repositories/contracts/repository-adapter.contract.d.mts.map +1 -1
  1014. package/esm/repositories/contracts/types.d.mts +1 -1
  1015. package/esm/repositories/contracts/types.d.mts.map +1 -1
  1016. package/esm/repositories/repository.manager.d.mts +1 -1
  1017. package/esm/repositories/repository.manager.d.mts.map +1 -1
  1018. package/esm/repositories/repository.manager.mjs +1 -1
  1019. package/esm/repositories/repository.manager.mjs.map +1 -1
  1020. package/esm/resource/define-resource.d.mts +1 -1
  1021. package/esm/resource/define-resource.d.mts.map +1 -1
  1022. package/esm/resource/define-resource.mjs +1 -1
  1023. package/esm/resource/define-resource.mjs.map +1 -1
  1024. package/esm/resource/nullable-resource.d.mts +1 -1
  1025. package/esm/resource/nullable-resource.d.mts.map +1 -1
  1026. package/esm/resource/nullable-resource.mjs +1 -1
  1027. package/esm/resource/nullable-resource.mjs.map +1 -1
  1028. package/esm/resource/register-resource.d.mts +1 -1
  1029. package/esm/resource/register-resource.d.mts.map +1 -1
  1030. package/esm/resource/register-resource.mjs +1 -1
  1031. package/esm/resource/register-resource.mjs.map +1 -1
  1032. package/esm/resource/resource-field-builder.d.mts +1 -1
  1033. package/esm/resource/resource-field-builder.d.mts.map +1 -1
  1034. package/esm/resource/resource-field-builder.mjs +1 -1
  1035. package/esm/resource/resource-field-builder.mjs.map +1 -1
  1036. package/esm/resource/resource.d.mts +1 -1
  1037. package/esm/resource/resource.d.mts.map +1 -1
  1038. package/esm/resource/resource.mjs +1 -1
  1039. package/esm/resource/resource.mjs.map +1 -1
  1040. package/esm/resource/types.d.mts +1 -1
  1041. package/esm/resource/types.d.mts.map +1 -1
  1042. package/esm/restful/restful.d.mts +1 -1
  1043. package/esm/restful/restful.d.mts.map +1 -1
  1044. package/esm/restful/restful.mjs +1 -1
  1045. package/esm/restful/restful.mjs.map +1 -1
  1046. package/esm/router/build-route-rate-limit.mjs +1 -1
  1047. package/esm/router/build-route-rate-limit.mjs.map +1 -1
  1048. package/esm/router/describe-route-for-log.mjs +1 -1
  1049. package/esm/router/describe-route-for-log.mjs.map +1 -1
  1050. package/esm/router/dev-dispatch.mjs +1 -1
  1051. package/esm/router/dev-dispatch.mjs.map +1 -1
  1052. package/esm/router/log-request-lifecycle.mjs +1 -1
  1053. package/esm/router/log-request-lifecycle.mjs.map +1 -1
  1054. package/esm/router/named-api-routes-with-responses.mjs +1 -1
  1055. package/esm/router/named-api-routes-with-responses.mjs.map +1 -1
  1056. package/esm/router/normalize-request-path.d.mts +1 -1
  1057. package/esm/router/normalize-request-path.d.mts.map +1 -1
  1058. package/esm/router/normalize-request-path.mjs +1 -1
  1059. package/esm/router/normalize-request-path.mjs.map +1 -1
  1060. package/esm/router/normalize-route-path.d.mts +1 -1
  1061. package/esm/router/normalize-route-path.d.mts.map +1 -1
  1062. package/esm/router/normalize-route-path.mjs +1 -1
  1063. package/esm/router/normalize-route-path.mjs.map +1 -1
  1064. package/esm/router/positional-handler-diagnostics.d.mts +1 -1
  1065. package/esm/router/positional-handler-diagnostics.d.mts.map +1 -1
  1066. package/esm/router/positional-handler-diagnostics.mjs +1 -1
  1067. package/esm/router/positional-handler-diagnostics.mjs.map +1 -1
  1068. package/esm/router/response-schema-types.mjs +1 -1
  1069. package/esm/router/response-schema-types.mjs.map +1 -1
  1070. package/esm/router/route-builder.d.mts +1 -1
  1071. package/esm/router/route-builder.d.mts.map +1 -1
  1072. package/esm/router/route-builder.mjs +1 -1
  1073. package/esm/router/route-builder.mjs.map +1 -1
  1074. package/esm/router/route-name-method-suffix.d.mts +1 -1
  1075. package/esm/router/route-name-method-suffix.d.mts.map +1 -1
  1076. package/esm/router/route-name-method-suffix.mjs +1 -1
  1077. package/esm/router/route-name-method-suffix.mjs.map +1 -1
  1078. package/esm/router/route-registry.d.mts +1 -1
  1079. package/esm/router/route-registry.d.mts.map +1 -1
  1080. package/esm/router/route-registry.mjs +1 -1
  1081. package/esm/router/route-registry.mjs.map +1 -1
  1082. package/esm/router/router.d.mts +8 -1
  1083. package/esm/router/router.d.mts.map +1 -1
  1084. package/esm/router/router.mjs +20 -15
  1085. package/esm/router/router.mjs.map +1 -1
  1086. package/esm/router/types.d.mts +13 -1
  1087. package/esm/router/types.d.mts.map +1 -1
  1088. package/esm/socket/types.d.mts +1 -1
  1089. package/esm/socket/types.d.mts.map +1 -1
  1090. package/esm/socket/utils.d.mts +1 -1
  1091. package/esm/socket/utils.d.mts.map +1 -1
  1092. package/esm/socket/utils.mjs +1 -1
  1093. package/esm/socket/utils.mjs.map +1 -1
  1094. package/esm/storage/config.d.mts +1 -1
  1095. package/esm/storage/config.d.mts.map +1 -1
  1096. package/esm/storage/config.mjs +1 -1
  1097. package/esm/storage/config.mjs.map +1 -1
  1098. package/esm/storage/context/storage-driver-context.d.mts +1 -1
  1099. package/esm/storage/context/storage-driver-context.d.mts.map +1 -1
  1100. package/esm/storage/context/storage-driver-context.mjs +1 -1
  1101. package/esm/storage/context/storage-driver-context.mjs.map +1 -1
  1102. package/esm/storage/drivers/cloud-driver.d.mts +1 -1
  1103. package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
  1104. package/esm/storage/drivers/cloud-driver.mjs +1 -1
  1105. package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
  1106. package/esm/storage/drivers/do-spaces-driver.d.mts +1 -1
  1107. package/esm/storage/drivers/do-spaces-driver.d.mts.map +1 -1
  1108. package/esm/storage/drivers/do-spaces-driver.mjs +1 -1
  1109. package/esm/storage/drivers/do-spaces-driver.mjs.map +1 -1
  1110. package/esm/storage/drivers/local-driver.d.mts +12 -1
  1111. package/esm/storage/drivers/local-driver.d.mts.map +1 -1
  1112. package/esm/storage/drivers/local-driver.mjs +33 -1
  1113. package/esm/storage/drivers/local-driver.mjs.map +1 -1
  1114. package/esm/storage/drivers/r2-driver.d.mts +1 -1
  1115. package/esm/storage/drivers/r2-driver.d.mts.map +1 -1
  1116. package/esm/storage/drivers/r2-driver.mjs +1 -1
  1117. package/esm/storage/drivers/r2-driver.mjs.map +1 -1
  1118. package/esm/storage/drivers/s3-driver.d.mts +1 -1
  1119. package/esm/storage/drivers/s3-driver.d.mts.map +1 -1
  1120. package/esm/storage/drivers/s3-driver.mjs +1 -1
  1121. package/esm/storage/drivers/s3-driver.mjs.map +1 -1
  1122. package/esm/storage/index.d.mts +1 -1
  1123. package/esm/storage/scoped-storage.d.mts +1 -1
  1124. package/esm/storage/scoped-storage.d.mts.map +1 -1
  1125. package/esm/storage/scoped-storage.mjs +1 -1
  1126. package/esm/storage/scoped-storage.mjs.map +1 -1
  1127. package/esm/storage/storage-file.d.mts +1 -1
  1128. package/esm/storage/storage-file.d.mts.map +1 -1
  1129. package/esm/storage/storage-file.mjs +1 -1
  1130. package/esm/storage/storage-file.mjs.map +1 -1
  1131. package/esm/storage/storage.d.mts +3 -3
  1132. package/esm/storage/storage.d.mts.map +1 -1
  1133. package/esm/storage/storage.mjs +1 -1
  1134. package/esm/storage/storage.mjs.map +1 -1
  1135. package/esm/storage/types.d.mts +3 -2
  1136. package/esm/storage/types.d.mts.map +1 -1
  1137. package/esm/storage/utils/classify-ip-address.d.mts +1 -1
  1138. package/esm/storage/utils/classify-ip-address.d.mts.map +1 -1
  1139. package/esm/storage/utils/classify-ip-address.mjs +1 -1
  1140. package/esm/storage/utils/classify-ip-address.mjs.map +1 -1
  1141. package/esm/storage/utils/contain-path.d.mts +1 -1
  1142. package/esm/storage/utils/contain-path.d.mts.map +1 -1
  1143. package/esm/storage/utils/contain-path.mjs +1 -1
  1144. package/esm/storage/utils/contain-path.mjs.map +1 -1
  1145. package/esm/storage/utils/mime.d.mts +1 -1
  1146. package/esm/storage/utils/mime.d.mts.map +1 -1
  1147. package/esm/storage/utils/mime.mjs +1 -1
  1148. package/esm/storage/utils/mime.mjs.map +1 -1
  1149. package/esm/storage/utils/safe-fetch.d.mts +1 -1
  1150. package/esm/storage/utils/safe-fetch.d.mts.map +1 -1
  1151. package/esm/storage/utils/safe-fetch.mjs +1 -1
  1152. package/esm/storage/utils/safe-fetch.mjs.map +1 -1
  1153. package/esm/storage/utils/storage-capability-error.d.mts +1 -1
  1154. package/esm/storage/utils/storage-capability-error.d.mts.map +1 -1
  1155. package/esm/storage/utils/storage-capability-error.mjs +1 -1
  1156. package/esm/storage/utils/storage-capability-error.mjs.map +1 -1
  1157. package/esm/storage/utils/storage-error.d.mts +1 -1
  1158. package/esm/storage/utils/storage-error.d.mts.map +1 -1
  1159. package/esm/storage/utils/storage-error.mjs +1 -1
  1160. package/esm/storage/utils/storage-error.mjs.map +1 -1
  1161. package/esm/storage/utils/storage-not-initialized-error.d.mts +1 -1
  1162. package/esm/storage/utils/storage-not-initialized-error.d.mts.map +1 -1
  1163. package/esm/storage/utils/storage-not-initialized-error.mjs +1 -1
  1164. package/esm/storage/utils/storage-not-initialized-error.mjs.map +1 -1
  1165. package/esm/tests/start-http-development-server.d.mts +1 -1
  1166. package/esm/tests/start-http-development-server.d.mts.map +1 -1
  1167. package/esm/tests/start-http-development-server.mjs +1 -1
  1168. package/esm/tests/start-http-development-server.mjs.map +1 -1
  1169. package/esm/tests/test-connectors-selection.d.mts +1 -1
  1170. package/esm/tests/test-connectors-selection.d.mts.map +1 -1
  1171. package/esm/tests/test-connectors-selection.mjs +1 -1
  1172. package/esm/tests/test-connectors-selection.mjs.map +1 -1
  1173. package/esm/tests/test-helpers.d.mts +1 -1
  1174. package/esm/tests/test-helpers.d.mts.map +1 -1
  1175. package/esm/tests/test-helpers.mjs +1 -1
  1176. package/esm/tests/test-helpers.mjs.map +1 -1
  1177. package/esm/tests/test-lifecycle-state.mjs +1 -1
  1178. package/esm/tests/test-lifecycle-state.mjs.map +1 -1
  1179. package/esm/tests/test-server-port-channel.mjs +1 -1
  1180. package/esm/tests/test-server-port-channel.mjs.map +1 -1
  1181. package/esm/tests/test-setup-timeout.mjs +1 -1
  1182. package/esm/tests/test-setup-timeout.mjs.map +1 -1
  1183. package/esm/tests/vitest-setup.d.mts +1 -1
  1184. package/esm/tests/vitest-setup.d.mts.map +1 -1
  1185. package/esm/tests/vitest-setup.mjs +1 -1
  1186. package/esm/tests/vitest-setup.mjs.map +1 -1
  1187. package/esm/updater/package-manager.mjs +1 -1
  1188. package/esm/updater/package-manager.mjs.map +1 -1
  1189. package/esm/updater/update-warlock-packages.mjs +1 -1
  1190. package/esm/updater/update-warlock-packages.mjs.map +1 -1
  1191. package/esm/use-cases/types.d.mts +1 -1
  1192. package/esm/use-cases/types.d.mts.map +1 -1
  1193. package/esm/use-cases/use-case-broadcast.d.mts +1 -1
  1194. package/esm/use-cases/use-case-broadcast.d.mts.map +1 -1
  1195. package/esm/use-cases/use-case-broadcast.mjs +1 -1
  1196. package/esm/use-cases/use-case-broadcast.mjs.map +1 -1
  1197. package/esm/use-cases/use-case-events.d.mts +1 -1
  1198. package/esm/use-cases/use-case-events.d.mts.map +1 -1
  1199. package/esm/use-cases/use-case-events.mjs +1 -1
  1200. package/esm/use-cases/use-case-events.mjs.map +1 -1
  1201. package/esm/use-cases/use-case-pipeline.d.mts +1 -1
  1202. package/esm/use-cases/use-case-pipeline.d.mts.map +1 -1
  1203. package/esm/use-cases/use-case-pipeline.mjs +1 -1
  1204. package/esm/use-cases/use-case-pipeline.mjs.map +1 -1
  1205. package/esm/use-cases/use-case.d.mts +1 -1
  1206. package/esm/use-cases/use-case.d.mts.map +1 -1
  1207. package/esm/use-cases/use-case.errors.d.mts +1 -1
  1208. package/esm/use-cases/use-case.errors.d.mts.map +1 -1
  1209. package/esm/use-cases/use-case.errors.mjs +1 -1
  1210. package/esm/use-cases/use-case.errors.mjs.map +1 -1
  1211. package/esm/use-cases/use-case.mjs +1 -1
  1212. package/esm/use-cases/use-case.mjs.map +1 -1
  1213. package/esm/use-cases/use-cases-registry.d.mts +1 -1
  1214. package/esm/use-cases/use-cases-registry.d.mts.map +1 -1
  1215. package/esm/use-cases/use-cases-registry.mjs +1 -1
  1216. package/esm/use-cases/use-cases-registry.mjs.map +1 -1
  1217. package/esm/utils/app-log.d.mts +6 -6
  1218. package/esm/utils/app-log.d.mts.map +1 -1
  1219. package/esm/utils/app-log.mjs +1 -1
  1220. package/esm/utils/app-log.mjs.map +1 -1
  1221. package/esm/utils/database-log.d.mts +1 -1
  1222. package/esm/utils/database-log.d.mts.map +1 -1
  1223. package/esm/utils/database-log.mjs +1 -1
  1224. package/esm/utils/database-log.mjs.map +1 -1
  1225. package/esm/utils/detect-environment-overrides.mjs +1 -1
  1226. package/esm/utils/detect-environment-overrides.mjs.map +1 -1
  1227. package/esm/utils/environment.d.mts +1 -1
  1228. package/esm/utils/environment.d.mts.map +1 -1
  1229. package/esm/utils/environment.mjs +1 -1
  1230. package/esm/utils/environment.mjs.map +1 -1
  1231. package/esm/utils/framework-vesion.mjs +1 -1
  1232. package/esm/utils/framework-vesion.mjs.map +1 -1
  1233. package/esm/utils/get-localized.d.mts +1 -1
  1234. package/esm/utils/get-localized.d.mts.map +1 -1
  1235. package/esm/utils/get-localized.mjs +1 -1
  1236. package/esm/utils/get-localized.mjs.map +1 -1
  1237. package/esm/utils/is-test-file.mjs +1 -1
  1238. package/esm/utils/is-test-file.mjs.map +1 -1
  1239. package/esm/utils/load-environment.mjs +1 -1
  1240. package/esm/utils/load-environment.mjs.map +1 -1
  1241. package/esm/utils/normalized-path.d.mts +1 -1
  1242. package/esm/utils/normalized-path.d.mts.map +1 -1
  1243. package/esm/utils/normalized-path.mjs +1 -1
  1244. package/esm/utils/normalized-path.mjs.map +1 -1
  1245. package/esm/utils/npm-registry.d.mts +1 -1
  1246. package/esm/utils/npm-registry.d.mts.map +1 -1
  1247. package/esm/utils/npm-registry.mjs +1 -1
  1248. package/esm/utils/npm-registry.mjs.map +1 -1
  1249. package/esm/utils/paths.d.mts +1 -1
  1250. package/esm/utils/paths.d.mts.map +1 -1
  1251. package/esm/utils/paths.mjs +1 -1
  1252. package/esm/utils/paths.mjs.map +1 -1
  1253. package/esm/utils/promise-all-object.d.mts +1 -1
  1254. package/esm/utils/promise-all-object.d.mts.map +1 -1
  1255. package/esm/utils/promise-all-object.mjs +1 -1
  1256. package/esm/utils/promise-all-object.mjs.map +1 -1
  1257. package/esm/utils/queue.d.mts +1 -1
  1258. package/esm/utils/queue.d.mts.map +1 -1
  1259. package/esm/utils/queue.mjs +1 -1
  1260. package/esm/utils/queue.mjs.map +1 -1
  1261. package/esm/utils/recorded-environment-overrides.mjs +1 -1
  1262. package/esm/utils/recorded-environment-overrides.mjs.map +1 -1
  1263. package/esm/utils/report-environment-overrides.mjs +1 -1
  1264. package/esm/utils/report-environment-overrides.mjs.map +1 -1
  1265. package/esm/utils/sleep.d.mts +1 -1
  1266. package/esm/utils/sleep.d.mts.map +1 -1
  1267. package/esm/utils/sleep.mjs +1 -1
  1268. package/esm/utils/sleep.mjs.map +1 -1
  1269. package/esm/utils/sluggable.d.mts +1 -1
  1270. package/esm/utils/sluggable.d.mts.map +1 -1
  1271. package/esm/utils/sluggable.mjs +1 -1
  1272. package/esm/utils/sluggable.mjs.map +1 -1
  1273. package/esm/utils/to-json.d.mts +1 -1
  1274. package/esm/utils/to-json.d.mts.map +1 -1
  1275. package/esm/utils/to-json.mjs +1 -1
  1276. package/esm/utils/to-json.mjs.map +1 -1
  1277. package/esm/utils/types.d.mts +1 -1
  1278. package/esm/utils/types.d.mts.map +1 -1
  1279. package/esm/utils/urls.d.mts +1 -1
  1280. package/esm/utils/urls.d.mts.map +1 -1
  1281. package/esm/utils/urls.mjs +1 -1
  1282. package/esm/utils/urls.mjs.map +1 -1
  1283. package/esm/utils/version-compare.d.mts +1 -1
  1284. package/esm/utils/version-compare.d.mts.map +1 -1
  1285. package/esm/utils/version-compare.mjs +1 -1
  1286. package/esm/utils/version-compare.mjs.map +1 -1
  1287. package/esm/validation/database/exists-except-current-id.d.mts +1 -1
  1288. package/esm/validation/database/exists-except-current-id.d.mts.map +1 -1
  1289. package/esm/validation/database/exists-except-current-id.mjs +1 -1
  1290. package/esm/validation/database/exists-except-current-id.mjs.map +1 -1
  1291. package/esm/validation/database/exists-except-current-user.d.mts +1 -1
  1292. package/esm/validation/database/exists-except-current-user.d.mts.map +1 -1
  1293. package/esm/validation/database/exists-except-current-user.mjs +1 -1
  1294. package/esm/validation/database/exists-except-current-user.mjs.map +1 -1
  1295. package/esm/validation/database/types.d.mts +1 -1
  1296. package/esm/validation/database/types.d.mts.map +1 -1
  1297. package/esm/validation/database/unique-except-current-id.d.mts +1 -1
  1298. package/esm/validation/database/unique-except-current-id.d.mts.map +1 -1
  1299. package/esm/validation/database/unique-except-current-id.mjs +1 -1
  1300. package/esm/validation/database/unique-except-current-id.mjs.map +1 -1
  1301. package/esm/validation/database/unique-except-current-user.d.mts +1 -1
  1302. package/esm/validation/database/unique-except-current-user.d.mts.map +1 -1
  1303. package/esm/validation/database/unique-except-current-user.mjs +1 -1
  1304. package/esm/validation/database/unique-except-current-user.mjs.map +1 -1
  1305. package/esm/validation/file/file.d.mts +1 -1
  1306. package/esm/validation/file/file.d.mts.map +1 -1
  1307. package/esm/validation/file/file.mjs +1 -1
  1308. package/esm/validation/file/file.mjs.map +1 -1
  1309. package/esm/validation/init.mjs +1 -1
  1310. package/esm/validation/init.mjs.map +1 -1
  1311. package/esm/validation/plugins/database-plugin.mjs +1 -1
  1312. package/esm/validation/plugins/database-plugin.mjs.map +1 -1
  1313. package/esm/validation/plugins/file-plugin.mjs +1 -1
  1314. package/esm/validation/plugins/file-plugin.mjs.map +1 -1
  1315. package/esm/validation/plugins/localized-plugin.mjs +1 -1
  1316. package/esm/validation/plugins/localized-plugin.mjs.map +1 -1
  1317. package/esm/validation/types.d.mts +1 -1
  1318. package/esm/validation/types.d.mts.map +1 -1
  1319. package/esm/validation/validateAll.mjs +1 -1
  1320. package/esm/validation/validateAll.mjs.map +1 -1
  1321. package/esm/validation/validators/file-validator.d.mts +44 -41
  1322. package/esm/validation/validators/file-validator.d.mts.map +1 -1
  1323. package/esm/validation/validators/file-validator.mjs +4 -1
  1324. package/esm/validation/validators/file-validator.mjs.map +1 -1
  1325. package/esm/vite/lower-stage3-decorators.d.mts +1 -1
  1326. package/esm/vite/lower-stage3-decorators.d.mts.map +1 -1
  1327. package/esm/vite/lower-stage3-decorators.mjs +1 -1
  1328. package/esm/vite/lower-stage3-decorators.mjs.map +1 -1
  1329. package/esm/warlock-config/bundle-config.mjs +148 -0
  1330. package/esm/warlock-config/bundle-config.mjs.map +1 -0
  1331. package/esm/warlock-config/default-configurations.mjs +1 -1
  1332. package/esm/warlock-config/default-configurations.mjs.map +1 -1
  1333. package/esm/warlock-config/define-config.d.mts +1 -1
  1334. package/esm/warlock-config/define-config.d.mts.map +1 -1
  1335. package/esm/warlock-config/define-config.mjs +1 -1
  1336. package/esm/warlock-config/define-config.mjs.map +1 -1
  1337. package/esm/warlock-config/index.d.mts +1 -1
  1338. package/esm/warlock-config/index.mjs +1 -1
  1339. package/esm/warlock-config/normalize-build-config.mjs +1 -1
  1340. package/esm/warlock-config/normalize-build-config.mjs.map +1 -1
  1341. package/esm/warlock-config/types.d.mts +1 -1
  1342. package/esm/warlock-config/types.d.mts.map +1 -1
  1343. package/esm/warlock-config/warlock-config.manager.d.mts +32 -7
  1344. package/esm/warlock-config/warlock-config.manager.d.mts.map +1 -1
  1345. package/esm/warlock-config/warlock-config.manager.mjs +94 -18
  1346. package/esm/warlock-config/warlock-config.manager.mjs.map +1 -1
  1347. package/esm/warlock-config/warn-deprecated-config.mjs +1 -1
  1348. package/esm/warlock-config/warn-deprecated-config.mjs.map +1 -1
  1349. package/llms-full.txt +66 -9
  1350. package/package.json +20 -13
  1351. package/skills/configure-app/SKILL.md +23 -1
  1352. package/skills/create-controller/SKILL.md +4 -0
  1353. package/skills/health-checks/SKILL.md +2 -0
  1354. package/skills/register-route/SKILL.md +10 -0
  1355. package/skills/run-app/SKILL.md +9 -2
  1356. package/skills/send-response/SKILL.md +10 -2
  1357. package/skills/store-file/SKILL.md +5 -1
  1358. package/skills/use-middleware/SKILL.md +2 -2
  1359. package/skills/validate-input/SKILL.md +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"build-contributions.mjs","names":[],"sources":["../../../../../../../core/src/production/build-contributions.ts"],"sourcesContent":["import type { Connector, ConnectorBuildContext, ConnectorEsbuildPatch } from \"../connectors/types\";\n\n/**\n * `Error` with the `cause` option typed. Same shim as\n * `application.ts` — lib.es2022 declares `cause` on `ErrorOptions`, but the\n * package still compiles against an older lib in some consumers.\n */\ntype ErrorWithCauseConstructor = new (message: string, options: { cause: unknown }) => Error;\n\nconst ErrorWithCause = Error as ErrorWithCauseConstructor;\n\n/**\n * The only keys a `build` contribution may carry.\n *\n * The runtime half of the closed-contribution constraint: the\n * type already makes `build: { plugins: [...] }` unrepresentable, but a\n * plain `warlock.config.js`, an `as any`, or a connector compiled against an\n * older core all slip past the type. Rejected rather than ignored — the same\n * posture as the `tsconfig` guard in `resolve-build-config`: dropping the key\n * quietly would leave the author believing their plugin ran.\n */\nconst ALLOWED_CONTRIBUTION_KEYS = [\"generate\", \"emit\", \"typings\"] as const;\n\n/**\n * What the generate pass produced, merged across every contributor.\n */\nexport type GenerateContributionsResult = {\n /** Entry lines in contributor order, appended after `./routes` */\n entryImports: string[];\n /** The contributors' esbuild patches, merged into one */\n esbuild: ConnectorEsbuildPatch;\n};\n\n/**\n * Reject a contribution object carrying anything but the two hooks.\n *\n * @throws Error naming the connector and the offending key\n */\nexport function assertClosedContribution(connector: Connector): void {\n const contribution = connector.build;\n\n if (!contribution) return;\n\n for (const key of Object.keys(contribution)) {\n if ((ALLOWED_CONTRIBUTION_KEYS as readonly string[]).includes(key)) continue;\n\n throw new Error(\n `Connector \"${connector.name}\" declares an unsupported build contribution key \"${key}\". ` +\n `A build contribution carries exactly these optional hooks — ` +\n `${ALLOWED_CONTRIBUTION_KEYS.join(\", \")} — and no data. ` +\n `Anything a hook needs (plugins, pipelines, aliases) must be constructed inside ` +\n `that hook, so it never lands in the connector's static import graph.`,\n );\n }\n}\n\n/**\n * Drain every connector's `generate` hook, in array order, sequentially.\n *\n * Semantics are copied from `Application.runStartupValidators`\n * (`application.ts:304-329`) on purpose: ordered, awaited one at a time, and\n * a throw is rethrown wrapped in an error NAMING the contributor. A\n * contributor failure IS the build failing — that is what makes\n * \"green build, no client bundle\" unrepresentable rather than merely\n * unlikely.\n */\nexport async function runGenerateContributions(\n connectors: readonly Connector[],\n context: ConnectorBuildContext,\n): Promise<GenerateContributionsResult> {\n const entryImports: string[] = [];\n let esbuild: ConnectorEsbuildPatch = {};\n\n for (const connector of connectors) {\n assertClosedContribution(connector);\n\n const generate = connector.build?.generate;\n\n if (!generate) continue;\n\n const result = await runHook(connector, \"generate\", () => generate(context));\n\n if (!result) continue;\n\n if (result.entryImports) {\n entryImports.push(...result.entryImports);\n }\n\n if (result.esbuild) {\n esbuild = mergeEsbuildPatches(esbuild, result.esbuild);\n }\n }\n\n return { entryImports, esbuild };\n}\n\n/**\n * Drain every connector's `emit` hook, in array order, sequentially.\n *\n * Runs after esbuild and before `.warlock/production` is removed, so a hook\n * may still read what `generate` wrote there.\n */\nexport async function runEmitContributions(\n connectors: readonly Connector[],\n context: ConnectorBuildContext,\n): Promise<void> {\n for (const connector of connectors) {\n assertClosedContribution(connector);\n\n const emit = connector.build?.emit;\n\n if (!emit) continue;\n\n await runHook(connector, \"emit\", () => emit(context));\n }\n}\n\n/**\n * Drain every connector's `typings` hook, in array order, sequentially.\n * Connectors without one — every API-only app — are skipped without error.\n */\nexport async function runTypingsContributions(\n connectors: readonly Connector[],\n context: ConnectorBuildContext,\n): Promise<void> {\n for (const connector of connectors) {\n assertClosedContribution(connector);\n\n const typings = connector.build?.typings;\n\n if (!typings) continue;\n\n await runHook(connector, \"typings\", () => typings(context));\n }\n}\n\n/**\n * Merge two contributor patches. Later wins, except:\n *\n * - `define` merges per key — two contributors defining different\n * `import.meta.env.*` entries must both survive; a wholesale replace would\n * drop one silently.\n * - `external` concatenates and dedupes — it is a set of package names, and\n * under `singleBundle` each contributor adds its own optional peers.\n * - `loader` merges per extension, for the same reason as `define`.\n * - `plugins` concatenate in contribution order. They are constructed inside\n * a hook, so this does not reopen the closed-contribution constraint.\n */\nexport function mergeEsbuildPatches(\n base: ConnectorEsbuildPatch,\n patch: ConnectorEsbuildPatch,\n): ConnectorEsbuildPatch {\n const merged: ConnectorEsbuildPatch = { ...base, ...patch };\n\n if (base.define || patch.define) {\n merged.define = { ...base.define, ...patch.define };\n }\n\n if (base.external || patch.external) {\n merged.external = dedupe([...(base.external ?? []), ...(patch.external ?? [])]);\n }\n\n if (base.loader || patch.loader) {\n merged.loader = { ...base.loader, ...patch.loader };\n }\n\n if (base.plugins || patch.plugins) {\n merged.plugins = [...(base.plugins ?? []), ...(patch.plugins ?? [])];\n }\n\n return merged;\n}\n\n/**\n * Concatenation order preserved — esbuild does not care, but a stable order\n * keeps build output diffable.\n */\nexport function dedupe(values: string[]): string[] {\n return [...new Set(values)];\n}\n\n/**\n * Run one hook and rename its failure after the connector that owns it.\n */\nasync function runHook<Result>(\n connector: Connector,\n hook: \"generate\" | \"emit\" | \"typings\",\n run: () => Result | Promise<Result>,\n): Promise<Result> {\n try {\n return await run();\n } catch (error) {\n const cause = error instanceof Error ? error.message : String(error);\n\n throw new ErrorWithCause(\n `Build contribution \"${connector.name}\" failed during ${hook}: ${cause}. ` +\n `The build cannot continue — an artifact this connector was responsible for ` +\n `is missing, and shipping the bundle without it would fail at runtime instead.`,\n { cause: error },\n );\n }\n}\n"],"mappings":";AASA,MAAM,iBAAiB;;;;;;;;;;;AAYvB,MAAM,4BAA4B;CAAC;CAAY;CAAQ;AAAS;;;;;;AAiBhE,SAAgB,yBAAyB,WAA4B;CACnE,MAAM,eAAe,UAAU;CAE/B,IAAI,CAAC,cAAc;CAEnB,KAAK,MAAM,OAAO,OAAO,KAAK,YAAY,GAAG;EAC3C,IAAK,0BAAgD,SAAS,GAAG,GAAG;EAEpE,MAAM,IAAI,MACR,cAAc,UAAU,KAAK,oDAAoD,IAAI,iEAEhF,0BAA0B,KAAK,IAAI,EAAE,oKAG5C;CACF;AACF;;;;;;;;;;;AAYA,eAAsB,yBACpB,YACA,SACsC;CACtC,MAAM,eAAyB,CAAC;CAChC,IAAI,UAAiC,CAAC;CAEtC,KAAK,MAAM,aAAa,YAAY;EAClC,yBAAyB,SAAS;EAElC,MAAM,WAAW,UAAU,OAAO;EAElC,IAAI,CAAC,UAAU;EAEf,MAAM,SAAS,MAAM,QAAQ,WAAW,kBAAkB,SAAS,OAAO,CAAC;EAE3E,IAAI,CAAC,QAAQ;EAEb,IAAI,OAAO,cACT,aAAa,KAAK,GAAG,OAAO,YAAY;EAG1C,IAAI,OAAO,SACT,UAAU,oBAAoB,SAAS,OAAO,OAAO;CAEzD;CAEA,OAAO;EAAE;EAAc;CAAQ;AACjC;;;;;;;AAQA,eAAsB,qBACpB,YACA,SACe;CACf,KAAK,MAAM,aAAa,YAAY;EAClC,yBAAyB,SAAS;EAElC,MAAM,OAAO,UAAU,OAAO;EAE9B,IAAI,CAAC,MAAM;EAEX,MAAM,QAAQ,WAAW,cAAc,KAAK,OAAO,CAAC;CACtD;AACF;;;;;AAMA,eAAsB,wBACpB,YACA,SACe;CACf,KAAK,MAAM,aAAa,YAAY;EAClC,yBAAyB,SAAS;EAElC,MAAM,UAAU,UAAU,OAAO;EAEjC,IAAI,CAAC,SAAS;EAEd,MAAM,QAAQ,WAAW,iBAAiB,QAAQ,OAAO,CAAC;CAC5D;AACF;;;;;;;;;;;;;AAcA,SAAgB,oBACd,MACA,OACuB;CACvB,MAAM,SAAgC;EAAE,GAAG;EAAM,GAAG;CAAM;CAE1D,IAAI,KAAK,UAAU,MAAM,QACvB,OAAO,SAAS;EAAE,GAAG,KAAK;EAAQ,GAAG,MAAM;CAAO;CAGpD,IAAI,KAAK,YAAY,MAAM,UACzB,OAAO,WAAW,OAAO,CAAC,GAAI,KAAK,YAAY,CAAC,GAAI,GAAI,MAAM,YAAY,CAAC,CAAE,CAAC;CAGhF,IAAI,KAAK,UAAU,MAAM,QACvB,OAAO,SAAS;EAAE,GAAG,KAAK;EAAQ,GAAG,MAAM;CAAO;CAGpD,IAAI,KAAK,WAAW,MAAM,SACxB,OAAO,UAAU,CAAC,GAAI,KAAK,WAAW,CAAC,GAAI,GAAI,MAAM,WAAW,CAAC,CAAE;CAGrE,OAAO;AACT;;;;;AAMA,SAAgB,OAAO,QAA4B;CACjD,OAAO,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC;AAC5B;;;;AAKA,eAAe,QACb,WACA,MACA,KACiB;CACjB,IAAI;EACF,OAAO,MAAM,IAAI;CACnB,SAAS,OAAO;EACd,MAAM,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EAEnE,MAAM,IAAI,eACR,uBAAuB,UAAU,KAAK,kBAAkB,KAAK,IAAI,MAAM,6JAGvE,EAAE,OAAO,MAAM,CACjB;CACF;AACF"}
1
+ {"version":3,"file":"build-contributions.mjs","names":[],"sources":["../../../../../../../../packages/core/src/production/build-contributions.ts"],"sourcesContent":["import type { Connector, ConnectorBuildContext, ConnectorEsbuildPatch } from \"../connectors/types\";\n\n/**\n * `Error` with the `cause` option typed. Same shim as\n * `application.ts` — lib.es2022 declares `cause` on `ErrorOptions`, but the\n * package still compiles against an older lib in some consumers.\n */\ntype ErrorWithCauseConstructor = new (message: string, options: { cause: unknown }) => Error;\n\nconst ErrorWithCause = Error as ErrorWithCauseConstructor;\n\n/**\n * The only keys a `build` contribution may carry.\n *\n * The runtime half of the closed-contribution constraint: the\n * type already makes `build: { plugins: [...] }` unrepresentable, but a\n * plain `warlock.config.js`, an `as any`, or a connector compiled against an\n * older core all slip past the type. Rejected rather than ignored — the same\n * posture as the `tsconfig` guard in `resolve-build-config`: dropping the key\n * quietly would leave the author believing their plugin ran.\n */\nconst ALLOWED_CONTRIBUTION_KEYS = [\"generate\", \"emit\", \"typings\"] as const;\n\n/**\n * What the generate pass produced, merged across every contributor.\n */\nexport type GenerateContributionsResult = {\n /** Entry lines in contributor order, appended after `./routes` */\n entryImports: string[];\n /** The contributors' esbuild patches, merged into one */\n esbuild: ConnectorEsbuildPatch;\n};\n\n/**\n * Reject a contribution object carrying anything but the two hooks.\n *\n * @throws Error naming the connector and the offending key\n */\nexport function assertClosedContribution(connector: Connector): void {\n const contribution = connector.build;\n\n if (!contribution) return;\n\n for (const key of Object.keys(contribution)) {\n if ((ALLOWED_CONTRIBUTION_KEYS as readonly string[]).includes(key)) continue;\n\n throw new Error(\n `Connector \"${connector.name}\" declares an unsupported build contribution key \"${key}\". ` +\n `A build contribution carries exactly these optional hooks — ` +\n `${ALLOWED_CONTRIBUTION_KEYS.join(\", \")} — and no data. ` +\n `Anything a hook needs (plugins, pipelines, aliases) must be constructed inside ` +\n `that hook, so it never lands in the connector's static import graph.`,\n );\n }\n}\n\n/**\n * Drain every connector's `generate` hook, in array order, sequentially.\n *\n * Semantics are copied from `Application.runStartupValidators`\n * (`application.ts:304-329`) on purpose: ordered, awaited one at a time, and\n * a throw is rethrown wrapped in an error NAMING the contributor. A\n * contributor failure IS the build failing — that is what makes\n * \"green build, no client bundle\" unrepresentable rather than merely\n * unlikely.\n */\nexport async function runGenerateContributions(\n connectors: readonly Connector[],\n context: ConnectorBuildContext,\n): Promise<GenerateContributionsResult> {\n const entryImports: string[] = [];\n let esbuild: ConnectorEsbuildPatch = {};\n\n for (const connector of connectors) {\n assertClosedContribution(connector);\n\n const generate = connector.build?.generate;\n\n if (!generate) continue;\n\n const result = await runHook(connector, \"generate\", () => generate(context));\n\n if (!result) continue;\n\n if (result.entryImports) {\n entryImports.push(...result.entryImports);\n }\n\n if (result.esbuild) {\n esbuild = mergeEsbuildPatches(esbuild, result.esbuild);\n }\n }\n\n return { entryImports, esbuild };\n}\n\n/**\n * Drain every connector's `emit` hook, in array order, sequentially.\n *\n * Runs after esbuild and before `.warlock/production` is removed, so a hook\n * may still read what `generate` wrote there.\n */\nexport async function runEmitContributions(\n connectors: readonly Connector[],\n context: ConnectorBuildContext,\n): Promise<void> {\n for (const connector of connectors) {\n assertClosedContribution(connector);\n\n const emit = connector.build?.emit;\n\n if (!emit) continue;\n\n await runHook(connector, \"emit\", () => emit(context));\n }\n}\n\n/**\n * Drain every connector's `typings` hook, in array order, sequentially.\n * Connectors without one — every API-only app — are skipped without error.\n */\nexport async function runTypingsContributions(\n connectors: readonly Connector[],\n context: ConnectorBuildContext,\n): Promise<void> {\n for (const connector of connectors) {\n assertClosedContribution(connector);\n\n const typings = connector.build?.typings;\n\n if (!typings) continue;\n\n await runHook(connector, \"typings\", () => typings(context));\n }\n}\n\n/**\n * Merge two contributor patches. Later wins, except:\n *\n * - `define` merges per key — two contributors defining different\n * `import.meta.env.*` entries must both survive; a wholesale replace would\n * drop one silently.\n * - `external` concatenates and dedupes — it is a set of package names, and\n * under `singleBundle` each contributor adds its own optional peers.\n * - `loader` merges per extension, for the same reason as `define`.\n * - `plugins` concatenate in contribution order. They are constructed inside\n * a hook, so this does not reopen the closed-contribution constraint.\n */\nexport function mergeEsbuildPatches(\n base: ConnectorEsbuildPatch,\n patch: ConnectorEsbuildPatch,\n): ConnectorEsbuildPatch {\n const merged: ConnectorEsbuildPatch = { ...base, ...patch };\n\n if (base.define || patch.define) {\n merged.define = { ...base.define, ...patch.define };\n }\n\n if (base.external || patch.external) {\n merged.external = dedupe([...(base.external ?? []), ...(patch.external ?? [])]);\n }\n\n if (base.loader || patch.loader) {\n merged.loader = { ...base.loader, ...patch.loader };\n }\n\n if (base.plugins || patch.plugins) {\n merged.plugins = [...(base.plugins ?? []), ...(patch.plugins ?? [])];\n }\n\n return merged;\n}\n\n/**\n * Concatenation order preserved — esbuild does not care, but a stable order\n * keeps build output diffable.\n */\nexport function dedupe(values: string[]): string[] {\n return [...new Set(values)];\n}\n\n/**\n * Run one hook and rename its failure after the connector that owns it.\n */\nasync function runHook<Result>(\n connector: Connector,\n hook: \"generate\" | \"emit\" | \"typings\",\n run: () => Result | Promise<Result>,\n): Promise<Result> {\n try {\n return await run();\n } catch (error) {\n const cause = error instanceof Error ? error.message : String(error);\n\n throw new ErrorWithCause(\n `Build contribution \"${connector.name}\" failed during ${hook}: ${cause}. ` +\n `The build cannot continue — an artifact this connector was responsible for ` +\n `is missing, and shipping the bundle without it would fail at runtime instead.`,\n { cause: error },\n );\n }\n}\n"],"mappings":";AASA,MAAM,iBAAiB;;;;;;;;;;;AAYvB,MAAM,4BAA4B;CAAC;CAAY;CAAQ;AAAS;;;;;;AAiBhE,SAAgB,yBAAyB,WAA4B;CACnE,MAAM,eAAe,UAAU;CAE/B,IAAI,CAAC,cAAc;CAEnB,KAAK,MAAM,OAAO,OAAO,KAAK,YAAY,GAAG;EAC3C,IAAK,0BAAgD,SAAS,GAAG,GAAG;EAEpE,MAAM,IAAI,MACR,cAAc,UAAU,KAAK,oDAAoD,IAAI,iEAEhF,0BAA0B,KAAK,IAAI,EAAE,oKAG5C;CACF;AACF;;;;;;;;;;;AAYA,eAAsB,yBACpB,YACA,SACsC;CACtC,MAAM,eAAyB,CAAC;CAChC,IAAI,UAAiC,CAAC;CAEtC,KAAK,MAAM,aAAa,YAAY;EAClC,yBAAyB,SAAS;EAElC,MAAM,WAAW,UAAU,OAAO;EAElC,IAAI,CAAC,UAAU;EAEf,MAAM,SAAS,MAAM,QAAQ,WAAW,kBAAkB,SAAS,OAAO,CAAC;EAE3E,IAAI,CAAC,QAAQ;EAEb,IAAI,OAAO,cACT,aAAa,KAAK,GAAG,OAAO,YAAY;EAG1C,IAAI,OAAO,SACT,UAAU,oBAAoB,SAAS,OAAO,OAAO;CAEzD;CAEA,OAAO;EAAE;EAAc;CAAQ;AACjC;;;;;;;AAQA,eAAsB,qBACpB,YACA,SACe;CACf,KAAK,MAAM,aAAa,YAAY;EAClC,yBAAyB,SAAS;EAElC,MAAM,OAAO,UAAU,OAAO;EAE9B,IAAI,CAAC,MAAM;EAEX,MAAM,QAAQ,WAAW,cAAc,KAAK,OAAO,CAAC;CACtD;AACF;;;;;AAMA,eAAsB,wBACpB,YACA,SACe;CACf,KAAK,MAAM,aAAa,YAAY;EAClC,yBAAyB,SAAS;EAElC,MAAM,UAAU,UAAU,OAAO;EAEjC,IAAI,CAAC,SAAS;EAEd,MAAM,QAAQ,WAAW,iBAAiB,QAAQ,OAAO,CAAC;CAC5D;AACF;;;;;;;;;;;;;AAcA,SAAgB,oBACd,MACA,OACuB;CACvB,MAAM,SAAgC;EAAE,GAAG;EAAM,GAAG;CAAM;CAE1D,IAAI,KAAK,UAAU,MAAM,QACvB,OAAO,SAAS;EAAE,GAAG,KAAK;EAAQ,GAAG,MAAM;CAAO;CAGpD,IAAI,KAAK,YAAY,MAAM,UACzB,OAAO,WAAW,OAAO,CAAC,GAAI,KAAK,YAAY,CAAC,GAAI,GAAI,MAAM,YAAY,CAAC,CAAE,CAAC;CAGhF,IAAI,KAAK,UAAU,MAAM,QACvB,OAAO,SAAS;EAAE,GAAG,KAAK;EAAQ,GAAG,MAAM;CAAO;CAGpD,IAAI,KAAK,WAAW,MAAM,SACxB,OAAO,UAAU,CAAC,GAAI,KAAK,WAAW,CAAC,GAAI,GAAI,MAAM,WAAW,CAAC,CAAE;CAGrE,OAAO;AACT;;;;;AAMA,SAAgB,OAAO,QAA4B;CACjD,OAAO,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC;AAC5B;;;;AAKA,eAAe,QACb,WACA,MACA,KACiB;CACjB,IAAI;EACF,OAAO,MAAM,IAAI;CACnB,SAAS,OAAO;EACd,MAAM,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EAEnE,MAAM,IAAI,eACR,uBAAuB,UAAU,KAAK,kBAAkB,KAAK,IAAI,MAAM,6JAGvE,EAAE,OAAO,MAAM,CACjB;CACF;AACF"}
@@ -2,7 +2,7 @@ import { isBuiltin } from "node:module";
2
2
  import path from "node:path";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
 
5
- //#region ../core/src/production/bundle-framework-dependencies.ts
5
+ //#region ../../packages/core/src/production/bundle-framework-dependencies.ts
6
6
  /**
7
7
  * The package name a bare specifier addresses, discarding any subpath:
8
8
  * `ajv/dist/jtd` → `ajv`, `@fastify/static/lib/x` → `@fastify/static`.
@@ -1 +1 @@
1
- {"version":3,"file":"bundle-framework-dependencies.mjs","names":[],"sources":["../../../../../../../core/src/production/bundle-framework-dependencies.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { isBuiltin } from \"node:module\";\nimport path from \"node:path\";\nimport type { Plugin } from \"esbuild\";\n\n/**\n * The package name a bare specifier addresses, discarding any subpath:\n * `ajv/dist/jtd` → `ajv`, `@fastify/static/lib/x` → `@fastify/static`.\n */\nexport function packageNameOfSpecifier(specifier: string): string {\n const segments = specifier.split(\"/\");\n\n return specifier.startsWith(\"@\") ? segments.slice(0, 2).join(\"/\") : (segments[0] ?? specifier);\n}\n\n/**\n * A specifier Node would resolve through `node_modules` — not a path. Both\n * separators are rejected because esbuild hands plugins Windows paths as\n * written, and `path.isAbsolute` is what catches a drive-letter root.\n */\nexport function isBareSpecifier(specifier: string): boolean {\n return (\n specifier.length > 0 &&\n !specifier.startsWith(\".\") &&\n !specifier.startsWith(\"/\") &&\n !specifier.startsWith(\"\\\\\") &&\n !path.isAbsolute(specifier)\n );\n}\n\n/**\n * The `dependencies` of the package that owns `file`, or `undefined` when the\n * walk reaches the filesystem root without finding a package.\n *\n * **The nearest `package.json` is not necessarily the owner.** Packages\n * publish TYPE-MARKER manifests — `glob/dist/commonjs/package.json` is the\n * two-line `{\"type\":\"commonjs\"}` that tells Node how to read the files beside\n * it — and a walk that stops at the first `package.json` it sees stops there,\n * reads no `dependencies`, and concludes the package declares nothing. Every\n * import from such a directory is then judged undeclared: `glob`'s own\n * `require(\"path-scurry\")` was left external and the built app died on it at\n * startup. A manifest with no `name` is not a package, so the walk continues\n * past it.\n */\nfunction findOwningDependencies(file: string): ReadonlySet<string> | undefined {\n let dir = path.dirname(file);\n\n for (;;) {\n const manifestPath = path.join(dir, \"package.json\");\n\n if (existsSync(manifestPath)) {\n try {\n const manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as {\n name?: string;\n dependencies?: Record<string, string>;\n };\n\n if (typeof manifest.name === \"string\" && manifest.name.length > 0) {\n return new Set(Object.keys(manifest.dependencies ?? {}));\n }\n } catch {\n // An unreadable or malformed manifest is not evidence about\n // anything. Keep walking; the enclosing package may still answer.\n }\n }\n\n const parent = path.dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n}\n\n/**\n * Whether `file` is code the APP owns — inside the app root and not inside\n * any `node_modules` below it. A file under `node_modules` is a package's\n * code that happens to sit beneath the app directory, which is the opposite\n * of what this asks.\n */\nfunction isAppOwnedFile(file: string, appRoot: string): boolean {\n const relative = path.relative(appRoot, file);\n\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) return false;\n\n return !relative.split(/[\\\\/]/).includes(\"node_modules\");\n}\n\n/**\n * Decide, per import edge, whether a bare specifier stays a bare specifier in\n * the emitted bundle or is bundled into it.\n *\n * **The defect.** The bundler ran `packages: \"external\"`, so EVERY bare\n * specifier survived verbatim into an artifact that Node then resolves from\n * the artifact's own location — inside the app's `dist/`. That is right for\n * the app's own dependencies and wrong for everything else, because the\n * bundle does not contain only app code: `buildAliasMapFromTsconfig` maps\n * `@warlock.js/*` onto its on-disk SOURCE (mandatory — those packages have\n * no built output in a source checkout, canon `5f684f28`), so the framework's\n * own compiled source is inlined into the app's bundle, and with it the bare\n * `@fastify/http-proxy`, `find-my-way`, `fast-jwt` and `@mongez/*` imports it\n * makes. The app never declared any of those. Under npm/yarn hoisting they\n * resolve by accident; under a strict pnpm tree the built app cannot boot.\n *\n * `assertGeneratedImports` already refuses this for the code the builder\n * GENERATES. This is the same rule for the framework source that generated\n * code pulls in — the half no assertion could reach, because rewriting the\n * import is not an option there: the framework is entitled to its own\n * dependencies.\n *\n * **The rule.** A bare specifier is external — today's behaviour, unchanged —\n * unless BOTH of:\n *\n * 1. the importer is not app-owned code, and\n * 2. the specifier names a package the importer's OWN package declares in\n * `dependencies`.\n *\n * Then it is bundled, and esbuild resolves it from the importer, which is the\n * only resolution that can be correct: `@fastify/ajv-compiler` needs ajv 8\n * while another dependent needs ajv 6, and under pnpm each has its own nested\n * copy. A flat `alias` map cannot express that — it collapses a name to one\n * target for the whole build and produces exactly the \"Could not resolve\n * ajv/dist/jtd\" class of failure. Resolving per edge is not an optimisation\n * here; it is the difference between working and not.\n *\n * Condition 2 is what keeps canon `5f684f28` intact. An optional peer reached\n * through `await import(...)` — `nodemailer`, `socket.io`, `vite`, the AI\n * SDKs — is declared as a `peerDependency`, never a `dependency`, precisely\n * because it may not be installed at all. Reading only `dependencies` leaves\n * every one of them external without needing a list of their names to\n * maintain, which is the failure mode a hand-written exclusion list has.\n *\n * Transitivity falls out rather than being coded: once `@fastify/http-proxy`\n * is bundled, IT is a non-app-owned importer, so its own `@fastify/reply-from`\n * dependency is judged by the same two conditions and resolved from\n * http-proxy's directory — the nested copy Node itself would have loaded.\n */\nexport function bundleFrameworkDependencies(options: {\n appRoot: string;\n /**\n * The keys of the esbuild `alias` map this same build is configured with.\n *\n * They MUST be excluded here, and the reason is a trap worth naming: an\n * `onResolve` callback pre-empts esbuild's built-in resolver, and `alias`\n * lives in that resolver. A plugin that answers `external: true` for\n * `@warlock.js/core` therefore beats the alias pointing it at core's\n * source — the framework silently stops being bundled at all, the build\n * still succeeds, and the artifact is a 2.8 KB entry file importing a\n * package the app cannot resolve. Returning `undefined` for these hands\n * them back to the resolver, alias intact.\n *\n * Matched as esbuild matches them: the exact key, or the key followed by a\n * subpath.\n */\n aliasKeys: readonly string[];\n}): Plugin {\n const appRoot = path.resolve(options.appRoot);\n const aliasKeys = [...options.aliasKeys];\n\n function isAliased(specifier: string): boolean {\n return aliasKeys.some((key) => specifier === key || specifier.startsWith(`${key}/`));\n }\n\n // Keyed by the importer's DIRECTORY: the walk and the manifest read are\n // identical for every file in it, and a bundle of this size resolves\n // thousands of edges out of a few hundred directories.\n const dependenciesByDir = new Map<string, ReadonlySet<string> | undefined>();\n\n function declaredDependenciesOf(importer: string): ReadonlySet<string> | undefined {\n const dir = path.dirname(importer);\n if (dependenciesByDir.has(dir)) return dependenciesByDir.get(dir);\n\n const result = findOwningDependencies(importer);\n dependenciesByDir.set(dir, result);\n\n return result;\n }\n\n return {\n name: \"warlock:bundle-framework-dependencies\",\n setup(build) {\n // Everything is inspected and the bare-specifier test is made in code:\n // a `filter` cheap enough to be worth writing cannot tell `C:\\…` (an\n // absolute Windows path, and what the tsconfig aliases resolve to) from\n // a package called `c`. Externalising one of those would be silent and\n // fatal.\n build.onResolve({ filter: /.*/ }, (args) => {\n if (args.namespace !== \"file\" && args.namespace !== \"\") return undefined;\n\n const specifier = args.path;\n\n if (!isBareSpecifier(specifier)) return undefined;\n\n if (isAliased(specifier)) return undefined;\n\n // A builtin is never external in the sense that matters — esbuild\n // already leaves `node:fs` alone and Node always has it.\n if (specifier.startsWith(\"node:\") || isBuiltin(specifier)) return undefined;\n\n const importer = args.importer;\n\n // Nothing on disk to ask. An entry point has no importer at all, and\n // a virtual or generated importer has no package around it — either\n // way there is no manifest that could declare this, so it keeps the\n // behaviour it had before this plugin existed.\n if (!importer || !path.isAbsolute(importer)) {\n return { path: specifier, external: true };\n }\n\n if (isAppOwnedFile(importer, appRoot)) {\n return { path: specifier, external: true };\n }\n\n const declared = declaredDependenciesOf(importer);\n\n if (!declared?.has(packageNameOfSpecifier(specifier))) {\n return { path: specifier, external: true };\n }\n\n // Declared by the package that imports it: let esbuild's own\n // resolver take it, from this importer, and bundle the result.\n return undefined;\n });\n },\n };\n}\n"],"mappings":";;;;;;;;;AASA,SAAgB,uBAAuB,WAA2B;CAChE,MAAM,WAAW,UAAU,MAAM,GAAG;CAEpC,OAAO,UAAU,WAAW,GAAG,IAAI,SAAS,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,IAAK,SAAS,MAAM;AACtF;;;;;;AAOA,SAAgB,gBAAgB,WAA4B;CAC1D,OACE,UAAU,SAAS,KACnB,CAAC,UAAU,WAAW,GAAG,KACzB,CAAC,UAAU,WAAW,GAAG,KACzB,CAAC,UAAU,WAAW,IAAI,KAC1B,CAAC,KAAK,WAAW,SAAS;AAE9B;;;;;;;;;;;;;;;AAgBA,SAAS,uBAAuB,MAA+C;CAC7E,IAAI,MAAM,KAAK,QAAQ,IAAI;CAE3B,SAAS;EACP,MAAM,eAAe,KAAK,KAAK,KAAK,cAAc;EAElD,IAAI,WAAW,YAAY,GACzB,IAAI;GACF,MAAM,WAAW,KAAK,MAAM,aAAa,cAAc,MAAM,CAAC;GAK9D,IAAI,OAAO,SAAS,SAAS,YAAY,SAAS,KAAK,SAAS,GAC9D,OAAO,IAAI,IAAI,OAAO,KAAK,SAAS,gBAAgB,CAAC,CAAC,CAAC;EAE3D,QAAQ,CAGR;EAGF,MAAM,SAAS,KAAK,QAAQ,GAAG;EAC/B,IAAI,WAAW,KAAK,OAAO;EAC3B,MAAM;CACR;AACF;;;;;;;AAQA,SAAS,eAAe,MAAc,SAA0B;CAC9D,MAAM,WAAW,KAAK,SAAS,SAAS,IAAI;CAE5C,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,WAAW,QAAQ,GAAG,OAAO;CAEnE,OAAO,CAAC,SAAS,MAAM,OAAO,CAAC,CAAC,SAAS,cAAc;AACzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDA,SAAgB,4BAA4B,SAkBjC;CACT,MAAM,UAAU,KAAK,QAAQ,QAAQ,OAAO;CAC5C,MAAM,YAAY,CAAC,GAAG,QAAQ,SAAS;CAEvC,SAAS,UAAU,WAA4B;EAC7C,OAAO,UAAU,MAAM,QAAQ,cAAc,OAAO,UAAU,WAAW,GAAG,IAAI,EAAE,CAAC;CACrF;CAKA,MAAM,oCAAoB,IAAI,IAA6C;CAE3E,SAAS,uBAAuB,UAAmD;EACjF,MAAM,MAAM,KAAK,QAAQ,QAAQ;EACjC,IAAI,kBAAkB,IAAI,GAAG,GAAG,OAAO,kBAAkB,IAAI,GAAG;EAEhE,MAAM,SAAS,uBAAuB,QAAQ;EAC9C,kBAAkB,IAAI,KAAK,MAAM;EAEjC,OAAO;CACT;CAEA,OAAO;EACL,MAAM;EACN,MAAM,OAAO;GAMX,MAAM,UAAU,EAAE,QAAQ,KAAK,IAAI,SAAS;IAC1C,IAAI,KAAK,cAAc,UAAU,KAAK,cAAc,IAAI,OAAO;IAE/D,MAAM,YAAY,KAAK;IAEvB,IAAI,CAAC,gBAAgB,SAAS,GAAG,OAAO;IAExC,IAAI,UAAU,SAAS,GAAG,OAAO;IAIjC,IAAI,UAAU,WAAW,OAAO,KAAK,UAAU,SAAS,GAAG,OAAO;IAElE,MAAM,WAAW,KAAK;IAMtB,IAAI,CAAC,YAAY,CAAC,KAAK,WAAW,QAAQ,GACxC,OAAO;KAAE,MAAM;KAAW,UAAU;IAAK;IAG3C,IAAI,eAAe,UAAU,OAAO,GAClC,OAAO;KAAE,MAAM;KAAW,UAAU;IAAK;IAK3C,IAAI,CAFa,uBAAuB,QAE5B,CAAC,EAAE,IAAI,uBAAuB,SAAS,CAAC,GAClD,OAAO;KAAE,MAAM;KAAW,UAAU;IAAK;GAM7C,CAAC;EACH;CACF;AACF"}
1
+ {"version":3,"file":"bundle-framework-dependencies.mjs","names":[],"sources":["../../../../../../../../packages/core/src/production/bundle-framework-dependencies.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { isBuiltin } from \"node:module\";\nimport path from \"node:path\";\nimport type { Plugin } from \"esbuild\";\n\n/**\n * The package name a bare specifier addresses, discarding any subpath:\n * `ajv/dist/jtd` → `ajv`, `@fastify/static/lib/x` → `@fastify/static`.\n */\nexport function packageNameOfSpecifier(specifier: string): string {\n const segments = specifier.split(\"/\");\n\n return specifier.startsWith(\"@\") ? segments.slice(0, 2).join(\"/\") : (segments[0] ?? specifier);\n}\n\n/**\n * A specifier Node would resolve through `node_modules` — not a path. Both\n * separators are rejected because esbuild hands plugins Windows paths as\n * written, and `path.isAbsolute` is what catches a drive-letter root.\n */\nexport function isBareSpecifier(specifier: string): boolean {\n return (\n specifier.length > 0 &&\n !specifier.startsWith(\".\") &&\n !specifier.startsWith(\"/\") &&\n !specifier.startsWith(\"\\\\\") &&\n !path.isAbsolute(specifier)\n );\n}\n\n/**\n * The `dependencies` of the package that owns `file`, or `undefined` when the\n * walk reaches the filesystem root without finding a package.\n *\n * **The nearest `package.json` is not necessarily the owner.** Packages\n * publish TYPE-MARKER manifests — `glob/dist/commonjs/package.json` is the\n * two-line `{\"type\":\"commonjs\"}` that tells Node how to read the files beside\n * it — and a walk that stops at the first `package.json` it sees stops there,\n * reads no `dependencies`, and concludes the package declares nothing. Every\n * import from such a directory is then judged undeclared: `glob`'s own\n * `require(\"path-scurry\")` was left external and the built app died on it at\n * startup. A manifest with no `name` is not a package, so the walk continues\n * past it.\n */\nfunction findOwningDependencies(file: string): ReadonlySet<string> | undefined {\n let dir = path.dirname(file);\n\n for (;;) {\n const manifestPath = path.join(dir, \"package.json\");\n\n if (existsSync(manifestPath)) {\n try {\n const manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as {\n name?: string;\n dependencies?: Record<string, string>;\n };\n\n if (typeof manifest.name === \"string\" && manifest.name.length > 0) {\n return new Set(Object.keys(manifest.dependencies ?? {}));\n }\n } catch {\n // An unreadable or malformed manifest is not evidence about\n // anything. Keep walking; the enclosing package may still answer.\n }\n }\n\n const parent = path.dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n}\n\n/**\n * Whether `file` is code the APP owns — inside the app root and not inside\n * any `node_modules` below it. A file under `node_modules` is a package's\n * code that happens to sit beneath the app directory, which is the opposite\n * of what this asks.\n */\nfunction isAppOwnedFile(file: string, appRoot: string): boolean {\n const relative = path.relative(appRoot, file);\n\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) return false;\n\n return !relative.split(/[\\\\/]/).includes(\"node_modules\");\n}\n\n/**\n * Decide, per import edge, whether a bare specifier stays a bare specifier in\n * the emitted bundle or is bundled into it.\n *\n * **The defect.** The bundler ran `packages: \"external\"`, so EVERY bare\n * specifier survived verbatim into an artifact that Node then resolves from\n * the artifact's own location — inside the app's `dist/`. That is right for\n * the app's own dependencies and wrong for everything else, because the\n * bundle does not contain only app code: `buildAliasMapFromTsconfig` maps\n * `@warlock.js/*` onto its on-disk SOURCE (mandatory — those packages have\n * no built output in a source checkout, canon `5f684f28`), so the framework's\n * own compiled source is inlined into the app's bundle, and with it the bare\n * `@fastify/http-proxy`, `find-my-way`, `fast-jwt` and `@mongez/*` imports it\n * makes. The app never declared any of those. Under npm/yarn hoisting they\n * resolve by accident; under a strict pnpm tree the built app cannot boot.\n *\n * `assertGeneratedImports` already refuses this for the code the builder\n * GENERATES. This is the same rule for the framework source that generated\n * code pulls in — the half no assertion could reach, because rewriting the\n * import is not an option there: the framework is entitled to its own\n * dependencies.\n *\n * **The rule.** A bare specifier is external — today's behaviour, unchanged —\n * unless BOTH of:\n *\n * 1. the importer is not app-owned code, and\n * 2. the specifier names a package the importer's OWN package declares in\n * `dependencies`.\n *\n * Then it is bundled, and esbuild resolves it from the importer, which is the\n * only resolution that can be correct: `@fastify/ajv-compiler` needs ajv 8\n * while another dependent needs ajv 6, and under pnpm each has its own nested\n * copy. A flat `alias` map cannot express that — it collapses a name to one\n * target for the whole build and produces exactly the \"Could not resolve\n * ajv/dist/jtd\" class of failure. Resolving per edge is not an optimisation\n * here; it is the difference between working and not.\n *\n * Condition 2 is what keeps canon `5f684f28` intact. An optional peer reached\n * through `await import(...)` — `nodemailer`, `socket.io`, `vite`, the AI\n * SDKs — is declared as a `peerDependency`, never a `dependency`, precisely\n * because it may not be installed at all. Reading only `dependencies` leaves\n * every one of them external without needing a list of their names to\n * maintain, which is the failure mode a hand-written exclusion list has.\n *\n * Transitivity falls out rather than being coded: once `@fastify/http-proxy`\n * is bundled, IT is a non-app-owned importer, so its own `@fastify/reply-from`\n * dependency is judged by the same two conditions and resolved from\n * http-proxy's directory — the nested copy Node itself would have loaded.\n */\nexport function bundleFrameworkDependencies(options: {\n appRoot: string;\n /**\n * The keys of the esbuild `alias` map this same build is configured with.\n *\n * They MUST be excluded here, and the reason is a trap worth naming: an\n * `onResolve` callback pre-empts esbuild's built-in resolver, and `alias`\n * lives in that resolver. A plugin that answers `external: true` for\n * `@warlock.js/core` therefore beats the alias pointing it at core's\n * source — the framework silently stops being bundled at all, the build\n * still succeeds, and the artifact is a 2.8 KB entry file importing a\n * package the app cannot resolve. Returning `undefined` for these hands\n * them back to the resolver, alias intact.\n *\n * Matched as esbuild matches them: the exact key, or the key followed by a\n * subpath.\n */\n aliasKeys: readonly string[];\n}): Plugin {\n const appRoot = path.resolve(options.appRoot);\n const aliasKeys = [...options.aliasKeys];\n\n function isAliased(specifier: string): boolean {\n return aliasKeys.some((key) => specifier === key || specifier.startsWith(`${key}/`));\n }\n\n // Keyed by the importer's DIRECTORY: the walk and the manifest read are\n // identical for every file in it, and a bundle of this size resolves\n // thousands of edges out of a few hundred directories.\n const dependenciesByDir = new Map<string, ReadonlySet<string> | undefined>();\n\n function declaredDependenciesOf(importer: string): ReadonlySet<string> | undefined {\n const dir = path.dirname(importer);\n if (dependenciesByDir.has(dir)) return dependenciesByDir.get(dir);\n\n const result = findOwningDependencies(importer);\n dependenciesByDir.set(dir, result);\n\n return result;\n }\n\n return {\n name: \"warlock:bundle-framework-dependencies\",\n setup(build) {\n // Everything is inspected and the bare-specifier test is made in code:\n // a `filter` cheap enough to be worth writing cannot tell `C:\\…` (an\n // absolute Windows path, and what the tsconfig aliases resolve to) from\n // a package called `c`. Externalising one of those would be silent and\n // fatal.\n build.onResolve({ filter: /.*/ }, (args) => {\n if (args.namespace !== \"file\" && args.namespace !== \"\") return undefined;\n\n const specifier = args.path;\n\n if (!isBareSpecifier(specifier)) return undefined;\n\n if (isAliased(specifier)) return undefined;\n\n // A builtin is never external in the sense that matters — esbuild\n // already leaves `node:fs` alone and Node always has it.\n if (specifier.startsWith(\"node:\") || isBuiltin(specifier)) return undefined;\n\n const importer = args.importer;\n\n // Nothing on disk to ask. An entry point has no importer at all, and\n // a virtual or generated importer has no package around it — either\n // way there is no manifest that could declare this, so it keeps the\n // behaviour it had before this plugin existed.\n if (!importer || !path.isAbsolute(importer)) {\n return { path: specifier, external: true };\n }\n\n if (isAppOwnedFile(importer, appRoot)) {\n return { path: specifier, external: true };\n }\n\n const declared = declaredDependenciesOf(importer);\n\n if (!declared?.has(packageNameOfSpecifier(specifier))) {\n return { path: specifier, external: true };\n }\n\n // Declared by the package that imports it: let esbuild's own\n // resolver take it, from this importer, and bundle the result.\n return undefined;\n });\n },\n };\n}\n"],"mappings":";;;;;;;;;AASA,SAAgB,uBAAuB,WAA2B;CAChE,MAAM,WAAW,UAAU,MAAM,GAAG;CAEpC,OAAO,UAAU,WAAW,GAAG,IAAI,SAAS,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,IAAK,SAAS,MAAM;AACtF;;;;;;AAOA,SAAgB,gBAAgB,WAA4B;CAC1D,OACE,UAAU,SAAS,KACnB,CAAC,UAAU,WAAW,GAAG,KACzB,CAAC,UAAU,WAAW,GAAG,KACzB,CAAC,UAAU,WAAW,IAAI,KAC1B,CAAC,KAAK,WAAW,SAAS;AAE9B;;;;;;;;;;;;;;;AAgBA,SAAS,uBAAuB,MAA+C;CAC7E,IAAI,MAAM,KAAK,QAAQ,IAAI;CAE3B,SAAS;EACP,MAAM,eAAe,KAAK,KAAK,KAAK,cAAc;EAElD,IAAI,WAAW,YAAY,GACzB,IAAI;GACF,MAAM,WAAW,KAAK,MAAM,aAAa,cAAc,MAAM,CAAC;GAK9D,IAAI,OAAO,SAAS,SAAS,YAAY,SAAS,KAAK,SAAS,GAC9D,OAAO,IAAI,IAAI,OAAO,KAAK,SAAS,gBAAgB,CAAC,CAAC,CAAC;EAE3D,QAAQ,CAGR;EAGF,MAAM,SAAS,KAAK,QAAQ,GAAG;EAC/B,IAAI,WAAW,KAAK,OAAO;EAC3B,MAAM;CACR;AACF;;;;;;;AAQA,SAAS,eAAe,MAAc,SAA0B;CAC9D,MAAM,WAAW,KAAK,SAAS,SAAS,IAAI;CAE5C,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,WAAW,QAAQ,GAAG,OAAO;CAEnE,OAAO,CAAC,SAAS,MAAM,OAAO,CAAC,CAAC,SAAS,cAAc;AACzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDA,SAAgB,4BAA4B,SAkBjC;CACT,MAAM,UAAU,KAAK,QAAQ,QAAQ,OAAO;CAC5C,MAAM,YAAY,CAAC,GAAG,QAAQ,SAAS;CAEvC,SAAS,UAAU,WAA4B;EAC7C,OAAO,UAAU,MAAM,QAAQ,cAAc,OAAO,UAAU,WAAW,GAAG,IAAI,EAAE,CAAC;CACrF;CAKA,MAAM,oCAAoB,IAAI,IAA6C;CAE3E,SAAS,uBAAuB,UAAmD;EACjF,MAAM,MAAM,KAAK,QAAQ,QAAQ;EACjC,IAAI,kBAAkB,IAAI,GAAG,GAAG,OAAO,kBAAkB,IAAI,GAAG;EAEhE,MAAM,SAAS,uBAAuB,QAAQ;EAC9C,kBAAkB,IAAI,KAAK,MAAM;EAEjC,OAAO;CACT;CAEA,OAAO;EACL,MAAM;EACN,MAAM,OAAO;GAMX,MAAM,UAAU,EAAE,QAAQ,KAAK,IAAI,SAAS;IAC1C,IAAI,KAAK,cAAc,UAAU,KAAK,cAAc,IAAI,OAAO;IAE/D,MAAM,YAAY,KAAK;IAEvB,IAAI,CAAC,gBAAgB,SAAS,GAAG,OAAO;IAExC,IAAI,UAAU,SAAS,GAAG,OAAO;IAIjC,IAAI,UAAU,WAAW,OAAO,KAAK,UAAU,SAAS,GAAG,OAAO;IAElE,MAAM,WAAW,KAAK;IAMtB,IAAI,CAAC,YAAY,CAAC,KAAK,WAAW,QAAQ,GACxC,OAAO;KAAE,MAAM;KAAW,UAAU;IAAK;IAG3C,IAAI,eAAe,UAAU,OAAO,GAClC,OAAO;KAAE,MAAM;KAAW,UAAU;IAAK;IAK3C,IAAI,CAFa,uBAAuB,QAE5B,CAAC,EAAE,IAAI,uBAAuB,SAAS,CAAC,GAClD,OAAO;KAAE,MAAM;KAAW,UAAU;IAAK;GAM7C,CAAC;EACH;CACF;AACF"}
@@ -1,7 +1,7 @@
1
1
  import path from "path";
2
2
  import { getJsonFileAsync, putJsonFileAsync } from "@warlock.js/fs";
3
3
 
4
- //#region ../core/src/production/dist-build-manifest.ts
4
+ //#region ../../packages/core/src/production/dist-build-manifest.ts
5
5
  /**
6
6
  * Name of the marker file `warlock build` writes into the output directory
7
7
  * as the last step before promoting it to `dist`, and the only thing
@@ -1 +1 @@
1
- {"version":3,"file":"dist-build-manifest.mjs","names":[],"sources":["../../../../../../../core/src/production/dist-build-manifest.ts"],"sourcesContent":["import { getJsonFileAsync, putJsonFileAsync } from \"@warlock.js/fs\";\nimport path from \"path\";\n\n/**\n * Name of the marker file `warlock build` writes into the output directory\n * as the last step before promoting it to `dist`, and the only thing\n * `warlock start` trusts to tell a genuine build from stale or\n * hand-assembled output.\n *\n * Hidden (leading dot) so it never collides with a route, a static asset, or\n * anything an app might legitimately name `manifest.json`.\n */\nexport const DIST_BUILD_MANIFEST_FILE_NAME = \".warlock-build.json\";\n\n/**\n * Recorded once, at the end of a build that reached the promote step. Its\n * presence — with `status: \"success\"` — is the whole contract `warlock\n * start` checks. Not any particular output file, which a future build shape\n * could rename or drop.\n */\nexport type DistBuildManifest = {\n status: \"success\";\n builtAt: string;\n};\n\n/**\n * Write the build-success marker into an output directory (the temp\n * directory a build assembled, before it is promoted to `dist`).\n */\nexport async function writeDistBuildManifestAsync(directory: string): Promise<void> {\n const manifest: DistBuildManifest = {\n status: \"success\",\n builtAt: new Date().toISOString(),\n };\n\n await putJsonFileAsync(path.join(directory, DIST_BUILD_MANIFEST_FILE_NAME), manifest);\n}\n\n/**\n * Read the build-success marker out of `dist`.\n *\n * Returns `undefined` for every way the marker can fail to back a real\n * build: missing, unreadable, malformed JSON, or present without\n * `status: \"success\"`. \"Never built\", \"build failed before promoting\", and\n * \"someone hand-edited dist\" all collapse to the same outcome, because\n * `warlock start` treats them identically — refuse, and say why.\n */\nexport async function readDistBuildManifestAsync(\n directory: string,\n): Promise<DistBuildManifest | undefined> {\n try {\n const manifest = await getJsonFileAsync<DistBuildManifest>(\n path.join(directory, DIST_BUILD_MANIFEST_FILE_NAME),\n );\n\n if (manifest?.status !== \"success\") {\n return undefined;\n }\n\n return manifest;\n } catch {\n return undefined;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAYA,MAAa,gCAAgC;;;;;AAiB7C,eAAsB,4BAA4B,WAAkC;CAClF,MAAM,WAA8B;EAClC,QAAQ;EACR,0BAAS,IAAI,KAAK,EAAC,CAAC,YAAY;CAClC;CAEA,MAAM,iBAAiB,KAAK,KAAK,WAAW,6BAA6B,GAAG,QAAQ;AACtF;;;;;;;;;;AAWA,eAAsB,2BACpB,WACwC;CACxC,IAAI;EACF,MAAM,WAAW,MAAM,iBACrB,KAAK,KAAK,WAAW,6BAA6B,CACpD;EAEA,IAAI,UAAU,WAAW,WACvB;EAGF,OAAO;CACT,QAAQ;EACN;CACF;AACF"}
1
+ {"version":3,"file":"dist-build-manifest.mjs","names":[],"sources":["../../../../../../../../packages/core/src/production/dist-build-manifest.ts"],"sourcesContent":["import { getJsonFileAsync, putJsonFileAsync } from \"@warlock.js/fs\";\nimport path from \"path\";\n\n/**\n * Name of the marker file `warlock build` writes into the output directory\n * as the last step before promoting it to `dist`, and the only thing\n * `warlock start` trusts to tell a genuine build from stale or\n * hand-assembled output.\n *\n * Hidden (leading dot) so it never collides with a route, a static asset, or\n * anything an app might legitimately name `manifest.json`.\n */\nexport const DIST_BUILD_MANIFEST_FILE_NAME = \".warlock-build.json\";\n\n/**\n * Recorded once, at the end of a build that reached the promote step. Its\n * presence — with `status: \"success\"` — is the whole contract `warlock\n * start` checks. Not any particular output file, which a future build shape\n * could rename or drop.\n */\nexport type DistBuildManifest = {\n status: \"success\";\n builtAt: string;\n};\n\n/**\n * Write the build-success marker into an output directory (the temp\n * directory a build assembled, before it is promoted to `dist`).\n */\nexport async function writeDistBuildManifestAsync(directory: string): Promise<void> {\n const manifest: DistBuildManifest = {\n status: \"success\",\n builtAt: new Date().toISOString(),\n };\n\n await putJsonFileAsync(path.join(directory, DIST_BUILD_MANIFEST_FILE_NAME), manifest);\n}\n\n/**\n * Read the build-success marker out of `dist`.\n *\n * Returns `undefined` for every way the marker can fail to back a real\n * build: missing, unreadable, malformed JSON, or present without\n * `status: \"success\"`. \"Never built\", \"build failed before promoting\", and\n * \"someone hand-edited dist\" all collapse to the same outcome, because\n * `warlock start` treats them identically — refuse, and say why.\n */\nexport async function readDistBuildManifestAsync(\n directory: string,\n): Promise<DistBuildManifest | undefined> {\n try {\n const manifest = await getJsonFileAsync<DistBuildManifest>(\n path.join(directory, DIST_BUILD_MANIFEST_FILE_NAME),\n );\n\n if (manifest?.status !== \"success\") {\n return undefined;\n }\n\n return manifest;\n } catch {\n return undefined;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAYA,MAAa,gCAAgC;;;;;AAiB7C,eAAsB,4BAA4B,WAAkC;CAClF,MAAM,WAA8B;EAClC,QAAQ;EACR,0BAAS,IAAI,KAAK,EAAC,CAAC,YAAY;CAClC;CAEA,MAAM,iBAAiB,KAAK,KAAK,WAAW,6BAA6B,GAAG,QAAQ;AACtF;;;;;;;;;;AAWA,eAAsB,2BACpB,WACwC;CACxC,IAAI;EACF,MAAM,WAAW,MAAM,iBACrB,KAAK,KAAK,WAAW,6BAA6B,CACpD;EAEA,IAAI,UAAU,WAAW,WACvB;EAGF,OAAO;CACT,QAAQ;EACN;CACF;AACF"}
@@ -1,6 +1,6 @@
1
1
  import { createRequire } from "node:module";
2
2
 
3
- //#region ../core/src/production/esbuild-plugins.ts
3
+ //#region ../../packages/core/src/production/esbuild-plugins.ts
4
4
  const esmRequire = createRequire(import.meta.url);
5
5
  const nativeNodeModulesPlugin = {
6
6
  name: "native-node-modules",
@@ -1 +1 @@
1
- {"version":3,"file":"esbuild-plugins.mjs","names":[],"sources":["../../../../../../../core/src/production/esbuild-plugins.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport type { OnLoadArgs, OnResolveArgs, PluginBuild } from \"esbuild\";\n\nconst esmRequire = createRequire(import.meta.url);\n\nexport const nativeNodeModulesPlugin = {\n name: \"native-node-modules\",\n setup(build: PluginBuild) {\n build.onResolve({ filter: /\\.node$/, namespace: \"file\" }, (args: OnResolveArgs) => ({\n path: esmRequire.resolve(args.path, { paths: [args.resolveDir] }),\n namespace: \"node-file\",\n }));\n\n build.onLoad({ filter: /.*/, namespace: \"node-file\" }, (args: OnLoadArgs) => ({\n contents: `\n import path from ${JSON.stringify(args.path)}\n try { module.exports = require(path) }\n catch {}\n `,\n }));\n\n build.onResolve({ filter: /\\.node$/, namespace: \"node-file\" }, (args: OnResolveArgs) => ({\n path: args.path,\n namespace: \"file\",\n }));\n\n const opts = build.initialOptions;\n opts.loader = opts.loader || {};\n opts.loader[\".node\"] = \"file\";\n },\n};\n"],"mappings":";;;AAGA,MAAM,aAAa,cAAc,OAAO,KAAK,GAAG;AAEhD,MAAa,0BAA0B;CACrC,MAAM;CACN,MAAM,OAAoB;EACxB,MAAM,UAAU;GAAE,QAAQ;GAAW,WAAW;EAAO,IAAI,UAAyB;GAClF,MAAM,WAAW,QAAQ,KAAK,MAAM,EAAE,OAAO,CAAC,KAAK,UAAU,EAAE,CAAC;GAChE,WAAW;EACb,EAAE;EAEF,MAAM,OAAO;GAAE,QAAQ;GAAM,WAAW;EAAY,IAAI,UAAsB,EAC5E,UAAU;6BACa,KAAK,UAAU,KAAK,IAAI,EAAE;;;UAInD,EAAE;EAEF,MAAM,UAAU;GAAE,QAAQ;GAAW,WAAW;EAAY,IAAI,UAAyB;GACvF,MAAM,KAAK;GACX,WAAW;EACb,EAAE;EAEF,MAAM,OAAO,MAAM;EACnB,KAAK,SAAS,KAAK,UAAU,CAAC;EAC9B,KAAK,OAAO,WAAW;CACzB;AACF"}
1
+ {"version":3,"file":"esbuild-plugins.mjs","names":[],"sources":["../../../../../../../../packages/core/src/production/esbuild-plugins.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport type { OnLoadArgs, OnResolveArgs, PluginBuild } from \"esbuild\";\n\nconst esmRequire = createRequire(import.meta.url);\n\nexport const nativeNodeModulesPlugin = {\n name: \"native-node-modules\",\n setup(build: PluginBuild) {\n build.onResolve({ filter: /\\.node$/, namespace: \"file\" }, (args: OnResolveArgs) => ({\n path: esmRequire.resolve(args.path, { paths: [args.resolveDir] }),\n namespace: \"node-file\",\n }));\n\n build.onLoad({ filter: /.*/, namespace: \"node-file\" }, (args: OnLoadArgs) => ({\n contents: `\n import path from ${JSON.stringify(args.path)}\n try { module.exports = require(path) }\n catch {}\n `,\n }));\n\n build.onResolve({ filter: /\\.node$/, namespace: \"node-file\" }, (args: OnResolveArgs) => ({\n path: args.path,\n namespace: \"file\",\n }));\n\n const opts = build.initialOptions;\n opts.loader = opts.loader || {};\n opts.loader[\".node\"] = \"file\";\n },\n};\n"],"mappings":";;;AAGA,MAAM,aAAa,cAAc,OAAO,KAAK,GAAG;AAEhD,MAAa,0BAA0B;CACrC,MAAM;CACN,MAAM,OAAoB;EACxB,MAAM,UAAU;GAAE,QAAQ;GAAW,WAAW;EAAO,IAAI,UAAyB;GAClF,MAAM,WAAW,QAAQ,KAAK,MAAM,EAAE,OAAO,CAAC,KAAK,UAAU,EAAE,CAAC;GAChE,WAAW;EACb,EAAE;EAEF,MAAM,OAAO;GAAE,QAAQ;GAAM,WAAW;EAAY,IAAI,UAAsB,EAC5E,UAAU;6BACa,KAAK,UAAU,KAAK,IAAI,EAAE;;;UAInD,EAAE;EAEF,MAAM,UAAU;GAAE,QAAQ;GAAW,WAAW;EAAY,IAAI,UAAyB;GACvF,MAAM,KAAK;GACX,WAAW;EACb,EAAE;EAEF,MAAM,OAAO,MAAM;EACnB,KAAK,SAAS,KAAK,UAAU,CAAC;EAC9B,KAAK,OAAO,WAAW;CACzB;AACF"}
@@ -1,7 +1,7 @@
1
1
  import { EsbuildBinaryMissingError } from "../errors/esbuild-binary-missing-error.mjs";
2
2
  import esbuild from "esbuild";
3
3
 
4
- //#region ../core/src/production/esbuild-preflight.ts
4
+ //#region ../../packages/core/src/production/esbuild-preflight.ts
5
5
  /**
6
6
  * The exact substring esbuild's own loader throws when the platform-specific
7
7
  * binary package (e.g. `@esbuild/win32-x64`) never got installed. This is
@@ -1 +1 @@
1
- {"version":3,"file":"esbuild-preflight.mjs","names":[],"sources":["../../../../../../../core/src/production/esbuild-preflight.ts"],"sourcesContent":["import esbuild from \"esbuild\";\nimport { EsbuildBinaryMissingError } from \"../errors/esbuild-binary-missing-error\";\n\nexport { EsbuildBinaryMissingError };\n\n/**\n * The exact substring esbuild's own loader throws when the platform-specific\n * binary package (e.g. `@esbuild/win32-x64`) never got installed. This is\n * the signature pnpm's build-script approval gate leaves behind: it blocks\n * esbuild's postinstall script, so the binary is never linked into place,\n * and any later call into esbuild dies with this message instead of a\n * project-shaped one.\n *\n * Source: `pkgAndSubpathForCurrentPlatform` in esbuild's `lib/main.js`.\n */\nconst UNLINKED_BINARY_SIGNATURE = \"could not be found, and is needed by esbuild\";\n\n/**\n * A cheap operation that forces esbuild to resolve and invoke its platform\n * binary. Injectable so tests can simulate a missing binary without deleting\n * anything from a real install.\n */\nexport type EsbuildProbe = () => void;\n\n/**\n * The default probe: a trivial `transformSync` call. Trivial input keeps the\n * cost negligible while still forcing esbuild to resolve and run its native\n * binary, which is the only way an unlinked binary actually surfaces.\n */\nfunction runDefaultProbe(): void {\n esbuild.transformSync(\"\", { loader: \"js\" });\n}\n\n/**\n * Fail fast, before dev or build does any other work, when esbuild's native\n * binary is not linked.\n *\n * A healthy esbuild install is a no-op. A binary genuinely missing — because\n * a platform package was never installed, or a package manager blocked its\n * postinstall script — is turned into {@link EsbuildBinaryMissingError}, a\n * message that names the cause and the fix. Any other failure (a real syntax\n * error, an unrelated platform mismatch, …) is rethrown unchanged — this\n * preflight only owns the one known failure mode.\n *\n * @param probe Overrides the default `esbuild.transformSync` invocation.\n * Intended for tests only.\n * @throws {EsbuildBinaryMissingError} when the platform binary is missing or unlinked.\n */\nexport function assertEsbuildBinaryIsLinked(probe: EsbuildProbe = runDefaultProbe): void {\n try {\n probe();\n } catch (error) {\n if (isUnlinkedBinaryError(error)) {\n throw new EsbuildBinaryMissingError({ cause: error });\n }\n\n throw error;\n }\n}\n\n/**\n * Narrow an unknown thrown value down to esbuild's known \"binary not\n * linked\" failure, identified by the fixed substring esbuild itself throws.\n */\nfunction isUnlinkedBinaryError(error: unknown): boolean {\n return error instanceof Error && error.message.includes(UNLINKED_BINARY_SIGNATURE);\n}\n"],"mappings":";;;;;;;;;;;;;;AAeA,MAAM,4BAA4B;;;;;;AAclC,SAAS,kBAAwB;CAC/B,QAAQ,cAAc,IAAI,EAAE,QAAQ,KAAK,CAAC;AAC5C;;;;;;;;;;;;;;;;AAiBA,SAAgB,4BAA4B,QAAsB,iBAAuB;CACvF,IAAI;EACF,MAAM;CACR,SAAS,OAAO;EACd,IAAI,sBAAsB,KAAK,GAC7B,MAAM,IAAI,0BAA0B,EAAE,OAAO,MAAM,CAAC;EAGtD,MAAM;CACR;AACF;;;;;AAMA,SAAS,sBAAsB,OAAyB;CACtD,OAAO,iBAAiB,SAAS,MAAM,QAAQ,SAAS,yBAAyB;AACnF"}
1
+ {"version":3,"file":"esbuild-preflight.mjs","names":[],"sources":["../../../../../../../../packages/core/src/production/esbuild-preflight.ts"],"sourcesContent":["import esbuild from \"esbuild\";\nimport { EsbuildBinaryMissingError } from \"../errors/esbuild-binary-missing-error\";\n\nexport { EsbuildBinaryMissingError };\n\n/**\n * The exact substring esbuild's own loader throws when the platform-specific\n * binary package (e.g. `@esbuild/win32-x64`) never got installed. This is\n * the signature pnpm's build-script approval gate leaves behind: it blocks\n * esbuild's postinstall script, so the binary is never linked into place,\n * and any later call into esbuild dies with this message instead of a\n * project-shaped one.\n *\n * Source: `pkgAndSubpathForCurrentPlatform` in esbuild's `lib/main.js`.\n */\nconst UNLINKED_BINARY_SIGNATURE = \"could not be found, and is needed by esbuild\";\n\n/**\n * A cheap operation that forces esbuild to resolve and invoke its platform\n * binary. Injectable so tests can simulate a missing binary without deleting\n * anything from a real install.\n */\nexport type EsbuildProbe = () => void;\n\n/**\n * The default probe: a trivial `transformSync` call. Trivial input keeps the\n * cost negligible while still forcing esbuild to resolve and run its native\n * binary, which is the only way an unlinked binary actually surfaces.\n */\nfunction runDefaultProbe(): void {\n esbuild.transformSync(\"\", { loader: \"js\" });\n}\n\n/**\n * Fail fast, before dev or build does any other work, when esbuild's native\n * binary is not linked.\n *\n * A healthy esbuild install is a no-op. A binary genuinely missing — because\n * a platform package was never installed, or a package manager blocked its\n * postinstall script — is turned into {@link EsbuildBinaryMissingError}, a\n * message that names the cause and the fix. Any other failure (a real syntax\n * error, an unrelated platform mismatch, …) is rethrown unchanged — this\n * preflight only owns the one known failure mode.\n *\n * @param probe Overrides the default `esbuild.transformSync` invocation.\n * Intended for tests only.\n * @throws {EsbuildBinaryMissingError} when the platform binary is missing or unlinked.\n */\nexport function assertEsbuildBinaryIsLinked(probe: EsbuildProbe = runDefaultProbe): void {\n try {\n probe();\n } catch (error) {\n if (isUnlinkedBinaryError(error)) {\n throw new EsbuildBinaryMissingError({ cause: error });\n }\n\n throw error;\n }\n}\n\n/**\n * Narrow an unknown thrown value down to esbuild's known \"binary not\n * linked\" failure, identified by the fixed substring esbuild itself throws.\n */\nfunction isUnlinkedBinaryError(error: unknown): boolean {\n return error instanceof Error && error.message.includes(UNLINKED_BINARY_SIGNATURE);\n}\n"],"mappings":";;;;;;;;;;;;;;AAeA,MAAM,4BAA4B;;;;;;AAclC,SAAS,kBAAwB;CAC/B,QAAQ,cAAc,IAAI,EAAE,QAAQ,KAAK,CAAC;AAC5C;;;;;;;;;;;;;;;;AAiBA,SAAgB,4BAA4B,QAAsB,iBAAuB;CACvF,IAAI;EACF,MAAM;CACR,SAAS,OAAO;EACd,IAAI,sBAAsB,KAAK,GAC7B,MAAM,IAAI,0BAA0B,EAAE,OAAO,MAAM,CAAC;EAGtD,MAAM;CACR;AACF;;;;;AAMA,SAAS,sBAAsB,OAAyB;CACtD,OAAO,iBAAiB,SAAS,MAAM,QAAQ,SAAS,yBAAyB;AACnF"}
@@ -23,7 +23,7 @@ import { ensureDirectoryAsync, fileExistsAsync, getFileAsync, getJsonFileAsync,
23
23
  import glob from "fast-glob";
24
24
  import esbuild from "esbuild";
25
25
 
26
- //#region ../core/src/production/production-builder.ts
26
+ //#region ../../packages/core/src/production/production-builder.ts
27
27
  /**
28
28
  * Recreates `require`, `__filename` and `__dirname` at the top of an ESM bundle.
29
29
  *
@@ -1 +1 @@
1
- {"version":3,"file":"production-builder.mjs","names":[],"sources":["../../../../../../../core/src/production/production-builder.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport {\n ensureDirectoryAsync,\n fileExistsAsync,\n getFileAsync,\n getJsonFileAsync,\n putFileAsync,\n removeDirectoryAsync,\n} from \"@warlock.js/fs\";\nimport esbuild from \"esbuild\";\nimport glob from \"fast-glob\";\nimport path from \"path\";\nimport { assertNoReservedConnectorNames } from \"../connectors/assert-no-reserved-connector-names\";\nimport { assertUniqueConnectorNames } from \"../connectors/assert-unique-connector-names\";\nimport type { Connector, ConnectorBuildContext, ConnectorEsbuildPatch } from \"../connectors/types\";\nimport { configKeyFromPath } from \"../config/config-key-from-path\";\nimport {\n isConfigFile,\n isEventFile,\n isLocaleFile,\n isMainFile,\n isRouteFile,\n isWorkerFile,\n} from \"../dev-server/special-file-patterns\";\nimport { tsconfigManager } from \"../dev-server/tsconfig-manager\";\nimport { appPath, rootPath, warlockPath } from \"../utils\";\nimport { warlockConfigManager } from \"../warlock-config/warlock-config.manager\";\nimport { assertGeneratedImportsAreDeclared } from \"./assert-generated-imports\";\nimport { bundleFrameworkDependencies } from \"./bundle-framework-dependencies\";\nimport { dedupe, runEmitContributions, runGenerateContributions } from \"./build-contributions\";\nimport { writeDistBuildManifestAsync } from \"./dist-build-manifest\";\nimport { nativeNodeModulesPlugin } from \"./esbuild-plugins\";\nimport { assertEsbuildBinaryIsLinked } from \"./esbuild-preflight\";\nimport { collectRouteRegistrationSnapshot } from \"./route-registration-snapshot\";\nimport { clearOwnedRouteTypes } from \"../dev-server/route-types-publisher\";\nimport {\n commitDistAsync,\n createTempOutputDir,\n rollbackDistAsync,\n stageDistAsync,\n type StagedDist,\n} from \"./promote-dist\";\nimport { resolveBuildConfig, type ResolvedBuildConfig } from \"./resolve-build-config\";\nimport { tsconfigPathAliases } from \"./tsconfig-path-aliases\";\nimport { toKebabCase } from \"@mongez/reinforcements\";\n\n/**\n * Recreates `require`, `__filename` and `__dirname` at the top of an ESM bundle.\n *\n * Bundled CommonJS dependencies call `require(\"node:assert\")` and read\n * `__dirname` to locate their own assets. Neither exists in an ES module, so\n * esbuild substitutes a stub that throws — **after the build has reported\n * success**. `Dynamic require of \"node:assert\" is not supported` is that stub\n * firing, and it is the defect this shim removes.\n *\n * `__dirname` matters as much as `require`: without it a dependency resolving\n * an asset path silently gets `undefined` and fails later, further from the\n * cause.\n *\n * Written as one line because esbuild inserts a banner verbatim above the\n * bundle and a multi-line string here would shift every mapped line.\n */\nconst ESM_INTEROP_SHIM =\n \"import{createRequire as __wlCreateRequire}from'node:module';\" +\n \"import{fileURLToPath as __wlFileURLToPath}from'node:url';\" +\n \"import{dirname as __wlDirname}from'node:path';\" +\n \"const require=__wlCreateRequire(import.meta.url);\" +\n \"const __filename=__wlFileURLToPath(import.meta.url);\" +\n \"const __dirname=__wlDirname(__filename);\";\n\n/**\n * Combine the framework's banner with the user's, keeping both.\n *\n * esbuild's `banner` is an object keyed by output type, and every merge in the\n * path to it — the config merge and the options spread — REPLACES that object\n * rather than merging it. So whichever is applied second silently deletes the\n * other. This is the only place the two can coexist.\n *\n * The shim goes first: it defines `require`, which a user banner may use.\n *\n * @param userBanner banner from `warlock.config.ts`, if any\n * @param shim the interop shim, or undefined when it does not apply\n */\nfunction mergeBanner(\n userBanner: Record<string, string> | undefined,\n shim: string | undefined,\n): Record<string, string> | undefined {\n if (!shim) return userBanner;\n\n const userJs = userBanner?.js;\n\n return {\n ...userBanner,\n js: userJs ? `${shim}${userJs}` : shim,\n };\n}\n\n/**\n * Prefix every generated file uses to reach the app root.\n *\n * Generated sources are written into `.warlock/production/`, two levels below\n * the app root, so `../../` lands back on it — the same hop already spelled\n * out in the `../../src/app/…` and `../../src/config/…` imports the module and\n * config-loader generators emit. Named once so a generator that needs a new\n * app-root file (`warlock.config`) cannot pick a different depth.\n */\nconst APP_ROOT_FROM_PRODUCTION_DIR = \"../../\";\n\n/**\n * Production Builder\n * Generates production-ready files and bundles them for deployment\n * Build options are loaded from warlock.config.ts\n */\nexport class ProductionBuilder {\n private options!: ResolvedBuildConfig;\n private readonly productionDir = warlockPath(\"production\");\n\n /**\n * Connectors declared in `warlock.config.ts`. Read statically — `build`\n * never calls `boot()`/`start()` on them; it only\n * drains their `build` contributions.\n */\n private connectors: readonly Connector[] = [];\n\n /**\n * The contributors' merged esbuild patch, produced by the `generate` pass\n * and consumed by {@link bundle}.\n */\n private contributedEsbuild: ConnectorEsbuildPatch = {};\n\n /** Browser-safe API metadata captured in a fresh registration-only child. */\n private namedApiRoutes?: readonly import(\"../router/types\").NamedApiRoute[];\n\n /**\n * Main build entry point\n *\n * The esbuild bundle is written into a TEMP directory next to the real\n * output directory, never into it, and that directory is renamed over\n * `outdir` as one filesystem operation — so `outdir` is never observed as\n * a mix of the old build and the new one, and a build that fails before\n * that rename never touches `outdir` at all.\n *\n * `this.options.outdir` is NOT repointed at the temp directory while that\n * happens, and must never be. It is not merely a write target: consumers\n * BAKE it into runtime output — `web`'s build contribution derives the\n * `clientDir` recorded in its pages manifest from it\n * (`web/src/build/contribution.ts`) — so a temp path reaching them\n * produces an artifact whose browser paths point at a directory promotion\n * has since renamed away. The temp path is passed explicitly, as a\n * parameter, to the one operation that writes into it ({@link bundle});\n * everything else, `buildContext()` included, keeps reading the final\n * destination.\n *\n * That is also why promotion is STAGED rather than done at the very end.\n * Connector `emit` hooks write real artifacts (the web client bundle) and\n * see the final `outdir`, so they must run when `outdir` genuinely holds\n * this build — after the rename, not before it, or promotion would replace\n * the directory they just wrote into. The previous build is kept parked\n * aside until they finish: `emit` throwing rolls the whole promotion back,\n * and the build-success marker `warlock start` checks is written last of\n * all, so a failure at any point leaves no `dist` that start will boot.\n */\n public async build(): Promise<void> {\n console.log(colors.cyan(\"Building for production...\\n\"));\n\n // Step 0: Fail fast when esbuild's native binary never got linked (the\n // state pnpm leaves a project in when its build-script approval gate\n // blocked esbuild's postinstall) rather than let bundling die on esbuild's\n // own cryptic \"package could not be found\" error several steps from now.\n assertEsbuildBinaryIsLinked();\n\n // Step 1: Initialize options from config\n await this.initializeOptions();\n\n const finalOutDir = this.options.outdir!;\n const tempOutDir = createTempOutputDir(finalOutDir);\n\n // Set once the temp directory has been renamed onto `finalOutDir`. Its\n // presence is what tells the catch below whether a failure has a\n // promotion to undo or only a temp directory to discard.\n let staged: StagedDist | undefined;\n\n try {\n // Step 2: Generate combined files\n await this.generateCombinedFiles();\n\n // Step 3: Generate entry point\n await this.generateEntryPoint();\n\n // Step 4: Refuse to bundle code the app could not resolve at runtime\n await this.assertGeneratedImports();\n\n // Step 4.5: Drain the connectors' `generate` contributions\n await this.captureNamedApiRoutesForWeb();\n const contributed = await this.runGenerateContributions();\n\n // Step 4.6: Re-assert over what the contributors just wrote.\n //\n // Step 4 only saw core's own generated files; a contributor writes its\n // code (a pages barrel, say) AFTER that assertion, so an undeclared bare\n // specifier in it reaches the bundle unchecked. Under\n // `packages: \"external\"` that specifier survives verbatim into the\n // artifact and dies as ERR_MODULE_NOT_FOUND at runtime — the same failure\n // step 4 exists to prevent. Skipped when nothing contributed: re-globbing\n // and re-reading the production dir is pure cost in the common case.\n if (contributed) {\n await this.assertGeneratedImports();\n }\n\n // Step 5: Bundle with esbuild into the temp directory. The ONLY\n // operation handed that path — it is a write target, not config.\n await this.bundle(tempOutDir);\n\n // Step 5.5: Promote the bundle into `outdir`, keeping the previous\n // build parked aside. `outdir` now holds exactly this build, so the\n // steps below write into — and record — the real destination.\n staged = await stageDistAsync(tempOutDir, finalOutDir);\n\n // Step 5.6: Drain the connectors' `emit` contributions — after the\n // bundle is in place (so what they write survives promotion and the\n // paths they bake in resolve), and BEFORE step 6 deletes the\n // production directory they may still read.\n await runEmitContributions(this.connectors, this.buildContext());\n\n // Step 5.7: Mark `dist` as a genuine, complete build — the one thing\n // `warlock start` trusts. Written LAST on purpose: every earlier step\n // can still fail, and until this file exists nothing will boot what\n // they left behind.\n await writeDistBuildManifestAsync(finalOutDir);\n\n // Step 5.8: Commit — drop the parked previous build. Cannot throw.\n await commitDistAsync(staged);\n } catch (error) {\n if (staged) {\n // The promotion already happened; put the previous build back and\n // take this half-finished one out of `outdir`.\n await rollbackDistAsync(staged);\n } else {\n // Nothing this build produced ever reached `outdir` — discard the\n // temp directory and leave `outdir` exactly as it was.\n await removeDirectoryAsync(tempOutDir).catch(() => undefined);\n }\n\n throw error;\n }\n\n // Step 6: Remove production folder\n await removeDirectoryAsync(this.productionDir);\n\n console.log(colors.green(\"Build complete!\"));\n console.log(`Start production server by running ${colors.cyan(\"warlock start\")}`);\n }\n\n /**\n * Initialize options from warlock.config.ts\n */\n private async initializeOptions(): Promise<void> {\n this.options = resolveBuildConfig();\n // Same config object `resolveBuildConfig` just read — `warlock build`\n // preloads warlock.config.ts, so no additional load happens here.\n const connectors = warlockConfigManager.get(\"connectors\") ?? [];\n\n // Checked here, where the array is first read, so nothing downstream has\n // drained anything yet: the `generate` and `emit` passes run per ENTRY, so\n // a name listed twice would write its files and merge its esbuild options\n // twice into an artifact the runtime then boots that name only once from.\n // A build that half-applied a connector and reported success is worse than\n // one that never started.\n assertUniqueConnectorNames([...connectors]);\n\n // And here rather than only at boot, for the same reason: a name a built-in\n // already owns is skipped by the runtime, so an artifact built from it\n // carries the custom connector's generated files and esbuild patches while\n // the server boots the built-in instead. Refusing it at boot alone would\n // mean the build had already emitted that artifact — the failure has to\n // land on the developer running `warlock build`, not on whoever starts the\n // server. Same assertion the registration half calls, over the same names.\n assertNoReservedConnectorNames([...connectors]);\n\n this.connectors = connectors;\n\n // Ensure production directory exists\n await ensureDirectoryAsync(this.productionDir);\n }\n\n /**\n * The context handed to every build contribution.\n */\n private buildContext(): ConnectorBuildContext {\n return {\n productionDir: this.productionDir,\n appRoot: rootPath(),\n options: this.options,\n namedApiRoutes: this.namedApiRoutes,\n };\n }\n\n /**\n * Web route declarations need application API registration, which cannot be\n * inferred from generated files. Capture it once in a disposable child before\n * contributors write build artifacts; no connector lifecycle runs there.\n */\n private async captureNamedApiRoutesForWeb(): Promise<void> {\n if (!this.connectors.some((connector) => connector.name === \"web\")) {\n await clearOwnedRouteTypes(rootPath());\n return;\n }\n\n this.namedApiRoutes = (\n await collectRouteRegistrationSnapshot({\n cwd: rootPath(),\n timeoutMs: this.options.routeRegistrationTimeoutMs,\n })\n ).routes;\n }\n\n /**\n * Drain the `generate` hooks and fold what they returned back into the\n * build.\n *\n * The entry point is REGENERATED here rather than generated later. The\n * contribution slot is fixed — after `assertGeneratedImports` (so nothing\n * bundles that the app could not resolve) and before `bundle` — while\n * `generateEntryPoint` must stay at step 3, because `app.ts` is itself\n * generated code the assertion has to see; moving it past the assertion\n * would silently drop the entry from that check. Rewriting one small file\n * is cheaper than losing either guarantee, and the write is pure\n * (`generatedFiles` + these imports), so doing it twice is not a\n * correctness risk.\n *\n * @returns whether any connector ran a `generate` hook — the caller uses it\n * to decide if the import assertion is worth a second pass. Keyed on the\n * hook EXISTING, not on what it returned: a hook that returns nothing may\n * still have written files into `productionDir`, and those are exactly the\n * files the second pass is there to read.\n */\n private async runGenerateContributions(): Promise<boolean> {\n const contributed = this.connectors.some((connector) => Boolean(connector.build?.generate));\n\n const { entryImports, esbuild } = await runGenerateContributions(\n this.connectors,\n this.buildContext(),\n );\n\n this.contributedEsbuild = esbuild;\n\n if (entryImports.length > 0) {\n await this.generateEntryPoint(entryImports);\n }\n\n return contributed;\n }\n\n /**\n * Track which special files were generated\n */\n private generatedFiles = {\n locales: false,\n events: false,\n main: false,\n routes: false,\n workers: false,\n };\n\n /**\n * Generate all combined files\n */\n private async generateCombinedFiles(): Promise<void> {\n console.log(colors.yellow(\" Generating production files...\"));\n\n // Generate bootstrap.ts file\n await this.generateBootstrap();\n\n // Generate config loader\n await this.generateConfigLoader();\n\n // Generate special files and track which ones have content\n const [locales, events, main, routes, workers] = await Promise.all([\n this.generateLocales(),\n this.generateEvents(),\n this.generateMain(),\n this.generateRoutes(),\n this.generateWorkers(),\n ]);\n\n this.generatedFiles = { locales, events, main, routes, workers };\n }\n\n /**\n * Generate bootstrap.ts - ensures bootstrap() runs first and sets production environment\n */\n private async generateBootstrap(): Promise<void> {\n // ESM hoists imports, so the app bootstrap must be the first import to run first\n const appBootstrapImport = (await fileExistsAsync(appPath(\"bootstrap.ts\")))\n ? \"import './../../src/app/bootstrap';\\n\"\n : \"\";\n\n const content = `${appBootstrapImport}import { bootstrap, Application } from \"@warlock.js/core\";\n\n// Production runtime; NODE_ENV is only defaulted so an explicit value (e.g. staging) wins\nApplication.setRuntimeStrategy(\"production\");\nif (!process.env.NODE_ENV) {\n Application.setEnvironment(\"production\");\n}\n\n// Bootstrap the application\nbootstrap();\n`;\n\n await putFileAsync(path.join(this.productionDir, \"bootstrap.ts\"), content);\n }\n\n /**\n * Fail the build when generated code imports a package the app does not\n * declare.\n *\n * The bundler is configured `packages: \"external\"`, so every bare specifier\n * written above survives verbatim into an artifact that resolves against the\n * **consuming app's** node_modules. A framework-internal dependency imported\n * there resolves by accident under npm/yarn hoisting and dies under pnpm —\n * which is how a production app shipped that could not boot. Rewriting the\n * offending import fixes today's bundle; this check is what stops the next\n * change to the generator from quietly reintroducing it.\n */\n private async assertGeneratedImports(): Promise<void> {\n const generatedPaths = await glob(\"**/*.{ts,tsx,js,mjs}\", {\n cwd: this.productionDir,\n absolute: false,\n });\n\n const [files, appPackage] = await Promise.all([\n Promise.all(\n generatedPaths.map(async (file) => ({\n file,\n content: await getFileAsync(path.join(this.productionDir, file)),\n })),\n ),\n getJsonFileAsync<{ dependencies?: Record<string, string> }>(rootPath(\"package.json\")),\n ]);\n\n assertGeneratedImportsAreDeclared(files, Object.keys(appPackage.dependencies ?? {}));\n }\n\n /**\n * Glob `src/app` and keep the files the shared dev-server predicate accepts,\n * so production discovers exactly what the dev collector does.\n * Returns relative paths from .warlock/production/ to src/app/\n */\n private async globModule(matches: (relativePath: string) => boolean): Promise<string[]> {\n const files = await glob(\"**/*.{ts,tsx,json}\", {\n cwd: appPath(),\n absolute: false,\n });\n\n // e.g., \"users/main.ts\" -> \"../../src/app/users/main\"\n return files\n .filter((file) => matches(\"src/app/\" + file))\n .sort()\n .map((file) => \"../../src/app/\" + file.replace(/\\.(ts|tsx)$/, \"\"));\n }\n\n /**\n * Generate config-loader.ts\n */\n private async generateConfigLoader(): Promise<void> {\n const configDirectory = path.join(process.cwd(), \"src/config\");\n\n const files = await glob(\"**/*.{ts,tsx}\", {\n cwd: configDirectory,\n absolute: false,\n });\n\n // Same key rule as the dev config loader: the raw path, never camel-cased\n const configNames = files\n .filter((f) => isConfigFile(\"src/config/\" + f))\n .map((f) => ({\n path: f.replace(/\\.(ts|tsx)$/, \"\"),\n key: configKeyFromPath(\"src/config/\" + f),\n }))\n .filter((entry): entry is { path: string; key: string } => entry.key !== undefined)\n .sort((a, b) => a.path.localeCompare(b.path));\n\n // Only `@warlock.js/core` — the one package the app itself declares. See\n // `assertGeneratedImportsAreDeclared`: `@mongez/config` is core's own\n // dependency, so a bare import of it resolved by luck under npm/yarn\n // hoisting and died under pnpm's strict layout.\n const imports: string[] = [\n 'import { setConfig, configSpecialHandlers } from \"@warlock.js/core\";',\n ];\n const configImports: string[] = [];\n const configSetCalls: string[] = [];\n const executors: string[] = [];\n\n configNames.forEach(({ path: configPath, key }, index) => {\n // Index-based identifier: keys like \"rate-limit\" or \"mail/smtp\" are not valid names\n const varName = `config${index}`;\n configImports.push(`import ${varName} from \"../../src/config/${configPath}\";`);\n configSetCalls.push(`setConfig(${JSON.stringify(key)}, ${varName});`);\n executors.push(`await configSpecialHandlers.execute(${JSON.stringify(key)}, ${varName});`);\n });\n\n // ESM hoists imports, so prestart must be the first import to run first\n const prestartImports = (await fileExistsAsync(appPath(\"prestart.ts\")))\n ? [\"import './../../src/app/prestart';\"]\n : [];\n\n const content = [\n ...prestartImports,\n ...imports,\n \"\",\n \"// Config imports\",\n ...configImports,\n \"\",\n \"// Register configs\",\n ...configSetCalls,\n \"\",\n \"// Special handlers\",\n ...executors,\n \"\",\n ].join(\"\\n\");\n\n await putFileAsync(path.join(this.productionDir, \"config-loader.ts\"), content);\n }\n\n /**\n * Generate locales.ts (only if there are locale files)\n * @returns true if file was generated with content\n */\n private async generateLocales(): Promise<boolean> {\n const files = await this.globModule(isLocaleFile);\n if (files.length === 0) return false;\n const content = files\n .map((file, index) => {\n if (!file.endsWith(\".json\")) return `import \"${file}\";`;\n const moduleFolder = file.split(\"/\").at(-3)!;\n return [\n `import dictionary${index} from \"${file}\";`,\n 'import { registerLocaleDictionary } from \"@warlock.js/core\";',\n `registerLocaleDictionary({ sourceFile: ${JSON.stringify(file)}, source: JSON.stringify(dictionary${index}), defaultNamespace: ${JSON.stringify(moduleFolder)} });`,\n ].join(\"\\n\");\n })\n .join(\"\\n\");\n await putFileAsync(path.join(this.productionDir, \"locales.ts\"), content + \"\\n\");\n return true;\n }\n\n /**\n * Generate events.ts (only if there are event files)\n * @returns true if file was generated with content\n */\n private async generateEvents(): Promise<boolean> {\n const files = await this.globModule(isEventFile);\n if (files.length === 0) return false;\n await this.generateImportsFile(files, \"events.ts\");\n return true;\n }\n\n /**\n * Generate main.ts (only if there are main files)\n * @returns true if file was generated with content\n */\n private async generateMain(): Promise<boolean> {\n const files = await this.globModule(isMainFile);\n if (files.length === 0) return false;\n await this.generateImportsFile(files, \"main.ts\");\n return true;\n }\n\n /**\n * Generate routes.ts (only if there are route files)\n * @returns true if file was generated with content\n */\n private async generateRoutes(): Promise<boolean> {\n const files = await this.globModule(isRouteFile);\n if (files.length === 0) return false;\n await this.generateImportsFile(files, \"routes.ts\");\n return true;\n }\n\n /**\n * Generate workers.ts (only if there are worker files)\n * @returns true if file was generated with content\n */\n private async generateWorkers(): Promise<boolean> {\n const files = await this.globModule(isWorkerFile);\n if (files.length === 0) return false;\n await this.generateImportsFile(files, \"workers.ts\");\n return true;\n }\n\n /**\n * Generate a file with imports from all given files\n */\n private async generateImportsFile(importPaths: string[], outputFile: string): Promise<void> {\n const imports = importPaths.map((importPath) => `import \"${importPath}\";`);\n const content = imports.join(\"\\n\") + \"\\n\";\n await putFileAsync(path.join(this.productionDir, outputFile), content);\n }\n\n /**\n * Generate the main entry point (app.ts)\n *\n * @param contributedImports lines from connector `generate` hooks, appended\n * to section 4 after `./routes`\n */\n private async generateEntryPoint(contributedImports: string[] = []): Promise<void> {\n console.log(colors.yellow(\" Generating entry point...\"));\n\n // The names this build resolved, baked in as a literal. The entry imports\n // the config source, and that source is re-evaluated at startup — an\n // env-conditional `connectors` array can hand the boot a different list\n // than the one drained here. A literal is the only part of the array that\n // survives into the artifact unchanged, so it is what the boot compares\n // against.\n const expectedNames = this.connectors\n .map((connector) => JSON.stringify(connector.name))\n .join(\", \");\n\n // Build imports based on which files were generated\n const imports: string[] = [\n \"// 1. Bootstrap (loads .env, initializes framework)\",\n 'import \"./bootstrap\";',\n \"\",\n \"// 2. Load configs\",\n 'import \"./config-loader\";',\n \"\",\n // Registration has to sit between the config being available and the\n // first phase starting: the connectors listed in `connectors` are the\n // same ones this build drained contributions from, so the bundle boots\n // exactly what it was built for. Register any later and an early-phase\n // connector would miss its own start.\n \"// 2.5 Register connectors declared in warlock.config (the same array this\",\n \"// build read its contributions from, so built-for and boots-with match).\",\n \"// The config is imported STATICALLY so esbuild bakes it into the bundle\",\n \"// and the array is handed over explicitly — an artifact has no\",\n \"// warlock.config.ts beside it to read at runtime, and a registration\",\n \"// that quietly found nothing to register is the exact drift this\",\n \"// section exists to prevent.\",\n \"// `expectedNames` is the list this build resolved, in order — boot\",\n \"// refuses to start when the config hands over a different set or order.\",\n 'import { registerConfiguredConnectors } from \"@warlock.js/core\";',\n `import warlockConfig from \"${APP_ROOT_FROM_PRODUCTION_DIR}warlock.config\";`,\n `registerConfiguredConnectors(warlockConfig.connectors ?? [], { expectedNames: [${expectedNames}] });`,\n \"\",\n \"// 2.6 Fail fast on a busy port. `http` is a LATE-phase connector, so its\",\n \"// own preflight is not reached until the database and cache have\",\n \"// connected and every app module has been imported — seconds of work\",\n \"// thrown away before anyone learns the port was taken. This probe is\",\n \"// a bind-and-release on a socket that is never served, and it reports\",\n \"// on stderr because no log channel is configured this early.\",\n 'import { Application, connectorsManager, ConnectorLifecyclePhase, preflightConfiguredHttpPort } from \"@warlock.js/core\";',\n 'if (Application.hasRole(\"api\") || Application.hasRole(\"web\")) {',\n \" await preflightConfiguredHttpPort();\",\n \"}\",\n \"\",\n \"// 3. Start early-phase connectors (database, cache, logger, ...)\",\n \"// so data sources, cache, etc. are ready before app code runs\",\n \"await connectorsManager.startPhase(ConnectorLifecyclePhase.Early);\",\n ];\n\n // App code uses dynamic `await import(...)` so each module's side\n // effects fire at THIS point in execution. Static imports would be\n // hoisted to module-instantiation time (before the early-phase await\n // resolves), which is exactly the bug this split is meant to fix.\n //\n // The guarantee comes from the imports being DYNAMIC — esbuild wraps a\n // dynamically-imported module in its `__esm(() => {…})` helper and runs\n // it at the await, not at instantiation. It does NOT come from\n // `splitting: true`, which only decides one-file-vs-chunks. This\n // previously said splitting was required; it is not, and `singleBundle`\n // (splitting: false) preserves the ordering.\n imports.push(\"\", \"// 4. Load app code (events, locales, main, routes)\");\n\n if (this.generatedFiles.events) {\n imports.push('await import(\"./events\");');\n }\n if (this.generatedFiles.locales) {\n imports.push('await import(\"./locales\");');\n }\n if (this.generatedFiles.main) {\n imports.push('await import(\"./main\");');\n }\n if (this.generatedFiles.routes) {\n imports.push('if (Application.hasRole(\"api\")) {', ' await import(\"./routes\");', \"}\");\n }\n if (this.generatedFiles.workers) {\n imports.push('if (Application.hasRole(\"worker\")) {', ' await import(\"./workers\");', \"}\");\n }\n\n // Contributor imports come AFTER `./routes`, never before: a connector\n // that registers pages needs the routes app code already collected —\n // the same ordering dev uses (routes first, then the connector installs\n // on top of them). Emitted verbatim; the contributor writes the whole\n // statement (e.g. `await import(\"./pages\");`).\n imports.push(...contributedImports);\n\n // A rejecting validator (Application.onValidateBoot) must abort boot\n // before late-phase connectors bind a port.\n imports.push(\n \"\",\n \"// 5. Run startup validators registered via Application.onValidateBoot(...)\",\n \"await Application.runStartupValidators();\",\n );\n\n // Start late-phase connectors after app code registers routes/listeners\n imports.push(\n \"\",\n \"// 6. Start late-phase connectors (http, socket) — routes and\",\n \"// listeners registered by app code are now ready to bind\",\n \"await connectorsManager.startPhase(ConnectorLifecyclePhase.Late);\",\n \"\",\n \"// 7. Signal a complete boot so `Application.onceBooted(...)` listeners fire\",\n \"Application.markBooted({ environment: Application.environment, runtimeStrategy: Application.runtimeStrategy });\",\n \"connectorsManager.shutdownOnProcessKill();\",\n );\n\n const content = imports.join(\"\\n\") + \"\\n\";\n await putFileAsync(path.join(this.productionDir, \"app.ts\"), content);\n }\n\n /**\n * Bundle with esbuild\n *\n * @param writeOutDir the directory esbuild writes into — the build's\n * private temp directory, NOT `options.outdir`. Taken as a parameter\n * rather than read off `this.options` because the two are different paths\n * with different meanings: `options.outdir` is the final destination every\n * consumer bakes into the artifact, and this is only where bytes land\n * before promotion moves them there.\n */\n private async bundle(writeOutDir: string): Promise<void> {\n console.log(colors.magenta(\" Bundling with esbuild...\"));\n\n const entryPoint = path.join(this.productionDir, \"app.ts\");\n const outFileName = this.options.outFile!;\n // Strip extension so entryNames produces \"<base>.js\" via esbuild\n const entryName = path.basename(outFileName, path.extname(outFileName));\n\n // `singleBundle` and `esmShim` are ours, not esbuild's — it throws on\n // unknown keys, and the user options are spread into its call verbatim.\n const singleBundle = this.options.singleBundle === true;\n const esmShim = this.options.esmShim !== false;\n // Read before deleting: the merged banner is applied AFTER the user\n // spread, so a user banner must not be lost to it or clobber the shim.\n const userBanner = this.options.banner;\n\n // `outFile` and `entryPath` are REQUIRED on ResolvedBuildConfig on purpose:\n // resolve-build-config.ts documents that widening them pushed a lie downstream\n // into start-production.command.ts, which then could not trust its own config.\n // This is the one place they must be absent - the object is spread into esbuild's\n // call verbatim and esbuild throws on unknown keys.\n //\n // Stripped off a LOCAL COPY of `this.options`, never off `this.options`\n // itself: `buildContext()` hands `this.options` to every `generate`/`emit`\n // contribution hook, including the `emit` pass that runs AFTER this method\n // returns (`build()` step 5.6). Deleting these keys from the shared object\n // used to leave those hooks reading `undefined` for `outFile`, `entryPath`,\n // `singleBundle`, `esmShim` and `banner` even though `ConnectorBuildContext`\n // types them as present. A shallow copy is enough — every field this method\n // reads off it is either scalar or already re-merged below (`define`,\n // `external`, `loader`, `banner`), so nothing here needs a deep clone.\n const esbuildOptions: Partial<ResolvedBuildConfig> = { ...this.options };\n\n delete esbuildOptions.outFile;\n delete esbuildOptions.entryPath;\n delete esbuildOptions.singleBundle;\n delete esbuildOptions.esmShim;\n delete esbuildOptions.banner;\n delete esbuildOptions.routeRegistrationTimeoutMs;\n\n await ensureDirectoryAsync(writeOutDir);\n\n const alias = this.buildAliasMapFromTsconfig();\n\n // Whether this build decides externality per import EDGE\n // (`bundle-framework-dependencies.ts`, which explains the rule at\n // length) or keeps the blunt `packages: \"external\"`.\n //\n // Not in `singleBundle` mode: that bundles everything by definition, and\n // a plugin that can only ever ADD an external would silently narrow it.\n // Not when the user set `packages` themselves: their value has always\n // won over the default below, and it must keep winning — the plugin is\n // the default's implementation, not a new policy layered on top.\n const perEdgeExternals = !singleBundle && (esbuildOptions as any).packages === undefined;\n\n // The user can override `format`, so gate the shim on the EFFECTIVE\n // format rather than on the default below. A CJS build already has\n // `require` and friends; injecting them there would be a redefinition.\n const isEsm = (esbuildOptions.format ?? \"esm\") === \"esm\";\n const banner = mergeBanner(userBanner, esmShim && isEsm ? ESM_INTEROP_SHIM : undefined);\n\n // Contributor patch, split into the part that can ride the spread order\n // and the three keys that cannot. `jsx` and `jsxImportSource` are placed\n // BEFORE the user spread below, which gives the ruled precedence for\n // free: builder defaults < contributor < user config.\n //\n // `define`, `external` and `loader` are pulled out because a spread\n // REPLACES them wholesale — the same trap `banner` documents. Two\n // contributors' env defines, a contributor's optional peers plus the\n // user's, or a contributor's `.svg` loader alongside the user's `.png`,\n // must both survive, so they are merged by key/by set and re-applied\n // after the spread with the user still winning per key.\n const {\n define: contributedDefine,\n external: contributedExternal,\n loader: contributedLoader,\n plugins: contributedPlugins,\n ...contributedOptions\n } = this.contributedEsbuild;\n\n const userDefine: Record<string, string> | undefined = esbuildOptions.define;\n const userExternal: string[] | undefined = esbuildOptions.external;\n const userLoader: ConnectorEsbuildPatch[\"loader\"] = esbuildOptions.loader;\n\n const define =\n contributedDefine || userDefine ? { ...contributedDefine, ...userDefine } : undefined;\n\n const loader =\n contributedLoader || userLoader ? { ...contributedLoader, ...userLoader } : undefined;\n\n const external =\n contributedExternal || userExternal\n ? dedupe([...(contributedExternal ?? []), ...(userExternal ?? [])])\n : undefined;\n\n if (singleBundle) {\n console.log(\n colors.magenta(\n \" Single-bundle mode — one JS file\" +\n (esmShim && isEsm ? \" with the ESM interop shim\" : \"\") +\n \". Native .node addons are still emitted alongside it.\",\n ),\n );\n }\n\n try {\n await esbuild.build({\n platform: \"node\",\n entryPoints: [entryPoint],\n bundle: true,\n // Both are DEFAULTS the user can override — they sit before the\n // `...esbuildOptions` spread deliberately. `singleBundle` moves them,\n // an explicit `splitting`/`packages` in warlock.config.ts beats both.\n //\n // Phase ordering does not depend on `splitting`: it comes from the\n // generated app.ts using dynamic `await import(...)` (see\n // generateAppEntry above), which esbuild defers to the call site in\n // either mode. Splitting only decides one file vs chunks.\n splitting: !singleBundle,\n // `\"bundle\"` under `perEdgeExternals` is not \"bundle everything\":\n // the plugin below returns `external: true` for every bare specifier\n // this build must not bundle, which is all of them bar the framework's\n // own declared dependencies. Saying `\"external\"` here instead would\n // externalise them before the plugin could rule.\n packages: singleBundle || perEdgeExternals ? \"bundle\" : \"external\",\n minify: esbuildOptions.minify,\n sourcemap: esbuildOptions.sourcemap === true ? \"linked\" : esbuildOptions.sourcemap,\n format: \"esm\",\n // Targeting a concrete Node version (not \"esnext\") so esbuild\n // transpiles TC39 stage 3 decorators into helpers — Node does not\n // implement them natively yet.\n target: [\"node22\"],\n entryNames: entryName,\n alias,\n plugins: [\n nativeNodeModulesPlugin,\n // BEFORE the framework-dependency plugin, and the order is\n // load-bearing: the first `onResolve` callback to answer wins, and\n // `app/users/...` is a bare specifier the other one would rule\n // external.\n tsconfigPathAliases(this.tsconfigPathAliasConfig()),\n ...(perEdgeExternals\n ? [bundleFrameworkDependencies({ appRoot: rootPath(), aliasKeys: Object.keys(alias) })]\n : []),\n // Contributor plugins run last: they load their own file types and\n // must not shadow the resolvers above.\n ...(contributedPlugins ?? []),\n ],\n // Between the defaults and the user spread — the ruled precedence.\n ...contributedOptions,\n ...(esbuildOptions as any),\n // AFTER the spread, and NOT overridable: `esbuildOptions.outdir` rides\n // that spread carrying the FINAL destination, which is exactly where\n // this build must not write yet. The final path is the user's setting\n // and stays authoritative for everyone reading the config — it is only\n // this one esbuild call that is redirected, and only until promotion\n // moves the result onto that very path.\n outdir: writeOutDir,\n // AFTER the spread for the same reason `banner` is: a spread replaces\n // these objects instead of merging them, so the merged values are\n // re-applied here. The user still wins — they were merged in last.\n ...(define ? { define } : {}),\n ...(external ? { external } : {}),\n ...(loader ? { loader } : {}),\n // AFTER the spread, and intentionally so: `banner` is an object, and\n // both the config merge and this spread REPLACE it wholesale rather\n // than merging. Left as a default above, any user banner would delete\n // the shim; left to the spread, the shim would delete theirs. The\n // merge is the only form that keeps both.\n ...(banner ? { banner } : {}),\n });\n } catch (e) {\n console.log(e);\n throw e;\n }\n }\n\n /**\n * The WILDCARD half of the same tsconfig `paths` map that\n * {@link ProductionBuilder.buildAliasMapFromTsconfig} reads the exact half\n * of. `tsconfig-path-aliases.ts` explains why the two halves need different\n * mechanisms — in short, esbuild's `alias` option cannot express a wildcard,\n * so the entries it skips have to be resolved by a plugin instead of being\n * left to no one.\n */\n private tsconfigPathAliasConfig(): { baseUrl: string; paths: Record<string, string[]> } {\n tsconfigManager.init();\n\n return {\n baseUrl: path.resolve(process.cwd(), tsconfigManager.baseUrl),\n paths: tsconfigManager.aliases as Record<string, string[]>,\n };\n }\n\n /**\n * Build an alias map from tsconfig `paths` so esbuild resolves local\n * source aliases (e.g. `@warlock.js/cascade`) to their on-disk source\n * folders during bundling. Without this, `packages: \"external\"` would\n * leave those bare specifiers as raw imports and Node would fail to\n * resolve them at runtime (they aren't installed in node_modules).\n *\n * Only exact (non-wildcard) aliases are included — esbuild's `alias`\n * option doesn't support glob-style mappings. The wildcard half is not\n * dropped, it is handled elsewhere: see\n * {@link ProductionBuilder.tsconfigPathAliasConfig}.\n */\n private buildAliasMapFromTsconfig(): Record<string, string> {\n tsconfigManager.init();\n\n const alias: Record<string, string> = {};\n const baseUrl = path.resolve(process.cwd(), tsconfigManager.baseUrl);\n\n for (const [from, to] of Object.entries(tsconfigManager.aliases)) {\n if (from.endsWith(\"/*\") || !Array.isArray(to) || to.length === 0) {\n continue;\n }\n\n const target = to[0];\n\n if (target === undefined) {\n continue;\n }\n\n alias[from] = path.resolve(baseUrl, target);\n }\n\n return alias;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"production-builder.mjs","names":[],"sources":["../../../../../../../../packages/core/src/production/production-builder.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport {\n ensureDirectoryAsync,\n fileExistsAsync,\n getFileAsync,\n getJsonFileAsync,\n putFileAsync,\n removeDirectoryAsync,\n} from \"@warlock.js/fs\";\nimport esbuild from \"esbuild\";\nimport glob from \"fast-glob\";\nimport path from \"path\";\nimport { assertNoReservedConnectorNames } from \"../connectors/assert-no-reserved-connector-names\";\nimport { assertUniqueConnectorNames } from \"../connectors/assert-unique-connector-names\";\nimport type { Connector, ConnectorBuildContext, ConnectorEsbuildPatch } from \"../connectors/types\";\nimport { configKeyFromPath } from \"../config/config-key-from-path\";\nimport {\n isConfigFile,\n isEventFile,\n isLocaleFile,\n isMainFile,\n isRouteFile,\n isWorkerFile,\n} from \"../dev-server/special-file-patterns\";\nimport { tsconfigManager } from \"../dev-server/tsconfig-manager\";\nimport { appPath, rootPath, warlockPath } from \"../utils\";\nimport { warlockConfigManager } from \"../warlock-config/warlock-config.manager\";\nimport { assertGeneratedImportsAreDeclared } from \"./assert-generated-imports\";\nimport { bundleFrameworkDependencies } from \"./bundle-framework-dependencies\";\nimport { dedupe, runEmitContributions, runGenerateContributions } from \"./build-contributions\";\nimport { writeDistBuildManifestAsync } from \"./dist-build-manifest\";\nimport { nativeNodeModulesPlugin } from \"./esbuild-plugins\";\nimport { assertEsbuildBinaryIsLinked } from \"./esbuild-preflight\";\nimport { collectRouteRegistrationSnapshot } from \"./route-registration-snapshot\";\nimport { clearOwnedRouteTypes } from \"../dev-server/route-types-publisher\";\nimport {\n commitDistAsync,\n createTempOutputDir,\n rollbackDistAsync,\n stageDistAsync,\n type StagedDist,\n} from \"./promote-dist\";\nimport { resolveBuildConfig, type ResolvedBuildConfig } from \"./resolve-build-config\";\nimport { tsconfigPathAliases } from \"./tsconfig-path-aliases\";\nimport { toKebabCase } from \"@mongez/reinforcements\";\n\n/**\n * Recreates `require`, `__filename` and `__dirname` at the top of an ESM bundle.\n *\n * Bundled CommonJS dependencies call `require(\"node:assert\")` and read\n * `__dirname` to locate their own assets. Neither exists in an ES module, so\n * esbuild substitutes a stub that throws — **after the build has reported\n * success**. `Dynamic require of \"node:assert\" is not supported` is that stub\n * firing, and it is the defect this shim removes.\n *\n * `__dirname` matters as much as `require`: without it a dependency resolving\n * an asset path silently gets `undefined` and fails later, further from the\n * cause.\n *\n * Written as one line because esbuild inserts a banner verbatim above the\n * bundle and a multi-line string here would shift every mapped line.\n */\nconst ESM_INTEROP_SHIM =\n \"import{createRequire as __wlCreateRequire}from'node:module';\" +\n \"import{fileURLToPath as __wlFileURLToPath}from'node:url';\" +\n \"import{dirname as __wlDirname}from'node:path';\" +\n \"const require=__wlCreateRequire(import.meta.url);\" +\n \"const __filename=__wlFileURLToPath(import.meta.url);\" +\n \"const __dirname=__wlDirname(__filename);\";\n\n/**\n * Combine the framework's banner with the user's, keeping both.\n *\n * esbuild's `banner` is an object keyed by output type, and every merge in the\n * path to it — the config merge and the options spread — REPLACES that object\n * rather than merging it. So whichever is applied second silently deletes the\n * other. This is the only place the two can coexist.\n *\n * The shim goes first: it defines `require`, which a user banner may use.\n *\n * @param userBanner banner from `warlock.config.ts`, if any\n * @param shim the interop shim, or undefined when it does not apply\n */\nfunction mergeBanner(\n userBanner: Record<string, string> | undefined,\n shim: string | undefined,\n): Record<string, string> | undefined {\n if (!shim) return userBanner;\n\n const userJs = userBanner?.js;\n\n return {\n ...userBanner,\n js: userJs ? `${shim}${userJs}` : shim,\n };\n}\n\n/**\n * Prefix every generated file uses to reach the app root.\n *\n * Generated sources are written into `.warlock/production/`, two levels below\n * the app root, so `../../` lands back on it — the same hop already spelled\n * out in the `../../src/app/…` and `../../src/config/…` imports the module and\n * config-loader generators emit. Named once so a generator that needs a new\n * app-root file (`warlock.config`) cannot pick a different depth.\n */\nconst APP_ROOT_FROM_PRODUCTION_DIR = \"../../\";\n\n/**\n * Production Builder\n * Generates production-ready files and bundles them for deployment\n * Build options are loaded from warlock.config.ts\n */\nexport class ProductionBuilder {\n private options!: ResolvedBuildConfig;\n private readonly productionDir = warlockPath(\"production\");\n\n /**\n * Connectors declared in `warlock.config.ts`. Read statically — `build`\n * never calls `boot()`/`start()` on them; it only\n * drains their `build` contributions.\n */\n private connectors: readonly Connector[] = [];\n\n /**\n * The contributors' merged esbuild patch, produced by the `generate` pass\n * and consumed by {@link bundle}.\n */\n private contributedEsbuild: ConnectorEsbuildPatch = {};\n\n /** Browser-safe API metadata captured in a fresh registration-only child. */\n private namedApiRoutes?: readonly import(\"../router/types\").NamedApiRoute[];\n\n /**\n * Main build entry point\n *\n * The esbuild bundle is written into a TEMP directory next to the real\n * output directory, never into it, and that directory is renamed over\n * `outdir` as one filesystem operation — so `outdir` is never observed as\n * a mix of the old build and the new one, and a build that fails before\n * that rename never touches `outdir` at all.\n *\n * `this.options.outdir` is NOT repointed at the temp directory while that\n * happens, and must never be. It is not merely a write target: consumers\n * BAKE it into runtime output — `web`'s build contribution derives the\n * `clientDir` recorded in its pages manifest from it\n * (`web/src/build/contribution.ts`) — so a temp path reaching them\n * produces an artifact whose browser paths point at a directory promotion\n * has since renamed away. The temp path is passed explicitly, as a\n * parameter, to the one operation that writes into it ({@link bundle});\n * everything else, `buildContext()` included, keeps reading the final\n * destination.\n *\n * That is also why promotion is STAGED rather than done at the very end.\n * Connector `emit` hooks write real artifacts (the web client bundle) and\n * see the final `outdir`, so they must run when `outdir` genuinely holds\n * this build — after the rename, not before it, or promotion would replace\n * the directory they just wrote into. The previous build is kept parked\n * aside until they finish: `emit` throwing rolls the whole promotion back,\n * and the build-success marker `warlock start` checks is written last of\n * all, so a failure at any point leaves no `dist` that start will boot.\n */\n public async build(): Promise<void> {\n console.log(colors.cyan(\"Building for production...\\n\"));\n\n // Step 0: Fail fast when esbuild's native binary never got linked (the\n // state pnpm leaves a project in when its build-script approval gate\n // blocked esbuild's postinstall) rather than let bundling die on esbuild's\n // own cryptic \"package could not be found\" error several steps from now.\n assertEsbuildBinaryIsLinked();\n\n // Step 1: Initialize options from config\n await this.initializeOptions();\n\n const finalOutDir = this.options.outdir!;\n const tempOutDir = createTempOutputDir(finalOutDir);\n\n // Set once the temp directory has been renamed onto `finalOutDir`. Its\n // presence is what tells the catch below whether a failure has a\n // promotion to undo or only a temp directory to discard.\n let staged: StagedDist | undefined;\n\n try {\n // Step 2: Generate combined files\n await this.generateCombinedFiles();\n\n // Step 3: Generate entry point\n await this.generateEntryPoint();\n\n // Step 4: Refuse to bundle code the app could not resolve at runtime\n await this.assertGeneratedImports();\n\n // Step 4.5: Drain the connectors' `generate` contributions\n await this.captureNamedApiRoutesForWeb();\n const contributed = await this.runGenerateContributions();\n\n // Step 4.6: Re-assert over what the contributors just wrote.\n //\n // Step 4 only saw core's own generated files; a contributor writes its\n // code (a pages barrel, say) AFTER that assertion, so an undeclared bare\n // specifier in it reaches the bundle unchecked. Under\n // `packages: \"external\"` that specifier survives verbatim into the\n // artifact and dies as ERR_MODULE_NOT_FOUND at runtime — the same failure\n // step 4 exists to prevent. Skipped when nothing contributed: re-globbing\n // and re-reading the production dir is pure cost in the common case.\n if (contributed) {\n await this.assertGeneratedImports();\n }\n\n // Step 5: Bundle with esbuild into the temp directory. The ONLY\n // operation handed that path — it is a write target, not config.\n await this.bundle(tempOutDir);\n\n // Step 5.5: Promote the bundle into `outdir`, keeping the previous\n // build parked aside. `outdir` now holds exactly this build, so the\n // steps below write into — and record — the real destination.\n staged = await stageDistAsync(tempOutDir, finalOutDir);\n\n // Step 5.6: Drain the connectors' `emit` contributions — after the\n // bundle is in place (so what they write survives promotion and the\n // paths they bake in resolve), and BEFORE step 6 deletes the\n // production directory they may still read.\n await runEmitContributions(this.connectors, this.buildContext());\n\n // Step 5.7: Mark `dist` as a genuine, complete build — the one thing\n // `warlock start` trusts. Written LAST on purpose: every earlier step\n // can still fail, and until this file exists nothing will boot what\n // they left behind.\n await writeDistBuildManifestAsync(finalOutDir);\n\n // Step 5.8: Commit — drop the parked previous build. Cannot throw.\n await commitDistAsync(staged);\n } catch (error) {\n if (staged) {\n // The promotion already happened; put the previous build back and\n // take this half-finished one out of `outdir`.\n await rollbackDistAsync(staged);\n } else {\n // Nothing this build produced ever reached `outdir` — discard the\n // temp directory and leave `outdir` exactly as it was.\n await removeDirectoryAsync(tempOutDir).catch(() => undefined);\n }\n\n throw error;\n }\n\n // Step 6: Remove production folder\n await removeDirectoryAsync(this.productionDir);\n\n console.log(colors.green(\"Build complete!\"));\n console.log(`Start production server by running ${colors.cyan(\"warlock start\")}`);\n }\n\n /**\n * Initialize options from warlock.config.ts\n */\n private async initializeOptions(): Promise<void> {\n this.options = resolveBuildConfig();\n // Same config object `resolveBuildConfig` just read — `warlock build`\n // preloads warlock.config.ts, so no additional load happens here.\n const connectors = warlockConfigManager.get(\"connectors\") ?? [];\n\n // Checked here, where the array is first read, so nothing downstream has\n // drained anything yet: the `generate` and `emit` passes run per ENTRY, so\n // a name listed twice would write its files and merge its esbuild options\n // twice into an artifact the runtime then boots that name only once from.\n // A build that half-applied a connector and reported success is worse than\n // one that never started.\n assertUniqueConnectorNames([...connectors]);\n\n // And here rather than only at boot, for the same reason: a name a built-in\n // already owns is skipped by the runtime, so an artifact built from it\n // carries the custom connector's generated files and esbuild patches while\n // the server boots the built-in instead. Refusing it at boot alone would\n // mean the build had already emitted that artifact — the failure has to\n // land on the developer running `warlock build`, not on whoever starts the\n // server. Same assertion the registration half calls, over the same names.\n assertNoReservedConnectorNames([...connectors]);\n\n this.connectors = connectors;\n\n // Ensure production directory exists\n await ensureDirectoryAsync(this.productionDir);\n }\n\n /**\n * The context handed to every build contribution.\n */\n private buildContext(): ConnectorBuildContext {\n return {\n productionDir: this.productionDir,\n appRoot: rootPath(),\n options: this.options,\n namedApiRoutes: this.namedApiRoutes,\n };\n }\n\n /**\n * Web route declarations need application API registration, which cannot be\n * inferred from generated files. Capture it once in a disposable child before\n * contributors write build artifacts; no connector lifecycle runs there.\n */\n private async captureNamedApiRoutesForWeb(): Promise<void> {\n if (!this.connectors.some((connector) => connector.name === \"web\")) {\n await clearOwnedRouteTypes(rootPath());\n return;\n }\n\n this.namedApiRoutes = (\n await collectRouteRegistrationSnapshot({\n cwd: rootPath(),\n timeoutMs: this.options.routeRegistrationTimeoutMs,\n })\n ).routes;\n }\n\n /**\n * Drain the `generate` hooks and fold what they returned back into the\n * build.\n *\n * The entry point is REGENERATED here rather than generated later. The\n * contribution slot is fixed — after `assertGeneratedImports` (so nothing\n * bundles that the app could not resolve) and before `bundle` — while\n * `generateEntryPoint` must stay at step 3, because `app.ts` is itself\n * generated code the assertion has to see; moving it past the assertion\n * would silently drop the entry from that check. Rewriting one small file\n * is cheaper than losing either guarantee, and the write is pure\n * (`generatedFiles` + these imports), so doing it twice is not a\n * correctness risk.\n *\n * @returns whether any connector ran a `generate` hook — the caller uses it\n * to decide if the import assertion is worth a second pass. Keyed on the\n * hook EXISTING, not on what it returned: a hook that returns nothing may\n * still have written files into `productionDir`, and those are exactly the\n * files the second pass is there to read.\n */\n private async runGenerateContributions(): Promise<boolean> {\n const contributed = this.connectors.some((connector) => Boolean(connector.build?.generate));\n\n const { entryImports, esbuild } = await runGenerateContributions(\n this.connectors,\n this.buildContext(),\n );\n\n this.contributedEsbuild = esbuild;\n\n if (entryImports.length > 0) {\n await this.generateEntryPoint(entryImports);\n }\n\n return contributed;\n }\n\n /**\n * Track which special files were generated\n */\n private generatedFiles = {\n locales: false,\n events: false,\n main: false,\n routes: false,\n workers: false,\n };\n\n /**\n * Generate all combined files\n */\n private async generateCombinedFiles(): Promise<void> {\n console.log(colors.yellow(\" Generating production files...\"));\n\n // Generate bootstrap.ts file\n await this.generateBootstrap();\n\n // Generate config loader\n await this.generateConfigLoader();\n\n // Generate special files and track which ones have content\n const [locales, events, main, routes, workers] = await Promise.all([\n this.generateLocales(),\n this.generateEvents(),\n this.generateMain(),\n this.generateRoutes(),\n this.generateWorkers(),\n ]);\n\n this.generatedFiles = { locales, events, main, routes, workers };\n }\n\n /**\n * Generate bootstrap.ts - ensures bootstrap() runs first and sets production environment\n */\n private async generateBootstrap(): Promise<void> {\n // ESM hoists imports, so the app bootstrap must be the first import to run first\n const appBootstrapImport = (await fileExistsAsync(appPath(\"bootstrap.ts\")))\n ? \"import './../../src/app/bootstrap';\\n\"\n : \"\";\n\n const content = `${appBootstrapImport}import { bootstrap, Application } from \"@warlock.js/core\";\n\n// Production runtime; NODE_ENV is only defaulted so an explicit value (e.g. staging) wins\nApplication.setRuntimeStrategy(\"production\");\nif (!process.env.NODE_ENV) {\n Application.setEnvironment(\"production\");\n}\n\n// Bootstrap the application\nbootstrap();\n`;\n\n await putFileAsync(path.join(this.productionDir, \"bootstrap.ts\"), content);\n }\n\n /**\n * Fail the build when generated code imports a package the app does not\n * declare.\n *\n * The bundler is configured `packages: \"external\"`, so every bare specifier\n * written above survives verbatim into an artifact that resolves against the\n * **consuming app's** node_modules. A framework-internal dependency imported\n * there resolves by accident under npm/yarn hoisting and dies under pnpm —\n * which is how a production app shipped that could not boot. Rewriting the\n * offending import fixes today's bundle; this check is what stops the next\n * change to the generator from quietly reintroducing it.\n */\n private async assertGeneratedImports(): Promise<void> {\n const generatedPaths = await glob(\"**/*.{ts,tsx,js,mjs}\", {\n cwd: this.productionDir,\n absolute: false,\n });\n\n const [files, appPackage] = await Promise.all([\n Promise.all(\n generatedPaths.map(async (file) => ({\n file,\n content: await getFileAsync(path.join(this.productionDir, file)),\n })),\n ),\n getJsonFileAsync<{ dependencies?: Record<string, string> }>(rootPath(\"package.json\")),\n ]);\n\n assertGeneratedImportsAreDeclared(files, Object.keys(appPackage.dependencies ?? {}));\n }\n\n /**\n * Glob `src/app` and keep the files the shared dev-server predicate accepts,\n * so production discovers exactly what the dev collector does.\n * Returns relative paths from .warlock/production/ to src/app/\n */\n private async globModule(matches: (relativePath: string) => boolean): Promise<string[]> {\n const files = await glob(\"**/*.{ts,tsx,json}\", {\n cwd: appPath(),\n absolute: false,\n });\n\n // e.g., \"users/main.ts\" -> \"../../src/app/users/main\"\n return files\n .filter((file) => matches(\"src/app/\" + file))\n .sort()\n .map((file) => \"../../src/app/\" + file.replace(/\\.(ts|tsx)$/, \"\"));\n }\n\n /**\n * Generate config-loader.ts\n */\n private async generateConfigLoader(): Promise<void> {\n const configDirectory = path.join(process.cwd(), \"src/config\");\n\n const files = await glob(\"**/*.{ts,tsx}\", {\n cwd: configDirectory,\n absolute: false,\n });\n\n // Same key rule as the dev config loader: the raw path, never camel-cased\n const configNames = files\n .filter((f) => isConfigFile(\"src/config/\" + f))\n .map((f) => ({\n path: f.replace(/\\.(ts|tsx)$/, \"\"),\n key: configKeyFromPath(\"src/config/\" + f),\n }))\n .filter((entry): entry is { path: string; key: string } => entry.key !== undefined)\n .sort((a, b) => a.path.localeCompare(b.path));\n\n // Only `@warlock.js/core` — the one package the app itself declares. See\n // `assertGeneratedImportsAreDeclared`: `@mongez/config` is core's own\n // dependency, so a bare import of it resolved by luck under npm/yarn\n // hoisting and died under pnpm's strict layout.\n const imports: string[] = [\n 'import { setConfig, configSpecialHandlers } from \"@warlock.js/core\";',\n ];\n const configImports: string[] = [];\n const configSetCalls: string[] = [];\n const executors: string[] = [];\n\n configNames.forEach(({ path: configPath, key }, index) => {\n // Index-based identifier: keys like \"rate-limit\" or \"mail/smtp\" are not valid names\n const varName = `config${index}`;\n configImports.push(`import ${varName} from \"../../src/config/${configPath}\";`);\n configSetCalls.push(`setConfig(${JSON.stringify(key)}, ${varName});`);\n executors.push(`await configSpecialHandlers.execute(${JSON.stringify(key)}, ${varName});`);\n });\n\n // ESM hoists imports, so prestart must be the first import to run first\n const prestartImports = (await fileExistsAsync(appPath(\"prestart.ts\")))\n ? [\"import './../../src/app/prestart';\"]\n : [];\n\n const content = [\n ...prestartImports,\n ...imports,\n \"\",\n \"// Config imports\",\n ...configImports,\n \"\",\n \"// Register configs\",\n ...configSetCalls,\n \"\",\n \"// Special handlers\",\n ...executors,\n \"\",\n ].join(\"\\n\");\n\n await putFileAsync(path.join(this.productionDir, \"config-loader.ts\"), content);\n }\n\n /**\n * Generate locales.ts (only if there are locale files)\n * @returns true if file was generated with content\n */\n private async generateLocales(): Promise<boolean> {\n const files = await this.globModule(isLocaleFile);\n if (files.length === 0) return false;\n const content = files\n .map((file, index) => {\n if (!file.endsWith(\".json\")) return `import \"${file}\";`;\n const moduleFolder = file.split(\"/\").at(-3)!;\n return [\n `import dictionary${index} from \"${file}\";`,\n 'import { registerLocaleDictionary } from \"@warlock.js/core\";',\n `registerLocaleDictionary({ sourceFile: ${JSON.stringify(file)}, source: JSON.stringify(dictionary${index}), defaultNamespace: ${JSON.stringify(moduleFolder)} });`,\n ].join(\"\\n\");\n })\n .join(\"\\n\");\n await putFileAsync(path.join(this.productionDir, \"locales.ts\"), content + \"\\n\");\n return true;\n }\n\n /**\n * Generate events.ts (only if there are event files)\n * @returns true if file was generated with content\n */\n private async generateEvents(): Promise<boolean> {\n const files = await this.globModule(isEventFile);\n if (files.length === 0) return false;\n await this.generateImportsFile(files, \"events.ts\");\n return true;\n }\n\n /**\n * Generate main.ts (only if there are main files)\n * @returns true if file was generated with content\n */\n private async generateMain(): Promise<boolean> {\n const files = await this.globModule(isMainFile);\n if (files.length === 0) return false;\n await this.generateImportsFile(files, \"main.ts\");\n return true;\n }\n\n /**\n * Generate routes.ts (only if there are route files)\n * @returns true if file was generated with content\n */\n private async generateRoutes(): Promise<boolean> {\n const files = await this.globModule(isRouteFile);\n if (files.length === 0) return false;\n await this.generateImportsFile(files, \"routes.ts\");\n return true;\n }\n\n /**\n * Generate workers.ts (only if there are worker files)\n * @returns true if file was generated with content\n */\n private async generateWorkers(): Promise<boolean> {\n const files = await this.globModule(isWorkerFile);\n if (files.length === 0) return false;\n await this.generateImportsFile(files, \"workers.ts\");\n return true;\n }\n\n /**\n * Generate a file with imports from all given files\n */\n private async generateImportsFile(importPaths: string[], outputFile: string): Promise<void> {\n const imports = importPaths.map((importPath) => `import \"${importPath}\";`);\n const content = imports.join(\"\\n\") + \"\\n\";\n await putFileAsync(path.join(this.productionDir, outputFile), content);\n }\n\n /**\n * Generate the main entry point (app.ts)\n *\n * @param contributedImports lines from connector `generate` hooks, appended\n * to section 4 after `./routes`\n */\n private async generateEntryPoint(contributedImports: string[] = []): Promise<void> {\n console.log(colors.yellow(\" Generating entry point...\"));\n\n // The names this build resolved, baked in as a literal. The entry imports\n // the config source, and that source is re-evaluated at startup — an\n // env-conditional `connectors` array can hand the boot a different list\n // than the one drained here. A literal is the only part of the array that\n // survives into the artifact unchanged, so it is what the boot compares\n // against.\n const expectedNames = this.connectors\n .map((connector) => JSON.stringify(connector.name))\n .join(\", \");\n\n // Build imports based on which files were generated\n const imports: string[] = [\n \"// 1. Bootstrap (loads .env, initializes framework)\",\n 'import \"./bootstrap\";',\n \"\",\n \"// 2. Load configs\",\n 'import \"./config-loader\";',\n \"\",\n // Registration has to sit between the config being available and the\n // first phase starting: the connectors listed in `connectors` are the\n // same ones this build drained contributions from, so the bundle boots\n // exactly what it was built for. Register any later and an early-phase\n // connector would miss its own start.\n \"// 2.5 Register connectors declared in warlock.config (the same array this\",\n \"// build read its contributions from, so built-for and boots-with match).\",\n \"// The config is imported STATICALLY so esbuild bakes it into the bundle\",\n \"// and the array is handed over explicitly — an artifact has no\",\n \"// warlock.config.ts beside it to read at runtime, and a registration\",\n \"// that quietly found nothing to register is the exact drift this\",\n \"// section exists to prevent.\",\n \"// `expectedNames` is the list this build resolved, in order — boot\",\n \"// refuses to start when the config hands over a different set or order.\",\n 'import { registerConfiguredConnectors } from \"@warlock.js/core\";',\n `import warlockConfig from \"${APP_ROOT_FROM_PRODUCTION_DIR}warlock.config\";`,\n `registerConfiguredConnectors(warlockConfig.connectors ?? [], { expectedNames: [${expectedNames}] });`,\n \"\",\n \"// 2.6 Fail fast on a busy port. `http` is a LATE-phase connector, so its\",\n \"// own preflight is not reached until the database and cache have\",\n \"// connected and every app module has been imported — seconds of work\",\n \"// thrown away before anyone learns the port was taken. This probe is\",\n \"// a bind-and-release on a socket that is never served, and it reports\",\n \"// on stderr because no log channel is configured this early.\",\n 'import { Application, connectorsManager, ConnectorLifecyclePhase, preflightConfiguredHttpPort } from \"@warlock.js/core\";',\n 'if (Application.hasRole(\"api\") || Application.hasRole(\"web\")) {',\n \" await preflightConfiguredHttpPort();\",\n \"}\",\n \"\",\n \"// 3. Start early-phase connectors (database, cache, logger, ...)\",\n \"// so data sources, cache, etc. are ready before app code runs\",\n \"await connectorsManager.startPhase(ConnectorLifecyclePhase.Early);\",\n ];\n\n // App code uses dynamic `await import(...)` so each module's side\n // effects fire at THIS point in execution. Static imports would be\n // hoisted to module-instantiation time (before the early-phase await\n // resolves), which is exactly the bug this split is meant to fix.\n //\n // The guarantee comes from the imports being DYNAMIC — esbuild wraps a\n // dynamically-imported module in its `__esm(() => {…})` helper and runs\n // it at the await, not at instantiation. It does NOT come from\n // `splitting: true`, which only decides one-file-vs-chunks. This\n // previously said splitting was required; it is not, and `singleBundle`\n // (splitting: false) preserves the ordering.\n imports.push(\"\", \"// 4. Load app code (events, locales, main, routes)\");\n\n if (this.generatedFiles.events) {\n imports.push('await import(\"./events\");');\n }\n if (this.generatedFiles.locales) {\n imports.push('await import(\"./locales\");');\n }\n if (this.generatedFiles.main) {\n imports.push('await import(\"./main\");');\n }\n if (this.generatedFiles.routes) {\n imports.push('if (Application.hasRole(\"api\")) {', ' await import(\"./routes\");', \"}\");\n }\n if (this.generatedFiles.workers) {\n imports.push('if (Application.hasRole(\"worker\")) {', ' await import(\"./workers\");', \"}\");\n }\n\n // Contributor imports come AFTER `./routes`, never before: a connector\n // that registers pages needs the routes app code already collected —\n // the same ordering dev uses (routes first, then the connector installs\n // on top of them). Emitted verbatim; the contributor writes the whole\n // statement (e.g. `await import(\"./pages\");`).\n imports.push(...contributedImports);\n\n // A rejecting validator (Application.onValidateBoot) must abort boot\n // before late-phase connectors bind a port.\n imports.push(\n \"\",\n \"// 5. Run startup validators registered via Application.onValidateBoot(...)\",\n \"await Application.runStartupValidators();\",\n );\n\n // Start late-phase connectors after app code registers routes/listeners\n imports.push(\n \"\",\n \"// 6. Start late-phase connectors (http, socket) — routes and\",\n \"// listeners registered by app code are now ready to bind\",\n \"await connectorsManager.startPhase(ConnectorLifecyclePhase.Late);\",\n \"\",\n \"// 7. Signal a complete boot so `Application.onceBooted(...)` listeners fire\",\n \"Application.markBooted({ environment: Application.environment, runtimeStrategy: Application.runtimeStrategy });\",\n \"connectorsManager.shutdownOnProcessKill();\",\n );\n\n const content = imports.join(\"\\n\") + \"\\n\";\n await putFileAsync(path.join(this.productionDir, \"app.ts\"), content);\n }\n\n /**\n * Bundle with esbuild\n *\n * @param writeOutDir the directory esbuild writes into — the build's\n * private temp directory, NOT `options.outdir`. Taken as a parameter\n * rather than read off `this.options` because the two are different paths\n * with different meanings: `options.outdir` is the final destination every\n * consumer bakes into the artifact, and this is only where bytes land\n * before promotion moves them there.\n */\n private async bundle(writeOutDir: string): Promise<void> {\n console.log(colors.magenta(\" Bundling with esbuild...\"));\n\n const entryPoint = path.join(this.productionDir, \"app.ts\");\n const outFileName = this.options.outFile!;\n // Strip extension so entryNames produces \"<base>.js\" via esbuild\n const entryName = path.basename(outFileName, path.extname(outFileName));\n\n // `singleBundle` and `esmShim` are ours, not esbuild's — it throws on\n // unknown keys, and the user options are spread into its call verbatim.\n const singleBundle = this.options.singleBundle === true;\n const esmShim = this.options.esmShim !== false;\n // Read before deleting: the merged banner is applied AFTER the user\n // spread, so a user banner must not be lost to it or clobber the shim.\n const userBanner = this.options.banner;\n\n // `outFile` and `entryPath` are REQUIRED on ResolvedBuildConfig on purpose:\n // resolve-build-config.ts documents that widening them pushed a lie downstream\n // into start-production.command.ts, which then could not trust its own config.\n // This is the one place they must be absent - the object is spread into esbuild's\n // call verbatim and esbuild throws on unknown keys.\n //\n // Stripped off a LOCAL COPY of `this.options`, never off `this.options`\n // itself: `buildContext()` hands `this.options` to every `generate`/`emit`\n // contribution hook, including the `emit` pass that runs AFTER this method\n // returns (`build()` step 5.6). Deleting these keys from the shared object\n // used to leave those hooks reading `undefined` for `outFile`, `entryPath`,\n // `singleBundle`, `esmShim` and `banner` even though `ConnectorBuildContext`\n // types them as present. A shallow copy is enough — every field this method\n // reads off it is either scalar or already re-merged below (`define`,\n // `external`, `loader`, `banner`), so nothing here needs a deep clone.\n const esbuildOptions: Partial<ResolvedBuildConfig> = { ...this.options };\n\n delete esbuildOptions.outFile;\n delete esbuildOptions.entryPath;\n delete esbuildOptions.singleBundle;\n delete esbuildOptions.esmShim;\n delete esbuildOptions.banner;\n delete esbuildOptions.routeRegistrationTimeoutMs;\n\n await ensureDirectoryAsync(writeOutDir);\n\n const alias = this.buildAliasMapFromTsconfig();\n\n // Whether this build decides externality per import EDGE\n // (`bundle-framework-dependencies.ts`, which explains the rule at\n // length) or keeps the blunt `packages: \"external\"`.\n //\n // Not in `singleBundle` mode: that bundles everything by definition, and\n // a plugin that can only ever ADD an external would silently narrow it.\n // Not when the user set `packages` themselves: their value has always\n // won over the default below, and it must keep winning — the plugin is\n // the default's implementation, not a new policy layered on top.\n const perEdgeExternals = !singleBundle && (esbuildOptions as any).packages === undefined;\n\n // The user can override `format`, so gate the shim on the EFFECTIVE\n // format rather than on the default below. A CJS build already has\n // `require` and friends; injecting them there would be a redefinition.\n const isEsm = (esbuildOptions.format ?? \"esm\") === \"esm\";\n const banner = mergeBanner(userBanner, esmShim && isEsm ? ESM_INTEROP_SHIM : undefined);\n\n // Contributor patch, split into the part that can ride the spread order\n // and the three keys that cannot. `jsx` and `jsxImportSource` are placed\n // BEFORE the user spread below, which gives the ruled precedence for\n // free: builder defaults < contributor < user config.\n //\n // `define`, `external` and `loader` are pulled out because a spread\n // REPLACES them wholesale — the same trap `banner` documents. Two\n // contributors' env defines, a contributor's optional peers plus the\n // user's, or a contributor's `.svg` loader alongside the user's `.png`,\n // must both survive, so they are merged by key/by set and re-applied\n // after the spread with the user still winning per key.\n const {\n define: contributedDefine,\n external: contributedExternal,\n loader: contributedLoader,\n plugins: contributedPlugins,\n ...contributedOptions\n } = this.contributedEsbuild;\n\n const userDefine: Record<string, string> | undefined = esbuildOptions.define;\n const userExternal: string[] | undefined = esbuildOptions.external;\n const userLoader: ConnectorEsbuildPatch[\"loader\"] = esbuildOptions.loader;\n\n const define =\n contributedDefine || userDefine ? { ...contributedDefine, ...userDefine } : undefined;\n\n const loader =\n contributedLoader || userLoader ? { ...contributedLoader, ...userLoader } : undefined;\n\n const external =\n contributedExternal || userExternal\n ? dedupe([...(contributedExternal ?? []), ...(userExternal ?? [])])\n : undefined;\n\n if (singleBundle) {\n console.log(\n colors.magenta(\n \" Single-bundle mode — one JS file\" +\n (esmShim && isEsm ? \" with the ESM interop shim\" : \"\") +\n \". Native .node addons are still emitted alongside it.\",\n ),\n );\n }\n\n try {\n await esbuild.build({\n platform: \"node\",\n entryPoints: [entryPoint],\n bundle: true,\n // Both are DEFAULTS the user can override — they sit before the\n // `...esbuildOptions` spread deliberately. `singleBundle` moves them,\n // an explicit `splitting`/`packages` in warlock.config.ts beats both.\n //\n // Phase ordering does not depend on `splitting`: it comes from the\n // generated app.ts using dynamic `await import(...)` (see\n // generateAppEntry above), which esbuild defers to the call site in\n // either mode. Splitting only decides one file vs chunks.\n splitting: !singleBundle,\n // `\"bundle\"` under `perEdgeExternals` is not \"bundle everything\":\n // the plugin below returns `external: true` for every bare specifier\n // this build must not bundle, which is all of them bar the framework's\n // own declared dependencies. Saying `\"external\"` here instead would\n // externalise them before the plugin could rule.\n packages: singleBundle || perEdgeExternals ? \"bundle\" : \"external\",\n minify: esbuildOptions.minify,\n sourcemap: esbuildOptions.sourcemap === true ? \"linked\" : esbuildOptions.sourcemap,\n format: \"esm\",\n // Targeting a concrete Node version (not \"esnext\") so esbuild\n // transpiles TC39 stage 3 decorators into helpers — Node does not\n // implement them natively yet.\n target: [\"node22\"],\n entryNames: entryName,\n alias,\n plugins: [\n nativeNodeModulesPlugin,\n // BEFORE the framework-dependency plugin, and the order is\n // load-bearing: the first `onResolve` callback to answer wins, and\n // `app/users/...` is a bare specifier the other one would rule\n // external.\n tsconfigPathAliases(this.tsconfigPathAliasConfig()),\n ...(perEdgeExternals\n ? [bundleFrameworkDependencies({ appRoot: rootPath(), aliasKeys: Object.keys(alias) })]\n : []),\n // Contributor plugins run last: they load their own file types and\n // must not shadow the resolvers above.\n ...(contributedPlugins ?? []),\n ],\n // Between the defaults and the user spread — the ruled precedence.\n ...contributedOptions,\n ...(esbuildOptions as any),\n // AFTER the spread, and NOT overridable: `esbuildOptions.outdir` rides\n // that spread carrying the FINAL destination, which is exactly where\n // this build must not write yet. The final path is the user's setting\n // and stays authoritative for everyone reading the config — it is only\n // this one esbuild call that is redirected, and only until promotion\n // moves the result onto that very path.\n outdir: writeOutDir,\n // AFTER the spread for the same reason `banner` is: a spread replaces\n // these objects instead of merging them, so the merged values are\n // re-applied here. The user still wins — they were merged in last.\n ...(define ? { define } : {}),\n ...(external ? { external } : {}),\n ...(loader ? { loader } : {}),\n // AFTER the spread, and intentionally so: `banner` is an object, and\n // both the config merge and this spread REPLACE it wholesale rather\n // than merging. Left as a default above, any user banner would delete\n // the shim; left to the spread, the shim would delete theirs. The\n // merge is the only form that keeps both.\n ...(banner ? { banner } : {}),\n });\n } catch (e) {\n console.log(e);\n throw e;\n }\n }\n\n /**\n * The WILDCARD half of the same tsconfig `paths` map that\n * {@link ProductionBuilder.buildAliasMapFromTsconfig} reads the exact half\n * of. `tsconfig-path-aliases.ts` explains why the two halves need different\n * mechanisms — in short, esbuild's `alias` option cannot express a wildcard,\n * so the entries it skips have to be resolved by a plugin instead of being\n * left to no one.\n */\n private tsconfigPathAliasConfig(): { baseUrl: string; paths: Record<string, string[]> } {\n tsconfigManager.init();\n\n return {\n baseUrl: path.resolve(process.cwd(), tsconfigManager.baseUrl),\n paths: tsconfigManager.aliases as Record<string, string[]>,\n };\n }\n\n /**\n * Build an alias map from tsconfig `paths` so esbuild resolves local\n * source aliases (e.g. `@warlock.js/cascade`) to their on-disk source\n * folders during bundling. Without this, `packages: \"external\"` would\n * leave those bare specifiers as raw imports and Node would fail to\n * resolve them at runtime (they aren't installed in node_modules).\n *\n * Only exact (non-wildcard) aliases are included — esbuild's `alias`\n * option doesn't support glob-style mappings. The wildcard half is not\n * dropped, it is handled elsewhere: see\n * {@link ProductionBuilder.tsconfigPathAliasConfig}.\n */\n private buildAliasMapFromTsconfig(): Record<string, string> {\n tsconfigManager.init();\n\n const alias: Record<string, string> = {};\n const baseUrl = path.resolve(process.cwd(), tsconfigManager.baseUrl);\n\n for (const [from, to] of Object.entries(tsconfigManager.aliases)) {\n if (from.endsWith(\"/*\") || !Array.isArray(to) || to.length === 0) {\n continue;\n }\n\n const target = to[0];\n\n if (target === undefined) {\n continue;\n }\n\n alias[from] = path.resolve(baseUrl, target);\n }\n\n return alias;\n }\n}\n"],"mappings":"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"}
@@ -3,7 +3,7 @@ import { displayMissingReadinessNotice, displayProductionReadyBanner, displayPro
3
3
  import { colors } from "@mongez/copper";
4
4
  import { spawn } from "child_process";
5
5
 
6
- //#region ../core/src/production/production-supervisor.ts
6
+ //#region ../../packages/core/src/production/production-supervisor.ts
7
7
  /**
8
8
  * How long a still-running child may stay silent before we say so.
9
9
  *
@@ -1 +1 @@
1
- {"version":3,"file":"production-supervisor.mjs","names":[],"sources":["../../../../../../../core/src/production/production-supervisor.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { spawn } from \"child_process\";\nimport { BOOT_SIGNAL_ENV_KEY, isBootSignal } from \"../application/boot-signal\";\nimport {\n displayMissingReadinessNotice,\n displayProductionReadyBanner,\n displayProductionStartFailure,\n} from \"../cli/cli-commands.utils\";\n\n/**\n * How long a still-running child may stay silent before we say so.\n *\n * Only reached by a bundle built before readiness reporting existed; a current\n * bundle signals as soon as its late-phase connectors are up.\n */\nexport const DEFAULT_READINESS_NOTICE_DELAY_MS = 10_000;\n\nexport type ProductionSupervisorOptions = {\n /** Arguments handed to the node binary, entry file included. */\n nodeArgs: string[];\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n readinessNoticeDelayMs?: number;\n};\n\nexport type ProductionSupervisorResult = {\n /** What the CLI should exit with — never 0 for a boot that never completed. */\n exitCode: number;\n /** Whether the child ever reported a finished boot. */\n ready: boolean;\n};\n\n/**\n * Run the production bundle in a child process and report honestly on it.\n *\n * The supervisor exists because a parent that only forwards `stdio` cannot\n * see whether its child ever booted — it only sees the process exit. It\n * therefore opens an IPC channel and treats the child's `warlock:ready`\n * signal, emitted by `Application.markBooted`, as the single source of truth\n * for \"started\":\n *\n * 1. The success banner is printed only on that signal.\n * 2. A child that dies before signalling is reported as a failed start and\n * forced to a non-zero exit, even if it exited 0.\n * 3. A child still running without having signalled draws a note on stderr —\n * never stdout, which would be the false-green this whole channel prevents.\n * 4. Whether the child ever wrote to stdout/stderr before dying is tracked\n * (`sawChildOutput`) so the failure summary only claims \"the cause is\n * printed above\" when that is actually true — see the stdio comment\n * below.\n *\n * Resolves rather than exiting so the outcome stays assertable in a test; the\n * `start` command turns the result into the process exit code.\n */\nexport function superviseProductionProcess({\n nodeArgs,\n cwd = process.cwd(),\n env = process.env,\n readinessNoticeDelayMs = DEFAULT_READINESS_NOTICE_DELAY_MS,\n}: ProductionSupervisorOptions): Promise<ProductionSupervisorResult> {\n return new Promise<ProductionSupervisorResult>((resolve) => {\n // On Windows, we need to be careful with signals - the console sends Ctrl+C\n // to all processes in the group, so we just need to not interfere.\n // `process.execPath`, not \"node\": the bare name needs `node` on PATH, which\n // a systemd unit, a cron job, or a slim container may not provide — and a\n // PATH `node` that *is* present can be a different version than the one\n // running this CLI. execPath is the binary already executing us.\n //\n // The fourth stdio slot opens the IPC channel the child reports readiness\n // on. Without it `process.send` is undefined in the child and we would be\n // back to guessing whether the boot succeeded.\n //\n // stdout/stderr are piped rather than inherited so this supervisor can\n // tell whether the child ever wrote anything, not just forward it blind.\n // `displayProductionStartFailure` used to claim \"the cause is printed\n // above\" on every failed boot, unconditionally — true when the child's\n // logger got far enough to print, false (and misleading) when it died\n // before its log channels were configured. Piping costs nothing here:\n // both streams are re-forwarded to this process's own stdout/stderr as\n // each chunk arrives, so a human watching the terminal sees the exact\n // same live output \"inherit\" gave them.\n const child = spawn(process.execPath, nodeArgs, {\n stdio: [\"inherit\", \"pipe\", \"pipe\", \"ipc\"],\n cwd,\n // The flag identifies us as a parent that speaks the boot protocol. The\n // child stays silent without it, so an app running under pm2 or any other\n // supervisor never writes to a channel that belongs to someone else.\n env: { ...env, [BOOT_SIGNAL_ENV_KEY]: \"1\" },\n // Important: keep child in same process group for proper signal handling\n detached: false,\n });\n\n const startedAt = Date.now();\n let isReady = false;\n let isShuttingDown = false;\n let isSettled = false;\n\n // Whether the child wrote anything to either stream — the only honest\n // basis for telling a developer \"the cause is printed above\". Set from\n // the first chunk on either stream; a child that dies before its first\n // write (a crash mid-import, a logger with no console channel) leaves\n // this `false`, which is exactly the case the summary must admit rather\n // than paper over.\n let sawChildOutput = false;\n\n const forwardChildOutput = (target: NodeJS.WritableStream) => (chunk: Buffer) => {\n sawChildOutput = true;\n target.write(chunk);\n };\n\n child.stdout?.on(\"data\", forwardChildOutput(process.stdout));\n child.stderr?.on(\"data\", forwardChildOutput(process.stderr));\n\n const readinessNoticeTimer = setTimeout(() => {\n if (isReady) {\n return;\n }\n\n displayMissingReadinessNotice(Date.now() - startedAt);\n }, readinessNoticeDelayMs);\n\n // A diagnostic timer must never be the reason the CLI stays alive.\n readinessNoticeTimer.unref?.();\n\n const settle = (result: ProductionSupervisorResult) => {\n if (isSettled) {\n return;\n }\n\n isSettled = true;\n clearTimeout(readinessNoticeTimer);\n process.off(\"SIGTERM\", onSigterm);\n process.off(\"SIGINT\", onSigint);\n process.off(\"SIGHUP\", onSighup);\n\n resolve(result);\n };\n\n child.on(\"message\", (message: unknown) => {\n if (isReady || !isBootSignal(message)) {\n return;\n }\n\n isReady = true;\n clearTimeout(readinessNoticeTimer);\n\n displayProductionReadyBanner({ bootDurationMs: message.bootDurationMs }).catch((error) => {\n // The server is up either way — a banner that fails to render must not\n // be reported as, or turn into, a boot failure.\n console.error(error);\n });\n\n // A worker-only process never binds a port, so `http-connector.ts`\n // never prints a URL for it — this is the one line that tells an\n // operator watching `warlock start` that the process is up on purpose,\n // not silently stuck.\n const roles = message.roles ?? [];\n\n if (roles.length > 0) {\n const servesHttp = roles.includes(\"api\") || roles.includes(\"web\");\n const summary = servesHttp\n ? `roles: ${roles.join(\", \")}`\n : `worker ready — roles: ${roles.join(\", \")}`;\n\n console.log(` ${colors.dim(summary)}`);\n }\n });\n\n // A spawn that never starts (missing binary, EACCES) emits `error` and no\n // `exit`, so without this the command would hang silently on a failure.\n // The error is printed BEFORE the summary that references it — the\n // summary says the cause is \"above\", so it has to already be there.\n child.on(\"error\", (error) => {\n console.error(error);\n displayProductionStartFailure(1, true);\n\n settle({ exitCode: 1, ready: false });\n });\n\n // Forward every stop signal so a supervisor that only signals this\n // process (docker kill -s INT, systemd KillSignal) still stops the child.\n // A repeated signal means the graceful shutdown is stuck: force-kill.\n const forward = (signal: NodeJS.Signals) => () => {\n if (isShuttingDown) {\n child.kill(\"SIGKILL\");\n return;\n }\n\n isShuttingDown = true;\n child.kill(signal);\n };\n\n const onSigterm = forward(\"SIGTERM\");\n const onSighup = forward(\"SIGHUP\");\n\n // On Windows Ctrl+C reaches both processes, so the child already has it —\n // we only record that this exit was asked for (kill() there is a hard kill).\n const onSigint =\n process.platform === \"win32\"\n ? () => {\n isShuttingDown = true;\n }\n : forward(\"SIGINT\");\n\n process.on(\"SIGTERM\", onSigterm);\n process.on(\"SIGINT\", onSigint);\n process.on(\"SIGHUP\", onSighup);\n\n // `close`, not `exit`: `exit` fires as soon as the OS process ends, which\n // can race ahead of the last chunks still in flight on the piped stdout/\n // stderr streams. `close` waits for those streams to end too, so\n // `sawChildOutput` reflects everything the child actually wrote instead\n // of whatever had been delivered by the time the process happened to die.\n child.on(\"close\", (code) => {\n // A child that dies before reporting readiness never served a request.\n // Exiting 0 there — which a clean `process.exit(0)` in failing app code\n // would do — reports a boot failure as a successful run, so the exit code\n // is forced non-zero to match what actually happened.\n //\n // An operator who interrupts the boot is not a failed boot, so a signalled\n // shutdown keeps the child's own exit code.\n if (!isReady && !isShuttingDown) {\n const exitCode = code === 0 || code === null ? 1 : code;\n\n displayProductionStartFailure(exitCode, sawChildOutput);\n\n return settle({ exitCode, ready: false });\n }\n\n settle({ exitCode: code ?? 0, ready: isReady });\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;AAeA,MAAa,oCAAoC;;;;;;;;;;;;;;;;;;;;;;;AAuCjD,SAAgB,2BAA2B,EACzC,UACA,MAAM,QAAQ,IAAI,GAClB,MAAM,QAAQ,KACd,yBAAyB,qCAC0C;CACnE,OAAO,IAAI,SAAqC,YAAY;EAqB1D,MAAM,QAAQ,MAAM,QAAQ,UAAU,UAAU;GAC9C,OAAO;IAAC;IAAW;IAAQ;IAAQ;GAAK;GACxC;GAIA,KAAK;IAAE,GAAG;KAAM,sBAAsB;GAAI;GAE1C,UAAU;EACZ,CAAC;EAED,MAAM,YAAY,KAAK,IAAI;EAC3B,IAAI,UAAU;EACd,IAAI,iBAAiB;EACrB,IAAI,YAAY;EAQhB,IAAI,iBAAiB;EAErB,MAAM,sBAAsB,YAAmC,UAAkB;GAC/E,iBAAiB;GACjB,OAAO,MAAM,KAAK;EACpB;EAEA,MAAM,QAAQ,GAAG,QAAQ,mBAAmB,QAAQ,MAAM,CAAC;EAC3D,MAAM,QAAQ,GAAG,QAAQ,mBAAmB,QAAQ,MAAM,CAAC;EAE3D,MAAM,uBAAuB,iBAAiB;GAC5C,IAAI,SACF;GAGF,8BAA8B,KAAK,IAAI,IAAI,SAAS;EACtD,GAAG,sBAAsB;EAGzB,qBAAqB,QAAQ;EAE7B,MAAM,UAAU,WAAuC;GACrD,IAAI,WACF;GAGF,YAAY;GACZ,aAAa,oBAAoB;GACjC,QAAQ,IAAI,WAAW,SAAS;GAChC,QAAQ,IAAI,UAAU,QAAQ;GAC9B,QAAQ,IAAI,UAAU,QAAQ;GAE9B,QAAQ,MAAM;EAChB;EAEA,MAAM,GAAG,YAAY,YAAqB;GACxC,IAAI,WAAW,CAAC,aAAa,OAAO,GAClC;GAGF,UAAU;GACV,aAAa,oBAAoB;GAEjC,6BAA6B,EAAE,gBAAgB,QAAQ,eAAe,CAAC,CAAC,CAAC,OAAO,UAAU;IAGxF,QAAQ,MAAM,KAAK;GACrB,CAAC;GAMD,MAAM,QAAQ,QAAQ,SAAS,CAAC;GAEhC,IAAI,MAAM,SAAS,GAAG;IAEpB,MAAM,UADa,MAAM,SAAS,KAAK,KAAK,MAAM,SAAS,KAAK,IAE5D,UAAU,MAAM,KAAK,IAAI,MACzB,yBAAyB,MAAM,KAAK,IAAI;IAE5C,QAAQ,IAAI,KAAK,OAAO,IAAI,OAAO,GAAG;GACxC;EACF,CAAC;EAMD,MAAM,GAAG,UAAU,UAAU;GAC3B,QAAQ,MAAM,KAAK;GACnB,8BAA8B,GAAG,IAAI;GAErC,OAAO;IAAE,UAAU;IAAG,OAAO;GAAM,CAAC;EACtC,CAAC;EAKD,MAAM,WAAW,iBAAiC;GAChD,IAAI,gBAAgB;IAClB,MAAM,KAAK,SAAS;IACpB;GACF;GAEA,iBAAiB;GACjB,MAAM,KAAK,MAAM;EACnB;EAEA,MAAM,YAAY,QAAQ,SAAS;EACnC,MAAM,WAAW,QAAQ,QAAQ;EAIjC,MAAM,WACJ,QAAQ,aAAa,gBACX;GACJ,iBAAiB;EACnB,IACA,QAAQ,QAAQ;EAEtB,QAAQ,GAAG,WAAW,SAAS;EAC/B,QAAQ,GAAG,UAAU,QAAQ;EAC7B,QAAQ,GAAG,UAAU,QAAQ;EAO7B,MAAM,GAAG,UAAU,SAAS;GAQ1B,IAAI,CAAC,WAAW,CAAC,gBAAgB;IAC/B,MAAM,WAAW,SAAS,KAAK,SAAS,OAAO,IAAI;IAEnD,8BAA8B,UAAU,cAAc;IAEtD,OAAO,OAAO;KAAE;KAAU,OAAO;IAAM,CAAC;GAC1C;GAEA,OAAO;IAAE,UAAU,QAAQ;IAAG,OAAO;GAAQ,CAAC;EAChD,CAAC;CACH,CAAC;AACH"}
1
+ {"version":3,"file":"production-supervisor.mjs","names":[],"sources":["../../../../../../../../packages/core/src/production/production-supervisor.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { spawn } from \"child_process\";\nimport { BOOT_SIGNAL_ENV_KEY, isBootSignal } from \"../application/boot-signal\";\nimport {\n displayMissingReadinessNotice,\n displayProductionReadyBanner,\n displayProductionStartFailure,\n} from \"../cli/cli-commands.utils\";\n\n/**\n * How long a still-running child may stay silent before we say so.\n *\n * Only reached by a bundle built before readiness reporting existed; a current\n * bundle signals as soon as its late-phase connectors are up.\n */\nexport const DEFAULT_READINESS_NOTICE_DELAY_MS = 10_000;\n\nexport type ProductionSupervisorOptions = {\n /** Arguments handed to the node binary, entry file included. */\n nodeArgs: string[];\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n readinessNoticeDelayMs?: number;\n};\n\nexport type ProductionSupervisorResult = {\n /** What the CLI should exit with — never 0 for a boot that never completed. */\n exitCode: number;\n /** Whether the child ever reported a finished boot. */\n ready: boolean;\n};\n\n/**\n * Run the production bundle in a child process and report honestly on it.\n *\n * The supervisor exists because a parent that only forwards `stdio` cannot\n * see whether its child ever booted — it only sees the process exit. It\n * therefore opens an IPC channel and treats the child's `warlock:ready`\n * signal, emitted by `Application.markBooted`, as the single source of truth\n * for \"started\":\n *\n * 1. The success banner is printed only on that signal.\n * 2. A child that dies before signalling is reported as a failed start and\n * forced to a non-zero exit, even if it exited 0.\n * 3. A child still running without having signalled draws a note on stderr —\n * never stdout, which would be the false-green this whole channel prevents.\n * 4. Whether the child ever wrote to stdout/stderr before dying is tracked\n * (`sawChildOutput`) so the failure summary only claims \"the cause is\n * printed above\" when that is actually true — see the stdio comment\n * below.\n *\n * Resolves rather than exiting so the outcome stays assertable in a test; the\n * `start` command turns the result into the process exit code.\n */\nexport function superviseProductionProcess({\n nodeArgs,\n cwd = process.cwd(),\n env = process.env,\n readinessNoticeDelayMs = DEFAULT_READINESS_NOTICE_DELAY_MS,\n}: ProductionSupervisorOptions): Promise<ProductionSupervisorResult> {\n return new Promise<ProductionSupervisorResult>((resolve) => {\n // On Windows, we need to be careful with signals - the console sends Ctrl+C\n // to all processes in the group, so we just need to not interfere.\n // `process.execPath`, not \"node\": the bare name needs `node` on PATH, which\n // a systemd unit, a cron job, or a slim container may not provide — and a\n // PATH `node` that *is* present can be a different version than the one\n // running this CLI. execPath is the binary already executing us.\n //\n // The fourth stdio slot opens the IPC channel the child reports readiness\n // on. Without it `process.send` is undefined in the child and we would be\n // back to guessing whether the boot succeeded.\n //\n // stdout/stderr are piped rather than inherited so this supervisor can\n // tell whether the child ever wrote anything, not just forward it blind.\n // `displayProductionStartFailure` used to claim \"the cause is printed\n // above\" on every failed boot, unconditionally — true when the child's\n // logger got far enough to print, false (and misleading) when it died\n // before its log channels were configured. Piping costs nothing here:\n // both streams are re-forwarded to this process's own stdout/stderr as\n // each chunk arrives, so a human watching the terminal sees the exact\n // same live output \"inherit\" gave them.\n const child = spawn(process.execPath, nodeArgs, {\n stdio: [\"inherit\", \"pipe\", \"pipe\", \"ipc\"],\n cwd,\n // The flag identifies us as a parent that speaks the boot protocol. The\n // child stays silent without it, so an app running under pm2 or any other\n // supervisor never writes to a channel that belongs to someone else.\n env: { ...env, [BOOT_SIGNAL_ENV_KEY]: \"1\" },\n // Important: keep child in same process group for proper signal handling\n detached: false,\n });\n\n const startedAt = Date.now();\n let isReady = false;\n let isShuttingDown = false;\n let isSettled = false;\n\n // Whether the child wrote anything to either stream — the only honest\n // basis for telling a developer \"the cause is printed above\". Set from\n // the first chunk on either stream; a child that dies before its first\n // write (a crash mid-import, a logger with no console channel) leaves\n // this `false`, which is exactly the case the summary must admit rather\n // than paper over.\n let sawChildOutput = false;\n\n const forwardChildOutput = (target: NodeJS.WritableStream) => (chunk: Buffer) => {\n sawChildOutput = true;\n target.write(chunk);\n };\n\n child.stdout?.on(\"data\", forwardChildOutput(process.stdout));\n child.stderr?.on(\"data\", forwardChildOutput(process.stderr));\n\n const readinessNoticeTimer = setTimeout(() => {\n if (isReady) {\n return;\n }\n\n displayMissingReadinessNotice(Date.now() - startedAt);\n }, readinessNoticeDelayMs);\n\n // A diagnostic timer must never be the reason the CLI stays alive.\n readinessNoticeTimer.unref?.();\n\n const settle = (result: ProductionSupervisorResult) => {\n if (isSettled) {\n return;\n }\n\n isSettled = true;\n clearTimeout(readinessNoticeTimer);\n process.off(\"SIGTERM\", onSigterm);\n process.off(\"SIGINT\", onSigint);\n process.off(\"SIGHUP\", onSighup);\n\n resolve(result);\n };\n\n child.on(\"message\", (message: unknown) => {\n if (isReady || !isBootSignal(message)) {\n return;\n }\n\n isReady = true;\n clearTimeout(readinessNoticeTimer);\n\n displayProductionReadyBanner({ bootDurationMs: message.bootDurationMs }).catch((error) => {\n // The server is up either way — a banner that fails to render must not\n // be reported as, or turn into, a boot failure.\n console.error(error);\n });\n\n // A worker-only process never binds a port, so `http-connector.ts`\n // never prints a URL for it — this is the one line that tells an\n // operator watching `warlock start` that the process is up on purpose,\n // not silently stuck.\n const roles = message.roles ?? [];\n\n if (roles.length > 0) {\n const servesHttp = roles.includes(\"api\") || roles.includes(\"web\");\n const summary = servesHttp\n ? `roles: ${roles.join(\", \")}`\n : `worker ready — roles: ${roles.join(\", \")}`;\n\n console.log(` ${colors.dim(summary)}`);\n }\n });\n\n // A spawn that never starts (missing binary, EACCES) emits `error` and no\n // `exit`, so without this the command would hang silently on a failure.\n // The error is printed BEFORE the summary that references it — the\n // summary says the cause is \"above\", so it has to already be there.\n child.on(\"error\", (error) => {\n console.error(error);\n displayProductionStartFailure(1, true);\n\n settle({ exitCode: 1, ready: false });\n });\n\n // Forward every stop signal so a supervisor that only signals this\n // process (docker kill -s INT, systemd KillSignal) still stops the child.\n // A repeated signal means the graceful shutdown is stuck: force-kill.\n const forward = (signal: NodeJS.Signals) => () => {\n if (isShuttingDown) {\n child.kill(\"SIGKILL\");\n return;\n }\n\n isShuttingDown = true;\n child.kill(signal);\n };\n\n const onSigterm = forward(\"SIGTERM\");\n const onSighup = forward(\"SIGHUP\");\n\n // On Windows Ctrl+C reaches both processes, so the child already has it —\n // we only record that this exit was asked for (kill() there is a hard kill).\n const onSigint =\n process.platform === \"win32\"\n ? () => {\n isShuttingDown = true;\n }\n : forward(\"SIGINT\");\n\n process.on(\"SIGTERM\", onSigterm);\n process.on(\"SIGINT\", onSigint);\n process.on(\"SIGHUP\", onSighup);\n\n // `close`, not `exit`: `exit` fires as soon as the OS process ends, which\n // can race ahead of the last chunks still in flight on the piped stdout/\n // stderr streams. `close` waits for those streams to end too, so\n // `sawChildOutput` reflects everything the child actually wrote instead\n // of whatever had been delivered by the time the process happened to die.\n child.on(\"close\", (code) => {\n // A child that dies before reporting readiness never served a request.\n // Exiting 0 there — which a clean `process.exit(0)` in failing app code\n // would do — reports a boot failure as a successful run, so the exit code\n // is forced non-zero to match what actually happened.\n //\n // An operator who interrupts the boot is not a failed boot, so a signalled\n // shutdown keeps the child's own exit code.\n if (!isReady && !isShuttingDown) {\n const exitCode = code === 0 || code === null ? 1 : code;\n\n displayProductionStartFailure(exitCode, sawChildOutput);\n\n return settle({ exitCode, ready: false });\n }\n\n settle({ exitCode: code ?? 0, ready: isReady });\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;AAeA,MAAa,oCAAoC;;;;;;;;;;;;;;;;;;;;;;;AAuCjD,SAAgB,2BAA2B,EACzC,UACA,MAAM,QAAQ,IAAI,GAClB,MAAM,QAAQ,KACd,yBAAyB,qCAC0C;CACnE,OAAO,IAAI,SAAqC,YAAY;EAqB1D,MAAM,QAAQ,MAAM,QAAQ,UAAU,UAAU;GAC9C,OAAO;IAAC;IAAW;IAAQ;IAAQ;GAAK;GACxC;GAIA,KAAK;IAAE,GAAG;KAAM,sBAAsB;GAAI;GAE1C,UAAU;EACZ,CAAC;EAED,MAAM,YAAY,KAAK,IAAI;EAC3B,IAAI,UAAU;EACd,IAAI,iBAAiB;EACrB,IAAI,YAAY;EAQhB,IAAI,iBAAiB;EAErB,MAAM,sBAAsB,YAAmC,UAAkB;GAC/E,iBAAiB;GACjB,OAAO,MAAM,KAAK;EACpB;EAEA,MAAM,QAAQ,GAAG,QAAQ,mBAAmB,QAAQ,MAAM,CAAC;EAC3D,MAAM,QAAQ,GAAG,QAAQ,mBAAmB,QAAQ,MAAM,CAAC;EAE3D,MAAM,uBAAuB,iBAAiB;GAC5C,IAAI,SACF;GAGF,8BAA8B,KAAK,IAAI,IAAI,SAAS;EACtD,GAAG,sBAAsB;EAGzB,qBAAqB,QAAQ;EAE7B,MAAM,UAAU,WAAuC;GACrD,IAAI,WACF;GAGF,YAAY;GACZ,aAAa,oBAAoB;GACjC,QAAQ,IAAI,WAAW,SAAS;GAChC,QAAQ,IAAI,UAAU,QAAQ;GAC9B,QAAQ,IAAI,UAAU,QAAQ;GAE9B,QAAQ,MAAM;EAChB;EAEA,MAAM,GAAG,YAAY,YAAqB;GACxC,IAAI,WAAW,CAAC,aAAa,OAAO,GAClC;GAGF,UAAU;GACV,aAAa,oBAAoB;GAEjC,6BAA6B,EAAE,gBAAgB,QAAQ,eAAe,CAAC,CAAC,CAAC,OAAO,UAAU;IAGxF,QAAQ,MAAM,KAAK;GACrB,CAAC;GAMD,MAAM,QAAQ,QAAQ,SAAS,CAAC;GAEhC,IAAI,MAAM,SAAS,GAAG;IAEpB,MAAM,UADa,MAAM,SAAS,KAAK,KAAK,MAAM,SAAS,KAAK,IAE5D,UAAU,MAAM,KAAK,IAAI,MACzB,yBAAyB,MAAM,KAAK,IAAI;IAE5C,QAAQ,IAAI,KAAK,OAAO,IAAI,OAAO,GAAG;GACxC;EACF,CAAC;EAMD,MAAM,GAAG,UAAU,UAAU;GAC3B,QAAQ,MAAM,KAAK;GACnB,8BAA8B,GAAG,IAAI;GAErC,OAAO;IAAE,UAAU;IAAG,OAAO;GAAM,CAAC;EACtC,CAAC;EAKD,MAAM,WAAW,iBAAiC;GAChD,IAAI,gBAAgB;IAClB,MAAM,KAAK,SAAS;IACpB;GACF;GAEA,iBAAiB;GACjB,MAAM,KAAK,MAAM;EACnB;EAEA,MAAM,YAAY,QAAQ,SAAS;EACnC,MAAM,WAAW,QAAQ,QAAQ;EAIjC,MAAM,WACJ,QAAQ,aAAa,gBACX;GACJ,iBAAiB;EACnB,IACA,QAAQ,QAAQ;EAEtB,QAAQ,GAAG,WAAW,SAAS;EAC/B,QAAQ,GAAG,UAAU,QAAQ;EAC7B,QAAQ,GAAG,UAAU,QAAQ;EAO7B,MAAM,GAAG,UAAU,SAAS;GAQ1B,IAAI,CAAC,WAAW,CAAC,gBAAgB;IAC/B,MAAM,WAAW,SAAS,KAAK,SAAS,OAAO,IAAI;IAEnD,8BAA8B,UAAU,cAAc;IAEtD,OAAO,OAAO;KAAE;KAAU,OAAO;IAAM,CAAC;GAC1C;GAEA,OAAO;IAAE,UAAU,QAAQ;IAAG,OAAO;GAAQ,CAAC;EAChD,CAAC;CACH,CAAC;AACH"}
@@ -2,7 +2,7 @@ import path from "path";
2
2
  import { directoryExistsAsync, removeDirectoryAsync, renameFileAsync } from "@warlock.js/fs";
3
3
  import { randomBytes } from "crypto";
4
4
 
5
- //#region ../core/src/production/promote-dist.ts
5
+ //#region ../../packages/core/src/production/promote-dist.ts
6
6
  /**
7
7
  * A sibling of `outDir` that esbuild bundles into instead of the real output
8
8
  * directory. Same parent folder as `outDir` on purpose — {@link stageDistAsync}
@@ -1 +1 @@
1
- {"version":3,"file":"promote-dist.mjs","names":[],"sources":["../../../../../../../core/src/production/promote-dist.ts"],"sourcesContent":["import { directoryExistsAsync, removeDirectoryAsync, renameFileAsync } from \"@warlock.js/fs\";\nimport { randomBytes } from \"crypto\";\nimport path from \"path\";\n\n/**\n * A sibling of `outDir` that esbuild bundles into instead of the real output\n * directory. Same parent folder as `outDir` on purpose — {@link stageDistAsync}\n * moves it into place with a directory rename, and a rename only stays a\n * single atomic filesystem operation when source and destination share a\n * volume.\n *\n * This path is a WRITE TARGET and nothing else. It is never written back into\n * the build config: `options.outdir` names the FINAL destination at all times,\n * because consumers bake it into runtime output (the web contribution derives\n * its `clientDir` from it) and a runtime path pointing at a temp directory\n * that promotion renames away is a broken artifact, not a broken build.\n */\nexport function createTempOutputDir(outDir: string): string {\n const parent = path.dirname(outDir);\n const base = path.basename(outDir);\n const suffix = randomBytes(6).toString(\"hex\");\n\n return path.join(parent, `.${base}.build-${suffix}`);\n}\n\n/**\n * A promotion in flight: the temp build has been renamed onto `outDir`, and\n * the previous `outDir` (when there was one) is parked under `previousDir`\n * until the caller {@link commitDistAsync commits} or\n * {@link rollbackDistAsync rolls back}.\n */\nexport type StagedDist = {\n /** The real output directory (`dist`) the temp build now occupies */\n outDir: string;\n /**\n * The moved-aside previous build, or `undefined` when `outDir` did not\n * exist before staging — the marker for \"a rollback has nothing to restore,\n * it only has to remove what this build put there\".\n */\n previousDir?: string;\n};\n\n/**\n * Move a freshly-built temp directory into place as `outDir`, replacing\n * whatever was there — without ever leaving `outDir` a mix of old and new\n * files, and without discarding the previous build yet.\n *\n * `fs.rename` moves a directory as a single filesystem operation, so each\n * rename below is atomic: `outDir` is observed as either wholly the old\n * build, wholly the new one, or (only for the instant between the two\n * renames below, and only when one previously existed) briefly absent —\n * never a mix of the two.\n *\n * Windows refuses to rename a directory onto a path that already exists, so\n * an existing `outDir` is moved aside first and only deleted by\n * {@link commitDistAsync}, once the build that follows has finished writing\n * into the new one. If the second rename throws — the only realistic way our\n * own code could leave `outDir` missing, as opposed to the process being\n * killed at the exact wrong instant — the old directory is moved straight\n * back before the error propagates, so a failed promotion never costs the\n * previous good build.\n *\n * Staging is deliberately separate from committing. The steps that run\n * between them — connector `emit` hooks, and the build-success marker — need\n * `outDir` to be the REAL path while they run, because what they write bakes\n * that path into the artifact. Renaming first and committing last is what\n * lets them see the final path and still be undone as a unit.\n *\n * @param tempDir the freshly-built directory to promote (removed as a side\n * effect of the rename; the caller does not need to clean it up once this\n * resolves)\n * @param outDir the real output directory (`dist`) to replace\n */\nexport async function stageDistAsync(tempDir: string, outDir: string): Promise<StagedDist> {\n const previousExists = await directoryExistsAsync(outDir);\n\n if (!previousExists) {\n await renameFileAsync(tempDir, outDir);\n\n return { outDir };\n }\n\n const previousDir = `${outDir}.stale-${randomBytes(6).toString(\"hex\")}`;\n\n await renameFileAsync(outDir, previousDir);\n\n try {\n await renameFileAsync(tempDir, outDir);\n } catch (error) {\n await renameFileAsync(previousDir, outDir).catch(() => undefined);\n throw error;\n }\n\n return { outDir, previousDir };\n}\n\n/**\n * Finish a staged promotion: the new `dist` is complete, so the parked\n * previous build is no longer needed.\n *\n * Never throws. It is the last step of a build that has already succeeded,\n * and a leftover `dist.stale-*` directory is untidy, not incorrect — failing\n * the build over it would turn a good artifact into a red run.\n */\nexport async function commitDistAsync(staged: StagedDist): Promise<void> {\n if (!staged.previousDir) return;\n\n await removeDirectoryAsync(staged.previousDir).catch(() => undefined);\n}\n\n/**\n * Undo a staged promotion after a later step failed: put the previous build\n * back where it was, and take the half-finished one out of `dist`.\n *\n * The failed build is renamed aside before the previous one is renamed back,\n * for the same reason {@link stageDistAsync} moves the old directory aside\n * first: a recursive delete of `dist` would leave it observable as a partial\n * tree, while a rename does not.\n *\n * Never throws. It runs inside a `catch`, and the error it is unwinding is\n * the one the developer needs to see — a rollback failure must not replace\n * it. The worst case it can leave behind is a `dist` holding an incomplete\n * build with no build-success marker, which `warlock start` refuses by\n * definition.\n */\nexport async function rollbackDistAsync(staged: StagedDist): Promise<void> {\n const { outDir, previousDir } = staged;\n\n if (!previousDir) {\n await removeDirectoryAsync(outDir).catch(() => undefined);\n\n return;\n }\n\n const discardDir = `${outDir}.failed-${randomBytes(6).toString(\"hex\")}`;\n\n await renameFileAsync(outDir, discardDir).catch(() => undefined);\n await renameFileAsync(previousDir, outDir).catch(() => undefined);\n await removeDirectoryAsync(discardDir).catch(() => undefined);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiBA,SAAgB,oBAAoB,QAAwB;CAC1D,MAAM,SAAS,KAAK,QAAQ,MAAM;CAClC,MAAM,OAAO,KAAK,SAAS,MAAM;CACjC,MAAM,SAAS,YAAY,CAAC,CAAC,CAAC,SAAS,KAAK;CAE5C,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,SAAS,QAAQ;AACrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,eAAsB,eAAe,SAAiB,QAAqC;CAGzF,IAAI,CAAC,MAFwB,qBAAqB,MAAM,GAEnC;EACnB,MAAM,gBAAgB,SAAS,MAAM;EAErC,OAAO,EAAE,OAAO;CAClB;CAEA,MAAM,cAAc,GAAG,OAAO,SAAS,YAAY,CAAC,CAAC,CAAC,SAAS,KAAK;CAEpE,MAAM,gBAAgB,QAAQ,WAAW;CAEzC,IAAI;EACF,MAAM,gBAAgB,SAAS,MAAM;CACvC,SAAS,OAAO;EACd,MAAM,gBAAgB,aAAa,MAAM,CAAC,CAAC,YAAY,MAAS;EAChE,MAAM;CACR;CAEA,OAAO;EAAE;EAAQ;CAAY;AAC/B;;;;;;;;;AAUA,eAAsB,gBAAgB,QAAmC;CACvE,IAAI,CAAC,OAAO,aAAa;CAEzB,MAAM,qBAAqB,OAAO,WAAW,CAAC,CAAC,YAAY,MAAS;AACtE;;;;;;;;;;;;;;;;AAiBA,eAAsB,kBAAkB,QAAmC;CACzE,MAAM,EAAE,QAAQ,gBAAgB;CAEhC,IAAI,CAAC,aAAa;EAChB,MAAM,qBAAqB,MAAM,CAAC,CAAC,YAAY,MAAS;EAExD;CACF;CAEA,MAAM,aAAa,GAAG,OAAO,UAAU,YAAY,CAAC,CAAC,CAAC,SAAS,KAAK;CAEpE,MAAM,gBAAgB,QAAQ,UAAU,CAAC,CAAC,YAAY,MAAS;CAC/D,MAAM,gBAAgB,aAAa,MAAM,CAAC,CAAC,YAAY,MAAS;CAChE,MAAM,qBAAqB,UAAU,CAAC,CAAC,YAAY,MAAS;AAC9D"}
1
+ {"version":3,"file":"promote-dist.mjs","names":[],"sources":["../../../../../../../../packages/core/src/production/promote-dist.ts"],"sourcesContent":["import { directoryExistsAsync, removeDirectoryAsync, renameFileAsync } from \"@warlock.js/fs\";\nimport { randomBytes } from \"crypto\";\nimport path from \"path\";\n\n/**\n * A sibling of `outDir` that esbuild bundles into instead of the real output\n * directory. Same parent folder as `outDir` on purpose — {@link stageDistAsync}\n * moves it into place with a directory rename, and a rename only stays a\n * single atomic filesystem operation when source and destination share a\n * volume.\n *\n * This path is a WRITE TARGET and nothing else. It is never written back into\n * the build config: `options.outdir` names the FINAL destination at all times,\n * because consumers bake it into runtime output (the web contribution derives\n * its `clientDir` from it) and a runtime path pointing at a temp directory\n * that promotion renames away is a broken artifact, not a broken build.\n */\nexport function createTempOutputDir(outDir: string): string {\n const parent = path.dirname(outDir);\n const base = path.basename(outDir);\n const suffix = randomBytes(6).toString(\"hex\");\n\n return path.join(parent, `.${base}.build-${suffix}`);\n}\n\n/**\n * A promotion in flight: the temp build has been renamed onto `outDir`, and\n * the previous `outDir` (when there was one) is parked under `previousDir`\n * until the caller {@link commitDistAsync commits} or\n * {@link rollbackDistAsync rolls back}.\n */\nexport type StagedDist = {\n /** The real output directory (`dist`) the temp build now occupies */\n outDir: string;\n /**\n * The moved-aside previous build, or `undefined` when `outDir` did not\n * exist before staging — the marker for \"a rollback has nothing to restore,\n * it only has to remove what this build put there\".\n */\n previousDir?: string;\n};\n\n/**\n * Move a freshly-built temp directory into place as `outDir`, replacing\n * whatever was there — without ever leaving `outDir` a mix of old and new\n * files, and without discarding the previous build yet.\n *\n * `fs.rename` moves a directory as a single filesystem operation, so each\n * rename below is atomic: `outDir` is observed as either wholly the old\n * build, wholly the new one, or (only for the instant between the two\n * renames below, and only when one previously existed) briefly absent —\n * never a mix of the two.\n *\n * Windows refuses to rename a directory onto a path that already exists, so\n * an existing `outDir` is moved aside first and only deleted by\n * {@link commitDistAsync}, once the build that follows has finished writing\n * into the new one. If the second rename throws — the only realistic way our\n * own code could leave `outDir` missing, as opposed to the process being\n * killed at the exact wrong instant — the old directory is moved straight\n * back before the error propagates, so a failed promotion never costs the\n * previous good build.\n *\n * Staging is deliberately separate from committing. The steps that run\n * between them — connector `emit` hooks, and the build-success marker — need\n * `outDir` to be the REAL path while they run, because what they write bakes\n * that path into the artifact. Renaming first and committing last is what\n * lets them see the final path and still be undone as a unit.\n *\n * @param tempDir the freshly-built directory to promote (removed as a side\n * effect of the rename; the caller does not need to clean it up once this\n * resolves)\n * @param outDir the real output directory (`dist`) to replace\n */\nexport async function stageDistAsync(tempDir: string, outDir: string): Promise<StagedDist> {\n const previousExists = await directoryExistsAsync(outDir);\n\n if (!previousExists) {\n await renameFileAsync(tempDir, outDir);\n\n return { outDir };\n }\n\n const previousDir = `${outDir}.stale-${randomBytes(6).toString(\"hex\")}`;\n\n await renameFileAsync(outDir, previousDir);\n\n try {\n await renameFileAsync(tempDir, outDir);\n } catch (error) {\n await renameFileAsync(previousDir, outDir).catch(() => undefined);\n throw error;\n }\n\n return { outDir, previousDir };\n}\n\n/**\n * Finish a staged promotion: the new `dist` is complete, so the parked\n * previous build is no longer needed.\n *\n * Never throws. It is the last step of a build that has already succeeded,\n * and a leftover `dist.stale-*` directory is untidy, not incorrect — failing\n * the build over it would turn a good artifact into a red run.\n */\nexport async function commitDistAsync(staged: StagedDist): Promise<void> {\n if (!staged.previousDir) return;\n\n await removeDirectoryAsync(staged.previousDir).catch(() => undefined);\n}\n\n/**\n * Undo a staged promotion after a later step failed: put the previous build\n * back where it was, and take the half-finished one out of `dist`.\n *\n * The failed build is renamed aside before the previous one is renamed back,\n * for the same reason {@link stageDistAsync} moves the old directory aside\n * first: a recursive delete of `dist` would leave it observable as a partial\n * tree, while a rename does not.\n *\n * Never throws. It runs inside a `catch`, and the error it is unwinding is\n * the one the developer needs to see — a rollback failure must not replace\n * it. The worst case it can leave behind is a `dist` holding an incomplete\n * build with no build-success marker, which `warlock start` refuses by\n * definition.\n */\nexport async function rollbackDistAsync(staged: StagedDist): Promise<void> {\n const { outDir, previousDir } = staged;\n\n if (!previousDir) {\n await removeDirectoryAsync(outDir).catch(() => undefined);\n\n return;\n }\n\n const discardDir = `${outDir}.failed-${randomBytes(6).toString(\"hex\")}`;\n\n await renameFileAsync(outDir, discardDir).catch(() => undefined);\n await renameFileAsync(previousDir, outDir).catch(() => undefined);\n await removeDirectoryAsync(discardDir).catch(() => undefined);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiBA,SAAgB,oBAAoB,QAAwB;CAC1D,MAAM,SAAS,KAAK,QAAQ,MAAM;CAClC,MAAM,OAAO,KAAK,SAAS,MAAM;CACjC,MAAM,SAAS,YAAY,CAAC,CAAC,CAAC,SAAS,KAAK;CAE5C,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,SAAS,QAAQ;AACrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,eAAsB,eAAe,SAAiB,QAAqC;CAGzF,IAAI,CAAC,MAFwB,qBAAqB,MAAM,GAEnC;EACnB,MAAM,gBAAgB,SAAS,MAAM;EAErC,OAAO,EAAE,OAAO;CAClB;CAEA,MAAM,cAAc,GAAG,OAAO,SAAS,YAAY,CAAC,CAAC,CAAC,SAAS,KAAK;CAEpE,MAAM,gBAAgB,QAAQ,WAAW;CAEzC,IAAI;EACF,MAAM,gBAAgB,SAAS,MAAM;CACvC,SAAS,OAAO;EACd,MAAM,gBAAgB,aAAa,MAAM,CAAC,CAAC,YAAY,MAAS;EAChE,MAAM;CACR;CAEA,OAAO;EAAE;EAAQ;CAAY;AAC/B;;;;;;;;;AAUA,eAAsB,gBAAgB,QAAmC;CACvE,IAAI,CAAC,OAAO,aAAa;CAEzB,MAAM,qBAAqB,OAAO,WAAW,CAAC,CAAC,YAAY,MAAS;AACtE;;;;;;;;;;;;;;;;AAiBA,eAAsB,kBAAkB,QAAmC;CACzE,MAAM,EAAE,QAAQ,gBAAgB;CAEhC,IAAI,CAAC,aAAa;EAChB,MAAM,qBAAqB,MAAM,CAAC,CAAC,YAAY,MAAS;EAExD;CACF;CAEA,MAAM,aAAa,GAAG,OAAO,UAAU,YAAY,CAAC,CAAC,CAAC,SAAS,KAAK;CAEpE,MAAM,gBAAgB,QAAQ,UAAU,CAAC,CAAC,YAAY,MAAS;CAC/D,MAAM,gBAAgB,aAAa,MAAM,CAAC,CAAC,YAAY,MAAS;CAChE,MAAM,qBAAqB,UAAU,CAAC,CAAC,YAAY,MAAS;AAC9D"}