@mintplayer/ng-spark 22.30.0 → 22.32.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.
Files changed (84) hide show
  1. package/README.md +2 -2
  2. package/auth/README.md +216 -0
  3. package/fesm2022/mintplayer-ng-spark-auth-account.mjs +2023 -0
  4. package/fesm2022/mintplayer-ng-spark-auth-account.mjs.map +1 -0
  5. package/fesm2022/mintplayer-ng-spark-auth-auth-bar.mjs +96 -0
  6. package/fesm2022/mintplayer-ng-spark-auth-auth-bar.mjs.map +1 -0
  7. package/fesm2022/mintplayer-ng-spark-auth-confirm-email.mjs +200 -0
  8. package/fesm2022/mintplayer-ng-spark-auth-confirm-email.mjs.map +1 -0
  9. package/fesm2022/mintplayer-ng-spark-auth-core.mjs +452 -0
  10. package/fesm2022/mintplayer-ng-spark-auth-core.mjs.map +1 -0
  11. package/fesm2022/mintplayer-ng-spark-auth-external-login.mjs +201 -0
  12. package/fesm2022/mintplayer-ng-spark-auth-external-login.mjs.map +1 -0
  13. package/fesm2022/mintplayer-ng-spark-auth-forgot-password.mjs +196 -0
  14. package/fesm2022/mintplayer-ng-spark-auth-forgot-password.mjs.map +1 -0
  15. package/fesm2022/mintplayer-ng-spark-auth-guards.mjs +16 -0
  16. package/fesm2022/mintplayer-ng-spark-auth-guards.mjs.map +1 -0
  17. package/fesm2022/mintplayer-ng-spark-auth-interceptors.mjs +18 -0
  18. package/fesm2022/mintplayer-ng-spark-auth-interceptors.mjs.map +1 -0
  19. package/fesm2022/mintplayer-ng-spark-auth-login.mjs +282 -0
  20. package/fesm2022/mintplayer-ng-spark-auth-login.mjs.map +1 -0
  21. package/fesm2022/mintplayer-ng-spark-auth-models.mjs +114 -0
  22. package/fesm2022/mintplayer-ng-spark-auth-models.mjs.map +1 -0
  23. package/fesm2022/mintplayer-ng-spark-auth-pipes.mjs +43 -0
  24. package/fesm2022/mintplayer-ng-spark-auth-pipes.mjs.map +1 -0
  25. package/fesm2022/mintplayer-ng-spark-auth-register.mjs +216 -0
  26. package/fesm2022/mintplayer-ng-spark-auth-register.mjs.map +1 -0
  27. package/fesm2022/mintplayer-ng-spark-auth-reset-password.mjs +223 -0
  28. package/fesm2022/mintplayer-ng-spark-auth-reset-password.mjs.map +1 -0
  29. package/fesm2022/mintplayer-ng-spark-auth-routes.mjs +194 -0
  30. package/fesm2022/mintplayer-ng-spark-auth-routes.mjs.map +1 -0
  31. package/fesm2022/mintplayer-ng-spark-auth-sign-in.mjs +210 -0
  32. package/fesm2022/mintplayer-ng-spark-auth-sign-in.mjs.map +1 -0
  33. package/fesm2022/mintplayer-ng-spark-auth-two-factor.mjs +218 -0
  34. package/fesm2022/mintplayer-ng-spark-auth-two-factor.mjs.map +1 -0
  35. package/fesm2022/mintplayer-ng-spark-auth.mjs +48 -0
  36. package/fesm2022/mintplayer-ng-spark-auth.mjs.map +1 -0
  37. package/fesm2022/mintplayer-ng-spark-client-operations.mjs +294 -2
  38. package/fesm2022/mintplayer-ng-spark-client-operations.mjs.map +1 -1
  39. package/fesm2022/mintplayer-ng-spark-identity-provider-connected-applications.mjs +389 -0
  40. package/fesm2022/mintplayer-ng-spark-identity-provider-connected-applications.mjs.map +1 -0
  41. package/fesm2022/mintplayer-ng-spark-identity-provider-core.mjs +204 -0
  42. package/fesm2022/mintplayer-ng-spark-identity-provider-core.mjs.map +1 -0
  43. package/fesm2022/mintplayer-ng-spark-identity-provider-developers.mjs +486 -0
  44. package/fesm2022/mintplayer-ng-spark-identity-provider-developers.mjs.map +1 -0
  45. package/fesm2022/mintplayer-ng-spark-identity-provider-management.mjs +350 -0
  46. package/fesm2022/mintplayer-ng-spark-identity-provider-management.mjs.map +1 -0
  47. package/fesm2022/mintplayer-ng-spark-identity-provider.mjs +66 -0
  48. package/fesm2022/mintplayer-ng-spark-identity-provider.mjs.map +1 -0
  49. package/fesm2022/mintplayer-ng-spark-po-detail.mjs +9 -4
  50. package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
  51. package/fesm2022/mintplayer-ng-spark-pwa.mjs +162 -0
  52. package/fesm2022/mintplayer-ng-spark-pwa.mjs.map +1 -0
  53. package/fesm2022/mintplayer-ng-spark-services.mjs +11 -1
  54. package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
  55. package/fesm2022/mintplayer-ng-spark-shell.mjs.map +1 -1
  56. package/fesm2022/mintplayer-ng-spark.mjs.map +1 -1
  57. package/package.json +99 -1
  58. package/types/mintplayer-ng-spark-auth-account.d.ts +255 -0
  59. package/types/mintplayer-ng-spark-auth-auth-bar.d.ts +22 -0
  60. package/types/mintplayer-ng-spark-auth-confirm-email.d.ts +21 -0
  61. package/types/mintplayer-ng-spark-auth-core.d.ts +197 -0
  62. package/types/mintplayer-ng-spark-auth-external-login.d.ts +132 -0
  63. package/types/mintplayer-ng-spark-auth-forgot-password.d.ts +18 -0
  64. package/types/mintplayer-ng-spark-auth-guards.d.ts +15 -0
  65. package/types/mintplayer-ng-spark-auth-interceptors.d.ts +2 -0
  66. package/types/mintplayer-ng-spark-auth-login.d.ts +46 -0
  67. package/types/mintplayer-ng-spark-auth-models.d.ts +489 -0
  68. package/types/mintplayer-ng-spark-auth-pipes.d.ts +8 -0
  69. package/types/mintplayer-ng-spark-auth-register.d.ts +21 -0
  70. package/types/mintplayer-ng-spark-auth-reset-password.d.ts +25 -0
  71. package/types/mintplayer-ng-spark-auth-routes.d.ts +154 -0
  72. package/types/mintplayer-ng-spark-auth-sign-in.d.ts +84 -0
  73. package/types/mintplayer-ng-spark-auth-two-factor.d.ts +23 -0
  74. package/types/mintplayer-ng-spark-auth.d.ts +24 -0
  75. package/types/mintplayer-ng-spark-client-operations.d.ts +78 -3
  76. package/types/mintplayer-ng-spark-identity-provider-connected-applications.d.ts +35 -0
  77. package/types/mintplayer-ng-spark-identity-provider-core.d.ts +144 -0
  78. package/types/mintplayer-ng-spark-identity-provider-developers.d.ts +55 -0
  79. package/types/mintplayer-ng-spark-identity-provider-management.d.ts +33 -0
  80. package/types/mintplayer-ng-spark-identity-provider.d.ts +64 -0
  81. package/types/mintplayer-ng-spark-pwa.d.ts +89 -0
  82. package/types/mintplayer-ng-spark-services.d.ts +10 -0
  83. package/types/mintplayer-ng-spark-shell.d.ts +2 -2
  84. package/types/mintplayer-ng-spark.d.ts +4 -4
