@vritti/api-sdk 0.3.3 → 0.3.5

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 (133) hide show
  1. package/dist/auth.cjs +942 -0
  2. package/dist/auth.cjs.map +1 -0
  3. package/dist/auth.d.cts +95 -0
  4. package/dist/auth.d.ts +95 -0
  5. package/dist/auth.js +884 -0
  6. package/dist/auth.js.map +1 -0
  7. package/dist/cache.cjs +182 -14
  8. package/dist/cache.cjs.map +1 -1
  9. package/dist/cache.d.cts +48 -4
  10. package/dist/cache.d.ts +48 -4
  11. package/dist/cache.js +177 -12
  12. package/dist/cache.js.map +1 -1
  13. package/dist/catalog-resolver.cjs +226 -51
  14. package/dist/catalog-resolver.cjs.map +1 -1
  15. package/dist/catalog-resolver.d.cts +41 -19
  16. package/dist/catalog-resolver.d.ts +41 -19
  17. package/dist/catalog-resolver.js +212 -46
  18. package/dist/catalog-resolver.js.map +1 -1
  19. package/dist/code-pattern-BP4zkNtT.d.cts +12 -0
  20. package/dist/code-pattern-BP4zkNtT.d.ts +12 -0
  21. package/dist/context.cjs +93 -0
  22. package/dist/context.cjs.map +1 -0
  23. package/dist/context.d.cts +19 -0
  24. package/dist/context.d.ts +19 -0
  25. package/dist/context.js +64 -0
  26. package/dist/context.js.map +1 -0
  27. package/dist/countries.cjs +1559 -0
  28. package/dist/countries.cjs.map +1 -0
  29. package/dist/countries.d.cts +13 -0
  30. package/dist/countries.d.ts +13 -0
  31. package/dist/countries.js +1532 -0
  32. package/dist/countries.js.map +1 -0
  33. package/dist/data-table.cjs +1280 -0
  34. package/dist/data-table.cjs.map +1 -0
  35. package/dist/data-table.d.cts +123 -0
  36. package/dist/data-table.d.ts +123 -0
  37. package/dist/data-table.js +1260 -0
  38. package/dist/data-table.js.map +1 -0
  39. package/dist/database.cjs +1510 -0
  40. package/dist/database.cjs.map +1 -0
  41. package/dist/database.d.cts +287 -0
  42. package/dist/database.d.ts +287 -0
  43. package/dist/database.js +1469 -0
  44. package/dist/database.js.map +1 -0
  45. package/dist/decimal.d.cts +0 -1
  46. package/dist/decimal.d.ts +0 -1
  47. package/dist/decorators.cjs +1817 -0
  48. package/dist/decorators.cjs.map +1 -0
  49. package/dist/decorators.d.cts +24 -0
  50. package/dist/decorators.d.ts +24 -0
  51. package/dist/decorators.js +1780 -0
  52. package/dist/decorators.js.map +1 -0
  53. package/dist/drizzle-pg-core.cjs +25 -0
  54. package/dist/drizzle-pg-core.cjs.map +1 -1
  55. package/dist/drizzle-pg-core.d.cts +7 -0
  56. package/dist/drizzle-pg-core.d.ts +7 -0
  57. package/dist/drizzle-pg-core.js +22 -0
  58. package/dist/drizzle-pg-core.js.map +1 -1
  59. package/dist/exceptions.cjs +301 -0
  60. package/dist/exceptions.cjs.map +1 -0
  61. package/dist/exceptions.d.cts +90 -0
  62. package/dist/exceptions.d.ts +90 -0
  63. package/dist/exceptions.js +257 -0
  64. package/dist/exceptions.js.map +1 -0
  65. package/dist/filter.types-PuARU9XD.d.cts +50 -0
  66. package/dist/filter.types-PuARU9XD.d.ts +50 -0
  67. package/dist/filters.cjs +407 -0
  68. package/dist/filters.cjs.map +1 -0
  69. package/dist/filters.d.cts +55 -0
  70. package/dist/filters.d.ts +55 -0
  71. package/dist/filters.js +377 -0
  72. package/dist/filters.js.map +1 -0
  73. package/dist/index.cjs +0 -5423
  74. package/dist/index.cjs.map +1 -1
  75. package/dist/index.d.cts +93 -854
  76. package/dist/index.d.ts +93 -854
  77. package/dist/index.js +0 -5301
  78. package/dist/index.js.map +1 -1
  79. package/dist/is-country.decorator-CcNwSSr5.d.cts +5 -0
  80. package/dist/is-country.decorator-CcNwSSr5.d.ts +5 -0
  81. package/dist/license.d.cts +1 -1
  82. package/dist/license.d.ts +1 -1
  83. package/dist/lodash.cjs.map +1 -1
  84. package/dist/lodash.js.map +1 -1
  85. package/dist/logger.cjs +862 -0
  86. package/dist/logger.cjs.map +1 -0
  87. package/dist/logger.d.cts +118 -0
  88. package/dist/logger.d.ts +118 -0
  89. package/dist/logger.js +816 -0
  90. package/dist/logger.js.map +1 -0
  91. package/dist/migrate.cjs +2 -2
  92. package/dist/migrate.cjs.map +1 -1
  93. package/dist/migrate.d.cts +2 -0
  94. package/dist/migrate.d.ts +2 -0
  95. package/dist/migrate.js +2 -2
  96. package/dist/migrate.js.map +1 -1
  97. package/dist/money.cjs +18 -3
  98. package/dist/money.cjs.map +1 -1
  99. package/dist/money.d.cts +13 -13
  100. package/dist/money.d.ts +13 -13
  101. package/dist/money.js +18 -3
  102. package/dist/money.js.map +1 -1
  103. package/dist/nats.cjs +34 -35
  104. package/dist/nats.cjs.map +1 -1
  105. package/dist/nats.d.cts +14 -14
  106. package/dist/nats.d.ts +14 -14
  107. package/dist/nats.js +32 -33
  108. package/dist/nats.js.map +1 -1
  109. package/dist/root.cjs +225 -0
  110. package/dist/root.cjs.map +1 -0
  111. package/dist/root.d.cts +4 -0
  112. package/dist/root.d.ts +4 -0
  113. package/dist/root.js +200 -0
  114. package/dist/root.js.map +1 -0
  115. package/dist/{types-DQRwj5rr.d.cts → types-C9jPdQqH.d.cts} +32 -6
  116. package/dist/{types-DQRwj5rr.d.ts → types-C9jPdQqH.d.ts} +32 -6
  117. package/dist/types.cjs +19 -0
  118. package/dist/types.cjs.map +1 -0
  119. package/dist/types.d.cts +17 -0
  120. package/dist/types.d.ts +17 -0
  121. package/dist/types.js +1 -0
  122. package/dist/types.js.map +1 -0
  123. package/dist/utils.cjs +273 -0
  124. package/dist/utils.cjs.map +1 -0
  125. package/dist/utils.d.cts +8 -0
  126. package/dist/utils.d.ts +8 -0
  127. package/dist/utils.js +245 -0
  128. package/dist/utils.js.map +1 -0
  129. package/package.json +122 -1
  130. package/dist/cache.service-_SuJIcNA.d.cts +0 -20
  131. package/dist/cache.service-_SuJIcNA.d.ts +0 -20
  132. package/dist/fastify-augmentation-CQPBNS5a.d.cts +0 -105
  133. package/dist/fastify-augmentation-CQPBNS5a.d.ts +0 -105
