@saasicat/ui-vue 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/{chunk-A3W2N26K.js → chunk-7N3CJTOA.js} +7 -227
  2. package/dist/{chunk-X5SQ5HMB.js → chunk-TBLXKSTR.js} +0 -137
  3. package/dist/{chunk-QZOSDCNP.js → chunk-TY2WYKME.js} +1 -1
  4. package/dist/client/index.cjs +112 -467
  5. package/dist/client/index.d.cts +4 -62
  6. package/dist/client/index.d.ts +4 -62
  7. package/dist/client/index.js +2 -6
  8. package/dist/index.cjs +204 -583
  9. package/dist/index.d.cts +10 -55
  10. package/dist/index.d.ts +10 -55
  11. package/dist/index.js +74 -101
  12. package/dist/{messages-7b0P8W75.d.ts → messages-BIYw32u1.d.cts} +0 -67
  13. package/dist/{messages-7b0P8W75.d.cts → messages-BIYw32u1.d.ts} +0 -67
  14. package/dist/quasar/index.cjs +0 -136
  15. package/dist/quasar/index.d.cts +2 -2
  16. package/dist/quasar/index.d.ts +2 -2
  17. package/dist/quasar/index.js +2 -2
  18. package/dist/{use-super-admin-i18n-B3v3-SWZ.d.ts → use-super-admin-i18n-CWNu_W3u.d.ts} +1 -1
  19. package/dist/{use-super-admin-i18n-DMktRVEt.d.cts → use-super-admin-i18n-DL_qI1BY.d.cts} +1 -1
  20. package/package.json +2 -2
  21. package/src/client/i18n/messages/nav.ts +0 -2
  22. package/src/client/i18n/messages/plan-versions.ts +0 -143
  23. package/src/client/index.ts +0 -2
  24. package/src/client/nav-builder.ts +9 -4
  25. package/src/index.ts +0 -1
  26. package/src/pages-standard/AdminLayout.vue +1 -1
  27. package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +1 -1
  28. package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +1 -1
  29. package/src/pages-standard/plan-versions/catalog-history.types.ts +37 -0
  30. package/src/pages-standard/plan-versions/format.ts +2 -38
  31. package/src/client/plan-versions-catalog.ts +0 -380
  32. package/src/pages-standard/PlanVersionsPage.vue +0 -220
  33. package/src/pages-standard/plan-versions/PlanVersionHeader.vue +0 -309
  34. package/src/pages-standard/plan-versions/PlanVersionStatusBadge.vue +0 -48
  35. package/src/pages-standard/plan-versions/PlanVersionsAudit.vue +0 -326
  36. package/src/pages-standard/plan-versions/PlanVersionsKpi.vue +0 -65
  37. package/src/pages-standard/plan-versions/PlanVersionsList.vue +0 -315
  38. package/src/pages-standard/plan-versions/PlanVersionsMatrix.vue +0 -261
  39. package/src/pages-standard/plan-versions/types.ts +0 -33
  40. package/src/vue/use-plan-versions.ts +0 -83
