@atlasauth/angular 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { OnDestroy, Signal } from '@angular/core';
2
2
  import { Observable } from 'rxjs';
3
- import { FapiClient, type ProviderToken, type SignOutOptions } from '@atlasauth/js';
3
+ import { FapiClient, type ProviderToken, type SignOutOptions, type SignOutResult } from '@atlasauth/js';
4
4
  import { type ProtectCondition } from '@atlasauth/authz';
5
5
  import { type Appearance, type AppearanceRender, type InstanceDesign } from './appearance';
6
6
  import { type Catalog } from './i18n';
@@ -34,6 +34,14 @@ export declare class AtlasService implements OnDestroy {
34
34
  private readonly cache;
35
35
  private readonly fapiClient;
36
36
  private refreshTimer;
37
+ /**
38
+ * The sessions this browser signed out of (tombstones in localStorage, per
39
+ * Frontend API origin), the revoke and its background re-tries. Every reload /
40
+ * refresh asks it before adopting a session, so a sign-out the server never
41
+ * confirmed is not undone by the still-valid refresh cookie.
42
+ */
43
+ private readonly guard;
44
+ private stopWatchingSignOut;
37
45
  private readonly catalog;
38
46
  /**
39
47
  * A sign-in attempt handed back by an OAuth redirect that still needs a second
@@ -110,8 +118,19 @@ export declare class AtlasService implements OnDestroy {
110
118
  getProviderToken(provider: string): Promise<ProviderToken | null>;
111
119
  /** Imperative `has()` — the same evaluation `*atlasProtect` renders on. */
112
120
  has(condition: ProtectCondition): boolean;
113
- /** Revoke the current session server-side and drop all local auth state. */
114
- signOut(options?: SignOutOptions): Promise<void>;
121
+ /**
122
+ * Revoke the current session server-side and drop all local auth state.
123
+ *
124
+ * The session id is remembered before the revoke (a tombstone shared by every
125
+ * tab), so a reload, a token refresh, a sibling tab or a tab opened later never
126
+ * re-adopts it — even when the revoke failed (it is retried once, then again in
127
+ * the background) and the refresh cookie is still valid. Resolves
128
+ * `{ revoked, activeSessionId? }`; with `{ strict: true }` an unconfirmed revoke
129
+ * rejects with a `SignOutError` instead (after the local sign-out). A parked
130
+ * session the server promoted on revoke is adopted. Front-channel logout runs
131
+ * unless `{ frontchannel: false }`.
132
+ */
133
+ signOut(options?: SignOutOptions): Promise<SignOutResult>;
115
134
  /**
116
135
  * Switch the active organization (or `null` for the personal account). The
117
136
  * new token carries the new org claims, so the app's permission checks update
@@ -132,6 +151,7 @@ export declare class AtlasService implements OnDestroy {
132
151
  private call;
133
152
  private applyToken;
134
153
  private refresh;
154
+ private clearLocalState;
135
155
  /** §7.4: proactive, jittered refresh scheduled from the token's own expiry. */
136
156
  private scheduleRefresh;
137
157
  private clearRefreshTimer;
@@ -36,8 +36,18 @@ export declare class AttemptFlowComponent {
36
36
  * with `needs_captcha`. Null when the flow draws none.
37
37
  */
38
38
  captcha: CaptchaController | null;
39
+ /**
40
+ * The first factors to offer on the `needs_first_factor` step — pass
41
+ * `AtlasFlowController.firstFactors()`, which drops email code / link while the
42
+ * app cannot deliver email. Null uses the server's list as-is.
43
+ */
44
+ firstFactors: string[] | null;
45
+ /** The first factor already sent (`AtlasFlowController.preparedFactor()`): its code is collected. */
46
+ preparedFactor: string | null;
39
47
  /** Emits the collected field values when the form is submitted. */
40
48
  submitFlow: EventEmitter<Record<string, string>>;
49
+ /** Emits when the user picks a first factor the server must send first (an emailed code). */
50
+ chooseFactor: EventEmitter<"email_code">;
41
51
  protected values: Record<string, string>;
42
52
  protected t(key: string, vars?: Record<string, string>): string;
43
53
  protected cls(key: ElementKey, base: string): string;
@@ -47,9 +57,12 @@ export declare class AttemptFlowComponent {
47
57
  protected fieldErrorsFor(name: string): FieldError[];
48
58
  private step;
49
59
  protected showCaptcha(): boolean;
60
+ /** The first factors on offer at a `needs_first_factor` step (empty on any other). */
61
+ private offered;
62
+ protected showEmailCodeOption(): boolean;
50
63
  protected showSubmit(): boolean;
51
64
  protected fields(): StepField[];
52
65
  static ɵfac: i0.ɵɵFactoryDeclaration<AttemptFlowComponent, never>;
53
- static ɵcmp: i0.ɵɵComponentDeclaration<AttemptFlowComponent, "atlas-attempt-flow", never, { "attempt": { "alias": "attempt"; "required": false; }; "busy": { "alias": "busy"; "required": false; }; "errors": { "alias": "errors"; "required": false; }; "titleKey": { "alias": "titleKey"; "required": false; }; "captcha": { "alias": "captcha"; "required": false; }; }, { "submitFlow": "submitFlow"; }, never, never, true, never>;
66
+ static ɵcmp: i0.ɵɵComponentDeclaration<AttemptFlowComponent, "atlas-attempt-flow", never, { "attempt": { "alias": "attempt"; "required": false; }; "busy": { "alias": "busy"; "required": false; }; "errors": { "alias": "errors"; "required": false; }; "titleKey": { "alias": "titleKey"; "required": false; }; "captcha": { "alias": "captcha"; "required": false; }; "firstFactors": { "alias": "firstFactors"; "required": false; }; "preparedFactor": { "alias": "preparedFactor"; "required": false; }; }, { "submitFlow": "submitFlow"; "chooseFactor": "chooseFactor"; }, never, never, true, never>;
54
67
  }
55
68
  export {};
@@ -34,6 +34,12 @@ export declare class AtlasFlowController {
34
34
  readonly captchaDrawn: WritableSignal<boolean>;
35
35
  /** Whether {@link signUpCaptcha} currently draws a widget (for templates). */
36
36
  readonly signUpCaptchaDrawn: WritableSignal<boolean>;
37
+ /**
38
+ * The first factor the server was asked to send ({@link prepare}) on the
39
+ * current `needs_first_factor` step — the form then collects its code. Null
40
+ * otherwise.
41
+ */
42
+ readonly preparedFactor: WritableSignal<"email_code">;
37
43
  private pollTimer;
38
44
  private identifier;
39
45
  constructor(client: FapiClient, reload: () => Promise<void>, pending: {
@@ -44,6 +50,26 @@ export declare class AtlasFlowController {
44
50
  t?: (key: string) => string);
45
51
  /** Fetch the instance's public settings and draw whatever captcha they require. */
46
52
  loadSettings(): Promise<void>;
53
+ /**
54
+ * The first factors to offer on a `needs_first_factor` step: the server's list
55
+ * without email code / link while the app cannot deliver email
56
+ * (`settings.emailDelivery.available === false`). Empty on any other step.
57
+ */
58
+ firstFactors(): string[];
59
+ /**
60
+ * True when email + password sign-up cannot complete because the app cannot
61
+ * send the verification email (`settings.emailDelivery.passwordSignUp === false`):
62
+ * `<atlas-sign-up>` shows the "can't send email" notice instead of the form.
63
+ */
64
+ signUpEmailUnavailable(): boolean;
65
+ /** False when a password reset email cannot be delivered — hide "Forgot password?". */
66
+ passwordResetAvailable(): boolean;
67
+ /**
68
+ * Ask the server to email a sign-in code for the current `needs_first_factor`
69
+ * step (`POST …/prepare_first_factor`); the form then collects the code, which
70
+ * {@link submit} posts as the `email_code` strategy.
71
+ */
72
+ prepare(strategy: 'email_code'): Promise<void>;
47
73
  /** Keep both captchas in step with the settings and the flow's current step. */
48
74
  private syncCaptcha;
49
75
  private setState;
@@ -11,7 +11,9 @@ export interface SignUpFormSubmit {
11
11
  * The create-account step of `<atlas-sign-up>`: the instance's configured extra
12
12
  * fields, email + password, the legal-consent row and — when the instance
13
13
  * requires one on sign-up — the captcha widget. Values live on the component so
14
- * a refused submit never clears them.
14
+ * a refused submit never clears them. When the app cannot send the verification
15
+ * email (`settings.emailDelivery.passwordSignUp === false`) it shows the
16
+ * `signUp.emailUnavailable` notice instead of the form.
15
17
  */
16
18
  export declare class SignUpFormComponent {
17
19
  private readonly atlas;
@@ -26,6 +28,8 @@ export declare class SignUpFormComponent {
26
28
  protected t(key: string, vars?: Record<string, string>): string;
27
29
  protected cls(key: ElementKey, base: string): string;
28
30
  protected setValue(name: string, value: string): void;
31
+ /** Email + password sign-up cannot complete: the app cannot send the verification email. */
32
+ protected emailUnavailable(): boolean;
29
33
  protected fields(): PublicSignUpField[];
30
34
  protected label(f: PublicSignUpField): string;
31
35
  protected inputType(f: PublicSignUpField): string;
@@ -28,4 +28,5 @@ export * from './lib/i18n';
28
28
  export * from './lib/protect';
29
29
  export * from './lib/types';
30
30
  export * from './lib/fapi';
31
- export type { InstanceSettings, PublicSignUpField, CaptchaController, CaptchaFlowKey, CaptchaWidgetMode, FlowCaptcha, } from '@atlasauth/js';
31
+ export type { InstanceSettings, PublicSignUpField, CaptchaController, CaptchaFlowKey, CaptchaWidgetMode, FlowCaptcha, EmailDelivery, SignOutOptions, SignOutResult, } from '@atlasauth/js';
32
+ export { SignOutError } from '@atlasauth/js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlasauth/angular",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Official Angular SDK for Atlas — the Angular peer of @atlasauth/react.",
5
5
  "license": "MIT",
6
6
  "module": "./dist/fesm2022/atlas-angular.mjs",
@@ -19,9 +19,9 @@
19
19
  "sideEffects": false,
20
20
  "dependencies": {
21
21
  "tslib": "^2.6.3",
22
- "@atlasauth/design": "0.1.0",
23
- "@atlasauth/authz": "0.1.1",
24
- "@atlasauth/js": "0.6.0"
22
+ "@atlasauth/design": "0.2.0",
23
+ "@atlasauth/js": "0.8.0",
24
+ "@atlasauth/authz": "0.1.1"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "@angular/core": ">=17",
@@ -64,6 +64,7 @@
64
64
  },
65
65
  "scripts": {
66
66
  "build": "ng-packagr -p ng-package.json",
67
- "typecheck": "tsc -p tsconfig.json --noEmit"
67
+ "typecheck": "tsc -p tsconfig.json --noEmit",
68
+ "test": "vitest run"
68
69
  }
69
70
  }