@aglyn/aglyn 1.0.0-beta.269 → 1.0.0-beta.271
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 +11 -11
- package/src/lib/app-utils/account-preferences.d.ts +248 -0
- package/src/lib/app-utils/account-preferences.js +434 -0
- package/src/lib/app-utils/account-preferences.js.map +1 -0
- package/src/lib/app-utils/activity-labels.js +2 -0
- package/src/lib/app-utils/activity-labels.js.map +1 -1
- package/src/lib/app-utils/analytics-events.d.ts +13 -0
- package/src/lib/app-utils/analytics-events.js +2 -0
- package/src/lib/app-utils/analytics-events.js.map +1 -1
- package/src/lib/app-utils/append-only-history.d.ts +94 -0
- package/src/lib/app-utils/append-only-history.js +73 -0
- package/src/lib/app-utils/append-only-history.js.map +1 -0
- package/src/lib/app-utils/bundle-intent.d.ts +186 -0
- package/src/lib/app-utils/bundle-intent.js +386 -0
- package/src/lib/app-utils/bundle-intent.js.map +1 -0
- package/src/lib/app-utils/client-build.d.ts +204 -0
- package/src/lib/app-utils/client-build.js +237 -0
- package/src/lib/app-utils/client-build.js.map +1 -0
- package/src/lib/app-utils/console-routes.d.ts +4 -0
- package/src/lib/app-utils/console-routes.js +2 -0
- package/src/lib/app-utils/console-routes.js.map +1 -1
- package/src/lib/app-utils/country-options.d.ts +27 -0
- package/src/lib/app-utils/country-options.js +96 -0
- package/src/lib/app-utils/country-options.js.map +1 -0
- package/src/lib/app-utils/docs-help-sections.generated.js +7 -5
- package/src/lib/app-utils/docs-help-sections.generated.js.map +1 -1
- package/src/lib/app-utils/docs-help.generated.d.ts +11 -5
- package/src/lib/app-utils/docs-help.generated.js +22 -2
- package/src/lib/app-utils/docs-help.generated.js.map +1 -1
- package/src/lib/app-utils/docs-index.generated.js +116 -39
- package/src/lib/app-utils/docs-index.generated.js.map +1 -1
- package/src/lib/app-utils/margin-utilization.js +6 -4
- package/src/lib/app-utils/margin-utilization.js.map +1 -1
- package/src/lib/app-utils/media-filter.d.ts +26 -0
- package/src/lib/app-utils/media-filter.js +32 -0
- package/src/lib/app-utils/media-filter.js.map +1 -1
- package/src/lib/app-utils/mobile-push.d.ts +8 -0
- package/src/lib/app-utils/mobile-push.js +4 -1
- package/src/lib/app-utils/mobile-push.js.map +1 -1
- package/src/lib/app-utils/native-app-association.d.ts +3 -2
- package/src/lib/app-utils/native-app-association.js +4 -2
- package/src/lib/app-utils/native-app-association.js.map +1 -1
- package/src/lib/app-utils/native-nav.d.ts +265 -0
- package/src/lib/app-utils/native-nav.js +741 -0
- package/src/lib/app-utils/native-nav.js.map +1 -0
- package/src/lib/app-utils/native-themes.d.ts +249 -0
- package/src/lib/app-utils/native-themes.js +732 -0
- package/src/lib/app-utils/native-themes.js.map +1 -0
- package/src/lib/app-utils/notifications.d.ts +1 -1
- package/src/lib/app-utils/notifications.js +10 -0
- package/src/lib/app-utils/notifications.js.map +1 -1
- package/src/lib/app-utils/onboarding-deep-link.d.ts +36 -2
- package/src/lib/app-utils/onboarding-deep-link.js +48 -5
- package/src/lib/app-utils/onboarding-deep-link.js.map +1 -1
- package/src/lib/app-utils/one-box-search.d.ts +108 -0
- package/src/lib/app-utils/one-box-search.js +167 -0
- package/src/lib/app-utils/one-box-search.js.map +1 -0
- package/src/lib/app-utils/operator-alerts.js +21 -0
- package/src/lib/app-utils/operator-alerts.js.map +1 -1
- package/src/lib/app-utils/org-permissions.js +10 -61
- package/src/lib/app-utils/org-permissions.js.map +1 -1
- package/src/lib/app-utils/org-role-grants.d.ts +95 -0
- package/src/lib/app-utils/org-role-grants.js +193 -0
- package/src/lib/app-utils/org-role-grants.js.map +1 -0
- package/src/lib/app-utils/owner-approval-record.d.ts +102 -0
- package/src/lib/app-utils/owner-approval-record.js +148 -0
- package/src/lib/app-utils/owner-approval-record.js.map +1 -0
- package/src/lib/app-utils/plan-entitlements.d.ts +224 -68
- package/src/lib/app-utils/plan-entitlements.js +278 -61
- package/src/lib/app-utils/plan-entitlements.js.map +1 -1
- package/src/lib/app-utils/release-flags.d.ts +1 -1
- package/src/lib/app-utils/release-flags.js +10 -0
- package/src/lib/app-utils/release-flags.js.map +1 -1
- package/src/lib/app-utils/server.d.ts +4 -0
- package/src/lib/app-utils/server.js +7 -0
- package/src/lib/app-utils/server.js.map +1 -1
- package/src/lib/app-utils/site-care-project.d.ts +227 -0
- package/src/lib/app-utils/site-care-project.js +423 -0
- package/src/lib/app-utils/site-care-project.js.map +1 -0
- package/src/lib/app-utils/site-care.d.ts +268 -0
- package/src/lib/app-utils/site-care.js +283 -0
- package/src/lib/app-utils/site-care.js.map +1 -0
- package/src/lib/app-utils/tenant-dns-targets.d.ts +62 -0
- package/src/lib/app-utils/tenant-dns-targets.js +80 -0
- package/src/lib/app-utils/tenant-dns-targets.js.map +1 -0
- package/src/lib/app-utils/upgrade-proposal.d.ts +29 -4
- package/src/lib/app-utils/upgrade-proposal.js +60 -9
- package/src/lib/app-utils/upgrade-proposal.js.map +1 -1
- package/src/lib/foundation/definitions/org-billing.types.d.ts +54 -10
- package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
- package/src/lib/foundation/definitions/organization.types.d.ts +3 -1
- package/src/lib/foundation/definitions/organization.types.js.map +1 -1
- package/src/lib/foundation/definitions/platform.types.d.ts +9 -0
- 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 +86 -0
- package/src/lib/plugin-manager/feature-plugins.js +20 -0
- package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
- package/src/lib/plugin-manager/first-party-plugins.generated.js +22 -1
- package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
- package/src/lib/plugin-manager/plugin-ai-capabilities.d.ts +19 -0
- package/src/lib/plugin-manager/plugin-ai-capabilities.js.map +1 -1
- package/src/lib/plugin-manager/plugin-domain-events.d.ts +4 -3
- package/src/lib/plugin-manager/plugin-domain-events.js.map +1 -1
- package/src/lib/plugin-manager/plugin-domain-search.d.ts +81 -0
- package/src/lib/plugin-manager/plugin-domain-search.js +63 -0
- package/src/lib/plugin-manager/plugin-domain-search.js.map +1 -0
- package/src/lib/plugin-manager/plugin-entitlements.d.ts +23 -5
- package/src/lib/plugin-manager/plugin-entitlements.js +10 -0
- package/src/lib/plugin-manager/plugin-entitlements.js.map +1 -1
- package/src/lib/plugin-manager/plugin-media-ingest.d.ts +25 -0
- package/src/lib/plugin-manager/plugin-media-ingest.js.map +1 -1
- package/src/lib/plugin-manager/plugin-search-sources.d.ts +85 -0
- package/src/lib/plugin-manager/plugin-search-sources.js +91 -0
- package/src/lib/plugin-manager/plugin-search-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-services.js +6 -0
- package/src/lib/plugin-manager/plugin-services.js.map +1 -1
- package/src/lib/plugin-manager/purchase-gate-preclearance.d.ts +61 -0
- package/src/lib/plugin-manager/purchase-gate-preclearance.js +102 -0
- package/src/lib/plugin-manager/purchase-gate-preclearance.js.map +1 -0
|
@@ -259,6 +259,10 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
259
259
|
siteExport: false,
|
|
260
260
|
multilingual: false,
|
|
261
261
|
eventCalendar: false,
|
|
262
|
+
// Site Care (AGL-3954) is never granted by a tier, on this plan or any
|
|
263
|
+
// other: it is the managed-website add-on, switched on only by a live
|
|
264
|
+
// `seatAddons.siteCare` purchase (or a staff override), never by a row.
|
|
265
|
+
siteCare: false,
|
|
262
266
|
redirects: false,
|
|
263
267
|
screenAnalytics: false,
|
|
264
268
|
/**
|
|
@@ -358,7 +362,10 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
358
362
|
removeBranding: true,
|
|
359
363
|
scheduledPublishing: false,
|
|
360
364
|
aiAssist: true,
|
|
361
|
-
|
|
365
|
+
// One pool (AGL-3965): the plan's included credits pay for generation
|
|
366
|
+
// as well as assist on every paid plan, and an Aglyn AI tier adds
|
|
367
|
+
// credits on top rather than opening this door.
|
|
368
|
+
aiGenerative: true,
|
|
362
369
|
workflows: true,
|
|
363
370
|
dataStore: true,
|
|
364
371
|
videoMedia: false,
|
|
@@ -377,6 +384,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
377
384
|
siteExport: false,
|
|
378
385
|
multilingual: false,
|
|
379
386
|
eventCalendar: false,
|
|
387
|
+
siteCare: false,
|
|
380
388
|
redirects: true,
|
|
381
389
|
screenAnalytics: false,
|
|
382
390
|
mediaCdn: true,
|
|
@@ -476,7 +484,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
476
484
|
removeBranding: true,
|
|
477
485
|
scheduledPublishing: false,
|
|
478
486
|
aiAssist: true,
|
|
479
|
-
aiGenerative:
|
|
487
|
+
aiGenerative: true,
|
|
480
488
|
workflows: true,
|
|
481
489
|
dataStore: true,
|
|
482
490
|
videoMedia: true,
|
|
@@ -490,6 +498,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
490
498
|
siteExport: true,
|
|
491
499
|
multilingual: false,
|
|
492
500
|
eventCalendar: false,
|
|
501
|
+
siteCare: false,
|
|
493
502
|
redirects: true,
|
|
494
503
|
screenAnalytics: true,
|
|
495
504
|
mediaCdn: true,
|
|
@@ -546,7 +555,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
546
555
|
removeBranding: true,
|
|
547
556
|
scheduledPublishing: true,
|
|
548
557
|
aiAssist: true,
|
|
549
|
-
aiGenerative:
|
|
558
|
+
aiGenerative: true,
|
|
550
559
|
workflows: true,
|
|
551
560
|
dataStore: true,
|
|
552
561
|
videoMedia: true,
|
|
@@ -560,6 +569,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
560
569
|
siteExport: true,
|
|
561
570
|
multilingual: true,
|
|
562
571
|
eventCalendar: false,
|
|
572
|
+
siteCare: false,
|
|
563
573
|
redirects: true,
|
|
564
574
|
screenAnalytics: true,
|
|
565
575
|
mediaCdn: true,
|
|
@@ -619,7 +629,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
619
629
|
removeBranding: true,
|
|
620
630
|
scheduledPublishing: true,
|
|
621
631
|
aiAssist: true,
|
|
622
|
-
aiGenerative:
|
|
632
|
+
aiGenerative: true,
|
|
623
633
|
workflows: true,
|
|
624
634
|
dataStore: true,
|
|
625
635
|
videoMedia: true,
|
|
@@ -633,6 +643,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
633
643
|
siteExport: true,
|
|
634
644
|
multilingual: true,
|
|
635
645
|
eventCalendar: false,
|
|
646
|
+
siteCare: false,
|
|
636
647
|
redirects: true,
|
|
637
648
|
screenAnalytics: true,
|
|
638
649
|
mediaCdn: true,
|
|
@@ -689,7 +700,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
689
700
|
removeBranding: true,
|
|
690
701
|
scheduledPublishing: true,
|
|
691
702
|
aiAssist: true,
|
|
692
|
-
aiGenerative:
|
|
703
|
+
aiGenerative: true,
|
|
693
704
|
workflows: true,
|
|
694
705
|
dataStore: true,
|
|
695
706
|
videoMedia: true,
|
|
@@ -703,6 +714,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
703
714
|
siteExport: true,
|
|
704
715
|
multilingual: true,
|
|
705
716
|
eventCalendar: false,
|
|
717
|
+
siteCare: false,
|
|
706
718
|
redirects: true,
|
|
707
719
|
screenAnalytics: true,
|
|
708
720
|
mediaCdn: true,
|
|
@@ -763,7 +775,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
763
775
|
removeBranding: true,
|
|
764
776
|
scheduledPublishing: true,
|
|
765
777
|
aiAssist: true,
|
|
766
|
-
aiGenerative:
|
|
778
|
+
aiGenerative: true,
|
|
767
779
|
workflows: true,
|
|
768
780
|
dataStore: true,
|
|
769
781
|
videoMedia: true,
|
|
@@ -777,6 +789,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
777
789
|
siteExport: true,
|
|
778
790
|
multilingual: true,
|
|
779
791
|
eventCalendar: false,
|
|
792
|
+
siteCare: false,
|
|
780
793
|
redirects: true,
|
|
781
794
|
screenAnalytics: true,
|
|
782
795
|
mediaCdn: true,
|
|
@@ -888,6 +901,7 @@ export const PLAN_ENTITLEMENTS = {
|
|
|
888
901
|
multilingual: true,
|
|
889
902
|
// Event Calendar stays an add-on purchase, as on every other tier.
|
|
890
903
|
eventCalendar: false,
|
|
904
|
+
siteCare: false,
|
|
891
905
|
redirects: true,
|
|
892
906
|
screenAnalytics: true,
|
|
893
907
|
mediaCdn: true,
|
|
@@ -955,6 +969,17 @@ fillPluginPlanEntitlements(PLAN_ENTITLEMENTS);
|
|
|
955
969
|
*/ export function isCustomPricedPlan(plan) {
|
|
956
970
|
return plan === 'enterprise';
|
|
957
971
|
}
|
|
972
|
+
/**
|
|
973
|
+
* Whether a plan sells the Site Care add-on (AGL-3954): every paid self-serve
|
|
974
|
+
* plan, never `free` (no subscription to bill it on) and never a
|
|
975
|
+
* custom-priced plan (Enterprise names it in the agreement instead). An
|
|
976
|
+
* unknown plan string sells nothing. The ONE reading of that rule — the
|
|
977
|
+
* add-on ceiling, the checkout refusal and the Billing card all ask it.
|
|
978
|
+
*/ export function planSellsSiteCare(plan) {
|
|
979
|
+
if (!plan || plan === 'free') return false;
|
|
980
|
+
if (isCustomPricedPlan(plan)) return false;
|
|
981
|
+
return SELF_SERVE_PLANS.includes(plan);
|
|
982
|
+
}
|
|
958
983
|
/** Human plan names — the ONE source every plan badge/label reads. */ export const PLAN_LABELS = {
|
|
959
984
|
free: 'Free',
|
|
960
985
|
starter: 'Starter',
|
|
@@ -977,52 +1002,166 @@ fillPluginPlanEntitlements(PLAN_ENTITLEMENTS);
|
|
|
977
1002
|
* boolean from any quantity >= 1. One purchase covers every host in the org.
|
|
978
1003
|
* The marketing copy on /pricing is written against that behaviour.
|
|
979
1004
|
*/ export const EVENT_CALENDAR_ADDON_MONTHLY_USD = 9;
|
|
1005
|
+
/**
|
|
1006
|
+
* Site Care add-on (AGL-3954): $49/mo per organization, the managed-website
|
|
1007
|
+
* service. It buys staff time, not capacity: small changes to the owner's
|
|
1008
|
+
* existing site (hours, prices, photos, a staff member, a seasonal banner, a
|
|
1009
|
+
* section on an existing page), up to about one hour of work a month, done
|
|
1010
|
+
* within two business days, minutes logged and no rollover. New pages, new
|
|
1011
|
+
* forms, redesigns, brand work, photography, whole-site copy and ads are
|
|
1012
|
+
* quoted separately, and it never raises a plan limit — a 26th page or a
|
|
1013
|
+
* second site is still an upgrade.
|
|
1014
|
+
*
|
|
1015
|
+
* Flat across plans, like the Event Calendar, because the work it pays for
|
|
1016
|
+
* is the same hour whichever tier the site is on; the yearly price is ×12
|
|
1017
|
+
* with no discount, as every add-on's is. Sold on every paid self-serve plan
|
|
1018
|
+
* and never on Free (no subscription to carry it) or Enterprise (quoted per
|
|
1019
|
+
* deal) — `planSellsSiteCare` is that rule. `resolveOrgEntitlements` flips
|
|
1020
|
+
* the org-wide `features.siteCare` from any purchased quantity >= 1.
|
|
1021
|
+
*/ export const SITE_CARE_ADDON_MONTHLY_USD = 49;
|
|
1022
|
+
/**
|
|
1023
|
+
* Site Care's included time (AGL-3959): about an hour of staff work a month,
|
|
1024
|
+
* no rollover. `SITE_CARE_INCLUDED_BLOCK_MINUTES` is the step each request is
|
|
1025
|
+
* counted against it in, always rounded up — a 10-minute change uses one
|
|
1026
|
+
* 15-minute block. The timer's actual minutes are still logged beside it.
|
|
1027
|
+
*/ export const SITE_CARE_INCLUDED_MINUTES = 60;
|
|
1028
|
+
/** The block a request counts against the included hour in (AGL-3959). */ export const SITE_CARE_INCLUDED_BLOCK_MINUTES = 15;
|
|
1029
|
+
/**
|
|
1030
|
+
* Site Care extra time (AGL-3959): $79 per STARTED hour past the included
|
|
1031
|
+
* hour in a month. Billed in whole hours, rounded up — any part of an hour is
|
|
1032
|
+
* the full rate — and never less than the hours the owner approved. Only with
|
|
1033
|
+
* the owner's recorded yes, as an invoice item on the next subscription
|
|
1034
|
+
* invoice; never recurring. `site-care.ts` holds the arithmetic.
|
|
1035
|
+
*/ export const SITE_CARE_EXTRA_HOUR_USD = 79;
|
|
1036
|
+
/**
|
|
1037
|
+
* Site Care projects (AGL-3970): work that adds a page, a form, a design or
|
|
1038
|
+
* a campaign is a flat quote, never hourly. The quote is the estimated hours
|
|
1039
|
+
* × `SITE_CARE_EXTRA_HOUR_USD`, rounded up to the whole hour, and never below
|
|
1040
|
+
* the published starting price of the kind of project it is. These three are
|
|
1041
|
+
* those starting prices, as `/pricing` publishes them.
|
|
1042
|
+
*/ export const SITE_CARE_PROJECT_LANDING_PAGE_FROM_USD = 249;
|
|
1043
|
+
/** A redesign's published starting price (AGL-3970). */ export const SITE_CARE_PROJECT_REDESIGN_FROM_USD = 749;
|
|
1044
|
+
/** A logo or brand kit's published starting price (AGL-3970). */ export const SITE_CARE_PROJECT_BRAND_KIT_FROM_USD = 349;
|
|
1045
|
+
/**
|
|
1046
|
+
* A project priced ABOVE this is billed half up front and half at launch, on
|
|
1047
|
+
* two invoices from the same record; at or below it, in full up front
|
|
1048
|
+
* (AGL-3970). `site-care-project.ts` holds the arithmetic.
|
|
1049
|
+
*/ export const SITE_CARE_PROJECT_SPLIT_ABOVE_USD = 500;
|
|
980
1050
|
/**
|
|
981
1051
|
* POS Pro register add-on (AGL-329): $89/mo per extra register/location
|
|
982
1052
|
* (Shopify POS Pro parity). Purchased add-ons land as a per-org
|
|
983
1053
|
* `posRegisters` entitlement override, which
|
|
984
1054
|
* `resolveOrgEntitlements` already applies over the plan default.
|
|
985
1055
|
*/ export const POS_REGISTER_ADDON_MONTHLY_USD = 89;
|
|
1056
|
+
/** The tiers, smallest first — the order every picker lists them in. */ export const AI_TIER_IDS = [
|
|
1057
|
+
'spark',
|
|
1058
|
+
'boost',
|
|
1059
|
+
'plus',
|
|
1060
|
+
'max',
|
|
1061
|
+
'ultra',
|
|
1062
|
+
'studio'
|
|
1063
|
+
];
|
|
1064
|
+
export const AI_TIERS = {
|
|
1065
|
+
spark: {
|
|
1066
|
+
label: 'Spark',
|
|
1067
|
+
monthlyUsd: 9,
|
|
1068
|
+
yearlyUsd: 108,
|
|
1069
|
+
credits: 4000
|
|
1070
|
+
},
|
|
1071
|
+
boost: {
|
|
1072
|
+
label: 'Boost',
|
|
1073
|
+
monthlyUsd: 19,
|
|
1074
|
+
yearlyUsd: 228,
|
|
1075
|
+
credits: 9000
|
|
1076
|
+
},
|
|
1077
|
+
plus: {
|
|
1078
|
+
label: 'Plus',
|
|
1079
|
+
monthlyUsd: 39,
|
|
1080
|
+
yearlyUsd: 468,
|
|
1081
|
+
credits: 19000
|
|
1082
|
+
},
|
|
1083
|
+
max: {
|
|
1084
|
+
label: 'Max',
|
|
1085
|
+
monthlyUsd: 69,
|
|
1086
|
+
yearlyUsd: 828,
|
|
1087
|
+
credits: 34000
|
|
1088
|
+
},
|
|
1089
|
+
ultra: {
|
|
1090
|
+
label: 'Ultra',
|
|
1091
|
+
monthlyUsd: 99,
|
|
1092
|
+
yearlyUsd: 1188,
|
|
1093
|
+
credits: 49000
|
|
1094
|
+
},
|
|
1095
|
+
studio: {
|
|
1096
|
+
label: 'Studio',
|
|
1097
|
+
monthlyUsd: 299,
|
|
1098
|
+
yearlyUsd: 3588,
|
|
1099
|
+
credits: 149000
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
986
1102
|
/**
|
|
987
|
-
* The
|
|
988
|
-
*
|
|
989
|
-
*
|
|
990
|
-
*
|
|
991
|
-
*
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
* Pro $9 of $19, Business $19 of $39, Scale $34 of $69, Advanced $49 of
|
|
1000
|
-
* $99, Agency $149 of $299 — which is the same line-margin floor
|
|
1001
|
-
* (`ASSIST_CREDIT_MIN_MARGIN_PCT`) every retail assist rate clears.
|
|
1002
|
-
* `tier-margin-floor.spec.ts` holds the whole tier non-negative with the
|
|
1003
|
-
* add-on band at 100% and the add-on's revenue counted, and pins each band's
|
|
1004
|
-
* share of its price.
|
|
1005
|
-
*
|
|
1006
|
-
* ## Free and Enterprise
|
|
1007
|
-
*
|
|
1008
|
-
* Free is 0: the plan sells no add-on (`aiAddonMonthlyUsd` is null), so a
|
|
1009
|
-
* quantity written onto a Free org adds nothing. Enterprise is finite at
|
|
1010
|
-
* twice Agency's, the rule every Enterprise fallback follows since the
|
|
1011
|
-
* 2026-09-07 decision (AGL-2654) — never `UNLIMITED`, for the reason
|
|
1012
|
-
* `ENTERPRISE_ASSIST_CREDITS_PER_MONTH` gives: an unbounded band reads back
|
|
1013
|
-
* as zero off the wire. Enterprise carries `aiGenerative` in the agreement
|
|
1014
|
-
* and its price is null too, so this figure is what a contract that names
|
|
1015
|
-
* the add-on starts from before its own number is written.
|
|
1016
|
-
*/ export const AI_ADDON_CREDITS_PER_MONTH = {
|
|
1017
|
-
free: 0,
|
|
1018
|
-
starter: 4000,
|
|
1019
|
-
pro: 9000,
|
|
1020
|
-
business: 19000,
|
|
1021
|
-
scale: 34000,
|
|
1022
|
-
advanced: 49000,
|
|
1023
|
-
agency: 149000,
|
|
1024
|
-
enterprise: 298000
|
|
1103
|
+
* The tier an add-on bought before AGL-3965 is (AGL-3965): the one with the
|
|
1104
|
+
* same price and the same band the plan sold it at, so a workspace that
|
|
1105
|
+
* held "the Pro add-on" holds Boost — $19, 9,000 credits — and neither its
|
|
1106
|
+
* bill nor its credits move. Read when `aiTier` is absent and to classify a
|
|
1107
|
+
* per-plan `STRIPE_PRICE_{PLAN}_AI_ADDON` item still on a subscription.
|
|
1108
|
+
*/ export const LEGACY_AI_ADDON_TIER_BY_PLAN = {
|
|
1109
|
+
starter: 'spark',
|
|
1110
|
+
pro: 'boost',
|
|
1111
|
+
business: 'plus',
|
|
1112
|
+
scale: 'max',
|
|
1113
|
+
advanced: 'ultra',
|
|
1114
|
+
agency: 'studio'
|
|
1025
1115
|
};
|
|
1116
|
+
/**
|
|
1117
|
+
* The tier a purchase that names a plan and no tier means (AGL-3965): a
|
|
1118
|
+
* `?plan=pro&ai=1` deep link, a checkout posting `aiAddon: true` alone. The
|
|
1119
|
+
* tier with that plan's old price and band, so a link published before tiers
|
|
1120
|
+
* existed still sells what it quoted. Null where the plan sells no tier.
|
|
1121
|
+
*/ export function defaultAiTierForPlan(plan) {
|
|
1122
|
+
var _LEGACY_AI_ADDON_TIER_BY_PLAN_plan;
|
|
1123
|
+
if (!planSellsAiTiers(plan)) return null;
|
|
1124
|
+
return (_LEGACY_AI_ADDON_TIER_BY_PLAN_plan = LEGACY_AI_ADDON_TIER_BY_PLAN[plan]) != null ? _LEGACY_AI_ADDON_TIER_BY_PLAN_plan : null;
|
|
1125
|
+
}
|
|
1126
|
+
/** Whether a value is one of the tier ids. */ export function isAiTierId(value) {
|
|
1127
|
+
return typeof value === 'string' && AI_TIER_IDS.includes(value);
|
|
1128
|
+
}
|
|
1129
|
+
/** `ai:<tier>` for a tier. */ export function aiTierAddonKey(tier) {
|
|
1130
|
+
return `ai:${tier}`;
|
|
1131
|
+
}
|
|
1132
|
+
/**
|
|
1133
|
+
* The tier an `ai:<tier>` key names, or null for anything else — another
|
|
1134
|
+
* add-on's key, a bare `ai`, an unknown tier, a non-string. Exact and
|
|
1135
|
+
* case-sensitive: a key is read off a link, and guessing is the expensive
|
|
1136
|
+
* direction to be wrong in (`parseOnboardingPlanIntent` reads `?ai=` the
|
|
1137
|
+
* same way).
|
|
1138
|
+
*/ export function parseAiTierAddonKey(key) {
|
|
1139
|
+
if (typeof key !== 'string' || !key.startsWith('ai:')) return null;
|
|
1140
|
+
const tier = key.slice(3);
|
|
1141
|
+
return isAiTierId(tier) ? tier : null;
|
|
1142
|
+
}
|
|
1143
|
+
/**
|
|
1144
|
+
* Every tier as an `ai:<tier>` add-on, smallest first — what a picker that
|
|
1145
|
+
* offers "Aglyn AI" beside the other add-ons lists. Empty for a plan that
|
|
1146
|
+
* sells no tier (Free, Enterprise) when a plan is given.
|
|
1147
|
+
*/ export function listAiTierAddons(plan) {
|
|
1148
|
+
if (plan !== undefined && !planSellsAiTiers(plan)) return [];
|
|
1149
|
+
return AI_TIER_IDS.map((tier)=>({
|
|
1150
|
+
key: aiTierAddonKey(tier),
|
|
1151
|
+
tier,
|
|
1152
|
+
label: AI_TIERS[tier].label,
|
|
1153
|
+
monthlyUsd: AI_TIERS[tier].monthlyUsd,
|
|
1154
|
+
yearlyUsd: AI_TIERS[tier].yearlyUsd,
|
|
1155
|
+
credits: AI_TIERS[tier].credits
|
|
1156
|
+
}));
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Whether a plan may buy an Aglyn AI tier (AGL-3965): every paid self-serve
|
|
1160
|
+
* plan. Not Free, which has no subscription to carry it, and not Enterprise,
|
|
1161
|
+
* whose AI is in the agreement.
|
|
1162
|
+
*/ export function planSellsAiTiers(plan) {
|
|
1163
|
+
return planSellsSiteCare(plan);
|
|
1164
|
+
}
|
|
1026
1165
|
/**
|
|
1027
1166
|
* The generative add-on's name as a person sees it (AGL-2896): the brand,
|
|
1028
1167
|
* then "AI". Read from the platform brand by default and from the org's
|
|
@@ -1069,7 +1208,6 @@ fillPluginPlanEntitlements(PLAN_ENTITLEMENTS);
|
|
|
1069
1208
|
extraDataGbMonthlyUsd: null,
|
|
1070
1209
|
extraApiRequestsUsdPer1k: null,
|
|
1071
1210
|
extraAssistCreditsUsdPer1k: null,
|
|
1072
|
-
aiAddonMonthlyUsd: null,
|
|
1073
1211
|
extraContactsUsdPer1k: null,
|
|
1074
1212
|
extraEmailSendsUsdPer1k: null,
|
|
1075
1213
|
meteredInfraPassThrough: false
|
|
@@ -1090,7 +1228,6 @@ fillPluginPlanEntitlements(PLAN_ENTITLEMENTS);
|
|
|
1090
1228
|
// the silent free overage, and this rate without the band is a fee
|
|
1091
1229
|
// advertised on a quantity the plan never sold.
|
|
1092
1230
|
extraAssistCreditsUsdPer1k: 3,
|
|
1093
|
-
aiAddonMonthlyUsd: 9,
|
|
1094
1231
|
extraContactsUsdPer1k: 1,
|
|
1095
1232
|
// No email band to be "over" — see `emailSendsPerMonth` on the Starter
|
|
1096
1233
|
// entitlements. `emailSendsOverage` returns 0 for any non-positive band,
|
|
@@ -1109,7 +1246,6 @@ fillPluginPlanEntitlements(PLAN_ENTITLEMENTS);
|
|
|
1109
1246
|
extraDataGbMonthlyUsd: 0.36,
|
|
1110
1247
|
extraApiRequestsUsdPer1k: null,
|
|
1111
1248
|
extraAssistCreditsUsdPer1k: 3,
|
|
1112
|
-
aiAddonMonthlyUsd: 19,
|
|
1113
1249
|
extraContactsUsdPer1k: 0.75,
|
|
1114
1250
|
extraEmailSendsUsdPer1k: 2.25,
|
|
1115
1251
|
meteredInfraPassThrough: true
|
|
@@ -1124,7 +1260,6 @@ fillPluginPlanEntitlements(PLAN_ENTITLEMENTS);
|
|
|
1124
1260
|
extraDataGbMonthlyUsd: 0.36,
|
|
1125
1261
|
extraApiRequestsUsdPer1k: 0.5,
|
|
1126
1262
|
extraAssistCreditsUsdPer1k: 2.75,
|
|
1127
|
-
aiAddonMonthlyUsd: 39,
|
|
1128
1263
|
extraContactsUsdPer1k: 0.5,
|
|
1129
1264
|
extraEmailSendsUsdPer1k: 2,
|
|
1130
1265
|
meteredInfraPassThrough: true
|
|
@@ -1139,7 +1274,6 @@ fillPluginPlanEntitlements(PLAN_ENTITLEMENTS);
|
|
|
1139
1274
|
extraDataGbMonthlyUsd: 0.36,
|
|
1140
1275
|
extraApiRequestsUsdPer1k: 0.35,
|
|
1141
1276
|
extraAssistCreditsUsdPer1k: 2.5,
|
|
1142
|
-
aiAddonMonthlyUsd: 69,
|
|
1143
1277
|
extraContactsUsdPer1k: 0.4,
|
|
1144
1278
|
extraEmailSendsUsdPer1k: 1.9,
|
|
1145
1279
|
meteredInfraPassThrough: true
|
|
@@ -1157,7 +1291,6 @@ fillPluginPlanEntitlements(PLAN_ENTITLEMENTS);
|
|
|
1157
1291
|
// or above $0.234 (AGL-3444).
|
|
1158
1292
|
extraApiRequestsUsdPer1k: 0.25,
|
|
1159
1293
|
extraAssistCreditsUsdPer1k: 2.25,
|
|
1160
|
-
aiAddonMonthlyUsd: 99,
|
|
1161
1294
|
// FLOORED at the 50% retail margin, not stepped down again. The ladder
|
|
1162
1295
|
// above it descends $1.00 → $0.75 → $0.50 → $0.40, and one more step
|
|
1163
1296
|
// would have reached $0.25 against a `perContactMonth` cost of $0.20 per
|
|
@@ -1191,7 +1324,6 @@ fillPluginPlanEntitlements(PLAN_ENTITLEMENTS);
|
|
|
1191
1324
|
// FLOORED at the 50% retail margin — see Advanced's.
|
|
1192
1325
|
extraApiRequestsUsdPer1k: 0.25,
|
|
1193
1326
|
extraAssistCreditsUsdPer1k: 2,
|
|
1194
|
-
aiAddonMonthlyUsd: 299,
|
|
1195
1327
|
// $0.40, because the band it meters is now FINITE.
|
|
1196
1328
|
//
|
|
1197
1329
|
// This row has been wrong in both directions. It shipped $0.20 against an
|
|
@@ -1234,7 +1366,6 @@ fillPluginPlanEntitlements(PLAN_ENTITLEMENTS);
|
|
|
1234
1366
|
extraDataGbMonthlyUsd: null,
|
|
1235
1367
|
extraApiRequestsUsdPer1k: null,
|
|
1236
1368
|
extraAssistCreditsUsdPer1k: null,
|
|
1237
|
-
aiAddonMonthlyUsd: null,
|
|
1238
1369
|
extraContactsUsdPer1k: null,
|
|
1239
1370
|
extraEmailSendsUsdPer1k: null,
|
|
1240
1371
|
meteredInfraPassThrough: false
|
|
@@ -1582,9 +1713,12 @@ function trimmedOrNull(value) {
|
|
|
1582
1713
|
const annual = (org == null ? void 0 : (_org_subscription1 = org.subscription) == null ? void 0 : _org_subscription1.interval) === 'year';
|
|
1583
1714
|
const addons = (_ref = org == null ? void 0 : org.seatAddons) != null ? _ref : {};
|
|
1584
1715
|
const seats = (quantity, price)=>Math.max(0, quantity != null ? quantity : 0) * (price != null ? price : 0);
|
|
1585
|
-
return (annual ? pricing.basePriceAnnualMonthlyUsd : pricing.basePriceMonthlyUsd) + seats(addons.managers, pricing.extraSeatMonthlyUsd) + seats(addons.members, pricing.extraCollaboratorMonthlyUsd) + seats(addons.datasets, pricing.extraDatasetMonthlyUsd) + seats(addons.hosts, pricing.extraHostMonthlyUsd) + seats(addons.posRegisters, POS_REGISTER_ADDON_MONTHLY_USD) + seats(addons.eventCalendar, EVENT_CALENDAR_ADDON_MONTHLY_USD) + // A toggle, not a quantity: one purchase covers the org, so a stored
|
|
1586
|
-
// quantity above one bills once.
|
|
1587
|
-
|
|
1716
|
+
return (annual ? pricing.basePriceAnnualMonthlyUsd : pricing.basePriceMonthlyUsd) + seats(addons.managers, pricing.extraSeatMonthlyUsd) + seats(addons.members, pricing.extraCollaboratorMonthlyUsd) + seats(addons.datasets, pricing.extraDatasetMonthlyUsd) + seats(addons.hosts, pricing.extraHostMonthlyUsd) + seats(addons.posRegisters, POS_REGISTER_ADDON_MONTHLY_USD) + seats(addons.eventCalendar, EVENT_CALENDAR_ADDON_MONTHLY_USD) + seats(siteCareUnits(addons), SITE_CARE_ADDON_MONTHLY_USD) + // A toggle, not a quantity: one purchase covers the org, so a stored
|
|
1717
|
+
// quantity above one bills once, at its tier's price (AGL-3965).
|
|
1718
|
+
aiTierMonthlyUsd(aiTierOfPurchase(org));
|
|
1719
|
+
}
|
|
1720
|
+
/** A tier's monthly price, or 0 for no tier. */ function aiTierMonthlyUsd(tier) {
|
|
1721
|
+
return tier ? AI_TIERS[tier].monthlyUsd : 0;
|
|
1588
1722
|
}
|
|
1589
1723
|
/**
|
|
1590
1724
|
* How many Aglyn AI add-ons a purchase map counts as: 0 or 1 (AGL-2896).
|
|
@@ -1596,6 +1730,15 @@ function trimmedOrNull(value) {
|
|
|
1596
1730
|
const quantity = Number((_ref = addons == null ? void 0 : addons.aiAddon) != null ? _ref : 0);
|
|
1597
1731
|
return Number.isFinite(quantity) && quantity >= 1 ? 1 : 0;
|
|
1598
1732
|
}
|
|
1733
|
+
/**
|
|
1734
|
+
* How many Site Care add-ons a purchase map counts as: 0 or 1 (AGL-3954).
|
|
1735
|
+
* Org-wide like the Aglyn AI add-on, so a quantity above one is one
|
|
1736
|
+
* purchase, and a non-number, `NaN` or a negative is none.
|
|
1737
|
+
*/ export function siteCareUnits(addons) {
|
|
1738
|
+
var _ref;
|
|
1739
|
+
const quantity = Number((_ref = addons == null ? void 0 : addons.siteCare) != null ? _ref : 0);
|
|
1740
|
+
return Number.isFinite(quantity) && quantity >= 1 ? 1 : 0;
|
|
1741
|
+
}
|
|
1599
1742
|
/**
|
|
1600
1743
|
* A list price net of a discount (AGL-1105). Percentage discounts scale the
|
|
1601
1744
|
* whole bill; fixed discounts subtract a flat USD amount. Never below 0, and
|
|
@@ -2401,6 +2544,74 @@ function resolvePlan(org) {
|
|
|
2401
2544
|
*/ export function hasAiAddon(org) {
|
|
2402
2545
|
return aiAddonUnits(resolvePurchasedAddons(org)) === 1;
|
|
2403
2546
|
}
|
|
2547
|
+
/**
|
|
2548
|
+
* Which Aglyn AI tier the org's purchase map holds (AGL-3965), whether or
|
|
2549
|
+
* not the subscription is still paying for it — `resolveAiTier` is the
|
|
2550
|
+
* reading that drops a dead one. `org.aiTier` when it names a tier;
|
|
2551
|
+
* otherwise, for an add-on bought before tiers existed, the tier with that
|
|
2552
|
+
* plan's old price and band (`LEGACY_AI_ADDON_TIER_BY_PLAN`). Null when no
|
|
2553
|
+
* add-on is held or the plan sells no tier (Free, Enterprise).
|
|
2554
|
+
*/ export function aiTierOfPurchase(org) {
|
|
2555
|
+
var _LEGACY_AI_ADDON_TIER_BY_PLAN_;
|
|
2556
|
+
if (aiAddonUnits(org == null ? void 0 : org.seatAddons) !== 1) return null;
|
|
2557
|
+
if (!planSellsAiTiers(org == null ? void 0 : org.plan)) return null;
|
|
2558
|
+
if (isAiTierId(org == null ? void 0 : org.aiTier)) return org.aiTier;
|
|
2559
|
+
return (_LEGACY_AI_ADDON_TIER_BY_PLAN_ = LEGACY_AI_ADDON_TIER_BY_PLAN[org == null ? void 0 : org.plan]) != null ? _LEGACY_AI_ADDON_TIER_BY_PLAN_ : null;
|
|
2560
|
+
}
|
|
2561
|
+
/**
|
|
2562
|
+
* The Aglyn AI tier that currently applies (AGL-3965): bought, on a
|
|
2563
|
+
* subscription still paying for it, on a plan that sells tiers. The ONE
|
|
2564
|
+
* reading every surface that shows or counts a tier goes through.
|
|
2565
|
+
*/ export function resolveAiTier(org) {
|
|
2566
|
+
return hasAiAddon(org) ? aiTierOfPurchase(org) : null;
|
|
2567
|
+
}
|
|
2568
|
+
/**
|
|
2569
|
+
* What `seatAddons.aiAddon` adds on an Enterprise org (AGL-2896, kept by
|
|
2570
|
+
* AGL-3965): twice Studio's band, the figure the per-plan table carried as
|
|
2571
|
+
* twice Agency's (the rule every Enterprise fallback follows since AGL-2654),
|
|
2572
|
+
* and still what a contract that names the add-on starts from before its own
|
|
2573
|
+
* number is written. Enterprise buys no tier — its AI is in the agreement —
|
|
2574
|
+
* so this is the contract figure kept, not a price; finite, never
|
|
2575
|
+
* `UNLIMITED`, for the reason `ENTERPRISE_ASSIST_CREDITS_PER_MONTH` gives.
|
|
2576
|
+
*/ export const ENTERPRISE_AI_ADDON_CREDITS_PER_MONTH = AI_TIERS.studio.credits * 2;
|
|
2577
|
+
/**
|
|
2578
|
+
* The Aglyn AI add-on's per-unit quota as `resolveOrgEntitlements` folds it
|
|
2579
|
+
* (AGL-3965): the purchased tier's credits, on a plan that sells tiers;
|
|
2580
|
+
* Enterprise's contract figure (`ENTERPRISE_AI_ADDON_CREDITS_PER_MONTH`);
|
|
2581
|
+
* else 0 (Free). The AI plugin declares its seat add-on with this as
|
|
2582
|
+
* `quota.perUnit`.
|
|
2583
|
+
*/ export function aiTierQuotaPerUnit(org, plan) {
|
|
2584
|
+
if (plan === 'enterprise') return ENTERPRISE_AI_ADDON_CREDITS_PER_MONTH;
|
|
2585
|
+
if (!planSellsAiTiers(plan)) return 0;
|
|
2586
|
+
const tier = aiTierOfPurchase(org);
|
|
2587
|
+
return tier ? AI_TIERS[tier].credits : 0;
|
|
2588
|
+
}
|
|
2589
|
+
/**
|
|
2590
|
+
* The credits a month the org's Aglyn AI add-on adds to its plan's included
|
|
2591
|
+
* band (AGL-3965) — 0 with none held. The SAME figure `resolveOrgEntitlements`
|
|
2592
|
+
* folds into `assistCreditsPerMonth` (`aiTierQuotaPerUnit`), so a surface
|
|
2593
|
+
* quoting "your tier adds" and the meter agree.
|
|
2594
|
+
*/ export function aiTierCreditsPerMonth(org) {
|
|
2595
|
+
if (!hasAiAddon(org)) return 0;
|
|
2596
|
+
return aiTierQuotaPerUnit(org, resolveEffectivePlan(org));
|
|
2597
|
+
}
|
|
2598
|
+
/**
|
|
2599
|
+
* Whether this org can buy or change an Aglyn AI tier itself (AGL-3965): a
|
|
2600
|
+
* plan that sells tiers, and not one a staff comp grants — a comp has no
|
|
2601
|
+
* subscription to put the tier on (`compPricing`).
|
|
2602
|
+
*/ export function orgCanBuyAiTier(org) {
|
|
2603
|
+
return !resolvePlanComp(org) && planSellsAiTiers(resolveEffectivePlan(org));
|
|
2604
|
+
}
|
|
2605
|
+
/** "Aglyn AI Boost": the product name, then the tier's. */ export const aiTierName = (tier, brand = PLATFORM_BRAND_NAME)=>`${aiAddonName(brand)} ${AI_TIERS[tier].label}`;
|
|
2606
|
+
/**
|
|
2607
|
+
* Whether the org's Site Care add-on currently applies (AGL-3954): bought,
|
|
2608
|
+
* and on a subscription that is still paying for it, so a dead subscription
|
|
2609
|
+
* reads false here exactly as it drops `features.siteCare`. The reader for
|
|
2610
|
+
* surfaces that ask about the purchase rather than the resolved feature —
|
|
2611
|
+
* the staff org page's chip, the request intake.
|
|
2612
|
+
*/ export function hasSiteCare(org) {
|
|
2613
|
+
return siteCareUnits(resolvePurchasedAddons(org)) === 1;
|
|
2614
|
+
}
|
|
2404
2615
|
/**
|
|
2405
2616
|
* Numeric entitlement keys that were REMOVED from `PLAN_ENTITLEMENTS` and
|
|
2406
2617
|
* must never be resolved again from a stored override (AGL-2133).
|
|
@@ -2484,7 +2695,7 @@ function resolvePlan(org) {
|
|
|
2484
2695
|
* per-key overrides applied (features merge key-by-key too), then
|
|
2485
2696
|
* purchased add-ons stacked on top (AGL-524): `seatAddons.hosts` raises
|
|
2486
2697
|
* `hostLimit`, `seatAddons.eventCalendar` switches the `eventCalendar`
|
|
2487
|
-
* feature on, and every seat add-on a plugin declared through
|
|
2698
|
+
* feature on, `seatAddons.siteCare` switches `siteCare` on, and every seat add-on a plugin declared through
|
|
2488
2699
|
* `registerPluginEntitlements` (AGL-2940) widens the quota it names by its
|
|
2489
2700
|
* per-plan figure per unit and switches its features on — the Aglyn AI
|
|
2490
2701
|
* add-on (AGL-2896) is the first such declaration. (Seat/dataset add-ons
|
|
@@ -2589,17 +2800,22 @@ function resolvePlan(org) {
|
|
|
2589
2800
|
const purchased = resolvePurchasedAddons(org);
|
|
2590
2801
|
const extraHosts = Math.max(0, (_purchased_hosts = purchased.hosts) != null ? _purchased_hosts : 0);
|
|
2591
2802
|
const eventCalendar = ((_purchased_eventCalendar = purchased.eventCalendar) != null ? _purchased_eventCalendar : 0) >= 1;
|
|
2803
|
+
const siteCare = siteCareUnits(purchased) === 1;
|
|
2592
2804
|
// A declared add-on's quota is added AFTER the per-org override, so a
|
|
2593
2805
|
// contracted figure and a purchased add-on stack the way a raised
|
|
2594
2806
|
// `hostLimit` and purchased sites do. The per-unit figure is the PLAN's,
|
|
2595
2807
|
// read off the effective plan rather than the stored one, so a dead
|
|
2596
2808
|
// subscription that resolved to free adds free's figure.
|
|
2597
|
-
const folded = foldPluginSeatAddons(resolved, purchased, resolvePlan(org));
|
|
2598
|
-
if (!extraHosts && !eventCalendar && folded === resolved)
|
|
2809
|
+
const folded = foldPluginSeatAddons(resolved, purchased, resolvePlan(org), org != null ? org : {});
|
|
2810
|
+
if (!extraHosts && !eventCalendar && !siteCare && folded === resolved) {
|
|
2811
|
+
return resolved;
|
|
2812
|
+
}
|
|
2599
2813
|
return _extends({}, folded, {
|
|
2600
2814
|
hostLimit: folded.hostLimit + extraHosts,
|
|
2601
2815
|
features: _extends({}, folded.features, eventCalendar ? {
|
|
2602
2816
|
eventCalendar: true
|
|
2817
|
+
} : {}, siteCare ? {
|
|
2818
|
+
siteCare: true
|
|
2603
2819
|
} : {})
|
|
2604
2820
|
});
|
|
2605
2821
|
}
|
|
@@ -2631,7 +2847,7 @@ function resolvePlan(org) {
|
|
|
2631
2847
|
* quota each names gains its per-plan figure per unit, and its features
|
|
2632
2848
|
* switch on. Returns the input object untouched when nothing applies, so a
|
|
2633
2849
|
* caller can tell "nothing folded" from "folded to the same numbers".
|
|
2634
|
-
*/ function foldPluginSeatAddons(resolved, purchased, plan) {
|
|
2850
|
+
*/ function foldPluginSeatAddons(resolved, purchased, plan, org) {
|
|
2635
2851
|
let out = resolved;
|
|
2636
2852
|
for (const addon of listPluginSeatAddons()){
|
|
2637
2853
|
var _addon_features;
|
|
@@ -2641,8 +2857,9 @@ function resolvePlan(org) {
|
|
|
2641
2857
|
features: _extends({}, out.features)
|
|
2642
2858
|
});
|
|
2643
2859
|
if (addon.quota) {
|
|
2644
|
-
var
|
|
2645
|
-
|
|
2860
|
+
var _ref, _bag_addon_quota_key;
|
|
2861
|
+
var _addon_quota_perUnitByPlan;
|
|
2862
|
+
const perUnit = addon.quota.perUnit ? addon.quota.perUnit(org, plan) : (_ref = (_addon_quota_perUnitByPlan = addon.quota.perUnitByPlan) == null ? void 0 : _addon_quota_perUnitByPlan[plan]) != null ? _ref : 0;
|
|
2646
2863
|
const bag = next;
|
|
2647
2864
|
const current = Number((_bag_addon_quota_key = bag[addon.quota.key]) != null ? _bag_addon_quota_key : 0);
|
|
2648
2865
|
bag[addon.quota.key] = (Number.isFinite(current) ? current : 0) + perUnit * units;
|