@portaidentity/cli 1.7.3 → 1.8.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 (328) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +125 -105
  3. package/dist/admin/admin-date-time.d.ts +6 -0
  4. package/dist/admin/admin-date-time.d.ts.map +1 -0
  5. package/dist/admin/admin-date-time.js +33 -0
  6. package/dist/admin/admin-date-time.js.map +1 -0
  7. package/dist/admin/application-client-features.d.ts +38 -0
  8. package/dist/admin/application-client-features.d.ts.map +1 -0
  9. package/dist/admin/application-client-features.js +545 -0
  10. package/dist/admin/application-client-features.js.map +1 -0
  11. package/dist/admin/application-controller.d.ts +58 -0
  12. package/dist/admin/application-controller.d.ts.map +1 -0
  13. package/dist/admin/application-controller.js +286 -0
  14. package/dist/admin/application-controller.js.map +1 -0
  15. package/dist/admin/application-dialogs.d.ts +91 -0
  16. package/dist/admin/application-dialogs.d.ts.map +1 -0
  17. package/dist/admin/application-dialogs.js +250 -0
  18. package/dist/admin/application-dialogs.js.map +1 -0
  19. package/dist/admin/application-rbac-controller.d.ts +56 -0
  20. package/dist/admin/application-rbac-controller.d.ts.map +1 -0
  21. package/dist/admin/application-rbac-controller.js +280 -0
  22. package/dist/admin/application-rbac-controller.js.map +1 -0
  23. package/dist/admin/application-rbac-features.d.ts +51 -0
  24. package/dist/admin/application-rbac-features.d.ts.map +1 -0
  25. package/dist/admin/application-rbac-features.js +175 -0
  26. package/dist/admin/application-rbac-features.js.map +1 -0
  27. package/dist/admin/application-rbac-workspace.d.ts +62 -0
  28. package/dist/admin/application-rbac-workspace.d.ts.map +1 -0
  29. package/dist/admin/application-rbac-workspace.js +344 -0
  30. package/dist/admin/application-rbac-workspace.js.map +1 -0
  31. package/dist/admin/application-runtime.d.ts +44 -0
  32. package/dist/admin/application-runtime.d.ts.map +1 -0
  33. package/dist/admin/application-runtime.js +183 -0
  34. package/dist/admin/application-runtime.js.map +1 -0
  35. package/dist/admin/application-service.d.ts +39 -0
  36. package/dist/admin/application-service.d.ts.map +1 -0
  37. package/dist/admin/application-service.js +248 -0
  38. package/dist/admin/application-service.js.map +1 -0
  39. package/dist/admin/application-state.d.ts +109 -0
  40. package/dist/admin/application-state.d.ts.map +1 -0
  41. package/dist/admin/application-state.js +3 -0
  42. package/dist/admin/application-state.js.map +1 -0
  43. package/dist/admin/application-workspace.d.ts +77 -0
  44. package/dist/admin/application-workspace.d.ts.map +1 -0
  45. package/dist/admin/application-workspace.js +302 -0
  46. package/dist/admin/application-workspace.js.map +1 -0
  47. package/dist/admin/application.d.ts +88 -0
  48. package/dist/admin/application.d.ts.map +1 -0
  49. package/dist/admin/application.js +932 -0
  50. package/dist/admin/application.js.map +1 -0
  51. package/dist/admin/client-authentication-dialog.d.ts +77 -0
  52. package/dist/admin/client-authentication-dialog.d.ts.map +1 -0
  53. package/dist/admin/client-authentication-dialog.js +217 -0
  54. package/dist/admin/client-authentication-dialog.js.map +1 -0
  55. package/dist/admin/client-controller.d.ts +58 -0
  56. package/dist/admin/client-controller.d.ts.map +1 -0
  57. package/dist/admin/client-controller.js +462 -0
  58. package/dist/admin/client-controller.js.map +1 -0
  59. package/dist/admin/client-credential-dialogs.d.ts +36 -0
  60. package/dist/admin/client-credential-dialogs.d.ts.map +1 -0
  61. package/dist/admin/client-credential-dialogs.js +145 -0
  62. package/dist/admin/client-credential-dialogs.js.map +1 -0
  63. package/dist/admin/client-dialogs.d.ts +64 -0
  64. package/dist/admin/client-dialogs.d.ts.map +1 -0
  65. package/dist/admin/client-dialogs.js +110 -0
  66. package/dist/admin/client-dialogs.js.map +1 -0
  67. package/dist/admin/client-form-scroller.d.ts +17 -0
  68. package/dist/admin/client-form-scroller.d.ts.map +1 -0
  69. package/dist/admin/client-form-scroller.js +67 -0
  70. package/dist/admin/client-form-scroller.js.map +1 -0
  71. package/dist/admin/client-registration-dialog.d.ts +27 -0
  72. package/dist/admin/client-registration-dialog.d.ts.map +1 -0
  73. package/dist/admin/client-registration-dialog.js +195 -0
  74. package/dist/admin/client-registration-dialog.js.map +1 -0
  75. package/dist/admin/client-service.d.ts +41 -0
  76. package/dist/admin/client-service.d.ts.map +1 -0
  77. package/dist/admin/client-service.js +484 -0
  78. package/dist/admin/client-service.js.map +1 -0
  79. package/dist/admin/client-state.d.ts +157 -0
  80. package/dist/admin/client-state.d.ts.map +1 -0
  81. package/dist/admin/client-state.js +3 -0
  82. package/dist/admin/client-state.js.map +1 -0
  83. package/dist/admin/client-workspace.d.ts +88 -0
  84. package/dist/admin/client-workspace.d.ts.map +1 -0
  85. package/dist/admin/client-workspace.js +484 -0
  86. package/dist/admin/client-workspace.js.map +1 -0
  87. package/dist/admin/delete-confirmation-layout.d.ts +38 -0
  88. package/dist/admin/delete-confirmation-layout.d.ts.map +1 -0
  89. package/dist/admin/delete-confirmation-layout.js +52 -0
  90. package/dist/admin/delete-confirmation-layout.js.map +1 -0
  91. package/dist/admin/index.d.ts +64 -0
  92. package/dist/admin/index.d.ts.map +1 -0
  93. package/dist/admin/index.js +31 -0
  94. package/dist/admin/index.js.map +1 -0
  95. package/dist/admin/organization-controller.d.ts +77 -0
  96. package/dist/admin/organization-controller.d.ts.map +1 -0
  97. package/dist/admin/organization-controller.js +472 -0
  98. package/dist/admin/organization-controller.js.map +1 -0
  99. package/dist/admin/organization-dialogs.d.ts +63 -0
  100. package/dist/admin/organization-dialogs.d.ts.map +1 -0
  101. package/dist/admin/organization-dialogs.js +303 -0
  102. package/dist/admin/organization-dialogs.js.map +1 -0
  103. package/dist/admin/organization-service.d.ts +110 -0
  104. package/dist/admin/organization-service.d.ts.map +1 -0
  105. package/dist/admin/organization-service.js +548 -0
  106. package/dist/admin/organization-service.js.map +1 -0
  107. package/dist/admin/organization-workspace.d.ts +29 -0
  108. package/dist/admin/organization-workspace.d.ts.map +1 -0
  109. package/dist/admin/organization-workspace.js +421 -0
  110. package/dist/admin/organization-workspace.js.map +1 -0
  111. package/dist/admin/portability-controller.d.ts +83 -0
  112. package/dist/admin/portability-controller.d.ts.map +1 -0
  113. package/dist/admin/portability-controller.js +466 -0
  114. package/dist/admin/portability-controller.js.map +1 -0
  115. package/dist/admin/portability-service.d.ts +31 -0
  116. package/dist/admin/portability-service.d.ts.map +1 -0
  117. package/dist/admin/portability-service.js +51 -0
  118. package/dist/admin/portability-service.js.map +1 -0
  119. package/dist/admin/portability-state.d.ts +88 -0
  120. package/dist/admin/portability-state.d.ts.map +1 -0
  121. package/dist/admin/portability-state.js +3 -0
  122. package/dist/admin/portability-state.js.map +1 -0
  123. package/dist/admin/portability-workspace.d.ts +78 -0
  124. package/dist/admin/portability-workspace.d.ts.map +1 -0
  125. package/dist/admin/portability-workspace.js +337 -0
  126. package/dist/admin/portability-workspace.js.map +1 -0
  127. package/dist/admin/presentation.d.ts +46 -0
  128. package/dist/admin/presentation.d.ts.map +1 -0
  129. package/dist/admin/presentation.js +271 -0
  130. package/dist/admin/presentation.js.map +1 -0
  131. package/dist/admin/rbac-dialogs.d.ts +73 -0
  132. package/dist/admin/rbac-dialogs.d.ts.map +1 -0
  133. package/dist/admin/rbac-dialogs.js +345 -0
  134. package/dist/admin/rbac-dialogs.js.map +1 -0
  135. package/dist/admin/rbac-service.d.ts +47 -0
  136. package/dist/admin/rbac-service.d.ts.map +1 -0
  137. package/dist/admin/rbac-service.js +258 -0
  138. package/dist/admin/rbac-service.js.map +1 -0
  139. package/dist/admin/rbac-state.d.ts +129 -0
  140. package/dist/admin/rbac-state.d.ts.map +1 -0
  141. package/dist/admin/rbac-state.js +136 -0
  142. package/dist/admin/rbac-state.js.map +1 -0
  143. package/dist/admin/selectable-read-only-input.d.ts +18 -0
  144. package/dist/admin/selectable-read-only-input.d.ts.map +1 -0
  145. package/dist/admin/selectable-read-only-input.js +24 -0
  146. package/dist/admin/selectable-read-only-input.js.map +1 -0
  147. package/dist/admin/session-service.d.ts +169 -0
  148. package/dist/admin/session-service.d.ts.map +1 -0
  149. package/dist/admin/session-service.js +353 -0
  150. package/dist/admin/session-service.js.map +1 -0
  151. package/dist/admin/state.d.ts +301 -0
  152. package/dist/admin/state.d.ts.map +1 -0
  153. package/dist/admin/state.js +10 -0
  154. package/dist/admin/state.js.map +1 -0
  155. package/dist/admin/system-config-controller.d.ts +58 -0
  156. package/dist/admin/system-config-controller.d.ts.map +1 -0
  157. package/dist/admin/system-config-controller.js +218 -0
  158. package/dist/admin/system-config-controller.js.map +1 -0
  159. package/dist/admin/system-config-service.d.ts +54 -0
  160. package/dist/admin/system-config-service.d.ts.map +1 -0
  161. package/dist/admin/system-config-service.js +180 -0
  162. package/dist/admin/system-config-service.js.map +1 -0
  163. package/dist/admin/system-config-state.d.ts +77 -0
  164. package/dist/admin/system-config-state.d.ts.map +1 -0
  165. package/dist/admin/system-config-state.js +78 -0
  166. package/dist/admin/system-config-state.js.map +1 -0
  167. package/dist/admin/system-config-workspace.d.ts +47 -0
  168. package/dist/admin/system-config-workspace.d.ts.map +1 -0
  169. package/dist/admin/system-config-workspace.js +217 -0
  170. package/dist/admin/system-config-workspace.js.map +1 -0
  171. package/dist/admin/user-controller-types.d.ts +67 -0
  172. package/dist/admin/user-controller-types.d.ts.map +1 -0
  173. package/dist/admin/user-controller-types.js +3 -0
  174. package/dist/admin/user-controller-types.js.map +1 -0
  175. package/dist/admin/user-controller.d.ts +6 -0
  176. package/dist/admin/user-controller.d.ts.map +1 -0
  177. package/dist/admin/user-controller.js +674 -0
  178. package/dist/admin/user-controller.js.map +1 -0
  179. package/dist/admin/user-dialog-fields.d.ts +44 -0
  180. package/dist/admin/user-dialog-fields.d.ts.map +1 -0
  181. package/dist/admin/user-dialog-fields.js +130 -0
  182. package/dist/admin/user-dialog-fields.js.map +1 -0
  183. package/dist/admin/user-dialogs.d.ts +66 -0
  184. package/dist/admin/user-dialogs.d.ts.map +1 -0
  185. package/dist/admin/user-dialogs.js +374 -0
  186. package/dist/admin/user-dialogs.js.map +1 -0
  187. package/dist/admin/user-role-controller.d.ts +82 -0
  188. package/dist/admin/user-role-controller.d.ts.map +1 -0
  189. package/dist/admin/user-role-controller.js +337 -0
  190. package/dist/admin/user-role-controller.js.map +1 -0
  191. package/dist/admin/user-role-dialog.d.ts +94 -0
  192. package/dist/admin/user-role-dialog.d.ts.map +1 -0
  193. package/dist/admin/user-role-dialog.js +265 -0
  194. package/dist/admin/user-role-dialog.js.map +1 -0
  195. package/dist/admin/user-service-types.d.ts +100 -0
  196. package/dist/admin/user-service-types.d.ts.map +1 -0
  197. package/dist/admin/user-service-types.js +3 -0
  198. package/dist/admin/user-service-types.js.map +1 -0
  199. package/dist/admin/user-service.d.ts +14 -0
  200. package/dist/admin/user-service.d.ts.map +1 -0
  201. package/dist/admin/user-service.js +612 -0
  202. package/dist/admin/user-service.js.map +1 -0
  203. package/dist/admin/user-state.d.ts +158 -0
  204. package/dist/admin/user-state.d.ts.map +1 -0
  205. package/dist/admin/user-state.js +3 -0
  206. package/dist/admin/user-state.js.map +1 -0
  207. package/dist/admin/user-workspace.d.ts +65 -0
  208. package/dist/admin/user-workspace.d.ts.map +1 -0
  209. package/dist/admin/user-workspace.js +366 -0
  210. package/dist/admin/user-workspace.js.map +1 -0
  211. package/dist/auth/browser-flow.d.ts +27 -1
  212. package/dist/auth/browser-flow.d.ts.map +1 -1
  213. package/dist/auth/browser-flow.js +55 -33
  214. package/dist/auth/browser-flow.js.map +1 -1
  215. package/dist/auth/callback-server.d.ts.map +1 -1
  216. package/dist/auth/callback-server.js +5 -9
  217. package/dist/auth/callback-server.js.map +1 -1
  218. package/dist/auth/id-token-verifier.d.ts +39 -0
  219. package/dist/auth/id-token-verifier.d.ts.map +1 -0
  220. package/dist/auth/id-token-verifier.js +104 -0
  221. package/dist/auth/id-token-verifier.js.map +1 -0
  222. package/dist/auth/login-coordinator.d.ts +72 -0
  223. package/dist/auth/login-coordinator.d.ts.map +1 -0
  224. package/dist/auth/login-coordinator.js +190 -0
  225. package/dist/auth/login-coordinator.js.map +1 -0
  226. package/dist/auth/metadata.d.ts +2 -1
  227. package/dist/auth/metadata.d.ts.map +1 -1
  228. package/dist/auth/metadata.js +67 -6
  229. package/dist/auth/metadata.js.map +1 -1
  230. package/dist/auth/types.d.ts +14 -0
  231. package/dist/auth/types.d.ts.map +1 -1
  232. package/dist/client-factory.d.ts.map +1 -1
  233. package/dist/client-factory.js +15 -2
  234. package/dist/client-factory.js.map +1 -1
  235. package/dist/commands/admin.d.ts +22 -0
  236. package/dist/commands/admin.d.ts.map +1 -0
  237. package/dist/commands/admin.js +112 -0
  238. package/dist/commands/admin.js.map +1 -0
  239. package/dist/commands/app-claim.d.ts.map +1 -1
  240. package/dist/commands/app-claim.js +11 -4
  241. package/dist/commands/app-claim.js.map +1 -1
  242. package/dist/commands/app-module.d.ts.map +1 -1
  243. package/dist/commands/app-module.js +61 -12
  244. package/dist/commands/app-module.js.map +1 -1
  245. package/dist/commands/app-permission.d.ts.map +1 -1
  246. package/dist/commands/app-permission.js +66 -24
  247. package/dist/commands/app-permission.js.map +1 -1
  248. package/dist/commands/app-role.d.ts.map +1 -1
  249. package/dist/commands/app-role.js +48 -27
  250. package/dist/commands/app-role.js.map +1 -1
  251. package/dist/commands/app.d.ts.map +1 -1
  252. package/dist/commands/app.js +37 -25
  253. package/dist/commands/app.js.map +1 -1
  254. package/dist/commands/bulk.d.ts.map +1 -1
  255. package/dist/commands/bulk.js +9 -2
  256. package/dist/commands/bulk.js.map +1 -1
  257. package/dist/commands/client-secret.d.ts.map +1 -1
  258. package/dist/commands/client-secret.js +12 -6
  259. package/dist/commands/client-secret.js.map +1 -1
  260. package/dist/commands/client.d.ts +3 -2
  261. package/dist/commands/client.d.ts.map +1 -1
  262. package/dist/commands/client.js +87 -43
  263. package/dist/commands/client.js.map +1 -1
  264. package/dist/commands/config.d.ts +4 -0
  265. package/dist/commands/config.d.ts.map +1 -1
  266. package/dist/commands/config.js +68 -7
  267. package/dist/commands/config.js.map +1 -1
  268. package/dist/commands/export.d.ts +6 -0
  269. package/dist/commands/export.d.ts.map +1 -0
  270. package/dist/commands/export.js +182 -0
  271. package/dist/commands/export.js.map +1 -0
  272. package/dist/commands/import.d.ts +6 -0
  273. package/dist/commands/import.d.ts.map +1 -0
  274. package/dist/commands/import.js +142 -0
  275. package/dist/commands/import.js.map +1 -0
  276. package/dist/commands/keys.d.ts.map +1 -1
  277. package/dist/commands/keys.js +11 -4
  278. package/dist/commands/keys.js.map +1 -1
  279. package/dist/commands/login.d.ts.map +1 -1
  280. package/dist/commands/login.js +24 -10
  281. package/dist/commands/login.js.map +1 -1
  282. package/dist/commands/org.d.ts +2 -4
  283. package/dist/commands/org.d.ts.map +1 -1
  284. package/dist/commands/org.js +16 -76
  285. package/dist/commands/org.js.map +1 -1
  286. package/dist/commands/user-role.d.ts.map +1 -1
  287. package/dist/commands/user-role.js +19 -14
  288. package/dist/commands/user-role.js.map +1 -1
  289. package/dist/commands/user.d.ts +3 -2
  290. package/dist/commands/user.d.ts.map +1 -1
  291. package/dist/commands/user.js +47 -71
  292. package/dist/commands/user.js.map +1 -1
  293. package/dist/commands/version.d.ts +1 -1
  294. package/dist/commands/version.js +1 -1
  295. package/dist/credential-lock.d.ts +20 -0
  296. package/dist/credential-lock.d.ts.map +1 -0
  297. package/dist/credential-lock.js +130 -0
  298. package/dist/credential-lock.js.map +1 -0
  299. package/dist/credential-store.d.ts +14 -0
  300. package/dist/credential-store.d.ts.map +1 -1
  301. package/dist/credential-store.js +114 -3
  302. package/dist/credential-store.js.map +1 -1
  303. package/dist/error-handler.d.ts.map +1 -1
  304. package/dist/error-handler.js +2 -0
  305. package/dist/error-handler.js.map +1 -1
  306. package/dist/global-options.d.ts +8 -0
  307. package/dist/global-options.d.ts.map +1 -1
  308. package/dist/global-options.js +19 -8
  309. package/dist/global-options.js.map +1 -1
  310. package/dist/index.js +7 -5
  311. package/dist/index.js.map +1 -1
  312. package/dist/output.d.ts +11 -0
  313. package/dist/output.d.ts.map +1 -1
  314. package/dist/output.js +25 -6
  315. package/dist/output.js.map +1 -1
  316. package/dist/prompt.d.ts +2 -2
  317. package/dist/prompt.d.ts.map +1 -1
  318. package/dist/prompt.js +27 -7
  319. package/dist/prompt.js.map +1 -1
  320. package/package.json +7 -3
  321. package/dist/commands/gui.d.ts +0 -21
  322. package/dist/commands/gui.d.ts.map +0 -1
  323. package/dist/commands/gui.js +0 -67
  324. package/dist/commands/gui.js.map +0 -1
  325. package/dist/commands/provision.d.ts +0 -47
  326. package/dist/commands/provision.d.ts.map +0 -1
  327. package/dist/commands/provision.js +0 -444
  328. package/dist/commands/provision.js.map +0 -1