package/dist/index.cjs CHANGED
@@ -65,7 +65,6 @@ __export(src_exports, {
65
65
  buildQuotaRegistry: () => buildQuotaRegistry,
66
66
  buildRoutes: () => buildRoutes,
67
67
  buildSidebar: () => buildSidebar,
68
- buildSnapshots: () => buildSnapshots,
69
68
  createAdminRoutes: () => createAdminRoutes,
70
69
  createManifestStore: () => createManifestStore,
71
70
  createPlatformLoaders: () => createPlatformLoaders,
@@ -81,7 +80,6 @@ __export(src_exports, {
81
80
  formatCurrency: () => formatCurrency,
82
81
  formatMessage: () => formatMessage,
83
82
  getJson: () => getJson,
84
- listOpenDrafts: () => listOpenDrafts,
85
83
  mergeMessages: () => mergeMessages,
86
84
  postJson: () => postJson,
87
85
  provideEntitlement: () => provideEntitlement,
@@ -106,7 +104,6 @@ __export(src_exports, {
106
104
  useNav: () => useNav,
107
105
  usePlanEditor: () => usePlanEditor,
108
106
  usePlanVersions: () => usePlanVersions,
109
- usePlanVersionsCatalog: () => usePlanVersionsCatalog,
110
107
  usePlans: () => usePlans,
111
108
  usePlatformTenantActions: () => usePlatformTenantActions,
112
109
  usePromotions: () => usePromotions,
@@ -349,7 +346,6 @@ var navMessages = defineMessages(
349
346
  subscriptions: "Abonnements",
350
347
  promoCodes: "Promo-Codes",
351
348
  plans: "Pl\xE4ne & Versionen",
352
- planVersions: "Plan-Versionen",
353
349
  audit: "Audit-Log",
354
350
  users: "Benutzer",
355
351
  pilots: "Piloten",
@@ -373,7 +369,6 @@ var navMessages = defineMessages(
373
369
  subscriptions: "Subscriptions",
374
370
  promoCodes: "Promo codes",
375
371
  plans: "Plans & versions",
376
- planVersions: "Plan versions",
377
372
  audit: "Audit log",
378
373
  users: "Users",
379
374
  pilots: "Pilots",
@@ -399,7 +394,6 @@ var DEFAULT_STANDARD_PAGE_ROUTES = {
399
394
  subscriptions: "/admin/subscriptions",
400
395
  promoCodes: "/admin/promo-codes",
401
396
  plans: "/admin/plans",
402
- planVersions: "/admin/plan-versions",
403
397
  audit: "/admin/audit",
404
398
  users: "/admin/users",
405
399
  pilots: "/admin/pilots",
@@ -409,13 +403,15 @@ var DEFAULT_STANDARD_PAGE_ROUTES = {
409
403
  platformEmail: "/admin/platform-email",
410
404
  platformEmailHistory: "/admin/platform-email-history"
411
405
  };
406
+ function isSupportedStandardPageKey(key) {
407
+ return Object.hasOwn(DEFAULT_STANDARD_PAGE_ROUTES, key);
408
+ }
412
409
  var DEFAULT_ICONS = {
413
410
  dashboard: "dashboard",
414
411
  tenants: "business",
415
412
  subscriptions: "card_membership",
416
413
  promoCodes: "local_activity",
417
414
  plans: "workspace_premium",
418
- planVersions: "history_edu",
419
415
  audit: "history",
420
416
  users: "people",
421
417
  pilots: "flight_takeoff",
@@ -430,7 +426,6 @@ var PAGE_SECTIONS = {
430
426
  discovery: "catalog",
431
427
  bundles: "catalog",
432
428
  plans: "catalog",
433
- planVersions: "catalog",
434
429
  marketingCatalog: "catalog",
435
430
  promoCodes: "catalog",
436
431
  tenants: "customers",
@@ -458,6 +453,7 @@ function buildRoutes(manifest, options = {}) {
458
453
  const overrideIcons = { ...DEFAULT_ICONS, ...options.standardPageIcons };
459
454
  const overrideNavSection = { ...defaultNavSections, ...options.standardPageNavSection };
460
455
  for (const key of Object.keys(standard)) {
456
+ if (!isSupportedStandardPageKey(key)) continue;
461
457
  const def = standard[key];
462
458
  if (!def?.enabled) continue;
463
459
  const cap = def.requiredCapability ?? null;
@@ -706,464 +702,6 @@ function formatMessage(template, params) {
706
702
  });
707
703
  }
708
704
 
709
- // src/client/i18n/messages/plan-versions.ts
710
- var planVersionsMessages = defineMessages(
711
- {
712
- compareEnd: "Vergleich beenden",
713
- page: {
714
- loadingCatalog: "Catalog wird geladen\u2026",
715
- noAuditLoader: "Kein Audit-Loader konfiguriert."
716
- },
717
- header: {
718
- modeList: "Plan-Liste",
719
- modeMatrix: "Feature-Matrix",
720
- modeAudit: "Aktivit\xE4t",
721
- publishedOn: "Publiziert {date}",
722
- openDrafts: "offene Drafts",
723
- regressionOne: "Regression",
724
- regressionMany: "Regressionen",
725
- startPublishFlow: "Publish-Flow starten",
726
- compareModeHint: "Vergleichsmodus aktiv \u2014 andere Ansichten deaktiviert"
727
- },
728
- status: {
729
- draft: "DRAFT",
730
- active: "AKTIV",
731
- archived: "ARCHIV"
732
- },
733
- timeline: {
734
- title: "Plan-Catalog",
735
- snapshotCount: "{count} Snapshots",
736
- noOpenDrafts: "keine offenen Drafts",
737
- openCount: "{count} offen",
738
- unknown: "unbekannt",
739
- compareHint: "Rechtsklick auf Snapshot \u2192 vergleichen"
740
- },
741
- list: {
742
- kpiPlans: "Pakete",
743
- kpiSelfService: "Self-Service",
744
- kpiOfTotal: "von {count}",
745
- kpiFeaturesTotal: "Features gesamt",
746
- missingPlansLabel: "Fehlende Pakete:",
747
- missingPlansHint: "\u2014 keine Live-Version in diesem Snapshot.",
748
- createDraftFor: "Draft f\xFCr {planId}",
749
- colPlan: "Paket",
750
- colPriceNet: "Preis (netto)",
751
- colFeatures: "Features",
752
- draftHintLabel: "Arbeitsstand:",
753
- draftHintBefore: "Drafts oben in der Liste. Limits, Preise und Features per Klick auf",
754
- draftHintEditButton: '\u201EBearbeiten"',
755
- draftHintMiddle: "\xE4ndern (ohne MFA). Erst",
756
- draftHintPublishFlow: "Publish-Flow",
757
- draftHintAfter: "(Validate \u2192 Diff-Review \u2192 MFA \u2192 Apply) macht sie f\xFCr k\xFCnftige Renewals wirksam."
758
- },
759
- matrix: {
760
- colFeature: "Feature",
761
- perMonthShort: "/Mo",
762
- fallbackGroup: "Sonstige"
763
- },
764
- diff: {
765
- legend: "Vergleich",
766
- plansChanged: "Pakete ge\xE4ndert",
767
- regressions: "Regressionen",
768
- sectionPlans: "Pakete",
769
- changeCountOne: "{count} \xC4nderung",
770
- changeCountMany: "{count} \xC4nderungen"
771
- },
772
- diffPreview: {
773
- empty: "Keine \xC4nderungen gegen\xFCber der Vorg\xE4ngerversion.",
774
- improvement: "Verbesserung",
775
- regression: "Verschlechterung",
776
- neutral: "Neutral"
777
- },
778
- diffFields: {
779
- featuresAdded: "Hinzugef\xFCgte Features",
780
- featuresRemoved: "Entfernte Features",
781
- maxUsers: "Max. Benutzer",
782
- maxStorageGb: "Speicher (GB)",
783
- monthlyNet: "Preis monatlich (netto)",
784
- yearlyNet: "Preis j\xE4hrlich (netto)",
785
- unitSize: "Einheitsgr\xF6\xDFe"
786
- },
787
- audit: {
788
- title: "Aktivit\xE4t",
789
- eventCount: "{count} Events",
790
- loading: "Audit-Trail wird geladen\u2026",
791
- empty: "Keine Plan-/Add-on-Events im Audit-Log gefunden.",
792
- actionPlanPublished: "Plan publiziert",
793
- actionPlanDraftCreated: "Plan-Draft angelegt",
794
- actionPlanDraftUpdated: "Plan-Draft ge\xE4ndert",
795
- actionPlanDraftDeleted: "Plan-Draft gel\xF6scht",
796
- actionCatalogPublished: "Catalog publiziert",
797
- detailRegression: "Mit mindestens einer Verschlechterung publiziert.",
798
- detailFieldsChanged: "{count} Felder ge\xE4ndert."
799
- },
800
- bulkPublish: {
801
- changeNoteRequired: "changeNote ist Pflicht beim Publish."
802
- },
803
- format: {
804
- priceIndividual: "individuell",
805
- today: "heute",
806
- yesterday: "gestern",
807
- daysAgo: "vor {count} Tagen",
808
- weeksAgoOne: "vor {count} Woche",
809
- weeksAgoMany: "vor {count} Wochen",
810
- monthsAgo: "vor {count} Monaten",
811
- yearsAgoOne: "vor {count} Jahr",
812
- yearsAgoMany: "vor {count} Jahren"
813
- },
814
- catalog: {
815
- draftsLabel: "Arbeitsstand",
816
- draftsTitleEmpty: "Keine offenen Drafts",
817
- draftsTitleOne: "{count} offener Draft bereit f\xFCr Publish",
818
- draftsTitleMany: "{count} offene Drafts bereit f\xFCr Publish",
819
- draftsDescriptionEmpty: "Lege einen Draft an, um Limits, Preise oder Features zu \xE4ndern. Drafts sind ohne MFA editierbar und werden erst beim Publish wirksam.",
820
- draftsDescription: "Diese Tabelle zeigt, wie der Catalog nach Publish aller Drafts aussehen w\xFCrde. Bestehende Mandanten bleiben auf der vorherigen Version, bis sie aktiv migriert werden.",
821
- activeLabel: "Aktuell",
822
- activeTitle: "Live-Catalog",
823
- activeDescription: "Diese Plan-Versionen sind aktuell f\xFCr neue Onboardings und f\xFCr Renewals nach Stichtag aktiv.",
824
- publishEvent: "Publish-Event",
825
- publishEventSingle: "{planId} v{version} publiziert",
826
- publishEventMultiple: "{count} Versionen publiziert",
827
- reconstructedSnapshot: "Snapshot rekonstruiert aus per-Entity-Versionen."
828
- }
829
- },
830
- {
831
- compareEnd: "End comparison",
832
- page: {
833
- loadingCatalog: "Loading catalog\u2026",
834
- noAuditLoader: "No audit loader configured."
835
- },
836
- header: {
837
- modeList: "Plan list",
838
- modeMatrix: "Feature matrix",
839
- modeAudit: "Activity",
840
- publishedOn: "Published {date}",
841
- openDrafts: "open drafts",
842
- regressionOne: "regression",
843
- regressionMany: "regressions",
844
- startPublishFlow: "Start publish flow",
845
- compareModeHint: "Comparison mode active \u2014 other views disabled"
846
- },
847
- status: {
848
- draft: "DRAFT",
849
- active: "ACTIVE",
850
- archived: "ARCHIVED"
851
- },
852
- timeline: {
853
- title: "Plan catalog",
854
- snapshotCount: "{count} snapshots",
855
- noOpenDrafts: "no open drafts",
856
- openCount: "{count} open",
857
- unknown: "unknown",
858
- compareHint: "Right-click a snapshot \u2192 compare"
859
- },
860
- list: {
861
- kpiPlans: "Plans",
862
- kpiSelfService: "Self-service",
863
- kpiOfTotal: "of {count}",
864
- kpiFeaturesTotal: "Features total",
865
- missingPlansLabel: "Missing plans:",
866
- missingPlansHint: "\u2014 no live version in this snapshot.",
867
- createDraftFor: "Draft for {planId}",
868
- colPlan: "Plan",
869
- colPriceNet: "Price (net)",
870
- colFeatures: "Features",
871
- draftHintLabel: "Working state:",
872
- draftHintBefore: "Drafts at the top of the list. Change limits, prices and features by clicking",
873
- draftHintEditButton: '"Edit"',
874
- draftHintMiddle: "(without MFA). Only the",
875
- draftHintPublishFlow: "publish flow",
876
- draftHintAfter: "(validate \u2192 diff review \u2192 MFA \u2192 apply) makes them effective for future renewals."
877
- },
878
- matrix: {
879
- colFeature: "Feature",
880
- perMonthShort: "/mo",
881
- fallbackGroup: "Other"
882
- },
883
- diff: {
884
- legend: "Comparison",
885
- plansChanged: "Plans changed",
886
- regressions: "Regressions",
887
- sectionPlans: "Plans",
888
- changeCountOne: "{count} change",
889
- changeCountMany: "{count} changes"
890
- },
891
- diffPreview: {
892
- empty: "No changes compared to the previous version.",
893
- improvement: "Improvement",
894
- regression: "Regression",
895
- neutral: "Neutral"
896
- },
897
- diffFields: {
898
- featuresAdded: "Added features",
899
- featuresRemoved: "Removed features",
900
- maxUsers: "Max. users",
901
- maxStorageGb: "Storage (GB)",
902
- monthlyNet: "Price monthly (net)",
903
- yearlyNet: "Price yearly (net)",
904
- unitSize: "Unit size"
905
- },
906
- audit: {
907
- title: "Activity",
908
- eventCount: "{count} events",
909
- loading: "Loading audit trail\u2026",
910
- empty: "No plan/add-on events found in the audit log.",
911
- actionPlanPublished: "Plan published",
912
- actionPlanDraftCreated: "Plan draft created",
913
- actionPlanDraftUpdated: "Plan draft changed",
914
- actionPlanDraftDeleted: "Plan draft deleted",
915
- actionCatalogPublished: "Catalog published",
916
- detailRegression: "Published with at least one regression.",
917
- detailFieldsChanged: "{count} fields changed."
918
- },
919
- bulkPublish: {
920
- changeNoteRequired: "changeNote is required when publishing."
921
- },
922
- format: {
923
- priceIndividual: "custom",
924
- today: "today",
925
- yesterday: "yesterday",
926
- daysAgo: "{count} days ago",
927
- weeksAgoOne: "{count} week ago",
928
- weeksAgoMany: "{count} weeks ago",
929
- monthsAgo: "{count} months ago",
930
- yearsAgoOne: "{count} year ago",
931
- yearsAgoMany: "{count} years ago"
932
- },
933
- catalog: {
934
- draftsLabel: "Working state",
935
- draftsTitleEmpty: "No open drafts",
936
- draftsTitleOne: "{count} open draft ready to publish",
937
- draftsTitleMany: "{count} open drafts ready to publish",
938
- draftsDescriptionEmpty: "Create a draft to change limits, prices or features. Drafts are editable without MFA and only take effect when published.",
939
- draftsDescription: "This table shows what the catalog would look like after publishing all drafts. Existing tenants stay on the previous version until they are actively migrated.",
940
- activeLabel: "Current",
941
- activeTitle: "Live catalog",
942
- activeDescription: "These plan versions are currently active for new onboardings and for renewals after the effective date.",
943
- publishEvent: "Publish event",
944
- publishEventSingle: "{planId} v{version} published",
945
- publishEventMultiple: "{count} versions published",
946
- reconstructedSnapshot: "Snapshot reconstructed from per-entity versions."
947
- }
948
- }
949
- );
950
-
951
- // src/client/plan-versions-catalog.ts
952
- var dec = (s) => Number(s);
953
- function extractQuotas(p) {
954
- if (p.quotas && Object.keys(p.quotas).length > 0) {
955
- return { ...p.quotas };
956
- }
957
- const out = {};
958
- if (typeof p.maxUsers === "number") out.users = p.maxUsers;
959
- if (typeof p.maxVehicles === "number") out.vehicles = p.maxVehicles;
960
- if (typeof p.maxStorageGb === "number") out.storageGb = p.maxStorageGb;
961
- return out;
962
- }
963
- var sortByPublishedDesc = (rows) => [...rows].sort((a, b) => {
964
- const at = a.publishedAt ? Date.parse(a.publishedAt) : Number.POSITIVE_INFINITY;
965
- const bt = b.publishedAt ? Date.parse(b.publishedAt) : Number.POSITIVE_INFINITY;
966
- if (at !== bt) return bt - at;
967
- return b.version - a.version;
968
- });
969
- function findLiveAt(rows, asOfMs) {
970
- const candidates = rows.filter((r) => {
971
- if (r.publishedAt === null) return false;
972
- if (Date.parse(r.publishedAt) > asOfMs) return false;
973
- if (r.supersededAt !== null && Date.parse(r.supersededAt) <= asOfMs) return false;
974
- return true;
975
- });
976
- if (candidates.length === 0) return null;
977
- return [...candidates].sort((a, b) => b.version - a.version)[0] ?? null;
978
- }
979
- function findCurrentLive(rows) {
980
- return rows.find((r) => r.publishedAt !== null && r.supersededAt === null) ?? null;
981
- }
982
- function findDraft(rows) {
983
- return rows.find((r) => r.publishedAt === null) ?? null;
984
- }
985
- function groupBy(rows, keyOf) {
986
- const out = /* @__PURE__ */ new Map();
987
- for (const r of rows) {
988
- const k = keyOf(r);
989
- const list = out.get(k) ?? [];
990
- list.push(r);
991
- out.set(k, list);
992
- }
993
- return out;
994
- }
995
- function resolvePlan(source, liveBase) {
996
- const quotas = extractQuotas(source);
997
- return {
998
- source,
999
- liveBase,
1000
- isDraft: source.publishedAt === null,
1001
- planId: source.planId,
1002
- features: source.features,
1003
- quotas,
1004
- monthlyNet: dec(source.monthlyNet),
1005
- yearlyNet: dec(source.yearlyNet),
1006
- marketed: source.marketed,
1007
- version: source.version,
1008
- maxUsers: quotas.users,
1009
- maxVehicles: quotas.vehicles,
1010
- maxStorageGb: quotas.storageGb
1011
- };
1012
- }
1013
- function draftsTitle(draftCount, msg) {
1014
- if (draftCount === 0) return msg.draftsTitleEmpty;
1015
- const template = draftCount === 1 ? msg.draftsTitleOne : msg.draftsTitleMany;
1016
- return formatMessage(template, { count: draftCount });
1017
- }
1018
- function dateLabel(iso, locale) {
1019
- return new Date(iso).toLocaleDateString(SA_INTL_LOCALES[locale], {
1020
- day: "2-digit",
1021
- month: "short",
1022
- year: "numeric"
1023
- });
1024
- }
1025
- function buildDraftsSnapshot(data, sortPlansFn, locale) {
1026
- const msg = planVersionsMessages[locale].catalog;
1027
- const planByKey = groupBy(data.planVersions, (r) => r.planId);
1028
- const plans = [];
1029
- for (const [, rows] of planByKey) {
1030
- const draft = findDraft(rows);
1031
- const live = findCurrentLive(rows);
1032
- if (draft) plans.push(resolvePlan(draft, live));
1033
- else if (live) plans.push(resolvePlan(live, null));
1034
- }
1035
- const draftCount = plans.filter((p) => p.isDraft).length;
1036
- return {
1037
- id: "drafts",
1038
- kind: "drafts",
1039
- status: "DRAFT",
1040
- label: msg.draftsLabel,
1041
- title: draftsTitle(draftCount, msg),
1042
- description: draftCount === 0 ? msg.draftsDescriptionEmpty : msg.draftsDescription,
1043
- asOf: null,
1044
- createdAt: null,
1045
- publishedAt: null,
1046
- authorEmail: null,
1047
- plans: sortPlansFn(plans),
1048
- draftCount,
1049
- regressionCount: 0
1050
- };
1051
- }
1052
- function buildActiveSnapshot(data, sortPlansFn, locale) {
1053
- const msg = planVersionsMessages[locale].catalog;
1054
- const planByKey = groupBy(data.planVersions, (r) => r.planId);
1055
- const plans = [];
1056
- for (const [, rows] of planByKey) {
1057
- const live = findCurrentLive(rows);
1058
- if (live) plans.push(resolvePlan(live, null));
1059
- }
1060
- if (plans.length === 0) return null;
1061
- const publishedDates = plans.map((p) => p.source.publishedAt).filter((t) => t !== null).sort();
1062
- const latestPublished = publishedDates[publishedDates.length - 1];
1063
- return {
1064
- id: "active",
1065
- kind: "active",
1066
- status: "ACTIVE",
1067
- label: msg.activeLabel,
1068
- title: msg.activeTitle,
1069
- description: msg.activeDescription,
1070
- asOf: latestPublished ?? null,
1071
- createdAt: null,
1072
- publishedAt: latestPublished ?? null,
1073
- authorEmail: null,
1074
- plans: sortPlansFn(plans),
1075
- draftCount: 0,
1076
- regressionCount: 0
1077
- };
1078
- }
1079
- function buildHistoricalSnapshots(data, sortPlansFn, locale) {
1080
- const msg = planVersionsMessages[locale].catalog;
1081
- const allPublishedAt = /* @__PURE__ */ new Set();
1082
- for (const r of data.planVersions) if (r.publishedAt) allPublishedAt.add(r.publishedAt);
1083
- if (allPublishedAt.size === 0) return [];
1084
- const planByKey = groupBy(data.planVersions, (r) => r.planId);
1085
- const liveTimestamps = /* @__PURE__ */ new Set();
1086
- for (const rows of planByKey.values()) {
1087
- const live = findCurrentLive(rows);
1088
- if (live?.publishedAt) liveTimestamps.add(live.publishedAt);
1089
- }
1090
- const liveSorted = [...liveTimestamps].sort();
1091
- const latestLive = liveSorted[liveSorted.length - 1];
1092
- const sortedDesc = [...allPublishedAt].sort((a, b) => Date.parse(b) - Date.parse(a));
1093
- const out = [];
1094
- for (const ts of sortedDesc) {
1095
- if (latestLive && Date.parse(ts) >= Date.parse(latestLive)) continue;
1096
- const tMs = Date.parse(ts) + 1;
1097
- const plans = [];
1098
- for (const [, rows] of planByKey) {
1099
- const live = findLiveAt(rows, tMs);
1100
- if (live) plans.push(resolvePlan(live, null));
1101
- }
1102
- if (plans.length === 0) continue;
1103
- const publishedAtThisEvent = data.planVersions.filter((r) => r.publishedAt === ts);
1104
- const regressionCount = publishedAtThisEvent.filter((r) => !r.nonRegressive).length;
1105
- const author = publishedAtThisEvent[0]?.publishedByUserId ?? null;
1106
- out.push({
1107
- id: `hist-${ts}`,
1108
- kind: "historical",
1109
- status: "ARCHIVED",
1110
- label: dateLabel(ts, locale),
1111
- title: summarizeEvent(publishedAtThisEvent, msg),
1112
- description: detailEvent(publishedAtThisEvent, msg),
1113
- asOf: ts,
1114
- createdAt: ts,
1115
- publishedAt: ts,
1116
- authorEmail: author,
1117
- plans: sortPlansFn(plans),
1118
- draftCount: 0,
1119
- regressionCount
1120
- });
1121
- }
1122
- return out;
1123
- }
1124
- function summarizeEvent(rows, msg) {
1125
- if (rows.length === 0) return msg.publishEvent;
1126
- if (rows.length === 1) {
1127
- const r = rows[0];
1128
- return formatMessage(msg.publishEventSingle, { planId: r.planId, version: r.version });
1129
- }
1130
- return formatMessage(msg.publishEventMultiple, { count: rows.length });
1131
- }
1132
- function detailEvent(rows, msg) {
1133
- if (rows.length === 0) return "";
1134
- const note = rows[0]?.changeNote ?? "";
1135
- return note.length > 0 ? note : msg.reconstructedSnapshot;
1136
- }
1137
- function sortPlansBy(order) {
1138
- if (!order || order.length === 0) {
1139
- return (rows) => [...rows].sort((a, b) => a.planId.localeCompare(b.planId));
1140
- }
1141
- const idx = {};
1142
- for (let i = 0; i < order.length; i++) idx[order[i]] = i;
1143
- return (rows) => [...rows].sort((a, b) => {
1144
- const ai = idx[a.planId] ?? Number.POSITIVE_INFINITY;
1145
- const bi = idx[b.planId] ?? Number.POSITIVE_INFINITY;
1146
- if (ai !== bi) return ai - bi;
1147
- return a.planId.localeCompare(b.planId);
1148
- });
1149
- }
1150
- function buildSnapshots(data, options = {}) {
1151
- const locale = options.locale ?? DEFAULT_SA_LOCALE;
1152
- const sortPlansFn = sortPlansBy(options.planSortOrder);
1153
- const drafts = buildDraftsSnapshot(data, sortPlansFn, locale);
1154
- const active = buildActiveSnapshot(data, sortPlansFn, locale);
1155
- const historical = buildHistoricalSnapshots(data, sortPlansFn, locale);
1156
- const out = [drafts];
1157
- if (active) out.push(active);
1158
- out.push(...historical);
1159
- return out;
1160
- }
1161
- function listOpenDrafts(data) {
1162
- return {
1163
- plans: sortByPublishedDesc(data.planVersions).filter((r) => r.publishedAt === null)
1164
- };
1165
- }
1166
-
1167
705
  // src/client/i18n/currency.ts
1168
706
  var DEFAULT_CURRENCY = "EUR";
1169
707
  var formatters = /* @__PURE__ */ new Map();
@@ -3030,6 +2568,114 @@ var planEditorMessages = defineMessages(
3030
2568
  }
3031
2569
  );
3032
2570
 
2571
+ // src/client/i18n/messages/plan-versions.ts
2572
+ var planVersionsMessages = defineMessages(
2573
+ {
2574
+ compareEnd: "Vergleich beenden",
2575
+ status: {
2576
+ draft: "DRAFT",
2577
+ active: "AKTIV",
2578
+ archived: "ARCHIV"
2579
+ },
2580
+ timeline: {
2581
+ title: "Plan-Catalog",
2582
+ snapshotCount: "{count} Snapshots",
2583
+ noOpenDrafts: "keine offenen Drafts",
2584
+ openCount: "{count} offen",
2585
+ unknown: "unbekannt",
2586
+ compareHint: "Rechtsklick auf Snapshot \u2192 vergleichen"
2587
+ },
2588
+ diff: {
2589
+ legend: "Vergleich",
2590
+ plansChanged: "Pakete ge\xE4ndert",
2591
+ regressions: "Regressionen",
2592
+ sectionPlans: "Pakete",
2593
+ changeCountOne: "{count} \xC4nderung",
2594
+ changeCountMany: "{count} \xC4nderungen"
2595
+ },
2596
+ diffPreview: {
2597
+ empty: "Keine \xC4nderungen gegen\xFCber der Vorg\xE4ngerversion.",
2598
+ improvement: "Verbesserung",
2599
+ regression: "Verschlechterung",
2600
+ neutral: "Neutral"
2601
+ },
2602
+ diffFields: {
2603
+ featuresAdded: "Hinzugef\xFCgte Features",
2604
+ featuresRemoved: "Entfernte Features",
2605
+ maxUsers: "Max. Benutzer",
2606
+ maxStorageGb: "Speicher (GB)",
2607
+ monthlyNet: "Preis monatlich (netto)",
2608
+ yearlyNet: "Preis j\xE4hrlich (netto)",
2609
+ unitSize: "Einheitsgr\xF6\xDFe"
2610
+ },
2611
+ bulkPublish: {
2612
+ changeNoteRequired: "changeNote ist Pflicht beim Publish."
2613
+ },
2614
+ format: {
2615
+ today: "heute",
2616
+ yesterday: "gestern",
2617
+ daysAgo: "vor {count} Tagen",
2618
+ weeksAgoOne: "vor {count} Woche",
2619
+ weeksAgoMany: "vor {count} Wochen",
2620
+ monthsAgo: "vor {count} Monaten",
2621
+ yearsAgoOne: "vor {count} Jahr",
2622
+ yearsAgoMany: "vor {count} Jahren"
2623
+ }
2624
+ },
2625
+ {
2626
+ compareEnd: "End comparison",
2627
+ status: {
2628
+ draft: "DRAFT",
2629
+ active: "ACTIVE",
2630
+ archived: "ARCHIVED"
2631
+ },
2632
+ timeline: {
2633
+ title: "Plan catalog",
2634
+ snapshotCount: "{count} snapshots",
2635
+ noOpenDrafts: "no open drafts",
2636
+ openCount: "{count} open",
2637
+ unknown: "unknown",
2638
+ compareHint: "Right-click a snapshot \u2192 compare"
2639
+ },
2640
+ diff: {
2641
+ legend: "Comparison",
2642
+ plansChanged: "Plans changed",
2643
+ regressions: "Regressions",
2644
+ sectionPlans: "Plans",
2645
+ changeCountOne: "{count} change",
2646
+ changeCountMany: "{count} changes"
2647
+ },
2648
+ diffPreview: {
2649
+ empty: "No changes compared to the previous version.",
2650
+ improvement: "Improvement",
2651
+ regression: "Regression",
2652
+ neutral: "Neutral"
2653
+ },
2654
+ diffFields: {
2655
+ featuresAdded: "Added features",
2656
+ featuresRemoved: "Removed features",
2657
+ maxUsers: "Max. users",
2658
+ maxStorageGb: "Storage (GB)",
2659
+ monthlyNet: "Price monthly (net)",
2660
+ yearlyNet: "Price yearly (net)",
2661
+ unitSize: "Unit size"
2662
+ },
2663
+ bulkPublish: {
2664
+ changeNoteRequired: "changeNote is required when publishing."
2665
+ },
2666
+ format: {
2667
+ today: "today",
2668
+ yesterday: "yesterday",
2669
+ daysAgo: "{count} days ago",
2670
+ weeksAgoOne: "{count} week ago",
2671
+ weeksAgoMany: "{count} weeks ago",
2672
+ monthsAgo: "{count} months ago",
2673
+ yearsAgoOne: "{count} year ago",
2674
+ yearsAgoMany: "{count} years ago"
2675
+ }
2676
+ }
2677
+ );
2678
+
3033
2679
  // src/client/i18n/messages/plans.ts
3034
2680
  var plansMessages = defineMessages(
3035
2681
  {
@@ -4877,30 +4523,8 @@ function useSubscriptionDraft(options) {
4877
4523
  };
4878
4524
  }
4879
4525
 
4880
- // src/vue/use-plan-versions.ts
4881
- var import_vue13 = require("vue");
4882
- function buildVersionsComposable(label) {
4883
- return function(options) {
4884
- if (!options?.endpoint) {
4885
- throw new Error(
4886
- `${label}: \`endpoint\` is required (e.g. "/api/admin/${label}" or "/api/v1/admin/${label}"). The platform has no default because apps use different globalPrefix conventions.`
4887
- );
4888
- }
4889
- const filter = options.filter ?? (0, import_vue13.ref)({});
4890
- const list = useApiList({
4891
- endpoint: options.endpoint,
4892
- filter,
4893
- http: options.http,
4894
- getAuthToken: options.getAuthToken,
4895
- autoLoad: options.autoLoad
4896
- });
4897
- return { ...list, filter };
4898
- };
4899
- }
4900
- var usePlanVersionsCatalog = buildVersionsComposable("plan-versions");
4901
-
4902
4526
  // src/vue/use-bulk-publish.ts
4903
- var import_vue14 = require("vue");
4527
+ var import_vue13 = require("vue");
4904
4528
  function useBulkPublish(options) {
4905
4529
  const msg = useSaMessages("planVersions");
4906
4530
  if (!options?.endpoints) {
@@ -4910,15 +4534,15 @@ function useBulkPublish(options) {
4910
4534
  }
4911
4535
  const http = options.http ?? defaultHttpClient();
4912
4536
  const endpoints = options.endpoints;
4913
- const items = (0, import_vue14.ref)([]);
4914
- const successCount = (0, import_vue14.computed)(() => items.value.filter((i) => i.status === "published").length);
4915
- const failureCount = (0, import_vue14.computed)(() => items.value.filter((i) => i.status === "failed").length);
4916
- const progress = (0, import_vue14.computed)(() => {
4537
+ const items = (0, import_vue13.ref)([]);
4538
+ const successCount = (0, import_vue13.computed)(() => items.value.filter((i) => i.status === "published").length);
4539
+ const failureCount = (0, import_vue13.computed)(() => items.value.filter((i) => i.status === "failed").length);
4540
+ const progress = (0, import_vue13.computed)(() => {
4917
4541
  if (items.value.length === 0) return 0;
4918
4542
  const done2 = successCount.value + failureCount.value;
4919
4543
  return done2 / items.value.length;
4920
4544
  });
4921
- const done = (0, import_vue14.computed)(
4545
+ const done = (0, import_vue13.computed)(
4922
4546
  () => items.value.length > 0 && items.value.every((i) => i.status === "published" || i.status === "failed")
4923
4547
  );
4924
4548
  function setItems(next) {
@@ -4976,7 +4600,7 @@ function useBulkPublish(options) {
4976
4600
  }
4977
4601
 
4978
4602
  // src/vue/use-plan-editor.ts
4979
- var import_vue15 = require("vue");
4603
+ var import_vue14 = require("vue");
4980
4604
  var PlannedOnlyFeatureError = class extends Error {
4981
4605
  constructor(violations) {
4982
4606
  super(
@@ -4996,10 +4620,10 @@ function tierWeight(tier) {
4996
4620
  function usePlanEditor(manifest, options = {}) {
4997
4621
  const baseSet = new Set(options.baseFeatures ?? []);
4998
4622
  const nonRegressive = options.nonRegressive ?? true;
4999
- const selectedFeatures = (0, import_vue15.ref)(new Set(options.initialFeatures ?? []));
4623
+ const selectedFeatures = (0, import_vue14.ref)(new Set(options.initialFeatures ?? []));
5000
4624
  const catalogFeatures = manifest.planCatalogSnapshot.features ?? [];
5001
4625
  const plannedOnlySet = new Set(catalogFeatures.filter((f) => f.plannedOnly).map((f) => f.key));
5002
- const availableFeatures = (0, import_vue15.computed)(() => {
4626
+ const availableFeatures = (0, import_vue14.computed)(() => {
5003
4627
  return catalogFeatures.map((def) => {
5004
4628
  const isSelected = selectedFeatures.value.has(def.key);
5005
4629
  const isPlannedOnly = !!def.plannedOnly;
@@ -5008,7 +4632,7 @@ function usePlanEditor(manifest, options = {}) {
5008
4632
  return { def, isSelected, isPlannedOnly, isInherited, canToggle };
5009
4633
  });
5010
4634
  });
5011
- const featuresByTier = (0, import_vue15.computed)(() => {
4635
+ const featuresByTier = (0, import_vue14.computed)(() => {
5012
4636
  const groups = /* @__PURE__ */ new Map();
5013
4637
  for (const row of availableFeatures.value) {
5014
4638
  const tier = row.def.tier ?? "OTHER";
@@ -5053,12 +4677,12 @@ function usePlanEditor(manifest, options = {}) {
5053
4677
  }
5054
4678
 
5055
4679
  // src/vue/use-public-boot.ts
5056
- var import_vue16 = require("vue");
4680
+ var import_vue15 = require("vue");
5057
4681
  function usePublicBoot(options) {
5058
4682
  const loader = new BootLoader(options);
5059
- const boot = (0, import_vue16.ref)(null);
5060
- const loading = (0, import_vue16.ref)(false);
5061
- const error = (0, import_vue16.ref)(null);
4683
+ const boot = (0, import_vue15.ref)(null);
4684
+ const loading = (0, import_vue15.ref)(false);
4685
+ const error = (0, import_vue15.ref)(null);
5062
4686
  async function load() {
5063
4687
  loading.value = true;
5064
4688
  error.value = null;
@@ -5075,7 +4699,7 @@ function usePublicBoot(options) {
5075
4699
  }
5076
4700
 
5077
4701
  // src/vue/use-discovery.ts
5078
- var import_vue17 = require("vue");
4702
+ var import_vue16 = require("vue");
5079
4703
  var DiscoveryLoadError = class extends Error {
5080
4704
  constructor(status, message) {
5081
4705
  super(message);
@@ -5092,10 +4716,10 @@ function useDiscovery(options) {
5092
4716
  );
5093
4717
  }
5094
4718
  const http = options.http ?? defaultHttpClient();
5095
- const snapshot = (0, import_vue17.ref)(null);
5096
- const etag = (0, import_vue17.ref)(null);
5097
- const loading = (0, import_vue17.ref)(false);
5098
- const error = (0, import_vue17.ref)(null);
4719
+ const snapshot = (0, import_vue16.ref)(null);
4720
+ const etag = (0, import_vue16.ref)(null);
4721
+ const loading = (0, import_vue16.ref)(false);
4722
+ const error = (0, import_vue16.ref)(null);
5099
4723
  async function fetchSnapshot(includeEtag) {
5100
4724
  loading.value = true;
5101
4725
  error.value = null;
@@ -5162,7 +4786,7 @@ function useDiscovery(options) {
5162
4786
  }
5163
4787
 
5164
4788
  // src/vue/use-catalog-entries.ts
5165
- var import_vue18 = require("vue");
4789
+ var import_vue17 = require("vue");
5166
4790
  var CatalogEntriesApiError = class extends Error {
5167
4791
  constructor(status, body, message) {
5168
4792
  super(message);
@@ -5182,11 +4806,11 @@ function useCatalogEntries(options) {
5182
4806
  }
5183
4807
  const msg = useSaMessages("discovery");
5184
4808
  const http = options.http ?? defaultHttpClient();
5185
- const capabilities = (0, import_vue18.ref)([]);
5186
- const features = (0, import_vue18.ref)([]);
5187
- const quotas = (0, import_vue18.ref)([]);
5188
- const loading = (0, import_vue18.ref)(false);
5189
- const error = (0, import_vue18.ref)(null);
4809
+ const capabilities = (0, import_vue17.ref)([]);
4810
+ const features = (0, import_vue17.ref)([]);
4811
+ const quotas = (0, import_vue17.ref)([]);
4812
+ const loading = (0, import_vue17.ref)(false);
4813
+ const error = (0, import_vue17.ref)(null);
5190
4814
  const base = `${options.adminEndpoint}/catalog`;
5191
4815
  const pk = encodeURIComponent(options.projectKey);
5192
4816
  function authHeaders() {
@@ -5312,7 +4936,7 @@ function useCatalogEntries(options) {
5312
4936
  }
5313
4937
 
5314
4938
  // src/vue/use-bundles.ts
5315
- var import_vue19 = require("vue");
4939
+ var import_vue18 = require("vue");
5316
4940
  var BundlesApiError = class extends Error {
5317
4941
  constructor(status, body, message) {
5318
4942
  super(message);
@@ -5333,9 +4957,9 @@ function useBundles(options) {
5333
4957
  throw new Error("useBundles: `projectKey` is required.");
5334
4958
  }
5335
4959
  const http = options.http ?? defaultHttpClient();
5336
- const bundles = (0, import_vue19.ref)([]);
5337
- const loading = (0, import_vue19.ref)(false);
5338
- const error = (0, import_vue19.ref)(null);
4960
+ const bundles = (0, import_vue18.ref)([]);
4961
+ const loading = (0, import_vue18.ref)(false);
4962
+ const error = (0, import_vue18.ref)(null);
5339
4963
  const baseUrl = `${options.adminEndpoint}/catalog/bundles`;
5340
4964
  function authHeaders() {
5341
4965
  const token = options.getAuthToken?.();
@@ -5407,9 +5031,9 @@ function useBundleVersions(options) {
5407
5031
  throw new Error("useBundleVersions: `bundleId` is required.");
5408
5032
  }
5409
5033
  const http = options.http ?? defaultHttpClient();
5410
- const versions = (0, import_vue19.ref)([]);
5411
- const loading = (0, import_vue19.ref)(false);
5412
- const error = (0, import_vue19.ref)(null);
5034
+ const versions = (0, import_vue18.ref)([]);
5035
+ const loading = (0, import_vue18.ref)(false);
5036
+ const error = (0, import_vue18.ref)(null);
5413
5037
  const bundleVersionsUrl = `${options.adminEndpoint}/catalog/bundles/${options.bundleId}/versions`;
5414
5038
  const versionUrlBase = `${options.adminEndpoint}/catalog/bundle-versions`;
5415
5039
  function authHeaders() {
@@ -5483,7 +5107,7 @@ function useBundleVersions(options) {
5483
5107
  }
5484
5108
 
5485
5109
  // src/vue/use-bundle-versions-map.ts
5486
- var import_vue20 = require("vue");
5110
+ var import_vue19 = require("vue");
5487
5111
  function useBundleVersionsMap(options) {
5488
5112
  if (!options?.adminEndpoint) {
5489
5113
  throw new Error("useBundleVersionsMap: `adminEndpoint` is required.");
@@ -5492,9 +5116,9 @@ function useBundleVersionsMap(options) {
5492
5116
  throw new Error("useBundleVersionsMap: `bundles` is required.");
5493
5117
  }
5494
5118
  const http = options.http ?? defaultHttpClient();
5495
- const versionsByBundle = (0, import_vue20.ref)({});
5496
- const loading = (0, import_vue20.ref)(false);
5497
- const error = (0, import_vue20.ref)(null);
5119
+ const versionsByBundle = (0, import_vue19.ref)({});
5120
+ const loading = (0, import_vue19.ref)(false);
5121
+ const error = (0, import_vue19.ref)(null);
5498
5122
  function authHeaders() {
5499
5123
  const token = options.getAuthToken?.();
5500
5124
  return token ? { Authorization: `Bearer ${token}` } : {};
@@ -5544,7 +5168,7 @@ function useBundleVersionsMap(options) {
5544
5168
  console.warn(`useBundleVersionsMap: refreshOne('${bundleId}') failed`, err);
5545
5169
  }
5546
5170
  }
5547
- (0, import_vue20.watch)(
5171
+ (0, import_vue19.watch)(
5548
5172
  () => options.bundles.value.map((b) => b.id).join(","),
5549
5173
  () => {
5550
5174
  if (options.bundles.value.length > 0) void refresh();
@@ -5556,7 +5180,7 @@ function useBundleVersionsMap(options) {
5556
5180
  }
5557
5181
 
5558
5182
  // src/vue/use-tenant-subscription-bundles.ts
5559
- var import_vue21 = require("vue");
5183
+ var import_vue20 = require("vue");
5560
5184
  var TenantSubscriptionBundlesApiError = class extends Error {
5561
5185
  constructor(status, body, message) {
5562
5186
  super(message);
@@ -5575,9 +5199,9 @@ function useTenantSubscriptionBundles(options) {
5575
5199
  }
5576
5200
  const http = options.http ?? defaultHttpClient();
5577
5201
  const baseUrl = `${options.billingEndpoint}/billing/subscription-bundles`;
5578
- const bundles = (0, import_vue21.ref)([]);
5579
- const loading = (0, import_vue21.ref)(false);
5580
- const error = (0, import_vue21.ref)(null);
5202
+ const bundles = (0, import_vue20.ref)([]);
5203
+ const loading = (0, import_vue20.ref)(false);
5204
+ const error = (0, import_vue20.ref)(null);
5581
5205
  function authHeaders() {
5582
5206
  const token = options.getAuthToken?.();
5583
5207
  return token ? { Authorization: `Bearer ${token}` } : {};
@@ -5651,7 +5275,7 @@ function rehydrateDates(raw) {
5651
5275
  }
5652
5276
 
5653
5277
  // src/vue/use-marketing-projections.ts
5654
- var import_vue22 = require("vue");
5278
+ var import_vue21 = require("vue");
5655
5279
  var MarketingProjectionsApiError = class extends Error {
5656
5280
  constructor(status, body, message) {
5657
5281
  super(message);
@@ -5671,10 +5295,10 @@ function useMarketingProjections(options) {
5671
5295
  }
5672
5296
  const msg = useSaMessages("marketing");
5673
5297
  const http = options.http ?? defaultHttpClient();
5674
- const projections = (0, import_vue22.ref)([]);
5675
- const filter = (0, import_vue22.ref)({ ...options.filter });
5676
- const loading = (0, import_vue22.ref)(false);
5677
- const error = (0, import_vue22.ref)(null);
5298
+ const projections = (0, import_vue21.ref)([]);
5299
+ const filter = (0, import_vue21.ref)({ ...options.filter });
5300
+ const loading = (0, import_vue21.ref)(false);
5301
+ const error = (0, import_vue21.ref)(null);
5678
5302
  const baseUrl = `${options.adminEndpoint}/catalog/marketing-projections`;
5679
5303
  function authHeaders() {
5680
5304
  const token = options.getAuthToken?.();
@@ -5755,7 +5379,7 @@ function useMarketingProjections(options) {
5755
5379
  }
5756
5380
 
5757
5381
  // src/vue/use-promotions.ts
5758
- var import_vue23 = require("vue");
5382
+ var import_vue22 = require("vue");
5759
5383
  var PromotionsApiError = class extends Error {
5760
5384
  constructor(status, body, message) {
5761
5385
  super(message);
@@ -5775,9 +5399,9 @@ function usePromotions(options) {
5775
5399
  }
5776
5400
  const msg = useSaMessages("promos");
5777
5401
  const http = options.http ?? defaultHttpClient();
5778
- const promotions = (0, import_vue23.ref)([]);
5779
- const loading = (0, import_vue23.ref)(false);
5780
- const error = (0, import_vue23.ref)(null);
5402
+ const promotions = (0, import_vue22.ref)([]);
5403
+ const loading = (0, import_vue22.ref)(false);
5404
+ const error = (0, import_vue22.ref)(null);
5781
5405
  const baseUrl = `${options.adminEndpoint}/catalog/promotions`;
5782
5406
  const pk = encodeURIComponent(options.projectKey);
5783
5407
  function authHeaders() {
@@ -5842,7 +5466,7 @@ function usePromotions(options) {
5842
5466
  }
5843
5467
 
5844
5468
  // src/vue/use-plans.ts
5845
- var import_vue24 = require("vue");
5469
+ var import_vue23 = require("vue");
5846
5470
  var PlansApiError = class extends Error {
5847
5471
  constructor(status, body, message) {
5848
5472
  super(message);
@@ -5863,10 +5487,10 @@ function usePlans(options) {
5863
5487
  throw new Error("usePlans: `projectKey` is required.");
5864
5488
  }
5865
5489
  const http = options.http ?? defaultHttpClient();
5866
- const plans = (0, import_vue24.ref)([]);
5867
- const loading = (0, import_vue24.ref)(false);
5868
- const error = (0, import_vue24.ref)(null);
5869
- const tenantCountsByPlanKey = (0, import_vue24.ref)({});
5490
+ const plans = (0, import_vue23.ref)([]);
5491
+ const loading = (0, import_vue23.ref)(false);
5492
+ const error = (0, import_vue23.ref)(null);
5493
+ const tenantCountsByPlanKey = (0, import_vue23.ref)({});
5870
5494
  const baseUrl = `${options.adminEndpoint}/catalog/plans`;
5871
5495
  function authHeaders() {
5872
5496
  const token = options.getAuthToken?.();
@@ -5967,9 +5591,9 @@ function usePlanVersions(options) {
5967
5591
  throw new Error("usePlanVersions: `planId` is required.");
5968
5592
  }
5969
5593
  const http = options.http ?? defaultHttpClient();
5970
- const versions = (0, import_vue24.ref)([]);
5971
- const loading = (0, import_vue24.ref)(false);
5972
- const error = (0, import_vue24.ref)(null);
5594
+ const versions = (0, import_vue23.ref)([]);
5595
+ const loading = (0, import_vue23.ref)(false);
5596
+ const error = (0, import_vue23.ref)(null);
5973
5597
  const planVersionsUrl = `${options.adminEndpoint}/catalog/plans/${options.planId}/versions`;
5974
5598
  const versionUrlBase = `${options.adminEndpoint}/catalog/plan-versions`;
5975
5599
  function authHeaders() {
@@ -6066,7 +5690,7 @@ function usePlanVersions(options) {
6066
5690
  }
6067
5691
 
6068
5692
  // src/vue/use-live-plan-versions.ts
6069
- var import_vue25 = require("vue");
5693
+ var import_vue24 = require("vue");
6070
5694
  function useLivePlanVersions(options) {
6071
5695
  if (!options?.adminEndpoint) {
6072
5696
  throw new Error("useLivePlanVersions: `adminEndpoint` is required.");
@@ -6075,9 +5699,9 @@ function useLivePlanVersions(options) {
6075
5699
  throw new Error("useLivePlanVersions: `plans` is required.");
6076
5700
  }
6077
5701
  const http = options.http ?? defaultHttpClient();
6078
- const livePlanVersions = (0, import_vue25.ref)({});
6079
- const loading = (0, import_vue25.ref)(false);
6080
- const error = (0, import_vue25.ref)(null);
5702
+ const livePlanVersions = (0, import_vue24.ref)({});
5703
+ const loading = (0, import_vue24.ref)(false);
5704
+ const error = (0, import_vue24.ref)(null);
6081
5705
  function authHeaders() {
6082
5706
  const token = options.getAuthToken?.();
6083
5707
  return token ? { Authorization: `Bearer ${token}` } : {};
@@ -6119,7 +5743,7 @@ function useLivePlanVersions(options) {
6119
5743
  loading.value = false;
6120
5744
  }
6121
5745
  }
6122
- (0, import_vue25.watch)(
5746
+ (0, import_vue24.watch)(
6123
5747
  () => options.plans.value.map((p) => p.id).join(","),
6124
5748
  () => {
6125
5749
  if (options.plans.value.length > 0) void refresh();
@@ -6141,12 +5765,12 @@ function findLatestLive(versions) {
6141
5765
  }
6142
5766
 
6143
5767
  // src/vue/use-manifest.ts
6144
- var import_vue26 = require("vue");
5768
+ var import_vue25 = require("vue");
6145
5769
  function useManifest(options) {
6146
5770
  const loader = new ManifestLoader(options);
6147
- const manifest = (0, import_vue26.ref)(null);
6148
- const loading = (0, import_vue26.ref)(false);
6149
- const error = (0, import_vue26.ref)(null);
5771
+ const manifest = (0, import_vue25.ref)(null);
5772
+ const loading = (0, import_vue25.ref)(false);
5773
+ const error = (0, import_vue25.ref)(null);
6150
5774
  async function load() {
6151
5775
  loading.value = true;
6152
5776
  error.value = null;
@@ -6172,24 +5796,24 @@ function useManifest(options) {
6172
5796
  }
6173
5797
 
6174
5798
  // src/vue/use-nav.ts
6175
- var import_vue27 = require("vue");
5799
+ var import_vue26 = require("vue");
6176
5800
  function useNav(manifest, options = {}) {
6177
5801
  const { locale } = useSuperAdminI18n();
6178
- const activeLocale = (0, import_vue27.computed)(() => options.locale ?? locale.value);
6179
- const routes = (0, import_vue27.computed)(() => {
5802
+ const activeLocale = (0, import_vue26.computed)(() => options.locale ?? locale.value);
5803
+ const routes = (0, import_vue26.computed)(() => {
6180
5804
  if (!manifest.value) return [];
6181
5805
  return buildRoutes(manifest.value, { ...options, locale: activeLocale.value });
6182
5806
  });
6183
- const sidebar = (0, import_vue27.computed)(
5807
+ const sidebar = (0, import_vue26.computed)(
6184
5808
  () => buildSidebar(routes.value, defaultSectionOrder(activeLocale.value))
6185
5809
  );
6186
5810
  return { routes, sidebar };
6187
5811
  }
6188
5812
 
6189
5813
  // src/vue/use-actions.ts
6190
- var import_vue28 = require("vue");
5814
+ var import_vue27 = require("vue");
6191
5815
  function useActions(manifest, actions) {
6192
- const registry = (0, import_vue28.computed)(() => {
5816
+ const registry = (0, import_vue27.computed)(() => {
6193
5817
  if (!manifest.value) return null;
6194
5818
  return new ActionRegistry(manifest.value, actions);
6195
5819
  });
@@ -6197,18 +5821,18 @@ function useActions(manifest, actions) {
6197
5821
  }
6198
5822
 
6199
5823
  // src/vue/use-tenant-action-flow.ts
6200
- var import_vue29 = require("vue");
5824
+ var import_vue28 = require("vue");
6201
5825
  function useTenantActionFlow(manifest, providers = {}) {
6202
5826
  const handlers = useSuperAdminActions();
6203
5827
  const msg = useSaMessages("tenants");
6204
- const registry = (0, import_vue29.computed)(() => {
5828
+ const registry = (0, import_vue28.computed)(() => {
6205
5829
  if (!manifest.value) return null;
6206
5830
  return new ActionRegistry(manifest.value, handlers);
6207
5831
  });
6208
- const orphanedDefs = (0, import_vue29.computed)(
5832
+ const orphanedDefs = (0, import_vue28.computed)(
6209
5833
  () => registry.value ? registry.value.listOrphanedDefs() : []
6210
5834
  );
6211
- const availableActions = (0, import_vue29.computed)(() => {
5835
+ const availableActions = (0, import_vue28.computed)(() => {
6212
5836
  const m = manifest.value;
6213
5837
  const reg = registry.value;
6214
5838
  if (!m || !reg) return [];
@@ -6281,7 +5905,7 @@ async function runFlow(def, row, registry, providers, successTemplate) {
6281
5905
  }
6282
5906
 
6283
5907
  // src/vue/use-platform-tenant-actions.ts
6284
- var import_vue30 = require("vue");
5908
+ var import_vue29 = require("vue");
6285
5909
  var DEFAULT_VISIBLE_FOR_ROW = (def, row) => {
6286
5910
  if (def.actionKey === "tenants.suspend") return row.isActive;
6287
5911
  if (def.actionKey === "tenants.reactivate") return !row.isActive;
@@ -6317,7 +5941,7 @@ function usePlatformTenantActions(options) {
6317
5941
  const iconForActionKey = options.iconForActionKey ?? DEFAULT_ICON_FOR_ACTION_KEY;
6318
5942
  const toneForActionKey = options.toneForActionKey ?? DEFAULT_TONE_FOR_ACTION_KEY;
6319
5943
  const visibleForRow = options.visibleForRow ?? DEFAULT_VISIBLE_FOR_ROW;
6320
- const mfa = (0, import_vue30.ref)({ show: false, description: "", error: "" });
5944
+ const mfa = (0, import_vue29.ref)({ show: false, description: "", error: "" });
6321
5945
  let pendingMfaResolve = null;
6322
5946
  function showMfaDialog(def, ctx) {
6323
5947
  return new Promise((resolve) => {
@@ -6342,7 +5966,7 @@ function usePlatformTenantActions(options) {
6342
5966
  pendingMfaResolve(null);
6343
5967
  }
6344
5968
  }
6345
- const confirmDialog = (0, import_vue30.ref)({
5969
+ const confirmDialog = (0, import_vue29.ref)({
6346
5970
  show: false,
6347
5971
  def: null,
6348
5972
  row: null
@@ -6384,7 +6008,7 @@ function usePlatformTenantActions(options) {
6384
6008
  },
6385
6009
  visibleForRow
6386
6010
  });
6387
- const manifestActions = (0, import_vue30.computed)(
6011
+ const manifestActions = (0, import_vue29.computed)(
6388
6012
  () => flow.availableActions.value.map((def) => ({
6389
6013
  id: def.id,
6390
6014
  label: def.label,
@@ -6398,7 +6022,7 @@ function usePlatformTenantActions(options) {
6398
6022
  }
6399
6023
  }))
6400
6024
  );
6401
- const realOrphans = (0, import_vue30.computed)(() => {
6025
+ const realOrphans = (0, import_vue29.computed)(() => {
6402
6026
  const caps = options.manifest.value?.capabilities ?? {};
6403
6027
  const defs = options.manifest.value?.tenants?.actions ?? [];
6404
6028
  const defByActionKey = new Map(defs.map((d) => [d.actionKey, d]));
@@ -6423,12 +6047,12 @@ function usePlatformTenantActions(options) {
6423
6047
  }
6424
6048
 
6425
6049
  // src/vue/use-batch-columns.ts
6426
- var import_vue31 = require("vue");
6050
+ var import_vue30 = require("vue");
6427
6051
  function useBatchColumns(manifest, tenantIds, options = {}) {
6428
6052
  const fetcher = new BatchColumnFetcher(options);
6429
- const data = (0, import_vue31.ref)({});
6430
- const loading = (0, import_vue31.ref)(false);
6431
- const error = (0, import_vue31.ref)(null);
6053
+ const data = (0, import_vue30.ref)({});
6054
+ const loading = (0, import_vue30.ref)(false);
6055
+ const error = (0, import_vue30.ref)(null);
6432
6056
  async function load() {
6433
6057
  if (!manifest.value || tenantIds.value.length === 0) {
6434
6058
  data.value = {};
@@ -6445,7 +6069,7 @@ function useBatchColumns(manifest, tenantIds, options = {}) {
6445
6069
  loading.value = false;
6446
6070
  }
6447
6071
  }
6448
- (0, import_vue31.watch)([manifest, tenantIds], () => {
6072
+ (0, import_vue30.watch)([manifest, tenantIds], () => {
6449
6073
  void load();
6450
6074
  });
6451
6075
  return { data, loading, error, reload: load };
@@ -6477,13 +6101,13 @@ function createPlatformLoaders(options) {
6477
6101
 
6478
6102
  // src/vue/manifest-store-factory.ts
6479
6103
  var import_pinia = require("pinia");
6480
- var import_vue32 = require("vue");
6104
+ var import_vue31 = require("vue");
6481
6105
  function createManifestStore(options) {
6482
6106
  return (0, import_pinia.defineStore)(options.id ?? "admin-manifest", () => {
6483
- const manifest = (0, import_vue32.ref)(null);
6484
- const loading = (0, import_vue32.ref)(false);
6485
- const error = (0, import_vue32.ref)(null);
6486
- const loaded = (0, import_vue32.ref)(false);
6107
+ const manifest = (0, import_vue31.ref)(null);
6108
+ const loading = (0, import_vue31.ref)(false);
6109
+ const error = (0, import_vue31.ref)(null);
6110
+ const loaded = (0, import_vue31.ref)(false);
6487
6111
  let inflight = null;
6488
6112
  async function load() {
6489
6113
  loading.value = true;
@@ -6908,7 +6532,6 @@ function defaultTenantPlanSectionI18n(locale) {
6908
6532
  buildQuotaRegistry,
6909
6533
  buildRoutes,
6910
6534
  buildSidebar,
6911
- buildSnapshots,
6912
6535
  createAdminRoutes,
6913
6536
  createManifestStore,
6914
6537
  createPlatformLoaders,
@@ -6924,7 +6547,6 @@ function defaultTenantPlanSectionI18n(locale) {
6924
6547
  formatCurrency,
6925
6548
  formatMessage,
6926
6549
  getJson,
6927
- listOpenDrafts,
6928
6550
  mergeMessages,
6929
6551
  postJson,
6930
6552
  provideEntitlement,
@@ -6949,7 +6571,6 @@ function defaultTenantPlanSectionI18n(locale) {
6949
6571
  useNav,
6950
6572
  usePlanEditor,
6951
6573
  usePlanVersions,
6952
- usePlanVersionsCatalog,
6953
6574
  usePlans,
6954
6575
  usePlatformTenantActions,
6955
6576
  usePromotions,