@aglyn/aglyn 1.0.0-beta.218 → 1.0.0-beta.220

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 (455) hide show
  1. package/package.json +12 -12
  2. package/src/lib/app-utils/actions.d.ts +26 -433
  3. package/src/lib/app-utils/actions.js +108 -633
  4. package/src/lib/app-utils/actions.js.map +1 -1
  5. package/src/lib/app-utils/activity-presenter.d.ts +3 -3
  6. package/src/lib/app-utils/activity-presenter.js +36 -52
  7. package/src/lib/app-utils/activity-presenter.js.map +1 -1
  8. package/src/lib/app-utils/analytics-events.d.ts +1 -1
  9. package/src/lib/app-utils/analytics-events.js.map +1 -1
  10. package/src/lib/app-utils/analytics-provider.d.ts +182 -0
  11. package/src/lib/app-utils/analytics-provider.js +133 -0
  12. package/src/lib/app-utils/analytics-provider.js.map +1 -0
  13. package/src/lib/app-utils/api-plugins.d.ts +46 -0
  14. package/src/lib/app-utils/api-plugins.js +19 -0
  15. package/src/lib/app-utils/api-plugins.js.map +1 -1
  16. package/src/lib/app-utils/{marketplace-overrides.d.ts → artifact-overrides.d.ts} +9 -6
  17. package/src/lib/app-utils/{marketplace-overrides.js → artifact-overrides.js} +10 -7
  18. package/src/lib/app-utils/artifact-overrides.js.map +1 -0
  19. package/src/lib/app-utils/{marketplace-provenance.d.ts → artifact-provenance.d.ts} +12 -10
  20. package/src/lib/app-utils/{marketplace-provenance.js → artifact-provenance.js} +9 -7
  21. package/src/lib/app-utils/artifact-provenance.js.map +1 -0
  22. package/src/lib/app-utils/binding-token-catalog.d.ts +5 -13
  23. package/src/lib/app-utils/binding-token-catalog.js +17 -41
  24. package/src/lib/app-utils/binding-token-catalog.js.map +1 -1
  25. package/src/lib/app-utils/brand-support-line.d.ts +36 -0
  26. package/src/lib/app-utils/brand-support-line.js +38 -0
  27. package/src/lib/app-utils/brand-support-line.js.map +1 -0
  28. package/src/lib/app-utils/collection-entries.d.ts +2 -2
  29. package/src/lib/app-utils/collection-entries.js.map +1 -1
  30. package/src/lib/app-utils/consent-group-change.d.ts +4 -0
  31. package/src/lib/app-utils/consent-group-change.js.map +1 -1
  32. package/src/lib/app-utils/consent-groups.d.ts +1 -1
  33. package/src/lib/app-utils/consent-groups.js.map +1 -1
  34. package/src/lib/app-utils/console-routes.d.ts +15 -42
  35. package/src/lib/app-utils/console-routes.js +10 -39
  36. package/src/lib/app-utils/console-routes.js.map +1 -1
  37. package/src/lib/app-utils/contacts.d.ts +24 -2
  38. package/src/lib/app-utils/contacts.js +21 -5
  39. package/src/lib/app-utils/contacts.js.map +1 -1
  40. package/src/lib/app-utils/container-membership.d.ts +93 -0
  41. package/src/lib/app-utils/container-membership.js +165 -0
  42. package/src/lib/app-utils/container-membership.js.map +1 -0
  43. package/src/lib/app-utils/crm-task-reminders.d.ts +23 -6
  44. package/src/lib/app-utils/crm-task-reminders.js +32 -11
  45. package/src/lib/app-utils/crm-task-reminders.js.map +1 -1
  46. package/src/lib/app-utils/crm.d.ts +24 -4
  47. package/src/lib/app-utils/crm.js +23 -0
  48. package/src/lib/app-utils/crm.js.map +1 -1
  49. package/src/lib/app-utils/cross-pool-desync.d.ts +39 -0
  50. package/src/lib/app-utils/cross-pool-desync.js +47 -0
  51. package/src/lib/app-utils/cross-pool-desync.js.map +1 -0
  52. package/src/lib/app-utils/csv-upload.d.ts +29 -0
  53. package/src/lib/app-utils/csv-upload.js +29 -0
  54. package/src/lib/app-utils/csv-upload.js.map +1 -0
  55. package/src/lib/app-utils/{dataset-csv.d.ts → csv.d.ts} +10 -43
  56. package/src/lib/app-utils/{dataset-csv.js → csv.js} +10 -81
  57. package/src/lib/app-utils/csv.js.map +1 -0
  58. package/src/lib/app-utils/dataset-models.d.ts +5 -5
  59. package/src/lib/app-utils/dataset-models.js +19 -2
  60. package/src/lib/app-utils/dataset-models.js.map +1 -1
  61. package/src/lib/app-utils/datasets.d.ts +65 -30
  62. package/src/lib/app-utils/datasets.js +74 -24
  63. package/src/lib/app-utils/datasets.js.map +1 -1
  64. package/src/lib/app-utils/docs-deflection.d.ts +6 -6
  65. package/src/lib/app-utils/docs-deflection.js.map +1 -1
  66. package/src/lib/app-utils/docs-help.generated.d.ts +14 -8
  67. package/src/lib/app-utils/docs-help.generated.js +23 -6
  68. package/src/lib/app-utils/docs-help.generated.js.map +1 -1
  69. package/src/lib/app-utils/docs-index.generated.d.ts +2 -2
  70. package/src/lib/app-utils/docs-index.generated.js +570 -346
  71. package/src/lib/app-utils/docs-index.generated.js.map +1 -1
  72. package/src/lib/app-utils/docs-retrieval.d.ts +3 -3
  73. package/src/lib/app-utils/docs-retrieval.js +14 -10
  74. package/src/lib/app-utils/docs-retrieval.js.map +1 -1
  75. package/src/lib/app-utils/duplicate-resource.d.ts +4 -1
  76. package/src/lib/app-utils/duplicate-resource.js +7 -4
  77. package/src/lib/app-utils/duplicate-resource.js.map +1 -1
  78. package/src/lib/app-utils/dynamic-list-rule.d.ts +1 -1
  79. package/src/lib/app-utils/dynamic-list-rule.js +3 -3
  80. package/src/lib/app-utils/dynamic-list-rule.js.map +1 -1
  81. package/src/lib/app-utils/element-ui.d.ts +1 -1
  82. package/src/lib/app-utils/element-ui.js +1 -1
  83. package/src/lib/app-utils/element-ui.js.map +1 -1
  84. package/src/lib/app-utils/email-starter-policy.js +3 -3
  85. package/src/lib/app-utils/email-starter-policy.js.map +1 -1
  86. package/src/lib/app-utils/email-text.d.ts +80 -0
  87. package/src/lib/app-utils/email-text.js +189 -0
  88. package/src/lib/app-utils/email-text.js.map +1 -0
  89. package/src/lib/app-utils/{list-assignment-policy.d.ts → enrollment-basis.d.ts} +4 -0
  90. package/src/lib/app-utils/{list-assignment-policy.js → enrollment-basis.js} +5 -1
  91. package/src/lib/app-utils/enrollment-basis.js.map +1 -0
  92. package/src/lib/app-utils/entity-picker-context.d.ts +10 -5
  93. package/src/lib/app-utils/entity-picker-context.js.map +1 -1
  94. package/src/lib/app-utils/error-beacon.d.ts +75 -6
  95. package/src/lib/app-utils/error-beacon.js +160 -21
  96. package/src/lib/app-utils/error-beacon.js.map +1 -1
  97. package/src/lib/app-utils/expand-repeatables.d.ts +10 -10
  98. package/src/lib/app-utils/expand-repeatables.js +14 -14
  99. package/src/lib/app-utils/expand-repeatables.js.map +1 -1
  100. package/src/lib/app-utils/forms.js +2 -2
  101. package/src/lib/app-utils/forms.js.map +1 -1
  102. package/src/lib/app-utils/health-report.d.ts +2 -3
  103. package/src/lib/app-utils/health-report.js +8 -6
  104. package/src/lib/app-utils/health-report.js.map +1 -1
  105. package/src/lib/app-utils/host-events.d.ts +82 -0
  106. package/src/lib/app-utils/host-events.js +62 -0
  107. package/src/lib/app-utils/host-events.js.map +1 -0
  108. package/src/lib/app-utils/inbound-mail-domain.d.ts +27 -0
  109. package/src/lib/app-utils/inbound-mail-domain.js +31 -0
  110. package/src/lib/app-utils/inbound-mail-domain.js.map +1 -0
  111. package/src/lib/app-utils/lockdown.d.ts +11 -0
  112. package/src/lib/app-utils/lockdown.js +33 -3
  113. package/src/lib/app-utils/lockdown.js.map +1 -1
  114. package/src/lib/app-utils/margin-utilization.d.ts +4 -69
  115. package/src/lib/app-utils/margin-utilization.js +82 -69
  116. package/src/lib/app-utils/margin-utilization.js.map +1 -1
  117. package/src/lib/app-utils/member-email-aliases.d.ts +25 -0
  118. package/src/lib/app-utils/member-email-aliases.js +29 -0
  119. package/src/lib/app-utils/member-email-aliases.js.map +1 -1
  120. package/src/lib/app-utils/node-definition-sanitizer.d.ts +16 -16
  121. package/src/lib/app-utils/node-definition-sanitizer.js +24 -20
  122. package/src/lib/app-utils/node-definition-sanitizer.js.map +1 -1
  123. package/src/lib/app-utils/node-interactions.d.ts +7 -7
  124. package/src/lib/app-utils/node-interactions.js.map +1 -1
  125. package/src/lib/app-utils/notifications.d.ts +147 -47
  126. package/src/lib/app-utils/notifications.js +182 -44
  127. package/src/lib/app-utils/notifications.js.map +1 -1
  128. package/src/lib/app-utils/operator-alerts.d.ts +15 -1
  129. package/src/lib/app-utils/operator-alerts.js +47 -10
  130. package/src/lib/app-utils/operator-alerts.js.map +1 -1
  131. package/src/lib/app-utils/payments-configured.d.ts +8 -21
  132. package/src/lib/app-utils/payments-configured.js +8 -23
  133. package/src/lib/app-utils/payments-configured.js.map +1 -1
  134. package/src/lib/app-utils/plan-entitlements.d.ts +207 -306
  135. package/src/lib/app-utils/plan-entitlements.js +345 -528
  136. package/src/lib/app-utils/plan-entitlements.js.map +1 -1
  137. package/src/lib/app-utils/platform-brand.d.ts +10 -0
  138. package/src/lib/app-utils/platform-brand.js +14 -3
  139. package/src/lib/app-utils/platform-brand.js.map +1 -1
  140. package/src/lib/app-utils/platform-marketing-consent.d.ts +56 -2
  141. package/src/lib/app-utils/platform-marketing-consent.js +6 -5
  142. package/src/lib/app-utils/platform-marketing-consent.js.map +1 -1
  143. package/src/lib/app-utils/plugin-api-rate-limit.d.ts +7 -1
  144. package/src/lib/app-utils/plugin-api-rate-limit.js +11 -3
  145. package/src/lib/app-utils/plugin-api-rate-limit.js.map +1 -1
  146. package/src/lib/app-utils/plugin-bundle-checks.js +2 -2
  147. package/src/lib/app-utils/plugin-bundle-checks.js.map +1 -1
  148. package/src/lib/app-utils/plugin-host-events.generated.d.ts +12 -0
  149. package/src/lib/app-utils/plugin-host-events.generated.js +169 -0
  150. package/src/lib/app-utils/plugin-host-events.generated.js.map +1 -0
  151. package/src/lib/app-utils/plugin-release-flags.generated.d.ts +12 -0
  152. package/src/lib/app-utils/plugin-release-flags.generated.js +106 -0
  153. package/src/lib/app-utils/plugin-release-flags.generated.js.map +1 -0
  154. package/src/lib/app-utils/plugin-starter-templates.generated.d.ts +12 -0
  155. package/src/lib/app-utils/plugin-starter-templates.generated.js +711 -0
  156. package/src/lib/app-utils/plugin-starter-templates.generated.js.map +1 -0
  157. package/src/lib/app-utils/realm-host-surface.generated.js +2 -0
  158. package/src/lib/app-utils/realm-host-surface.generated.js.map +1 -1
  159. package/src/lib/app-utils/release-flags.d.ts +14 -5
  160. package/src/lib/app-utils/release-flags.js +21 -125
  161. package/src/lib/app-utils/release-flags.js.map +1 -1
  162. package/src/lib/app-utils/repeat-query.d.ts +56 -0
  163. package/src/lib/app-utils/{dataset-query.js → repeat-query.js} +16 -16
  164. package/src/lib/app-utils/repeat-query.js.map +1 -0
  165. package/src/lib/app-utils/repeat-sources.d.ts +9 -0
  166. package/src/lib/app-utils/repeat-sources.js.map +1 -1
  167. package/src/lib/app-utils/retained-refusals.d.ts +73 -0
  168. package/src/lib/app-utils/retained-refusals.js +186 -0
  169. package/src/lib/app-utils/retained-refusals.js.map +1 -0
  170. package/src/lib/app-utils/scope-tokens.d.ts +27 -0
  171. package/src/lib/app-utils/scope-tokens.js +61 -0
  172. package/src/lib/app-utils/scope-tokens.js.map +1 -1
  173. package/src/lib/app-utils/screen-link-context.js +3 -3
  174. package/src/lib/app-utils/screen-link-context.js.map +1 -1
  175. package/src/lib/app-utils/screen-route.js +1 -1
  176. package/src/lib/app-utils/screen-route.js.map +1 -1
  177. package/src/lib/app-utils/seo-audit.d.ts +132 -0
  178. package/src/lib/app-utils/seo-audit.js +246 -0
  179. package/src/lib/app-utils/seo-audit.js.map +1 -0
  180. package/src/lib/app-utils/seo-keywords.d.ts +48 -0
  181. package/src/lib/app-utils/seo-keywords.js +60 -0
  182. package/src/lib/app-utils/seo-keywords.js.map +1 -0
  183. package/src/lib/app-utils/seo-page-facts.d.ts +66 -0
  184. package/src/lib/app-utils/seo-page-facts.js +155 -0
  185. package/src/lib/app-utils/seo-page-facts.js.map +1 -0
  186. package/src/lib/app-utils/seo-site-scan.d.ts +126 -0
  187. package/src/lib/app-utils/seo-site-scan.js +162 -0
  188. package/src/lib/app-utils/seo-site-scan.js.map +1 -0
  189. package/src/lib/app-utils/seo-title-variables.js +1 -1
  190. package/src/lib/app-utils/seo-title-variables.js.map +1 -1
  191. package/src/lib/app-utils/server.d.ts +13 -18
  192. package/src/lib/app-utils/server.js +33 -51
  193. package/src/lib/app-utils/server.js.map +1 -1
  194. package/src/lib/app-utils/site-interactions.d.ts +501 -0
  195. package/src/lib/app-utils/site-interactions.js +554 -0
  196. package/src/lib/app-utils/site-interactions.js.map +1 -0
  197. package/src/lib/app-utils/{marketplace-theme.d.ts → site-theme.d.ts} +13 -2
  198. package/src/lib/app-utils/{marketplace-theme.js → site-theme.js} +2 -2
  199. package/src/lib/app-utils/site-theme.js.map +1 -0
  200. package/src/lib/app-utils/sitemap.d.ts +4 -3
  201. package/src/lib/app-utils/sitemap.js +9 -7
  202. package/src/lib/app-utils/sitemap.js.map +1 -1
  203. package/src/lib/app-utils/stale-build-error.d.ts +51 -0
  204. package/src/lib/app-utils/stale-build-error.js +100 -1
  205. package/src/lib/app-utils/stale-build-error.js.map +1 -1
  206. package/src/lib/app-utils/starter-template-nodes.d.ts +137 -0
  207. package/src/lib/app-utils/starter-template-nodes.js +129 -0
  208. package/src/lib/app-utils/starter-template-nodes.js.map +1 -0
  209. package/src/lib/app-utils/starter-templates.d.ts +11 -34
  210. package/src/lib/app-utils/starter-templates.js +19 -230
  211. package/src/lib/app-utils/starter-templates.js.map +1 -1
  212. package/src/lib/app-utils/{email-topics.d.ts → subscription-topics.d.ts} +64 -48
  213. package/src/lib/app-utils/{email-topics.js → subscription-topics.js} +39 -109
  214. package/src/lib/app-utils/subscription-topics.js.map +1 -0
  215. package/src/lib/app-utils/tax-jurisdiction-figures.d.ts +118 -0
  216. package/src/lib/app-utils/tax-jurisdiction-figures.js +123 -0
  217. package/src/lib/app-utils/tax-jurisdiction-figures.js.map +1 -0
  218. package/src/lib/app-utils/theme-library.d.ts +10 -3
  219. package/src/lib/app-utils/theme-library.js +13 -4
  220. package/src/lib/app-utils/theme-library.js.map +1 -1
  221. package/src/lib/app-utils/usage-budget.d.ts +73 -188
  222. package/src/lib/app-utils/usage-budget.js +58 -194
  223. package/src/lib/app-utils/usage-budget.js.map +1 -1
  224. package/src/lib/app-utils/{campaign-attribution.d.ts → utm-attribution.d.ts} +11 -6
  225. package/src/lib/app-utils/{campaign-attribution.js → utm-attribution.js} +13 -8
  226. package/src/lib/app-utils/utm-attribution.js.map +1 -0
  227. package/src/lib/app-utils/{campaign-forwarding.d.ts → utm-forwarding.d.ts} +14 -14
  228. package/src/lib/app-utils/{campaign-forwarding.js → utm-forwarding.js} +26 -26
  229. package/src/lib/app-utils/utm-forwarding.js.map +1 -0
  230. package/src/lib/app-utils/{campaign-touch.d.ts → utm-touch.d.ts} +25 -17
  231. package/src/lib/app-utils/{campaign-touch.js → utm-touch.js} +38 -30
  232. package/src/lib/app-utils/utm-touch.js.map +1 -0
  233. package/src/lib/app-utils/variables.d.ts +9 -9
  234. package/src/lib/app-utils/variables.js.map +1 -1
  235. package/src/lib/app-utils/video-object.js +6 -5
  236. package/src/lib/app-utils/video-object.js.map +1 -1
  237. package/src/lib/app-utils/visitor-consent.d.ts +41 -164
  238. package/src/lib/app-utils/visitor-consent.js +66 -277
  239. package/src/lib/app-utils/visitor-consent.js.map +1 -1
  240. package/src/lib/app-utils/visitor-record-ceiling.d.ts +32 -0
  241. package/src/lib/app-utils/visitor-record-ceiling.js +39 -0
  242. package/src/lib/app-utils/visitor-record-ceiling.js.map +1 -1
  243. package/src/lib/app-utils/web-vitals-rum.d.ts +7 -7
  244. package/src/lib/app-utils/web-vitals-rum.js +31 -63
  245. package/src/lib/app-utils/web-vitals-rum.js.map +1 -1
  246. package/src/lib/app-utils/where-used.d.ts +11 -6
  247. package/src/lib/app-utils/where-used.js +3 -8
  248. package/src/lib/app-utils/where-used.js.map +1 -1
  249. package/src/lib/foundation/definitions/components.types.d.ts +1 -1
  250. package/src/lib/foundation/definitions/components.types.js +1 -1
  251. package/src/lib/foundation/definitions/components.types.js.map +1 -1
  252. package/src/lib/foundation/definitions/org-billing.types.d.ts +11 -137
  253. package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
  254. package/src/lib/foundation/definitions/organization.types.d.ts +1 -3
  255. package/src/lib/foundation/definitions/organization.types.js.map +1 -1
  256. package/src/lib/foundation/definitions/platform.types.d.ts +11 -5
  257. package/src/lib/foundation/definitions/platform.types.js.map +1 -1
  258. package/src/lib/foundation/definitions/write-deny-coverage.util.d.ts +16 -0
  259. package/src/lib/foundation/definitions/write-deny-coverage.util.js +20 -0
  260. package/src/lib/foundation/definitions/write-deny-coverage.util.js.map +1 -1
  261. package/src/lib/foundation/index.d.ts +1 -1
  262. package/src/lib/foundation/index.js.map +1 -1
  263. package/src/lib/plugin-manager/besigner-documents.d.ts +96 -0
  264. package/src/lib/plugin-manager/besigner-documents.js +61 -0
  265. package/src/lib/plugin-manager/besigner-documents.js.map +1 -0
  266. package/src/lib/plugin-manager/computed-variables.d.ts +71 -0
  267. package/src/lib/plugin-manager/computed-variables.js +74 -0
  268. package/src/lib/plugin-manager/computed-variables.js.map +1 -0
  269. package/src/lib/plugin-manager/custom-fields.d.ts +29 -2
  270. package/src/lib/plugin-manager/custom-fields.js +47 -1
  271. package/src/lib/plugin-manager/custom-fields.js.map +1 -1
  272. package/src/lib/plugin-manager/feature-plugins.d.ts +372 -99
  273. package/src/lib/plugin-manager/feature-plugins.js +126 -51
  274. package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
  275. package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +134 -0
  276. package/src/lib/plugin-manager/first-party-plugins.generated.js +840 -10
  277. package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
  278. package/src/lib/plugin-manager/index.d.ts +0 -1
  279. package/src/lib/plugin-manager/index.js +0 -1
  280. package/src/lib/plugin-manager/index.js.map +1 -1
  281. package/src/lib/plugin-manager/plugin-activity-actions.d.ts +12 -0
  282. package/src/lib/plugin-manager/plugin-activity-actions.js +25 -0
  283. package/src/lib/plugin-manager/plugin-activity-actions.js.map +1 -1
  284. package/src/lib/plugin-manager/plugin-contact-capture.d.ts +9 -4
  285. package/src/lib/plugin-manager/plugin-contact-capture.js.map +1 -1
  286. package/src/lib/plugin-manager/plugin-containers.d.ts +68 -0
  287. package/src/lib/plugin-manager/plugin-containers.generated.d.ts +10 -0
  288. package/src/lib/plugin-manager/plugin-containers.generated.js +20 -0
  289. package/src/lib/plugin-manager/plugin-containers.generated.js.map +1 -0
  290. package/src/lib/plugin-manager/plugin-containers.js +27 -0
  291. package/src/lib/plugin-manager/plugin-containers.js.map +1 -0
  292. package/src/lib/plugin-manager/plugin-contributions.d.ts +1 -1
  293. package/src/lib/plugin-manager/plugin-contributions.js.map +1 -1
  294. package/src/lib/plugin-manager/plugin-declarations-repair.d.ts +36 -0
  295. package/src/lib/plugin-manager/plugin-declarations-repair.js +64 -0
  296. package/src/lib/plugin-manager/plugin-declarations-repair.js.map +1 -0
  297. package/src/lib/plugin-manager/plugin-dependents.d.ts +101 -0
  298. package/src/lib/plugin-manager/plugin-dependents.js +75 -0
  299. package/src/lib/plugin-manager/plugin-dependents.js.map +1 -0
  300. package/src/lib/plugin-manager/plugin-distribution.d.ts +55 -0
  301. package/src/lib/plugin-manager/plugin-distribution.js +45 -0
  302. package/src/lib/plugin-manager/plugin-distribution.js.map +1 -0
  303. package/src/lib/plugin-manager/plugin-entitlements.d.ts +8 -0
  304. package/src/lib/plugin-manager/plugin-entitlements.js.map +1 -1
  305. package/src/lib/plugin-manager/plugin-host-collections.d.ts +17 -0
  306. package/src/lib/plugin-manager/plugin-host-collections.js +6 -0
  307. package/src/lib/plugin-manager/plugin-host-collections.js.map +1 -1
  308. package/src/lib/plugin-manager/plugin-host-resources.d.ts +133 -0
  309. package/src/lib/plugin-manager/plugin-host-resources.js +52 -0
  310. package/src/lib/plugin-manager/plugin-host-resources.js.map +1 -0
  311. package/src/lib/plugin-manager/plugin-membership-detach.js +1 -1
  312. package/src/lib/plugin-manager/plugin-membership-detach.js.map +1 -1
  313. package/src/lib/plugin-manager/plugin-org-erasure.d.ts +28 -2
  314. package/src/lib/plugin-manager/plugin-org-erasure.js +61 -2
  315. package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -1
  316. package/src/lib/plugin-manager/plugin-plan-entitlements.d.ts +123 -0
  317. package/src/lib/plugin-manager/plugin-plan-entitlements.js +101 -0
  318. package/src/lib/plugin-manager/plugin-plan-entitlements.js.map +1 -0
  319. package/src/lib/plugin-manager/plugin-record-email-state.d.ts +69 -0
  320. package/src/lib/plugin-manager/plugin-record-email-state.js +32 -0
  321. package/src/lib/plugin-manager/plugin-record-email-state.js.map +1 -1
  322. package/src/lib/plugin-manager/plugin-record-index.d.ts +95 -0
  323. package/src/lib/plugin-manager/plugin-record-index.js +51 -0
  324. package/src/lib/plugin-manager/plugin-record-index.js.map +1 -0
  325. package/src/lib/plugin-manager/plugin-record-lists.d.ts +115 -0
  326. package/src/lib/plugin-manager/plugin-record-lists.js +75 -0
  327. package/src/lib/plugin-manager/plugin-record-lists.js.map +1 -0
  328. package/src/lib/plugin-manager/plugin-record-timeline.d.ts +42 -8
  329. package/src/lib/plugin-manager/plugin-record-timeline.js.map +1 -1
  330. package/src/lib/plugin-manager/plugin-record-written.d.ts +58 -0
  331. package/src/lib/plugin-manager/plugin-record-written.js +42 -0
  332. package/src/lib/plugin-manager/plugin-record-written.js.map +1 -0
  333. package/src/lib/plugin-manager/plugin-revenue-sources.d.ts +213 -0
  334. package/src/lib/plugin-manager/plugin-revenue-sources.js +194 -0
  335. package/src/lib/plugin-manager/plugin-revenue-sources.js.map +1 -0
  336. package/src/lib/plugin-manager/plugin-site-beacons.d.ts +71 -0
  337. package/src/lib/plugin-manager/plugin-site-beacons.js +54 -0
  338. package/src/lib/plugin-manager/plugin-site-beacons.js.map +1 -0
  339. package/src/lib/plugin-manager/plugin-site-bundle.d.ts +145 -0
  340. package/src/lib/plugin-manager/plugin-site-bundle.js +78 -0
  341. package/src/lib/plugin-manager/plugin-site-bundle.js.map +1 -0
  342. package/src/lib/plugin-manager/plugin-site-cache.d.ts +12 -0
  343. package/src/lib/plugin-manager/plugin-site-cache.js.map +1 -1
  344. package/src/lib/plugin-manager/plugin-site-export.d.ts +81 -0
  345. package/src/lib/plugin-manager/plugin-site-export.js +40 -0
  346. package/src/lib/plugin-manager/plugin-site-export.js.map +1 -0
  347. package/src/lib/plugin-manager/plugin-sitemap-sections.d.ts +88 -0
  348. package/src/lib/plugin-manager/plugin-sitemap-sections.js +29 -0
  349. package/src/lib/plugin-manager/plugin-sitemap-sections.js.map +1 -0
  350. package/src/lib/plugin-manager/plugin-subscription-topics.generated.d.ts +11 -0
  351. package/src/lib/plugin-manager/plugin-subscription-topics.generated.js +41 -0
  352. package/src/lib/plugin-manager/plugin-subscription-topics.generated.js.map +1 -0
  353. package/src/lib/plugin-manager/plugin-tax-profile.d.ts +20 -4
  354. package/src/lib/plugin-manager/plugin-tax-profile.js.map +1 -1
  355. package/src/lib/plugin-manager/plugin-tax-return-sources.d.ts +255 -0
  356. package/src/lib/plugin-manager/plugin-tax-return-sources.js +191 -0
  357. package/src/lib/plugin-manager/plugin-tax-return-sources.js.map +1 -0
  358. package/src/lib/plugin-manager/plugin-template-sources.d.ts +75 -0
  359. package/src/lib/plugin-manager/plugin-template-sources.js +37 -0
  360. package/src/lib/plugin-manager/plugin-template-sources.js.map +1 -0
  361. package/src/lib/plugin-manager/plugin-usage-axes.d.ts +319 -0
  362. package/src/lib/plugin-manager/plugin-usage-axes.js +186 -0
  363. package/src/lib/plugin-manager/plugin-usage-axes.js.map +1 -0
  364. package/src/lib/plugin-manager/plugin-usage-meters.d.ts +108 -0
  365. package/src/lib/plugin-manager/plugin-usage-meters.js +105 -0
  366. package/src/lib/plugin-manager/plugin-usage-meters.js.map +1 -0
  367. package/src/lib/plugin-manager/plugin-zones.d.ts +4 -5
  368. package/src/lib/plugin-manager/plugin-zones.js.map +1 -1
  369. package/src/lib/plugin-manager/realm-host-aglyn.generated.js +2 -0
  370. package/src/lib/plugin-manager/realm-host-aglyn.generated.js.map +1 -1
  371. package/src/lib/plugin-manager/record-captured-contact.d.ts +1 -14
  372. package/src/lib/plugin-manager/record-captured-contact.js +10 -32
  373. package/src/lib/plugin-manager/record-captured-contact.js.map +1 -1
  374. package/src/lib/plugin-manager/repeat-rows.d.ts +124 -0
  375. package/src/lib/plugin-manager/repeat-rows.js +108 -0
  376. package/src/lib/plugin-manager/repeat-rows.js.map +1 -0
  377. package/src/lib/plugin-manager/submission-record-target.d.ts +144 -0
  378. package/src/lib/plugin-manager/submission-record-target.js +125 -0
  379. package/src/lib/plugin-manager/submission-record-target.js.map +1 -0
  380. package/src/lib/plugin-manager/usage-alert-contributors.d.ts +76 -6
  381. package/src/lib/plugin-manager/usage-alert-contributors.js +23 -10
  382. package/src/lib/plugin-manager/usage-alert-contributors.js.map +1 -1
  383. package/src/lib/plugin-manager/video-embed-provider.d.ts +108 -0
  384. package/src/lib/plugin-manager/video-embed-provider.js +165 -0
  385. package/src/lib/plugin-manager/video-embed-provider.js.map +1 -0
  386. package/src/lib/types/nodes.d.ts +2 -2
  387. package/src/lib/types/nodes.js.map +1 -1
  388. package/src/lib/app-utils/assist-credits.d.ts +0 -482
  389. package/src/lib/app-utils/assist-credits.js +0 -509
  390. package/src/lib/app-utils/assist-credits.js.map +0 -1
  391. package/src/lib/app-utils/campaign-attribution.js.map +0 -1
  392. package/src/lib/app-utils/campaign-forwarding.js.map +0 -1
  393. package/src/lib/app-utils/campaign-membership.d.ts +0 -121
  394. package/src/lib/app-utils/campaign-membership.js +0 -189
  395. package/src/lib/app-utils/campaign-membership.js.map +0 -1
  396. package/src/lib/app-utils/campaign-touch.js.map +0 -1
  397. package/src/lib/app-utils/console-record-links.d.ts +0 -163
  398. package/src/lib/app-utils/console-record-links.js +0 -180
  399. package/src/lib/app-utils/console-record-links.js.map +0 -1
  400. package/src/lib/app-utils/contact-holder.d.ts +0 -68
  401. package/src/lib/app-utils/contact-holder.js +0 -129
  402. package/src/lib/app-utils/contact-holder.js.map +0 -1
  403. package/src/lib/app-utils/contact-merge.d.ts +0 -136
  404. package/src/lib/app-utils/contact-merge.js +0 -412
  405. package/src/lib/app-utils/contact-merge.js.map +0 -1
  406. package/src/lib/app-utils/crm-booking.d.ts +0 -75
  407. package/src/lib/app-utils/crm-booking.js +0 -133
  408. package/src/lib/app-utils/crm-booking.js.map +0 -1
  409. package/src/lib/app-utils/crm-csv.d.ts +0 -239
  410. package/src/lib/app-utils/crm-csv.js +0 -467
  411. package/src/lib/app-utils/crm-csv.js.map +0 -1
  412. package/src/lib/app-utils/crm-digest.d.ts +0 -185
  413. package/src/lib/app-utils/crm-digest.js +0 -272
  414. package/src/lib/app-utils/crm-digest.js.map +0 -1
  415. package/src/lib/app-utils/crm-inbound.d.ts +0 -245
  416. package/src/lib/app-utils/crm-inbound.js +0 -407
  417. package/src/lib/app-utils/crm-inbound.js.map +0 -1
  418. package/src/lib/app-utils/crm-reports.d.ts +0 -479
  419. package/src/lib/app-utils/crm-reports.js +0 -680
  420. package/src/lib/app-utils/crm-reports.js.map +0 -1
  421. package/src/lib/app-utils/dataset-csv.js.map +0 -1
  422. package/src/lib/app-utils/dataset-query.d.ts +0 -57
  423. package/src/lib/app-utils/dataset-query.js.map +0 -1
  424. package/src/lib/app-utils/email-topics.js.map +0 -1
  425. package/src/lib/app-utils/form-dataset-binding.d.ts +0 -50
  426. package/src/lib/app-utils/form-dataset-binding.js +0 -74
  427. package/src/lib/app-utils/form-dataset-binding.js.map +0 -1
  428. package/src/lib/app-utils/list-assignment-policy.js.map +0 -1
  429. package/src/lib/app-utils/list-import.d.ts +0 -158
  430. package/src/lib/app-utils/list-import.js +0 -332
  431. package/src/lib/app-utils/list-import.js.map +0 -1
  432. package/src/lib/app-utils/marketplace-listing-visibility.d.ts +0 -122
  433. package/src/lib/app-utils/marketplace-listing-visibility.js +0 -147
  434. package/src/lib/app-utils/marketplace-listing-visibility.js.map +0 -1
  435. package/src/lib/app-utils/marketplace-overrides.js.map +0 -1
  436. package/src/lib/app-utils/marketplace-provenance.js.map +0 -1
  437. package/src/lib/app-utils/marketplace-theme.js.map +0 -1
  438. package/src/lib/app-utils/marketplace-update-state.d.ts +0 -119
  439. package/src/lib/app-utils/marketplace-update-state.js +0 -132
  440. package/src/lib/app-utils/marketplace-update-state.js.map +0 -1
  441. package/src/lib/app-utils/publisher-agreement.d.ts +0 -289
  442. package/src/lib/app-utils/publisher-agreement.js +0 -321
  443. package/src/lib/app-utils/publisher-agreement.js.map +0 -1
  444. package/src/lib/app-utils/wistia-embed.d.ts +0 -104
  445. package/src/lib/app-utils/wistia-embed.js +0 -138
  446. package/src/lib/app-utils/wistia-embed.js.map +0 -1
  447. package/src/lib/app-utils/workflows.d.ts +0 -136
  448. package/src/lib/app-utils/workflows.js +0 -346
  449. package/src/lib/app-utils/workflows.js.map +0 -1
  450. package/src/lib/plugin-manager/commerce-zone-props.d.ts +0 -172
  451. package/src/lib/plugin-manager/commerce-zone-props.js +0 -31
  452. package/src/lib/plugin-manager/commerce-zone-props.js.map +0 -1
  453. package/src/lib/plugin-manager/plugin-metered-lines.d.ts +0 -97
  454. package/src/lib/plugin-manager/plugin-metered-lines.js +0 -123
  455. package/src/lib/plugin-manager/plugin-metered-lines.js.map +0 -1
