@vritti/api-sdk 0.3.5 → 0.3.7

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.
@@ -1,51 +1,9 @@
1
- import { S as ScopeType, a as SiteType, P as PlatformBucket, b as SiteFeatureLocks, V as VersionSnapshot, F as FeatureCatalogEntry, R as RoleItem, c as SnapshotFeature, d as PlatformCodes, e as FeatureUnlocks, f as PlatformDenyCodes, L as LockReason } from './types-C9jPdQqH.cjs';
2
- export { B as BusinessVocabulary, C as CatalogPermission, g as FeatureLocks, h as PLATFORMS, i as SITE_TYPES, j as SNAPSHOT_SCHEMA_VERSION, k as SnapshotApp, l as SnapshotAppFeatureRef, n as SnapshotBusiness, o as SnapshotMicrofrontendMobile, q as SnapshotMicrofrontendWeb, p as SnapshotMicrofrontends, r as SnapshotPermission, s as SnapshotPlan, t as SnapshotRoleTemplate, m as VocabularyEntry, u as snapshotFeatureKey } from './types-C9jPdQqH.cjs';
3
-
4
- interface SiteMatrixCell {
5
- inPlan: boolean;
6
- selected: boolean;
7
- availableIn: string[];
8
- }
9
- interface SiteMatrixPermission {
10
- code: string;
11
- label: string;
12
- dependsOn: string[];
13
- web: SiteMatrixCell | null;
14
- mobile: SiteMatrixCell | null;
15
- }
16
- interface SiteMatrixFeature {
17
- code: string;
18
- name: string;
19
- icon: string | null;
20
- scope: ScopeType;
21
- applicableSiteTypes: SiteType[];
22
- platforms: PlatformBucket[];
23
- inPlan: boolean;
24
- availableIn: string[];
25
- permissions: SiteMatrixPermission[];
26
- }
27
- interface SiteMatrixApp {
28
- code: string;
29
- name: string;
30
- icon: string | null;
31
- unlockedCount: number;
32
- totalCount: number;
33
- features: SiteMatrixFeature[];
34
- }
35
- interface SiteMatrix {
36
- plan: {
37
- code: string;
38
- name: string;
39
- };
40
- apps: SiteMatrixApp[];
41
- locks: SiteFeatureLocks;
42
- }
43
- declare function buildSiteMatrix(snapshot: VersionSnapshot, businessCode: string | undefined, planCode: string | undefined, siteLocks: SiteFeatureLocks | undefined, siteType?: SiteType): SiteMatrix;
44
- declare function buildPlanMatrix(snapshot: VersionSnapshot, businessCode: string | undefined, planCode: string | undefined, siteLocks?: SiteFeatureLocks): SiteMatrix;
1
+ import { V as VersionSnapshot, S as SiteFeatureLocks, P as PlatformBucket, a as SiteType, b as ScopeType, c as ServiceCode, F as FeatureCatalogEntry, R as RoleItem, d as SnapshotFeature, e as PlatformCodes, f as FeatureUnlocks, g as PlatformDenyCodes, L as LockReason } from './types-BBK6MG-U.cjs';
2
+ export { B as BusinessVocabulary, C as CatalogPermission, h as FeatureLocks, i as PLATFORMS, j as SERVICE_CODES, k as SITE_TYPES, l as SNAPSHOT_SCHEMA_VERSION, m as SnapshotApp, n as SnapshotAppFeatureRef, o as SnapshotBusiness, p as SnapshotMicrofrontendMobile, r as SnapshotMicrofrontendWeb, q as SnapshotMicrofrontends, s as SnapshotPermission, t as SnapshotPlan, u as SnapshotRoleTemplate, w as VocabularyEntry, v as snapshotFeatureKey } from './types-BBK6MG-U.cjs';
45
3
 
46
4
  declare function featureAppliesAtNode(applicableSiteTypes: SiteType[], siteType: SiteType): boolean;
47
5
  declare function findFeatureByCode(snapshot: VersionSnapshot, code: string): SnapshotFeature | undefined;
48
- declare function buildSiteCatalog(snapshot: VersionSnapshot, businessCode: string | undefined, planCode: string | undefined, siteLocks: SiteFeatureLocks | undefined, bucket: PlatformBucket, siteType?: SiteType, scope?: ScopeType): FeatureCatalogEntry[];
6
+ declare function buildSiteCatalog(snapshot: VersionSnapshot, businessCode: string | undefined, planCode: string | undefined, siteLocks: SiteFeatureLocks | undefined, bucket: PlatformBucket, siteType?: SiteType, scope?: ScopeType, availableServices?: ServiceCode[]): FeatureCatalogEntry[];
49
7
  declare function isPlanMember(entry: PlatformCodes | undefined): boolean;
50
8
  declare function isSiteLockedOnPlatform(entry: SiteFeatureLocks[string] | undefined, platform: PlatformBucket, code: string): boolean;
