@rdlabo/ionic-angular-kit 0.0.15 → 0.0.17
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.
- package/README.md +65 -1
- package/fesm2022/rdlabo-ionic-angular-kit-auth-firebase-social.mjs +218 -0
- package/fesm2022/rdlabo-ionic-angular-kit-auth-firebase-social.mjs.map +1 -0
- package/fesm2022/rdlabo-ionic-angular-kit-auth-firebase.mjs +340 -0
- package/fesm2022/rdlabo-ionic-angular-kit-auth-firebase.mjs.map +1 -0
- package/fesm2022/rdlabo-ionic-angular-kit.mjs +182 -34
- package/fesm2022/rdlabo-ionic-angular-kit.mjs.map +1 -1
- package/package.json +26 -1
- package/types/rdlabo-ionic-angular-kit-auth-firebase-social.d.ts +104 -0
- package/types/rdlabo-ionic-angular-kit-auth-firebase.d.ts +266 -0
- package/types/rdlabo-ionic-angular-kit.d.ts +106 -28
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rdlabo/ionic-angular-kit",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/common": "^21.0.0",
|
|
6
6
|
"@angular/core": "^21.0.0",
|
|
7
|
+
"@angular/forms": "^21.0.0",
|
|
7
8
|
"@angular/router": "^21.0.0",
|
|
8
9
|
"@ionic/angular": "^8.0.0",
|
|
9
10
|
"@ionic/storage-angular": "^4.0.0",
|
|
11
|
+
"@angular/fire": ">=21.0.0-rc.0",
|
|
12
|
+
"firebase": "^11.0.0",
|
|
10
13
|
"@capacitor/core": ">=6.0.0 <9.0.0",
|
|
11
14
|
"@capacitor/haptics": ">=6.0.0 <9.0.0",
|
|
12
15
|
"@capacitor/keyboard": ">=6.0.0 <9.0.0",
|
|
@@ -14,11 +17,19 @@
|
|
|
14
17
|
"@capacitor/preferences": ">=6.0.0 <9.0.0",
|
|
15
18
|
"@capacitor/status-bar": ">=6.0.0 <9.0.0",
|
|
16
19
|
"@capacitor-community/in-app-review": ">=6.0.0 <9.0.0",
|
|
20
|
+
"@capacitor-community/facebook-login": ">=8.0.0 <9.0.0",
|
|
21
|
+
"@capacitor-community/apple-sign-in": "*",
|
|
17
22
|
"@rdlabo/capacitor-brotherprint": ">=6.0.0 <9.0.0",
|
|
18
23
|
"dom-to-image-more": "^3.0.0",
|
|
19
24
|
"rxjs": "^7.8.0"
|
|
20
25
|
},
|
|
21
26
|
"peerDependenciesMeta": {
|
|
27
|
+
"@angular/fire": {
|
|
28
|
+
"optional": true
|
|
29
|
+
},
|
|
30
|
+
"firebase": {
|
|
31
|
+
"optional": true
|
|
32
|
+
},
|
|
22
33
|
"@capacitor/preferences": {
|
|
23
34
|
"optional": true
|
|
24
35
|
},
|
|
@@ -28,6 +39,12 @@
|
|
|
28
39
|
"@capacitor-community/in-app-review": {
|
|
29
40
|
"optional": true
|
|
30
41
|
},
|
|
42
|
+
"@capacitor-community/facebook-login": {
|
|
43
|
+
"optional": true
|
|
44
|
+
},
|
|
45
|
+
"@capacitor-community/apple-sign-in": {
|
|
46
|
+
"optional": true
|
|
47
|
+
},
|
|
31
48
|
"@rdlabo/capacitor-brotherprint": {
|
|
32
49
|
"optional": true
|
|
33
50
|
},
|
|
@@ -49,6 +66,14 @@
|
|
|
49
66
|
"types": "./types/rdlabo-ionic-angular-kit.d.ts",
|
|
50
67
|
"default": "./fesm2022/rdlabo-ionic-angular-kit.mjs"
|
|
51
68
|
},
|
|
69
|
+
"./auth-firebase": {
|
|
70
|
+
"types": "./types/rdlabo-ionic-angular-kit-auth-firebase.d.ts",
|
|
71
|
+
"default": "./fesm2022/rdlabo-ionic-angular-kit-auth-firebase.mjs"
|
|
72
|
+
},
|
|
73
|
+
"./auth-firebase/social": {
|
|
74
|
+
"types": "./types/rdlabo-ionic-angular-kit-auth-firebase-social.d.ts",
|
|
75
|
+
"default": "./fesm2022/rdlabo-ionic-angular-kit-auth-firebase-social.mjs"
|
|
76
|
+
},
|
|
52
77
|
"./printer": {
|
|
53
78
|
"types": "./types/rdlabo-ionic-angular-kit-printer.d.ts",
|
|
54
79
|
"default": "./fesm2022/rdlabo-ionic-angular-kit-printer.mjs"
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Auth } from 'firebase/auth';
|
|
2
|
+
|
|
3
|
+
/** How a social-credential failure is classified for the app's error hook. */
|
|
4
|
+
type KitOAuthErrorCategory = 'already-in-use' | 'cancelled' | 'other';
|
|
5
|
+
/** The mode a social login runs in. */
|
|
6
|
+
type KitOAuthModeName = 'new' | 'link' | 'credential';
|
|
7
|
+
/**
|
|
8
|
+
* The mode discriminator. `'credential'` links an email/password to the (re-authenticated) social
|
|
9
|
+
* account, so it requires the new email/password; `'new'` / `'link'` do not.
|
|
10
|
+
*/
|
|
11
|
+
type KitOAuthMode = {
|
|
12
|
+
mode: 'new';
|
|
13
|
+
} | {
|
|
14
|
+
mode: 'link';
|
|
15
|
+
} | {
|
|
16
|
+
mode: 'credential';
|
|
17
|
+
emailLogin: {
|
|
18
|
+
email: string;
|
|
19
|
+
password: string;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The apple identity payload handed to the `success` hook for the backend call. Populated from the
|
|
24
|
+
* native plugin on device, or synthesized from the popup result on the web.
|
|
25
|
+
*/
|
|
26
|
+
interface KitAppleResponse {
|
|
27
|
+
user: string | null;
|
|
28
|
+
email: string | null;
|
|
29
|
+
givenName: string | null;
|
|
30
|
+
familyName: string | null;
|
|
31
|
+
identityToken: string | null;
|
|
32
|
+
authorizationCode: string | null;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The uniform lifecycle hooks for a social flow — the same `before / success / error / finally`
|
|
36
|
+
* shape as {@link KitFirebaseAuthService}'s hooks, so a call site reads the same everywhere. All are
|
|
37
|
+
* optional; the kit renders nothing itself.
|
|
38
|
+
*
|
|
39
|
+
* @typeParam Info - the identity payload handed to {@link success} (Facebook access token / Apple
|
|
40
|
+
* response), so an app can notify its backend and give feedback in one place.
|
|
41
|
+
*
|
|
42
|
+
* @remarks
|
|
43
|
+
* `before` runs before the plugin login starts, `success` after the mode's Firebase op succeeds
|
|
44
|
+
* (carrying the identity payload — do the backend call and the toast here), `error` on a classified
|
|
45
|
+
* failure (`'cancelled'` is passed through so the app can stay silent on a user cancel), and
|
|
46
|
+
* `finally` always. The kit swallows none of these errors.
|
|
47
|
+
*/
|
|
48
|
+
interface KitSocialHooks<Info> {
|
|
49
|
+
before?: () => void | Promise<unknown>;
|
|
50
|
+
success?: (info: Info) => void | Promise<unknown>;
|
|
51
|
+
error?: (category: KitOAuthErrorCategory, error: unknown) => void | Promise<unknown>;
|
|
52
|
+
finally?: () => void | Promise<unknown>;
|
|
53
|
+
}
|
|
54
|
+
/** Options for {@link kitFacebookLogin}. */
|
|
55
|
+
type KitFacebookLoginOptions = KitOAuthMode & KitSocialHooks<{
|
|
56
|
+
accessToken: string;
|
|
57
|
+
mode: KitOAuthModeName;
|
|
58
|
+
}> & {
|
|
59
|
+
/** Facebook permissions to request. */
|
|
60
|
+
permissions: string[];
|
|
61
|
+
};
|
|
62
|
+
/** Options for {@link kitAppleLogin}. */
|
|
63
|
+
type KitAppleLoginOptions = KitOAuthMode & KitSocialHooks<{
|
|
64
|
+
response: KitAppleResponse;
|
|
65
|
+
mode: KitOAuthModeName;
|
|
66
|
+
}>;
|
|
67
|
+
/**
|
|
68
|
+
* Facebook login / link, bundled: native plugin → credential → the shared 3-mode state machine.
|
|
69
|
+
*
|
|
70
|
+
* @remarks
|
|
71
|
+
* On iOS the credential is built from the OIDC token with a nonce (`OAuthProvider('facebook.com')`);
|
|
72
|
+
* elsewhere from the access token (`FacebookAuthProvider`). Returns `{ status: false }` on a
|
|
73
|
+
* cancelled/failed plugin login or a handled Firebase error (the app was already notified via the
|
|
74
|
+
* hooks).
|
|
75
|
+
*/
|
|
76
|
+
declare const kitFacebookLogin: (auth: Auth, options: KitFacebookLoginOptions) => Promise<{
|
|
77
|
+
status: boolean;
|
|
78
|
+
}>;
|
|
79
|
+
/**
|
|
80
|
+
* Log out of the Facebook SDK (best-effort; errors are ignored).
|
|
81
|
+
*
|
|
82
|
+
* @remarks
|
|
83
|
+
* Apps that offer Facebook login typically call this alongside the Firebase sign-out, so it lives
|
|
84
|
+
* here to keep the `@capacitor-community/facebook-login` import out of the app.
|
|
85
|
+
*/
|
|
86
|
+
declare const kitFacebookLogout: () => Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Sign in with Apple / link, bundled. Native uses the plugin; the web uses the Firebase popup.
|
|
89
|
+
*
|
|
90
|
+
* @remarks
|
|
91
|
+
* - **Native**: `SignInWithApple.authorize()` → `OAuthProvider('apple.com')` credential → the shared
|
|
92
|
+
* 3-mode state machine.
|
|
93
|
+
* - **Web**: `signInWithPopup` / `linkWithPopup` (with `email`/`name` scopes), or, for `credential`,
|
|
94
|
+
* `reauthenticateWithPopup` then link the email/password. The identity payload for the backend is
|
|
95
|
+
* synthesized from the popup result.
|
|
96
|
+
*
|
|
97
|
+
* Every failure path (including popup errors) is routed through `onError`.
|
|
98
|
+
*/
|
|
99
|
+
declare const kitAppleLogin: (auth: Auth, options: KitAppleLoginOptions) => Promise<{
|
|
100
|
+
status: boolean;
|
|
101
|
+
}>;
|
|
102
|
+
|
|
103
|
+
export { kitAppleLogin, kitFacebookLogin, kitFacebookLogout };
|
|
104
|
+
export type { KitAppleLoginOptions, KitAppleResponse, KitFacebookLoginOptions, KitOAuthErrorCategory, KitOAuthMode, KitOAuthModeName };
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { InjectionToken, EnvironmentProviders } from '@angular/core';
|
|
2
|
+
import { FirebaseOptions } from '@angular/fire/app';
|
|
3
|
+
import { Auth, User, UserCredential } from 'firebase/auth';
|
|
4
|
+
import { Observable } from 'rxjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* DI token for the Firebase `Auth` instance.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* Inject this (`inject(KIT_FIREBASE_AUTH)`) instead of `@angular/fire`'s `Auth`, so the
|
|
11
|
+
* `@angular/fire` dependency stays isolated inside the kit. This is the seam that makes the planned
|
|
12
|
+
* `@angular/fire` → `firebase/auth` migration a kit-internal change: only {@link provideKitFirebase}
|
|
13
|
+
* (which binds this token) has to change; every consumer keeps injecting `KIT_FIREBASE_AUTH`.
|
|
14
|
+
*
|
|
15
|
+
* The value is a `firebase/auth` `Auth` (the SDK type is exposed directly, not re-abstracted —
|
|
16
|
+
* Firebase Auth itself is not being dropped, only the `@angular/fire` wrapper).
|
|
17
|
+
*/
|
|
18
|
+
declare const KIT_FIREBASE_AUTH: InjectionToken<Auth>;
|
|
19
|
+
/** Configuration for {@link provideKitFirebase}. */
|
|
20
|
+
interface KitFirebaseConfig {
|
|
21
|
+
/** The Firebase project options (`apiKey`, `authDomain`, `projectId`, …). */
|
|
22
|
+
readonly firebaseConfig: FirebaseOptions;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Wire Firebase App + Auth into the application and bind {@link KIT_FIREBASE_AUTH}.
|
|
26
|
+
*
|
|
27
|
+
* @remarks
|
|
28
|
+
* Replaces each app's hand-rolled `provideFirebaseApp(...)` + `provideAuth(...)` (with its
|
|
29
|
+
* native/web persistence branch) with one call, and — crucially — keeps `@angular/fire` out of the
|
|
30
|
+
* application: apps inject {@link KIT_FIREBASE_AUTH} and import auth operations/types straight from
|
|
31
|
+
* `firebase/auth`. On a native platform the persistence uses `indexedDBLocalPersistence`; on the web
|
|
32
|
+
* it uses the default (`getAuth`).
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* bootstrapApplication(AppComponent, {
|
|
37
|
+
* providers: [provideKitFirebase({ firebaseConfig: environment.firebase })],
|
|
38
|
+
* });
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
declare const provideKitFirebase: (config: KitFirebaseConfig) => EnvironmentProviders;
|
|
42
|
+
/**
|
|
43
|
+
* Wire Firebase Analytics into the application (optional; only the apps that use it call this).
|
|
44
|
+
*/
|
|
45
|
+
declare const provideKitFirebaseAnalytics: () => EnvironmentProviders;
|
|
46
|
+
|
|
47
|
+
/** A user-facing message (alert header + body). */
|
|
48
|
+
interface KitAuthMessage {
|
|
49
|
+
readonly header: string;
|
|
50
|
+
readonly message: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The fleet's canonical Firebase auth error dictionary: error `code` → message, plus a fallback for
|
|
54
|
+
* unmapped codes.
|
|
55
|
+
*
|
|
56
|
+
* @remarks
|
|
57
|
+
* The kit does *not* present errors itself (that's an app side effect). This is offered as an
|
|
58
|
+
* importable constant so an app can render its error alert from a shared, canonical source instead of
|
|
59
|
+
* re-declaring the same five messages. Apps that need `$localize` (i18n) keep their own dictionary;
|
|
60
|
+
* JA-only apps can import {@link KIT_DEFAULT_AUTH_TEXT} and spread it, overriding the odd code.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* import { KIT_DEFAULT_AUTH_TEXT } from '@rdlabo/ionic-angular-kit/auth-firebase';
|
|
65
|
+
*
|
|
66
|
+
* const AUTH_ERRORS = { ...KIT_DEFAULT_AUTH_TEXT.errors, 'auth/wrong-password': { header: '…', message: '…' } };
|
|
67
|
+
* presentError(code: string) {
|
|
68
|
+
* const msg = AUTH_ERRORS[code] ?? KIT_DEFAULT_AUTH_TEXT.fallbackError;
|
|
69
|
+
* return this.overlay.alertClose(msg);
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
interface KitAuthText {
|
|
74
|
+
/** Firebase error `code` → message. */
|
|
75
|
+
readonly errors: Readonly<Record<string, KitAuthMessage>>;
|
|
76
|
+
/** Shown when an error has no matching `code`. */
|
|
77
|
+
readonly fallbackError: KitAuthMessage;
|
|
78
|
+
}
|
|
79
|
+
/** The fleet's canonical Japanese error dictionary (see {@link KitAuthText}). */
|
|
80
|
+
declare const KIT_DEFAULT_AUTH_TEXT: KitAuthText;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Uniform lifecycle hooks for the bundled email/password auth flows — where the app hangs its own
|
|
84
|
+
* side effects on a flow.
|
|
85
|
+
*
|
|
86
|
+
* @remarks
|
|
87
|
+
* The kit performs the Firebase operation and renders nothing itself. `before` runs before the op,
|
|
88
|
+
* `success` on success, `error` on failure (with the raw error — the app presents it, from its own
|
|
89
|
+
* dictionary), and `finally` always. Failures are *not* thrown: value flows resolve to `null` and
|
|
90
|
+
* boolean flows to `false`. Return values are awaited and ignored.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* kitSignIn(auth, email, password, {
|
|
95
|
+
* error: (e) => this.presentAuthError(e), // app's own error dictionary
|
|
96
|
+
* success: () => this.nav.navigateRoot('/'),
|
|
97
|
+
* });
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
interface KitAuthHooks {
|
|
101
|
+
before?: () => void | Promise<unknown>;
|
|
102
|
+
success?: () => void | Promise<unknown>;
|
|
103
|
+
error?: (error: unknown) => void | Promise<unknown>;
|
|
104
|
+
finally?: () => void | Promise<unknown>;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Sign in with email and password.
|
|
108
|
+
*
|
|
109
|
+
* @remarks
|
|
110
|
+
* Bundles the Firebase op so the app never imports `signInWithEmailAndPassword` directly (the SDK
|
|
111
|
+
* stays isolated in the kit). Resolves the credential, or `null` on failure (handed to the `error`
|
|
112
|
+
* hook).
|
|
113
|
+
*/
|
|
114
|
+
declare const kitSignIn: (auth: Auth, email: string, password: string, hooks?: KitAuthHooks) => Promise<UserCredential | null>;
|
|
115
|
+
/**
|
|
116
|
+
* Create an account and send the verification email.
|
|
117
|
+
*
|
|
118
|
+
* @remarks
|
|
119
|
+
* Bundles the two-step "create → send verification" sequence. Resolves the credential, or `null` on
|
|
120
|
+
* failure. Any success toast is the caller's, via the `success` hook.
|
|
121
|
+
*/
|
|
122
|
+
declare const kitSignUp: (auth: Auth, email: string, password: string, hooks?: KitAuthHooks) => Promise<UserCredential | null>;
|
|
123
|
+
/**
|
|
124
|
+
* Sign out.
|
|
125
|
+
*
|
|
126
|
+
* @remarks
|
|
127
|
+
* App-specific cleanup (clearing stores, toasts, navigation, third-party logout) is the caller's,
|
|
128
|
+
* done via the hooks — the kit only owns the Firebase op. `true` on success, `false` on failure.
|
|
129
|
+
*/
|
|
130
|
+
declare const kitSignOut: (auth: Auth, hooks?: KitAuthHooks) => Promise<boolean>;
|
|
131
|
+
/** Send a password-reset email. `true` on success, `false` on failure. */
|
|
132
|
+
declare const kitSendPasswordReset: (auth: Auth, email: string, hooks?: KitAuthHooks) => Promise<boolean>;
|
|
133
|
+
/**
|
|
134
|
+
* Unlink a linked auth provider (e.g. `'facebook.com'`, `'apple.com'`) from the current user.
|
|
135
|
+
*
|
|
136
|
+
* @remarks
|
|
137
|
+
* Exposed from the core (not `/social`) so an app can unlink without importing `unlink` from
|
|
138
|
+
* `firebase/auth` directly — keeping the invariant that the SDK is only imported inside the kit. Any
|
|
139
|
+
* app-specific step around it (e.g. a backend DELETE before unlinking) goes in the `before` hook.
|
|
140
|
+
* Resolves the updated `User`, or `null` on failure (including when there is no signed-in user).
|
|
141
|
+
*/
|
|
142
|
+
declare const kitUnlinkProvider: (auth: Auth, providerId: string, hooks?: KitAuthHooks) => Promise<User | null>;
|
|
143
|
+
/**
|
|
144
|
+
* (Re-)send the verification email to the signed-in user (a no-op when signed out).
|
|
145
|
+
*
|
|
146
|
+
* @remarks
|
|
147
|
+
* `true` on success (including the signed-out no-op), `false` on failure.
|
|
148
|
+
*/
|
|
149
|
+
declare const kitSendEmailVerification: (auth: Auth, hooks?: KitAuthHooks) => Promise<boolean>;
|
|
150
|
+
/**
|
|
151
|
+
* The current Firebase user as an Observable (emits on every auth-state change; `null` when signed out).
|
|
152
|
+
*
|
|
153
|
+
* @remarks
|
|
154
|
+
* Wraps `onAuthStateChanged` so consumers get an rxjs stream without pulling in `@angular/fire`'s
|
|
155
|
+
* `authState` (or `rxfire`). Emits the current value on subscribe and completes its listener on
|
|
156
|
+
* teardown.
|
|
157
|
+
*
|
|
158
|
+
* @param auth - the Firebase `Auth` instance (inject `KIT_FIREBASE_AUTH`)
|
|
159
|
+
*/
|
|
160
|
+
declare const kitAuthState: (auth: Auth) => Observable<User | null>;
|
|
161
|
+
/**
|
|
162
|
+
* The current user's ID token, or `null` when signed out.
|
|
163
|
+
*
|
|
164
|
+
* @remarks
|
|
165
|
+
* For building `Authorization` / bearer headers in interceptors and services. Failure to fetch a
|
|
166
|
+
* token is **thrown, not swallowed** — the caller decides the fallback (e.g. an empty header) as its
|
|
167
|
+
* own side effect, so the kit never silently hides an auth failure.
|
|
168
|
+
*
|
|
169
|
+
* @param auth - the Firebase `Auth` instance (inject `KIT_FIREBASE_AUTH`)
|
|
170
|
+
* @param forceRefresh - force a token refresh (default `false`)
|
|
171
|
+
* @returns the ID token, or `null` if there is no signed-in user
|
|
172
|
+
* @throws if the token fetch fails for a signed-in user
|
|
173
|
+
*/
|
|
174
|
+
declare const kitGetIdToken: (auth: Auth, forceRefresh?: boolean) => Promise<string | null>;
|
|
175
|
+
/**
|
|
176
|
+
* The app-supplied side effects for {@link kitReauthWithRetry}.
|
|
177
|
+
*
|
|
178
|
+
* @remarks
|
|
179
|
+
* The kit owns the *control flow* but generates no UI; every user-facing effect (the prompt, the
|
|
180
|
+
* loading overlay) is a callback the app implements, rendering from its own dictionary.
|
|
181
|
+
*/
|
|
182
|
+
interface KitReauthWithRetryOptions {
|
|
183
|
+
/**
|
|
184
|
+
* Present the current-password prompt.
|
|
185
|
+
*
|
|
186
|
+
* @remarks
|
|
187
|
+
* A side effect — the app presents whatever it likes (e.g. an `ion-alert` with a masked input and
|
|
188
|
+
* dictionary text). Receives `true` when re-prompting after a wrong password.
|
|
189
|
+
*
|
|
190
|
+
* @returns the entered password, or `null` if the user cancels/dismisses
|
|
191
|
+
*/
|
|
192
|
+
prompt: (wrongPasswordRetry: boolean) => Promise<string | null>;
|
|
193
|
+
/**
|
|
194
|
+
* The sensitive change to run once re-authenticated.
|
|
195
|
+
*
|
|
196
|
+
* @remarks
|
|
197
|
+
* Keep this pure — just the Firebase op(s) (e.g. `updatePassword(user, next)`). Loading and other
|
|
198
|
+
* UI are side effects handled by {@link withLoading}, not here.
|
|
199
|
+
*/
|
|
200
|
+
mutate: (user: User) => Promise<void>;
|
|
201
|
+
/**
|
|
202
|
+
* Wrap the re-authentication + mutation with a loading indicator (a side effect).
|
|
203
|
+
*
|
|
204
|
+
* @remarks
|
|
205
|
+
* Optional. Runs only after a password is entered, around each attempt — so no loading flashes on a
|
|
206
|
+
* cancelled prompt, and it re-shows on a wrong-password retry. The app implements it (e.g.
|
|
207
|
+
* present/dismiss an `ion-loading`).
|
|
208
|
+
*/
|
|
209
|
+
withLoading?: (run: () => Promise<void>) => Promise<void>;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Run the fleet's canonical "confirm current password → change" flow, re-prompting in place on a
|
|
213
|
+
* wrong password.
|
|
214
|
+
*
|
|
215
|
+
* @remarks
|
|
216
|
+
* Owns the drift-prone *control flow* (the retry loop, the wrong-password classification every app
|
|
217
|
+
* once got wrong, and when to show loading) while generating **no UI** — the prompt and the loading
|
|
218
|
+
* overlay are {@link KitReauthWithRetryOptions | side-effect callbacks} the app supplies. On a wrong
|
|
219
|
+
* password the loop re-prompts instead of dropping the user out of the flow. Any non-wrong-password
|
|
220
|
+
* re-auth failure (lockout, offline, expired session) and any error from `mutate` are re-thrown —
|
|
221
|
+
* re-auth failures unwrapped to the underlying Firebase error so the caller's error dictionary can
|
|
222
|
+
* read its `code`.
|
|
223
|
+
*
|
|
224
|
+
* @param auth - the Firebase `Auth` instance
|
|
225
|
+
* @param currentEmail - the current email (for the re-auth credential)
|
|
226
|
+
* @param options - the pure mutation plus the app's prompt / loading side effects
|
|
227
|
+
* @returns `true` if the mutation completed, `false` if the user cancelled
|
|
228
|
+
* @throws the underlying Firebase error on a non-wrong-password failure, or `mutate`'s own error
|
|
229
|
+
*/
|
|
230
|
+
declare const kitReauthWithRetry: (auth: Auth, currentEmail: string, options: KitReauthWithRetryOptions) => Promise<boolean>;
|
|
231
|
+
/** The fleet's 3-state auth status derived from the Firebase user. */
|
|
232
|
+
type KitAuthStatus = 'user' | 'confirm' | 'required';
|
|
233
|
+
/** Options for {@link kitResolveAuthStatus}. */
|
|
234
|
+
interface KitResolveAuthStatusOptions {
|
|
235
|
+
/**
|
|
236
|
+
* Provider IDs that count as verified even without `emailVerified` — a social login (e.g.
|
|
237
|
+
* `'facebook.com'`, `'apple.com'`) has no email-verification step but is a real, trusted account.
|
|
238
|
+
*/
|
|
239
|
+
readonly verifiedProviders?: readonly string[];
|
|
240
|
+
/**
|
|
241
|
+
* Extra predicate to treat a signed-in user as fully authed regardless of verification — for an
|
|
242
|
+
* e2e bypass or an anonymous-allowed app. Receives the current user.
|
|
243
|
+
*/
|
|
244
|
+
readonly allowWhen?: (user: User) => boolean;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Classify a Firebase user into the fleet's 3-state auth status.
|
|
248
|
+
*
|
|
249
|
+
* @remarks
|
|
250
|
+
* `null` (signed out) → `'required'`. A signed-in user is `'user'` when their email is verified, OR
|
|
251
|
+
* they signed in with one of `verifiedProviders`, OR `allowWhen` returns true; otherwise `'confirm'`
|
|
252
|
+
* (signed in but unverified). This is only the shared classification — app-specific side effects
|
|
253
|
+
* around it (reloading the user to refresh `emailVerified`, caching a token) stay in the app.
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```ts
|
|
257
|
+
* kitResolveAuthStatus(user, {
|
|
258
|
+
* verifiedProviders: ['facebook.com', 'apple.com'],
|
|
259
|
+
* allowWhen: () => environment.e2e,
|
|
260
|
+
* });
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
declare const kitResolveAuthStatus: (user: User | null, options?: KitResolveAuthStatusOptions) => KitAuthStatus;
|
|
264
|
+
|
|
265
|
+
export { KIT_DEFAULT_AUTH_TEXT, KIT_FIREBASE_AUTH, kitAuthState, kitGetIdToken, kitReauthWithRetry, kitResolveAuthStatus, kitSendEmailVerification, kitSendPasswordReset, kitSignIn, kitSignOut, kitSignUp, kitUnlinkProvider, provideKitFirebase, provideKitFirebaseAnalytics };
|
|
266
|
+
export type { KitAuthHooks, KitAuthMessage, KitAuthStatus, KitAuthText, KitFirebaseConfig, KitReauthWithRetryOptions, KitResolveAuthStatusOptions };
|
|
@@ -79,6 +79,57 @@ declare class KitStorageService {
|
|
|
79
79
|
static ɵprov: i0.ɵɵInjectableDeclaration<KitStorageService>;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Remember the email a user last entered on the sign-in form so the field can be prefilled next
|
|
84
|
+
* time (the password is never stored).
|
|
85
|
+
*
|
|
86
|
+
* @remarks
|
|
87
|
+
* Storage-agnostic: the helpers take a minimal async key/value store that {@link KitStorageService}
|
|
88
|
+
* satisfies structurally, so they stay pure and unit-testable without DI. `kitRememberEmail`
|
|
89
|
+
* **validates the address before persisting** — a malformed or partial string is silently ignored,
|
|
90
|
+
* so a garbage entry (or a fat-fingered attempt) never becomes the next prefill. A well-formed email
|
|
91
|
+
* that later fails to sign in is still remembered by design: the user simply re-enters/corrects it.
|
|
92
|
+
*
|
|
93
|
+
* These live in the main entry (next to {@link KitStorageService}) rather than in `auth-firebase`,
|
|
94
|
+
* so the `KitAutofillDirective` can consume them without the main entry depending on the Firebase
|
|
95
|
+
* entry.
|
|
96
|
+
*/
|
|
97
|
+
/** Minimal async key/value store — structurally satisfied by `KitStorageService`. */
|
|
98
|
+
interface KitEmailStore {
|
|
99
|
+
get<T>(key: string): Promise<T | null>;
|
|
100
|
+
set<T>(key: string, value: T): Promise<void>;
|
|
101
|
+
remove(key: string): Promise<void>;
|
|
102
|
+
}
|
|
103
|
+
/** Storage key under which the last entered sign-in email is kept. */
|
|
104
|
+
declare const KIT_LAST_AUTH_EMAIL_KEY = "kit:last-auth-email";
|
|
105
|
+
/** Whether `email` is a well-formed address (matches `@angular/forms` `Validators.email`). */
|
|
106
|
+
declare const kitIsValidEmail: (email: string) => boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Persist the entered email for next time — but only when it is a well-formed address.
|
|
109
|
+
*
|
|
110
|
+
* @param store - the app's storage (e.g. `KitStorageService`)
|
|
111
|
+
* @param email - the entered email; ignored (not stored) when malformed
|
|
112
|
+
* @returns `true` when the value passed validation and was stored, `false` when it was ignored
|
|
113
|
+
*/
|
|
114
|
+
declare const kitRememberEmail: (store: KitEmailStore, email: string) => Promise<boolean>;
|
|
115
|
+
/**
|
|
116
|
+
* Recall the last remembered email.
|
|
117
|
+
*
|
|
118
|
+
* @param store - the app's storage (e.g. `KitStorageService`)
|
|
119
|
+
* @returns the stored email, or `null` when none has been remembered
|
|
120
|
+
*/
|
|
121
|
+
declare const kitRecallEmail: (store: KitEmailStore) => Promise<string | null>;
|
|
122
|
+
/**
|
|
123
|
+
* Forget the remembered email.
|
|
124
|
+
*
|
|
125
|
+
* @remarks
|
|
126
|
+
* Called when the user intentionally clears or invalidates the field, so a stale prefill is not
|
|
127
|
+
* resurrected next time.
|
|
128
|
+
*
|
|
129
|
+
* @param store - the app's storage (e.g. `KitStorageService`)
|
|
130
|
+
*/
|
|
131
|
+
declare const kitForgetEmail: (store: KitEmailStore) => Promise<void>;
|
|
132
|
+
|
|
82
133
|
/**
|
|
83
134
|
* User-visible button labels consumed by `KitOverlayController`.
|
|
84
135
|
*
|
|
@@ -603,43 +654,70 @@ interface KitLanguageActionSheetOptions {
|
|
|
603
654
|
declare const kitPresentLanguageActionSheet: (actionSheetCtrl: ActionSheetController, options: KitLanguageActionSheetOptions) => Promise<void>;
|
|
604
655
|
|
|
605
656
|
/**
|
|
606
|
-
*
|
|
657
|
+
* The mode of {@link KitAuthInputDirective}.
|
|
607
658
|
*
|
|
608
|
-
*
|
|
609
|
-
*
|
|
610
|
-
*
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
*
|
|
615
|
-
*
|
|
616
|
-
*
|
|
617
|
-
*
|
|
618
|
-
*
|
|
619
|
-
*
|
|
620
|
-
*
|
|
659
|
+
* - `'autofill'` — iOS autofill propagation only (use on the password input).
|
|
660
|
+
* - `'email'` — sign-in email: prefill from storage + remember on change + forget when cleared.
|
|
661
|
+
* - `'email-remember'` — sign-up email: remember on change only (no prefill, no forget).
|
|
662
|
+
*/
|
|
663
|
+
type KitAuthInputMode = 'autofill' | 'email' | 'email-remember';
|
|
664
|
+
/**
|
|
665
|
+
* Input conveniences for an `ion-input` in a sign-in / sign-up form, applied via the `kitAuthInput`
|
|
666
|
+
* attribute. The mode is a typed union so a typo is a compile-time error.
|
|
667
|
+
*
|
|
668
|
+
* 1. **iOS autofill propagation (always on, every mode).** On iOS, when the browser autofills an
|
|
669
|
+
* `ion-input` (e.g. a saved password) the value is written to the underlying native `<input>`
|
|
670
|
+
* but the `change` event is not forwarded to the host `ion-input`, so the Angular form model
|
|
671
|
+
* never sees it. This directive mirrors the first inner-input `change` back onto the host,
|
|
672
|
+
* restoring two-way binding. It is a no-op on every other platform.
|
|
673
|
+
*
|
|
674
|
+
* 2. **Remember / prefill the email (`'email'` and `'email-remember'`).**
|
|
675
|
+
* - `'email'` (sign-in) — on init recalls the last entered email and, *only while the field is
|
|
676
|
+
* still empty*, seeds it via the bound Signal Forms field, so a browser/OS autofill the user
|
|
677
|
+
* actually picks always wins over the prefill. On every committed change (`ionChange`) it
|
|
678
|
+
* remembers a well-formed address, or **forgets** the stored one when the field is cleared
|
|
679
|
+
* (empty after trim) or holds an invalid address — the user intentionally removing the prefill.
|
|
680
|
+
* - `'email-remember'` (sign-up) — remembers a well-formed address on change, but never prefills
|
|
681
|
+
* and never forgets. So the first-sign-up address is captured without pre-populating a
|
|
682
|
+
* stranger's email into a new-account form, and clearing the field does not wipe an email
|
|
683
|
+
* remembered elsewhere.
|
|
684
|
+
*
|
|
685
|
+
* A well-formed email is persisted even if it later fails to sign in — by design; the user simply
|
|
686
|
+
* re-enters it. A malformed/partial entry is never stored (see {@link kitRememberEmail}).
|
|
621
687
|
*
|
|
622
688
|
* @example
|
|
623
689
|
* ```html
|
|
624
|
-
*
|
|
690
|
+
* <!-- sign-in email: iOS autofill + prefill + remember/forget -->
|
|
691
|
+
* <ion-input type="email" autocomplete="email" kitAuthInput="email" [formField]="form.email" />
|
|
692
|
+
* <!-- sign-up email: remember only -->
|
|
693
|
+
* <ion-input type="email" autocomplete="email" kitAuthInput="email-remember" [formField]="form.email" />
|
|
694
|
+
* <!-- password: iOS autofill propagation only -->
|
|
695
|
+
* <ion-input type="password" autocomplete="current-password" kitAuthInput="autofill" [formField]="form.password" />
|
|
625
696
|
* ```
|
|
697
|
+
*
|
|
698
|
+
* @remarks
|
|
699
|
+
* Prefill writes through the Signal Forms `FORM_FIELD` bound on the same element; with no such field
|
|
700
|
+
* (e.g. `ngModel` / reactive forms) prefill is skipped — remember/forget still work off the DOM
|
|
701
|
+
* event. Storage is resolved lazily so the iOS mirror still works in apps without `@ionic/storage`.
|
|
626
702
|
*/
|
|
627
|
-
declare class
|
|
703
|
+
declare class KitAuthInputDirective implements OnInit {
|
|
628
704
|
#private;
|
|
705
|
+
/** Mode selector; see {@link KitAuthInputMode}. */
|
|
706
|
+
readonly kitAuthInput: i0.InputSignal<KitAuthInputMode>;
|
|
629
707
|
constructor();
|
|
630
708
|
/**
|
|
631
|
-
* Register the iOS autofill workaround
|
|
632
|
-
*
|
|
633
|
-
* Returns immediately on non-iOS platforms. On iOS, after a short delay it attaches a one-shot,
|
|
634
|
-
* passive `change` listener to the inner `<input>` element that `ion-input` renders, copying the
|
|
635
|
-
* autofilled value back onto the host element so the Angular form model stays in sync. Any error
|
|
636
|
-
* while locating the inner input (for example if the element is not yet present) is swallowed.
|
|
637
|
-
*
|
|
638
|
-
* @returns Nothing.
|
|
709
|
+
* Register the iOS autofill workaround and, in `'email'` mode, seed the field from storage.
|
|
639
710
|
*/
|
|
640
711
|
ngOnInit(): void;
|
|
641
|
-
|
|
642
|
-
|
|
712
|
+
/**
|
|
713
|
+
* On every committed change (`ionChange`): remember a well-formed email, or — only in the
|
|
714
|
+
* prefilling `'email'` (sign-in) mode — forget the stored one when the field is cleared or invalid,
|
|
715
|
+
* which is the user intentionally removing the prefill. `'email-remember'` never forgets, so
|
|
716
|
+
* editing the sign-up field cannot wipe an email remembered from sign-in.
|
|
717
|
+
*/
|
|
718
|
+
onIonChange(event: Event): void;
|
|
719
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<KitAuthInputDirective, never>;
|
|
720
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<KitAuthInputDirective, "[kitAuthInput]", never, { "kitAuthInput": { "alias": "kitAuthInput"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
643
721
|
}
|
|
644
722
|
|
|
645
723
|
/**
|
|
@@ -1236,5 +1314,5 @@ declare const kitChangeEventDisabled: (completeEvent: WritableSignal<HTMLIonInfi
|
|
|
1236
1314
|
*/
|
|
1237
1315
|
declare const kitCreateDidEnter: (el: ElementRef) => Observable<boolean>;
|
|
1238
1316
|
|
|
1239
|
-
export { KIT_AUTH_CONFIG, KIT_HTTP_CONFIG, KIT_OVERLAY_CONFIG,
|
|
1240
|
-
export type { KitAlertCloseOptions, KitAlertConfirmOptions, KitAuthConfig, KitAuthFailedAlertOptions, KitAuthRedirects, KitAuthState, KitHttpConfig, KitKeyboardAdjust, KitLabels, KitLanguageActionSheetOptions, KitLanguageOption, KitModalPresentOptions, KitOverlayConfig, KitReloadAlertOptions, ModalMetadata };
|
|
1317
|
+
export { KIT_AUTH_CONFIG, KIT_HTTP_CONFIG, KIT_LAST_AUTH_EMAIL_KEY, KIT_OVERLAY_CONFIG, KitAuthInputDirective, KitLoadingController, KitOverlayController, KitReloadAlertController, KitStorageService, arrayConcatById, disableHandler, kitAuthInterceptor, kitChangeEventDisabled, kitCreateDidEnter, kitForgetEmail, kitImpact, kitIsValidEmail, kitKeyboardInit, kitPresentAuthFailedAlert, kitPresentLanguageActionSheet, kitRecallEmail, kitRememberEmail, kitRequireAuthorizedGuard, kitRequireConfirmingGuard, kitRequiredUnauthorizedGuard, objectEqual, provideKitAuth, provideKitHttp, provideKitOverlay };
|
|
1318
|
+
export type { KitAlertCloseOptions, KitAlertConfirmOptions, KitAuthConfig, KitAuthFailedAlertOptions, KitAuthInputMode, KitAuthRedirects, KitAuthState, KitEmailStore, KitHttpConfig, KitKeyboardAdjust, KitLabels, KitLanguageActionSheetOptions, KitLanguageOption, KitModalPresentOptions, KitOverlayConfig, KitReloadAlertOptions, ModalMetadata };
|