@aglyn/aglyn 1.0.0-beta.217 → 1.0.0-beta.219

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 (348) hide show
  1. package/package.json +14 -14
  2. package/src/lib/app-utils/actions.d.ts +25 -374
  3. package/src/lib/app-utils/actions.js +101 -561
  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/admin-audit-index.js +2 -2
  9. package/src/lib/app-utils/admin-audit-index.js.map +1 -1
  10. package/src/lib/app-utils/analytics-events.d.ts +11 -2
  11. package/src/lib/app-utils/analytics-events.js +11 -2
  12. package/src/lib/app-utils/analytics-events.js.map +1 -1
  13. package/src/lib/app-utils/analytics-provider.d.ts +182 -0
  14. package/src/lib/app-utils/analytics-provider.js +133 -0
  15. package/src/lib/app-utils/analytics-provider.js.map +1 -0
  16. package/src/lib/app-utils/api-plugins.d.ts +46 -0
  17. package/src/lib/app-utils/api-plugins.js +19 -0
  18. package/src/lib/app-utils/api-plugins.js.map +1 -1
  19. package/src/lib/app-utils/{marketplace-overrides.d.ts → artifact-overrides.d.ts} +9 -6
  20. package/src/lib/app-utils/{marketplace-overrides.js → artifact-overrides.js} +10 -7
  21. package/src/lib/app-utils/artifact-overrides.js.map +1 -0
  22. package/src/lib/app-utils/{marketplace-provenance.d.ts → artifact-provenance.d.ts} +12 -10
  23. package/src/lib/app-utils/{marketplace-provenance.js → artifact-provenance.js} +9 -7
  24. package/src/lib/app-utils/artifact-provenance.js.map +1 -0
  25. package/src/lib/app-utils/assist-credits.js +2 -1
  26. package/src/lib/app-utils/assist-credits.js.map +1 -1
  27. package/src/lib/app-utils/binding-token-catalog.d.ts +5 -13
  28. package/src/lib/app-utils/binding-token-catalog.js +17 -41
  29. package/src/lib/app-utils/binding-token-catalog.js.map +1 -1
  30. package/src/lib/app-utils/binding-tokens.js +1 -1
  31. package/src/lib/app-utils/binding-tokens.js.map +1 -1
  32. package/src/lib/app-utils/brand-support-line.d.ts +36 -0
  33. package/src/lib/app-utils/brand-support-line.js +38 -0
  34. package/src/lib/app-utils/brand-support-line.js.map +1 -0
  35. package/src/lib/app-utils/campaign-touch.d.ts +5 -5
  36. package/src/lib/app-utils/campaign-touch.js +8 -8
  37. package/src/lib/app-utils/campaign-touch.js.map +1 -1
  38. package/src/lib/app-utils/collection-entries.d.ts +2 -2
  39. package/src/lib/app-utils/collection-entries.js.map +1 -1
  40. package/src/lib/app-utils/consent-group-change.d.ts +4 -0
  41. package/src/lib/app-utils/consent-group-change.js.map +1 -1
  42. package/src/lib/app-utils/console-record-links.d.ts +10 -89
  43. package/src/lib/app-utils/console-record-links.js +3 -107
  44. package/src/lib/app-utils/console-record-links.js.map +1 -1
  45. package/src/lib/app-utils/console-routes.d.ts +16 -7
  46. package/src/lib/app-utils/console-routes.js +9 -3
  47. package/src/lib/app-utils/console-routes.js.map +1 -1
  48. package/src/lib/app-utils/contacts.d.ts +23 -1
  49. package/src/lib/app-utils/contacts.js +21 -5
  50. package/src/lib/app-utils/contacts.js.map +1 -1
  51. package/src/lib/app-utils/cross-pool-desync.d.ts +39 -0
  52. package/src/lib/app-utils/cross-pool-desync.js +47 -0
  53. package/src/lib/app-utils/cross-pool-desync.js.map +1 -0
  54. package/src/lib/app-utils/csv-upload.d.ts +29 -0
  55. package/src/lib/app-utils/csv-upload.js +29 -0
  56. package/src/lib/app-utils/csv-upload.js.map +1 -0
  57. package/src/lib/app-utils/dataset-models.d.ts +5 -5
  58. package/src/lib/app-utils/dataset-models.js +19 -2
  59. package/src/lib/app-utils/dataset-models.js.map +1 -1
  60. package/src/lib/app-utils/datasets.d.ts +65 -11
  61. package/src/lib/app-utils/datasets.js +74 -11
  62. package/src/lib/app-utils/datasets.js.map +1 -1
  63. package/src/lib/app-utils/docs-deflection.d.ts +6 -6
  64. package/src/lib/app-utils/docs-deflection.js.map +1 -1
  65. package/src/lib/app-utils/docs-help.generated.d.ts +12 -6
  66. package/src/lib/app-utils/docs-help.generated.js +21 -6
  67. package/src/lib/app-utils/docs-help.generated.js.map +1 -1
  68. package/src/lib/app-utils/docs-index.generated.d.ts +2 -2
  69. package/src/lib/app-utils/docs-index.generated.js +514 -318
  70. package/src/lib/app-utils/docs-index.generated.js.map +1 -1
  71. package/src/lib/app-utils/docs-retrieval.d.ts +3 -3
  72. package/src/lib/app-utils/docs-retrieval.js +14 -10
  73. package/src/lib/app-utils/docs-retrieval.js.map +1 -1
  74. package/src/lib/app-utils/duplicate-resource.d.ts +4 -1
  75. package/src/lib/app-utils/duplicate-resource.js +7 -4
  76. package/src/lib/app-utils/duplicate-resource.js.map +1 -1
  77. package/src/lib/app-utils/dynamic-list-rule.d.ts +1 -1
  78. package/src/lib/app-utils/dynamic-list-rule.js.map +1 -1
  79. package/src/lib/app-utils/element-ui.d.ts +1 -1
  80. package/src/lib/app-utils/element-ui.js +1 -1
  81. package/src/lib/app-utils/element-ui.js.map +1 -1
  82. package/src/lib/app-utils/email-starter-policy.js +3 -3
  83. package/src/lib/app-utils/email-starter-policy.js.map +1 -1
  84. package/src/lib/app-utils/entity-picker-context.d.ts +10 -5
  85. package/src/lib/app-utils/entity-picker-context.js.map +1 -1
  86. package/src/lib/app-utils/error-beacon.d.ts +75 -6
  87. package/src/lib/app-utils/error-beacon.js +160 -21
  88. package/src/lib/app-utils/error-beacon.js.map +1 -1
  89. package/src/lib/app-utils/expand-repeatables.d.ts +10 -10
  90. package/src/lib/app-utils/expand-repeatables.js +10 -10
  91. package/src/lib/app-utils/expand-repeatables.js.map +1 -1
  92. package/src/lib/app-utils/host-events.d.ts +82 -0
  93. package/src/lib/app-utils/host-events.js +62 -0
  94. package/src/lib/app-utils/host-events.js.map +1 -0
  95. package/src/lib/app-utils/lockdown.d.ts +33 -1
  96. package/src/lib/app-utils/lockdown.js +45 -4
  97. package/src/lib/app-utils/lockdown.js.map +1 -1
  98. package/src/lib/app-utils/margin-utilization.d.ts +4 -69
  99. package/src/lib/app-utils/margin-utilization.js +82 -69
  100. package/src/lib/app-utils/margin-utilization.js.map +1 -1
  101. package/src/lib/app-utils/node-definition-sanitizer.d.ts +16 -16
  102. package/src/lib/app-utils/node-definition-sanitizer.js +24 -20
  103. package/src/lib/app-utils/node-definition-sanitizer.js.map +1 -1
  104. package/src/lib/app-utils/node-interactions.d.ts +7 -7
  105. package/src/lib/app-utils/node-interactions.js.map +1 -1
  106. package/src/lib/app-utils/notifications.d.ts +78 -47
  107. package/src/lib/app-utils/notifications.js +63 -44
  108. package/src/lib/app-utils/notifications.js.map +1 -1
  109. package/src/lib/app-utils/payments-configured.d.ts +8 -21
  110. package/src/lib/app-utils/payments-configured.js +8 -23
  111. package/src/lib/app-utils/payments-configured.js.map +1 -1
  112. package/src/lib/app-utils/plan-entitlements.d.ts +43 -128
  113. package/src/lib/app-utils/plan-entitlements.js +145 -304
  114. package/src/lib/app-utils/plan-entitlements.js.map +1 -1
  115. package/src/lib/app-utils/platform-brand.d.ts +10 -0
  116. package/src/lib/app-utils/platform-brand.js +14 -3
  117. package/src/lib/app-utils/platform-brand.js.map +1 -1
  118. package/src/lib/app-utils/plugin-api-rate-limit.d.ts +7 -1
  119. package/src/lib/app-utils/plugin-api-rate-limit.js +11 -3
  120. package/src/lib/app-utils/plugin-api-rate-limit.js.map +1 -1
  121. package/src/lib/app-utils/plugin-bundle-checks.js +2 -2
  122. package/src/lib/app-utils/plugin-bundle-checks.js.map +1 -1
  123. package/src/lib/app-utils/plugin-host-events.generated.d.ts +12 -0
  124. package/src/lib/app-utils/plugin-host-events.generated.js +169 -0
  125. package/src/lib/app-utils/plugin-host-events.generated.js.map +1 -0
  126. package/src/lib/app-utils/plugin-release-flags.generated.d.ts +12 -0
  127. package/src/lib/app-utils/plugin-release-flags.generated.js +106 -0
  128. package/src/lib/app-utils/plugin-release-flags.generated.js.map +1 -0
  129. package/src/lib/app-utils/realm-host-surface.generated.js +2 -0
  130. package/src/lib/app-utils/realm-host-surface.generated.js.map +1 -1
  131. package/src/lib/app-utils/release-flags.d.ts +14 -5
  132. package/src/lib/app-utils/release-flags.js +21 -125
  133. package/src/lib/app-utils/release-flags.js.map +1 -1
  134. package/src/lib/app-utils/repeat-sources.d.ts +9 -0
  135. package/src/lib/app-utils/repeat-sources.js.map +1 -1
  136. package/src/lib/app-utils/retained-refusals.d.ts +73 -0
  137. package/src/lib/app-utils/retained-refusals.js +186 -0
  138. package/src/lib/app-utils/retained-refusals.js.map +1 -0
  139. package/src/lib/app-utils/scope-tokens.d.ts +27 -0
  140. package/src/lib/app-utils/scope-tokens.js +61 -0
  141. package/src/lib/app-utils/scope-tokens.js.map +1 -1
  142. package/src/lib/app-utils/screen-link-context.js +3 -3
  143. package/src/lib/app-utils/screen-link-context.js.map +1 -1
  144. package/src/lib/app-utils/screen-route.d.ts +15 -0
  145. package/src/lib/app-utils/screen-route.js +21 -1
  146. package/src/lib/app-utils/screen-route.js.map +1 -1
  147. package/src/lib/app-utils/seo-audit.d.ts +132 -0
  148. package/src/lib/app-utils/seo-audit.js +246 -0
  149. package/src/lib/app-utils/seo-audit.js.map +1 -0
  150. package/src/lib/app-utils/seo-keywords.d.ts +48 -0
  151. package/src/lib/app-utils/seo-keywords.js +60 -0
  152. package/src/lib/app-utils/seo-keywords.js.map +1 -0
  153. package/src/lib/app-utils/seo-page-facts.d.ts +66 -0
  154. package/src/lib/app-utils/seo-page-facts.js +155 -0
  155. package/src/lib/app-utils/seo-page-facts.js.map +1 -0
  156. package/src/lib/app-utils/seo-site-scan.d.ts +126 -0
  157. package/src/lib/app-utils/seo-site-scan.js +162 -0
  158. package/src/lib/app-utils/seo-site-scan.js.map +1 -0
  159. package/src/lib/app-utils/seo-title-variables.js +1 -1
  160. package/src/lib/app-utils/seo-title-variables.js.map +1 -1
  161. package/src/lib/app-utils/server.d.ts +6 -9
  162. package/src/lib/app-utils/server.js +17 -27
  163. package/src/lib/app-utils/server.js.map +1 -1
  164. package/src/lib/app-utils/site-interactions.d.ts +501 -0
  165. package/src/lib/app-utils/site-interactions.js +554 -0
  166. package/src/lib/app-utils/site-interactions.js.map +1 -0
  167. package/src/lib/app-utils/{marketplace-theme.d.ts → site-theme.d.ts} +13 -2
  168. package/src/lib/app-utils/{marketplace-theme.js → site-theme.js} +5 -2
  169. package/src/lib/app-utils/site-theme.js.map +1 -0
  170. package/src/lib/app-utils/sitemap.d.ts +4 -3
  171. package/src/lib/app-utils/sitemap.js +9 -7
  172. package/src/lib/app-utils/sitemap.js.map +1 -1
  173. package/src/lib/app-utils/stale-build-error.d.ts +51 -0
  174. package/src/lib/app-utils/stale-build-error.js +100 -1
  175. package/src/lib/app-utils/stale-build-error.js.map +1 -1
  176. package/src/lib/app-utils/starter-templates.d.ts +20 -0
  177. package/src/lib/app-utils/starter-templates.js +49 -0
  178. package/src/lib/app-utils/starter-templates.js.map +1 -1
  179. package/src/lib/app-utils/tax-jurisdiction-figures.d.ts +118 -0
  180. package/src/lib/app-utils/tax-jurisdiction-figures.js +123 -0
  181. package/src/lib/app-utils/tax-jurisdiction-figures.js.map +1 -0
  182. package/src/lib/app-utils/theme-library.d.ts +10 -3
  183. package/src/lib/app-utils/theme-library.js +13 -4
  184. package/src/lib/app-utils/theme-library.js.map +1 -1
  185. package/src/lib/app-utils/{campaign-attribution.d.ts → utm-attribution.d.ts} +11 -6
  186. package/src/lib/app-utils/{campaign-attribution.js → utm-attribution.js} +13 -8
  187. package/src/lib/app-utils/utm-attribution.js.map +1 -0
  188. package/src/lib/app-utils/{campaign-forwarding.d.ts → utm-forwarding.d.ts} +14 -14
  189. package/src/lib/app-utils/{campaign-forwarding.js → utm-forwarding.js} +26 -26
  190. package/src/lib/app-utils/utm-forwarding.js.map +1 -0
  191. package/src/lib/app-utils/video-object.js +6 -5
  192. package/src/lib/app-utils/video-object.js.map +1 -1
  193. package/src/lib/app-utils/visitor-consent.d.ts +41 -164
  194. package/src/lib/app-utils/visitor-consent.js +66 -277
  195. package/src/lib/app-utils/visitor-consent.js.map +1 -1
  196. package/src/lib/app-utils/web-vitals-rum.d.ts +7 -7
  197. package/src/lib/app-utils/web-vitals-rum.js +31 -63
  198. package/src/lib/app-utils/web-vitals-rum.js.map +1 -1
  199. package/src/lib/app-utils/where-used.d.ts +11 -6
  200. package/src/lib/app-utils/where-used.js +3 -8
  201. package/src/lib/app-utils/where-used.js.map +1 -1
  202. package/src/lib/canvas-manager/canvas-manager.js +3 -3
  203. package/src/lib/canvas-manager/canvas-manager.js.map +1 -1
  204. package/src/lib/foundation/definitions/components.types.d.ts +1 -1
  205. package/src/lib/foundation/definitions/components.types.js +1 -1
  206. package/src/lib/foundation/definitions/components.types.js.map +1 -1
  207. package/src/lib/foundation/definitions/org-billing.types.d.ts +18 -135
  208. package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
  209. package/src/lib/foundation/definitions/organization.types.d.ts +6 -3
  210. package/src/lib/foundation/definitions/organization.types.js.map +1 -1
  211. package/src/lib/foundation/definitions/platform.types.d.ts +27 -5
  212. package/src/lib/foundation/definitions/platform.types.js.map +1 -1
  213. package/src/lib/foundation/definitions/write-deny-coverage.util.d.ts +16 -0
  214. package/src/lib/foundation/definitions/write-deny-coverage.util.js +20 -0
  215. package/src/lib/foundation/definitions/write-deny-coverage.util.js.map +1 -1
  216. package/src/lib/foundation/index.d.ts +1 -1
  217. package/src/lib/foundation/index.js.map +1 -1
  218. package/src/lib/plugin-manager/besigner-documents.d.ts +96 -0
  219. package/src/lib/plugin-manager/besigner-documents.js +61 -0
  220. package/src/lib/plugin-manager/besigner-documents.js.map +1 -0
  221. package/src/lib/plugin-manager/computed-variables.d.ts +71 -0
  222. package/src/lib/plugin-manager/computed-variables.js +74 -0
  223. package/src/lib/plugin-manager/computed-variables.js.map +1 -0
  224. package/src/lib/plugin-manager/custom-fields.d.ts +29 -2
  225. package/src/lib/plugin-manager/custom-fields.js +47 -1
  226. package/src/lib/plugin-manager/custom-fields.js.map +1 -1
  227. package/src/lib/plugin-manager/feature-plugins.d.ts +292 -20
  228. package/src/lib/plugin-manager/feature-plugins.js +105 -17
  229. package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
  230. package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +123 -0
  231. package/src/lib/plugin-manager/first-party-plugins.generated.js +785 -14
  232. package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
  233. package/src/lib/plugin-manager/plugin-activity-actions.d.ts +12 -0
  234. package/src/lib/plugin-manager/plugin-activity-actions.js +25 -0
  235. package/src/lib/plugin-manager/plugin-activity-actions.js.map +1 -1
  236. package/src/lib/plugin-manager/plugin-contributions.d.ts +1 -1
  237. package/src/lib/plugin-manager/plugin-contributions.js.map +1 -1
  238. package/src/lib/plugin-manager/plugin-declarations-repair.d.ts +36 -0
  239. package/src/lib/plugin-manager/plugin-declarations-repair.js +64 -0
  240. package/src/lib/plugin-manager/plugin-declarations-repair.js.map +1 -0
  241. package/src/lib/plugin-manager/plugin-dependents.d.ts +101 -0
  242. package/src/lib/plugin-manager/plugin-dependents.js +75 -0
  243. package/src/lib/plugin-manager/plugin-dependents.js.map +1 -0
  244. package/src/lib/plugin-manager/plugin-distribution.d.ts +55 -0
  245. package/src/lib/plugin-manager/plugin-distribution.js +45 -0
  246. package/src/lib/plugin-manager/plugin-distribution.js.map +1 -0
  247. package/src/lib/plugin-manager/plugin-host-collections.d.ts +17 -0
  248. package/src/lib/plugin-manager/plugin-host-collections.js +6 -0
  249. package/src/lib/plugin-manager/plugin-host-collections.js.map +1 -1
  250. package/src/lib/plugin-manager/plugin-host-resources.d.ts +133 -0
  251. package/src/lib/plugin-manager/plugin-host-resources.js +52 -0
  252. package/src/lib/plugin-manager/plugin-host-resources.js.map +1 -0
  253. package/src/lib/plugin-manager/plugin-org-erasure.d.ts +28 -2
  254. package/src/lib/plugin-manager/plugin-org-erasure.js +61 -2
  255. package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -1
  256. package/src/lib/plugin-manager/plugin-plan-entitlements.d.ts +123 -0
  257. package/src/lib/plugin-manager/plugin-plan-entitlements.js +101 -0
  258. package/src/lib/plugin-manager/plugin-plan-entitlements.js.map +1 -0
  259. package/src/lib/plugin-manager/plugin-record-index.d.ts +95 -0
  260. package/src/lib/plugin-manager/plugin-record-index.js +51 -0
  261. package/src/lib/plugin-manager/plugin-record-index.js.map +1 -0
  262. package/src/lib/plugin-manager/plugin-record-written.d.ts +58 -0
  263. package/src/lib/plugin-manager/plugin-record-written.js +42 -0
  264. package/src/lib/plugin-manager/plugin-record-written.js.map +1 -0
  265. package/src/lib/plugin-manager/plugin-revenue-sources.d.ts +213 -0
  266. package/src/lib/plugin-manager/plugin-revenue-sources.js +194 -0
  267. package/src/lib/plugin-manager/plugin-revenue-sources.js.map +1 -0
  268. package/src/lib/plugin-manager/plugin-site-bundle.d.ts +145 -0
  269. package/src/lib/plugin-manager/plugin-site-bundle.js +78 -0
  270. package/src/lib/plugin-manager/plugin-site-bundle.js.map +1 -0
  271. package/src/lib/plugin-manager/plugin-site-cache.d.ts +12 -0
  272. package/src/lib/plugin-manager/plugin-site-cache.js.map +1 -1
  273. package/src/lib/plugin-manager/plugin-site-export.d.ts +81 -0
  274. package/src/lib/plugin-manager/plugin-site-export.js +40 -0
  275. package/src/lib/plugin-manager/plugin-site-export.js.map +1 -0
  276. package/src/lib/plugin-manager/plugin-sitemap-sections.d.ts +88 -0
  277. package/src/lib/plugin-manager/plugin-sitemap-sections.js +29 -0
  278. package/src/lib/plugin-manager/plugin-sitemap-sections.js.map +1 -0
  279. package/src/lib/plugin-manager/plugin-tax-profile.d.ts +20 -4
  280. package/src/lib/plugin-manager/plugin-tax-profile.js.map +1 -1
  281. package/src/lib/plugin-manager/plugin-tax-return-sources.d.ts +255 -0
  282. package/src/lib/plugin-manager/plugin-tax-return-sources.js +191 -0
  283. package/src/lib/plugin-manager/plugin-tax-return-sources.js.map +1 -0
  284. package/src/lib/plugin-manager/plugin-template-sources.d.ts +75 -0
  285. package/src/lib/plugin-manager/plugin-template-sources.js +37 -0
  286. package/src/lib/plugin-manager/plugin-template-sources.js.map +1 -0
  287. package/src/lib/plugin-manager/plugin-usage-axes.d.ts +107 -0
  288. package/src/lib/plugin-manager/plugin-usage-axes.js +107 -0
  289. package/src/lib/plugin-manager/plugin-usage-axes.js.map +1 -0
  290. package/src/lib/plugin-manager/plugin-zones.d.ts +4 -5
  291. package/src/lib/plugin-manager/plugin-zones.js.map +1 -1
  292. package/src/lib/plugin-manager/realm-host-aglyn.generated.js +2 -0
  293. package/src/lib/plugin-manager/realm-host-aglyn.generated.js.map +1 -1
  294. package/src/lib/plugin-manager/record-captured-contact.d.ts +1 -14
  295. package/src/lib/plugin-manager/record-captured-contact.js +10 -32
  296. package/src/lib/plugin-manager/record-captured-contact.js.map +1 -1
  297. package/src/lib/plugin-manager/repeat-rows.d.ts +124 -0
  298. package/src/lib/plugin-manager/repeat-rows.js +108 -0
  299. package/src/lib/plugin-manager/repeat-rows.js.map +1 -0
  300. package/src/lib/plugin-manager/submission-record-target.d.ts +144 -0
  301. package/src/lib/plugin-manager/submission-record-target.js +125 -0
  302. package/src/lib/plugin-manager/submission-record-target.js.map +1 -0
  303. package/src/lib/plugin-manager/video-embed-provider.d.ts +108 -0
  304. package/src/lib/plugin-manager/video-embed-provider.js +165 -0
  305. package/src/lib/plugin-manager/video-embed-provider.js.map +1 -0
  306. package/src/lib/types/nodes.d.ts +2 -2
  307. package/src/lib/types/nodes.js.map +1 -1
  308. package/src/lib/app-utils/campaign-attribution.js.map +0 -1
  309. package/src/lib/app-utils/campaign-forwarding.js.map +0 -1
  310. package/src/lib/app-utils/contact-holder.d.ts +0 -68
  311. package/src/lib/app-utils/contact-holder.js +0 -129
  312. package/src/lib/app-utils/contact-holder.js.map +0 -1
  313. package/src/lib/app-utils/contact-merge.d.ts +0 -136
  314. package/src/lib/app-utils/contact-merge.js +0 -412
  315. package/src/lib/app-utils/contact-merge.js.map +0 -1
  316. package/src/lib/app-utils/crm-csv.d.ts +0 -239
  317. package/src/lib/app-utils/crm-csv.js +0 -467
  318. package/src/lib/app-utils/crm-csv.js.map +0 -1
  319. package/src/lib/app-utils/crm-digest.d.ts +0 -185
  320. package/src/lib/app-utils/crm-digest.js +0 -272
  321. package/src/lib/app-utils/crm-digest.js.map +0 -1
  322. package/src/lib/app-utils/form-dataset-binding.d.ts +0 -50
  323. package/src/lib/app-utils/form-dataset-binding.js +0 -74
  324. package/src/lib/app-utils/form-dataset-binding.js.map +0 -1
  325. package/src/lib/app-utils/list-import.d.ts +0 -158
  326. package/src/lib/app-utils/list-import.js +0 -332
  327. package/src/lib/app-utils/list-import.js.map +0 -1
  328. package/src/lib/app-utils/marketplace-listing-visibility.d.ts +0 -122
  329. package/src/lib/app-utils/marketplace-listing-visibility.js +0 -147
  330. package/src/lib/app-utils/marketplace-listing-visibility.js.map +0 -1
  331. package/src/lib/app-utils/marketplace-overrides.js.map +0 -1
  332. package/src/lib/app-utils/marketplace-provenance.js.map +0 -1
  333. package/src/lib/app-utils/marketplace-theme.js.map +0 -1
  334. package/src/lib/app-utils/marketplace-update-state.d.ts +0 -119
  335. package/src/lib/app-utils/marketplace-update-state.js +0 -132
  336. package/src/lib/app-utils/marketplace-update-state.js.map +0 -1
  337. package/src/lib/app-utils/publisher-agreement.d.ts +0 -289
  338. package/src/lib/app-utils/publisher-agreement.js +0 -321
  339. package/src/lib/app-utils/publisher-agreement.js.map +0 -1
  340. package/src/lib/app-utils/wistia-embed.d.ts +0 -104
  341. package/src/lib/app-utils/wistia-embed.js +0 -138
  342. package/src/lib/app-utils/wistia-embed.js.map +0 -1
  343. package/src/lib/app-utils/workflows.d.ts +0 -136
  344. package/src/lib/app-utils/workflows.js +0 -346
  345. package/src/lib/app-utils/workflows.js.map +0 -1
  346. package/src/lib/plugin-manager/commerce-zone-props.d.ts +0 -172
  347. package/src/lib/plugin-manager/commerce-zone-props.js +0 -31
  348. package/src/lib/plugin-manager/commerce-zone-props.js.map +0 -1
