@aglyn/aglyn 1.0.0-beta.221 → 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.
- package/package.json +15 -11
- package/src/lib/app-utils/agent-openapi.js +1 -1
- package/src/lib/app-utils/agent-openapi.js.map +1 -1
- package/src/lib/app-utils/analytics-events.d.ts +3 -2
- package/src/lib/app-utils/analytics-events.js +3 -2
- package/src/lib/app-utils/analytics-events.js.map +1 -1
- package/src/lib/app-utils/api-plugins.d.ts +30 -0
- package/src/lib/app-utils/api-plugins.js +24 -1
- package/src/lib/app-utils/api-plugins.js.map +1 -1
- package/src/lib/app-utils/author-html.d.ts +1 -1
- package/src/lib/app-utils/author-html.js.map +1 -1
- package/src/lib/app-utils/bandwidth-cap.d.ts +12 -1
- package/src/lib/app-utils/bandwidth-cap.js +17 -1
- package/src/lib/app-utils/bandwidth-cap.js.map +1 -1
- package/src/lib/app-utils/compose-reusable-components.d.ts +19 -0
- package/src/lib/app-utils/compose-reusable-components.js +116 -26
- package/src/lib/app-utils/compose-reusable-components.js.map +1 -1
- package/src/lib/app-utils/console-routes.d.ts +4 -0
- package/src/lib/app-utils/console-routes.js +3 -0
- package/src/lib/app-utils/console-routes.js.map +1 -1
- package/src/lib/app-utils/contacts.d.ts +71 -0
- package/src/lib/app-utils/contacts.js +55 -0
- package/src/lib/app-utils/contacts.js.map +1 -1
- package/src/lib/app-utils/contexts.d.ts +1 -0
- package/src/lib/app-utils/contexts.js +1 -0
- package/src/lib/app-utils/contexts.js.map +1 -1
- package/src/lib/app-utils/crm-email-templates.js +21 -4
- package/src/lib/app-utils/crm-email-templates.js.map +1 -1
- package/src/lib/app-utils/crm-kinds.d.ts +2 -0
- package/src/lib/app-utils/crm-kinds.js +1 -0
- package/src/lib/app-utils/crm-kinds.js.map +1 -1
- package/src/lib/app-utils/crm.d.ts +1199 -67
- package/src/lib/app-utils/crm.js +1951 -310
- package/src/lib/app-utils/crm.js.map +1 -1
- package/src/lib/app-utils/csv-import.d.ts +10 -38
- package/src/lib/app-utils/csv-import.js +17 -42
- package/src/lib/app-utils/csv-import.js.map +1 -1
- package/src/lib/app-utils/csv.d.ts +32 -11
- package/src/lib/app-utils/csv.js +43 -5
- package/src/lib/app-utils/csv.js.map +1 -1
- package/src/lib/app-utils/default-site.d.ts +116 -0
- package/src/lib/app-utils/default-site.js +1024 -0
- package/src/lib/app-utils/default-site.js.map +1 -0
- package/src/lib/app-utils/docs-help.generated.d.ts +22 -22
- package/src/lib/app-utils/docs-help.generated.js +44 -10
- package/src/lib/app-utils/docs-help.generated.js.map +1 -1
- package/src/lib/app-utils/docs-index.generated.js +738 -150
- package/src/lib/app-utils/docs-index.generated.js.map +1 -1
- package/src/lib/app-utils/draft-placeholders.d.ts +76 -0
- package/src/lib/app-utils/draft-placeholders.js +115 -0
- package/src/lib/app-utils/draft-placeholders.js.map +1 -0
- package/src/lib/app-utils/entity-picker-context.d.ts +19 -15
- package/src/lib/app-utils/entity-picker-context.js +4 -4
- package/src/lib/app-utils/entity-picker-context.js.map +1 -1
- package/src/lib/app-utils/expand-repeatables.d.ts +66 -10
- package/src/lib/app-utils/expand-repeatables.js +88 -14
- package/src/lib/app-utils/expand-repeatables.js.map +1 -1
- package/src/lib/app-utils/forms.d.ts +33 -22
- package/src/lib/app-utils/forms.js +47 -28
- package/src/lib/app-utils/forms.js.map +1 -1
- package/src/lib/app-utils/full-use-cost.d.ts +277 -0
- package/src/lib/app-utils/full-use-cost.js +421 -0
- package/src/lib/app-utils/full-use-cost.js.map +1 -0
- package/src/lib/app-utils/health-report.js +11 -0
- package/src/lib/app-utils/health-report.js.map +1 -1
- package/src/lib/app-utils/llms-txt.d.ts +20 -0
- package/src/lib/app-utils/llms-txt.js +7 -1
- package/src/lib/app-utils/llms-txt.js.map +1 -1
- package/src/lib/app-utils/media-asset-facts.d.ts +16 -1
- package/src/lib/app-utils/media-asset-facts.js +40 -13
- package/src/lib/app-utils/media-asset-facts.js.map +1 -1
- package/src/lib/app-utils/media-bandwidth.d.ts +52 -0
- package/src/lib/app-utils/media-bandwidth.js +94 -0
- package/src/lib/app-utils/media-bandwidth.js.map +1 -0
- package/src/lib/app-utils/media-ref.d.ts +241 -33
- package/src/lib/app-utils/media-ref.js +324 -43
- package/src/lib/app-utils/media-ref.js.map +1 -1
- package/src/lib/app-utils/media-src.d.ts +8 -8
- package/src/lib/app-utils/media-src.js +27 -11
- package/src/lib/app-utils/media-src.js.map +1 -1
- package/src/lib/app-utils/media-takedown-reach.d.ts +4 -1
- package/src/lib/app-utils/media-takedown-reach.js +6 -3
- package/src/lib/app-utils/media-takedown-reach.js.map +1 -1
- package/src/lib/app-utils/notifications.d.ts +1 -1
- package/src/lib/app-utils/notifications.js +2 -0
- package/src/lib/app-utils/notifications.js.map +1 -1
- package/src/lib/app-utils/organizations.d.ts +51 -2
- package/src/lib/app-utils/organizations.js +56 -3
- package/src/lib/app-utils/organizations.js.map +1 -1
- package/src/lib/app-utils/page-record-sources.d.ts +87 -0
- package/src/lib/app-utils/page-record-sources.js +53 -0
- package/src/lib/app-utils/page-record-sources.js.map +1 -0
- package/src/lib/app-utils/paid-media-source.d.ts +3 -7
- package/src/lib/app-utils/paid-media-source.js +5 -19
- package/src/lib/app-utils/paid-media-source.js.map +1 -1
- package/src/lib/app-utils/person-erasure.d.ts +5 -2
- package/src/lib/app-utils/person-erasure.js.map +1 -1
- package/src/lib/app-utils/picklists.d.ts +187 -0
- package/src/lib/app-utils/picklists.js +320 -0
- package/src/lib/app-utils/picklists.js.map +1 -0
- package/src/lib/app-utils/plan-entitlements.d.ts +220 -50
- package/src/lib/app-utils/plan-entitlements.js +309 -115
- package/src/lib/app-utils/plan-entitlements.js.map +1 -1
- package/src/lib/app-utils/realm-host-surface.generated.js +2 -0
- package/src/lib/app-utils/realm-host-surface.generated.js.map +1 -1
- package/src/lib/app-utils/release-flags.d.ts +1 -1
- package/src/lib/app-utils/release-flags.js +11 -0
- package/src/lib/app-utils/release-flags.js.map +1 -1
- package/src/lib/app-utils/rendered-widths.d.ts +121 -0
- package/src/lib/app-utils/rendered-widths.js +211 -0
- package/src/lib/app-utils/rendered-widths.js.map +1 -0
- package/src/lib/app-utils/repeat-sources.d.ts +2 -1
- package/src/lib/app-utils/repeat-sources.js.map +1 -1
- package/src/lib/app-utils/screen-route.d.ts +154 -36
- package/src/lib/app-utils/screen-route.js +185 -40
- package/src/lib/app-utils/screen-route.js.map +1 -1
- package/src/lib/app-utils/seo-audit.d.ts +11 -1
- package/src/lib/app-utils/seo-audit.js +33 -13
- package/src/lib/app-utils/seo-audit.js.map +1 -1
- package/src/lib/app-utils/seo-keywords.d.ts +11 -0
- package/src/lib/app-utils/seo-keywords.js +19 -5
- package/src/lib/app-utils/seo-keywords.js.map +1 -1
- package/src/lib/app-utils/seo-page-facts.d.ts +47 -4
- package/src/lib/app-utils/seo-page-facts.js +136 -31
- package/src/lib/app-utils/seo-page-facts.js.map +1 -1
- package/src/lib/app-utils/seo-site-scan.d.ts +42 -4
- package/src/lib/app-utils/seo-site-scan.js +113 -12
- package/src/lib/app-utils/seo-site-scan.js.map +1 -1
- package/src/lib/app-utils/server.d.ts +5 -4
- package/src/lib/app-utils/server.js +14 -5
- package/src/lib/app-utils/server.js.map +1 -1
- package/src/lib/app-utils/site-icon-set.d.ts +195 -0
- package/src/lib/app-utils/site-icon-set.js +351 -0
- package/src/lib/app-utils/site-icon-set.js.map +1 -0
- package/src/lib/app-utils/site-interactions.d.ts +101 -4
- package/src/lib/app-utils/site-interactions.js +120 -4
- package/src/lib/app-utils/site-interactions.js.map +1 -1
- package/src/lib/app-utils/starter-template-nodes.d.ts +7 -0
- package/src/lib/app-utils/starter-template-nodes.js +3 -0
- package/src/lib/app-utils/starter-template-nodes.js.map +1 -1
- package/src/lib/app-utils/starter-templates.d.ts +5 -19
- package/src/lib/app-utils/starter-templates.js +5 -49
- package/src/lib/app-utils/starter-templates.js.map +1 -1
- package/src/lib/app-utils/transfer-launcher-context.d.ts +136 -0
- package/src/lib/app-utils/transfer-launcher-context.js +23 -0
- package/src/lib/app-utils/transfer-launcher-context.js.map +1 -0
- package/src/lib/app-utils/transfer-resume-import.d.ts +39 -0
- package/src/lib/app-utils/transfer-resume-import.js +128 -0
- package/src/lib/app-utils/transfer-resume-import.js.map +1 -0
- package/src/lib/app-utils/upgrade-proposal.d.ts +66 -0
- package/src/lib/app-utils/upgrade-proposal.js +95 -0
- package/src/lib/app-utils/upgrade-proposal.js.map +1 -0
- package/src/lib/app-utils/utc-month.d.ts +33 -0
- package/src/lib/app-utils/utc-month.js +35 -0
- package/src/lib/app-utils/utc-month.js.map +1 -0
- package/src/lib/app-utils/visitor-record-ceiling.d.ts +4 -4
- package/src/lib/app-utils/visitor-record-ceiling.js +4 -4
- package/src/lib/app-utils/visitor-record-ceiling.js.map +1 -1
- package/src/lib/app-utils/wire-nodes.d.ts +39 -19
- package/src/lib/app-utils/wire-nodes.js +120 -34
- package/src/lib/app-utils/wire-nodes.js.map +1 -1
- package/src/lib/data-transfer/access.d.ts +74 -0
- package/src/lib/data-transfer/access.js +93 -0
- package/src/lib/data-transfer/access.js.map +1 -0
- package/src/lib/data-transfer/derive.d.ts +246 -0
- package/src/lib/data-transfer/derive.js +1007 -0
- package/src/lib/data-transfer/derive.js.map +1 -0
- package/src/lib/data-transfer/export-file.d.ts +46 -0
- package/src/lib/data-transfer/export-file.js +146 -0
- package/src/lib/data-transfer/export-file.js.map +1 -0
- package/src/lib/data-transfer/field-catalog.d.ts +134 -0
- package/src/lib/data-transfer/field-catalog.js +278 -0
- package/src/lib/data-transfer/field-catalog.js.map +1 -0
- package/src/lib/data-transfer/header-match.d.ts +129 -0
- package/src/lib/data-transfer/header-match.js +367 -0
- package/src/lib/data-transfer/header-match.js.map +1 -0
- package/src/lib/data-transfer/index.d.ts +34 -0
- package/src/lib/data-transfer/index.js +40 -0
- package/src/lib/data-transfer/index.js.map +1 -0
- package/src/lib/data-transfer/job.d.ts +190 -0
- package/src/lib/data-transfer/job.js +229 -0
- package/src/lib/data-transfer/job.js.map +1 -0
- package/src/lib/data-transfer/lookup.d.ts +45 -0
- package/src/lib/data-transfer/lookup.js +71 -0
- package/src/lib/data-transfer/lookup.js.map +1 -0
- package/src/lib/data-transfer/match.d.ts +99 -0
- package/src/lib/data-transfer/match.js +244 -0
- package/src/lib/data-transfer/match.js.map +1 -0
- package/src/lib/data-transfer/package-plan.d.ts +205 -0
- package/src/lib/data-transfer/package-plan.js +475 -0
- package/src/lib/data-transfer/package-plan.js.map +1 -0
- package/src/lib/data-transfer/package.d.ts +181 -0
- package/src/lib/data-transfer/package.js +426 -0
- package/src/lib/data-transfer/package.js.map +1 -0
- package/src/lib/data-transfer/picklist-map.d.ts +139 -0
- package/src/lib/data-transfer/picklist-map.js +271 -0
- package/src/lib/data-transfer/picklist-map.js.map +1 -0
- package/src/lib/data-transfer/plan.d.ts +176 -0
- package/src/lib/data-transfer/plan.js +451 -0
- package/src/lib/data-transfer/plan.js.map +1 -0
- package/src/lib/data-transfer/policy.d.ts +170 -0
- package/src/lib/data-transfer/policy.js +378 -0
- package/src/lib/data-transfer/policy.js.map +1 -0
- package/src/lib/data-transfer/resource.d.ts +211 -0
- package/src/lib/data-transfer/resource.js +241 -0
- package/src/lib/data-transfer/resource.js.map +1 -0
- package/src/lib/data-transfer/review.d.ts +70 -0
- package/src/lib/data-transfer/review.js +233 -0
- package/src/lib/data-transfer/review.js.map +1 -0
- package/src/lib/data-transfer/similarity.d.ts +40 -0
- package/src/lib/data-transfer/similarity.js +106 -0
- package/src/lib/data-transfer/similarity.js.map +1 -0
- package/src/lib/data-transfer/site-package.d.ts +365 -0
- package/src/lib/data-transfer/site-package.js +1077 -0
- package/src/lib/data-transfer/site-package.js.map +1 -0
- package/src/lib/data-transfer/source.d.ts +74 -0
- package/src/lib/data-transfer/source.js +293 -0
- package/src/lib/data-transfer/source.js.map +1 -0
- package/src/lib/data-transfer/transfer-api.d.ts +898 -0
- package/src/lib/data-transfer/transfer-api.js +107 -0
- package/src/lib/data-transfer/transfer-api.js.map +1 -0
- package/src/lib/foundation/definitions/org-billing.types.d.ts +31 -0
- package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
- package/src/lib/foundation/definitions/organization.types.d.ts +42 -1
- package/src/lib/foundation/definitions/organization.types.js.map +1 -1
- package/src/lib/foundation/definitions/platform.types.d.ts +6 -4
- package/src/lib/foundation/definitions/platform.types.js.map +1 -1
- package/src/lib/foundation/index.d.ts +1 -1
- package/src/lib/foundation/index.js.map +1 -1
- package/src/lib/plugin-manager/feature-plugins.d.ts +91 -2
- package/src/lib/plugin-manager/feature-plugins.js +48 -3
- package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
- package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +50 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.js +1129 -28
- package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
- package/src/lib/plugin-manager/index.d.ts +0 -1
- package/src/lib/plugin-manager/index.js +0 -1
- package/src/lib/plugin-manager/index.js.map +1 -1
- package/src/lib/plugin-manager/interaction-recipes.d.ts +142 -0
- package/src/lib/plugin-manager/interaction-recipes.js +104 -0
- package/src/lib/plugin-manager/interaction-recipes.js.map +1 -0
- package/src/lib/plugin-manager/interaction-step-checks.d.ts +66 -0
- package/src/lib/plugin-manager/interaction-step-checks.js +86 -0
- package/src/lib/plugin-manager/interaction-step-checks.js.map +1 -0
- package/src/lib/plugin-manager/plugin-artifact-types.d.ts +235 -0
- package/src/lib/plugin-manager/plugin-artifact-types.js +99 -0
- package/src/lib/plugin-manager/plugin-artifact-types.js.map +1 -0
- package/src/lib/plugin-manager/plugin-contact-capture.d.ts +8 -0
- package/src/lib/plugin-manager/plugin-contact-capture.js.map +1 -1
- package/src/lib/plugin-manager/plugin-conversion-credit.d.ts +216 -0
- package/src/lib/plugin-manager/plugin-conversion-credit.js +91 -0
- package/src/lib/plugin-manager/plugin-conversion-credit.js.map +1 -0
- package/src/lib/plugin-manager/plugin-entity-pickers.d.ts +83 -0
- package/src/lib/plugin-manager/plugin-entity-pickers.js +87 -0
- package/src/lib/plugin-manager/plugin-entity-pickers.js.map +1 -0
- package/src/lib/plugin-manager/plugin-host-resources.d.ts +6 -0
- package/src/lib/plugin-manager/plugin-host-resources.js +6 -1
- package/src/lib/plugin-manager/plugin-host-resources.js.map +1 -1
- package/src/lib/plugin-manager/plugin-intake-gates.d.ts +75 -0
- package/src/lib/plugin-manager/plugin-intake-gates.js +49 -0
- package/src/lib/plugin-manager/plugin-intake-gates.js.map +1 -0
- package/src/lib/plugin-manager/plugin-jobs.d.ts +5 -5
- package/src/lib/plugin-manager/plugin-jobs.js +7 -7
- package/src/lib/plugin-manager/plugin-jobs.js.map +1 -1
- package/src/lib/plugin-manager/plugin-live-paths.d.ts +70 -0
- package/src/lib/plugin-manager/plugin-live-paths.js +66 -0
- package/src/lib/plugin-manager/plugin-live-paths.js.map +1 -0
- package/src/lib/plugin-manager/plugin-org-erasure.d.ts +3 -2
- package/src/lib/plugin-manager/plugin-org-erasure.js +30 -5
- package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -1
- package/src/lib/plugin-manager/plugin-person-erasure.d.ts +68 -9
- package/src/lib/plugin-manager/plugin-person-erasure.js +196 -51
- package/src/lib/plugin-manager/plugin-person-erasure.js.map +1 -1
- package/src/lib/plugin-manager/plugin-person-records.d.ts +275 -0
- package/src/lib/plugin-manager/plugin-person-records.js +107 -0
- package/src/lib/plugin-manager/plugin-person-records.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-counts.d.ts +76 -0
- package/src/lib/plugin-manager/plugin-record-counts.js +49 -0
- package/src/lib/plugin-manager/plugin-record-counts.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-email-state.d.ts +26 -0
- package/src/lib/plugin-manager/plugin-record-email-state.js +16 -0
- package/src/lib/plugin-manager/plugin-record-email-state.js.map +1 -1
- package/src/lib/plugin-manager/plugin-record-index.d.ts +10 -0
- package/src/lib/plugin-manager/plugin-record-index.js.map +1 -1
- package/src/lib/plugin-manager/plugin-record-lists.d.ts +86 -6
- package/src/lib/plugin-manager/plugin-record-lists.js +42 -5
- package/src/lib/plugin-manager/plugin-record-lists.js.map +1 -1
- package/src/lib/plugin-manager/plugin-record-origin.d.ts +79 -0
- package/src/lib/plugin-manager/plugin-record-origin.js +46 -0
- package/src/lib/plugin-manager/plugin-record-origin.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-pages.d.ts +37 -0
- package/src/lib/plugin-manager/plugin-record-pages.js +52 -0
- package/src/lib/plugin-manager/plugin-record-pages.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-timeline.d.ts +60 -0
- package/src/lib/plugin-manager/plugin-record-timeline.js +16 -0
- package/src/lib/plugin-manager/plugin-record-timeline.js.map +1 -1
- package/src/lib/plugin-manager/plugin-resource-drafts.d.ts +5 -5
- package/src/lib/plugin-manager/plugin-resource-drafts.js.map +1 -1
- package/src/lib/plugin-manager/plugin-revocations.d.ts +64 -0
- package/src/lib/plugin-manager/plugin-revocations.js +47 -0
- package/src/lib/plugin-manager/plugin-revocations.js.map +1 -0
- package/src/lib/plugin-manager/plugin-send-tallies.d.ts +69 -0
- package/src/lib/plugin-manager/plugin-send-tallies.js +45 -0
- package/src/lib/plugin-manager/plugin-send-tallies.js.map +1 -0
- package/src/lib/plugin-manager/plugin-site-bundle.d.ts +40 -0
- package/src/lib/plugin-manager/plugin-site-bundle.js +4 -0
- package/src/lib/plugin-manager/plugin-site-bundle.js.map +1 -1
- package/src/lib/plugin-manager/plugin-site-export.d.ts +57 -1
- package/src/lib/plugin-manager/plugin-site-export.js +23 -10
- package/src/lib/plugin-manager/plugin-site-export.js.map +1 -1
- package/src/lib/plugin-manager/plugin-sitemap-readers.d.ts +146 -0
- package/src/lib/plugin-manager/plugin-sitemap-readers.js +110 -0
- package/src/lib/plugin-manager/plugin-sitemap-readers.js.map +1 -0
- package/src/lib/plugin-manager/plugin-transfer-resources.d.ts +714 -0
- package/src/lib/plugin-manager/plugin-transfer-resources.js +443 -0
- package/src/lib/plugin-manager/plugin-transfer-resources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-usage-axes.d.ts +54 -5
- package/src/lib/plugin-manager/plugin-usage-axes.js +11 -3
- package/src/lib/plugin-manager/plugin-usage-axes.js.map +1 -1
- package/src/lib/plugin-manager/plugin-user-erasure.js +9 -1
- package/src/lib/plugin-manager/plugin-user-erasure.js.map +1 -1
- package/src/lib/plugin-manager/plugin-visitor-doors.d.ts +104 -0
- package/src/lib/plugin-manager/plugin-visitor-doors.js +108 -0
- package/src/lib/plugin-manager/plugin-visitor-doors.js.map +1 -0
- package/src/lib/plugin-manager/realm-host-aglyn.generated.js +2 -0
- package/src/lib/plugin-manager/realm-host-aglyn.generated.js.map +1 -1
- package/src/lib/plugin-manager/repeat-rows.d.ts +5 -6
- package/src/lib/plugin-manager/repeat-rows.js.map +1 -1
- package/src/lib/app-utils/actions.d.ts +0 -310
- package/src/lib/app-utils/actions.js +0 -506
- package/src/lib/app-utils/actions.js.map +0 -1
- package/src/lib/app-utils/automation-placeholders.d.ts +0 -72
- package/src/lib/app-utils/automation-placeholders.js +0 -207
- package/src/lib/app-utils/automation-placeholders.js.map +0 -1
- package/src/lib/app-utils/dataset-models.d.ts +0 -339
- package/src/lib/app-utils/dataset-models.js +0 -722
- package/src/lib/app-utils/dataset-models.js.map +0 -1
- package/src/lib/app-utils/datasets.d.ts +0 -171
- package/src/lib/app-utils/datasets.js +0 -227
- package/src/lib/app-utils/datasets.js.map +0 -1
- package/src/lib/app-utils/form-abuse-ceiling.d.ts +0 -146
- package/src/lib/app-utils/form-abuse-ceiling.js +0 -158
- package/src/lib/app-utils/form-abuse-ceiling.js.map +0 -1
- package/src/lib/plugin-manager/order-fulfilment.d.ts +0 -142
- package/src/lib/plugin-manager/order-fulfilment.js +0 -104
- package/src/lib/plugin-manager/order-fulfilment.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/data-transfer/derive.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 * DERIVATIONS — reading a cell as the field it was mapped to, and saying how.\n *\n * Every parser here returns the value AND a record of each thing it did to\n * get there: a date read as day/month/year, a `1.234,56` read with a\n * decimal comma, a `$` read as a currency, a full name split at its last\n * word. Nothing is changed silently. The wizard counts the records by kind,\n * shows samples, and a `flagged` record (a guess that could be wrong — an\n * ambiguous date, a best-effort address) is a warning the person must\n * acknowledge before anything is written.\n *\n * ## Three outcomes\n *\n * - blank — the cell was empty: `{ blank: true, value: null }`, never a problem.\n * - read — `{ ok: true, value }`, with zero or more derivations.\n * - unreadable — `{ ok: false, problem }`: the cell is dropped and reported,\n * never stored as something it did not say.\n *=========================================*/\n\nimport { normalizePhone } from '../foundation/definitions/contact.types'\nimport type { AglynPostalAddress } from '../foundation/definitions/contact.types'\nimport type { TransferField } from './resource'\n\n/** What a parser did to a cell. */\nexport type DerivationKind =\n | 'truncated'\n | 'lowercased'\n | 'extracted'\n | 'dateFormat'\n | 'ambiguousDate'\n | 'twoDigitYear'\n | 'excelSerial'\n | 'timeDropped'\n | 'timeAssumed'\n | 'zoneAssumed'\n | 'epochTime'\n | 'thousandsSeparator'\n | 'decimalComma'\n | 'ambiguousNumber'\n | 'negativeParentheses'\n | 'currencySymbol'\n | 'currencyAssumed'\n | 'rounded'\n | 'percentScaled'\n | 'booleanWord'\n | 'phoneNormalized'\n | 'phoneUnnormalized'\n | 'phoneExtensionDropped'\n | 'urlScheme'\n | 'nameSplit'\n | 'honorificDropped'\n | 'addressSplit'\n | 'listSplit'\n | 'listDeduplicated'\n\n/** One thing a parser did, in words a person can check. */\nexport interface Derivation {\n kind: DerivationKind\n /** The cell as the file had it. */\n from: string\n /** What it became, as text. */\n to: string\n /** The rule in a sentence: \"Read as day/month/year\". */\n note: string\n /** A guess that could be wrong; the wizard asks for acknowledgement. */\n flagged: boolean\n}\n\n/** Why a cell could not be read. */\nexport type DeriveProblemCode =\n | 'invalidEmail'\n | 'invalidDate'\n | 'invalidDateTime'\n | 'invalidNumber'\n | 'notInteger'\n | 'invalidCurrency'\n | 'invalidPercent'\n | 'invalidBoolean'\n | 'invalidUrl'\n | 'invalidJson'\n\nexport interface DeriveProblem {\n code: DeriveProblemCode\n message: string\n}\n\n/** A cell read as a field. */\nexport interface DerivedValue<T> {\n /** `null` when blank or unreadable. */\n value: T | null\n /** The cell was empty. */\n blank: boolean\n /** The cell was blank or read; `false` means it is dropped. */\n ok: boolean\n derivations: Derivation[]\n problem?: DeriveProblem\n}\n\nfunction blankValue<T>(): DerivedValue<T> {\n return { value: null, blank: true, ok: true, derivations: [] }\n}\n\nfunction readValue<T>(value: T, derivations: Derivation[] = []): DerivedValue<T> {\n return { value, blank: false, ok: true, derivations }\n}\n\nfunction unreadable<T>(code: DeriveProblemCode, message: string): DerivedValue<T> {\n return { value: null, blank: false, ok: false, derivations: [], problem: { code, message } }\n}\n\nfunction derivation(kind: DerivationKind, from: string, to: unknown, note: string, flagged = false): Derivation {\n return { kind, from, to: typeof to === 'string' ? to : JSON.stringify(to), note, flagged }\n}\n\nfunction cellText(raw: unknown): string {\n if (raw === null || raw === undefined) return ''\n if (typeof raw === 'string') return raw.trim()\n if (typeof raw === 'number' || typeof raw === 'boolean') return String(raw)\n if (raw instanceof Date) return Number.isNaN(raw.getTime()) ? '' : raw.toISOString()\n return String(raw).trim()\n}\n\n/*------------------------------------------\n * Text\n *-----------------------------------------*/\n\n/** A text cell, trimmed; capped at `maxLength` with a flagged record when cut. */\nexport function deriveText(raw: unknown, options: { maxLength?: number; multiline?: boolean } = {}): DerivedValue<string> {\n let text = options.multiline ? String(raw ?? '').replace(/\\r\\n?/g, '\\n').trim() : cellText(raw)\n if (!options.multiline) text = text.replace(/\\s+/g, ' ')\n if (!text) return blankValue()\n if (options.maxLength && text.length > options.maxLength) {\n const cut = text.slice(0, options.maxLength)\n return readValue(cut, [\n derivation('truncated', text, cut, `Cut to ${options.maxLength} characters`, true),\n ])\n }\n return readValue(text)\n}\n\n/*------------------------------------------\n * Boolean\n *-----------------------------------------*/\n\nconst TRUE_WORDS = ['yes', 'y', 'true', '1', 'on', 'subscribed', 'opted in', 'opted-in']\nconst FALSE_WORDS = ['no', 'n', 'false', '0', 'off', 'unsubscribed', '']\n\n/**\n * A yes/no cell as a boolean, or `null` when it is neither.\n *\n * The affirmatives are the ones consent and checkbox columns actually\n * carry; the negatives are listed so that an explicit `no` is a `false`\n * rather than an unreadable value that gets reported as dropped. An empty\n * cell reads as `false`, which is what a checkbox column means by it.\n */\nexport function parseImportFlag(value: unknown): boolean | null {\n if (typeof value === 'boolean') return value\n if (typeof value === 'number') return value === 1 ? true : value === 0 ? false : null\n const text = String(value ?? '')\n .trim()\n .toLowerCase()\n if (TRUE_WORDS.includes(text)) return true\n if (FALSE_WORDS.includes(text)) return false\n return null\n}\n\n/** A boolean cell; a word other than true/false is recorded. */\nexport function deriveBoolean(raw: unknown): DerivedValue<boolean> {\n const text = cellText(raw)\n if (!text) return blankValue()\n const flag = parseImportFlag(typeof raw === 'string' ? text : raw)\n if (flag === null) return unreadable('invalidBoolean', `\"${text}\" is not a yes or a no.`)\n const plain = text.toLowerCase() === String(flag)\n return readValue(flag, plain ? [] : [derivation('booleanWord', text, String(flag), `Read \"${text}\" as ${flag ? 'yes' : 'no'}`)])\n}\n\n/*------------------------------------------\n * Email, phone, URL\n *-----------------------------------------*/\n\nconst EMAIL = /^[^\\s@<>(),;:\"[\\]]+@[^\\s@<>(),;:\"[\\]]+\\.[^\\s@<>(),;:\"[\\]]{2,}$/\n\n/** An address cell: `mailto:` and a display name stripped, lowercased, checked. */\nexport function deriveEmail(raw: unknown): DerivedValue<string> {\n const text = cellText(raw)\n if (!text) return blankValue()\n const derivations: Derivation[] = []\n let address = text\n const angled = /<([^<>]+)>\\s*$/.exec(address)\n if (angled?.[1]) {\n address = angled[1].trim()\n derivations.push(derivation('extracted', text, address, 'Took the address out of a name and address'))\n }\n if (/^mailto:/i.test(address)) {\n const stripped = address.replace(/^mailto:/i, '').split('?')[0] ?? ''\n derivations.push(derivation('extracted', address, stripped, 'Removed \"mailto:\"'))\n address = stripped\n }\n const lower = address.toLowerCase()\n if (lower !== address) derivations.push(derivation('lowercased', address, lower, 'Lowercased the address'))\n if (!EMAIL.test(lower)) return unreadable('invalidEmail', `\"${text}\" is not an email address.`)\n return readValue(lower, derivations)\n}\n\nconst EXTENSION = /\\s*(?:ext\\.?|extension|x|#)\\s*(\\d{1,6})\\s*$/i\n\n/**\n * A phone cell in E.164 through the platform's `normalizePhone`. A number it\n * cannot normalize confidently is kept as typed and flagged — dropping a\n * real number is worse than storing it unformatted. An extension is\n * removed (E.164 has no place for it) and flagged.\n */\nexport function derivePhone(raw: unknown, options: { defaultCountry?: string } = {}): DerivedValue<string> {\n const text = cellText(raw)\n if (!text) return blankValue()\n const derivations: Derivation[] = []\n let number = text\n const extension = EXTENSION.exec(number)\n if (extension && number.replace(EXTENSION, '').replace(/\\D/g, '').length >= 7) {\n const without = number.replace(EXTENSION, '').trim()\n derivations.push(\n derivation('phoneExtensionDropped', text, without, `Dropped extension ${extension[1]}`, true),\n )\n number = without\n }\n const normalized = normalizePhone(number, options.defaultCountry ?? 'US')\n if (!normalized) {\n derivations.push(\n derivation('phoneUnnormalized', text, number, 'Kept as typed: no country code to read it by', true),\n )\n return readValue(number, derivations)\n }\n if (normalized !== number) {\n derivations.push(derivation('phoneNormalized', number, normalized, 'Written in international format'))\n }\n return readValue(normalized, derivations)\n}\n\n/** A web address cell: `https://` added to a bare domain, host lowercased, checked. */\nexport function deriveUrl(raw: unknown): DerivedValue<string> {\n const text = cellText(raw)\n if (!text) return blankValue()\n const derivations: Derivation[] = []\n let candidate = text\n if (!/^[a-z][a-z0-9+.-]*:\\/\\//i.test(candidate)) {\n if (!/^(?:[\\w-]+\\.)+[a-z]{2,}(?::\\d+)?(?:[/?#].*)?$/i.test(candidate)) {\n return unreadable('invalidUrl', `\"${text}\" is not a web address.`)\n }\n candidate = `https://${candidate}`\n derivations.push(derivation('urlScheme', text, candidate, 'Added https://'))\n }\n let url: URL\n try {\n url = new URL(candidate)\n } catch {\n return unreadable('invalidUrl', `\"${text}\" is not a web address.`)\n }\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n return unreadable('invalidUrl', `\"${text}\" is not a web address.`)\n }\n const rest = candidate.slice(candidate.indexOf('//') + 2).replace(/^[^/?#]*/, '')\n return readValue(`${url.protocol}//${url.host}${rest}`, derivations)\n}\n\n/*------------------------------------------\n * Dates and times\n *-----------------------------------------*/\n\n/** How an all-number date's day and month are told apart. */\nexport interface DateOptions {\n /** Fixed by the person, or `auto` to read it from the values. */\n order?: 'auto' | 'mdy' | 'dmy'\n /** The order an ambiguous date is read in under `auto`; default `mdy`. */\n preferredOrder?: 'mdy' | 'dmy'\n /** Read a bare five-digit number as a spreadsheet serial day; default true. */\n excelSerials?: boolean\n /** Two-digit years below this are 20xx, the rest 19xx; default 50. */\n twoDigitYearPivot?: number\n}\n\nconst MONTHS = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']\n\nfunction monthOf(word: string): number | null {\n const key = word.toLowerCase().slice(0, 3)\n const at = MONTHS.indexOf(key)\n if (at < 0) return null\n // `sept` and full names are fine; a word that only starts like a month is not.\n const full = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december']\n const lower = word.toLowerCase()\n return full[at]?.startsWith(lower) ? at + 1 : null\n}\n\nfunction pad(n: number, width = 2): string {\n return String(n).padStart(width, '0')\n}\n\nfunction isoDate(year: number, month: number, day: number): string | null {\n if (!Number.isInteger(year) || year < 1 || year > 9999) return null\n if (month < 1 || month > 12 || day < 1) return null\n const date = new Date(Date.UTC(year, month - 1, day))\n date.setUTCFullYear(year)\n if (date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day) return null\n return `${pad(year, 4)}-${pad(month)}-${pad(day)}`\n}\n\n/** The spreadsheet epoch: serial day 0 is 1899-12-30 (the leap-year bug folded in). */\nconst SERIAL_EPOCH_MS = Date.UTC(1899, 11, 30)\nconst DAY_MS = 86_400_000\n\nfunction serialToDate(serial: number): Date {\n return new Date(SERIAL_EPOCH_MS + Math.round(serial * DAY_MS))\n}\n\nfunction fullYear(text: string, pivot: number, from: string, derivations: Derivation[]): number {\n const n = Number(text)\n if (text.length !== 2) return n\n const year = n < pivot ? 2000 + n : 1900 + n\n derivations.push(derivation('twoDigitYear', from, String(year), `Read year \"${text}\" as ${year}`, true))\n return year\n}\n\n/**\n * A date cell as `YYYY-MM-DD`.\n *\n * ISO dates read as they are; `2024/03/05` and `20240305` are read year\n * first; an all-number date with the year last is read by `order`, and\n * under `auto` a value whose day and month could be swapped (`03/05/2024`)\n * is read in `preferredOrder` and flagged; month names read in either\n * order; a bare serial number is a spreadsheet's date.\n */\nexport function deriveDate(raw: unknown, options: DateOptions = {}): DerivedValue<string> {\n const derivations: Derivation[] = []\n const result = parseDateText(raw, options, derivations)\n if (result === undefined) return blankValue()\n if (result === null) return unreadable('invalidDate', `\"${cellText(raw)}\" is not a date.`)\n return readValue(result, derivations)\n}\n\nfunction parseDateText(raw: unknown, options: DateOptions, derivations: Derivation[]): string | null | undefined {\n const text = cellText(raw)\n if (!text) return undefined\n const pivot = options.twoDigitYearPivot ?? 50\n\n const iso = /^(\\d{4})-(\\d{1,2})-(\\d{1,2})(?:[T ](.+))?$/.exec(text)\n if (iso) {\n const date = isoDate(Number(iso[1]), Number(iso[2]), Number(iso[3]))\n if (date && iso[4]) derivations.push(derivation('timeDropped', text, date, 'Kept the date, dropped the time'))\n return date\n }\n\n const yearFirst = /^(\\d{4})[/.](\\d{1,2})[/.](\\d{1,2})$/.exec(text) ?? /^(\\d{4})(\\d{2})(\\d{2})$/.exec(text)\n if (yearFirst) {\n const date = isoDate(Number(yearFirst[1]), Number(yearFirst[2]), Number(yearFirst[3]))\n if (date) derivations.push(derivation('dateFormat', text, date, 'Read as year/month/day'))\n return date\n }\n\n const numeric = /^(\\d{1,2})[/.-](\\d{1,2})[/.-](\\d{2}|\\d{4})$/.exec(text)\n if (numeric) {\n const a = Number(numeric[1])\n const b = Number(numeric[2])\n const yearDerivations: Derivation[] = []\n const year = fullYear(numeric[3] as string, pivot, text, yearDerivations)\n let order: 'mdy' | 'dmy'\n let ambiguous = false\n if (options.order === 'mdy' || options.order === 'dmy') order = options.order\n else if (a > 12 && b <= 12) order = 'dmy'\n else if (b > 12 && a <= 12) order = 'mdy'\n else if (a > 12 && b > 12) return null\n else {\n order = options.preferredOrder ?? 'mdy'\n ambiguous = a !== b\n }\n const date = order === 'mdy' ? isoDate(year, a, b) : isoDate(year, b, a)\n if (!date) return null\n const words = order === 'mdy' ? 'month/day/year' : 'day/month/year'\n derivations.push(\n ambiguous\n ? derivation('ambiguousDate', text, date, `Could be either order; read as ${words}`, true)\n : derivation('dateFormat', text, date, `Read as ${words}`),\n )\n derivations.push(...yearDerivations)\n return date\n }\n\n const named =\n /^(?:[a-z]+,?\\s+)?(\\d{1,2})(?:st|nd|rd|th)?[\\s-]+([a-z]+)\\.?,?[\\s-]+(\\d{2}|\\d{4})$/i.exec(text) ??\n null\n const namedMonthFirst =\n /^(?:[a-z]+,\\s+)?([a-z]+)\\.?[\\s-]+(\\d{1,2})(?:st|nd|rd|th)?,?[\\s-]+(\\d{2}|\\d{4})$/i.exec(text) ?? null\n if (named || namedMonthFirst) {\n const day = Number(named ? named[1] : namedMonthFirst?.[2])\n const month = monthOf((named ? named[2] : namedMonthFirst?.[1]) as string)\n if (!month) return null\n const yearDerivations: Derivation[] = []\n const year = fullYear((named ? named[3] : namedMonthFirst?.[3]) as string, pivot, text, yearDerivations)\n const date = isoDate(year, month, day)\n if (!date) return null\n derivations.push(derivation('dateFormat', text, date, 'Read the month by name'), ...yearDerivations)\n return date\n }\n\n const serial = typeof raw === 'number' ? raw : /^\\d{5}(?:\\.\\d+)?$/.test(text) ? Number(text) : NaN\n if (options.excelSerials !== false && Number.isFinite(serial) && serial >= 1 && serial <= 2_958_465) {\n const at = serialToDate(serial)\n const date = isoDate(at.getUTCFullYear(), at.getUTCMonth() + 1, at.getUTCDate())\n if (date) derivations.push(derivation('excelSerial', text, date, 'Read as a spreadsheet serial date', true))\n return date\n }\n return null\n}\n\n/** How a date and time without a zone is placed. */\nexport interface DateTimeOptions extends DateOptions {\n /** Minutes east of UTC a zone-less time is read in; default 0 (UTC). */\n offsetMinutes?: number\n}\n\nconst ZONED_ISO = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d+)?)?(?:Z|[+-]\\d{2}:?\\d{2})$/i\n\nfunction zoneLabel(offsetMinutes: number): string {\n if (!offsetMinutes) return 'UTC'\n const sign = offsetMinutes > 0 ? '+' : '-'\n const abs = Math.abs(offsetMinutes)\n return `UTC${sign}${pad(Math.floor(abs / 60))}:${pad(abs % 60)}`\n}\n\nfunction offsetOf(zone: string): number | null {\n if (/^(?:z|utc|gmt)$/i.test(zone)) return 0\n const match = /^([+-])(\\d{2}):?(\\d{2})$/.exec(zone)\n if (!match) return null\n const minutes = Number(match[2]) * 60 + Number(match[3])\n return match[1] === '-' ? -minutes : minutes\n}\n\n/**\n * A date-and-time cell as an ISO instant (`…Z`).\n *\n * A time with a zone is exact. A time without one is read in\n * `offsetMinutes` and flagged; a date alone is midnight there. A ten- or\n * thirteen-digit number is a Unix time in seconds or milliseconds, and a\n * serial number with a fraction is a spreadsheet's date and time — both\n * flagged, because a column of numbers could be something else.\n */\nexport function deriveDateTime(raw: unknown, options: DateTimeOptions = {}): DerivedValue<string> {\n const text = cellText(raw)\n if (!text) return blankValue()\n const fail = (): DerivedValue<string> => unreadable('invalidDateTime', `\"${text}\" is not a date and time.`)\n const offset = options.offsetMinutes ?? 0\n\n if (ZONED_ISO.test(text)) {\n const ms = Date.parse(text)\n return Number.isNaN(ms) ? fail() : readValue(new Date(ms).toISOString())\n }\n\n if (/^\\d{10}$|^\\d{13}$/.test(text)) {\n const ms = text.length === 10 ? Number(text) * 1000 : Number(text)\n const iso = new Date(ms).toISOString()\n return readValue(iso, [\n derivation('epochTime', text, iso, `Read as a Unix time in ${text.length === 10 ? 'seconds' : 'milliseconds'}`, true),\n ])\n }\n\n const serial = typeof raw === 'number' ? raw : /^\\d{5}\\.\\d+$/.test(text) ? Number(text) : NaN\n if (options.excelSerials !== false && Number.isFinite(serial) && serial >= 1 && serial <= 2_958_465) {\n const iso = new Date(serialToDate(serial).getTime() - offset * 60_000).toISOString()\n return readValue(iso, [derivation('excelSerial', text, iso, 'Read as a spreadsheet serial date and time', true)])\n }\n\n const timed =\n /^(.*?)[T\\s,]+(\\d{1,2}):(\\d{2})(?::(\\d{2})(?:\\.\\d+)?)?\\s*([ap]\\.?m\\.?)?\\s*(z|utc|gmt|[+-]\\d{2}:?\\d{2})?$/i.exec(text)\n const derivations: Derivation[] = []\n const datePart = timed ? (timed[1] as string) : text\n const date = parseDateText(datePart, options, derivations)\n if (!date) return fail()\n let hours = 0\n let minutes = 0\n let seconds = 0\n let zoneOffset: number | null = null\n if (timed) {\n hours = Number(timed[2])\n minutes = Number(timed[3])\n seconds = Number(timed[4] ?? 0)\n const meridiem = timed[5]?.toLowerCase().replace(/\\./g, '')\n if (meridiem) {\n if (hours < 1 || hours > 12) return fail()\n if (meridiem === 'pm' && hours !== 12) hours += 12\n if (meridiem === 'am' && hours === 12) hours = 0\n }\n if (hours > 23 || minutes > 59 || seconds > 59) return fail()\n if (timed[6]) {\n zoneOffset = offsetOf(timed[6])\n if (zoneOffset === null) return fail()\n }\n } else {\n derivations.push(derivation('timeAssumed', text, '00:00', 'No time given; read as midnight'))\n }\n // A date-only cell is a day, not a moment someone was unsure of the zone\n // of — only a cell that HAS a time without a zone is flagged.\n if (zoneOffset === null && timed) {\n derivations.push(derivation('zoneAssumed', text, zoneLabel(offset), `No time zone; read as ${zoneLabel(offset)}`, true))\n }\n const [y, m, d] = date.split('-').map(Number) as [number, number, number]\n const local = new Date(Date.UTC(2000, m - 1, d, hours, minutes, seconds))\n // `Date.UTC` reads a year below 100 as 19xx; the year is set on its own.\n local.setUTCFullYear(y, m - 1, d)\n const at = new Date(local.getTime() - (zoneOffset ?? offset) * 60_000)\n return readValue(at.toISOString(), derivations)\n}\n\n/*------------------------------------------\n * Numbers, currency, percent\n *-----------------------------------------*/\n\n/** Which character a number's decimal point is. */\nexport interface NumberOptions {\n /** Fixed by the person, or `auto` to read it from the value; default `auto`. */\n decimal?: 'auto' | '.' | ','\n}\n\nconst GROUPED_COMMA = /^\\d{1,3}(?:,\\d{3})+$/\nconst GROUPED_DOT = /^\\d{1,3}(?:\\.\\d{3})+$/\nconst PLAIN_NUMBER = /^\\d+(?:\\.\\d+)?(?:e[+-]?\\d+)?$|^\\.\\d+$/i\n\n/**\n * A locale-formatted number: separators read, parentheses as a minus.\n * `null` when the text is not a number. Every separator decision is\n * recorded; a lone `1,234` or `1.234` under `auto` could be a thousand or\n * one-and-a-bit, so it is read as the thousand and flagged.\n */\nexport function parseLocaleNumber(\n text: string,\n options: NumberOptions = {},\n derivations: Derivation[] = [],\n): number | null {\n const from = text\n // Spaces (plain, non-breaking, narrow) and apostrophes only ever group thousands.\n let body = text.trim().replace(/[\\s\\u00a0\\u202f'\\u2019]+/g, '_')\n let negative = false\n const paren = /^\\((.*)\\)$/.exec(body)\n if (paren) {\n body = paren[1] as string\n negative = true\n derivations.push(derivation('negativeParentheses', from, `-${body}`, 'Read parentheses as a minus'))\n }\n if (/^[+-]/.test(body)) {\n if (body.startsWith('-')) negative = !negative\n body = body.slice(1)\n } else if (/-$/.test(body)) {\n negative = !negative\n body = body.slice(0, -1)\n }\n if (body.includes('_')) {\n if (!/^\\d{1,3}(?:_\\d{3})+(?:[.,]\\d+)?$/.test(body)) return null\n body = body.replace(/_/g, '')\n derivations.push(derivation('thousandsSeparator', from, body, 'Removed the thousands separators'))\n }\n const decimal = options.decimal ?? 'auto'\n const hasDot = body.includes('.')\n const hasComma = body.includes(',')\n if (hasDot && hasComma) {\n const commaLast = body.lastIndexOf(',') > body.lastIndexOf('.')\n const point = decimal === 'auto' ? (commaLast ? ',' : '.') : decimal\n const group = point === ',' ? '.' : ','\n const [whole, fraction, extra] = body.split(point)\n if (extra !== undefined || !whole || !fraction) return null\n if (!(group === '.' ? GROUPED_DOT : GROUPED_COMMA).test(whole)) return null\n body = `${whole.split(group).join('')}.${fraction}`\n derivations.push(derivation('thousandsSeparator', from, body, `Read \"${group}\" as the thousands separator`))\n if (point === ',') derivations.push(derivation('decimalComma', from, body, 'Read \",\" as the decimal point'))\n } else if (hasComma) {\n if (decimal === ',' || (decimal === 'auto' && !GROUPED_COMMA.test(body))) {\n if ((body.match(/,/g) ?? []).length > 1) return null\n body = body.replace(',', '.')\n derivations.push(derivation('decimalComma', from, body, 'Read \",\" as the decimal point'))\n } else {\n if (!GROUPED_COMMA.test(body)) return null\n const ambiguous = decimal === 'auto' && (body.match(/,/g) ?? []).length === 1\n body = body.replace(/,/g, '')\n derivations.push(\n ambiguous\n ? derivation('ambiguousNumber', from, body, 'Read \",\" as the thousands separator; it could be a decimal comma', true)\n : derivation('thousandsSeparator', from, body, 'Read \",\" as the thousands separator'),\n )\n }\n } else if (hasDot) {\n const dots = (body.match(/\\./g) ?? []).length\n if (dots > 1 || (decimal === ',' && GROUPED_DOT.test(body))) {\n if (!GROUPED_DOT.test(body)) return null\n body = body.replace(/\\./g, '')\n derivations.push(derivation('thousandsSeparator', from, body, 'Read \".\" as the thousands separator'))\n }\n }\n if (!PLAIN_NUMBER.test(body)) return null\n const value = Number(body)\n if (!Number.isFinite(value)) return null\n return negative ? -value : value\n}\n\n/** A number cell. */\nexport function deriveNumber(raw: unknown, options: NumberOptions = {}): DerivedValue<number> {\n if (typeof raw === 'number') return Number.isFinite(raw) ? readValue(raw) : unreadable('invalidNumber', 'Not a number.')\n const text = cellText(raw)\n if (!text) return blankValue()\n const derivations: Derivation[] = []\n const value = parseLocaleNumber(text, options, derivations)\n if (value === null) return unreadable('invalidNumber', `\"${text}\" is not a number.`)\n return readValue(value, derivations)\n}\n\n/** A whole-number cell; a fraction is unreadable rather than rounded away. */\nexport function deriveInteger(raw: unknown, options: NumberOptions = {}): DerivedValue<number> {\n const result = deriveNumber(raw, options)\n if (!result.ok || result.value === null) return result\n if (!Number.isInteger(result.value)) {\n return unreadable('notInteger', `\"${cellText(raw)}\" is not a whole number.`)\n }\n return result\n}\n\n/** An amount of money in the currency's smallest unit (cents for USD). */\nexport interface CurrencyAmount {\n amountMinor: number\n /** ISO 4217, uppercase. */\n currency: string\n}\n\n/** Currencies whose smallest unit is not the hundredth. */\nexport const CURRENCY_MINOR_UNITS: Readonly<Record<string, number>> = {\n BHD: 3,\n CLP: 0,\n ISK: 0,\n JOD: 3,\n JPY: 0,\n KRW: 0,\n KWD: 3,\n OMR: 3,\n TND: 3,\n UGX: 0,\n VND: 0,\n XAF: 0,\n XOF: 0,\n}\n\n/** How many decimal places a currency's smallest unit is. */\nexport function currencyMinorUnits(currency: string): number {\n return CURRENCY_MINOR_UNITS[currency.toUpperCase()] ?? 2\n}\n\n/** Symbols longest first, so `US$` is found before `$`. */\nconst CURRENCY_SYMBOLS: readonly (readonly [string, string | null])[] = [\n ['US$', 'USD'],\n ['CA$', 'CAD'],\n ['AU$', 'AUD'],\n ['NZ$', 'NZD'],\n ['HK$', 'HKD'],\n ['R$', 'BRL'],\n ['A$', 'AUD'],\n ['C$', 'CAD'],\n ['€', 'EUR'],\n ['£', 'GBP'],\n ['¥', 'JPY'],\n ['₹', 'INR'],\n ['₩', 'KRW'],\n ['₪', 'ILS'],\n ['₱', 'PHP'],\n ['₫', 'VND'],\n ['₺', 'TRY'],\n ['$', null],\n]\n\nconst DOLLAR_CURRENCIES = ['USD', 'CAD', 'AUD', 'NZD', 'HKD', 'SGD', 'MXN']\n\n/** What currency a cell is read in when it names none. */\nexport interface CurrencyOptions extends NumberOptions {\n /** ISO 4217; default `USD`. */\n defaultCurrency?: string\n}\n\n/**\n * A money cell as an amount in minor units and a currency. A symbol or a\n * three-letter code on either side names the currency; `$` alone is the\n * default currency when that is a dollar, else US dollars; a bare number\n * is the default currency. More decimals than the currency has are rounded\n * and flagged.\n */\nexport function deriveCurrency(raw: unknown, options: CurrencyOptions = {}): DerivedValue<CurrencyAmount> {\n const fallback = (options.defaultCurrency ?? 'USD').toUpperCase()\n const text = cellText(raw)\n if (!text) return blankValue()\n const derivations: Derivation[] = []\n let body = text\n let currency: string | null = null\n const coded = /^([a-z]{3})\\s*(.+)$/i.exec(body) ?? /^(.+?)\\s*([a-z]{3})$/i.exec(body)\n if (coded) {\n const codeFirst = /^[a-z]{3}$/i.test(coded[1] as string) && !/^\\d/.test(coded[1] as string)\n const code = (codeFirst ? coded[1] : coded[2]) as string\n if (/^[a-z]{3}$/i.test(code) && !/^e[+-]?\\d/i.test(code)) {\n currency = code.toUpperCase()\n body = ((codeFirst ? coded[2] : coded[1]) as string).trim()\n }\n }\n for (const [symbol, code] of CURRENCY_SYMBOLS) {\n const at = body.indexOf(symbol)\n if (at < 0) continue\n body = (body.slice(0, at) + body.slice(at + symbol.length)).trim()\n const named = code ?? (DOLLAR_CURRENCIES.includes(fallback) ? fallback : 'USD')\n if (!currency) currency = named\n derivations.push(derivation('currencySymbol', text, currency, `Read \"${symbol}\" as ${currency}`))\n break\n }\n if (!currency) {\n currency = fallback\n derivations.push(derivation('currencyAssumed', text, currency, `No currency given; read as ${currency}`))\n }\n const value = parseLocaleNumber(body, options, derivations)\n if (value === null) return unreadable('invalidCurrency', `\"${text}\" is not an amount of money.`)\n const units = currencyMinorUnits(currency)\n const scaled = value * 10 ** units\n const amountMinor = Math.round(scaled)\n if (Math.abs(scaled - amountMinor) > 1e-6) {\n derivations.push(\n derivation('rounded', text, String(amountMinor / 10 ** units), `Rounded to ${units} decimal places`, true),\n )\n }\n return readValue({ amountMinor, currency }, derivations)\n}\n\n/** Whether a percent is stored as `12` (whole) or `0.12` (fraction) for 12%. */\nexport interface PercentOptions extends NumberOptions {\n /** Default `whole`. */\n scale?: 'whole' | 'fraction'\n}\n\n/**\n * A percent cell. `12%` is twelve percent. A number with no `%` between 0\n * and 1 (`0.12`) is read as a fraction — twelve percent — and flagged,\n * because a file of fractions and a file of tiny percents look the same.\n */\nexport function derivePercent(raw: unknown, options: PercentOptions = {}): DerivedValue<number> {\n const text = cellText(raw)\n if (!text) return blankValue()\n const derivations: Derivation[] = []\n const signed = /%\\s*$|^\\s*%/.test(text)\n const value = parseLocaleNumber(text.replace(/%/g, '').trim(), options, derivations)\n if (value === null) return unreadable('invalidPercent', `\"${text}\" is not a percent.`)\n let whole = value\n if (!signed && value !== 0 && Math.abs(value) < 1) {\n whole = Number((value * 100).toPrecision(12))\n derivations.push(derivation('percentScaled', text, `${whole}%`, `Read ${text} as a fraction: ${whole}%`, true))\n }\n return readValue(options.scale === 'fraction' ? Number((whole / 100).toPrecision(12)) : whole, derivations)\n}\n\n/*------------------------------------------\n * Names, addresses, lists\n *-----------------------------------------*/\n\n/** Which rule split a full name. */\nexport type NameSplitRule = 'lastCommaFirst' | 'lastWord' | 'surnameParticle' | 'singleWord'\n\nexport interface SplitName {\n first: string | null\n last: string | null\n rule: NameSplitRule\n}\n\nconst HONORIFICS = ['mr', 'mrs', 'ms', 'miss', 'mx', 'dr', 'prof', 'sir', 'dame', 'rev']\nconst SUFFIXES = ['jr', 'sr', 'ii', 'iii', 'iv', 'v', 'phd', 'md', 'esq', 'dds', 'cpa']\nconst PARTICLES = ['van', 'von', 'de', 'der', 'den', 'da', 'das', 'dos', 'del', 'della', 'di', 'du', 'la', 'le', 'bin', 'binti', 'al', 'el', 'ter', 'ten', 'st', 'st.']\n\nfunction bare(word: string): string {\n return word.toLowerCase().replace(/[.,]/g, '')\n}\n\n/**\n * A full name as first and last. \"Last, First\" splits at the comma; an\n * honorific is dropped (and recorded); a suffix stays with the last name; a\n * surname particle (`van`, `de la`) starts the last name; otherwise the\n * last word is the last name. Every split is recorded with its rule.\n */\nexport function splitFullName(raw: unknown): DerivedValue<SplitName> {\n const text = cellText(raw).replace(/\\s+/g, ' ')\n if (!text) return blankValue()\n const derivations: Derivation[] = []\n const done = (first: string | null, last: string | null, rule: NameSplitRule, note: string): DerivedValue<SplitName> => {\n derivations.push(derivation('nameSplit', text, { first, last }, note))\n return readValue({ first: first || null, last: last || null, rule }, derivations)\n }\n const comma = /^([^,]+),\\s*([^,]+)$/.exec(text)\n if (comma && !SUFFIXES.includes(bare(comma[2] as string))) {\n return done((comma[2] as string).trim(), (comma[1] as string).trim(), 'lastCommaFirst', 'Read as \"Last, First\"')\n }\n let words = text.replace(/,/g, ' ').split(' ').filter(Boolean)\n while (words.length > 1 && HONORIFICS.includes(bare(words[0] as string))) {\n derivations.push(derivation('honorificDropped', text, words[0] as string, `Dropped \"${words[0]}\"`))\n words = words.slice(1)\n }\n const suffixes: string[] = []\n while (words.length > 2 && SUFFIXES.includes(bare(words[words.length - 1] as string))) {\n suffixes.unshift(words.pop() as string)\n }\n if (words.length === 1) return done(words[0] as string, null, 'singleWord', 'One word; kept as the first name')\n const particleAt = words.findIndex((word, index) => index > 0 && index < words.length - 1 && PARTICLES.includes(word.toLowerCase()))\n const tail = suffixes.length ? ` ${suffixes.join(' ')}` : ''\n if (particleAt > 0) {\n return done(\n words.slice(0, particleAt).join(' '),\n words.slice(particleAt).join(' ') + tail,\n 'surnameParticle',\n `Last name starts at \"${words[particleAt]}\"`,\n )\n }\n return done(\n words.slice(0, -1).join(' '),\n (words[words.length - 1] as string) + tail,\n 'lastWord',\n 'Last word is the last name',\n )\n}\n\nconst COUNTRY_NAMES: Readonly<Record<string, string>> = {\n 'us': 'US',\n 'usa': 'US',\n 'u s a': 'US',\n 'united states': 'US',\n 'united states of america': 'US',\n 'america': 'US',\n 'ca': 'CA',\n 'canada': 'CA',\n 'uk': 'GB',\n 'gb': 'GB',\n 'united kingdom': 'GB',\n 'great britain': 'GB',\n 'england': 'GB',\n 'scotland': 'GB',\n 'wales': 'GB',\n 'ireland': 'IE',\n 'australia': 'AU',\n 'new zealand': 'NZ',\n 'germany': 'DE',\n 'deutschland': 'DE',\n 'france': 'FR',\n 'spain': 'ES',\n 'italy': 'IT',\n 'netherlands': 'NL',\n 'mexico': 'MX',\n 'india': 'IN',\n 'japan': 'JP',\n 'brazil': 'BR',\n}\n\nfunction countryOf(part: string): string | null {\n const key = part.toLowerCase().replace(/[.]/g, '').replace(/\\s+/g, ' ').trim()\n return COUNTRY_NAMES[key] ?? null\n}\n\n/**\n * A one-line address as parts, best effort, always flagged: commas split\n * it; a trailing country name becomes its two-letter code; `TX 78701`,\n * a bare postal code or a two-letter region is read from the end; the part\n * before that is the city; the rest is the street.\n */\nexport function parseAddressLine(raw: unknown): DerivedValue<AglynPostalAddress> {\n if (raw && typeof raw === 'object' && !Array.isArray(raw)) {\n return readValue(raw as AglynPostalAddress)\n }\n const text = cellText(raw).replace(/\\s*\\n\\s*/g, ', ')\n if (!text) return blankValue()\n const parts = text\n .split(',')\n .map((part) => part.trim())\n .filter(Boolean)\n const address: AglynPostalAddress = {}\n const last = parts[parts.length - 1]\n if (parts.length > 1 && last) {\n const country = countryOf(last)\n if (country) {\n address.country = country\n parts.pop()\n }\n }\n const tail = parts[parts.length - 1]\n if (parts.length > 1 && tail) {\n const regionPostal = /^([A-Za-z][A-Za-z .]{1,30}?)\\s+([A-Z0-9]{3,10}(?:[ -][A-Z0-9]{2,5})?)$/i.exec(tail)\n if (regionPostal && /\\d/.test(regionPostal[2] as string)) {\n address.state = (regionPostal[1] as string).trim()\n address.postalCode = (regionPostal[2] as string).toUpperCase()\n parts.pop()\n } else if (/^[A-Z0-9]{3,10}(?:[ -][A-Z0-9]{2,5})?$/i.test(tail) && /\\d/.test(tail)) {\n address.postalCode = tail.toUpperCase()\n parts.pop()\n } else if (/^[A-Za-z]{2}$/.test(tail) && parts.length > 2) {\n address.state = tail.toUpperCase()\n parts.pop()\n }\n }\n if (parts.length > 1) address.city = parts.pop()\n if (parts.length) address.line1 = parts.join(', ')\n return readValue(address, [\n derivation('addressSplit', text, address, 'Split one line into street, city, region, postal code and country', true),\n ])\n}\n\n/** How a list cell is split. */\nexport interface ListOptions {\n /** Default `,` `;` `|` and line breaks. */\n separators?: RegExp\n /** Lowercase every item (tags). */\n lowercase?: boolean\n /** The most items kept. */\n max?: number\n}\n\n/**\n * A list cell as its items: split on `,` `;` `|` or line breaks, trimmed,\n * duplicates (in any case) dropped keeping the first spelling. An array\n * (from a JSON file) is taken item by item.\n */\nexport function splitTransferList(raw: unknown, options: ListOptions = {}): DerivedValue<string[]> {\n const parts = Array.isArray(raw)\n ? raw.map((item) => cellText(item))\n : cellText(raw).split(options.separators ?? /[,;|\\n]/)\n const text = Array.isArray(raw) ? JSON.stringify(raw) : cellText(raw)\n const items: string[] = []\n const seen = new Set<string>()\n let duplicates = 0\n for (const part of parts) {\n const item = options.lowercase ? part.trim().toLowerCase() : part.trim()\n if (!item) continue\n const key = item.toLowerCase()\n if (seen.has(key)) {\n duplicates += 1\n continue\n }\n seen.add(key)\n items.push(item)\n }\n if (!items.length) return blankValue()\n const derivations: Derivation[] = []\n if (!Array.isArray(raw) && items.length + duplicates > 1) {\n derivations.push(derivation('listSplit', text, items, `Split into ${items.length} items`))\n }\n if (duplicates) derivations.push(derivation('listDeduplicated', text, items, `Dropped ${duplicates} repeated item(s)`))\n const max = options.max\n if (max !== undefined && items.length > max) {\n const kept = items.slice(0, max)\n derivations.push(derivation('truncated', text, kept, `Kept the first ${max} items`, true))\n return readValue(kept, derivations)\n }\n return readValue(items, derivations)\n}\n\n/*------------------------------------------\n * One cell, one row\n *-----------------------------------------*/\n\n/** Options for every parser, by kind. */\nexport interface DeriveOptions {\n date?: DateOptions\n dateTime?: DateTimeOptions\n number?: NumberOptions\n currency?: CurrencyOptions\n percent?: PercentOptions\n phone?: { defaultCountry?: string }\n list?: Omit<ListOptions, 'lowercase'>\n}\n\n/** A JSON cell parsed; an object or array from a JSON file passes through. */\nexport function deriveJson(raw: unknown): DerivedValue<unknown> {\n if (raw !== null && typeof raw === 'object') return readValue(raw)\n const text = cellText(raw)\n if (!text) return blankValue()\n try {\n return readValue(JSON.parse(text) as unknown)\n } catch {\n return unreadable('invalidJson', 'Not valid JSON.')\n }\n}\n\n/** A cell read as the field it was mapped to. */\nexport function deriveTransferCell(field: TransferField, raw: unknown, options: DeriveOptions = {}): DerivedValue<unknown> {\n switch (field.type) {\n case 'email':\n return deriveEmail(raw)\n case 'phone':\n return derivePhone(raw, options.phone)\n case 'url':\n return deriveUrl(raw)\n case 'number':\n return deriveNumber(raw, options.number)\n case 'integer':\n return deriveInteger(raw, options.number)\n case 'currency':\n return deriveCurrency(raw, options.currency)\n case 'percent':\n return derivePercent(raw, options.percent)\n case 'boolean':\n return deriveBoolean(raw)\n case 'date':\n return deriveDate(raw, options.date)\n case 'datetime':\n return deriveDateTime(raw, options.dateTime ?? options.date)\n case 'multiPicklist':\n return splitTransferList(raw, options.list)\n case 'tags':\n return splitTransferList(raw, { ...options.list, lowercase: true })\n case 'list':\n return splitTransferList(raw, options.list)\n case 'address':\n return parseAddressLine(raw)\n case 'json':\n return deriveJson(raw)\n case 'longText':\n return deriveText(raw, { maxLength: field.maxLength, multiline: true })\n case 'picklist':\n case 'lookup':\n case 'text':\n default:\n return deriveText(raw, { maxLength: field.maxLength })\n }\n}\n\n/** A derivation, located. */\nexport interface FieldDerivation extends Derivation {\n fieldId: string\n}\n\n/** A cell that could not be read, located. */\nexport interface FieldProblem extends DeriveProblem {\n fieldId: string\n /** The cell as the file had it. */\n raw: string\n}\n\n/** A row read field by field. */\nexport interface DerivedRow {\n /** Field id → value; `null` for a mapped blank cell; absent for an unmapped or dropped one. */\n values: Record<string, unknown>\n derivations: FieldDerivation[]\n problems: FieldProblem[]\n}\n\n/**\n * A mapped row read as its fields. `cells` is field id → raw cell (from\n * {@link mapTransferRow} or a JSON object); a field the catalog does not\n * know is ignored. `fieldOptions` overrides `options` for one field — the\n * date order a person chose for that column, say.\n */\nexport function deriveTransferRow(\n fields: ReadonlyMap<string, TransferField>,\n cells: Readonly<Record<string, unknown>>,\n options: DeriveOptions = {},\n fieldOptions: Readonly<Record<string, DeriveOptions>> = {},\n): DerivedRow {\n const row: DerivedRow = { values: {}, derivations: [], problems: [] }\n for (const [fieldId, raw] of Object.entries(cells)) {\n const field = fields.get(fieldId)\n if (!field) continue\n const own = fieldOptions[fieldId]\n const result = deriveTransferCell(field, raw, own ? { ...options, ...own } : options)\n if (!result.ok) {\n row.problems.push({ fieldId, raw: cellText(raw), ...(result.problem as DeriveProblem) })\n continue\n }\n row.values[fieldId] = result.value\n for (const entry of result.derivations) row.derivations.push({ fieldId, ...entry })\n }\n return row\n}\n\n/**\n * One line's cells under a column → field mapping, as field id → raw cell.\n * Every mapped column is present, blank or not, so a blank cell can mean\n * \"clear\" when the person chose that.\n */\nexport function mapTransferRow(\n cells: readonly unknown[],\n mapping: Readonly<Record<number, string | null | undefined>>,\n): Record<string, unknown> {\n const mapped: Record<string, unknown> = {}\n for (const [indexText, fieldId] of Object.entries(mapping)) {\n if (!fieldId) continue\n mapped[fieldId] = cells[Number(indexText)] ?? ''\n }\n return mapped\n}\n"],"names":["normalizePhone","blankValue","value","blank","ok","derivations","readValue","unreadable","code","message","problem","derivation","kind","from","to","note","flagged","JSON","stringify","cellText","raw","undefined","trim","String","Date","Number","isNaN","getTime","toISOString","deriveText","options","text","multiline","replace","maxLength","length","cut","slice","TRUE_WORDS","FALSE_WORDS","parseImportFlag","toLowerCase","includes","deriveBoolean","flag","plain","EMAIL","deriveEmail","address","angled","exec","push","test","stripped","split","lower","EXTENSION","derivePhone","number","extension","without","normalized","defaultCountry","deriveUrl","candidate","url","URL","protocol","rest","indexOf","host","MONTHS","monthOf","word","full","key","at","startsWith","pad","n","width","padStart","isoDate","year","month","day","isInteger","date","UTC","setUTCFullYear","getUTCMonth","getUTCDate","SERIAL_EPOCH_MS","DAY_MS","serialToDate","serial","Math","round","fullYear","pivot","deriveDate","result","parseDateText","twoDigitYearPivot","iso","yearFirst","numeric","a","b","yearDerivations","order","ambiguous","preferredOrder","words","named","namedMonthFirst","NaN","excelSerials","isFinite","getUTCFullYear","ZONED_ISO","zoneLabel","offsetMinutes","sign","abs","floor","offsetOf","zone","match","minutes","deriveDateTime","fail","offset","ms","parse","timed","datePart","hours","seconds","zoneOffset","meridiem","y","m","d","map","local","GROUPED_COMMA","GROUPED_DOT","PLAIN_NUMBER","parseLocaleNumber","body","negative","paren","decimal","hasDot","hasComma","commaLast","lastIndexOf","point","group","whole","fraction","extra","join","dots","deriveNumber","deriveInteger","CURRENCY_MINOR_UNITS","BHD","CLP","ISK","JOD","JPY","KRW","KWD","OMR","TND","UGX","VND","XAF","XOF","currencyMinorUnits","currency","toUpperCase","CURRENCY_SYMBOLS","DOLLAR_CURRENCIES","deriveCurrency","fallback","defaultCurrency","coded","codeFirst","symbol","units","scaled","amountMinor","derivePercent","signed","toPrecision","scale","HONORIFICS","SUFFIXES","PARTICLES","bare","splitFullName","done","first","last","rule","comma","filter","Boolean","suffixes","unshift","pop","particleAt","findIndex","index","tail","COUNTRY_NAMES","countryOf","part","parseAddressLine","Array","isArray","parts","country","regionPostal","state","postalCode","city","line1","splitTransferList","item","separators","items","seen","Set","duplicates","lowercase","has","add","max","kept","deriveJson","deriveTransferCell","field","type","phone","percent","dateTime","list","deriveTransferRow","fields","cells","fieldOptions","row","values","problems","fieldId","Object","entries","get","own","entry","mapTransferRow","mapping","mapped","indexText"],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
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 { TransferFieldType, TransferFormat } from './resource';
|
|
18
|
+
import type { TransferPrefs } from './transfer-api';
|
|
19
|
+
/** A value as one CSV cell's text. */
|
|
20
|
+
export declare function transferExportCellText(value: unknown): string;
|
|
21
|
+
/** One row's chosen fields, in order, keyed by field id. */
|
|
22
|
+
export declare function transferExportRecord(row: Readonly<Record<string, unknown>>, fieldIds: readonly string[]): Record<string, unknown>;
|
|
23
|
+
/** The CSV header line: each field's label (its id when it has none). */
|
|
24
|
+
export declare function transferExportCsvHeader(fieldIds: readonly string[], labelOf: (fieldId: string) => string): string;
|
|
25
|
+
/**
|
|
26
|
+
* One value as a CSV cell: its text, guarded against running as a formula
|
|
27
|
+
* unless it is a genuine number — a number value, or a number-typed field
|
|
28
|
+
* whose text reads as one — so `-5` stays `-5` and `-5 off` becomes `'-5 off`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function transferExportCsvCell(value: unknown, type?: TransferFieldType): string;
|
|
31
|
+
/** One row as a CSV line; `typeOf` names each field's type so numbers stay numbers. */
|
|
32
|
+
export declare function transferExportCsvLine(row: Readonly<Record<string, unknown>>, fieldIds: readonly string[], typeOf?: (fieldId: string) => TransferFieldType | undefined): string;
|
|
33
|
+
/** The file's name: the resource key and the day, `people-2026-10-05.csv`. */
|
|
34
|
+
export declare function transferExportFileName(resource: string, format: TransferFormat, at: Date): string;
|
|
35
|
+
/**
|
|
36
|
+
* The rows a downloaded export holds, to check against the count the route
|
|
37
|
+
* promised. `null` for a JSON body that does not parse — it did not arrive
|
|
38
|
+
* whole.
|
|
39
|
+
*/
|
|
40
|
+
export declare function countTransferExportRows(text: string, format: TransferFormat): number | null;
|
|
41
|
+
/**
|
|
42
|
+
* A stored or sent `TransferPrefs`, as far as it can be trusted: whatever
|
|
43
|
+
* is not the right shape is dropped, so a hand-edited document never breaks
|
|
44
|
+
* the dialog that reads it.
|
|
45
|
+
*/
|
|
46
|
+
export declare function normalizeTransferPrefs(raw: unknown): TransferPrefs;
|
|
@@ -0,0 +1,146 @@
|
|
|
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
|
+
* THE EXPORT FILE — rows of chosen fields written as CSV, JSON or NDJSON.
|
|
18
|
+
*
|
|
19
|
+
* The export route writes it a page at a time and the console's client
|
|
20
|
+
* counts what arrived against the row count the route promised, so both
|
|
21
|
+
* sides use these functions and cannot disagree about what a row is.
|
|
22
|
+
*
|
|
23
|
+
* - CSV: the header is each field's label, so the file maps straight back
|
|
24
|
+
* in on import; a list is written as its items joined by `; ` (the list
|
|
25
|
+
* reader splits on it), an object as JSON, a blank as an empty cell. A
|
|
26
|
+
* cell that a spreadsheet would run as a formula gets a leading `'`
|
|
27
|
+
* (AGL-3548) — a number in a number field excepted — and the import's
|
|
28
|
+
* reader takes it back off.
|
|
29
|
+
* - JSON: one array of objects keyed by field id; NDJSON: one object per
|
|
30
|
+
* line. Values are written as they are.
|
|
31
|
+
*=========================================*/ import { countCsvDataRows, escapeCsvCell } from "../app-utils/csv.js";
|
|
32
|
+
/** A value as one CSV cell's text. */ export function transferExportCellText(value) {
|
|
33
|
+
if (value === null || value === undefined) return '';
|
|
34
|
+
if (typeof value === 'string') return value;
|
|
35
|
+
if (typeof value === 'number' || typeof value === 'boolean') return String(value);
|
|
36
|
+
if (Array.isArray(value) && value.every((item)=>item === null || [
|
|
37
|
+
'string',
|
|
38
|
+
'number',
|
|
39
|
+
'boolean'
|
|
40
|
+
].includes(typeof item))) {
|
|
41
|
+
return value.filter((item)=>item !== null && item !== '').join('; ');
|
|
42
|
+
}
|
|
43
|
+
return JSON.stringify(value);
|
|
44
|
+
}
|
|
45
|
+
/** One row's chosen fields, in order, keyed by field id. */ export function transferExportRecord(row, fieldIds) {
|
|
46
|
+
return Object.fromEntries(fieldIds.map((fieldId)=>{
|
|
47
|
+
var _row_fieldId;
|
|
48
|
+
return [
|
|
49
|
+
fieldId,
|
|
50
|
+
(_row_fieldId = row[fieldId]) != null ? _row_fieldId : null
|
|
51
|
+
];
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
/** The CSV header line: each field's label (its id when it has none). */ export function transferExportCsvHeader(fieldIds, labelOf) {
|
|
55
|
+
return fieldIds.map((fieldId)=>escapeCsvCell(labelOf(fieldId) || fieldId)).join(',');
|
|
56
|
+
}
|
|
57
|
+
/** Field types whose value is a number, written unguarded when it reads as one. */ const NUMERIC_FIELD_TYPES = new Set([
|
|
58
|
+
'number',
|
|
59
|
+
'integer',
|
|
60
|
+
'currency',
|
|
61
|
+
'percent'
|
|
62
|
+
]);
|
|
63
|
+
/**
|
|
64
|
+
* One value as a CSV cell: its text, guarded against running as a formula
|
|
65
|
+
* unless it is a genuine number — a number value, or a number-typed field
|
|
66
|
+
* whose text reads as one — so `-5` stays `-5` and `-5 off` becomes `'-5 off`.
|
|
67
|
+
*/ export function transferExportCsvCell(value, type) {
|
|
68
|
+
const numeric = typeof value === 'number' || type !== undefined && NUMERIC_FIELD_TYPES.has(type);
|
|
69
|
+
return escapeCsvCell(transferExportCellText(value), {
|
|
70
|
+
numeric
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/** One row as a CSV line; `typeOf` names each field's type so numbers stay numbers. */ export function transferExportCsvLine(row, fieldIds, typeOf) {
|
|
74
|
+
return fieldIds.map((fieldId)=>transferExportCsvCell(row[fieldId], typeOf == null ? void 0 : typeOf(fieldId))).join(',');
|
|
75
|
+
}
|
|
76
|
+
const EXTENSIONS = {
|
|
77
|
+
csv: 'csv',
|
|
78
|
+
json: 'json',
|
|
79
|
+
ndjson: 'ndjson'
|
|
80
|
+
};
|
|
81
|
+
/** The file's name: the resource key and the day, `people-2026-10-05.csv`. */ export function transferExportFileName(resource, format, at) {
|
|
82
|
+
const base = resource.replace(/[^a-z0-9-]+/gi, '-').replace(/^-+|-+$/g, '') || 'export';
|
|
83
|
+
return `${base}-${at.toISOString().slice(0, 10)}.${EXTENSIONS[format]}`;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The rows a downloaded export holds, to check against the count the route
|
|
87
|
+
* promised. `null` for a JSON body that does not parse — it did not arrive
|
|
88
|
+
* whole.
|
|
89
|
+
*/ export function countTransferExportRows(text, format) {
|
|
90
|
+
if (format === 'csv') return countCsvDataRows(text.charCodeAt(0) === 0xfeff ? text.slice(1) : text);
|
|
91
|
+
if (format === 'ndjson') return text.split(/\r?\n/).filter((line)=>line.trim()).length;
|
|
92
|
+
try {
|
|
93
|
+
const parsed = JSON.parse(text);
|
|
94
|
+
return Array.isArray(parsed) ? parsed.length : null;
|
|
95
|
+
} catch (unused) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const FORMATS = [
|
|
100
|
+
'csv',
|
|
101
|
+
'json',
|
|
102
|
+
'ndjson'
|
|
103
|
+
];
|
|
104
|
+
const SCOPES = [
|
|
105
|
+
'selection',
|
|
106
|
+
'filter',
|
|
107
|
+
'all'
|
|
108
|
+
];
|
|
109
|
+
const PRESETS_MAX = 50;
|
|
110
|
+
const FIELDS_MAX = 500;
|
|
111
|
+
const stringList = (value, max)=>Array.isArray(value) ? value.filter((entry)=>typeof entry === 'string' && entry.length > 0).slice(0, max) : [];
|
|
112
|
+
/**
|
|
113
|
+
* A stored or sent `TransferPrefs`, as far as it can be trusted: whatever
|
|
114
|
+
* is not the right shape is dropped, so a hand-edited document never breaks
|
|
115
|
+
* the dialog that reads it.
|
|
116
|
+
*/ export function normalizeTransferPrefs(raw) {
|
|
117
|
+
const source = raw && typeof raw === 'object' ? raw : {};
|
|
118
|
+
const presets = [];
|
|
119
|
+
for (const entry of Array.isArray(source['presets']) ? source['presets'] : []){
|
|
120
|
+
const preset = entry && typeof entry === 'object' ? entry : {};
|
|
121
|
+
if (typeof preset['id'] !== 'string' || !preset['id'] || typeof preset['label'] !== 'string') continue;
|
|
122
|
+
presets.push({
|
|
123
|
+
id: preset['id'],
|
|
124
|
+
label: preset['label'].slice(0, 120),
|
|
125
|
+
fieldIds: stringList(preset['fieldIds'], FIELDS_MAX)
|
|
126
|
+
});
|
|
127
|
+
if (presets.length >= PRESETS_MAX) break;
|
|
128
|
+
}
|
|
129
|
+
const prefs = {
|
|
130
|
+
presets
|
|
131
|
+
};
|
|
132
|
+
const last = source['export'] && typeof source['export'] === 'object' ? source['export'] : null;
|
|
133
|
+
if (last && FORMATS.includes(last['format'])) {
|
|
134
|
+
const exported = {
|
|
135
|
+
presetId: typeof last['presetId'] === 'string' ? last['presetId'] : null,
|
|
136
|
+
fieldIds: stringList(last['fieldIds'], FIELDS_MAX),
|
|
137
|
+
format: last['format'],
|
|
138
|
+
bom: last['bom'] === true,
|
|
139
|
+
scope: SCOPES.includes(last['scope']) ? last['scope'] : 'all'
|
|
140
|
+
};
|
|
141
|
+
prefs.export = exported;
|
|
142
|
+
}
|
|
143
|
+
return prefs;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
//# sourceMappingURL=export-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/data-transfer/export-file.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 * THE EXPORT FILE — rows of chosen fields written as CSV, JSON or NDJSON.\n *\n * The export route writes it a page at a time and the console's client\n * counts what arrived against the row count the route promised, so both\n * sides use these functions and cannot disagree about what a row is.\n *\n * - CSV: the header is each field's label, so the file maps straight back\n * in on import; a list is written as its items joined by `; ` (the list\n * reader splits on it), an object as JSON, a blank as an empty cell. A\n * cell that a spreadsheet would run as a formula gets a leading `'`\n * (AGL-3548) — a number in a number field excepted — and the import's\n * reader takes it back off.\n * - JSON: one array of objects keyed by field id; NDJSON: one object per\n * line. Values are written as they are.\n *=========================================*/\n\nimport { countCsvDataRows, escapeCsvCell } from '../app-utils/csv'\nimport type { TransferFieldType, TransferFormat } from './resource'\nimport type { TransferExportPrefs, TransferExportScopeKind, TransferPrefs } from './transfer-api'\n\n/** A value as one CSV cell's text. */\nexport function transferExportCellText(value: unknown): string {\n if (value === null || value === undefined) return ''\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'boolean') return String(value)\n if (Array.isArray(value) && value.every((item) => item === null || ['string', 'number', 'boolean'].includes(typeof item))) {\n return value.filter((item) => item !== null && item !== '').join('; ')\n }\n return JSON.stringify(value)\n}\n\n/** One row's chosen fields, in order, keyed by field id. */\nexport function transferExportRecord(\n row: Readonly<Record<string, unknown>>,\n fieldIds: readonly string[],\n): Record<string, unknown> {\n return Object.fromEntries(fieldIds.map((fieldId) => [fieldId, row[fieldId] ?? null]))\n}\n\n/** The CSV header line: each field's label (its id when it has none). */\nexport function transferExportCsvHeader(fieldIds: readonly string[], labelOf: (fieldId: string) => string): string {\n return fieldIds.map((fieldId) => escapeCsvCell(labelOf(fieldId) || fieldId)).join(',')\n}\n\n/** Field types whose value is a number, written unguarded when it reads as one. */\nconst NUMERIC_FIELD_TYPES: ReadonlySet<TransferFieldType> = new Set(['number', 'integer', 'currency', 'percent'])\n\n/**\n * One value as a CSV cell: its text, guarded against running as a formula\n * unless it is a genuine number — a number value, or a number-typed field\n * whose text reads as one — so `-5` stays `-5` and `-5 off` becomes `'-5 off`.\n */\nexport function transferExportCsvCell(value: unknown, type?: TransferFieldType): string {\n const numeric = typeof value === 'number' || (type !== undefined && NUMERIC_FIELD_TYPES.has(type))\n return escapeCsvCell(transferExportCellText(value), { numeric })\n}\n\n/** One row as a CSV line; `typeOf` names each field's type so numbers stay numbers. */\nexport function transferExportCsvLine(\n row: Readonly<Record<string, unknown>>,\n fieldIds: readonly string[],\n typeOf?: (fieldId: string) => TransferFieldType | undefined,\n): string {\n return fieldIds.map((fieldId) => transferExportCsvCell(row[fieldId], typeOf?.(fieldId))).join(',')\n}\n\nconst EXTENSIONS: Readonly<Record<TransferFormat, string>> = { csv: 'csv', json: 'json', ndjson: 'ndjson' }\n\n/** The file's name: the resource key and the day, `people-2026-10-05.csv`. */\nexport function transferExportFileName(resource: string, format: TransferFormat, at: Date): string {\n const base = resource.replace(/[^a-z0-9-]+/gi, '-').replace(/^-+|-+$/g, '') || 'export'\n return `${base}-${at.toISOString().slice(0, 10)}.${EXTENSIONS[format]}`\n}\n\n/**\n * The rows a downloaded export holds, to check against the count the route\n * promised. `null` for a JSON body that does not parse — it did not arrive\n * whole.\n */\nexport function countTransferExportRows(text: string, format: TransferFormat): number | null {\n if (format === 'csv') return countCsvDataRows(text.charCodeAt(0) === 0xfeff ? text.slice(1) : text)\n if (format === 'ndjson') return text.split(/\\r?\\n/).filter((line) => line.trim()).length\n try {\n const parsed = JSON.parse(text) as unknown\n return Array.isArray(parsed) ? parsed.length : null\n } catch {\n return null\n }\n}\n\nconst FORMATS: readonly TransferFormat[] = ['csv', 'json', 'ndjson']\nconst SCOPES: readonly TransferExportScopeKind[] = ['selection', 'filter', 'all']\nconst PRESETS_MAX = 50\nconst FIELDS_MAX = 500\n\nconst stringList = (value: unknown, max: number): string[] =>\n Array.isArray(value) ? value.filter((entry): entry is string => typeof entry === 'string' && entry.length > 0).slice(0, max) : []\n\n/**\n * A stored or sent `TransferPrefs`, as far as it can be trusted: whatever\n * is not the right shape is dropped, so a hand-edited document never breaks\n * the dialog that reads it.\n */\nexport function normalizeTransferPrefs(raw: unknown): TransferPrefs {\n const source = (raw && typeof raw === 'object' ? raw : {}) as Record<string, unknown>\n const presets: TransferPrefs['presets'] = []\n for (const entry of Array.isArray(source['presets']) ? source['presets'] : []) {\n const preset = (entry && typeof entry === 'object' ? entry : {}) as Record<string, unknown>\n if (typeof preset['id'] !== 'string' || !preset['id'] || typeof preset['label'] !== 'string') continue\n presets.push({ id: preset['id'], label: preset['label'].slice(0, 120), fieldIds: stringList(preset['fieldIds'], FIELDS_MAX) })\n if (presets.length >= PRESETS_MAX) break\n }\n const prefs: TransferPrefs = { presets }\n const last = (source['export'] && typeof source['export'] === 'object' ? source['export'] : null) as Record<string, unknown> | null\n if (last && FORMATS.includes(last['format'] as TransferFormat)) {\n const exported: TransferExportPrefs = {\n presetId: typeof last['presetId'] === 'string' ? last['presetId'] : null,\n fieldIds: stringList(last['fieldIds'], FIELDS_MAX),\n format: last['format'] as TransferFormat,\n bom: last['bom'] === true,\n scope: SCOPES.includes(last['scope'] as TransferExportScopeKind) ? (last['scope'] as TransferExportScopeKind) : 'all',\n }\n prefs.export = exported\n }\n return prefs\n}\n"],"names":["countCsvDataRows","escapeCsvCell","transferExportCellText","value","undefined","String","Array","isArray","every","item","includes","filter","join","JSON","stringify","transferExportRecord","row","fieldIds","Object","fromEntries","map","fieldId","transferExportCsvHeader","labelOf","NUMERIC_FIELD_TYPES","Set","transferExportCsvCell","type","numeric","has","transferExportCsvLine","typeOf","EXTENSIONS","csv","json","ndjson","transferExportFileName","resource","format","at","base","replace","toISOString","slice","countTransferExportRows","text","charCodeAt","split","line","trim","length","parsed","parse","FORMATS","SCOPES","PRESETS_MAX","FIELDS_MAX","stringList","max","entry","normalizeTransferPrefs","raw","source","presets","preset","push","id","label","prefs","last","exported","presetId","bom","scope","export"],"mappings":"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"}
|
|
@@ -0,0 +1,134 @@
|
|
|
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 { TransferField, TransferFieldType } from './resource';
|
|
18
|
+
/** A heading fields are listed under. */
|
|
19
|
+
export interface TransferFieldGroup {
|
|
20
|
+
id: string;
|
|
21
|
+
label: string;
|
|
22
|
+
}
|
|
23
|
+
/** The group a field with no group, or an unknown one, is listed under. */
|
|
24
|
+
export declare const TRANSFER_OTHER_GROUP: TransferFieldGroup;
|
|
25
|
+
/** The group custom fields are listed under unless they name their own. */
|
|
26
|
+
export declare const TRANSFER_CUSTOM_GROUP: TransferFieldGroup;
|
|
27
|
+
/** The group system fields are listed under unless they name their own. */
|
|
28
|
+
export declare const TRANSFER_SYSTEM_GROUP: TransferFieldGroup;
|
|
29
|
+
/** A resource's fields, grouped and ordered. */
|
|
30
|
+
export interface TransferFieldCatalog {
|
|
31
|
+
/** Every field, in picker order: group by group, declaration order within. */
|
|
32
|
+
fields: TransferField[];
|
|
33
|
+
byId: ReadonlyMap<string, TransferField>;
|
|
34
|
+
/** The groups that hold at least one field, in order. */
|
|
35
|
+
groups: TransferFieldGroup[];
|
|
36
|
+
}
|
|
37
|
+
/** A custom field as the organization defined it. */
|
|
38
|
+
export interface TransferCustomFieldDefinition {
|
|
39
|
+
key: string;
|
|
40
|
+
label: string;
|
|
41
|
+
type?: TransferFieldType;
|
|
42
|
+
picklistId?: string;
|
|
43
|
+
required?: boolean;
|
|
44
|
+
group?: string;
|
|
45
|
+
}
|
|
46
|
+
/** A custom field definition as a catalog field, with id `custom:<key>`. */
|
|
47
|
+
export declare function customTransferField(definition: TransferCustomFieldDefinition): TransferField;
|
|
48
|
+
/** What a catalog is built from. */
|
|
49
|
+
export interface TransferCatalogInput {
|
|
50
|
+
/** The resource's own fields. */
|
|
51
|
+
standard: readonly TransferField[];
|
|
52
|
+
/** The organization's custom fields. */
|
|
53
|
+
custom?: readonly TransferCustomFieldDefinition[];
|
|
54
|
+
/** Computed fields, exported and never written. */
|
|
55
|
+
derived?: readonly TransferField[];
|
|
56
|
+
/** Platform-written fields; the Aglyn id is added when absent. */
|
|
57
|
+
system?: readonly TransferField[];
|
|
58
|
+
/** The groups, in order. Groups a field names but this list lacks are listed after these. */
|
|
59
|
+
groups?: readonly TransferFieldGroup[];
|
|
60
|
+
}
|
|
61
|
+
/** The Aglyn id field every catalog carries, labeled with the configured brand. */
|
|
62
|
+
export declare function transferIdField(label?: string): TransferField;
|
|
63
|
+
/**
|
|
64
|
+
* The catalog for a resource.
|
|
65
|
+
*
|
|
66
|
+
* Standard fields come first in their groups, then derived ones, then custom
|
|
67
|
+
* ones, then system ones; within a group the declaration order holds. A
|
|
68
|
+
* field id declared twice keeps its first declaration — a custom field can
|
|
69
|
+
* never shadow a standard one because its id carries the `custom:` prefix.
|
|
70
|
+
*/
|
|
71
|
+
export declare function buildTransferFieldCatalog(input: TransferCatalogInput): TransferFieldCatalog;
|
|
72
|
+
/** The fields under each group, in catalog order; `fieldIds` narrows and keeps catalog order. */
|
|
73
|
+
export declare function groupTransferFields(catalog: TransferFieldCatalog, fieldIds?: readonly string[]): {
|
|
74
|
+
group: TransferFieldGroup;
|
|
75
|
+
fields: TransferField[];
|
|
76
|
+
}[];
|
|
77
|
+
/** The fields whose label, id or an alias contains every word of `query`. */
|
|
78
|
+
export declare function searchTransferFields(catalog: TransferFieldCatalog, query: string): TransferField[];
|
|
79
|
+
/** The built-in presets. */
|
|
80
|
+
export type TransferPresetId = 'everything' | 'reimportable' | 'minimal';
|
|
81
|
+
export declare const TRANSFER_PRESET_IDS: readonly TransferPresetId[];
|
|
82
|
+
/** A preset a person saved: a name and the fields in their chosen order. */
|
|
83
|
+
export interface TransferSavedPreset {
|
|
84
|
+
id: string;
|
|
85
|
+
label: string;
|
|
86
|
+
fieldIds: readonly string[];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* A preset the resource itself offers, listed after the built-in ones: its
|
|
90
|
+
* fields in order and, for a layout another product imports, that
|
|
91
|
+
* product's column name for each field. Its id must not be a built-in
|
|
92
|
+
* preset's.
|
|
93
|
+
*/
|
|
94
|
+
export interface TransferResourcePreset extends TransferSavedPreset {
|
|
95
|
+
/** One sentence beside the preset in the picker. */
|
|
96
|
+
description?: string;
|
|
97
|
+
/** Field id → the CSV column name written instead of the field's label. */
|
|
98
|
+
headers?: Readonly<Record<string, string>>;
|
|
99
|
+
}
|
|
100
|
+
/** The longest column name a preset or an export request may give a field. */
|
|
101
|
+
export declare const TRANSFER_HEADER_MAX = 120;
|
|
102
|
+
/**
|
|
103
|
+
* The column names an export may write, from what a request or a preset
|
|
104
|
+
* carries: only for the chosen fields, trimmed, non-empty, at most
|
|
105
|
+
* {@link TRANSFER_HEADER_MAX} characters, and never two fields under one
|
|
106
|
+
* name — a file whose columns repeat cannot be read back.
|
|
107
|
+
*/
|
|
108
|
+
export declare function transferExportHeaders(fieldIds: readonly string[], headers: unknown): Record<string, string>;
|
|
109
|
+
/** What a resource says about its own presets. */
|
|
110
|
+
export interface TransferPresetHints {
|
|
111
|
+
/** The fields a re-import matches on (the id is always included). */
|
|
112
|
+
matchKeyFieldIds?: readonly string[];
|
|
113
|
+
/** Fields the minimal preset adds beyond the id, match keys and required ones. */
|
|
114
|
+
minimalFieldIds?: readonly string[];
|
|
115
|
+
}
|
|
116
|
+
/** A resolved selection: the ids to export, in order, and the ids that no longer exist. */
|
|
117
|
+
export interface TransferFieldSelection {
|
|
118
|
+
fieldIds: string[];
|
|
119
|
+
unknown: string[];
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* A list of field ids against the catalog: unknown ids dropped (and
|
|
123
|
+
* reported), duplicates dropped, the given order kept, and every id in
|
|
124
|
+
* `ensure` present — added in catalog order at the front when missing.
|
|
125
|
+
*/
|
|
126
|
+
export declare function resolveTransferFieldSelection(catalog: TransferFieldCatalog, selected: readonly string[], ensure?: readonly string[]): TransferFieldSelection;
|
|
127
|
+
/**
|
|
128
|
+
* The fields a preset exports, in order. A built-in preset is computed from
|
|
129
|
+
* the catalog; a saved one is resolved against it. The re-importable and
|
|
130
|
+
* minimal presets lead with the id and the match keys.
|
|
131
|
+
*/
|
|
132
|
+
export declare function resolveTransferPreset(catalog: TransferFieldCatalog, preset: TransferPresetId | TransferSavedPreset, hints?: TransferPresetHints): TransferFieldSelection;
|
|
133
|
+
/** `ids` with the entry at `from` moved to `to` — the picker's drag to reorder. */
|
|
134
|
+
export declare function moveTransferField(ids: readonly string[], from: number, to: number): string[];
|