@@ -0,0 +1,145 @@
1
+ /** Focused OIDC client credential dialogs and their shared secret-expiry composition. */
2
+ import { addDays, addMonths, Button, col, ComboBox, Commands, compare, cover, DatePicker, Dialog, fixed, fromDate, grow, Input, Label, row, Show, signal, spacer, Text, toISO, } from '@jsvision/ui';
3
+ import { runAbortableAdminDialog } from './application-runtime.js';
4
+ import { textValidator } from './user-dialog-fields.js';
5
+ /** Exact warning shown when an administrator chooses a non-expiring secret. */
6
+ export const NEVER_SECRET_EXPIRY_WARNING = 'This secret will remain valid until it is deleted. Regular rotation is recommended.';
7
+ /** Non-blocking warning shown for a selected date beyond the 24-month preset boundary. */
8
+ export const LONG_SECRET_EXPIRY_WARNING = 'This secret expires after 24 months. Regular rotation is recommended.';
9
+ const SECRET_EXPIRY_CHOICES = [
10
+ { kind: 'months', months: 3, label: '3 months' },
11
+ { kind: 'months', months: 6, label: '6 months' },
12
+ { kind: 'months', months: 12, label: '12 months' },
13
+ { kind: 'months', months: 24, label: '24 months' },
14
+ { kind: 'custom', label: 'Custom' },
15
+ { kind: 'never', label: 'Never' },
16
+ ];
17
+ /** Secret-generation dialog with one shared validity rule for every submit route. */
18
+ class GenerateClientSecretDialog extends Dialog {
19
+ label;
20
+ labelInput;
21
+ expiry;
22
+ /** Creates a spacious focused credential form. */
23
+ constructor(width, height, label, labelInput, expiry) {
24
+ super({ title: 'Add client secret', width, height, centered: true });
25
+ this.label = label;
26
+ this.labelInput = labelInput;
27
+ this.expiry = expiry;
28
+ }
29
+ /** Rejects unsafe labels and invalid custom expiry dates before closing. */
30
+ valid(command) {
31
+ if (command === Commands.cancel)
32
+ return true;
33
+ if (!validLabel(this.label.peek()) || !this.expiry.isValid()) {
34
+ this.firstInvalid = this.labelInput;
35
+ return false;
36
+ }
37
+ return super.valid(command);
38
+ }
39
+ }
40
+ /** Serializes a selected civil expiry as midnight UTC on the following day. */
41
+ function serializeSecretExpiry(date) {
42
+ return `${toISO(addDays(date, 1))}T00:00:00.000Z`;
43
+ }
44
+ /** Resolves the civil expiry date represented by the current selector state. */
45
+ function selectedExpiryDate(choice, customDate, today) {
46
+ if (!choice || choice.kind === 'never')
47
+ return null;
48
+ return choice.kind === 'months' ? addMonths(today, choice.months) : customDate;
49
+ }
50
+ /** Creates one complete calendar-based secret-expiry selector with a six-month default. */
51
+ export function createClientSecretExpiryFields(now = new Date()) {
52
+ const today = fromDate(now);
53
+ const tomorrow = addDays(today, 1);
54
+ const choice = signal(SECRET_EXPIRY_CHOICES[1] ?? null);
55
+ const customDate = signal(tomorrow);
56
+ const picker = new DatePicker({ value: customDate, today, min: tomorrow });
57
+ const choicePicker = new ComboBox({
58
+ items: signal([...SECRET_EXPIRY_CHOICES]),
59
+ getText: (item) => item.label,
60
+ value: choice,
61
+ editable: false,
62
+ });
63
+ const content = col({ gap: 1 }, fixed(row({ gap: 1 }, fixed(new Label('Expires', choicePicker), 18), grow(choicePicker)), 1));
64
+ content.addDynamic(() => Show(() => choice()?.kind === 'custom', () => fixed(row({ gap: 1 }, fixed(new Label('Custom date', picker.input), 18), grow(picker)), 1)));
65
+ content.addDynamic(() => Show(() => {
66
+ const selected = selectedExpiryDate(choice(), customDate(), today);
67
+ return choice()?.kind === 'custom' && (selected === null || compare(selected, today) !== 1);
68
+ }, () => fixed(new Text('Custom date must be in the future.', { severity: 'error' }), 2)));
69
+ content.addDynamic(() => Show(() => choice()?.kind === 'never', () => fixed(new Text(NEVER_SECRET_EXPIRY_WARNING), 3)));
70
+ content.addDynamic(() => Show(() => {
71
+ const selected = selectedExpiryDate(choice(), customDate(), today);
72
+ return (choice()?.kind === 'custom' &&
73
+ selected !== null &&
74
+ compare(selected, addMonths(today, 24)) === 1);
75
+ }, () => fixed(new Text(LONG_SECRET_EXPIRY_WARNING), 3)));
76
+ return {
77
+ content,
78
+ isValid: () => {
79
+ const selected = selectedExpiryDate(choice(), customDate(), today);
80
+ return choice()?.kind === 'never' || (selected !== null && compare(selected, today) === 1);
81
+ },
82
+ expiresAt: () => {
83
+ const selected = selectedExpiryDate(choice.peek(), customDate.peek(), today);
84
+ return selected ? serializeSecretExpiry(selected) : undefined;
85
+ },
86
+ };
87
+ }
88
+ /** Returns true for an optional bounded label without terminal control characters. */
89
+ function validLabel(value) {
90
+ if (value.length > 255)
91
+ return false;
92
+ return ![...value].some((character) => {
93
+ const codePoint = character.codePointAt(0) ?? 0;
94
+ return codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f);
95
+ });
96
+ }
97
+ /** Runs one abortable credential modal and always removes it from the desktop. */
98
+ async function runCredentialDialog(host, dialog, operationSignal) {
99
+ host.desktop.addWindow(dialog);
100
+ try {
101
+ return await runAbortableAdminDialog(host.loop, operationSignal, async () => (await host.loop.execView(dialog)) ?? Commands.cancel);
102
+ }
103
+ catch (error) {
104
+ if (error instanceof DOMException && error.name === 'AbortError')
105
+ return Commands.cancel;
106
+ throw error;
107
+ }
108
+ finally {
109
+ host.desktop.removeWindow(dialog);
110
+ }
111
+ }
112
+ /** Opens focused label and calendar expiry controls for a new client secret. */
113
+ export async function showGenerateClientSecretDialog(host, operationSignal, client) {
114
+ const label = signal('');
115
+ const labelInput = new Input({
116
+ value: label,
117
+ maxLength: 255,
118
+ validator: textValidator(0, 255),
119
+ });
120
+ const expiry = createClientSecretExpiryFields();
121
+ const width = Math.max(1, Math.min(68, host.desktop.bounds.width));
122
+ const height = Math.max(1, Math.min(18, host.desktop.bounds.height));
123
+ const dialog = new GenerateClientSecretDialog(width, height, label, labelInput, expiry);
124
+ const fields = col({ gap: 1 }, fixed(new Text(`Client: ${client.clientName}`), 1), fixed(row({ gap: 1 }, fixed(new Label('Label', labelInput), 18), grow(labelInput)), 1), fixed(expiry.content, 7), fixed(new Text('The secret value is shown only once after creation.'), 2));
125
+ const canGenerate = () => validLabel(label()) && expiry.isValid();
126
+ dialog.add(cover(col({
127
+ gap: 1,
128
+ padding: { top: 1, right: 1, bottom: 1, left: 1 },
129
+ }, grow(fields), fixed(row({ gap: 1 }, spacer(), new Button('~A~dd', {
130
+ command: Commands.ok,
131
+ default: true,
132
+ disabled: () => !canGenerate(),
133
+ }), new Button('Cancel', { command: Commands.cancel })), 2))));
134
+ if ((await runCredentialDialog(host, dialog, operationSignal)) !== Commands.ok) {
135
+ return { kind: 'cancel' };
136
+ }
137
+ const input = {};
138
+ if (label.peek())
139
+ input.label = label.peek();
140
+ const expiresAt = expiry.expiresAt();
141
+ if (expiresAt)
142
+ input.expiresAt = expiresAt;
143
+ return { kind: 'generate', clientId: client.id, ...(Object.keys(input).length ? { input } : {}) };
144
+ }
145
+ //# sourceMappingURL=client-credential-dialogs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-credential-dialogs.js","sourceRoot":"","sources":["../../src/admin/client-credential-dialogs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /** Movable Layout DSL dialogs for selected-organization OIDC client administration. */
2
+ import type { EventLoop, ModalDialogHost } from '@jsvision/ui';
3
+ import type { AdminClient, AdminClientSecret } from './client-state.js';
4
+ import type { AdminOrganizationContext } from './state.js';
5
+ export { showClientRegistrationDialog } from './client-registration-dialog.js';
6
+ export type { AdminClientRegistrationDialogHost, AdminClientRegistrationDialogOptions, AdminClientRegistrationDialogResult, } from './client-registration-dialog.js';
7
+ export { AUTHENTICATION_URL_CHOICES, authenticationUrlRows, buildAuthenticationUrlUpdate, showAuthenticationUrlDialog, showDeleteAuthenticationUrlDialog, } from './client-authentication-dialog.js';
8
+ export type { AdminAuthenticationUrlRow, AuthenticationUrlChoice, AuthenticationUrlDialogResult, AuthenticationUrlDraft, AuthenticationUrlKind, AuthenticationUrlMutation, ClientAuthenticationDialogHost, DeleteAuthenticationUrlDialogResult, } from './client-authentication-dialog.js';
9
+ export { showGenerateClientSecretDialog } from './client-credential-dialogs.js';
10
+ export type { ClientCredentialDialogHost, GenerateClientSecretDialogResult, } from './client-credential-dialogs.js';
11
+ /** Modal host needed for abort-driven client dialog closure. */
12
+ export interface AdminClientDialogHost extends ModalDialogHost {
13
+ /** Event loop that can synchronously close and focus the owned modal. */
14
+ readonly loop: ModalDialogHost['loop'] & Pick<EventLoop, 'endModal' | 'focusView'>;
15
+ }
16
+ /** Result of an explicit client lifecycle confirmation. */
17
+ export type ClientLifecycleDialogResult = {
18
+ readonly kind: 'deactivate';
19
+ readonly clientId: string;
20
+ } | {
21
+ readonly kind: 'cancel';
22
+ };
23
+ /** Result of the focused client-name editor. */
24
+ export type EditClientNameDialogResult = {
25
+ readonly kind: 'update';
26
+ readonly clientId: string;
27
+ readonly input: {
28
+ readonly clientName: string;
29
+ };
30
+ } | {
31
+ readonly kind: 'cancel';
32
+ };
33
+ /** Result of an irreversible client-deletion dialog. */
34
+ export type DeleteClientDialogResult = {
35
+ readonly kind: 'delete';
36
+ readonly clientId: string;
37
+ } | {
38
+ readonly kind: 'cancel';
39
+ };
40
+ /** Result of a permanent nested-secret deletion confirmation. */
41
+ export type RevokeClientSecretDialogResult = {
42
+ readonly kind: 'revoke-secret';
43
+ readonly clientId: string;
44
+ readonly secretId: string;
45
+ } | {
46
+ readonly kind: 'cancel';
47
+ };
48
+ /** Shows one small editor for the only mutable field in the Overview section. */
49
+ export declare function showEditClientNameDialog(host: AdminClientDialogHost, operationSignal: AbortSignal, organization: AdminOrganizationContext, client: AdminClient): Promise<EditClientNameDialogResult>;
50
+ /** Shows a named client lifecycle confirmation with the selected organization. */
51
+ export declare function showClientLifecycleDialog(host: AdminClientDialogHost, operationSignal: AbortSignal, action: 'deactivate', organization: AdminOrganizationContext, client: AdminClient): Promise<ClientLifecycleDialogResult>;
52
+ /** Shows the protocol-authority cascade before permanently deleting a client. */
53
+ export declare function showDeleteClientDialog(host: AdminClientDialogHost, operationSignal: AbortSignal, organization: AdminOrganizationContext, client: AdminClient): Promise<DeleteClientDialogResult>;
54
+ /** Confirms permanent deletion while preserving the stable controller operation contract. */
55
+ export declare function showRevokeClientSecretDialog(host: AdminClientDialogHost, operationSignal: AbortSignal, organization: AdminOrganizationContext, client: AdminClient, secret: AdminClientSecret): Promise<RevokeClientSecretDialogResult>;
56
+ /** Shows one transient plaintext secret in a bounded non-editable view. */
57
+ export declare function showOneTimeClientSecretDialog(host: AdminClientDialogHost, operationSignal: AbortSignal, value: {
58
+ readonly clientName: string;
59
+ readonly clientId: string;
60
+ readonly label: string | null;
61
+ readonly plaintext: string;
62
+ readonly expiresAt: string | null;
63
+ }): Promise<void>;
64
+ //# sourceMappingURL=client-dialogs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-dialogs.d.ts","sourceRoot":"","sources":["../../src/admin/client-dialogs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ /** Movable Layout DSL dialogs for selected-organization OIDC client administration. */
2
+ import { Button, col, Commands, cover, Dialog, fixed, grow, Input, Label, row, signal, spacer, Text, } from '@jsvision/ui';
3
+ import { deleteActionLabel, deleteConfirmationLayout } from './delete-confirmation-layout.js';
4
+ import { formatOptionalAdminDateTime } from './admin-date-time.js';
5
+ import { runAbortableAdminDialog } from './application-runtime.js';
6
+ import { SelectableReadOnlyInput } from './selectable-read-only-input.js';
7
+ import { textValidator } from './user-dialog-fields.js';
8
+ export { showClientRegistrationDialog } from './client-registration-dialog.js';
9
+ export { AUTHENTICATION_URL_CHOICES, authenticationUrlRows, buildAuthenticationUrlUpdate, showAuthenticationUrlDialog, showDeleteAuthenticationUrlDialog, } from './client-authentication-dialog.js';
10
+ export { showGenerateClientSecretDialog } from './client-credential-dialogs.js';
11
+ /** Returns a dialog size capped to the current terminal surface. */
12
+ function dialogSize(host, preferredWidth, preferredHeight) {
13
+ return {
14
+ width: Math.max(1, Math.min(preferredWidth, host.desktop.bounds.width)),
15
+ height: Math.max(1, Math.min(preferredHeight, host.desktop.bounds.height)),
16
+ };
17
+ }
18
+ /** Runs one abortable modal and always removes it from the desktop. */
19
+ async function runDialog(host, dialog, operationSignal) {
20
+ host.desktop.addWindow(dialog);
21
+ try {
22
+ return await runAbortableAdminDialog(host.loop, operationSignal, async () => (await host.loop.execView(dialog)) ?? Commands.cancel);
23
+ }
24
+ catch (error) {
25
+ if (error instanceof DOMException && error.name === 'AbortError')
26
+ return Commands.cancel;
27
+ throw error;
28
+ }
29
+ finally {
30
+ host.desktop.removeWindow(dialog);
31
+ }
32
+ }
33
+ /** Creates one fixed one-row labeled input. */
34
+ function inputRow(label, input) {
35
+ return fixed(row({ gap: 1 }, fixed(new Label(label, input), 18), grow(input)), 1);
36
+ }
37
+ /** Shows one small editor for the only mutable field in the Overview section. */
38
+ export async function showEditClientNameDialog(host, operationSignal, organization, client) {
39
+ if (client.organizationId !== organization.id)
40
+ return { kind: 'cancel' };
41
+ const { width, height } = dialogSize(host, 62, 13);
42
+ const clientName = signal(client.clientName);
43
+ const nameInput = new Input({
44
+ value: clientName,
45
+ maxLength: 255,
46
+ validator: textValidator(1, 255, false),
47
+ });
48
+ const dialog = new Dialog({ title: 'Edit OIDC client name', width, height, centered: true });
49
+ const fields = col({ gap: 1 }, fixed(new Text(`Client ID: ${client.clientId}`), 1), fixed(new Text(`Client type: ${client.clientType}`), 1), fixed(new Text(`Application type: ${client.applicationType}`), 1), inputRow('Client name', nameInput));
50
+ dialog.add(cover(col({ gap: 1, padding: { top: 1, right: 2, bottom: 0, left: 2 } }, grow(fields), fixed(row({ gap: 1 }, spacer(), new Button('~S~ave', { command: Commands.ok, default: true }), new Button('Cancel', { command: Commands.cancel })), 2))));
51
+ if ((await runDialog(host, dialog, operationSignal)) !== Commands.ok)
52
+ return { kind: 'cancel' };
53
+ return { kind: 'update', clientId: client.id, input: { clientName: clientName.peek() } };
54
+ }
55
+ /** Shows a named client lifecycle confirmation with the selected organization. */
56
+ export async function showClientLifecycleDialog(host, operationSignal, action, organization, client) {
57
+ const { width, height } = dialogSize(host, 60, 12);
58
+ const dialog = new Dialog({ title: 'Deactivate OIDC client', width, height, centered: true });
59
+ dialog.add(cover(col({ gap: 1, padding: { top: 1, right: 2, bottom: 1, left: 2 } }, grow(new Text(`Organization: ${organization.name}\nClient: ${client.clientName}\nThe client can be activated again later.`)), fixed(row({ gap: 1 }, spacer(), new Button('Deactivate', { command: Commands.ok, default: true }), new Button('Cancel', { command: Commands.cancel })), 2))));
60
+ return (await runDialog(host, dialog, operationSignal)) === Commands.ok
61
+ ? { kind: action, clientId: client.id }
62
+ : { kind: 'cancel' };
63
+ }
64
+ /** Shows the protocol-authority cascade before permanently deleting a client. */
65
+ export async function showDeleteClientDialog(host, operationSignal, organization, client) {
66
+ if (client.organizationId !== organization.id)
67
+ return { kind: 'cancel' };
68
+ const { width, height } = dialogSize(host, 72, 14);
69
+ const keep = new Button('Keep', { command: Commands.cancel, default: true });
70
+ const remove = new Button(deleteActionLabel(client.clientName, width), {
71
+ command: Commands.yes,
72
+ });
73
+ const dialog = new Dialog({ title: 'Delete OIDC client', width, height, centered: true });
74
+ const confirmation = deleteConfirmationLayout({
75
+ dialogWidth: width,
76
+ details: `Organization: ${organization.name}\nClient: ${client.clientName}`,
77
+ warning: 'Deleting this client removes its secrets and client, grant, and protocol authority.',
78
+ keep,
79
+ remove,
80
+ });
81
+ dialog.add(cover(confirmation.content));
82
+ const outcome = runDialog(host, dialog, operationSignal);
83
+ host.loop.focusView(keep);
84
+ return (await outcome) === Commands.yes
85
+ ? { kind: 'delete', clientId: client.id }
86
+ : { kind: 'cancel' };
87
+ }
88
+ /** Confirms permanent deletion while preserving the stable controller operation contract. */
89
+ export async function showRevokeClientSecretDialog(host, operationSignal, organization, client, secret) {
90
+ if (secret.clientId !== client.id)
91
+ return { kind: 'cancel' };
92
+ const { width, height } = dialogSize(host, 60, 12);
93
+ const dialog = new Dialog({ title: 'Delete client secret', width, height, centered: true });
94
+ dialog.add(cover(col({ gap: 1, padding: { top: 1, right: 2, bottom: 1, left: 2 } }, grow(new Text(`Organization: ${organization.name}\nClient: ${client.clientName}\nSecret: ${secret.label ?? secret.id}\nDeleting this secret is permanent.`)), fixed(row({ gap: 1 }, spacer(), new Button('Keep', { command: Commands.cancel, default: true }), new Button(deleteActionLabel(secret.label ?? secret.id, width), {
95
+ command: Commands.ok,
96
+ })), 2))));
97
+ return (await runDialog(host, dialog, operationSignal)) === Commands.ok
98
+ ? { kind: 'revoke-secret', clientId: client.id, secretId: secret.id }
99
+ : { kind: 'cancel' };
100
+ }
101
+ /** Shows one transient plaintext secret in a bounded non-editable view. */
102
+ export async function showOneTimeClientSecretDialog(host, operationSignal, value) {
103
+ const { width, height } = dialogSize(host, 76, 15);
104
+ const dialog = new Dialog({ title: 'One-time client secret', width, height, centered: true });
105
+ const clientIdInput = new SelectableReadOnlyInput(value.clientId);
106
+ const secretInput = new SelectableReadOnlyInput(value.plaintext);
107
+ dialog.add(cover(col({ gap: 1, padding: { top: 1, right: 2, bottom: 1, left: 2 } }, fixed(new Text(`Client: ${value.clientName}`), 1), fixed(row({ gap: 1 }, fixed(new Label('Client ID', clientIdInput), 12), grow(clientIdInput)), 1), fixed(new Text(`Label: ${value.label ?? 'Not provided'}`), 1), fixed(new Text(`Expires: ${formatOptionalAdminDateTime(value.expiresAt, 'Never')}`), 1), fixed(row({ gap: 1 }, fixed(new Label('Secret', secretInput), 12), grow(secretInput)), 1), fixed(new Text('Store this value now. It cannot be shown again.'), 1), fixed(row({ gap: 1 }, spacer(), new Button('Close', { command: Commands.ok, default: true })), 2))));
108
+ await runDialog(host, dialog, operationSignal);
109
+ }
110
+ //# sourceMappingURL=client-dialogs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-dialogs.js","sourceRoot":"","sources":["../../src/admin/client-dialogs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /** Focus-aware scrolling shared by OIDC client forms. */
2
+ import { Group, Scroller } from '@jsvision/ui';
3
+ import type { Size2D, View } from '@jsvision/ui';
4
+ /**
5
+ * Vertical scroller that reveals the focused control in a complete OIDC client form.
6
+ *
7
+ * The content retains its comfortable logical height while the viewport may shrink to a compact
8
+ * terminal. Keeping focus and scrolling coupled prevents keyboard navigation from moving into a
9
+ * clipped control.
10
+ */
11
+ export declare class ClientFormScroller extends Scroller {
12
+ /** Creates a scrolling viewport over one complete client form. */
13
+ constructor(content: Group, extent: () => Size2D);
14
+ /** Adjusts only the vertical offset needed to reveal one focused descendant. */
15
+ protected revealFocused(target: View | null): void;
16
+ }
17
+ //# sourceMappingURL=client-form-scroller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-form-scroller.d.ts","sourceRoot":"","sources":["../../src/admin/client-form-scroller.ts"],"names":[],"mappings":"AAAA,yDAAyD;AAEzD,OAAO,EAAQ,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAgBjD;;;;;;GAMG;AACH,qBAAa,kBAAmB,SAAQ,QAAQ;IAC9C,kEAAkE;IAClE,YAAmB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,EAoBtD;IAED,gFAAgF;IAChF,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAcjD;CACF"}
@@ -0,0 +1,67 @@
1
+ /** Focus-aware scrolling shared by OIDC client forms. */
2
+ import { grow, Group, Scroller } from '@jsvision/ui';
3
+ /** Returns leaf views, including controls that may become focusable after mounting. */
4
+ function leafDescendants(root) {
5
+ const result = [];
6
+ const visit = (view) => {
7
+ if (view instanceof Group) {
8
+ for (const child of view.children)
9
+ visit(child);
10
+ }
11
+ else {
12
+ result.push(view);
13
+ }
14
+ };
15
+ visit(root);
16
+ return result;
17
+ }
18
+ /**
19
+ * Vertical scroller that reveals the focused control in a complete OIDC client form.
20
+ *
21
+ * The content retains its comfortable logical height while the viewport may shrink to a compact
22
+ * terminal. Keeping focus and scrolling coupled prevents keyboard navigation from moving into a
23
+ * clipped control.
24
+ */
25
+ export class ClientFormScroller extends Scroller {
26
+ /** Creates a scrolling viewport over one complete client form. */
27
+ constructor(content, extent) {
28
+ // A growing initial layout prevents nested DSL rows from first solving at their small intrinsic
29
+ // frame width before Scroller applies the complete content extent.
30
+ super({ content: grow(content), extent, scrollbars: 'vertical' });
31
+ this.onMount(() => {
32
+ // Some controls, such as explicit login methods, become focusable only after another field
33
+ // changes. Observe every leaf so those later transitions retain focus-driven scrolling.
34
+ const targets = leafDescendants(content);
35
+ this.bind(() => {
36
+ let focused = null;
37
+ for (const target of targets) {
38
+ target.focusSignal()();
39
+ if (target.state.focused)
40
+ focused = target;
41
+ }
42
+ return focused;
43
+ }, (focused) => this.revealFocused(focused));
44
+ });
45
+ }
46
+ /** Adjusts only the vertical offset needed to reveal one focused descendant. */
47
+ revealFocused(target) {
48
+ if (!target || this.vpH <= 0)
49
+ return;
50
+ let top = 0;
51
+ let current = target;
52
+ while (current && current !== this.content) {
53
+ top += current.bounds.y;
54
+ current = current.parent;
55
+ }
56
+ if (!current)
57
+ return;
58
+ // Leave guidance below the focused control visible when the logical form has room for it.
59
+ const bottom = top + Math.max(1, target.bounds.height) + 3;
60
+ const offset = this.dy.peek();
61
+ if (top < offset)
62
+ this.dy.set(top);
63
+ else if (bottom > offset + this.vpH)
64
+ this.dy.set(Math.min(this.maxY, bottom - this.vpH));
65
+ }
66
+ }
67
+ //# sourceMappingURL=client-form-scroller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-form-scroller.js","sourceRoot":"","sources":["../../src/admin/client-form-scroller.ts"],"names":[],"mappings":"AAAA,yDAAyD;AAEzD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAGrD,uFAAuF;AACvF,SAAS,eAAe,CAAC,IAAU;IACjC,MAAM,MAAM,GAAW,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,CAAC,IAAU,EAAQ,EAAE;QACjC,IAAI,IAAI,YAAY,KAAK,EAAE,CAAC;YAC1B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ;gBAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,CAAC;IACZ,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,kBAAmB,SAAQ,QAAQ;IAC9C,kEAAkE;IAClE,YAAmB,OAAc,EAAE,MAAoB;QACrD,gGAAgG;QAChG,mEAAmE;QACnE,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE;YAChB,2FAA2F;YAC3F,wFAAwF;YACxF,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YACzC,IAAI,CAAC,IAAI,CACP,GAAG,EAAE;gBACH,IAAI,OAAO,GAAgB,IAAI,CAAC;gBAChC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;oBAC7B,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;oBACvB,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO;wBAAE,OAAO,GAAG,MAAM,CAAC;gBAC7C,CAAC;gBACD,OAAO,OAAO,CAAC;YACjB,CAAC,EACD,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CACzC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,gFAAgF;IACtE,aAAa,CAAC,MAAmB;QACzC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC;YAAE,OAAO;QACrC,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,IAAI,OAAO,GAAgB,MAAM,CAAC;QAClC,OAAO,OAAO,IAAI,OAAO,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3C,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YACxB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,0FAA0F;QAC1F,MAAM,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,GAAG,GAAG,MAAM;YAAE,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;aAC9B,IAAI,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG;YAAE,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3F,CAAC;CACF"}
@@ -0,0 +1,27 @@
1
+ /** Compact registration dialog for creating one OIDC client from server-backed defaults. */
2
+ import type { EventLoop, ModalDialogHost } from '@jsvision/ui';
3
+ import type { CreateClientInput } from '@portaidentity/sdk';
4
+ import type { AdminApplication } from './application-state.js';
5
+ import type { AdminOrganizationContext } from './state.js';
6
+ /** Modal host needed for abort-driven registration dialog closure. */
7
+ export interface AdminClientRegistrationDialogHost extends ModalDialogHost {
8
+ /** Event loop that can synchronously close and focus the owned modal. */
9
+ readonly loop: ModalDialogHost['loop'] & Pick<EventLoop, 'endModal' | 'focusView'>;
10
+ }
11
+ /** Context and active applications available to client registration. */
12
+ export interface AdminClientRegistrationDialogOptions {
13
+ /** Organization that will own the new client. */
14
+ readonly organization: AdminOrganizationContext;
15
+ /** Applications visible in the current organization context. */
16
+ readonly applications: readonly AdminApplication[];
17
+ }
18
+ /** Result returned by compact client registration. */
19
+ export type AdminClientRegistrationDialogResult = {
20
+ readonly kind: 'create';
21
+ readonly input: Omit<CreateClientInput, 'organizationId'>;
22
+ } | {
23
+ readonly kind: 'cancel';
24
+ };
25
+ /** Opens compact OIDC client registration using server defaults for advanced fields. */
26
+ export declare function showClientRegistrationDialog(host: AdminClientRegistrationDialogHost, operationSignal: AbortSignal, options: AdminClientRegistrationDialogOptions): Promise<AdminClientRegistrationDialogResult>;
27
+ //# sourceMappingURL=client-registration-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-registration-dialog.d.ts","sourceRoot":"","sources":["../../src/admin/client-registration-dialog.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAE5F,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAU,MAAM,cAAc,CAAC;AAkBvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAG5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAgC3D,sEAAsE;AACtE,MAAM,WAAW,iCAAkC,SAAQ,eAAe;IACxE,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,WAAW,CAAC,CAAC;CACpF;AAED,wEAAwE;AACxE,MAAM,WAAW,oCAAoC;IACnD,iDAAiD;IACjD,QAAQ,CAAC,YAAY,EAAE,wBAAwB,CAAC;IAChD,gEAAgE;IAChE,QAAQ,CAAC,YAAY,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACpD;AAED,sDAAsD;AACtD,MAAM,MAAM,mCAAmC,GAC3C;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAA;CAAE,GACtF;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AA+OhC,wFAAwF;AACxF,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,iCAAiC,EACvC,eAAe,EAAE,WAAW,EAC5B,OAAO,EAAE,oCAAoC,GAC5C,OAAO,CAAC,mCAAmC,CAAC,CAS9C"}