@dereekb/dbx-firebase 13.11.3 → 13.11.4

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,17 +1,17 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, computed, output, ChangeDetectionStrategy, Component, inject, Injectable, signal, effect, Directive, provideAppInitializer, makeEnvironmentProviders } from '@angular/core';
2
+ import { input, computed, output, ChangeDetectionStrategy, Component, inject, Injectable, signal, effect, Directive, viewChild, provideAppInitializer, makeEnvironmentProviders } from '@angular/core';
3
3
  import * as i1$1 from '@dereekb/dbx-web';
4
- import { DbxBasicLoadingComponent, DbxErrorComponent, DbxButtonComponent, DbxAvatarComponent, DbxLoadingComponent, DbxButtonSpacerDirective, AbstractDbxSelectionListWrapperDirective, DbxListWrapperComponentImportsModule, provideDbxListViewWrapper, DEFAULT_LIST_WRAPPER_COMPONENT_CONFIGURATION_TEMPLATE, AbstractDbxSelectionListViewDirective, DbxSelectionValueListViewComponentImportsModule, provideDbxListView, DEFAULT_DBX_SELECTION_VALUE_LIST_COMPONENT_CONFIGURATION_TEMPLATE, AbstractDbxValueListViewItemComponent, DbxActionSnackbarErrorDirective, DbxContentPitDirective, DbxDetailBlockComponent, DbxClickToCopyTextComponent, DbxActionConfirmDirective } from '@dereekb/dbx-web';
4
+ import { DbxBasicLoadingComponent, DbxErrorComponent, DbxButtonComponent, DbxAvatarComponent, DbxLoadingComponent, DbxButtonSpacerDirective, AbstractDbxSelectionListWrapperDirective, DbxListWrapperComponentImportsModule, provideDbxListViewWrapper, DEFAULT_LIST_WRAPPER_COMPONENT_CONFIGURATION_TEMPLATE, AbstractDbxSelectionListViewDirective, DbxSelectionValueListViewComponentImportsModule, provideDbxListView, DEFAULT_DBX_SELECTION_VALUE_LIST_COMPONENT_CONFIGURATION_TEMPLATE, AbstractDbxValueListViewItemComponent, DbxSpacerDirective, DbxActionConfirmDirective, DbxActionSnackbarErrorDirective, DbxContentPitDirective, DbxDetailBlockComponent, DbxClickToCopyTextComponent } from '@dereekb/dbx-web';
5
5
  import { readableError, SPACE_STRING_SPLIT_JOIN, separateValues, generatePkceCodeVerifier, generatePkceCodeChallenge } from '@dereekb/util';
6
- import { DbxInjectionComponent, DBX_INJECTION_COMPONENT_DATA, DbxRouterService, dbxRouteParamReaderInstance, completeOnDestroy, DbxActionDirective, DbxActionEnforceModifiedDirective, DbxActionHandlerDirective, DbxActionButtonDirective, DbxAppAuthRouterService } from '@dereekb/dbx-core';
6
+ import { DbxInjectionComponent, DBX_INJECTION_COMPONENT_DATA, DbxRouterService, dbxRouteParamReaderInstance, completeOnDestroy, DbxActionDirective, DbxActionHandlerDirective, DbxActionButtonDirective, DbxActionEnforceModifiedDirective, DbxAppAuthRouterService } from '@dereekb/dbx-core';
7
7
  import { toSignal } from '@angular/core/rxjs-interop';
8
- import { DbxFirebaseAuthService, AbstractDbxFirebaseDocumentStore, firebaseDocumentStoreCreateFunction, firebaseDocumentStoreUpdateFunction, firebaseDocumentStoreDeleteFunction, AbstractDbxFirebaseCollectionStore, DbxFirebaseCollectionStoreDirective, provideDbxFirebaseCollectionStoreDirective, DbxFirebaseDocumentStoreDirective, provideDbxFirebaseDocumentStoreDirective } from '@dereekb/dbx-firebase';
8
+ import { DbxFirebaseAuthService, AbstractDbxFirebaseDocumentStore, firebaseDocumentStoreCreateFunction, firebaseDocumentStoreUpdateFunction, firebaseDocumentStoreDeleteFunction, AbstractDbxFirebaseCollectionStore, DbxFirebaseCollectionStoreDirective, provideDbxFirebaseCollectionStoreDirective, DbxFirebaseCollectionListDirective, DbxFirebaseCollectionChangeDirective, DbxFirebaseDocumentStoreDirective, provideDbxFirebaseDocumentStoreDirective } from '@dereekb/dbx-firebase';
9
9
  import { HttpClient } from '@angular/common/http';
10
10
  import { first, switchMap, of, map, BehaviorSubject, tap } from 'rxjs';
11
11
  import * as i1 from '@dereekb/dbx-form';
12
12
  import { dbxForgeValueSelectionField, dbxForgeTextField, dbxForgeSearchableStringChipField, isWebsiteUrlValidator, dbxForgeContainer, dbxForgePickableChipField, pickableValueFieldValuesConfigForStaticLabeledValues, AbstractConfigAsyncForgeFormDirective, DbxForgeFormComponentImportsModule, dbxForgeFormComponentProviders, DBX_FORGE_FORM_COMPONENT_TEMPLATE, DbxActionFormDirective, DbxFormSourceDirective, DbxFormValueChangeDirective } from '@dereekb/dbx-form';
13
- import { ALL_OIDC_TOKEN_ENDPOINT_AUTH_METHOD_OPTIONS, PRIVATE_KEY_JWT_TOKEN_ENDPOINT_AUTH_METHOD, OIDC_ENTRY_CLIENT_TYPE, OidcModelFunctions, OidcModelFirestoreCollections } from '@dereekb/firebase';
14
- import { CommonModule } from '@angular/common';
13
+ import { ALL_OIDC_TOKEN_ENDPOINT_AUTH_METHOD_OPTIONS, PRIVATE_KEY_JWT_TOKEN_ENDPOINT_AUTH_METHOD, OidcModelFunctions, OidcModelFirestoreCollections, OIDC_ENTRY_CLIENT_TYPE, oidcGrantEntriesByUidQuery } from '@dereekb/firebase';
14
+ import { DatePipe, CommonModule } from '@angular/common';
15
15
 
16
16
  /**
17
17
  * Presentational component for the OIDC OAuth login interaction.
@@ -39,6 +39,9 @@ class DbxFirebaseOAuthLoginViewComponent {
39
39
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: DbxFirebaseOAuthLoginViewComponent, isStandalone: true, selector: "dbx-firebase-oauth-login-view", inputs: { loginStateCase: { classPropertyName: "loginStateCase", publicName: "loginStateCase", isSignal: true, isRequired: true, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { retryClick: "retryClick" }, host: { classAttribute: "d-block dbx-firebase-oauth-login-view" }, ngImport: i0, template: `
40
40
  <div class="dbx-firebase-oauth-login-view">
41
41
  @switch (loginStateCase()) {
42
+ @case ('unknown') {
43
+ <dbx-basic-loading [loading]="true"></dbx-basic-loading>
44
+ }
42
45
  @case ('no_user') {
43
46
  <ng-content></ng-content>
44
47
  }
@@ -65,6 +68,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
65
68
  template: `
66
69
  <div class="dbx-firebase-oauth-login-view">
67
70
  @switch (loginStateCase()) {
71
+ @case ('unknown') {
72
+ <dbx-basic-loading [loading]="true"></dbx-basic-loading>
73
+ }
68
74
  @case ('no_user') {
69
75
  <ng-content></ng-content>
70
76
  }
@@ -95,11 +101,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
95
101
  * information. Renders the client name, logo, client URL, scopes (via `<dbx-injection>`),
96
102
  * error/loading states, and approve/deny action buttons.
97
103
  *
104
+ * Supports ng-content projection — content provided is rendered for the `'no_user'` state
105
+ * (so apps can project a login view, mirroring `DbxFirebaseOAuthLoginViewComponent`).
106
+ *
98
107
  * @example
99
108
  * ```html
100
109
  * <dbx-firebase-oauth-consent-view
101
110
  * [details]="loginDetails"
102
- * [loading]="false"
111
+ * [consentStateCase]="'user'"
103
112
  * [scopeInjectionConfig]="scopeConfig"
104
113
  * (approveClick)="onApprove()"
105
114
  * (denyClick)="onDeny()">
@@ -108,7 +117,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
108
117
  */
