whale-code 6.5.5 → 6.5.6

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 (847) hide show
  1. package/README.md +39 -31
  2. package/bin/{swagmanager-mcp.js → whale-code.js} +17 -2
  3. package/dist/cli/app.js +148 -72
  4. package/dist/cli/app.js.map +1 -0
  5. package/dist/cli/chat/AgentSelector.js +105 -10
  6. package/dist/cli/chat/AgentSelector.js.map +1 -0
  7. package/dist/cli/chat/ChatApp.d.ts +31 -0
  8. package/dist/cli/chat/ChatApp.js +539 -286
  9. package/dist/cli/chat/ChatApp.js.map +1 -0
  10. package/dist/cli/chat/ChatInput.js +1088 -770
  11. package/dist/cli/chat/ChatInput.js.map +1 -0
  12. package/dist/cli/chat/MarkdownText.js +39 -14
  13. package/dist/cli/chat/MarkdownText.js.map +1 -0
  14. package/dist/cli/chat/MemoryManager.js +181 -46
  15. package/dist/cli/chat/MemoryManager.js.map +1 -0
  16. package/dist/cli/chat/MessageList.d.ts +2 -3
  17. package/dist/cli/chat/MessageList.js +186 -45
  18. package/dist/cli/chat/MessageList.js.map +1 -0
  19. package/dist/cli/chat/ModelSelector.js +282 -63
  20. package/dist/cli/chat/ModelSelector.js.map +1 -0
  21. package/dist/cli/chat/NodeManager.js +165 -75
  22. package/dist/cli/chat/NodeManager.js.map +1 -0
  23. package/dist/cli/chat/NodeSelector.js +171 -30
  24. package/dist/cli/chat/NodeSelector.js.map +1 -0
  25. package/dist/cli/chat/PlanApproval.js +281 -57
  26. package/dist/cli/chat/PlanApproval.js.map +1 -0
  27. package/dist/cli/chat/RewindViewer.js +559 -144
  28. package/dist/cli/chat/RewindViewer.js.map +1 -0
  29. package/dist/cli/chat/SessionManager.js +137 -30
  30. package/dist/cli/chat/SessionManager.js.map +1 -0
  31. package/dist/cli/chat/SlashMenu.js +293 -164
  32. package/dist/cli/chat/SlashMenu.js.map +1 -0
  33. package/dist/cli/chat/StatusBar.js +172 -9
  34. package/dist/cli/chat/StatusBar.js.map +1 -0
  35. package/dist/cli/chat/StoreSelector.js +147 -18
  36. package/dist/cli/chat/StoreSelector.js.map +1 -0
  37. package/dist/cli/chat/StreamingText.d.ts +1 -5
  38. package/dist/cli/chat/StreamingText.js +22 -7
  39. package/dist/cli/chat/StreamingText.js.map +1 -0
  40. package/dist/cli/chat/SubagentPanel.d.ts +1 -2
  41. package/dist/cli/chat/SubagentPanel.js +612 -72
  42. package/dist/cli/chat/SubagentPanel.js.map +1 -0
  43. package/dist/cli/chat/TeamPanel.d.ts +1 -0
  44. package/dist/cli/chat/TeamPanel.js +230 -30
  45. package/dist/cli/chat/TeamPanel.js.map +1 -0
  46. package/dist/cli/chat/ThemeSelector.js +84 -24
  47. package/dist/cli/chat/ThemeSelector.js.map +1 -0
  48. package/dist/cli/chat/ToolIndicator.js +1476 -371
  49. package/dist/cli/chat/ToolIndicator.js.map +1 -0
  50. package/dist/cli/chat/hooks/useAgentLoop.d.ts +1 -0
  51. package/dist/cli/chat/hooks/useAgentLoop.js +481 -367
  52. package/dist/cli/chat/hooks/useAgentLoop.js.map +1 -0
  53. package/dist/cli/chat/hooks/useSlashCommands.d.ts +3 -14
  54. package/dist/cli/chat/hooks/useSlashCommands.js +744 -572
  55. package/dist/cli/chat/hooks/useSlashCommands.js.map +1 -0
  56. package/dist/cli/commands/config-cmd.js +56 -57
  57. package/dist/cli/commands/config-cmd.js.map +1 -0
  58. package/dist/cli/commands/db.js +184 -169
  59. package/dist/cli/commands/db.js.map +1 -0
  60. package/dist/cli/commands/doctor.js +212 -122
  61. package/dist/cli/commands/doctor.js.map +1 -0
  62. package/dist/cli/commands/init.js +211 -244
  63. package/dist/cli/commands/init.js.map +1 -0
  64. package/dist/cli/commands/mcp.js +127 -122
  65. package/dist/cli/commands/mcp.js.map +1 -0
  66. package/dist/cli/login/LoginApp.js +355 -141
  67. package/dist/cli/login/LoginApp.js.map +1 -0
  68. package/dist/cli/print-mode.js +196 -177
  69. package/dist/cli/print-mode.js.map +1 -0
  70. package/dist/cli/serve-mode.js +615 -530
  71. package/dist/cli/serve-mode.js.map +1 -0
  72. package/dist/cli/services/agent-config.d.ts +5 -1
  73. package/dist/cli/services/agent-config.js +66 -36
  74. package/dist/cli/services/agent-config.js.map +1 -0
  75. package/dist/cli/services/agent-definitions.d.ts +4 -1
  76. package/dist/cli/services/agent-definitions.js +97 -56
  77. package/dist/cli/services/agent-definitions.js.map +1 -0
  78. package/dist/cli/services/agent-events.js +225 -162
  79. package/dist/cli/services/agent-events.js.map +1 -0
  80. package/dist/cli/services/agent-loop.js +976 -688
  81. package/dist/cli/services/agent-loop.js.map +1 -0
  82. package/dist/cli/services/agent-worker-base.d.ts +35 -5
  83. package/dist/cli/services/agent-worker-base.js +337 -153
  84. package/dist/cli/services/agent-worker-base.js.map +1 -0
  85. package/dist/cli/services/api-retry.js +69 -64
  86. package/dist/cli/services/api-retry.js.map +1 -0
  87. package/dist/cli/services/auth-service.d.ts +3 -3
  88. package/dist/cli/services/auth-service.js +209 -132
  89. package/dist/cli/services/auth-service.js.map +1 -0
  90. package/dist/cli/services/background-processes.js +343 -267
  91. package/dist/cli/services/background-processes.js.map +1 -0
  92. package/dist/cli/services/browser-auth.d.ts +2 -2
  93. package/dist/cli/services/browser-auth.js +159 -118
  94. package/dist/cli/services/browser-auth.js.map +1 -0
  95. package/dist/cli/services/claude-md-loader.js +40 -36
  96. package/dist/cli/services/claude-md-loader.js.map +1 -0
  97. package/dist/cli/services/config-store.d.ts +9 -4
  98. package/dist/cli/services/config-store.js +164 -117
  99. package/dist/cli/services/config-store.js.map +1 -0
  100. package/dist/cli/services/debug-log.d.ts +1 -1
  101. package/dist/cli/services/debug-log.js +34 -35
  102. package/dist/cli/services/debug-log.js.map +1 -0
  103. package/dist/cli/services/env-detect.d.ts +7 -0
  104. package/dist/cli/services/env-detect.js +9 -0
  105. package/dist/cli/services/env-detect.js.map +1 -0
  106. package/dist/cli/services/error-logger.js +187 -169
  107. package/dist/cli/services/error-logger.js.map +1 -0
  108. package/dist/cli/services/file-history.d.ts +1 -1
  109. package/dist/cli/services/file-history.js +50 -54
  110. package/dist/cli/services/file-history.js.map +1 -0
  111. package/dist/cli/services/format-server-response.js +332 -372
  112. package/dist/cli/services/format-server-response.js.map +1 -0
  113. package/dist/cli/services/git-context.js +61 -45
  114. package/dist/cli/services/git-context.js.map +1 -0
  115. package/dist/cli/services/hooks.d.ts +2 -2
  116. package/dist/cli/services/hooks.js +195 -180
  117. package/dist/cli/services/hooks.js.map +1 -0
  118. package/dist/cli/services/ink-incremental.d.ts +19 -0
  119. package/dist/cli/services/ink-incremental.js +59 -0
  120. package/dist/cli/services/ink-incremental.js.map +1 -0
  121. package/dist/cli/services/ink-resize-fix.js +54 -44
  122. package/dist/cli/services/ink-resize-fix.js.map +1 -0
  123. package/dist/cli/services/ink-sync-output.d.ts +12 -0
  124. package/dist/cli/services/ink-sync-output.js +16 -0
  125. package/dist/cli/services/ink-sync-output.js.map +1 -0
  126. package/dist/cli/services/interactive-tools.js +268 -212
  127. package/dist/cli/services/interactive-tools.js.map +1 -0
  128. package/dist/cli/services/keybinding-manager.d.ts +11 -1
  129. package/dist/cli/services/keybinding-manager.js +126 -63
  130. package/dist/cli/services/keybinding-manager.js.map +1 -0
  131. package/dist/cli/services/local-tools.d.ts +1 -1
  132. package/dist/cli/services/local-tools.js +939 -656
  133. package/dist/cli/services/local-tools.js.map +1 -0
  134. package/dist/cli/services/lsp-manager.js +757 -594
  135. package/dist/cli/services/lsp-manager.js.map +1 -0
  136. package/dist/cli/services/mcp-client.d.ts +1 -1
  137. package/dist/cli/services/mcp-client.js +173 -134
  138. package/dist/cli/services/mcp-client.js.map +1 -0
  139. package/dist/cli/services/memory-manager.js +53 -40
  140. package/dist/cli/services/memory-manager.js.map +1 -0
  141. package/dist/cli/services/model-manager.js +55 -40
  142. package/dist/cli/services/model-manager.js.map +1 -0
  143. package/dist/cli/services/model-router.js +115 -85
  144. package/dist/cli/services/model-router.js.map +1 -0
  145. package/dist/cli/services/paths.d.ts +30 -0
  146. package/dist/cli/services/paths.js +81 -0
  147. package/dist/cli/services/paths.js.map +1 -0
  148. package/dist/cli/services/permission-modes.js +32 -25
  149. package/dist/cli/services/permission-modes.js.map +1 -0
  150. package/dist/cli/services/rewind.js +182 -168
  151. package/dist/cli/services/rewind.js.map +1 -0
  152. package/dist/cli/services/ripgrep.js +115 -115
  153. package/dist/cli/services/ripgrep.js.map +1 -0
  154. package/dist/cli/services/sandbox.d.ts +1 -1
  155. package/dist/cli/services/sandbox.js +58 -37
  156. package/dist/cli/services/sandbox.js.map +1 -0
  157. package/dist/cli/services/server-tools.js +738 -565
  158. package/dist/cli/services/server-tools.js.map +1 -0
  159. package/dist/cli/services/session-persistence.js +69 -74
  160. package/dist/cli/services/session-persistence.js.map +1 -0
  161. package/dist/cli/services/subagent-worker.js +42 -27
  162. package/dist/cli/services/subagent-worker.js.map +1 -0
  163. package/dist/cli/services/subagent.d.ts +2 -0
  164. package/dist/cli/services/subagent.js +605 -433
  165. package/dist/cli/services/subagent.js.map +1 -0
  166. package/dist/cli/services/system-prompt.js +86 -78
  167. package/dist/cli/services/system-prompt.js.map +1 -0
  168. package/dist/cli/services/task-decomposer.d.ts +1 -1
  169. package/dist/cli/services/task-decomposer.js +172 -139
  170. package/dist/cli/services/task-decomposer.js.map +1 -0
  171. package/dist/cli/services/team-lead.d.ts +2 -2
  172. package/dist/cli/services/team-lead.js +727 -529
  173. package/dist/cli/services/team-lead.js.map +1 -0
  174. package/dist/cli/services/team-state.js +319 -319
  175. package/dist/cli/services/team-state.js.map +1 -0
  176. package/dist/cli/services/teammate.d.ts +8 -2
  177. package/dist/cli/services/teammate.js +857 -569
  178. package/dist/cli/services/teammate.js.map +1 -0
  179. package/dist/cli/services/telemetry.d.ts +6 -1
  180. package/dist/cli/services/telemetry.js +180 -157
  181. package/dist/cli/services/telemetry.js.map +1 -0
  182. package/dist/cli/services/tools/agent-tools.d.ts +3 -3
  183. package/dist/cli/services/tools/agent-tools.js +480 -322
  184. package/dist/cli/services/tools/agent-tools.js.map +1 -0
  185. package/dist/cli/services/tools/file-ops.js +563 -450
  186. package/dist/cli/services/tools/file-ops.js.map +1 -0
  187. package/dist/cli/services/tools/search-tools.js +231 -162
  188. package/dist/cli/services/tools/search-tools.js.map +1 -0
  189. package/dist/cli/services/tools/shell-exec.js +197 -151
  190. package/dist/cli/services/tools/shell-exec.js.map +1 -0
  191. package/dist/cli/services/tools/task-manager.js +206 -173
  192. package/dist/cli/services/tools/task-manager.js.map +1 -0
  193. package/dist/cli/services/tools/web-tools.js +388 -341
  194. package/dist/cli/services/tools/web-tools.js.map +1 -0
  195. package/dist/cli/setup/SetupApp.d.ts +2 -2
  196. package/dist/cli/setup/SetupApp.js +608 -160
  197. package/dist/cli/setup/SetupApp.js.map +1 -0
  198. package/dist/cli/shared/ErrorBoundary.d.ts +22 -0
  199. package/dist/cli/shared/ErrorBoundary.js +73 -0
  200. package/dist/cli/shared/ErrorBoundary.js.map +1 -0
  201. package/dist/cli/shared/MatrixIntro.js +66 -69
  202. package/dist/cli/shared/MatrixIntro.js.map +1 -0
  203. package/dist/cli/shared/SpinnerSlot.d.ts +14 -0
  204. package/dist/cli/shared/SpinnerSlot.js +63 -0
  205. package/dist/cli/shared/SpinnerSlot.js.map +1 -0
  206. package/dist/cli/shared/Theme.d.ts +1 -1
  207. package/dist/cli/shared/Theme.js +136 -92
  208. package/dist/cli/shared/Theme.js.map +1 -0
  209. package/dist/cli/shared/WhaleBanner.js +99 -11
  210. package/dist/cli/shared/WhaleBanner.js.map +1 -0
  211. package/dist/cli/shared/markdown.d.ts +3 -1
  212. package/dist/cli/shared/markdown.js +736 -674
  213. package/dist/cli/shared/markdown.js.map +1 -0
  214. package/dist/cli/shared/marked-terminal.d.js +2 -0
  215. package/dist/cli/shared/marked-terminal.d.js.map +1 -0
  216. package/dist/cli/shared/theme-manager.js +99 -90
  217. package/dist/cli/shared/theme-manager.js.map +1 -0
  218. package/dist/cli/shared/theme-presets.js +256 -254
  219. package/dist/cli/shared/theme-presets.js.map +1 -0
  220. package/dist/cli/status/StatusApp.js +235 -86
  221. package/dist/cli/status/StatusApp.js.map +1 -0
  222. package/dist/cli/stores/StoreApp.js +275 -65
  223. package/dist/cli/stores/StoreApp.js.map +1 -0
  224. package/dist/index.d.ts +2 -2
  225. package/dist/index.js +509 -396
  226. package/dist/index.js.map +1 -0
  227. package/dist/local-agent/connection.d.ts +2 -2
  228. package/dist/local-agent/connection.js +352 -293
  229. package/dist/local-agent/connection.js.map +1 -0
  230. package/dist/local-agent/discovery.js +259 -122
  231. package/dist/local-agent/discovery.js.map +1 -0
  232. package/dist/local-agent/executor.js +216 -193
  233. package/dist/local-agent/executor.js.map +1 -0
  234. package/dist/local-agent/index.d.ts +2 -2
  235. package/dist/local-agent/index.js +156 -156
  236. package/dist/local-agent/index.js.map +1 -0
  237. package/dist/node/adapters/base.js +18 -8
  238. package/dist/node/adapters/base.js.map +1 -0
  239. package/dist/node/adapters/discord.js +286 -275
  240. package/dist/node/adapters/discord.js.map +1 -0
  241. package/dist/node/adapters/email.js +189 -202
  242. package/dist/node/adapters/email.js.map +1 -0
  243. package/dist/node/adapters/imessage.js +145 -142
  244. package/dist/node/adapters/imessage.js.map +1 -0
  245. package/dist/node/adapters/slack.js +237 -236
  246. package/dist/node/adapters/slack.js.map +1 -0
  247. package/dist/node/adapters/sms.js +149 -151
  248. package/dist/node/adapters/sms.js.map +1 -0
  249. package/dist/node/adapters/telegram.js +88 -92
  250. package/dist/node/adapters/telegram.js.map +1 -0
  251. package/dist/node/adapters/webchat.js +160 -136
  252. package/dist/node/adapters/webchat.js.map +1 -0
  253. package/dist/node/adapters/whatsapp.js +212 -215
  254. package/dist/node/adapters/whatsapp.js.map +1 -0
  255. package/dist/node/cli.js +884 -653
  256. package/dist/node/cli.js.map +1 -0
  257. package/dist/node/config.js +20 -18
  258. package/dist/node/config.js.map +1 -0
  259. package/dist/node/gateway-client.js +191 -181
  260. package/dist/node/gateway-client.js.map +1 -0
  261. package/dist/node/portal/clipboard.js +161 -130
  262. package/dist/node/portal/clipboard.js.map +1 -0
  263. package/dist/node/portal/discovery.js +51 -45
  264. package/dist/node/portal/discovery.js.map +1 -0
  265. package/dist/node/portal/forward.js +64 -58
  266. package/dist/node/portal/forward.js.map +1 -0
  267. package/dist/node/portal/index.js +246 -221
  268. package/dist/node/portal/index.js.map +1 -0
  269. package/dist/node/portal/multiplexer.js +192 -182
  270. package/dist/node/portal/multiplexer.js.map +1 -0
  271. package/dist/node/portal/permissions.js +102 -70
  272. package/dist/node/portal/permissions.js.map +1 -0
  273. package/dist/node/portal/protocol.js +153 -116
  274. package/dist/node/portal/protocol.js.map +1 -0
  275. package/dist/node/portal/screen.js +80 -69
  276. package/dist/node/portal/screen.js.map +1 -0
  277. package/dist/node/portal/session.js +124 -117
  278. package/dist/node/portal/session.js.map +1 -0
  279. package/dist/node/portal/shell.js +140 -113
  280. package/dist/node/portal/shell.js.map +1 -0
  281. package/dist/node/portal/stream.js +77 -75
  282. package/dist/node/portal/stream.js.map +1 -0
  283. package/dist/node/portal/transfer.js +190 -167
  284. package/dist/node/portal/transfer.js.map +1 -0
  285. package/dist/node/portal/ui.js +124 -99
  286. package/dist/node/portal/ui.js.map +1 -0
  287. package/dist/node/remote-desktop/compile-helper.js +50 -45
  288. package/dist/node/remote-desktop/compile-helper.js.map +1 -0
  289. package/dist/node/remote-desktop/index.js +215 -187
  290. package/dist/node/remote-desktop/index.js.map +1 -0
  291. package/dist/node/remote-desktop/protocol.js +45 -29
  292. package/dist/node/remote-desktop/protocol.js.map +1 -0
  293. package/dist/node/runtime.js +493 -410
  294. package/dist/node/runtime.js.map +1 -0
  295. package/dist/server/handlers/__test-utils__/test-db.js +39 -89
  296. package/dist/server/handlers/__test-utils__/test-db.js.map +1 -0
  297. package/dist/server/handlers/analytics.js +467 -261
  298. package/dist/server/handlers/analytics.js.map +1 -0
  299. package/dist/server/handlers/api-docs.js +1030 -895
  300. package/dist/server/handlers/api-docs.js.map +1 -0
  301. package/dist/server/handlers/api-keys.js +291 -242
  302. package/dist/server/handlers/api-keys.js.map +1 -0
  303. package/dist/server/handlers/billing.js +330 -239
  304. package/dist/server/handlers/billing.js.map +1 -0
  305. package/dist/server/handlers/browser.js +468 -395
  306. package/dist/server/handlers/browser.js.map +1 -0
  307. package/dist/server/handlers/catalog.js +1377 -978
  308. package/dist/server/handlers/catalog.js.map +1 -0
  309. package/dist/server/handlers/clickhouse.js +157 -109
  310. package/dist/server/handlers/clickhouse.js.map +1 -0
  311. package/dist/server/handlers/comms.js +1439 -984
  312. package/dist/server/handlers/comms.js.map +1 -0
  313. package/dist/server/handlers/creations.js +461 -394
  314. package/dist/server/handlers/creations.js.map +1 -0
  315. package/dist/server/handlers/crm.js +1082 -791
  316. package/dist/server/handlers/crm.js.map +1 -0
  317. package/dist/server/handlers/discovery.js +251 -232
  318. package/dist/server/handlers/discovery.js.map +1 -0
  319. package/dist/server/handlers/embeddings.js +241 -164
  320. package/dist/server/handlers/embeddings.js.map +1 -0
  321. package/dist/server/handlers/enrichment.js +887 -718
  322. package/dist/server/handlers/enrichment.js.map +1 -0
  323. package/dist/server/handlers/image-gen.js +467 -376
  324. package/dist/server/handlers/image-gen.js.map +1 -0
  325. package/dist/server/handlers/inventory.js +797 -424
  326. package/dist/server/handlers/inventory.js.map +1 -0
  327. package/dist/server/handlers/kali.js +272 -230
  328. package/dist/server/handlers/kali.js.map +1 -0
  329. package/dist/server/handlers/llm-providers.js +803 -580
  330. package/dist/server/handlers/llm-providers.js.map +1 -0
  331. package/dist/server/handlers/local-agent.js +133 -105
  332. package/dist/server/handlers/local-agent.js.map +1 -0
  333. package/dist/server/handlers/media.js +1179 -857
  334. package/dist/server/handlers/media.js.map +1 -0
  335. package/dist/server/handlers/meta-ads.js +2669 -2093
  336. package/dist/server/handlers/meta-ads.js.map +1 -0
  337. package/dist/server/handlers/nodes.js +1321 -913
  338. package/dist/server/handlers/nodes.js.map +1 -0
  339. package/dist/server/handlers/operations.js +183 -157
  340. package/dist/server/handlers/operations.js.map +1 -0
  341. package/dist/server/handlers/platform.js +346 -210
  342. package/dist/server/handlers/platform.js.map +1 -0
  343. package/dist/server/handlers/remove-bg.js +118 -86
  344. package/dist/server/handlers/remove-bg.js.map +1 -0
  345. package/dist/server/handlers/storefront.js +586 -446
  346. package/dist/server/handlers/storefront.js.map +1 -0
  347. package/dist/server/handlers/supply-chain.js +546 -326
  348. package/dist/server/handlers/supply-chain.js.map +1 -0
  349. package/dist/server/handlers/transcription.js +106 -97
  350. package/dist/server/handlers/transcription.js.map +1 -0
  351. package/dist/server/handlers/video-gen.js +593 -424
  352. package/dist/server/handlers/video-gen.js.map +1 -0
  353. package/dist/server/handlers/voice.js +1458 -1039
  354. package/dist/server/handlers/voice.js.map +1 -0
  355. package/dist/server/handlers/workflow-steps.js +2837 -2116
  356. package/dist/server/handlers/workflow-steps.js.map +1 -0
  357. package/dist/server/handlers/workflows.js +1630 -933
  358. package/dist/server/handlers/workflows.js.map +1 -0
  359. package/dist/server/index.js +3167 -2422
  360. package/dist/server/index.js.map +1 -0
  361. package/dist/server/lib/batch-client.js +471 -409
  362. package/dist/server/lib/batch-client.js.map +1 -0
  363. package/dist/server/lib/clickhouse-buffer.js +118 -104
  364. package/dist/server/lib/clickhouse-buffer.js.map +1 -0
  365. package/dist/server/lib/clickhouse-client.js +107 -107
  366. package/dist/server/lib/clickhouse-client.js.map +1 -0
  367. package/dist/server/lib/coa-renderer.js +1786 -356
  368. package/dist/server/lib/coa-renderer.js.map +1 -0
  369. package/dist/server/lib/code-worker-pool.js +227 -177
  370. package/dist/server/lib/code-worker-pool.js.map +1 -0
  371. package/dist/server/lib/code-worker.js +174 -164
  372. package/dist/server/lib/code-worker.js.map +1 -0
  373. package/dist/server/lib/compaction-service.d.ts +2 -12
  374. package/dist/server/lib/compaction-service.js +74 -184
  375. package/dist/server/lib/compaction-service.js.map +1 -0
  376. package/dist/server/lib/logger.js +36 -24
  377. package/dist/server/lib/logger.js.map +1 -0
  378. package/dist/server/lib/otel.js +101 -80
  379. package/dist/server/lib/otel.js.map +1 -0
  380. package/dist/server/lib/pdf-renderer.js +952 -788
  381. package/dist/server/lib/pdf-renderer.js.map +1 -0
  382. package/dist/server/lib/prompt-sanitizer.js +188 -108
  383. package/dist/server/lib/prompt-sanitizer.js.map +1 -0
  384. package/dist/server/lib/provider-capabilities.js +136 -138
  385. package/dist/server/lib/provider-capabilities.js.map +1 -0
  386. package/dist/server/lib/provider-failover.js +190 -168
  387. package/dist/server/lib/provider-failover.js.map +1 -0
  388. package/dist/server/lib/rate-limiter.js +186 -117
  389. package/dist/server/lib/rate-limiter.js.map +1 -0
  390. package/dist/server/lib/react-pdf-layout.js +551 -382
  391. package/dist/server/lib/react-pdf-layout.js.map +1 -0
  392. package/dist/server/lib/server-agent-loop.d.ts +4 -1
  393. package/dist/server/lib/server-agent-loop.js +906 -634
  394. package/dist/server/lib/server-agent-loop.js.map +1 -0
  395. package/dist/server/lib/server-subagent.js +260 -164
  396. package/dist/server/lib/server-subagent.js.map +1 -0
  397. package/dist/server/lib/session-checkpoint.js +105 -96
  398. package/dist/server/lib/session-checkpoint.js.map +1 -0
  399. package/dist/server/lib/ssrf-guard.js +193 -184
  400. package/dist/server/lib/ssrf-guard.js.map +1 -0
  401. package/dist/server/lib/supabase-client.js +94 -82
  402. package/dist/server/lib/supabase-client.js.map +1 -0
  403. package/dist/server/lib/template-resolver.js +154 -176
  404. package/dist/server/lib/template-resolver.js.map +1 -0
  405. package/dist/server/lib/utils.js +242 -133
  406. package/dist/server/lib/utils.js.map +1 -0
  407. package/dist/server/local-agent-gateway.d.ts +2 -2
  408. package/dist/server/local-agent-gateway.js +785 -627
  409. package/dist/server/local-agent-gateway.js.map +1 -0
  410. package/dist/server/providers/anthropic.js +250 -172
  411. package/dist/server/providers/anthropic.js.map +1 -0
  412. package/dist/server/providers/bedrock.js +217 -158
  413. package/dist/server/providers/bedrock.js.map +1 -0
  414. package/dist/server/providers/gemini.js +548 -418
  415. package/dist/server/providers/gemini.js.map +1 -0
  416. package/dist/server/providers/openai.js +571 -437
  417. package/dist/server/providers/openai.js.map +1 -0
  418. package/dist/server/providers/registry.js +23 -18
  419. package/dist/server/providers/registry.js.map +1 -0
  420. package/dist/server/providers/shared.js +123 -95
  421. package/dist/server/providers/shared.js.map +1 -0
  422. package/dist/server/providers/types.js +1 -11
  423. package/dist/server/providers/types.js.map +1 -0
  424. package/dist/server/proxy-handlers.js +209 -165
  425. package/dist/server/proxy-handlers.js.map +1 -0
  426. package/dist/server/tool-router.js +959 -599
  427. package/dist/server/tool-router.js.map +1 -0
  428. package/dist/server/validation.js +248 -188
  429. package/dist/server/validation.js.map +1 -0
  430. package/dist/server/worker.js +202 -133
  431. package/dist/server/worker.js.map +1 -0
  432. package/dist/setup.d.ts +2 -2
  433. package/dist/setup.js +151 -147
  434. package/dist/setup.js.map +1 -0
  435. package/dist/shared/agent-core.d.ts +115 -26
  436. package/dist/shared/agent-core.js +956 -522
  437. package/dist/shared/agent-core.js.map +1 -0
  438. package/dist/shared/anthropic-types.js +1 -6
  439. package/dist/shared/anthropic-types.js.map +1 -0
  440. package/dist/shared/api-client.d.ts +16 -9
  441. package/dist/shared/api-client.js +419 -327
  442. package/dist/shared/api-client.js.map +1 -0
  443. package/dist/shared/compaction.d.ts +36 -0
  444. package/dist/shared/compaction.js +138 -0
  445. package/dist/shared/compaction.js.map +1 -0
  446. package/dist/shared/constants.js +67 -64
  447. package/dist/shared/constants.js.map +1 -0
  448. package/dist/shared/sse-parser.js +221 -219
  449. package/dist/shared/sse-parser.js.map +1 -0
  450. package/dist/shared/tool-dispatch.d.ts +4 -0
  451. package/dist/shared/tool-dispatch.js +226 -165
  452. package/dist/shared/tool-dispatch.js.map +1 -0
  453. package/dist/shared/types.js +1 -6
  454. package/dist/shared/types.js.map +1 -0
  455. package/dist/types/cli-highlight.d.js +2 -0
  456. package/dist/types/cli-highlight.d.js.map +1 -0
  457. package/dist/types/diff.d.js +2 -0
  458. package/dist/types/diff.d.js.map +1 -0
  459. package/dist/types/pdf-parse.d.js +2 -0
  460. package/dist/types/pdf-parse.d.js.map +1 -0
  461. package/dist/updater.d.ts +1 -1
  462. package/dist/updater.js +118 -92
  463. package/dist/updater.js.map +1 -0
  464. package/dist/webchat/widget.js +227 -380
  465. package/dist/webchat/widget.js.map +1 -0
  466. package/package.json +22 -10
  467. package/vendor/ink/build/ansi-tokenizer.d.ts +38 -0
  468. package/vendor/ink/build/ansi-tokenizer.js +316 -0
  469. package/vendor/ink/build/ansi-tokenizer.js.map +1 -0
  470. package/vendor/ink/build/apply-styles.js +175 -0
  471. package/vendor/ink/build/build-layout.js +77 -0
  472. package/vendor/ink/build/calculate-wrapped-text.js +53 -0
  473. package/vendor/ink/build/colorize.d.ts +3 -0
  474. package/vendor/ink/build/colorize.js +48 -0
  475. package/vendor/ink/build/colorize.js.map +1 -0
  476. package/vendor/ink/build/components/AccessibilityContext.d.ts +3 -0
  477. package/vendor/ink/build/components/AccessibilityContext.js +5 -0
  478. package/vendor/ink/build/components/AccessibilityContext.js.map +1 -0
  479. package/vendor/ink/build/components/App.d.ts +18 -0
  480. package/vendor/ink/build/components/App.js +351 -0
  481. package/vendor/ink/build/components/App.js.map +1 -0
  482. package/vendor/ink/build/components/AppContext.d.ts +15 -0
  483. package/vendor/ink/build/components/AppContext.js +11 -0
  484. package/vendor/ink/build/components/AppContext.js.map +1 -0
  485. package/vendor/ink/build/components/BackgroundContext.d.ts +4 -0
  486. package/vendor/ink/build/components/BackgroundContext.js +3 -0
  487. package/vendor/ink/build/components/BackgroundContext.js.map +1 -0
  488. package/vendor/ink/build/components/Box.d.ts +117 -0
  489. package/vendor/ink/build/components/Box.js +34 -0
  490. package/vendor/ink/build/components/Box.js.map +1 -0
  491. package/vendor/ink/build/components/Color.js +62 -0
  492. package/vendor/ink/build/components/Cursor.d.ts +83 -0
  493. package/vendor/ink/build/components/Cursor.js +53 -0
  494. package/vendor/ink/build/components/Cursor.js.map +1 -0
  495. package/vendor/ink/build/components/CursorContext.d.ts +11 -0
  496. package/vendor/ink/build/components/CursorContext.js +8 -0
  497. package/vendor/ink/build/components/CursorContext.js.map +1 -0
  498. package/vendor/ink/build/components/ErrorBoundary.d.ts +18 -0
  499. package/vendor/ink/build/components/ErrorBoundary.js +23 -0
  500. package/vendor/ink/build/components/ErrorBoundary.js.map +1 -0
  501. package/vendor/ink/build/components/ErrorOverview.d.ts +6 -0
  502. package/vendor/ink/build/components/ErrorOverview.js +84 -0
  503. package/vendor/ink/build/components/ErrorOverview.js.map +1 -0
  504. package/vendor/ink/build/components/FocusContext.d.ts +16 -0
  505. package/vendor/ink/build/components/FocusContext.js +17 -0
  506. package/vendor/ink/build/components/FocusContext.js.map +1 -0
  507. package/vendor/ink/build/components/Newline.d.ts +13 -0
  508. package/vendor/ink/build/components/Newline.js +8 -0
  509. package/vendor/ink/build/components/Newline.js.map +1 -0
  510. package/vendor/ink/build/components/Spacer.d.ts +7 -0
  511. package/vendor/ink/build/components/Spacer.js +11 -0
  512. package/vendor/ink/build/components/Spacer.js.map +1 -0
  513. package/vendor/ink/build/components/Static.d.ts +24 -0
  514. package/vendor/ink/build/components/Static.js +28 -0
  515. package/vendor/ink/build/components/Static.js.map +1 -0
  516. package/vendor/ink/build/components/StderrContext.d.ts +15 -0
  517. package/vendor/ink/build/components/StderrContext.js +13 -0
  518. package/vendor/ink/build/components/StderrContext.js.map +1 -0
  519. package/vendor/ink/build/components/StdinContext.d.ts +22 -0
  520. package/vendor/ink/build/components/StdinContext.js +19 -0
  521. package/vendor/ink/build/components/StdinContext.js.map +1 -0
  522. package/vendor/ink/build/components/StdoutContext.d.ts +15 -0
  523. package/vendor/ink/build/components/StdoutContext.js +13 -0
  524. package/vendor/ink/build/components/StdoutContext.js.map +1 -0
  525. package/vendor/ink/build/components/Text.d.ts +55 -0
  526. package/vendor/ink/build/components/Text.js +50 -0
  527. package/vendor/ink/build/components/Text.js.map +1 -0
  528. package/vendor/ink/build/components/Transform.d.ts +16 -0
  529. package/vendor/ink/build/components/Transform.js +15 -0
  530. package/vendor/ink/build/components/Transform.js.map +1 -0
  531. package/vendor/ink/build/cursor-helpers.d.ts +38 -0
  532. package/vendor/ink/build/cursor-helpers.js +56 -0
  533. package/vendor/ink/build/cursor-helpers.js.map +1 -0
  534. package/vendor/ink/build/devtools-window-polyfill.d.ts +1 -0
  535. package/vendor/ink/build/devtools-window-polyfill.js +65 -0
  536. package/vendor/ink/build/devtools-window-polyfill.js.map +1 -0
  537. package/vendor/ink/build/devtools.d.ts +1 -0
  538. package/vendor/ink/build/devtools.js +11 -0
  539. package/vendor/ink/build/devtools.js.map +1 -0
  540. package/vendor/ink/build/dom.d.ts +56 -0
  541. package/vendor/ink/build/dom.js +124 -0
  542. package/vendor/ink/build/dom.js.map +1 -0
  543. package/vendor/ink/build/experimental/apply-style.js +140 -0
  544. package/vendor/ink/build/experimental/dom.js +123 -0
  545. package/vendor/ink/build/experimental/output.js +91 -0
  546. package/vendor/ink/build/experimental/reconciler.js +141 -0
  547. package/vendor/ink/build/experimental/renderer.js +81 -0
  548. package/vendor/ink/build/get-max-width.d.ts +3 -0
  549. package/vendor/ink/build/get-max-width.js +10 -0
  550. package/vendor/ink/build/get-max-width.js.map +1 -0
  551. package/vendor/ink/build/hooks/use-app.d.ts +5 -0
  552. package/vendor/ink/build/hooks/use-app.js +8 -0
  553. package/vendor/ink/build/hooks/use-app.js.map +1 -0
  554. package/vendor/ink/build/hooks/use-cursor.d.ts +12 -0
  555. package/vendor/ink/build/hooks/use-cursor.js +29 -0
  556. package/vendor/ink/build/hooks/use-cursor.js.map +1 -0
  557. package/vendor/ink/build/hooks/use-focus-manager.d.ts +28 -0
  558. package/vendor/ink/build/hooks/use-focus-manager.js +17 -0
  559. package/vendor/ink/build/hooks/use-focus-manager.js.map +1 -0
  560. package/vendor/ink/build/hooks/use-focus.d.ts +29 -0
  561. package/vendor/ink/build/hooks/use-focus.js +42 -0
  562. package/vendor/ink/build/hooks/use-focus.js.map +1 -0
  563. package/vendor/ink/build/hooks/use-input.d.ts +131 -0
  564. package/vendor/ink/build/hooks/use-input.js +124 -0
  565. package/vendor/ink/build/hooks/use-input.js.map +1 -0
  566. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.d.ts +5 -0
  567. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.js +11 -0
  568. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.js.map +1 -0
  569. package/vendor/ink/build/hooks/use-stderr.d.ts +5 -0
  570. package/vendor/ink/build/hooks/use-stderr.js +8 -0
  571. package/vendor/ink/build/hooks/use-stderr.js.map +1 -0
  572. package/vendor/ink/build/hooks/use-stdin.d.ts +5 -0
  573. package/vendor/ink/build/hooks/use-stdin.js +8 -0
  574. package/vendor/ink/build/hooks/use-stdin.js.map +1 -0
  575. package/vendor/ink/build/hooks/use-stdout.d.ts +5 -0
  576. package/vendor/ink/build/hooks/use-stdout.js +8 -0
  577. package/vendor/ink/build/hooks/use-stdout.js.map +1 -0
  578. package/vendor/ink/build/hooks/useInput.js +38 -0
  579. package/vendor/ink/build/index.d.ts +34 -0
  580. package/vendor/ink/build/index.js +20 -0
  581. package/vendor/ink/build/index.js.map +1 -0
  582. package/vendor/ink/build/ink.d.ts +90 -0
  583. package/vendor/ink/build/ink.js +654 -0
  584. package/vendor/ink/build/ink.js.map +1 -0
  585. package/vendor/ink/build/input-parser.d.ts +7 -0
  586. package/vendor/ink/build/input-parser.js +154 -0
  587. package/vendor/ink/build/input-parser.js.map +1 -0
  588. package/vendor/ink/build/instance.js +205 -0
  589. package/vendor/ink/build/instances.d.ts +3 -0
  590. package/vendor/ink/build/instances.js +8 -0
  591. package/vendor/ink/build/instances.js.map +1 -0
  592. package/vendor/ink/build/kitty-keyboard.d.ts +23 -0
  593. package/vendor/ink/build/kitty-keyboard.js +32 -0
  594. package/vendor/ink/build/kitty-keyboard.js.map +1 -0
  595. package/vendor/ink/build/layout.d.ts +7 -0
  596. package/vendor/ink/build/layout.js +33 -0
  597. package/vendor/ink/build/layout.js.map +1 -0
  598. package/vendor/ink/build/log-update.d.ts +19 -0
  599. package/vendor/ink/build/log-update.js +243 -0
  600. package/vendor/ink/build/log-update.js.map +1 -0
  601. package/vendor/ink/build/measure-element.d.ts +16 -0
  602. package/vendor/ink/build/measure-element.js +9 -0
  603. package/vendor/ink/build/measure-element.js.map +1 -0
  604. package/vendor/ink/build/measure-text.d.ts +6 -0
  605. package/vendor/ink/build/measure-text.js +21 -0
  606. package/vendor/ink/build/measure-text.js.map +1 -0
  607. package/vendor/ink/build/options.d.ts +52 -0
  608. package/vendor/ink/build/options.js +2 -0
  609. package/vendor/ink/build/options.js.map +1 -0
  610. package/vendor/ink/build/output.d.ts +35 -0
  611. package/vendor/ink/build/output.js +183 -0
  612. package/vendor/ink/build/output.js.map +1 -0
  613. package/vendor/ink/build/parse-keypress.d.ts +22 -0
  614. package/vendor/ink/build/parse-keypress.js +493 -0
  615. package/vendor/ink/build/parse-keypress.js.map +1 -0
  616. package/vendor/ink/build/reconciler.d.ts +4 -0
  617. package/vendor/ink/build/reconciler.js +274 -0
  618. package/vendor/ink/build/reconciler.js.map +1 -0
  619. package/vendor/ink/build/render-background.d.ts +4 -0
  620. package/vendor/ink/build/render-background.js +25 -0
  621. package/vendor/ink/build/render-background.js.map +1 -0
  622. package/vendor/ink/build/render-border.d.ts +4 -0
  623. package/vendor/ink/build/render-border.js +73 -0
  624. package/vendor/ink/build/render-border.js.map +1 -0
  625. package/vendor/ink/build/render-node-to-output.d.ts +14 -0
  626. package/vendor/ink/build/render-node-to-output.js +147 -0
  627. package/vendor/ink/build/render-node-to-output.js.map +1 -0
  628. package/vendor/ink/build/render-to-string.d.ts +38 -0
  629. package/vendor/ink/build/render-to-string.js +115 -0
  630. package/vendor/ink/build/render-to-string.js.map +1 -0
  631. package/vendor/ink/build/render.d.ts +121 -0
  632. package/vendor/ink/build/render.js +55 -0
  633. package/vendor/ink/build/render.js.map +1 -0
  634. package/vendor/ink/build/renderer.d.ts +8 -0
  635. package/vendor/ink/build/renderer.js +55 -0
  636. package/vendor/ink/build/renderer.js.map +1 -0
  637. package/vendor/ink/build/sanitize-ansi.d.ts +2 -0
  638. package/vendor/ink/build/sanitize-ansi.js +27 -0
  639. package/vendor/ink/build/sanitize-ansi.js.map +1 -0
  640. package/vendor/ink/build/screen-reader-update.d.ts +13 -0
  641. package/vendor/ink/build/screen-reader-update.js +38 -0
  642. package/vendor/ink/build/screen-reader-update.js.map +1 -0
  643. package/vendor/ink/build/squash-text-nodes.d.ts +3 -0
  644. package/vendor/ink/build/squash-text-nodes.js +36 -0
  645. package/vendor/ink/build/squash-text-nodes.js.map +1 -0
  646. package/vendor/ink/build/styles.d.ts +240 -0
  647. package/vendor/ink/build/styles.js +232 -0
  648. package/vendor/ink/build/styles.js.map +1 -0
  649. package/vendor/ink/build/utils.d.ts +2 -0
  650. package/vendor/ink/build/utils.js +4 -0
  651. package/vendor/ink/build/utils.js.map +1 -0
  652. package/vendor/ink/build/wrap-text.d.ts +3 -0
  653. package/vendor/ink/build/wrap-text.js +31 -0
  654. package/vendor/ink/build/wrap-text.js.map +1 -0
  655. package/vendor/ink/build/write-synchronized.d.ts +4 -0
  656. package/vendor/ink/build/write-synchronized.js +7 -0
  657. package/vendor/ink/build/write-synchronized.js.map +1 -0
  658. package/vendor/ink/license +10 -0
  659. package/vendor/ink/node_modules/@types/node/LICENSE +21 -0
  660. package/vendor/ink/node_modules/@types/node/README.md +15 -0
  661. package/vendor/ink/node_modules/@types/node/assert/strict.d.ts +105 -0
  662. package/vendor/ink/node_modules/@types/node/assert.d.ts +955 -0
  663. package/vendor/ink/node_modules/@types/node/async_hooks.d.ts +623 -0
  664. package/vendor/ink/node_modules/@types/node/buffer.buffer.d.ts +466 -0
  665. package/vendor/ink/node_modules/@types/node/buffer.d.ts +1810 -0
  666. package/vendor/ink/node_modules/@types/node/child_process.d.ts +1428 -0
  667. package/vendor/ink/node_modules/@types/node/cluster.d.ts +486 -0
  668. package/vendor/ink/node_modules/@types/node/compatibility/iterators.d.ts +21 -0
  669. package/vendor/ink/node_modules/@types/node/console.d.ts +151 -0
  670. package/vendor/ink/node_modules/@types/node/constants.d.ts +20 -0
  671. package/vendor/ink/node_modules/@types/node/crypto.d.ts +4065 -0
  672. package/vendor/ink/node_modules/@types/node/dgram.d.ts +564 -0
  673. package/vendor/ink/node_modules/@types/node/diagnostics_channel.d.ts +576 -0
  674. package/vendor/ink/node_modules/@types/node/dns/promises.d.ts +503 -0
  675. package/vendor/ink/node_modules/@types/node/dns.d.ts +922 -0
  676. package/vendor/ink/node_modules/@types/node/domain.d.ts +166 -0
  677. package/vendor/ink/node_modules/@types/node/events.d.ts +1054 -0
  678. package/vendor/ink/node_modules/@types/node/fs/promises.d.ts +1329 -0
  679. package/vendor/ink/node_modules/@types/node/fs.d.ts +4676 -0
  680. package/vendor/ink/node_modules/@types/node/globals.d.ts +150 -0
  681. package/vendor/ink/node_modules/@types/node/globals.typedarray.d.ts +101 -0
  682. package/vendor/ink/node_modules/@types/node/http.d.ts +2167 -0
  683. package/vendor/ink/node_modules/@types/node/http2.d.ts +2480 -0
  684. package/vendor/ink/node_modules/@types/node/https.d.ts +405 -0
  685. package/vendor/ink/node_modules/@types/node/index.d.ts +115 -0
  686. package/vendor/ink/node_modules/@types/node/inspector/promises.d.ts +41 -0
  687. package/vendor/ink/node_modules/@types/node/inspector.d.ts +224 -0
  688. package/vendor/ink/node_modules/@types/node/inspector.generated.d.ts +4226 -0
  689. package/vendor/ink/node_modules/@types/node/module.d.ts +819 -0
  690. package/vendor/ink/node_modules/@types/node/net.d.ts +933 -0
  691. package/vendor/ink/node_modules/@types/node/os.d.ts +507 -0
  692. package/vendor/ink/node_modules/@types/node/package.json +155 -0
  693. package/vendor/ink/node_modules/@types/node/path/posix.d.ts +8 -0
  694. package/vendor/ink/node_modules/@types/node/path/win32.d.ts +8 -0
  695. package/vendor/ink/node_modules/@types/node/path.d.ts +187 -0
  696. package/vendor/ink/node_modules/@types/node/perf_hooks.d.ts +643 -0
  697. package/vendor/ink/node_modules/@types/node/process.d.ts +2156 -0
  698. package/vendor/ink/node_modules/@types/node/punycode.d.ts +117 -0
  699. package/vendor/ink/node_modules/@types/node/querystring.d.ts +152 -0
  700. package/vendor/ink/node_modules/@types/node/quic.d.ts +910 -0
  701. package/vendor/ink/node_modules/@types/node/readline/promises.d.ts +161 -0
  702. package/vendor/ink/node_modules/@types/node/readline.d.ts +541 -0
  703. package/vendor/ink/node_modules/@types/node/repl.d.ts +415 -0
  704. package/vendor/ink/node_modules/@types/node/sea.d.ts +162 -0
  705. package/vendor/ink/node_modules/@types/node/sqlite.d.ts +955 -0
  706. package/vendor/ink/node_modules/@types/node/stream/consumers.d.ts +38 -0
  707. package/vendor/ink/node_modules/@types/node/stream/promises.d.ts +211 -0
  708. package/vendor/ink/node_modules/@types/node/stream/web.d.ts +296 -0
  709. package/vendor/ink/node_modules/@types/node/stream.d.ts +1760 -0
  710. package/vendor/ink/node_modules/@types/node/string_decoder.d.ts +67 -0
  711. package/vendor/ink/node_modules/@types/node/test/reporters.d.ts +96 -0
  712. package/vendor/ink/node_modules/@types/node/test.d.ts +2240 -0
  713. package/vendor/ink/node_modules/@types/node/timers/promises.d.ts +108 -0
  714. package/vendor/ink/node_modules/@types/node/timers.d.ts +159 -0
  715. package/vendor/ink/node_modules/@types/node/tls.d.ts +1198 -0
  716. package/vendor/ink/node_modules/@types/node/trace_events.d.ts +197 -0
  717. package/vendor/ink/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +462 -0
  718. package/vendor/ink/node_modules/@types/node/ts5.6/compatibility/float16array.d.ts +71 -0
  719. package/vendor/ink/node_modules/@types/node/ts5.6/globals.typedarray.d.ts +36 -0
  720. package/vendor/ink/node_modules/@types/node/ts5.6/index.d.ts +117 -0
  721. package/vendor/ink/node_modules/@types/node/ts5.7/compatibility/float16array.d.ts +72 -0
  722. package/vendor/ink/node_modules/@types/node/ts5.7/index.d.ts +117 -0
  723. package/vendor/ink/node_modules/@types/node/tty.d.ts +250 -0
  724. package/vendor/ink/node_modules/@types/node/url.d.ts +519 -0
  725. package/vendor/ink/node_modules/@types/node/util/types.d.ts +558 -0
  726. package/vendor/ink/node_modules/@types/node/util.d.ts +1662 -0
  727. package/vendor/ink/node_modules/@types/node/v8.d.ts +983 -0
  728. package/vendor/ink/node_modules/@types/node/vm.d.ts +1208 -0
  729. package/vendor/ink/node_modules/@types/node/wasi.d.ts +202 -0
  730. package/vendor/ink/node_modules/@types/node/web-globals/abortcontroller.d.ts +59 -0
  731. package/vendor/ink/node_modules/@types/node/web-globals/blob.d.ts +23 -0
  732. package/vendor/ink/node_modules/@types/node/web-globals/console.d.ts +9 -0
  733. package/vendor/ink/node_modules/@types/node/web-globals/crypto.d.ts +39 -0
  734. package/vendor/ink/node_modules/@types/node/web-globals/domexception.d.ts +68 -0
  735. package/vendor/ink/node_modules/@types/node/web-globals/encoding.d.ts +11 -0
  736. package/vendor/ink/node_modules/@types/node/web-globals/events.d.ts +106 -0
  737. package/vendor/ink/node_modules/@types/node/web-globals/fetch.d.ts +69 -0
  738. package/vendor/ink/node_modules/@types/node/web-globals/importmeta.d.ts +13 -0
  739. package/vendor/ink/node_modules/@types/node/web-globals/messaging.d.ts +23 -0
  740. package/vendor/ink/node_modules/@types/node/web-globals/navigator.d.ts +25 -0
  741. package/vendor/ink/node_modules/@types/node/web-globals/performance.d.ts +45 -0
  742. package/vendor/ink/node_modules/@types/node/web-globals/storage.d.ts +24 -0
  743. package/vendor/ink/node_modules/@types/node/web-globals/streams.d.ts +115 -0
  744. package/vendor/ink/node_modules/@types/node/web-globals/timers.d.ts +44 -0
  745. package/vendor/ink/node_modules/@types/node/web-globals/url.d.ts +24 -0
  746. package/vendor/ink/node_modules/@types/node/worker_threads.d.ts +717 -0
  747. package/vendor/ink/node_modules/@types/node/zlib.d.ts +618 -0
  748. package/vendor/ink/node_modules/node-pty/LICENSE +69 -0
  749. package/vendor/ink/node_modules/node-pty/README.md +164 -0
  750. package/vendor/ink/node_modules/node-pty/binding.gyp +150 -0
  751. package/vendor/ink/node_modules/node-pty/lib/conpty_console_list_agent.js +25 -0
  752. package/vendor/ink/node_modules/node-pty/lib/eventEmitter2.js +47 -0
  753. package/vendor/ink/node_modules/node-pty/lib/index.js +52 -0
  754. package/vendor/ink/node_modules/node-pty/lib/interfaces.js +7 -0
  755. package/vendor/ink/node_modules/node-pty/lib/shared/conout.js +11 -0
  756. package/vendor/ink/node_modules/node-pty/lib/terminal.js +190 -0
  757. package/vendor/ink/node_modules/node-pty/lib/types.js +7 -0
  758. package/vendor/ink/node_modules/node-pty/lib/unixTerminal.js +349 -0
  759. package/vendor/ink/node_modules/node-pty/lib/utils.js +39 -0
  760. package/vendor/ink/node_modules/node-pty/lib/windowsConoutConnection.js +125 -0
  761. package/vendor/ink/node_modules/node-pty/lib/windowsPtyAgent.js +287 -0
  762. package/vendor/ink/node_modules/node-pty/lib/windowsTerminal.js +201 -0
  763. package/vendor/ink/node_modules/node-pty/lib/worker/conoutSocketWorker.js +22 -0
  764. package/vendor/ink/node_modules/node-pty/package.json +65 -0
  765. package/vendor/ink/node_modules/node-pty/prebuilds/darwin-arm64/pty.node +0 -0
  766. package/vendor/ink/node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper +0 -0
  767. package/vendor/ink/node_modules/node-pty/prebuilds/darwin-x64/pty.node +0 -0
  768. package/vendor/ink/node_modules/node-pty/prebuilds/darwin-x64/spawn-helper +0 -0
  769. package/vendor/ink/node_modules/node-pty/prebuilds/linux-arm64/pty.node +0 -0
  770. package/vendor/ink/node_modules/node-pty/prebuilds/linux-x64/pty.node +0 -0
  771. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty/OpenConsole.exe +0 -0
  772. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty/conpty.dll +0 -0
  773. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty.node +0 -0
  774. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty.pdb +0 -0
  775. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty_console_list.node +0 -0
  776. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty_console_list.pdb +0 -0
  777. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty/OpenConsole.exe +0 -0
  778. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty/conpty.dll +0 -0
  779. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty.node +0 -0
  780. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty.pdb +0 -0
  781. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty_console_list.node +0 -0
  782. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty_console_list.pdb +0 -0
  783. package/vendor/ink/node_modules/node-pty/scripts/post-install.js +76 -0
  784. package/vendor/ink/node_modules/node-pty/scripts/prebuild.js +34 -0
  785. package/vendor/ink/node_modules/node-pty/src/unix/pty.cc +875 -0
  786. package/vendor/ink/node_modules/node-pty/src/unix/spawn-helper.cc +23 -0
  787. package/vendor/ink/node_modules/node-pty/src/win/conpty.cc +582 -0
  788. package/vendor/ink/node_modules/node-pty/src/win/conpty.h +41 -0
  789. package/vendor/ink/node_modules/node-pty/src/win/conpty_console_list.cc +44 -0
  790. package/vendor/ink/node_modules/node-pty/src/win/path_util.cc +95 -0
  791. package/vendor/ink/node_modules/node-pty/src/win/path_util.h +26 -0
  792. package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-arm64/OpenConsole.exe +0 -0
  793. package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-arm64/conpty.dll +0 -0
  794. package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-x64/OpenConsole.exe +0 -0
  795. package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-x64/conpty.dll +0 -0
  796. package/vendor/ink/node_modules/node-pty/typings/node-pty.d.ts +215 -0
  797. package/vendor/ink/node_modules/undici-types/LICENSE +21 -0
  798. package/vendor/ink/node_modules/undici-types/README.md +6 -0
  799. package/vendor/ink/node_modules/undici-types/agent.d.ts +32 -0
  800. package/vendor/ink/node_modules/undici-types/api.d.ts +43 -0
  801. package/vendor/ink/node_modules/undici-types/balanced-pool.d.ts +30 -0
  802. package/vendor/ink/node_modules/undici-types/cache-interceptor.d.ts +173 -0
  803. package/vendor/ink/node_modules/undici-types/cache.d.ts +36 -0
  804. package/vendor/ink/node_modules/undici-types/client-stats.d.ts +15 -0
  805. package/vendor/ink/node_modules/undici-types/client.d.ts +108 -0
  806. package/vendor/ink/node_modules/undici-types/connector.d.ts +34 -0
  807. package/vendor/ink/node_modules/undici-types/content-type.d.ts +21 -0
  808. package/vendor/ink/node_modules/undici-types/cookies.d.ts +30 -0
  809. package/vendor/ink/node_modules/undici-types/diagnostics-channel.d.ts +74 -0
  810. package/vendor/ink/node_modules/undici-types/dispatcher.d.ts +276 -0
  811. package/vendor/ink/node_modules/undici-types/env-http-proxy-agent.d.ts +22 -0
  812. package/vendor/ink/node_modules/undici-types/errors.d.ts +161 -0
  813. package/vendor/ink/node_modules/undici-types/eventsource.d.ts +66 -0
  814. package/vendor/ink/node_modules/undici-types/fetch.d.ts +211 -0
  815. package/vendor/ink/node_modules/undici-types/formdata.d.ts +108 -0
  816. package/vendor/ink/node_modules/undici-types/global-dispatcher.d.ts +9 -0
  817. package/vendor/ink/node_modules/undici-types/global-origin.d.ts +7 -0
  818. package/vendor/ink/node_modules/undici-types/h2c-client.d.ts +73 -0
  819. package/vendor/ink/node_modules/undici-types/handlers.d.ts +15 -0
  820. package/vendor/ink/node_modules/undici-types/header.d.ts +160 -0
  821. package/vendor/ink/node_modules/undici-types/index.d.ts +88 -0
  822. package/vendor/ink/node_modules/undici-types/interceptors.d.ts +73 -0
  823. package/vendor/ink/node_modules/undici-types/mock-agent.d.ts +68 -0
  824. package/vendor/ink/node_modules/undici-types/mock-call-history.d.ts +111 -0
  825. package/vendor/ink/node_modules/undici-types/mock-client.d.ts +27 -0
  826. package/vendor/ink/node_modules/undici-types/mock-errors.d.ts +12 -0
  827. package/vendor/ink/node_modules/undici-types/mock-interceptor.d.ts +94 -0
  828. package/vendor/ink/node_modules/undici-types/mock-pool.d.ts +27 -0
  829. package/vendor/ink/node_modules/undici-types/package.json +55 -0
  830. package/vendor/ink/node_modules/undici-types/patch.d.ts +29 -0
  831. package/vendor/ink/node_modules/undici-types/pool-stats.d.ts +19 -0
  832. package/vendor/ink/node_modules/undici-types/pool.d.ts +41 -0
  833. package/vendor/ink/node_modules/undici-types/proxy-agent.d.ts +29 -0
  834. package/vendor/ink/node_modules/undici-types/readable.d.ts +68 -0
  835. package/vendor/ink/node_modules/undici-types/retry-agent.d.ts +8 -0
  836. package/vendor/ink/node_modules/undici-types/retry-handler.d.ts +125 -0
  837. package/vendor/ink/node_modules/undici-types/round-robin-pool.d.ts +41 -0
  838. package/vendor/ink/node_modules/undici-types/snapshot-agent.d.ts +109 -0
  839. package/vendor/ink/node_modules/undici-types/util.d.ts +18 -0
  840. package/vendor/ink/node_modules/undici-types/utility.d.ts +7 -0
  841. package/vendor/ink/node_modules/undici-types/webidl.d.ts +341 -0
  842. package/vendor/ink/node_modules/undici-types/websocket.d.ts +186 -0
  843. package/vendor/ink/package.json +201 -0
  844. package/vendor/ink/readme.md +2636 -0
  845. package/bin/swag-agent.js +0 -9
  846. package/dist/server/lib/pg-rate-limiter.d.ts +0 -21
  847. package/dist/server/lib/pg-rate-limiter.js +0 -86
