@mintplayer/ng-spark 22.29.0 → 22.31.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 (103) hide show
  1. package/README.md +3 -3
  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 +368 -2
  38. package/fesm2022/mintplayer-ng-spark-client-operations.mjs.map +1 -1
  39. package/fesm2022/mintplayer-ng-spark-grid.mjs +22 -9
  40. package/fesm2022/mintplayer-ng-spark-grid.mjs.map +1 -1
  41. package/fesm2022/mintplayer-ng-spark-identity-provider-connected-applications.mjs +389 -0
  42. package/fesm2022/mintplayer-ng-spark-identity-provider-connected-applications.mjs.map +1 -0
  43. package/fesm2022/mintplayer-ng-spark-identity-provider-core.mjs +204 -0
  44. package/fesm2022/mintplayer-ng-spark-identity-provider-core.mjs.map +1 -0
  45. package/fesm2022/mintplayer-ng-spark-identity-provider-developers.mjs +486 -0
  46. package/fesm2022/mintplayer-ng-spark-identity-provider-developers.mjs.map +1 -0
  47. package/fesm2022/mintplayer-ng-spark-identity-provider-management.mjs +350 -0
  48. package/fesm2022/mintplayer-ng-spark-identity-provider-management.mjs.map +1 -0
  49. package/fesm2022/mintplayer-ng-spark-identity-provider.mjs +66 -0
  50. package/fesm2022/mintplayer-ng-spark-identity-provider.mjs.map +1 -0
  51. package/fesm2022/mintplayer-ng-spark-models.mjs +2 -1
  52. package/fesm2022/mintplayer-ng-spark-models.mjs.map +1 -1
  53. package/fesm2022/mintplayer-ng-spark-po-detail.mjs +13 -3
  54. package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
  55. package/fesm2022/mintplayer-ng-spark-po-form.mjs +6 -3
  56. package/fesm2022/mintplayer-ng-spark-po-form.mjs.map +1 -1
  57. package/fesm2022/mintplayer-ng-spark-pwa.mjs +162 -0
  58. package/fesm2022/mintplayer-ng-spark-pwa.mjs.map +1 -0
  59. package/fesm2022/mintplayer-ng-spark-query-list.mjs +5 -2
  60. package/fesm2022/mintplayer-ng-spark-query-list.mjs.map +1 -1
  61. package/fesm2022/mintplayer-ng-spark-renderers.mjs +109 -4
  62. package/fesm2022/mintplayer-ng-spark-renderers.mjs.map +1 -1
  63. package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs +36 -6
  64. package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs.map +1 -1
  65. package/fesm2022/mintplayer-ng-spark-services.mjs +48 -6
  66. package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
  67. package/fesm2022/mintplayer-ng-spark-shell.mjs.map +1 -1
  68. package/fesm2022/mintplayer-ng-spark.mjs.map +1 -1
  69. package/package.json +101 -3
  70. package/types/mintplayer-ng-spark-auth-account.d.ts +255 -0
  71. package/types/mintplayer-ng-spark-auth-auth-bar.d.ts +22 -0
  72. package/types/mintplayer-ng-spark-auth-confirm-email.d.ts +21 -0
  73. package/types/mintplayer-ng-spark-auth-core.d.ts +197 -0
  74. package/types/mintplayer-ng-spark-auth-external-login.d.ts +132 -0
  75. package/types/mintplayer-ng-spark-auth-forgot-password.d.ts +18 -0
  76. package/types/mintplayer-ng-spark-auth-guards.d.ts +15 -0
  77. package/types/mintplayer-ng-spark-auth-interceptors.d.ts +2 -0
  78. package/types/mintplayer-ng-spark-auth-login.d.ts +46 -0
  79. package/types/mintplayer-ng-spark-auth-models.d.ts +489 -0
  80. package/types/mintplayer-ng-spark-auth-pipes.d.ts +8 -0
  81. package/types/mintplayer-ng-spark-auth-register.d.ts +21 -0
  82. package/types/mintplayer-ng-spark-auth-reset-password.d.ts +25 -0
  83. package/types/mintplayer-ng-spark-auth-routes.d.ts +154 -0
  84. package/types/mintplayer-ng-spark-auth-sign-in.d.ts +84 -0
  85. package/types/mintplayer-ng-spark-auth-two-factor.d.ts +23 -0
  86. package/types/mintplayer-ng-spark-auth.d.ts +24 -0
  87. package/types/mintplayer-ng-spark-client-operations.d.ts +148 -3
  88. package/types/mintplayer-ng-spark-grid.d.ts +19 -1
  89. package/types/mintplayer-ng-spark-identity-provider-connected-applications.d.ts +35 -0
  90. package/types/mintplayer-ng-spark-identity-provider-core.d.ts +144 -0
  91. package/types/mintplayer-ng-spark-identity-provider-developers.d.ts +55 -0
  92. package/types/mintplayer-ng-spark-identity-provider-management.d.ts +33 -0
  93. package/types/mintplayer-ng-spark-identity-provider.d.ts +64 -0
  94. package/types/mintplayer-ng-spark-models.d.ts +28 -0
  95. package/types/mintplayer-ng-spark-po-detail.d.ts +8 -0
  96. package/types/mintplayer-ng-spark-po-form.d.ts +2 -0
  97. package/types/mintplayer-ng-spark-pwa.d.ts +89 -0
  98. package/types/mintplayer-ng-spark-query-list.d.ts +2 -0
  99. package/types/mintplayer-ng-spark-renderers.d.ts +47 -0
  100. package/types/mintplayer-ng-spark-retry-action-modal.d.ts +1 -0
  101. package/types/mintplayer-ng-spark-services.d.ts +37 -1
  102. package/types/mintplayer-ng-spark-shell.d.ts +2 -2
  103. package/types/mintplayer-ng-spark.d.ts +4 -4
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mintplayer/ng-spark",
3
3
  "private": false,
