@rapidmx/web-client 0.37.1 → 0.38.1

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 (123) hide show
  1. package/apps/admin/configuration-encryption/index.tsx +17 -0
  2. package/apps/admin/domains/[uid].tsx +17 -4
  3. package/apps/admin/integrations/dns-providers/[uid].tsx +205 -0
  4. package/apps/admin/integrations/dns-providers/index.tsx +164 -0
  5. package/apps/admin/integrations/dns-providers/new/index.tsx +55 -0
  6. package/apps/admin/integrations/dns-resolver/index.tsx +16 -0
  7. package/apps/admin/integrations/giphy/index.tsx +16 -0
  8. package/apps/admin/integrations/index.tsx +31 -0
  9. package/apps/admin/integrations/plugin-registry/index.tsx +16 -0
  10. package/apps/admin/integrations/signing-ca/index.tsx +16 -0
  11. package/apps/admin/integrations/stun/index.tsx +16 -0
  12. package/apps/shared/components/admin/configEncryption/ConfigKeysManager.tsx +529 -0
  13. package/apps/shared/components/admin/configEncryption/keyringParts.ts +37 -0
  14. package/apps/shared/components/admin/diagnostics/DiagnosticsManager.tsx +20 -4
  15. package/apps/shared/components/admin/diagnostics/InformationPanel.tsx +23 -6
  16. package/apps/shared/components/admin/diagnostics/KeyringCard.tsx +144 -0
  17. package/apps/shared/components/admin/diagnostics/SettingsTable.tsx +21 -6
  18. package/apps/shared/components/admin/diagnostics/diagnosticsApi.ts +15 -3
  19. package/apps/shared/components/admin/integrations/DnsProviderForm.tsx +354 -0
  20. package/apps/shared/components/admin/integrations/DnsProviderHosts.tsx +197 -0
  21. package/apps/shared/components/admin/integrations/DnsProviderOperations.tsx +115 -0
  22. package/apps/shared/components/admin/integrations/DnsResolverForm.tsx +61 -0
  23. package/apps/shared/components/admin/integrations/GiphyForm.tsx +59 -0
  24. package/apps/shared/components/admin/integrations/IntegrationSectionForm.tsx +234 -0
  25. package/apps/shared/components/admin/integrations/IntegrationSectionPage.tsx +40 -0
  26. package/apps/shared/components/admin/integrations/IntegrationsLayout.tsx +72 -0
  27. package/apps/shared/components/admin/integrations/PluginRegistryForm.tsx +230 -0
  28. package/apps/shared/components/admin/integrations/SecretField.tsx +91 -0
  29. package/apps/shared/components/admin/integrations/SigningCaForm.tsx +95 -0
  30. package/apps/shared/components/admin/integrations/StunForm.tsx +63 -0
  31. package/apps/shared/components/admin/integrations/dnsProviderParts.tsx +72 -0
  32. package/apps/shared/components/admin/layout/AdminShell.tsx +12 -1
  33. package/apps/shared/components/admin/settings/CopyableValue.tsx +16 -0
  34. package/apps/shared/components/admin/settings/DomainApexTxt.tsx +319 -0
  35. package/apps/shared/components/admin/settings/DomainDkimRotation.tsx +408 -0
  36. package/apps/shared/components/admin/settings/DomainDnsProvider.tsx +147 -0
  37. package/apps/shared/components/admin/settings/DomainDnsSetup.tsx +174 -17
  38. package/apps/shared/components/admin/setup/SetupWizard.tsx +39 -6
  39. package/dist/apps/admin/configuration-encryption/index.d.ts +4 -0
  40. package/dist/apps/admin/configuration-encryption/index.js +7 -0
  41. package/dist/apps/admin/domains/[uid].js +11 -4
  42. package/dist/apps/admin/integrations/dns-providers/[uid].d.ts +7 -0
  43. package/dist/apps/admin/integrations/dns-providers/[uid].js +117 -0
  44. package/dist/apps/admin/integrations/dns-providers/index.d.ts +3 -0
  45. package/dist/apps/admin/integrations/dns-providers/index.js +68 -0
  46. package/dist/apps/admin/integrations/dns-providers/new/index.d.ts +3 -0
  47. package/dist/apps/admin/integrations/dns-providers/new/index.js +31 -0
  48. package/dist/apps/admin/integrations/dns-resolver/index.d.ts +3 -0
  49. package/dist/apps/admin/integrations/dns-resolver/index.js +6 -0
  50. package/dist/apps/admin/integrations/giphy/index.d.ts +3 -0
  51. package/dist/apps/admin/integrations/giphy/index.js +6 -0
  52. package/dist/apps/admin/integrations/index.d.ts +4 -0
  53. package/dist/apps/admin/integrations/index.js +7 -0
  54. package/dist/apps/admin/integrations/plugin-registry/index.d.ts +3 -0
  55. package/dist/apps/admin/integrations/plugin-registry/index.js +6 -0
  56. package/dist/apps/admin/integrations/signing-ca/index.d.ts +3 -0
  57. package/dist/apps/admin/integrations/signing-ca/index.js +6 -0
  58. package/dist/apps/admin/integrations/stun/index.d.ts +3 -0
  59. package/dist/apps/admin/integrations/stun/index.js +6 -0
  60. package/dist/apps/shared/components/admin/configEncryption/ConfigKeysManager.d.ts +9 -0
  61. package/dist/apps/shared/components/admin/configEncryption/ConfigKeysManager.js +187 -0
  62. package/dist/apps/shared/components/admin/configEncryption/keyringParts.d.ts +10 -0
  63. package/dist/apps/shared/components/admin/configEncryption/keyringParts.js +26 -0
  64. package/dist/apps/shared/components/admin/diagnostics/DiagnosticsManager.js +20 -4
  65. package/dist/apps/shared/components/admin/diagnostics/InformationPanel.d.ts +8 -4
  66. package/dist/apps/shared/components/admin/diagnostics/InformationPanel.js +7 -5
  67. package/dist/apps/shared/components/admin/diagnostics/KeyringCard.d.ts +18 -0
  68. package/dist/apps/shared/components/admin/diagnostics/KeyringCard.js +51 -0
  69. package/dist/apps/shared/components/admin/diagnostics/SettingsTable.d.ts +9 -1
  70. package/dist/apps/shared/components/admin/diagnostics/SettingsTable.js +10 -3
  71. package/dist/apps/shared/components/admin/diagnostics/diagnosticsApi.d.ts +13 -3
  72. package/dist/apps/shared/components/admin/integrations/DnsProviderForm.d.ts +17 -0
  73. package/dist/apps/shared/components/admin/integrations/DnsProviderForm.js +147 -0
  74. package/dist/apps/shared/components/admin/integrations/DnsProviderHosts.d.ts +10 -0
  75. package/dist/apps/shared/components/admin/integrations/DnsProviderHosts.js +101 -0
  76. package/dist/apps/shared/components/admin/integrations/DnsProviderOperations.d.ts +8 -0
  77. package/dist/apps/shared/components/admin/integrations/DnsProviderOperations.js +60 -0
  78. package/dist/apps/shared/components/admin/integrations/DnsResolverForm.d.ts +7 -0
  79. package/dist/apps/shared/components/admin/integrations/DnsResolverForm.js +15 -0
  80. package/dist/apps/shared/components/admin/integrations/GiphyForm.d.ts +7 -0
  81. package/dist/apps/shared/components/admin/integrations/GiphyForm.js +11 -0
  82. package/dist/apps/shared/components/admin/integrations/IntegrationSectionForm.d.ts +54 -0
  83. package/dist/apps/shared/components/admin/integrations/IntegrationSectionForm.js +131 -0
  84. package/dist/apps/shared/components/admin/integrations/IntegrationSectionPage.d.ts +12 -0
  85. package/dist/apps/shared/components/admin/integrations/IntegrationSectionPage.js +21 -0
  86. package/dist/apps/shared/components/admin/integrations/IntegrationsLayout.d.ts +14 -0
  87. package/dist/apps/shared/components/admin/integrations/IntegrationsLayout.js +46 -0
  88. package/dist/apps/shared/components/admin/integrations/PluginRegistryForm.d.ts +7 -0
  89. package/dist/apps/shared/components/admin/integrations/PluginRegistryForm.js +90 -0
  90. package/dist/apps/shared/components/admin/integrations/SecretField.d.ts +25 -0
  91. package/dist/apps/shared/components/admin/integrations/SecretField.js +25 -0
  92. package/dist/apps/shared/components/admin/integrations/SigningCaForm.d.ts +7 -0
  93. package/dist/apps/shared/components/admin/integrations/SigningCaForm.js +25 -0
  94. package/dist/apps/shared/components/admin/integrations/StunForm.d.ts +9 -0
  95. package/dist/apps/shared/components/admin/integrations/StunForm.js +26 -0
  96. package/dist/apps/shared/components/admin/integrations/dnsProviderParts.d.ts +28 -0
  97. package/dist/apps/shared/components/admin/integrations/dnsProviderParts.js +43 -0
  98. package/dist/apps/shared/components/admin/layout/AdminShell.d.ts +1 -1
  99. package/dist/apps/shared/components/admin/layout/AdminShell.js +8 -1
  100. package/dist/apps/shared/components/admin/settings/CopyableValue.d.ts +6 -0
  101. package/dist/apps/shared/components/admin/settings/CopyableValue.js +6 -0
  102. package/dist/apps/shared/components/admin/settings/DomainApexTxt.d.ts +13 -0
  103. package/dist/apps/shared/components/admin/settings/DomainApexTxt.js +148 -0
  104. package/dist/apps/shared/components/admin/settings/DomainDkimRotation.d.ts +15 -0
  105. package/dist/apps/shared/components/admin/settings/DomainDkimRotation.js +200 -0
  106. package/dist/apps/shared/components/admin/settings/DomainDnsProvider.d.ts +12 -0
  107. package/dist/apps/shared/components/admin/settings/DomainDnsProvider.js +70 -0
  108. package/dist/apps/shared/components/admin/settings/DomainDnsSetup.d.ts +3 -3
  109. package/dist/apps/shared/components/admin/settings/DomainDnsSetup.js +61 -8
  110. package/dist/apps/shared/components/admin/setup/SetupWizard.js +9 -1
  111. package/dist/lib/admin/configKeysApi.d.ts +96 -0
  112. package/dist/lib/admin/configKeysApi.js +34 -0
  113. package/dist/lib/admin/dnsProvidersApi.d.ts +172 -0
  114. package/dist/lib/admin/dnsProvidersApi.js +70 -0
  115. package/dist/lib/admin/domainsApi.d.ts +116 -1
  116. package/dist/lib/admin/domainsApi.js +33 -0
  117. package/dist/lib/admin/integrationsApi.d.ts +75 -0
  118. package/dist/lib/admin/integrationsApi.js +31 -0
  119. package/lib/admin/configKeysApi.ts +117 -0
  120. package/lib/admin/dnsProvidersApi.ts +241 -0
  121. package/lib/admin/domainsApi.ts +145 -1
  122. package/lib/admin/integrationsApi.ts +107 -0
  123. package/package.json +1 -1
