@milaboratories/pl-middle-layer 1.74.11 → 1.74.13

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 (320) hide show
  1. package/dist/_virtual/{_@oxc-project_runtime@0.137.0 → _@oxc-project_runtime@0.155.0}/helpers/esm/usingCtx.cjs +1 -2
  2. package/dist/_virtual/{_@oxc-project_runtime@0.137.0 → _@oxc-project_runtime@0.155.0}/helpers/esm/usingCtx.js +1 -2
  3. package/dist/_virtual/_rolldown/runtime.cjs +2 -3
  4. package/dist/block_registry/location_provider.cjs +1 -2
  5. package/dist/block_registry/location_provider.cjs.map +1 -1
  6. package/dist/block_registry/location_provider.js +1 -2
  7. package/dist/block_registry/registry-v2-provider.cjs +1 -2
  8. package/dist/block_registry/registry-v2-provider.cjs.map +1 -1
  9. package/dist/block_registry/registry-v2-provider.d.ts +0 -2
  10. package/dist/block_registry/registry-v2-provider.d.ts.map +1 -1
  11. package/dist/block_registry/registry-v2-provider.js +1 -2
  12. package/dist/block_registry/registry.cjs +3 -3
  13. package/dist/block_registry/registry.cjs.map +1 -1
  14. package/dist/block_registry/registry.d.ts +0 -2
  15. package/dist/block_registry/registry.d.ts.map +1 -1
  16. package/dist/block_registry/registry.js +3 -3
  17. package/dist/block_registry/registry.js.map +1 -1
  18. package/dist/block_registry/template_provider.cjs +1 -2
  19. package/dist/block_registry/template_provider.cjs.map +1 -1
  20. package/dist/block_registry/template_provider.d.ts +0 -2
  21. package/dist/block_registry/template_provider.d.ts.map +1 -1
  22. package/dist/block_registry/template_provider.js +1 -2
  23. package/dist/block_registry/watcher.cjs +15 -14
  24. package/dist/block_registry/watcher.cjs.map +1 -1
  25. package/dist/block_registry/watcher.d.ts +0 -2
  26. package/dist/block_registry/watcher.d.ts.map +1 -1
  27. package/dist/block_registry/watcher.js +15 -14
  28. package/dist/block_registry/watcher.js.map +1 -1
  29. package/dist/block_registry/well_known_registries.cjs +1 -2
  30. package/dist/block_registry/well_known_registries.d.ts +0 -2
  31. package/dist/block_registry/well_known_registries.d.ts.map +1 -1
  32. package/dist/block_registry/well_known_registries.js +1 -2
  33. package/dist/cfg_render/executor.cjs +1 -2
  34. package/dist/cfg_render/executor.cjs.map +1 -1
  35. package/dist/cfg_render/executor.js +1 -2
  36. package/dist/cfg_render/renderer.cjs +1 -2
  37. package/dist/cfg_render/renderer.cjs.map +1 -1
  38. package/dist/cfg_render/renderer.js +1 -2
  39. package/dist/cfg_render/traverse.cjs +1 -2
  40. package/dist/cfg_render/traverse.js +1 -2
  41. package/dist/cfg_render/util.cjs +1 -2
  42. package/dist/cfg_render/util.js +1 -2
  43. package/dist/debug/index.cjs +1 -2
  44. package/dist/debug/index.js +1 -2
  45. package/dist/dev_env/index.cjs +1 -2
  46. package/dist/dev_env/index.cjs.map +1 -1
  47. package/dist/dev_env/index.js +1 -2
  48. package/dist/dev_env/util.cjs +1 -2
  49. package/dist/dev_env/util.js +1 -2
  50. package/dist/js_render/column_registry.cjs +1 -2
  51. package/dist/js_render/column_registry.cjs.map +1 -1
  52. package/dist/js_render/column_registry.js +1 -2
  53. package/dist/js_render/computable_context.cjs +4 -4
  54. package/dist/js_render/computable_context.cjs.map +1 -1
  55. package/dist/js_render/computable_context.js +4 -4
  56. package/dist/js_render/computable_context.js.map +1 -1
  57. package/dist/js_render/context.cjs +1 -2
  58. package/dist/js_render/context.cjs.map +1 -1
  59. package/dist/js_render/context.js +1 -2
  60. package/dist/js_render/index.cjs +12 -9
  61. package/dist/js_render/index.cjs.map +1 -1
  62. package/dist/js_render/index.js +12 -9
  63. package/dist/js_render/index.js.map +1 -1
  64. package/dist/js_render/service_injectors.cjs +2 -3
  65. package/dist/js_render/service_injectors.js +2 -3
  66. package/dist/js_render/spec_override_collapse.cjs +1 -2
  67. package/dist/js_render/spec_override_collapse.cjs.map +1 -1
  68. package/dist/js_render/spec_override_collapse.js +1 -2
  69. package/dist/middle_layer/active_cfg.cjs +1 -2
  70. package/dist/middle_layer/active_cfg.cjs.map +1 -1
  71. package/dist/middle_layer/active_cfg.js +1 -2
  72. package/dist/middle_layer/block.cjs +1 -2
  73. package/dist/middle_layer/block.cjs.map +1 -1
  74. package/dist/middle_layer/block.js +1 -2
  75. package/dist/middle_layer/block_ctx.cjs +3 -3
  76. package/dist/middle_layer/block_ctx.cjs.map +1 -1
  77. package/dist/middle_layer/block_ctx.js +3 -3
  78. package/dist/middle_layer/block_ctx.js.map +1 -1
  79. package/dist/middle_layer/block_ctx_unsafe.cjs +1 -2
  80. package/dist/middle_layer/block_ctx_unsafe.js +1 -2
  81. package/dist/middle_layer/build_stamp.cjs +2 -3
  82. package/dist/middle_layer/build_stamp.js +2 -3
  83. package/dist/middle_layer/driver_kit.cjs +1 -2
  84. package/dist/middle_layer/driver_kit.cjs.map +1 -1
  85. package/dist/middle_layer/driver_kit.d.ts +0 -2
  86. package/dist/middle_layer/driver_kit.d.ts.map +1 -1
  87. package/dist/middle_layer/driver_kit.js +1 -2
  88. package/dist/middle_layer/finality_stop_rules.cjs +1 -2
  89. package/dist/middle_layer/finality_stop_rules.js +1 -2
  90. package/dist/middle_layer/folders.cjs +12 -8
  91. package/dist/middle_layer/folders.cjs.map +1 -1
  92. package/dist/middle_layer/folders.d.ts +0 -2
  93. package/dist/middle_layer/folders.d.ts.map +1 -1
  94. package/dist/middle_layer/folders.js +12 -8
  95. package/dist/middle_layer/folders.js.map +1 -1
  96. package/dist/middle_layer/frontend_path.cjs +1 -2
  97. package/dist/middle_layer/frontend_path.cjs.map +1 -1
  98. package/dist/middle_layer/frontend_path.js +1 -2
  99. package/dist/middle_layer/middle_layer.cjs +7 -6
  100. package/dist/middle_layer/middle_layer.cjs.map +1 -1
  101. package/dist/middle_layer/middle_layer.d.ts +0 -2
  102. package/dist/middle_layer/middle_layer.d.ts.map +1 -1
  103. package/dist/middle_layer/middle_layer.js +7 -6
  104. package/dist/middle_layer/middle_layer.js.map +1 -1
  105. package/dist/middle_layer/navigation_states.cjs +1 -2
  106. package/dist/middle_layer/navigation_states.js +1 -2
  107. package/dist/middle_layer/ops.cjs +10 -11
  108. package/dist/middle_layer/ops.cjs.map +1 -1
  109. package/dist/middle_layer/ops.d.ts +0 -2
  110. package/dist/middle_layer/ops.d.ts.map +1 -1
  111. package/dist/middle_layer/ops.js +10 -11
  112. package/dist/middle_layer/ops.js.map +1 -1
  113. package/dist/middle_layer/project.cjs +3 -3
  114. package/dist/middle_layer/project.cjs.map +1 -1
  115. package/dist/middle_layer/project.d.ts +3 -5
  116. package/dist/middle_layer/project.d.ts.map +1 -1
  117. package/dist/middle_layer/project.js +3 -3
  118. package/dist/middle_layer/project.js.map +1 -1
  119. package/dist/middle_layer/project_list.cjs +1 -2
  120. package/dist/middle_layer/project_list.cjs.map +1 -1
  121. package/dist/middle_layer/project_list.d.ts +0 -2
  122. package/dist/middle_layer/project_list.d.ts.map +1 -1
  123. package/dist/middle_layer/project_list.js +1 -2
  124. package/dist/middle_layer/project_overview.cjs +8 -5
  125. package/dist/middle_layer/project_overview.cjs.map +1 -1
  126. package/dist/middle_layer/project_overview.js +8 -5
  127. package/dist/middle_layer/project_overview.js.map +1 -1
  128. package/dist/middle_layer/project_overview_light.cjs +4 -3
  129. package/dist/middle_layer/project_overview_light.cjs.map +1 -1
  130. package/dist/middle_layer/project_overview_light.js +4 -3
  131. package/dist/middle_layer/project_overview_light.js.map +1 -1
  132. package/dist/middle_layer/render.cjs +1 -2
  133. package/dist/middle_layer/render.cjs.map +1 -1
  134. package/dist/middle_layer/render.js +1 -2
  135. package/dist/middle_layer/sharing_list.cjs +1 -2
  136. package/dist/middle_layer/sharing_list.cjs.map +1 -1
  137. package/dist/middle_layer/sharing_list.d.ts +0 -2
  138. package/dist/middle_layer/sharing_list.d.ts.map +1 -1
  139. package/dist/middle_layer/sharing_list.js +1 -2
  140. package/dist/middle_layer/sharing_list.js.map +1 -1
  141. package/dist/middle_layer/template_list.cjs +1 -2
  142. package/dist/middle_layer/template_list.cjs.map +1 -1
  143. package/dist/middle_layer/template_list.d.ts +0 -2
  144. package/dist/middle_layer/template_list.d.ts.map +1 -1
  145. package/dist/middle_layer/template_list.js +1 -2
  146. package/dist/middle_layer/tree_snapshot_store.cjs +3 -3
  147. package/dist/middle_layer/tree_snapshot_store.cjs.map +1 -1
  148. package/dist/middle_layer/tree_snapshot_store.d.ts +0 -2
  149. package/dist/middle_layer/tree_snapshot_store.d.ts.map +1 -1
  150. package/dist/middle_layer/tree_snapshot_store.js +3 -3
  151. package/dist/middle_layer/tree_snapshot_store.js.map +1 -1
  152. package/dist/middle_layer/types.d.ts +0 -2
  153. package/dist/middle_layer/types.d.ts.map +1 -1
  154. package/dist/middle_layer/util.cjs +1 -2
  155. package/dist/middle_layer/util.cjs.map +1 -1
  156. package/dist/middle_layer/util.js +1 -2
  157. package/dist/model/args.cjs +1 -2
  158. package/dist/model/args.cjs.map +1 -1
  159. package/dist/model/args.js +1 -2
  160. package/dist/model/block_pack_spec.cjs +1 -2
  161. package/dist/model/block_pack_spec.d.ts +0 -2
  162. package/dist/model/block_pack_spec.d.ts.map +1 -1
  163. package/dist/model/block_pack_spec.js +1 -2
  164. package/dist/model/frontend.d.ts +0 -2
  165. package/dist/model/frontend.d.ts.map +1 -1
  166. package/dist/model/project_helper.cjs +1 -2
  167. package/dist/model/project_helper.cjs.map +1 -1
  168. package/dist/model/project_helper.d.ts +0 -2
  169. package/dist/model/project_helper.d.ts.map +1 -1
  170. package/dist/model/project_helper.js +1 -2
  171. package/dist/model/project_model.cjs +1 -2
  172. package/dist/model/project_model.d.ts +0 -2
  173. package/dist/model/project_model.d.ts.map +1 -1
  174. package/dist/model/project_model.js +1 -2
  175. package/dist/model/project_model_util.cjs +1 -2
  176. package/dist/model/project_model_util.js +1 -2
  177. package/dist/model/project_model_v1.cjs +1 -2
  178. package/dist/model/project_model_v1.js +1 -2
  179. package/dist/model/sharing_model.cjs +1 -2
  180. package/dist/model/sharing_model.cjs.map +1 -1
  181. package/dist/model/sharing_model.d.ts +0 -2
  182. package/dist/model/sharing_model.d.ts.map +1 -1
  183. package/dist/model/sharing_model.js +1 -2
  184. package/dist/model/template_apply.cjs +1 -2
  185. package/dist/model/template_apply.cjs.map +1 -1
  186. package/dist/model/template_apply.d.ts +0 -2
  187. package/dist/model/template_apply.d.ts.map +1 -1
  188. package/dist/model/template_apply.js +1 -2
  189. package/dist/model/template_export.cjs +1 -2
  190. package/dist/model/template_export.d.ts +0 -2
  191. package/dist/model/template_export.d.ts.map +1 -1
  192. package/dist/model/template_export.js +1 -2
  193. package/dist/model/template_parser.cjs +1 -2
  194. package/dist/model/template_parser.cjs.map +1 -1
  195. package/dist/model/template_parser.d.ts +0 -2
  196. package/dist/model/template_parser.d.ts.map +1 -1
  197. package/dist/model/template_parser.js +1 -2
  198. package/dist/model/template_resolve.cjs +1 -2
  199. package/dist/model/template_resolve.cjs.map +1 -1
  200. package/dist/model/template_resolve.d.ts +0 -2
  201. package/dist/model/template_resolve.d.ts.map +1 -1
  202. package/dist/model/template_resolve.js +1 -2
  203. package/dist/model/template_serializer.cjs +1 -2
  204. package/dist/model/template_serializer.cjs.map +1 -1
  205. package/dist/model/template_serializer.d.ts +0 -2
  206. package/dist/model/template_serializer.d.ts.map +1 -1
  207. package/dist/model/template_serializer.js +1 -2
  208. package/dist/model/template_spec.d.ts +0 -2
  209. package/dist/model/template_spec.d.ts.map +1 -1
  210. package/dist/mutator/block-pack/block_pack.cjs +7 -6
  211. package/dist/mutator/block-pack/block_pack.cjs.map +1 -1
  212. package/dist/mutator/block-pack/block_pack.d.ts +0 -2
  213. package/dist/mutator/block-pack/block_pack.d.ts.map +1 -1
  214. package/dist/mutator/block-pack/block_pack.js +7 -6
  215. package/dist/mutator/block-pack/block_pack.js.map +1 -1
  216. package/dist/mutator/block-pack/frontend.cjs +1 -2
  217. package/dist/mutator/block-pack/frontend.cjs.map +1 -1
  218. package/dist/mutator/block-pack/frontend.js +1 -2
  219. package/dist/mutator/block-pack/required_capabilities.cjs +1 -2
  220. package/dist/mutator/block-pack/required_capabilities.cjs.map +1 -1
  221. package/dist/mutator/block-pack/required_capabilities.js +1 -2
  222. package/dist/mutator/context_export.cjs +1 -2
  223. package/dist/mutator/context_export.cjs.map +1 -1
  224. package/dist/mutator/context_export.js +1 -2
  225. package/dist/mutator/list.cjs +1 -2
  226. package/dist/mutator/list.cjs.map +1 -1
  227. package/dist/mutator/list.js +1 -2
  228. package/dist/mutator/migration.cjs +1 -2
  229. package/dist/mutator/migration.cjs.map +1 -1
  230. package/dist/mutator/migration.js +1 -2
  231. package/dist/mutator/project.cjs +30 -22
  232. package/dist/mutator/project.cjs.map +1 -1
  233. package/dist/mutator/project.d.ts +0 -2
  234. package/dist/mutator/project.d.ts.map +1 -1
  235. package/dist/mutator/project.js +30 -22
  236. package/dist/mutator/project.js.map +1 -1
  237. package/dist/mutator/sharing.cjs +1 -2
  238. package/dist/mutator/sharing.cjs.map +1 -1
  239. package/dist/mutator/sharing.js +1 -2
  240. package/dist/mutator/template/direct_template_loader.cjs +1 -2
  241. package/dist/mutator/template/direct_template_loader.cjs.map +1 -1
  242. package/dist/mutator/template/direct_template_loader.js +1 -2
  243. package/dist/mutator/template/direct_template_loader_v3.cjs +1 -2
  244. package/dist/mutator/template/direct_template_loader_v3.cjs.map +1 -1
  245. package/dist/mutator/template/direct_template_loader_v3.js +1 -2
  246. package/dist/mutator/template/render_block.cjs +1 -2
  247. package/dist/mutator/template/render_block.cjs.map +1 -1
  248. package/dist/mutator/template/render_block.js +1 -2
  249. package/dist/mutator/template/render_template.cjs +1 -2
  250. package/dist/mutator/template/render_template.cjs.map +1 -1
  251. package/dist/mutator/template/render_template.d.ts +0 -2
  252. package/dist/mutator/template/render_template.d.ts.map +1 -1
  253. package/dist/mutator/template/render_template.js +1 -2
  254. package/dist/mutator/template/template_cache.cjs +6 -5
  255. package/dist/mutator/template/template_cache.cjs.map +1 -1
  256. package/dist/mutator/template/template_cache.d.ts +1 -2
  257. package/dist/mutator/template/template_cache.d.ts.map +1 -1
  258. package/dist/mutator/template/template_cache.js +6 -5
  259. package/dist/mutator/template/template_cache.js.map +1 -1
  260. package/dist/mutator/template/template_loading.cjs +1 -2
  261. package/dist/mutator/template/template_loading.cjs.map +1 -1
  262. package/dist/mutator/template/template_loading.d.ts +0 -2
  263. package/dist/mutator/template/template_loading.d.ts.map +1 -1
  264. package/dist/mutator/template/template_loading.js +1 -2
  265. package/dist/mutator/template.cjs +1 -2
  266. package/dist/mutator/template.cjs.map +1 -1
  267. package/dist/mutator/template.js +1 -2
  268. package/dist/mutator/template_construct.cjs +1 -2
  269. package/dist/mutator/template_construct.cjs.map +1 -1
  270. package/dist/mutator/template_construct.js +1 -2
  271. package/dist/network_check/network_check.cjs +2 -3
  272. package/dist/network_check/network_check.cjs.map +1 -1
  273. package/dist/network_check/network_check.d.ts +0 -2
  274. package/dist/network_check/network_check.d.ts.map +1 -1
  275. package/dist/network_check/network_check.js +2 -3
  276. package/dist/network_check/network_check.js.map +1 -1
  277. package/dist/network_check/pings.cjs +1 -2
  278. package/dist/network_check/pings.cjs.map +1 -1
  279. package/dist/network_check/pings.js +1 -2
  280. package/dist/network_check/template.cjs +5 -4
  281. package/dist/network_check/template.cjs.map +1 -1
  282. package/dist/network_check/template.js +5 -4
  283. package/dist/network_check/template.js.map +1 -1
  284. package/dist/pool/data.cjs +1 -2
  285. package/dist/pool/data.cjs.map +1 -1
  286. package/dist/pool/data.d.ts +0 -2
  287. package/dist/pool/data.d.ts.map +1 -1
  288. package/dist/pool/data.js +1 -2
  289. package/dist/pool/driver.cjs +5 -4
  290. package/dist/pool/driver.cjs.map +1 -1
  291. package/dist/pool/driver.d.ts +0 -2
  292. package/dist/pool/driver.d.ts.map +1 -1
  293. package/dist/pool/driver.js +5 -4
  294. package/dist/pool/driver.js.map +1 -1
  295. package/dist/pool/p_object_collection.cjs +9 -8
  296. package/dist/pool/p_object_collection.cjs.map +1 -1
  297. package/dist/pool/p_object_collection.d.ts +0 -2
  298. package/dist/pool/p_object_collection.d.ts.map +1 -1
  299. package/dist/pool/p_object_collection.js +9 -8
  300. package/dist/pool/p_object_collection.js.map +1 -1
  301. package/dist/pool/result_pool.cjs +8 -7
  302. package/dist/pool/result_pool.cjs.map +1 -1
  303. package/dist/pool/result_pool.js +8 -7
  304. package/dist/pool/result_pool.js.map +1 -1
  305. package/dist/pool/upstream_block_ctx.cjs +1 -2
  306. package/dist/pool/upstream_block_ctx.cjs.map +1 -1
  307. package/dist/pool/upstream_block_ctx.js +1 -2
  308. package/dist/service_factories.cjs +1 -2
  309. package/dist/service_factories.js +1 -2
  310. package/dist/worker/WorkerManager.cjs +1 -2
  311. package/dist/worker/WorkerManager.js +1 -2
  312. package/dist/worker/WorkerManager.js.map +1 -1
  313. package/dist/worker/worker.cjs +1 -2
  314. package/dist/worker/worker.js +1 -2
  315. package/dist/worker/workerApi.cjs +1 -2
  316. package/dist/worker/workerApi.cjs.map +1 -1
  317. package/dist/worker/workerApi.js +1 -2
  318. package/package.json +33 -33
  319. package/src/middle_layer/middle_layer.ts +4 -6
  320. package/src/middle_layer/tree_snapshot_store.test.ts +4 -1
