@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
@@ -0,0 +1,144 @@
1
+ import * as i0 from "@angular/core";
2
+ import { PipeTransform } from "@angular/core";
3
+ /** One granted scope, with its text in the request's language (`spark-lang` cookie). */
4
+ export interface SparkConnectedScope {
5
+ name: string;
6
+ displayName: string;
7
+ description?: string | null;
8
+ /** `openid`, or a scope the resource or the application marks required: only withdrawable with the whole grant. */
9
+ required: boolean;
10
+ }
11
+ /** One application the signed-in user granted access to (`GET /applications`, PRD D6). */
12
+ export interface SparkConnectedApplication {
13
+ applicationId: string;
14
+ displayName: string;
15
+ logoUrl?: string | null;
16
+ publisher?: string | null;
17
+ homepageUrl?: string | null;
18
+ scopes: SparkConnectedScope[];
19
+ firstGrantedAt: string;
20
+ lastUsedAt?: string | null;
21
+ remembered: boolean;
22
+ rememberedUntil?: string | null;
23
+ }
24
+ /** The body of `POST /applications/withdraw`. No `scopes` withdraws the whole grant. */
25
+ export interface SparkWithdrawAccessRequest {
26
+ applicationId: string;
27
+ scopes?: string[];
28
+ }
29
+ /** The developer statuses the server stores (`OidcDeveloperStatuses`). */
30
+ export type SparkDeveloperStatusName = 'Requested' | 'Approved' | 'Rejected' | 'Revoked';
31
+ /** `GET /developer` and `POST /developer` (`OidcDeveloperStatusResponse`). */
32
+ export interface SparkDeveloperStatus {
33
+ /** Null when the user never asked. */
34
+ status: SparkDeveloperStatusName | string | null;
35
+ acceptedTermsVersion: number | null;
36
+ currentTermsVersion: number;
37
+ termsUrl: string | null;
38
+ requireApproval: boolean;
39
+ isActive: boolean;
40
+ requestedAt: string | null;
41
+ decidedAt: string | null;
42
+ note: string | null;
43
+ }
44
+ /** `POST /developer/registration-token`: an RFC 7591 initial access token, shown once. */
45
+ export interface SparkRegistrationToken {
46
+ initialAccessToken: string;
47
+ /** Seconds. */
48
+ expiresIn: number;
49
+ }
50
+ /** `POST /invitations/accept` (`OidcAcceptInvitationResponse`). */
51
+ export interface SparkInvitationOutcome {
52
+ accepted: boolean;
53
+ application: string | null;
54
+ problem: string | null;
55
+ }
56
+ /** One signing key on the management page (`OidcKeySummary`); never its private material. */
57
+ export interface SparkSigningKey {
58
+ kid: string;
59
+ algorithm: string;
60
+ state: string;
61
+ createdAt: string;
62
+ activatedAt: string | null;
63
+ retiredAt: string | null;
64
+ }
65
+ /** `POST /admin/keys/rotate`. */
66
+ export interface SparkKeyRotation {
67
+ changes: string[];
68
+ }
69
+ /** The outcome of a portal call: the value, or the status and the server's problem text. */
70
+ export type SparkPortalResult<T> = {
71
+ ok: true;
72
+ value: T;
73
+ } | {
74
+ ok: false;
75
+ status: number;
76
+ problem: string | null;
77
+ };
78
+ /** The portal API's prefix (`IdentityProviderPortalGroup.Prefix` on the server). */
79
+ export declare const SPARK_IDENTITY_PROVIDER_API = "/spark/identity-provider";
80
+ /**
81
+ * The identity provider's portal API for the SPA pages (PRD D7). Every call is for a signed-in user;
82
+ * the POSTs require the antiforgery token, which Angular's XSRF support adds from the `XSRF-TOKEN`
83
+ * cookie (`withSparkAuth()` configures it), so the calls are plain `HttpClient` requests.
84
+ *
85
+ * Calls never throw: each resolves to a {@link SparkPortalResult}, so a page branches on `ok` and on
86
+ * the status (403 for a page the user may not see) instead of catching.
87
+ */
88
+ export declare class SparkIdentityProviderPortalService {
89
+ private readonly http;
90
+ connectedApplications(): Promise<SparkPortalResult<SparkConnectedApplication[]>>;
91
+ /** Withdraws the whole grant, or only `scopes` when given. Answers 204, or 409 when it could not. */
92
+ withdraw(request: SparkWithdrawAccessRequest): Promise<SparkPortalResult<null>>;
93
+ developerStatus(): Promise<SparkPortalResult<SparkDeveloperStatus>>;
94
+ /** Accepts the terms version the page showed; the server refuses (409) a version that is no longer current. */
95
+ requestDeveloperStatus(termsVersion: number): Promise<SparkPortalResult<SparkDeveloperStatus>>;
96
+ issueRegistrationToken(): Promise<SparkPortalResult<SparkRegistrationToken>>;
97
+ acceptInvitation(applicationId: string, token: string): Promise<SparkPortalResult<SparkInvitationOutcome>>;
98
+ signingKeys(): Promise<SparkPortalResult<SparkSigningKey[]>>;
99
+ rotateSigningKeys(): Promise<SparkPortalResult<SparkKeyRotation>>;
100
+ private call;
101
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkIdentityProviderPortalService, never>;
102
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
103
+ }
104
+ /**
105
+ * A text function for component code: `private readonly text = injectIdentityProviderText();` then
106
+ * `this.text('apps.withdrawn')`. The texts come from the server's translations in the app's current
107
+ * language, like every other ng-spark page; `{0}`, `{1}` are replaced by the arguments.
108
+ */
109
+ export declare function injectIdentityProviderText(): (key: string, ...args: unknown[]) => string;
110
+ /** `{{ 'apps.title' | idp }}`, `{{ 'apps.by' | idp: publisher }}`. Impure: follows the language and the loaded translations. */
111
+ export declare class SparkIdentityProviderTextPipe implements PipeTransform {
112
+ private readonly translations;
113
+ transform(key: string, ...args: unknown[]): string;
114
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkIdentityProviderTextPipe, never>;
115
+ static ɵpipe: i0.ɵɵPipeDeclaration<SparkIdentityProviderTextPipe, "idp", true>;
116
+ }
117
+ /**
118
+ * A server date (ISO string) as a date and time in the app's current language; empty for null.
119
+ * `Intl` rather than Angular's `DatePipe`, which needs locale data registered for every language.
120
+ */
121
+ export declare function identityProviderDate(value: string | null | undefined): string;
122
+ /** `{{ app.firstGrantedAt | idpDate }}`. Impure: follows the language signal. */
123
+ export declare class SparkIdentityProviderDatePipe implements PipeTransform {
124
+ transform(value: string | null | undefined): string;
125
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkIdentityProviderDatePipe, never>;
126
+ static ɵpipe: i0.ɵɵPipeDeclaration<SparkIdentityProviderDatePipe, "idpDate", true>;
127
+ }
128
+ /**
129
+ * The identity-provider library's queries, by the aliases in its `App_Data/Model/*.json`
130
+ * (`queries[].alias`). They open in the generic query page of `sparkRoutes()`, `/query/:queryId`,
131
+ * which resolves an alias as well as an id. Each lists only what the caller may see.
132
+ */
133
+ export declare const SPARK_IDENTITY_PROVIDER_QUERIES: {
134
+ /** `OidcApplication`: the caller's applications (members-only filter), or all of them for an administrator. */
135
+ readonly applications: "oidc-applications";
136
+ readonly resources: "oidc-resources";
137
+ readonly developerRequests: "oidc-developer-requests";
138
+ readonly scopeApprovals: "oidc-scope-approvals";
139
+ readonly goLiveReviews: "oidc-golive-reviews";
140
+ readonly grants: "oidc-grants";
141
+ readonly auditEvents: "oidc-audit-events";
142
+ };
143
+ /** The router commands that open one of {@link SPARK_IDENTITY_PROVIDER_QUERIES}. */
144
+ export declare function identityProviderQueryLink(alias: string): string[];
@@ -0,0 +1,55 @@
1
+ import { Color } from "@mintplayer/ng-bootstrap";
2
+ import { SparkDeveloperStatus } from "@mintplayer/ng-spark/identity-provider/core";
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * The developer portal's landing page (`/developers`, PRD D2/D7): the user's developer status, the
6
+ * terms to accept to request it (again, when they were raised), and for an active developer a link to
7
+ * their applications (the generic query page, members-only filtered) and a one-time registration
8
+ * token for dynamic client registration (RFC 7591), shown in the same dialog as `showSecret`.
9
+ */
10
+ export declare class SparkDevelopersComponent {
11
+ private readonly text;
12
+ private readonly portal;
13
+ private readonly secrets;
14
+ protected readonly colors: typeof Color;
15
+ protected readonly applicationsLink: string[];
16
+ readonly loading: import("@angular/core").WritableSignal<boolean>;
17
+ readonly busy: import("@angular/core").WritableSignal<boolean>;
18
+ readonly status: import("@angular/core").WritableSignal<SparkDeveloperStatus | null>;
19
+ readonly accepted: import("@angular/core").WritableSignal<boolean>;
20
+ readonly error: import("@angular/core").WritableSignal<string>;
21
+ readonly notice: import("@angular/core").WritableSignal<string>;
22
+ protected readonly statusKey: import("@angular/core").Signal<string>;
23
+ /** A developer (or a pending request) whose accepted terms are older than the current ones. */
24
+ protected readonly termsChanged: import("@angular/core").Signal<boolean>;
25
+ /** Asking (again) is possible unless an administrator revoked the status; the server refuses that too. */
26
+ protected readonly canRequest: import("@angular/core").Signal<boolean>;
27
+ constructor();
28
+ load(): Promise<void>;
29
+ request(): Promise<void>;
30
+ issueToken(): Promise<void>;
31
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkDevelopersComponent, never>;
32
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkDevelopersComponent, "spark-developers", never, {}, {}, never, never, true, never>;
33
+ }
34
+ /**
35
+ * The target of a mailed team invitation (`/developers/invitations/:token?app=<applicationId>`, PRD
36
+ * D3). Accepting is an explicit click, not a side effect of opening the link, and needs the signed-in
37
+ * account the invitation was sent to; every failure reads the same, as the server answers it.
38
+ */
39
+ export declare class SparkAcceptInvitationComponent {
40
+ private readonly portal;
41
+ private readonly route;
42
+ protected readonly colors: typeof Color;
43
+ protected readonly applicationsLink: string[];
44
+ private readonly token;
45
+ private readonly applicationId;
46
+ /** A link without both values cannot be an invitation. */
47
+ protected readonly valid: boolean;
48
+ readonly busy: import("@angular/core").WritableSignal<boolean>;
49
+ readonly failed: import("@angular/core").WritableSignal<boolean>;
50
+ /** The application joined, once accepted. */
51
+ readonly joined: import("@angular/core").WritableSignal<string | null>;
52
+ accept(): Promise<void>;
53
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkAcceptInvitationComponent, never>;
54
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkAcceptInvitationComponent, "spark-accept-invitation", never, {}, {}, never, never, true, never>;
55
+ }
@@ -0,0 +1,33 @@
1
+ import { Color } from "@mintplayer/ng-bootstrap";
2
+ import { SparkSigningKey, identityProviderQueryLink } from "@mintplayer/ng-spark/identity-provider/core";
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * The identity provider's management page (`identity-provider/admin`, PRD D9), for its
6
+ * administrators (`ManageAll/IdentityProvider`): the signing keys with a rotate-now action, and links
7
+ * to the library's queues (developer requests, scope approvals, go-live reviews) and records (grants,
8
+ * the audit trail) in the generic query page. The server answers 403 to anyone else, and the page
9
+ * then says so instead of rendering an empty administration screen.
10
+ */
11
+ export declare class SparkIdentityProviderManagementComponent {
12
+ private readonly text;
13
+ private readonly portal;
14
+ protected readonly colors: typeof Color;
15
+ protected readonly queues: {
16
+ label: string;
17
+ alias: string;
18
+ }[];
19
+ protected readonly queryLink: typeof identityProviderQueryLink;
20
+ readonly loading: import("@angular/core").WritableSignal<boolean>;
21
+ readonly busy: import("@angular/core").WritableSignal<boolean>;
22
+ readonly forbidden: import("@angular/core").WritableSignal<boolean>;
23
+ readonly keys: import("@angular/core").WritableSignal<SparkSigningKey[]>;
24
+ readonly changes: import("@angular/core").WritableSignal<string[]>;
25
+ readonly error: import("@angular/core").WritableSignal<string>;
26
+ readonly notice: import("@angular/core").WritableSignal<string>;
27
+ constructor();
28
+ load(): Promise<void>;
29
+ rotate(): Promise<void>;
30
+ protected stateColor(state: string): Color;
31
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkIdentityProviderManagementComponent, never>;
32
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkIdentityProviderManagementComponent, "spark-identity-provider-management", never, {}, {}, never, never, true, never>;
33
+ }
@@ -0,0 +1,64 @@
1
+ import { CanActivateFn } from "@angular/router";
2
+ import { SparkAccountOverviewLink, SparkAuthRouteEntry, SparkAuthRoutePaths } from "@mintplayer/ng-spark/auth/models";
3
+ import { SparkAuthRoutesFeature } from "@mintplayer/ng-spark/auth/routes";
4
+ export * from "@mintplayer/ng-spark/identity-provider/core";
5
+ type Child = SparkAuthRoutesFeature['children'][number];
6
+ /**
7
+ * One group of identity-provider pages, passed to {@link withIdentityProvider}. Produced only by
8
+ * `withConnectedApplications()`, `withDeveloperRoutes()` and `withManagementRoutes()`.
9
+ */
10
+ export interface SparkIdentityProviderRoutesFeature {
11
+ readonly children: Child[];
12
+ readonly paths: SparkAuthRoutePaths;
13
+ readonly accountLinks?: SparkAccountOverviewLink[];
14
+ }
15
+ /** Every feature's guard option: defaults to `[sparkAuthGuard]`; `[]` under an already guarded parent. */
16
+ export interface SparkIdentityProviderGuardOptions {
17
+ canActivate?: CanActivateFn[];
18
+ }
19
+ /**
20
+ * The identity provider's SPA pages (`docs/identity_provider_platform_PRD.md` D7), as one
21
+ * `sparkAuthRoutes()` feature:
22
+ *
23
+ * ```ts
24
+ * sparkAuthRoutes(
25
+ * withLocalLogin(), withAccount(),
26
+ * withIdentityProvider(withConnectedApplications(), withDeveloperRoutes(), withManagementRoutes()),
27
+ * )
28
+ * ```
29
+ *
30
+ * The sub-features merge into one feature, and each page keeps its own `import()` (its own secondary
31
+ * entry point), so a page nobody opts into is never bundled. The pages popups show (`/connect/*`:
32
+ * sign-in, consent, device, logout, error) are server-rendered and not part of this.
33
+ *
34
+ * Every path has a literal first segment, so the group neither shadows `sparkRoutes()` nor is shadowed
35
+ * by it. Apps and resources are edited in the generic `po/:type` screens (PRD Q1 = A).
36
+ */
37
+ export declare function withIdentityProvider(...features: SparkIdentityProviderRoutesFeature[]): SparkAuthRoutesFeature;
38
+ /**
39
+ * Mounts the connected-applications page (default `account/applications`, PRD D6): the applications
40
+ * the user granted access to, with whole-grant and per-scope withdrawal. Sets
41
+ * `SPARK_AUTH_ROUTE_PATHS.connectedApplications` and adds a link to the account overview.
42
+ */
43
+ export declare function withConnectedApplications(options?: SparkIdentityProviderGuardOptions & {
44
+ connectedApplications?: SparkAuthRouteEntry;
45
+ }): SparkIdentityProviderRoutesFeature;
46
+ /**
47
+ * Mounts the developer portal (PRD D2/D3): `developers` (status, terms, request, registration token)
48
+ * and `developers/invitations/:token?app=<applicationId>` (accept a team invitation; the mailed link's
49
+ * target, which the server builds from this default path). Both need a signed-in user; the guard sends
50
+ * anyone else to sign in and back.
51
+ */
52
+ export declare function withDeveloperRoutes(options?: SparkIdentityProviderGuardOptions & {
53
+ developers?: SparkAuthRouteEntry;
54
+ invitation?: SparkAuthRouteEntry;
55
+ }): SparkIdentityProviderRoutesFeature;
56
+ /**
57
+ * Mounts the management page (default `identity-provider/admin`, PRD D9): signing keys with
58
+ * rotate-now, and links to the queues (developer requests, scope approvals, go-live reviews) and
59
+ * records (applications, resources, grants, audit trail). Mount it for everyone signed in: the server
60
+ * decides who is an administrator, and the page tells anyone else they may not see it.
61
+ */
62
+ export declare function withManagementRoutes(options?: SparkIdentityProviderGuardOptions & {
63
+ identityProviderManagement?: SparkAuthRouteEntry;
64
+ }): SparkIdentityProviderRoutesFeature;
@@ -169,6 +169,12 @@ export interface CustomActionDefinition {
169
169
  * `/po/new`, the edit page and `/po/delete-many`, never `/actions/execute`. Absent for a custom action.
170
170
  */
171
171
  isDefault?: boolean;
172
+ /**
173
+ * The client method the action needs in the browser (`provideSparkClientMethods`), e.g.
174
+ * `'webauthn.create'`. When it is not registered, or its `supported()` says no, the action is shown
175
+ * disabled with the reason as its tooltip. Advisory: the server still handles a cancelled step.
176
+ */
177
+ requiresClient?: string;
172
178
  }
