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

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 (358) hide show
  1. package/package.json +15 -11
  2. package/src/lib/app-utils/agent-openapi.js +1 -1
  3. package/src/lib/app-utils/agent-openapi.js.map +1 -1
  4. package/src/lib/app-utils/analytics-events.d.ts +3 -2
  5. package/src/lib/app-utils/analytics-events.js +3 -2
  6. package/src/lib/app-utils/analytics-events.js.map +1 -1
  7. package/src/lib/app-utils/api-plugins.d.ts +30 -0
  8. package/src/lib/app-utils/api-plugins.js +24 -1
  9. package/src/lib/app-utils/api-plugins.js.map +1 -1
  10. package/src/lib/app-utils/author-html.d.ts +1 -1
  11. package/src/lib/app-utils/author-html.js.map +1 -1
  12. package/src/lib/app-utils/bandwidth-cap.d.ts +12 -1
  13. package/src/lib/app-utils/bandwidth-cap.js +17 -1
  14. package/src/lib/app-utils/bandwidth-cap.js.map +1 -1
  15. package/src/lib/app-utils/compose-reusable-components.d.ts +19 -0
  16. package/src/lib/app-utils/compose-reusable-components.js +116 -26
  17. package/src/lib/app-utils/compose-reusable-components.js.map +1 -1
  18. package/src/lib/app-utils/console-routes.d.ts +4 -0
  19. package/src/lib/app-utils/console-routes.js +3 -0
  20. package/src/lib/app-utils/console-routes.js.map +1 -1
  21. package/src/lib/app-utils/contacts.d.ts +71 -0
  22. package/src/lib/app-utils/contacts.js +55 -0
  23. package/src/lib/app-utils/contacts.js.map +1 -1
  24. package/src/lib/app-utils/contexts.d.ts +1 -0
  25. package/src/lib/app-utils/contexts.js +1 -0
  26. package/src/lib/app-utils/contexts.js.map +1 -1
  27. package/src/lib/app-utils/crm-email-templates.js +21 -4
  28. package/src/lib/app-utils/crm-email-templates.js.map +1 -1
  29. package/src/lib/app-utils/crm-kinds.d.ts +2 -0
  30. package/src/lib/app-utils/crm-kinds.js +1 -0
  31. package/src/lib/app-utils/crm-kinds.js.map +1 -1
  32. package/src/lib/app-utils/crm.d.ts +1199 -67
  33. package/src/lib/app-utils/crm.js +1951 -310
  34. package/src/lib/app-utils/crm.js.map +1 -1
  35. package/src/lib/app-utils/csv-import.d.ts +10 -38
  36. package/src/lib/app-utils/csv-import.js +17 -42
  37. package/src/lib/app-utils/csv-import.js.map +1 -1
  38. package/src/lib/app-utils/csv.d.ts +32 -11
  39. package/src/lib/app-utils/csv.js +43 -5
  40. package/src/lib/app-utils/csv.js.map +1 -1
  41. package/src/lib/app-utils/default-site.d.ts +116 -0
  42. package/src/lib/app-utils/default-site.js +1024 -0
  43. package/src/lib/app-utils/default-site.js.map +1 -0
  44. package/src/lib/app-utils/docs-help.generated.d.ts +23 -23
  45. package/src/lib/app-utils/docs-help.generated.js +47 -10
  46. package/src/lib/app-utils/docs-help.generated.js.map +1 -1
  47. package/src/lib/app-utils/docs-index.generated.js +746 -151
  48. package/src/lib/app-utils/docs-index.generated.js.map +1 -1
  49. package/src/lib/app-utils/draft-placeholders.d.ts +76 -0
  50. package/src/lib/app-utils/draft-placeholders.js +115 -0
  51. package/src/lib/app-utils/draft-placeholders.js.map +1 -0
  52. package/src/lib/app-utils/entity-picker-context.d.ts +19 -15
  53. package/src/lib/app-utils/entity-picker-context.js +4 -4
  54. package/src/lib/app-utils/entity-picker-context.js.map +1 -1
  55. package/src/lib/app-utils/expand-repeatables.d.ts +66 -10
  56. package/src/lib/app-utils/expand-repeatables.js +88 -14
  57. package/src/lib/app-utils/expand-repeatables.js.map +1 -1
  58. package/src/lib/app-utils/forms.d.ts +33 -22
  59. package/src/lib/app-utils/forms.js +47 -28
  60. package/src/lib/app-utils/forms.js.map +1 -1
  61. package/src/lib/app-utils/full-use-cost.d.ts +277 -0
  62. package/src/lib/app-utils/full-use-cost.js +421 -0
  63. package/src/lib/app-utils/full-use-cost.js.map +1 -0
  64. package/src/lib/app-utils/health-report.js +33 -0
  65. package/src/lib/app-utils/health-report.js.map +1 -1
  66. package/src/lib/app-utils/leaving-notice.d.ts +96 -0
  67. package/src/lib/app-utils/leaving-notice.js +157 -0
  68. package/src/lib/app-utils/leaving-notice.js.map +1 -0
  69. package/src/lib/app-utils/llms-txt.d.ts +20 -0
  70. package/src/lib/app-utils/llms-txt.js +7 -1
  71. package/src/lib/app-utils/llms-txt.js.map +1 -1
  72. package/src/lib/app-utils/media-asset-facts.d.ts +16 -1
  73. package/src/lib/app-utils/media-asset-facts.js +40 -13
  74. package/src/lib/app-utils/media-asset-facts.js.map +1 -1
  75. package/src/lib/app-utils/media-bandwidth.d.ts +52 -0
  76. package/src/lib/app-utils/media-bandwidth.js +94 -0
  77. package/src/lib/app-utils/media-bandwidth.js.map +1 -0
  78. package/src/lib/app-utils/media-ref.d.ts +241 -33
  79. package/src/lib/app-utils/media-ref.js +324 -43
  80. package/src/lib/app-utils/media-ref.js.map +1 -1
  81. package/src/lib/app-utils/media-src.d.ts +8 -8
  82. package/src/lib/app-utils/media-src.js +27 -11
  83. package/src/lib/app-utils/media-src.js.map +1 -1
  84. package/src/lib/app-utils/media-takedown-reach.d.ts +4 -1
  85. package/src/lib/app-utils/media-takedown-reach.js +6 -3
  86. package/src/lib/app-utils/media-takedown-reach.js.map +1 -1
  87. package/src/lib/app-utils/notifications.d.ts +1 -1
  88. package/src/lib/app-utils/notifications.js +2 -0
  89. package/src/lib/app-utils/notifications.js.map +1 -1
  90. package/src/lib/app-utils/operator-alerts.js +17 -0
  91. package/src/lib/app-utils/operator-alerts.js.map +1 -1
  92. package/src/lib/app-utils/organizations.d.ts +51 -2
  93. package/src/lib/app-utils/organizations.js +56 -3
  94. package/src/lib/app-utils/organizations.js.map +1 -1
  95. package/src/lib/app-utils/page-record-sources.d.ts +87 -0
  96. package/src/lib/app-utils/page-record-sources.js +53 -0
  97. package/src/lib/app-utils/page-record-sources.js.map +1 -0
  98. package/src/lib/app-utils/paid-media-source.d.ts +3 -7
  99. package/src/lib/app-utils/paid-media-source.js +5 -19
  100. package/src/lib/app-utils/paid-media-source.js.map +1 -1
  101. package/src/lib/app-utils/person-erasure.d.ts +5 -2
  102. package/src/lib/app-utils/person-erasure.js.map +1 -1
  103. package/src/lib/app-utils/picklists.d.ts +187 -0
  104. package/src/lib/app-utils/picklists.js +320 -0
  105. package/src/lib/app-utils/picklists.js.map +1 -0
  106. package/src/lib/app-utils/plan-entitlements.d.ts +220 -50
  107. package/src/lib/app-utils/plan-entitlements.js +309 -115
  108. package/src/lib/app-utils/plan-entitlements.js.map +1 -1
  109. package/src/lib/app-utils/realm-host-surface.generated.js +2 -0
  110. package/src/lib/app-utils/realm-host-surface.generated.js.map +1 -1
  111. package/src/lib/app-utils/release-flags.d.ts +1 -1
  112. package/src/lib/app-utils/release-flags.js +11 -0
  113. package/src/lib/app-utils/release-flags.js.map +1 -1
  114. package/src/lib/app-utils/rendered-widths.d.ts +121 -0
  115. package/src/lib/app-utils/rendered-widths.js +211 -0
  116. package/src/lib/app-utils/rendered-widths.js.map +1 -0
  117. package/src/lib/app-utils/repeat-sources.d.ts +2 -1
  118. package/src/lib/app-utils/repeat-sources.js.map +1 -1
  119. package/src/lib/app-utils/screen-link-context-value.d.ts +7 -0
  120. package/src/lib/app-utils/screen-link-context-value.js.map +1 -1
  121. package/src/lib/app-utils/screen-link-context.js +14 -2
  122. package/src/lib/app-utils/screen-link-context.js.map +1 -1
  123. package/src/lib/app-utils/screen-route.d.ts +157 -36
  124. package/src/lib/app-utils/screen-route.js +191 -41
  125. package/src/lib/app-utils/screen-route.js.map +1 -1
  126. package/src/lib/app-utils/seo-audit.d.ts +11 -1
  127. package/src/lib/app-utils/seo-audit.js +33 -13
  128. package/src/lib/app-utils/seo-audit.js.map +1 -1
  129. package/src/lib/app-utils/seo-keywords.d.ts +11 -0
  130. package/src/lib/app-utils/seo-keywords.js +19 -5
  131. package/src/lib/app-utils/seo-keywords.js.map +1 -1
  132. package/src/lib/app-utils/seo-page-facts.d.ts +47 -4
  133. package/src/lib/app-utils/seo-page-facts.js +136 -31
  134. package/src/lib/app-utils/seo-page-facts.js.map +1 -1
  135. package/src/lib/app-utils/seo-site-scan.d.ts +42 -4
  136. package/src/lib/app-utils/seo-site-scan.js +113 -12
  137. package/src/lib/app-utils/seo-site-scan.js.map +1 -1
  138. package/src/lib/app-utils/server.d.ts +5 -4
  139. package/src/lib/app-utils/server.js +14 -5
  140. package/src/lib/app-utils/server.js.map +1 -1
  141. package/src/lib/app-utils/site-icon-set.d.ts +195 -0
  142. package/src/lib/app-utils/site-icon-set.js +351 -0
  143. package/src/lib/app-utils/site-icon-set.js.map +1 -0
  144. package/src/lib/app-utils/site-interactions.d.ts +101 -4
  145. package/src/lib/app-utils/site-interactions.js +120 -4
  146. package/src/lib/app-utils/site-interactions.js.map +1 -1
  147. package/src/lib/app-utils/starter-template-nodes.d.ts +7 -0
  148. package/src/lib/app-utils/starter-template-nodes.js +3 -0
  149. package/src/lib/app-utils/starter-template-nodes.js.map +1 -1
  150. package/src/lib/app-utils/starter-templates.d.ts +5 -19
  151. package/src/lib/app-utils/starter-templates.js +5 -49
  152. package/src/lib/app-utils/starter-templates.js.map +1 -1
  153. package/src/lib/app-utils/transfer-launcher-context.d.ts +136 -0
  154. package/src/lib/app-utils/transfer-launcher-context.js +23 -0
  155. package/src/lib/app-utils/transfer-launcher-context.js.map +1 -0
  156. package/src/lib/app-utils/transfer-resume-import.d.ts +39 -0
  157. package/src/lib/app-utils/transfer-resume-import.js +128 -0
  158. package/src/lib/app-utils/transfer-resume-import.js.map +1 -0
  159. package/src/lib/app-utils/upgrade-proposal.d.ts +66 -0
  160. package/src/lib/app-utils/upgrade-proposal.js +95 -0
  161. package/src/lib/app-utils/upgrade-proposal.js.map +1 -0
  162. package/src/lib/app-utils/utc-month.d.ts +33 -0
  163. package/src/lib/app-utils/utc-month.js +35 -0
  164. package/src/lib/app-utils/utc-month.js.map +1 -0
  165. package/src/lib/app-utils/visitor-record-ceiling.d.ts +4 -4
  166. package/src/lib/app-utils/visitor-record-ceiling.js +4 -4
  167. package/src/lib/app-utils/visitor-record-ceiling.js.map +1 -1
  168. package/src/lib/app-utils/wire-nodes.d.ts +39 -19
  169. package/src/lib/app-utils/wire-nodes.js +120 -34
  170. package/src/lib/app-utils/wire-nodes.js.map +1 -1
  171. package/src/lib/data-transfer/access.d.ts +74 -0
  172. package/src/lib/data-transfer/access.js +93 -0
  173. package/src/lib/data-transfer/access.js.map +1 -0
  174. package/src/lib/data-transfer/derive.d.ts +246 -0
  175. package/src/lib/data-transfer/derive.js +1007 -0
  176. package/src/lib/data-transfer/derive.js.map +1 -0
  177. package/src/lib/data-transfer/export-file.d.ts +46 -0
  178. package/src/lib/data-transfer/export-file.js +146 -0
  179. package/src/lib/data-transfer/export-file.js.map +1 -0
  180. package/src/lib/data-transfer/field-catalog.d.ts +134 -0
  181. package/src/lib/data-transfer/field-catalog.js +278 -0
  182. package/src/lib/data-transfer/field-catalog.js.map +1 -0
  183. package/src/lib/data-transfer/header-match.d.ts +129 -0
  184. package/src/lib/data-transfer/header-match.js +367 -0
  185. package/src/lib/data-transfer/header-match.js.map +1 -0
  186. package/src/lib/data-transfer/index.d.ts +34 -0
  187. package/src/lib/data-transfer/index.js +40 -0
  188. package/src/lib/data-transfer/index.js.map +1 -0
  189. package/src/lib/data-transfer/job.d.ts +190 -0
  190. package/src/lib/data-transfer/job.js +229 -0
  191. package/src/lib/data-transfer/job.js.map +1 -0
  192. package/src/lib/data-transfer/lookup.d.ts +45 -0
  193. package/src/lib/data-transfer/lookup.js +71 -0
  194. package/src/lib/data-transfer/lookup.js.map +1 -0
  195. package/src/lib/data-transfer/match.d.ts +99 -0
  196. package/src/lib/data-transfer/match.js +244 -0
  197. package/src/lib/data-transfer/match.js.map +1 -0
  198. package/src/lib/data-transfer/package-plan.d.ts +205 -0
  199. package/src/lib/data-transfer/package-plan.js +475 -0
  200. package/src/lib/data-transfer/package-plan.js.map +1 -0
  201. package/src/lib/data-transfer/package.d.ts +181 -0
  202. package/src/lib/data-transfer/package.js +426 -0
  203. package/src/lib/data-transfer/package.js.map +1 -0
  204. package/src/lib/data-transfer/picklist-map.d.ts +139 -0
  205. package/src/lib/data-transfer/picklist-map.js +271 -0
  206. package/src/lib/data-transfer/picklist-map.js.map +1 -0
  207. package/src/lib/data-transfer/plan.d.ts +176 -0
  208. package/src/lib/data-transfer/plan.js +451 -0
  209. package/src/lib/data-transfer/plan.js.map +1 -0
  210. package/src/lib/data-transfer/policy.d.ts +170 -0
  211. package/src/lib/data-transfer/policy.js +378 -0
  212. package/src/lib/data-transfer/policy.js.map +1 -0
  213. package/src/lib/data-transfer/resource.d.ts +211 -0
  214. package/src/lib/data-transfer/resource.js +241 -0
  215. package/src/lib/data-transfer/resource.js.map +1 -0
  216. package/src/lib/data-transfer/review.d.ts +70 -0
  217. package/src/lib/data-transfer/review.js +233 -0
  218. package/src/lib/data-transfer/review.js.map +1 -0
  219. package/src/lib/data-transfer/similarity.d.ts +40 -0
  220. package/src/lib/data-transfer/similarity.js +106 -0
  221. package/src/lib/data-transfer/similarity.js.map +1 -0
  222. package/src/lib/data-transfer/site-package.d.ts +365 -0
  223. package/src/lib/data-transfer/site-package.js +1077 -0
  224. package/src/lib/data-transfer/site-package.js.map +1 -0
  225. package/src/lib/data-transfer/source.d.ts +74 -0
  226. package/src/lib/data-transfer/source.js +293 -0
  227. package/src/lib/data-transfer/source.js.map +1 -0
  228. package/src/lib/data-transfer/transfer-api.d.ts +898 -0
  229. package/src/lib/data-transfer/transfer-api.js +107 -0
  230. package/src/lib/data-transfer/transfer-api.js.map +1 -0
  231. package/src/lib/foundation/definitions/org-billing.types.d.ts +31 -0
  232. package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
  233. package/src/lib/foundation/definitions/organization.types.d.ts +42 -1
  234. package/src/lib/foundation/definitions/organization.types.js.map +1 -1
  235. package/src/lib/foundation/definitions/platform.types.d.ts +6 -4
  236. package/src/lib/foundation/definitions/platform.types.js.map +1 -1
  237. package/src/lib/foundation/index.d.ts +1 -1
  238. package/src/lib/foundation/index.js.map +1 -1
  239. package/src/lib/plugin-manager/feature-plugins.d.ts +91 -2
  240. package/src/lib/plugin-manager/feature-plugins.js +48 -3
  241. package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
  242. package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +56 -0
  243. package/src/lib/plugin-manager/first-party-plugins.generated.js +1132 -27
  244. package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
  245. package/src/lib/plugin-manager/index.d.ts +0 -1
  246. package/src/lib/plugin-manager/index.js +0 -1
  247. package/src/lib/plugin-manager/index.js.map +1 -1
  248. package/src/lib/plugin-manager/interaction-recipes.d.ts +142 -0
  249. package/src/lib/plugin-manager/interaction-recipes.js +104 -0
  250. package/src/lib/plugin-manager/interaction-recipes.js.map +1 -0
  251. package/src/lib/plugin-manager/interaction-step-checks.d.ts +66 -0
  252. package/src/lib/plugin-manager/interaction-step-checks.js +86 -0
  253. package/src/lib/plugin-manager/interaction-step-checks.js.map +1 -0
  254. package/src/lib/plugin-manager/plugin-artifact-types.d.ts +235 -0
  255. package/src/lib/plugin-manager/plugin-artifact-types.js +99 -0
  256. package/src/lib/plugin-manager/plugin-artifact-types.js.map +1 -0
  257. package/src/lib/plugin-manager/plugin-contact-capture.d.ts +8 -0
  258. package/src/lib/plugin-manager/plugin-contact-capture.js.map +1 -1
  259. package/src/lib/plugin-manager/plugin-conversion-credit.d.ts +216 -0
  260. package/src/lib/plugin-manager/plugin-conversion-credit.js +91 -0
  261. package/src/lib/plugin-manager/plugin-conversion-credit.js.map +1 -0
  262. package/src/lib/plugin-manager/plugin-entity-pickers.d.ts +83 -0
  263. package/src/lib/plugin-manager/plugin-entity-pickers.js +87 -0
  264. package/src/lib/plugin-manager/plugin-entity-pickers.js.map +1 -0
  265. package/src/lib/plugin-manager/plugin-host-resources.d.ts +6 -0
  266. package/src/lib/plugin-manager/plugin-host-resources.js +6 -1
  267. package/src/lib/plugin-manager/plugin-host-resources.js.map +1 -1
  268. package/src/lib/plugin-manager/plugin-intake-gates.d.ts +75 -0
  269. package/src/lib/plugin-manager/plugin-intake-gates.js +49 -0
  270. package/src/lib/plugin-manager/plugin-intake-gates.js.map +1 -0
  271. package/src/lib/plugin-manager/plugin-jobs.d.ts +5 -5
  272. package/src/lib/plugin-manager/plugin-jobs.js +7 -7
  273. package/src/lib/plugin-manager/plugin-jobs.js.map +1 -1
  274. package/src/lib/plugin-manager/plugin-live-paths.d.ts +70 -0
  275. package/src/lib/plugin-manager/plugin-live-paths.js +66 -0
  276. package/src/lib/plugin-manager/plugin-live-paths.js.map +1 -0
  277. package/src/lib/plugin-manager/plugin-org-erasure.d.ts +3 -2
  278. package/src/lib/plugin-manager/plugin-org-erasure.js +30 -5
  279. package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -1
  280. package/src/lib/plugin-manager/plugin-person-erasure.d.ts +68 -9
  281. package/src/lib/plugin-manager/plugin-person-erasure.js +196 -51
  282. package/src/lib/plugin-manager/plugin-person-erasure.js.map +1 -1
  283. package/src/lib/plugin-manager/plugin-person-records.d.ts +275 -0
  284. package/src/lib/plugin-manager/plugin-person-records.js +107 -0
  285. package/src/lib/plugin-manager/plugin-person-records.js.map +1 -0
  286. package/src/lib/plugin-manager/plugin-record-counts.d.ts +76 -0
  287. package/src/lib/plugin-manager/plugin-record-counts.js +49 -0
  288. package/src/lib/plugin-manager/plugin-record-counts.js.map +1 -0
  289. package/src/lib/plugin-manager/plugin-record-email-state.d.ts +26 -0
  290. package/src/lib/plugin-manager/plugin-record-email-state.js +16 -0
  291. package/src/lib/plugin-manager/plugin-record-email-state.js.map +1 -1
  292. package/src/lib/plugin-manager/plugin-record-index.d.ts +10 -0
  293. package/src/lib/plugin-manager/plugin-record-index.js.map +1 -1
  294. package/src/lib/plugin-manager/plugin-record-lists.d.ts +86 -6
  295. package/src/lib/plugin-manager/plugin-record-lists.js +42 -5
  296. package/src/lib/plugin-manager/plugin-record-lists.js.map +1 -1
  297. package/src/lib/plugin-manager/plugin-record-origin.d.ts +79 -0
  298. package/src/lib/plugin-manager/plugin-record-origin.js +46 -0
  299. package/src/lib/plugin-manager/plugin-record-origin.js.map +1 -0
  300. package/src/lib/plugin-manager/plugin-record-pages.d.ts +37 -0
  301. package/src/lib/plugin-manager/plugin-record-pages.js +52 -0
  302. package/src/lib/plugin-manager/plugin-record-pages.js.map +1 -0
  303. package/src/lib/plugin-manager/plugin-record-timeline.d.ts +60 -0
  304. package/src/lib/plugin-manager/plugin-record-timeline.js +16 -0
  305. package/src/lib/plugin-manager/plugin-record-timeline.js.map +1 -1
  306. package/src/lib/plugin-manager/plugin-resource-drafts.d.ts +5 -5
  307. package/src/lib/plugin-manager/plugin-resource-drafts.js.map +1 -1
  308. package/src/lib/plugin-manager/plugin-revocations.d.ts +64 -0
  309. package/src/lib/plugin-manager/plugin-revocations.js +47 -0
  310. package/src/lib/plugin-manager/plugin-revocations.js.map +1 -0
  311. package/src/lib/plugin-manager/plugin-send-tallies.d.ts +69 -0
  312. package/src/lib/plugin-manager/plugin-send-tallies.js +45 -0
  313. package/src/lib/plugin-manager/plugin-send-tallies.js.map +1 -0
  314. package/src/lib/plugin-manager/plugin-server-steps.d.ts +170 -0
  315. package/src/lib/plugin-manager/plugin-server-steps.js +116 -0
  316. package/src/lib/plugin-manager/plugin-server-steps.js.map +1 -0
  317. package/src/lib/plugin-manager/plugin-site-bundle.d.ts +40 -0
  318. package/src/lib/plugin-manager/plugin-site-bundle.js +4 -0
  319. package/src/lib/plugin-manager/plugin-site-bundle.js.map +1 -1
  320. package/src/lib/plugin-manager/plugin-site-export.d.ts +57 -1
  321. package/src/lib/plugin-manager/plugin-site-export.js +23 -10
  322. package/src/lib/plugin-manager/plugin-site-export.js.map +1 -1
  323. package/src/lib/plugin-manager/plugin-sitemap-readers.d.ts +146 -0
  324. package/src/lib/plugin-manager/plugin-sitemap-readers.js +110 -0
  325. package/src/lib/plugin-manager/plugin-sitemap-readers.js.map +1 -0
  326. package/src/lib/plugin-manager/plugin-transfer-resources.d.ts +714 -0
  327. package/src/lib/plugin-manager/plugin-transfer-resources.js +443 -0
  328. package/src/lib/plugin-manager/plugin-transfer-resources.js.map +1 -0
  329. package/src/lib/plugin-manager/plugin-usage-axes.d.ts +54 -5
  330. package/src/lib/plugin-manager/plugin-usage-axes.js +11 -3
  331. package/src/lib/plugin-manager/plugin-usage-axes.js.map +1 -1
  332. package/src/lib/plugin-manager/plugin-user-erasure.js +9 -1
  333. package/src/lib/plugin-manager/plugin-user-erasure.js.map +1 -1
  334. package/src/lib/plugin-manager/plugin-visitor-doors.d.ts +104 -0
  335. package/src/lib/plugin-manager/plugin-visitor-doors.js +108 -0
  336. package/src/lib/plugin-manager/plugin-visitor-doors.js.map +1 -0
  337. package/src/lib/plugin-manager/realm-host-aglyn.generated.js +2 -0
  338. package/src/lib/plugin-manager/realm-host-aglyn.generated.js.map +1 -1
  339. package/src/lib/plugin-manager/repeat-rows.d.ts +5 -6
  340. package/src/lib/plugin-manager/repeat-rows.js.map +1 -1
  341. package/src/lib/app-utils/actions.d.ts +0 -310
  342. package/src/lib/app-utils/actions.js +0 -506
  343. package/src/lib/app-utils/actions.js.map +0 -1
  344. package/src/lib/app-utils/automation-placeholders.d.ts +0 -72
  345. package/src/lib/app-utils/automation-placeholders.js +0 -207
  346. package/src/lib/app-utils/automation-placeholders.js.map +0 -1
  347. package/src/lib/app-utils/dataset-models.d.ts +0 -339
  348. package/src/lib/app-utils/dataset-models.js +0 -722
  349. package/src/lib/app-utils/dataset-models.js.map +0 -1
  350. package/src/lib/app-utils/datasets.d.ts +0 -171
  351. package/src/lib/app-utils/datasets.js +0 -227
  352. package/src/lib/app-utils/datasets.js.map +0 -1
  353. package/src/lib/app-utils/form-abuse-ceiling.d.ts +0 -146
  354. package/src/lib/app-utils/form-abuse-ceiling.js +0 -158
  355. package/src/lib/app-utils/form-abuse-ceiling.js.map +0 -1
  356. package/src/lib/plugin-manager/order-fulfilment.d.ts +0 -142
  357. package/src/lib/plugin-manager/order-fulfilment.js +0 -104
  358. package/src/lib/plugin-manager/order-fulfilment.js.map +0 -1