@@ -15,7 +15,12 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  export interface ErrorBeaconEvent {
18
- /** 'error' | 'unhandledrejection' — which handler caught it. */
18
+ /**
19
+ * Which handler caught it — 'error' | 'unhandledrejection' — or the
20
+ * family it was labeled with: 'hydration', {@link AUTH_DESYNC_KIND},
21
+ * {@link CHUNK_LOAD_KIND}, or a caller's own kind for a handled error.
22
+ * Lands at `jsonPayload.kind`, where the alert policies filter on it.
23
+ */
19
24
  kind: string;
20
25
  /** Error message, clamped. */
21
26
  message: string;
@@ -39,8 +44,8 @@ export interface ErrorBeaconOptions {
39
44
  /**
40
45
  * Was this thrown by a script somebody ELSE evaluated into our page?
41
46
  *
42
- * Two tells, both read off the frames' URLs and neither off a function name —
43
- * a name would be a denylist needing a new entry per vendor.
47
+ * Three tells, all read off the frames' positions and none off a function
48
+ * name — a name would be a denylist needing a new entry per vendor.
44
49
  *
45
50
  * **Every frame is the DOCUMENT.** Measured 2026-09-02 (AGL-2523) on
46
51
  * aglyn.com/pricing, reported as an error of ours:
@@ -59,9 +64,22 @@ export interface ErrorBeaconOptions {
59
64
  * at sendDataToNative (iabjs://navigation_performance_logger_android:1:10632)
60
65
  *
61
66
  * That webview names its scripts under its own `iabjs://` scheme, and
62
- * extensions do the same under theirs — see `FOREIGN_SCRIPT_SCHEMES`. A frame
63
- * may carry either tell. Nothing we ship can be fixed in response to any of
64
- * them, which is the same test the opaque `Script error.` cut already applies.
67
+ * extensions do the same under theirs — see `FOREIGN_SCRIPT_SCHEMES`.
68
+ *
69
+ * **Every frame is a script with NO URL** (AGL-3423). Measured on the
70
+ * sign-up page and on aglyn.com/solutions/agencies:
71
+ *
72
+ * at eval (<anonymous>)
73
+ * at predicate (eval at evaluate (:234:30), <anonymous>:11:37)
74
+ *
75
+ * at <anonymous>:1:54
76
+ * at <anonymous>:1:64
77
+ *
78
+ * An automation driver's `evaluate` and a snippet pasted into devtools. Every
79
+ * script we serve has a URL — a chunk, a CDN asset, or the document for an
80
+ * inline one — so a frame whose position is `<anonymous>:line:col`, or code
81
+ * `eval`'d by such a frame, was not served by us. See
82
+ * {@link anonymousScriptFrameCount} for exactly which frames count.
65
83
  *
66
84
  * ⚑ Deliberately `every`, and deliberately compared against the document
67
85
  * rather than against our asset path. A rule like "no frame under
@@ -70,11 +88,42 @@ export interface ErrorBeaconOptions {
70
88
  * Comparing to the document cannot fail that way: a CDN frame is not the
71
89
  * document either, so it keeps the report.
72
90
  *
91
+ * A stack may mix the tells frame by frame. Nothing we ship can be fixed in
92
+ * response to any of them, which is the same test the opaque `Script error.`
93
+ * cut already applies.
94
+ *
73
95
  * The cost is honest and small: a throw from one of our own inline
74
96
  * bootstrap scripts looks the same and is dropped with it. That trade buys a
75
97
  * rule that needs no maintenance as new webviews and extensions appear.
76
98
  */
77
99
  export declare function isInjectedThirdPartyFrame(stack: string, documentUrl: string): boolean;
100
+ /** How many frames of this stack are in a script with no URL at all. */
101
+ export declare function anonymousScriptFrameCount(stack: string): number;
102
+ export declare function isBenignBrowserNotice(message: string): boolean;
103
+ /**
104
+ * `kind` for Firebase's `auth/tenant-id-mismatch` — a sibling tab signed in to
105
+ * another account pool (AGL-3280). The console recovers the tab by reloading
106
+ * it once it is hidden and deliberately leaves the rejection unhandled so it
107
+ * is still seen; this label is what lets it be seen by RATE instead of paging
108
+ * on each of the several rejections one storage event raises.
109
+ */
110
+ export declare const AUTH_DESYNC_KIND = "auth-desync";
111
+ /**
112
+ * `kind` for a chunk the document names and the origin no longer serves
113
+ * (AGL-3279). Every boundary reloads once for it; what still arrives is the
114
+ * failure the reload did not cure. One of those is a visitor on a bad
115
+ * connection; a burst of them is a broken deploy, which only a rate can tell.
116
+ */
117
+ export declare const CHUNK_LOAD_KIND = "chunk-load";
118
+ /**
119
+ * The label for a fault we RECOVER from and still want to see, or undefined.
120
+ *
121
+ * These could be ours, so unlike an injected stack they are never dropped:
122
+ * they are written at full severity under their own `kind`, the per-entry
123
+ * policy excludes that kind, and a rate policy watches it — the same split
124
+ * `hydration` already has.
125
+ */
126
+ export declare function recoveredErrorKind(error: unknown): string | undefined;
78
127
  export declare function isHydrationMismatch(message: string): boolean;
79
128
  /**
80
129
  * WHAT A REJECTED PROMISE ACTUALLY CARRIED (AGL-3279).
@@ -100,6 +149,26 @@ export declare function isHydrationMismatch(message: string): boolean;
100
149
  * was called to improve.
101
150
  */
102
151
  export declare function describeRejectionReason(reason: unknown): string;
152
+ /**
153
+ * How many frames a thrown error keeps, on a pageview that reports (AGL-3423).
154
+ *
155
+ * V8 keeps ten by default, and ten is not enough to find where a render loop
156
+ * STARTED. The Besigner's one React #185 report (2026-09-24) was a
157
+ * react-final-form field's `setState` inside final-form's `notify` loop, and
158
+ * every one of its ten frames was inside those two libraries: the component
159
+ * whose update fed the loop was cut off below them. Fifty reaches past a
160
+ * form library's own frames to ours, and still fits the {@link MAX_STACK}
161
+ * clamp at the length a minified frame line has.
162
+ */
163
+ export declare const BEACON_STACK_TRACE_LIMIT = 50;
164
+ /**
165
+ * Raises the engine's frame limit to `limit`, never lowers it. V8 and
166
+ * JavaScriptCore read `Error.stackTraceLimit`; an engine that does not has no
167
+ * such number, and is left without one rather than handed a property it
168
+ * ignores. It applies to errors created after the call, which is why the
169
+ * beacon sets it at install, at module scope of the app's first client chunk.
170
+ */
171
+ export declare function raiseStackTraceLimit(limit: number): void;
103
172
  /**
104
173
  * Re-export so `error-beacon` stays the one name a caller has to know for
105
174
  * browser error reporting. The definition lives in its own module because a
@@ -41,7 +41,9 @@
41
41
  * tenant runtime from its own, and neither needs React here. Deliberately NO
42
42
  * 'use client' directive — inside this shared lib the directive forks the
43
43
  * module graph (AGL-52); every importer is already a client module.
44
- */ import { isForeignScriptUrl, stackFrameUrls } from "./foreign-script.js";
44
+ */ import { isCrossPoolDesync } from "./cross-pool-desync.js";
45
+ import { isForeignScriptUrl, stackFrameUrls } from "./foreign-script.js";
46
+ import { isStaleBuildError, recoverStaleBuildRejection } from "./stale-build-error.js";
45
47
  const MAX_MESSAGE = 1024;
46
48
  const MAX_STACK = 8192;
47
49
  const FLUSH_DELAY_MS = 2000;
@@ -60,8 +62,8 @@ function clamp(value, max) {
60
62
  /**
61
63
  * Was this thrown by a script somebody ELSE evaluated into our page?
62
64
  *
63
- * Two tells, both read off the frames' URLs and neither off a function name —
64
- * a name would be a denylist needing a new entry per vendor.
65
+ * Three tells, all read off the frames' positions and none off a function
66
+ * name — a name would be a denylist needing a new entry per vendor.
65
67
  *
66
68
  * **Every frame is the DOCUMENT.** Measured 2026-09-02 (AGL-2523) on
67
69
  * aglyn.com/pricing, reported as an error of ours:
@@ -80,9 +82,22 @@ function clamp(value, max) {
80
82
  * at sendDataToNative (iabjs://navigation_performance_logger_android:1:10632)
81
83
  *
82
84
  * That webview names its scripts under its own `iabjs://` scheme, and
83
- * extensions do the same under theirs — see `FOREIGN_SCRIPT_SCHEMES`. A frame
84
- * may carry either tell. Nothing we ship can be fixed in response to any of
85
- * them, which is the same test the opaque `Script error.` cut already applies.
85
+ * extensions do the same under theirs — see `FOREIGN_SCRIPT_SCHEMES`.
86
+ *
87
+ * **Every frame is a script with NO URL** (AGL-3423). Measured on the
88
+ * sign-up page and on aglyn.com/solutions/agencies:
89
+ *
90
+ * at eval (<anonymous>)
91
+ * at predicate (eval at evaluate (:234:30), <anonymous>:11:37)
92
+ *
93
+ * at <anonymous>:1:54
94
+ * at <anonymous>:1:64
95
+ *
96
+ * An automation driver's `evaluate` and a snippet pasted into devtools. Every
97
+ * script we serve has a URL — a chunk, a CDN asset, or the document for an
98
+ * inline one — so a frame whose position is `<anonymous>:line:col`, or code
99
+ * `eval`'d by such a frame, was not served by us. See
100
+ * {@link anonymousScriptFrameCount} for exactly which frames count.
86
101
  *
87
102
  * ⚑ Deliberately `every`, and deliberately compared against the document
88
103
  * rather than against our asset path. A rule like "no frame under
@@ -91,15 +106,92 @@ function clamp(value, max) {
91
106
  * Comparing to the document cannot fail that way: a CDN frame is not the
92
107
  * document either, so it keeps the report.
93
108
  *
109
+ * A stack may mix the tells frame by frame. Nothing we ship can be fixed in
110
+ * response to any of them, which is the same test the opaque `Script error.`
111
+ * cut already applies.
112
+ *
94
113
  * The cost is honest and small: a throw from one of our own inline
95
114
  * bootstrap scripts looks the same and is dropped with it. That trade buys a
96
115
  * rule that needs no maintenance as new webviews and extensions appear.
97
116
  */ export function isInjectedThirdPartyFrame(stack, documentUrl) {
98
117
  const urls = stackFrameUrls(stack);
99
- // No frames parsed is not evidence of anything — keep the report.
100
- if (!urls.length) return false;
118
+ // No frames parsed is not evidence of anything — keep the report. A stack
119
+ // with neither a URL nor an anonymous-script frame is exactly that: an
120
+ // empty frame list must never read as "every frame is injected".
121
+ if (!urls.length && !anonymousScriptFrameCount(stack)) return false;
122
+ // Anonymous frames need no test of their own — they are injected by
123
+ // definition — so `every` over the URLs is `every` over the whole stack.
124
+ // One URL of ours, even as the origin of an `eval`, keeps the report.
101
125
  return urls.every((url)=>isForeignScriptUrl(url) || scrubUrl(url) === documentUrl);
102
126
  }
127
+ /** A frame line, in V8's `at …` format or WebKit/Firefox's `fn@location`. */ const STACK_FRAME_LINE = /^\s*at\s|@/;
128
+ /**
129
+ * A position in a script that has no URL.
130
+ *
131
+ * - `<anonymous>:line:col` — V8's name for such a script, both for a top-level
132
+ * snippet and as the position of code run through `eval`/`new Function`.
133
+ * - `eval at …` — V8's origin of `eval`'d code. When OUR script ran the eval
134
+ * its URL is inside this origin, `stackFrameUrls` reads it, and the report
135
+ * is kept; that is how the marketing plugin's `runJs` step stays reported.
136
+ * - `debugger eval code:line:col` — Firefox's devtools console, in the
137
+ * `fn@location` format WebKit also uses.
138
+ *
139
+ * ⚑ A BARE `(<anonymous>)` with no line and column is NOT one of these. It is
140
+ * how V8 prints a builtin — `at Array.forEach (<anonymous>)`,
141
+ * `at JSON.parse (<anonymous>)` — and a builtin is called by whoever called
142
+ * it, including us.
143
+ */ const ANONYMOUS_SCRIPT_POSITION = /<anonymous>:\d+:\d+|\beval at\s|\bdebugger eval code:\d+:\d+/;
144
+ /** How many frames of this stack are in a script with no URL at all. */ export function anonymousScriptFrameCount(stack) {
145
+ let count = 0;
146
+ for (const line of stack.split('\n')){
147
+ if (STACK_FRAME_LINE.test(line) && ANONYMOUS_SCRIPT_POSITION.test(line)) {
148
+ count += 1;
149
+ }
150
+ }
151
+ return count;
152
+ }
153
+ /**
154
+ * Browser notices that are not failures, and that no fix of ours could act on.
155
+ *
156
+ * `ResizeObserver loop completed with undelivered notifications` (and its older
157
+ * wording, `ResizeObserver loop limit exceeded`) is the browser saying it
158
+ * deferred some resize callbacks to the next frame. Nothing threw: the event
159
+ * carries no error object and no stack, and every observer is still
160
+ * delivered. It arrived from the Besigner on 2026-09-26 and paged. Dropped, on
161
+ * the browser's exact wording.
162
+ */ const BENIGN_BROWSER_NOTICE = /^(?:Uncaught )?(?:Error: )?ResizeObserver loop (?:completed with undelivered notifications|limit exceeded)/;
163
+ export function isBenignBrowserNotice(message) {
164
+ return BENIGN_BROWSER_NOTICE.test(message);
165
+ }
166
+ /**
167
+ * `kind` for Firebase's `auth/tenant-id-mismatch` — a sibling tab signed in to
168
+ * another account pool (AGL-3280). The console recovers the tab by reloading
169
+ * it once it is hidden and deliberately leaves the rejection unhandled so it
170
+ * is still seen; this label is what lets it be seen by RATE instead of paging
171
+ * on each of the several rejections one storage event raises.
172
+ */ export const AUTH_DESYNC_KIND = 'auth-desync';
173
+ /**
174
+ * `kind` for a chunk the document names and the origin no longer serves
175
+ * (AGL-3279). Every boundary reloads once for it; what still arrives is the
176
+ * failure the reload did not cure. One of those is a visitor on a bad
177
+ * connection; a burst of them is a broken deploy, which only a rate can tell.
178
+ */ export const CHUNK_LOAD_KIND = 'chunk-load';
179
+ /**
180
+ * The label for a fault we RECOVER from and still want to see, or undefined.
181
+ *
182
+ * These could be ours, so unlike an injected stack they are never dropped:
183
+ * they are written at full severity under their own `kind`, the per-entry
184
+ * policy excludes that kind, and a rate policy watches it — the same split
185
+ * `hydration` already has.
186
+ */ export function recoveredErrorKind(error) {
187
+ try {
188
+ if (isCrossPoolDesync(error)) return AUTH_DESYNC_KIND;
189
+ if (isStaleBuildError(error)) return CHUNK_LOAD_KIND;
190
+ } catch (unused) {
191
+ // A getter that throws leaves the event unlabeled, never unreported.
192
+ }
193
+ return undefined;
194
+ }
103
195
  /**
104
196
  * React's hydration-mismatch family, which a page TRANSLATOR causes and a
105
197
  * real render divergence also causes.
@@ -184,6 +276,33 @@ export function isHydrationMismatch(message) {
184
276
  return 'Unhandled promise rejection (undescribable)';
185
277
  }
186
278
  }
279
+ /**
280
+ * How many frames a thrown error keeps, on a pageview that reports (AGL-3423).
281
+ *
282
+ * V8 keeps ten by default, and ten is not enough to find where a render loop
283
+ * STARTED. The Besigner's one React #185 report (2026-09-24) was a
284
+ * react-final-form field's `setState` inside final-form's `notify` loop, and
285
+ * every one of its ten frames was inside those two libraries: the component
286
+ * whose update fed the loop was cut off below them. Fifty reaches past a
287
+ * form library's own frames to ours, and still fits the {@link MAX_STACK}
288
+ * clamp at the length a minified frame line has.
289
+ */ export const BEACON_STACK_TRACE_LIMIT = 50;
290
+ /**
291
+ * Raises the engine's frame limit to `limit`, never lowers it. V8 and
292
+ * JavaScriptCore read `Error.stackTraceLimit`; an engine that does not has no
293
+ * such number, and is left without one rather than handed a property it
294
+ * ignores. It applies to errors created after the call, which is why the
295
+ * beacon sets it at install, at module scope of the app's first client chunk.
296
+ */ export function raiseStackTraceLimit(limit) {
297
+ try {
298
+ const engine = Error;
299
+ const current = engine.stackTraceLimit;
300
+ if (typeof current !== 'number' || current >= limit) return;
301
+ engine.stackTraceLimit = limit;
302
+ } catch (unused) {
303
+ // A frozen or exotic `Error` keeps its own limit.
304
+ }
305
+ }
187
306
  let installed = false;
188
307
  /**
189
308
  * The live beacon's `enqueue`, published for {@link reportHandledError}.
@@ -238,7 +357,11 @@ let installed = false;
238
357
  const endpoint = (_ref = options == null ? void 0 : options.endpoint) != null ? _ref : '/api/errors';
239
358
  const sampleRate = (_ref1 = options == null ? void 0 : options.sampleRate) != null ? _ref1 : 1;
240
359
  const maxPerPage = (_ref2 = options == null ? void 0 : options.maxPerPage) != null ? _ref2 : 10;
241
- if (Math.random() >= sampleRate) return;
360
+ // Only a sampled pageview REPORTS. Every pageview recovers a stale build
361
+ // (the rejection handler below), because a tab left on a dead deploy is a
362
+ // visitor's problem whether or not its errors are counted.
363
+ const sampled = Math.random() < sampleRate;
364
+ if (sampled) raiseStackTraceLimit(BEACON_STACK_TRACE_LIMIT);
242
365
  const seen = new Set();
243
366
  let queued = [];
244
367
  let sent = 0;
@@ -270,7 +393,7 @@ let installed = false;
270
393
  };
271
394
  const enqueue = (event)=>{
272
395
  var _event_stack;
273
- if (sent >= maxPerPage) return;
396
+ if (!sampled || sent >= maxPerPage) return;
274
397
  // Message + first stack line: enough identity to collapse a render loop
275
398
  // without collapsing distinct errors that share a message.
276
399
  const key = `${event.message}\x00${((_event_stack = event.stack) != null ? _event_stack : '').split('\n', 2).join('\n')}`;
@@ -280,18 +403,18 @@ let installed = false;
280
403
  queued.push(event);
281
404
  if (!timer) timer = setTimeout(flush, FLUSH_DELAY_MS);
282
405
  };
283
- // Published AFTER the sample-rate return above, so an unsampled pageview
284
- // reports nothing by either door rather than one by one and none by the
285
- // other.
286
- publishEvent = enqueue;
406
+ // Null on an unsampled pageview, so it reports nothing by either door
407
+ // rather than one by one and none by the other.
408
+ publishEvent = sampled ? enqueue : null;
287
409
  window.addEventListener('error', (event)=>{
288
410
  try {
289
- var _ref;
411
+ var _ref, _recoveredErrorKind;
290
412
  const error = event.error;
291
413
  const message = clamp((_ref = error == null ? void 0 : error.message) != null ? _ref : event.message, MAX_MESSAGE);
292
414
  // Cross-origin scripts yield an opaque "Script error." with nothing
293
415
  // actionable attached; reporting it would only create a noisy group.
294
416
  if (!message || message === 'Script error.') return;
417
+ if (isBenignBrowserNotice(message)) return;
295
418
  const pageUrl = scrubUrl(window.location.href);
296
419
  const fullStack = (error == null ? void 0 : error.stack) ? String(error.stack) : undefined;
297
420
  // A webview or extension that evaluated its own code into our page —
@@ -302,9 +425,12 @@ let installed = false;
302
425
  if (fullStack && isInjectedThirdPartyFrame(fullStack, pageUrl)) return;
303
426
  const stack = fullStack ? clamp(fullStack, MAX_STACK) : undefined;
304
427
  enqueue({
305
- // MARKED, not dropped: a translator causes these and so does a real
306
- // render divergence, and only a rate tells them apart.
307
- kind: isHydrationMismatch(message) ? 'hydration' : 'error',
428
+ // MARKED, not dropped: a translator causes a hydration mismatch and
429
+ // so does a real render divergence, and a recovered fault is still a
430
+ // fault. Only a rate tells either apart from noise.
431
+ kind: (_recoveredErrorKind = recoveredErrorKind(error != null ? error : {
432
+ message
433
+ })) != null ? _recoveredErrorKind : isHydrationMismatch(message) ? 'hydration' : 'error',
308
434
  message,
309
435
  stack,
310
436
  source: scrubUrl(event.filename) || undefined,
@@ -318,14 +444,27 @@ let installed = false;
318
444
  });
319
445
  window.addEventListener('unhandledrejection', (event)=>{
320
446
  try {
447
+ var _recoveredErrorKind;
448
+ // An `import()` of a chunk this document names and the origin dropped,
449
+ // which no boundary saw. Recovered by a reload once the tab is hidden,
450
+ // and, like a boundary's reload, not reported: see
451
+ // `recoverStaleBuildRejection`. A tab whose recovery is spent still
452
+ // reports it, as `chunk-load`.
453
+ if (recoverStaleBuildRejection(event.reason)) return;
321
454
  const reason = event.reason;
322
455
  const message = clamp(describeRejectionReason(event.reason), MAX_MESSAGE);
323
456
  if (!message) return;
457
+ const pageUrl = scrubUrl(window.location.href);
458
+ const fullStack = (reason == null ? void 0 : reason.stack) ? String(reason.stack) : undefined;
459
+ // The same injected-code drop as an uncaught error: a rejection raised
460
+ // by a devtools snippet or an automation driver's `evaluate` is no more
461
+ // ours for having been a promise.
462
+ if (fullStack && isInjectedThirdPartyFrame(fullStack, pageUrl)) return;
324
463
  enqueue({
325
- kind: 'unhandledrejection',
464
+ kind: (_recoveredErrorKind = recoveredErrorKind(event.reason)) != null ? _recoveredErrorKind : 'unhandledrejection',
326
465
  message,
327
- stack: (reason == null ? void 0 : reason.stack) ? clamp(reason.stack, MAX_STACK) : undefined,
328
- url: scrubUrl(window.location.href)
466
+ stack: fullStack ? clamp(fullStack, MAX_STACK) : undefined,
467
+ url: pageUrl
329
468
  });
330
469
  } catch (unused) {
331
470
  // Never rethrow from an error handler.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/error-beacon.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * First-party browser error beacon (AGL-1538).\n *\n * Crashlytics does not exist for web, and adding a third-party error vendor\n * is a subprocessor-list decision that was explicitly deferred. This is the\n * first-party alternative: `window.onerror` / `unhandledrejection` handlers\n * that batch uncaught failures to the app's own `/api/errors` route, which\n * forwards them to Google Cloud Error Reporting — a processor already on the\n * list, alerting through the GCP stack that already pages (AGL-1502).\n *\n * Design constraints, in order:\n *\n * - **It must never become the outage.** Everything is wrapped; a failure to\n * report is silence, not a thrown error. Batches are capped per page so an\n * error thrown in a loop cannot DDoS our own API — after `maxPerPage`\n * events the beacon disarms for the rest of the pageview.\n * - **No PII.** URLs are scrubbed to origin + pathname (query strings and\n * fragments carry tokens and search terms), no user id, no cookies —\n * the payload is the error text and where in the CODE it happened.\n * Cross-origin scripts surface as the browser's opaque \"Script error.\"\n * with no stack; those are dropped since they cannot be acted on.\n * - **Dedupe.** One page throwing the same error on every frame reports it\n * once.\n *\n * Framework-free on purpose: the console mounts it from its root layout, the\n * tenant runtime from its own, and neither needs React here. Deliberately NO\n * 'use client' directive — inside this shared lib the directive forks the\n * module graph (AGL-52); every importer is already a client module.\n */\n\nimport { isForeignScriptUrl, stackFrameUrls } from './foreign-script'\n\nexport interface ErrorBeaconEvent {\n /** 'error' | 'unhandledrejection' — which handler caught it. */\n kind: string\n /** Error message, clamped. */\n message: string\n /** Stack trace when the thrown value carried one, clamped. */\n stack?: string\n /** Script URL for stackless `window.onerror` events, scrubbed. */\n source?: string\n line?: number\n col?: number\n /** Page URL, scrubbed to origin + pathname. */\n url: string\n}\n\nexport interface ErrorBeaconOptions {\n /** POST target; same-origin. Default `/api/errors`. */\n endpoint?: string\n /** 0..1 — fraction of pageviews that report at all. Default 1. */\n sampleRate?: number\n /** Max events reported per pageview before the beacon disarms. */\n maxPerPage?: number\n}\n\nconst MAX_MESSAGE = 1_024\nconst MAX_STACK = 8_192\nconst FLUSH_DELAY_MS = 2_000\n\n/** Origin + pathname only — query strings and fragments never leave. */\nfunction scrubUrl(raw: string | null | undefined): string {\n if (!raw) return ''\n try {\n const url = new URL(String(raw), window.location.href)\n return `${url.origin}${url.pathname}`\n } catch {\n return ''\n }\n}\n\nfunction clamp(value: unknown, max: number): string {\n return String(value ?? '').slice(0, max)\n}\n\n/**\n * Was this thrown by a script somebody ELSE evaluated into our page?\n *\n * Two tells, both read off the frames' URLs and neither off a function name —\n * a name would be a denylist needing a new entry per vendor.\n *\n * **Every frame is the DOCUMENT.** Measured 2026-09-02 (AGL-2523) on\n * aglyn.com/pricing, reported as an error of ours:\n *\n * sendDataToNative@https://aglyn.com/pricing:1:1325\n * sendPageHideMessage@https://aglyn.com/pricing:1:4139\n * @https://aglyn.com/pricing:1:6257\n *\n * `sendDataToNative` is the Meta in-app browser's native bridge, injected by\n * the Facebook/Instagram webview. In WebKit's format the code was evaluated\n * inline, so every frame is the document rather than a script we served.\n *\n * **Every frame is under a FOREIGN scheme.** Measured 2026-09-10 (AGL-2786) on\n * aglyn.com, the same bridge in the Android webview:\n *\n * at sendDataToNative (iabjs://navigation_performance_logger_android:1:10632)\n *\n * That webview names its scripts under its own `iabjs://` scheme, and\n * extensions do the same under theirs — see `FOREIGN_SCRIPT_SCHEMES`. A frame\n * may carry either tell. Nothing we ship can be fixed in response to any of\n * them, which is the same test the opaque `Script error.` cut already applies.\n *\n * ⚑ Deliberately `every`, and deliberately compared against the document\n * rather than against our asset path. A rule like \"no frame under\n * `/_next/static/`\" would delete EVERY error from a self-hosted deployment\n * that serves its assets from a CDN, because none of its frames would match.\n * Comparing to the document cannot fail that way: a CDN frame is not the\n * document either, so it keeps the report.\n *\n * The cost is honest and small: a throw from one of our own inline\n * bootstrap scripts looks the same and is dropped with it. That trade buys a\n * rule that needs no maintenance as new webviews and extensions appear.\n */\nexport function isInjectedThirdPartyFrame(\n stack: string,\n documentUrl: string,\n): boolean {\n const urls = stackFrameUrls(stack)\n // No frames parsed is not evidence of anything — keep the report.\n if (!urls.length) return false\n return urls.every(\n (url) => isForeignScriptUrl(url) || scrubUrl(url) === documentUrl,\n )\n}\n\n/**\n * React's hydration-mismatch family, which a page TRANSLATOR causes and a\n * real render divergence also causes.\n *\n * These are `onRecoverableError` reports, not crashes: React has already\n * re-rendered on the client and the visitor has a working page. They arrive\n * here as uncaught errors only because React re-throws them to `reportError`.\n *\n * They are marked rather than dropped, and the distinction is the whole\n * design. Dropping would hide a real hydration regression, which is a genuine\n * and expensive bug; the entries stay in `client-errors` at full severity and\n * still group in Error Reporting. What the mark buys is that the log-match\n * policy can stop paging on a single report, while a rate-based policy on the\n * same mark still catches a systemic one.\n *\n * ⚠️ THE MARK IS NOT A VERDICT, and the one cluster this repo has measured is\n * why. Eight #418 reports arrived inside a nine-minute window on 2026-09-01,\n * on one build, and the three pages they came from were exactly the three\n * carrying a form — `/`, `/pricing` and the solutions pages reported nothing\n * in the same window, which no browser-side rewrite would respect. A placed\n * form was expanding inside its own grafted subtree, so every page carrying\n * one shipped six nested `<form>` elements; nested forms are invalid HTML, the\n * parser dropped the inner ones, and the client tree disagreed with the server\n * tree. The visible cost was a submission the route never received, because\n * the native submit came from an unhandled ancestor and the browser fell back\n * to a GET with the visitor's name, email and message in the address bar. The\n * reports stopped because the nesting was fixed, roughly a quarter of an hour\n * after the last one.\n *\n * So a rate low enough not to page is a reason to READ the entry — the page\n * it names, and whether the set of pages has a shape — never a reason to\n * assume somebody's extension.\n */\nconst HYDRATION_MINIFIED = /Minified React error #(?:418|423|425)\\b/\nconst HYDRATION_TEXT =\n /Hydration failed because|Text content does not match server-rendered HTML|There was an error while hydrating/\n\nexport function isHydrationMismatch(message: string): boolean {\n return HYDRATION_MINIFIED.test(message) || HYDRATION_TEXT.test(message)\n}\n\n/**\n * WHAT A REJECTED PROMISE ACTUALLY CARRIED (AGL-3279).\n *\n * `unhandledrejection` hands over whatever was passed to `reject`, and only\n * an `Error` brings a message and a stack. A rejection with anything else —\n * an API's `{ code, message }` object, a `DOMException` from an aborted\n * fetch, a bare string, a `Response` — used to be reported as the literal\n * words \"Unhandled promise rejection\" with no stack and no other field,\n * which names the handler rather than the failure. One such report arrived\n * on 2026-09-21 from the Besigner editor and there is nothing in it to act\n * on: no message, no stack, no code, nothing but the page.\n *\n * So the value is DESCRIBED rather than defaulted. In order of how much a\n * reader can do with it: the error's own message; a string as itself; a\n * `name`/`code`/`message` shape assembled from whatever of those it has —\n * the shape every Firebase, DOM and fetch rejection takes; the value's own\n * `toString` when it says more than `[object Object]`; and last its own\n * keys, which at least name what kind of thing rejected.\n *\n * Nothing here may throw: a getter on the reason can, `toString` can, and\n * a describer that throws inside the rejection handler loses the report it\n * was called to improve.\n */\nexport function describeRejectionReason(reason: unknown): string {\n try {\n if (reason instanceof Error && reason.message) return reason.message\n if (typeof reason === 'string') return reason\n if (reason === null || reason === undefined) {\n return `Unhandled promise rejection (${String(reason)})`\n }\n if (typeof reason !== 'object') {\n return `Unhandled promise rejection (${typeof reason}: ${String(reason)})`\n }\n const shape = reason as Record<string, unknown>\n const named = [\n shape['name'] ?? shape['code'] ?? '',\n shape['message'] ?? shape['statusText'] ?? '',\n ]\n .map((part) => String(part ?? '').trim())\n .filter(Boolean)\n if (named.length) return named.join(': ')\n const printed = String(reason)\n if (printed && printed !== '[object Object]') return printed\n const keys = Object.keys(shape).slice(0, 12).join(', ')\n return keys\n ? `Unhandled promise rejection (object with ${keys})`\n : 'Unhandled promise rejection (empty object)'\n } catch {\n return 'Unhandled promise rejection (undescribable)'\n }\n}\n\nlet installed = false\n\n/**\n * The live beacon's `enqueue`, published for {@link reportHandledError}.\n *\n * Null until `installErrorBeacon` runs, and null forever on a surface that\n * never installs one — so a caught error reported from a page with no beacon\n * is silently dropped rather than throwing inside somebody's error handler.\n */\nlet publishEvent: ((event: ErrorBeaconEvent) => void) | null = null\n\n/**\n * Re-export so `error-beacon` stays the one name a caller has to know for\n * browser error reporting. The definition lives in its own module because a\n * boundary that imports it must not pull the installer below into a chunk\n * every visitor downloads.\n */\nexport { redispatchCaughtError } from './redispatch-caught-error'\n\n/**\n * Report an error the code ALREADY CAUGHT.\n *\n * The two window handlers below see only what nothing caught. A `catch` that\n * swallows its error is invisible to them by construction, which is the whole\n * failure mode this exists for: a background write that can only fail\n * silently is one that stays broken for as long as nobody thinks to look.\n *\n * It rides the same queue as an uncaught error, which is the point — the\n * dedupe collapses a failure that repeats on every edit into one report, and\n * `maxPerPage` bounds it, so a call site in a loop cannot turn a broken\n * feature into a flood. Reporting is never worth an exception of its own, so\n * every path here returns rather than throws.\n */\nexport function reportHandledError(\n error: unknown,\n options?: { kind?: string },\n): void {\n try {\n if (!publishEvent) return\n const thrown = error as Error | undefined\n const message = clamp(\n thrown?.message ?? (typeof error === 'string' ? error : ''),\n MAX_MESSAGE,\n )\n if (!message) return\n publishEvent({\n kind: clamp(options?.kind ?? 'handled', 32),\n message,\n stack: thrown?.stack ? clamp(thrown.stack, MAX_STACK) : undefined,\n url: scrubUrl(window.location.href),\n })\n } catch {\n // An observer that throws is worse than one that misses an event.\n }\n}\n\n/**\n * Installs the handlers once per page. Safe to call from module scope of a\n * client bundle: it no-ops during SSR and on repeat calls.\n */\nexport function installErrorBeacon(options?: ErrorBeaconOptions): void {\n if (typeof window === 'undefined' || installed) return\n installed = true\n\n const endpoint = options?.endpoint ?? '/api/errors'\n const sampleRate = options?.sampleRate ?? 1\n const maxPerPage = options?.maxPerPage ?? 10\n if (Math.random() >= sampleRate) return\n\n const seen = new Set<string>()\n let queued: ErrorBeaconEvent[] = []\n let sent = 0\n let timer: ReturnType<typeof setTimeout> | null = null\n\n const flush = () => {\n timer = null\n if (!queued.length) return\n const batch = queued\n queued = []\n try {\n const body = JSON.stringify({ events: batch })\n // sendBeacon survives unloads and never blocks; keepalive fetch is the\n // fallback for browsers that refuse the payload.\n if (!navigator.sendBeacon?.(endpoint, body)) {\n void fetch(endpoint, {\n method: 'POST',\n body,\n keepalive: true,\n headers: { 'Content-Type': 'application/json' },\n }).catch((): undefined => undefined)\n }\n } catch {\n // Reporting never breaks the page.\n }\n }\n\n const enqueue = (event: ErrorBeaconEvent) => {\n if (sent >= maxPerPage) return\n // Message + first stack line: enough identity to collapse a render loop\n // without collapsing distinct errors that share a message.\n const key = `${event.message}\\x00${(event.stack ?? '').split('\\n', 2).join('\\n')}`\n if (seen.has(key)) return\n seen.add(key)\n sent += 1\n queued.push(event)\n if (!timer) timer = setTimeout(flush, FLUSH_DELAY_MS)\n }\n // Published AFTER the sample-rate return above, so an unsampled pageview\n // reports nothing by either door rather than one by one and none by the\n // other.\n publishEvent = enqueue\n\n window.addEventListener('error', (event) => {\n try {\n const error = event.error as Error | undefined\n const message = clamp(error?.message ?? event.message, MAX_MESSAGE)\n // Cross-origin scripts yield an opaque \"Script error.\" with nothing\n // actionable attached; reporting it would only create a noisy group.\n if (!message || message === 'Script error.') return\n const pageUrl = scrubUrl(window.location.href)\n const fullStack = error?.stack ? String(error.stack) : undefined\n // A webview or extension that evaluated its own code into our page —\n // see `isInjectedThirdPartyFrame`. Nothing we ship can be changed in\n // response, so it is dropped on the same test as `Script error.`.\n // Judged on the WHOLE stack, before the clamp: a frame of ours past the\n // clamp still makes the error ours.\n if (fullStack && isInjectedThirdPartyFrame(fullStack, pageUrl)) return\n const stack = fullStack ? clamp(fullStack, MAX_STACK) : undefined\n enqueue({\n // MARKED, not dropped: a translator causes these and so does a real\n // render divergence, and only a rate tells them apart.\n kind: isHydrationMismatch(message) ? 'hydration' : 'error',\n message,\n stack,\n source: scrubUrl(event.filename) || undefined,\n line: typeof event.lineno === 'number' ? event.lineno : undefined,\n col: typeof event.colno === 'number' ? event.colno : undefined,\n url: pageUrl,\n })\n } catch {\n // Never rethrow from an error handler.\n }\n })\n\n window.addEventListener('unhandledrejection', (event) => {\n try {\n const reason = event.reason as Error | undefined\n const message = clamp(describeRejectionReason(event.reason), MAX_MESSAGE)\n if (!message) return\n enqueue({\n kind: 'unhandledrejection',\n message,\n stack: reason?.stack ? clamp(reason.stack, MAX_STACK) : undefined,\n url: scrubUrl(window.location.href),\n })\n } catch {\n // Never rethrow from an error handler.\n }\n })\n\n // A batch waiting out its debounce when the page hides would be lost;\n // `pagehide`/`visibilitychange` are the last reliable moments to send.\n window.addEventListener('pagehide', flush)\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') flush()\n })\n}\n"],"names":["isForeignScriptUrl","stackFrameUrls","MAX_MESSAGE","MAX_STACK","FLUSH_DELAY_MS","scrubUrl","raw","url","URL","String","window","location","href","origin","pathname","clamp","value","max","slice","isInjectedThirdPartyFrame","stack","documentUrl","urls","length","every","HYDRATION_MINIFIED","HYDRATION_TEXT","isHydrationMismatch","message","test","describeRejectionReason","reason","shape","Error","undefined","named","map","part","trim","filter","Boolean","join","printed","keys","Object","installed","publishEvent","redispatchCaughtError","reportHandledError","error","options","thrown","kind","installErrorBeacon","endpoint","sampleRate","maxPerPage","Math","random","seen","Set","queued","sent","timer","flush","batch","body","JSON","stringify","events","navigator","sendBeacon","fetch","method","keepalive","headers","catch","enqueue","event","key","split","has","add","push","setTimeout","addEventListener","pageUrl","fullStack","source","filename","line","lineno","col","colno","document","visibilityState"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/error-beacon.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * First-party browser error beacon (AGL-1538).\n *\n * Crashlytics does not exist for web, and adding a third-party error vendor\n * is a subprocessor-list decision that was explicitly deferred. This is the\n * first-party alternative: `window.onerror` / `unhandledrejection` handlers\n * that batch uncaught failures to the app's own `/api/errors` route, which\n * forwards them to Google Cloud Error Reporting — a processor already on the\n * list, alerting through the GCP stack that already pages (AGL-1502).\n *\n * Design constraints, in order:\n *\n * - **It must never become the outage.** Everything is wrapped; a failure to\n * report is silence, not a thrown error. Batches are capped per page so an\n * error thrown in a loop cannot DDoS our own API — after `maxPerPage`\n * events the beacon disarms for the rest of the pageview.\n * - **No PII.** URLs are scrubbed to origin + pathname (query strings and\n * fragments carry tokens and search terms), no user id, no cookies —\n * the payload is the error text and where in the CODE it happened.\n * Cross-origin scripts surface as the browser's opaque \"Script error.\"\n * with no stack; those are dropped since they cannot be acted on.\n * - **Dedupe.** One page throwing the same error on every frame reports it\n * once.\n *\n * Framework-free on purpose: the console mounts it from its root layout, the\n * tenant runtime from its own, and neither needs React here. Deliberately NO\n * 'use client' directive — inside this shared lib the directive forks the\n * module graph (AGL-52); every importer is already a client module.\n */\n\nimport { isCrossPoolDesync } from './cross-pool-desync'\nimport { isForeignScriptUrl, stackFrameUrls } from './foreign-script'\nimport { isStaleBuildError, recoverStaleBuildRejection } from './stale-build-error'\n\nexport interface ErrorBeaconEvent {\n /**\n * Which handler caught it — 'error' | 'unhandledrejection' — or the\n * family it was labeled with: 'hydration', {@link AUTH_DESYNC_KIND},\n * {@link CHUNK_LOAD_KIND}, or a caller's own kind for a handled error.\n * Lands at `jsonPayload.kind`, where the alert policies filter on it.\n */\n kind: string\n /** Error message, clamped. */\n message: string\n /** Stack trace when the thrown value carried one, clamped. */\n stack?: string\n /** Script URL for stackless `window.onerror` events, scrubbed. */\n source?: string\n line?: number\n col?: number\n /** Page URL, scrubbed to origin + pathname. */\n url: string\n}\n\nexport interface ErrorBeaconOptions {\n /** POST target; same-origin. Default `/api/errors`. */\n endpoint?: string\n /** 0..1 — fraction of pageviews that report at all. Default 1. */\n sampleRate?: number\n /** Max events reported per pageview before the beacon disarms. */\n maxPerPage?: number\n}\n\nconst MAX_MESSAGE = 1_024\nconst MAX_STACK = 8_192\nconst FLUSH_DELAY_MS = 2_000\n\n/** Origin + pathname only — query strings and fragments never leave. */\nfunction scrubUrl(raw: string | null | undefined): string {\n if (!raw) return ''\n try {\n const url = new URL(String(raw), window.location.href)\n return `${url.origin}${url.pathname}`\n } catch {\n return ''\n }\n}\n\nfunction clamp(value: unknown, max: number): string {\n return String(value ?? '').slice(0, max)\n}\n\n/**\n * Was this thrown by a script somebody ELSE evaluated into our page?\n *\n * Three tells, all read off the frames' positions and none off a function\n * name — a name would be a denylist needing a new entry per vendor.\n *\n * **Every frame is the DOCUMENT.** Measured 2026-09-02 (AGL-2523) on\n * aglyn.com/pricing, reported as an error of ours:\n *\n * sendDataToNative@https://aglyn.com/pricing:1:1325\n * sendPageHideMessage@https://aglyn.com/pricing:1:4139\n * @https://aglyn.com/pricing:1:6257\n *\n * `sendDataToNative` is the Meta in-app browser's native bridge, injected by\n * the Facebook/Instagram webview. In WebKit's format the code was evaluated\n * inline, so every frame is the document rather than a script we served.\n *\n * **Every frame is under a FOREIGN scheme.** Measured 2026-09-10 (AGL-2786) on\n * aglyn.com, the same bridge in the Android webview:\n *\n * at sendDataToNative (iabjs://navigation_performance_logger_android:1:10632)\n *\n * That webview names its scripts under its own `iabjs://` scheme, and\n * extensions do the same under theirs — see `FOREIGN_SCRIPT_SCHEMES`.\n *\n * **Every frame is a script with NO URL** (AGL-3423). Measured on the\n * sign-up page and on aglyn.com/solutions/agencies:\n *\n * at eval (<anonymous>)\n * at predicate (eval at evaluate (:234:30), <anonymous>:11:37)\n *\n * at <anonymous>:1:54\n * at <anonymous>:1:64\n *\n * An automation driver's `evaluate` and a snippet pasted into devtools. Every\n * script we serve has a URL — a chunk, a CDN asset, or the document for an\n * inline one — so a frame whose position is `<anonymous>:line:col`, or code\n * `eval`'d by such a frame, was not served by us. See\n * {@link anonymousScriptFrameCount} for exactly which frames count.\n *\n * ⚑ Deliberately `every`, and deliberately compared against the document\n * rather than against our asset path. A rule like \"no frame under\n * `/_next/static/`\" would delete EVERY error from a self-hosted deployment\n * that serves its assets from a CDN, because none of its frames would match.\n * Comparing to the document cannot fail that way: a CDN frame is not the\n * document either, so it keeps the report.\n *\n * A stack may mix the tells frame by frame. Nothing we ship can be fixed in\n * response to any of them, which is the same test the opaque `Script error.`\n * cut already applies.\n *\n * The cost is honest and small: a throw from one of our own inline\n * bootstrap scripts looks the same and is dropped with it. That trade buys a\n * rule that needs no maintenance as new webviews and extensions appear.\n */\nexport function isInjectedThirdPartyFrame(\n stack: string,\n documentUrl: string,\n): boolean {\n const urls = stackFrameUrls(stack)\n // No frames parsed is not evidence of anything — keep the report. A stack\n // with neither a URL nor an anonymous-script frame is exactly that: an\n // empty frame list must never read as \"every frame is injected\".\n if (!urls.length && !anonymousScriptFrameCount(stack)) return false\n // Anonymous frames need no test of their own — they are injected by\n // definition — so `every` over the URLs is `every` over the whole stack.\n // One URL of ours, even as the origin of an `eval`, keeps the report.\n return urls.every(\n (url) => isForeignScriptUrl(url) || scrubUrl(url) === documentUrl,\n )\n}\n\n/** A frame line, in V8's `at …` format or WebKit/Firefox's `fn@location`. */\nconst STACK_FRAME_LINE = /^\\s*at\\s|@/\n\n/**\n * A position in a script that has no URL.\n *\n * - `<anonymous>:line:col` — V8's name for such a script, both for a top-level\n * snippet and as the position of code run through `eval`/`new Function`.\n * - `eval at …` — V8's origin of `eval`'d code. When OUR script ran the eval\n * its URL is inside this origin, `stackFrameUrls` reads it, and the report\n * is kept; that is how the marketing plugin's `runJs` step stays reported.\n * - `debugger eval code:line:col` — Firefox's devtools console, in the\n * `fn@location` format WebKit also uses.\n *\n * ⚑ A BARE `(<anonymous>)` with no line and column is NOT one of these. It is\n * how V8 prints a builtin — `at Array.forEach (<anonymous>)`,\n * `at JSON.parse (<anonymous>)` — and a builtin is called by whoever called\n * it, including us.\n */\nconst ANONYMOUS_SCRIPT_POSITION =\n /<anonymous>:\\d+:\\d+|\\beval at\\s|\\bdebugger eval code:\\d+:\\d+/\n\n/** How many frames of this stack are in a script with no URL at all. */\nexport function anonymousScriptFrameCount(stack: string): number {\n let count = 0\n for (const line of stack.split('\\n')) {\n if (STACK_FRAME_LINE.test(line) && ANONYMOUS_SCRIPT_POSITION.test(line)) {\n count += 1\n }\n }\n return count\n}\n\n/**\n * Browser notices that are not failures, and that no fix of ours could act on.\n *\n * `ResizeObserver loop completed with undelivered notifications` (and its older\n * wording, `ResizeObserver loop limit exceeded`) is the browser saying it\n * deferred some resize callbacks to the next frame. Nothing threw: the event\n * carries no error object and no stack, and every observer is still\n * delivered. It arrived from the Besigner on 2026-09-26 and paged. Dropped, on\n * the browser's exact wording.\n */\nconst BENIGN_BROWSER_NOTICE =\n /^(?:Uncaught )?(?:Error: )?ResizeObserver loop (?:completed with undelivered notifications|limit exceeded)/\n\nexport function isBenignBrowserNotice(message: string): boolean {\n return BENIGN_BROWSER_NOTICE.test(message)\n}\n\n/**\n * `kind` for Firebase's `auth/tenant-id-mismatch` — a sibling tab signed in to\n * another account pool (AGL-3280). The console recovers the tab by reloading\n * it once it is hidden and deliberately leaves the rejection unhandled so it\n * is still seen; this label is what lets it be seen by RATE instead of paging\n * on each of the several rejections one storage event raises.\n */\nexport const AUTH_DESYNC_KIND = 'auth-desync'\n\n/**\n * `kind` for a chunk the document names and the origin no longer serves\n * (AGL-3279). Every boundary reloads once for it; what still arrives is the\n * failure the reload did not cure. One of those is a visitor on a bad\n * connection; a burst of them is a broken deploy, which only a rate can tell.\n */\nexport const CHUNK_LOAD_KIND = 'chunk-load'\n\n/**\n * The label for a fault we RECOVER from and still want to see, or undefined.\n *\n * These could be ours, so unlike an injected stack they are never dropped:\n * they are written at full severity under their own `kind`, the per-entry\n * policy excludes that kind, and a rate policy watches it — the same split\n * `hydration` already has.\n */\nexport function recoveredErrorKind(error: unknown): string | undefined {\n try {\n if (isCrossPoolDesync(error)) return AUTH_DESYNC_KIND\n if (isStaleBuildError(error)) return CHUNK_LOAD_KIND\n } catch {\n // A getter that throws leaves the event unlabeled, never unreported.\n }\n return undefined\n}\n\n/**\n * React's hydration-mismatch family, which a page TRANSLATOR causes and a\n * real render divergence also causes.\n *\n * These are `onRecoverableError` reports, not crashes: React has already\n * re-rendered on the client and the visitor has a working page. They arrive\n * here as uncaught errors only because React re-throws them to `reportError`.\n *\n * They are marked rather than dropped, and the distinction is the whole\n * design. Dropping would hide a real hydration regression, which is a genuine\n * and expensive bug; the entries stay in `client-errors` at full severity and\n * still group in Error Reporting. What the mark buys is that the log-match\n * policy can stop paging on a single report, while a rate-based policy on the\n * same mark still catches a systemic one.\n *\n * ⚠️ THE MARK IS NOT A VERDICT, and the one cluster this repo has measured is\n * why. Eight #418 reports arrived inside a nine-minute window on 2026-09-01,\n * on one build, and the three pages they came from were exactly the three\n * carrying a form — `/`, `/pricing` and the solutions pages reported nothing\n * in the same window, which no browser-side rewrite would respect. A placed\n * form was expanding inside its own grafted subtree, so every page carrying\n * one shipped six nested `<form>` elements; nested forms are invalid HTML, the\n * parser dropped the inner ones, and the client tree disagreed with the server\n * tree. The visible cost was a submission the route never received, because\n * the native submit came from an unhandled ancestor and the browser fell back\n * to a GET with the visitor's name, email and message in the address bar. The\n * reports stopped because the nesting was fixed, roughly a quarter of an hour\n * after the last one.\n *\n * So a rate low enough not to page is a reason to READ the entry — the page\n * it names, and whether the set of pages has a shape — never a reason to\n * assume somebody's extension.\n */\nconst HYDRATION_MINIFIED = /Minified React error #(?:418|423|425)\\b/\nconst HYDRATION_TEXT =\n /Hydration failed because|Text content does not match server-rendered HTML|There was an error while hydrating/\n\nexport function isHydrationMismatch(message: string): boolean {\n return HYDRATION_MINIFIED.test(message) || HYDRATION_TEXT.test(message)\n}\n\n/**\n * WHAT A REJECTED PROMISE ACTUALLY CARRIED (AGL-3279).\n *\n * `unhandledrejection` hands over whatever was passed to `reject`, and only\n * an `Error` brings a message and a stack. A rejection with anything else —\n * an API's `{ code, message }` object, a `DOMException` from an aborted\n * fetch, a bare string, a `Response` — used to be reported as the literal\n * words \"Unhandled promise rejection\" with no stack and no other field,\n * which names the handler rather than the failure. One such report arrived\n * on 2026-09-21 from the Besigner editor and there is nothing in it to act\n * on: no message, no stack, no code, nothing but the page.\n *\n * So the value is DESCRIBED rather than defaulted. In order of how much a\n * reader can do with it: the error's own message; a string as itself; a\n * `name`/`code`/`message` shape assembled from whatever of those it has —\n * the shape every Firebase, DOM and fetch rejection takes; the value's own\n * `toString` when it says more than `[object Object]`; and last its own\n * keys, which at least name what kind of thing rejected.\n *\n * Nothing here may throw: a getter on the reason can, `toString` can, and\n * a describer that throws inside the rejection handler loses the report it\n * was called to improve.\n */\nexport function describeRejectionReason(reason: unknown): string {\n try {\n if (reason instanceof Error && reason.message) return reason.message\n if (typeof reason === 'string') return reason\n if (reason === null || reason === undefined) {\n return `Unhandled promise rejection (${String(reason)})`\n }\n if (typeof reason !== 'object') {\n return `Unhandled promise rejection (${typeof reason}: ${String(reason)})`\n }\n const shape = reason as Record<string, unknown>\n const named = [\n shape['name'] ?? shape['code'] ?? '',\n shape['message'] ?? shape['statusText'] ?? '',\n ]\n .map((part) => String(part ?? '').trim())\n .filter(Boolean)\n if (named.length) return named.join(': ')\n const printed = String(reason)\n if (printed && printed !== '[object Object]') return printed\n const keys = Object.keys(shape).slice(0, 12).join(', ')\n return keys\n ? `Unhandled promise rejection (object with ${keys})`\n : 'Unhandled promise rejection (empty object)'\n } catch {\n return 'Unhandled promise rejection (undescribable)'\n }\n}\n\n/**\n * How many frames a thrown error keeps, on a pageview that reports (AGL-3423).\n *\n * V8 keeps ten by default, and ten is not enough to find where a render loop\n * STARTED. The Besigner's one React #185 report (2026-09-24) was a\n * react-final-form field's `setState` inside final-form's `notify` loop, and\n * every one of its ten frames was inside those two libraries: the component\n * whose update fed the loop was cut off below them. Fifty reaches past a\n * form library's own frames to ours, and still fits the {@link MAX_STACK}\n * clamp at the length a minified frame line has.\n */\nexport const BEACON_STACK_TRACE_LIMIT = 50\n\n/**\n * Raises the engine's frame limit to `limit`, never lowers it. V8 and\n * JavaScriptCore read `Error.stackTraceLimit`; an engine that does not has no\n * such number, and is left without one rather than handed a property it\n * ignores. It applies to errors created after the call, which is why the\n * beacon sets it at install, at module scope of the app's first client chunk.\n */\nexport function raiseStackTraceLimit(limit: number): void {\n try {\n const engine = Error as ErrorConstructor & { stackTraceLimit?: number }\n const current = engine.stackTraceLimit\n if (typeof current !== 'number' || current >= limit) return\n engine.stackTraceLimit = limit\n } catch {\n // A frozen or exotic `Error` keeps its own limit.\n }\n}\n\nlet installed = false\n\n/**\n * The live beacon's `enqueue`, published for {@link reportHandledError}.\n *\n * Null until `installErrorBeacon` runs, and null forever on a surface that\n * never installs one — so a caught error reported from a page with no beacon\n * is silently dropped rather than throwing inside somebody's error handler.\n */\nlet publishEvent: ((event: ErrorBeaconEvent) => void) | null = null\n\n/**\n * Re-export so `error-beacon` stays the one name a caller has to know for\n * browser error reporting. The definition lives in its own module because a\n * boundary that imports it must not pull the installer below into a chunk\n * every visitor downloads.\n */\nexport { redispatchCaughtError } from './redispatch-caught-error'\n\n/**\n * Report an error the code ALREADY CAUGHT.\n *\n * The two window handlers below see only what nothing caught. A `catch` that\n * swallows its error is invisible to them by construction, which is the whole\n * failure mode this exists for: a background write that can only fail\n * silently is one that stays broken for as long as nobody thinks to look.\n *\n * It rides the same queue as an uncaught error, which is the point — the\n * dedupe collapses a failure that repeats on every edit into one report, and\n * `maxPerPage` bounds it, so a call site in a loop cannot turn a broken\n * feature into a flood. Reporting is never worth an exception of its own, so\n * every path here returns rather than throws.\n */\nexport function reportHandledError(\n error: unknown,\n options?: { kind?: string },\n): void {\n try {\n if (!publishEvent) return\n const thrown = error as Error | undefined\n const message = clamp(\n thrown?.message ?? (typeof error === 'string' ? error : ''),\n MAX_MESSAGE,\n )\n if (!message) return\n publishEvent({\n kind: clamp(options?.kind ?? 'handled', 32),\n message,\n stack: thrown?.stack ? clamp(thrown.stack, MAX_STACK) : undefined,\n url: scrubUrl(window.location.href),\n })\n } catch {\n // An observer that throws is worse than one that misses an event.\n }\n}\n\n/**\n * Installs the handlers once per page. Safe to call from module scope of a\n * client bundle: it no-ops during SSR and on repeat calls.\n */\nexport function installErrorBeacon(options?: ErrorBeaconOptions): void {\n if (typeof window === 'undefined' || installed) return\n installed = true\n\n const endpoint = options?.endpoint ?? '/api/errors'\n const sampleRate = options?.sampleRate ?? 1\n const maxPerPage = options?.maxPerPage ?? 10\n // Only a sampled pageview REPORTS. Every pageview recovers a stale build\n // (the rejection handler below), because a tab left on a dead deploy is a\n // visitor's problem whether or not its errors are counted.\n const sampled = Math.random() < sampleRate\n if (sampled) raiseStackTraceLimit(BEACON_STACK_TRACE_LIMIT)\n\n const seen = new Set<string>()\n let queued: ErrorBeaconEvent[] = []\n let sent = 0\n let timer: ReturnType<typeof setTimeout> | null = null\n\n const flush = () => {\n timer = null\n if (!queued.length) return\n const batch = queued\n queued = []\n try {\n const body = JSON.stringify({ events: batch })\n // sendBeacon survives unloads and never blocks; keepalive fetch is the\n // fallback for browsers that refuse the payload.\n if (!navigator.sendBeacon?.(endpoint, body)) {\n void fetch(endpoint, {\n method: 'POST',\n body,\n keepalive: true,\n headers: { 'Content-Type': 'application/json' },\n }).catch((): undefined => undefined)\n }\n } catch {\n // Reporting never breaks the page.\n }\n }\n\n const enqueue = (event: ErrorBeaconEvent) => {\n if (!sampled || sent >= maxPerPage) return\n // Message + first stack line: enough identity to collapse a render loop\n // without collapsing distinct errors that share a message.\n const key = `${event.message}\\x00${(event.stack ?? '').split('\\n', 2).join('\\n')}`\n if (seen.has(key)) return\n seen.add(key)\n sent += 1\n queued.push(event)\n if (!timer) timer = setTimeout(flush, FLUSH_DELAY_MS)\n }\n // Null on an unsampled pageview, so it reports nothing by either door\n // rather than one by one and none by the other.\n publishEvent = sampled ? enqueue : null\n\n window.addEventListener('error', (event) => {\n try {\n const error = event.error as Error | undefined\n const message = clamp(error?.message ?? event.message, MAX_MESSAGE)\n // Cross-origin scripts yield an opaque \"Script error.\" with nothing\n // actionable attached; reporting it would only create a noisy group.\n if (!message || message === 'Script error.') return\n if (isBenignBrowserNotice(message)) return\n const pageUrl = scrubUrl(window.location.href)\n const fullStack = error?.stack ? String(error.stack) : undefined\n // A webview or extension that evaluated its own code into our page —\n // see `isInjectedThirdPartyFrame`. Nothing we ship can be changed in\n // response, so it is dropped on the same test as `Script error.`.\n // Judged on the WHOLE stack, before the clamp: a frame of ours past the\n // clamp still makes the error ours.\n if (fullStack && isInjectedThirdPartyFrame(fullStack, pageUrl)) return\n const stack = fullStack ? clamp(fullStack, MAX_STACK) : undefined\n enqueue({\n // MARKED, not dropped: a translator causes a hydration mismatch and\n // so does a real render divergence, and a recovered fault is still a\n // fault. Only a rate tells either apart from noise.\n kind:\n recoveredErrorKind(error ?? { message }) ??\n (isHydrationMismatch(message) ? 'hydration' : 'error'),\n message,\n stack,\n source: scrubUrl(event.filename) || undefined,\n line: typeof event.lineno === 'number' ? event.lineno : undefined,\n col: typeof event.colno === 'number' ? event.colno : undefined,\n url: pageUrl,\n })\n } catch {\n // Never rethrow from an error handler.\n }\n })\n\n window.addEventListener('unhandledrejection', (event) => {\n try {\n // An `import()` of a chunk this document names and the origin dropped,\n // which no boundary saw. Recovered by a reload once the tab is hidden,\n // and, like a boundary's reload, not reported: see\n // `recoverStaleBuildRejection`. A tab whose recovery is spent still\n // reports it, as `chunk-load`.\n if (recoverStaleBuildRejection(event.reason)) return\n const reason = event.reason as Error | undefined\n const message = clamp(describeRejectionReason(event.reason), MAX_MESSAGE)\n if (!message) return\n const pageUrl = scrubUrl(window.location.href)\n const fullStack = reason?.stack ? String(reason.stack) : undefined\n // The same injected-code drop as an uncaught error: a rejection raised\n // by a devtools snippet or an automation driver's `evaluate` is no more\n // ours for having been a promise.\n if (fullStack && isInjectedThirdPartyFrame(fullStack, pageUrl)) return\n enqueue({\n kind: recoveredErrorKind(event.reason) ?? 'unhandledrejection',\n message,\n stack: fullStack ? clamp(fullStack, MAX_STACK) : undefined,\n url: pageUrl,\n })\n } catch {\n // Never rethrow from an error handler.\n }\n })\n\n // A batch waiting out its debounce when the page hides would be lost;\n // `pagehide`/`visibilitychange` are the last reliable moments to send.\n window.addEventListener('pagehide', flush)\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') flush()\n })\n}\n"],"names":["isCrossPoolDesync","isForeignScriptUrl","stackFrameUrls","isStaleBuildError","recoverStaleBuildRejection","MAX_MESSAGE","MAX_STACK","FLUSH_DELAY_MS","scrubUrl","raw","url","URL","String","window","location","href","origin","pathname","clamp","value","max","slice","isInjectedThirdPartyFrame","stack","documentUrl","urls","length","anonymousScriptFrameCount","every","STACK_FRAME_LINE","ANONYMOUS_SCRIPT_POSITION","count","line","split","test","BENIGN_BROWSER_NOTICE","isBenignBrowserNotice","message","AUTH_DESYNC_KIND","CHUNK_LOAD_KIND","recoveredErrorKind","error","undefined","HYDRATION_MINIFIED","HYDRATION_TEXT","isHydrationMismatch","describeRejectionReason","reason","shape","Error","named","map","part","trim","filter","Boolean","join","printed","keys","Object","BEACON_STACK_TRACE_LIMIT","raiseStackTraceLimit","limit","engine","current","stackTraceLimit","installed","publishEvent","redispatchCaughtError","reportHandledError","options","thrown","kind","installErrorBeacon","endpoint","sampleRate","maxPerPage","sampled","Math","random","seen","Set","queued","sent","timer","flush","batch","body","JSON","stringify","events","navigator","sendBeacon","fetch","method","keepalive","headers","catch","enqueue","event","key","has","add","push","setTimeout","addEventListener","pageUrl","fullStack","source","filename","lineno","col","colno","document","visibilityState"],"mappings":"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"}
@@ -116,27 +116,27 @@ export declare function repeatedRecords(node: unknown, dataset: RepeatableDatase
116
116
  /**
117
117
  * Does this tree contain anything {@link expandRepeatables} would expand?
118
118
  *
119
- * The datasets read is the largest on the render path — up to two pages of
120
- * {@link REPEAT_MAX_RECORDS} records for every dataset a page repeats over —
121
- * and a page that repeats over nothing should pay none of it (AGL-1440).
119
+ * The rows read is the largest on the render path — up to two pages of
120
+ * {@link REPEAT_MAX_RECORDS} records for every key a page repeats over — and a
121
+ * page that repeats over nothing should pay none of it (AGL-1440).
122
122
  *
123
123
  * Any gate on that read has to ask EXACTLY the question the expansion asks,
124
- * which is why this and {@link repeatDatasetKeys} share the one predicate
124
+ * which is why this and {@link repeatKeys} share the one predicate
125
125
  * `expandRepeatables` looks keys up with, {@link repeatKey}. A gate that is
126
126
  * even slightly stricter than the expansion is not a saving: it is a published
127
127
  * page that quietly renders one template row where the author put a list.
128
128
  */
129
129
  export declare function hasRepeatableNodes(nodes: Record<NodeId, unknown> | null | undefined): boolean;
130
130
  /**
131
- * Every dataset key this tree repeats over — a dataset id or a display name,
132
- * exactly as {@link expandRepeatables} looks it up — sorted and without
133
- * repeats.
131
+ * Every key this tree repeats over, exactly as {@link expandRepeatables} looks
132
+ * it up — sorted and without repeats.
134
133
  *
135
- * What the tenant compose reads, so a page loads the datasets it renders and
136
- * not every dataset its site may see. Built on the same predicate as
134
+ * What the tenant compose asks the repeat-rows contract for
135
+ * (`plugin-manager/repeat-rows.ts`), so a page loads the rows it renders and
136
+ * not everything its site may see. Built on the same predicate as
137
137
  * {@link hasRepeatableNodes} for the reason given there.
138
138
  */
139
- export declare function repeatDatasetKeys(nodes: Record<NodeId, unknown> | null | undefined): string[];
139
+ export declare function repeatKeys(nodes: Record<NodeId, unknown> | null | undefined): string[];
140
140
  /**
141
141
  * Repeats (AGL-103, AGL-3111): any node carrying `props.repeatDataset` (a
142
142
  * dataset id or display name) renders once per record of that dataset, with
@@ -14,7 +14,7 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */ import { _ as _extends } from "@swc/helpers/_/_extends";
17
- import { applyDatasetQuery, parseDatasetFilter, parseDatasetSort } from "./dataset-query.js";
17
+ import { applyRepeatQuery, parseRepeatFilter, parseRepeatSort } from "./repeat-query.js";
18
18
  /** Namespaces cloned template ids per container/record. */ export const REPEAT_NODE_ID_PREFIX = 'rep__';
19
19
  /**
20
20
  * `{{item.field}}` token, plus an optional single reference hop
@@ -155,10 +155,10 @@ function substituteValue(value, context) {
155
155
  */ export function repeatedRecords(node, dataset) {
156
156
  var _ref, _props_repeatFilter, _props_repeatSort, _ref1;
157
157
  const props = (_ref = node == null ? void 0 : node.props) != null ? _ref : {};
158
- const where = parseDatasetFilter(String((_props_repeatFilter = props['repeatFilter']) != null ? _props_repeatFilter : ''));
159
- const orderBy = parseDatasetSort(String((_props_repeatSort = props['repeatSort']) != null ? _props_repeatSort : ''));
158
+ const where = parseRepeatFilter(String((_props_repeatFilter = props['repeatFilter']) != null ? _props_repeatFilter : ''));
159
+ const orderBy = parseRepeatSort(String((_props_repeatSort = props['repeatSort']) != null ? _props_repeatSort : ''));
160
160
  const limit = Number(props['repeatLimit']);
161
- return applyDatasetQuery(dataset == null ? void 0 : dataset.model, (_ref1 = dataset == null ? void 0 : dataset.records) != null ? _ref1 : [], _extends({}, where ? {
161
+ return applyRepeatQuery((_ref1 = dataset == null ? void 0 : dataset.records) != null ? _ref1 : [], _extends({}, where ? {
162
162
  where: [
163
163
  where
164
164
  ]
@@ -169,12 +169,12 @@ function substituteValue(value, context) {
169
169
  /**
170
170
  * Does this tree contain anything {@link expandRepeatables} would expand?
171
171
  *
172
- * The datasets read is the largest on the render path — up to two pages of
173
- * {@link REPEAT_MAX_RECORDS} records for every dataset a page repeats over —
174
- * and a page that repeats over nothing should pay none of it (AGL-1440).
172
+ * The rows read is the largest on the render path — up to two pages of
173
+ * {@link REPEAT_MAX_RECORDS} records for every key a page repeats over — and a
174
+ * page that repeats over nothing should pay none of it (AGL-1440).
175
175
  *
176
176
  * Any gate on that read has to ask EXACTLY the question the expansion asks,
177
- * which is why this and {@link repeatDatasetKeys} share the one predicate
177
+ * which is why this and {@link repeatKeys} share the one predicate
178
178
  * `expandRepeatables` looks keys up with, {@link repeatKey}. A gate that is
179
179
  * even slightly stricter than the expansion is not a saving: it is a published
180
180
  * page that quietly renders one template row where the author put a list.
@@ -183,14 +183,14 @@ function substituteValue(value, context) {
183
183
  return Object.values(nodes).some((node)=>repeatKey(node) !== '');
184
184
  }
185
185
  /**
186
- * Every dataset key this tree repeats over — a dataset id or a display name,
187
- * exactly as {@link expandRepeatables} looks it up — sorted and without
188
- * repeats.
186
+ * Every key this tree repeats over, exactly as {@link expandRepeatables} looks
187
+ * it up — sorted and without repeats.
189
188
  *
190
- * What the tenant compose reads, so a page loads the datasets it renders and
191
- * not every dataset its site may see. Built on the same predicate as
189
+ * What the tenant compose asks the repeat-rows contract for
190
+ * (`plugin-manager/repeat-rows.ts`), so a page loads the rows it renders and
191
+ * not everything its site may see. Built on the same predicate as
192
192
  * {@link hasRepeatableNodes} for the reason given there.
193
- */ export function repeatDatasetKeys(nodes) {
193
+ */ export function repeatKeys(nodes) {
194
194
  const keys = new Set();
195
195
  for (const node of Object.values(nodes != null ? nodes : {})){
196
196
  const key = repeatKey(node);