@@ -31,6 +31,24 @@ export interface Domain {
31
31
  /** When set, this domain is a pure alias of the domain named here - it has no mailboxes of its own; mail
32
32
  * addressed to it is delivered to the matching mailbox on the domain it aliases instead. */
33
33
  aliasOf?: string;
34
+ /** Where the domain came from: `"seed"` for one the server added at start-up from the installation's own list, `"console"` for one added through
35
+ * the API. Unset on a domain from before this was recorded, which counts as added through the console. Server-managed. */
36
+ origin?: "seed" | "console" | null;
37
+ /** The DNS provider config (`system/dns-providers`) that publishes this domain's records, `null` or unset for "manual": the administrator adds
38
+ * them by hand. Changes only through `assignDnsProvider()`. */
39
+ dnsProviderUid?: string | null;
40
+ /** Whether RapidMX owns the domain's root TXT records (to publish SPF there) and which other values it keeps in them. Unset means not managed;
41
+ * `keep` and `spf` stay after an opt-out. Changes only through `updateApexTxt()`. */
42
+ apexTxt?: ApexTxtSettings | null;
43
+ /** The DKIM key rotation in progress, if any (`getDkimRotation()` is the console's view of it). Server-managed: changes only through `rotateDkim()`,
44
+ * `cancelDkimRotation()` and `setDkimRotationPaused()`. */
45
+ dkimRotation?: DkimRotationState | null;
46
+ }
47
+
48
+ export interface ApexTxtSettings {
49
+ managed: boolean;
50
+ keep: string[];
51
+ spf?: string;
34
52
  }