@@ -22,38 +22,147 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
22
22
  var catalog_resolver_exports = {};
23
23
  __export(catalog_resolver_exports, {
24
24
  PLATFORMS: () => PLATFORMS,
25
+ SITE_TYPES: () => SITE_TYPES,
25
26
  SNAPSHOT_SCHEMA_VERSION: () => SNAPSHOT_SCHEMA_VERSION,
26
- buildBuCatalog: () => buildBuCatalog,
27
- buildBuMatrix: () => buildBuMatrix,
28
- buildBuRoles: () => buildBuRoles,
27
+ buildDependsMap: () => buildDependsMap,
28
+ buildPlanMatrix: () => buildPlanMatrix,
29
+ buildSiteCatalog: () => buildSiteCatalog,
30
+ buildSiteMatrix: () => buildSiteMatrix,
31
+ buildSiteRoles: () => buildSiteRoles,
32
+ cascadeLocked: () => cascadeLocked,
29
33
  composeRoleGrants: () => composeRoleGrants,
30
- isBuLockedOnPlatform: () => isBuLockedOnPlatform,
34
+ featureAppliesAtNode: () => featureAppliesAtNode,
35
+ filterGrantedByDeps: () => filterGrantedByDeps,
36
+ findFeatureByCode: () => findFeatureByCode,
31
37
  isPlanMember: () => isPlanMember,
38
+ isSiteLockedOnPlatform: () => isSiteLockedOnPlatform,
32
39
  pickRouteForPlatform: () => pickRouteForPlatform,
33
- resolveUserFeatures: () => resolveUserFeatures
40
+ prereqClosure: () => prereqClosure,
41
+ resolveUserFeatures: () => resolveUserFeatures,
42
+ snapshotFeatureKey: () => snapshotFeatureKey
34
43
  });