@@ -16,22 +16,39 @@
16
16
  */
17
17
  /**
18
18
  * A published page's node map as it crosses from the server into the
19
- * browser, without the two fields the map already states (AGL-3401).
19
+ * browser, stating each node's id once (AGL-3401, AGL-3438).
20
20
  *
21
- * The map rides in the page's flight payload, inside its HTML, and on
22
- * aglyn.com it was 242 KB of it. Every node repeats its own key as `$id` and
23
- * its parent's key as `parentId`, though the key IS the id and the parent's
24
- * `nodes` list already says whose child it is. Both are random ids, which is
25
- * the part of the map compression does least with: dropping them took the
26
- * map from 34.5 KB to about 28.5 KB gzipped on that page.
21
+ * The map rides in the page's flight payload, inside its HTML, and it is
22
+ * nearly all of that payload: 346 KB of aglyn.com/press's 376 KB. A stored
23
+ * map names every node three times — as its key, as its `$id`, and in its
24
+ * parent's `nodes` list — and once more as `parentId` in each child. The
25
+ * ids are random, which is the part of the map compression does least with,
26
+ * so every repeat costs close to its full length on the wire.
27
+ *
28
+ * Packed, the map is a TREE in document order: each node is an entry
29
+ * `[id, fields, ...children]`, and a child is either its own entry, inlined
30
+ * where its parent lists it, or its bare id when the node is inlined
31
+ * somewhere else or is not in the map at all. The id is stated once, by its
32
+ * entry; `$id`, `parentId` and `nodes` are left out of `fields` whenever the
33
+ * entry's position says the same thing. On aglyn.com/press that is 6.8 KB
34
+ * less HTML on the wire than the AGL-3401 packing, which only dropped
35
+ * `$id` and `parentId`.
27
36
  *
28
37
  * `packNodesForWire` drops a field only when `unpackWireNodes` will put back
29
- * the same value — an `$id` that differs from its key, or a `parentId` no
30
- * single parent's `nodes` list agrees with, is left in place — so a node that
31
- * carries both comes back exactly as it left, well-formed map or not. (One
32
- * that carried neither comes back with them.) Unpacking is idempotent, which is
33
- * what lets a full map (a withheld panel's patch from `/api/screen/nodes`, a
34
- * members-only tree) be merged over a packed one and unpacked together.
38
+ * the same value — an `$id` that differs from its key, a `parentId` other
39
+ * than the parent the node is inlined under, or a `nodes` value that is not
40
+ * a list of ids stays in `fields` — so every node comes back equal to the
41
+ * one that left, well-formed map or not. (One that carried no `$id`, or no
42
+ * `parentId` under a parent that lists it, comes back with them.) A child
43
+ * two parents list is inlined under the first and named by id in the other,
44
+ * a cycle is cut where it closes, and a node no list reaches is an entry of
45
+ * its own at the top level — so every key comes back, in document order.
46
+ *
47
+ * Unpacking also takes the flat form — a full map, or one packed by the
48
+ * AGL-3401 format — and fills in each `$id` and `parentId` it can from the
49
+ * keys and `nodes` lists, so it is idempotent. That is what lets a full patch
50
+ * (a withheld panel from `/api/screen/nodes`) be merged over an unpacked map
51
+ * and unpacked again.
35
52
  *
36
53
  * Banner-free and dependency-free: the tenant's server page packs and its
37
54
  * client root unpacks, so it must be importable from both.
@@ -45,9 +62,11 @@ type WireNode = Record<string, unknown> & {
45
62
  /** A node map, packed or not. */
