@divmain/jdm-asm 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (397) hide show
  1. package/.github/workflows/ci.yml +53 -0
  2. package/.oxfmtrc.json +16 -0
  3. package/.oxlintrc.json +183 -0
  4. package/AGENTS.md +81 -0
  5. package/README.md +769 -0
  6. package/asconfig.json +23 -0
  7. package/benchmarks/fixtures.ts +111 -0
  8. package/benchmarks/input-fixtures.ts +80 -0
  9. package/benchmarks/run.ts +913 -0
  10. package/benchmarks/worker-pool.ts +223 -0
  11. package/benchmarks/worker.ts +374 -0
  12. package/dist/index.d.ts +996 -0
  13. package/dist/index.js +12239 -0
  14. package/dist/index.js.map +1 -0
  15. package/package.json +49 -0
  16. package/scripts/run-all-tests.ts +220 -0
  17. package/src/compiler/EXPRESSION_SUBSETS.md +228 -0
  18. package/src/compiler/asc-compiler.ts +315 -0
  19. package/src/compiler/ast-types.ts +215 -0
  20. package/src/compiler/build.ts +56 -0
  21. package/src/compiler/cache.ts +414 -0
  22. package/src/compiler/code-generators.ts +211 -0
  23. package/src/compiler/codegen/index.ts +15 -0
  24. package/src/compiler/codegen/js-marshal.ts +999 -0
  25. package/src/compiler/codegen/js-validation.ts +243 -0
  26. package/src/compiler/codegen.ts +19 -0
  27. package/src/compiler/compile-time-validation.ts +507 -0
  28. package/src/compiler/cst-visitor.ts +434 -0
  29. package/src/compiler/errors.ts +227 -0
  30. package/src/compiler/expression-parser.ts +536 -0
  31. package/src/compiler/graph.ts +197 -0
  32. package/src/compiler/index.ts +199 -0
  33. package/src/compiler/input-validation.ts +33 -0
  34. package/src/compiler/marshal-gen.ts +21 -0
  35. package/src/compiler/nodes/context-resolvers.ts +197 -0
  36. package/src/compiler/nodes/decision-table.ts +507 -0
  37. package/src/compiler/nodes/decision.ts +292 -0
  38. package/src/compiler/nodes/expression-compiler.ts +526 -0
  39. package/src/compiler/nodes/expression.ts +425 -0
  40. package/src/compiler/nodes/function.ts +316 -0
  41. package/src/compiler/nodes/input.ts +60 -0
  42. package/src/compiler/nodes/switch.ts +547 -0
  43. package/src/compiler/optimizer.ts +948 -0
  44. package/src/compiler/orchestrator.ts +352 -0
  45. package/src/compiler/parser.ts +115 -0
  46. package/src/compiler/result-selection.ts +161 -0
  47. package/src/compiler/runtime/index.ts +26 -0
  48. package/src/compiler/runtime-codegen.ts +211 -0
  49. package/src/compiler/runtime-validation-codegen.ts +294 -0
  50. package/src/compiler/runtime.ts +452 -0
  51. package/src/compiler/schema.ts +245 -0
  52. package/src/compiler/switch-branch-detection.ts +92 -0
  53. package/src/compiler/types.ts +136 -0
  54. package/src/compiler/unary-ast-transforms.ts +148 -0
  55. package/src/compiler/unary-parser.ts +301 -0
  56. package/src/compiler/unary-transform.ts +161 -0
  57. package/src/compiler/utils.ts +27 -0
  58. package/src/compiler/virtual-fs.ts +90 -0
  59. package/src/compiler/wasm-instantiate.ts +127 -0
  60. package/src/index.ts +1 -0
  61. package/src/runtime/arrays.ts +579 -0
  62. package/src/runtime/context.ts +189 -0
  63. package/src/runtime/expressions.ts +1811 -0
  64. package/src/runtime/index.ts +8 -0
  65. package/src/runtime/memory.ts +607 -0
  66. package/src/runtime/strings.ts +260 -0
  67. package/src/runtime/tables.ts +96 -0
  68. package/src/runtime/tsconfig.json +4 -0
  69. package/src/runtime/values.ts +209 -0
  70. package/test-data/README.md +83 -0
  71. package/test-data/decision-tables/basic/8k.json +87992 -0
  72. package/test-data/decision-tables/basic/affiliate-commission-calculator.json +228 -0
  73. package/test-data/decision-tables/basic/airline-loyalty-points-calculations.json +285 -0
  74. package/test-data/decision-tables/basic/airline-upgrade-eligibility.json +466 -0
  75. package/test-data/decision-tables/basic/auto-insurance-premium-calculator.json +412 -0
  76. package/test-data/decision-tables/basic/booking-personalization-system.json +553 -0
  77. package/test-data/decision-tables/basic/care-team-assignment-system.json +585 -0
  78. package/test-data/decision-tables/basic/claim-validation-system.json +307 -0
  79. package/test-data/decision-tables/basic/clinical-lab-result-interpreter.json +433 -0
  80. package/test-data/decision-tables/basic/clinical-treatment-protocol.json +474 -0
  81. package/test-data/decision-tables/basic/credit-limit-adjustment.json +479 -0
  82. package/test-data/decision-tables/basic/customer-eligibility-engine.json +551 -0
  83. package/test-data/decision-tables/basic/customer-lifetime-value.json +200 -0
  84. package/test-data/decision-tables/basic/customer-onboarding-kyc-verification.json +611 -0
  85. package/test-data/decision-tables/basic/customer-service-escalation.json +191 -0
  86. package/test-data/decision-tables/basic/decision-table-discounts.json +168 -0
  87. package/test-data/decision-tables/basic/decision-table-shipping.json +398 -0
  88. package/test-data/decision-tables/basic/delivery-route-optimizer.json +271 -0
  89. package/test-data/decision-tables/basic/device-compatibility-checker.json +303 -0
  90. package/test-data/decision-tables/basic/disaster-relief-fund-allocation.json +296 -0
  91. package/test-data/decision-tables/basic/dynamic-fx-rate-pricing-system.json +237 -0
  92. package/test-data/decision-tables/basic/dynamic-marketplace-comission-calculator.json +242 -0
  93. package/test-data/decision-tables/basic/dynamic-shipping-cost-calculator.json +378 -0
  94. package/test-data/decision-tables/basic/dynamic-tarrif-engine.json +289 -0
  95. package/test-data/decision-tables/basic/dynamic-ticket-pricing.json +325 -0
  96. package/test-data/decision-tables/basic/empty-column-with-space.json +100 -0
  97. package/test-data/decision-tables/basic/empty-column-without-space.json +100 -0
  98. package/test-data/decision-tables/basic/environment-compliance-assessment.json +386 -0
  99. package/test-data/decision-tables/basic/expression-table-map.json +313 -0
  100. package/test-data/decision-tables/basic/flash-sale-eligibility.json +366 -0
  101. package/test-data/decision-tables/basic/flight-dispatch-decision-system.json +455 -0
  102. package/test-data/decision-tables/basic/flight-rebooking-fee-calculator.json +406 -0
  103. package/test-data/decision-tables/basic/government-assistance.json +299 -0
  104. package/test-data/decision-tables/basic/grant-funding-distribution.json +307 -0
  105. package/test-data/decision-tables/basic/hazardous-materials-management-system.json +414 -0
  106. package/test-data/decision-tables/basic/immigration-eligibility-evaluator.json +765 -0
  107. package/test-data/decision-tables/basic/import-duties-calculator.json +318 -0
  108. package/test-data/decision-tables/basic/insurance-agent-commission.json +228 -0
  109. package/test-data/decision-tables/basic/insurance-coverage-calculator.json +362 -0
  110. package/test-data/decision-tables/basic/insurance-underwriting-risk.json +321 -0
  111. package/test-data/decision-tables/basic/international-roaming-policy-manager.json +199 -0
  112. package/test-data/decision-tables/basic/legacy-plan-management.json +434 -0
  113. package/test-data/decision-tables/basic/marketplace-listing-verification-system.json +334 -0
  114. package/test-data/decision-tables/basic/medication-dosage-calculator.json +318 -0
  115. package/test-data/decision-tables/basic/merch-bags.json +171 -0
  116. package/test-data/decision-tables/basic/municipal-permit-evaluation-system.json +364 -0
  117. package/test-data/decision-tables/basic/mvno-partner-enablement.json +313 -0
  118. package/test-data/decision-tables/basic/partner-revenue-sharing.json +244 -0
  119. package/test-data/decision-tables/basic/payment-routing-and-fee-calculator.json +475 -0
  120. package/test-data/decision-tables/basic/policy-discount-calculator.json +307 -0
  121. package/test-data/decision-tables/basic/policy-eligibility-analyzer.json +299 -0
  122. package/test-data/decision-tables/basic/product-listing-scoring.json +358 -0
  123. package/test-data/decision-tables/basic/realtime-fraud-detection.json +235 -0
  124. package/test-data/decision-tables/basic/regional-compliance-manager.json +278 -0
  125. package/test-data/decision-tables/basic/returns-and-refund-policy.json +366 -0
  126. package/test-data/decision-tables/basic/returns-processing-system.json +448 -0
  127. package/test-data/decision-tables/basic/school-district-resource-allocation.json +282 -0
  128. package/test-data/decision-tables/basic/seat-map-optimization.json +325 -0
  129. package/test-data/decision-tables/basic/seller-fee-calculator.json +307 -0
  130. package/test-data/decision-tables/basic/service-level-agreement-enforcement.json +575 -0
  131. package/test-data/decision-tables/basic/smart-financial-product-matcher.json +249 -0
  132. package/test-data/decision-tables/basic/supply-chain-risk.json +316 -0
  133. package/test-data/decision-tables/basic/table-loop.json +93 -0
  134. package/test-data/decision-tables/basic/table.json +76 -0
  135. package/test-data/decision-tables/basic/traffic-violation-penalty-calculator.json +436 -0
  136. package/test-data/decision-tables/basic/transaction-compliance-classifier.json +525 -0
  137. package/test-data/decision-tables/basic/vehicle-claims-resolution.json +310 -0
  138. package/test-data/decision-tables/basic/warehouse-storage-location.json +345 -0
  139. package/test-data/decision-tables/hit-policy-collect/collect-multiple-matches.json +127 -0
  140. package/test-data/decision-tables/hit-policy-collect/collect-no-match.json +95 -0
  141. package/test-data/decision-tables/hit-policy-first/first-match.json +103 -0
  142. package/test-data/decision-tables/hit-policy-first/no-match.json +95 -0
  143. package/test-data/decision-tables/hit-policy-output-order/output-order-respected.json +94 -0
  144. package/test-data/decision-tables/hit-policy-output-order/string-output-order.json +94 -0
  145. package/test-data/decision-tables/hit-policy-priority/priority-respected.json +86 -0
  146. package/test-data/decision-tables/hit-policy-rule-order/rule-order-respected.json +94 -0
  147. package/test-data/decision-tables/hit-policy-unique/all-match-error.json +89 -0
  148. package/test-data/decision-tables/hit-policy-unique/multiple-match-error.json +89 -0
  149. package/test-data/decision-tables/hit-policy-unique/no-match.json +88 -0
  150. package/test-data/decision-tables/hit-policy-unique/unique-match.json +99 -0
  151. package/test-data/expressions/arithmetic/error-cyclic.json +114 -0
  152. package/test-data/expressions/arithmetic/error-missing-input.json +54 -0
  153. package/test-data/expressions/arithmetic/error-missing-output.json +54 -0
  154. package/test-data/expressions/arithmetic/expression-default.json +93 -0
  155. package/test-data/expressions/arithmetic/expression-fields.json +94 -0
  156. package/test-data/expressions/arithmetic/expression-loop.json +94 -0
  157. package/test-data/expressions/arithmetic/expression-passthrough.json +108 -0
  158. package/test-data/expressions/arithmetic/expression.json +69 -0
  159. package/test-data/expressions/arithmetic/nested-request.json +125 -0
  160. package/test-data/expressions/arithmetic/number-function.json +58 -0
  161. package/test-data/expressions/arithmetic/test-number-functions.json +68 -0
  162. package/test-data/expressions/functions/all.json +149 -0
  163. package/test-data/expressions/functions/avg.json +89 -0
  164. package/test-data/expressions/functions/filter.json +109 -0
  165. package/test-data/expressions/functions/flat.json +167 -0
  166. package/test-data/expressions/functions/map-strings.json +65 -0
  167. package/test-data/expressions/functions/map.json +73 -0
  168. package/test-data/expressions/functions/reduce.json +49 -0
  169. package/test-data/expressions/functions/some.json +175 -0
  170. package/test-data/expressions/functions/sort-strings.json +97 -0
  171. package/test-data/expressions/functions/sort.json +97 -0
  172. package/test-data/expressions/logical/logical-and.json +116 -0
  173. package/test-data/expressions/logical/logical-complex.json +260 -0
  174. package/test-data/expressions/logical/logical-not.json +111 -0
  175. package/test-data/expressions/logical/logical-or.json +123 -0
  176. package/test-data/expressions/string/string-comparison.json +128 -0
  177. package/test-data/expressions/string/string-concat.json +106 -0
  178. package/test-data/expressions/string/string-contains.json +125 -0
  179. package/test-data/expressions/string/string-endsWith.json +113 -0
  180. package/test-data/expressions/string/string-indexOf.json +131 -0
  181. package/test-data/expressions/string/string-join.json +92 -0
  182. package/test-data/expressions/string/string-lower.json +94 -0
  183. package/test-data/expressions/string/string-replace.json +130 -0
  184. package/test-data/expressions/string/string-split.json +101 -0
  185. package/test-data/expressions/string/string-startsWith.json +113 -0
  186. package/test-data/expressions/string/string-substring.json +138 -0
  187. package/test-data/expressions/string/string-trim.json +100 -0
  188. package/test-data/expressions/string/string-upper.json +94 -0
  189. package/test-data/other/custom.json +51 -0
  190. package/test-data/other/customer-input-schema.json +34 -0
  191. package/test-data/other/customer-output-schema.json +34 -0
  192. package/test-data/other/passthrough.json +31 -0
  193. package/test-data/sub-decisions/basic/$nodes-child.json +31 -0
  194. package/test-data/sub-decisions/basic/$nodes-parent.json +49 -0
  195. package/test-data/sub-decisions/basic/recursive-table1.json +49 -0
  196. package/test-data/sub-decisions/basic/recursive-table2.json +49 -0
  197. package/test-data/sub-decisions/complex-multi/approval-decision.json +31 -0
  198. package/test-data/sub-decisions/complex-multi/complex-dag.json +175 -0
  199. package/test-data/sub-decisions/complex-multi/credit-check.json +31 -0
  200. package/test-data/sub-decisions/complex-multi/customer-segmentation.json +31 -0
  201. package/test-data/sub-decisions/complex-multi/discount-eligibility.json +31 -0
  202. package/test-data/sub-decisions/complex-multi/eligibility-check.json +31 -0
  203. package/test-data/sub-decisions/complex-multi/final-offer.json +31 -0
  204. package/test-data/sub-decisions/complex-multi/income-verification.json +31 -0
  205. package/test-data/sub-decisions/complex-multi/linear-chain.json +121 -0
  206. package/test-data/sub-decisions/complex-multi/pricing-calculation.json +31 -0
  207. package/test-data/sub-decisions/complex-multi/product-eligibility.json +31 -0
  208. package/test-data/sub-decisions/complex-multi/risk-assessment.json +31 -0
  209. package/test-data/sub-decisions/complex-multi/shared-validation.json +31 -0
  210. package/test-data/sub-decisions/complex-multi/validation.json +31 -0
  211. package/test-data/sub-decisions/diamond/decision-a.json +31 -0
  212. package/test-data/sub-decisions/diamond/decision-b.json +31 -0
  213. package/test-data/sub-decisions/diamond/decision-c.json +31 -0
  214. package/test-data/sub-decisions/diamond/decision-shared.json +31 -0
  215. package/test-data/sub-decisions/diamond/diamond-pattern.json +109 -0
  216. package/test-data/sub-decisions/error-propagation/parent-calls-error.json +44 -0
  217. package/test-data/sub-decisions/error-propagation/sub-decision-with-error.json +60 -0
  218. package/test-data/switch-nodes/basic/account-dormancy-management.json +245 -0
  219. package/test-data/switch-nodes/basic/application-risk-assessment.json +474 -0
  220. package/test-data/switch-nodes/basic/cellular-data-rollover-system.json +281 -0
  221. package/test-data/switch-nodes/basic/clinical-pathway-selection.json +454 -0
  222. package/test-data/switch-nodes/basic/insurance-prior-authorization.json +467 -0
  223. package/test-data/switch-nodes/basic/last-mile-delivery-assignment.json +373 -0
  224. package/test-data/switch-nodes/basic/loan-approval.json +469 -0
  225. package/test-data/switch-nodes/basic/multi-switch.json +498 -0
  226. package/test-data/switch-nodes/basic/online-checkin-eligibility.json +285 -0
  227. package/test-data/switch-nodes/basic/order-consolidation-system.json +493 -0
  228. package/test-data/switch-nodes/basic/seller-approval-workflow.json +383 -0
  229. package/test-data/switch-nodes/basic/set-fee.json +243 -0
  230. package/test-data/switch-nodes/basic/shipping-carrier-selector.json +379 -0
  231. package/test-data/switch-nodes/basic/switch-node.json +167 -0
  232. package/test-data/switch-nodes/basic/switch-performance-2.json +1307 -0
  233. package/test-data/switch-nodes/basic/switch-performance.json +691 -0
  234. package/test-data/switch-nodes/basic/tax-exemption.json +295 -0
  235. package/test-data/switch-nodes/basic/warehouse-cross-docking.json +313 -0
  236. package/test-data/switch-nodes/default-cases/switch-with-default.json +134 -0
  237. package/test-data/zen-reference/$nodes-child.json +69 -0
  238. package/test-data/zen-reference/$nodes-parent.json +34 -0
  239. package/test-data/zen-reference/8k.json +87992 -0
  240. package/test-data/zen-reference/credit-analysis.json +324 -0
  241. package/test-data/zen-reference/custom.json +51 -0
  242. package/test-data/zen-reference/customer-input-schema.json +34 -0
  243. package/test-data/zen-reference/customer-output-schema.json +34 -0
  244. package/test-data/zen-reference/error-cyclic.json +114 -0
  245. package/test-data/zen-reference/error-missing-input.json +54 -0
  246. package/test-data/zen-reference/error-missing-output.json +54 -0
  247. package/test-data/zen-reference/expression.json +69 -0
  248. package/test-data/zen-reference/function-v2.json +48 -0
  249. package/test-data/zen-reference/function.json +46 -0
  250. package/test-data/zen-reference/graphs/account-dormancy-management.json +245 -0
  251. package/test-data/zen-reference/graphs/affiliate-commission-calculator.json +228 -0
  252. package/test-data/zen-reference/graphs/airline-loyalty-points-calculations.json +285 -0
  253. package/test-data/zen-reference/graphs/airline-upgrade-eligibility.json +466 -0
  254. package/test-data/zen-reference/graphs/aml.json +537 -0
  255. package/test-data/zen-reference/graphs/application-risk-assessment.json +474 -0
  256. package/test-data/zen-reference/graphs/auto-insurance-premium-calculator.json +412 -0
  257. package/test-data/zen-reference/graphs/booking-personalization-system.json +553 -0
  258. package/test-data/zen-reference/graphs/care-team-assignment-system.json +585 -0
  259. package/test-data/zen-reference/graphs/cellular-data-rollover-system.json +281 -0
  260. package/test-data/zen-reference/graphs/claim-validation-system.json +307 -0
  261. package/test-data/zen-reference/graphs/clinical-lab-result-interpreter.json +433 -0
  262. package/test-data/zen-reference/graphs/clinical-pathway-selection.json +454 -0
  263. package/test-data/zen-reference/graphs/clinical-treatment-protocol.json +474 -0
  264. package/test-data/zen-reference/graphs/company-analysis.json +390 -0
  265. package/test-data/zen-reference/graphs/credit-limit-adjustment.json +479 -0
  266. package/test-data/zen-reference/graphs/customer-eligibility-engine.json +551 -0
  267. package/test-data/zen-reference/graphs/customer-lifetime-value.json +200 -0
  268. package/test-data/zen-reference/graphs/customer-onboarding-kyc-verification.json +611 -0
  269. package/test-data/zen-reference/graphs/customer-service-escalation.json +191 -0
  270. package/test-data/zen-reference/graphs/decision-table-discounts.json +168 -0
  271. package/test-data/zen-reference/graphs/decision-table-shipping.json +398 -0
  272. package/test-data/zen-reference/graphs/delivery-route-optimizer.json +271 -0
  273. package/test-data/zen-reference/graphs/device-compatibility-checker.json +303 -0
  274. package/test-data/zen-reference/graphs/disaster-relief-fund-allocation.json +296 -0
  275. package/test-data/zen-reference/graphs/dynamic-fx-rate-pricing-system.json +237 -0
  276. package/test-data/zen-reference/graphs/dynamic-marketplace-comission-calculator.json +242 -0
  277. package/test-data/zen-reference/graphs/dynamic-shipping-cost-calculator.json +378 -0
  278. package/test-data/zen-reference/graphs/dynamic-tarrif-engine.json +289 -0
  279. package/test-data/zen-reference/graphs/dynamic-ticket-pricing.json +325 -0
  280. package/test-data/zen-reference/graphs/empty-column-with-space.json +100 -0
  281. package/test-data/zen-reference/graphs/empty-column-without-space.json +100 -0
  282. package/test-data/zen-reference/graphs/environment-compliance-assessment.json +386 -0
  283. package/test-data/zen-reference/graphs/expression-default.json +93 -0
  284. package/test-data/zen-reference/graphs/expression-fields.json +94 -0
  285. package/test-data/zen-reference/graphs/expression-loop.json +94 -0
  286. package/test-data/zen-reference/graphs/expression-passthrough.json +108 -0
  287. package/test-data/zen-reference/graphs/expression-table-map.json +313 -0
  288. package/test-data/zen-reference/graphs/flash-sale-eligibility.json +366 -0
  289. package/test-data/zen-reference/graphs/flight-dispatch-decision-system.json +455 -0
  290. package/test-data/zen-reference/graphs/flight-rebooking-fee-calculator.json +406 -0
  291. package/test-data/zen-reference/graphs/government-assistance.json +299 -0
  292. package/test-data/zen-reference/graphs/grant-funding-distribution.json +307 -0
  293. package/test-data/zen-reference/graphs/hazardous-materials-management-system.json +414 -0
  294. package/test-data/zen-reference/graphs/immigration-eligibility-evaluator.json +765 -0
  295. package/test-data/zen-reference/graphs/import-duties-calculator.json +318 -0
  296. package/test-data/zen-reference/graphs/insurance-agent-commission.json +228 -0
  297. package/test-data/zen-reference/graphs/insurance-breakdown.json +421 -0
  298. package/test-data/zen-reference/graphs/insurance-coverage-calculator.json +362 -0
  299. package/test-data/zen-reference/graphs/insurance-prior-authorization.json +467 -0
  300. package/test-data/zen-reference/graphs/insurance-underwriting-risk.json +321 -0
  301. package/test-data/zen-reference/graphs/international-roaming-policy-manager.json +199 -0
  302. package/test-data/zen-reference/graphs/last-mile-delivery-assignment.json +373 -0
  303. package/test-data/zen-reference/graphs/legacy-plan-management.json +434 -0
  304. package/test-data/zen-reference/graphs/loan-approval.json +469 -0
  305. package/test-data/zen-reference/graphs/marketplace-listing-verification-system.json +334 -0
  306. package/test-data/zen-reference/graphs/medication-dosage-calculator.json +318 -0
  307. package/test-data/zen-reference/graphs/merch-bags.json +171 -0
  308. package/test-data/zen-reference/graphs/multi-switch.json +498 -0
  309. package/test-data/zen-reference/graphs/municipal-permit-evaluation-system.json +364 -0
  310. package/test-data/zen-reference/graphs/mvno-partner-enablement.json +313 -0
  311. package/test-data/zen-reference/graphs/nested-request.json +125 -0
  312. package/test-data/zen-reference/graphs/online-checkin-eligibility.json +285 -0
  313. package/test-data/zen-reference/graphs/order-consolidation-system.json +493 -0
  314. package/test-data/zen-reference/graphs/partner-revenue-sharing.json +244 -0
  315. package/test-data/zen-reference/graphs/payment-routing-and-fee-calculator.json +475 -0
  316. package/test-data/zen-reference/graphs/policy-discount-calculator.json +307 -0
  317. package/test-data/zen-reference/graphs/policy-eligibility-analyzer.json +299 -0
  318. package/test-data/zen-reference/graphs/product-listing-scoring.json +358 -0
  319. package/test-data/zen-reference/graphs/realtime-fraud-detection.json +235 -0
  320. package/test-data/zen-reference/graphs/regional-compliance-manager.json +278 -0
  321. package/test-data/zen-reference/graphs/returns-and-refund-policy.json +366 -0
  322. package/test-data/zen-reference/graphs/returns-processing-system.json +448 -0
  323. package/test-data/zen-reference/graphs/school-district-resource-allocation.json +282 -0
  324. package/test-data/zen-reference/graphs/seat-map-optimization.json +325 -0
  325. package/test-data/zen-reference/graphs/seller-approval-workflow.json +383 -0
  326. package/test-data/zen-reference/graphs/seller-fee-calculator.json +307 -0
  327. package/test-data/zen-reference/graphs/service-level-agreement-enforcement.json +575 -0
  328. package/test-data/zen-reference/graphs/set-fee.json +243 -0
  329. package/test-data/zen-reference/graphs/shipping-carrier-selector.json +379 -0
  330. package/test-data/zen-reference/graphs/smart-financial-product-matcher.json +249 -0
  331. package/test-data/zen-reference/graphs/supply-chain-risk.json +316 -0
  332. package/test-data/zen-reference/graphs/table-loop.json +93 -0
  333. package/test-data/zen-reference/graphs/tax-exemption.json +295 -0
  334. package/test-data/zen-reference/graphs/traffic-violation-penalty-calculator.json +436 -0
  335. package/test-data/zen-reference/graphs/transaction-compliance-classifier.json +525 -0
  336. package/test-data/zen-reference/graphs/vehicle-claims-resolution.json +310 -0
  337. package/test-data/zen-reference/graphs/warehouse-cross-docking.json +313 -0
  338. package/test-data/zen-reference/graphs/warehouse-storage-location.json +345 -0
  339. package/test-data/zen-reference/http-function.json +34 -0
  340. package/test-data/zen-reference/infinite-function.json +46 -0
  341. package/test-data/zen-reference/js/imports.js +25 -0
  342. package/test-data/zen-reference/passthrough.json +31 -0
  343. package/test-data/zen-reference/recursive-table1.json +49 -0
  344. package/test-data/zen-reference/recursive-table2.json +49 -0
  345. package/test-data/zen-reference/sleep-function.json +34 -0
  346. package/test-data/zen-reference/switch-node.json +167 -0
  347. package/test-data/zen-reference/switch-performance-2.json +1307 -0
  348. package/test-data/zen-reference/switch-performance.json +691 -0
  349. package/test-data/zen-reference/table.json +76 -0
  350. package/tests/helpers/index.ts +73 -0
  351. package/tests/helpers/mock-context.ts +231 -0
  352. package/tests/helpers/round-trip.ts +398 -0
  353. package/tests/helpers/test-harness-comparison.ts +325 -0
  354. package/tests/helpers/test-harness-wasm.ts +710 -0
  355. package/tests/helpers/test-harness.ts +28 -0
  356. package/tests/helpers/wasm-test.ts +659 -0
  357. package/tests/integration/compilation-errors.test.ts +864 -0
  358. package/tests/integration/decision-tables.test.ts +531 -0
  359. package/tests/integration/edge-cases.test.ts +787 -0
  360. package/tests/integration/expressions.test.ts +513 -0
  361. package/tests/integration/function-node-integration.test.ts +182 -0
  362. package/tests/integration/sub-decisions.test.ts +108 -0
  363. package/tests/integration/switch-nodes.test.ts +399 -0
  364. package/tests/integration/unary-or-matching.test.ts +53 -0
  365. package/tests/integration/wasm-data-types.test.ts +398 -0
  366. package/tests/integration/wasm-errors.test.ts +199 -0
  367. package/tests/integration/wasm-execution.test.ts +348 -0
  368. package/tests/integration/wasm-memory.test.ts +228 -0
  369. package/tests/scripts/analyze-coverage.ts +166 -0
  370. package/tests/scripts/categorize-tests.ts +396 -0
  371. package/tests/scripts/coverage-analysis.ts +836 -0
  372. package/tests/unit/compiler/cache.test.ts +238 -0
  373. package/tests/unit/compiler/errors.test.ts +316 -0
  374. package/tests/unit/compiler/graph-scalability.test.ts +510 -0
  375. package/tests/unit/compiler/graph.test.ts +878 -0
  376. package/tests/unit/compiler/input-validation.test.ts +447 -0
  377. package/tests/unit/compiler/logical-and-parser.test.ts +143 -0
  378. package/tests/unit/compiler/logical-not-parser.test.ts +107 -0
  379. package/tests/unit/compiler/logical-or-parser.test.ts +236 -0
  380. package/tests/unit/compiler/marshal-gen/marshal-gen.test.ts +97 -0
  381. package/tests/unit/compiler/nodes/decision-table.test.ts +103 -0
  382. package/tests/unit/compiler/nodes/decision.test.ts +182 -0
  383. package/tests/unit/compiler/nodes/function-compile.test.ts +204 -0
  384. package/tests/unit/compiler/nodes/function.test.ts +176 -0
  385. package/tests/unit/compiler/nodes/input.test.ts +30 -0
  386. package/tests/unit/compiler/nodes/switch.test.ts +127 -0
  387. package/tests/unit/compiler/optimizer-cache.test.ts +327 -0
  388. package/tests/unit/compiler/optimizer-implementation.test.ts +625 -0
  389. package/tests/unit/compiler/parser.test.ts +508 -0
  390. package/tests/unit/compiler/runtime-error-cleanup.test.ts +426 -0
  391. package/tests/unit/compiler/runtime-validation.test.ts +303 -0
  392. package/tests/unit/compiler/runtime.test.ts +221 -0
  393. package/tests/unit/compiler/schema/schema.test.ts +248 -0
  394. package/tests/unit/compiler/unary-ast-transforms.test.ts +245 -0
  395. package/tsconfig.json +27 -0
  396. package/tsup.config.ts +11 -0
  397. package/vitest.config.ts +12 -0
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Legacy test-harness.ts - Re-exports for backward compatibility
3
+ *
4
+ * This file has been split into focused helpers:
5
+ * - test-harness-wasm.ts: WASM-only testing (compilation, execution, marshaling)
6
+ * - test-harness-comparison.ts: zen-engine compatibility testing
7
+ *
8
+ * All exports are preserved for backward compatibility with existing tests.
9
+ */
10
+
11
+ // Re-export everything from the new focused modules
12
+ export {
13
+ compile,
14
+ evaluateCompiled,
15
+ inferSchema,
16
+ runWasmTest,
17
+ runSimpleWasmTest,
18
+ type WasmTestConfig,
19
+ type SimpleWasmTestConfig,
20
+ } from './test-harness-wasm';
21
+
22
+ export {
23
+ runCompatibilityTest,
24
+ runSimpleCompatibilityTest,
25
+ matchers,
26
+ type TestConfig,
27
+ type SimpleTestConfig,
28
+ } from './test-harness-comparison';
@@ -0,0 +1,659 @@
1
+ /**
2
+ * WASM test utilities for compiling and evaluating JDM decisions.
3
+ *
4
+ * These helpers simplify the process of compiling JDM to WASM and
5
+ * evaluating decisions in tests, reducing boilerplate and ensuring
6
+ * consistent test patterns.
7
+ *
8
+ * @module tests/helpers/wasm-test
9
+ */
10
+
11
+ import { readFileSync } from 'fs';
12
+ import { type TSchema, Type } from '@sinclair/typebox';
13
+ import { compile, type JDMDecision, type CompilationResult } from '../../src/compiler';
14
+ import { createCompiledDecision, type CompiledDecision } from '../../src/compiler/runtime';
15
+
16
+ /**
17
+ * Options for compiling and evaluating JDM.
18
+ */
19
+ export interface CompileAndEvaluateOptions {
20
+ /**
21
+ * Input schema for the decision.
22
+ * If not provided, will be inferred from the input value.
23
+ */
24
+ inputSchema?: TSchema;
25
+
26
+ /**
27
+ * Output schema for the decision.
28
+ * If not provided, will be inferred from expected shape or use a generic object.
29
+ */
30
+ outputSchema?: TSchema;
31
+
32
+ /**
33
+ * Enable debug mode for compilation (includes AssemblyScript source and WAT in result).
34
+ * @default false
35
+ */
36
+ debug?: boolean;
37
+
38
+ /**
39
+ * Skip input validation during evaluation.
40
+ * @default false
41
+ */
42
+ skipValidation?: boolean;
43
+ }
44
+
45
+ /**
46
+ * Result of compileAndEvaluate operations.
47
+ */
48
+ export interface EvaluationResult<T = unknown> {
49
+ /** The evaluation result */
50
+ result: T;
51
+ /** The compiled decision (can be reused for additional evaluations) */
52
+ decision: CompiledDecision;
53
+ /** The raw compilation result */
54
+ compilation: CompilationResult;
55
+ }
56
+
57
+ /**
58
+ * Compile a JDM file and evaluate with the given input.
59
+ *
60
+ * This is the primary helper for file-based JDM tests. It handles:
61
+ * - Loading the JDM file
62
+ * - Schema inference if not provided
63
+ * - Compilation to WASM
64
+ * - Evaluation with the input
65
+ *
66
+ * @param jdmPath - Path to the JDM JSON file
67
+ * @param input - Input data for evaluation
68
+ * @param options - Optional compilation/evaluation options
69
+ * @returns The evaluation result
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * // Simple usage
74
+ * const result = await compileAndEvaluate(
75
+ * 'test-data/simple-decision.json',
76
+ * { age: 25, income: 50000 }
77
+ * );
78
+ * expect(result).toEqual({ eligible: true });
79
+ *
80
+ * // With explicit schemas
81
+ * const result = await compileAndEvaluate(
82
+ * 'path/to/decision.json',
83
+ * { x: 10 },
84
+ * {
85
+ * inputSchema: Type.Object({ x: Type.Number() }),
86
+ * outputSchema: Type.Object({ y: Type.Number() }),
87
+ * }
88
+ * );
89
+ * ```
90
+ */
91
+ export async function compileAndEvaluate<I extends Record<string, unknown>, O = unknown>(
92
+ jdmPath: string,
93
+ input: I,
94
+ options: CompileAndEvaluateOptions = {},
95
+ ): Promise<O> {
96
+ const jdmContent = readFileSync(jdmPath, 'utf-8');
97
+ const jdm = JSON.parse(jdmContent) as JDMDecision;
98
+ return compileAndEvaluateInline(jdm, input, options);
99
+ }
100
+
101
+ /**
102
+ * Compile an inline JDM object and evaluate with the given input.
103
+ *
104
+ * Use this when you want to define the JDM directly in your test
105
+ * without a separate file.
106
+ *
107
+ * @param jdm - The JDM decision object
108
+ * @param input - Input data for evaluation
109
+ * @param options - Optional compilation/evaluation options
110
+ * @returns The evaluation result
111
+ *
112
+ * @example
113
+ * ```typescript
114
+ * const jdm = createExpressionJDM([
115
+ * { key: 'doubled', value: 'x * 2' }
116
+ * ]);
117
+ * const result = await compileAndEvaluateInline(jdm, { x: 21 });
118
+ * expect(result).toEqual({ doubled: 42 });
119
+ * ```
120
+ */
121
+ export async function compileAndEvaluateInline<I extends Record<string, unknown>, O = unknown>(
122
+ jdm: JDMDecision | object,
123
+ input: I,
124
+ options: CompileAndEvaluateOptions = {},
125
+ ): Promise<O> {
126
+ const { debug = false } = options;
127
+
128
+ // Infer schemas if not provided
129
+ const inputSchema = options.inputSchema ?? inferSchema(input);
130
+ const outputSchema = options.outputSchema ?? Type.Object({});
131
+
132
+ // Compile to WASM
133
+ const compiled = await compile({
134
+ jdm: jdm as JDMDecision,
135
+ inputSchema,
136
+ outputSchema,
137
+ debug,
138
+ });
139
+
140
+ // Create decision instance and evaluate
141
+ const decision = await createCompiledDecision(
142
+ compiled,
143
+ // FIXME: Double undefined - second param should be validation schema or options object
144
+ options.skipValidation ? undefined : undefined,
145
+ );
146
+
147
+ const result = await decision.evaluate<I, O>(input);
148
+ return result;
149
+ }
150
+
151
+ /**
152
+ * Compile and evaluate with full result details.
153
+ *
154
+ * Returns the compiled decision for potential reuse, along with
155
+ * the compilation result for debugging.
156
+ *
157
+ * @param jdm - The JDM decision object or path to file
158
+ * @param input - Input data for evaluation
159
+ * @param options - Optional compilation/evaluation options
160
+ * @returns Full evaluation result including decision and compilation
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * const { result, decision, compilation } = await compileAndEvaluateFull(
165
+ * jdm,
166
+ * input,
167
+ * { debug: true }
168
+ * );
169
+ *
170
+ * // Reuse decision for multiple evaluations
171
+ * const result2 = await decision.evaluate({ x: 100 });
172
+ *
173
+ * // Debug: inspect generated code
174
+ * console.log(compilation.assemblyScript);
175
+ * ```
176
+ */
177
+ export async function compileAndEvaluateFull<I extends Record<string, unknown>, O = unknown>(
178
+ jdm: JDMDecision | object | string,
179
+ input: I,
180
+ options: CompileAndEvaluateOptions = {},
181
+ ): Promise<EvaluationResult<O>> {
182
+ const { debug = false } = options;
183
+
184
+ // Load JDM if path provided
185
+ const jdmObj =
186
+ typeof jdm === 'string'
187
+ ? (JSON.parse(readFileSync(jdm, 'utf-8')) as JDMDecision)
188
+ : (jdm as JDMDecision);
189
+
190
+ // Infer schemas if not provided
191
+ const inputSchema = options.inputSchema ?? inferSchema(input);
192
+ const outputSchema = options.outputSchema ?? Type.Object({});
193
+
194
+ // Compile to WASM
195
+ const compiled = await compile({
196
+ jdm: jdmObj,
197
+ inputSchema,
198
+ outputSchema,
199
+ debug,
200
+ });
201
+
202
+ // Create decision instance and evaluate
203
+ const decision = await createCompiledDecision(compiled);
204
+ const result = await decision.evaluate<I, O>(input);
205
+
206
+ return {
207
+ result,
208
+ decision,
209
+ compilation: compiled,
210
+ };
211
+ }
212
+
213
+ /**
214
+ * Create a minimal JDM decision with expression nodes.
215
+ *
216
+ * This helper creates a simple JDM structure for testing expression
217
+ * evaluation without needing to define the full JDM JSON.
218
+ *
219
+ * @param expressions - Array of key-value expressions to evaluate
220
+ * @returns A complete JDM decision object
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * // Single expression
225
+ * const jdm = createExpressionJDM([{ key: 'result', value: 'x + y' }]);
226
+ *
227
+ * // Multiple expressions
228
+ * const jdm = createExpressionJDM([
229
+ * { key: 'sum', value: 'a + b' },
230
+ * { key: 'product', value: 'a * b' },
231
+ * { key: 'isPositive', value: 'a > 0 and b > 0' },
232
+ * ]);
233
+ * ```
234
+ */
235
+ export function createExpressionJDM(
236
+ expressions: Array<{ key: string; value: string }>,
237
+ ): JDMDecision {
238
+ return {
239
+ nodes: [
240
+ {
241
+ id: 'input-1',
242
+ type: 'inputNode' as any,
243
+ position: { x: 0, y: 0 },
244
+ name: 'Request',
245
+ },
246
+ {
247
+ id: 'expr-1',
248
+ type: 'expressionNode' as any,
249
+ position: { x: 200, y: 0 },
250
+ name: 'Expression',
251
+ content: {
252
+ expressions: expressions.map((e, i) => ({
253
+ id: `expr-${i}`,
254
+ key: e.key,
255
+ value: e.value,
256
+ })),
257
+ },
258
+ },
259
+ {
260
+ id: 'output-1',
261
+ type: 'outputNode' as any,
262
+ position: { x: 400, y: 0 },
263
+ name: 'Response',
264
+ },
265
+ ],
266
+ edges: [
267
+ {
268
+ id: 'edge-1',
269
+ sourceId: 'input-1',
270
+ targetId: 'expr-1',
271
+ type: 'edge',
272
+ },
273
+ {
274
+ id: 'edge-2',
275
+ sourceId: 'expr-1',
276
+ targetId: 'output-1',
277
+ type: 'edge',
278
+ },
279
+ ],
280
+ };
281
+ }
282
+
283
+ /**
284
+ * Create a JDM decision with a decision table.
285
+ *
286
+ * This helper creates a JDM with a decision table for testing
287
+ * rule-based decision logic.
288
+ *
289
+ * @param rules - Array of rules with inputs and outputs
290
+ * @param hitPolicy - Hit policy for the decision table
291
+ * @returns A complete JDM decision object
292
+ *
293
+ * @example
294
+ * ```typescript
295
+ * const jdm = createDecisionTableJDM(
296
+ * [
297
+ * { inputs: { age: '>= 18' }, outputs: { category: '"adult"' } },
298
+ * { inputs: { age: '< 18' }, outputs: { category: '"minor"' } },
299
+ * ],
300
+ * 'first'
301
+ * );
302
+ * ```
303
+ */
304
+ export function createDecisionTableJDM(
305
+ rules: Array<{
306
+ inputs: Record<string, string>;
307
+ outputs: Record<string, string>;
308
+ }>,
309
+ hitPolicy: 'first' | 'collect' = 'first',
310
+ ): JDMDecision {
311
+ // Extract input and output field names from rules
312
+ const inputFields = new Set<string>();
313
+ const outputFields = new Set<string>();
314
+
315
+ for (const rule of rules) {
316
+ Object.keys(rule.inputs).forEach((k) => inputFields.add(k));
317
+ Object.keys(rule.outputs).forEach((k) => outputFields.add(k));
318
+ }
319
+
320
+ // Create input columns
321
+ const inputs = Array.from(inputFields).map((field, i) => ({
322
+ id: `input-col-${i}`,
323
+ name: field,
324
+ field,
325
+ type: 'expression' as const,
326
+ }));
327
+
328
+ // Create output columns
329
+ const outputs = Array.from(outputFields).map((field, i) => ({
330
+ id: `output-col-${i}`,
331
+ name: field,
332
+ field,
333
+ type: 'expression' as const,
334
+ }));
335
+
336
+ // Create rules
337
+ const tableRules = rules.map((rule, i) => ({
338
+ _id: `rule-${i}`,
339
+ ...Object.fromEntries(inputs.map((inp) => [inp.id, rule.inputs[inp.field] ?? ''])),
340
+ ...Object.fromEntries(outputs.map((out) => [out.id, rule.outputs[out.field] ?? ''])),
341
+ }));
342
+
343
+ return {
344
+ nodes: [
345
+ {
346
+ id: 'input-1',
347
+ type: 'inputNode' as any,
348
+ position: { x: 0, y: 0 },
349
+ name: 'Request',
350
+ },
351
+ {
352
+ id: 'table-1',
353
+ type: 'decisionTableNode' as any,
354
+ position: { x: 200, y: 0 },
355
+ name: 'Decision Table',
356
+ content: {
357
+ hitPolicy,
358
+ inputs,
359
+ outputs,
360
+ rules: tableRules,
361
+ },
362
+ },
363
+ {
364
+ id: 'output-1',
365
+ type: 'outputNode' as any,
366
+ position: { x: 400, y: 0 },
367
+ name: 'Response',
368
+ },
369
+ ],
370
+ edges: [
371
+ {
372
+ id: 'edge-1',
373
+ sourceId: 'input-1',
374
+ targetId: 'table-1',
375
+ type: 'edge',
376
+ },
377
+ {
378
+ id: 'edge-2',
379
+ sourceId: 'table-1',
380
+ targetId: 'output-1',
381
+ type: 'edge',
382
+ },
383
+ ],
384
+ };
385
+ }
386
+
387
+ /**
388
+ * Create a JDM decision with a switch node.
389
+ *
390
+ * @param conditions - Array of condition/content pairs
391
+ * @returns A complete JDM decision object
392
+ *
393
+ * @example
394
+ * ```typescript
395
+ * const jdm = createSwitchJDM([
396
+ * { condition: 'score >= 90', expressions: [{ key: 'grade', value: '"A"' }] },
397
+ * { condition: 'score >= 80', expressions: [{ key: 'grade', value: '"B"' }] },
398
+ * { condition: 'true', expressions: [{ key: 'grade', value: '"C"' }] }, // default
399
+ * ]);
400
+ * ```
401
+ */
402
+ export function createSwitchJDM(
403
+ conditions: Array<{
404
+ condition: string;
405
+ expressions: Array<{ key: string; value: string }>;
406
+ }>,
407
+ ): JDMDecision {
408
+ const nodes: any[] = [
409
+ {
410
+ id: 'input-1',
411
+ type: 'inputNode',
412
+ position: { x: 0, y: 0 },
413
+ name: 'Request',
414
+ },
415
+ {
416
+ id: 'switch-1',
417
+ type: 'switchNode',
418
+ position: { x: 200, y: 0 },
419
+ name: 'Switch',
420
+ content: {
421
+ hitPolicy: 'first',
422
+ statements: conditions.map((c, i) => ({
423
+ id: `stmt-${i}`,
424
+ condition: c.condition,
425
+ })),
426
+ },
427
+ },
428
+ {
429
+ id: 'output-1',
430
+ type: 'outputNode',
431
+ position: { x: 600, y: 0 },
432
+ name: 'Response',
433
+ },
434
+ ];
435
+
436
+ const edges: any[] = [
437
+ {
438
+ id: 'edge-input-switch',
439
+ sourceId: 'input-1',
440
+ targetId: 'switch-1',
441
+ type: 'edge',
442
+ },
443
+ ];
444
+
445
+ // Create expression nodes for each condition
446
+ conditions.forEach((c, i) => {
447
+ const exprNodeId = `expr-${i}`;
448
+ nodes.push({
449
+ id: exprNodeId,
450
+ type: 'expressionNode',
451
+ position: { x: 400, y: i * 100 },
452
+ name: `Expression ${i + 1}`,
453
+ content: {
454
+ expressions: c.expressions.map((e, j) => ({
455
+ id: `expr-${i}-${j}`,
456
+ key: e.key,
457
+ value: e.value,
458
+ })),
459
+ },
460
+ });
461
+
462
+ // Edge from switch to expression (with sourceHandle for the statement)
463
+ edges.push({
464
+ id: `edge-switch-expr-${i}`,
465
+ sourceId: 'switch-1',
466
+ sourceHandle: `stmt-${i}`,
467
+ targetId: exprNodeId,
468
+ type: 'edge',
469
+ });
470
+
471
+ // Edge from expression to output
472
+ edges.push({
473
+ id: `edge-expr-output-${i}`,
474
+ sourceId: exprNodeId,
475
+ targetId: 'output-1',
476
+ type: 'edge',
477
+ });
478
+ });
479
+
480
+ return { nodes, edges };
481
+ }
482
+
483
+ /**
484
+ * Infer a TypeBox schema from a value.
485
+ *
486
+ * This is a simple schema inference for testing purposes.
487
+ * For production use, prefer explicit schemas.
488
+ *
489
+ * @param value - The value to infer schema from
490
+ * @returns A TypeBox schema matching the value structure
491
+ */
492
+ export function inferSchema(value: unknown): TSchema {
493
+ if (value === null) {
494
+ return Type.Null();
495
+ }
496
+ if (value === undefined) {
497
+ return Type.Unknown();
498
+ }
499
+ if (typeof value === 'boolean') {
500
+ return Type.Boolean();
501
+ }
502
+ if (typeof value === 'number') {
503
+ return Type.Number();
504
+ }
505
+ if (typeof value === 'string') {
506
+ return Type.String();
507
+ }
508
+
509
+ if (Array.isArray(value)) {
510
+ if (value.length === 0) {
511
+ return Type.Array(Type.Unknown());
512
+ }
513
+ // Use first element to infer array type
514
+ return Type.Array(inferSchema(value[0]));
515
+ }
516
+
517
+ if (typeof value === 'object') {
518
+ const properties: Record<string, TSchema> = {};
519
+ for (const [key, val] of Object.entries(value)) {
520
+ properties[key] = inferSchema(val);
521
+ }
522
+ return Type.Object(properties);
523
+ }
524
+
525
+ return Type.Unknown();
526
+ }
527
+
528
+ /**
529
+ * Compile a JDM decision and return the compiled result.
530
+ *
531
+ * Use this when you need access to the compilation result
532
+ * without immediately evaluating.
533
+ *
534
+ * @param jdm - The JDM decision object or path to file
535
+ * @param options - Compilation options
536
+ * @returns The compilation result
537
+ *
538
+ * @example
539
+ * ```typescript
540
+ * const compiled = await compileJDM(jdm, {
541
+ * inputSchema: MyInputSchema,
542
+ * outputSchema: MyOutputSchema,
543
+ * debug: true,
544
+ * });
545
+ *
546
+ * // Inspect generated code
547
+ * console.log(compiled.assemblyScript);
548
+ *
549
+ * // Create multiple decision instances
550
+ * const decision1 = await createCompiledDecision(compiled);
551
+ * const decision2 = await createCompiledDecision(compiled);
552
+ * ```
553
+ */
554
+ export async function compileJDM(
555
+ jdm: JDMDecision | object | string,
556
+ options: {
557
+ inputSchema?: TSchema;
558
+ outputSchema?: TSchema;
559
+ debug?: boolean;
560
+ } = {},
561
+ ): Promise<CompilationResult> {
562
+ const { debug = false } = options;
563
+
564
+ // Load JDM if path provided
565
+ const jdmObj =
566
+ typeof jdm === 'string'
567
+ ? (JSON.parse(readFileSync(jdm, 'utf-8')) as JDMDecision)
568
+ : (jdm as JDMDecision);
569
+
570
+ // Default schemas
571
+ const inputSchema = options.inputSchema ?? Type.Object({});
572
+ const outputSchema = options.outputSchema ?? Type.Object({});
573
+
574
+ return compile({
575
+ jdm: jdmObj,
576
+ inputSchema,
577
+ outputSchema,
578
+ debug,
579
+ });
580
+ }
581
+
582
+ /**
583
+ * Test assertion helper for comparing evaluation results.
584
+ *
585
+ * Handles floating point comparison and nested object comparison.
586
+ *
587
+ * @param actual - The actual evaluation result
588
+ * @param expected - The expected result
589
+ * @param message - Optional error message prefix
590
+ */
591
+ export function assertEvaluationResult(
592
+ actual: unknown,
593
+ expected: unknown,
594
+ message = 'Evaluation result mismatch',
595
+ ): void {
596
+ const compare = (a: unknown, b: unknown, path: string): void => {
597
+ if (a === b) {
598
+ return;
599
+ }
600
+
601
+ // Handle null/undefined
602
+ if (a === null || b === null || a === undefined || b === undefined) {
603
+ if (a !== b) {
604
+ throw new Error(`${message} at ${path}: expected ${b}, got ${a}`);
605
+ }
606
+ return;
607
+ }
608
+
609
+ // Handle numbers with floating point tolerance
610
+ if (typeof a === 'number' && typeof b === 'number') {
611
+ const tolerance = 1e-10;
612
+ if (Math.abs(a - b) > tolerance) {
613
+ throw new Error(`${message} at ${path}: expected ${b}, got ${a}`);
614
+ }
615
+ return;
616
+ }
617
+
618
+ // Handle arrays
619
+ if (Array.isArray(a) && Array.isArray(b)) {
620
+ if (a.length !== b.length) {
621
+ throw new Error(
622
+ `${message} at ${path}: array length mismatch (expected ${b.length}, got ${a.length})`,
623
+ );
624
+ }
625
+ for (let i = 0; i < a.length; i++) {
626
+ compare(a[i], b[i], `${path}[${i}]`);
627
+ }
628
+ return;
629
+ }
630
+
631
+ // Handle objects
632
+ if (typeof a === 'object' && typeof b === 'object') {
633
+ const aObj = a as Record<string, unknown>;
634
+ const bObj = b as Record<string, unknown>;
635
+ const aKeys = Object.keys(aObj);
636
+ const bKeys = Object.keys(bObj);
637
+
638
+ // Check for missing keys
639
+ for (const key of bKeys) {
640
+ if (!(key in aObj)) {
641
+ throw new Error(`${message} at ${path}: missing key "${key}"`);
642
+ }
643
+ }
644
+
645
+ // Compare values
646
+ for (const key of aKeys) {
647
+ compare(aObj[key], bObj[key], `${path}.${key}`);
648
+ }
649
+ return;
650
+ }
651
+
652
+ // Direct comparison for primitives
653
+ if (a !== b) {
654
+ throw new Error(`${message} at ${path}: expected ${b}, got ${a}`);
655
+ }
656
+ };
657
+
658
+ compare(actual, expected, 'root');
659
+ }