35
44
  module.exports = __toCommonJS(catalog_resolver_exports);
36
45
 
46
+ // src/catalog-resolver/permission-deps.ts
47
+ function buildDependsMap(permissions) {
48
+ const present = new Set(permissions.map((p) => p.code));
49
+ const map = /* @__PURE__ */ new Map();
50
+ for (const p of permissions) {
51
+ map.set(p.code, (p.dependsOn ?? []).filter((dep) => dep !== p.code && present.has(dep)));
52
+ }
53
+ return map;
54
+ }
55
+ __name(buildDependsMap, "buildDependsMap");
56
+ function prereqClosure(code, deps) {
57
+ const out = /* @__PURE__ */ new Set();
58
+ const seen = /* @__PURE__ */ new Set([
59
+ code
60
+ ]);
61
+ const stack = [
62
+ code
63
+ ];
64
+ while (stack.length > 0) {
65
+ const current = stack.pop();
66
+ for (const dep of deps.get(current) ?? []) {
67
+ if (seen.has(dep)) continue;
68
+ seen.add(dep);
69
+ out.add(dep);
70
+ stack.push(dep);
71
+ }
72
+ }
73
+ return [
74
+ ...out
75
+ ];
76
+ }
77
+ __name(prereqClosure, "prereqClosure");
78
+ function cascadeLocked(codes, directlyLocked, deps) {
79
+ const locked = /* @__PURE__ */ new Set();
80
+ const visiting = /* @__PURE__ */ new Set();
81
+ const check = /* @__PURE__ */ __name((code) => {
82
+ if (locked.has(code)) return true;
83
+ if (directlyLocked.has(code)) {
84
+ locked.add(code);
85
+ return true;
86
+ }
87
+ if (visiting.has(code)) return false;
88
+ visiting.add(code);
89
+ const viaDep = (deps.get(code) ?? []).some(check);
90
+ visiting.delete(code);
91
+ if (viaDep) locked.add(code);
92
+ return viaDep;
93
+ }, "check");
94
+ for (const code of codes) check(code);
95
+ return locked;
96
+ }
97
+ __name(cascadeLocked, "cascadeLocked");
98
+ function filterGrantedByDeps(granted, deps) {
99
+ const ok = /* @__PURE__ */ new Set();
100
+ const visiting = /* @__PURE__ */ new Set();
101
+ const check = /* @__PURE__ */ __name((code) => {
102
+ if (ok.has(code)) return true;
103
+ if (!granted.has(code)) return false;
104
+ if (visiting.has(code)) return true;
105
+ visiting.add(code);
106
+ const satisfied = (deps.get(code) ?? []).every(check);
107
+ visiting.delete(code);
108
+ if (satisfied) ok.add(code);
109
+ return satisfied;
110
+ }, "check");
111
+ for (const code of granted) check(code);
112
+ return ok;
113
+ }
114
+ __name(filterGrantedByDeps, "filterGrantedByDeps");
115
+
116
+ // src/catalog-resolver/types.ts
117
+ var PLATFORMS = [
118
+ "web",
119
+ "mobile"
120
+ ];
121
+ var SITE_TYPES = [
122
+ "OUTLET",
123
+ "WAREHOUSE",
124
+ "PRODUCTION"
125
+ ];
126
+ function snapshotFeatureKey(code, scope) {
127
+ return `${scope}.${code}`;
128
+ }
129
+ __name(snapshotFeatureKey, "snapshotFeatureKey");
130
+ var SNAPSHOT_SCHEMA_VERSION = 2;
131
+
37
132
  // src/catalog-resolver/catalog.builder.ts