35
53
 
36
54
  /** `client`, given by every function below, is an explicit `ApiClient` from `createApiClient()` (e.g. one
@@ -90,7 +108,36 @@ export function verifyDomain(uid: string, client?: ApiClient): Promise<Domain> {
90
108
  return withClient(client, `/mail/domains/${encodeURIComponent(uid)}/verify`, { method: "POST" });
91
109
  }
92
110
 
93
- export type DnsRecordType = "ownership" | "mx" | "spf" | "dkim" | "dmarc" | "openpgpkey_cname" | "autodiscover_cname" | "autodiscover_srv";
111
+ export type DnsRecordType =
112
+ | "ownership"
113
+ | "mx"
114
+ | "spf"
115
+ | "dkim"
116
+ | "dkim_next"
117
+ | "dkim_previous"
118
+ | "dmarc"
119
+ | "openpgpkey_cname"
120
+ | "autodiscover_cname"
121
+ | "autodiscover_srv";
122
+
123
+ /** How a record is published: `published` (the DNS controller applied it and the live lookup sees it), `pending`, `conflict` (a record this deployment
124
+ * doesn't own is there) or `manual` (the administrator adds it, see `DnsManualReason`). */
125
+ export type DnsPublicationState = "published" | "pending" | "conflict" | "manual";
126
+
127
+ /** Why a published record is in conflict: a record of the same type is there that this deployment doesn't own (`not_owned`, which a takeover can
128
+ * overwrite), or records of another type that can't stand next to it (`type_mismatch`: a CNAME wanted where other records are, or other records wanted
129
+ * where a CNAME is), which RapidMX never deletes or takes over and the administrator deletes at their DNS host. */
130
+ export type DnsConflictReason = "not_owned" | "type_mismatch";
131
+
132
+ /** A live record in the way of a published one (`type_mismatch`): its type and its value as text. */
133
+ export interface DnsExistingRecord {
134
+ type: "A" | "AAAA" | "CNAME" | "MX" | "TXT" | "SRV";
135
+ value: string;
136
+ }
137
+
138
+ /** Why a record is `manual`: no provider is assigned, the provider can't hold the record's kind, the name lies outside the provider's zones, or the
139
+ * record belongs to the root TXT set, which RapidMX manages only on the administrator's opt-in. */
140
+ export type DnsManualReason = "no_provider" | "kind_unsupported" | "outside_zones" | "apex_txt_unmanaged";
94
141
 