4
- "version": "22.29.0",
4
+ "version": "22.31.0",
5
5
  "description": "Angular component library for MintPlayer.Spark CRUD applications",
6
6
  "repository": {
7
7
  "type": "git",
@@ -14,11 +14,17 @@
14
14
  "@angular/common": "^22.0.0",
15
15
  "@angular/router": "^22.0.0",
16
16
  "@angular/forms": "^22.0.0",
17
- "@mintplayer/ng-bootstrap": "^22.21.0",
18
- "@mintplayer/web-components": "^2.18.0",
17
+ "@angular/service-worker": "^22.0.0",
18
+ "@mintplayer/ng-bootstrap": "^22.22.0",
19
+ "@mintplayer/web-components": "^2.19.0",
19
20
  "@mintplayer/pagination": "*",
20
21
  "rxjs": "~7.8.0"
21
22
  },
23
+ "peerDependenciesMeta": {
24
+ "@angular/service-worker": {
25
+ "optional": true
26
+ }
27
+ },
22
28
  "sideEffects": false,
23
29
  "module": "fesm2022/mintplayer-ng-spark.mjs",
24
30
  "typings": "types/mintplayer-ng-spark.d.ts",
@@ -34,6 +40,74 @@
34
40
  "types": "./types/mintplayer-ng-spark-attribute-description.d.ts",
35
41
  "default": "./fesm2022/mintplayer-ng-spark-attribute-description.mjs"
36
42
  },
43
+ "./auth": {
44
+ "types": "./types/mintplayer-ng-spark-auth.d.ts",
45
+ "default": "./fesm2022/mintplayer-ng-spark-auth.mjs"
46
+ },
47
+ "./auth/account": {
48
+ "types": "./types/mintplayer-ng-spark-auth-account.d.ts",
49
+ "default": "./fesm2022/mintplayer-ng-spark-auth-account.mjs"
50
+ },
51
+ "./auth/auth-bar": {
52
+ "types": "./types/mintplayer-ng-spark-auth-auth-bar.d.ts",
53
+ "default": "./fesm2022/mintplayer-ng-spark-auth-auth-bar.mjs"
54
+ },
55
+ "./auth/confirm-email": {
56
+ "types": "./types/mintplayer-ng-spark-auth-confirm-email.d.ts",
57
+ "default": "./fesm2022/mintplayer-ng-spark-auth-confirm-email.mjs"
58
+ },
59
+ "./auth/core": {
60
+ "types": "./types/mintplayer-ng-spark-auth-core.d.ts",
61
+ "default": "./fesm2022/mintplayer-ng-spark-auth-core.mjs"
62
+ },
63
+ "./auth/external-login": {
64
+ "types": "./types/mintplayer-ng-spark-auth-external-login.d.ts",
65
+ "default": "./fesm2022/mintplayer-ng-spark-auth-external-login.mjs"
66
+ },
67
+ "./auth/forgot-password": {
68
+ "types": "./types/mintplayer-ng-spark-auth-forgot-password.d.ts",
69
+ "default": "./fesm2022/mintplayer-ng-spark-auth-forgot-password.mjs"
70
+ },
71
+ "./auth/guards": {
72
+ "types": "./types/mintplayer-ng-spark-auth-guards.d.ts",
73
+ "default": "./fesm2022/mintplayer-ng-spark-auth-guards.mjs"
74
+ },
75
+ "./auth/interceptors": {
76
+ "types": "./types/mintplayer-ng-spark-auth-interceptors.d.ts",
77
+ "default": "./fesm2022/mintplayer-ng-spark-auth-interceptors.mjs"
78
+ },
79
+ "./auth/login": {
80
+ "types": "./types/mintplayer-ng-spark-auth-login.d.ts",
81
+ "default": "./fesm2022/mintplayer-ng-spark-auth-login.mjs"
82
+ },
83
+ "./auth/models": {
84
+ "types": "./types/mintplayer-ng-spark-auth-models.d.ts",
85
+ "default": "./fesm2022/mintplayer-ng-spark-auth-models.mjs"
86
+ },
87
+ "./auth/pipes": {
88
+ "types": "./types/mintplayer-ng-spark-auth-pipes.d.ts",
89
+ "default": "./fesm2022/mintplayer-ng-spark-auth-pipes.mjs"
90
+ },
91
+ "./auth/register": {
92
+ "types": "./types/mintplayer-ng-spark-auth-register.d.ts",
93
+ "default": "./fesm2022/mintplayer-ng-spark-auth-register.mjs"
94
+ },
95
+ "./auth/reset-password": {
96
+ "types": "./types/mintplayer-ng-spark-auth-reset-password.d.ts",
97
+ "default": "./fesm2022/mintplayer-ng-spark-auth-reset-password.mjs"
98
+ },
99
+ "./auth/routes": {
100
+ "types": "./types/mintplayer-ng-spark-auth-routes.d.ts",
101
+ "default": "./fesm2022/mintplayer-ng-spark-auth-routes.mjs"
102
+ },
103
+ "./auth/sign-in": {
104
+ "types": "./types/mintplayer-ng-spark-auth-sign-in.d.ts",
105
+ "default": "./fesm2022/mintplayer-ng-spark-auth-sign-in.mjs"
106
+ },
107
+ "./auth/two-factor": {
108
+ "types": "./types/mintplayer-ng-spark-auth-two-factor.d.ts",
109
+ "default": "./fesm2022/mintplayer-ng-spark-auth-two-factor.mjs"
110
+ },
37
111
  "./client-operations": {
38
112
  "types": "./types/mintplayer-ng-spark-client-operations.d.ts",
39
113
  "default": "./fesm2022/mintplayer-ng-spark-client-operations.mjs"
@@ -58,6 +132,26 @@
58
132
  "types": "./types/mintplayer-ng-spark-icon.d.ts",
59
133
  "default": "./fesm2022/mintplayer-ng-spark-icon.mjs"
60
134
  },