38
- function buildBuCatalog(snapshot, businessCode, planCode, buLocks, bucket) {
133
+ function featureAppliesAtNode(applicableSiteTypes, siteType) {
134
+ return applicableSiteTypes.includes(siteType);
135
+ }
136
+ __name(featureAppliesAtNode, "featureAppliesAtNode");
137
+ function findFeatureByCode(snapshot, code) {
138
+ for (const feature of Object.values(snapshot.features ?? {})) {
139
+ if (feature?.code === code) return feature;
140
+ }
141
+ return void 0;
142
+ }
143
+ __name(findFeatureByCode, "findFeatureByCode");
144
+ function buildSiteCatalog(snapshot, businessCode, planCode, siteLocks, bucket, siteType, scope) {
39
145
  if (!businessCode) return [];
40
146
  const business = snapshot.businesses?.[businessCode];
41
147
  if (!business) return [];
42
148
  const plan = planCode ? business.plans?.[planCode] : void 0;
43
149
  const plans = business.plans ?? {};
44
150
  const catalog = [];
45
- for (const app of business.apps) {
46
- const businessAppFeatures = app.features.map((code) => snapshot.features?.[code]).filter((f) => !!f && !!(f.microfrontends?.web || f.microfrontends?.mobile));
151
+ const sortedApps = [
152
+ ...business.apps
153
+ ].sort((a, b) => a.name.localeCompare(b.name));
154
+ for (const app of sortedApps) {
155
+ const businessAppFeatures = app.features.filter((ref) => scope === void 0 || ref.scope === scope).map((ref) => snapshot.features?.[snapshotFeatureKey(ref.code, ref.scope)]).filter((f) => !!f && !!(f.microfrontends?.web || f.microfrontends?.mobile) && (siteType === void 0 || featureAppliesAtNode(f.applicableSiteTypes, siteType)));
47
156
  if (businessAppFeatures.length === 0) continue;
48
157
  for (const feature of businessAppFeatures) {
49
158
  const membership = plan?.unlockedPermissions?.[feature.code];
50
159
  const web = feature.microfrontends?.web;
51
160
  const mobile = feature.microfrontends?.mobile;
52
- const permissions = buildPermissions(feature, businessCode, membership, buLocks, plans, bucket);
161
+ const permissions = buildPermissions(feature, businessCode, membership, siteLocks, plans, bucket);
53
162
  const memberOnBucket = membership?.[bucket] !== void 0;
54
- const buPlatformLocked = buLocks?.[feature.code]?.[bucket] === null;
55
- const locked = !memberOnBucket || buPlatformLocked;
56
- const lockReason = !memberOnBucket ? "PLAN" : buPlatformLocked ? "BU" : null;
163
+ const sitePlatformLocked = siteLocks?.[feature.code]?.[bucket] === null;
164
+ const locked = !memberOnBucket || sitePlatformLocked;
165
+ const lockReason = !memberOnBucket ? "PLAN" : sitePlatformLocked ? "SITE" : null;
57
166
  const unlockPlans = lockReason === "PLAN" ? plansIncludingFeature(plans, feature.code, bucket) : [];
58
167
  catalog.push({
59
168
  code: feature.code,
@@ -85,25 +194,43 @@ function buildBuCatalog(snapshot, businessCode, planCode, buLocks, bucket) {
85
194
  }
86
195
  return catalog;
87
196
  }
88
- __name(buildBuCatalog, "buildBuCatalog");
197
+ __name(buildSiteCatalog, "buildSiteCatalog");
89
198
  function isPlanMember(entry) {
90
199
  return !!entry && (entry.web !== void 0 || entry.mobile !== void 0);
91
200
  }
92
201
  __name(isPlanMember, "isPlanMember");
93
- function isBuLockedOnPlatform(entry, platform, code) {
202
+ function isSiteLockedOnPlatform(entry, platform, code) {
94
203
  const locks = entry?.[platform];
95
204
  return locks === null || (locks?.includes(code) ?? false);
96
205
  }
97
- __name(isBuLockedOnPlatform, "isBuLockedOnPlatform");
98
- function buildPermissions(feature, businessCode, planMembership, buLocks, plans, bucket) {
206
+ __name(isSiteLockedOnPlatform, "isSiteLockedOnPlatform");
207
+ function buildPermissions(feature, businessCode, planMembership, siteLocks, plans, bucket) {
99
208
  const planUnlocked = new Set(planMembership?.[bucket] ?? []);
100
- const lockEntry = buLocks?.[feature.code];
101
- return (feature.permissions ?? []).filter((p) => p.isGlobal || p.businesses.includes(businessCode)).map((p) => {
102
- const planAllows = planUnlocked.has(p.code);
103
- const buAllows = !isBuLockedOnPlatform(lockEntry, bucket, p.code);
104
- const locked = !planAllows || !buAllows;
105
- const lockReason = !planAllows ? "PLAN" : !buAllows ? "BU" : null;
106
- const unlockPlans = lockReason === "PLAN" ? plansUnlockingPermission(plans, feature.code, p.code, bucket) : [];
209
+ const lockEntry = siteLocks?.[feature.code];
210
+ const perms = (feature.permissions ?? []).filter((p) => p.isGlobal || p.businesses.includes(businessCode));
211
+ const deps = buildDependsMap(perms);
212
+ const codes = perms.map((p) => p.code);
213
+ const directlyPlanLocked = /* @__PURE__ */ new Set();
214
+ const directlySiteLocked = /* @__PURE__ */ new Set();
215
+ for (const p of perms) {
216
+ if (!planUnlocked.has(p.code)) directlyPlanLocked.add(p.code);
217
+ if (isSiteLockedOnPlatform(lockEntry, bucket, p.code)) directlySiteLocked.add(p.code);
218
+ }
219
+ const directlyLocked = /* @__PURE__ */ new Set([
220
+ ...directlyPlanLocked,
221
+ ...directlySiteLocked
222
+ ]);
223
+ const lockedSet = cascadeLocked(codes, directlyLocked, deps);
224
+ return perms.map((p) => {
225
+ const locked = lockedSet.has(p.code);
226
+ const closure = [
227
+ p.code,
228
+ ...prereqClosure(p.code, deps)
229
+ ];
230
+ const planReason = closure.some((c) => directlyPlanLocked.has(c));
231
+ const siteReason = closure.some((c) => directlySiteLocked.has(c));
232
+ const lockReason = !locked ? null : planReason ? "PLAN" : siteReason ? "SITE" : null;
233
+ const unlockPlans = locked && lockReason === "PLAN" ? plansUnlockingClosure(plans, feature.code, closure, bucket) : [];
107
234
  return {
108
235
  code: p.code,
109
236
  locked,
@@ -113,14 +240,15 @@ function buildPermissions(feature, businessCode, planMembership, buLocks, plans,
113
240
  });
114
241
  }
115
242
  __name(buildPermissions, "buildPermissions");
116
- function plansUnlockingPermission(plans, featureCode, permCode, bucket) {
243
+ function plansUnlockingClosure(plans, featureCode, closure, bucket) {
117
244
  const result = [];
118
245
  for (const [code, plan] of Object.entries(plans)) {
119
- if (plan.unlockedPermissions?.[featureCode]?.[bucket]?.includes(permCode)) result.push(code);
246
+ const unlocked = plan.unlockedPermissions?.[featureCode]?.[bucket];
247
+ if (unlocked && closure.every((c) => unlocked.includes(c))) result.push(code);
120
248
  }
121
249
  return result;
122
250
  }
123
- __name(plansUnlockingPermission, "plansUnlockingPermission");
251
+ __name(plansUnlockingClosure, "plansUnlockingClosure");
124
252
  function plansIncludingFeature(plans, featureCode, bucket) {
125
253
  const result = [];
126
254
  for (const [code, plan] of Object.entries(plans)) {
@@ -129,23 +257,24 @@ function plansIncludingFeature(plans, featureCode, bucket) {
129
257
  return result;
130
258
  }
131
259
  __name(plansIncludingFeature, "plansIncludingFeature");
132
- function buildBuRoles(snapshot, businessCode) {
260
+ function buildSiteRoles(snapshot, businessCode) {
133
261
  if (!businessCode) return [];
134
262
  const business = snapshot.businesses?.[businessCode];
135
263
  if (!business) return [];
136
264
  return Object.values(business.roleTemplates ?? {});
137
265
  }
138
- __name(buildBuRoles, "buildBuRoles");
266
+ __name(buildSiteRoles, "buildSiteRoles");
139
267
 
140
- // src/catalog-resolver/types.ts
141
- var PLATFORMS = [
142
- "web",
143
- "mobile"
144
- ];
145
- var SNAPSHOT_SCHEMA_VERSION = 1;
146
-
147
- // src/catalog-resolver/bu-matrix.builder.ts
148
- function buildBuMatrix(snapshot, businessCode, planCode, buLocks) {
268
+ // src/catalog-resolver/site-matrix.builder.ts
269
+ function buildSiteMatrix(snapshot, businessCode, planCode, siteLocks, siteType) {
270
+ return buildMatrix(snapshot, businessCode, planCode, siteLocks, false, siteType);
271
+ }
272
+ __name(buildSiteMatrix, "buildSiteMatrix");
273
+ function buildPlanMatrix(snapshot, businessCode, planCode, siteLocks) {
274
+ return buildMatrix(snapshot, businessCode, planCode, siteLocks, true);
275
+ }
276
+ __name(buildPlanMatrix, "buildPlanMatrix");
277
+ function buildMatrix(snapshot, businessCode, planCode, siteLocks, allScopes, siteType) {
149
278
  const business = businessCode ? snapshot.businesses?.[businessCode] : void 0;
150
279
  const plans = business?.plans ?? {};
151
280
  const plan = planCode ? plans[planCode] : void 0;
@@ -153,7 +282,7 @@ function buildBuMatrix(snapshot, businessCode, planCode, buLocks) {
153
282
  code: planCode ?? "",
154
283
  name: plan?.name ?? planCode ?? ""
155
284
  };
156
- const locks = buLocks ?? {};
285
+ const locks = siteLocks ?? {};
157
286
  if (!business || !plan) return {
158
287
  plan: planMeta,
159
288
  apps: [],
@@ -164,20 +293,23 @@ function buildBuMatrix(snapshot, businessCode, planCode, buLocks) {
164
293
  let unlockedCount = 0;
165
294
  let totalCount = 0;
166
295
  const features = [];
167
- for (const code of app.features) {
168
- const feature = snapshot.features?.[code];
296
+ for (const ref of app.features) {
297
+ if (!allScopes && ref.scope !== "SITE") continue;
298
+ const code = ref.code;
299
+ const feature = snapshot.features?.[snapshotFeatureKey(code, ref.scope)];
169
300
  if (!feature) continue;
301
+ if (siteType !== void 0 && !featureAppliesAtNode(feature.applicableSiteTypes, siteType)) continue;
170
302
  const platforms = PLATFORMS.filter((p) => !!feature.microfrontends?.[p]);
171
303
  if (platforms.length === 0) continue;
172
304
  const membership = plan.unlockedPermissions?.[code];
173
305
  const featureInPlan = isPlanMember(membership);
174
- const buEntry = buLocks?.[code];
306
+ const siteEntry = siteLocks?.[code];
175
307
  const permissions = (feature.permissions ?? []).filter((p) => p.isGlobal || p.businesses.includes(businessCode ?? "")).map((p) => {
176
308
  const cell = /* @__PURE__ */ __name((plat) => {
177
309
  if (!platforms.includes(plat)) return null;
178
310
  const planCodes = membership?.[plat];
179
311
  const inPlan = featureInPlan && planCodes !== void 0 && planCodes.includes(p.code);
180
- const selected = inPlan && !isBuLockedOnPlatform(buEntry, plat, p.code);
312
+ const selected = inPlan && !isSiteLockedOnPlatform(siteEntry, plat, p.code);
181
313
  const availableIn = inPlan ? [] : plansUnlockingPerm(plans, code, p.code, plat, planCode);
182
314
  totalCount += 1;
183
315
  if (inPlan) unlockedCount += 1;
@@ -190,6 +322,7 @@ function buildBuMatrix(snapshot, businessCode, planCode, buLocks) {
190
322
  return {
191
323
  code: p.code,
192
324
  label: p.label,
325
+ dependsOn: p.dependsOn ?? [],
193
326
  web: cell("web"),
194
327
  mobile: cell("mobile")
195
328
  };
@@ -198,12 +331,15 @@ function buildBuMatrix(snapshot, businessCode, planCode, buLocks) {
198
331
  code: feature.code,
199
332
  name: feature.name,
200
333
  icon: feature.lucideIcon ?? null,
334
+ scope: feature.scope,
335
+ applicableSiteTypes: feature.applicableSiteTypes,
201
336
  platforms,
202
337
  inPlan: featureInPlan,
203
338
  availableIn: featureInPlan ? [] : plansIncludingFeature2(plans, code, planCode),
204
339
  permissions
205
340
  });
206
341
  }
342
+ if (features.length === 0) continue;
207
343
  apps.push({
208
344
  code: app.code,
209
345
  name: app.name,
@@ -213,13 +349,14 @@ function buildBuMatrix(snapshot, businessCode, planCode, buLocks) {
213
349
  features
214
350
  });
215
351
  }
352
+ apps.sort((a, b) => a.name.localeCompare(b.name));
216
353
  return {
217
354
  plan: planMeta,
218
355
  apps,
219
356
  locks
220
357
  };
221
358
  }
222
- __name(buildBuMatrix, "buildBuMatrix");
359
+ __name(buildMatrix, "buildMatrix");
223
360
  function plansUnlockingPerm(plans, featureCode, permCode, platform, excludeCode) {
224
361
  const names = [];
225
362
  for (const [code, p] of Object.entries(plans)) {
@@ -278,13 +415,35 @@ __name(composeRoleGrants, "composeRoleGrants");
278
415
 
279
416
  // src/catalog-resolver/resolve-user-features.ts
280
417
  function resolveUserFeatures(params) {
281
- const { snapshot, businessCode, planCode, buLocks, roleFeatures, platform } = params;
418
+ const { snapshot, businessCode, planCode, siteLocks, roleFeatures, platform, siteType, scope } = params;
282
419
  const bucket = platform === "web" ? "web" : "mobile";
283
- const catalog = buildBuCatalog(snapshot, businessCode, planCode, buLocks, bucket);
420
+ const featureByCode = /* @__PURE__ */ __name((code) => scope ? snapshot.features?.[snapshotFeatureKey(code, scope)] : findFeatureByCode(snapshot, code), "featureByCode");
421
+ const catalog = buildSiteCatalog(snapshot, businessCode, planCode, siteLocks, bucket, siteType, scope);
284
422
  const catalogMap = new Map(catalog.map((f) => [
285
423
  f.code,
286
424
  f
287
425
  ]));
426
+ const businessPlans = snapshot.businesses[businessCode]?.plans ?? {};
427
+ const currentUnlockedCodes = /* @__PURE__ */ new Set();
428
+ if (planCode && businessPlans[planCode]) {
429
+ for (const [featureCode, platforms] of Object.entries(businessPlans[planCode].unlockedPermissions ?? {})) {
430
+ if (platforms?.[bucket] !== void 0) currentUnlockedCodes.add(featureCode);
431
+ }
432
+ }
433
+ const planAdds = /* @__PURE__ */ new Map();
434
+ for (const [planKey, plan] of Object.entries(businessPlans)) {
435
+ if (planKey === planCode) continue;
436
+ const adds = [];
437
+ for (const [featureCode, platforms] of Object.entries(plan.unlockedPermissions ?? {})) {
438
+ if (platforms?.[bucket] === void 0 || currentUnlockedCodes.has(featureCode)) continue;
439
+ const name = featureByCode(featureCode)?.name;
440
+ if (name) adds.push({
441
+ code: featureCode,
442
+ name
443
+ });
444
+ }
445
+ planAdds.set(planKey, adds);
446
+ }
288
447
  const grantedFeatures = /* @__PURE__ */ new Map();
289
448
  for (const [code, grant] of Object.entries(roleFeatures ?? {})) {
290
449
  const granted = grant?.[bucket];
@@ -298,18 +457,23 @@ function resolveUserFeatures(params) {
298
457
  if (!catalogEntry) continue;
299
458
  const route = pickRouteForPlatform(catalogEntry, platform);
300
459
  if (!route) continue;
460
+ const featureDeps = buildDependsMap(featureByCode(code)?.permissions ?? []);
301
461
  const permByCode = new Map((catalogEntry.permissions ?? []).map((p) => [
302
462
  p.code,
303
463
  p
304
464
  ]));
305
465
  const grantedPerms = [
306
- ...permsSet
466
+ ...filterGrantedByDeps(permsSet, featureDeps)
307
467
  ];
308
468
  const lockedPermissions = grantedPerms.map((c) => permByCode.get(c)).filter((p) => !!p?.locked).map((p) => ({
309
469
  code: p.code,
310
470
  reason: p.lockReason ?? null,
311
471
  unlockPlans: p.unlockPlans ?? []
312
472
  }));
473
+ const upsell = catalogEntry.locked && catalogEntry.lockReason === "PLAN" ? (catalogEntry.unlockPlans ?? []).map((plan) => ({
474
+ plan,
475
+ features: (planAdds.get(plan) ?? []).filter((f) => f.code !== code).map((f) => f.name)
476
+ })).filter((group) => group.features.length > 0) : [];
313
477
  features.push({
314
478
  code,
315
479
  name: catalogEntry.name,
@@ -321,6 +485,7 @@ function resolveUserFeatures(params) {
321
485
  lockReason: catalogEntry.lockReason ?? null,
322
486
  unlockPlans: catalogEntry.unlockPlans ?? [],
323
487
  lockedPermissions,
488
+ upsell,
324
489
  route,
325
490
  appCode: catalogEntry.appCode,
326
491
  appName: catalogEntry.appName,
@@ -328,6 +493,7 @@ function resolveUserFeatures(params) {
328
493
  appSortOrder: catalogEntry.appSortOrder
329
494
  });
330
495
  }
496
+ features.sort((a, b) => a.appName.localeCompare(b.appName));
331
497
  return features;
332
498
  }
333
499
  __name(resolveUserFeatures, "resolveUserFeatures");
@@ -351,14 +517,23 @@ __name(pickRouteForPlatform, "pickRouteForPlatform");
351
517
  // Annotate the CommonJS export names for ESM import in node:
352
518
  0 && (module.exports = {
353
519
  PLATFORMS,
520
+ SITE_TYPES,
354
521
  SNAPSHOT_SCHEMA_VERSION,
355
- buildBuCatalog,
356
- buildBuMatrix,
357
- buildBuRoles,
522
+ buildDependsMap,
523
+ buildPlanMatrix,
524
+ buildSiteCatalog,
525
+ buildSiteMatrix,
526
+ buildSiteRoles,
527
+ cascadeLocked,
358
528
  composeRoleGrants,
359
- isBuLockedOnPlatform,
529
+ featureAppliesAtNode,
530
+ filterGrantedByDeps,
531
+ findFeatureByCode,
360
532
  isPlanMember,
533
+ isSiteLockedOnPlatform,
361
534
  pickRouteForPlatform,
362
- resolveUserFeatures
535
+ prereqClosure,
536
+ resolveUserFeatures,
537
+ snapshotFeatureKey
363
538
  });
364
539
  //# sourceMappingURL=catalog-resolver.cjs.map