173
179
  /**
174
180
  * Whether a grid lets the user tick rows — what `<bs-datatable>` renders. There is no single
@@ -665,19 +671,41 @@ export interface LookupReferenceValue {
665
671
  isActive: boolean;
666
672
  extra?: Record<string, unknown>;
667
673
  }
674
+ /**
675
+ * The option a cancelled retry step answers with (`RetryResult.CancelOption` on the server): the
676
+ * modal's own Cancel button or its dismissal on a `cancellable` prompt, and a client method that did
677
+ * not answer. An identifier, never a label: the button shows `common.cancel` in the user's language.
678
+ */
679
+ export declare const SPARK_RETRY_CANCEL = "Cancel";
668
680
  export interface RetryActionPayload {
669
681
  type: 'retry-action';
670
682
  step: number;
671
683
  title: string;
672
684
  message?: string;
685
+ /** The action's own options, shown as given. Never `'Cancel'`: see {@link cancellable}. */
673
686
  options: string[];
674
687
  defaultOption?: string;
675
688
  persistentObject?: PersistentObject;
689
+ /**
690
+ * Whether the modal adds its own Cancel button, labelled `common.cancel`, which, like closing the
691
+ * modal, answers {@link SPARK_RETRY_CANCEL}. Without it a closed modal abandons the request.
692
+ */
693
+ cancellable?: boolean;
694
+ /**
695
+ * Set when the server asks for a client method (`IRetryAccessor.Invoke`) instead of a choice: the
696
+ * name a method was registered under with `provideSparkClientMethods`. No modal is shown then.
697
+ */
698
+ clientMethod?: string;
699
+ /** The client method's argument, as the server serialized it. */
700
+ arguments?: unknown;
676
701
  }