@@ -14,8 +14,8 @@
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 { diffOverride, isEmptyOverride, overrideWriteValue, readArtifactOverride, resolveOverride } from "./marketplace-overrides.js";
18
- import { resolveSiteTheme, themeArtifactContent } from "./marketplace-theme.js";
17
+ import { diffOverride, isEmptyOverride, overrideWriteValue, readArtifactOverride, resolveOverride } from "./artifact-overrides.js";
18
+ import { resolveSiteTheme, themeArtifactContent } from "./site-theme.js";
19
19
  /**
20
20
  * A site's theme library (AGL-3404): the themes a site can switch between,
21
21
  * and the rule that switching, editing and saving never destroy one.
@@ -72,7 +72,14 @@ const KINDS = [
72
72
  * leaves it. Before the library a site had exactly one theme of its own, so
73
73
  * a fixed id cannot collide with another.
74
74
  */ export const SITE_THEME_ENTRY_ID = 'site-theme';
75
- /** The default's name when nothing else names it. */ export const DEFAULT_THEME_NAME = 'Material UI';
75
+ /**
76
+ * The default's name, wherever the library names it.
77
+ *
78
+ * Not "Material UI": the platform default keeps MUI's palette but draws it in
79
+ * the platform's own type and component defaults, and stock Material UI is a
80
+ * built-in theme of its own (AGL-3422). A console shows the operator's brand
81
+ * name in its place.
82
+ */ export const DEFAULT_THEME_NAME = 'Platform default';
76
83
  /** A preset's entry id, which holds only its stash. */ export function presetEntryId(presetId) {
77
84
  return `preset--${presetId.replace(/[/]/g, '_')}`;
78
85
  }