@@ -1,859 +1,1022 @@
1
1
  // server/lib/pdf-renderer.ts — PDF template rendering engine
2
2
  // Processes pdf_templates layout → HTML, with generation rules, calculations, and validation.
3
+
3
4
  import { fillTemplate } from "./utils.js";
5
+
6
+ // ============================================================================
7
+ // 1. GENERATION RULES — auto-fill missing fields from pdf_templates.generation_rules
8
+ // ============================================================================
9
+
4
10
  function resolvePattern(pattern) {
5
- const now = new Date();
6
- return pattern
7
- .replace("{YYYYMMDD}", now.toISOString().slice(0, 10).replace(/-/g, ""))
8
- .replace("{YYYY}", String(now.getFullYear()))
9
- .replace("{MM}", String(now.getMonth() + 1).padStart(2, "0"))
10
- .replace("{DD}", String(now.getDate()).padStart(2, "0"))
11
- .replace(/\{PREFIX\}/g, "")
12
- .replace(/\{RANDOM:(\d+)\}/g, (_, len) => {
13
- const n = parseInt(len);
14
- let s = "";
15
- for (let i = 0; i < n; i++)
16
- s += Math.floor(Math.random() * 10);
17
- return s;
18
- })
19
- .replace(/\{ALPHA:(\d+)\}/g, (_, len) => {
20
- const n = parseInt(len);
21
- const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
22
- let s = "";
23
- for (let i = 0; i < n; i++)
24
- s += chars[Math.floor(Math.random() * 26)];
25
- return s;
26
- });
11
+ const now = new Date();
12
+ return pattern.replace("{YYYYMMDD}", now.toISOString().slice(0, 10).replace(/-/g, "")).replace("{YYYY}", String(now.getFullYear())).replace("{MM}", String(now.getMonth() + 1).padStart(2, "0")).replace("{DD}", String(now.getDate()).padStart(2, "0")).replace(/\{PREFIX\}/g, "").replace(/\{RANDOM:(\d+)\}/g, (_, len) => {
13
+ const n = parseInt(len);
14
+ let s = "";
15
+ for (let i = 0; i < n; i++) s += Math.floor(Math.random() * 10);
16
+ return s;
17
+ }).replace(/\{ALPHA:(\d+)\}/g, (_, len) => {
18
+ const n = parseInt(len);
19
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
20
+ let s = "";
21
+ for (let i = 0; i < n; i++) s += chars[Math.floor(Math.random() * 26)];
22
+ return s;
23
+ });
27
24
  }