109
118
  class DbxFirebaseOAuthConsentViewComponent {
110
119
  details = input(...(ngDevMode ? [undefined, { debugName: "details" }] : /* istanbul ignore next */ []));
111
- loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
120
+ consentStateCase = input.required(...(ngDevMode ? [{ debugName: "consentStateCase" }] : /* istanbul ignore next */ []));
112
121
  error = input(...(ngDevMode ? [undefined, { debugName: "error" }] : /* istanbul ignore next */ []));
113
122
  scopeInjectionConfig = input.required(...(ngDevMode ? [{ debugName: "scopeInjectionConfig" }] : /* istanbul ignore next */ []));
114
123
  clientName = computed(() => this.details()?.client_name ?? '', ...(ngDevMode ? [{ debugName: "clientName" }] : /* istanbul ignore next */ []));
@@ -121,6 +130,7 @@ class DbxFirebaseOAuthConsentViewComponent {
121
130
  }, ...(ngDevMode ? [{ debugName: "resolvedError" }] : /* istanbul ignore next */ []));
122
131
  approveClick = output();
123
132
  denyClick = output();
133
+ retryClick = output();
124
134
  resolvedScopeInjectionConfig = computed(() => {
125
135
  const data = {
126
136
  details: this.details(),
@@ -130,72 +140,92 @@ class DbxFirebaseOAuthConsentViewComponent {
130
140
  return { ...this.scopeInjectionConfig(), data };
131
141
  }, ...(ngDevMode ? [{ debugName: "resolvedScopeInjectionConfig" }] : /* istanbul ignore next */ []));
132
142
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxFirebaseOAuthConsentViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
133
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: DbxFirebaseOAuthConsentViewComponent, isStandalone: true, selector: "dbx-firebase-oauth-consent-view", inputs: { details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, scopeInjectionConfig: { classPropertyName: "scopeInjectionConfig", publicName: "scopeInjectionConfig", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { approveClick: "approveClick", denyClick: "denyClick" }, host: { classAttribute: "d-block dbx-firebase-oauth-consent-view" }, ngImport: i0, template: `
143
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: DbxFirebaseOAuthConsentViewComponent, isStandalone: true, selector: "dbx-firebase-oauth-consent-view", inputs: { details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: false, transformFunction: null }, consentStateCase: { classPropertyName: "consentStateCase", publicName: "consentStateCase", isSignal: true, isRequired: true, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, scopeInjectionConfig: { classPropertyName: "scopeInjectionConfig", publicName: "scopeInjectionConfig", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { approveClick: "approveClick", denyClick: "denyClick", retryClick: "retryClick" }, host: { classAttribute: "d-block dbx-firebase-oauth-consent-view" }, ngImport: i0, template: `
134
144
  <div class="dbx-firebase-oauth-consent-view">
135
- @if (loading()) {
136
- <dbx-loading [loading]="true" text="Processing..."></dbx-loading>
137
- } @else {
138
- <div class="dbx-firebase-oauth-consent-header">
139
- @if (clientName()) {
140
- <h2>You're signing in to {{ clientName() }}</h2>
141
- }
142
- <div class="dbx-firebase-oauth-consent-header-info dbx-flex">
143
- <dbx-avatar [avatarUrl]="logoUri()" [avatarStyle]="'square'" avatarIcon="apps"></dbx-avatar>
144
- <span>
145
- @if (clientUri()) {
146
- <a class="dbx-firebase-oauth-consent-client-uri" [href]="clientUri()" target="_blank" rel="noopener noreferrer">{{ clientUri() }}</a>
147
- }
148
- </span>
149
- </div>
150
- </div>
151
- <dbx-injection [config]="resolvedScopeInjectionConfig()"></dbx-injection>
152
- <div class="dbx-pt3 dbx-pb3 dbx-firebase-oauth-consent-actions">
153
- <dbx-button text="Approve" [raised]="true" color="primary" (buttonClick)="approveClick.emit()"></dbx-button>
154
- <dbx-button-spacer></dbx-button-spacer>
155
- <dbx-button text="Deny" [flat]="true" color="warn" (buttonClick)="denyClick.emit()"></dbx-button>
156
- </div>
157
- @if (resolvedError()) {
145
+ @switch (consentStateCase()) {
146
+ @case ('unknown') {
147
+ <dbx-basic-loading [loading]="true"></dbx-basic-loading>
148
+ }
149
+ @case ('no_user') {
150
+ <ng-content></ng-content>
151
+ }
152
+ @case ('submitting') {
153
+ <dbx-loading [loading]="true" text="Processing..."></dbx-loading>
154
+ }
155
+ @case ('error') {
156
+ <dbx-button text="Retry" [raised]="true" (buttonClick)="retryClick.emit()"></dbx-button>
158
157
  <dbx-error [error]="resolvedError()"></dbx-error>
159
158
  }
159
+ @case ('user') {
160
+ <div class="dbx-firebase-oauth-consent-header">
161
+ @if (clientName()) {
162
+ <h2>You're signing in to {{ clientName() }}</h2>
163
+ }
164
+ <div class="dbx-firebase-oauth-consent-header-info dbx-flex">
165
+ <dbx-avatar [avatarUrl]="logoUri()" [avatarStyle]="'square'" avatarIcon="apps"></dbx-avatar>
166
+ <span>
167
+ @if (clientUri()) {
168
+ <a class="dbx-firebase-oauth-consent-client-uri" [href]="clientUri()" target="_blank" rel="noopener noreferrer">{{ clientUri() }}</a>
169
+ }
170
+ </span>
171
+ </div>
172
+ </div>
173
+ <dbx-injection [config]="resolvedScopeInjectionConfig()"></dbx-injection>
174
+ <div class="dbx-pt3 dbx-pb3 dbx-firebase-oauth-consent-actions">
175
+ <dbx-button text="Approve" [raised]="true" color="primary" (buttonClick)="approveClick.emit()"></dbx-button>
176
+ <dbx-button-spacer></dbx-button-spacer>
177
+ <dbx-button text="Deny" [flat]="true" color="warn" (buttonClick)="denyClick.emit()"></dbx-button>
178
+ </div>
179
+ }
160
180
  }
161
181
  </div>
162
- `, isInline: true, styles: [".dbx-firebase-oauth-consent-view .dbx-firebase-oauth-consent-header-info{align-items:center;gap:12px}\n"], dependencies: [{ kind: "component", type: DbxInjectionComponent, selector: "dbx-injection, [dbxInjection], [dbx-injection]", inputs: ["config", "template"] }, { kind: "component", type: DbxAvatarComponent, selector: "dbx-avatar", inputs: ["context", "avatarSelector", "avatarUid", "avatarUrl", "avatarKey", "avatarIcon", "avatarStyle", "avatarSize", "avatarHideOnError"] }, { kind: "component", type: DbxLoadingComponent, selector: "dbx-loading", inputs: ["padding", "show", "text", "mode", "color", "diameter", "linear", "loading", "error", "context"] }, { kind: "component", type: DbxErrorComponent, selector: "dbx-error", inputs: ["error", "iconOnly"], outputs: ["popoverOpened"] }, { kind: "component", type: DbxButtonComponent, selector: "dbx-button", inputs: ["bar", "type", "buttonStyle", "color", "spinnerColor", "customButtonColor", "customTextColor", "customSpinnerColor", "basic", "tonal", "raised", "stroked", "flat", "iconOnly", "fab", "customContent", "allowClickPropagation", "mode"] }, { kind: "directive", type: DbxButtonSpacerDirective, selector: "dbx-button-spacer,[dbxButtonSpacer]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
182
+ `, isInline: true, styles: [".dbx-firebase-oauth-consent-view .dbx-firebase-oauth-consent-header-info{align-items:center;gap:12px}\n"], dependencies: [{ kind: "component", type: DbxInjectionComponent, selector: "dbx-injection, [dbxInjection], [dbx-injection]", inputs: ["config", "template"] }, { kind: "component", type: DbxAvatarComponent, selector: "dbx-avatar", inputs: ["context", "avatarSelector", "avatarUid", "avatarUrl", "avatarKey", "avatarIcon", "avatarStyle", "avatarSize", "avatarHideOnError"] }, { kind: "component", type: DbxBasicLoadingComponent, selector: "dbx-basic-loading", inputs: ["diameter", "mode", "color", "text", "linear", "show", "loading", "error"] }, { kind: "component", type: DbxLoadingComponent, selector: "dbx-loading", inputs: ["padding", "show", "text", "mode", "color", "diameter", "linear", "loading", "error", "context"] }, { kind: "component", type: DbxErrorComponent, selector: "dbx-error", inputs: ["error", "iconOnly"], outputs: ["popoverOpened"] }, { kind: "component", type: DbxButtonComponent, selector: "dbx-button", inputs: ["bar", "type", "buttonStyle", "color", "spinnerColor", "customButtonColor", "customTextColor", "customSpinnerColor", "basic", "tonal", "raised", "stroked", "flat", "iconOnly", "fab", "customContent", "allowClickPropagation", "mode"] }, { kind: "directive", type: DbxButtonSpacerDirective, selector: "dbx-button-spacer,[dbxButtonSpacer]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
163
183
  }
164
184
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxFirebaseOAuthConsentViewComponent, decorators: [{
165
185
  type: Component,
166
- args: [{ selector: 'dbx-firebase-oauth-consent-view', standalone: true, imports: [DbxInjectionComponent, DbxAvatarComponent, DbxLoadingComponent, DbxErrorComponent, DbxButtonComponent, DbxButtonSpacerDirective], template: `
186
+ args: [{ selector: 'dbx-firebase-oauth-consent-view', standalone: true, imports: [DbxInjectionComponent, DbxAvatarComponent, DbxBasicLoadingComponent, DbxLoadingComponent, DbxErrorComponent, DbxButtonComponent, DbxButtonSpacerDirective], template: `
167
187
  <div class="dbx-firebase-oauth-consent-view">
168
- @if (loading()) {
169
- <dbx-loading [loading]="true" text="Processing..."></dbx-loading>
170
- } @else {
171
- <div class="dbx-firebase-oauth-consent-header">
172
- @if (clientName()) {
173
- <h2>You're signing in to {{ clientName() }}</h2>
174
- }
175
- <div class="dbx-firebase-oauth-consent-header-info dbx-flex">
176
- <dbx-avatar [avatarUrl]="logoUri()" [avatarStyle]="'square'" avatarIcon="apps"></dbx-avatar>
177
- <span>
178
- @if (clientUri()) {
179
- <a class="dbx-firebase-oauth-consent-client-uri" [href]="clientUri()" target="_blank" rel="noopener noreferrer">{{ clientUri() }}</a>
180
- }
181
- </span>
182
- </div>
183
- </div>
184
- <dbx-injection [config]="resolvedScopeInjectionConfig()"></dbx-injection>
185
- <div class="dbx-pt3 dbx-pb3 dbx-firebase-oauth-consent-actions">
186
- <dbx-button text="Approve" [raised]="true" color="primary" (buttonClick)="approveClick.emit()"></dbx-button>
187
- <dbx-button-spacer></dbx-button-spacer>
188
- <dbx-button text="Deny" [flat]="true" color="warn" (buttonClick)="denyClick.emit()"></dbx-button>
189
- </div>
190
- @if (resolvedError()) {
188
+ @switch (consentStateCase()) {
189
+ @case ('unknown') {
190
+ <dbx-basic-loading [loading]="true"></dbx-basic-loading>
191
+ }
192
+ @case ('no_user') {
193
+ <ng-content></ng-content>
194
+ }
195
+ @case ('submitting') {
196
+ <dbx-loading [loading]="true" text="Processing..."></dbx-loading>
197
+ }
198
+ @case ('error') {
199
+ <dbx-button text="Retry" [raised]="true" (buttonClick)="retryClick.emit()"></dbx-button>
191
200
  <dbx-error [error]="resolvedError()"></dbx-error>
192
201
  }
202
+ @case ('user') {
203
+ <div class="dbx-firebase-oauth-consent-header">
204
+ @if (clientName()) {
205
+ <h2>You're signing in to {{ clientName() }}</h2>
206
+ }
207
+ <div class="dbx-firebase-oauth-consent-header-info dbx-flex">
208
+ <dbx-avatar [avatarUrl]="logoUri()" [avatarStyle]="'square'" avatarIcon="apps"></dbx-avatar>
209
+ <span>
210
+ @if (clientUri()) {
211
+ <a class="dbx-firebase-oauth-consent-client-uri" [href]="clientUri()" target="_blank" rel="noopener noreferrer">{{ clientUri() }}</a>
212
+ }
213
+ </span>
214
+ </div>
215
+ </div>
216
+ <dbx-injection [config]="resolvedScopeInjectionConfig()"></dbx-injection>
217
+ <div class="dbx-pt3 dbx-pb3 dbx-firebase-oauth-consent-actions">
218
+ <dbx-button text="Approve" [raised]="true" color="primary" (buttonClick)="approveClick.emit()"></dbx-button>
219
+ <dbx-button-spacer></dbx-button-spacer>
220
+ <dbx-button text="Deny" [flat]="true" color="warn" (buttonClick)="denyClick.emit()"></dbx-button>
221
+ </div>
222
+ }
193
223
  }
194
224
  </div>
195
225
  `, host: {
196
226
  class: 'd-block dbx-firebase-oauth-consent-view'
197
227
  }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".dbx-firebase-oauth-consent-view .dbx-firebase-oauth-consent-header-info{align-items:center;gap:12px}\n"] }]
198
- }], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], scopeInjectionConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "scopeInjectionConfig", required: true }] }], approveClick: [{ type: i0.Output, args: ["approveClick"] }], denyClick: [{ type: i0.Output, args: ["denyClick"] }] } });
228
+ }], propDecorators: { details: [{ type: i0.Input, args: [{ isSignal: true, alias: "details", required: false }] }], consentStateCase: [{ type: i0.Input, args: [{ isSignal: true, alias: "consentStateCase", required: true }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], scopeInjectionConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "scopeInjectionConfig", required: true }] }], approveClick: [{ type: i0.Output, args: ["approveClick"] }], denyClick: [{ type: i0.Output, args: ["denyClick"] }], retryClick: [{ type: i0.Output, args: ["retryClick"] }] } });
199
229
 
200
230
  /**
201
231
  * Abstract base class for consent scope view components.
@@ -454,7 +484,7 @@ class DbxFirebaseOAuthLoginComponent {
454
484
  interactionService = inject(DbxFirebaseOidcInteractionService);
455
485
  uidParamReader = dbxRouteParamReaderInstance(this.dbxRouterService, DEFAULT_OIDC_INTERACTION_UID_PARAM_KEY);
456
486
  interactionUid = toSignal(this.uidParamReader.value$);
457
- isLoggedIn = toSignal(this.dbxFirebaseAuthService.isLoggedIn$, { initialValue: false });
487
+ isLoggedIn = toSignal(this.dbxFirebaseAuthService.isLoggedIn$);
458
488
  submitting = signal(false, ...(ngDevMode ? [{ debugName: "submitting" }] : /* istanbul ignore next */ []));
459
489
  errorMessage = signal(null, ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
460
490
  loginStateCase = computed(() => {
@@ -464,7 +494,11 @@ class DbxFirebaseOAuthLoginComponent {
464
494
  if (this.errorMessage()) {
465
495
  return 'error';
466
496
  }
467
- if (!this.isLoggedIn()) {
497
+ const isLoggedIn = this.isLoggedIn();
498
+ if (isLoggedIn === undefined) {
499
+ return 'unknown';
500
+ }
501
+ if (!isLoggedIn) {
468
502
  return 'no_user';
469
503
  }
470
504
  return 'user';
@@ -533,14 +567,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
533
567
  /**
534
568
  * Container component for the OIDC OAuth consent screen.
535
569
  *
536
- * Manages all state: route param reading, consent submission, and error handling.
537
- * Delegates visual rendering to `DbxFirebaseOAuthConsentViewComponent`.
570
+ * Manages all state: route param reading, Firebase Auth observation, consent submission,
571
+ * and error handling. Delegates visual rendering to `DbxFirebaseOAuthConsentViewComponent`.
538
572
  *
539
573
  * Reads interaction UID and client details from route params (populated by
540
574
  * the server redirect), then assembles them into `OAuthInteractionLoginDetails`.
575
+ *
576
+ * Supports ng-content projection — any content provided is passed through to
577
+ * the view component for the `'no_user'` state (e.g. an app's login view).
541
578
  */
542
579
  class DbxOAuthConsentComponent {
543
580
  dbxRouterService = inject(DbxRouterService);
581
+ dbxFirebaseAuthService = inject(DbxFirebaseAuthService);
544
582
  interactionService = inject(DbxFirebaseOidcInteractionService);
545
583
  oidcConfigService = inject(DbxFirebaseOidcConfigService);
546
584
  // Config input
@@ -559,6 +597,8 @@ class DbxOAuthConsentComponent {
559
597
  routeClientUri = toSignal(this.clientUriParamReader.value$);
560
598
  routeLogoUri = toSignal(this.logoUriParamReader.value$);
561
599
  routeScopes = toSignal(this.scopesParamReader.value$);
600
+ // Auth state — undefined until Firebase resolves to avoid a flash between 'unknown' → 'no_user'/'user'
601
+ isLoggedIn = toSignal(this.dbxFirebaseAuthService.isLoggedIn$);
562
602
  // Resolved values
563
603
  resolvedInteractionUid = computed(() => this.routeUid(), ...(ngDevMode ? [{ debugName: "resolvedInteractionUid" }] : /* istanbul ignore next */ []));
564
604
  resolvedDetails = computed(() => {
@@ -579,8 +619,24 @@ class DbxOAuthConsentComponent {
579
619
  scopeInjectionConfig = computed(() => ({
580
620
  componentClass: this.config()?.consentScopeListViewClass ?? this.oidcConfigService.consentScopeListViewClass ?? DbxFirebaseOAuthConsentScopeDefaultViewComponent
581
621
  }), ...(ngDevMode ? [{ debugName: "scopeInjectionConfig" }] : /* istanbul ignore next */ []));
582
- loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
583
- error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
622
+ submitting = signal(false, ...(ngDevMode ? [{ debugName: "submitting" }] : /* istanbul ignore next */ []));
623
+ errorMessage = signal(null, ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
624
+ consentStateCase = computed(() => {
625
+ if (this.submitting()) {
626
+ return 'submitting';
627
+ }
628
+ if (this.errorMessage()) {
629
+ return 'error';
630
+ }
631
+ const isLoggedIn = this.isLoggedIn();
632
+ if (isLoggedIn === undefined) {
633
+ return 'unknown';
634
+ }
635
+ if (!isLoggedIn) {
636
+ return 'no_user';
637
+ }
638
+ return 'user';
639
+ }, ...(ngDevMode ? [{ debugName: "consentStateCase" }] : /* istanbul ignore next */ []));
584
640
  ngOnDestroy() {
585
641
  this.interactionUidParamReader.destroy();
586
642
  this.clientIdParamReader.destroy();
@@ -595,31 +651,39 @@ class DbxOAuthConsentComponent {
595
651
  deny() {
596
652
  this._submitConsent(false);
597
653
  }
654
+ retry() {
655
+ this.errorMessage.set(null);
656
+ }
598
657
  _submitConsent(approved) {
658
+ if (this.consentStateCase() !== 'user') {
659
+ return;
660
+ }
599
661
  const uid = this.resolvedInteractionUid();
600
662
  if (!uid) {
601
- this.error.set('Missing interaction UID');
663
+ this.errorMessage.set('Missing interaction UID');
602
664
  return;
603
665
  }
604
- this.loading.set(true);
605
- this.error.set(null);
666
+ this.submitting.set(true);
667
+ this.errorMessage.set(null);
606
668
  this.interactionService.submitConsent(uid, approved).subscribe({
607
669
  next: (response) => {
608
- this.loading.set(false);
670
+ this.submitting.set(false);
609
671
  if (response.redirectTo) {
610
672
  window.location.href = response.redirectTo;
611
673
  }
612
674
  },
613
675
  error: () => {
614
- this.loading.set(false);
615
- this.error.set('Failed to process consent. Please try again.');
676
+ this.submitting.set(false);
677
+ this.errorMessage.set('Failed to process consent. Please try again.');
616
678
  }
617
679
  });
618
680
  }
619
681
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxOAuthConsentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
620
682
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.11", type: DbxOAuthConsentComponent, isStandalone: true, selector: "dbx-firebase-oauth-consent", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "d-block dbx-firebase-oauth-consent" }, ngImport: i0, template: `
621
- <dbx-firebase-oauth-consent-view [details]="resolvedDetails()" [loading]="loading()" [error]="error()" [scopeInjectionConfig]="scopeInjectionConfig()" (approveClick)="approve()" (denyClick)="deny()"></dbx-firebase-oauth-consent-view>
622
- `, isInline: true, dependencies: [{ kind: "component", type: DbxFirebaseOAuthConsentViewComponent, selector: "dbx-firebase-oauth-consent-view", inputs: ["details", "loading", "error", "scopeInjectionConfig"], outputs: ["approveClick", "denyClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
683
+ <dbx-firebase-oauth-consent-view [details]="resolvedDetails()" [consentStateCase]="consentStateCase()" [error]="errorMessage()" [scopeInjectionConfig]="scopeInjectionConfig()" (approveClick)="approve()" (denyClick)="deny()" (retryClick)="retry()">
684
+ <ng-content />
685
+ </dbx-firebase-oauth-consent-view>
686
+ `, isInline: true, dependencies: [{ kind: "component", type: DbxFirebaseOAuthConsentViewComponent, selector: "dbx-firebase-oauth-consent-view", inputs: ["details", "consentStateCase", "error", "scopeInjectionConfig"], outputs: ["approveClick", "denyClick", "retryClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
623
687
  }
624
688
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxOAuthConsentComponent, decorators: [{
625
689
  type: Component,
@@ -628,7 +692,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
628
692
  standalone: true,
629
693
  imports: [DbxFirebaseOAuthConsentViewComponent],
630
694
  template: `
631
- <dbx-firebase-oauth-consent-view [details]="resolvedDetails()" [loading]="loading()" [error]="error()" [scopeInjectionConfig]="scopeInjectionConfig()" (approveClick)="approve()" (denyClick)="deny()"></dbx-firebase-oauth-consent-view>
695
+ <dbx-firebase-oauth-consent-view [details]="resolvedDetails()" [consentStateCase]="consentStateCase()" [error]="errorMessage()" [scopeInjectionConfig]="scopeInjectionConfig()" (approveClick)="approve()" (denyClick)="deny()" (retryClick)="retry()">
696
+ <ng-content />
697
+ </dbx-firebase-oauth-consent-view>
632
698
  `,
633
699
  host: {
634
700
  class: 'd-block dbx-firebase-oauth-consent'
@@ -892,6 +958,173 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
892
958
  }]
893
959
  }] });
894
960
 
961
+ /**
962
+ * Document store for a single {@link OidcEntry}.
963
+ */
964
+ class OidcEntryDocumentStore extends AbstractDbxFirebaseDocumentStore {
965
+ oidcModelFunctions = inject(OidcModelFunctions);
966
+ _latestClientSecret$ = completeOnDestroy(new BehaviorSubject(undefined));
967
+ /**
968
+ * The client secret from the most recent create operation.
969
+ *
970
+ * Only available immediately after creation — the server does not return it again.
971
+ */
972
+ latestClientSecret$ = this._latestClientSecret$.asObservable();
973
+ get latestClientSecret() {
974
+ return this._latestClientSecret$.value;
975
+ }
976
+ constructor() {
977
+ super({ firestoreCollection: inject(OidcModelFirestoreCollections).oidcEntryCollection });
978
+ }
979
+ createClient = firebaseDocumentStoreCreateFunction(this, this.oidcModelFunctions.oidcEntry.createOidcEntry.client, {
980
+ onResult: (_params, result) => {
981
+ this._latestClientSecret$.next(result.client_secret);
982
+ }
983
+ });
984
+ updateClient = firebaseDocumentStoreUpdateFunction(this, this.oidcModelFunctions.oidcEntry.updateOidcEntry.client);
985
+ rotateClientSecret = firebaseDocumentStoreUpdateFunction(this, this.oidcModelFunctions.oidcEntry.updateOidcEntry.rotateClientSecret, {
986
+ onResult: (_params, result) => {
987
+ this._latestClientSecret$.next(result.client_secret);
988
+ }
989
+ });
990
+ deleteClient = firebaseDocumentStoreDeleteFunction(this, this.oidcModelFunctions.oidcEntry.deleteOidcEntry.client);
991
+ deleteToken = firebaseDocumentStoreDeleteFunction(this, this.oidcModelFunctions.oidcEntry.deleteOidcEntry.token);
992
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryDocumentStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
993
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryDocumentStore });
994
+ }
995
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryDocumentStore, decorators: [{
996
+ type: Injectable
997
+ }], ctorParameters: () => [] });
998
+
999
+ /**
1000
+ * Wrapper list of {@link OidcEntry} Grant rows belonging to the current user.
1001
+ *
1002
+ * Renders one row per Grant — i.e. one row per "app with access to my account" —
1003
+ * with an inline Revoke button that cascades through every grantable token.
1004
+ */
1005
+ class DbxFirebaseOidcEntryGrantListComponent extends AbstractDbxSelectionListWrapperDirective {
1006
+ constructor() {
1007
+ super({
1008
+ componentClass: DbxFirebaseOidcEntryGrantListViewComponent,
1009
+ defaultSelectionMode: 'view'
1010
+ });
1011
+ }
1012
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxFirebaseOidcEntryGrantListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1013
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", type: DbxFirebaseOidcEntryGrantListComponent, isStandalone: true, selector: "dbx-firebase-oidc-grant-list", host: { classAttribute: "dbx-list-no-hover-effects dbx-list-card-items-list" }, providers: provideDbxListViewWrapper(DbxFirebaseOidcEntryGrantListComponent), usesInheritance: true, ngImport: i0, template: "\n <dbx-list [state]=\"currentState$\" [config]=\"configSignal()\" [hasMore]=\"hasMore()\" [disabled]=\"disabledSignal()\" [selectionMode]=\"selectionModeSignal()\">\n <ng-content top select=\"[top]\"></ng-content>\n <ng-content bottom select=\"[bottom]\"></ng-content>\n <ng-content empty select=\"[empty]\"></ng-content>\n <ng-content emptyLoading select=\"[emptyLoading]\"></ng-content>\n <ng-content end select=\"[end]\"></ng-content>\n </dbx-list>", isInline: true, dependencies: [{ kind: "ngmodule", type: DbxListWrapperComponentImportsModule }, { kind: "component", type: i1$1.DbxListComponent, selector: "dbx-list", inputs: ["padded", "state", "config", "disabled", "selectionMode", "hasMore"], outputs: ["contentScrolled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1014
+ }
1015
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxFirebaseOidcEntryGrantListComponent, decorators: [{
1016
+ type: Component,
1017
+ args: [{
1018
+ selector: 'dbx-firebase-oidc-grant-list',
1019
+ template: DEFAULT_LIST_WRAPPER_COMPONENT_CONFIGURATION_TEMPLATE,
1020
+ providers: provideDbxListViewWrapper(DbxFirebaseOidcEntryGrantListComponent),
1021
+ standalone: true,
1022
+ host: {
1023
+ class: 'dbx-list-no-hover-effects dbx-list-card-items-list'
1024
+ },
1025
+ imports: [DbxListWrapperComponentImportsModule],
1026
+ changeDetection: ChangeDetectionStrategy.OnPush
1027
+ }]
1028
+ }], ctorParameters: () => [] });
1029
+ class DbxFirebaseOidcEntryGrantListViewComponent extends AbstractDbxSelectionListViewDirective {
1030
+ config = {
1031
+ componentClass: DbxFirebaseOidcEntryGrantListViewItemComponent,
1032
+ mapValuesToItemValues: (x) => of(x.map((y, i) => {
1033
+ const id = y.id;
1034
+ return { ...y, key: id ?? `grant_${i}`, itemValue: y };
1035
+ }))
1036
+ };
1037
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxFirebaseOidcEntryGrantListViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1038
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", type: DbxFirebaseOidcEntryGrantListViewComponent, isStandalone: true, selector: "dbx-firebase-oidc-grant-list-view", providers: provideDbxListView(DbxFirebaseOidcEntryGrantListViewComponent), usesInheritance: true, ngImport: i0, template: "<dbx-selection-list-view [config]=\"config\"></dbx-selection-list-view>", isInline: true, dependencies: [{ kind: "ngmodule", type: DbxSelectionValueListViewComponentImportsModule }, { kind: "component", type: i1$1.DbxSelectionValueListViewComponent, selector: "dbx-selection-list-view" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1039
+ }
1040
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxFirebaseOidcEntryGrantListViewComponent, decorators: [{
1041
+ type: Component,
1042
+ args: [{
1043
+ selector: 'dbx-firebase-oidc-grant-list-view',
1044
+ template: DEFAULT_DBX_SELECTION_VALUE_LIST_COMPONENT_CONFIGURATION_TEMPLATE,
1045
+ providers: provideDbxListView(DbxFirebaseOidcEntryGrantListViewComponent),
1046
+ standalone: true,
1047
+ imports: [DbxSelectionValueListViewComponentImportsModule],
1048
+ changeDetection: ChangeDetectionStrategy.OnPush
1049
+ }]
1050
+ }] });
1051
+ // MARK: Item
1052
+ /**
1053
+ * Per-row view for a Grant entry. Inline "Revoke" button uses a per-component
1054
+ * {@link OidcEntryDocumentStore} keyed to this entry's id so calling
1055
+ * `deleteToken` invokes the {@link DeleteOidcTokenParams} callModel against
1056
+ * the right document.
1057
+ */
1058
+ class DbxFirebaseOidcEntryGrantListViewItemComponent extends AbstractDbxValueListViewItemComponent {
1059
+ oidcEntryDocumentStore = inject(OidcEntryDocumentStore);
1060
+ clientIdSignal = computed(() => this._payload().clientId ?? '', ...(ngDevMode ? [{ debugName: "clientIdSignal" }] : /* istanbul ignore next */ []));
1061
+ scopeSignal = computed(() => this._payload().openid?.scope ?? null, ...(ngDevMode ? [{ debugName: "scopeSignal" }] : /* istanbul ignore next */ []));
1062
+ expiresAtSignal = computed(() => this.itemValue.expiresAt ?? null, ...(ngDevMode ? [{ debugName: "expiresAtSignal" }] : /* istanbul ignore next */ []));
1063
+ revokeConfirmConfig = {
1064
+ title: 'Revoke access',
1065
+ prompt: 'This app will lose access to your account immediately. Existing access and refresh tokens stop working.',
1066
+ confirmText: 'Revoke'
1067
+ };
1068
+ handleRevoke = (_, context) => {
1069
+ context.startWorkingWithLoadingStateObservable(this.oidcEntryDocumentStore.deleteToken({}));
1070
+ };
1071
+ constructor() {
1072
+ super();
1073
+ const id = this.itemValue.id;
1074
+ if (id) {
1075
+ this.oidcEntryDocumentStore.setId(id);
1076
+ }
1077
+ }
1078
+ _payload() {
1079
+ return this.itemValue.payload ?? {};
1080
+ }
1081
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxFirebaseOidcEntryGrantListViewItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1082
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: DbxFirebaseOidcEntryGrantListViewItemComponent, isStandalone: true, selector: "dbx-firebase-oidc-grant-list-view-item", providers: [OidcEntryDocumentStore], usesInheritance: true, ngImport: i0, template: `
1083
+ <div class="dbx-list-item-padded dbx-list-item-padded-thick dbx-list-two-line-item">
1084
+ <div class="item-left">
1085
+ <span class="item-title">{{ clientIdSignal() }}</span>
1086
+ @if (scopeSignal()) {
1087
+ <span class="item-details">{{ scopeSignal() }}</span>
1088
+ }
1089
+ @if (expiresAtSignal()) {
1090
+ <span class="item-details-footnote">Expires {{ expiresAtSignal() | date: 'medium' }}</span>
1091
+ }
1092
+ </div>
1093
+ <dbx-spacer></dbx-spacer>
1094
+ <div class="item-right">
1095
+ <dbx-button dbxAction [dbxActionHandler]="handleRevoke" [dbxActionConfirm]="revokeConfirmConfig" dbxActionButton text="Revoke" icon="block" color="warn" [raised]="true"></dbx-button>
1096
+ </div>
1097
+ </div>
1098
+ `, isInline: true, dependencies: [{ kind: "directive", type: DbxSpacerDirective, selector: "dbx-spacer, [dbxSpacer]" }, { kind: "component", type: DbxButtonComponent, selector: "dbx-button", inputs: ["bar", "type", "buttonStyle", "color", "spinnerColor", "customButtonColor", "customTextColor", "customSpinnerColor", "basic", "tonal", "raised", "stroked", "flat", "iconOnly", "fab", "customContent", "allowClickPropagation", "mode"] }, { kind: "directive", type: DbxActionDirective, selector: "dbx-action,[dbxAction]", exportAs: ["action", "dbxAction"] }, { kind: "directive", type: DbxActionHandlerDirective, selector: "[dbxActionHandler]", inputs: ["dbxActionHandler"] }, { kind: "directive", type: DbxActionButtonDirective, selector: "[dbxActionButton]", inputs: ["dbxActionButtonEcho"] }, { kind: "directive", type: DbxActionConfirmDirective, selector: "[dbxActionConfirm]", inputs: ["dbxActionConfirm", "dbxActionConfirmSkip"] }, { kind: "pipe", type: DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1099
+ }
1100
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxFirebaseOidcEntryGrantListViewItemComponent, decorators: [{
1101
+ type: Component,
1102
+ args: [{
1103
+ selector: 'dbx-firebase-oidc-grant-list-view-item',
1104
+ template: `
1105
+ <div class="dbx-list-item-padded dbx-list-item-padded-thick dbx-list-two-line-item">
1106
+ <div class="item-left">
1107
+ <span class="item-title">{{ clientIdSignal() }}</span>
1108
+ @if (scopeSignal()) {
1109
+ <span class="item-details">{{ scopeSignal() }}</span>
1110
+ }
1111
+ @if (expiresAtSignal()) {
1112
+ <span class="item-details-footnote">Expires {{ expiresAtSignal() | date: 'medium' }}</span>
1113
+ }
1114
+ </div>
1115
+ <dbx-spacer></dbx-spacer>
1116
+ <div class="item-right">
1117
+ <dbx-button dbxAction [dbxActionHandler]="handleRevoke" [dbxActionConfirm]="revokeConfirmConfig" dbxActionButton text="Revoke" icon="block" color="warn" [raised]="true"></dbx-button>
1118
+ </div>
1119
+ </div>
1120
+ `,
1121
+ standalone: true,
1122
+ imports: [DatePipe, DbxSpacerDirective, DbxButtonComponent, DbxActionDirective, DbxActionHandlerDirective, DbxActionButtonDirective, DbxActionConfirmDirective],
1123
+ providers: [OidcEntryDocumentStore],
1124
+ changeDetection: ChangeDetectionStrategy.OnPush
1125
+ }]
1126
+ }], ctorParameters: () => [] });
1127
+
895
1128
  class DbxFirebaseOidcEntryClientListComponent extends AbstractDbxSelectionListWrapperDirective {
896
1129
  constructor() {
897
1130
  super({
@@ -1016,42 +1249,77 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
1016
1249
  }] });
1017
1250
 
1018
1251
  /**
1019
- * Document store for a single {@link OidcEntry}.
1252
+ * Collection store for querying {@link OidcEntry} documents.
1020
1253
  */
1021
- class OidcEntryDocumentStore extends AbstractDbxFirebaseDocumentStore {
1022
- oidcModelFunctions = inject(OidcModelFunctions);
1023
- _latestClientSecret$ = completeOnDestroy(new BehaviorSubject(undefined));
1024
- /**
1025
- * The client secret from the most recent create operation.
1026
- *
1027
- * Only available immediately after creation — the server does not return it again.
1028
- */
1029
- latestClientSecret$ = this._latestClientSecret$.asObservable();
1030
- get latestClientSecret() {
1031
- return this._latestClientSecret$.value;
1032
- }
1254
+ class OidcEntryCollectionStore extends AbstractDbxFirebaseCollectionStore {
1033
1255
  constructor() {
1034
1256
  super({ firestoreCollection: inject(OidcModelFirestoreCollections).oidcEntryCollection });
1035
1257
  }
1036
- createClient = firebaseDocumentStoreCreateFunction(this, this.oidcModelFunctions.oidcEntry.createOidcEntry.client, {
1037
- onResult: (_params, result) => {
1038
- this._latestClientSecret$.next(result.client_secret);
1039
- }
1040
- });
1041
- updateClient = firebaseDocumentStoreUpdateFunction(this, this.oidcModelFunctions.oidcEntry.updateOidcEntry.client);
1042
- rotateClientSecret = firebaseDocumentStoreUpdateFunction(this, this.oidcModelFunctions.oidcEntry.updateOidcEntry.rotateClientSecret, {
1043
- onResult: (_params, result) => {
1044
- this._latestClientSecret$.next(result.client_secret);
1045
- }
1046
- });
1047
- deleteClient = firebaseDocumentStoreDeleteFunction(this, this.oidcModelFunctions.oidcEntry.deleteOidcEntry.client);
1048
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryDocumentStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1049
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryDocumentStore });
1258
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryCollectionStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1259
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryCollectionStore });
1050
1260
  }
1051
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryDocumentStore, decorators: [{
1261
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryCollectionStore, decorators: [{
1052
1262
  type: Injectable
1053
1263
  }], ctorParameters: () => [] });
1054
1264
 
1265
+ /**
1266
+ * Directive providing a {@link OidcEntryCollectionStore} for querying {@link OidcEntry} documents.
1267
+ */
1268
+ class OidcEntryCollectionStoreDirective extends DbxFirebaseCollectionStoreDirective {
1269
+ constructor() {
1270
+ super(inject(OidcEntryCollectionStore));
1271
+ }
1272
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryCollectionStoreDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1273
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.11", type: OidcEntryCollectionStoreDirective, isStandalone: true, selector: "[dbxOidcEntryCollection]", providers: provideDbxFirebaseCollectionStoreDirective(OidcEntryCollectionStoreDirective, OidcEntryCollectionStore), usesInheritance: true, ngImport: i0 });
1274
+ }
1275
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryCollectionStoreDirective, decorators: [{
1276
+ type: Directive,
1277
+ args: [{
1278
+ selector: '[dbxOidcEntryCollection]',
1279
+ providers: provideDbxFirebaseCollectionStoreDirective(OidcEntryCollectionStoreDirective, OidcEntryCollectionStore),
1280
+ standalone: true
1281
+ }]
1282
+ }], ctorParameters: () => [] });
1283
+
1284
+ /**
1285
+ * Drop-in container for the "apps with access to my account" management UI.
1286
+ *
1287
+ * Wires a {@link OidcEntryCollectionStoreDirective} to query Grant entries
1288
+ * for the signed-in user, then renders {@link DbxFirebaseOidcEntryGrantListComponent}
1289
+ * with inline Revoke buttons. No inputs — the container resolves the current
1290
+ * user via {@link DbxFirebaseAuthService}.
1291
+ */
1292
+ class DbxFirebaseOidcEntryGrantListContainerComponent {
1293
+ dbxFirebaseAuthService = inject(DbxFirebaseAuthService);
1294
+ oidcEntryCollectionStoreDirective = viewChild(OidcEntryCollectionStoreDirective, ...(ngDevMode ? [{ debugName: "oidcEntryCollectionStoreDirective" }] : /* istanbul ignore next */ []));
1295
+ grantConstraintsSignal = toSignal(this.dbxFirebaseAuthService.currentAuthUser$.pipe(map((user) => (user?.uid ? oidcGrantEntriesByUidQuery(user.uid) : []))));
1296
+ ngOnInit() {
1297
+ const directive = this.oidcEntryCollectionStoreDirective();
1298
+ directive?.setMaxPages(5);
1299
+ directive?.setItemsPerPage(20);
1300
+ }
1301
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxFirebaseOidcEntryGrantListContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1302
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.11", type: DbxFirebaseOidcEntryGrantListContainerComponent, isStandalone: true, selector: "dbx-firebase-oidc-grant-list-container", viewQueries: [{ propertyName: "oidcEntryCollectionStoreDirective", first: true, predicate: OidcEntryCollectionStoreDirective, descendants: true, isSignal: true }], ngImport: i0, template: `
1303
+ <div dbxOidcEntryCollection dbxFirebaseCollectionChange="auto" [constraints]="grantConstraintsSignal()">
1304
+ <dbx-firebase-oidc-grant-list dbxFirebaseCollectionList></dbx-firebase-oidc-grant-list>
1305
+ </div>
1306
+ `, isInline: true, dependencies: [{ kind: "directive", type: OidcEntryCollectionStoreDirective, selector: "[dbxOidcEntryCollection]" }, { kind: "directive", type: DbxFirebaseCollectionListDirective, selector: "[dbxFirebaseCollectionList]" }, { kind: "directive", type: DbxFirebaseCollectionChangeDirective, selector: "[dbxFirebaseCollectionChange]", inputs: ["dbxFirebaseCollectionChange"] }, { kind: "component", type: DbxFirebaseOidcEntryGrantListComponent, selector: "dbx-firebase-oidc-grant-list" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1307
+ }
1308
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxFirebaseOidcEntryGrantListContainerComponent, decorators: [{
1309
+ type: Component,
1310
+ args: [{
1311
+ selector: 'dbx-firebase-oidc-grant-list-container',
1312
+ template: `
1313
+ <div dbxOidcEntryCollection dbxFirebaseCollectionChange="auto" [constraints]="grantConstraintsSignal()">
1314
+ <dbx-firebase-oidc-grant-list dbxFirebaseCollectionList></dbx-firebase-oidc-grant-list>
1315
+ </div>
1316
+ `,
1317
+ standalone: true,
1318
+ imports: [OidcEntryCollectionStoreDirective, DbxFirebaseCollectionListDirective, DbxFirebaseCollectionChangeDirective, DbxFirebaseOidcEntryGrantListComponent],
1319
+ changeDetection: ChangeDetectionStrategy.OnPush
1320
+ }]
1321
+ }], propDecorators: { oidcEntryCollectionStoreDirective: [{ type: i0.ViewChild, args: [i0.forwardRef(() => OidcEntryCollectionStoreDirective), { isSignal: true }] }] } });
1322
+
1055
1323
  /**
1056
1324
  * Container component for creating a new OAuth client.
1057
1325
  *
@@ -1365,39 +1633,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
1365
1633
  }]
1366
1634
  }] });
1367
1635
 
1368
- /**
1369
- * Collection store for querying {@link OidcEntry} documents.
1370
- */
1371
- class OidcEntryCollectionStore extends AbstractDbxFirebaseCollectionStore {
1372
- constructor() {
1373
- super({ firestoreCollection: inject(OidcModelFirestoreCollections).oidcEntryCollection });
1374
- }
1375
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryCollectionStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1376
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryCollectionStore });
1377
- }
1378
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryCollectionStore, decorators: [{
1379
- type: Injectable
1380
- }], ctorParameters: () => [] });
1381
-
1382
- /**
1383
- * Directive providing a {@link OidcEntryCollectionStore} for querying {@link OidcEntry} documents.
1384
- */
1385
- class OidcEntryCollectionStoreDirective extends DbxFirebaseCollectionStoreDirective {
1386
- constructor() {
1387
- super(inject(OidcEntryCollectionStore));
1388
- }
1389
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryCollectionStoreDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1390
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.11", type: OidcEntryCollectionStoreDirective, isStandalone: true, selector: "[dbxOidcEntryCollection]", providers: provideDbxFirebaseCollectionStoreDirective(OidcEntryCollectionStoreDirective, OidcEntryCollectionStore), usesInheritance: true, ngImport: i0 });
1391
- }
1392
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: OidcEntryCollectionStoreDirective, decorators: [{
1393
- type: Directive,
1394
- args: [{
1395
- selector: '[dbxOidcEntryCollection]',
1396
- providers: provideDbxFirebaseCollectionStoreDirective(OidcEntryCollectionStoreDirective, OidcEntryCollectionStore),
1397
- standalone: true
1398
- }]
1399
- }], ctorParameters: () => [] });
1400
-
1401
1636
  /**
1402
1637
  * Directive providing a {@link OidcEntryDocumentStore} for accessing a single {@link OidcEntry} document.
1403
1638
  */
@@ -1465,5 +1700,5 @@ function provideDbxFirebaseOidc(config) {
1465
1700
  * Generated bundle index. Do not edit.
1466
1701
  */
1467
1702
 
1468
- export { AbstractDbxFirebaseOAuthConsentScopeViewComponent, DEFAULT_OIDC_AUTHORIZATION_ENDPOINT_PATH, DEFAULT_OIDC_CLIENT_ID_PARAM_KEY, DEFAULT_OIDC_CLIENT_NAME_PARAM_KEY, DEFAULT_OIDC_CLIENT_URI_PARAM_KEY, DEFAULT_OIDC_INTERACTION_ENDPOINT_PATH, DEFAULT_OIDC_INTERACTION_UID_PARAM_KEY, DEFAULT_OIDC_LOGO_URI_PARAM_KEY, DEFAULT_OIDC_SCOPES_PARAM_KEY, DEFAULT_OIDC_TOKEN_ENDPOINT_AUTH_METHODS, DbxFirebaseOAuthConsentScopeDefaultViewComponent, DbxFirebaseOAuthConsentScopeListComponent, DbxFirebaseOAuthConsentViewComponent, DbxFirebaseOAuthLoginComponent, DbxFirebaseOAuthLoginViewComponent, DbxFirebaseOidcConfig, DbxFirebaseOidcConfigService, DbxFirebaseOidcEntryClientCreateComponent, DbxFirebaseOidcEntryClientForgeFormComponent, DbxFirebaseOidcEntryClientListComponent, DbxFirebaseOidcEntryClientListViewComponent, DbxFirebaseOidcEntryClientListViewItemClientComponent, DbxFirebaseOidcEntryClientListViewItemComponent, DbxFirebaseOidcEntryClientListViewItemDefaultComponent, DbxFirebaseOidcEntryClientTestComponent, DbxFirebaseOidcEntryClientTestForgeFormComponent, DbxFirebaseOidcEntryClientUpdateComponent, DbxFirebaseOidcEntryClientViewComponent, DbxFirebaseOidcInteractionService, DbxOAuthConsentComponent, OidcEntryCollectionStore, OidcEntryCollectionStoreDirective, OidcEntryDocumentStore, OidcEntryDocumentStoreDirective, oidcClientHomepageUriForgeField, oidcClientJwksUriForgeField, oidcClientLogoUriForgeField, oidcClientNameForgeField, oidcClientRedirectUrisForgeField, oidcClientTestClientIdForgeField, oidcClientTestRedirectUriForgeField, oidcClientTestScopesForgeField, oidcClientTokenEndpointAuthMethodForgeField, oidcEntryClientForgeFormFields, oidcEntryClientTestForgeFormFields, oidcEntryClientUpdateForgeFormFields, provideDbxFirebaseOidc, provideOidcModelFirestoreCollections };
1703
+ export { AbstractDbxFirebaseOAuthConsentScopeViewComponent, DEFAULT_OIDC_AUTHORIZATION_ENDPOINT_PATH, DEFAULT_OIDC_CLIENT_ID_PARAM_KEY, DEFAULT_OIDC_CLIENT_NAME_PARAM_KEY, DEFAULT_OIDC_CLIENT_URI_PARAM_KEY, DEFAULT_OIDC_INTERACTION_ENDPOINT_PATH, DEFAULT_OIDC_INTERACTION_UID_PARAM_KEY, DEFAULT_OIDC_LOGO_URI_PARAM_KEY, DEFAULT_OIDC_SCOPES_PARAM_KEY, DEFAULT_OIDC_TOKEN_ENDPOINT_AUTH_METHODS, DbxFirebaseOAuthConsentScopeDefaultViewComponent, DbxFirebaseOAuthConsentScopeListComponent, DbxFirebaseOAuthConsentViewComponent, DbxFirebaseOAuthLoginComponent, DbxFirebaseOAuthLoginViewComponent, DbxFirebaseOidcConfig, DbxFirebaseOidcConfigService, DbxFirebaseOidcEntryClientCreateComponent, DbxFirebaseOidcEntryClientForgeFormComponent, DbxFirebaseOidcEntryClientListComponent, DbxFirebaseOidcEntryClientListViewComponent, DbxFirebaseOidcEntryClientListViewItemClientComponent, DbxFirebaseOidcEntryClientListViewItemComponent, DbxFirebaseOidcEntryClientListViewItemDefaultComponent, DbxFirebaseOidcEntryClientTestComponent, DbxFirebaseOidcEntryClientTestForgeFormComponent, DbxFirebaseOidcEntryClientUpdateComponent, DbxFirebaseOidcEntryClientViewComponent, DbxFirebaseOidcEntryGrantListComponent, DbxFirebaseOidcEntryGrantListContainerComponent, DbxFirebaseOidcEntryGrantListViewComponent, DbxFirebaseOidcEntryGrantListViewItemComponent, DbxFirebaseOidcInteractionService, DbxOAuthConsentComponent, OidcEntryCollectionStore, OidcEntryCollectionStoreDirective, OidcEntryDocumentStore, OidcEntryDocumentStoreDirective, oidcClientHomepageUriForgeField, oidcClientJwksUriForgeField, oidcClientLogoUriForgeField, oidcClientNameForgeField, oidcClientRedirectUrisForgeField, oidcClientTestClientIdForgeField, oidcClientTestRedirectUriForgeField, oidcClientTestScopesForgeField, oidcClientTokenEndpointAuthMethodForgeField, oidcEntryClientForgeFormFields, oidcEntryClientTestForgeFormFields, oidcEntryClientUpdateForgeFormFields, provideDbxFirebaseOidc, provideOidcModelFirestoreCollections };
1469
1704
  //# sourceMappingURL=dereekb-dbx-firebase-oidc.mjs.map