@@ -1 +1 @@
1
- {"version":3,"file":"template_cache.cjs","names":["PlTemplateLibV1","PlTemplateSoftwareV1","PlWasmV1","PlTemplateV1","PlTemplateOverrideV1","_","getDebugFlags"],"sources":["../../../src/mutator/template/template_cache.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport type {\n AnyResourceRef,\n PlClient,\n PlTransaction,\n SignedResourceId,\n ResourceRef,\n} from \"@milaboratories/pl-client\";\nimport {\n ensureSignedResourceIdNotNull,\n field,\n resourceType,\n toGlobalResourceId,\n} from \"@milaboratories/pl-client\";\nimport {\n parseTemplate,\n PlTemplateLibV1,\n PlTemplateOverrideV1,\n PlTemplateSoftwareV1,\n PlTemplateV1,\n PlWasmV1,\n} from \"@milaboratories/pl-model-backend\";\nimport type {\n CompiledTemplateV3,\n TemplateData,\n TemplateDataV3,\n TemplateLibData,\n TemplateLibDataV3,\n TemplateSoftwareData,\n TemplateSoftwareDataV3,\n TemplateWasmDataV3,\n} from \"@milaboratories/pl-model-backend\";\nimport { notEmpty } from \"@milaboratories/ts-helpers\";\nimport type { BlockPackSpecPrepared } from \"../../model\";\nimport type { TemplateSpecPrepared } from \"../../model/template_spec\";\nimport { getDebugFlags } from \"../../debug\";\n\nexport const TemplateCacheType = resourceType(\"TemplateCache\", \"1\");\n\nexport const TemplateCacheFieldName = \"__templateCache\";\nconst BATCH_SIZE = 50;\n/** @internal exported for testing */\nexport const GC_ACCESS_THRESHOLD = 30;\n/** @internal exported for testing */\nexport const GC_MAX_ENTRIES = 3000;\n/** @internal exported for testing */\nexport const ACCESS_COUNT_KEY = \"_accessCount\";\n/** @internal exported for testing */\nexport const ACCESS_KEY_PREFIX = \"access_\";\n\nexport type TemplateCacheStat = {\n totalMs: number;\n flattenMs: number;\n cacheInitMs: number;\n materializeMs: number;\n totalNodes: number;\n cacheHits: number;\n cacheMisses: number;\n batchCount: number;\n happyPath: boolean;\n gcTriggered: boolean;\n retries: number;\n templateFormat: string;\n};\n\nfunction initialStat(): TemplateCacheStat {\n return {\n totalMs: 0,\n flattenMs: 0,\n cacheInitMs: 0,\n materializeMs: 0,\n totalNodes: 0,\n cacheHits: 0,\n cacheMisses: 0,\n batchCount: 0,\n happyPath: false,\n gcTriggered: false,\n retries: 0,\n templateFormat: \"\",\n };\n}\n\ninterface CacheableNode {\n /** SHA-256 content hash (includes all descendant content) */\n hash: string;\n /** Creates this node's resource in a transaction.\n * childRefs maps child hash → already-resolved ResourceRef or SignedResourceId */\n create: (tx: PlTransaction, childRefs: ReadonlyMap<string, AnyResourceRef>) => ResourceRef;\n /** Hashes of direct child nodes this node depends on */\n childHashes: string[];\n}\n\nfunction getSourceCode(name: string, sources: Record<string, string>, sourceHash: string): string {\n return notEmpty(\n sources[sourceHash],\n `trying to get \"${name}\" source: sources map doesn't contain source hash ${sourceHash}`,\n );\n}\n\n/**\n * Bottom-up hash composition: each node hashes its OWN content + child hash STRINGS.\n * This means each unique node is hashed exactly once → O(n) instead of O(n * depth).\n */\n\n// V2 leaf hashes (libs, software — no children)\n\nfunction hashLibV2(lib: TemplateLibData): string {\n return createHash(\"sha256\")\n .update(PlTemplateLibV1.type.name)\n .update(PlTemplateLibV1.type.version)\n .update(lib.name)\n .update(lib.version)\n .update(lib.src)\n .digest(\"hex\");\n}\n\nfunction hashSoftwareV2(sw: TemplateSoftwareData): string {\n return createHash(\"sha256\")\n .update(PlTemplateSoftwareV1.type.name)\n .update(PlTemplateSoftwareV1.type.version)\n .update(sw.name)\n .update(sw.version)\n .update(sw.src)\n .digest(\"hex\");\n}\n\n// V3 leaf hashes — use sourceHash directly instead of resolving source content\n\nfunction hashLibV3(lib: TemplateLibDataV3): string {\n return createHash(\"sha256\")\n .update(PlTemplateLibV1.type.name)\n .update(PlTemplateLibV1.type.version)\n .update(lib.name)\n .update(lib.version)\n .update(lib.sourceHash)\n .digest(\"hex\");\n}\n\nfunction hashSoftwareV3(sw: TemplateSoftwareDataV3): string {\n return createHash(\"sha256\")\n .update(PlTemplateSoftwareV1.type.name)\n .update(PlTemplateSoftwareV1.type.version)\n .update(sw.name)\n .update(sw.version)\n .update(sw.sourceHash)\n .digest(\"hex\");\n}\n\nfunction hashWasmV3(wasm: TemplateWasmDataV3): string {\n return createHash(\"sha256\")\n .update(PlWasmV1.type.name)\n .update(PlWasmV1.type.version)\n .update(wasm.name)\n .update(wasm.version)\n .update(wasm.sourceHash)\n .digest(\"hex\");\n}\n\n// ─── Tree flattening ─────────────────────────────────────────────────────────\n\nfunction flattenV2Tree(data: TemplateData): CacheableNode[] {\n const nodes: CacheableNode[] = [];\n const seen = new Set<string>();\n\n function processLib(lib: TemplateLibData): string {\n const hash = hashLibV2(lib);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) =>\n tx.createValue(\n PlTemplateLibV1.type,\n JSON.stringify(PlTemplateLibV1.fromV2Data(lib).data),\n ),\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processSoftware(sw: TemplateSoftwareData): string {\n const hash = hashSoftwareV2(sw);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) => {\n const swData = PlTemplateSoftwareV1.fromV2Data(sw);\n const ref = tx.createStruct(PlTemplateSoftwareV1.type, swData.data);\n tx.setKValue(ref, PlTemplateSoftwareV1.metaNameKey, JSON.stringify(swData.name));\n tx.lock(ref);\n return ref;\n },\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processTemplate(tpl: TemplateData): string {\n // Process children first (bottom-up) — their hashes are computed before ours\n const childHashes: string[] = [];\n const children: { fieldName: string; hash: string }[] = [];\n\n for (const [libId, lib] of Object.entries(tpl.libs ?? {})) {\n const h = processLib(lib);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.libPrefix}/${libId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.software ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.assets ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [tplId, sub] of Object.entries(tpl.templates ?? {})) {\n const h = processTemplate(sub);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.tplPrefix}/${tplId}`, hash: h });\n }\n\n // Compose hash from own content + child hash strings (NOT child content)\n const h = createHash(\"sha256\")\n .update(PlTemplateV1.type.name)\n .update(PlTemplateV1.type.version)\n .update(tpl.hashOverride ?? \"no-override\")\n .update(tpl.name)\n .update(tpl.version)\n .update(tpl.src);\n for (const child of children) {\n h.update(\"child:\" + child.fieldName + \":\" + child.hash);\n }\n const hash = h.digest(\"hex\");\n\n if (seen.has(hash)) return hash;\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx, childRefs) => {\n const tplRef = tx.createStruct(\n PlTemplateV1.type,\n JSON.stringify(PlTemplateV1.fromV2Data(tpl).data),\n );\n for (const child of children) {\n const fld = field(tplRef, child.fieldName);\n tx.createField(fld, \"Input\");\n tx.setField(fld, notEmpty(childRefs.get(child.hash), `missing child ref ${child.hash}`));\n }\n tx.lock(tplRef);\n\n if (!tpl.hashOverride) return tplRef;\n\n const overrideRef = tx.createStruct(\n PlTemplateOverrideV1.type,\n JSON.stringify(PlTemplateOverrideV1.fromV2Data(tpl)),\n );\n const overrideFld = PlTemplateOverrideV1.tplField(overrideRef);\n tx.createField(overrideFld, \"Service\");\n tx.setField(overrideFld, tplRef);\n tx.lock(overrideRef);\n return overrideRef;\n },\n childHashes,\n });\n\n return hash;\n }\n\n processTemplate(data);\n return nodes;\n}\n\nfunction flattenV3Tree(data: CompiledTemplateV3): CacheableNode[] {\n const nodes: CacheableNode[] = [];\n const seen = new Set<string>();\n const sources = data.hashToSource;\n\n function processLib(lib: TemplateLibDataV3): string {\n const hash = hashLibV3(lib);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) =>\n tx.createValue(\n PlTemplateLibV1.type,\n JSON.stringify(\n PlTemplateLibV1.fromV3Data(lib, getSourceCode(lib.name, sources, lib.sourceHash))\n .data,\n ),\n ),\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processSoftware(sw: TemplateSoftwareDataV3): string {\n const hash = hashSoftwareV3(sw);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) => {\n const swData = PlTemplateSoftwareV1.fromV3Data(\n sw,\n getSourceCode(sw.name, sources, sw.sourceHash),\n );\n const ref = tx.createStruct(PlTemplateSoftwareV1.type, swData.data);\n tx.setKValue(ref, PlTemplateSoftwareV1.metaNameKey, JSON.stringify(swData.name));\n tx.lock(ref);\n return ref;\n },\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processWasm(wasm: TemplateWasmDataV3): string {\n const hash = hashWasmV3(wasm);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) =>\n tx.createValue(\n PlWasmV1.type,\n JSON.stringify(\n PlWasmV1.fromV3Data(wasm, getSourceCode(wasm.name, sources, wasm.sourceHash)).data,\n ),\n ),\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processTemplate(tpl: TemplateDataV3): string {\n // Defensive: a template can carry no embedded version at runtime even\n // though the type says `string` — the compiler writes `packageJson.version`\n // unchecked, so a template built from a package with no `version` field\n // yields undefined. Identity is fully covered by name + sourceHash, so the\n // placeholder is safe for both the cache key and the backend resource's\n // required Version field.\n const version = tpl.version ?? \"0.0.0\";\n\n // Process children first (bottom-up)\n const childHashes: string[] = [];\n const children: { fieldName: string; hash: string }[] = [];\n\n for (const [libId, lib] of Object.entries(tpl.libs ?? {})) {\n const h = processLib(lib);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.libPrefix}/${libId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.software ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.assets ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [tplId, sub] of Object.entries(tpl.templates ?? {})) {\n const h = processTemplate(sub);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.tplPrefix}/${tplId}`, hash: h });\n }\n for (const [wasmId, wasm] of Object.entries(tpl.wasm ?? {})) {\n const h = processWasm(wasm);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.wasmPrefix}/${wasmId}`, hash: h });\n }\n\n // Compose hash from own content + child hash strings (NOT child content).\n // Uses sourceHash directly — it already uniquely identifies the source.\n const h = createHash(\"sha256\")\n .update(PlTemplateV1.type.name)\n .update(PlTemplateV1.type.version)\n .update(tpl.hashOverride ?? \"no-override\")\n .update(tpl.name)\n .update(version)\n .update(tpl.sourceHash);\n for (const child of children) {\n h.update(\"child:\" + child.fieldName + \":\" + child.hash);\n }\n const hash = h.digest(\"hex\");\n\n if (seen.has(hash)) return hash;\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx, childRefs) => {\n const sourceCode = getSourceCode(tpl.name, sources, tpl.sourceHash);\n const tplRef = tx.createStruct(\n PlTemplateV1.type,\n JSON.stringify(PlTemplateV1.fromV3Data({ ...tpl, version }, sourceCode).data),\n );\n for (const child of children) {\n const fld = field(tplRef, child.fieldName);\n tx.createField(fld, \"Input\");\n tx.setField(fld, notEmpty(childRefs.get(child.hash), `missing child ref ${child.hash}`));\n }\n tx.lock(tplRef);\n\n if (!tpl.hashOverride) return tplRef;\n\n const overrideRef = tx.createStruct(\n PlTemplateOverrideV1.type,\n JSON.stringify(PlTemplateOverrideV1.fromV3Data(tpl)),\n );\n const overrideFld = PlTemplateOverrideV1.tplField(overrideRef);\n tx.createField(overrideFld, \"Service\");\n tx.setField(overrideFld, tplRef);\n tx.lock(overrideRef);\n return overrideRef;\n },\n childHashes,\n });\n\n return hash;\n }\n\n processTemplate(data.template);\n return nodes;\n}\n\n/** Flatten template tree into a topologically ordered list of cacheable nodes (leaves first). */\nexport function flattenTemplateTree(data: TemplateData | CompiledTemplateV3): CacheableNode[] {\n if (data.type === \"pl.tengo-template.v2\") {\n return flattenV2Tree(data);\n } else {\n return flattenV3Tree(data);\n }\n}\n\n/** In-memory cache for the TemplateCache SignedResourceId per PlClient instance. */\nconst cacheRidMap = new WeakMap<PlClient, SignedResourceId>();\n\n/** Clear the in-memory cacheRid entry (call on errors referencing the cache resource). */\nexport function invalidateTemplateCacheId(pl: PlClient): void {\n cacheRidMap.delete(pl);\n}\n\n/** Find or create the TemplateCache/1 resource on user root. */\nexport async function getOrCreateTemplateCache(pl: PlClient): Promise<SignedResourceId> {\n // Check in-memory cache first (0ms after first call)\n const cached = cacheRidMap.get(pl);\n if (cached !== undefined) return cached;\n\n // Try read-only check\n const existing = await pl.withReadTx(\"templateCache:check\", async (tx) => {\n const fd = await tx.getFieldIfExists(field(pl.clientRoot, TemplateCacheFieldName));\n return fd ? ensureSignedResourceIdNotNull(fd.value) : undefined;\n });\n if (existing) {\n cacheRidMap.set(pl, existing);\n return existing;\n }\n\n const result = await pl.withWriteTx(\"templateCache:init\", async (tx) => {\n // Double-check inside write tx (another instance may have created it)\n const fd = await tx.getFieldIfExists(field(pl.clientRoot, TemplateCacheFieldName));\n if (fd) return ensureSignedResourceIdNotNull(fd.value);\n\n const cache = tx.createStruct(TemplateCacheType);\n tx.createField(field(pl.clientRoot, TemplateCacheFieldName), \"Dynamic\", cache);\n tx.lock(cache);\n await tx.commit();\n return await cache.globalId;\n });\n cacheRidMap.set(pl, result);\n return result;\n}\n\n/** Remove the template cache from user root. */\nexport async function dropTemplateCache(pl: PlClient): Promise<void> {\n await pl.withWriteTx(\"templateCache:drop\", async (tx) => {\n const cacheField = field(pl.clientRoot, TemplateCacheFieldName);\n const fd = await tx.getFieldIfExists(cacheField);\n if (fd) {\n tx.removeField(cacheField);\n await tx.commit();\n }\n });\n invalidateTemplateCacheId(pl);\n}\n\n/**\n * Run count-based garbage collection on the template cache.\n * Evicts least-recently-used entries when the cache exceeds maxEntries.\n * Always resets the access counter to 0.\n *\n * @internal exported for testing (maxEntries parameter allows low thresholds in tests)\n * @returns true if entries were evicted\n */\nexport async function runGc(\n pl: PlClient,\n cacheRid: SignedResourceId,\n maxEntries: number = GC_MAX_ENTRIES,\n): Promise<boolean> {\n return await pl.withWriteTx(\"templateCache:gc\", async (tx) => {\n const kvs = await tx.listKeyValuesString(cacheRid);\n const entries: { hash: string; timestamp: number }[] = [];\n for (const { key, value } of kvs) {\n if (!key.startsWith(ACCESS_KEY_PREFIX)) continue;\n entries.push({\n hash: key.slice(ACCESS_KEY_PREFIX.length),\n timestamp: parseInt(value, 10),\n });\n }\n\n // Always reset counter\n tx.setKValue(cacheRid, ACCESS_COUNT_KEY, \"0\");\n\n if (entries.length <= maxEntries) {\n await tx.commit();\n return false;\n }\n\n // Sort oldest first, evict until under limit\n entries.sort((a, b) => a.timestamp - b.timestamp);\n const toEvict = entries.length - maxEntries;\n for (let i = 0; i < toEvict; i++) {\n tx.removeField(field(cacheRid, entries[i].hash));\n tx.deleteKValue(cacheRid, ACCESS_KEY_PREFIX + entries[i].hash);\n }\n\n await tx.commit();\n return true;\n });\n}\n\n/** Create a batch of cache nodes in the current transaction. */\nfunction createBatchNodes(\n tx: PlTransaction,\n cacheRid: SignedResourceId,\n batch: CacheableNode[],\n resolvedIds: ReadonlyMap<string, SignedResourceId>,\n newRefs: Map<string, ResourceRef>,\n now: string,\n): void {\n for (const node of batch) {\n const childRefs = new Map<string, AnyResourceRef>();\n for (const ch of node.childHashes) {\n const resolved = resolvedIds.get(ch) ?? newRefs.get(ch);\n if (resolved === undefined) {\n throw new Error(`BUG: child ${ch} not resolved`);\n }\n childRefs.set(ch, resolved);\n }\n const ref = node.create(tx, childRefs);\n newRefs.set(node.hash, ref);\n tx.createField(field(cacheRid, node.hash), \"Dynamic\", ref);\n tx.setKValue(cacheRid, ACCESS_KEY_PREFIX + node.hash, now);\n }\n}\n\n/**\n * Materialize a template tree via the cache using \"probe all + batched creation\".\n *\n * Phase 1 (single write tx):\n * - Check existence of ALL hashes in one roundtrip\n * - Happy path: if root cached, update access tracking and return\n * - Otherwise: fetch ResourceIds for all cache hits, create first batch of missing nodes\n *\n * Phase 2..N (one write tx per batch):\n * - Create remaining missing nodes in BATCH_SIZE chunks\n *\n * @returns root SignedResourceId and current access count (for GC decision)\n */\nasync function materialize(\n pl: PlClient,\n cacheRid: SignedResourceId,\n rootHash: string,\n nodes: CacheableNode[],\n stat: TemplateCacheStat,\n): Promise<{ rootId: SignedResourceId; accessCount: number }> {\n const allHashes = nodes.map((n) => n.hash);\n const resolvedIds = new Map<string, SignedResourceId>();\n\n // Phase 1: probe all + first batch\n const phase1 = await pl.withWriteTx(\"templateCache:materialize\", async (tx) => {\n // 1 roundtrip: check all hashes + read access count\n const [exists, countStr] = await Promise.all([\n Promise.all(allHashes.map((h) => tx.fieldExists(field(cacheRid, h)))),\n tx.getKValueStringIfExists(cacheRid, ACCESS_COUNT_KEY),\n ]);\n\n const prevCount = countStr ? parseInt(countStr, 10) : 0;\n const newCount = prevCount + 1;\n const now = Date.now().toString();\n const rootIdx = allHashes.length - 1;\n\n // Happy path: root already cached\n if (exists[rootIdx]) {\n const rootFd = await tx.getField(field(cacheRid, rootHash));\n const rootRid = ensureSignedResourceIdNotNull(rootFd.value);\n tx.setKValue(cacheRid, ACCESS_KEY_PREFIX + rootHash, now);\n tx.setKValue(cacheRid, ACCESS_COUNT_KEY, newCount.toString());\n await tx.commit();\n stat.happyPath = true;\n stat.cacheHits = stat.totalNodes;\n stat.batchCount = 1;\n return { done: true as const, rootId: rootRid, accessCount: newCount };\n }\n\n // Fetch ResourceIds for all cache hits (1 roundtrip)\n const hitIndices: number[] = [];\n for (let i = 0; i < allHashes.length; i++) {\n if (exists[i]) hitIndices.push(i);\n }\n\n if (hitIndices.length > 0) {\n const hitFields = await Promise.all(\n hitIndices.map((i) => tx.getField(field(cacheRid, allHashes[i]))),\n );\n for (let j = 0; j < hitIndices.length; j++) {\n resolvedIds.set(\n allHashes[hitIndices[j]],\n ensureSignedResourceIdNotNull(hitFields[j].value),\n );\n }\n }\n stat.cacheHits = hitIndices.length;\n\n // Missing nodes (topo order preserved from flatten)\n const missing = nodes.filter((n) => !resolvedIds.has(n.hash));\n stat.cacheMisses = missing.length;\n\n // Create first batch of missing nodes\n const firstBatch = missing.slice(0, BATCH_SIZE);\n const newRefs = new Map<string, ResourceRef>();\n createBatchNodes(tx, cacheRid, firstBatch, resolvedIds, newRefs, now);\n\n // Update access tracking for cache hits\n for (const i of hitIndices) {\n tx.setKValue(cacheRid, ACCESS_KEY_PREFIX + allHashes[i], now);\n }\n tx.setKValue(cacheRid, ACCESS_COUNT_KEY, newCount.toString());\n\n await tx.commit();\n\n // Resolve new refs to global IDs (after commit)\n for (const [hash, ref] of newRefs) {\n resolvedIds.set(hash, await toGlobalResourceId(ref));\n }\n\n return {\n done: false as const,\n remaining: missing.slice(BATCH_SIZE),\n accessCount: newCount,\n };\n });\n\n if (phase1.done) {\n return { rootId: phase1.rootId, accessCount: phase1.accessCount };\n }\n\n stat.batchCount = 1;\n\n // Phase 2+: remaining batches\n const { remaining } = phase1;\n for (let i = 0; i < remaining.length; i += BATCH_SIZE) {\n const batch = remaining.slice(i, i + BATCH_SIZE);\n stat.batchCount++;\n\n await pl.withWriteTx(\"templateCache:create\", async (tx) => {\n const newRefs = new Map<string, ResourceRef>();\n const now = Date.now().toString();\n createBatchNodes(tx, cacheRid, batch, resolvedIds, newRefs, now);\n await tx.commit();\n\n for (const [hash, ref] of newRefs) {\n resolvedIds.set(hash, await toGlobalResourceId(ref));\n }\n });\n }\n\n const rootId = resolvedIds.get(rootHash);\n if (!rootId) throw new Error(\"BUG: root hash not resolved after all batches\");\n return { rootId, accessCount: phase1.accessCount };\n}\n\n/**\n * Materialize a template tree via the cache.\n * Manages its own transactions internally — do NOT call inside an existing tx.\n *\n * @returns concrete SignedResourceId of the root template\n */\nexport async function loadTemplateCached(\n pl: PlClient,\n spec: TemplateSpecPrepared,\n options?: { cacheResourceId?: SignedResourceId },\n): Promise<SignedResourceId> {\n const stat = initialStat();\n const t0 = performance.now();\n\n try {\n // Parse to data if needed\n let tplData: TemplateData | CompiledTemplateV3;\n switch (spec.type) {\n case \"explicit\":\n tplData = parseTemplate(spec.content);\n break;\n case \"prepared\":\n tplData = spec.data;\n break;\n case \"cached\":\n return spec.resourceId;\n case \"from-registry\":\n throw new Error(\n \"loadTemplateCached does not support from-registry specs; use loadTemplate instead\",\n );\n default: {\n const _: never = spec;\n throw new Error(`unexpected spec type: ${(_ as any).type}`);\n }\n }\n\n stat.templateFormat = tplData.type;\n\n // Flatten to ordered nodes\n const tFlatten = performance.now();\n const nodes = flattenTemplateTree(tplData);\n stat.flattenMs = performance.now() - tFlatten;\n if (nodes.length === 0) throw new Error(\"template tree produced no nodes\");\n\n stat.totalNodes = nodes.length;\n const rootHash = nodes[nodes.length - 1].hash;\n\n // Resolve or create cache resource\n const tCacheInit = performance.now();\n const cacheRid = options?.cacheResourceId ?? (await getOrCreateTemplateCache(pl));\n stat.cacheInitMs = performance.now() - tCacheInit;\n\n // Retry loop: if a write tx fails (e.g. concurrent GC invalidated a cached resource),\n // restart materialization from scratch.\n const MAX_RETRIES = 3;\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n const tMat = performance.now();\n const result = await materialize(pl, cacheRid, rootHash, nodes, stat);\n stat.materializeMs = performance.now() - tMat;\n stat.retries = attempt;\n\n // GC in separate tx if access count exceeded threshold\n if (result.accessCount >= GC_ACCESS_THRESHOLD) {\n await runGc(pl, cacheRid);\n stat.gcTriggered = true;\n }\n\n return result.rootId;\n } catch (e) {\n if (attempt === MAX_RETRIES - 1) throw e;\n // Retry from scratch — previous batch results may reference GC'd resources\n stat.cacheHits = 0;\n stat.cacheMisses = 0;\n }\n }\n\n throw new Error(\"BUG: unreachable\");\n } finally {\n stat.totalMs = performance.now() - t0;\n if (getDebugFlags().logTemplateCacheStat) {\n console.log(`[templateCache] ${JSON.stringify(stat)}`);\n }\n }\n}\n\n/**\n * Pre-materialize a block pack's template via cache.\n * Returns a copy of the spec with the template replaced by a cached reference.\n * If the template is already cached, returns the spec unchanged.\n */\nexport async function cacheBlockPackTemplate(\n pl: PlClient,\n spec: BlockPackSpecPrepared,\n options?: { cacheResourceId?: SignedResourceId },\n): Promise<BlockPackSpecPrepared> {\n if (spec.template.type === \"cached\") return spec;\n\n const resourceId = await loadTemplateCached(pl, spec.template, options);\n return {\n ...spec,\n template: { type: \"cached\", resourceId },\n };\n}\n"],"mappings":";;;;;;AAqCA,MAAa,qBAAA,GAAA,0BAAA,aAAA,CAAiC,iBAAiB,GAAG;AAElE,MAAa,yBAAyB;AACtC,MAAM,aAAa;;AAEnB,MAAa,sBAAsB;;AAEnC,MAAa,iBAAiB;;AAE9B,MAAa,mBAAmB;;AAEhC,MAAa,oBAAoB;AAiBjC,SAAS,cAAiC;CACxC,OAAO;EACL,SAAS;EACT,WAAW;EACX,aAAa;EACb,eAAe;EACf,YAAY;EACZ,WAAW;EACX,aAAa;EACb,YAAY;EACZ,WAAW;EACX,aAAa;EACb,SAAS;EACT,gBAAgB;CAClB;AACF;AAYA,SAAS,cAAc,MAAc,SAAiC,YAA4B;CAChG,QAAA,GAAA,2BAAA,SAAA,CACE,QAAQ,aACR,kBAAkB,KAAK,oDAAoD,YAC7E;AACF;;;;;AASA,SAAS,UAAU,KAA8B;CAC/C,QAAA,GAAA,YAAA,WAAA,CAAkB,QAAQ,CAAC,CACxB,OAAOA,iCAAAA,gBAAgB,KAAK,IAAI,CAAC,CACjC,OAAOA,iCAAAA,gBAAgB,KAAK,OAAO,CAAC,CACpC,OAAO,IAAI,IAAI,CAAC,CAChB,OAAO,IAAI,OAAO,CAAC,CACnB,OAAO,IAAI,GAAG,CAAC,CACf,OAAO,KAAK;AACjB;AAEA,SAAS,eAAe,IAAkC;CACxD,QAAA,GAAA,YAAA,WAAA,CAAkB,QAAQ,CAAC,CACxB,OAAOC,iCAAAA,qBAAqB,KAAK,IAAI,CAAC,CACtC,OAAOA,iCAAAA,qBAAqB,KAAK,OAAO,CAAC,CACzC,OAAO,GAAG,IAAI,CAAC,CACf,OAAO,GAAG,OAAO,CAAC,CAClB,OAAO,GAAG,GAAG,CAAC,CACd,OAAO,KAAK;AACjB;AAIA,SAAS,UAAU,KAAgC;CACjD,QAAA,GAAA,YAAA,WAAA,CAAkB,QAAQ,CAAC,CACxB,OAAOD,iCAAAA,gBAAgB,KAAK,IAAI,CAAC,CACjC,OAAOA,iCAAAA,gBAAgB,KAAK,OAAO,CAAC,CACpC,OAAO,IAAI,IAAI,CAAC,CAChB,OAAO,IAAI,OAAO,CAAC,CACnB,OAAO,IAAI,UAAU,CAAC,CACtB,OAAO,KAAK;AACjB;AAEA,SAAS,eAAe,IAAoC;CAC1D,QAAA,GAAA,YAAA,WAAA,CAAkB,QAAQ,CAAC,CACxB,OAAOC,iCAAAA,qBAAqB,KAAK,IAAI,CAAC,CACtC,OAAOA,iCAAAA,qBAAqB,KAAK,OAAO,CAAC,CACzC,OAAO,GAAG,IAAI,CAAC,CACf,OAAO,GAAG,OAAO,CAAC,CAClB,OAAO,GAAG,UAAU,CAAC,CACrB,OAAO,KAAK;AACjB;AAEA,SAAS,WAAW,MAAkC;CACpD,QAAA,GAAA,YAAA,WAAA,CAAkB,QAAQ,CAAC,CACxB,OAAOC,iCAAAA,SAAS,KAAK,IAAI,CAAC,CAC1B,OAAOA,iCAAAA,SAAS,KAAK,OAAO,CAAC,CAC7B,OAAO,KAAK,IAAI,CAAC,CACjB,OAAO,KAAK,OAAO,CAAC,CACpB,OAAO,KAAK,UAAU,CAAC,CACvB,OAAO,KAAK;AACjB;AAIA,SAAS,cAAc,MAAqC;CAC1D,MAAM,QAAyB,CAAC;CAChC,MAAM,uBAAO,IAAI,IAAY;CAE7B,SAAS,WAAW,KAA8B;EAChD,MAAM,OAAO,UAAU,GAAG;EAC1B,IAAI,CAAC,KAAK,IAAI,IAAI,GAAG;GACnB,KAAK,IAAI,IAAI;GACb,MAAM,KAAK;IACT;IACA,SAAS,OACP,GAAG,YACDF,iCAAAA,gBAAgB,MAChB,KAAK,UAAUA,iCAAAA,gBAAgB,WAAW,GAAG,CAAC,CAAC,IAAI,CACrD;IACF,aAAa,CAAC;GAChB,CAAC;EACH;EACA,OAAO;CACT;CAEA,SAAS,gBAAgB,IAAkC;EACzD,MAAM,OAAO,eAAe,EAAE;EAC9B,IAAI,CAAC,KAAK,IAAI,IAAI,GAAG;GACnB,KAAK,IAAI,IAAI;GACb,MAAM,KAAK;IACT;IACA,SAAS,OAAO;KACd,MAAM,SAASC,iCAAAA,qBAAqB,WAAW,EAAE;KACjD,MAAM,MAAM,GAAG,aAAaA,iCAAAA,qBAAqB,MAAM,OAAO,IAAI;KAClE,GAAG,UAAU,KAAKA,iCAAAA,qBAAqB,aAAa,KAAK,UAAU,OAAO,IAAI,CAAC;KAC/E,GAAG,KAAK,GAAG;KACX,OAAO;IACT;IACA,aAAa,CAAC;GAChB,CAAC;EACH;EACA,OAAO;CACT;CAEA,SAAS,gBAAgB,KAA2B;EAElD,MAAM,cAAwB,CAAC;EAC/B,MAAM,WAAkD,CAAC;EAEzD,KAAK,MAAM,CAAC,OAAO,QAAQ,OAAO,QAAQ,IAAI,QAAQ,CAAC,CAAC,GAAG;GACzD,MAAM,IAAI,WAAW,GAAG;GACxB,YAAY,KAAK,CAAC;GAClB,SAAS,KAAK;IAAE,WAAW,GAAGE,iCAAAA,aAAa,UAAU,GAAG;IAAS,MAAM;GAAE,CAAC;EAC5E;EACA,KAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,IAAI,YAAY,CAAC,CAAC,GAAG;GAC3D,MAAM,IAAI,gBAAgB,EAAE;GAC5B,YAAY,KAAK,CAAC;GAClB,SAAS,KAAK;IAAE,WAAW,GAAGA,iCAAAA,aAAa,WAAW,GAAG;IAAQ,MAAM;GAAE,CAAC;EAC5E;EACA,KAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,IAAI,UAAU,CAAC,CAAC,GAAG;GACzD,MAAM,IAAI,gBAAgB,EAAE;GAC5B,YAAY,KAAK,CAAC;GAClB,SAAS,KAAK;IAAE,WAAW,GAAGA,iCAAAA,aAAa,WAAW,GAAG;IAAQ,MAAM;GAAE,CAAC;EAC5E;EACA,KAAK,MAAM,CAAC,OAAO,QAAQ,OAAO,QAAQ,IAAI,aAAa,CAAC,CAAC,GAAG;GAC9D,MAAM,IAAI,gBAAgB,GAAG;GAC7B,YAAY,KAAK,CAAC;GAClB,SAAS,KAAK;IAAE,WAAW,GAAGA,iCAAAA,aAAa,UAAU,GAAG;IAAS,MAAM;GAAE,CAAC;EAC5E;EAGA,MAAM,KAAA,GAAA,YAAA,WAAA,CAAe,QAAQ,CAAC,CAC3B,OAAOA,iCAAAA,aAAa,KAAK,IAAI,CAAC,CAC9B,OAAOA,iCAAAA,aAAa,KAAK,OAAO,CAAC,CACjC,OAAO,IAAI,gBAAgB,aAAa,CAAC,CACzC,OAAO,IAAI,IAAI,CAAC,CAChB,OAAO,IAAI,OAAO,CAAC,CACnB,OAAO,IAAI,GAAG;EACjB,KAAK,MAAM,SAAS,UAClB,EAAE,OAAO,WAAW,MAAM,YAAY,MAAM,MAAM,IAAI;EAExD,MAAM,OAAO,EAAE,OAAO,KAAK;EAE3B,IAAI,KAAK,IAAI,IAAI,GAAG,OAAO;EAC3B,KAAK,IAAI,IAAI;EACb,MAAM,KAAK;GACT;GACA,SAAS,IAAI,cAAc;IACzB,MAAM,SAAS,GAAG,aAChBA,iCAAAA,aAAa,MACb,KAAK,UAAUA,iCAAAA,aAAa,WAAW,GAAG,CAAC,CAAC,IAAI,CAClD;IACA,KAAK,MAAM,SAAS,UAAU;KAC5B,MAAM,OAAA,GAAA,0BAAA,MAAA,CAAY,QAAQ,MAAM,SAAS;KACzC,GAAG,YAAY,KAAK,OAAO;KAC3B,GAAG,SAAS,MAAA,GAAA,2BAAA,SAAA,CAAc,UAAU,IAAI,MAAM,IAAI,GAAG,qBAAqB,MAAM,MAAM,CAAC;IACzF;IACA,GAAG,KAAK,MAAM;IAEd,IAAI,CAAC,IAAI,cAAc,OAAO;IAE9B,MAAM,cAAc,GAAG,aACrBC,iCAAAA,qBAAqB,MACrB,KAAK,UAAUA,iCAAAA,qBAAqB,WAAW,GAAG,CAAC,CACrD;IACA,MAAM,cAAcA,iCAAAA,qBAAqB,SAAS,WAAW;IAC7D,GAAG,YAAY,aAAa,SAAS;IACrC,GAAG,SAAS,aAAa,MAAM;IAC/B,GAAG,KAAK,WAAW;IACnB,OAAO;GACT;GACA;EACF,CAAC;EAED,OAAO;CACT;CAEA,gBAAgB,IAAI;CACpB,OAAO;AACT;AAEA,SAAS,cAAc,MAA2C;CAChE,MAAM,QAAyB,CAAC;CAChC,MAAM,uBAAO,IAAI,IAAY;CAC7B,MAAM,UAAU,KAAK;CAErB,SAAS,WAAW,KAAgC;EAClD,MAAM,OAAO,UAAU,GAAG;EAC1B,IAAI,CAAC,KAAK,IAAI,IAAI,GAAG;GACnB,KAAK,IAAI,IAAI;GACb,MAAM,KAAK;IACT;IACA,SAAS,OACP,GAAG,YACDJ,iCAAAA,gBAAgB,MAChB,KAAK,UACHA,iCAAAA,gBAAgB,WAAW,KAAK,cAAc,IAAI,MAAM,SAAS,IAAI,UAAU,CAAC,CAAC,CAC9E,IACL,CACF;IACF,aAAa,CAAC;GAChB,CAAC;EACH;EACA,OAAO;CACT;CAEA,SAAS,gBAAgB,IAAoC;EAC3D,MAAM,OAAO,eAAe,EAAE;EAC9B,IAAI,CAAC,KAAK,IAAI,IAAI,GAAG;GACnB,KAAK,IAAI,IAAI;GACb,MAAM,KAAK;IACT;IACA,SAAS,OAAO;KACd,MAAM,SAASC,iCAAAA,qBAAqB,WAClC,IACA,cAAc,GAAG,MAAM,SAAS,GAAG,UAAU,CAC/C;KACA,MAAM,MAAM,GAAG,aAAaA,iCAAAA,qBAAqB,MAAM,OAAO,IAAI;KAClE,GAAG,UAAU,KAAKA,iCAAAA,qBAAqB,aAAa,KAAK,UAAU,OAAO,IAAI,CAAC;KAC/E,GAAG,KAAK,GAAG;KACX,OAAO;IACT;IACA,aAAa,CAAC;GAChB,CAAC;EACH;EACA,OAAO;CACT;CAEA,SAAS,YAAY,MAAkC;EACrD,MAAM,OAAO,WAAW,IAAI;EAC5B,IAAI,CAAC,KAAK,IAAI,IAAI,GAAG;GACnB,KAAK,IAAI,IAAI;GACb,MAAM,KAAK;IACT;IACA,SAAS,OACP,GAAG,YACDC,iCAAAA,SAAS,MACT,KAAK,UACHA,iCAAAA,SAAS,WAAW,MAAM,cAAc,KAAK,MAAM,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,IAChF,CACF;IACF,aAAa,CAAC;GAChB,CAAC;EACH;EACA,OAAO;CACT;CAEA,SAAS,gBAAgB,KAA6B;EAOpD,MAAM,UAAU,IAAI,WAAW;EAG/B,MAAM,cAAwB,CAAC;EAC/B,MAAM,WAAkD,CAAC;EAEzD,KAAK,MAAM,CAAC,OAAO,QAAQ,OAAO,QAAQ,IAAI,QAAQ,CAAC,CAAC,GAAG;GACzD,MAAM,IAAI,WAAW,GAAG;GACxB,YAAY,KAAK,CAAC;GAClB,SAAS,KAAK;IAAE,WAAW,GAAGC,iCAAAA,aAAa,UAAU,GAAG;IAAS,MAAM;GAAE,CAAC;EAC5E;EACA,KAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,IAAI,YAAY,CAAC,CAAC,GAAG;GAC3D,MAAM,IAAI,gBAAgB,EAAE;GAC5B,YAAY,KAAK,CAAC;GAClB,SAAS,KAAK;IAAE,WAAW,GAAGA,iCAAAA,aAAa,WAAW,GAAG;IAAQ,MAAM;GAAE,CAAC;EAC5E;EACA,KAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,IAAI,UAAU,CAAC,CAAC,GAAG;GACzD,MAAM,IAAI,gBAAgB,EAAE;GAC5B,YAAY,KAAK,CAAC;GAClB,SAAS,KAAK;IAAE,WAAW,GAAGA,iCAAAA,aAAa,WAAW,GAAG;IAAQ,MAAM;GAAE,CAAC;EAC5E;EACA,KAAK,MAAM,CAAC,OAAO,QAAQ,OAAO,QAAQ,IAAI,aAAa,CAAC,CAAC,GAAG;GAC9D,MAAM,IAAI,gBAAgB,GAAG;GAC7B,YAAY,KAAK,CAAC;GAClB,SAAS,KAAK;IAAE,WAAW,GAAGA,iCAAAA,aAAa,UAAU,GAAG;IAAS,MAAM;GAAE,CAAC;EAC5E;EACA,KAAK,MAAM,CAAC,QAAQ,SAAS,OAAO,QAAQ,IAAI,QAAQ,CAAC,CAAC,GAAG;GAC3D,MAAM,IAAI,YAAY,IAAI;GAC1B,YAAY,KAAK,CAAC;GAClB,SAAS,KAAK;IAAE,WAAW,GAAGA,iCAAAA,aAAa,WAAW,GAAG;IAAU,MAAM;GAAE,CAAC;EAC9E;EAIA,MAAM,KAAA,GAAA,YAAA,WAAA,CAAe,QAAQ,CAAC,CAC3B,OAAOA,iCAAAA,aAAa,KAAK,IAAI,CAAC,CAC9B,OAAOA,iCAAAA,aAAa,KAAK,OAAO,CAAC,CACjC,OAAO,IAAI,gBAAgB,aAAa,CAAC,CACzC,OAAO,IAAI,IAAI,CAAC,CAChB,OAAO,OAAO,CAAC,CACf,OAAO,IAAI,UAAU;EACxB,KAAK,MAAM,SAAS,UAClB,EAAE,OAAO,WAAW,MAAM,YAAY,MAAM,MAAM,IAAI;EAExD,MAAM,OAAO,EAAE,OAAO,KAAK;EAE3B,IAAI,KAAK,IAAI,IAAI,GAAG,OAAO;EAC3B,KAAK,IAAI,IAAI;EACb,MAAM,KAAK;GACT;GACA,SAAS,IAAI,cAAc;IACzB,MAAM,aAAa,cAAc,IAAI,MAAM,SAAS,IAAI,UAAU;IAClE,MAAM,SAAS,GAAG,aAChBA,iCAAAA,aAAa,MACb,KAAK,UAAUA,iCAAAA,aAAa,WAAW;KAAE,GAAG;KAAK;IAAQ,GAAG,UAAU,CAAC,CAAC,IAAI,CAC9E;IACA,KAAK,MAAM,SAAS,UAAU;KAC5B,MAAM,OAAA,GAAA,0BAAA,MAAA,CAAY,QAAQ,MAAM,SAAS;KACzC,GAAG,YAAY,KAAK,OAAO;KAC3B,GAAG,SAAS,MAAA,GAAA,2BAAA,SAAA,CAAc,UAAU,IAAI,MAAM,IAAI,GAAG,qBAAqB,MAAM,MAAM,CAAC;IACzF;IACA,GAAG,KAAK,MAAM;IAEd,IAAI,CAAC,IAAI,cAAc,OAAO;IAE9B,MAAM,cAAc,GAAG,aACrBC,iCAAAA,qBAAqB,MACrB,KAAK,UAAUA,iCAAAA,qBAAqB,WAAW,GAAG,CAAC,CACrD;IACA,MAAM,cAAcA,iCAAAA,qBAAqB,SAAS,WAAW;IAC7D,GAAG,YAAY,aAAa,SAAS;IACrC,GAAG,SAAS,aAAa,MAAM;IAC/B,GAAG,KAAK,WAAW;IACnB,OAAO;GACT;GACA;EACF,CAAC;EAED,OAAO;CACT;CAEA,gBAAgB,KAAK,QAAQ;CAC7B,OAAO;AACT;;AAGA,SAAgB,oBAAoB,MAA0D;CAC5F,IAAI,KAAK,SAAS,wBAChB,OAAO,cAAc,IAAI;MAEzB,OAAO,cAAc,IAAI;AAE7B;;AAGA,MAAM,8BAAc,IAAI,QAAoC;;AAG5D,SAAgB,0BAA0B,IAAoB;CAC5D,YAAY,OAAO,EAAE;AACvB;;AAGA,eAAsB,yBAAyB,IAAyC;CAEtF,MAAM,SAAS,YAAY,IAAI,EAAE;CACjC,IAAI,WAAW,KAAA,GAAW,OAAO;CAGjC,MAAM,WAAW,MAAM,GAAG,WAAW,uBAAuB,OAAO,OAAO;EACxE,MAAM,KAAK,MAAM,GAAG,kBAAA,GAAA,0BAAA,MAAA,CAAuB,GAAG,YAAY,sBAAsB,CAAC;EACjF,OAAO,MAAA,GAAA,0BAAA,8BAAA,CAAmC,GAAG,KAAK,IAAI,KAAA;CACxD,CAAC;CACD,IAAI,UAAU;EACZ,YAAY,IAAI,IAAI,QAAQ;EAC5B,OAAO;CACT;CAEA,MAAM,SAAS,MAAM,GAAG,YAAY,sBAAsB,OAAO,OAAO;EAEtE,MAAM,KAAK,MAAM,GAAG,kBAAA,GAAA,0BAAA,MAAA,CAAuB,GAAG,YAAY,sBAAsB,CAAC;EACjF,IAAI,IAAI,QAAA,GAAA,0BAAA,8BAAA,CAAqC,GAAG,KAAK;EAErD,MAAM,QAAQ,GAAG,aAAa,iBAAiB;EAC/C,GAAG,aAAA,GAAA,0BAAA,MAAA,CAAkB,GAAG,YAAY,sBAAsB,GAAG,WAAW,KAAK;EAC7E,GAAG,KAAK,KAAK;EACb,MAAM,GAAG,OAAO;EAChB,OAAO,MAAM,MAAM;CACrB,CAAC;CACD,YAAY,IAAI,IAAI,MAAM;CAC1B,OAAO;AACT;;AAGA,eAAsB,kBAAkB,IAA6B;CACnE,MAAM,GAAG,YAAY,sBAAsB,OAAO,OAAO;EACvD,MAAM,cAAA,GAAA,0BAAA,MAAA,CAAmB,GAAG,YAAY,sBAAsB;EAE9D,IAAI,MADa,GAAG,iBAAiB,UAAU,GACvC;GACN,GAAG,YAAY,UAAU;GACzB,MAAM,GAAG,OAAO;EAClB;CACF,CAAC;CACD,0BAA0B,EAAE;AAC9B;;;;;;;;;AAUA,eAAsB,MACpB,IACA,UACA,aAAqB,gBACH;CAClB,OAAO,MAAM,GAAG,YAAY,oBAAoB,OAAO,OAAO;EAC5D,MAAM,MAAM,MAAM,GAAG,oBAAoB,QAAQ;EACjD,MAAM,UAAiD,CAAC;EACxD,KAAK,MAAM,EAAE,KAAK,WAAW,KAAK;GAChC,IAAI,CAAC,IAAI,WAAA,SAA4B,GAAG;GACxC,QAAQ,KAAK;IACX,MAAM,IAAI,MAAM,CAAwB;IACxC,WAAW,SAAS,OAAO,EAAE;GAC/B,CAAC;EACH;EAGA,GAAG,UAAU,UAAU,kBAAkB,GAAG;EAE5C,IAAI,QAAQ,UAAU,YAAY;GAChC,MAAM,GAAG,OAAO;GAChB,OAAO;EACT;EAGA,QAAQ,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;EAChD,MAAM,UAAU,QAAQ,SAAS;EACjC,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,KAAK;GAChC,GAAG,aAAA,GAAA,0BAAA,MAAA,CAAkB,UAAU,QAAQ,EAAE,CAAC,IAAI,CAAC;GAC/C,GAAG,aAAa,UAAU,oBAAoB,QAAQ,EAAE,CAAC,IAAI;EAC/D;EAEA,MAAM,GAAG,OAAO;EAChB,OAAO;CACT,CAAC;AACH;;AAGA,SAAS,iBACP,IACA,UACA,OACA,aACA,SACA,KACM;CACN,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,4BAAY,IAAI,IAA4B;EAClD,KAAK,MAAM,MAAM,KAAK,aAAa;GACjC,MAAM,WAAW,YAAY,IAAI,EAAE,KAAK,QAAQ,IAAI,EAAE;GACtD,IAAI,aAAa,KAAA,GACf,MAAM,IAAI,MAAM,cAAc,GAAG,cAAc;GAEjD,UAAU,IAAI,IAAI,QAAQ;EAC5B;EACA,MAAM,MAAM,KAAK,OAAO,IAAI,SAAS;EACrC,QAAQ,IAAI,KAAK,MAAM,GAAG;EAC1B,GAAG,aAAA,GAAA,0BAAA,MAAA,CAAkB,UAAU,KAAK,IAAI,GAAG,WAAW,GAAG;EACzD,GAAG,UAAU,UAAU,oBAAoB,KAAK,MAAM,GAAG;CAC3D;AACF;;;;;;;;;;;;;;AAeA,eAAe,YACb,IACA,UACA,UACA,OACA,MAC4D;CAC5D,MAAM,YAAY,MAAM,KAAK,MAAM,EAAE,IAAI;CACzC,MAAM,8BAAc,IAAI,IAA8B;CAGtD,MAAM,SAAS,MAAM,GAAG,YAAY,6BAA6B,OAAO,OAAO;EAE7E,MAAM,CAAC,QAAQ,YAAY,MAAM,QAAQ,IAAI,CAC3C,QAAQ,IAAI,UAAU,KAAK,MAAM,GAAG,aAAA,GAAA,0BAAA,MAAA,CAAkB,UAAU,CAAC,CAAC,CAAC,CAAC,GACpE,GAAG,wBAAwB,UAAU,gBAAgB,CACvD,CAAC;EAGD,MAAM,YADY,WAAW,SAAS,UAAU,EAAE,IAAI,KACzB;EAC7B,MAAM,MAAM,KAAK,IAAI,CAAC,CAAC,SAAS;EAIhC,IAAI,OAHY,UAAU,SAAS,IAGd;GAEnB,MAAM,WAAA,GAAA,0BAAA,8BAAA,EAAwC,MADzB,GAAG,UAAA,GAAA,0BAAA,MAAA,CAAe,UAAU,QAAQ,CAAC,EAAA,CACL,KAAK;GAC1D,GAAG,UAAU,UAAU,oBAAoB,UAAU,GAAG;GACxD,GAAG,UAAU,UAAU,kBAAkB,SAAS,SAAS,CAAC;GAC5D,MAAM,GAAG,OAAO;GAChB,KAAK,YAAY;GACjB,KAAK,YAAY,KAAK;GACtB,KAAK,aAAa;GAClB,OAAO;IAAE,MAAM;IAAe,QAAQ;IAAS,aAAa;GAAS;EACvE;EAGA,MAAM,aAAuB,CAAC;EAC9B,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KACpC,IAAI,OAAO,IAAI,WAAW,KAAK,CAAC;EAGlC,IAAI,WAAW,SAAS,GAAG;GACzB,MAAM,YAAY,MAAM,QAAQ,IAC9B,WAAW,KAAK,MAAM,GAAG,UAAA,GAAA,0BAAA,MAAA,CAAe,UAAU,UAAU,EAAE,CAAC,CAAC,CAClE;GACA,KAAK,IAAI,IAAI,GAAG,IAAI,WAAW,QAAQ,KACrC,YAAY,IACV,UAAU,WAAW,MAAA,GAAA,0BAAA,8BAAA,CACS,UAAU,EAAE,CAAC,KAAK,CAClD;EAEJ;EACA,KAAK,YAAY,WAAW;EAG5B,MAAM,UAAU,MAAM,QAAQ,MAAM,CAAC,YAAY,IAAI,EAAE,IAAI,CAAC;EAC5D,KAAK,cAAc,QAAQ;EAG3B,MAAM,aAAa,QAAQ,MAAM,GAAG,UAAU;EAC9C,MAAM,0BAAU,IAAI,IAAyB;EAC7C,iBAAiB,IAAI,UAAU,YAAY,aAAa,SAAS,GAAG;EAGpE,KAAK,MAAM,KAAK,YACd,GAAG,UAAU,UAAU,oBAAoB,UAAU,IAAI,GAAG;EAE9D,GAAG,UAAU,UAAU,kBAAkB,SAAS,SAAS,CAAC;EAE5D,MAAM,GAAG,OAAO;EAGhB,KAAK,MAAM,CAAC,MAAM,QAAQ,SACxB,YAAY,IAAI,MAAM,OAAA,GAAA,0BAAA,mBAAA,CAAyB,GAAG,CAAC;EAGrD,OAAO;GACL,MAAM;GACN,WAAW,QAAQ,MAAM,UAAU;GACnC,aAAa;EACf;CACF,CAAC;CAED,IAAI,OAAO,MACT,OAAO;EAAE,QAAQ,OAAO;EAAQ,aAAa,OAAO;CAAY;CAGlE,KAAK,aAAa;CAGlB,MAAM,EAAE,cAAc;CACtB,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,YAAY;EACrD,MAAM,QAAQ,UAAU,MAAM,GAAG,IAAI,UAAU;EAC/C,KAAK;EAEL,MAAM,GAAG,YAAY,wBAAwB,OAAO,OAAO;GACzD,MAAM,0BAAU,IAAI,IAAyB;GAE7C,iBAAiB,IAAI,UAAU,OAAO,aAAa,SADvC,KAAK,IAAI,CAAC,CAAC,SACuC,CAAC;GAC/D,MAAM,GAAG,OAAO;GAEhB,KAAK,MAAM,CAAC,MAAM,QAAQ,SACxB,YAAY,IAAI,MAAM,OAAA,GAAA,0BAAA,mBAAA,CAAyB,GAAG,CAAC;EAEvD,CAAC;CACH;CAEA,MAAM,SAAS,YAAY,IAAI,QAAQ;CACvC,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,+CAA+C;CAC5E,OAAO;EAAE;EAAQ,aAAa,OAAO;CAAY;AACnD;;;;;;;AAQA,eAAsB,mBACpB,IACA,MACA,SAC2B;CAC3B,MAAM,OAAO,YAAY;CACzB,MAAM,KAAK,YAAY,IAAI;CAE3B,IAAI;EAEF,IAAI;EACJ,QAAQ,KAAK,MAAb;GACE,KAAK;IACH,WAAA,GAAA,iCAAA,cAAA,CAAwB,KAAK,OAAO;IACpC;GACF,KAAK;IACH,UAAU,KAAK;IACf;GACF,KAAK,UACH,OAAO,KAAK;GACd,KAAK,iBACH,MAAM,IAAI,MACR,mFACF;GACF,SAEE,MAAM,IAAI,MAAM,yBAA0BC,KAAU,MAAM;EAE9D;EAEA,KAAK,iBAAiB,QAAQ;EAG9B,MAAM,WAAW,YAAY,IAAI;EACjC,MAAM,QAAQ,oBAAoB,OAAO;EACzC,KAAK,YAAY,YAAY,IAAI,IAAI;EACrC,IAAI,MAAM,WAAW,GAAG,MAAM,IAAI,MAAM,iCAAiC;EAEzE,KAAK,aAAa,MAAM;EACxB,MAAM,WAAW,MAAM,MAAM,SAAS,EAAE,CAAC;EAGzC,MAAM,aAAa,YAAY,IAAI;EACnC,MAAM,WAAW,SAAS,mBAAoB,MAAM,yBAAyB,EAAE;EAC/E,KAAK,cAAc,YAAY,IAAI,IAAI;EAIvC,MAAM,cAAc;EACpB,KAAK,IAAI,UAAU,GAAG,UAAU,aAAa,WAC3C,IAAI;GACF,MAAM,OAAO,YAAY,IAAI;GAC7B,MAAM,SAAS,MAAM,YAAY,IAAI,UAAU,UAAU,OAAO,IAAI;GACpE,KAAK,gBAAgB,YAAY,IAAI,IAAI;GACzC,KAAK,UAAU;GAGf,IAAI,OAAO,eAAA,IAAoC;IAC7C,MAAM,MAAM,IAAI,QAAQ;IACxB,KAAK,cAAc;GACrB;GAEA,OAAO,OAAO;EAChB,SAAS,GAAG;GACV,IAAI,YAAY,cAAc,GAAG,MAAM;GAEvC,KAAK,YAAY;GACjB,KAAK,cAAc;EACrB;EAGF,MAAM,IAAI,MAAM,kBAAkB;CACpC,UAAU;EACR,KAAK,UAAU,YAAY,IAAI,IAAI;EACnC,IAAIC,cAAAA,cAAc,CAAC,CAAC,sBAClB,QAAQ,IAAI,mBAAmB,KAAK,UAAU,IAAI,GAAG;CAEzD;AACF;;;;;;AAOA,eAAsB,uBACpB,IACA,MACA,SACgC;CAChC,IAAI,KAAK,SAAS,SAAS,UAAU,OAAO;CAE5C,MAAM,aAAa,MAAM,mBAAmB,IAAI,KAAK,UAAU,OAAO;CACtE,OAAO;EACL,GAAG;EACH,UAAU;GAAE,MAAM;GAAU;EAAW;CACzC;AACF"}
1
+ {"version":3,"file":"template_cache.cjs","names":["resourceType","notEmpty","createHash","PlTemplateLibV1","PlTemplateSoftwareV1","PlWasmV1","PlTemplateV1","field","PlTemplateOverrideV1","ensureSignedResourceIdNotNull","toGlobalResourceId","parseTemplate","_","getDebugFlags"],"sources":["../../../src/mutator/template/template_cache.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport type {\n AnyResourceRef,\n PlClient,\n PlTransaction,\n SignedResourceId,\n ResourceRef,\n} from \"@milaboratories/pl-client\";\nimport {\n ensureSignedResourceIdNotNull,\n field,\n resourceType,\n toGlobalResourceId,\n} from \"@milaboratories/pl-client\";\nimport {\n parseTemplate,\n PlTemplateLibV1,\n PlTemplateOverrideV1,\n PlTemplateSoftwareV1,\n PlTemplateV1,\n PlWasmV1,\n} from \"@milaboratories/pl-model-backend\";\nimport type {\n CompiledTemplateV3,\n TemplateData,\n TemplateDataV3,\n TemplateLibData,\n TemplateLibDataV3,\n TemplateSoftwareData,\n TemplateSoftwareDataV3,\n TemplateWasmDataV3,\n} from \"@milaboratories/pl-model-backend\";\nimport { notEmpty } from \"@milaboratories/ts-helpers\";\nimport type { BlockPackSpecPrepared } from \"../../model\";\nimport type { TemplateSpecPrepared } from \"../../model/template_spec\";\nimport { getDebugFlags } from \"../../debug\";\n\nexport const TemplateCacheType = resourceType(\"TemplateCache\", \"1\");\n\nexport const TemplateCacheFieldName = \"__templateCache\";\nconst BATCH_SIZE = 50;\n/** @internal exported for testing */\nexport const GC_ACCESS_THRESHOLD = 30;\n/** @internal exported for testing */\nexport const GC_MAX_ENTRIES = 3000;\n/** @internal exported for testing */\nexport const ACCESS_COUNT_KEY = \"_accessCount\";\n/** @internal exported for testing */\nexport const ACCESS_KEY_PREFIX = \"access_\";\n\nexport type TemplateCacheStat = {\n totalMs: number;\n flattenMs: number;\n cacheInitMs: number;\n materializeMs: number;\n totalNodes: number;\n cacheHits: number;\n cacheMisses: number;\n batchCount: number;\n happyPath: boolean;\n gcTriggered: boolean;\n retries: number;\n templateFormat: string;\n};\n\nfunction initialStat(): TemplateCacheStat {\n return {\n totalMs: 0,\n flattenMs: 0,\n cacheInitMs: 0,\n materializeMs: 0,\n totalNodes: 0,\n cacheHits: 0,\n cacheMisses: 0,\n batchCount: 0,\n happyPath: false,\n gcTriggered: false,\n retries: 0,\n templateFormat: \"\",\n };\n}\n\ninterface CacheableNode {\n /** SHA-256 content hash (includes all descendant content) */\n hash: string;\n /** Creates this node's resource in a transaction.\n * childRefs maps child hash → already-resolved ResourceRef or SignedResourceId */\n create: (tx: PlTransaction, childRefs: ReadonlyMap<string, AnyResourceRef>) => ResourceRef;\n /** Hashes of direct child nodes this node depends on */\n childHashes: string[];\n}\n\nfunction getSourceCode(name: string, sources: Record<string, string>, sourceHash: string): string {\n return notEmpty(\n sources[sourceHash],\n `trying to get \"${name}\" source: sources map doesn't contain source hash ${sourceHash}`,\n );\n}\n\n/**\n * Bottom-up hash composition: each node hashes its OWN content + child hash STRINGS.\n * This means each unique node is hashed exactly once → O(n) instead of O(n * depth).\n */\n\n// V2 leaf hashes (libs, software — no children)\n\nfunction hashLibV2(lib: TemplateLibData): string {\n return createHash(\"sha256\")\n .update(PlTemplateLibV1.type.name)\n .update(PlTemplateLibV1.type.version)\n .update(lib.name)\n .update(lib.version)\n .update(lib.src)\n .digest(\"hex\");\n}\n\nfunction hashSoftwareV2(sw: TemplateSoftwareData): string {\n return createHash(\"sha256\")\n .update(PlTemplateSoftwareV1.type.name)\n .update(PlTemplateSoftwareV1.type.version)\n .update(sw.name)\n .update(sw.version)\n .update(sw.src)\n .digest(\"hex\");\n}\n\n// V3 leaf hashes — use sourceHash directly instead of resolving source content\n\nfunction hashLibV3(lib: TemplateLibDataV3): string {\n return createHash(\"sha256\")\n .update(PlTemplateLibV1.type.name)\n .update(PlTemplateLibV1.type.version)\n .update(lib.name)\n .update(lib.version)\n .update(lib.sourceHash)\n .digest(\"hex\");\n}\n\nfunction hashSoftwareV3(sw: TemplateSoftwareDataV3): string {\n return createHash(\"sha256\")\n .update(PlTemplateSoftwareV1.type.name)\n .update(PlTemplateSoftwareV1.type.version)\n .update(sw.name)\n .update(sw.version)\n .update(sw.sourceHash)\n .digest(\"hex\");\n}\n\nfunction hashWasmV3(wasm: TemplateWasmDataV3): string {\n return createHash(\"sha256\")\n .update(PlWasmV1.type.name)\n .update(PlWasmV1.type.version)\n .update(wasm.name)\n .update(wasm.version)\n .update(wasm.sourceHash)\n .digest(\"hex\");\n}\n\n// ─── Tree flattening ─────────────────────────────────────────────────────────\n\nfunction flattenV2Tree(data: TemplateData): CacheableNode[] {\n const nodes: CacheableNode[] = [];\n const seen = new Set<string>();\n\n function processLib(lib: TemplateLibData): string {\n const hash = hashLibV2(lib);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) =>\n tx.createValue(\n PlTemplateLibV1.type,\n JSON.stringify(PlTemplateLibV1.fromV2Data(lib).data),\n ),\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processSoftware(sw: TemplateSoftwareData): string {\n const hash = hashSoftwareV2(sw);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) => {\n const swData = PlTemplateSoftwareV1.fromV2Data(sw);\n const ref = tx.createStruct(PlTemplateSoftwareV1.type, swData.data);\n tx.setKValue(ref, PlTemplateSoftwareV1.metaNameKey, JSON.stringify(swData.name));\n tx.lock(ref);\n return ref;\n },\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processTemplate(tpl: TemplateData): string {\n // Process children first (bottom-up) — their hashes are computed before ours\n const childHashes: string[] = [];\n const children: { fieldName: string; hash: string }[] = [];\n\n for (const [libId, lib] of Object.entries(tpl.libs ?? {})) {\n const h = processLib(lib);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.libPrefix}/${libId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.software ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.assets ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [tplId, sub] of Object.entries(tpl.templates ?? {})) {\n const h = processTemplate(sub);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.tplPrefix}/${tplId}`, hash: h });\n }\n\n // Compose hash from own content + child hash strings (NOT child content)\n const h = createHash(\"sha256\")\n .update(PlTemplateV1.type.name)\n .update(PlTemplateV1.type.version)\n .update(tpl.hashOverride ?? \"no-override\")\n .update(tpl.name)\n .update(tpl.version)\n .update(tpl.src);\n for (const child of children) {\n h.update(\"child:\" + child.fieldName + \":\" + child.hash);\n }\n const hash = h.digest(\"hex\");\n\n if (seen.has(hash)) return hash;\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx, childRefs) => {\n const tplRef = tx.createStruct(\n PlTemplateV1.type,\n JSON.stringify(PlTemplateV1.fromV2Data(tpl).data),\n );\n for (const child of children) {\n const fld = field(tplRef, child.fieldName);\n tx.createField(fld, \"Input\");\n tx.setField(fld, notEmpty(childRefs.get(child.hash), `missing child ref ${child.hash}`));\n }\n tx.lock(tplRef);\n\n if (!tpl.hashOverride) return tplRef;\n\n const overrideRef = tx.createStruct(\n PlTemplateOverrideV1.type,\n JSON.stringify(PlTemplateOverrideV1.fromV2Data(tpl)),\n );\n const overrideFld = PlTemplateOverrideV1.tplField(overrideRef);\n tx.createField(overrideFld, \"Service\");\n tx.setField(overrideFld, tplRef);\n tx.lock(overrideRef);\n return overrideRef;\n },\n childHashes,\n });\n\n return hash;\n }\n\n processTemplate(data);\n return nodes;\n}\n\nfunction flattenV3Tree(data: CompiledTemplateV3): CacheableNode[] {\n const nodes: CacheableNode[] = [];\n const seen = new Set<string>();\n const sources = data.hashToSource;\n\n function processLib(lib: TemplateLibDataV3): string {\n const hash = hashLibV3(lib);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) =>\n tx.createValue(\n PlTemplateLibV1.type,\n JSON.stringify(\n PlTemplateLibV1.fromV3Data(lib, getSourceCode(lib.name, sources, lib.sourceHash))\n .data,\n ),\n ),\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processSoftware(sw: TemplateSoftwareDataV3): string {\n const hash = hashSoftwareV3(sw);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) => {\n const swData = PlTemplateSoftwareV1.fromV3Data(\n sw,\n getSourceCode(sw.name, sources, sw.sourceHash),\n );\n const ref = tx.createStruct(PlTemplateSoftwareV1.type, swData.data);\n tx.setKValue(ref, PlTemplateSoftwareV1.metaNameKey, JSON.stringify(swData.name));\n tx.lock(ref);\n return ref;\n },\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processWasm(wasm: TemplateWasmDataV3): string {\n const hash = hashWasmV3(wasm);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) =>\n tx.createValue(\n PlWasmV1.type,\n JSON.stringify(\n PlWasmV1.fromV3Data(wasm, getSourceCode(wasm.name, sources, wasm.sourceHash)).data,\n ),\n ),\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processTemplate(tpl: TemplateDataV3): string {\n // Defensive: a template can carry no embedded version at runtime even\n // though the type says `string` — the compiler writes `packageJson.version`\n // unchecked, so a template built from a package with no `version` field\n // yields undefined. Identity is fully covered by name + sourceHash, so the\n // placeholder is safe for both the cache key and the backend resource's\n // required Version field.\n const version = tpl.version ?? \"0.0.0\";\n\n // Process children first (bottom-up)\n const childHashes: string[] = [];\n const children: { fieldName: string; hash: string }[] = [];\n\n for (const [libId, lib] of Object.entries(tpl.libs ?? {})) {\n const h = processLib(lib);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.libPrefix}/${libId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.software ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.assets ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [tplId, sub] of Object.entries(tpl.templates ?? {})) {\n const h = processTemplate(sub);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.tplPrefix}/${tplId}`, hash: h });\n }\n for (const [wasmId, wasm] of Object.entries(tpl.wasm ?? {})) {\n const h = processWasm(wasm);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.wasmPrefix}/${wasmId}`, hash: h });\n }\n\n // Compose hash from own content + child hash strings (NOT child content).\n // Uses sourceHash directly — it already uniquely identifies the source.\n const h = createHash(\"sha256\")\n .update(PlTemplateV1.type.name)\n .update(PlTemplateV1.type.version)\n .update(tpl.hashOverride ?? \"no-override\")\n .update(tpl.name)\n .update(version)\n .update(tpl.sourceHash);\n for (const child of children) {\n h.update(\"child:\" + child.fieldName + \":\" + child.hash);\n }\n const hash = h.digest(\"hex\");\n\n if (seen.has(hash)) return hash;\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx, childRefs) => {\n const sourceCode = getSourceCode(tpl.name, sources, tpl.sourceHash);\n const tplRef = tx.createStruct(\n PlTemplateV1.type,\n JSON.stringify(PlTemplateV1.fromV3Data({ ...tpl, version }, sourceCode).data),\n );\n for (const child of children) {\n const fld = field(tplRef, child.fieldName);\n tx.createField(fld, \"Input\");\n tx.setField(fld, notEmpty(childRefs.get(child.hash), `missing child ref ${child.hash}`));\n }\n tx.lock(tplRef);\n\n if (!tpl.hashOverride) return tplRef;\n\n const overrideRef = tx.createStruct(\n PlTemplateOverrideV1.type,\n JSON.stringify(PlTemplateOverrideV1.fromV3Data(tpl)),\n );\n const overrideFld = PlTemplateOverrideV1.tplField(overrideRef);\n tx.createField(overrideFld, \"Service\");\n tx.setField(overrideFld, tplRef);\n tx.lock(overrideRef);\n return overrideRef;\n },\n childHashes,\n });\n\n return hash;\n }\n\n processTemplate(data.template);\n return nodes;\n}\n\n/** Flatten template tree into a topologically ordered list of cacheable nodes (leaves first). */\nexport function flattenTemplateTree(data: TemplateData | CompiledTemplateV3): CacheableNode[] {\n if (data.type === \"pl.tengo-template.v2\") {\n return flattenV2Tree(data);\n } else {\n return flattenV3Tree(data);\n }\n}\n\n/** In-memory cache for the TemplateCache SignedResourceId per PlClient instance. */\nconst cacheRidMap = new WeakMap<PlClient, SignedResourceId>();\n\n/** Clear the in-memory cacheRid entry (call on errors referencing the cache resource). */\nexport function invalidateTemplateCacheId(pl: PlClient): void {\n cacheRidMap.delete(pl);\n}\n\n/** Find or create the TemplateCache/1 resource on user root. */\nexport async function getOrCreateTemplateCache(pl: PlClient): Promise<SignedResourceId> {\n // Check in-memory cache first (0ms after first call)\n const cached = cacheRidMap.get(pl);\n if (cached !== undefined) return cached;\n\n // Try read-only check\n const existing = await pl.withReadTx(\"templateCache:check\", async (tx) => {\n const fd = await tx.getFieldIfExists(field(pl.clientRoot, TemplateCacheFieldName));\n return fd ? ensureSignedResourceIdNotNull(fd.value) : undefined;\n });\n if (existing) {\n cacheRidMap.set(pl, existing);\n return existing;\n }\n\n const result = await pl.withWriteTx(\"templateCache:init\", async (tx) => {\n // Double-check inside write tx (another instance may have created it)\n const fd = await tx.getFieldIfExists(field(pl.clientRoot, TemplateCacheFieldName));\n if (fd) return ensureSignedResourceIdNotNull(fd.value);\n\n const cache = tx.createStruct(TemplateCacheType);\n tx.createField(field(pl.clientRoot, TemplateCacheFieldName), \"Dynamic\", cache);\n tx.lock(cache);\n await tx.commit();\n return await cache.globalId;\n });\n cacheRidMap.set(pl, result);\n return result;\n}\n\n/** Remove the template cache from user root. */\nexport async function dropTemplateCache(pl: PlClient): Promise<void> {\n await pl.withWriteTx(\"templateCache:drop\", async (tx) => {\n const cacheField = field(pl.clientRoot, TemplateCacheFieldName);\n const fd = await tx.getFieldIfExists(cacheField);\n if (fd) {\n tx.removeField(cacheField);\n await tx.commit();\n }\n });\n invalidateTemplateCacheId(pl);\n}\n\n/**\n * Run count-based garbage collection on the template cache.\n * Evicts least-recently-used entries when the cache exceeds maxEntries.\n * Always resets the access counter to 0.\n *\n * @internal exported for testing (maxEntries parameter allows low thresholds in tests)\n * @returns true if entries were evicted\n */\nexport async function runGc(\n pl: PlClient,\n cacheRid: SignedResourceId,\n maxEntries: number = GC_MAX_ENTRIES,\n): Promise<boolean> {\n return await pl.withWriteTx(\"templateCache:gc\", async (tx) => {\n const kvs = await tx.listKeyValuesString(cacheRid);\n const entries: { hash: string; timestamp: number }[] = [];\n for (const { key, value } of kvs) {\n if (!key.startsWith(ACCESS_KEY_PREFIX)) continue;\n entries.push({\n hash: key.slice(ACCESS_KEY_PREFIX.length),\n timestamp: parseInt(value, 10),\n });\n }\n\n // Always reset counter\n tx.setKValue(cacheRid, ACCESS_COUNT_KEY, \"0\");\n\n if (entries.length <= maxEntries) {\n await tx.commit();\n return false;\n }\n\n // Sort oldest first, evict until under limit\n entries.sort((a, b) => a.timestamp - b.timestamp);\n const toEvict = entries.length - maxEntries;\n for (let i = 0; i < toEvict; i++) {\n tx.removeField(field(cacheRid, entries[i].hash));\n tx.deleteKValue(cacheRid, ACCESS_KEY_PREFIX + entries[i].hash);\n }\n\n await tx.commit();\n return true;\n });\n}\n\n/** Create a batch of cache nodes in the current transaction. */\nfunction createBatchNodes(\n tx: PlTransaction,\n cacheRid: SignedResourceId,\n batch: CacheableNode[],\n resolvedIds: ReadonlyMap<string, SignedResourceId>,\n newRefs: Map<string, ResourceRef>,\n now: string,\n): void {\n for (const node of batch) {\n const childRefs = new Map<string, AnyResourceRef>();\n for (const ch of node.childHashes) {\n const resolved = resolvedIds.get(ch) ?? newRefs.get(ch);\n if (resolved === undefined) {\n throw new Error(`BUG: child ${ch} not resolved`);\n }\n childRefs.set(ch, resolved);\n }\n const ref = node.create(tx, childRefs);\n newRefs.set(node.hash, ref);\n tx.createField(field(cacheRid, node.hash), \"Dynamic\", ref);\n tx.setKValue(cacheRid, ACCESS_KEY_PREFIX + node.hash, now);\n }\n}\n\n/**\n * Materialize a template tree via the cache using \"probe all + batched creation\".\n *\n * Phase 1 (single write tx):\n * - Check existence of ALL hashes in one roundtrip\n * - Happy path: if root cached, update access tracking and return\n * - Otherwise: fetch ResourceIds for all cache hits, create first batch of missing nodes\n *\n * Phase 2..N (one write tx per batch):\n * - Create remaining missing nodes in BATCH_SIZE chunks\n *\n * @returns root SignedResourceId and current access count (for GC decision)\n */\nasync function materialize(\n pl: PlClient,\n cacheRid: SignedResourceId,\n rootHash: string,\n nodes: CacheableNode[],\n stat: TemplateCacheStat,\n): Promise<{ rootId: SignedResourceId; accessCount: number }> {\n const allHashes = nodes.map((n) => n.hash);\n const resolvedIds = new Map<string, SignedResourceId>();\n\n // Phase 1: probe all + first batch\n const phase1 = await pl.withWriteTx(\"templateCache:materialize\", async (tx) => {\n // 1 roundtrip: check all hashes + read access count\n const [exists, countStr] = await Promise.all([\n Promise.all(allHashes.map((h) => tx.fieldExists(field(cacheRid, h)))),\n tx.getKValueStringIfExists(cacheRid, ACCESS_COUNT_KEY),\n ]);\n\n const prevCount = countStr ? parseInt(countStr, 10) : 0;\n const newCount = prevCount + 1;\n const now = Date.now().toString();\n const rootIdx = allHashes.length - 1;\n\n // Happy path: root already cached\n if (exists[rootIdx]) {\n const rootFd = await tx.getField(field(cacheRid, rootHash));\n const rootRid = ensureSignedResourceIdNotNull(rootFd.value);\n tx.setKValue(cacheRid, ACCESS_KEY_PREFIX + rootHash, now);\n tx.setKValue(cacheRid, ACCESS_COUNT_KEY, newCount.toString());\n await tx.commit();\n stat.happyPath = true;\n stat.cacheHits = stat.totalNodes;\n stat.batchCount = 1;\n return { done: true as const, rootId: rootRid, accessCount: newCount };\n }\n\n // Fetch ResourceIds for all cache hits (1 roundtrip)\n const hitIndices: number[] = [];\n for (let i = 0; i < allHashes.length; i++) {\n if (exists[i]) hitIndices.push(i);\n }\n\n if (hitIndices.length > 0) {\n const hitFields = await Promise.all(\n hitIndices.map((i) => tx.getField(field(cacheRid, allHashes[i]))),\n );\n for (let j = 0; j < hitIndices.length; j++) {\n resolvedIds.set(\n allHashes[hitIndices[j]],\n ensureSignedResourceIdNotNull(hitFields[j].value),\n );\n }\n }\n stat.cacheHits = hitIndices.length;\n\n // Missing nodes (topo order preserved from flatten)\n const missing = nodes.filter((n) => !resolvedIds.has(n.hash));\n stat.cacheMisses = missing.length;\n\n // Create first batch of missing nodes\n const firstBatch = missing.slice(0, BATCH_SIZE);\n const newRefs = new Map<string, ResourceRef>();\n createBatchNodes(tx, cacheRid, firstBatch, resolvedIds, newRefs, now);\n\n // Update access tracking for cache hits\n for (const i of hitIndices) {\n tx.setKValue(cacheRid, ACCESS_KEY_PREFIX + allHashes[i], now);\n }\n tx.setKValue(cacheRid, ACCESS_COUNT_KEY, newCount.toString());\n\n await tx.commit();\n\n // Resolve new refs to global IDs (after commit)\n for (const [hash, ref] of newRefs) {\n resolvedIds.set(hash, await toGlobalResourceId(ref));\n }\n\n return {\n done: false as const,\n remaining: missing.slice(BATCH_SIZE),\n accessCount: newCount,\n };\n });\n\n if (phase1.done) {\n return { rootId: phase1.rootId, accessCount: phase1.accessCount };\n }\n\n stat.batchCount = 1;\n\n // Phase 2+: remaining batches\n const { remaining } = phase1;\n for (let i = 0; i < remaining.length; i += BATCH_SIZE) {\n const batch = remaining.slice(i, i + BATCH_SIZE);\n stat.batchCount++;\n\n await pl.withWriteTx(\"templateCache:create\", async (tx) => {\n const newRefs = new Map<string, ResourceRef>();\n const now = Date.now().toString();\n createBatchNodes(tx, cacheRid, batch, resolvedIds, newRefs, now);\n await tx.commit();\n\n for (const [hash, ref] of newRefs) {\n resolvedIds.set(hash, await toGlobalResourceId(ref));\n }\n });\n }\n\n const rootId = resolvedIds.get(rootHash);\n if (!rootId) throw new Error(\"BUG: root hash not resolved after all batches\");\n return { rootId, accessCount: phase1.accessCount };\n}\n\n/**\n * Materialize a template tree via the cache.\n * Manages its own transactions internally — do NOT call inside an existing tx.\n *\n * @returns concrete SignedResourceId of the root template\n */\nexport async function loadTemplateCached(\n pl: PlClient,\n spec: TemplateSpecPrepared,\n options?: { cacheResourceId?: SignedResourceId },\n): Promise<SignedResourceId> {\n const stat = initialStat();\n const t0 = performance.now();\n\n try {\n // Parse to data if needed\n let tplData: TemplateData | CompiledTemplateV3;\n switch (spec.type) {\n case \"explicit\":\n tplData = parseTemplate(spec.content);\n break;\n case \"prepared\":\n tplData = spec.data;\n break;\n case \"cached\":\n return spec.resourceId;\n case \"from-registry\":\n throw new Error(\n \"loadTemplateCached does not support from-registry specs; use loadTemplate instead\",\n );\n default: {\n const _: never = spec;\n throw new Error(`unexpected spec type: ${(_ as any).type}`);\n }\n }\n\n stat.templateFormat = tplData.type;\n\n // Flatten to ordered nodes\n const tFlatten = performance.now();\n const nodes = flattenTemplateTree(tplData);\n stat.flattenMs = performance.now() - tFlatten;\n if (nodes.length === 0) throw new Error(\"template tree produced no nodes\");\n\n stat.totalNodes = nodes.length;\n const rootHash = nodes[nodes.length - 1].hash;\n\n // Resolve or create cache resource\n const tCacheInit = performance.now();\n const cacheRid = options?.cacheResourceId ?? (await getOrCreateTemplateCache(pl));\n stat.cacheInitMs = performance.now() - tCacheInit;\n\n // Retry loop: if a write tx fails (e.g. concurrent GC invalidated a cached resource),\n // restart materialization from scratch.\n const MAX_RETRIES = 3;\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n const tMat = performance.now();\n const result = await materialize(pl, cacheRid, rootHash, nodes, stat);\n stat.materializeMs = performance.now() - tMat;\n stat.retries = attempt;\n\n // GC in separate tx if access count exceeded threshold\n if (result.accessCount >= GC_ACCESS_THRESHOLD) {\n await runGc(pl, cacheRid);\n stat.gcTriggered = true;\n }\n\n return result.rootId;\n } catch (e) {\n if (attempt === MAX_RETRIES - 1) throw e;\n // Retry from scratch — previous batch results may reference GC'd resources\n stat.cacheHits = 0;\n stat.cacheMisses = 0;\n }\n }\n\n throw new Error(\"BUG: unreachable\");\n } finally {\n stat.totalMs = performance.now() - t0;\n if (getDebugFlags().logTemplateCacheStat) {\n console.log(`[templateCache] ${JSON.stringify(stat)}`);\n }\n }\n}\n\n/**\n * Pre-materialize a block pack's template via cache.\n * Returns a copy of the spec with the template replaced by a cached reference.\n * If the template is already cached, returns the spec unchanged.\n */\nexport async function cacheBlockPackTemplate(\n pl: PlClient,\n spec: BlockPackSpecPrepared,\n options?: { cacheResourceId?: SignedResourceId },\n): Promise<BlockPackSpecPrepared> {\n if (spec.template.type === \"cached\") return spec;\n\n const resourceId = await loadTemplateCached(pl, spec.template, options);\n return {\n ...spec,\n template: { type: \"cached\", resourceId },\n };\n}\n"],"mappings":"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"}
@@ -3,7 +3,6 @@ import { BlockPackSpecPrepared } from "../../model/block_pack_spec.js";
3
3
  import "../../model/index.js";