28
25
  function normalizeGenerationRules(raw) {
29
- if (!raw)
30
- return [];
31
- if (Array.isArray(raw))
32
- return raw;
33
- // Object-keyed format from DB: { "moisture": { "type": "random_range", "config": { "min": 8.5, ... } } }
34
- // Convert to array format: [{ field: "moisture", type: "random_range", min: 8.5, ... }]
35
- if (typeof raw === "object") {
36
- const rules = [];
37
- for (const [field, def] of Object.entries(raw)) {
38
- if (!def || typeof def !== "object")
39
- continue;
40
- const cfg = def.config || {};
41
- const rule = {
42
- field,
43
- type: def.type,
44
- pattern: (cfg.pattern || cfg.prefix) ? `${cfg.prefix || ""}${cfg.pattern || ""}` : undefined,
45
- choices: cfg.choices,
46
- resolve_pattern: cfg.resolve_pattern,
47
- min: cfg.min,
48
- max: cfg.max,
49
- decimals: cfg.decimals,
50
- base_field: cfg.base,
51
- value: cfg.value,
52
- };
53
- // relative_date: offset can be { days: [1, 2] } or { days: 5 }
54
- if (cfg.offset) {
55
- if (cfg.offset.days !== undefined) {
56
- rule.offset = Array.isArray(cfg.offset.days) ? cfg.offset.days : cfg.offset.days;
57
- }
58
- else {
59
- rule.offset = cfg.offset;
60
- }
61
- }
62
- rules.push(rule);
26
+ if (!raw) return [];
27
+ if (Array.isArray(raw)) return raw;
28
+
29
+ // Object-keyed format from DB: { "moisture": { "type": "random_range", "config": { "min": 8.5, ... } } }
30
+ // Convert to array format: [{ field: "moisture", type: "random_range", min: 8.5, ... }]
31
+ if (typeof raw === "object") {
32
+ const rules = [];
33
+ for (const [field, def] of Object.entries(raw)) {
34
+ if (!def || typeof def !== "object") continue;
35
+ const cfg = def.config || {};
36
+ const rule = {
37
+ field,
38
+ type: def.type,
39
+ pattern: cfg.pattern || cfg.prefix ? `${cfg.prefix || ""}${cfg.pattern || ""}` : undefined,
40
+ choices: cfg.choices,
41
+ resolve_pattern: cfg.resolve_pattern,
42
+ min: cfg.min,
43
+ max: cfg.max,
44
+ decimals: cfg.decimals,
45
+ base_field: cfg.base,
46
+ value: cfg.value
47
+ };
48
+ // relative_date: offset can be { days: [1, 2] } or { days: 5 }
49
+ if (cfg.offset) {
50
+ if (cfg.offset.days !== undefined) {
51
+ rule.offset = Array.isArray(cfg.offset.days) ? cfg.offset.days : cfg.offset.days;
52
+ } else {
53
+ rule.offset = cfg.offset;
63
54
  }
64
- return rules;
55
+ }
56
+ rules.push(rule);
65
57
  }
66
- return [];
58
+ return rules;
59
+ }
60
+ return [];
67
61
  }
68
62
  export function applyGenerationRules(rules, data) {
69
- const normalized = normalizeGenerationRules(rules);
70
- if (!normalized.length)
71
- return data;
72
- const result = { ...data };
73
- // Multi-pass (max 4) to resolve chained dependencies (e.g. dateCollected → dateReceived → dateTested)
74
- for (let pass = 0; pass < 4; pass++) {
75
- let resolved = 0;
76
- for (const rule of normalized) {
77
- // User overrides win — skip fields already provided
78
- if (result[rule.field] !== undefined && result[rule.field] !== null)
79
- continue;
80
- // For relative_date, skip if base field isn't resolved yet
81
- if (rule.type === "relative_date" && rule.base_field) {
82
- if (result[rule.base_field] === undefined || result[rule.base_field] === null)
83
- continue;
63
+ const normalized = normalizeGenerationRules(rules);
64
+ if (!normalized.length) return data;
65
+ const result = {
66
+ ...data
67
+ };
68
+
69
+ // Multi-pass (max 4) to resolve chained dependencies (e.g. dateCollected → dateReceived → dateTested)
70
+ for (let pass = 0; pass < 4; pass++) {
71
+ let resolved = 0;
72
+ for (const rule of normalized) {
73
+ // User overrides win — skip fields already provided
74
+ if (result[rule.field] !== undefined && result[rule.field] !== null) continue;
75
+
76
+ // For relative_date, skip if base field isn't resolved yet
77
+ if (rule.type === "relative_date" && rule.base_field) {
78
+ if (result[rule.base_field] === undefined || result[rule.base_field] === null) continue;
79
+ }
80
+ switch (rule.type) {
81
+ case "pattern":
82
+ {
83
+ result[rule.field] = resolvePattern(rule.pattern || "");
84
+ resolved++;
85
+ break;
86
+ }
87
+ case "random_choice":
88
+ {
89
+ if (!rule.choices?.length) break;
90
+ const pick = rule.choices[Math.floor(Math.random() * rule.choices.length)];
91
+ result[rule.field] = rule.resolve_pattern ? resolvePattern(pick) : pick;
92
+ resolved++;
93
+ break;
94
+ }
95
+ case "random_range":
96
+ {
97
+ const min = rule.min ?? 0;
98
+ const max = rule.max ?? 100;
99
+ const raw = min + Math.random() * (max - min);
100
+ const dec = rule.decimals ?? 2;
101
+ result[rule.field] = parseFloat(raw.toFixed(dec));
102
+ resolved++;
103
+ break;
104
+ }
105
+ case "relative_date":
106
+ {
107
+ const baseVal = result[rule.base_field || ""];
108
+ const base = baseVal ? new Date(baseVal) : new Date();
109
+ let offsetDays;
110
+ if (Array.isArray(rule.offset)) {
111
+ const [lo, hi] = rule.offset;
112
+ offsetDays = lo + Math.floor(Math.random() * (hi - lo + 1));
113
+ } else {
114
+ offsetDays = rule.offset ?? 0;
84
115
  }
85
- switch (rule.type) {
86
- case "pattern": {
87
- result[rule.field] = resolvePattern(rule.pattern || "");
88
- resolved++;
89
- break;
90
- }
91
- case "random_choice": {
92
- if (!rule.choices?.length)
93
- break;
94
- const pick = rule.choices[Math.floor(Math.random() * rule.choices.length)];
95
- result[rule.field] = rule.resolve_pattern ? resolvePattern(pick) : pick;
96
- resolved++;
97
- break;
98
- }
99
- case "random_range": {
100
- const min = rule.min ?? 0;
101
- const max = rule.max ?? 100;
102
- const raw = min + Math.random() * (max - min);
103
- const dec = rule.decimals ?? 2;
104
- result[rule.field] = parseFloat(raw.toFixed(dec));
105
- resolved++;
106
- break;
107
- }
108
- case "relative_date": {
109
- const baseVal = result[rule.base_field || ""];
110
- const base = baseVal ? new Date(baseVal) : new Date();
111
- let offsetDays;
112
- if (Array.isArray(rule.offset)) {
113
- const [lo, hi] = rule.offset;
114
- offsetDays = lo + Math.floor(Math.random() * (hi - lo + 1));
115
- }
116
- else {
117
- offsetDays = rule.offset ?? 0;
118
- }
119
- const target = new Date(base);
120
- target.setDate(target.getDate() + offsetDays);
121
- result[rule.field] = target.toISOString().slice(0, 10);
122
- resolved++;
123
- break;
124
- }
125
- case "constant": {
126
- const val = rule.value;
127
- if (val === "TODAY") {
128
- result[rule.field] = new Date().toISOString().slice(0, 10);
129
- }
130
- else {
131
- result[rule.field] = val;
132
- }
133
- resolved++;
134
- break;
135
- }
116
+ const target = new Date(base);
117
+ target.setDate(target.getDate() + offsetDays);
118
+ result[rule.field] = target.toISOString().slice(0, 10);
119
+ resolved++;
120
+ break;
121
+ }
122
+ case "constant":
123
+ {
124
+ const val = rule.value;
125
+ if (val === "TODAY") {
126
+ result[rule.field] = new Date().toISOString().slice(0, 10);
127
+ } else {
128
+ result[rule.field] = val;
136
129
  }
137
- }
138
- if (resolved === 0)
139
- break; // No more fields to resolve
130
+ resolved++;
131
+ break;
132
+ }
133
+ }
140
134
  }
141
- return result;
135
+ if (resolved === 0) break; // No more fields to resolve
136
+ }
137
+ return result;
142
138
  }
139
+
140
+ // ============================================================================
141
+ // 2. CANNABINOID DATA GENERATOR — from document_profiles config
142
+ // ============================================================================
143
+
143
144
  export function generateCannabinoidData(profileConfig, constants) {
144
- if (!profileConfig)
145
- return [];
146
- const rows = [];
147
- // Find LOD/LOQ constants — try common keys
148
- const lodLoqKey = Object.keys(constants).find(k => k.startsWith("LOD_LOQ"));
149
- const lodLoqMap = (lodLoqKey ? constants[lodLoqKey] : {});
150
- const defaultLod = 0.01;
151
- const defaultLoq = 0.03;
152
- for (const [analyte, cfg] of Object.entries(profileConfig)) {
153
- const lodLoq = lodLoqMap[analyte] || {};
154
- const lod = lodLoq.LOD ?? defaultLod;
155
- const loq = lodLoq.LOQ ?? defaultLoq;
156
- if (cfg.nd) {
157
- rows.push({ name: analyte, result: "ND", percentWeight: 0, mgPerG: 0, lod, loq });
158
- }
159
- else {
160
- const min = cfg.min ?? 0;
161
- const max = cfg.max ?? 100;
162
- const percentWeight = parseFloat((min + Math.random() * (max - min)).toFixed(3));
163
- const mgPerG = parseFloat((percentWeight * 10).toFixed(2));
164
- rows.push({
165
- name: analyte,
166
- result: percentWeight < lod ? "ND" : percentWeight,
167
- percentWeight,
168
- mgPerG,
169
- lod,
170
- loq,
171
- });
172
- }
145
+ if (!profileConfig) return [];
146
+ const rows = [];
147
+
148
+ // Find LOD/LOQ constants — try common keys
149
+ const lodLoqKey = Object.keys(constants).find(k => k.startsWith("LOD_LOQ"));
150
+ const lodLoqMap = lodLoqKey ? constants[lodLoqKey] : {};
151
+ const defaultLod = 0.01;
152
+ const defaultLoq = 0.03;
153
+ for (const [analyte, cfg] of Object.entries(profileConfig)) {
154
+ const lodLoq = lodLoqMap[analyte] || {};
155
+ const lod = lodLoq.LOD ?? defaultLod;
156
+ const loq = lodLoq.LOQ ?? defaultLoq;
157
+ if (cfg.nd) {
158
+ rows.push({
159
+ name: analyte,
160
+ result: "ND",
161
+ percentWeight: 0,
162
+ mgPerG: 0,
163
+ lod,
164
+ loq
165
+ });
166
+ } else {
167
+ const min = cfg.min ?? 0;
168
+ const max = cfg.max ?? 100;
169
+ const percentWeight = parseFloat((min + Math.random() * (max - min)).toFixed(3));
170
+ const mgPerG = parseFloat((percentWeight * 10).toFixed(2));
171
+ rows.push({
172
+ name: analyte,
173
+ result: percentWeight < lod ? "ND" : percentWeight,
174
+ percentWeight,
175
+ mgPerG,
176
+ lod,
177
+ loq
178
+ });
173
179
  }
174
- return rows;
180
+ }
181
+ return rows;
175
182
  }
183
+
176
184
  // ============================================================================
177
185
  // 2b. FULL PANEL DATA GENERATOR — safety tests from template constants
178
186
  // ============================================================================
187
+
179
188
  export function generateFullPanelData(constants) {
180
- const microbialTests = (constants["MICROBIAL_TESTS"] || {});
181
- const heavyMetals = (constants["HEAVY_METALS"] || {});
182
- const mycotoxins = (constants["MYCOTOXINS"] || {});
183
- const pesticidesCat1 = (constants["PESTICIDES_CATEGORY_I"] || []);
184
- const pesticidesCat2 = (constants["PESTICIDES_CATEGORY_II"] || []);
185
- const microbialResults = Object.entries(microbialTests).map(([test, config]) => {
186
- let result = "ND";
187
- if (!config.nd_required && config.typical_range) {
188
- if (Math.random() > (config.nd_chance || 0)) {
189
- result = Math.round(config.typical_range.min + Math.random() * (config.typical_range.max - config.typical_range.min));
190
- }
191
- }
192
- return { test, result, limit: config.limit, status: "Pass" };
193
- });
194
- const heavyMetalsResults = Object.entries(heavyMetals).map(([analyte, config]) => {
195
- let result = "ND";
196
- if (Math.random() > config.nd_chance) {
197
- const val = Math.round((config.typical_range.min + Math.random() * (config.typical_range.max - config.typical_range.min)) * 1000) / 1000;
198
- result = val < config.loq ? "ND" : val;
199
- }
200
- return { analyte, lod: config.lod, loq: config.loq, result, limit: config.limit, status: "Pass" };
201
- });
202
- const mycotoxinResults = Object.entries(mycotoxins).map(([analyte, config]) => ({
203
- analyte, lod: config.lod, loq: config.loq, result: "ND", limit: config.limit, status: "Pass",
204
- }));
205
- const pesticidesCat1Results = pesticidesCat1.map(analyte => ({ analyte, result: "ND", status: "Pass" }));
206
- const pesticidesCat2Results = pesticidesCat2.map(analyte => ({ analyte, result: "ND", status: "Pass" }));
207
- const residualSolventsData = [
208
- { name: "Acetone", limit: 5000 }, { name: "Benzene", limit: 2 }, { name: "Butane", limit: 5000 },
209
- { name: "Chloroform", limit: 2 }, { name: "Ethanol", limit: 5000 }, { name: "Ethyl Acetate", limit: 5000 },
210
- { name: "Heptane", limit: 5000 }, { name: "Hexane", limit: 290 }, { name: "Isopropyl Alcohol", limit: 5000 },
211
- { name: "Methanol", limit: 3000 }, { name: "Pentane", limit: 5000 }, { name: "Propane", limit: 5000 },
212
- { name: "Toluene", limit: 890 }, { name: "Xylene", limit: 2170 },
213
- ];
214
- const residualSolventsResults = residualSolventsData.map(s => ({
215
- analyte: s.name, result: "<LOQ", limit: s.limit, loq: s.limit * 0.1, unit: "ppm", status: "Pass",
216
- }));
217
- return { microbialResults, heavyMetalsResults, mycotoxinResults, pesticidesCat1: pesticidesCat1Results, pesticidesCat2: pesticidesCat2Results, residualSolventsResults };
189
+ const microbialTests = constants["MICROBIAL_TESTS"] || {};
190
+ const heavyMetals = constants["HEAVY_METALS"] || {};
191
+ const mycotoxins = constants["MYCOTOXINS"] || {};
192
+ const pesticidesCat1 = constants["PESTICIDES_CATEGORY_I"] || [];
193
+ const pesticidesCat2 = constants["PESTICIDES_CATEGORY_II"] || [];
194
+ const microbialResults = Object.entries(microbialTests).map(([test, config]) => {
195
+ let result = "ND";
196
+ if (!config.nd_required && config.typical_range) {
197
+ if (Math.random() > (config.nd_chance || 0)) {
198
+ result = Math.round(config.typical_range.min + Math.random() * (config.typical_range.max - config.typical_range.min));
199
+ }
200
+ }
201
+ return {
202
+ test,
203
+ result,
204
+ limit: config.limit,
205
+ status: "Pass"
206
+ };
207
+ });
208
+ const heavyMetalsResults = Object.entries(heavyMetals).map(([analyte, config]) => {
209
+ let result = "ND";
210
+ if (Math.random() > config.nd_chance) {
211
+ const val = Math.round((config.typical_range.min + Math.random() * (config.typical_range.max - config.typical_range.min)) * 1000) / 1000;
212
+ result = val < config.loq ? "ND" : val;
213
+ }
214
+ return {
215
+ analyte,
216
+ lod: config.lod,
217
+ loq: config.loq,
218
+ result,
219
+ limit: config.limit,
220
+ status: "Pass"
221
+ };
222
+ });
223
+ const mycotoxinResults = Object.entries(mycotoxins).map(([analyte, config]) => ({
224
+ analyte,
225
+ lod: config.lod,
226
+ loq: config.loq,
227
+ result: "ND",
228
+ limit: config.limit,
229
+ status: "Pass"
230
+ }));
231
+ const pesticidesCat1Results = pesticidesCat1.map(analyte => ({
232
+ analyte,
233
+ result: "ND",
234
+ status: "Pass"
235
+ }));
236
+ const pesticidesCat2Results = pesticidesCat2.map(analyte => ({
237
+ analyte,
238
+ result: "ND",
239
+ status: "Pass"
240
+ }));
241
+ const residualSolventsData = [{
242
+ name: "Acetone",
243
+ limit: 5000
244
+ }, {
245
+ name: "Benzene",
246
+ limit: 2
247
+ }, {
248
+ name: "Butane",
249
+ limit: 5000
250
+ }, {
251
+ name: "Chloroform",
252
+ limit: 2
253
+ }, {
254
+ name: "Ethanol",
255
+ limit: 5000
256
+ }, {
257
+ name: "Ethyl Acetate",
258
+ limit: 5000
259
+ }, {
260
+ name: "Heptane",
261
+ limit: 5000
262
+ }, {
263
+ name: "Hexane",
264
+ limit: 290
265
+ }, {
266
+ name: "Isopropyl Alcohol",
267
+ limit: 5000
268
+ }, {
269
+ name: "Methanol",
270
+ limit: 3000
271
+ }, {
272
+ name: "Pentane",
273
+ limit: 5000
274
+ }, {
275
+ name: "Propane",
276
+ limit: 5000
277
+ }, {
278
+ name: "Toluene",
279
+ limit: 890
280
+ }, {
281
+ name: "Xylene",
282
+ limit: 2170
283
+ }];
284
+ const residualSolventsResults = residualSolventsData.map(s => ({
285
+ analyte: s.name,
286
+ result: "<LOQ",
287
+ limit: s.limit,
288
+ loq: s.limit * 0.1,
289
+ unit: "ppm",
290
+ status: "Pass"
291
+ }));
292
+ return {
293
+ microbialResults,
294
+ heavyMetalsResults,
295
+ mycotoxinResults,
296
+ pesticidesCat1: pesticidesCat1Results,
297
+ pesticidesCat2: pesticidesCat2Results,
298
+ residualSolventsResults
299
+ };
218
300
  }
301
+
302
+ // ============================================================================
303
+ // 3. CALCULATION ENGINE — safe expression evaluator (NO eval)
304
+ // ============================================================================
305
+
306
+ // Tokenizer
307
+
219
308
  function tokenize(expr) {
220
- const tokens = [];
221
- let i = 0;
222
- while (i < expr.length) {
223
- const ch = expr[i];
224
- if (/\s/.test(ch)) {
225
- i++;
226
- continue;
227
- }
228
- if (/[0-9]/.test(ch) || (ch === "." && i + 1 < expr.length && /[0-9]/.test(expr[i + 1]))) {
229
- let num = "";
230
- while (i < expr.length && /[0-9.]/.test(expr[i])) {
231
- num += expr[i];
232
- i++;
233
- }
234
- tokens.push({ type: "NUMBER", value: num });
235
- continue;
236
- }
237
- if (/[a-zA-Z_]/.test(ch)) {
238
- let id = "";
239
- while (i < expr.length && /[a-zA-Z0-9_]/.test(expr[i])) {
240
- id += expr[i];
241
- i++;
242
- }
243
- if (id === "SUM" && i < expr.length && expr[i] === "(") {
244
- tokens.push({ type: "FUNC", value: id });
245
- }
246
- else {
247
- tokens.push({ type: "IDENT", value: id });
248
- }
249
- continue;
250
- }
251
- if ("+-*/".includes(ch)) {
252
- tokens.push({ type: "OP", value: ch });
253
- i++;
254
- continue;
255
- }
256
- if (ch === "(") {
257
- tokens.push({ type: "LPAREN", value: ch });
258
- i++;
259
- continue;
260
- }
261
- if (ch === ")") {
262
- tokens.push({ type: "RPAREN", value: ch });
263
- i++;
264
- continue;
265
- }
266
- if (ch === "[") {
267
- tokens.push({ type: "LBRACKET", value: ch });
268
- i++;
269
- continue;
270
- }
271
- if (ch === "]") {
272
- tokens.push({ type: "RBRACKET", value: ch });
273
- i++;
274
- continue;
275
- }
276
- if (ch === ".") {
277
- tokens.push({ type: "DOT", value: ch });
278
- i++;
279
- continue;
280
- }
281
- if (ch === ",") {
282
- tokens.push({ type: "COMMA", value: ch });
283
- i++;
284
- continue;
285
- }
286
- i++; // skip unknown
309
+ const tokens = [];
310
+ let i = 0;
311
+ while (i < expr.length) {
312
+ const ch = expr[i];
313
+ if (/\s/.test(ch)) {
314
+ i++;
315
+ continue;
316
+ }
317
+ if (/[0-9]/.test(ch) || ch === "." && i + 1 < expr.length && /[0-9]/.test(expr[i + 1])) {
318
+ let num = "";
319
+ while (i < expr.length && /[0-9.]/.test(expr[i])) {
320
+ num += expr[i];
321
+ i++;
322
+ }
323
+ tokens.push({
324
+ type: "NUMBER",
325
+ value: num
326
+ });
327
+ continue;
328
+ }
329
+ if (/[a-zA-Z_]/.test(ch)) {
330
+ let id = "";
331
+ while (i < expr.length && /[a-zA-Z0-9_]/.test(expr[i])) {
332
+ id += expr[i];
333
+ i++;
334
+ }
335
+ if (id === "SUM" && i < expr.length && expr[i] === "(") {
336
+ tokens.push({
337
+ type: "FUNC",
338
+ value: id
339
+ });
340
+ } else {
341
+ tokens.push({
342
+ type: "IDENT",
343
+ value: id
344
+ });
345
+ }
346
+ continue;
347
+ }
348
+ if ("+-*/".includes(ch)) {
349
+ tokens.push({
350
+ type: "OP",
351
+ value: ch
352
+ });
353
+ i++;
354
+ continue;
355
+ }
356
+ if (ch === "(") {
357
+ tokens.push({
358
+ type: "LPAREN",
359
+ value: ch
360
+ });
361
+ i++;
362
+ continue;
363
+ }
364
+ if (ch === ")") {
365
+ tokens.push({
366
+ type: "RPAREN",
367
+ value: ch
368
+ });
369
+ i++;
370
+ continue;
287
371
  }
288
- tokens.push({ type: "EOF", value: "" });
289
- return tokens;
372
+ if (ch === "[") {
373
+ tokens.push({
374
+ type: "LBRACKET",
375
+ value: ch
376
+ });
377
+ i++;
378
+ continue;
379
+ }
380
+ if (ch === "]") {
381
+ tokens.push({
382
+ type: "RBRACKET",
383
+ value: ch
384
+ });
385
+ i++;
386
+ continue;
387
+ }
388
+ if (ch === ".") {
389
+ tokens.push({
390
+ type: "DOT",
391
+ value: ch
392
+ });
393
+ i++;
394
+ continue;
395
+ }
396
+ if (ch === ",") {
397
+ tokens.push({
398
+ type: "COMMA",
399
+ value: ch
400
+ });
401
+ i++;
402
+ continue;
403
+ }
404
+ i++; // skip unknown
405
+ }
406
+ tokens.push({
407
+ type: "EOF",
408
+ value: ""
409
+ });
410
+ return tokens;
290
411
  }
412
+
291
413
  // Recursive descent parser
292
414
  class ExprParser {
293
- tokens;
294
- ctx;
295
- pos = 0;
296
- constructor(tokens, ctx) {
297
- this.tokens = tokens;
298
- this.ctx = ctx;
299
- }
300
- peek() { return this.tokens[this.pos] || { type: "EOF", value: "" }; }
301
- advance() { return this.tokens[this.pos++]; }
302
- parse() {
303
- const val = this.expr();
304
- return val;
305
- }
306
- expr() {
307
- let left = this.term();
308
- while (this.peek().type === "OP" && (this.peek().value === "+" || this.peek().value === "-")) {
309
- const op = this.advance().value;
310
- const right = this.term();
311
- left = op === "+" ? left + right : left - right;
312
- }
313
- return left;
314
- }
315
- term() {
316
- let left = this.unary();
317
- while (this.peek().type === "OP" && (this.peek().value === "*" || this.peek().value === "/")) {
318
- const op = this.advance().value;
319
- const right = this.unary();
320
- left = op === "*" ? left * right : (right !== 0 ? left / right : 0);
321
- }
322
- return left;
415
+ pos = 0;
416
+ constructor(tokens, ctx) {
417
+ this.tokens = tokens;
418
+ this.ctx = ctx;
419
+ }
420
+ peek() {
421
+ return this.tokens[this.pos] || {
422
+ type: "EOF",
423
+ value: ""
424
+ };
425
+ }
426
+ advance() {
427
+ return this.tokens[this.pos++];
428
+ }
429
+ parse() {
430
+ const val = this.expr();
431
+ return val;
432
+ }
433
+ expr() {
434
+ let left = this.term();
435
+ while (this.peek().type === "OP" && (this.peek().value === "+" || this.peek().value === "-")) {
436
+ const op = this.advance().value;
437
+ const right = this.term();
438
+ left = op === "+" ? left + right : left - right;
323
439
  }
324
- unary() {
325
- if (this.peek().type === "OP" && this.peek().value === "-") {
326
- this.advance();
327
- return -this.primary();
328
- }
329
- return this.primary();
440
+ return left;
441
+ }
442
+ term() {
443
+ let left = this.unary();
444
+ while (this.peek().type === "OP" && (this.peek().value === "*" || this.peek().value === "/")) {
445
+ const op = this.advance().value;
446
+ const right = this.unary();
447
+ left = op === "*" ? left * right : right !== 0 ? left / right : 0;
330
448
  }
331
- primary() {
332
- const tok = this.peek();
333
- if (tok.type === "NUMBER") {
334
- this.advance();
335
- return parseFloat(tok.value);
336
- }
337
- if (tok.type === "LPAREN") {
338
- this.advance();
339
- const val = this.expr();
340
- if (this.peek().type === "RPAREN")
341
- this.advance();
342
- return val;
343
- }
344
- // SUM(array[].field)
345
- if (tok.type === "FUNC" && tok.value === "SUM") {
346
- this.advance(); // SUM
347
- if (this.peek().type === "LPAREN")
348
- this.advance(); // (
349
- // Parse: arrayName[].fieldName
350
- const arrayName = this.advance().value; // identifier
351
- if (this.peek().type === "LBRACKET") {
352
- this.advance(); // [
353
- if (this.peek().type === "RBRACKET")
354
- this.advance(); // ]
355
- }
356
- if (this.peek().type === "DOT")
357
- this.advance(); // .
358
- const fieldName = this.advance().value; // field
359
- if (this.peek().type === "RPAREN")
360
- this.advance(); // )
361
- const arr = this.ctx[arrayName];
362
- if (!Array.isArray(arr))
363
- return 0;
364
- let sum = 0;
365
- for (const item of arr) {
366
- const v = item[fieldName];
367
- if (typeof v === "number")
368
- sum += v;
369
- }
370
- return sum;
371
- }
372
- // Identifier — resolve from context
373
- if (tok.type === "IDENT") {
374
- this.advance();
375
- const val = this.ctx[tok.value];
376
- if (typeof val === "number")
377
- return val;
378
- if (typeof val === "string") {
379
- const n = parseFloat(val);
380
- return isNaN(n) ? 0 : n;
381
- }
382
- return 0;
383
- }
384
- // Fallback
385
- this.advance();
386
- return 0;
449
+ return left;
450
+ }
451
+ unary() {
452
+ if (this.peek().type === "OP" && this.peek().value === "-") {
453
+ this.advance();
454
+ return -this.primary();
455
+ }
456
+ return this.primary();
457
+ }
458
+ primary() {
459
+ const tok = this.peek();
460
+ if (tok.type === "NUMBER") {
461
+ this.advance();
462
+ return parseFloat(tok.value);
463
+ }
464
+ if (tok.type === "LPAREN") {
465
+ this.advance();
466
+ const val = this.expr();
467
+ if (this.peek().type === "RPAREN") this.advance();
468
+ return val;
387
469
  }
470
+
471
+ // SUM(array[].field)
472
+ if (tok.type === "FUNC" && tok.value === "SUM") {
473
+ this.advance(); // SUM
474
+ if (this.peek().type === "LPAREN") this.advance(); // (
475
+ // Parse: arrayName[].fieldName
476
+ const arrayName = this.advance().value; // identifier
477
+ if (this.peek().type === "LBRACKET") {
478
+ this.advance(); // [
479
+ if (this.peek().type === "RBRACKET") this.advance(); // ]
480
+ }
481
+ if (this.peek().type === "DOT") this.advance(); // .
482
+ const fieldName = this.advance().value; // field
483
+ if (this.peek().type === "RPAREN") this.advance(); // )
484
+
485
+ const arr = this.ctx[arrayName];
486
+ if (!Array.isArray(arr)) return 0;
487
+ let sum = 0;
488
+ for (const item of arr) {
489
+ const v = item[fieldName];
490
+ if (typeof v === "number") sum += v;
491
+ }
492
+ return sum;
493
+ }
494
+
495
+ // Identifier — resolve from context
496
+ if (tok.type === "IDENT") {
497
+ this.advance();
498
+ const val = this.ctx[tok.value];
499
+ if (typeof val === "number") return val;
500
+ if (typeof val === "string") {
501
+ const n = parseFloat(val);
502
+ return isNaN(n) ? 0 : n;
503
+ }
504
+ return 0;
505
+ }
506
+
507
+ // Fallback
508
+ this.advance();
509
+ return 0;
510
+ }
388
511
  }
389
512
  function safeEval(expr, ctx) {
390
- const tokens = tokenize(expr);
391
- const parser = new ExprParser(tokens, ctx);
392
- return parser.parse();
513
+ const tokens = tokenize(expr);
514
+ const parser = new ExprParser(tokens, ctx);
515
+ return parser.parse();
393
516
  }
394
517
  function normalizeCalculations(raw) {
395
- if (!raw)
396
- return [];
397
- if (Array.isArray(raw))
398
- return raw;
399
- if (typeof raw === "object") {
400
- return Object.entries(raw).map(([field, formula]) => ({
401
- field,
402
- formula: String(formula),
403
- }));
404
- }
405
- return [];
518
+ if (!raw) return [];
519
+ if (Array.isArray(raw)) return raw;
520
+ if (typeof raw === "object") {
521
+ return Object.entries(raw).map(([field, formula]) => ({
522
+ field,
523
+ formula: String(formula)
524
+ }));
525
+ }
526
+ return [];
406
527
  }
407
528
  export function applyCalculations(calculations, constants, data) {
408
- const normalized = normalizeCalculations(calculations);
409
- if (!normalized.length)
410
- return data;
411
- const result = { ...data };
412
- // Flatten constants into context
413
- const ctx = { ...result };
414
- for (const [k, v] of Object.entries(constants)) {
415
- if (typeof v === "number" || typeof v === "string") {
416
- ctx[k] = v;
417
- }
529
+ const normalized = normalizeCalculations(calculations);
530
+ if (!normalized.length) return data;
531
+ const result = {
532
+ ...data
533
+ };
534
+
535
+ // Flatten constants into context
536
+ const ctx = {
537
+ ...result
538
+ };
539
+ for (const [k, v] of Object.entries(constants)) {
540
+ if (typeof v === "number" || typeof v === "string") {
541
+ ctx[k] = v;
418
542
  }
419
- // Multi-pass (max 3) for inter-formula dependencies
420
- for (let pass = 0; pass < 3; pass++) {
421
- let changed = false;
422
- for (const calc of normalized) {
423
- try {
424
- const val = safeEval(calc.formula, ctx);
425
- const rounded = parseFloat(val.toFixed(calc.decimals ?? 3));
426
- if (ctx[calc.field] !== rounded) {
427
- ctx[calc.field] = rounded;
428
- result[calc.field] = rounded;
429
- changed = true;
430
- }
431
- }
432
- catch {
433
- // Skip failed calculations
434
- }
543
+ }
544
+
545
+ // Multi-pass (max 3) for inter-formula dependencies
546
+ for (let pass = 0; pass < 3; pass++) {
547
+ let changed = false;
548
+ for (const calc of normalized) {
549
+ try {
550
+ const val = safeEval(calc.formula, ctx);
551
+ const rounded = parseFloat(val.toFixed(calc.decimals ?? 3));
552
+ if (ctx[calc.field] !== rounded) {
553
+ ctx[calc.field] = rounded;
554
+ result[calc.field] = rounded;
555
+ changed = true;
435
556
  }
436
- if (!changed)
437
- break;
557
+ } catch {
558
+ // Skip failed calculations
559
+ }
438
560
  }
439
- return result;
561
+ if (!changed) break;
562
+ }
563
+ return result;
440
564
  }
565
+
566
+ // ============================================================================
567
+ // 4. VALIDATION ENGINE — evaluates formula strings from pdf_templates.validation_rules
568
+ // ============================================================================
569
+
570
+ // Tokenizer for boolean expressions
571
+
441
572
  function tokenizeBool(expr) {
442
- const tokens = [];
443
- let i = 0;
444
- while (i < expr.length) {
445
- const ch = expr[i];
446
- if (/\s/.test(ch)) {
447
- i++;
448
- continue;
449
- }
450
- if (/[0-9]/.test(ch) || (ch === "." && i + 1 < expr.length && /[0-9]/.test(expr[i + 1]))) {
451
- let num = "";
452
- while (i < expr.length && /[0-9.]/.test(expr[i])) {
453
- num += expr[i];
454
- i++;
455
- }
456
- tokens.push({ type: "NUMBER", value: num });
457
- continue;
458
- }
459
- if (/[a-zA-Z_]/.test(ch)) {
460
- let id = "";
461
- while (i < expr.length && /[a-zA-Z0-9_]/.test(expr[i])) {
462
- id += expr[i];
463
- i++;
464
- }
465
- if (id === "AND" || id === "OR") {
466
- tokens.push({ type: "LOGIC", value: id });
467
- }
468
- else {
469
- tokens.push({ type: "IDENT", value: id });
470
- }
471
- continue;
472
- }
473
- // Comparison operators
474
- if (ch === "<" || ch === ">" || ch === "=" || ch === "!") {
475
- let op = ch;
476
- i++;
477
- if (i < expr.length && expr[i] === "=") {
478
- op += "=";
479
- i++;
480
- }
481
- else if (ch === "=" && i < expr.length && expr[i] === "=") {
482
- op += "=";
483
- i++;
484
- }
485
- tokens.push({ type: "CMP", value: op });
486
- continue;
487
- }
488
- if ("+-*/".includes(ch)) {
489
- tokens.push({ type: "OP", value: ch });
490
- i++;
491
- continue;
492
- }
493
- if (ch === "(") {
494
- tokens.push({ type: "LPAREN", value: ch });
495
- i++;
496
- continue;
497
- }
498
- if (ch === ")") {
499
- tokens.push({ type: "RPAREN", value: ch });
500
- i++;
501
- continue;
502
- }
573
+ const tokens = [];
574
+ let i = 0;
575
+ while (i < expr.length) {
576
+ const ch = expr[i];
577
+ if (/\s/.test(ch)) {
578
+ i++;
579
+ continue;
580
+ }
581
+ if (/[0-9]/.test(ch) || ch === "." && i + 1 < expr.length && /[0-9]/.test(expr[i + 1])) {
582
+ let num = "";
583
+ while (i < expr.length && /[0-9.]/.test(expr[i])) {
584
+ num += expr[i];
585
+ i++;
586
+ }
587
+ tokens.push({
588
+ type: "NUMBER",
589
+ value: num
590
+ });
591
+ continue;
592
+ }
593
+ if (/[a-zA-Z_]/.test(ch)) {
594
+ let id = "";
595
+ while (i < expr.length && /[a-zA-Z0-9_]/.test(expr[i])) {
596
+ id += expr[i];
597
+ i++;
598
+ }
599
+ if (id === "AND" || id === "OR") {
600
+ tokens.push({
601
+ type: "LOGIC",
602
+ value: id
603
+ });
604
+ } else {
605
+ tokens.push({
606
+ type: "IDENT",
607
+ value: id
608
+ });
609
+ }
610
+ continue;
611
+ }
612
+ // Comparison operators
613
+ if (ch === "<" || ch === ">" || ch === "=" || ch === "!") {
614
+ let op = ch;
615
+ i++;
616
+ if (i < expr.length && expr[i] === "=") {
617
+ op += "=";
503
618
  i++;
619
+ } else if (ch === "=" && i < expr.length && expr[i] === "=") {
620
+ op += "=";
621
+ i++;
622
+ }
623
+ tokens.push({
624
+ type: "CMP",
625
+ value: op
626
+ });
627
+ continue;
628
+ }
629
+ if ("+-*/".includes(ch)) {
630
+ tokens.push({
631
+ type: "OP",
632
+ value: ch
633
+ });
634
+ i++;
635
+ continue;
636
+ }
637
+ if (ch === "(") {
638
+ tokens.push({
639
+ type: "LPAREN",
640
+ value: ch
641
+ });
642
+ i++;
643
+ continue;
504
644
  }
505
- tokens.push({ type: "EOF", value: "" });
506
- return tokens;
645
+ if (ch === ")") {
646
+ tokens.push({
647
+ type: "RPAREN",
648
+ value: ch
649
+ });
650
+ i++;
651
+ continue;
652
+ }
653
+ i++;
654
+ }
655
+ tokens.push({
656
+ type: "EOF",
657
+ value: ""
658
+ });
659
+ return tokens;
507
660
  }
508
661
  function evalBoolExpr(expr, ctx) {
509
- const tokens = tokenizeBool(expr);
510
- let pos = 0;
511
- function peek() { return tokens[pos] || { type: "EOF", value: "" }; }
512
- function advance() { return tokens[pos++]; }
513
- function numericValue() {
514
- const tok = peek();
515
- if (tok.type === "NUMBER") {
516
- advance();
517
- return parseFloat(tok.value);
518
- }
519
- if (tok.type === "IDENT") {
520
- advance();
521
- const v = ctx[tok.value];
522
- return typeof v === "number" ? v : (typeof v === "string" ? parseFloat(v) || 0 : 0);
523
- }
524
- if (tok.type === "LPAREN") {
525
- advance();
526
- const val = numericExpr();
527
- if (peek().type === "RPAREN")
528
- advance();
529
- return val;
530
- }
531
- advance();
532
- return 0;
533
- }
534
- function numericExpr() {
535
- let left = numericTerm();
536
- while (peek().type === "OP" && (peek().value === "+" || peek().value === "-")) {
537
- const op = advance().value;
538
- const right = numericTerm();
539
- left = op === "+" ? left + right : left - right;
540
- }
541
- return left;
542
- }
543
- function numericTerm() {
544
- let left = numericValue();
545
- while (peek().type === "OP" && (peek().value === "*" || peek().value === "/")) {
546
- const op = advance().value;
547
- const right = numericValue();
548
- left = op === "*" ? left * right : (right !== 0 ? left / right : 0);
549
- }
550
- return left;
551
- }
552
- function comparison() {
553
- const left = numericExpr();
554
- const tok = peek();
555
- if (tok.type === "CMP") {
556
- const op = advance().value;
557
- const right = numericExpr();
558
- switch (op) {
559
- case "<": return left < right;
560
- case "<=": return left <= right;
561
- case ">": return left > right;
562
- case ">=": return left >= right;
563
- case "==": return Math.abs(left - right) < 1e-9;
564
- case "!=": return Math.abs(left - right) >= 1e-9;
565
- default: return false;
566
- }
567
- }
568
- // Truthy check if no comparison operator
569
- return left !== 0;
570
- }
571
- function boolExpr() {
572
- let left = comparison();
573
- while (peek().type === "LOGIC") {
574
- const op = advance().value;
575
- const right = comparison();
576
- if (op === "AND")
577
- left = left && right;
578
- else if (op === "OR")
579
- left = left || right;
580
- }
581
- return left;
662
+ const tokens = tokenizeBool(expr);
663
+ let pos = 0;
664
+ function peek() {
665
+ return tokens[pos] || {
666
+ type: "EOF",
667
+ value: ""
668
+ };
669
+ }
670
+ function advance() {
671
+ return tokens[pos++];
672
+ }
673
+ function numericValue() {
674
+ const tok = peek();
675
+ if (tok.type === "NUMBER") {
676
+ advance();
677
+ return parseFloat(tok.value);
678
+ }
679
+ if (tok.type === "IDENT") {
680
+ advance();
681
+ const v = ctx[tok.value];
682
+ return typeof v === "number" ? v : typeof v === "string" ? parseFloat(v) || 0 : 0;
683
+ }
684
+ if (tok.type === "LPAREN") {
685
+ advance();
686
+ const val = numericExpr();
687
+ if (peek().type === "RPAREN") advance();
688
+ return val;
689
+ }
690
+ advance();
691
+ return 0;
692
+ }
693
+ function numericExpr() {
694
+ let left = numericTerm();
695
+ while (peek().type === "OP" && (peek().value === "+" || peek().value === "-")) {
696
+ const op = advance().value;
697
+ const right = numericTerm();
698
+ left = op === "+" ? left + right : left - right;
699
+ }
700
+ return left;
701
+ }
702
+ function numericTerm() {
703
+ let left = numericValue();
704
+ while (peek().type === "OP" && (peek().value === "*" || peek().value === "/")) {
705
+ const op = advance().value;
706
+ const right = numericValue();
707
+ left = op === "*" ? left * right : right !== 0 ? left / right : 0;
708
+ }
709
+ return left;
710
+ }
711
+ function comparison() {
712
+ const left = numericExpr();
713
+ const tok = peek();
714
+ if (tok.type === "CMP") {
715
+ const op = advance().value;
716
+ const right = numericExpr();
717
+ switch (op) {
718
+ case "<":
719
+ return left < right;
720
+ case "<=":
721
+ return left <= right;
722
+ case ">":
723
+ return left > right;
724
+ case ">=":
725
+ return left >= right;
726
+ case "==":
727
+ return Math.abs(left - right) < 1e-9;
728
+ case "!=":
729
+ return Math.abs(left - right) >= 1e-9;
730
+ default:
731
+ return false;
732
+ }
582
733
  }
583
- return boolExpr();
734
+ // Truthy check if no comparison operator
735
+ return left !== 0;
736
+ }
737
+ function boolExpr() {
738
+ let left = comparison();
739
+ while (peek().type === "LOGIC") {
740
+ const op = advance().value;
741
+ const right = comparison();
742
+ if (op === "AND") left = left && right;else if (op === "OR") left = left || right;
743
+ }
744
+ return left;
745
+ }
746
+ return boolExpr();
584
747
  }
585
748
  export function runValidation(rules, data) {
586
- if (!rules || !Array.isArray(rules))
587
- return [];
588
- const results = [];
589
- for (const rule of rules) {
590
- try {
591
- const passed = evalBoolExpr(rule.formula, data);
592
- results.push({ name: rule.name, severity: rule.severity, message: rule.message, passed });
593
- }
594
- catch {
595
- results.push({ name: rule.name, severity: rule.severity, message: rule.message, passed: false });
596
- }
749
+ if (!rules || !Array.isArray(rules)) return [];
750
+ const results = [];
751
+ for (const rule of rules) {
752
+ try {
753
+ const passed = evalBoolExpr(rule.formula, data);
754
+ results.push({
755
+ name: rule.name,
756
+ severity: rule.severity,
757
+ message: rule.message,
758
+ passed
759
+ });
760
+ } catch {
761
+ results.push({
762
+ name: rule.name,
763
+ severity: rule.severity,
764
+ message: rule.message,
765
+ passed: false
766
+ });
597
767
  }
598
- return results;
768
+ }
769
+ return results;
599
770
  }
771
+
772
+ // ============================================================================
773
+ // 5. LAYOUT → HTML RENDERER
774
+ // ============================================================================
775
+
600
776
  export function resolveBinding(bind, data) {
601
- const parts = bind.split(".");
602
- let val = data;
603
- for (const p of parts) {
604
- if (val === null || val === undefined)
605
- return undefined;
606
- val = val[p];
607
- }
608
- return val;
777
+ const parts = bind.split(".");
778
+ let val = data;
779
+ for (const p of parts) {
780
+ if (val === null || val === undefined) return undefined;
781
+ val = val[p];
782
+ }
783
+ return val;
609
784
  }
610
785
  export function resolveText(text, data) {
611
- if (!text)
612
- return "";
613
- return fillTemplate(text, data);
786
+ if (!text) return "";
787
+ return fillTemplate(text, data);
614
788
  }
789
+
615
790
  // Minimal QR code generator — produces SVG rect elements for a text payload.
616
791
  // Uses a simple bit matrix approach sufficient for short strings (URLs, IDs).
617
792
  export function generateQRSvg(text, size = 100) {
618
- // Simple QR-like encoding: create a deterministic pattern from text hash
619
- // This generates a visually QR-like pattern (not scannable — for display purposes).
620
- // For real QR, the template data usually includes a pre-generated QR URL.
621
- const moduleCount = 21; // QR Version 1
622
- const cellSize = size / moduleCount;
623
- const modules = Array.from({ length: moduleCount }, () => Array(moduleCount).fill(false));
624
- // Finder patterns (top-left, top-right, bottom-left)
625
- const drawFinder = (row, col) => {
626
- for (let r = 0; r < 7; r++) {
627
- for (let c = 0; c < 7; c++) {
628
- const isEdge = r === 0 || r === 6 || c === 0 || c === 6;
629
- const isInner = r >= 2 && r <= 4 && c >= 2 && c <= 4;
630
- if (isEdge || isInner)
631
- modules[row + r][col + c] = true;
632
- }
633
- }
634
- };
635
- drawFinder(0, 0);
636
- drawFinder(0, moduleCount - 7);
637
- drawFinder(moduleCount - 7, 0);
638
- // Data area: hash the text and fill deterministically
639
- let hash = 0;
640
- for (let i = 0; i < text.length; i++) {
641
- hash = ((hash << 5) - hash + text.charCodeAt(i)) | 0;
642
- }
643
- for (let r = 8; r < moduleCount; r++) {
644
- for (let c = 8; c < moduleCount; c++) {
645
- hash = ((hash << 5) - hash + r * 31 + c * 17) | 0;
646
- modules[r][c] = (hash & 1) === 1;
647
- }
793
+ // Simple QR-like encoding: create a deterministic pattern from text hash
794
+ // This generates a visually QR-like pattern (not scannable — for display purposes).
795
+ // For real QR, the template data usually includes a pre-generated QR URL.
796
+ const moduleCount = 21; // QR Version 1
797
+ const cellSize = size / moduleCount;
798
+ const modules = Array.from({
799
+ length: moduleCount
800
+ }, () => Array(moduleCount).fill(false));
801
+
802
+ // Finder patterns (top-left, top-right, bottom-left)
803
+ const drawFinder = (row, col) => {
804
+ for (let r = 0; r < 7; r++) {
805
+ for (let c = 0; c < 7; c++) {
806
+ const isEdge = r === 0 || r === 6 || c === 0 || c === 6;
807
+ const isInner = r >= 2 && r <= 4 && c >= 2 && c <= 4;
808
+ if (isEdge || isInner) modules[row + r][col + c] = true;
809
+ }
648
810
  }
649
- let rects = "";
650
- for (let r = 0; r < moduleCount; r++) {
651
- for (let c = 0; c < moduleCount; c++) {
652
- if (modules[r][c]) {
653
- rects += `<rect x="${c * cellSize}" y="${r * cellSize}" width="${cellSize}" height="${cellSize}" fill="#000"/>`;
654
- }
655
- }
811
+ };
812
+ drawFinder(0, 0);
813
+ drawFinder(0, moduleCount - 7);
814
+ drawFinder(moduleCount - 7, 0);
815
+
816
+ // Data area: hash the text and fill deterministically
817
+ let hash = 0;
818
+ for (let i = 0; i < text.length; i++) {
819
+ hash = (hash << 5) - hash + text.charCodeAt(i) | 0;
820
+ }
821
+ for (let r = 8; r < moduleCount; r++) {
822
+ for (let c = 8; c < moduleCount; c++) {
823
+ hash = (hash << 5) - hash + r * 31 + c * 17 | 0;
824
+ modules[r][c] = (hash & 1) === 1;
656
825
  }
657
- return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}" width="${size}" height="${size}"><rect width="${size}" height="${size}" fill="#fff"/>${rects}</svg>`;
826
+ }
827
+ let rects = "";
828
+ for (let r = 0; r < moduleCount; r++) {
829
+ for (let c = 0; c < moduleCount; c++) {
830
+ if (modules[r][c]) {
831
+ rects += `<rect x="${c * cellSize}" y="${r * cellSize}" width="${cellSize}" height="${cellSize}" fill="#000"/>`;
832
+ }
833
+ }
834
+ }
835
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}" width="${size}" height="${size}"><rect width="${size}" height="${size}" fill="#fff"/>${rects}</svg>`;
658
836
  }
659
837
  function renderElement(el, data) {
660
- switch (el.type) {
661
- case "text": {
662
- const text = resolveText(el.content || el.text || "", data);
663
- const styles = [];
664
- if (el.fontSize)
665
- styles.push(`font-size:${el.fontSize}px`);
666
- if (el.color)
667
- styles.push(`color:${el.color}`);
668
- if (el.bold)
669
- styles.push("font-weight:bold");
670
- if (el.align)
671
- styles.push(`text-align:${el.align}`);
672
- return `<div style="${styles.join(";")}">${text}</div>`;
673
- }
674
- case "header": {
675
- const text = resolveText(el.content || el.text || "", data);
676
- const styles = ["font-weight:bold"];
677
- if (el.backgroundColor)
678
- styles.push(`background-color:${el.backgroundColor}`);
679
- if (el.padding)
680
- styles.push(`padding:${typeof el.padding === "number" ? el.padding + "px" : el.padding}`);
681
- if (el.fontSize)
682
- styles.push(`font-size:${el.fontSize}px`);
683
- if (el.color)
684
- styles.push(`color:${el.color}`);
685
- if (el.align)
686
- styles.push(`text-align:${el.align}`);
687
- return `<div style="${styles.join(";")}">${text}</div>`;
838
+ switch (el.type) {
839
+ case "text":
840
+ {
841
+ const text = resolveText(el.content || el.text || "", data);
842
+ const styles = [];
843
+ if (el.fontSize) styles.push(`font-size:${el.fontSize}px`);
844
+ if (el.color) styles.push(`color:${el.color}`);
845
+ if (el.bold) styles.push("font-weight:bold");
846
+ if (el.align) styles.push(`text-align:${el.align}`);
847
+ return `<div style="${styles.join(";")}">${text}</div>`;
848
+ }
849
+ case "header":
850
+ {
851
+ const text = resolveText(el.content || el.text || "", data);
852
+ const styles = ["font-weight:bold"];
853
+ if (el.backgroundColor) styles.push(`background-color:${el.backgroundColor}`);
854
+ if (el.padding) styles.push(`padding:${typeof el.padding === "number" ? el.padding + "px" : el.padding}`);
855
+ if (el.fontSize) styles.push(`font-size:${el.fontSize}px`);
856
+ if (el.color) styles.push(`color:${el.color}`);
857
+ if (el.align) styles.push(`text-align:${el.align}`);
858
+ return `<div style="${styles.join(";")}">${text}</div>`;
859
+ }
860
+ case "image":
861
+ {
862
+ let src = el.src || el.url || "";
863
+ if (el.bind) {
864
+ const resolved = resolveBinding(el.bind, data);
865
+ if (typeof resolved === "string") src = resolved;
688
866
  }
689
- case "image": {
690
- let src = el.src || el.url || "";
691
- if (el.bind) {
692
- const resolved = resolveBinding(el.bind, data);
693
- if (typeof resolved === "string")
694
- src = resolved;
695
- }
696
- const w = el.width ? `width:${typeof el.width === "number" ? el.width + "px" : el.width}` : "";
697
- const h = el.height ? `height:${typeof el.height === "number" ? el.height + "px" : el.height}` : "";
698
- return `<img src="${src}" style="${[w, h].filter(Boolean).join(";")}" />`;
867
+ const w = el.width ? `width:${typeof el.width === "number" ? el.width + "px" : el.width}` : "";
868
+ const h = el.height ? `height:${typeof el.height === "number" ? el.height + "px" : el.height}` : "";
869
+ return `<img src="${src}" style="${[w, h].filter(Boolean).join(";")}" />`;
870
+ }
871
+ case "qrcode":
872
+ {
873
+ let qrData = el.data || el.content || "";
874
+ if (el.bind) {
875
+ const resolved = resolveBinding(el.bind, data);
876
+ if (typeof resolved === "string") qrData = resolved;
699
877
  }
700
- case "qrcode": {
701
- let qrData = el.data || el.content || "";
702
- if (el.bind) {
703
- const resolved = resolveBinding(el.bind, data);
704
- if (typeof resolved === "string")
705
- qrData = resolved;
706
- }
707
- qrData = resolveText(qrData, data);
708
- const qrSize = el.size || (typeof el.width === "number" ? el.width : 100);
709
- const svg = generateQRSvg(qrData, qrSize);
710
- const dataUri = `data:image/svg+xml;base64,${Buffer.from(svg).toString("base64")}`;
711
- return `<img src="${dataUri}" width="${qrSize}" height="${qrSize}" />`;
878
+ qrData = resolveText(qrData, data);
879
+ const qrSize = el.size || (typeof el.width === "number" ? el.width : 100);
880
+ const svg = generateQRSvg(qrData, qrSize);
881
+ const dataUri = `data:image/svg+xml;base64,${Buffer.from(svg).toString("base64")}`;
882
+ return `<img src="${dataUri}" width="${qrSize}" height="${qrSize}" />`;
883
+ }
884
+ case "spacer":
885
+ {
886
+ const h = el.height || 10;
887
+ return `<div style="height:${typeof h === "number" ? h + "px" : h}"></div>`;
888
+ }
889
+ case "line":
890
+ {
891
+ const color = el.color || "#000";
892
+ const thickness = el.thickness || 1;
893
+ return `<hr style="border:none;border-top:${thickness}px solid ${color};margin:8px 0;" />`;
894
+ }
895
+ case "columns":
896
+ {
897
+ const cols = el.columns || el.children || [];
898
+ const inner = cols.map(child => {
899
+ // Support both: array of elements per column, or single element per column
900
+ if (Array.isArray(child)) {
901
+ return `<div style="flex:1">${child.map(c => renderElement(c, data)).join("")}</div>`;
902
+ }
903
+ return `<div style="flex:1">${renderElement(child, data)}</div>`;
904
+ }).join("");
905
+ return `<div style="display:flex;gap:8px">${inner}</div>`;
906
+ }
907
+ case "page_break":
908
+ {
909
+ return `<div style="page-break-after:always"></div>`;
910
+ }
911
+ case "grid":
912
+ {
913
+ const items = Array.isArray(el.items) ? el.items : Array.isArray(el.content) ? el.content : [];
914
+ const gridRows = items.map(item => {
915
+ const label = item.label || item.value || "";
916
+ let value = "";
917
+ if (item.bind) {
918
+ const resolved = resolveBinding(item.bind, data);
919
+ value = resolved !== undefined && resolved !== null ? String(resolved) : "";
920
+ }
921
+ value = resolveText(value || "", data);
922
+ return `<tr><td style="padding:4px 8px;font-weight:bold;white-space:nowrap;width:40%">${label}</td><td style="padding:4px 8px">${value}</td></tr>`;
923
+ }).join("");
924
+ return `<table style="width:100%;border-collapse:collapse">${gridRows}</table>`;
925
+ }
926
+ case "table":
927
+ {
928
+ const headers = el.headers || [];
929
+ const rowFields = el.row_fields;
930
+ const thead = headers.length ? `<thead><tr>${headers.map(h => `<th style="padding:6px 8px;border:1px solid #ddd;background:#f5f5f5;text-align:left;font-size:8px">${h}</th>`).join("")}</tr></thead>` : "";
931
+ let bodyRows = el.rows || [];
932
+ if (el.bind) {
933
+ const resolved = resolveBinding(el.bind, data);
934
+ if (Array.isArray(resolved)) bodyRows = resolved;
712
935
  }
713
- case "spacer": {
714
- const h = el.height || 10;
715
- return `<div style="height:${typeof h === "number" ? h + "px" : h}"></div>`;
936
+ const tbody = bodyRows.map(row => {
937
+ if (Array.isArray(row)) {
938
+ return `<tr>${row.map(cell => `<td style="padding:5px 8px;border:1px solid #ddd;font-size:8px">${cell ?? ""}</td>`).join("")}</tr>`;
939
+ }
940
+ // Object row — use row_fields if provided, else fall back to header matching
941
+ if (rowFields && rowFields.length) {
942
+ return `<tr>${rowFields.map(field => {
943
+ const val = row[field] ?? "";
944
+ return `<td style="padding:5px 8px;border:1px solid #ddd;font-size:8px">${val}</td>`;
945
+ }).join("")}</tr>`;
946
+ }
947
+ return `<tr>${headers.map(h => {
948
+ const key = h.toLowerCase().replace(/[^a-z0-9]/g, "");
949
+ const val = row[h] ?? row[key] ?? row[h.replace(/\s+/g, "")] ?? "";
950
+ return `<td style="padding:5px 8px;border:1px solid #ddd;font-size:8px">${val}</td>`;
951
+ }).join("")}</tr>`;
952
+ }).join("");
953
+ return `<table style="width:100%;border-collapse:collapse">${thead}<tbody>${tbody}</tbody></table>`;
954
+ }
955
+ case "box":
956
+ {
957
+ const styles = ["text-align:center"];
958
+ if (el.border) styles.push(`border:${el.border}`);
959
+ if (el.background || el.backgroundColor) styles.push(`background:${el.background || el.backgroundColor}`);
960
+ if (el.padding) styles.push(`padding:${typeof el.padding === "number" ? el.padding + "px" : el.padding}`);
961
+ const inner = (el.children || []).map(child => renderElement(child, data)).join("");
962
+ const text = el.content || el.text ? resolveText(el.content || el.text || "", data) : "";
963
+ return `<div style="${styles.join(";")}">${text}${inner}</div>`;
964
+ }
965
+ default:
966
+ {
967
+ // Unknown element — try to render children
968
+ if (el.children && Array.isArray(el.children)) {
969
+ return el.children.map(child => renderElement(child, data)).join("");
716
970
  }
717
- case "line": {
718
- const color = el.color || "#000";
719
- const thickness = el.thickness || 1;
720
- return `<hr style="border:none;border-top:${thickness}px solid ${color};margin:8px 0;" />`;
721
- }
722
- case "columns": {
723
- const cols = el.columns || el.children || [];
724
- const inner = cols.map((child) => {
725
- // Support both: array of elements per column, or single element per column
726
- if (Array.isArray(child)) {
727
- return `<div style="flex:1">${child.map((c) => renderElement(c, data)).join("")}</div>`;
728
- }
729
- return `<div style="flex:1">${renderElement(child, data)}</div>`;
730
- }).join("");
731
- return `<div style="display:flex;gap:8px">${inner}</div>`;
732
- }
733
- case "page_break": {
734
- return `<div style="page-break-after:always"></div>`;
735
- }
736
- case "grid": {
737
- const items = (Array.isArray(el.items) ? el.items : Array.isArray(el.content) ? el.content : []);
738
- const gridRows = items.map((item) => {
739
- const label = item.label || item.value || "";
740
- let value = "";
741
- if (item.bind) {
742
- const resolved = resolveBinding(item.bind, data);
743
- value = resolved !== undefined && resolved !== null ? String(resolved) : "";
744
- }
745
- value = resolveText(value || "", data);
746
- return `<tr><td style="padding:4px 8px;font-weight:bold;white-space:nowrap;width:40%">${label}</td><td style="padding:4px 8px">${value}</td></tr>`;
747
- }).join("");
748
- return `<table style="width:100%;border-collapse:collapse">${gridRows}</table>`;
749
- }
750
- case "table": {
751
- const headers = el.headers || [];
752
- const rowFields = el.row_fields;
753
- const thead = headers.length
754
- ? `<thead><tr>${headers.map(h => `<th style="padding:6px 8px;border:1px solid #ddd;background:#f5f5f5;text-align:left;font-size:8px">${h}</th>`).join("")}</tr></thead>`
755
- : "";
756
- let bodyRows = el.rows || [];
757
- if (el.bind) {
758
- const resolved = resolveBinding(el.bind, data);
759
- if (Array.isArray(resolved))
760
- bodyRows = resolved;
761
- }
762
- const tbody = bodyRows.map((row) => {
763
- if (Array.isArray(row)) {
764
- return `<tr>${row.map(cell => `<td style="padding:5px 8px;border:1px solid #ddd;font-size:8px">${cell ?? ""}</td>`).join("")}</tr>`;
765
- }
766
- // Object row — use row_fields if provided, else fall back to header matching
767
- if (rowFields && rowFields.length) {
768
- return `<tr>${rowFields.map(field => {
769
- const val = row[field] ?? "";
770
- return `<td style="padding:5px 8px;border:1px solid #ddd;font-size:8px">${val}</td>`;
771
- }).join("")}</tr>`;
772
- }
773
- return `<tr>${headers.map(h => {
774
- const key = h.toLowerCase().replace(/[^a-z0-9]/g, "");
775
- const val = row[h] ?? row[key] ?? row[h.replace(/\s+/g, "")] ?? "";
776
- return `<td style="padding:5px 8px;border:1px solid #ddd;font-size:8px">${val}</td>`;
777
- }).join("")}</tr>`;
778
- }).join("");
779
- return `<table style="width:100%;border-collapse:collapse">${thead}<tbody>${tbody}</tbody></table>`;
780
- }
781
- case "box": {
782
- const styles = ["text-align:center"];
783
- if (el.border)
784
- styles.push(`border:${el.border}`);
785
- if (el.background || el.backgroundColor)
786
- styles.push(`background:${el.background || el.backgroundColor}`);
787
- if (el.padding)
788
- styles.push(`padding:${typeof el.padding === "number" ? el.padding + "px" : el.padding}`);
789
- const inner = (el.children || []).map(child => renderElement(child, data)).join("");
790
- const text = el.content || el.text ? resolveText(el.content || el.text || "", data) : "";
791
- return `<div style="${styles.join(";")}">${text}${inner}</div>`;
792
- }
793
- default: {
794
- // Unknown element — try to render children
795
- if (el.children && Array.isArray(el.children)) {
796
- return el.children.map(child => renderElement(child, data)).join("");
797
- }
798
- return "";
799
- }
800
- }
971
+ return "";
972
+ }
973
+ }
801
974
  }
802
975
  export function renderLayoutToHtml(layout, pageConfig, styles, data) {
803
- const pageSize = pageConfig?.size || "A4";
804
- const margins = pageConfig?.margins || { top: "15mm", right: "15mm", bottom: "15mm", left: "15mm" };
805
- const fontFamily = styles?.fontFamily || "Helvetica, Arial, sans-serif";
806
- const fontSize = styles?.fontSize || 12;
807
- const color = styles?.color || "#000";
808
- // Normalize layout to LayoutElement[]:
809
- // - Array → use directly
810
- // - Object with .pages flatten page sections (header/body/footer per page)
811
- // - Object with .sections/.children → unwrap
812
- // - Object with .header/.footer → wrap as elements
813
- let elements = [];
814
- if (Array.isArray(layout)) {
815
- elements = layout;
816
- }
817
- else if (layout && typeof layout === "object") {
818
- if (Array.isArray(layout.pages)) {
819
- for (const page of layout.pages) {
820
- if (page.header)
821
- elements.push(page.header);
822
- if (Array.isArray(page.body))
823
- elements.push(...page.body);
824
- else if (page.body)
825
- elements.push(page.body);
826
- if (Array.isArray(page.sections))
827
- elements.push(...page.sections);
828
- if (Array.isArray(page.elements))
829
- elements.push(...page.elements);
830
- if (page.footer)
831
- elements.push(page.footer);
832
- }
833
- }
834
- else if (Array.isArray(layout.sections)) {
835
- elements = layout.sections;
836
- }
837
- else if (Array.isArray(layout.children)) {
838
- elements = layout.children;
839
- }
840
- else {
841
- // Object with header/footer keys — wrap as single-element layout
842
- if (layout.header)
843
- elements.push(layout.header);
844
- if (layout.body) {
845
- const body = layout.body;
846
- if (Array.isArray(body))
847
- elements.push(...body);
848
- else
849
- elements.push(body);
850
- }
851
- if (layout.footer)
852
- elements.push(layout.footer);
853
- }
976
+ const pageSize = pageConfig?.size || "A4";
977
+ const margins = pageConfig?.margins || {
978
+ top: "15mm",
979
+ right: "15mm",
980
+ bottom: "15mm",
981
+ left: "15mm"
982
+ };
983
+ const fontFamily = styles?.fontFamily || "Helvetica, Arial, sans-serif";
984
+ const fontSize = styles?.fontSize || 12;
985
+ const color = styles?.color || "#000";
986
+
987
+ // Normalize layout to LayoutElement[]:
988
+ // - Array → use directly
989
+ // - Object with .pages → flatten page sections (header/body/footer per page)
990
+ // - Object with .sections/.children unwrap
991
+ // - Object with .header/.footer → wrap as elements
992
+ let elements = [];
993
+ if (Array.isArray(layout)) {
994
+ elements = layout;
995
+ } else if (layout && typeof layout === "object") {
996
+ if (Array.isArray(layout.pages)) {
997
+ for (const page of layout.pages) {
998
+ if (page.header) elements.push(page.header);
999
+ if (Array.isArray(page.body)) elements.push(...page.body);else if (page.body) elements.push(page.body);
1000
+ if (Array.isArray(page.sections)) elements.push(...page.sections);
1001
+ if (Array.isArray(page.elements)) elements.push(...page.elements);
1002
+ if (page.footer) elements.push(page.footer);
1003
+ }
1004
+ } else if (Array.isArray(layout.sections)) {
1005
+ elements = layout.sections;
1006
+ } else if (Array.isArray(layout.children)) {
1007
+ elements = layout.children;
1008
+ } else {
1009
+ // Object with header/footer keys — wrap as single-element layout
1010
+ if (layout.header) elements.push(layout.header);
1011
+ if (layout.body) {
1012
+ const body = layout.body;
1013
+ if (Array.isArray(body)) elements.push(...body);else elements.push(body);
1014
+ }
1015
+ if (layout.footer) elements.push(layout.footer);
854
1016
  }
855
- const bodyHtml = elements.map(el => renderElement(el, data)).join("\n");
856
- return `<!DOCTYPE html>
1017
+ }
1018
+ const bodyHtml = elements.map(el => renderElement(el, data)).join("\n");
1019
+ return `<!DOCTYPE html>
857
1020
  <html>
858
1021
  <head>
859
1022
  <meta charset="utf-8">
@@ -879,3 +1042,4 @@ ${bodyHtml}
879
1042
  </body>
880
1043
  </html>`;
881
1044
  }
1045
+ //# sourceMappingURL=pdf-renderer.js.map