95
142
  /** One mail-related DNS record this server recommends for a domain, live-checked against real DNS —
96
143
  * purely diagnostic, never mutates anything (unlike `verifyDomain`). The two `autodiscover_*` types are only
@@ -106,8 +153,105 @@ export interface DnsRecordCheck {
106
153
  found: boolean;
107
154
  matches: boolean;
108
155
  actualValue?: string;
156
+ /** Whether, and how, the DNS controller publishes this record. Present only on a server that publishes, and only for a configured record. */
157
+ publication?: DnsPublicationState;
158
+ manualReason?: DnsManualReason;
159
+ /** With `publication: "conflict"`: why. A server that doesn't say means `not_owned`. */
160
+ conflictReason?: DnsConflictReason;
161
+ /** With `conflictReason: "type_mismatch"`: the live records the administrator has to delete. */
162
+ existing?: DnsExistingRecord[];
163
+ /** `ownership` only: the token is (still) at the domain's root, where it lived before `_rapidmx-verify.<domain>`. */
164
+ legacyApex?: boolean;
109
165
  }
110
166
 
111
167
  export function getDnsSetup(uid: string, client?: ApiClient): Promise<DnsRecordCheck[]> {
112
168
  return withClient(client, `/mail/domains/${encodeURIComponent(uid)}/dns-setup`);
113
169
  }