4
4
  import { AnyResourceRef, PlClient, PlTransaction, ResourceRef, SignedResourceId } from "@milaboratories/pl-client";
5
5
  import { CompiledTemplateV3, TemplateData } from "@milaboratories/pl-model-backend";
6
- //#region src/mutator/template/template_cache.d.ts
7
6
  export declare const TemplateCacheType: import("@milaboratories/pl-client").ResourceType;
8
7
  export declare const TemplateCacheFieldName = "__templateCache";
9
8
  /** @internal exported for testing */
@@ -71,5 +70,5 @@ export declare function loadTemplateCached(pl: PlClient, spec: TemplateSpecPrepa
71
70
  export declare function cacheBlockPackTemplate(pl: PlClient, spec: BlockPackSpecPrepared, options?: {
72
71
  cacheResourceId?: SignedResourceId;
73
72
  }): Promise<BlockPackSpecPrepared>;
74
- //#endregion
73
+ export {};
75
74
  //# sourceMappingURL=template_cache.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"template_cache.d.ts","names":[],"sources":["../../../src/mutator/template/template_cache.ts"],"mappings":";;;;;;qBAqCa,uDAAiB;qBAEjB;;qBAGA;;qBAEA;;qBAEA;;qBAEA;YAED;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;UAoBQ;;EAER;;;EAGA,SAAS,IAAI,eAAe,WAAW,oBAAoB,oBAAoB;;EAE/E;;;wBA2Vc,oBAAoB,MAAM,eAAe,qBAAqB;;wBAY9D,0BAA0B,IAAI;;wBAKxB,yBAAyB,IAAI,WAAW,QAAQ;;wBA+BhD,kBAAkB,IAAI,WAAW;;;;;;;;;wBAoBjC,MACpB,IAAI,UACJ,UAAU,kBACV,sBACC;;;;;;;wBA8LmB,mBACpB,IAAI,UACJ,MAAM,sBACN;EAAY,kBAAkB;IAC7B,QAAQ;;;;;;wBAiFW,uBACpB,IAAI,UACJ,MAAM,uBACN;EAAY,kBAAkB;IAC7B,QAAQ"}
1
+ {"version":3,"file":"template_cache.d.ts","names":[],"sources":["../../../src/mutator/template/template_cache.ts"],"mappings":";;;;;qBAqCa,uDAAiB;qBAEjB;;qBAGA;;qBAEA;;qBAEA;;qBAEA;YAED;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;UAoBQ;;EAER;;;EAGA,SAAS,IAAI,eAAe,WAAW,oBAAoB,oBAAoB;;EAE/E;;;wBA2Vc,oBAAoB,MAAM,eAAe,qBAAqB;;wBAY9D,0BAA0B,IAAI;;wBAKxB,yBAAyB,IAAI,WAAW,QAAQ;;wBA+BhD,kBAAkB,IAAI,WAAW;;;;;;;;;wBAoBjC,MACpB,IAAI,UACJ,UAAU,kBACV,sBACC;;;;;;;wBA8LmB,mBACpB,IAAI,UACJ,MAAM,sBACN;EAAY,kBAAkB;IAC7B,QAAQ;;;;;;wBAiFW,uBACpB,IAAI,UACJ,MAAM,uBACN;EAAY,kBAAkB;IAC7B,QAAQ"}
@@ -3,7 +3,7 @@ import { notEmpty } from "@milaboratories/ts-helpers";
3
3
  import { ensureSignedResourceIdNotNull, field, resourceType, toGlobalResourceId } from "@milaboratories/pl-client";
4
4
  import { createHash } from "node:crypto";
5
5
  import { PlTemplateLibV1, PlTemplateOverrideV1, PlTemplateSoftwareV1, PlTemplateV1, PlWasmV1, parseTemplate } from "@milaboratories/pl-model-backend";
6
- //#region src/mutator/template/template_cache.ts
6
+ // src/mutator/template/template_cache.ts
7
7
  const TemplateCacheType = resourceType("TemplateCache", "1");
8
8
  const TemplateCacheFieldName = "__templateCache";
9
9
  const BATCH_SIZE = 50;
@@ -391,7 +391,8 @@ async function materialize(pl, cacheRid, rootHash, nodes, stat) {
391
391
  const newCount = (countStr ? parseInt(countStr, 10) : 0) + 1;
392
392
  const now = Date.now().toString();
393
393
  if (exists[allHashes.length - 1]) {
394
- const rootRid = ensureSignedResourceIdNotNull((await tx.getField(field(cacheRid, rootHash))).value);
394
+ const rootFd = await tx.getField(field(cacheRid, rootHash));
395
+ const rootRid = ensureSignedResourceIdNotNull(rootFd.value);
395
396
  tx.setKValue(cacheRid, ACCESS_KEY_PREFIX + rootHash, now);
396
397
  tx.setKValue(cacheRid, ACCESS_COUNT_KEY, newCount.toString());
397
398
  await tx.commit();
@@ -437,7 +438,8 @@ async function materialize(pl, cacheRid, rootHash, nodes, stat) {
437
438
  stat.batchCount++;
438
439
  await pl.withWriteTx("templateCache:create", async (tx) => {
439
440
  const newRefs = /* @__PURE__ */ new Map();
440
- createBatchNodes(tx, cacheRid, batch, resolvedIds, newRefs, Date.now().toString());
441
+ const now = Date.now().toString();
442
+ createBatchNodes(tx, cacheRid, batch, resolvedIds, newRefs, now);
441
443
  await tx.commit();
442
444
  for (const [hash, ref] of newRefs) resolvedIds.set(hash, await toGlobalResourceId(ref));
443
445
  });
@@ -493,7 +495,7 @@ async function loadTemplateCached(pl, spec, options) {
493
495
  }
494
496
  return result.rootId;
495
497
  } catch (e) {
496
- if (attempt === MAX_RETRIES - 1) throw e;
498
+ if (attempt === 2) throw e;
497
499
  stat.cacheHits = 0;
498
500
  stat.cacheMisses = 0;
499
501
  }
@@ -519,7 +521,6 @@ async function cacheBlockPackTemplate(pl, spec, options) {
519
521
  }
520
522
  };
521
523
  }
522
- //#endregion
523
524
  export { ACCESS_COUNT_KEY, ACCESS_KEY_PREFIX, GC_ACCESS_THRESHOLD, GC_MAX_ENTRIES, TemplateCacheFieldName, TemplateCacheType, cacheBlockPackTemplate, dropTemplateCache, flattenTemplateTree, getOrCreateTemplateCache, invalidateTemplateCacheId, loadTemplateCached, runGc };
524
525
 
525
526
  //# sourceMappingURL=template_cache.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"template_cache.js","names":["_"],"sources":["../../../src/mutator/template/template_cache.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport type {\n AnyResourceRef,\n PlClient,\n PlTransaction,\n SignedResourceId,\n ResourceRef,\n} from \"@milaboratories/pl-client\";\nimport {\n ensureSignedResourceIdNotNull,\n field,\n resourceType,\n toGlobalResourceId,\n} from \"@milaboratories/pl-client\";\nimport {\n parseTemplate,\n PlTemplateLibV1,\n PlTemplateOverrideV1,\n PlTemplateSoftwareV1,\n PlTemplateV1,\n PlWasmV1,\n} from \"@milaboratories/pl-model-backend\";\nimport type {\n CompiledTemplateV3,\n TemplateData,\n TemplateDataV3,\n TemplateLibData,\n TemplateLibDataV3,\n TemplateSoftwareData,\n TemplateSoftwareDataV3,\n TemplateWasmDataV3,\n} from \"@milaboratories/pl-model-backend\";\nimport { notEmpty } from \"@milaboratories/ts-helpers\";\nimport type { BlockPackSpecPrepared } from \"../../model\";\nimport type { TemplateSpecPrepared } from \"../../model/template_spec\";\nimport { getDebugFlags } from \"../../debug\";\n\nexport const TemplateCacheType = resourceType(\"TemplateCache\", \"1\");\n\nexport const TemplateCacheFieldName = \"__templateCache\";\nconst BATCH_SIZE = 50;\n/** @internal exported for testing */\nexport const GC_ACCESS_THRESHOLD = 30;\n/** @internal exported for testing */\nexport const GC_MAX_ENTRIES = 3000;\n/** @internal exported for testing */\nexport const ACCESS_COUNT_KEY = \"_accessCount\";\n/** @internal exported for testing */\nexport const ACCESS_KEY_PREFIX = \"access_\";\n\nexport type TemplateCacheStat = {\n totalMs: number;\n flattenMs: number;\n cacheInitMs: number;\n materializeMs: number;\n totalNodes: number;\n cacheHits: number;\n cacheMisses: number;\n batchCount: number;\n happyPath: boolean;\n gcTriggered: boolean;\n retries: number;\n templateFormat: string;\n};\n\nfunction initialStat(): TemplateCacheStat {\n return {\n totalMs: 0,\n flattenMs: 0,\n cacheInitMs: 0,\n materializeMs: 0,\n totalNodes: 0,\n cacheHits: 0,\n cacheMisses: 0,\n batchCount: 0,\n happyPath: false,\n gcTriggered: false,\n retries: 0,\n templateFormat: \"\",\n };\n}\n\ninterface CacheableNode {\n /** SHA-256 content hash (includes all descendant content) */\n hash: string;\n /** Creates this node's resource in a transaction.\n * childRefs maps child hash → already-resolved ResourceRef or SignedResourceId */\n create: (tx: PlTransaction, childRefs: ReadonlyMap<string, AnyResourceRef>) => ResourceRef;\n /** Hashes of direct child nodes this node depends on */\n childHashes: string[];\n}\n\nfunction getSourceCode(name: string, sources: Record<string, string>, sourceHash: string): string {\n return notEmpty(\n sources[sourceHash],\n `trying to get \"${name}\" source: sources map doesn't contain source hash ${sourceHash}`,\n );\n}\n\n/**\n * Bottom-up hash composition: each node hashes its OWN content + child hash STRINGS.\n * This means each unique node is hashed exactly once → O(n) instead of O(n * depth).\n */\n\n// V2 leaf hashes (libs, software — no children)\n\nfunction hashLibV2(lib: TemplateLibData): string {\n return createHash(\"sha256\")\n .update(PlTemplateLibV1.type.name)\n .update(PlTemplateLibV1.type.version)\n .update(lib.name)\n .update(lib.version)\n .update(lib.src)\n .digest(\"hex\");\n}\n\nfunction hashSoftwareV2(sw: TemplateSoftwareData): string {\n return createHash(\"sha256\")\n .update(PlTemplateSoftwareV1.type.name)\n .update(PlTemplateSoftwareV1.type.version)\n .update(sw.name)\n .update(sw.version)\n .update(sw.src)\n .digest(\"hex\");\n}\n\n// V3 leaf hashes — use sourceHash directly instead of resolving source content\n\nfunction hashLibV3(lib: TemplateLibDataV3): string {\n return createHash(\"sha256\")\n .update(PlTemplateLibV1.type.name)\n .update(PlTemplateLibV1.type.version)\n .update(lib.name)\n .update(lib.version)\n .update(lib.sourceHash)\n .digest(\"hex\");\n}\n\nfunction hashSoftwareV3(sw: TemplateSoftwareDataV3): string {\n return createHash(\"sha256\")\n .update(PlTemplateSoftwareV1.type.name)\n .update(PlTemplateSoftwareV1.type.version)\n .update(sw.name)\n .update(sw.version)\n .update(sw.sourceHash)\n .digest(\"hex\");\n}\n\nfunction hashWasmV3(wasm: TemplateWasmDataV3): string {\n return createHash(\"sha256\")\n .update(PlWasmV1.type.name)\n .update(PlWasmV1.type.version)\n .update(wasm.name)\n .update(wasm.version)\n .update(wasm.sourceHash)\n .digest(\"hex\");\n}\n\n// ─── Tree flattening ─────────────────────────────────────────────────────────\n\nfunction flattenV2Tree(data: TemplateData): CacheableNode[] {\n const nodes: CacheableNode[] = [];\n const seen = new Set<string>();\n\n function processLib(lib: TemplateLibData): string {\n const hash = hashLibV2(lib);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) =>\n tx.createValue(\n PlTemplateLibV1.type,\n JSON.stringify(PlTemplateLibV1.fromV2Data(lib).data),\n ),\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processSoftware(sw: TemplateSoftwareData): string {\n const hash = hashSoftwareV2(sw);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) => {\n const swData = PlTemplateSoftwareV1.fromV2Data(sw);\n const ref = tx.createStruct(PlTemplateSoftwareV1.type, swData.data);\n tx.setKValue(ref, PlTemplateSoftwareV1.metaNameKey, JSON.stringify(swData.name));\n tx.lock(ref);\n return ref;\n },\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processTemplate(tpl: TemplateData): string {\n // Process children first (bottom-up) — their hashes are computed before ours\n const childHashes: string[] = [];\n const children: { fieldName: string; hash: string }[] = [];\n\n for (const [libId, lib] of Object.entries(tpl.libs ?? {})) {\n const h = processLib(lib);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.libPrefix}/${libId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.software ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.assets ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [tplId, sub] of Object.entries(tpl.templates ?? {})) {\n const h = processTemplate(sub);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.tplPrefix}/${tplId}`, hash: h });\n }\n\n // Compose hash from own content + child hash strings (NOT child content)\n const h = createHash(\"sha256\")\n .update(PlTemplateV1.type.name)\n .update(PlTemplateV1.type.version)\n .update(tpl.hashOverride ?? \"no-override\")\n .update(tpl.name)\n .update(tpl.version)\n .update(tpl.src);\n for (const child of children) {\n h.update(\"child:\" + child.fieldName + \":\" + child.hash);\n }\n const hash = h.digest(\"hex\");\n\n if (seen.has(hash)) return hash;\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx, childRefs) => {\n const tplRef = tx.createStruct(\n PlTemplateV1.type,\n JSON.stringify(PlTemplateV1.fromV2Data(tpl).data),\n );\n for (const child of children) {\n const fld = field(tplRef, child.fieldName);\n tx.createField(fld, \"Input\");\n tx.setField(fld, notEmpty(childRefs.get(child.hash), `missing child ref ${child.hash}`));\n }\n tx.lock(tplRef);\n\n if (!tpl.hashOverride) return tplRef;\n\n const overrideRef = tx.createStruct(\n PlTemplateOverrideV1.type,\n JSON.stringify(PlTemplateOverrideV1.fromV2Data(tpl)),\n );\n const overrideFld = PlTemplateOverrideV1.tplField(overrideRef);\n tx.createField(overrideFld, \"Service\");\n tx.setField(overrideFld, tplRef);\n tx.lock(overrideRef);\n return overrideRef;\n },\n childHashes,\n });\n\n return hash;\n }\n\n processTemplate(data);\n return nodes;\n}\n\nfunction flattenV3Tree(data: CompiledTemplateV3): CacheableNode[] {\n const nodes: CacheableNode[] = [];\n const seen = new Set<string>();\n const sources = data.hashToSource;\n\n function processLib(lib: TemplateLibDataV3): string {\n const hash = hashLibV3(lib);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) =>\n tx.createValue(\n PlTemplateLibV1.type,\n JSON.stringify(\n PlTemplateLibV1.fromV3Data(lib, getSourceCode(lib.name, sources, lib.sourceHash))\n .data,\n ),\n ),\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processSoftware(sw: TemplateSoftwareDataV3): string {\n const hash = hashSoftwareV3(sw);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) => {\n const swData = PlTemplateSoftwareV1.fromV3Data(\n sw,\n getSourceCode(sw.name, sources, sw.sourceHash),\n );\n const ref = tx.createStruct(PlTemplateSoftwareV1.type, swData.data);\n tx.setKValue(ref, PlTemplateSoftwareV1.metaNameKey, JSON.stringify(swData.name));\n tx.lock(ref);\n return ref;\n },\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processWasm(wasm: TemplateWasmDataV3): string {\n const hash = hashWasmV3(wasm);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) =>\n tx.createValue(\n PlWasmV1.type,\n JSON.stringify(\n PlWasmV1.fromV3Data(wasm, getSourceCode(wasm.name, sources, wasm.sourceHash)).data,\n ),\n ),\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processTemplate(tpl: TemplateDataV3): string {\n // Defensive: a template can carry no embedded version at runtime even\n // though the type says `string` — the compiler writes `packageJson.version`\n // unchecked, so a template built from a package with no `version` field\n // yields undefined. Identity is fully covered by name + sourceHash, so the\n // placeholder is safe for both the cache key and the backend resource's\n // required Version field.\n const version = tpl.version ?? \"0.0.0\";\n\n // Process children first (bottom-up)\n const childHashes: string[] = [];\n const children: { fieldName: string; hash: string }[] = [];\n\n for (const [libId, lib] of Object.entries(tpl.libs ?? {})) {\n const h = processLib(lib);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.libPrefix}/${libId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.software ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.assets ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [tplId, sub] of Object.entries(tpl.templates ?? {})) {\n const h = processTemplate(sub);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.tplPrefix}/${tplId}`, hash: h });\n }\n for (const [wasmId, wasm] of Object.entries(tpl.wasm ?? {})) {\n const h = processWasm(wasm);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.wasmPrefix}/${wasmId}`, hash: h });\n }\n\n // Compose hash from own content + child hash strings (NOT child content).\n // Uses sourceHash directly — it already uniquely identifies the source.\n const h = createHash(\"sha256\")\n .update(PlTemplateV1.type.name)\n .update(PlTemplateV1.type.version)\n .update(tpl.hashOverride ?? \"no-override\")\n .update(tpl.name)\n .update(version)\n .update(tpl.sourceHash);\n for (const child of children) {\n h.update(\"child:\" + child.fieldName + \":\" + child.hash);\n }\n const hash = h.digest(\"hex\");\n\n if (seen.has(hash)) return hash;\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx, childRefs) => {\n const sourceCode = getSourceCode(tpl.name, sources, tpl.sourceHash);\n const tplRef = tx.createStruct(\n PlTemplateV1.type,\n JSON.stringify(PlTemplateV1.fromV3Data({ ...tpl, version }, sourceCode).data),\n );\n for (const child of children) {\n const fld = field(tplRef, child.fieldName);\n tx.createField(fld, \"Input\");\n tx.setField(fld, notEmpty(childRefs.get(child.hash), `missing child ref ${child.hash}`));\n }\n tx.lock(tplRef);\n\n if (!tpl.hashOverride) return tplRef;\n\n const overrideRef = tx.createStruct(\n PlTemplateOverrideV1.type,\n JSON.stringify(PlTemplateOverrideV1.fromV3Data(tpl)),\n );\n const overrideFld = PlTemplateOverrideV1.tplField(overrideRef);\n tx.createField(overrideFld, \"Service\");\n tx.setField(overrideFld, tplRef);\n tx.lock(overrideRef);\n return overrideRef;\n },\n childHashes,\n });\n\n return hash;\n }\n\n processTemplate(data.template);\n return nodes;\n}\n\n/** Flatten template tree into a topologically ordered list of cacheable nodes (leaves first). */\nexport function flattenTemplateTree(data: TemplateData | CompiledTemplateV3): CacheableNode[] {\n if (data.type === \"pl.tengo-template.v2\") {\n return flattenV2Tree(data);\n } else {\n return flattenV3Tree(data);\n }\n}\n\n/** In-memory cache for the TemplateCache SignedResourceId per PlClient instance. */\nconst cacheRidMap = new WeakMap<PlClient, SignedResourceId>();\n\n/** Clear the in-memory cacheRid entry (call on errors referencing the cache resource). */\nexport function invalidateTemplateCacheId(pl: PlClient): void {\n cacheRidMap.delete(pl);\n}\n\n/** Find or create the TemplateCache/1 resource on user root. */\nexport async function getOrCreateTemplateCache(pl: PlClient): Promise<SignedResourceId> {\n // Check in-memory cache first (0ms after first call)\n const cached = cacheRidMap.get(pl);\n if (cached !== undefined) return cached;\n\n // Try read-only check\n const existing = await pl.withReadTx(\"templateCache:check\", async (tx) => {\n const fd = await tx.getFieldIfExists(field(pl.clientRoot, TemplateCacheFieldName));\n return fd ? ensureSignedResourceIdNotNull(fd.value) : undefined;\n });\n if (existing) {\n cacheRidMap.set(pl, existing);\n return existing;\n }\n\n const result = await pl.withWriteTx(\"templateCache:init\", async (tx) => {\n // Double-check inside write tx (another instance may have created it)\n const fd = await tx.getFieldIfExists(field(pl.clientRoot, TemplateCacheFieldName));\n if (fd) return ensureSignedResourceIdNotNull(fd.value);\n\n const cache = tx.createStruct(TemplateCacheType);\n tx.createField(field(pl.clientRoot, TemplateCacheFieldName), \"Dynamic\", cache);\n tx.lock(cache);\n await tx.commit();\n return await cache.globalId;\n });\n cacheRidMap.set(pl, result);\n return result;\n}\n\n/** Remove the template cache from user root. */\nexport async function dropTemplateCache(pl: PlClient): Promise<void> {\n await pl.withWriteTx(\"templateCache:drop\", async (tx) => {\n const cacheField = field(pl.clientRoot, TemplateCacheFieldName);\n const fd = await tx.getFieldIfExists(cacheField);\n if (fd) {\n tx.removeField(cacheField);\n await tx.commit();\n }\n });\n invalidateTemplateCacheId(pl);\n}\n\n/**\n * Run count-based garbage collection on the template cache.\n * Evicts least-recently-used entries when the cache exceeds maxEntries.\n * Always resets the access counter to 0.\n *\n * @internal exported for testing (maxEntries parameter allows low thresholds in tests)\n * @returns true if entries were evicted\n */\nexport async function runGc(\n pl: PlClient,\n cacheRid: SignedResourceId,\n maxEntries: number = GC_MAX_ENTRIES,\n): Promise<boolean> {\n return await pl.withWriteTx(\"templateCache:gc\", async (tx) => {\n const kvs = await tx.listKeyValuesString(cacheRid);\n const entries: { hash: string; timestamp: number }[] = [];\n for (const { key, value } of kvs) {\n if (!key.startsWith(ACCESS_KEY_PREFIX)) continue;\n entries.push({\n hash: key.slice(ACCESS_KEY_PREFIX.length),\n timestamp: parseInt(value, 10),\n });\n }\n\n // Always reset counter\n tx.setKValue(cacheRid, ACCESS_COUNT_KEY, \"0\");\n\n if (entries.length <= maxEntries) {\n await tx.commit();\n return false;\n }\n\n // Sort oldest first, evict until under limit\n entries.sort((a, b) => a.timestamp - b.timestamp);\n const toEvict = entries.length - maxEntries;\n for (let i = 0; i < toEvict; i++) {\n tx.removeField(field(cacheRid, entries[i].hash));\n tx.deleteKValue(cacheRid, ACCESS_KEY_PREFIX + entries[i].hash);\n }\n\n await tx.commit();\n return true;\n });\n}\n\n/** Create a batch of cache nodes in the current transaction. */\nfunction createBatchNodes(\n tx: PlTransaction,\n cacheRid: SignedResourceId,\n batch: CacheableNode[],\n resolvedIds: ReadonlyMap<string, SignedResourceId>,\n newRefs: Map<string, ResourceRef>,\n now: string,\n): void {\n for (const node of batch) {\n const childRefs = new Map<string, AnyResourceRef>();\n for (const ch of node.childHashes) {\n const resolved = resolvedIds.get(ch) ?? newRefs.get(ch);\n if (resolved === undefined) {\n throw new Error(`BUG: child ${ch} not resolved`);\n }\n childRefs.set(ch, resolved);\n }\n const ref = node.create(tx, childRefs);\n newRefs.set(node.hash, ref);\n tx.createField(field(cacheRid, node.hash), \"Dynamic\", ref);\n tx.setKValue(cacheRid, ACCESS_KEY_PREFIX + node.hash, now);\n }\n}\n\n/**\n * Materialize a template tree via the cache using \"probe all + batched creation\".\n *\n * Phase 1 (single write tx):\n * - Check existence of ALL hashes in one roundtrip\n * - Happy path: if root cached, update access tracking and return\n * - Otherwise: fetch ResourceIds for all cache hits, create first batch of missing nodes\n *\n * Phase 2..N (one write tx per batch):\n * - Create remaining missing nodes in BATCH_SIZE chunks\n *\n * @returns root SignedResourceId and current access count (for GC decision)\n */\nasync function materialize(\n pl: PlClient,\n cacheRid: SignedResourceId,\n rootHash: string,\n nodes: CacheableNode[],\n stat: TemplateCacheStat,\n): Promise<{ rootId: SignedResourceId; accessCount: number }> {\n const allHashes = nodes.map((n) => n.hash);\n const resolvedIds = new Map<string, SignedResourceId>();\n\n // Phase 1: probe all + first batch\n const phase1 = await pl.withWriteTx(\"templateCache:materialize\", async (tx) => {\n // 1 roundtrip: check all hashes + read access count\n const [exists, countStr] = await Promise.all([\n Promise.all(allHashes.map((h) => tx.fieldExists(field(cacheRid, h)))),\n tx.getKValueStringIfExists(cacheRid, ACCESS_COUNT_KEY),\n ]);\n\n const prevCount = countStr ? parseInt(countStr, 10) : 0;\n const newCount = prevCount + 1;\n const now = Date.now().toString();\n const rootIdx = allHashes.length - 1;\n\n // Happy path: root already cached\n if (exists[rootIdx]) {\n const rootFd = await tx.getField(field(cacheRid, rootHash));\n const rootRid = ensureSignedResourceIdNotNull(rootFd.value);\n tx.setKValue(cacheRid, ACCESS_KEY_PREFIX + rootHash, now);\n tx.setKValue(cacheRid, ACCESS_COUNT_KEY, newCount.toString());\n await tx.commit();\n stat.happyPath = true;\n stat.cacheHits = stat.totalNodes;\n stat.batchCount = 1;\n return { done: true as const, rootId: rootRid, accessCount: newCount };\n }\n\n // Fetch ResourceIds for all cache hits (1 roundtrip)\n const hitIndices: number[] = [];\n for (let i = 0; i < allHashes.length; i++) {\n if (exists[i]) hitIndices.push(i);\n }\n\n if (hitIndices.length > 0) {\n const hitFields = await Promise.all(\n hitIndices.map((i) => tx.getField(field(cacheRid, allHashes[i]))),\n );\n for (let j = 0; j < hitIndices.length; j++) {\n resolvedIds.set(\n allHashes[hitIndices[j]],\n ensureSignedResourceIdNotNull(hitFields[j].value),\n );\n }\n }\n stat.cacheHits = hitIndices.length;\n\n // Missing nodes (topo order preserved from flatten)\n const missing = nodes.filter((n) => !resolvedIds.has(n.hash));\n stat.cacheMisses = missing.length;\n\n // Create first batch of missing nodes\n const firstBatch = missing.slice(0, BATCH_SIZE);\n const newRefs = new Map<string, ResourceRef>();\n createBatchNodes(tx, cacheRid, firstBatch, resolvedIds, newRefs, now);\n\n // Update access tracking for cache hits\n for (const i of hitIndices) {\n tx.setKValue(cacheRid, ACCESS_KEY_PREFIX + allHashes[i], now);\n }\n tx.setKValue(cacheRid, ACCESS_COUNT_KEY, newCount.toString());\n\n await tx.commit();\n\n // Resolve new refs to global IDs (after commit)\n for (const [hash, ref] of newRefs) {\n resolvedIds.set(hash, await toGlobalResourceId(ref));\n }\n\n return {\n done: false as const,\n remaining: missing.slice(BATCH_SIZE),\n accessCount: newCount,\n };\n });\n\n if (phase1.done) {\n return { rootId: phase1.rootId, accessCount: phase1.accessCount };\n }\n\n stat.batchCount = 1;\n\n // Phase 2+: remaining batches\n const { remaining } = phase1;\n for (let i = 0; i < remaining.length; i += BATCH_SIZE) {\n const batch = remaining.slice(i, i + BATCH_SIZE);\n stat.batchCount++;\n\n await pl.withWriteTx(\"templateCache:create\", async (tx) => {\n const newRefs = new Map<string, ResourceRef>();\n const now = Date.now().toString();\n createBatchNodes(tx, cacheRid, batch, resolvedIds, newRefs, now);\n await tx.commit();\n\n for (const [hash, ref] of newRefs) {\n resolvedIds.set(hash, await toGlobalResourceId(ref));\n }\n });\n }\n\n const rootId = resolvedIds.get(rootHash);\n if (!rootId) throw new Error(\"BUG: root hash not resolved after all batches\");\n return { rootId, accessCount: phase1.accessCount };\n}\n\n/**\n * Materialize a template tree via the cache.\n * Manages its own transactions internally — do NOT call inside an existing tx.\n *\n * @returns concrete SignedResourceId of the root template\n */\nexport async function loadTemplateCached(\n pl: PlClient,\n spec: TemplateSpecPrepared,\n options?: { cacheResourceId?: SignedResourceId },\n): Promise<SignedResourceId> {\n const stat = initialStat();\n const t0 = performance.now();\n\n try {\n // Parse to data if needed\n let tplData: TemplateData | CompiledTemplateV3;\n switch (spec.type) {\n case \"explicit\":\n tplData = parseTemplate(spec.content);\n break;\n case \"prepared\":\n tplData = spec.data;\n break;\n case \"cached\":\n return spec.resourceId;\n case \"from-registry\":\n throw new Error(\n \"loadTemplateCached does not support from-registry specs; use loadTemplate instead\",\n );\n default: {\n const _: never = spec;\n throw new Error(`unexpected spec type: ${(_ as any).type}`);\n }\n }\n\n stat.templateFormat = tplData.type;\n\n // Flatten to ordered nodes\n const tFlatten = performance.now();\n const nodes = flattenTemplateTree(tplData);\n stat.flattenMs = performance.now() - tFlatten;\n if (nodes.length === 0) throw new Error(\"template tree produced no nodes\");\n\n stat.totalNodes = nodes.length;\n const rootHash = nodes[nodes.length - 1].hash;\n\n // Resolve or create cache resource\n const tCacheInit = performance.now();\n const cacheRid = options?.cacheResourceId ?? (await getOrCreateTemplateCache(pl));\n stat.cacheInitMs = performance.now() - tCacheInit;\n\n // Retry loop: if a write tx fails (e.g. concurrent GC invalidated a cached resource),\n // restart materialization from scratch.\n const MAX_RETRIES = 3;\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n const tMat = performance.now();\n const result = await materialize(pl, cacheRid, rootHash, nodes, stat);\n stat.materializeMs = performance.now() - tMat;\n stat.retries = attempt;\n\n // GC in separate tx if access count exceeded threshold\n if (result.accessCount >= GC_ACCESS_THRESHOLD) {\n await runGc(pl, cacheRid);\n stat.gcTriggered = true;\n }\n\n return result.rootId;\n } catch (e) {\n if (attempt === MAX_RETRIES - 1) throw e;\n // Retry from scratch — previous batch results may reference GC'd resources\n stat.cacheHits = 0;\n stat.cacheMisses = 0;\n }\n }\n\n throw new Error(\"BUG: unreachable\");\n } finally {\n stat.totalMs = performance.now() - t0;\n if (getDebugFlags().logTemplateCacheStat) {\n console.log(`[templateCache] ${JSON.stringify(stat)}`);\n }\n }\n}\n\n/**\n * Pre-materialize a block pack's template via cache.\n * Returns a copy of the spec with the template replaced by a cached reference.\n * If the template is already cached, returns the spec unchanged.\n */\nexport async function cacheBlockPackTemplate(\n pl: PlClient,\n spec: BlockPackSpecPrepared,\n options?: { cacheResourceId?: SignedResourceId },\n): Promise<BlockPackSpecPrepared> {\n if (spec.template.type === \"cached\") return spec;\n\n const resourceId = await loadTemplateCached(pl, spec.template, options);\n return {\n ...spec,\n template: { type: \"cached\", resourceId },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"template_cache.js","names":["_"],"sources":["../../../src/mutator/template/template_cache.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport type {\n AnyResourceRef,\n PlClient,\n PlTransaction,\n SignedResourceId,\n ResourceRef,\n} from \"@milaboratories/pl-client\";\nimport {\n ensureSignedResourceIdNotNull,\n field,\n resourceType,\n toGlobalResourceId,\n} from \"@milaboratories/pl-client\";\nimport {\n parseTemplate,\n PlTemplateLibV1,\n PlTemplateOverrideV1,\n PlTemplateSoftwareV1,\n PlTemplateV1,\n PlWasmV1,\n} from \"@milaboratories/pl-model-backend\";\nimport type {\n CompiledTemplateV3,\n TemplateData,\n TemplateDataV3,\n TemplateLibData,\n TemplateLibDataV3,\n TemplateSoftwareData,\n TemplateSoftwareDataV3,\n TemplateWasmDataV3,\n} from \"@milaboratories/pl-model-backend\";\nimport { notEmpty } from \"@milaboratories/ts-helpers\";\nimport type { BlockPackSpecPrepared } from \"../../model\";\nimport type { TemplateSpecPrepared } from \"../../model/template_spec\";\nimport { getDebugFlags } from \"../../debug\";\n\nexport const TemplateCacheType = resourceType(\"TemplateCache\", \"1\");\n\nexport const TemplateCacheFieldName = \"__templateCache\";\nconst BATCH_SIZE = 50;\n/** @internal exported for testing */\nexport const GC_ACCESS_THRESHOLD = 30;\n/** @internal exported for testing */\nexport const GC_MAX_ENTRIES = 3000;\n/** @internal exported for testing */\nexport const ACCESS_COUNT_KEY = \"_accessCount\";\n/** @internal exported for testing */\nexport const ACCESS_KEY_PREFIX = \"access_\";\n\nexport type TemplateCacheStat = {\n totalMs: number;\n flattenMs: number;\n cacheInitMs: number;\n materializeMs: number;\n totalNodes: number;\n cacheHits: number;\n cacheMisses: number;\n batchCount: number;\n happyPath: boolean;\n gcTriggered: boolean;\n retries: number;\n templateFormat: string;\n};\n\nfunction initialStat(): TemplateCacheStat {\n return {\n totalMs: 0,\n flattenMs: 0,\n cacheInitMs: 0,\n materializeMs: 0,\n totalNodes: 0,\n cacheHits: 0,\n cacheMisses: 0,\n batchCount: 0,\n happyPath: false,\n gcTriggered: false,\n retries: 0,\n templateFormat: \"\",\n };\n}\n\ninterface CacheableNode {\n /** SHA-256 content hash (includes all descendant content) */\n hash: string;\n /** Creates this node's resource in a transaction.\n * childRefs maps child hash → already-resolved ResourceRef or SignedResourceId */\n create: (tx: PlTransaction, childRefs: ReadonlyMap<string, AnyResourceRef>) => ResourceRef;\n /** Hashes of direct child nodes this node depends on */\n childHashes: string[];\n}\n\nfunction getSourceCode(name: string, sources: Record<string, string>, sourceHash: string): string {\n return notEmpty(\n sources[sourceHash],\n `trying to get \"${name}\" source: sources map doesn't contain source hash ${sourceHash}`,\n );\n}\n\n/**\n * Bottom-up hash composition: each node hashes its OWN content + child hash STRINGS.\n * This means each unique node is hashed exactly once → O(n) instead of O(n * depth).\n */\n\n// V2 leaf hashes (libs, software — no children)\n\nfunction hashLibV2(lib: TemplateLibData): string {\n return createHash(\"sha256\")\n .update(PlTemplateLibV1.type.name)\n .update(PlTemplateLibV1.type.version)\n .update(lib.name)\n .update(lib.version)\n .update(lib.src)\n .digest(\"hex\");\n}\n\nfunction hashSoftwareV2(sw: TemplateSoftwareData): string {\n return createHash(\"sha256\")\n .update(PlTemplateSoftwareV1.type.name)\n .update(PlTemplateSoftwareV1.type.version)\n .update(sw.name)\n .update(sw.version)\n .update(sw.src)\n .digest(\"hex\");\n}\n\n// V3 leaf hashes — use sourceHash directly instead of resolving source content\n\nfunction hashLibV3(lib: TemplateLibDataV3): string {\n return createHash(\"sha256\")\n .update(PlTemplateLibV1.type.name)\n .update(PlTemplateLibV1.type.version)\n .update(lib.name)\n .update(lib.version)\n .update(lib.sourceHash)\n .digest(\"hex\");\n}\n\nfunction hashSoftwareV3(sw: TemplateSoftwareDataV3): string {\n return createHash(\"sha256\")\n .update(PlTemplateSoftwareV1.type.name)\n .update(PlTemplateSoftwareV1.type.version)\n .update(sw.name)\n .update(sw.version)\n .update(sw.sourceHash)\n .digest(\"hex\");\n}\n\nfunction hashWasmV3(wasm: TemplateWasmDataV3): string {\n return createHash(\"sha256\")\n .update(PlWasmV1.type.name)\n .update(PlWasmV1.type.version)\n .update(wasm.name)\n .update(wasm.version)\n .update(wasm.sourceHash)\n .digest(\"hex\");\n}\n\n// ─── Tree flattening ─────────────────────────────────────────────────────────\n\nfunction flattenV2Tree(data: TemplateData): CacheableNode[] {\n const nodes: CacheableNode[] = [];\n const seen = new Set<string>();\n\n function processLib(lib: TemplateLibData): string {\n const hash = hashLibV2(lib);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) =>\n tx.createValue(\n PlTemplateLibV1.type,\n JSON.stringify(PlTemplateLibV1.fromV2Data(lib).data),\n ),\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processSoftware(sw: TemplateSoftwareData): string {\n const hash = hashSoftwareV2(sw);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) => {\n const swData = PlTemplateSoftwareV1.fromV2Data(sw);\n const ref = tx.createStruct(PlTemplateSoftwareV1.type, swData.data);\n tx.setKValue(ref, PlTemplateSoftwareV1.metaNameKey, JSON.stringify(swData.name));\n tx.lock(ref);\n return ref;\n },\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processTemplate(tpl: TemplateData): string {\n // Process children first (bottom-up) — their hashes are computed before ours\n const childHashes: string[] = [];\n const children: { fieldName: string; hash: string }[] = [];\n\n for (const [libId, lib] of Object.entries(tpl.libs ?? {})) {\n const h = processLib(lib);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.libPrefix}/${libId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.software ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.assets ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [tplId, sub] of Object.entries(tpl.templates ?? {})) {\n const h = processTemplate(sub);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.tplPrefix}/${tplId}`, hash: h });\n }\n\n // Compose hash from own content + child hash strings (NOT child content)\n const h = createHash(\"sha256\")\n .update(PlTemplateV1.type.name)\n .update(PlTemplateV1.type.version)\n .update(tpl.hashOverride ?? \"no-override\")\n .update(tpl.name)\n .update(tpl.version)\n .update(tpl.src);\n for (const child of children) {\n h.update(\"child:\" + child.fieldName + \":\" + child.hash);\n }\n const hash = h.digest(\"hex\");\n\n if (seen.has(hash)) return hash;\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx, childRefs) => {\n const tplRef = tx.createStruct(\n PlTemplateV1.type,\n JSON.stringify(PlTemplateV1.fromV2Data(tpl).data),\n );\n for (const child of children) {\n const fld = field(tplRef, child.fieldName);\n tx.createField(fld, \"Input\");\n tx.setField(fld, notEmpty(childRefs.get(child.hash), `missing child ref ${child.hash}`));\n }\n tx.lock(tplRef);\n\n if (!tpl.hashOverride) return tplRef;\n\n const overrideRef = tx.createStruct(\n PlTemplateOverrideV1.type,\n JSON.stringify(PlTemplateOverrideV1.fromV2Data(tpl)),\n );\n const overrideFld = PlTemplateOverrideV1.tplField(overrideRef);\n tx.createField(overrideFld, \"Service\");\n tx.setField(overrideFld, tplRef);\n tx.lock(overrideRef);\n return overrideRef;\n },\n childHashes,\n });\n\n return hash;\n }\n\n processTemplate(data);\n return nodes;\n}\n\nfunction flattenV3Tree(data: CompiledTemplateV3): CacheableNode[] {\n const nodes: CacheableNode[] = [];\n const seen = new Set<string>();\n const sources = data.hashToSource;\n\n function processLib(lib: TemplateLibDataV3): string {\n const hash = hashLibV3(lib);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) =>\n tx.createValue(\n PlTemplateLibV1.type,\n JSON.stringify(\n PlTemplateLibV1.fromV3Data(lib, getSourceCode(lib.name, sources, lib.sourceHash))\n .data,\n ),\n ),\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processSoftware(sw: TemplateSoftwareDataV3): string {\n const hash = hashSoftwareV3(sw);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) => {\n const swData = PlTemplateSoftwareV1.fromV3Data(\n sw,\n getSourceCode(sw.name, sources, sw.sourceHash),\n );\n const ref = tx.createStruct(PlTemplateSoftwareV1.type, swData.data);\n tx.setKValue(ref, PlTemplateSoftwareV1.metaNameKey, JSON.stringify(swData.name));\n tx.lock(ref);\n return ref;\n },\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processWasm(wasm: TemplateWasmDataV3): string {\n const hash = hashWasmV3(wasm);\n if (!seen.has(hash)) {\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx) =>\n tx.createValue(\n PlWasmV1.type,\n JSON.stringify(\n PlWasmV1.fromV3Data(wasm, getSourceCode(wasm.name, sources, wasm.sourceHash)).data,\n ),\n ),\n childHashes: [],\n });\n }\n return hash;\n }\n\n function processTemplate(tpl: TemplateDataV3): string {\n // Defensive: a template can carry no embedded version at runtime even\n // though the type says `string` — the compiler writes `packageJson.version`\n // unchecked, so a template built from a package with no `version` field\n // yields undefined. Identity is fully covered by name + sourceHash, so the\n // placeholder is safe for both the cache key and the backend resource's\n // required Version field.\n const version = tpl.version ?? \"0.0.0\";\n\n // Process children first (bottom-up)\n const childHashes: string[] = [];\n const children: { fieldName: string; hash: string }[] = [];\n\n for (const [libId, lib] of Object.entries(tpl.libs ?? {})) {\n const h = processLib(lib);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.libPrefix}/${libId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.software ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [swId, sw] of Object.entries(tpl.assets ?? {})) {\n const h = processSoftware(sw);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.softPrefix}/${swId}`, hash: h });\n }\n for (const [tplId, sub] of Object.entries(tpl.templates ?? {})) {\n const h = processTemplate(sub);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.tplPrefix}/${tplId}`, hash: h });\n }\n for (const [wasmId, wasm] of Object.entries(tpl.wasm ?? {})) {\n const h = processWasm(wasm);\n childHashes.push(h);\n children.push({ fieldName: `${PlTemplateV1.wasmPrefix}/${wasmId}`, hash: h });\n }\n\n // Compose hash from own content + child hash strings (NOT child content).\n // Uses sourceHash directly — it already uniquely identifies the source.\n const h = createHash(\"sha256\")\n .update(PlTemplateV1.type.name)\n .update(PlTemplateV1.type.version)\n .update(tpl.hashOverride ?? \"no-override\")\n .update(tpl.name)\n .update(version)\n .update(tpl.sourceHash);\n for (const child of children) {\n h.update(\"child:\" + child.fieldName + \":\" + child.hash);\n }\n const hash = h.digest(\"hex\");\n\n if (seen.has(hash)) return hash;\n seen.add(hash);\n nodes.push({\n hash,\n create: (tx, childRefs) => {\n const sourceCode = getSourceCode(tpl.name, sources, tpl.sourceHash);\n const tplRef = tx.createStruct(\n PlTemplateV1.type,\n JSON.stringify(PlTemplateV1.fromV3Data({ ...tpl, version }, sourceCode).data),\n );\n for (const child of children) {\n const fld = field(tplRef, child.fieldName);\n tx.createField(fld, \"Input\");\n tx.setField(fld, notEmpty(childRefs.get(child.hash), `missing child ref ${child.hash}`));\n }\n tx.lock(tplRef);\n\n if (!tpl.hashOverride) return tplRef;\n\n const overrideRef = tx.createStruct(\n PlTemplateOverrideV1.type,\n JSON.stringify(PlTemplateOverrideV1.fromV3Data(tpl)),\n );\n const overrideFld = PlTemplateOverrideV1.tplField(overrideRef);\n tx.createField(overrideFld, \"Service\");\n tx.setField(overrideFld, tplRef);\n tx.lock(overrideRef);\n return overrideRef;\n },\n childHashes,\n });\n\n return hash;\n }\n\n processTemplate(data.template);\n return nodes;\n}\n\n/** Flatten template tree into a topologically ordered list of cacheable nodes (leaves first). */\nexport function flattenTemplateTree(data: TemplateData | CompiledTemplateV3): CacheableNode[] {\n if (data.type === \"pl.tengo-template.v2\") {\n return flattenV2Tree(data);\n } else {\n return flattenV3Tree(data);\n }\n}\n\n/** In-memory cache for the TemplateCache SignedResourceId per PlClient instance. */\nconst cacheRidMap = new WeakMap<PlClient, SignedResourceId>();\n\n/** Clear the in-memory cacheRid entry (call on errors referencing the cache resource). */\nexport function invalidateTemplateCacheId(pl: PlClient): void {\n cacheRidMap.delete(pl);\n}\n\n/** Find or create the TemplateCache/1 resource on user root. */\nexport async function getOrCreateTemplateCache(pl: PlClient): Promise<SignedResourceId> {\n // Check in-memory cache first (0ms after first call)\n const cached = cacheRidMap.get(pl);\n if (cached !== undefined) return cached;\n\n // Try read-only check\n const existing = await pl.withReadTx(\"templateCache:check\", async (tx) => {\n const fd = await tx.getFieldIfExists(field(pl.clientRoot, TemplateCacheFieldName));\n return fd ? ensureSignedResourceIdNotNull(fd.value) : undefined;\n });\n if (existing) {\n cacheRidMap.set(pl, existing);\n return existing;\n }\n\n const result = await pl.withWriteTx(\"templateCache:init\", async (tx) => {\n // Double-check inside write tx (another instance may have created it)\n const fd = await tx.getFieldIfExists(field(pl.clientRoot, TemplateCacheFieldName));\n if (fd) return ensureSignedResourceIdNotNull(fd.value);\n\n const cache = tx.createStruct(TemplateCacheType);\n tx.createField(field(pl.clientRoot, TemplateCacheFieldName), \"Dynamic\", cache);\n tx.lock(cache);\n await tx.commit();\n return await cache.globalId;\n });\n cacheRidMap.set(pl, result);\n return result;\n}\n\n/** Remove the template cache from user root. */\nexport async function dropTemplateCache(pl: PlClient): Promise<void> {\n await pl.withWriteTx(\"templateCache:drop\", async (tx) => {\n const cacheField = field(pl.clientRoot, TemplateCacheFieldName);\n const fd = await tx.getFieldIfExists(cacheField);\n if (fd) {\n tx.removeField(cacheField);\n await tx.commit();\n }\n });\n invalidateTemplateCacheId(pl);\n}\n\n/**\n * Run count-based garbage collection on the template cache.\n * Evicts least-recently-used entries when the cache exceeds maxEntries.\n * Always resets the access counter to 0.\n *\n * @internal exported for testing (maxEntries parameter allows low thresholds in tests)\n * @returns true if entries were evicted\n */\nexport async function runGc(\n pl: PlClient,\n cacheRid: SignedResourceId,\n maxEntries: number = GC_MAX_ENTRIES,\n): Promise<boolean> {\n return await pl.withWriteTx(\"templateCache:gc\", async (tx) => {\n const kvs = await tx.listKeyValuesString(cacheRid);\n const entries: { hash: string; timestamp: number }[] = [];\n for (const { key, value } of kvs) {\n if (!key.startsWith(ACCESS_KEY_PREFIX)) continue;\n entries.push({\n hash: key.slice(ACCESS_KEY_PREFIX.length),\n timestamp: parseInt(value, 10),\n });\n }\n\n // Always reset counter\n tx.setKValue(cacheRid, ACCESS_COUNT_KEY, \"0\");\n\n if (entries.length <= maxEntries) {\n await tx.commit();\n return false;\n }\n\n // Sort oldest first, evict until under limit\n entries.sort((a, b) => a.timestamp - b.timestamp);\n const toEvict = entries.length - maxEntries;\n for (let i = 0; i < toEvict; i++) {\n tx.removeField(field(cacheRid, entries[i].hash));\n tx.deleteKValue(cacheRid, ACCESS_KEY_PREFIX + entries[i].hash);\n }\n\n await tx.commit();\n return true;\n });\n}\n\n/** Create a batch of cache nodes in the current transaction. */\nfunction createBatchNodes(\n tx: PlTransaction,\n cacheRid: SignedResourceId,\n batch: CacheableNode[],\n resolvedIds: ReadonlyMap<string, SignedResourceId>,\n newRefs: Map<string, ResourceRef>,\n now: string,\n): void {\n for (const node of batch) {\n const childRefs = new Map<string, AnyResourceRef>();\n for (const ch of node.childHashes) {\n const resolved = resolvedIds.get(ch) ?? newRefs.get(ch);\n if (resolved === undefined) {\n throw new Error(`BUG: child ${ch} not resolved`);\n }\n childRefs.set(ch, resolved);\n }\n const ref = node.create(tx, childRefs);\n newRefs.set(node.hash, ref);\n tx.createField(field(cacheRid, node.hash), \"Dynamic\", ref);\n tx.setKValue(cacheRid, ACCESS_KEY_PREFIX + node.hash, now);\n }\n}\n\n/**\n * Materialize a template tree via the cache using \"probe all + batched creation\".\n *\n * Phase 1 (single write tx):\n * - Check existence of ALL hashes in one roundtrip\n * - Happy path: if root cached, update access tracking and return\n * - Otherwise: fetch ResourceIds for all cache hits, create first batch of missing nodes\n *\n * Phase 2..N (one write tx per batch):\n * - Create remaining missing nodes in BATCH_SIZE chunks\n *\n * @returns root SignedResourceId and current access count (for GC decision)\n */\nasync function materialize(\n pl: PlClient,\n cacheRid: SignedResourceId,\n rootHash: string,\n nodes: CacheableNode[],\n stat: TemplateCacheStat,\n): Promise<{ rootId: SignedResourceId; accessCount: number }> {\n const allHashes = nodes.map((n) => n.hash);\n const resolvedIds = new Map<string, SignedResourceId>();\n\n // Phase 1: probe all + first batch\n const phase1 = await pl.withWriteTx(\"templateCache:materialize\", async (tx) => {\n // 1 roundtrip: check all hashes + read access count\n const [exists, countStr] = await Promise.all([\n Promise.all(allHashes.map((h) => tx.fieldExists(field(cacheRid, h)))),\n tx.getKValueStringIfExists(cacheRid, ACCESS_COUNT_KEY),\n ]);\n\n const prevCount = countStr ? parseInt(countStr, 10) : 0;\n const newCount = prevCount + 1;\n const now = Date.now().toString();\n const rootIdx = allHashes.length - 1;\n\n // Happy path: root already cached\n if (exists[rootIdx]) {\n const rootFd = await tx.getField(field(cacheRid, rootHash));\n const rootRid = ensureSignedResourceIdNotNull(rootFd.value);\n tx.setKValue(cacheRid, ACCESS_KEY_PREFIX + rootHash, now);\n tx.setKValue(cacheRid, ACCESS_COUNT_KEY, newCount.toString());\n await tx.commit();\n stat.happyPath = true;\n stat.cacheHits = stat.totalNodes;\n stat.batchCount = 1;\n return { done: true as const, rootId: rootRid, accessCount: newCount };\n }\n\n // Fetch ResourceIds for all cache hits (1 roundtrip)\n const hitIndices: number[] = [];\n for (let i = 0; i < allHashes.length; i++) {\n if (exists[i]) hitIndices.push(i);\n }\n\n if (hitIndices.length > 0) {\n const hitFields = await Promise.all(\n hitIndices.map((i) => tx.getField(field(cacheRid, allHashes[i]))),\n );\n for (let j = 0; j < hitIndices.length; j++) {\n resolvedIds.set(\n allHashes[hitIndices[j]],\n ensureSignedResourceIdNotNull(hitFields[j].value),\n );\n }\n }\n stat.cacheHits = hitIndices.length;\n\n // Missing nodes (topo order preserved from flatten)\n const missing = nodes.filter((n) => !resolvedIds.has(n.hash));\n stat.cacheMisses = missing.length;\n\n // Create first batch of missing nodes\n const firstBatch = missing.slice(0, BATCH_SIZE);\n const newRefs = new Map<string, ResourceRef>();\n createBatchNodes(tx, cacheRid, firstBatch, resolvedIds, newRefs, now);\n\n // Update access tracking for cache hits\n for (const i of hitIndices) {\n tx.setKValue(cacheRid, ACCESS_KEY_PREFIX + allHashes[i], now);\n }\n tx.setKValue(cacheRid, ACCESS_COUNT_KEY, newCount.toString());\n\n await tx.commit();\n\n // Resolve new refs to global IDs (after commit)\n for (const [hash, ref] of newRefs) {\n resolvedIds.set(hash, await toGlobalResourceId(ref));\n }\n\n return {\n done: false as const,\n remaining: missing.slice(BATCH_SIZE),\n accessCount: newCount,\n };\n });\n\n if (phase1.done) {\n return { rootId: phase1.rootId, accessCount: phase1.accessCount };\n }\n\n stat.batchCount = 1;\n\n // Phase 2+: remaining batches\n const { remaining } = phase1;\n for (let i = 0; i < remaining.length; i += BATCH_SIZE) {\n const batch = remaining.slice(i, i + BATCH_SIZE);\n stat.batchCount++;\n\n await pl.withWriteTx(\"templateCache:create\", async (tx) => {\n const newRefs = new Map<string, ResourceRef>();\n const now = Date.now().toString();\n createBatchNodes(tx, cacheRid, batch, resolvedIds, newRefs, now);\n await tx.commit();\n\n for (const [hash, ref] of newRefs) {\n resolvedIds.set(hash, await toGlobalResourceId(ref));\n }\n });\n }\n\n const rootId = resolvedIds.get(rootHash);\n if (!rootId) throw new Error(\"BUG: root hash not resolved after all batches\");\n return { rootId, accessCount: phase1.accessCount };\n}\n\n/**\n * Materialize a template tree via the cache.\n * Manages its own transactions internally — do NOT call inside an existing tx.\n *\n * @returns concrete SignedResourceId of the root template\n */\nexport async function loadTemplateCached(\n pl: PlClient,\n spec: TemplateSpecPrepared,\n options?: { cacheResourceId?: SignedResourceId },\n): Promise<SignedResourceId> {\n const stat = initialStat();\n const t0 = performance.now();\n\n try {\n // Parse to data if needed\n let tplData: TemplateData | CompiledTemplateV3;\n switch (spec.type) {\n case \"explicit\":\n tplData = parseTemplate(spec.content);\n break;\n case \"prepared\":\n tplData = spec.data;\n break;\n case \"cached\":\n return spec.resourceId;\n case \"from-registry\":\n throw new Error(\n \"loadTemplateCached does not support from-registry specs; use loadTemplate instead\",\n );\n default: {\n const _: never = spec;\n throw new Error(`unexpected spec type: ${(_ as any).type}`);\n }\n }\n\n stat.templateFormat = tplData.type;\n\n // Flatten to ordered nodes\n const tFlatten = performance.now();\n const nodes = flattenTemplateTree(tplData);\n stat.flattenMs = performance.now() - tFlatten;\n if (nodes.length === 0) throw new Error(\"template tree produced no nodes\");\n\n stat.totalNodes = nodes.length;\n const rootHash = nodes[nodes.length - 1].hash;\n\n // Resolve or create cache resource\n const tCacheInit = performance.now();\n const cacheRid = options?.cacheResourceId ?? (await getOrCreateTemplateCache(pl));\n stat.cacheInitMs = performance.now() - tCacheInit;\n\n // Retry loop: if a write tx fails (e.g. concurrent GC invalidated a cached resource),\n // restart materialization from scratch.\n const MAX_RETRIES = 3;\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n const tMat = performance.now();\n const result = await materialize(pl, cacheRid, rootHash, nodes, stat);\n stat.materializeMs = performance.now() - tMat;\n stat.retries = attempt;\n\n // GC in separate tx if access count exceeded threshold\n if (result.accessCount >= GC_ACCESS_THRESHOLD) {\n await runGc(pl, cacheRid);\n stat.gcTriggered = true;\n }\n\n return result.rootId;\n } catch (e) {\n if (attempt === MAX_RETRIES - 1) throw e;\n // Retry from scratch — previous batch results may reference GC'd resources\n stat.cacheHits = 0;\n stat.cacheMisses = 0;\n }\n }\n\n throw new Error(\"BUG: unreachable\");\n } finally {\n stat.totalMs = performance.now() - t0;\n if (getDebugFlags().logTemplateCacheStat) {\n console.log(`[templateCache] ${JSON.stringify(stat)}`);\n }\n }\n}\n\n/**\n * Pre-materialize a block pack's template via cache.\n * Returns a copy of the spec with the template replaced by a cached reference.\n * If the template is already cached, returns the spec unchanged.\n */\nexport async function cacheBlockPackTemplate(\n pl: PlClient,\n spec: BlockPackSpecPrepared,\n options?: { cacheResourceId?: SignedResourceId },\n): Promise<BlockPackSpecPrepared> {\n if (spec.template.type === \"cached\") return spec;\n\n const resourceId = await loadTemplateCached(pl, spec.template, options);\n return {\n ...spec,\n template: { type: \"cached\", resourceId },\n };\n}\n"],"mappings":"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"}
@@ -4,7 +4,7 @@ let node_fs = require("node:fs");
4
4
  node_fs = require_runtime.__toESM(node_fs, 1);
5
5
  let _milaboratories_ts_helpers = require("@milaboratories/ts-helpers");
6
6
  let _milaboratories_pl_client = require("@milaboratories/pl-client");
7
- //#region src/mutator/template/template_loading.ts
7
+ // src/mutator/template/template_loading.ts
8
8
  const TengoTemplateGet = {
9
9
  name: "TengoTemplateGet",
10
10
  version: "1"
@@ -53,7 +53,6 @@ function loadTemplate(tx, spec) {
53
53
  default: return (0, _milaboratories_ts_helpers.assertNever)(spec);
54
54
  }
55
55
  }
56
- //#endregion
57
56
  exports.TengoTemplateGet = TengoTemplateGet;
58
57
  exports.TengoTemplateGetRegistry = TengoTemplateGetRegistry;
59
58
  exports.TengoTemplateGetTemplate = TengoTemplateGetTemplate;
@@ -1 +1 @@
1
- {"version":3,"file":"template_loading.cjs","names":["fs","Pl","loadTemplateFromExplicitDirect","loadTemplateFromPrepared"],"sources":["../../../src/mutator/template/template_loading.ts"],"sourcesContent":["import type { AnyRef, PlTransaction, ResourceType } from \"@milaboratories/pl-client\";\nimport { field, Pl } from \"@milaboratories/pl-client\";\nimport fs from \"node:fs\";\nimport type {\n TemplateFromRegistry,\n TemplateSpecAny,\n TemplateSpecPrepared,\n} from \"../../model/template_spec\";\nimport { assertNever } from \"@milaboratories/ts-helpers\";\nimport { loadTemplateFromExplicitDirect, loadTemplateFromPrepared } from \"./direct_template_loader\";\n\n//\n// Resource schema\n//\n\nexport const TengoTemplateGet: ResourceType = { name: \"TengoTemplateGet\", version: \"1\" };\nexport const TengoTemplateGetRegistry = \"registry\";\nexport const TengoTemplateGetTemplateURI = \"templateURI\";\nexport const TengoTemplateGetTemplate = \"template\";\n\nexport const TengoTemplatePack: ResourceType = { name: \"TengoTemplatePack\", version: \"1\" };\nexport const TengoTemplatePackConvert: ResourceType = {\n name: \"TengoTemplatePackConvert\",\n version: \"1\",\n};\nexport const TengoTemplatePackConvertTemplatePack = \"templatePack\";\nexport const TengoTemplatePackConvertTemplate = \"template\";\n\nexport async function prepareTemplateSpec(tpl: TemplateSpecAny): Promise<TemplateSpecPrepared> {\n switch (tpl.type) {\n case \"from-file\":\n return {\n type: \"explicit\",\n content: await fs.promises.readFile(tpl.path),\n };\n case \"from-registry\":\n case \"explicit\":\n case \"cached\":\n return tpl;\n case \"prepared\":\n return tpl;\n default:\n return assertNever(tpl);\n }\n}\n\nfunction loadTemplateFromRegistry(tx: PlTransaction, spec: TemplateFromRegistry): AnyRef {\n const getTemplate = tx.createStruct(TengoTemplateGet);\n const registry = field(getTemplate, TengoTemplateGetRegistry);\n const uri = field(getTemplate, TengoTemplateGetTemplateURI);\n const templateFromRegistry = field(getTemplate, TengoTemplateGetTemplate);\n\n // Note: it has a resource schema, so platforma creates fields by itself.\n\n tx.setField(registry, tx.createValue(Pl.JsonString, Buffer.from(JSON.stringify(spec.registry))));\n tx.setField(uri, tx.createValue(Pl.JsonString, Buffer.from(JSON.stringify(spec.path))));\n\n return templateFromRegistry;\n}\n\nexport function loadTemplate(tx: PlTransaction, spec: TemplateSpecPrepared): AnyRef {\n switch (spec.type) {\n case \"from-registry\":\n return loadTemplateFromRegistry(tx, spec);\n case \"explicit\":\n return loadTemplateFromExplicitDirect(tx, spec);\n case \"prepared\":\n return loadTemplateFromPrepared(tx, spec);\n case \"cached\":\n return spec.resourceId;\n default:\n return assertNever(spec);\n }\n}\n"],"mappings":";;;;;;;AAeA,MAAa,mBAAiC;CAAE,MAAM;CAAoB,SAAS;AAAI;AACvF,MAAa,2BAA2B;AACxC,MAAa,8BAA8B;AAC3C,MAAa,2BAA2B;AAExC,MAAa,oBAAkC;CAAE,MAAM;CAAqB,SAAS;AAAI;AACzF,MAAa,2BAAyC;CACpD,MAAM;CACN,SAAS;AACX;AACA,MAAa,uCAAuC;AACpD,MAAa,mCAAmC;AAEhD,eAAsB,oBAAoB,KAAqD;CAC7F,QAAQ,IAAI,MAAZ;EACE,KAAK,aACH,OAAO;GACL,MAAM;GACN,SAAS,MAAMA,QAAAA,QAAG,SAAS,SAAS,IAAI,IAAI;EAC9C;EACF,KAAK;EACL,KAAK;EACL,KAAK,UACH,OAAO;EACT,KAAK,YACH,OAAO;EACT,SACE,QAAA,GAAA,2BAAA,YAAA,CAAmB,GAAG;CAC1B;AACF;AAEA,SAAS,yBAAyB,IAAmB,MAAoC;CACvF,MAAM,cAAc,GAAG,aAAa,gBAAgB;CACpD,MAAM,YAAA,GAAA,0BAAA,MAAA,CAAiB,aAAa,wBAAwB;CAC5D,MAAM,OAAA,GAAA,0BAAA,MAAA,CAAY,aAAa,2BAA2B;CAC1D,MAAM,wBAAA,GAAA,0BAAA,MAAA,CAA6B,aAAa,wBAAwB;CAIxE,GAAG,SAAS,UAAU,GAAG,YAAYC,0BAAAA,GAAG,YAAY,OAAO,KAAK,KAAK,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC;CAC/F,GAAG,SAAS,KAAK,GAAG,YAAYA,0BAAAA,GAAG,YAAY,OAAO,KAAK,KAAK,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC;CAEtF,OAAO;AACT;AAEA,SAAgB,aAAa,IAAmB,MAAoC;CAClF,QAAQ,KAAK,MAAb;EACE,KAAK,iBACH,OAAO,yBAAyB,IAAI,IAAI;EAC1C,KAAK,YACH,OAAOC,+BAAAA,+BAA+B,IAAI,IAAI;EAChD,KAAK,YACH,OAAOC,+BAAAA,yBAAyB,IAAI,IAAI;EAC1C,KAAK,UACH,OAAO,KAAK;EACd,SACE,QAAA,GAAA,2BAAA,YAAA,CAAmB,IAAI;CAC3B;AACF"}
1
+ {"version":3,"file":"template_loading.cjs","names":["fs","assertNever","field","Pl","loadTemplateFromExplicitDirect","loadTemplateFromPrepared"],"sources":["../../../src/mutator/template/template_loading.ts"],"sourcesContent":["import type { AnyRef, PlTransaction, ResourceType } from \"@milaboratories/pl-client\";\nimport { field, Pl } from \"@milaboratories/pl-client\";\nimport fs from \"node:fs\";\nimport type {\n TemplateFromRegistry,\n TemplateSpecAny,\n TemplateSpecPrepared,\n} from \"../../model/template_spec\";\nimport { assertNever } from \"@milaboratories/ts-helpers\";\nimport { loadTemplateFromExplicitDirect, loadTemplateFromPrepared } from \"./direct_template_loader\";\n\n//\n// Resource schema\n//\n\nexport const TengoTemplateGet: ResourceType = { name: \"TengoTemplateGet\", version: \"1\" };\nexport const TengoTemplateGetRegistry = \"registry\";\nexport const TengoTemplateGetTemplateURI = \"templateURI\";\nexport const TengoTemplateGetTemplate = \"template\";\n\nexport const TengoTemplatePack: ResourceType = { name: \"TengoTemplatePack\", version: \"1\" };\nexport const TengoTemplatePackConvert: ResourceType = {\n name: \"TengoTemplatePackConvert\",\n version: \"1\",\n};\nexport const TengoTemplatePackConvertTemplatePack = \"templatePack\";\nexport const TengoTemplatePackConvertTemplate = \"template\";\n\nexport async function prepareTemplateSpec(tpl: TemplateSpecAny): Promise<TemplateSpecPrepared> {\n switch (tpl.type) {\n case \"from-file\":\n return {\n type: \"explicit\",\n content: await fs.promises.readFile(tpl.path),\n };\n case \"from-registry\":\n case \"explicit\":\n case \"cached\":\n return tpl;\n case \"prepared\":\n return tpl;\n default:\n return assertNever(tpl);\n }\n}\n\nfunction loadTemplateFromRegistry(tx: PlTransaction, spec: TemplateFromRegistry): AnyRef {\n const getTemplate = tx.createStruct(TengoTemplateGet);\n const registry = field(getTemplate, TengoTemplateGetRegistry);\n const uri = field(getTemplate, TengoTemplateGetTemplateURI);\n const templateFromRegistry = field(getTemplate, TengoTemplateGetTemplate);\n\n // Note: it has a resource schema, so platforma creates fields by itself.\n\n tx.setField(registry, tx.createValue(Pl.JsonString, Buffer.from(JSON.stringify(spec.registry))));\n tx.setField(uri, tx.createValue(Pl.JsonString, Buffer.from(JSON.stringify(spec.path))));\n\n return templateFromRegistry;\n}\n\nexport function loadTemplate(tx: PlTransaction, spec: TemplateSpecPrepared): AnyRef {\n switch (spec.type) {\n case \"from-registry\":\n return loadTemplateFromRegistry(tx, spec);\n case \"explicit\":\n return loadTemplateFromExplicitDirect(tx, spec);\n case \"prepared\":\n return loadTemplateFromPrepared(tx, spec);\n case \"cached\":\n return spec.resourceId;\n default:\n return assertNever(spec);\n }\n}\n"],"mappings":";;;;;;;AAeA,MAAa,mBAAiC;CAAE,MAAM;CAAoB,SAAS;AAAI;AACvF,MAAa,2BAA2B;AACxC,MAAa,8BAA8B;AAC3C,MAAa,2BAA2B;AAExC,MAAa,oBAAkC;CAAE,MAAM;CAAqB,SAAS;AAAI;AACzF,MAAa,2BAAyC;CACpD,MAAM;CACN,SAAS;AACX;AACA,MAAa,uCAAuC;AACpD,MAAa,mCAAmC;AAEhD,eAAsB,oBAAoB,KAAqD;CAC7F,QAAQ,IAAI,MAAZ;EACE,KAAK,aACH,OAAO;GACL,MAAM;GACN,SAAS,MAAMA,QAAAA,QAAG,SAAS,SAAS,IAAI,IAAI;EAC9C;EACF,KAAK;EACL,KAAK;EACL,KAAK,UACH,OAAO;EACT,KAAK,YACH,OAAO;EACT,SACE,QAAA,GAAOC,2BAAAA,YAAAA,CAAY,GAAG;CAC1B;AACF;AAEA,SAAS,yBAAyB,IAAmB,MAAoC;CACvF,MAAM,cAAc,GAAG,aAAa,gBAAgB;CACpD,MAAM,YAAA,GAAWC,0BAAAA,MAAAA,CAAM,aAAa,wBAAwB;CAC5D,MAAM,OAAA,GAAMA,0BAAAA,MAAAA,CAAM,aAAa,2BAA2B;CAC1D,MAAM,wBAAA,GAAuBA,0BAAAA,MAAAA,CAAM,aAAa,wBAAwB;CAIxE,GAAG,SAAS,UAAU,GAAG,YAAYC,0BAAAA,GAAG,YAAY,OAAO,KAAK,KAAK,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC;CAC/F,GAAG,SAAS,KAAK,GAAG,YAAYA,0BAAAA,GAAG,YAAY,OAAO,KAAK,KAAK,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC;CAEtF,OAAO;AACT;AAEA,SAAgB,aAAa,IAAmB,MAAoC;CAClF,QAAQ,KAAK,MAAb;EACE,KAAK,iBACH,OAAO,yBAAyB,IAAI,IAAI;EAC1C,KAAK,YACH,OAAOC,+BAAAA,+BAA+B,IAAI,IAAI;EAChD,KAAK,YACH,OAAOC,+BAAAA,yBAAyB,IAAI,IAAI;EAC1C,KAAK,UACH,OAAO,KAAK;EACd,SACE,QAAA,GAAOJ,2BAAAA,YAAAA,CAAY,IAAI;CAC3B;AACF"}
@@ -1,6 +1,5 @@
1
1
  import { TemplateSpecAny, TemplateSpecPrepared } from "../../model/template_spec.js";
2
2
  import { AnyRef, PlTransaction, ResourceType } from "@milaboratories/pl-client";
3
- //#region src/mutator/template/template_loading.d.ts
4
3
  export declare const TengoTemplateGet: ResourceType;
5
4
  export declare const TengoTemplateGetRegistry = "registry";
6
5
  export declare const TengoTemplateGetTemplateURI = "templateURI";
@@ -11,5 +10,4 @@ export declare const TengoTemplatePackConvertTemplatePack = "templatePack";
11
10
  export declare const TengoTemplatePackConvertTemplate = "template";
12
11
  export declare function prepareTemplateSpec(tpl: TemplateSpecAny): Promise<TemplateSpecPrepared>;
13
12
  export declare function loadTemplate(tx: PlTransaction, spec: TemplateSpecPrepared): AnyRef;
14
- //#endregion
15
13
  //# sourceMappingURL=template_loading.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"template_loading.d.ts","names":[],"sources":["../../../src/mutator/template/template_loading.ts"],"mappings":";;;qBAea,kBAAkB;qBAClB;qBACA;qBACA;qBAEA,mBAAmB;qBACnB,0BAA0B;qBAI1B;qBACA;wBAES,oBAAoB,KAAK,kBAAkB,QAAQ;wBAgCzD,aAAa,IAAI,eAAe,MAAM,uBAAuB"}
1
+ {"version":3,"file":"template_loading.d.ts","names":[],"sources":["../../../src/mutator/template/template_loading.ts"],"mappings":";;qBAea,kBAAkB;qBAClB;qBACA;qBACA;qBAEA,mBAAmB;qBACnB,0BAA0B;qBAI1B;qBACA;wBAES,oBAAoB,KAAK,kBAAkB,QAAQ;wBAgCzD,aAAa,IAAI,eAAe,MAAM,uBAAuB"}
@@ -2,7 +2,7 @@ import { loadTemplateFromExplicitDirect, loadTemplateFromPrepared } from "./dire
2
2
  import fs from "node:fs";
3
3
  import { assertNever } from "@milaboratories/ts-helpers";
4
4
  import { Pl, field } from "@milaboratories/pl-client";
5
- //#region src/mutator/template/template_loading.ts
5
+ // src/mutator/template/template_loading.ts
6
6
  const TengoTemplateGet = {
7
7
  name: "TengoTemplateGet",
8
8
  version: "1"
@@ -51,7 +51,6 @@ function loadTemplate(tx, spec) {
51
51
  default: return assertNever(spec);
52
52
  }
53
53
  }
54
- //#endregion
55
54
  export { TengoTemplateGet, TengoTemplateGetRegistry, TengoTemplateGetTemplate, TengoTemplateGetTemplateURI, TengoTemplatePack, TengoTemplatePackConvert, TengoTemplatePackConvertTemplate, TengoTemplatePackConvertTemplatePack, loadTemplate, prepareTemplateSpec };
56
55
 
57
56
  //# sourceMappingURL=template_loading.js.map
@@ -3,7 +3,7 @@ const require_list = require("./list.cjs");
3
3
  let _milaboratories_pl_model_middle_layer = require("@milaboratories/pl-model-middle-layer");
4
4
  let _milaboratories_pl_client = require("@milaboratories/pl-client");
5
5
  let node_crypto = require("node:crypto");
6
- //#region src/mutator/template.ts
6
+ // src/mutator/template.ts
7
7
  /**
8
8
  * Creates one `UserTemplate` inside the given write transaction and attaches it to the
9
9
  * templates list under a freshly minted uuid field.
@@ -52,7 +52,6 @@ async function deleteTemplate(tx, listRid, id) {
52
52
  if (entry === void 0) throw require_list.notListedError("Template", id);
53
53
  tx.removeField((0, _milaboratories_pl_client.field)(listRid, entry.fieldName));
54
54
  }
55
- //#endregion
56
55
  exports.createTemplate = createTemplate;
57
56
  exports.deleteTemplate = deleteTemplate;
58
57
  exports.renameTemplate = renameTemplate;
@@ -1 +1 @@
1
- {"version":3,"file":"template.cjs","names":["TemplateResourceType","TemplateLabelKey","TemplateCreatedTimestamp","TemplateDescriptionKey","listedById","notListedError"],"sources":["../../src/mutator/template.ts"],"sourcesContent":["import type {\n AnyResourceRef,\n PlTransaction,\n ResourceRef,\n SignedResourceId,\n} from \"@milaboratories/pl-client\";\nimport { field } from \"@milaboratories/pl-client\";\nimport { normalizeDescription } from \"@milaboratories/pl-model-middle-layer\";\nimport { randomUUID } from \"node:crypto\";\nimport type { StoredTemplateData, TemplateId } from \"../middle_layer/template_list\";\nimport {\n TemplateCreatedTimestamp,\n TemplateDescriptionKey,\n TemplateLabelKey,\n TemplateResourceType,\n} from \"../middle_layer/template_list\";\nimport { listedById, notListedError } from \"./list\";\n\n/**\n * Creates one `UserTemplate` inside the given write transaction and attaches it to the\n * templates list under a freshly minted uuid field.\n *\n * Create and attach are the same transaction on purpose: an ephemeral resource nothing\n * holds is collectable, so the list field is what keeps the template alive.\n *\n * The document rides in the immutable `data` blob, set once here and never altered. The label,\n * the creation timestamp and the description live in KV beside it; the label and the description\n * may be written again later, the timestamp never is. A blank description stores nothing, the\n * same as {@link setTemplateDescription} does.\n *\n * @returns the new template resource; the caller reads its `globalId` after the commit.\n */\nexport function createTemplate(\n tx: PlTransaction,\n listRid: SignedResourceId,\n meta: { readonly label: string; readonly description?: string },\n data: StoredTemplateData,\n): ResourceRef {\n const tpl = tx.createEphemeral(TemplateResourceType, JSON.stringify(data));\n tx.lock(tpl);\n tx.setKValue(tpl, TemplateLabelKey, JSON.stringify(meta.label));\n tx.setKValue(tpl, TemplateCreatedTimestamp, String(Date.now()));\n const description = normalizeDescription(meta.description);\n if (description !== undefined)\n tx.setKValue(tpl, TemplateDescriptionKey, JSON.stringify(description));\n tx.createField(field(listRid, randomUUID()), \"Dynamic\", tpl);\n return tpl;\n}\n\n/** Renames a stored template. Touches the label KV entry and nothing else, so the stored\n * document stays byte-identical. */\nexport function renameTemplate(tx: PlTransaction, rid: SignedResourceId, label: string): void {\n tx.setKValue(rid, TemplateLabelKey, JSON.stringify(label));\n}\n\n/**\n * Sets what a stored template says about itself. Blank removes the entry rather than storing an\n * empty one, so a template that was never described and one whose description was cleared are\n * stored the same way.\n */\nexport function setTemplateDescription(\n tx: PlTransaction,\n rid: AnyResourceRef,\n description: string,\n): void {\n const wanted = normalizeDescription(description);\n if (wanted === undefined) tx.deleteKValue(rid, TemplateDescriptionKey);\n else tx.setKValue(rid, TemplateDescriptionKey, JSON.stringify(wanted));\n}\n\n/**\n * Detaches a template from the templates list, which is what destroys it — the list field is\n * the only thing holding the ephemeral resource.\n */\nexport async function deleteTemplate(\n tx: PlTransaction,\n listRid: SignedResourceId,\n id: TemplateId,\n): Promise<void> {\n const entry = (await listedById(tx, listRid)).get(id);\n if (entry === undefined) throw notListedError(\"Template\", id);\n tx.removeField(field(listRid, entry.fieldName));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAgCA,SAAgB,eACd,IACA,SACA,MACA,MACa;CACb,MAAM,MAAM,GAAG,gBAAgBA,sBAAAA,sBAAsB,KAAK,UAAU,IAAI,CAAC;CACzE,GAAG,KAAK,GAAG;CACX,GAAG,UAAU,KAAKC,sBAAAA,kBAAkB,KAAK,UAAU,KAAK,KAAK,CAAC;CAC9D,GAAG,UAAU,KAAKC,sBAAAA,0BAA0B,OAAO,KAAK,IAAI,CAAC,CAAC;CAC9D,MAAM,eAAA,GAAA,sCAAA,qBAAA,CAAmC,KAAK,WAAW;CACzD,IAAI,gBAAgB,KAAA,GAClB,GAAG,UAAU,KAAKC,sBAAAA,wBAAwB,KAAK,UAAU,WAAW,CAAC;CACvE,GAAG,aAAA,GAAA,0BAAA,MAAA,CAAkB,UAAA,GAAA,YAAA,WAAA,CAAoB,CAAC,GAAG,WAAW,GAAG;CAC3D,OAAO;AACT;;;AAIA,SAAgB,eAAe,IAAmB,KAAuB,OAAqB;CAC5F,GAAG,UAAU,KAAKF,sBAAAA,kBAAkB,KAAK,UAAU,KAAK,CAAC;AAC3D;;;;;;AAOA,SAAgB,uBACd,IACA,KACA,aACM;CACN,MAAM,UAAA,GAAA,sCAAA,qBAAA,CAA8B,WAAW;CAC/C,IAAI,WAAW,KAAA,GAAW,GAAG,aAAa,KAAKE,sBAAAA,sBAAsB;MAChE,GAAG,UAAU,KAAKA,sBAAAA,wBAAwB,KAAK,UAAU,MAAM,CAAC;AACvE;;;;;AAMA,eAAsB,eACpB,IACA,SACA,IACe;CACf,MAAM,SAAS,MAAMC,aAAAA,WAAW,IAAI,OAAO,EAAA,CAAG,IAAI,EAAE;CACpD,IAAI,UAAU,KAAA,GAAW,MAAMC,aAAAA,eAAe,YAAY,EAAE;CAC5D,GAAG,aAAA,GAAA,0BAAA,MAAA,CAAkB,SAAS,MAAM,SAAS,CAAC;AAChD"}
1
+ {"version":3,"file":"template.cjs","names":["TemplateResourceType","TemplateLabelKey","TemplateCreatedTimestamp","normalizeDescription","TemplateDescriptionKey","field","randomUUID","listedById","notListedError"],"sources":["../../src/mutator/template.ts"],"sourcesContent":["import type {\n AnyResourceRef,\n PlTransaction,\n ResourceRef,\n SignedResourceId,\n} from \"@milaboratories/pl-client\";\nimport { field } from \"@milaboratories/pl-client\";\nimport { normalizeDescription } from \"@milaboratories/pl-model-middle-layer\";\nimport { randomUUID } from \"node:crypto\";\nimport type { StoredTemplateData, TemplateId } from \"../middle_layer/template_list\";\nimport {\n TemplateCreatedTimestamp,\n TemplateDescriptionKey,\n TemplateLabelKey,\n TemplateResourceType,\n} from \"../middle_layer/template_list\";\nimport { listedById, notListedError } from \"./list\";\n\n/**\n * Creates one `UserTemplate` inside the given write transaction and attaches it to the\n * templates list under a freshly minted uuid field.\n *\n * Create and attach are the same transaction on purpose: an ephemeral resource nothing\n * holds is collectable, so the list field is what keeps the template alive.\n *\n * The document rides in the immutable `data` blob, set once here and never altered. The label,\n * the creation timestamp and the description live in KV beside it; the label and the description\n * may be written again later, the timestamp never is. A blank description stores nothing, the\n * same as {@link setTemplateDescription} does.\n *\n * @returns the new template resource; the caller reads its `globalId` after the commit.\n */\nexport function createTemplate(\n tx: PlTransaction,\n listRid: SignedResourceId,\n meta: { readonly label: string; readonly description?: string },\n data: StoredTemplateData,\n): ResourceRef {\n const tpl = tx.createEphemeral(TemplateResourceType, JSON.stringify(data));\n tx.lock(tpl);\n tx.setKValue(tpl, TemplateLabelKey, JSON.stringify(meta.label));\n tx.setKValue(tpl, TemplateCreatedTimestamp, String(Date.now()));\n const description = normalizeDescription(meta.description);\n if (description !== undefined)\n tx.setKValue(tpl, TemplateDescriptionKey, JSON.stringify(description));\n tx.createField(field(listRid, randomUUID()), \"Dynamic\", tpl);\n return tpl;\n}\n\n/** Renames a stored template. Touches the label KV entry and nothing else, so the stored\n * document stays byte-identical. */\nexport function renameTemplate(tx: PlTransaction, rid: SignedResourceId, label: string): void {\n tx.setKValue(rid, TemplateLabelKey, JSON.stringify(label));\n}\n\n/**\n * Sets what a stored template says about itself. Blank removes the entry rather than storing an\n * empty one, so a template that was never described and one whose description was cleared are\n * stored the same way.\n */\nexport function setTemplateDescription(\n tx: PlTransaction,\n rid: AnyResourceRef,\n description: string,\n): void {\n const wanted = normalizeDescription(description);\n if (wanted === undefined) tx.deleteKValue(rid, TemplateDescriptionKey);\n else tx.setKValue(rid, TemplateDescriptionKey, JSON.stringify(wanted));\n}\n\n/**\n * Detaches a template from the templates list, which is what destroys it — the list field is\n * the only thing holding the ephemeral resource.\n */\nexport async function deleteTemplate(\n tx: PlTransaction,\n listRid: SignedResourceId,\n id: TemplateId,\n): Promise<void> {\n const entry = (await listedById(tx, listRid)).get(id);\n if (entry === undefined) throw notListedError(\"Template\", id);\n tx.removeField(field(listRid, entry.fieldName));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAgCA,SAAgB,eACd,IACA,SACA,MACA,MACa;CACb,MAAM,MAAM,GAAG,gBAAgBA,sBAAAA,sBAAsB,KAAK,UAAU,IAAI,CAAC;CACzE,GAAG,KAAK,GAAG;CACX,GAAG,UAAU,KAAKC,sBAAAA,kBAAkB,KAAK,UAAU,KAAK,KAAK,CAAC;CAC9D,GAAG,UAAU,KAAKC,sBAAAA,0BAA0B,OAAO,KAAK,IAAI,CAAC,CAAC;CAC9D,MAAM,eAAA,GAAcC,sCAAAA,qBAAAA,CAAqB,KAAK,WAAW;CACzD,IAAI,gBAAgB,KAAA,GAClB,GAAG,UAAU,KAAKC,sBAAAA,wBAAwB,KAAK,UAAU,WAAW,CAAC;CACvE,GAAG,aAAA,GAAYC,0BAAAA,MAAAA,CAAM,UAAA,GAASC,YAAAA,WAAAA,CAAW,CAAC,GAAG,WAAW,GAAG;CAC3D,OAAO;AACT;;;AAIA,SAAgB,eAAe,IAAmB,KAAuB,OAAqB;CAC5F,GAAG,UAAU,KAAKL,sBAAAA,kBAAkB,KAAK,UAAU,KAAK,CAAC;AAC3D;;;;;;AAOA,SAAgB,uBACd,IACA,KACA,aACM;CACN,MAAM,UAAA,GAASE,sCAAAA,qBAAAA,CAAqB,WAAW;CAC/C,IAAI,WAAW,KAAA,GAAW,GAAG,aAAa,KAAKC,sBAAAA,sBAAsB;MAChE,GAAG,UAAU,KAAKA,sBAAAA,wBAAwB,KAAK,UAAU,MAAM,CAAC;AACvE;;;;;AAMA,eAAsB,eACpB,IACA,SACA,IACe;CACf,MAAM,SAAS,MAAMG,aAAAA,WAAW,IAAI,OAAO,EAAA,CAAG,IAAI,EAAE;CACpD,IAAI,UAAU,KAAA,GAAW,MAAMC,aAAAA,eAAe,YAAY,EAAE;CAC5D,GAAG,aAAA,GAAYH,0BAAAA,MAAAA,CAAM,SAAS,MAAM,SAAS,CAAC;AAChD"}
@@ -3,7 +3,7 @@ import { listedById, notListedError } from "./list.js";
3
3
  import { normalizeDescription } from "@milaboratories/pl-model-middle-layer";
4
4
  import { field } from "@milaboratories/pl-client";
5
5
  import { randomUUID } from "node:crypto";
6
- //#region src/mutator/template.ts
6
+ // src/mutator/template.ts
7
7
  /**
8
8
  * Creates one `UserTemplate` inside the given write transaction and attaches it to the
9
9
  * templates list under a freshly minted uuid field.
@@ -52,7 +52,6 @@ async function deleteTemplate(tx, listRid, id) {
52
52
  if (entry === void 0) throw notListedError("Template", id);
53
53
  tx.removeField(field(listRid, entry.fieldName));
54
54
  }
55
- //#endregion
56
55
  export { createTemplate, deleteTemplate, renameTemplate, setTemplateDescription };
57
56
 
58
57
  //# sourceMappingURL=template.js.map