46
63
  export type WireNodeMap<N = WireNode> = Record<string, N | null | undefined>;
47
64
  /**
48
- * The map without each `$id` that equals its key and each `parentId` its
49
- * parent's `nodes` list states. A new map of new node objects; the argument
50
- * is never mutated, because the server's is the cached loader's.
65
+ * The map as a tree of entries in document order: every node reachable from
66
+ * a node no list names, then any node that leaves out (a cycle, or a subtree
67
+ * whose only parent is unreachable), each as an entry of its own. A new
68
+ * structure throughout; the argument is never mutated, because the server's
69
+ * is the cached loader's.
51
70
  *
52
71
  * Typed as the map it is handed rather than as a looser one: the packed form
53
72
  * has one reader, `unpackWireNodes`, and the prop it travels in is read
@@ -55,10 +74,11 @@ export type WireNodeMap<N = WireNode> = Record<string, N | null | undefined>;
55
74
  */
56
75
  export declare function packNodesForWire<M extends WireNodeMap | null | undefined>(nodes: M): M;
57
76
  /**
58
- * The map with every node's `$id` and `parentId` back, from its key and its
77
+ * The map with every node whole: from a packed tree, each entry back under
78
+ * its id with its `$id`, its `parentId` and its `nodes` list restored; from a
79
+ * flat map, each node's `$id` and `parentId` filled in from its key and its
59
80
  * parent's `nodes` list. A node that already carries either keeps its own,
60
- * so an unpacked map comes back equal and a packed one merged with an
61
- * unpacked patch comes back whole.
81
+ * so a full map comes back equal.
62
82
  */