677
702
  export interface RetryActionResult {
678
703
  step: number;
704
+ /** The option chosen. For a client-method step `'OK'` when it answered, `'Cancel'` otherwise. */
679
705
  option: string;
680
706
  persistentObject?: PersistentObject;
707
+ /** What the client method resolved with; absent for an ordinary prompt and for a cancelled step. */
708
+ value?: unknown;
681
709
  }
682
710
  export interface EntityPermissions {
683
711
  /**
@@ -13,6 +13,7 @@ export declare class SparkPoDetailComponent {
13
13
  private readonly queryRefresh;
14
14
  private readonly attributeRefresh;
15
15
  protected readonly lang: SparkLanguageService;
16
+ private readonly clientMethods;
16
17
  protected readonly rendererRegistry: import("@mintplayer/ng-spark/renderers").SparkAttributeRendererRegistration[];
17
18
  /**
18
19
  * Add-on panels and action-bar buttons (#460, `SPARK_DETAIL_PANELS` / `SPARK_DETAIL_ACTIONS`).
@@ -118,6 +119,8 @@ export declare class SparkPoDetailComponent {
118
119
  resolvedTabs: import("@angular/core").Signal<AttributeTab[]>;
119
120
  groupsForTab(tab: AttributeTab): AttributeGroup[];
120
121
  attrsForGroup(group: AttributeGroup): EntityAttributeDefinition[];
122
+ /** Whether the attribute's renderer asks for the whole row, without a label (`fullWidth`). */
123
+ isFullWidthRenderer(attr: EntityAttributeDefinition): boolean;
121
124
  getDetailRendererComponent(attr: EntityAttributeDefinition): Type<any> | null;
122
125
  /** Inputs of an AsDetail row renderer (`rowComponent`): the row and the object that owns it. */
123
126
  getRowRendererInputs(renderer: SparkResolvedRowRenderer, row: Record<string, any>, item: PersistentObject): Record<string, any>;
@@ -146,6 +149,11 @@ export declare class SparkPoDetailComponent {
146
149
  * a slow action and a broken one became indistinguishable.
147
150
  */
148
151
  runningAction: import("@angular/core").WritableSignal<string | null>;
152
+ /**
153
+ * Why an action cannot run in this browser, translated, for its tooltip: the client method it
154
+ * requires (`requiresClient`) is not registered or not supported here (Q9). Null otherwise.
155
+ */
156
+ protected customActionUnavailableReason(action: CustomActionDefinition): string | null;
149
157
  onCustomAction(action: CustomActionDefinition): Promise<void>;
150
158
  onEdit(): void;
151
159
  onDelete(): Promise<void>;
@@ -516,6 +516,8 @@ export declare class SparkReferencePickerComponent {
516
516
  searchTerm: string;
517
517
  /** The picker lists query rows, so its columns are the query's: `showedOn` includes Query (#264; not None). */
518
518
  visibleAttributes: import("@angular/core").Signal<import("@mintplayer/ng-spark/models").EntityAttributeDefinition[]>;
519
+ /** The resize handle and its options dialog, translated; columns are named by `bsDatatableColumnLabel`. */
520
+ datatableLabels: import("@angular/core").Signal<import("@mintplayer/ng-spark/services").SparkDatatableLabels>;
519
521
  rows: import("@angular/core").Signal<QueryResultItem[]>;
520
522
  displayValue: import("@angular/core").Signal<string>;
521
523
  open(): Promise<void>;
@@ -0,0 +1,89 @@
1
+ import * as i0 from "@angular/core";
2
+ import { EnvironmentProviders, InjectionToken } from "@angular/core";
3
+ import { SwRegistrationOptions } from "@angular/service-worker";
4
+ export interface SparkServiceWorkerOptions {
5
+ /** Whether the worker registers. Default: `!isDevMode()`, so only production builds register it. */
6
+ enabled?: boolean;
7
+ /** The worker script, relative to the base href. Default: `ngsw-worker.js`. */
8
+ script?: string;
9
+ /** When the worker registers. Default: `registerWhenStable:30000`. */
10
+ registrationStrategy?: SwRegistrationOptions['registrationStrategy'];
11
+ }
12
+ /**
13
+ * Registers Angular's service worker with Spark's update policy (#464, Q1b); see
14
+ * {@link SparkServiceWorkerUpdates} for what happens when a new version is deployed.
15
+ *
16
+ * The application also needs an `ngsw-config.json` with Spark's navigation exclusions and
17
+ * `serviceWorker` in its production build configuration; see `docs/guide-pwa.md`.
18
+ */
19
+ export declare function provideSparkServiceWorker(options?: SparkServiceWorkerOptions): EnvironmentProviders;
20
+ /** A service-worker version as `ngsw.json` describes it. `appData` is the config's `appData`. */
21
+ export interface SparkAppVersion {
22
+ hash: string;
23
+ appData?: Record<string, unknown>;
24
+ }
25
+ /** The two page loads the update policy performs. Replaceable for tests. */
26
+ export interface SparkPageLoader {
27
+ assign(url: string): void;
28
+ reload(): void;
29
+ }
30
+ /** How the update policy loads a page: `window.location` by default. */
31
+ export declare const SPARK_SW_PAGE_LOADER: InjectionToken<SparkPageLoader>;
32
+ /** Update-check timing. Defaults: every 6 h, and on becoming visible at most once a minute. */
33
+ export interface SparkServiceWorkerSchedule {
34
+ checkIntervalMs: number;
35
+ visibleCheckThrottleMs: number;
36
+ }
37
+ export declare const SPARK_SW_SCHEDULE: InjectionToken<SparkServiceWorkerSchedule>;
38
+ /**
39
+ * The update policy of `provideSparkServiceWorker()` (#464, Q1b).
40
+ *
41
+ * - `VERSION_READY`: the **next** router navigation becomes a full page load of its target, so the
42
+ * user lands on the page they asked for, in the new version, without losing anything on the page
43
+ * they are leaving (the navigation was leaving it anyway).
44
+ * - `unrecoverable`: the running version can no longer be served, so the page reloads at once.
45
+ * - Checks: once the application is stable, every 6 h, and when the tab becomes visible again
46
+ * (at most once a minute).
47
+ * - **A hidden tab never reloads.** Spark has no unsaved-changes tracking to consult, so a reload
48
+ * nobody is looking at could throw away an open edit. An `unrecoverable` in a hidden tab waits
49
+ * until the tab is visible; a navigation in a hidden tab stays a normal in-app navigation.
50
+ *
51
+ * Nothing happens when the service worker is disabled (development builds, unsupported browsers)
52
+ * or on the server.
53
+ */
54
+ export declare class SparkServiceWorkerUpdates {
55
+ private readonly swUpdate;
56
+ private readonly router;
57
+ private readonly location;
58
+ private readonly appRef;
59
+ private readonly document;
60
+ private readonly platformId;
61
+ private readonly destroyRef;
62
+ private readonly pageLoader;
63
+ private readonly schedule;
64
+ private readonly _updateReady;
65
+ private readonly _currentVersion;
66
+ private readonly _latestVersion;
67
+ /** True once a new version is downloaded and the next navigation will load it. */
68
+ readonly updateReady: import("@angular/core").Signal<boolean>;
69
+ /** The running version, known once an update was reported. */
70
+ readonly currentVersion: import("@angular/core").Signal<SparkAppVersion | null>;
71
+ /** The version the next navigation loads (`appData.build` is the ng-spark version). */
72
+ readonly latestVersion: import("@angular/core").Signal<SparkAppVersion | null>;
73
+ private started;
74
+ private leaving;
75
+ private reloadWhenVisible;
76
+ private lastCheck;
77
+ /** Starts the policy. Idempotent; called by the app initializer `provideSparkServiceWorker()` adds. */
78
+ start(): void;
79
+ private onVersionReady;
80
+ private onUnrecoverable;
81
+ private onNavigationStart;
82
+ private check;
83
+ private reload;
84
+ private isHidden;
85
+ private readReloadedFor;
86
+ private writeReloadedFor;
87
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkServiceWorkerUpdates, never>;
88
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
89
+ }
@@ -85,6 +85,8 @@ export declare class SparkQueryListComponent {
85
85
  protected readonly toolbarActions: import("@angular/core").Signal<SparkQueryToolbarAction[]>;
86
86
  protected toolbarActionClass(action: SparkQueryToolbarAction): string;
87
87
  protected isToolbarActionEnabled(action: SparkQueryToolbarAction): boolean;
88
+ /** The tooltip of an action disabled for want of its client method (`requiresClient`); null otherwise. */
89
+ protected toolbarActionUnavailableReason(action: SparkQueryToolbarAction): string | null;
88
90
  protected runToolbarAction(action: SparkQueryToolbarAction): void;
89
91
  protected isActionEnabled(action: CustomActionDefinition): boolean;
90
92
  isStreaming: import("@angular/core").WritableSignal<boolean>;
@@ -1,3 +1,4 @@
1
+ import * as i0 from "@angular/core";
1
2
  import { InjectionToken, InputSignal, Provider, Type } from "@angular/core";
2
3
  import { EntityAttributeDefinition, EntityType, PersistentObject, PersistentObjectAttribute, QueryResultItem, QueryResultItemValue, SparkCellColumn } from "@mintplayer/ng-spark/models";
3
4
  /**
@@ -136,7 +137,17 @@ export interface SparkAttributeRendererRegistration {
136
137
  * give it, which is the whole reason the renderer itself cannot be used here.
137
138
  */
138
139
  filterLabel?: (value: unknown) => string;
140
+ /**
141
+ * The detail page draws the renderer across the whole row, with no label: for text blocks such
142
+ * as the core `paragraph` renderer, which are body text rather than a labelled value.
143
+ */
144
+ fullWidth?: boolean;
139
145
  }
146
+ /**
147
+ * The renderers ng-spark ships itself, available in every app without registration. An app's own
148
+ * registration of the same name wins (it comes first in the list).
149
+ */
150
+ export declare const sparkCoreRenderers: readonly SparkAttributeRendererRegistration[];
140
151
  export declare const SPARK_ATTRIBUTE_RENDERERS: InjectionToken<SparkAttributeRendererRegistration[]>;
141
152
  /**
142
153
  * Register custom attribute renderers globally.
@@ -148,6 +159,42 @@ export declare const SPARK_ATTRIBUTE_RENDERERS: InjectionToken<SparkAttributeRen
148
159
  * ])
149
160
  */
150
161
  export declare function provideSparkAttributeRenderers(renderers: SparkAttributeRendererRegistration[]): Provider;
162
+ /**
163
+ * The core `paragraph` renderer (generic passkeys page, D5): a read-only string shown as body text,
164
+ * full width and without a label — an explanatory text block on a persistent object, filled from
165
+ * translations by the actions class. Pair it with `showedOn: PersistentObject` so it never becomes a
166
+ * grid column.
167
+ *
168
+ * **Escaped by default.** The value is interpolated, so markup in it is shown as text. A blank line
169
+ * starts a new paragraph and a single newline is a line break.
170
+ *
171
+ * `"rendererOptions": { "sanitize": false }` renders the value as HTML instead, through Angular's
172
+ * `[innerHTML]`, whose sanitizer still strips scripts, event handlers and `javascript:` URLs. There is
173
+ * deliberately no `bypassSecurityTrustHtml` anywhere on this path: the opt-out is "allow markup",
174
+ * never "allow script".
175
+ */
176
+ export declare class SparkParagraphRendererComponent implements SparkAttributeDetailRenderer {
177
+ readonly value: import("@angular/core").InputSignal<any>;
178
+ readonly options: import("@angular/core").InputSignal<Record<string, any> | undefined>;
179
+ protected readonly text: import("@angular/core").Signal<string>;
180
+ /** Only an explicit `false` opts out of escaping; anything else, absent included, escapes. */
181
+ protected readonly asHtml: import("@angular/core").Signal<boolean>;
182
+ /** Paragraphs split on blank lines, each a list of its lines. */
183
+ protected readonly paragraphs: import("@angular/core").Signal<string[][]>;
184
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparkParagraphRendererComponent, never>;
185
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparkParagraphRendererComponent, "spark-paragraph-renderer", never, {
186
+ "value": {
187
+ "alias": "value";
188
+ "required": false;
189
+ "isSignal": true;
190
+ };
191
+ "options": {
192
+ "alias": "options";
193
+ "required": false;
194
+ "isSignal": true;
195
+ };
196
+ }, {}, never, never, true, never>;
197
+ }
151
198
  /** The row renderer of an AsDetail row type, resolved once per type (see `rowComponent`). */
152
199
  export interface SparkResolvedRowRenderer {
153
200
  component: Type<any>;
@@ -15,6 +15,7 @@ export declare class SparkRetryActionModalComponent {
15
15
  protected readonly retryActionService: RetryActionService;
16
16
  private readonly sparkService;
17
17
  colors: typeof Color;
18
+ protected readonly cancel = "Cancel";
18
19
  isOpen: import("@angular/core").Signal<boolean>;
19
20
  /**
20
21
  * EntityType definition for the incoming PO — fetched lazily via SparkService so the
@@ -15,6 +15,8 @@ export declare class RetryActionService {
15
15
  export declare class SparkLanguageService {
16
16
  private readonly http;
17
17
  private readonly config;
18
+ /** Null outside a browser (server-side rendering), where there is no cookie to write. */
19
+ private readonly document;
18
20
  private readonly baseUrl;
19
21
  private readonly currentLang;
20
22
  private readonly translationsMap;
@@ -22,6 +24,14 @@ export declare class SparkLanguageService {
22
24
  readonly languages: import("@angular/core").WritableSignal<Record<string, TranslatedString>>;
23
25
  constructor();
24
26
  private loadCulture;
27
+ /**
28
+ * Mirrors the language into the `spark-lang` cookie, which the server-rendered pages read
29
+ * (`/connect/*` of the identity provider, `ConnectText.CultureCookie`): they cannot see
30
+ * localStorage, and without the cookie a sign-in popup would open in the browser's language
31
+ * rather than the one the user picked in the app. Not `HttpOnly` by nature (script writes it);
32
+ * it carries only a language code, which the server matches against its supported cultures.
33
+ */
34
+ private writeCookie;
25
35
  private loadTranslations;
26
36
  setLanguage(lang: string): void;
27
37
  resolve(ts: TranslatedString | undefined): string;
@@ -102,6 +112,7 @@ export declare class SparkService {
102
112
  */
103
113
  private static readonly MAX_RETRY_DEPTH;
104
114
  private readonly dispatcher;
115
+ private readonly clientMethods;
105
116
  getEntityTypes(): Promise<EntityType[]>;
106
117
  /**
107
118
  * One entity type, shaped by the caller's attribute rights. `purpose` narrows it for one form (#264, G1/G2):
@@ -492,4 +503,29 @@ export declare class SparkReturnNavigationService {
492
503
  listRouteFor(entityTypeName: string): Promise<unknown[] | null>;
493
504
  static ɵfac: i0.ɵɵFactoryDeclaration<SparkReturnNavigationService, never>;
494
505
  static ɵprov: i0.ɵɵInjectableDeclaration<any>;
495
- }
506
+ }
507
+ /** The `<bs-datatable>` strings Spark translates: the column-resize handle and its options dialog. */
508
+ export interface SparkDatatableLabels {
509
+ resizeColumn: (column: string) => string;
510
+ resizeColumnHint: string;
511
+ resizeColumnOptions: (column: string) => string;
512
+ narrowerColumn: (column: string) => string;
513
+ widerColumn: (column: string) => string;
514
+ columnWidth: (px: number) => string;
515
+ fitColumn: string;
516
+ resetColumn: string;
517
+ }
518
+ /**
519
+ * The `[labels]` a Spark `<bs-datatable>` passes so the column-resize handle, its keymap
520
+ * announcement and its resize options dialog (ng-bootstrap 22.22.0 / web-components 2.19.0) speak
521
+ * the viewer's language.
522
+ *
523
+ * The `column` these formatters receive is the column's label: every Spark grid binds
524
+ * `bsDatatableColumnLabel` to the header's translated text (and the row-actions column to
525
+ * "Actions"), so the datatable no longer falls back to the internal name. The keys omitted here
526
+ * keep the web component's English defaults.
527
+ *
528
+ * Every translation is read EAGERLY, so a `computed` that calls this tracks the language and the
529
+ * translation map, and hands the datatable a new object — which re-renders it — when either changes.
530
+ */
531
+ export declare function sparkDatatableLabels(lang: SparkLanguageService): SparkDatatableLabels;
@@ -43,7 +43,7 @@ export declare class SparkShellTopbarStartDirective {
43
43
  /**
44
44
  * Topbar, trailing edge. Default: the language selector (which hides itself when the app has
45
45
  * one language). This is where an auth bar goes — the shell cannot ship one itself, since
46
- * `@mintplayer/ng-spark` does not (and must not) depend on `@mintplayer/ng-spark-auth`.
46
+ * the non-auth entry points of `@mintplayer/ng-spark` do not (and must not) import `@mintplayer/ng-spark/auth/*`.
47
47
  */
48
48
  export declare class SparkShellTopbarEndDirective {
49
49
  readonly templateRef: TemplateRef<unknown>;
@@ -320,7 +320,7 @@ export declare class SparkShellComponent {
320
320
  * instead.
321
321
  *
322
322
  * Because the response is caller-scoped it must be re-fetched when the caller changes: the
323
- * component tracks the optional `SPARK_AUTH_STATE` signal (supplied by ng-spark-auth's
323
+ * component tracks the optional `SPARK_AUTH_STATE` signal (supplied by ng-spark/auth's
324
324
  * `provideSparkAuth()`, or by the app's own auth stack) and reloads on every change. Without a
325
325
  * provider it fetches once. `reloadToken` is the manual escape hatch (any changed value triggers
326
326
  * a reload), and `reload()` the imperative one.