135
+ "./identity-provider": {
136
+ "types": "./types/mintplayer-ng-spark-identity-provider.d.ts",
137
+ "default": "./fesm2022/mintplayer-ng-spark-identity-provider.mjs"
138
+ },
139
+ "./identity-provider/connected-applications": {
140
+ "types": "./types/mintplayer-ng-spark-identity-provider-connected-applications.d.ts",
141
+ "default": "./fesm2022/mintplayer-ng-spark-identity-provider-connected-applications.mjs"
142
+ },
143
+ "./identity-provider/core": {
144
+ "types": "./types/mintplayer-ng-spark-identity-provider-core.d.ts",
145
+ "default": "./fesm2022/mintplayer-ng-spark-identity-provider-core.mjs"
146
+ },
147
+ "./identity-provider/developers": {
148
+ "types": "./types/mintplayer-ng-spark-identity-provider-developers.d.ts",
149
+ "default": "./fesm2022/mintplayer-ng-spark-identity-provider-developers.mjs"
150
+ },
151
+ "./identity-provider/management": {
152
+ "types": "./types/mintplayer-ng-spark-identity-provider-management.d.ts",
153
+ "default": "./fesm2022/mintplayer-ng-spark-identity-provider-management.mjs"
154
+ },
61
155
  "./models": {
62
156
  "types": "./types/mintplayer-ng-spark-models.d.ts",
63
157
  "default": "./fesm2022/mintplayer-ng-spark-models.mjs"
@@ -90,6 +184,10 @@
90
184
  "types": "./types/mintplayer-ng-spark-po-form.d.ts",
91
185
  "default": "./fesm2022/mintplayer-ng-spark-po-form.mjs"
92
186
  },
