@franzzemen/brokenstock-shell 0.0.39 → 0.0.40

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.
@@ -80,6 +80,8 @@ class AuthenticationService {
80
80
  this.authenticating = signal(false, ...(ngDevMode ? [{ debugName: "authenticating" }] : /* istanbul ignore next */ []));
81
81
  this.userSession = signal(undefined, ...(ngDevMode ? [{ debugName: "userSession" }] : /* istanbul ignore next */ []));
82
82
  this.effectivePermissions = signal({}, ...(ngDevMode ? [{ debugName: "effectivePermissions" }] : /* istanbul ignore next */ []));
83
+ /** First-class plan-feature grants for the current session (supersedes effectivePermissions). */
84
+ this.features = signal({}, ...(ngDevMode ? [{ debugName: "features" }] : /* istanbul ignore next */ []));
83
85
  this.conflictSessions = signal(undefined, ...(ngDevMode ? [{ debugName: "conflictSessions" }] : /* istanbul ignore next */ []));
84
86
  this.pendingCredentials = signal(undefined, ...(ngDevMode ? [{ debugName: "pendingCredentials" }] : /* istanbul ignore next */ []));
85
87
  this.#refreshing = null;
@@ -106,6 +108,18 @@ class AuthenticationService {
106
108
  hasAnyRole(roleNames) {
107
109
  return this.authenticated() && roleNames.some(r => this.userSession()?.roles.includes(r) === true);
108
110
  }
111
+ /**
112
+ * Check whether the current session holds a plan-feature (truthy grant).
113
+ * Works for boolean features (`true`) and quantity features (limit > 0).
114
+ * e.g. `hasFeature('real-time')`.
115
+ */
116
+ hasFeature(slug) {
117
+ return this.authenticated() && !!this.features()[slug];
118
+ }
119
+ /** Raw plan-feature value (`true` for boolean grants, the numeric limit for quantity features, else undefined). */
120
+ featureValue(slug) {
121
+ return this.features()[slug];
122
+ }
109
123
  refresh() {
110
124
  if (this.#refreshing) {
111
125
  return this.#refreshing;
@@ -164,6 +178,7 @@ class AuthenticationService {
164
178
  delete authResponse.session.token;
165
179
  this.userSession.set(authResponse.session);
166
180
  this.effectivePermissions.set(authResponse.effectivePermissions ?? {});
181
+ this.features.set(authResponse.features ?? {});
167
182
  const auth = response.headers.get(HttpHeader.Authorization);
168
183
  if (!auth || !BEARER_TOKEN_REGEX.test(auth)) {
169
184
  reject('Unable to login');
@@ -222,6 +237,7 @@ class AuthenticationService {
222
237
  this.#auth = auth;
223
238
  this.userSession.set(body.session);
224
239
  this.effectivePermissions.set(body.effectivePermissions ?? {});
240
+ this.features.set(body.features ?? {});
225
241
  return true;
226
242
  }
227
243
  catch {
@@ -232,6 +248,7 @@ class AuthenticationService {
232
248
  this.authenticated.set(false);
233
249
  this.userSession.set(undefined);
234
250
  this.effectivePermissions.set({});
251
+ this.features.set({});
235
252
  this.conflictSessions.set(undefined);
236
253
  this.pendingCredentials.set(undefined);
237
254
  this.#auth = 'Bearer ..';