63
83
  export declare function unpackWireNodes<M extends WireNodeMap | null | undefined>(nodes: M): M;
64
84
  export {};
@@ -15,27 +15,51 @@
15
15
  * limitations under the License.
16
16
  */ /**
17
17
  * A published page's node map as it crosses from the server into the
18
- * browser, without the two fields the map already states (AGL-3401).
18
+ * browser, stating each node's id once (AGL-3401, AGL-3438).
19
19
  *
20
- * The map rides in the page's flight payload, inside its HTML, and on
21
- * aglyn.com it was 242 KB of it. Every node repeats its own key as `$id` and
22
- * its parent's key as `parentId`, though the key IS the id and the parent's
23
- * `nodes` list already says whose child it is. Both are random ids, which is
24
- * the part of the map compression does least with: dropping them took the
25
- * map from 34.5 KB to about 28.5 KB gzipped on that page.
20
+ * The map rides in the page's flight payload, inside its HTML, and it is
21
+ * nearly all of that payload: 346 KB of aglyn.com/press's 376 KB. A stored
22
+ * map names every node three times — as its key, as its `$id`, and in its
23
+ * parent's `nodes` list — and once more as `parentId` in each child. The
24
+ * ids are random, which is the part of the map compression does least with,
25
+ * so every repeat costs close to its full length on the wire.
26
+ *
27
+ * Packed, the map is a TREE in document order: each node is an entry
28
+ * `[id, fields, ...children]`, and a child is either its own entry, inlined
29
+ * where its parent lists it, or its bare id when the node is inlined
30
+ * somewhere else or is not in the map at all. The id is stated once, by its
31
+ * entry; `$id`, `parentId` and `nodes` are left out of `fields` whenever the
32
+ * entry's position says the same thing. On aglyn.com/press that is 6.8 KB
33
+ * less HTML on the wire than the AGL-3401 packing, which only dropped
34
+ * `$id` and `parentId`.
26
35
  *
27
36
  * `packNodesForWire` drops a field only when `unpackWireNodes` will put back
28
- * the same value — an `$id` that differs from its key, or a `parentId` no
29
- * single parent's `nodes` list agrees with, is left in place — so a node that
30
- * carries both comes back exactly as it left, well-formed map or not. (One
31
- * that carried neither comes back with them.) Unpacking is idempotent, which is
32
- * what lets a full map (a withheld panel's patch from `/api/screen/nodes`, a
33
- * members-only tree) be merged over a packed one and unpacked together.
37
+ * the same value — an `$id` that differs from its key, a `parentId` other
38
+ * than the parent the node is inlined under, or a `nodes` value that is not
39
+ * a list of ids stays in `fields` — so every node comes back equal to the
40
+ * one that left, well-formed map or not. (One that carried no `$id`, or no
41
+ * `parentId` under a parent that lists it, comes back with them.) A child
42
+ * two parents list is inlined under the first and named by id in the other,
43
+ * a cycle is cut where it closes, and a node no list reaches is an entry of
44
+ * its own at the top level — so every key comes back, in document order.
45
+ *
46
+ * Unpacking also takes the flat form — a full map, or one packed by the
47
+ * AGL-3401 format — and fills in each `$id` and `parentId` it can from the
48
+ * keys and `nodes` lists, so it is idempotent. That is what lets a full patch
49
+ * (a withheld panel from `/api/screen/nodes`) be merged over an unpacked map
50
+ * and unpacked again.
34
51
  *
35
52
  * Banner-free and dependency-free: the tenant's server page packs and its
36
53
  * client root unpacks, so it must be importable from both.
37
54
  */ /** A node as the map carries it: an object, keyed by its id. */ import { _ as _extends } from "@swc/helpers/_/_extends";
38
55
  import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
56
+ /**
57
+ * The one key a packed map has. `~` is outside the alphabet node ids are
58
+ * drawn from; a map that nevertheless has that key ships flat rather than
59
+ * risk being read back as a tree.
60
+ */ const WIRE_TREE_KEY = '~';
61
+ const isNode = (value)=>Boolean(value) && typeof value === 'object' && !Array.isArray(value);
62
+ /** A `nodes` value the tree can carry as its children: ids, and only ids. */ const childIds = (node)=>Array.isArray(node.nodes) && node.nodes.length > 0 && node.nodes.every((child)=>typeof child === 'string') ? node.nodes : undefined;
39
63
  /** Each child id to the key of the node whose `nodes` list names it. */ function parentsOf(nodes) {
40
64
  const parents = new Map();
41
65
  const claimed = new Set();
@@ -53,43 +77,84 @@ import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_wi
53
77
  }
54
78
  return parents;
55
79
  }