@@ -0,0 +1,489 @@
1
+ import { InjectionToken, Provider, Type } from "@angular/core";
2
+ import { Router } from "@angular/router";
3
+ export interface AuthUser {
4
+ isAuthenticated: boolean;
5
+ userName: string;
6
+ email: string;
7
+ roles: string[];
8
+ }
9
+ /** How the user is sent to the external provider, and how the result comes back. */
10
+ export type SparkExternalLoginMode = 'popup' | 'redirect';
11
+ /**
12
+ * The app-wide default for {@link SparkExternalLoginMode}, set through
13
+ * `provideSparkAuth({ externalLoginMode })`.
14
+ *
15
+ * `'auto'` (the default) uses `'redirect'` inside an installed web app (`display-mode: standalone`,
16
+ * or iOS's `navigator.standalone`) and `'popup'` in a browser tab. Inside an installed app a popup is
17
+ * captured into the app, or lands in a custom tab with no usable opener, so only a full-page
18
+ * redirect is reliable there.
19
+ */
20
+ export type SparkExternalLoginModeSetting = 'auto' | SparkExternalLoginMode;
21
+ export interface SparkExternalLoginOptions {
22
+ /**
23
+ * Where to land after a successful provider round trip. Server-side sanitized to an in-app path.
24
+ */
25
+ returnUrl?: string;
26
+ /**
27
+ * `'redirect'` mode only: where a failure lands, with `?sparkExternalLogin=<code>` added.
28
+ * Server-side sanitized like `returnUrl`. Defaults to the page the attempt started from (the
29
+ * router URL with any earlier `sparkExternalLogin` removed), which is the page that reads and
30
+ * shows the code. Ignored in popup mode, where the outcome comes back to the opener instead.
31
+ */
32
+ errorUrl?: string;
33
+ /** Overrides the configured `externalLoginMode` (default `'auto'`) for this one call. */
34
+ mode?: SparkExternalLoginMode;
35
+ }
36
+ /** Whether this document runs as an installed web app rather than in a browser tab. */
37
+ export declare function sparkIsStandaloneDisplay(): boolean;
38
+ /**
39
+ * The value of `externalLoginMode` resolved against this document: `'auto'` becomes `'redirect'` in
40
+ * an installed web app and `'popup'` everywhere else.
41
+ */
42
+ export declare function resolveSparkExternalLoginMode(setting: SparkExternalLoginModeSetting | undefined): SparkExternalLoginMode;
43
+ /**
44
+ * Why an external login did not sign anyone in. Everything but the two `popup_*` codes comes
45
+ * from the server; those two are raised here, because the browser is the only place that can
46
+ * observe them.
47
+ *
48
+ * ⚠️ `link_confirmation_sent` is **not a failure**. It travels on this channel because no session
49
+ * was created, which is what `success: false` means to the opener — but the right response is to
50
+ * tell the user to check their mail, not to show an error.
51
+ *
52
+ * ⚠️ `email_already_registered` admits that an account exists, which the older codes deliberately
53
+ * avoid doing. That trade is made on the server (the alternative was a generic failure that reads
54
+ * as "this application is broken"); a client must not widen it by pairing the code with the address
55
+ * it was asked about.
56
+ */
57
+ export type SparkExternalLoginError = 'no_login_info' | 'email_not_verified' | 'account_creation_failed' | 'email_already_registered' | 'sign_in_to_link' | 'link_confirmation_sent' | 'login_already_associated' | 'link_failed' |
58
+ /** The provider reported an error, or the correlation of its answer failed. */
59
+ 'remote_failure' |
60
+ /** The challenge refused the nonce (HTTP 400). It never travels in a popup payload. */
61
+ 'invalid_nonce' | 'popup_blocked' | 'popup_closed';
62
+ /** Every {@link SparkExternalLoginError}; a code read from a URL is checked against it. */
63
+ export declare const SPARK_EXTERNAL_LOGIN_ERRORS: readonly SparkExternalLoginError[];
64
+ export interface SparkExternalLoginResult {
65
+ success: boolean;
66
+ error?: SparkExternalLoginError;
67
+ }
68
+ /**
69
+ * The payload the callback page hands back: posted to the opener, posted on the
70
+ * {@link SPARK_EXTERNAL_LOGIN_CHANNEL} BroadcastChannel, and written to `localStorage` under
71
+ * {@link sparkExternalLoginStorageKey} (with an `at` timestamp). Any of the three may be the one
72
+ * that arrives: COOP on the provider's pages cuts the opener, and a frozen background tab may only
73
+ * see the storage entry once it is shown again.
74
+ */
75
+ export interface SparkExternalLoginMessage {
76
+ type: typeof SPARK_EXTERNAL_LOGIN_MESSAGE_TYPE;
77
+ success: boolean;
78
+ error?: SparkExternalLoginError | null;
79
+ /** The nonce the opener sent on the challenge; `null` from a challenge that carried none. */
80
+ nonce?: string | null;
81
+ }
82
+ /** The opener's answer on the BroadcastChannel: the callback page sets its done-marker and closes. */
83
+ export interface SparkExternalLoginAck {
84
+ type: typeof SPARK_EXTERNAL_LOGIN_ACK_TYPE;
85
+ nonce: string;
86
+ }
87
+ export declare const SPARK_EXTERNAL_LOGIN_MESSAGE_TYPE = "spark:external-login";
88
+ export declare const SPARK_EXTERNAL_LOGIN_ACK_TYPE = "spark:external-login-ack";
89
+ /** The BroadcastChannel the callback page and the opener share. */
90
+ export declare const SPARK_EXTERNAL_LOGIN_CHANNEL = "spark:external-login";
91
+ /** The query parameter a redirect-mode failure comes back with. */
92
+ export declare const SPARK_EXTERNAL_LOGIN_QUERY_PARAM = "sparkExternalLogin";
93
+ /** How long a popup attempt waits for its result before it settles `popup_closed`. */
94
+ export declare const SPARK_EXTERNAL_LOGIN_TIMEOUT_MS: number;
95
+ /** The `localStorage` key the callback page writes its payload to. */
96
+ export declare function sparkExternalLoginStorageKey(nonce: string): string;
97
+ /**
98
+ * The `localStorage` done-marker: set once the opener has the result. The callback page reads it to
99
+ * restore itself to the app when an installed web app shows it again.
100
+ */
101
+ export declare function sparkExternalLoginDoneKey(nonce: string): string;
102
+ /**
103
+ * A fresh nonce for one popup attempt: 32 base64url characters from `crypto.getRandomValues`
104
+ * (24 bytes, so no padding). The server accepts `^[A-Za-z0-9_-]{16,64}$`.
105
+ */
106
+ export declare function sparkExternalLoginNonce(): string;
107
+ /** One external login attached to the signed-in account. */
108
+ export interface SparkLinkedExternalLogin {
109
+ provider: string;
110
+ providerKey: string;
111
+ displayName: string;
112
+ /**
113
+ * ⚠️ `false` when removing this login would leave the account with no way to sign in.
114
+ *
115
+ * Served by the server so the UI can disable the control rather than offer an action that will
116
+ * be refused. It is **not** the enforcement — the server refuses the request too — and a client
117
+ * that treats it as advisory only is behaving correctly.
118
+ */
119
+ canUnlink: boolean;
120
+ }
121
+ /** A provider that is configured but not yet attached to the signed-in account. */
122
+ export interface SparkAvailableExternalProvider {
123
+ provider: string;
124
+ displayName: string;
125
+ }
126
+ export interface SparkExternalLogins {
127
+ linked: SparkLinkedExternalLogin[];
128
+ available: SparkAvailableExternalProvider[];
129
+ }
130
+ /** Why a login was not detached. */
131
+ export type SparkUnlinkError =
132
+ /** ⚠️ It was the account's last way in, so removing it would have locked the owner out for good. */
133
+ 'last_credential' |
134
+ /** Not attached to this account. */
135
+ 'login_not_found' |
136
+ /** The store refused, for a reason that is not either of the above. */
137
+ 'unlink_failed';
138
+ export interface SparkUnlinkResult {
139
+ success: boolean;
140
+ error?: SparkUnlinkError;
141
+ }
142
+ export interface SparkAuthConfig {
143
+ apiBasePath: string;
144
+ defaultRedirectUrl: string;
145
+ loginUrl: string;
146
+ /**
147
+ * How external sign-in and linking reach the provider by default. `'auto'` (the default) is a
148
+ * popup in a browser tab and a full-page redirect inside an installed web app. A call's own
149
+ * `mode` option overrides it.
150
+ */
151
+ externalLoginMode?: SparkExternalLoginModeSetting;
152
+ }
153
+ export declare const SPARK_AUTH_CONFIG: InjectionToken<SparkAuthConfig>;
154
+ export declare const defaultSparkAuthConfig: SparkAuthConfig;
155
+ /** An external provider a user can actually click, as reported by the server. */
156
+ export interface SparkExternalProvider {
157
+ scheme: string;
158
+ displayName: string;
159
+ }
160
+ /** An identifier kind password sign-in can accept. */
161
+ export type SparkSignInIdentifier = 'email' | 'userName';
162
+ /**
163
+ * What `GET /spark/auth/capabilities` reports: how much of the local-credential surface this
164
+ * application mounts, and which external providers are registered.
165
+ *
166
+ * This exists so the two tiers cannot silently disagree. The route config is a build-time choice
167
+ * and the server's mode is a deployment-time one; without a channel between them, a mismatch shows
168
+ * up as a form that posts into a 404, or a sign-in page with no way to sign in.
169
+ */
170
+ export interface SparkAuthCapabilities {
171
+ localCredentials: 'Full' | 'SignInOnly' | 'Disabled';
172
+ externalProviders: SparkExternalProvider[];
173
+ /**
174
+ * What password sign-in accepts as the identifier — the server's `SignInIdentifiers`. Empty when
175
+ * `localCredentials` is `Disabled`. Optional: a server older than this client omits it, and absent
176
+ * reads as both, which is what such a server accepts.
177
+ */
178
+ signInIdentifiers?: SparkSignInIdentifier[];
179
+ /**
180
+ * Whether an anonymous visitor can sign in with a passkey — i.e. whether the server mounted the
181
+ * passkey sign-in endpoint.
182
+ *
183
+ * Necessary but not sufficient for showing the button: the browser must also support the
184
+ * ceremony. Check `passkeysSupported()` too, or the page offers a flow that cannot start.
185
+ *
186
+ * Optional because a server older than this client omits the field entirely, and an absent
187
+ * capability must read as "no" rather than as `undefined` leaking into a template.
188
+ */
189
+ passkeys?: boolean;
190
+ /**
191
+ * Whether the two-factor setup page is served — the server mapped `manage/2fa` and the
192
+ * authenticator-URI endpoint. Optional: absent reads as "no".
193
+ */
194
+ twoFactor?: boolean;
195
+ /**
196
+ * Whether a signed-in user may change their email address — the server's opt-in
197
+ * `SparkEmailChange.Enabled`, and a local-credential mode that maps `POST manage/info`. Optional for
198
+ * the same reason as `passkeys`: absent reads as "no".
199
+ */
200
+ emailChange?: boolean;
201
+ /**
202
+ * Whether the connected-logins page is served — the server's `ExternalLoginLinking` is not
203
+ * `Disabled`. External SIGN-IN can be on while this is off. Optional: absent reads as "no".
204
+ */
205
+ externalLogins?: boolean;
206
+ /**
207
+ * Whether a user with two-factor enabled may choose to skip the code when signing in with an
208
+ * external account (`manage/external-login-two-factor`). Optional: absent reads as "no".
209
+ */
210
+ externalLoginTwoFactorBypass?: boolean;
211
+ }
212
+ export type SparkAuthRouteEntry = string | {
213
+ path: string;
214
+ component?: Type<unknown>;
215
+ };
216
+ /** The routable authentication pages. */
217
+ export interface SparkAuthRouteEntries {
218
+ /** The provider-button landing page, mounted by `withExternalLogin()`. */
219
+ signIn?: SparkAuthRouteEntry;
220
+ login?: SparkAuthRouteEntry;
221
+ twoFactor?: SparkAuthRouteEntry;
222
+ register?: SparkAuthRouteEntry;
223
+ forgotPassword?: SparkAuthRouteEntry;
224
+ resetPassword?: SparkAuthRouteEntry;
225
+ /**
226
+ * Passkey management, mounted by `withPasskeys()`.
227
+ *
228
+ * Unlike its siblings this page is for a user who is already signed in, so it belongs behind
229
+ * whatever guard the application uses for its account area rather than on the public sign-in path.
230
+ */
231
+ passkeys?: SparkAuthRouteEntry;
232
+ /**
233
+ * The link target of confirmation mails, mounted by `withAccount()`. Public (the link is opened from a
234
+ * mailbox, possibly signed out); its path must equal the server's `Spark:Auth:Links:ConfirmEmailPath`
235
+ * (default `/confirm-email`).
236
+ */
237
+ confirmEmail?: SparkAuthRouteEntry;
238
+ /** The account overview (links to every mounted account page), mounted by `withAccount()`. */
239
+ account?: SparkAuthRouteEntry;
240
+ /** User name, email change, preferred mail language and app fields (`withAccount()`). */
241
+ profile?: SparkAuthRouteEntry;
242
+ /** Change the password, or set a first one on a social-only account (`withAccount()`). */
243
+ changePassword?: SparkAuthRouteEntry;
244
+ /** Authenticator enrollment, recovery codes, disabling 2FA (`withAccount()`). */
245
+ twoFactorSetup?: SparkAuthRouteEntry;
246
+ /** Connected external logins: link and unlink providers (`withAccount()`). */
247
+ externalLogins?: SparkAuthRouteEntry;
248
+ /** Download personal data and delete the account (`withAccount()`). */
249
+ personalData?: SparkAuthRouteEntry;
250
+ /**
251
+ * The applications the user granted access to, with per-scope withdrawal. Mounted by
252
+ * `withIdentityProvider(withConnectedApplications())` from `@mintplayer/ng-spark/identity-provider`.
253
+ */
254
+ connectedApplications?: SparkAuthRouteEntry;
255
+ /** The developer portal's landing page (`withIdentityProvider(withDeveloperRoutes())`). */
256
+ developers?: SparkAuthRouteEntry;
257
+ /** The identity provider's management page (`withIdentityProvider(withManagementRoutes())`). */
258
+ identityProviderManagement?: SparkAuthRouteEntry;
259
+ }
260
+ /**
261
+ * An extra link on the account overview (`SparkAccountOverviewComponent`), contributed by a route
262
+ * feature from another entry point, e.g. `withConnectedApplications()`. The overview lists it after
263
+ * its own pages. The label carries its own translations because the contributing entry point, not
264
+ * the auth translations, owns the text.
265
+ */
266
+ export interface SparkAccountOverviewLink {
267
+ /** Identifies the link (`track`), e.g. the {@link SparkAuthRoutePaths} key it points at. */
268
+ key: string;
269
+ /** The absolute router path, e.g. `/account/applications`. */
270
+ path: string;
271
+ /** The link text per language code; resolved in the app's current language. */
272
+ label: Record<string, string>;
273
+ }
274
+ /**
275
+ * The extra account-overview links of the mounted route features, provided by `sparkAuthRoutes()`
276
+ * on its route. Optional: without it the overview shows only the auth pages.
277
+ */
278
+ export declare const SPARK_ACCOUNT_OVERVIEW_LINKS: InjectionToken<readonly SparkAccountOverviewLink[]>;
279
+ /**
280
+ * The paths of the pages that were actually mounted.
281
+ *
282
+ * Partial, and that is the change: pages are opted into individually now, so a template cannot
283
+ * assume its siblings exist. `login` links to `register` only when registration was opted into, and
284
+ * the sign-in landing page links to `login` only when local login was. A `[routerLink]` bound to
285
+ * `undefined` silently navigates to the current route, so every cross-feature link is guarded.
286
+ */
287
+ export type SparkAuthRoutePaths = Partial<Record<keyof SparkAuthRouteEntries, string>>;
288
+ export declare const SPARK_AUTH_ROUTE_PATHS: InjectionToken<Partial<Record<keyof SparkAuthRouteEntries, string>>>;
289
+ /** The slice of an Angular `Route` the lookup below reads — kept structural so `/models` stays router-free. */
290
+ interface RouteLike {
291
+ providers?: readonly unknown[];
292
+ children?: readonly RouteLike[];
293
+ }
294
+ /**
295
+ * The paths `sparkAuthRoutes()` mounted, read from the router configuration.
296
+ *
297
+ * For components that live **outside** that route subtree, such as `<spark-auth-bar>` in the
298
+ * application shell: `SPARK_AUTH_ROUTE_PATHS` is provided on the subtree's own route, so it is not
299
+ * injectable from there. Walks the eagerly declared routes only — a `sparkAuthRoutes()` behind a
300
+ * `loadChildren` is not loaded yet and is not found, which reads as "nothing mounted".
301
+ */
302
+ export declare function findSparkAuthRoutePaths(routes: readonly RouteLike[] | undefined): SparkAuthRoutePaths | null;
303
+ /**
304
+ * Presentation for one external provider's button — an icon, a label, an ordering.
305
+ *
306
+ * **It decorates; it does not declare.** The server stays authoritative over which providers exist
307
+ * (`GET /spark/auth/capabilities`), because letting the client declare them would reintroduce exactly
308
+ * the string-literal mismatch that endpoint exists to prevent. A scheme the server reports with no
309
+ * matching declaration falls back to the default button, so adding a provider server-side never
310
+ * yields a blank page; a declaration matching no reported scheme is simply unused.
311
+ */
312
+ export interface SparkExternalProviderPresentation {
313
+ /** The ASP.NET Core authentication scheme, as the server reports it. Matched case-insensitively. */
314
+ scheme: string;
315
+ /** Overrides the server's display name. */
316
+ displayName?: string;
317
+ /** A CSS class for an icon element rendered before the label. */
318
+ iconClass?: string;
319
+ /** Lower sorts first. Providers with no declared order keep the server's order, after declared ones. */
320
+ order?: number;
321
+ }
322
+ export declare const SPARK_EXTERNAL_PROVIDERS: InjectionToken<SparkExternalProviderPresentation[]>;
323
+ /**
324
+ * Shared validator for `returnUrl` query parameters consumed by the auth
325
+ * components and interceptor. The framework-side equivalent in
326
+ * `SparkAuthenticationExtensions.SanitizeReturnUrl` enforces the same rule;
327
+ * keep them in sync.
328
+ *
329
+ * Accepts only local in-app paths:
330
+ * - Must start with a single `/`.
331
+ * - Must not start with `//` or `/\` (protocol-relative navigation that some
332
+ * browsers and routers interpret as an external host).
333
+ * - Must not contain CR/LF (defensive — the value flows into Router state and
334
+ * eventually back into a `router.navigateByUrl` call).
335
+ *
336
+ * Returns the supplied default for anything else, never throws. Per R2-H9.
337
+ */
338
+ export declare function isSafeReturnUrl(value: string | null | undefined): boolean;
339
+ export declare function sanitizeReturnUrl(value: string | null | undefined, defaultUrl: string): string;
340
+ /**
341
+ * Why a passkey ceremony did not complete.
342
+ *
343
+ * ⚠️ Every server-side sign-in rejection arrives as `failed`, and that is deliberate rather than
344
+ * lossy: distinguishing "unknown credential" from "bad signature" would tell an anonymous caller
345
+ * whether a credential exists. Do not try to recover the detail — it is not sent.
346
+ *
347
+ * The three codes the server never sends are raised here, because the browser is the only place
348
+ * that can observe them.
349
+ */
350
+ export type SparkPasskeyError =
351
+ /** The browser cannot run the ceremony at all. Offer another sign-in method. */
352
+ 'unsupported' |
353
+ /** The user dismissed the authenticator prompt. Not an error worth showing. */
354
+ 'cancelled' |
355
+ /** The authenticator produced nothing — no matching credential, or the user gave up. */
356
+ 'no_credential' |
357
+ /** The account is locked out. The one server-side outcome worth distinguishing. */
358
+ 'locked_out' |
359
+ /** Everything else, server or client. */
360
+ 'failed';
361
+ export interface SparkPasskeyResult {
362
+ success: boolean;
363
+ error?: SparkPasskeyError;
364
+ }
365
+ /**
366
+ * Collapses everything that can go wrong in a ceremony into the closed error union.
367
+ *
368
+ * `AbortError` and `NotAllowedError` are how a browser reports "the user dismissed the prompt" and
369
+ * "no credential was produced" — neither is a fault, and neither should surface as a red banner.
370
+ */
371
+ export declare function sparkPasskeyError(error: unknown): SparkPasskeyError;
372
+ /**
373
+ * Whether this browser can run a passkey ceremony.
374
+ *
375
+ * Checks the native JSON helpers as well as `navigator.credentials`, because the ceremony is built
376
+ * on them: the server speaks WebAuthn's JSON encoding, and without
377
+ * `parseCreationOptionsFromJSON` / `parseRequestOptionsFromJSON` the client would have to hand-roll
378
+ * base64url conversion over every field of the options — on the security-critical path, to support
379
+ * browsers that a user holding a passkey is unlikely to be running.
380
+ *
381
+ * ⚠️ `window.isSecureContext` is part of the test rather than an afterthought: WebAuthn is
382
+ * unavailable on an insecure origin, and without this the button would render and then fail at the
383
+ * moment the user clicks it.
384
+ */
385
+ export declare function passkeysSupported(): boolean;
386
+ /**
387
+ * Where to send someone who is not signed in.
388
+ *
389
+ * `loginUrl` is the single source of truth for this, and the only thing the guard, the interceptor
390
+ * and the auth bar should consult — an application that turns off local credentials points it at
391
+ * its own sign-in landing route.
392
+ *
393
+ * The reason this is a function rather than a property read is the failure mode it closes: nothing
394
+ * connects `loginUrl` to the routes that actually exist, so pointing it at a route that was never
395
+ * registered produces a redirect into a blank page with no type error, no build failure and no
396
+ * runtime error. In development that now warns, once, naming the value and the fix.
397
+ */
398
+ export declare function resolveSignInUrl(config: SparkAuthConfig, router: Router): string;
399
+ /** `GET/POST /spark/auth/manage/profile` (#460, D16). */
400
+ export interface SparkAccountProfile {
401
+ userName: string | null;
402
+ email: string | null;
403
+ /** App-contributed fields (`ISparkProfileContributor<TUser>`), by name. */
404
+ fields: Record<string, unknown>;
405
+ /** The culture account mail is written in (`SparkUser.PreferredCulture`); null = the app default. */
406
+ preferredCulture: string | null;
407
+ }
408
+ /** The body of `POST /spark/auth/manage/profile`. Absent keeps a value; `preferredCulture: null` clears it. */
409
+ export interface SparkAccountProfileUpdate {
410
+ userName?: string | null;
411
+ fields?: Record<string, unknown>;
412
+ preferredCulture?: string | null;
413
+ }
414
+ /** `GET /spark/auth/manage/info` / answer of `POST manage/info`. */
415
+ export interface SparkAccountInfo {
416
+ email: string;
417
+ isEmailConfirmed: boolean;
418
+ }
419
+ /** Answer of `POST /spark/auth/manage/2fa` (ASP.NET Core Identity's contract). */
420
+ export interface SparkTwoFactorState {
421
+ sharedKey: string | null;
422
+ recoveryCodesLeft: number;
423
+ /** Only present right after codes were (re)generated — show them once. */
424
+ recoveryCodes?: string[] | null;
425
+ isTwoFactorEnabled: boolean;
426
+ isMachineRemembered: boolean;
427
+ }
428
+ /** The body of `POST /spark/auth/manage/2fa`. An empty body reads the state (and creates a key if none). */
429
+ export interface SparkTwoFactorRequest {
430
+ enable?: boolean;
431
+ twoFactorCode?: string;
432
+ resetSharedKey?: boolean;
433
+ resetRecoveryCodes?: boolean;
434
+ forgetMachine?: boolean;
435
+ }
436
+ /** `GET /spark/auth/manage/2fa/authenticator-uri`: the key, its otpauth URI and a server-rendered QR SVG. */
437
+ /**
438
+ * `GET`/`POST /manage/external-login-two-factor`: whether a sign-in with an external account skips
439
+ * the second factor for this user, and whether two-factor is enabled at all.
440
+ */
441
+ export interface SparkExternalLoginTwoFactor {
442
+ bypass: boolean;
443
+ twoFactorEnabled: boolean;
444
+ }
445
+ export interface SparkAuthenticatorUri {
446
+ sharedKey: string;
447
+ authenticatorUri: string;
448
+ qrCodeSvg: string;
449
+ }
450
+ /**
451
+ * The outcome of an account call that can fail with a message for the user.
452
+ *
453
+ * `errors` flattens an RFC 7807 validation problem (Identity codes, `PreferredCulture`, contributor
454
+ * fields) into `field → messages`; `error` carries a Spark error code (`reauthentication_required`,
455
+ * `no_authenticator_key`, …) when the server sent one.
456
+ */
457
+ export interface SparkAccountResult<T = void> {
458
+ success: boolean;
459
+ value?: T;
460
+ error?: string;
461
+ errors?: Record<string, string[]>;
462
+ status?: number;
463
+ }
464
+ /**
465
+ * One application field on the profile page (#460, D16), validated and stored server-side by an
466
+ * `ISparkProfileContributor<TUser>` declaring the same `name`.
467
+ */
468
+ export interface SparkAccountProfileField {
469
+ /** The field name, as the contributor declares it (matched case-insensitively by the server). */
470
+ name: string;
471
+ /** A translation key (looked up with the `t` pipe) or literal text. */
472
+ label: string;
473
+ type?: 'text' | 'textarea' | 'email' | 'url' | 'tel' | 'number' | 'date' | 'checkbox' | 'select';
474
+ /** For `select`. `label` is a translation key or literal text. */
475
+ options?: {
476
+ value: string;
477
+ label: string;
478
+ }[];
479
+ required?: boolean;
480
+ maxLength?: number;
481
+ /** A translation key or literal text shown under the control. */
482
+ hint?: string;
483
+ /** Ascending; unordered fields follow in registration order. */
484
+ order?: number;
485
+ }
486
+ /** Multi-provider: the application's profile fields. Use {@link provideSparkAccountProfileFields}. */
487
+ export declare const SPARK_ACCOUNT_PROFILE_FIELDS: InjectionToken<SparkAccountProfileField[]>;
488
+ /** Registers profile fields; every call adds. */
489
+ export declare function provideSparkAccountProfileFields(...fields: SparkAccountProfileField[]): Provider[];
@@ -0,0 +1,8 @@
1
+ import * as i0 from "@angular/core";
2
+ import { PipeTransform } from "@angular/core";
3
+ export declare class TranslateKeyPipe implements PipeTransform {
4
+ private readonly translation;
5
+ transform(key: string): string;
6
+ static ɵfac: i0.ɵɵFactoryDeclaration<TranslateKeyPipe, never>;
7
+ static ɵpipe: i0.ɵɵPipeDeclaration<TranslateKeyPipe, "t", true>;
8
+ }
@@ -0,0 +1,21 @@
1
+ import { Color } from "@mintplayer/ng-bootstrap";
2
+ import * as i0 from "@angular/core";
3
+ export declare class SparkRegisterComponent {
4
+ private readonly fb;
5
+ private readonly authService;
6
+ private readonly router;
7
+ private readonly translation;
8
+ readonly routePaths: Partial<Record<keyof import("@mintplayer/ng-spark/auth/models").SparkAuthRouteEntries, string>>;
9
+ colors: typeof Color;
10
+ readonly loading: import("@angular/core").WritableSignal<boolean>;
11
+ readonly errorMessage: import("@angular/core").WritableSignal<string>;
12
+ readonly form: import("@angular/forms").FormGroup<{
13
+ email: import("@angular/forms").FormControl<string | null>;
14
+ userName: import("@angular/forms").FormControl<string | null>;
15
+ password: import("@angular/forms").FormControl<string | null>;
16
+ confirmPassword: import("@angular/forms").FormControl<string | null>;
17
+ }>;
18
+ onSubmit(): Promise<void>;
19
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkRegisterComponent, never>;
20
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkRegisterComponent, "spark-register", never, {}, {}, never, never, true, never>;
21
+ }
@@ -0,0 +1,25 @@
1
+ import * as i0 from "@angular/core";
2
+ import { OnInit } from "@angular/core";
3
+ import { Color } from "@mintplayer/ng-bootstrap";
4
+ export declare class SparkResetPasswordComponent implements OnInit {
5
+ private readonly fb;
6
+ private readonly authService;
7
+ private readonly router;
8
+ private readonly route;
9
+ private readonly translation;
10
+ readonly routePaths: Partial<Record<keyof import("@mintplayer/ng-spark/auth/models").SparkAuthRouteEntries, string>>;
11
+ colors: typeof Color;
12
+ readonly loading: import("@angular/core").WritableSignal<boolean>;
13
+ readonly errorMessage: import("@angular/core").WritableSignal<string>;
14
+ readonly successMessage: import("@angular/core").WritableSignal<string>;
15
+ private email;
16
+ private code;
17
+ readonly form: import("@angular/forms").FormGroup<{
18
+ newPassword: import("@angular/forms").FormControl<string | null>;
19
+ confirmPassword: import("@angular/forms").FormControl<string | null>;
20
+ }>;
21
+ ngOnInit(): void;
22
+ onSubmit(): Promise<void>;
23
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkResetPasswordComponent, never>;
24
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkResetPasswordComponent, "spark-reset-password", never, {}, {}, never, never, true, never>;
25
+ }