@@ -98,7 +105,9 @@ function hasContent(theme) {
98
105
  return {
99
106
  kind: stored['kind'],
100
107
  id: stored['id'],
101
- name: typeof stored['name'] === 'string' && stored['name'] ? stored['name'] : stored['kind'] === 'default' ? DEFAULT_THEME_NAME : 'Theme'
108
+ // The default is always named by the constant: a selection stored
109
+ // before AGL-3422 calls it "Material UI", which is now another theme.
110
+ name: stored['kind'] === 'default' ? DEFAULT_THEME_NAME : typeof stored['name'] === 'string' && stored['name'] ? stored['name'] : 'Theme'
102
111
  };
103
112
  }
104
113
  const listingId = host == null ? void 0 : (_host_themeInstalledFrom = host.themeInstalledFrom) == null ? void 0 : _host_themeInstalledFrom.listingId;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/theme-library.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\nimport type { HostTheme } from '@aglyn/shared-data-types'\nimport {\n diffOverride,\n isEmptyOverride,\n overrideWriteValue,\n readArtifactOverride,\n resolveOverride,\n} from './marketplace-overrides'\nimport {\n resolveSiteTheme,\n themeArtifactContent,\n type ThemeHostDocument,\n} from './marketplace-theme'\n\n/**\n * A site's theme library (AGL-3404): the themes a site can switch between,\n * and the rule that switching, editing and saving never destroy one.\n *\n * ## Three layers, one of them picked\n *\n * The site renders `theme ⊕ themeOverride` (`resolveSiteTheme`), exactly as\n * it did before there was a library. What the library adds is WHERE `theme`\n * came from, named by `themeSelection`:\n *\n * - `default` — the platform default. `theme` is empty.\n * - `preset` — a built-in theme a plugin contributes. `theme` is a copy.\n * - `custom` — one of the site's own saved themes, kept in the library.\n * - `installed` — a marketplace theme, kept in the library with the\n * provenance an update needs.\n *\n * Every edit is an override patch over the picked theme and never a write to\n * it, so \"Restore\" is deleting the patch and the theme it restores to is\n * still exactly the one that was picked. \"Save as custom theme\" copies the\n * resolved result into a new library entry; the theme it started from stays\n * as it was.\n *\n * ## Switching keeps each theme's own edits\n *\n * Leaving a theme stashes its override on its library entry, and coming back\n * restores it — so trying another theme is not a way to lose work. A preset\n * or the default has no content to keep, so its entry holds only the stash.\n *\n * ## The site's own settings travel with the site\n *\n * `darkScheme` is a decision about the site's content, not about a design\n * (`THEME_ARTIFACT_FIELDS` says the same for publishing), so it survives every\n * switch, save and restore: whichever theme is picked, a site that switched\n * dark off stays light.\n *\n * Pure: the console route and the marketplace install route both plan here\n * and write the plan in their own transaction, so neither can file a switch\n * differently from the other.\n */\n\n/** The host subcollection the library lives in. */\nexport const THEME_LIBRARY_COLLECTION = 'themes'\n\n/**\n * The most custom themes one site keeps. A client can read the library, so an\n * unbounded one is an unbounded read on every visit to the theme page.\n */\nexport const THEME_LIBRARY_MAX_CUSTOM = 25\n\n/** The longest name a saved theme takes. */\nexport const THEME_NAME_MAX = 60\n\nexport type ThemeLibraryKind = 'default' | 'preset' | 'custom' | 'installed'\n\nconst KINDS: readonly ThemeLibraryKind[] = [\n 'default',\n 'preset',\n 'custom',\n 'installed',\n]\n\n/** What `themeSelection` on a host names. */\nexport interface HostThemeSelection {\n kind: ThemeLibraryKind\n /** The library entry id (or the preset's entry id). */\n id: string\n /** Shown in the picker; a copy, so a renamed entry renames the selection too. */\n name: string\n}\n\n/** A document in `hosts/{hostId}/themes`. */\nexport interface ThemeLibraryEntry {\n kind: ThemeLibraryKind\n name: string\n /** The theme itself, for `custom` and `installed`. Never edited in place by the editor. */\n theme?: HostTheme | null\n /** The override stashed while this theme is not the picked one. */\n override?: unknown\n /** Marketplace provenance, for `installed` — what `themeInstalledFrom` is restored from. */\n installedFrom?: Record<string, unknown> | null\n createdAt?: unknown\n updatedAt?: unknown\n}\n\n/** The entry id the platform default's stash lives under. */\nexport const DEFAULT_THEME_ENTRY_ID = 'default'\n\n/**\n * The entry id a pre-library site's own theme is filed under when it first\n * leaves it. Before the library a site had exactly one theme of its own, so\n * a fixed id cannot collide with another.\n */\nexport const SITE_THEME_ENTRY_ID = 'site-theme'\n\n/** The default's name when nothing else names it. */\nexport const DEFAULT_THEME_NAME = 'Material UI'\n\n/** A preset's entry id, which holds only its stash. */\nexport function presetEntryId(presetId: string): string {\n return `preset--${presetId.replace(/[/]/g, '_')}`\n}\n\n/** A marketplace theme's entry id: one per listing, so reinstalling updates it. */\nexport function installedEntryId(listingId: string): string {\n return `installed--${listingId.replace(/[/]/g, '_')}`\n}\n\n/** A host document as the library reads it. */\nexport interface ThemeLibraryHost extends ThemeHostDocument {\n themeSelection?: unknown\n themeInstalledFrom?:\n | ({ sha256?: string | null; listingId?: string; name?: string } & Record<\n string,\n unknown\n >)\n | null\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction hasContent(theme: HostTheme | null | undefined): theme is HostTheme {\n return Boolean(theme && Object.keys(theme).length)\n}\n\n/**\n * The theme a site has picked.\n *\n * A site from before the library has no `themeSelection`, and reads as what\n * it was: a marketplace theme, its own theme, or the default. That is what\n * lets the library ship without touching a single existing host document.\n */\nexport function readThemeSelection(\n host: ThemeLibraryHost | null | undefined,\n): HostThemeSelection {\n const stored = host?.themeSelection\n if (\n isRecord(stored) &&\n KINDS.includes(stored['kind'] as ThemeLibraryKind) &&\n typeof stored['id'] === 'string' &&\n stored['id']\n ) {\n return {\n kind: stored['kind'] as ThemeLibraryKind,\n id: stored['id'],\n name:\n typeof stored['name'] === 'string' && stored['name']\n ? stored['name']\n : stored['kind'] === 'default'\n ? DEFAULT_THEME_NAME\n : 'Theme',\n }\n }\n const listingId = host?.themeInstalledFrom?.listingId\n if (listingId) {\n const name = host?.themeInstalledFrom?.name\n return {\n kind: 'installed',\n id: installedEntryId(listingId),\n name: typeof name === 'string' && name ? name : 'Marketplace theme',\n }\n }\n if (hasContent(host?.theme)) {\n return { kind: 'custom', id: SITE_THEME_ENTRY_ID, name: 'Site theme' }\n }\n return {\n kind: 'default',\n id: DEFAULT_THEME_ENTRY_ID,\n name: DEFAULT_THEME_NAME,\n }\n}\n\n/** A name as stored: trimmed, bounded, and never empty. */\nexport function normalizeThemeName(name: unknown): string | null {\n if (typeof name !== 'string') return null\n const trimmed = name.replace(/\\s+/g, ' ').trim()\n if (!trimmed) return null\n return trimmed.slice(0, THEME_NAME_MAX)\n}\n\n/** Marks a field for deletion; the route writing the plan maps it to its store's delete. */\nexport const THEME_FIELD_DELETE = '__aglynThemeFieldDelete'\n\nexport type ThemeLibraryEntryWrite =\n | { id: string; op: 'create'; data: ThemeLibraryEntry }\n | { id: string; op: 'update'; data: Record<string, unknown> }\n | { id: string; op: 'delete' }\n\nexport type ThemeLibraryPlan =\n | {\n ok: true\n /**\n * Host fields to replace WHOLESALE (`update`, never a deep merge: a\n * merged override is the union of two patches, and a merged theme keeps\n * the tokens of the one it replaced).\n */\n host: Record<string, unknown>\n entries: ThemeLibraryEntryWrite[]\n /** The theme picked once the plan is written. */\n selection: HostThemeSelection\n }\n | { ok: false; status: number; error: string }\n\nexport type ThemeLibraryTarget =\n | { kind: 'default' }\n /** A plugin's theme, sent by the console that listed it. */\n | { kind: 'preset'; id: string; name: string; theme: HostTheme }\n | { kind: 'custom' | 'installed'; id: string }\n\nexport type ThemeLibraryAction =\n | { action: 'select'; target: ThemeLibraryTarget }\n | { action: 'save-as'; name: string }\n | { action: 'update' }\n | { action: 'restore' }\n | { action: 'rename'; id: string; name: string }\n | { action: 'delete'; id: string }\n | {\n action: 'install'\n listingId: string\n name: string\n theme: HostTheme\n installedFrom: Record<string, unknown>\n }\n\n/**\n * The override to store for a theme showing `edited` over `base`, or the\n * delete marker when they are the same.\n */\nfunction overrideValue(\n base: HostTheme,\n edited: HostTheme,\n baseSha256: string | null,\n): unknown {\n const patch = diffOverride(base, edited)\n const value = overrideWriteValue(patch, baseSha256)\n return value && !isEmptyOverride(value.patch) ? value : THEME_FIELD_DELETE\n}\n\n/** The site's own setting carried onto another theme. */\nfunction withSiteSettings(theme: HostTheme, from: HostTheme | undefined): HostTheme {\n const next = { ...theme }\n if (from?.darkScheme === 'off') next.darkScheme = 'off'\n else delete next.darkScheme\n return next\n}\n\n/** A stash as it resolves over the theme it belongs to. */\nfunction resolveStash(base: HostTheme, stash: unknown): HostTheme {\n const read = readArtifactOverride({ overrides: stash })\n return read ? resolveOverride<HostTheme>(base, read.patch) : base\n}\n\nfunction sha(installedFrom: unknown): string | null {\n return isRecord(installedFrom) && typeof installedFrom['sha256'] === 'string'\n ? installedFrom['sha256']\n : null\n}\n\n/**\n * Files the theme being left: its override goes onto its entry, and a theme\n * that exists nowhere but on the host (a pre-library site's own theme, or a\n * marketplace install from before the library) gets an entry of its own\n * first, so it is still in the list to come back to.\n *\n * `override` is what to stash — the live one when switching, none when the\n * edits have just moved into a new theme.\n */\nfunction fileCurrent(\n host: ThemeLibraryHost,\n current: HostThemeSelection,\n entries: Readonly<Record<string, ThemeLibraryEntry>>,\n override: unknown,\n): ThemeLibraryEntryWrite[] {\n const stash = override === undefined ? THEME_FIELD_DELETE : override\n if (entries[current.id]) {\n return [{ id: current.id, op: 'update', data: { override: stash } }]\n }\n // The default and a preset have no content to keep, so with nothing to\n // stash there is nothing to file.\n if (\n stash === THEME_FIELD_DELETE &&\n (current.kind === 'default' || current.kind === 'preset')\n ) {\n return []\n }\n const entry: ThemeLibraryEntry = { kind: current.kind, name: current.name }\n if (current.kind === 'custom' || current.kind === 'installed') {\n entry.theme = themeArtifactContent(host.theme)\n }\n if (current.kind === 'installed' && host.themeInstalledFrom) {\n entry.installedFrom = host.themeInstalledFrom\n }\n if (stash !== THEME_FIELD_DELETE) entry.override = stash\n return [{ id: current.id, op: 'create', data: entry }]\n}\n\n/** Host fields that point the site at `selection` over `base`. */\nfunction pointAt(\n selection: HostThemeSelection,\n base: HostTheme,\n override: unknown,\n installedFrom: unknown,\n): Record<string, unknown> {\n return {\n theme: hasContent(base) ? base : THEME_FIELD_DELETE,\n themeOverride: override,\n themeSelection: selection,\n themeInstalledFrom:\n selection.kind === 'installed' && installedFrom\n ? installedFrom\n : THEME_FIELD_DELETE,\n // The library is the way back now: every theme a site has left is in it,\n // edits included. A `themeReplaced` left behind would offer a second,\n // older \"previous theme\" that restores around the library.\n themeReplaced: THEME_FIELD_DELETE,\n }\n}\n\n/**\n * Plans one library action against the host document and its library as\n * read in the same transaction.\n *\n * `newId` mints a library entry id for a new custom theme.\n */\nexport function planThemeLibraryAction(input: {\n host: ThemeLibraryHost | null | undefined\n entries: Readonly<Record<string, ThemeLibraryEntry>>\n action: ThemeLibraryAction\n newId: () => string\n}): ThemeLibraryPlan {\n const host: ThemeLibraryHost = input.host ?? {}\n const { entries, action } = input\n const current = readThemeSelection(host)\n const resolved = resolveSiteTheme(host) ?? {}\n\n switch (action.action) {\n case 'select':\n return planSelect(host, current, resolved, entries, action.target)\n\n case 'install': {\n const id = installedEntryId(action.listingId)\n const name = normalizeThemeName(action.name) ?? 'Marketplace theme'\n const theme = themeArtifactContent(action.theme)\n const selection: HostThemeSelection = { kind: 'installed', id, name }\n if (current.kind === 'installed' && current.id === id) {\n // An update of the theme already picked. The override stays exactly\n // as stored — including the hash it was written against, which is\n // how the editor knows to say an override predates this version.\n return {\n ok: true,\n host: {\n theme,\n themeInstalledFrom: action.installedFrom,\n themeSelection: selection,\n },\n entries: [\n entries[id]\n ? {\n id,\n op: 'update',\n data: { theme, installedFrom: action.installedFrom, name },\n }\n : {\n id,\n op: 'create',\n data: {\n kind: 'installed',\n name,\n theme,\n installedFrom: action.installedFrom,\n },\n },\n ],\n selection,\n }\n }\n const stash = entries[id]?.override\n const edited = withSiteSettings(resolveStash(theme, stash), resolved)\n return {\n ok: true,\n host: pointAt(\n selection,\n theme,\n overrideValue(theme, edited, sha(action.installedFrom)),\n action.installedFrom,\n ),\n entries: [\n ...fileCurrent(host, current, entries, host.themeOverride),\n entries[id]\n ? {\n id,\n op: 'update',\n data: {\n theme,\n installedFrom: action.installedFrom,\n name,\n override: THEME_FIELD_DELETE,\n },\n }\n : {\n id,\n op: 'create',\n data: {\n kind: 'installed',\n name,\n theme,\n installedFrom: action.installedFrom,\n },\n },\n ],\n selection,\n }\n }\n\n case 'save-as': {\n const name = normalizeThemeName(action.name)\n if (!name) {\n return { ok: false, status: 400, error: 'Give the theme a name.' }\n }\n const customCount = Object.values(entries).filter(\n (entry) => entry.kind === 'custom',\n ).length\n if (customCount >= THEME_LIBRARY_MAX_CUSTOM) {\n return {\n ok: false,\n status: 409,\n error:\n `A site keeps up to ${THEME_LIBRARY_MAX_CUSTOM} custom themes. ` +\n 'Delete one you no longer use first.',\n }\n }\n const id = input.newId()\n const theme = themeArtifactContent(resolved)\n const selection: HostThemeSelection = { kind: 'custom', id, name }\n return {\n ok: true,\n host: pointAt(\n selection,\n theme,\n overrideValue(theme, withSiteSettings(theme, resolved), null),\n null,\n ),\n entries: [\n // The theme this started from stays as it was picked: the edits\n // now live in the new theme, not on top of the old one.\n ...fileCurrent(host, current, entries, undefined),\n { id, op: 'create', data: { kind: 'custom', name, theme } },\n ],\n selection,\n }\n }\n\n case 'update': {\n if (current.kind !== 'custom') {\n return {\n ok: false,\n status: 409,\n error:\n 'Only your own themes can be updated. Save your changes as a ' +\n 'custom theme instead.',\n }\n }\n const theme = themeArtifactContent(resolved)\n const override = overrideValue(\n theme,\n withSiteSettings(theme, resolved),\n null,\n )\n return {\n ok: true,\n host: {\n theme: hasContent(theme) ? theme : THEME_FIELD_DELETE,\n themeOverride: override,\n themeSelection: current,\n },\n entries: [\n entries[current.id]\n ? { id: current.id, op: 'update', data: { theme } }\n : {\n id: current.id,\n op: 'create',\n data: { kind: 'custom', name: current.name, theme },\n },\n ],\n selection: current,\n }\n }\n\n case 'restore': {\n const base = host.theme ?? {}\n return {\n ok: true,\n host: {\n themeOverride: overrideValue(\n base,\n withSiteSettings(base, resolved),\n current.kind === 'installed' ? sha(host.themeInstalledFrom) : null,\n ),\n },\n entries: [],\n selection: current,\n }\n }\n\n case 'rename': {\n const name = normalizeThemeName(action.name)\n if (!name) {\n return { ok: false, status: 400, error: 'Give the theme a name.' }\n }\n const isLegacySiteTheme =\n action.id === SITE_THEME_ENTRY_ID &&\n current.id === SITE_THEME_ENTRY_ID &&\n !entries[SITE_THEME_ENTRY_ID]\n const entry = entries[action.id]\n if (!isLegacySiteTheme && entry?.kind !== 'custom') {\n return { ok: false, status: 404, error: 'Only your own themes can be renamed.' }\n }\n const renamedSelection =\n current.id === action.id ? { ...current, name } : null\n return {\n ok: true,\n host: renamedSelection ? { themeSelection: renamedSelection } : {},\n entries: isLegacySiteTheme\n ? [\n {\n id: action.id,\n op: 'create',\n data: {\n kind: 'custom',\n name,\n theme: themeArtifactContent(host.theme),\n },\n },\n ]\n : [{ id: action.id, op: 'update', data: { name } }],\n selection: renamedSelection ?? current,\n }\n }\n\n case 'delete': {\n const entry = entries[action.id]\n if (!entry || (entry.kind !== 'custom' && entry.kind !== 'installed')) {\n return { ok: false, status: 404, error: 'There is no such theme to delete.' }\n }\n if (current.id === action.id) {\n return {\n ok: false,\n status: 409,\n error: 'This theme is in use. Pick another theme first, then delete it.',\n }\n }\n return {\n ok: true,\n host: {},\n entries: [{ id: action.id, op: 'delete' }],\n selection: current,\n }\n }\n }\n}\n\nfunction planSelect(\n host: ThemeLibraryHost,\n current: HostThemeSelection,\n resolved: HostTheme,\n entries: Readonly<Record<string, ThemeLibraryEntry>>,\n target: ThemeLibraryTarget,\n): ThemeLibraryPlan {\n let selection: HostThemeSelection\n let base: HostTheme\n let installedFrom: unknown = null\n if (target.kind === 'default') {\n selection = {\n kind: 'default',\n id: DEFAULT_THEME_ENTRY_ID,\n name: DEFAULT_THEME_NAME,\n }\n base = {}\n } else if (target.kind === 'preset') {\n const name = normalizeThemeName(target.name)\n if (!target.id || !name || !isRecord(target.theme)) {\n return { ok: false, status: 400, error: 'That theme could not be read.' }\n }\n selection = { kind: 'preset', id: presetEntryId(target.id), name }\n base = themeArtifactContent(target.theme)\n } else {\n const entry = entries[target.id]\n if (!entry || entry.kind !== target.kind) {\n return { ok: false, status: 404, error: 'That theme is not in this site’s library.' }\n }\n selection = { kind: entry.kind, id: target.id, name: entry.name }\n base = themeArtifactContent(entry.theme ?? {})\n installedFrom = entry.installedFrom ?? null\n }\n if (selection.id === current.id && selection.kind === current.kind) {\n return { ok: true, host: {}, entries: [], selection: current }\n }\n\n const stash = entries[selection.id]?.override\n const edited = withSiteSettings(resolveStash(base, stash), resolved)\n const writes: ThemeLibraryEntryWrite[] = fileCurrent(\n host,\n current,\n entries,\n host.themeOverride,\n )\n // Its stash is live again, so the entry stops holding a second copy.\n if (entries[selection.id]?.override !== undefined) {\n writes.push({\n id: selection.id,\n op: 'update',\n data: { override: THEME_FIELD_DELETE },\n })\n }\n return {\n ok: true,\n host: pointAt(\n selection,\n base,\n overrideValue(\n base,\n edited,\n selection.kind === 'installed' ? sha(installedFrom) : null,\n ),\n installedFrom,\n ),\n entries: writes,\n selection,\n }\n}\n\n/**\n * Whether the picked theme carries edits of this site's own — what \"Restore\"\n * and \"Update\" act on. The site's dark-scheme setting is not an edit to the\n * theme, so an override holding only that does not count.\n */\nexport function hasThemeEdits(host: ThemeLibraryHost | null | undefined): boolean {\n const read = readArtifactOverride({ overrides: host?.themeOverride })\n if (!read || isEmptyOverride(read.patch)) return false\n if (!isRecord(read.patch)) return true\n return Object.keys(read.patch).some((key) => key !== 'darkScheme')\n}\n"],"names":["diffOverride","isEmptyOverride","overrideWriteValue","readArtifactOverride","resolveOverride","resolveSiteTheme","themeArtifactContent","THEME_LIBRARY_COLLECTION","THEME_LIBRARY_MAX_CUSTOM","THEME_NAME_MAX","KINDS","DEFAULT_THEME_ENTRY_ID","SITE_THEME_ENTRY_ID","DEFAULT_THEME_NAME","presetEntryId","presetId","replace","installedEntryId","listingId","isRecord","value","Array","isArray","hasContent","theme","Boolean","Object","keys","length","readThemeSelection","host","stored","themeSelection","includes","kind","id","name","themeInstalledFrom","normalizeThemeName","trimmed","trim","slice","THEME_FIELD_DELETE","overrideValue","base","edited","baseSha256","patch","withSiteSettings","from","next","darkScheme","resolveStash","stash","read","overrides","sha","installedFrom","fileCurrent","current","entries","override","undefined","op","data","entry","pointAt","selection","themeOverride","themeReplaced","planThemeLibraryAction","input","action","resolved","planSelect","target","ok","status","error","customCount","values","filter","newId","isLegacySiteTheme","renamedSelection","writes","push","hasThemeEdits","some","key"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/theme-library.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\nimport type { HostTheme } from '@aglyn/shared-data-types'\nimport {\n diffOverride,\n isEmptyOverride,\n overrideWriteValue,\n readArtifactOverride,\n resolveOverride,\n} from './artifact-overrides'\nimport {\n resolveSiteTheme,\n themeArtifactContent,\n type ThemeHostDocument,\n} from './site-theme'\n\n/**\n * A site's theme library (AGL-3404): the themes a site can switch between,\n * and the rule that switching, editing and saving never destroy one.\n *\n * ## Three layers, one of them picked\n *\n * The site renders `theme ⊕ themeOverride` (`resolveSiteTheme`), exactly as\n * it did before there was a library. What the library adds is WHERE `theme`\n * came from, named by `themeSelection`:\n *\n * - `default` — the platform default. `theme` is empty.\n * - `preset` — a built-in theme a plugin contributes. `theme` is a copy.\n * - `custom` — one of the site's own saved themes, kept in the library.\n * - `installed` — a marketplace theme, kept in the library with the\n * provenance an update needs.\n *\n * Every edit is an override patch over the picked theme and never a write to\n * it, so \"Restore\" is deleting the patch and the theme it restores to is\n * still exactly the one that was picked. \"Save as custom theme\" copies the\n * resolved result into a new library entry; the theme it started from stays\n * as it was.\n *\n * ## Switching keeps each theme's own edits\n *\n * Leaving a theme stashes its override on its library entry, and coming back\n * restores it — so trying another theme is not a way to lose work. A preset\n * or the default has no content to keep, so its entry holds only the stash.\n *\n * ## The site's own settings travel with the site\n *\n * `darkScheme` is a decision about the site's content, not about a design\n * (`THEME_ARTIFACT_FIELDS` says the same for publishing), so it survives every\n * switch, save and restore: whichever theme is picked, a site that switched\n * dark off stays light.\n *\n * Pure: the console route and the marketplace install route both plan here\n * and write the plan in their own transaction, so neither can file a switch\n * differently from the other.\n */\n\n/** The host subcollection the library lives in. */\nexport const THEME_LIBRARY_COLLECTION = 'themes'\n\n/**\n * The most custom themes one site keeps. A client can read the library, so an\n * unbounded one is an unbounded read on every visit to the theme page.\n */\nexport const THEME_LIBRARY_MAX_CUSTOM = 25\n\n/** The longest name a saved theme takes. */\nexport const THEME_NAME_MAX = 60\n\nexport type ThemeLibraryKind = 'default' | 'preset' | 'custom' | 'installed'\n\nconst KINDS: readonly ThemeLibraryKind[] = [\n 'default',\n 'preset',\n 'custom',\n 'installed',\n]\n\n/** What `themeSelection` on a host names. */\nexport interface HostThemeSelection {\n kind: ThemeLibraryKind\n /** The library entry id (or the preset's entry id). */\n id: string\n /** Shown in the picker; a copy, so a renamed entry renames the selection too. */\n name: string\n}\n\n/** A document in `hosts/{hostId}/themes`. */\nexport interface ThemeLibraryEntry {\n kind: ThemeLibraryKind\n name: string\n /** The theme itself, for `custom` and `installed`. Never edited in place by the editor. */\n theme?: HostTheme | null\n /** The override stashed while this theme is not the picked one. */\n override?: unknown\n /** Marketplace provenance, for `installed` — what `themeInstalledFrom` is restored from. */\n installedFrom?: Record<string, unknown> | null\n createdAt?: unknown\n updatedAt?: unknown\n}\n\n/** The entry id the platform default's stash lives under. */\nexport const DEFAULT_THEME_ENTRY_ID = 'default'\n\n/**\n * The entry id a pre-library site's own theme is filed under when it first\n * leaves it. Before the library a site had exactly one theme of its own, so\n * a fixed id cannot collide with another.\n */\nexport const SITE_THEME_ENTRY_ID = 'site-theme'\n\n/**\n * The default's name, wherever the library names it.\n *\n * Not \"Material UI\": the platform default keeps MUI's palette but draws it in\n * the platform's own type and component defaults, and stock Material UI is a\n * built-in theme of its own (AGL-3422). A console shows the operator's brand\n * name in its place.\n */\nexport const DEFAULT_THEME_NAME = 'Platform default'\n\n/** A preset's entry id, which holds only its stash. */\nexport function presetEntryId(presetId: string): string {\n return `preset--${presetId.replace(/[/]/g, '_')}`\n}\n\n/** A marketplace theme's entry id: one per listing, so reinstalling updates it. */\nexport function installedEntryId(listingId: string): string {\n return `installed--${listingId.replace(/[/]/g, '_')}`\n}\n\n/** A host document as the library reads it. */\nexport interface ThemeLibraryHost extends ThemeHostDocument {\n themeSelection?: unknown\n themeInstalledFrom?:\n | ({ sha256?: string | null; listingId?: string; name?: string } & Record<\n string,\n unknown\n >)\n | null\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction hasContent(theme: HostTheme | null | undefined): theme is HostTheme {\n return Boolean(theme && Object.keys(theme).length)\n}\n\n/**\n * The theme a site has picked.\n *\n * A site from before the library has no `themeSelection`, and reads as what\n * it was: a marketplace theme, its own theme, or the default. That is what\n * lets the library ship without touching a single existing host document.\n */\nexport function readThemeSelection(\n host: ThemeLibraryHost | null | undefined,\n): HostThemeSelection {\n const stored = host?.themeSelection\n if (\n isRecord(stored) &&\n KINDS.includes(stored['kind'] as ThemeLibraryKind) &&\n typeof stored['id'] === 'string' &&\n stored['id']\n ) {\n return {\n kind: stored['kind'] as ThemeLibraryKind,\n id: stored['id'],\n // The default is always named by the constant: a selection stored\n // before AGL-3422 calls it \"Material UI\", which is now another theme.\n name:\n stored['kind'] === 'default'\n ? DEFAULT_THEME_NAME\n : typeof stored['name'] === 'string' && stored['name']\n ? stored['name']\n : 'Theme',\n }\n }\n const listingId = host?.themeInstalledFrom?.listingId\n if (listingId) {\n const name = host?.themeInstalledFrom?.name\n return {\n kind: 'installed',\n id: installedEntryId(listingId),\n name: typeof name === 'string' && name ? name : 'Marketplace theme',\n }\n }\n if (hasContent(host?.theme)) {\n return { kind: 'custom', id: SITE_THEME_ENTRY_ID, name: 'Site theme' }\n }\n return {\n kind: 'default',\n id: DEFAULT_THEME_ENTRY_ID,\n name: DEFAULT_THEME_NAME,\n }\n}\n\n/** A name as stored: trimmed, bounded, and never empty. */\nexport function normalizeThemeName(name: unknown): string | null {\n if (typeof name !== 'string') return null\n const trimmed = name.replace(/\\s+/g, ' ').trim()\n if (!trimmed) return null\n return trimmed.slice(0, THEME_NAME_MAX)\n}\n\n/** Marks a field for deletion; the route writing the plan maps it to its store's delete. */\nexport const THEME_FIELD_DELETE = '__aglynThemeFieldDelete'\n\nexport type ThemeLibraryEntryWrite =\n | { id: string; op: 'create'; data: ThemeLibraryEntry }\n | { id: string; op: 'update'; data: Record<string, unknown> }\n | { id: string; op: 'delete' }\n\nexport type ThemeLibraryPlan =\n | {\n ok: true\n /**\n * Host fields to replace WHOLESALE (`update`, never a deep merge: a\n * merged override is the union of two patches, and a merged theme keeps\n * the tokens of the one it replaced).\n */\n host: Record<string, unknown>\n entries: ThemeLibraryEntryWrite[]\n /** The theme picked once the plan is written. */\n selection: HostThemeSelection\n }\n | { ok: false; status: number; error: string }\n\nexport type ThemeLibraryTarget =\n | { kind: 'default' }\n /** A plugin's theme, sent by the console that listed it. */\n | { kind: 'preset'; id: string; name: string; theme: HostTheme }\n | { kind: 'custom' | 'installed'; id: string }\n\nexport type ThemeLibraryAction =\n | { action: 'select'; target: ThemeLibraryTarget }\n | { action: 'save-as'; name: string }\n | { action: 'update' }\n | { action: 'restore' }\n | { action: 'rename'; id: string; name: string }\n | { action: 'delete'; id: string }\n | {\n action: 'install'\n listingId: string\n name: string\n theme: HostTheme\n installedFrom: Record<string, unknown>\n }\n\n/**\n * The override to store for a theme showing `edited` over `base`, or the\n * delete marker when they are the same.\n */\nfunction overrideValue(\n base: HostTheme,\n edited: HostTheme,\n baseSha256: string | null,\n): unknown {\n const patch = diffOverride(base, edited)\n const value = overrideWriteValue(patch, baseSha256)\n return value && !isEmptyOverride(value.patch) ? value : THEME_FIELD_DELETE\n}\n\n/** The site's own setting carried onto another theme. */\nfunction withSiteSettings(theme: HostTheme, from: HostTheme | undefined): HostTheme {\n const next = { ...theme }\n if (from?.darkScheme === 'off') next.darkScheme = 'off'\n else delete next.darkScheme\n return next\n}\n\n/** A stash as it resolves over the theme it belongs to. */\nfunction resolveStash(base: HostTheme, stash: unknown): HostTheme {\n const read = readArtifactOverride({ overrides: stash })\n return read ? resolveOverride<HostTheme>(base, read.patch) : base\n}\n\nfunction sha(installedFrom: unknown): string | null {\n return isRecord(installedFrom) && typeof installedFrom['sha256'] === 'string'\n ? installedFrom['sha256']\n : null\n}\n\n/**\n * Files the theme being left: its override goes onto its entry, and a theme\n * that exists nowhere but on the host (a pre-library site's own theme, or a\n * marketplace install from before the library) gets an entry of its own\n * first, so it is still in the list to come back to.\n *\n * `override` is what to stash — the live one when switching, none when the\n * edits have just moved into a new theme.\n */\nfunction fileCurrent(\n host: ThemeLibraryHost,\n current: HostThemeSelection,\n entries: Readonly<Record<string, ThemeLibraryEntry>>,\n override: unknown,\n): ThemeLibraryEntryWrite[] {\n const stash = override === undefined ? THEME_FIELD_DELETE : override\n if (entries[current.id]) {\n return [{ id: current.id, op: 'update', data: { override: stash } }]\n }\n // The default and a preset have no content to keep, so with nothing to\n // stash there is nothing to file.\n if (\n stash === THEME_FIELD_DELETE &&\n (current.kind === 'default' || current.kind === 'preset')\n ) {\n return []\n }\n const entry: ThemeLibraryEntry = { kind: current.kind, name: current.name }\n if (current.kind === 'custom' || current.kind === 'installed') {\n entry.theme = themeArtifactContent(host.theme)\n }\n if (current.kind === 'installed' && host.themeInstalledFrom) {\n entry.installedFrom = host.themeInstalledFrom\n }\n if (stash !== THEME_FIELD_DELETE) entry.override = stash\n return [{ id: current.id, op: 'create', data: entry }]\n}\n\n/** Host fields that point the site at `selection` over `base`. */\nfunction pointAt(\n selection: HostThemeSelection,\n base: HostTheme,\n override: unknown,\n installedFrom: unknown,\n): Record<string, unknown> {\n return {\n theme: hasContent(base) ? base : THEME_FIELD_DELETE,\n themeOverride: override,\n themeSelection: selection,\n themeInstalledFrom:\n selection.kind === 'installed' && installedFrom\n ? installedFrom\n : THEME_FIELD_DELETE,\n // The library is the way back now: every theme a site has left is in it,\n // edits included. A `themeReplaced` left behind would offer a second,\n // older \"previous theme\" that restores around the library.\n themeReplaced: THEME_FIELD_DELETE,\n }\n}\n\n/**\n * Plans one library action against the host document and its library as\n * read in the same transaction.\n *\n * `newId` mints a library entry id for a new custom theme.\n */\nexport function planThemeLibraryAction(input: {\n host: ThemeLibraryHost | null | undefined\n entries: Readonly<Record<string, ThemeLibraryEntry>>\n action: ThemeLibraryAction\n newId: () => string\n}): ThemeLibraryPlan {\n const host: ThemeLibraryHost = input.host ?? {}\n const { entries, action } = input\n const current = readThemeSelection(host)\n const resolved = resolveSiteTheme(host) ?? {}\n\n switch (action.action) {\n case 'select':\n return planSelect(host, current, resolved, entries, action.target)\n\n case 'install': {\n const id = installedEntryId(action.listingId)\n const name = normalizeThemeName(action.name) ?? 'Marketplace theme'\n const theme = themeArtifactContent(action.theme)\n const selection: HostThemeSelection = { kind: 'installed', id, name }\n if (current.kind === 'installed' && current.id === id) {\n // An update of the theme already picked. The override stays exactly\n // as stored — including the hash it was written against, which is\n // how the editor knows to say an override predates this version.\n return {\n ok: true,\n host: {\n theme,\n themeInstalledFrom: action.installedFrom,\n themeSelection: selection,\n },\n entries: [\n entries[id]\n ? {\n id,\n op: 'update',\n data: { theme, installedFrom: action.installedFrom, name },\n }\n : {\n id,\n op: 'create',\n data: {\n kind: 'installed',\n name,\n theme,\n installedFrom: action.installedFrom,\n },\n },\n ],\n selection,\n }\n }\n const stash = entries[id]?.override\n const edited = withSiteSettings(resolveStash(theme, stash), resolved)\n return {\n ok: true,\n host: pointAt(\n selection,\n theme,\n overrideValue(theme, edited, sha(action.installedFrom)),\n action.installedFrom,\n ),\n entries: [\n ...fileCurrent(host, current, entries, host.themeOverride),\n entries[id]\n ? {\n id,\n op: 'update',\n data: {\n theme,\n installedFrom: action.installedFrom,\n name,\n override: THEME_FIELD_DELETE,\n },\n }\n : {\n id,\n op: 'create',\n data: {\n kind: 'installed',\n name,\n theme,\n installedFrom: action.installedFrom,\n },\n },\n ],\n selection,\n }\n }\n\n case 'save-as': {\n const name = normalizeThemeName(action.name)\n if (!name) {\n return { ok: false, status: 400, error: 'Give the theme a name.' }\n }\n const customCount = Object.values(entries).filter(\n (entry) => entry.kind === 'custom',\n ).length\n if (customCount >= THEME_LIBRARY_MAX_CUSTOM) {\n return {\n ok: false,\n status: 409,\n error:\n `A site keeps up to ${THEME_LIBRARY_MAX_CUSTOM} custom themes. ` +\n 'Delete one you no longer use first.',\n }\n }\n const id = input.newId()\n const theme = themeArtifactContent(resolved)\n const selection: HostThemeSelection = { kind: 'custom', id, name }\n return {\n ok: true,\n host: pointAt(\n selection,\n theme,\n overrideValue(theme, withSiteSettings(theme, resolved), null),\n null,\n ),\n entries: [\n // The theme this started from stays as it was picked: the edits\n // now live in the new theme, not on top of the old one.\n ...fileCurrent(host, current, entries, undefined),\n { id, op: 'create', data: { kind: 'custom', name, theme } },\n ],\n selection,\n }\n }\n\n case 'update': {\n if (current.kind !== 'custom') {\n return {\n ok: false,\n status: 409,\n error:\n 'Only your own themes can be updated. Save your changes as a ' +\n 'custom theme instead.',\n }\n }\n const theme = themeArtifactContent(resolved)\n const override = overrideValue(\n theme,\n withSiteSettings(theme, resolved),\n null,\n )\n return {\n ok: true,\n host: {\n theme: hasContent(theme) ? theme : THEME_FIELD_DELETE,\n themeOverride: override,\n themeSelection: current,\n },\n entries: [\n entries[current.id]\n ? { id: current.id, op: 'update', data: { theme } }\n : {\n id: current.id,\n op: 'create',\n data: { kind: 'custom', name: current.name, theme },\n },\n ],\n selection: current,\n }\n }\n\n case 'restore': {\n const base = host.theme ?? {}\n return {\n ok: true,\n host: {\n themeOverride: overrideValue(\n base,\n withSiteSettings(base, resolved),\n current.kind === 'installed' ? sha(host.themeInstalledFrom) : null,\n ),\n },\n entries: [],\n selection: current,\n }\n }\n\n case 'rename': {\n const name = normalizeThemeName(action.name)\n if (!name) {\n return { ok: false, status: 400, error: 'Give the theme a name.' }\n }\n const isLegacySiteTheme =\n action.id === SITE_THEME_ENTRY_ID &&\n current.id === SITE_THEME_ENTRY_ID &&\n !entries[SITE_THEME_ENTRY_ID]\n const entry = entries[action.id]\n if (!isLegacySiteTheme && entry?.kind !== 'custom') {\n return { ok: false, status: 404, error: 'Only your own themes can be renamed.' }\n }\n const renamedSelection =\n current.id === action.id ? { ...current, name } : null\n return {\n ok: true,\n host: renamedSelection ? { themeSelection: renamedSelection } : {},\n entries: isLegacySiteTheme\n ? [\n {\n id: action.id,\n op: 'create',\n data: {\n kind: 'custom',\n name,\n theme: themeArtifactContent(host.theme),\n },\n },\n ]\n : [{ id: action.id, op: 'update', data: { name } }],\n selection: renamedSelection ?? current,\n }\n }\n\n case 'delete': {\n const entry = entries[action.id]\n if (!entry || (entry.kind !== 'custom' && entry.kind !== 'installed')) {\n return { ok: false, status: 404, error: 'There is no such theme to delete.' }\n }\n if (current.id === action.id) {\n return {\n ok: false,\n status: 409,\n error: 'This theme is in use. Pick another theme first, then delete it.',\n }\n }\n return {\n ok: true,\n host: {},\n entries: [{ id: action.id, op: 'delete' }],\n selection: current,\n }\n }\n }\n}\n\nfunction planSelect(\n host: ThemeLibraryHost,\n current: HostThemeSelection,\n resolved: HostTheme,\n entries: Readonly<Record<string, ThemeLibraryEntry>>,\n target: ThemeLibraryTarget,\n): ThemeLibraryPlan {\n let selection: HostThemeSelection\n let base: HostTheme\n let installedFrom: unknown = null\n if (target.kind === 'default') {\n selection = {\n kind: 'default',\n id: DEFAULT_THEME_ENTRY_ID,\n name: DEFAULT_THEME_NAME,\n }\n base = {}\n } else if (target.kind === 'preset') {\n const name = normalizeThemeName(target.name)\n if (!target.id || !name || !isRecord(target.theme)) {\n return { ok: false, status: 400, error: 'That theme could not be read.' }\n }\n selection = { kind: 'preset', id: presetEntryId(target.id), name }\n base = themeArtifactContent(target.theme)\n } else {\n const entry = entries[target.id]\n if (!entry || entry.kind !== target.kind) {\n return { ok: false, status: 404, error: 'That theme is not in this site’s library.' }\n }\n selection = { kind: entry.kind, id: target.id, name: entry.name }\n base = themeArtifactContent(entry.theme ?? {})\n installedFrom = entry.installedFrom ?? null\n }\n if (selection.id === current.id && selection.kind === current.kind) {\n return { ok: true, host: {}, entries: [], selection: current }\n }\n\n const stash = entries[selection.id]?.override\n const edited = withSiteSettings(resolveStash(base, stash), resolved)\n const writes: ThemeLibraryEntryWrite[] = fileCurrent(\n host,\n current,\n entries,\n host.themeOverride,\n )\n // Its stash is live again, so the entry stops holding a second copy.\n if (entries[selection.id]?.override !== undefined) {\n writes.push({\n id: selection.id,\n op: 'update',\n data: { override: THEME_FIELD_DELETE },\n })\n }\n return {\n ok: true,\n host: pointAt(\n selection,\n base,\n overrideValue(\n base,\n edited,\n selection.kind === 'installed' ? sha(installedFrom) : null,\n ),\n installedFrom,\n ),\n entries: writes,\n selection,\n }\n}\n\n/**\n * Whether the picked theme carries edits of this site's own — what \"Restore\"\n * and \"Update\" act on. The site's dark-scheme setting is not an edit to the\n * theme, so an override holding only that does not count.\n */\nexport function hasThemeEdits(host: ThemeLibraryHost | null | undefined): boolean {\n const read = readArtifactOverride({ overrides: host?.themeOverride })\n if (!read || isEmptyOverride(read.patch)) return false\n if (!isRecord(read.patch)) return true\n return Object.keys(read.patch).some((key) => key !== 'darkScheme')\n}\n"],"names":["diffOverride","isEmptyOverride","overrideWriteValue","readArtifactOverride","resolveOverride","resolveSiteTheme","themeArtifactContent","THEME_LIBRARY_COLLECTION","THEME_LIBRARY_MAX_CUSTOM","THEME_NAME_MAX","KINDS","DEFAULT_THEME_ENTRY_ID","SITE_THEME_ENTRY_ID","DEFAULT_THEME_NAME","presetEntryId","presetId","replace","installedEntryId","listingId","isRecord","value","Array","isArray","hasContent","theme","Boolean","Object","keys","length","readThemeSelection","host","stored","themeSelection","includes","kind","id","name","themeInstalledFrom","normalizeThemeName","trimmed","trim","slice","THEME_FIELD_DELETE","overrideValue","base","edited","baseSha256","patch","withSiteSettings","from","next","darkScheme","resolveStash","stash","read","overrides","sha","installedFrom","fileCurrent","current","entries","override","undefined","op","data","entry","pointAt","selection","themeOverride","themeReplaced","planThemeLibraryAction","input","action","resolved","planSelect","target","ok","status","error","customCount","values","filter","newId","isLegacySiteTheme","renamedSelection","writes","push","hasThemeEdits","some","key"],"mappings":"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"}
@@ -18,6 +18,11 @@
18
18
  * Where an account came from (AGL-1731) — the campaign contract between the
19
19
  * marketing site's links and the console's signup.
20
20
  *
21
+ * Named for what it parses, the web's UTM labels. The `campaign` in
22
+ * `utm_campaign` is the label an ad push carries; it is not the Marketing
23
+ * plugin's campaign, and nothing here reads one. What a site's own visitors
24
+ * carry to the moment they identify is `campaign-touch.ts`'s.
25
+ *
21
26
  * Until this existed a paid click, an organic visit and a partner link
22
27
  * arrived indistinguishable: `sign_up` carried `method` and nothing else, so
23
28
  * no report could say which spend produced a customer. That is tolerable
@@ -70,9 +75,9 @@
70
75
  * identically — two spellings would read as two dimensions in GA4 and split
71
76
  * every report in half.
72
77
  */
73
- export declare const CAMPAIGN_QUERY_KEYS: readonly ["utm_source", "utm_medium", "utm_campaign"];
78
+ export declare const UTM_QUERY_KEYS: readonly ["utm_source", "utm_medium", "utm_campaign"];
74
79
  /** A campaign, with every field optional — a partial one is still worth having. */
75
- export interface CampaignAttribution {
80
+ export interface UtmAttribution {
76
81
  /** `utm_source` — the channel: `google`, `hn`, a partner's name. */
77
82
  source?: string;
78
83
  /** `utm_medium` — the kind of placement: `cpc`, `email`, `referral`. */
@@ -81,7 +86,7 @@ export interface CampaignAttribution {
81
86
  campaign?: string;
82
87
  }
83
88
  /** What a Server Component holds before it has a `URLSearchParams`. */
84
- export type CampaignParamSource = URLSearchParams | Record<string, string | string[] | undefined> | null | undefined;
89
+ export type UtmParamSource = URLSearchParams | Record<string, string | string[] | undefined> | null | undefined;
85
90
  /**
86
91
  * Read the campaign off a signup URL, or null when it names none.
87
92
  *
@@ -89,12 +94,12 @@ export type CampaignParamSource = URLSearchParams | Record<string, string | stri
89
94
  * all". An empty object written to an account would read as "arrived from
90
95
  * nowhere, confirmed" instead of "never asked", and those are different facts.
91
96
  */
92
- export declare function parseCampaignAttribution(params: CampaignParamSource): CampaignAttribution | null;
97
+ export declare function parseUtmAttribution(params: UtmParamSource): UtmAttribution | null;
93
98
  /**
94
99
  * The canonical query string for a campaign — the ONLY place the stored form
95
100
  * is written, so it cannot drift from what the parser reads back.
96
101
  */
97
- export declare function campaignAttributionQuery(attribution: CampaignAttribution | null | undefined): string;
102
+ export declare function utmAttributionQuery(attribution: UtmAttribution | null | undefined): string;
98
103
  /**
99
104
  * The campaign as GA4 event parameters, ready to spread into `sign_up`.
100
105
  *
@@ -110,7 +115,7 @@ export declare function campaignAttributionQuery(attribution: CampaignAttributio
110
115
  * sanitizer as an absence but read, to whoever writes the report, as a
111
116
  * dimension that is populated sometimes and broken the rest of the time.
112
117
  */
113
- export declare function campaignEventParams(attribution: CampaignAttribution | null | undefined): {
118
+ export declare function utmEventParams(attribution: UtmAttribution | null | undefined): {
114
119
  campaign_source?: string;
115
120
  campaign_medium?: string;
116
121
  campaign_name?: string;
@@ -18,6 +18,11 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
18
18
  * Where an account came from (AGL-1731) — the campaign contract between the
19
19
  * marketing site's links and the console's signup.
20
20
  *
21
+ * Named for what it parses, the web's UTM labels. The `campaign` in
22
+ * `utm_campaign` is the label an ad push carries; it is not the Marketing
23
+ * plugin's campaign, and nothing here reads one. What a site's own visitors
24
+ * carry to the moment they identify is `campaign-touch.ts`'s.
25
+ *
21
26
  * Until this existed a paid click, an organic visit and a partner link
22
27
  * arrived indistinguishable: `sign_up` carried `method` and nothing else, so
23
28
  * no report could say which spend produced a customer. That is tolerable
@@ -68,14 +73,14 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
68
73
  * site's links, the stored wire form and this parser all have to spell them
69
74
  * identically — two spellings would read as two dimensions in GA4 and split
70
75
  * every report in half.
71
- */ export const CAMPAIGN_QUERY_KEYS = [
76
+ */ export const UTM_QUERY_KEYS = [
72
77
  'utm_source',
73
78
  'utm_medium',
74
79
  'utm_campaign'
75
80
  ];
76
81
  /** Longest value stored or sent, matching `sanitizeEventParams`'s own cap. */ const MAX_VALUE_LENGTH = 100;
77
82
  /** The same shape test the event sanitizer uses, applied to the stored exit too. */ const EMAIL_SHAPED = /[^\s@]+@[^\s@]+\.[^\s@]+/;
78
- /** Which `CampaignAttribution` field each URL key fills. */ const FIELD_FOR_KEY = {
83
+ /** Which `UtmAttribution` field each URL key fills. */ const FIELD_FOR_KEY = {
79
84
  utm_source: 'source',
80
85
  utm_medium: 'medium',
81
86
  utm_campaign: 'campaign'
@@ -113,10 +118,10 @@ function rawValue(params, key) {
113
118
  * Null rather than `{}` so a caller can branch on "was there a campaign at
114
119
  * all". An empty object written to an account would read as "arrived from
115
120
  * nowhere, confirmed" instead of "never asked", and those are different facts.
116
- */ export function parseCampaignAttribution(params) {
121
+ */ export function parseUtmAttribution(params) {
117
122
  if (!params) return null;
118
123
  const attribution = {};
119
- for (const key of CAMPAIGN_QUERY_KEYS){
124
+ for (const key of UTM_QUERY_KEYS){
120
125
  const value = scrubValue(rawValue(params, key));
121
126
  if (value) attribution[FIELD_FOR_KEY[key]] = value;
122
127
  }
@@ -125,10 +130,10 @@ function rawValue(params, key) {
125
130
  /**
126
131
  * The canonical query string for a campaign — the ONLY place the stored form
127
132
  * is written, so it cannot drift from what the parser reads back.
128
- */ export function campaignAttributionQuery(attribution) {
133
+ */ export function utmAttributionQuery(attribution) {
129
134
  if (!attribution) return '';
130
135
  const params = new URLSearchParams();
131
- for (const key of CAMPAIGN_QUERY_KEYS){
136
+ for (const key of UTM_QUERY_KEYS){
132
137
  const value = attribution[FIELD_FOR_KEY[key]];
133
138
  if (value) params.set(key, value);
134
139
  }
@@ -148,7 +153,7 @@ function rawValue(params, key) {
148
153
  * `campaign_source: undefined` on every unattributed signup would survive the
149
154
  * sanitizer as an absence but read, to whoever writes the report, as a
150
155
  * dimension that is populated sometimes and broken the rest of the time.
151
- */ export function campaignEventParams(attribution) {
156
+ */ export function utmEventParams(attribution) {
152
157
  if (!attribution) return {};
153
158
  return _extends({}, attribution.source ? {
154
159
  campaign_source: attribution.source
@@ -159,4 +164,4 @@ function rawValue(params, key) {
159
164
  } : {});
160
165
  }
161
166
 
162
- //# sourceMappingURL=campaign-attribution.js.map
167
+ //# sourceMappingURL=utm-attribution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/utm-attribution.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 * Where an account came from (AGL-1731) — the campaign contract between the\n * marketing site's links and the console's signup.\n *\n * Named for what it parses, the web's UTM labels. The `campaign` in\n * `utm_campaign` is the label an ad push carries; it is not the Marketing\n * plugin's campaign, and nothing here reads one. What a site's own visitors\n * carry to the moment they identify is `campaign-touch.ts`'s.\n *\n * Until this existed a paid click, an organic visit and a partner link\n * arrived indistinguishable: `sign_up` carried `method` and nothing else, so\n * no report could say which spend produced a customer. That is tolerable\n * while nothing is being spent and not tolerable the day advertising starts,\n * because the measurement has to exist BEFORE the traffic — a signup that\n * lands unattributed is unattributed forever.\n *\n * ## Why an allowlist, and why exactly three\n *\n * `utm_source`, `utm_medium` and `utm_campaign` are the three axes an ad\n * report is read on: which channel, what kind of placement, which push. They\n * are also the three the marketing site can be told to emit without further\n * decisions.\n *\n * `utm_term` and `utm_content` are deliberately OUT, matching the refusal the\n * tenant's own first-party collector already made for its visitors\n * (`apps/tenant/app/api/analytics/collect/route.ts`): keyword- and\n * variant-level labels multiply cardinality without answering a question\n * anyone asks of a signup, and a keyword string is the most likely of the\n * five to carry something a person typed. `gclid` and bare `ref` are out for\n * that same cardinality reason. Not for a privacy one: the property runs ads\n * personalization ON in every region, and Google's own auto-tagging already\n * carries the click identifier into it, so re-collecting `gclid` here would\n * duplicate a field the platform owns rather than withhold anything.\n *\n * The allowlist is the privacy mechanism, not a convenience. A parser that\n * copied \"the campaign-ish parameters\" would be one marketing link away from\n * storing `?email=` against a person, and the standing rule is that personal\n * data never travels in a URL parameter in the first place.\n *\n * ## Two exits, and only one of them is already guarded\n *\n * A parsed campaign leaves this process twice: onto the GA4 `sign_up` hit,\n * and into `users/{uid}` so revenue can be attributed to it months later.\n * Only the first passes `sanitizeEventParams`. The Firestore write does not,\n * so the scrub — email shape refused, length capped, blanks dropped — lives\n * HERE, on the way in, and both exits inherit it.\n *\n * ## Why the wire form is what gets stored\n *\n * Same contract as the AGL-1535 plan intent it rides beside: the stored value\n * is the query string, re-parsed by this parser on the way out. `users/{uid}`\n * is owner-writable, so a stored field is a client-FORGEABLE field. Re-parsing\n * means a hand-edited document can claim no more than a hand-edited URL could,\n * which is a marketing label and nothing that touches entitlement.\n */\n\n/**\n * The URL parameter names, in report order. Exported because the marketing\n * site's links, the stored wire form and this parser all have to spell them\n * identically — two spellings would read as two dimensions in GA4 and split\n * every report in half.\n */\nexport const UTM_QUERY_KEYS = [\n 'utm_source',\n 'utm_medium',\n 'utm_campaign',\n] as const\n\n/** A campaign, with every field optional — a partial one is still worth having. */\nexport interface UtmAttribution {\n /** `utm_source` — the channel: `google`, `hn`, a partner's name. */\n source?: string\n /** `utm_medium` — the kind of placement: `cpc`, `email`, `referral`. */\n medium?: string\n /** `utm_campaign` — which push: `sept-launch`. */\n campaign?: string\n}\n\n/** Longest value stored or sent, matching `sanitizeEventParams`'s own cap. */\nconst MAX_VALUE_LENGTH = 100\n\n/** The same shape test the event sanitizer uses, applied to the stored exit too. */\nconst EMAIL_SHAPED = /[^\\s@]+@[^\\s@]+\\.[^\\s@]+/\n\n/** Which `UtmAttribution` field each URL key fills. */\nconst FIELD_FOR_KEY: Record<\n (typeof UTM_QUERY_KEYS)[number],\n keyof UtmAttribution\n> = {\n utm_source: 'source',\n utm_medium: 'medium',\n utm_campaign: 'campaign',\n}\n\n/** What a Server Component holds before it has a `URLSearchParams`. */\nexport type UtmParamSource =\n | URLSearchParams\n | Record<string, string | string[] | undefined>\n | null\n | undefined\n\nfunction rawValue(params: UtmParamSource, key: string): string | null {\n if (!params) return null\n if (typeof (params as URLSearchParams).get === 'function') {\n return (params as URLSearchParams).get(key)\n }\n const value = (params as Record<string, string | string[] | undefined>)[key]\n // A repeated parameter arrives as an array. The first one wins rather than\n // being joined: `utm_medium=cpc&utm_medium=organic` is a malformed link, and\n // inventing `cpc,organic` would put a value in the reports that no campaign\n // ever set.\n if (Array.isArray(value)) return value.length ? value[0] : null\n return typeof value === 'string' ? value : null\n}\n\n/**\n * Reduce one raw parameter to something storable, or null to drop it.\n *\n * Dropping the single value rather than the whole campaign is deliberate: a\n * mail-merge link that puts an address in `utm_source` still names a real\n * `utm_campaign`, and keeping the half that is safe beats losing the\n * attribution to protect the half that is not.\n */\nfunction scrubValue(value: string | null): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n if (!trimmed) return null\n if (EMAIL_SHAPED.test(trimmed)) return null\n return trimmed.slice(0, MAX_VALUE_LENGTH)\n}\n\n/**\n * Read the campaign off a signup URL, or null when it names none.\n *\n * Null rather than `{}` so a caller can branch on \"was there a campaign at\n * all\". An empty object written to an account would read as \"arrived from\n * nowhere, confirmed\" instead of \"never asked\", and those are different facts.\n */\nexport function parseUtmAttribution(\n params: UtmParamSource,\n): UtmAttribution | null {\n if (!params) return null\n const attribution: UtmAttribution = {}\n for (const key of UTM_QUERY_KEYS) {\n const value = scrubValue(rawValue(params, key))\n if (value) attribution[FIELD_FOR_KEY[key]] = value\n }\n return Object.keys(attribution).length ? attribution : null\n}\n\n/**\n * The canonical query string for a campaign — the ONLY place the stored form\n * is written, so it cannot drift from what the parser reads back.\n */\nexport function utmAttributionQuery(\n attribution: UtmAttribution | null | undefined,\n): string {\n if (!attribution) return ''\n const params = new URLSearchParams()\n for (const key of UTM_QUERY_KEYS) {\n const value = attribution[FIELD_FOR_KEY[key]]\n if (value) params.set(key, value)\n }\n return params.toString()\n}\n\n/**\n * The campaign as GA4 event parameters, ready to spread into `sign_up`.\n *\n * Renamed off the `utm_` spellings on purpose. These are OUR event parameters,\n * registered as custom dimensions on the property (see `docs/ANALYTICS.md`);\n * the `utm_` names belong to GA's own automatic campaign collection, and\n * shipping a custom parameter under a name the platform also owns is how a\n * dimension ends up meaning two things.\n *\n * Returns an empty object — never keys with `undefined` values — so that\n * spreading it into an organic signup's params adds nothing at all. A\n * `campaign_source: undefined` on every unattributed signup would survive the\n * sanitizer as an absence but read, to whoever writes the report, as a\n * dimension that is populated sometimes and broken the rest of the time.\n */\nexport function utmEventParams(\n attribution: UtmAttribution | null | undefined,\n): {\n campaign_source?: string\n campaign_medium?: string\n campaign_name?: string\n} {\n if (!attribution) return {}\n return {\n ...(attribution.source ? { campaign_source: attribution.source } : {}),\n ...(attribution.medium ? { campaign_medium: attribution.medium } : {}),\n ...(attribution.campaign ? { campaign_name: attribution.campaign } : {}),\n }\n}\n"],"names":["UTM_QUERY_KEYS","MAX_VALUE_LENGTH","EMAIL_SHAPED","FIELD_FOR_KEY","utm_source","utm_medium","utm_campaign","rawValue","params","key","get","value","Array","isArray","length","scrubValue","trimmed","trim","test","slice","parseUtmAttribution","attribution","Object","keys","utmAttributionQuery","URLSearchParams","set","toString","utmEventParams","source","campaign_source","medium","campaign_medium","campaign","campaign_name"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsDC,GAED;;;;;CAKC,GACD,OAAO,MAAMA,iBAAiB;IAC5B;IACA;IACA;CACD,CAAS;AAYV,4EAA4E,GAC5E,MAAMC,mBAAmB;AAEzB,kFAAkF,GAClF,MAAMC,eAAe;AAErB,qDAAqD,GACrD,MAAMC,gBAGF;IACFC,YAAY;IACZC,YAAY;IACZC,cAAc;AAChB;AASA,SAASC,SAASC,MAAsB,EAAEC,GAAW;IACnD,IAAI,CAACD,QAAQ,OAAO;IACpB,IAAI,OAAO,AAACA,OAA2BE,GAAG,KAAK,YAAY;QACzD,OAAO,AAACF,OAA2BE,GAAG,CAACD;IACzC;IACA,MAAME,QAAQ,AAACH,MAAwD,CAACC,IAAI;IAC5E,2EAA2E;IAC3E,6EAA6E;IAC7E,4EAA4E;IAC5E,YAAY;IACZ,IAAIG,MAAMC,OAAO,CAACF,QAAQ,OAAOA,MAAMG,MAAM,GAAGH,KAAK,CAAC,EAAE,GAAG;IAC3D,OAAO,OAAOA,UAAU,WAAWA,QAAQ;AAC7C;AAEA;;;;;;;CAOC,GACD,SAASI,WAAWJ,KAAoB;IACtC,IAAI,OAAOA,UAAU,UAAU,OAAO;IACtC,MAAMK,UAAUL,MAAMM,IAAI;IAC1B,IAAI,CAACD,SAAS,OAAO;IACrB,IAAId,aAAagB,IAAI,CAACF,UAAU,OAAO;IACvC,OAAOA,QAAQG,KAAK,CAAC,GAAGlB;AAC1B;AAEA;;;;;;CAMC,GACD,OAAO,SAASmB,oBACdZ,MAAsB;IAEtB,IAAI,CAACA,QAAQ,OAAO;IACpB,MAAMa,cAA8B,CAAC;IACrC,KAAK,MAAMZ,OAAOT,eAAgB;QAChC,MAAMW,QAAQI,WAAWR,SAASC,QAAQC;QAC1C,IAAIE,OAAOU,WAAW,CAAClB,aAAa,CAACM,IAAI,CAAC,GAAGE;IAC/C;IACA,OAAOW,OAAOC,IAAI,CAACF,aAAaP,MAAM,GAAGO,cAAc;AACzD;AAEA;;;CAGC,GACD,OAAO,SAASG,oBACdH,WAA8C;IAE9C,IAAI,CAACA,aAAa,OAAO;IACzB,MAAMb,SAAS,IAAIiB;IACnB,KAAK,MAAMhB,OAAOT,eAAgB;QAChC,MAAMW,QAAQU,WAAW,CAAClB,aAAa,CAACM,IAAI,CAAC;QAC7C,IAAIE,OAAOH,OAAOkB,GAAG,CAACjB,KAAKE;IAC7B;IACA,OAAOH,OAAOmB,QAAQ;AACxB;AAEA;;;;;;;;;;;;;;CAcC,GACD,OAAO,SAASC,eACdP,WAA8C;IAM9C,IAAI,CAACA,aAAa,OAAO,CAAC;IAC1B,OAAO,aACDA,YAAYQ,MAAM,GAAG;QAAEC,iBAAiBT,YAAYQ,MAAM;IAAC,IAAI,CAAC,GAChER,YAAYU,MAAM,GAAG;QAAEC,iBAAiBX,YAAYU,MAAM;IAAC,IAAI,CAAC,GAChEV,YAAYY,QAAQ,GAAG;QAAEC,eAAeb,YAAYY,QAAQ;IAAC,IAAI,CAAC;AAE1E"}
@@ -15,9 +15,9 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  /**
18
- * Carry the campaign across the domain hop (AGL-1731).
18
+ * Carry the visit's UTM labels across the domain hop (AGL-1731).
19
19
  *
20
- * `campaign-attribution.ts` is the READER half of this contract and it works.
20
+ * `utm-attribution.ts` is the READER half of this contract and it works.
21
21
  * This is the half that was missing, and without it the reader was fed
22
22
  * nothing: `aglyn.com` is a tenant published site and `app.aglyn.com` is the
23
23
  * console, a real cross-origin hop, and no code anywhere put a `utm_*`
@@ -95,7 +95,7 @@
95
95
  * it. There is no default, no inference from the referrer, and no
96
96
  * `utm_source=direct` — a signup with no campaign must reach the console with
97
97
  * no campaign, so that "arrived from nowhere" and "never asked" stay the
98
- * distinct facts `campaign-attribution.ts` keeps them.
98
+ * distinct facts `utm-attribution.ts` keeps them.
99
99
  *
100
100
  * Only links to OUR OWN console origin are touched, and the origin is supplied
101
101
  * by the caller rather than written here — a self-host install points
@@ -115,14 +115,14 @@
115
115
  * is the exact failure AGL-1731 is about, and it is worse than a few
116
116
  * mislabelled rows that GA's own Hostname dimension can already separate.
117
117
  */
118
- import { type CampaignAttribution } from './campaign-attribution';
118
+ import { type UtmAttribution } from './utm-attribution';
119
119
  /**
120
120
  * Where the first touch of this visit is held. `sessionStorage`, so it dies
121
121
  * with the tab: a campaign is a fact about one visit, and a value that
122
122
  * outlived the visit would start attributing next week's organic return to
123
123
  * this week's ad.
124
124
  */
125
- export declare const CAMPAIGN_VISIT_STORAGE_KEY = "aglyn:campaign";
125
+ export declare const UTM_VISIT_STORAGE_KEY = "aglyn:campaign";
126
126
  /**
127
127
  * What a read of the first-touch store produced.
128
128
  *
@@ -134,9 +134,9 @@ export declare const CAMPAIGN_VISIT_STORAGE_KEY = "aglyn:campaign";
134
134
  * treats it differently: it falls through to the live URL instead of
135
135
  * concluding anything.
136
136
  */
137
- export type VisitCampaignRead = {
137
+ export type VisitUtmRead = {
138
138
  status: 'campaign';
139
- campaign: CampaignAttribution;
139
+ campaign: UtmAttribution;
140
140
  } | {
141
141
  status: 'none';
142
142
  } | {
@@ -150,7 +150,7 @@ export type VisitCampaignRead = {
150
150
  * string can claim no more than an inbound URL could — three allowlisted keys,
151
151
  * trimmed, email shapes refused, capped.
152
152
  */
153
- export declare function readVisitCampaign(): VisitCampaignRead;
153
+ export declare function readVisitUtm(): VisitUtmRead;
154
154
  /**
155
155
  * Remember the campaign on the current URL as this visit's first touch.
156
156
  *
@@ -161,7 +161,7 @@ export declare function readVisitCampaign(): VisitCampaignRead;
161
161
  *
162
162
  * Returns what is now remembered so a caller can assert on it.
163
163
  */
164
- export declare function rememberVisitCampaign(search?: string): CampaignAttribution | null;
164
+ export declare function rememberVisitUtm(search?: string): UtmAttribution | null;
165
165
  /**
166
166
  * Tell this module what the visitor's analytics consent state is.
167
167
  *
@@ -171,7 +171,7 @@ export declare function rememberVisitCampaign(search?: string): CampaignAttribut
171
171
  * visitor who changes their mind mid-visit should not leave the thing they
172
172
  * withdrew consent for sitting on their device.
173
173
  */
174
- export declare function setCampaignForwardingConsent(allowed: boolean | null): void;
174
+ export declare function setUtmForwardingConsent(allowed: boolean | null): void;
175
175
  /**
176
176
  * The campaign to forward, first touch preferred.
177
177
  *
@@ -179,7 +179,7 @@ export declare function setCampaignForwardingConsent(allowed: boolean | null): v
179
179
  * which is the point of carrying that state at all: a broken store degrades
180
180
  * this to tier 1 rather than to silence.
181
181
  */
182
- export declare function campaignToForward(search?: string): CampaignAttribution | null;
182
+ export declare function utmToForward(search?: string): UtmAttribution | null;
183
183
  /**
184
184
  * The href a console-bound link should carry for this visitor, or null to
185
185
  * leave it exactly as authored.
@@ -194,7 +194,7 @@ export declare function campaignToForward(search?: string): CampaignAttribution
194
194
  * row describes an event that never happened. Everything else on the href —
195
195
  * `plan`, `interval`, the AGL-1535 intent — is preserved untouched.
196
196
  */
197
- export declare function decorateCampaignHref(href: string, baseHref: string, consoleOrigin: string, campaign: CampaignAttribution | null): string | null;
197
+ export declare function decorateUtmHref(href: string, baseHref: string, consoleOrigin: string, campaign: UtmAttribution | null): string | null;
198
198
  /**
199
199
  * Start forwarding the campaign onto console-bound links on this page.
200
200
  *
@@ -213,8 +213,8 @@ export declare function decorateCampaignHref(href: string, baseHref: string, con
213
213
  * Returns an uninstall function for tests and for a caller that owns the page
214
214
  * lifecycle.
215
215
  */
216
- export declare function installCampaignForwarding(options: {
216
+ export declare function installUtmForwarding(options: {
217
217
  consoleOrigin: string;
218
218
  }): () => void;
219
219
  /** Test seam — removes both listeners, forgets them, and forgets consent. */
220
- export declare function resetCampaignForwarding(): void;
220
+ export declare function resetUtmForwarding(): void;