51
9
  declare function buildSiteRoles(snapshot: VersionSnapshot, businessCode: string | undefined): RoleItem[];
@@ -72,6 +30,7 @@ interface LockedPermission {
72
30
  code: string;
73
31
  reason: LockReason | null;
74
32
  unlockPlans: string[];
33
+ missingServices: ServiceCode[];
75
34
  }
76
35
  interface PlanUpsell {
77
36
  plan: string;
@@ -87,6 +46,7 @@ interface PermissionFeature {
87
46
  locked: boolean;
88
47
  lockReason: LockReason | null;
89
48
  unlockPlans: string[];
49
+ missingServices: ServiceCode[];
90
50
  lockedPermissions: LockedPermission[];
91
51
  upsell: PlanUpsell[];
92
52
  route: {
@@ -108,6 +68,7 @@ interface ResolveUserFeaturesParams {
108
68
  platform: ClientPlatform;
109
69
  siteType?: SiteType;
110
70
  scope?: ScopeType;
71
+ availableServices?: ServiceCode[];
111
72
  }
112
73
  declare function resolveUserFeatures(params: ResolveUserFeaturesParams): PermissionFeature[];
113
74
  declare function pickRouteForPlatform(entry: {
@@ -128,4 +89,46 @@ declare function pickRouteForPlatform(entry: {
128
89
  routePrefix: string;
129
90
  } | null;
130
91
 
131
- export { type ClientPlatform, type ComposeRoleGrantsParams, type DependsMap, FeatureCatalogEntry, FeatureUnlocks, LockReason, type LockedPermission, type PermissionFeature, PlatformBucket, PlatformCodes, PlatformDenyCodes, type ResolveUserFeaturesParams, type RevokedGrants, RoleItem, ScopeType, SiteFeatureLocks, type SiteMatrix, type SiteMatrixApp, type SiteMatrixCell, type SiteMatrixFeature, type SiteMatrixPermission, SiteType, SnapshotFeature, VersionSnapshot, buildDependsMap, buildPlanMatrix, buildSiteCatalog, buildSiteMatrix, buildSiteRoles, cascadeLocked, composeRoleGrants, featureAppliesAtNode, filterGrantedByDeps, findFeatureByCode, isPlanMember, isSiteLockedOnPlatform, pickRouteForPlatform, prereqClosure, resolveUserFeatures };
92
+ interface SiteMatrixCell {
93
+ inPlan: boolean;
94
+ selected: boolean;
95
+ availableIn: string[];
96
+ }
97
+ interface SiteMatrixPermission {
98
+ code: string;
99
+ label: string;
100
+ dependsOn: string[];
101
+ web: SiteMatrixCell | null;
102
+ mobile: SiteMatrixCell | null;
103
+ }
104
+ interface SiteMatrixFeature {
105
+ code: string;
106
+ name: string;
107
+ icon: string | null;
108
+ scope: ScopeType;
109
+ applicableSiteTypes: SiteType[];
110
+ platforms: PlatformBucket[];
111
+ inPlan: boolean;
112
+ availableIn: string[];
113
+ permissions: SiteMatrixPermission[];
114
+ }
115
+ interface SiteMatrixApp {
116
+ code: string;
117
+ name: string;
118
+ icon: string | null;
119
+ unlockedCount: number;
120
+ totalCount: number;
121
+ features: SiteMatrixFeature[];
122
+ }
123
+ interface SiteMatrix {
124
+ plan: {
125
+ code: string;
126
+ name: string;
127
+ };
128
+ apps: SiteMatrixApp[];
129
+ locks: SiteFeatureLocks;
130
+ }
131
+ declare function buildSiteMatrix(snapshot: VersionSnapshot, businessCode: string | undefined, planCode: string | undefined, siteLocks: SiteFeatureLocks | undefined, siteType?: SiteType): SiteMatrix;
132
+ declare function buildPlanMatrix(snapshot: VersionSnapshot, businessCode: string | undefined, planCode: string | undefined, siteLocks?: SiteFeatureLocks): SiteMatrix;
133
+
134
+ export { type ClientPlatform, type ComposeRoleGrantsParams, type DependsMap, FeatureCatalogEntry, FeatureUnlocks, LockReason, type LockedPermission, type PermissionFeature, PlatformBucket, PlatformCodes, PlatformDenyCodes, type ResolveUserFeaturesParams, type RevokedGrants, RoleItem, ScopeType, ServiceCode, SiteFeatureLocks, type SiteMatrix, type SiteMatrixApp, type SiteMatrixCell, type SiteMatrixFeature, type SiteMatrixPermission, SiteType, SnapshotFeature, VersionSnapshot, buildDependsMap, buildPlanMatrix, buildSiteCatalog, buildSiteMatrix, buildSiteRoles, cascadeLocked, composeRoleGrants, featureAppliesAtNode, filterGrantedByDeps, findFeatureByCode, isPlanMember, isSiteLockedOnPlatform, pickRouteForPlatform, prereqClosure, resolveUserFeatures };
@@ -1,51 +1,9 @@
1
- import { S as ScopeType, a as SiteType, P as PlatformBucket, b as SiteFeatureLocks, V as VersionSnapshot, F as FeatureCatalogEntry, R as RoleItem, c as SnapshotFeature, d as PlatformCodes, e as FeatureUnlocks, f as PlatformDenyCodes, L as LockReason } from './types-C9jPdQqH.js';
2
- export { B as BusinessVocabulary, C as CatalogPermission, g as FeatureLocks, h as PLATFORMS, i as SITE_TYPES, j as SNAPSHOT_SCHEMA_VERSION, k as SnapshotApp, l as SnapshotAppFeatureRef, n as SnapshotBusiness, o as SnapshotMicrofrontendMobile, q as SnapshotMicrofrontendWeb, p as SnapshotMicrofrontends, r as SnapshotPermission, s as SnapshotPlan, t as SnapshotRoleTemplate, m as VocabularyEntry, u as snapshotFeatureKey } from './types-C9jPdQqH.js';
3
-
4
- interface SiteMatrixCell {
5
- inPlan: boolean;
6
- selected: boolean;
7
- availableIn: string[];
8
- }
9
- interface SiteMatrixPermission {
10
- code: string;
11
- label: string;
12
- dependsOn: string[];
13
- web: SiteMatrixCell | null;
14
- mobile: SiteMatrixCell | null;
15
- }
16
- interface SiteMatrixFeature {
17
- code: string;
18
- name: string;
19
- icon: string | null;
20
- scope: ScopeType;
21
- applicableSiteTypes: SiteType[];
22
- platforms: PlatformBucket[];
23
- inPlan: boolean;
24
- availableIn: string[];
25
- permissions: SiteMatrixPermission[];
26
- }
27
- interface SiteMatrixApp {
28
- code: string;
29
- name: string;
30
- icon: string | null;
31
- unlockedCount: number;
32
- totalCount: number;
33
- features: SiteMatrixFeature[];
34
- }
35
- interface SiteMatrix {
36
- plan: {
37
- code: string;
38
- name: string;
39
- };
40
- apps: SiteMatrixApp[];
41
- locks: SiteFeatureLocks;
42
- }
43
- declare function buildSiteMatrix(snapshot: VersionSnapshot, businessCode: string | undefined, planCode: string | undefined, siteLocks: SiteFeatureLocks | undefined, siteType?: SiteType): SiteMatrix;
44
- declare function buildPlanMatrix(snapshot: VersionSnapshot, businessCode: string | undefined, planCode: string | undefined, siteLocks?: SiteFeatureLocks): SiteMatrix;
1
+ import { V as VersionSnapshot, S as SiteFeatureLocks, P as PlatformBucket, a as SiteType, b as ScopeType, c as ServiceCode, F as FeatureCatalogEntry, R as RoleItem, d as SnapshotFeature, e as PlatformCodes, f as FeatureUnlocks, g as PlatformDenyCodes, L as LockReason } from './types-BBK6MG-U.js';
2
+ export { B as BusinessVocabulary, C as CatalogPermission, h as FeatureLocks, i as PLATFORMS, j as SERVICE_CODES, k as SITE_TYPES, l as SNAPSHOT_SCHEMA_VERSION, m as SnapshotApp, n as SnapshotAppFeatureRef, o as SnapshotBusiness, p as SnapshotMicrofrontendMobile, r as SnapshotMicrofrontendWeb, q as SnapshotMicrofrontends, s as SnapshotPermission, t as SnapshotPlan, u as SnapshotRoleTemplate, w as VocabularyEntry, v as snapshotFeatureKey } from './types-BBK6MG-U.js';
45
3
 
46
4
  declare function featureAppliesAtNode(applicableSiteTypes: SiteType[], siteType: SiteType): boolean;
47
5
  declare function findFeatureByCode(snapshot: VersionSnapshot, code: string): SnapshotFeature | undefined;
48
- declare function buildSiteCatalog(snapshot: VersionSnapshot, businessCode: string | undefined, planCode: string | undefined, siteLocks: SiteFeatureLocks | undefined, bucket: PlatformBucket, siteType?: SiteType, scope?: ScopeType): FeatureCatalogEntry[];
6
+ declare function buildSiteCatalog(snapshot: VersionSnapshot, businessCode: string | undefined, planCode: string | undefined, siteLocks: SiteFeatureLocks | undefined, bucket: PlatformBucket, siteType?: SiteType, scope?: ScopeType, availableServices?: ServiceCode[]): FeatureCatalogEntry[];
49
7
  declare function isPlanMember(entry: PlatformCodes | undefined): boolean;
50
8
  declare function isSiteLockedOnPlatform(entry: SiteFeatureLocks[string] | undefined, platform: PlatformBucket, code: string): boolean;
51
9
  declare function buildSiteRoles(snapshot: VersionSnapshot, businessCode: string | undefined): RoleItem[];
@@ -72,6 +30,7 @@ interface LockedPermission {
72
30
  code: string;
73
31
  reason: LockReason | null;
74
32
  unlockPlans: string[];
33
+ missingServices: ServiceCode[];
75
34
  }
76
35
  interface PlanUpsell {
77
36
  plan: string;
@@ -87,6 +46,7 @@ interface PermissionFeature {
87
46
  locked: boolean;
88
47
  lockReason: LockReason | null;
89
48
  unlockPlans: string[];
49
+ missingServices: ServiceCode[];
90
50
  lockedPermissions: LockedPermission[];
91
51
  upsell: PlanUpsell[];
92
52
  route: {
@@ -108,6 +68,7 @@ interface ResolveUserFeaturesParams {
108
68
  platform: ClientPlatform;
109
69
  siteType?: SiteType;
110
70
  scope?: ScopeType;
71
+ availableServices?: ServiceCode[];
111
72
  }
112
73
  declare function resolveUserFeatures(params: ResolveUserFeaturesParams): PermissionFeature[];
113
74
  declare function pickRouteForPlatform(entry: {
@@ -128,4 +89,46 @@ declare function pickRouteForPlatform(entry: {
128
89
  routePrefix: string;
129
90
  } | null;
130
91
 
131
- export { type ClientPlatform, type ComposeRoleGrantsParams, type DependsMap, FeatureCatalogEntry, FeatureUnlocks, LockReason, type LockedPermission, type PermissionFeature, PlatformBucket, PlatformCodes, PlatformDenyCodes, type ResolveUserFeaturesParams, type RevokedGrants, RoleItem, ScopeType, SiteFeatureLocks, type SiteMatrix, type SiteMatrixApp, type SiteMatrixCell, type SiteMatrixFeature, type SiteMatrixPermission, SiteType, SnapshotFeature, VersionSnapshot, buildDependsMap, buildPlanMatrix, buildSiteCatalog, buildSiteMatrix, buildSiteRoles, cascadeLocked, composeRoleGrants, featureAppliesAtNode, filterGrantedByDeps, findFeatureByCode, isPlanMember, isSiteLockedOnPlatform, pickRouteForPlatform, prereqClosure, resolveUserFeatures };
92
+ interface SiteMatrixCell {
93
+ inPlan: boolean;
94
+ selected: boolean;
95
+ availableIn: string[];
96
+ }
97
+ interface SiteMatrixPermission {
98
+ code: string;
99
+ label: string;
100
+ dependsOn: string[];
101
+ web: SiteMatrixCell | null;
102
+ mobile: SiteMatrixCell | null;
103
+ }
104
+ interface SiteMatrixFeature {
105
+ code: string;
106
+ name: string;
107
+ icon: string | null;
108
+ scope: ScopeType;
109
+ applicableSiteTypes: SiteType[];
110
+ platforms: PlatformBucket[];
111
+ inPlan: boolean;
112
+ availableIn: string[];
113
+ permissions: SiteMatrixPermission[];
114
+ }
115
+ interface SiteMatrixApp {
116
+ code: string;
117
+ name: string;
118
+ icon: string | null;
119
+ unlockedCount: number;
120
+ totalCount: number;
121
+ features: SiteMatrixFeature[];
122
+ }
123
+ interface SiteMatrix {
124
+ plan: {
125
+ code: string;
126
+ name: string;
127
+ };
128
+ apps: SiteMatrixApp[];
129
+ locks: SiteFeatureLocks;
130
+ }
131
+ declare function buildSiteMatrix(snapshot: VersionSnapshot, businessCode: string | undefined, planCode: string | undefined, siteLocks: SiteFeatureLocks | undefined, siteType?: SiteType): SiteMatrix;
132
+ declare function buildPlanMatrix(snapshot: VersionSnapshot, businessCode: string | undefined, planCode: string | undefined, siteLocks?: SiteFeatureLocks): SiteMatrix;
133
+
134
+ export { type ClientPlatform, type ComposeRoleGrantsParams, type DependsMap, FeatureCatalogEntry, FeatureUnlocks, LockReason, type LockedPermission, type PermissionFeature, PlatformBucket, PlatformCodes, PlatformDenyCodes, type ResolveUserFeaturesParams, type RevokedGrants, RoleItem, ScopeType, ServiceCode, SiteFeatureLocks, type SiteMatrix, type SiteMatrixApp, type SiteMatrixCell, type SiteMatrixFeature, type SiteMatrixPermission, SiteType, SnapshotFeature, VersionSnapshot, buildDependsMap, buildPlanMatrix, buildSiteCatalog, buildSiteMatrix, buildSiteRoles, cascadeLocked, composeRoleGrants, featureAppliesAtNode, filterGrantedByDeps, findFeatureByCode, isPlanMember, isSiteLockedOnPlatform, pickRouteForPlatform, prereqClosure, resolveUserFeatures };
@@ -81,6 +81,9 @@ var SITE_TYPES = [
81
81
  "WAREHOUSE",
82
82
  "PRODUCTION"
83
83
  ];
84
+ var SERVICE_CODES = [
85
+ "GITEA"
86
+ ];
84
87
  function snapshotFeatureKey(code, scope) {
85
88
  return `${scope}.${code}`;
86
89
  }
@@ -99,7 +102,7 @@ function findFeatureByCode(snapshot, code) {
99
102
  return void 0;
100
103
  }
101
104
  __name(findFeatureByCode, "findFeatureByCode");
102
- function buildSiteCatalog(snapshot, businessCode, planCode, siteLocks, bucket, siteType, scope) {
105
+ function buildSiteCatalog(snapshot, businessCode, planCode, siteLocks, bucket, siteType, scope, availableServices = []) {
103
106
  if (!businessCode) return [];
104
107
  const business = snapshot.businesses?.[businessCode];
105
108
  if (!business) return [];
@@ -116,11 +119,12 @@ function buildSiteCatalog(snapshot, businessCode, planCode, siteLocks, bucket, s
116
119
  const membership = plan?.unlockedPermissions?.[feature.code];
117
120
  const web = feature.microfrontends?.web;
118
121
  const mobile = feature.microfrontends?.mobile;
119
- const permissions = buildPermissions(feature, businessCode, membership, siteLocks, plans, bucket);
120
122
  const memberOnBucket = membership?.[bucket] !== void 0;
121
123
  const sitePlatformLocked = siteLocks?.[feature.code]?.[bucket] === null;
122
- const locked = !memberOnBucket || sitePlatformLocked;
123
- const lockReason = !memberOnBucket ? "PLAN" : sitePlatformLocked ? "SITE" : null;
124
+ const missingServices = unmetServices(feature, availableServices);
125
+ const permissions = buildPermissions(feature, businessCode, membership, siteLocks, plans, bucket, missingServices);
126
+ const lockReason = resolveLockReason(!memberOnBucket, sitePlatformLocked, missingServices);
127
+ const locked = lockReason !== null;
124
128
  const unlockPlans = lockReason === "PLAN" ? plansIncludingFeature(plans, feature.code, bucket) : [];
125
129
  catalog.push({
126
130
  code: feature.code,
@@ -146,6 +150,7 @@ function buildSiteCatalog(snapshot, businessCode, planCode, siteLocks, bucket, s
146
150
  locked,
147
151
  lockReason,
148
152
  unlockPlans,
153
+ missingServices,
149
154
  permissions
150
155
  });
151
156
  }
@@ -157,12 +162,23 @@ function isPlanMember(entry) {
157
162
  return !!entry && (entry.web !== void 0 || entry.mobile !== void 0);
158
163
  }
159
164
  __name(isPlanMember, "isPlanMember");
165
+ function resolveLockReason(planLocked, siteLocked, missingServices) {
166
+ if (planLocked) return "PLAN";
167
+ if (siteLocked) return "SITE";
168
+ if (missingServices.length > 0) return "SERVICE";
169
+ return null;
170
+ }
171
+ __name(resolveLockReason, "resolveLockReason");
172
+ function unmetServices(feature, availableServices) {
173
+ return (feature.requiredServices ?? []).filter((service) => !availableServices.includes(service));
174
+ }
175
+ __name(unmetServices, "unmetServices");
160
176
  function isSiteLockedOnPlatform(entry, platform, code) {
161
177
  const locks = entry?.[platform];
162
178
  return locks === null || (locks?.includes(code) ?? false);
163
179
  }
164
180
  __name(isSiteLockedOnPlatform, "isSiteLockedOnPlatform");
165
- function buildPermissions(feature, businessCode, planMembership, siteLocks, plans, bucket) {
181
+ function buildPermissions(feature, businessCode, planMembership, siteLocks, plans, bucket, missingServices = []) {
166
182
  const planUnlocked = new Set(planMembership?.[bucket] ?? []);
167
183
  const lockEntry = siteLocks?.[feature.code];
168
184
  const perms = (feature.permissions ?? []).filter((p) => p.isGlobal || p.businesses.includes(businessCode));
@@ -180,20 +196,22 @@ function buildPermissions(feature, businessCode, planMembership, siteLocks, plan
180
196
  ]);
181
197
  const lockedSet = cascadeLocked(codes, directlyLocked, deps);
182
198
  return perms.map((p) => {
183
- const locked = lockedSet.has(p.code);
184
199
  const closure = [
185
200
  p.code,
186
201
  ...prereqClosure(p.code, deps)
187
202
  ];
188
- const planReason = closure.some((c) => directlyPlanLocked.has(c));
189
- const siteReason = closure.some((c) => directlySiteLocked.has(c));
190
- const lockReason = !locked ? null : planReason ? "PLAN" : siteReason ? "SITE" : null;
191
- const unlockPlans = locked && lockReason === "PLAN" ? plansUnlockingClosure(plans, feature.code, closure, bucket) : [];
203
+ const cascaded = lockedSet.has(p.code);
204
+ const planReason = cascaded && closure.some((c) => directlyPlanLocked.has(c));
205
+ const siteReason = cascaded && closure.some((c) => directlySiteLocked.has(c));
206
+ const lockReason = resolveLockReason(planReason, siteReason, missingServices);
207
+ const locked = lockReason !== null;
208
+ const unlockPlans = lockReason === "PLAN" ? plansUnlockingClosure(plans, feature.code, closure, bucket) : [];
192
209
  return {
193
210
  code: p.code,
194
211
  locked,
195
212
  lockReason,
196
- unlockPlans
213
+ unlockPlans,
214
+ missingServices
197
215
  };
198
216
  });
199
217
  }
@@ -223,117 +241,6 @@ function buildSiteRoles(snapshot, businessCode) {
223
241
  }
224
242
  __name(buildSiteRoles, "buildSiteRoles");
225
243
 
226
- // src/catalog-resolver/site-matrix.builder.ts
227
- function buildSiteMatrix(snapshot, businessCode, planCode, siteLocks, siteType) {
228
- return buildMatrix(snapshot, businessCode, planCode, siteLocks, false, siteType);
229
- }
230
- __name(buildSiteMatrix, "buildSiteMatrix");
231
- function buildPlanMatrix(snapshot, businessCode, planCode, siteLocks) {
232
- return buildMatrix(snapshot, businessCode, planCode, siteLocks, true);
233
- }
234
- __name(buildPlanMatrix, "buildPlanMatrix");
235
- function buildMatrix(snapshot, businessCode, planCode, siteLocks, allScopes, siteType) {
236
- const business = businessCode ? snapshot.businesses?.[businessCode] : void 0;
237
- const plans = business?.plans ?? {};
238
- const plan = planCode ? plans[planCode] : void 0;
239
- const planMeta = {
240
- code: planCode ?? "",
241
- name: plan?.name ?? planCode ?? ""
242
- };
243
- const locks = siteLocks ?? {};
244
- if (!business || !plan) return {
245
- plan: planMeta,
246
- apps: [],
247
- locks
248
- };
249
- const apps = [];
250
- for (const app of business.apps) {
251
- let unlockedCount = 0;
252
- let totalCount = 0;
253
- const features = [];
254
- for (const ref of app.features) {
255
- if (!allScopes && ref.scope !== "SITE") continue;
256
- const code = ref.code;
257
- const feature = snapshot.features?.[snapshotFeatureKey(code, ref.scope)];
258
- if (!feature) continue;
259
- if (siteType !== void 0 && !featureAppliesAtNode(feature.applicableSiteTypes, siteType)) continue;
260
- const platforms = PLATFORMS.filter((p) => !!feature.microfrontends?.[p]);
261
- if (platforms.length === 0) continue;
262
- const membership = plan.unlockedPermissions?.[code];
263
- const featureInPlan = isPlanMember(membership);
264
- const siteEntry = siteLocks?.[code];
265
- const permissions = (feature.permissions ?? []).filter((p) => p.isGlobal || p.businesses.includes(businessCode ?? "")).map((p) => {
266
- const cell = /* @__PURE__ */ __name((plat) => {
267
- if (!platforms.includes(plat)) return null;
268
- const planCodes = membership?.[plat];
269
- const inPlan = featureInPlan && planCodes !== void 0 && planCodes.includes(p.code);
270
- const selected = inPlan && !isSiteLockedOnPlatform(siteEntry, plat, p.code);
271
- const availableIn = inPlan ? [] : plansUnlockingPerm(plans, code, p.code, plat, planCode);
272
- totalCount += 1;
273
- if (inPlan) unlockedCount += 1;
274
- return {
275
- inPlan,
276
- selected,
277
- availableIn
278
- };
279
- }, "cell");
280
- return {
281
- code: p.code,
282
- label: p.label,
283
- dependsOn: p.dependsOn ?? [],
284
- web: cell("web"),
285
- mobile: cell("mobile")
286
- };
287
- });
288
- features.push({
289
- code: feature.code,
290
- name: feature.name,
291
- icon: feature.lucideIcon ?? null,
292
- scope: feature.scope,
293
- applicableSiteTypes: feature.applicableSiteTypes,
294
- platforms,
295
- inPlan: featureInPlan,
296
- availableIn: featureInPlan ? [] : plansIncludingFeature2(plans, code, planCode),
297
- permissions
298
- });
299
- }
300
- if (features.length === 0) continue;
301
- apps.push({
302
- code: app.code,
303
- name: app.name,
304
- icon: app.icon ?? null,
305
- unlockedCount,
306
- totalCount,
307
- features
308
- });
309
- }
310
- apps.sort((a, b) => a.name.localeCompare(b.name));
311
- return {
312
- plan: planMeta,
313
- apps,
314
- locks
315
- };
316
- }
317
- __name(buildMatrix, "buildMatrix");
318
- function plansUnlockingPerm(plans, featureCode, permCode, platform, excludeCode) {
319
- const names = [];
320
- for (const [code, p] of Object.entries(plans)) {
321
- if (code === excludeCode) continue;
322
- if ((p.unlockedPermissions?.[featureCode]?.[platform] ?? []).includes(permCode)) names.push(p.name);
323
- }
324
- return names;
325
- }
326
- __name(plansUnlockingPerm, "plansUnlockingPerm");
327
- function plansIncludingFeature2(plans, featureCode, excludeCode) {
328
- const names = [];
329
- for (const [code, p] of Object.entries(plans)) {
330
- if (code === excludeCode) continue;
331
- if (isPlanMember(p.unlockedPermissions?.[featureCode])) names.push(p.name);
332
- }
333
- return names;
334
- }
335
- __name(plansIncludingFeature2, "plansIncludingFeature");
336
-
337
244
  // src/catalog-resolver/compose-role-grants.ts
338
245
  function unionBucket(base, add) {
339
246
  if (base === void 0 && add === void 0) return void 0;
@@ -373,10 +280,10 @@ __name(composeRoleGrants, "composeRoleGrants");
373
280
 
374
281
  // src/catalog-resolver/resolve-user-features.ts
375
282
  function resolveUserFeatures(params) {
376
- const { snapshot, businessCode, planCode, siteLocks, roleFeatures, platform, siteType, scope } = params;
283
+ const { snapshot, businessCode, planCode, siteLocks, roleFeatures, platform, siteType, scope, availableServices } = params;
377
284
  const bucket = platform === "web" ? "web" : "mobile";
378
285
  const featureByCode = /* @__PURE__ */ __name((code) => scope ? snapshot.features?.[snapshotFeatureKey(code, scope)] : findFeatureByCode(snapshot, code), "featureByCode");
379
- const catalog = buildSiteCatalog(snapshot, businessCode, planCode, siteLocks, bucket, siteType, scope);
286
+ const catalog = buildSiteCatalog(snapshot, businessCode, planCode, siteLocks, bucket, siteType, scope, availableServices);
380
287
  const catalogMap = new Map(catalog.map((f) => [
381
288
  f.code,
382
289
  f
@@ -426,7 +333,8 @@ function resolveUserFeatures(params) {
426
333
  const lockedPermissions = grantedPerms.map((c) => permByCode.get(c)).filter((p) => !!p?.locked).map((p) => ({
427
334
  code: p.code,
428
335
  reason: p.lockReason ?? null,
429
- unlockPlans: p.unlockPlans ?? []
336
+ unlockPlans: p.unlockPlans ?? [],
337
+ missingServices: p.missingServices ?? []
430
338
  }));
431
339
  const upsell = catalogEntry.locked && catalogEntry.lockReason === "PLAN" ? (catalogEntry.unlockPlans ?? []).map((plan) => ({
432
340
  plan,
@@ -442,6 +350,7 @@ function resolveUserFeatures(params) {
442
350
  locked: catalogEntry.locked ?? false,
443
351
  lockReason: catalogEntry.lockReason ?? null,
444
352
  unlockPlans: catalogEntry.unlockPlans ?? [],
353
+ missingServices: catalogEntry.missingServices ?? [],
445
354
  lockedPermissions,
446
355
  upsell,
447
356
  route,
@@ -472,8 +381,120 @@ function pickRouteForPlatform(entry, platform) {
472
381
  };
473
382
  }
474
383
  __name(pickRouteForPlatform, "pickRouteForPlatform");
384
+
385
+ // src/catalog-resolver/site-matrix.builder.ts
386
+ function buildSiteMatrix(snapshot, businessCode, planCode, siteLocks, siteType) {
387
+ return buildMatrix(snapshot, businessCode, planCode, siteLocks, false, siteType);
388
+ }
389
+ __name(buildSiteMatrix, "buildSiteMatrix");
390
+ function buildPlanMatrix(snapshot, businessCode, planCode, siteLocks) {
391
+ return buildMatrix(snapshot, businessCode, planCode, siteLocks, true);
392
+ }
393
+ __name(buildPlanMatrix, "buildPlanMatrix");
394
+ function buildMatrix(snapshot, businessCode, planCode, siteLocks, allScopes, siteType) {
395
+ const business = businessCode ? snapshot.businesses?.[businessCode] : void 0;
396
+ const plans = business?.plans ?? {};
397
+ const plan = planCode ? plans[planCode] : void 0;
398
+ const planMeta = {
399
+ code: planCode ?? "",
400
+ name: plan?.name ?? planCode ?? ""
401
+ };
402
+ const locks = siteLocks ?? {};
403
+ if (!business || !plan) return {
404
+ plan: planMeta,
405
+ apps: [],
406
+ locks
407
+ };
408
+ const apps = [];
409
+ for (const app of business.apps) {
410
+ let unlockedCount = 0;
411
+ let totalCount = 0;
412
+ const features = [];
413
+ for (const ref of app.features) {
414
+ if (!allScopes && ref.scope !== "SITE") continue;
415
+ const code = ref.code;
416
+ const feature = snapshot.features?.[snapshotFeatureKey(code, ref.scope)];
417
+ if (!feature) continue;
418
+ if (siteType !== void 0 && !featureAppliesAtNode(feature.applicableSiteTypes, siteType)) continue;
419
+ const platforms = PLATFORMS.filter((p) => !!feature.microfrontends?.[p]);
420
+ if (platforms.length === 0) continue;
421
+ const membership = plan.unlockedPermissions?.[code];
422
+ const featureInPlan = isPlanMember(membership);
423
+ const siteEntry = siteLocks?.[code];
424
+ const permissions = (feature.permissions ?? []).filter((p) => p.isGlobal || p.businesses.includes(businessCode ?? "")).map((p) => {
425
+ const cell = /* @__PURE__ */ __name((plat) => {
426
+ if (!platforms.includes(plat)) return null;
427
+ const planCodes = membership?.[plat];
428
+ const inPlan = featureInPlan && planCodes !== void 0 && planCodes.includes(p.code);
429
+ const selected = inPlan && !isSiteLockedOnPlatform(siteEntry, plat, p.code);
430
+ const availableIn = inPlan ? [] : plansUnlockingPerm(plans, code, p.code, plat, planCode);
431
+ totalCount += 1;
432
+ if (inPlan) unlockedCount += 1;
433
+ return {
434
+ inPlan,
435
+ selected,
436
+ availableIn
437
+ };
438
+ }, "cell");
439
+ return {
440
+ code: p.code,
441
+ label: p.label,
442
+ dependsOn: p.dependsOn ?? [],
443
+ web: cell("web"),
444
+ mobile: cell("mobile")
445
+ };
446
+ });
447
+ features.push({
448
+ code: feature.code,
449
+ name: feature.name,
450
+ icon: feature.lucideIcon ?? null,
451
+ scope: feature.scope,
452
+ applicableSiteTypes: feature.applicableSiteTypes,
453
+ platforms,
454
+ inPlan: featureInPlan,
455
+ availableIn: featureInPlan ? [] : plansIncludingFeature2(plans, code, planCode),
456
+ permissions
457
+ });
458
+ }
459
+ if (features.length === 0) continue;
460
+ apps.push({
461
+ code: app.code,
462
+ name: app.name,
463
+ icon: app.icon ?? null,
464
+ unlockedCount,
465
+ totalCount,
466
+ features
467
+ });
468
+ }
469
+ apps.sort((a, b) => a.name.localeCompare(b.name));
470
+ return {
471
+ plan: planMeta,
472
+ apps,
473
+ locks
474
+ };
475
+ }
476
+ __name(buildMatrix, "buildMatrix");
477
+ function plansUnlockingPerm(plans, featureCode, permCode, platform, excludeCode) {
478
+ const names = [];
479
+ for (const [code, p] of Object.entries(plans)) {
480
+ if (code === excludeCode) continue;
481
+ if ((p.unlockedPermissions?.[featureCode]?.[platform] ?? []).includes(permCode)) names.push(p.name);
482
+ }
483
+ return names;
484
+ }
485
+ __name(plansUnlockingPerm, "plansUnlockingPerm");
486
+ function plansIncludingFeature2(plans, featureCode, excludeCode) {
487
+ const names = [];
488
+ for (const [code, p] of Object.entries(plans)) {
489
+ if (code === excludeCode) continue;
490
+ if (isPlanMember(p.unlockedPermissions?.[featureCode])) names.push(p.name);
491
+ }
492
+ return names;
493
+ }
494
+ __name(plansIncludingFeature2, "plansIncludingFeature");
475
495
  export {
476
496
  PLATFORMS,
497
+ SERVICE_CODES,
477
498
  SITE_TYPES,
478
499
  SNAPSHOT_SCHEMA_VERSION,
479
500
  buildDependsMap,