187
+ "./pwa": {
188
+ "types": "./types/mintplayer-ng-spark-pwa.d.ts",
189
+ "default": "./fesm2022/mintplayer-ng-spark-pwa.mjs"
190
+ },
93
191
  "./query-list": {
94
192
  "types": "./types/mintplayer-ng-spark-query-list.d.ts",
95
193
  "default": "./fesm2022/mintplayer-ng-spark-query-list.mjs"
@@ -0,0 +1,255 @@
1
+ import { SparkAccountProfileField, SparkAccountResult, SparkAuthCapabilities, SparkAuthRoutePaths, SparkAuthenticatorUri, SparkExternalLogins, SparkTwoFactorState } from "@mintplayer/ng-spark/auth/models";
2
+ import { SparkAuthService } from "@mintplayer/ng-spark/auth/core";
3
+ import * as i0 from "@angular/core";
4
+ import { OnInit } from "@angular/core";
5
+ import { FormControl, FormGroup } from "@angular/forms";
6
+ import { Color } from "@mintplayer/ng-bootstrap";
7
+ /**
8
+ * The messages to show for a failed account call: the server's validation messages (already written
9
+ * for the user by Identity or a profile contributor), else a translation key for its error code or
10
+ * status. Keys start with `auth.`; the page runs everything through the `t` pipe, which returns
11
+ * anything that is not a key unchanged.
12
+ */
13
+ export declare function accountMessages(result: SparkAccountResult<unknown>): string[];
14
+ /** The messages for one field of a validation problem, matched case-insensitively. */
15
+ export declare function fieldMessages(result: SparkAccountResult<unknown> | null, field: string): string[];
16
+ /**
17
+ * Whether the server serves a page's feature. Mounting a page on the client is necessary but not
18
+ * sufficient: the route table and the server's switches are configured independently, which is why
19
+ * `/spark/auth/capabilities` exists. Pages without an entry need no switch beyond being mounted.
20
+ */
21
+ type ServerCheck = (capabilities: SparkAuthCapabilities) => boolean;
22
+ /**
23
+ * The account area's landing page (#460, D16): who is signed in, and a link per account page that is
24
+ * both mounted (`withAccount()`) and served (`/spark/auth/capabilities`), then the links other route
25
+ * features contribute through `SPARK_ACCOUNT_OVERVIEW_LINKS` (e.g. connected applications, from
26
+ * `@mintplayer/ng-spark/identity-provider`).
27
+ */
28
+ export declare class SparkAccountOverviewComponent {
29
+ protected readonly auth: SparkAuthService;
30
+ private readonly paths;
31
+ private readonly capabilities;
32
+ /**
33
+ * Pages behind a server switch stay hidden until the capabilities arrive, and stay hidden if the
34
+ * call fails: offering a page whose endpoints the server does not map is worse than omitting it.
35
+ */
36
+ protected readonly pages: import("@angular/core").Signal<{
37
+ path: string;
38
+ key: keyof SparkAuthRoutePaths;
39
+ label: string;
40
+ server?: ServerCheck;
41
+ }[]>;
42
+ private readonly accountLinks;
43
+ /**
44
+ * Links contributed by route features of other entry points (connected applications), after the
45
+ * auth pages. Each carries its own translations; resolved in the app's current language.
46
+ */
47
+ protected readonly extraLinks: import("@angular/core").Signal<{
48
+ key: string;
49
+ path: string;
50
+ label: string;
51
+ }[]>;
52
+ constructor();
53
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkAccountOverviewComponent, never>;
54
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkAccountOverviewComponent, "spark-account-overview", never, {}, {}, never, never, true, never>;
55
+ }
56
+ interface CultureOption {
57
+ value: string;
58
+ label: string;
59
+ }
60
+ /**
61
+ * The profile page (#460, D16): user name, email (changeable only under the server's opt-in
62
+ * `SparkEmailChange.Enabled`; a change is confirmed from the NEW address first),
63
+ * the preferred mail language (`SparkUser.PreferredCulture`, M8) and the application's own fields
64
+ * (`SPARK_ACCOUNT_PROFILE_FIELDS`, validated server-side by `ISparkProfileContributor<TUser>`).
65
+ *
66
+ * The language list is the application's UI languages (`GET /spark/culture`); a stored culture not in
67
+ * that list (e.g. `nl-BE`) is kept as an option so opening the page never changes it.
68
+ */
69
+ export declare class SparkAccountProfileComponent {
70
+ private readonly auth;
71
+ private readonly http;
72
+ protected readonly colors: typeof Color;
73
+ /** The app's fields, ordered; each becomes a control under `fields`. */
74
+ protected readonly profileFields: SparkAccountProfileField[];
75
+ readonly form: FormGroup<{
76
+ userName: FormControl<string>;
77
+ preferredCulture: FormControl<string>;
78
+ fields: FormGroup<Record<string, FormControl<unknown>>>;
79
+ }>;
80
+ readonly emailForm: FormGroup<{
81
+ newEmail: FormControl<string>;
82
+ }>;
83
+ readonly loading: import("@angular/core").WritableSignal<boolean>;
84
+ readonly busy: import("@angular/core").WritableSignal<boolean>;
85
+ readonly saved: import("@angular/core").WritableSignal<boolean>;
86
+ readonly messages: import("@angular/core").WritableSignal<string[]>;
87
+ private readonly lastResult;
88
+ readonly email: import("@angular/core").WritableSignal<string | null>;
89
+ readonly emailConfirmed: import("@angular/core").WritableSignal<boolean | null>;
90
+ readonly emailSent: import("@angular/core").WritableSignal<boolean>;
91
+ readonly emailMessages: import("@angular/core").WritableSignal<string[]>;
92
+ /** Off until the server reports `emailChange`, and off if the capabilities call fails. */
93
+ readonly emailChangeAllowed: import("@angular/core").WritableSignal<boolean>;
94
+ private readonly languages;
95
+ private readonly storedCulture;
96
+ readonly cultureOptions: import("@angular/core").Signal<CultureOption[]>;
97
+ readonly userNameErrors: import("@angular/core").Signal<string[]>;
98
+ constructor();
99
+ private isInlineError;
100
+ protected fieldErrors(name: string): string[];
101
+ private load;
102
+ private loadLanguages;
103
+ private apply;
104
+ save(): Promise<void>;
105
+ changeEmail(): Promise<void>;
106
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkAccountProfileComponent, never>;
107
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkAccountProfileComponent, "spark-account-profile", never, {}, {}, never, never, true, never>;
108
+ }
109
+ /**
110
+ * Change the password — or set a first one on an account created through an external provider
111
+ * (`POST /spark/auth/manage/password`, #460 D16). The current password is required only when the
112
+ * account has one; the server says so (`CurrentPasswordRequired`) rather than the page guessing.
113
+ */
114
+ export declare class SparkChangePasswordComponent {
115
+ private readonly auth;
116
+ protected readonly colors: typeof Color;
117
+ readonly form: FormGroup<{
118
+ currentPassword: FormControl<string>;
119
+ newPassword: FormControl<string>;
120
+ confirmPassword: FormControl<string>;
121
+ }>;
122
+ readonly busy: import("@angular/core").WritableSignal<boolean>;
123
+ readonly saved: import("@angular/core").WritableSignal<boolean>;
124
+ readonly messages: import("@angular/core").WritableSignal<string[]>;
125
+ submit(): Promise<void>;
126
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkChangePasswordComponent, never>;
127
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkChangePasswordComponent, "spark-change-password", never, {}, {}, never, never, true, never>;
128
+ }
129
+ /**
130
+ * Two-factor authentication (#460, D16): enroll an authenticator app (server-rendered QR SVG, SP-D),
131
+ * see and regenerate recovery codes, forget this browser, reset the key, disable 2FA; and, when the
132
+ * server offers it and 2FA is on, let an external sign-in skip the code (switching that on needs a code).
133
+ *
134
+ * Built on Identity's `POST /manage/2fa` (which creates the key on the first read) and Spark's read-only
135
+ * `GET /manage/2fa/authenticator-uri`. The QR SVG is shown through an `<img>` data URL, never inserted
136
+ * as markup: an image cannot run script, whatever the SVG contains.
137
+ */
138
+ export declare class SparkTwoFactorSetupComponent {
139
+ private readonly auth;
140
+ private readonly translation;
141
+ protected readonly colors: typeof Color;
142
+ readonly form: FormGroup<{
143
+ code: FormControl<string>;
144
+ }>;
145
+ readonly loading: import("@angular/core").WritableSignal<boolean>;
146
+ readonly busy: import("@angular/core").WritableSignal<boolean>;
147
+ readonly messages: import("@angular/core").WritableSignal<string[]>;
148
+ readonly state: import("@angular/core").WritableSignal<SparkTwoFactorState | null>;
149
+ readonly authenticator: import("@angular/core").WritableSignal<SparkAuthenticatorUri | null>;
150
+ readonly recoveryCodes: import("@angular/core").WritableSignal<string[]>;
151
+ /** The server's SVG as an image URL — displayed, never parsed into the DOM. */
152
+ readonly qrDataUrl: import("@angular/core").Signal<string | null>;
153
+ readonly bypassForm: FormGroup<{
154
+ code: FormControl<string>;
155
+ }>;
156
+ /** The server offers the external-login bypass (`capabilities.externalLoginTwoFactorBypass`). */
157
+ private readonly bypassCapability;
158
+ /** The account's bypass setting, or null until read (or when the read failed). */
159
+ readonly bypass: import("@angular/core").WritableSignal<boolean | null>;
160
+ /** Switched on but not yet confirmed with an authenticator code. */
161
+ readonly bypassPending: import("@angular/core").WritableSignal<boolean>;
162
+ /** Shown only when the server offers it AND the account has two-factor on: there is nothing to skip otherwise. */
163
+ readonly bypassOffered: import("@angular/core").Signal<boolean>;
164
+ readonly bypassChecked: import("@angular/core").Signal<boolean>;
165
+ constructor();
166
+ private loadBypass;
167
+ /** Off: saved at once. On: asks for an authenticator code first ({@link confirmBypass}). */
168
+ toggleBypass(on: boolean): Promise<void>;
169
+ confirmBypass(): Promise<void>;
170
+ private saveBypass;
171
+ /** Groups the base32 key in fours, the way authenticator apps show it. */
172
+ protected formatKey(key: string): string;
173
+ refresh(): Promise<void>;
174
+ enable(): Promise<void>;
175
+ disable(): Promise<void>;
176
+ regenerateRecoveryCodes(): Promise<void>;
177
+ forgetMachine(): Promise<void>;
178
+ resetKey(): Promise<void>;
179
+ private run;
180
+ private applyState;
181
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkTwoFactorSetupComponent, never>;
182
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkTwoFactorSetupComponent, "spark-two-factor-setup", never, {}, {}, never, never, true, never>;
183
+ }
184
+ /**
185
+ * Connected logins (#460, D16): the providers attached to the account (remove, unless it is the last
186
+ * way in — the server's `canUnlink`, and its refusal), and the configured providers that could be
187
+ * attached (a popup handshake keyed on the signed-in user).
188
+ *
189
+ * Presentation (icon, display name) comes from the same `externalProvider()` declarations as the
190
+ * sign-in page when they are in scope; the server stays authoritative over which providers exist.
191
+ */
192
+ export declare class SparkExternalLoginsComponent {
193
+ private readonly auth;
194
+ private readonly router;
195
+ private readonly presentations;
196
+ protected readonly colors: typeof Color;
197
+ readonly loading: import("@angular/core").WritableSignal<boolean>;
198
+ readonly busy: import("@angular/core").WritableSignal<boolean>;
199
+ readonly errorKey: import("@angular/core").WritableSignal<string>;
200
+ readonly logins: import("@angular/core").WritableSignal<SparkExternalLogins | null>;
201
+ /**
202
+ * While a link popup is open. Taken from the service, not from the link() promise: under COOP the
203
+ * popup reads closed long before the result arrives, and the attempt keeps listening (D2).
204
+ */
205
+ readonly linkPending: import("@angular/core").Signal<boolean>;
206
+ /** `link_confirmation_sent` travels as a failure but is news, not an error. */
207
+ readonly errorIsNotice: import("@angular/core").Signal<boolean>;
208
+ constructor();
209
+ private showLinkError;
210
+ private presentation;
211
+ protected iconFor(scheme: string): string | undefined;
212
+ protected nameFor(scheme: string, serverName: string): string;
213
+ refresh(): Promise<void>;
214
+ /**
215
+ * Links another provider. The buttons follow {@link linkPending} rather than this promise, which
216
+ * settles only on the result, a newer attempt or the 10-minute timeout.
217
+ */
218
+ link(provider: string): Promise<void>;
219
+ unlink(provider: string, providerKey: string): Promise<void>;
220
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkExternalLoginsComponent, never>;
221
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkExternalLoginsComponent, "spark-external-logins", never, {}, {}, never, never, true, never>;
222
+ }
223
+ /**
224
+ * Personal data (#460, D8/D16): download everything the account and the application's
225
+ * `ISparkPersonalDataContributor`s hold as JSON, and delete the account.
226
+ *
227
+ * Deletion needs re-authentication: the current password (the field shows only when the account has
228
+ * one, from `account.hasPassword`), or — for an account without one — a sign-in
229
+ * younger than the server's `ReauthenticationMaxAge` (5 minutes). A 403 `reauthentication_required`
230
+ * says which is missing; the page then asks to sign in again. Handlers run first and the account is
231
+ * removed last, so a failure (500 `deletion_failed`) leaves the account intact and retryable.
232
+ */
233
+ export declare class SparkPersonalDataComponent implements OnInit {
234
+ private readonly auth;
235
+ private readonly router;
236
+ private readonly config;
237
+ protected readonly colors: typeof Color;
238
+ readonly form: FormGroup<{
239
+ password: FormControl<string>;
240
+ confirm: FormControl<boolean>;
241
+ }>;
242
+ readonly busy: import("@angular/core").WritableSignal<boolean>;
243
+ readonly downloadMessages: import("@angular/core").WritableSignal<string[]>;
244
+ readonly deleteMessages: import("@angular/core").WritableSignal<string[]>;
245
+ /**
246
+ * Whether the account has a password (`account.hasPassword` of the personal data). Null while
247
+ * unknown — an older server, or the read failed — which keeps the password field, as before.
248
+ */
249
+ readonly hasPassword: import("@angular/core").WritableSignal<boolean | null>;
250
+ ngOnInit(): Promise<void>;
251
+ download(): Promise<void>;
252
+ deleteAccount(): Promise<void>;
253
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkPersonalDataComponent, never>;
254
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkPersonalDataComponent, "spark-personal-data", never, {}, {}, never, never, true, never>;
255
+ }
@@ -0,0 +1,22 @@
1
+ import { SparkAuthService } from "@mintplayer/ng-spark/auth/core";
2
+ import * as i0 from "@angular/core";
3
+ export declare class SparkAuthBarComponent {
4
+ readonly authService: SparkAuthService;
5
+ readonly config: import("@mintplayer/ng-spark/auth/models").SparkAuthConfig;
6
+ private readonly router;
7
+ /** Same target the guard and interceptor use, so the bar cannot link somewhere they would not send you. */
8
+ readonly signInUrl: string;
9
+ /**
10
+ * Where the account overview lives, or `undefined` when `withAccount()` did not mount it — then the
11
+ * bar offers logout alone rather than a link that would fall through to some other route.
12
+ *
13
+ * `SPARK_AUTH_ROUTE_PATHS` is provided by `sparkAuthRoutes()` on its own route subtree, and this bar
14
+ * usually lives in the application shell, outside it, so the token is injected optionally and the
15
+ * router configuration is the fallback. Reading the configuration makes a custom `account` path
16
+ * exact here too, instead of assuming the default.
17
+ */
18
+ readonly accountUrl: string | undefined;
19
+ onLogout(): Promise<void>;
20
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkAuthBarComponent, never>;
21
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkAuthBarComponent, "spark-auth-bar", never, {}, {}, never, never, true, never>;
22
+ }
@@ -0,0 +1,21 @@
1
+ import { Color } from "@mintplayer/ng-bootstrap";
2
+ import { SparkAuthService } from "@mintplayer/ng-spark/auth/core";
3
+ import * as i0 from "@angular/core";
4
+ type ConfirmState = 'working' | 'confirmed' | 'changed' | 'invalid';
5
+ /**
6
+ * The target of every confirmation mail (#460, D16): `?userId=&code=` confirms an address,
7
+ * `&changedEmail=` completes an email change (M5: one route for both). Posts once, on load, to
8
+ * `POST /spark/auth/confirm-email`. Public — the link is opened from a mailbox, often signed out.
9
+ */
10
+ export declare class SparkConfirmEmailComponent {
11
+ protected readonly auth: SparkAuthService;
12
+ private readonly route;
13
+ protected readonly routePaths: Partial<Record<keyof import("@mintplayer/ng-spark/auth/models").SparkAuthRouteEntries, string>>;
14
+ protected readonly homeUrl: string;
15
+ protected readonly colors: typeof Color;
16
+ readonly state: import("@angular/core").WritableSignal<ConfirmState>;
17
+ constructor();
18
+ private confirm;
19
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkConfirmEmailComponent, never>;
20
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkConfirmEmailComponent, "spark-confirm-email", never, {}, {}, never, never, true, never>;
21
+ }
@@ -0,0 +1,197 @@
1
+ import { AuthUser, SparkAccountInfo, SparkAccountProfile, SparkAccountProfileUpdate, SparkAccountResult, SparkAuthCapabilities, SparkAuthenticatorUri, SparkExternalLoginError, SparkExternalLoginOptions, SparkExternalLoginResult, SparkExternalLoginTwoFactor, SparkExternalLogins, SparkPasskeyResult, SparkTwoFactorRequest, SparkTwoFactorState, SparkUnlinkResult } from "@mintplayer/ng-spark/auth/models";
2
+ import * as i0 from "@angular/core";
3
+ export declare class SparkAuthService {
4
+ private readonly http;
5
+ private readonly config;
6
+ private readonly zone;
7
+ private readonly currentUser;
8
+ readonly user: import("@angular/core").Signal<AuthUser | null>;
9
+ readonly isAuthenticated: import("@angular/core").Signal<boolean>;
10
+ /** Resolved lazily: only {@link takeExternalLoginResult} needs the router. */
11
+ private readonly injector;
12
+ private readonly pendingExternalLogin;
13
+ /**
14
+ * `true` while a popup sign-in or link attempt is open and its popup has not been seen closed.
15
+ *
16
+ * ⚠️ Drive button and spinner state from this, **not** from the promise settling. When the
17
+ * provider's login page sends COOP the popup reads closed long before its result arrives, so this
18
+ * turns `false` early (the buttons re-enable) while the attempt keeps listening, and a late result
19
+ * still settles it.
20
+ */
21
+ readonly externalLoginPending: import("@angular/core").Signal<boolean>;
22
+ /** Settles the open popup attempt; `null` when none is open. */
23
+ private activeExternalAttempt;
24
+ constructor();
25
+ /**
26
+ * The credentials of a sign-in that answered `RequiresTwoFactor`, held in memory only until the
27
+ * second step. MapIdentityApi's `/login` is stateless per request: the 2FA step must repeat the
28
+ * email and password next to the code (its `LoginRequest` requires both), or it answers 400.
29
+ */
30
+ private pendingTwoFactorLogin;
31
+ /** Whether the pending sign-in (and its two-factor step) asked for a persistent cookie. */
32
+ private pendingRememberMe;
33
+ /**
34
+ * The login URL. MapIdentityApi's `/login` issues a persistent cookie for `useCookies=true`
35
+ * and a session cookie (no `Expires`) when `useSessionCookies=true` is added.
36
+ */
37
+ private loginUrl;
38
+ /**
39
+ * Signs in with a cookie. `rememberMe` (default `true`) makes the cookie persistent; `false`
40
+ * makes it a session cookie that ends with the browser session.
41
+ */
42
+ login(email: string, password: string, rememberMe?: boolean): Promise<void>;
43
+ loginTwoFactor(twoFactorCode: string, twoFactorRecoveryCode?: string): Promise<void>;
44
+ /** `userName` is the public handle other users see; it is required and may not contain `@`. */
45
+ register(email: string, password: string, userName: string): Promise<void>;
46
+ logout(): Promise<void>;
47
+ /**
48
+ * What sign-in methods this deployment actually offers.
49
+ *
50
+ * Read from the server rather than assumed from the client's own route configuration: the two are
51
+ * configured independently, and a mismatch is otherwise invisible until a user hits it.
52
+ *
53
+ * Callers that ask while a request is already in flight share it: the login page and the
54
+ * `<spark-external-login-buttons>` it hosts both ask on construction, and that is one request, not
55
+ * two. Nothing is cached once it settles, so a later call still reads the server's current answer.
56
+ */
57
+ capabilities(): Promise<SparkAuthCapabilities>;
58
+ private capabilitiesInFlight;
59
+ csrfRefresh(): Promise<void>;
60
+ checkAuth(): Promise<AuthUser | null>;
61
+ /**
62
+ * Signs in through an external provider (GitHub, Google, …) and leaves this service's
63
+ * `user()` signal up to date, exactly as `login()` does.
64
+ *
65
+ * The whole handshake lives here: a per-attempt nonce, four ways for the result to come back
66
+ * (`postMessage` from the opener-held popup, a BroadcastChannel, a `localStorage` entry and its
67
+ * `storage` event, and a re-read of that entry when this tab is shown again), the acknowledgement
68
+ * that lets the callback page close itself, teardown on every exit path, and re-reading the
69
+ * session afterwards. Callers get an outcome, not a protocol.
70
+ *
71
+ * A popup attempt settles only when its result arrives, when another attempt starts (the old one
72
+ * settles `popup_closed`), or after 10 minutes (`popup_closed`). A popup that *looks* closed does
73
+ * not settle it: the provider's COOP header severs the handle while the user is still signing in.
74
+ * ⚠️ Take button and spinner state from {@link externalLoginPending}, not from this promise.
75
+ *
76
+ * The mode is the call's `mode`, else the configured `externalLoginMode` (`'auto'`: redirect in an
77
+ * installed web app, popup otherwise). In `'redirect'` mode the returned promise never settles:
78
+ * this document is being replaced, and the outcome arrives as the next page load
79
+ * ({@link takeExternalLoginResult}) rather than as a value.
80
+ */
81
+ loginWithProvider(provider: string, options?: SparkExternalLoginOptions): Promise<SparkExternalLoginResult>;
82
+ /**
83
+ * What external logins are attached to the signed-in account, and what else could be.
84
+ *
85
+ * Only served when the deployment allows linking at all; under `Disabled` the endpoint is not
86
+ * mapped, so this rejects with a 404. That is deliberate on the server side — an account page
87
+ * offering an action the deployment forbids is worse than one that is absent.
88
+ */
89
+ externalLogins(): Promise<SparkExternalLogins>;
90
+ /**
91
+ * Attaches another provider to the account that is already signed in.
92
+ *
93
+ * The same handshake as {@link loginWithProvider}, against the endpoint that links rather than
94
+ * the one that signs in — the difference that matters is on the server, where the challenge is
95
+ * keyed on the current user so the identity coming back cannot land in somebody else's session.
96
+ */
97
+ linkProvider(provider: string, options?: SparkExternalLoginOptions): Promise<SparkExternalLoginResult>;
98
+ /**
99
+ * Detaches a provider from the signed-in account.
100
+ *
101
+ * ⚠️ Resolves with `error: 'last_credential'` rather than throwing when the server refuses to
102
+ * remove the account's last way in. It is an expected answer to a reasonable request, not a
103
+ * fault — and it is the server's refusal that protects the user, not the `canUnlink` flag the
104
+ * list hands out.
105
+ */
106
+ unlinkProvider(provider: string, providerKey: string): Promise<SparkUnlinkResult>;
107
+ /**
108
+ * Reads the `?sparkExternalLogin=<code>` a redirect-mode round trip came back with, and strips it
109
+ * from the address bar (a `replaceUrl` navigation, so Back does not bring it back and a reload
110
+ * does not show it twice).
111
+ *
112
+ * Answers `null` when the URL carries none. A value that is not a known
113
+ * {@link SparkExternalLoginError} is answered as `no_login_info` rather than echoed, so a crafted
114
+ * link cannot put text of its choosing on the page.
115
+ *
116
+ * Only failures carry the parameter, and they land on the `errorUrl` the attempt was started with
117
+ * (by default the page that started it); a successful redirect lands on the `returnUrl` signed in.
118
+ * The shipped `<spark-external-login-buttons>` (on the sign-in and login pages) and the account
119
+ * pages call this on load. Each failure is answered once: a second call before the strip lands
120
+ * answers `null`. An app that starts a redirect-mode
121
+ * attempt from some other page calls it there (or in its shell) to show the failure.
122
+ */
123
+ takeExternalLoginResult(): SparkExternalLoginError | null;
124
+ /** The URL whose `sparkExternalLogin` {@link takeExternalLoginResult} already took, until the strip lands. */
125
+ private externalLoginResultTakenFrom;
126
+ /**
127
+ * The in-app URL of this page (path and query, as the router sees it) with any earlier
128
+ * `sparkExternalLogin` removed, so a second failure does not stack onto the first one's code.
129
+ * Falls back to `location` when no router is provided.
130
+ */
131
+ private currentUrlForExternalLoginError;
132
+ /**
133
+ * The full-page navigation of a redirect-mode attempt. Its own method only so a unit test can
134
+ * observe the URL: jsdom locks `window.location.assign` against redefinition.
135
+ */
136
+ private leaveForProvider;
137
+ private externalFlow;
138
+ forgotPassword(email: string): Promise<void>;
139
+ resetPassword(email: string, resetCode: string, newPassword: string): Promise<void>;
140
+ /** `POST /confirm-email` — the query of a mailed confirmation link (a changed email too). */
141
+ confirmEmail(userId: string, code: string, changedEmail?: string | null): Promise<SparkAccountResult>;
142
+ /** `POST /manage/password` — change it (`currentPassword` required when the account has one) or set a first one. */
143
+ setPassword(newPassword: string, currentPassword?: string | null): Promise<SparkAccountResult>;
144
+ /** `GET /manage/info` — the email and whether it is confirmed. */
145
+ accountInfo(): Promise<SparkAccountResult<SparkAccountInfo>>;
146
+ /**
147
+ * `POST /manage/info { newEmail }` — mails a confirmation link to the NEW address; nothing changes
148
+ * until it is followed (the confirm-email page completes it).
149
+ */
150
+ changeEmail(newEmail: string): Promise<SparkAccountResult<SparkAccountInfo>>;
151
+ /** `GET /manage/profile`. */
152
+ profile(): Promise<SparkAccountResult<SparkAccountProfile>>;
153
+ /** `POST /manage/profile` — answers the saved profile, or field errors. */
154
+ updateProfile(update: SparkAccountProfileUpdate): Promise<SparkAccountResult<SparkAccountProfile>>;
155
+ /** `POST /manage/2fa` (Identity's) — an empty request reads the state and creates a key when none exists. */
156
+ twoFactor(request?: SparkTwoFactorRequest): Promise<SparkAccountResult<SparkTwoFactorState>>;
157
+ /** `GET /manage/2fa/authenticator-uri` — 409 `no_authenticator_key` until {@link twoFactor} created one. */
158
+ authenticatorUri(): Promise<SparkAccountResult<SparkAuthenticatorUri>>;
159
+ /** `GET /manage/external-login-two-factor` — whether an external sign-in skips the second factor. */
160
+ externalLoginTwoFactor(): Promise<SparkAccountResult<SparkExternalLoginTwoFactor>>;
161
+ /**
162
+ * `POST /manage/external-login-two-factor` — turning the bypass on needs a current authenticator
163
+ * `code` (400 when it is not valid); turning it off needs none.
164
+ */
165
+ setExternalLoginTwoFactor(bypass: boolean, code?: string): Promise<SparkAccountResult<SparkExternalLoginTwoFactor>>;
166
+ /** `GET /manage/personal-data` — the account and every contributor's data, as JSON. */
167
+ personalData(): Promise<SparkAccountResult<unknown>>;
168
+ /**
169
+ * `DELETE /manage/account` — re-authenticated by `password`, or by a sign-in younger than the server's
170
+ * `ReauthenticationMaxAge` (5 minutes) when omitted. 403 `reauthentication_required` otherwise. On
171
+ * success the session is gone.
172
+ */
173
+ deleteAccount(password?: string | null): Promise<SparkAccountResult>;
174
+ private accountCall;
175
+ /**
176
+ * Signs in with a passkey.
177
+ *
178
+ * ⚠️ Takes no username, and must not grow one. The server's request-options endpoint refuses to
179
+ * accept an identity precisely so that its response cannot reveal whether an account exists; the
180
+ * browser offers whatever discoverable credential it holds, and the account is resolved from the
181
+ * credential afterwards.
182
+ */
183
+ signInWithPasskey(): Promise<SparkPasskeyResult>;
184
+ /** {@link sparkPasskeyError}; shared with the `webauthn.create` client method. */
185
+ private passkeyError;
186
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkAuthService, never>;
187
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
188
+ }
189
+ export declare class SparkAuthTranslationService {
190
+ private readonly http;
191
+ private readonly translationsMap;
192
+ constructor();
193
+ private loadTranslations;
194
+ t(key: string): string;
195
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkAuthTranslationService, never>;
196
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
197
+ }