170
+
171
+ /** Assigns the domain to a DNS provider config, or back to manual (`null`). Needs an elevated token; the provider must cover the domain more specifically
172
+ * than any other (a 400 otherwise). Answers the domain. */
173
+ export function assignDnsProvider(uid: string, dnsProviderUid: string | null, client?: ApiClient): Promise<Domain> {
174
+ return withClient(client, `/mail/domains/${encodeURIComponent(uid)}/dns-provider`, {
175
+ method: "PUT",
176
+ body: JSON.stringify({ dnsProviderUid }),
177
+ });
178
+ }
179
+
180
+ /** What `GET /:id/apex-txt` answers: the managed state and what the opt-in form starts from. */
181
+ export interface ApexTxtView {
182
+ managed: boolean;
183
+ keep: string[];
184
+ spf?: string;
185
+ /** The values at the domain's root now, as a live lookup sees them. */
186
+ current: string[];
187
+ /** `current` without SPF records and RapidMX ownership tokens: what the list of values to keep starts as. */
188
+ suggestedKeep: string[];
189
+ /** The lookup couldn't be answered, so `current` and `suggestedKeep` say nothing about what is there: the opt-in must not be offered. */
190
+ lookupFailed?: true;
191
+ }
192
+
193
+ export function getApexTxt(uid: string, client?: ApiClient): Promise<ApexTxtView> {
194
+ return withClient(client, `/mail/domains/${encodeURIComponent(uid)}/apex-txt`);
195
+ }
196
+
197
+ /** Opts the domain's root TXT records into RapidMX's management (`managed: true` with the values to keep), edits the kept values while managed, or
198
+ * opts out (`managed: false`). Needs an elevated token. Answers the domain. */
199
+ export function updateApexTxt(uid: string, input: { managed: boolean; keep?: string[] }, client?: ApiClient): Promise<Domain> {
200
+ return withClient(client, `/mail/domains/${encodeURIComponent(uid)}/apex-txt`, { method: "PUT", body: JSON.stringify(input) });
201
+ }
202
+
203
+ /** Why a DKIM key rotation began: the schedule, an administrator's "Rotate now", or a key reported compromised (no publish wait, no overlap). */
204
+ export type DkimRotationReason = "scheduled" | "manual" | "compromised";
205
+
206
+ /** A domain's DKIM key rotation, as `Domain.dkimRotation` holds it. `idle`: none in progress. `pending`: the new key (`next`, whose `publicKey` is `""`
207
+ * until it is generated) is published and signing waits for it to be live (`liveSince`) and the publish wait to pass. `switching`: signing switched to the
208
+ * new key (`switchedAt`) and the mail server hasn't confirmed it yet. `overlap`: confirmed; the old key (`previous`) stays published until its
209
+ * `retireAt`. */
210
+ export interface DkimRotationState {
211
+ phase: "idle" | "pending" | "switching" | "overlap";
212
+ next?: { selector: string; publicKey: string; createdAt: string; liveSince?: string; reason: DkimRotationReason };
213
+ previous?: { selector: string; publicKey: string; retireAt?: string };
214
+ /** The reason of the rotation that switched, kept until it is retired. */
215
+ reason?: DkimRotationReason;
216
+ switchedAt?: string;
217
+ lastRotatedAt?: string;
218
+ lastCancelledAt?: string;
219
+ /** Scheduled rotation is paused for this domain. */
220
+ paused?: boolean;
221
+ /** What is holding the rotation up: no confirmation from the mail server, a key that couldn't be generated. */
222
+ lastError?: string;
223
+ }
224
+
225
+ /** Why a domain's key can't rotate: the key provider doesn't rotate, outbound mail is signed by SES, the domain has no key yet, or its key was imported by
226
+ * hand or can't be told from one. */
227
+ export type DkimRotationBlocker = "unsupported" | "ses" | "no_key" | "imported" | "unknown_key";
228
+
229
+ /** What `GET /:id/dkim/rotation` answers. */
230
+ export interface DkimRotationView {
231
+ rotation: DkimRotationState | null;
232
+ rotatable: boolean;
233
+ blocker?: DkimRotationBlocker;
234
+ /** When the next scheduled rotation starts; only while none is in progress, the domain isn't paused and scheduled rotation is on. */
235
+ nextScheduledAt?: string;
236
+ }
237
+
238
+ export function getDkimRotation(uid: string, client?: ApiClient): Promise<DkimRotationView> {
239
+ return withClient(client, `/mail/domains/${encodeURIComponent(uid)}/dkim/rotation`);
240
+ }
241
+
242
+ /** Starts a rotation of the domain's DKIM key ("Rotate now"). With `compromised`, the publish wait and the overlap are skipped, and during a rotation it
243
+ * reports the key being replaced as compromised. Needs an elevated token. Answers the domain. */
244
+ export function rotateDkim(uid: string, input: { compromised?: boolean } = {}, client?: ApiClient): Promise<Domain> {
245
+ return withClient(client, `/mail/domains/${encodeURIComponent(uid)}/dkim/rotate`, { method: "POST", body: JSON.stringify(input) });
246
+ }
247
+
248
+ /** Abandons a rotation the mail server hasn't confirmed (a switch not yet confirmed is reverted); a 409 once it has. Needs an elevated token. Answers the
249
+ * domain. */
250
+ export function cancelDkimRotation(uid: string, client?: ApiClient): Promise<Domain> {
251
+ return withClient(client, `/mail/domains/${encodeURIComponent(uid)}/dkim/rotation/cancel`, { method: "POST" });
252
+ }
253
+
254
+ /** Pauses or resumes scheduled rotation for the domain; a rotation in progress still finishes. Needs an elevated token. Answers the domain. */
255
+ export function setDkimRotationPaused(uid: string, paused: boolean, client?: ApiClient): Promise<Domain> {
256
+ return withClient(client, `/mail/domains/${encodeURIComponent(uid)}/dkim/rotation`, { method: "PUT", body: JSON.stringify({ paused }) });
257
+ }
@@ -0,0 +1,107 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ /**
6
+ * Typed wrappers over `@rapidmx/restapi`'s `BaseIntegrationsRoute` (mounted at `system/integrations`): the third-party services an administrator
7
+ * chooses (Giphy, STUN, the S/MIME signing CA, the DNS resolver, the plugin registry), each section overriding some of the deployment's configuration.
8
+ * `GET` needs a trusted role; every write a trusted role and an elevated token. Secrets are write-only: the server answers them only as the mask.
9
+ */
10
+ import { ApiClient, withClient } from "../util/api.js";
11
+
12
+ /** What the server shows in place of a secret that is set (restapi `SecretMask`); sent back, it means "keep the saved value". `unreadable` is the
13
+ * server saying that this copy can't decrypt it (a key missing from its keyring, after a restore with an older one): never sent back. */
14
+ export interface SecretMask {
15
+ secret: true;
16
+ unreadable?: boolean;
17
+ }
18
+
19
+ /** Whether `value` is the mask: an object whose keys are `secret`, set to `true`, and at most `unreadable`, a flag. */
20
+ export function isSecretMask(value: unknown): value is SecretMask {
21
+ if (typeof value !== "object" || value === null || (value as SecretMask).secret !== true) {
22
+ return false;
23
+ }
24
+ const unreadable: unknown = (value as SecretMask).unreadable;
25
+ return Object.keys(value).length === (unreadable === undefined ? 1 : 2) && (unreadable === undefined || typeof unreadable === "boolean");
26
+ }
27
+
28
+ /** Whether `value` is the mask of a secret that is set but that the server can't read: it must be entered again. */
29
+ export function isUnreadableSecret(value: unknown): boolean {
30
+ return isSecretMask(value) && value.unreadable === true;
31
+ }
32
+
33
+ export type IntegrationSectionName = "giphy" | "stun" | "signingCa" | "dnsResolver" | "pluginRegistry";
34
+
35
+ /** Where a field's value comes from: saved by an administrator here, or the deployment's configuration. */
36
+ export type IntegrationSource = "admin" | "deployment";
37
+
38
+ /** One section as the server shows it (restapi `IntegrationSectionView`): the values in effect, the deployment's own values (what a reset puts a field
39
+ * back to) and where each value comes from. A secret is the mask when set, else `null`. */
40
+ export interface IntegrationSectionView<V> {
41
+ values: V;
42
+ defaults: V;
43
+ source: Record<keyof V, IntegrationSource>;
44
+ }
45
+
46
+ export interface GiphyIntegration {
47
+ enabled: boolean;
48
+ apiKey: SecretMask | null;
49
+ }
50
+
51
+ export interface StunIntegration {
52
+ /** `null`: the meet plugin's built-in list. */
53
+ urls: string[] | null;
54
+ }
55
+
56
+ export type SigningCaBackend = "rfc8823" | "manual" | "none";
57
+
58
+ export interface SigningCaIntegration {
59
+ backend: SigningCaBackend;
60
+ directoryUrl: string;
61
+ contactEmail: string | null;
62
+ }
63
+
64
+ export type DnsResolverMode = "node" | "doh-dnssec";
65
+
66
+ export interface DnsResolverIntegration {
67
+ mode: DnsResolverMode;
68
+ dohEndpoint: string;
69
+ }
70
+
71
+ /** A plugin namespace as the view shows it: its token only as the mask. Sent back, `token` is the mask (keep), a new value, or left out (none). */
72
+ export interface IntegrationPluginNamespace {
73
+ name: string;
74
+ registry?: string;
75
+ token?: SecretMask | string;
76
+ }
77
+
78
+ export interface PluginRegistryIntegration {
79
+ url: string;
80
+ token: SecretMask | null;
81
+ namespaces: IntegrationPluginNamespace[];
82
+ }
83
+
84
+ /** What `GET /system/integrations` and every write answer (restapi `IntegrationSettingsResponse`). */
85
+ export interface IntegrationSettings {
86
+ giphy: IntegrationSectionView<GiphyIntegration>;
87
+ stun: IntegrationSectionView<StunIntegration>;
88
+ signingCa: IntegrationSectionView<SigningCaIntegration>;
89
+ dnsResolver: IntegrationSectionView<DnsResolverIntegration>;
90
+ pluginRegistry: IntegrationSectionView<PluginRegistryIntegration>;
91
+ /** The saved settings' version (0 before anything was saved), sent back with a change so one made against an older version is refused (409). */
92
+ version: number;
93
+ }
94
+
95
+ /** A section's change: a field left out is unchanged, `null` puts it back to the deployment's value, a secret sent back as the mask is kept. */
96
+ export type IntegrationSectionPatch = Record<string, unknown> & { version?: number };
97
+
98
+ /** `client`, given by every function below, is an explicit `ApiClient` from `createApiClient()` (e.g. one
99
+ * account of a multi-account app) to call instead of the default global `apiFetch()` - see `withClient()`'s
100
+ * own doc comment in `util/api.ts`. Omitted (the default), every function here behaves exactly as before. */
101
+ export function getIntegrations(client?: ApiClient): Promise<IntegrationSettings> {
102
+ return withClient(client, "/system/integrations");
103
+ }
104
+
105
+ export function updateIntegrationSection(section: IntegrationSectionName, patch: IntegrationSectionPatch, client?: ApiClient): Promise<IntegrationSettings> {
106
+ return withClient(client, `/system/integrations/${section}`, { method: "PUT", body: JSON.stringify(patch) });
107
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rapidmx/web-client",
3
- "version": "0.37.1",
3
+ "version": "0.38.1",
4
4
  "description": "RapidMX's webmail and admin console React UI for web-based clients.",
5
5
  "type": "module",
6
6
  "repository": "https://github.com/rapidmx/web-client",