80
+ /** Whether `value` is a map packed by {@link packNodesForWire}. */ function isPackedTree(value) {
81
+ if (!value || typeof value !== 'object') return false;
82
+ const keys = Object.keys(value);
83
+ return keys.length === 1 && keys[0] === WIRE_TREE_KEY && Array.isArray(value[WIRE_TREE_KEY]);
84
+ }
56
85
  /**
57
- * The map without each `$id` that equals its key and each `parentId` its
58
- * parent's `nodes` list states. A new map of new node objects; the argument
59
- * is never mutated, because the server's is the cached loader's.
86
+ * The map as a tree of entries in document order: every node reachable from
87
+ * a node no list names, then any node that leaves out (a cycle, or a subtree
88
+ * whose only parent is unreachable), each as an entry of its own. A new
89
+ * structure throughout; the argument is never mutated, because the server's
90
+ * is the cached loader's.
60
91
  *
61
92
  * Typed as the map it is handed rather than as a looser one: the packed form
62
93
  * has one reader, `unpackWireNodes`, and the prop it travels in is read
63
94
  * nowhere else, so a second type would buy a cast at both ends.
64
95
  */ export function packNodesForWire(nodes) {
65
96
  if (!nodes) return nodes;
66
- const parents = parentsOf(nodes);
67
- const packed = {};
68
- for (const [key, node] of Object.entries(nodes)){
69
- if (!node || typeof node !== 'object') {
70
- packed[key] = node;
71
- continue;
72
- }
73
- const { $id, parentId } = node, rest = _object_without_properties_loose(node, [
97
+ if (Object.prototype.hasOwnProperty.call(nodes, WIRE_TREE_KEY)) return nodes;
98
+ const map = nodes;
99
+ const listed = new Set();
100
+ for (const node of Object.values(map)){
101
+ var _childIds;
102
+ if (!isNode(node)) continue;
103
+ for (const child of (_childIds = childIds(node)) != null ? _childIds : [])listed.add(child);
104
+ }
105
+ const entered = new Set();
106
+ const enter = (key, parent)=>{
107
+ entered.add(key);
108
+ const node = map[key];
109
+ if (!isNode(node)) return [
110
+ key,
111
+ node
112
+ ];
113
+ const { $id, parentId, nodes: list } = node, rest = _object_without_properties_loose(node, [
74
114
  "$id",
75
- "parentId"
115
+ "parentId",
116
+ "nodes"
76
117
  ]);
77
- const out = rest;
78
- if ($id !== key) out.$id = $id;
79
- if (parentId !== undefined && parentId !== parents.get(key)) {
80
- out.parentId = parentId;
118
+ const fields = rest;
119
+ if ('$id' in node && $id !== key) fields.$id = $id;
120
+ if ('parentId' in node && parentId !== parent) fields.parentId = parentId;
121
+ const children = childIds(node);
122
+ if (!children) {
123
+ if ('nodes' in node) fields.nodes = list;
124
+ return [
125
+ key,
126
+ fields
127
+ ];
128
+ }
129
+ const entry = [
130
+ key,
131
+ fields
132
+ ];
133
+ for (const child of children){
134
+ entry.push(Object.prototype.hasOwnProperty.call(map, child) && !entered.has(child) ? enter(child, key) : child);
81
135
  }
82
- packed[key] = out;
136
+ return entry;
137
+ };
138
+ const tree = [];
139
+ for (const key of Object.keys(map)){
140
+ if (!listed.has(key) && !entered.has(key)) tree.push(enter(key, undefined));
141
+ }
142
+ for (const key of Object.keys(map)){
143
+ if (!entered.has(key)) tree.push(enter(key, undefined));
83
144
  }
84
- return packed;
145
+ return {
146
+ [WIRE_TREE_KEY]: tree
147
+ };
85
148
  }
86
149
  /**
87
- * The map with every node's `$id` and `parentId` back, from its key and its
150
+ * The map with every node whole: from a packed tree, each entry back under
151
+ * its id with its `$id`, its `parentId` and its `nodes` list restored; from a
152
+ * flat map, each node's `$id` and `parentId` filled in from its key and its
88
153
  * parent's `nodes` list. A node that already carries either keeps its own,
89
- * so an unpacked map comes back equal and a packed one merged with an
90
- * unpacked patch comes back whole.
154
+ * so a full map comes back equal.
91
155
  */ export function unpackWireNodes(nodes) {
92
156
  if (!nodes) return nodes;
157
+ if (isPackedTree(nodes)) return unpackTree(nodes[WIRE_TREE_KEY]);
93
158
  const parents = parentsOf(nodes);
94
159
  const unpacked = {};
95
160
  for (const [key, node] of Object.entries(nodes)){
@@ -108,5 +173,26 @@ import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_wi
108
173
  }
109
174
  return unpacked;
110
175
  }
176
+ function unpackTree(tree) {
177
+ const out = {};
178
+ const visit = (entry, parent)=>{
179
+ const [key, fields, ...children] = entry;
180
+ if (!isNode(fields)) {
181
+ out[key] = fields;
182
+ return;
183
+ }
184
+ const node = _extends({
185
+ $id: key
186
+ }, fields);
187
+ if (children.length) {
188
+ node.nodes = children.map((child)=>typeof child === 'string' ? child : child[0]);
189
+ }
190
+ if (parent !== undefined && !('parentId' in fields)) node.parentId = parent;
191
+ out[key] = node;
192
+ for (const child of children)if (typeof child !== 'string') visit(child, key);
193
+ };
194
+ for (const entry of tree)visit(entry, undefined);
195
+ return out;
196
+ }
111
197
 
112
198
  //# sourceMappingURL=wire-nodes.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/wire-nodes.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 * A published page's node map as it crosses from the server into the\n * browser, without the two fields the map already states (AGL-3401).\n *\n * The map rides in the page's flight payload, inside its HTML, and on\n * aglyn.com it was 242 KB of it. Every node repeats its own key as `$id` and\n * its parent's key as `parentId`, though the key IS the id and the parent's\n * `nodes` list already says whose child it is. Both are random ids, which is\n * the part of the map compression does least with: dropping them took the\n * map from 34.5 KB to about 28.5 KB gzipped on that page.\n *\n * `packNodesForWire` drops a field only when `unpackWireNodes` will put back\n * the same value — an `$id` that differs from its key, or a `parentId` no\n * single parent's `nodes` list agrees with, is left in place — so a node that\n * carries both comes back exactly as it left, well-formed map or not. (One\n * that carried neither comes back with them.) Unpacking is idempotent, which is\n * what lets a full map (a withheld panel's patch from `/api/screen/nodes`, a\n * members-only tree) be merged over a packed one and unpacked together.\n *\n * Banner-free and dependency-free: the tenant's server page packs and its\n * client root unpacks, so it must be importable from both.\n */\n\n/** A node as the map carries it: an object, keyed by its id. */\ntype WireNode = Record<string, unknown> & {\n $id?: unknown\n parentId?: unknown\n nodes?: unknown\n}\n\n/** A node map, packed or not. */\nexport type WireNodeMap<N = WireNode> = Record<string, N | null | undefined>\n\n/** Each child id to the key of the node whose `nodes` list names it. */\nfunction parentsOf(nodes: WireNodeMap): Map<string, string> {\n const parents = new Map<string, string>()\n const claimed = new Set<string>()\n for (const [key, node] of Object.entries(nodes)) {\n const children = node?.nodes\n if (!Array.isArray(children)) continue\n for (const child of children) {\n if (typeof child !== 'string') continue\n // A child two parents list has no single answer, so neither may stand\n // in for the `parentId` it stores.\n if (claimed.has(child)) parents.delete(child)\n else parents.set(child, key)\n claimed.add(child)\n }\n }\n return parents\n}\n\n/**\n * The map without each `$id` that equals its key and each `parentId` its\n * parent's `nodes` list states. A new map of new node objects; the argument\n * is never mutated, because the server's is the cached loader's.\n *\n * Typed as the map it is handed rather than as a looser one: the packed form\n * has one reader, `unpackWireNodes`, and the prop it travels in is read\n * nowhere else, so a second type would buy a cast at both ends.\n */\nexport function packNodesForWire<M extends WireNodeMap | null | undefined>(\n nodes: M,\n): M {\n if (!nodes) return nodes\n const parents = parentsOf(nodes)\n const packed: WireNodeMap = {}\n for (const [key, node] of Object.entries(nodes)) {\n if (!node || typeof node !== 'object') {\n packed[key] = node\n continue\n }\n const { $id, parentId, ...rest } = node\n const out: WireNode = rest\n if ($id !== key) out.$id = $id\n if (parentId !== undefined && parentId !== parents.get(key)) {\n out.parentId = parentId\n }\n packed[key] = out\n }\n return packed as M\n}\n\n/**\n * The map with every node's `$id` and `parentId` back, from its key and its\n * parent's `nodes` list. A node that already carries either keeps its own,\n * so an unpacked map comes back equal and a packed one merged with an\n * unpacked patch comes back whole.\n */\nexport function unpackWireNodes<M extends WireNodeMap | null | undefined>(\n nodes: M,\n): M {\n if (!nodes) return nodes\n const parents = parentsOf(nodes)\n const unpacked: WireNodeMap = {}\n for (const [key, node] of Object.entries(nodes)) {\n if (!node || typeof node !== 'object') {\n unpacked[key] = node\n continue\n }\n const parent = parents.get(key)\n const needsId = !('$id' in node)\n const needsParent = !('parentId' in node) && parent !== undefined\n unpacked[key] =\n needsId || needsParent\n ? {\n ...(needsId ? { $id: key } : {}),\n ...node,\n ...(needsParent ? { parentId: parent } : {}),\n }\n : node\n }\n return unpacked as M\n}\n"],"names":["parentsOf","nodes","parents","Map","claimed","Set","key","node","Object","entries","children","Array","isArray","child","has","delete","set","add","packNodesForWire","packed","$id","parentId","rest","out","undefined","get","unpackWireNodes","unpacked","parent","needsId","needsParent"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;CAqBC,GAED,8DAA8D;;AAU9D,sEAAsE,GACtE,SAASA,UAAUC,KAAkB;IACnC,MAAMC,UAAU,IAAIC;IACpB,MAAMC,UAAU,IAAIC;IACpB,KAAK,MAAM,CAACC,KAAKC,KAAK,IAAIC,OAAOC,OAAO,CAACR,OAAQ;QAC/C,MAAMS,WAAWH,wBAAAA,KAAMN,KAAK;QAC5B,IAAI,CAACU,MAAMC,OAAO,CAACF,WAAW;QAC9B,KAAK,MAAMG,SAASH,SAAU;YAC5B,IAAI,OAAOG,UAAU,UAAU;YAC/B,sEAAsE;YACtE,mCAAmC;YACnC,IAAIT,QAAQU,GAAG,CAACD,QAAQX,QAAQa,MAAM,CAACF;iBAClCX,QAAQc,GAAG,CAACH,OAAOP;YACxBF,QAAQa,GAAG,CAACJ;QACd;IACF;IACA,OAAOX;AACT;AAEA;;;;;;;;CAQC,GACD,OAAO,SAASgB,iBACdjB,KAAQ;IAER,IAAI,CAACA,OAAO,OAAOA;IACnB,MAAMC,UAAUF,UAAUC;IAC1B,MAAMkB,SAAsB,CAAC;IAC7B,KAAK,MAAM,CAACb,KAAKC,KAAK,IAAIC,OAAOC,OAAO,CAACR,OAAQ;QAC/C,IAAI,CAACM,QAAQ,OAAOA,SAAS,UAAU;YACrCY,MAAM,CAACb,IAAI,GAAGC;YACd;QACF;QACA,MAAM,EAAEa,GAAG,EAAEC,QAAQ,EAAW,GAAGd,MAATe,wCAASf;;;;QACnC,MAAMgB,MAAgBD;QACtB,IAAIF,QAAQd,KAAKiB,IAAIH,GAAG,GAAGA;QAC3B,IAAIC,aAAaG,aAAaH,aAAanB,QAAQuB,GAAG,CAACnB,MAAM;YAC3DiB,IAAIF,QAAQ,GAAGA;QACjB;QACAF,MAAM,CAACb,IAAI,GAAGiB;IAChB;IACA,OAAOJ;AACT;AAEA;;;;;CAKC,GACD,OAAO,SAASO,gBACdzB,KAAQ;IAER,IAAI,CAACA,OAAO,OAAOA;IACnB,MAAMC,UAAUF,UAAUC;IAC1B,MAAM0B,WAAwB,CAAC;IAC/B,KAAK,MAAM,CAACrB,KAAKC,KAAK,IAAIC,OAAOC,OAAO,CAACR,OAAQ;QAC/C,IAAI,CAACM,QAAQ,OAAOA,SAAS,UAAU;YACrCoB,QAAQ,CAACrB,IAAI,GAAGC;YAChB;QACF;QACA,MAAMqB,SAAS1B,QAAQuB,GAAG,CAACnB;QAC3B,MAAMuB,UAAU,CAAE,CAAA,SAAStB,IAAG;QAC9B,MAAMuB,cAAc,CAAE,CAAA,cAAcvB,IAAG,KAAMqB,WAAWJ;QACxDG,QAAQ,CAACrB,IAAI,GACXuB,WAAWC,cACP,aACMD,UAAU;YAAET,KAAKd;QAAI,IAAI,CAAC,GAC3BC,MACCuB,cAAc;YAAET,UAAUO;QAAO,IAAI,CAAC,KAE5CrB;IACR;IACA,OAAOoB;AACT"}
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/wire-nodes.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 * A published page's node map as it crosses from the server into the\n * browser, stating each node's id once (AGL-3401, AGL-3438).\n *\n * The map rides in the page's flight payload, inside its HTML, and it is\n * nearly all of that payload: 346 KB of aglyn.com/press's 376 KB. A stored\n * map names every node three times — as its key, as its `$id`, and in its\n * parent's `nodes` list — and once more as `parentId` in each child. The\n * ids are random, which is the part of the map compression does least with,\n * so every repeat costs close to its full length on the wire.\n *\n * Packed, the map is a TREE in document order: each node is an entry\n * `[id, fields, ...children]`, and a child is either its own entry, inlined\n * where its parent lists it, or its bare id when the node is inlined\n * somewhere else or is not in the map at all. The id is stated once, by its\n * entry; `$id`, `parentId` and `nodes` are left out of `fields` whenever the\n * entry's position says the same thing. On aglyn.com/press that is 6.8 KB\n * less HTML on the wire than the AGL-3401 packing, which only dropped\n * `$id` and `parentId`.\n *\n * `packNodesForWire` drops a field only when `unpackWireNodes` will put back\n * the same value — an `$id` that differs from its key, a `parentId` other\n * than the parent the node is inlined under, or a `nodes` value that is not\n * a list of ids stays in `fields` — so every node comes back equal to the\n * one that left, well-formed map or not. (One that carried no `$id`, or no\n * `parentId` under a parent that lists it, comes back with them.) A child\n * two parents list is inlined under the first and named by id in the other,\n * a cycle is cut where it closes, and a node no list reaches is an entry of\n * its own at the top level — so every key comes back, in document order.\n *\n * Unpacking also takes the flat form — a full map, or one packed by the\n * AGL-3401 format — and fills in each `$id` and `parentId` it can from the\n * keys and `nodes` lists, so it is idempotent. That is what lets a full patch\n * (a withheld panel from `/api/screen/nodes`) be merged over an unpacked map\n * and unpacked again.\n *\n * Banner-free and dependency-free: the tenant's server page packs and its\n * client root unpacks, so it must be importable from both.\n */\n\n/** A node as the map carries it: an object, keyed by its id. */\ntype WireNode = Record<string, unknown> & {\n $id?: unknown\n parentId?: unknown\n nodes?: unknown\n}\n\n/** A node map, packed or not. */\nexport type WireNodeMap<N = WireNode> = Record<string, N | null | undefined>\n\n/**\n * One node of the packed tree: its id, the fields its position does not\n * already state, and its children — each an entry of its own, or the id of a\n * node that is entered elsewhere or nowhere.\n */\ntype WireEntry = [id: string, fields: unknown, ...children: WireChild[]]\ntype WireChild = WireEntry | string\n\n/**\n * The one key a packed map has. `~` is outside the alphabet node ids are\n * drawn from; a map that nevertheless has that key ships flat rather than\n * risk being read back as a tree.\n */\nconst WIRE_TREE_KEY = '~'\n\nconst isNode = (value: unknown): value is WireNode =>\n Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n\n/** A `nodes` value the tree can carry as its children: ids, and only ids. */\nconst childIds = (node: WireNode): string[] | undefined =>\n Array.isArray(node.nodes) &&\n node.nodes.length > 0 &&\n node.nodes.every((child) => typeof child === 'string')\n ? (node.nodes as string[])\n : undefined\n\n/** Each child id to the key of the node whose `nodes` list names it. */\nfunction parentsOf(nodes: WireNodeMap): Map<string, string> {\n const parents = new Map<string, string>()\n const claimed = new Set<string>()\n for (const [key, node] of Object.entries(nodes)) {\n const children = node?.nodes\n if (!Array.isArray(children)) continue\n for (const child of children) {\n if (typeof child !== 'string') continue\n // A child two parents list has no single answer, so neither may stand\n // in for the `parentId` it stores.\n if (claimed.has(child)) parents.delete(child)\n else parents.set(child, key)\n claimed.add(child)\n }\n }\n return parents\n}\n\n/** Whether `value` is a map packed by {@link packNodesForWire}. */\nfunction isPackedTree(\n value: unknown,\n): value is { [WIRE_TREE_KEY]: WireEntry[] } {\n if (!value || typeof value !== 'object') return false\n const keys = Object.keys(value)\n return (\n keys.length === 1 &&\n keys[0] === WIRE_TREE_KEY &&\n Array.isArray((value as Record<string, unknown>)[WIRE_TREE_KEY])\n )\n}\n\n/**\n * The map as a tree of entries in document order: every node reachable from\n * a node no list names, then any node that leaves out (a cycle, or a subtree\n * whose only parent is unreachable), each as an entry of its own. A new\n * structure throughout; the argument is never mutated, because the server's\n * is the cached loader's.\n *\n * Typed as the map it is handed rather than as a looser one: the packed form\n * has one reader, `unpackWireNodes`, and the prop it travels in is read\n * nowhere else, so a second type would buy a cast at both ends.\n */\nexport function packNodesForWire<M extends WireNodeMap | null | undefined>(\n nodes: M,\n): M {\n if (!nodes) return nodes\n if (Object.prototype.hasOwnProperty.call(nodes, WIRE_TREE_KEY)) return nodes\n const map = nodes as WireNodeMap\n const listed = new Set<string>()\n for (const node of Object.values(map)) {\n if (!isNode(node)) continue\n for (const child of childIds(node) ?? []) listed.add(child)\n }\n const entered = new Set<string>()\n const enter = (key: string, parent: string | undefined): WireEntry => {\n entered.add(key)\n const node = map[key]\n if (!isNode(node)) return [key, node]\n const { $id, parentId, nodes: list, ...rest } = node\n const fields: WireNode = rest\n if ('$id' in node && $id !== key) fields.$id = $id\n if ('parentId' in node && parentId !== parent) fields.parentId = parentId\n const children = childIds(node)\n if (!children) {\n if ('nodes' in node) fields.nodes = list\n return [key, fields]\n }\n const entry: WireEntry = [key, fields]\n for (const child of children) {\n entry.push(\n Object.prototype.hasOwnProperty.call(map, child) && !entered.has(child)\n ? enter(child, key)\n : child,\n )\n }\n return entry\n }\n const tree: WireEntry[] = []\n for (const key of Object.keys(map)) {\n if (!listed.has(key) && !entered.has(key)) tree.push(enter(key, undefined))\n }\n for (const key of Object.keys(map)) {\n if (!entered.has(key)) tree.push(enter(key, undefined))\n }\n return { [WIRE_TREE_KEY]: tree } as unknown as M\n}\n\n/**\n * The map with every node whole: from a packed tree, each entry back under\n * its id with its `$id`, its `parentId` and its `nodes` list restored; from a\n * flat map, each node's `$id` and `parentId` filled in from its key and its\n * parent's `nodes` list. A node that already carries either keeps its own,\n * so a full map comes back equal.\n */\nexport function unpackWireNodes<M extends WireNodeMap | null | undefined>(\n nodes: M,\n): M {\n if (!nodes) return nodes\n if (isPackedTree(nodes)) return unpackTree(nodes[WIRE_TREE_KEY]) as M\n const parents = parentsOf(nodes)\n const unpacked: WireNodeMap = {}\n for (const [key, node] of Object.entries(nodes)) {\n if (!node || typeof node !== 'object') {\n unpacked[key] = node\n continue\n }\n const parent = parents.get(key)\n const needsId = !('$id' in node)\n const needsParent = !('parentId' in node) && parent !== undefined\n unpacked[key] =\n needsId || needsParent\n ? {\n ...(needsId ? { $id: key } : {}),\n ...node,\n ...(needsParent ? { parentId: parent } : {}),\n }\n : node\n }\n return unpacked as M\n}\n\nfunction unpackTree(tree: readonly WireEntry[]): WireNodeMap {\n const out: WireNodeMap = {}\n const visit = (entry: WireEntry, parent: string | undefined): void => {\n const [key, fields, ...children] = entry\n if (!isNode(fields)) {\n out[key] = fields as WireNode | null | undefined\n return\n }\n const node: WireNode = { $id: key, ...fields }\n if (children.length) {\n node.nodes = children.map((child) =>\n typeof child === 'string' ? child : child[0],\n )\n }\n if (parent !== undefined && !('parentId' in fields)) node.parentId = parent\n out[key] = node\n for (const child of children) if (typeof child !== 'string') visit(child, key)\n }\n for (const entry of tree) visit(entry, undefined)\n return out\n}\n"],"names":["WIRE_TREE_KEY","isNode","value","Boolean","Array","isArray","childIds","node","nodes","length","every","child","undefined","parentsOf","parents","Map","claimed","Set","key","Object","entries","children","has","delete","set","add","isPackedTree","keys","packNodesForWire","prototype","hasOwnProperty","call","map","listed","values","entered","enter","parent","$id","parentId","list","rest","fields","entry","push","tree","unpackWireNodes","unpackTree","unpacked","get","needsId","needsParent","out","visit"],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import type { TransferImportRole, TransferResourceDescriptor } from './resource';
18
+ import { type TransferApiRoute, type TransferPlanRequiredResponse } from './transfer-api';
19
+ /** What a resource declares about who may read and import its records. */
20
+ export type TransferReadDeclaration = Pick<TransferResourceDescriptor, 'readPermission' | 'readableByMembers' | 'importRoles'>;
21
+ /** What a resource declares about the plan that moves its records. */
22
+ export type TransferPlanDeclaration = Pick<TransferResourceDescriptor, 'featureFlag' | 'featureFlagExempt'>;
23
+ /** What a member is doing with a resource's records. */
24
+ export type TransferAccessIntent = 'import' | 'export';
25
+ /** The permission every import asks for. */
26
+ export declare const TRANSFER_MANAGE_PERMISSION = "data.manage";
27
+ /** The routes that only read records, and so ask for export access. */
28
+ export declare const TRANSFER_EXPORT_ROUTES: readonly TransferApiRoute[];
29
+ /** The intent a transfer route asks with. */
30
+ export declare function transferRouteIntent(route: TransferApiRoute): TransferAccessIntent;
31
+ /**
32
+ * The permissions any ONE of which admits a member to `intent` on a
33
+ * resource. Empty means membership is enough (and, for a collaborator,
34
+ * reaching the named site).
35
+ */
36
+ export declare function transferAccessPermissions(intent: TransferAccessIntent, descriptor: TransferReadDeclaration | null | undefined): readonly string[];
37
+ /** How one member's permissions resolve where the records are. */
38
+ export interface TransferMemberAxis {
39
+ /** Whether the member holds `permission` on the named site, or on the workspace when none is named. */
40
+ holds(permission: string): boolean;
41
+ /** Whether the member reaches the named site; `true` when none is named or the member is org-wide. */
42
+ reachesSite: boolean;
43
+ /**
44
+ * The member's role where the records are — on the named site
45
+ * (`hostRoleFor`), or on the workspace (`transferWorkspaceRole`) — for a
46
+ * resource that names `importRoles`; `null` for none.
47
+ */
48
+ role?: TransferImportRole | null;
49
+ }
50
+ /** Whether a member may `intent` a resource's records: see the block above. */
51
+ export declare function transferAccessAllowed(intent: TransferAccessIntent, descriptor: TransferReadDeclaration | null | undefined, axis: TransferMemberAxis): boolean;
52
+ /**
53
+ * Whether a member in `role` may `intent` the records, as far as the
54
+ * resource's `importRoles` say: always for an export, or a resource that
55
+ * names none (AGL-3554).
56
+ */
57
+ export declare function transferImportRoleAllowed(intent: TransferAccessIntent, descriptor: Pick<TransferResourceDescriptor, 'importRoles'> | null | undefined, role: TransferImportRole | null): boolean;
58
+ /**
59
+ * A workspace role as the site role it is on every site, for a workspace's
60
+ * records: an owner or an admin is every site's admin (`hostRoleFor`), and
61
+ * any other role is itself.
62
+ */
63
+ export declare function transferWorkspaceRole(role: string | null | undefined): TransferImportRole | null;
64
+ /** The sentence refusing a member whose role is not among the resource's `importRoles`. */
65
+ export declare function transferImportRoleRefusal(descriptor: Pick<TransferResourceDescriptor, 'importRoles' | 'label' | 'scope'>): string;
66
+ /**
67
+ * The plan feature a workspace needs to `intent` a resource's records, or
68
+ * `null` when every plan may — no `featureFlag`, or an intent the resource
69
+ * exempts. The entitlement itself is the caller's to resolve
70
+ * (`checkEntitlement`), from the workspace document it already holds.
71
+ */
72
+ export declare function transferPlanFeature(intent: TransferAccessIntent, descriptor: TransferPlanDeclaration | null | undefined): string | null;
73
+ /** Whether a refusal's body is one for the workspace's plan. */
74
+ export declare function isTransferPlanRequired(body: unknown): body is TransferPlanRequiredResponse;
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { TRANSFER_PLAN_REQUIRED } from "./transfer-api.js";
17
+ /** The permission every import asks for. */ export const TRANSFER_MANAGE_PERMISSION = 'data.manage';
18
+ /** The routes that only read records, and so ask for export access. */ export const TRANSFER_EXPORT_ROUTES = [
19
+ 'fields',
20
+ 'export'
21
+ ];
22
+ /** The intent a transfer route asks with. */ export function transferRouteIntent(route) {
23
+ return TRANSFER_EXPORT_ROUTES.includes(route) ? 'export' : 'import';
24
+ }
25
+ /**
26
+ * The permissions any ONE of which admits a member to `intent` on a
27
+ * resource. Empty means membership is enough (and, for a collaborator,
28
+ * reaching the named site).
29
+ */ export function transferAccessPermissions(intent, descriptor) {
30
+ var _descriptor_readPermission;
31
+ if (intent === 'import') return [
32
+ TRANSFER_MANAGE_PERMISSION
33
+ ];
34
+ if ((descriptor == null ? void 0 : descriptor.readableByMembers) === true) return [];
35
+ const read = descriptor == null ? void 0 : (_descriptor_readPermission = descriptor.readPermission) == null ? void 0 : _descriptor_readPermission.trim();
36
+ // Whoever may write the records may read them.
37
+ return read && read !== TRANSFER_MANAGE_PERMISSION ? [
38
+ read,
39
+ TRANSFER_MANAGE_PERMISSION
40
+ ] : [
41
+ TRANSFER_MANAGE_PERMISSION
42
+ ];
43
+ }
44
+ /** Whether a member may `intent` a resource's records: see the block above. */ export function transferAccessAllowed(intent, descriptor, axis) {
45
+ var _axis_role;
46
+ if (!axis.reachesSite) return false;
47
+ if (!transferImportRoleAllowed(intent, descriptor, (_axis_role = axis.role) != null ? _axis_role : null)) return false;
48
+ const needed = transferAccessPermissions(intent, descriptor);
49
+ return !needed.length || needed.some((permission)=>axis.holds(permission));
50
+ }
51
+ /**
52
+ * Whether a member in `role` may `intent` the records, as far as the
53
+ * resource's `importRoles` say: always for an export, or a resource that
54
+ * names none (AGL-3554).
55
+ */ export function transferImportRoleAllowed(intent, descriptor, role) {
56
+ const roles = descriptor == null ? void 0 : descriptor.importRoles;
57
+ if (intent !== 'import' || !(roles == null ? void 0 : roles.length)) return true;
58
+ return role !== null && roles.includes(role);
59
+ }
60
+ /**
61
+ * A workspace role as the site role it is on every site, for a workspace's
62
+ * records: an owner or an admin is every site's admin (`hostRoleFor`), and
63
+ * any other role is itself.
64
+ */ export function transferWorkspaceRole(role) {
65
+ if (role === 'owner' || role === 'admin') return 'admin';
66
+ return role === 'editor' || role === 'author' || role === 'viewer' ? role : null;
67
+ }
68
+ /** The sentence refusing a member whose role is not among the resource's `importRoles`. */ export function transferImportRoleRefusal(descriptor) {
69
+ var _descriptor_importRoles;
70
+ const roles = (_descriptor_importRoles = descriptor.importRoles) != null ? _descriptor_importRoles : [];
71
+ const what = /^[A-Z][a-z]/.test(descriptor.label) ? descriptor.label.charAt(0).toLowerCase() + descriptor.label.slice(1) : descriptor.label;
72
+ if (roles.length === 1 && roles[0] === 'admin') {
73
+ return descriptor.scope === 'host' ? `Only the workspace’s owners and admins, and the site’s admins, can import ${what}.` : `Only the workspace’s owners and admins can import ${what}.`;
74
+ }
75
+ const named = roles.map((role)=>role.charAt(0).toUpperCase() + role.slice(1)).join(', ');
76
+ return `Importing ${what} needs one of these roles${descriptor.scope === 'host' ? ' on the site' : ''}: ${named}.`;
77
+ }
78
+ /**
79
+ * The plan feature a workspace needs to `intent` a resource's records, or
80
+ * `null` when every plan may — no `featureFlag`, or an intent the resource
81
+ * exempts. The entitlement itself is the caller's to resolve
82
+ * (`checkEntitlement`), from the workspace document it already holds.
83
+ */ export function transferPlanFeature(intent, descriptor) {
84
+ var _descriptor_featureFlag, _descriptor_featureFlagExempt;
85
+ const feature = descriptor == null ? void 0 : (_descriptor_featureFlag = descriptor.featureFlag) == null ? void 0 : _descriptor_featureFlag.trim();
86
+ if (!feature) return null;
87
+ return (descriptor == null ? void 0 : (_descriptor_featureFlagExempt = descriptor.featureFlagExempt) == null ? void 0 : _descriptor_featureFlagExempt.includes(intent)) ? null : feature;
88
+ }
89
+ /** Whether a refusal's body is one for the workspace's plan. */ export function isTransferPlanRequired(body) {
90
+ return Boolean(body && typeof body === 'object' && body.reason === TRANSFER_PLAN_REQUIRED);
91
+ }
92
+
93
+ //# sourceMappingURL=access.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/data-transfer/access.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 { TransferImportRole, TransferResourceDescriptor } from './resource'\nimport { TRANSFER_PLAN_REQUIRED, type TransferApiRoute, type TransferPlanRequiredResponse } from './transfer-api'\n\n/*==========================================\n * WHO MAY MOVE A RESOURCE'S RECORDS (AGL-3546)\n *\n * Two intents, answered the same way by the transfer routes' gate and by the\n * console's display of Import and Export, so a button is never offered that\n * the route refuses:\n *\n * - IMPORT (upload, analyze, plan, apply, status, undo — and the job list\n * and packages, which the gate asks with the same intent) writes records, and\n * needs `data.manage` — on the named site, or on the workspace. A\n * resource stricter than that names its `importRoles` (AGL-3554): the\n * member's role where the records are must also be one of them (gift\n * cards: a site's admins, which a workspace's owners and admins are).\n * - EXPORT (export, and `fields`, which the export dialog opens with) only\n * reads them, and asks what the resource declares: `readableByMembers`\n * admits any member (a collaborator who reaches the named site), the\n * way datasets are read; a `readPermission` admits whoever holds it; and\n * a resource that declares neither keeps `data.manage`, because its\n * records may be ones the rules let only managers read (CRM contacts).\n * `data.manage` always admits. Which records a reader then sees is the\n * resource's own business: `readPage` and `count` honor the reader's\n * `scopeTokens`, as every other door onto the records does.\n *\n * And one question of the WORKSPACE, asked after the member's (AGL-3555):\n * a resource that declares a `featureFlag` is moved only by a workspace\n * whose plan carries that feature, for every intent but the ones it lists\n * in `featureFlagExempt`. {@link transferPlanFeature} names the feature an\n * intent needs; the gate refuses without it (403 `plan_required`, the\n * feature as `code`), staff included, and the console's `can` answers\n * `false`, so neither button is offered on a plan the route refuses.\n *==========================================*/\n\n/** What a resource declares about who may read and import its records. */\nexport type TransferReadDeclaration = Pick<TransferResourceDescriptor, 'readPermission' | 'readableByMembers' | 'importRoles'>\n\n/** What a resource declares about the plan that moves its records. */\nexport type TransferPlanDeclaration = Pick<TransferResourceDescriptor, 'featureFlag' | 'featureFlagExempt'>\n\n/** What a member is doing with a resource's records. */\nexport type TransferAccessIntent = 'import' | 'export'\n\n/** The permission every import asks for. */\nexport const TRANSFER_MANAGE_PERMISSION = 'data.manage'\n\n/** The routes that only read records, and so ask for export access. */\nexport const TRANSFER_EXPORT_ROUTES: readonly TransferApiRoute[] = ['fields', 'export']\n\n/** The intent a transfer route asks with. */\nexport function transferRouteIntent(route: TransferApiRoute): TransferAccessIntent {\n return TRANSFER_EXPORT_ROUTES.includes(route) ? 'export' : 'import'\n}\n\n/**\n * The permissions any ONE of which admits a member to `intent` on a\n * resource. Empty means membership is enough (and, for a collaborator,\n * reaching the named site).\n */\nexport function transferAccessPermissions(\n intent: TransferAccessIntent,\n descriptor: TransferReadDeclaration | null | undefined,\n): readonly string[] {\n if (intent === 'import') return [TRANSFER_MANAGE_PERMISSION]\n if (descriptor?.readableByMembers === true) return []\n const read = descriptor?.readPermission?.trim()\n // Whoever may write the records may read them.\n return read && read !== TRANSFER_MANAGE_PERMISSION ? [read, TRANSFER_MANAGE_PERMISSION] : [TRANSFER_MANAGE_PERMISSION]\n}\n\n/** How one member's permissions resolve where the records are. */\nexport interface TransferMemberAxis {\n /** Whether the member holds `permission` on the named site, or on the workspace when none is named. */\n holds(permission: string): boolean\n /** Whether the member reaches the named site; `true` when none is named or the member is org-wide. */\n reachesSite: boolean\n /**\n * The member's role where the records are — on the named site\n * (`hostRoleFor`), or on the workspace (`transferWorkspaceRole`) — for a\n * resource that names `importRoles`; `null` for none.\n */\n role?: TransferImportRole | null\n}\n\n/** Whether a member may `intent` a resource's records: see the block above. */\nexport function transferAccessAllowed(\n intent: TransferAccessIntent,\n descriptor: TransferReadDeclaration | null | undefined,\n axis: TransferMemberAxis,\n): boolean {\n if (!axis.reachesSite) return false\n if (!transferImportRoleAllowed(intent, descriptor, axis.role ?? null)) return false\n const needed = transferAccessPermissions(intent, descriptor)\n return !needed.length || needed.some((permission) => axis.holds(permission))\n}\n\n/**\n * Whether a member in `role` may `intent` the records, as far as the\n * resource's `importRoles` say: always for an export, or a resource that\n * names none (AGL-3554).\n */\nexport function transferImportRoleAllowed(\n intent: TransferAccessIntent,\n descriptor: Pick<TransferResourceDescriptor, 'importRoles'> | null | undefined,\n role: TransferImportRole | null,\n): boolean {\n const roles = descriptor?.importRoles\n if (intent !== 'import' || !roles?.length) return true\n return role !== null && roles.includes(role)\n}\n\n/**\n * A workspace role as the site role it is on every site, for a workspace's\n * records: an owner or an admin is every site's admin (`hostRoleFor`), and\n * any other role is itself.\n */\nexport function transferWorkspaceRole(role: string | null | undefined): TransferImportRole | null {\n if (role === 'owner' || role === 'admin') return 'admin'\n return role === 'editor' || role === 'author' || role === 'viewer' ? role : null\n}\n\n/** The sentence refusing a member whose role is not among the resource's `importRoles`. */\nexport function transferImportRoleRefusal(\n descriptor: Pick<TransferResourceDescriptor, 'importRoles' | 'label' | 'scope'>,\n): string {\n const roles = descriptor.importRoles ?? []\n const what = /^[A-Z][a-z]/.test(descriptor.label)\n ? descriptor.label.charAt(0).toLowerCase() + descriptor.label.slice(1)\n : descriptor.label\n if (roles.length === 1 && roles[0] === 'admin') {\n return descriptor.scope === 'host'\n ? `Only the workspace’s owners and admins, and the site’s admins, can import ${what}.`\n : `Only the workspace’s owners and admins can import ${what}.`\n }\n const named = roles.map((role) => role.charAt(0).toUpperCase() + role.slice(1)).join(', ')\n return `Importing ${what} needs one of these roles${descriptor.scope === 'host' ? ' on the site' : ''}: ${named}.`\n}\n\n/**\n * The plan feature a workspace needs to `intent` a resource's records, or\n * `null` when every plan may — no `featureFlag`, or an intent the resource\n * exempts. The entitlement itself is the caller's to resolve\n * (`checkEntitlement`), from the workspace document it already holds.\n */\nexport function transferPlanFeature(\n intent: TransferAccessIntent,\n descriptor: TransferPlanDeclaration | null | undefined,\n): string | null {\n const feature = descriptor?.featureFlag?.trim()\n if (!feature) return null\n return descriptor?.featureFlagExempt?.includes(intent) ? null : feature\n}\n\n/** Whether a refusal's body is one for the workspace's plan. */\nexport function isTransferPlanRequired(body: unknown): body is TransferPlanRequiredResponse {\n return Boolean(body && typeof body === 'object' && (body as { reason?: unknown }).reason === TRANSFER_PLAN_REQUIRED)\n}\n"],"names":["TRANSFER_PLAN_REQUIRED","TRANSFER_MANAGE_PERMISSION","TRANSFER_EXPORT_ROUTES","transferRouteIntent","route","includes","transferAccessPermissions","intent","descriptor","readableByMembers","read","readPermission","trim","transferAccessAllowed","axis","reachesSite","transferImportRoleAllowed","role","needed","length","some","permission","holds","roles","importRoles","transferWorkspaceRole","transferImportRoleRefusal","what","test","label","charAt","toLowerCase","slice","scope","named","map","toUpperCase","join","transferPlanFeature","feature","featureFlag","featureFlagExempt","isTransferPlanRequired","body","Boolean","reason"],"mappings":"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"}