@quazardous/qdadm 1.19.3

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 (291) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/package.json +101 -0
  4. package/src/assets/logo.svg +6 -0
  5. package/src/auth/SessionAuthAdapter.ts +459 -0
  6. package/src/auth/index.ts +15 -0
  7. package/src/chain/ActiveStack.ts +154 -0
  8. package/src/chain/StackHydrator.ts +292 -0
  9. package/src/chain/index.ts +25 -0
  10. package/src/chain/useActiveStack.ts +120 -0
  11. package/src/chain/useStackHydrator.ts +155 -0
  12. package/src/components/BoolCell.vue +34 -0
  13. package/src/components/InfoBanner.vue +73 -0
  14. package/src/components/QdadmRoot.vue +52 -0
  15. package/src/components/SeverityTag.vue +86 -0
  16. package/src/components/dialogs/BulkStatusDialog.vue +60 -0
  17. package/src/components/dialogs/MultiStepDialog.vue +331 -0
  18. package/src/components/dialogs/SimpleDialog.vue +122 -0
  19. package/src/components/dialogs/UnsavedChangesDialog.vue +80 -0
  20. package/src/components/display/BannerZone.vue +65 -0
  21. package/src/components/display/CardsGrid.vue +72 -0
  22. package/src/components/display/CopyableId.vue +84 -0
  23. package/src/components/display/EmptyState.vue +62 -0
  24. package/src/components/display/IntensityBar.vue +190 -0
  25. package/src/components/display/RichCardsGrid.vue +101 -0
  26. package/src/components/edit/FormActions.vue +78 -0
  27. package/src/components/edit/FormField.vue +82 -0
  28. package/src/components/edit/FormInput.vue +158 -0
  29. package/src/components/edit/FormPage.vue +260 -0
  30. package/src/components/edit/FormTab.vue +217 -0
  31. package/src/components/edit/FormTabs.vue +120 -0
  32. package/src/components/edit/LookupField.vue +406 -0
  33. package/src/components/edit/LookupPickerDialog.vue +230 -0
  34. package/src/components/editors/JsonEditorFoldable.vue +470 -0
  35. package/src/components/editors/JsonStructuredField.vue +264 -0
  36. package/src/components/editors/JsonViewer.vue +51 -0
  37. package/src/components/editors/KeyValueEditor.vue +314 -0
  38. package/src/components/editors/LanguageEditor.vue +259 -0
  39. package/src/components/editors/PermissionEditor.vue +558 -0
  40. package/src/components/editors/ScopeEditor.vue +372 -0
  41. package/src/components/editors/VanillaJsonEditor.vue +183 -0
  42. package/src/components/index.ts +83 -0
  43. package/src/components/item/FieldGroups.vue +392 -0
  44. package/src/components/layout/AppLayout.vue +1032 -0
  45. package/src/components/layout/BaseLayout.vue +190 -0
  46. package/src/components/layout/Breadcrumb.vue +55 -0
  47. package/src/components/layout/DashboardLayout.vue +104 -0
  48. package/src/components/layout/FormLayout.vue +256 -0
  49. package/src/components/layout/ListLayout.vue +278 -0
  50. package/src/components/layout/PageHeader.vue +156 -0
  51. package/src/components/layout/PageLayout.vue +126 -0
  52. package/src/components/layout/PageNav.vue +192 -0
  53. package/src/components/layout/SidebarBox.vue +87 -0
  54. package/src/components/layout/Zone.vue +182 -0
  55. package/src/components/layout/defaults/DefaultBreadcrumb.vue +149 -0
  56. package/src/components/layout/defaults/DefaultFooter.vue +89 -0
  57. package/src/components/layout/defaults/DefaultFormActions.vue +67 -0
  58. package/src/components/layout/defaults/DefaultHeader.vue +78 -0
  59. package/src/components/layout/defaults/DefaultMenu.vue +188 -0
  60. package/src/components/layout/defaults/DefaultPagination.vue +75 -0
  61. package/src/components/layout/defaults/DefaultTable.vue +137 -0
  62. package/src/components/layout/defaults/DefaultUserInfo.vue +111 -0
  63. package/src/components/layout/defaults/index.ts +16 -0
  64. package/src/components/lists/ActionButtons.vue +49 -0
  65. package/src/components/lists/ActionColumn.vue +40 -0
  66. package/src/components/lists/FilterBar.vue +54 -0
  67. package/src/components/lists/ListPage.vue +467 -0
  68. package/src/components/pages/LoginPage.vue +334 -0
  69. package/src/components/pages/NotFoundPage.vue +98 -0
  70. package/src/components/show/ShowDisplay.vue +343 -0
  71. package/src/components/show/ShowField.vue +67 -0
  72. package/src/components/show/ShowPage.vue +431 -0
  73. package/src/composables/index.ts +155 -0
  74. package/src/composables/useApp.ts +67 -0
  75. package/src/composables/useAuth.ts +98 -0
  76. package/src/composables/useBareForm.ts +319 -0
  77. package/src/composables/useBreadcrumb.ts +252 -0
  78. package/src/composables/useChildPage.ts +113 -0
  79. package/src/composables/useCurrentEntity.ts +60 -0
  80. package/src/composables/useDeferred.ts +94 -0
  81. package/src/composables/useDirtyState.ts +138 -0
  82. package/src/composables/useEntityItemFormPage.ts +942 -0
  83. package/src/composables/useEntityItemFormPage.types.ts +451 -0
  84. package/src/composables/useEntityItemPage.ts +438 -0
  85. package/src/composables/useEntityItemShowPage.ts +722 -0
  86. package/src/composables/useFieldManager.ts +692 -0
  87. package/src/composables/useForm.ts +544 -0
  88. package/src/composables/useGuardStore.ts +53 -0
  89. package/src/composables/useHooks.ts +56 -0
  90. package/src/composables/useInfoBanner.ts +217 -0
  91. package/src/composables/useJsonSyntax.ts +122 -0
  92. package/src/composables/useLayoutResolver.ts +329 -0
  93. package/src/composables/useListPage.ts +1535 -0
  94. package/src/composables/useListPage.types.ts +437 -0
  95. package/src/composables/useListPage.utils.ts +101 -0
  96. package/src/composables/useNavContext.ts +439 -0
  97. package/src/composables/useNavigation.ts +216 -0
  98. package/src/composables/useOptionsLookup.ts +323 -0
  99. package/src/composables/usePageTitle.ts +84 -0
  100. package/src/composables/useSSEBridge.ts +142 -0
  101. package/src/composables/useSemanticBreadcrumb.ts +222 -0
  102. package/src/composables/useSidebarState.ts +24 -0
  103. package/src/composables/useSignals.ts +52 -0
  104. package/src/composables/useUnsavedChangesGuard.ts +155 -0
  105. package/src/composables/useUserImpersonator.ts +317 -0
  106. package/src/composables/useZoneRegistry.ts +252 -0
  107. package/src/core/bundles.ts +558 -0
  108. package/src/core/decorator.ts +420 -0
  109. package/src/core/extension.ts +470 -0
  110. package/src/core/index.ts +59 -0
  111. package/src/deferred/DeferredRegistry.ts +353 -0
  112. package/src/deferred/index.ts +15 -0
  113. package/src/editors/index.ts +12 -0
  114. package/src/entity/EntityManager.cache.ts +530 -0
  115. package/src/entity/EntityManager.crud.ts +615 -0
  116. package/src/entity/EntityManager.interface.ts +78 -0
  117. package/src/entity/EntityManager.query.ts +221 -0
  118. package/src/entity/EntityManager.relations.ts +151 -0
  119. package/src/entity/EntityManager.ts +944 -0
  120. package/src/entity/EntityManager.types.ts +288 -0
  121. package/src/entity/auth/CompositeAuthAdapter.ts +194 -0
  122. package/src/entity/auth/EntityAuthAdapter.ts +119 -0
  123. package/src/entity/auth/PermissiveAdapter.ts +43 -0
  124. package/src/entity/auth/RoleHierarchy.ts +128 -0
  125. package/src/entity/auth/SecurityChecker.ts +202 -0
  126. package/src/entity/auth/factory.ts +203 -0
  127. package/src/entity/auth/index.ts +47 -0
  128. package/src/entity/factory.test.js +189 -0
  129. package/src/entity/factory.ts +146 -0
  130. package/src/entity/index.ts +49 -0
  131. package/src/entity/storage/ApiStorage.ts +228 -0
  132. package/src/entity/storage/IStorage.ts +100 -0
  133. package/src/entity/storage/LocalStorage.ts +200 -0
  134. package/src/entity/storage/MemoryStorage.ts +184 -0
  135. package/src/entity/storage/MockApiStorage.ts +318 -0
  136. package/src/entity/storage/SdkStorage.ts +377 -0
  137. package/src/entity/storage/factory.test.js +159 -0
  138. package/src/entity/storage/factory.ts +209 -0
  139. package/src/entity/storage/index.ts +75 -0
  140. package/src/gen/FieldMapper.ts +122 -0
  141. package/src/gen/StorageProfileFactory.ts +93 -0
  142. package/src/gen/connectors/BaseConnector.ts +150 -0
  143. package/src/gen/connectors/ManualConnector.test.js +499 -0
  144. package/src/gen/connectors/ManualConnector.ts +414 -0
  145. package/src/gen/connectors/OpenAPIConnector.test.js +836 -0
  146. package/src/gen/connectors/OpenAPIConnector.ts +693 -0
  147. package/src/gen/connectors/__fixtures__/sample-openapi.json +311 -0
  148. package/src/gen/connectors/index.ts +27 -0
  149. package/src/gen/createManagers.ts +245 -0
  150. package/src/gen/decorators.ts +134 -0
  151. package/src/gen/generateManagers.test.js +540 -0
  152. package/src/gen/generateManagers.ts +398 -0
  153. package/src/gen/index.ts +66 -0
  154. package/src/gen/schema.ts +248 -0
  155. package/src/gen/vite-plugin.ts +114 -0
  156. package/src/generated/managers/testManager.js +45 -0
  157. package/src/generated/managers/testManager.ts +46 -0
  158. package/src/hooks/HookRegistry.ts +16 -0
  159. package/src/hooks/index.ts +15 -0
  160. package/src/i18n/I18n.ts +344 -0
  161. package/src/i18n/IncrementalDomainProvider.ts +153 -0
  162. package/src/i18n/InlineTranslationProvider.ts +4 -0
  163. package/src/i18n/LazyTranslationProvider.ts +102 -0
  164. package/src/i18n/MessagesRegistry.ts +4 -0
  165. package/src/i18n/Resolver.ts +4 -0
  166. package/src/i18n/__tests__/I18n.test.ts +169 -0
  167. package/src/i18n/__tests__/IncrementalDomainProvider.test.ts +146 -0
  168. package/src/i18n/__tests__/LazyTranslationProvider.test.ts +100 -0
  169. package/src/i18n/__tests__/Resolver.test.ts +271 -0
  170. package/src/i18n/defaults/DefaultCoreProvider.ts +28 -0
  171. package/src/i18n/defaults/core.en.yml +55 -0
  172. package/src/i18n/defaults/core.fr.yml +55 -0
  173. package/src/i18n/index.ts +55 -0
  174. package/src/i18n/loaders/raw-modules.d.ts +15 -0
  175. package/src/i18n/loaders/yaml.ts +35 -0
  176. package/src/i18n/strategies.ts +4 -0
  177. package/src/i18n/types.ts +34 -0
  178. package/src/i18n/useI18n.ts +34 -0
  179. package/src/index.ts +453 -0
  180. package/src/kernel/EventRouter.ts +23 -0
  181. package/src/kernel/Kernel.api.ts +79 -0
  182. package/src/kernel/Kernel.auth.ts +120 -0
  183. package/src/kernel/Kernel.i18n.ts +29 -0
  184. package/src/kernel/Kernel.modules.ts +170 -0
  185. package/src/kernel/Kernel.registries.ts +237 -0
  186. package/src/kernel/Kernel.routing.ts +334 -0
  187. package/src/kernel/Kernel.ts +460 -0
  188. package/src/kernel/Kernel.types.ts +263 -0
  189. package/src/kernel/Kernel.vue.ts +304 -0
  190. package/src/kernel/KernelContext.entities.ts +80 -0
  191. package/src/kernel/KernelContext.events.ts +57 -0
  192. package/src/kernel/KernelContext.i18n.ts +37 -0
  193. package/src/kernel/KernelContext.permissions.ts +38 -0
  194. package/src/kernel/KernelContext.routing.ts +280 -0
  195. package/src/kernel/KernelContext.ts +252 -0
  196. package/src/kernel/KernelContext.types.ts +173 -0
  197. package/src/kernel/KernelContext.zones.ts +54 -0
  198. package/src/kernel/Module.ts +169 -0
  199. package/src/kernel/ModuleLoader.ts +645 -0
  200. package/src/kernel/SSEBridge.ts +11 -0
  201. package/src/kernel/SignalBus.ts +48 -0
  202. package/src/kernel/index.ts +56 -0
  203. package/src/module/index.ts +33 -0
  204. package/src/module/moduleRegistry.ts +492 -0
  205. package/src/modules/debug/AuthCollector.ts +501 -0
  206. package/src/modules/debug/Collector.ts +20 -0
  207. package/src/modules/debug/DebugBridge.ts +14 -0
  208. package/src/modules/debug/DebugModule.ts +220 -0
  209. package/src/modules/debug/EntitiesCollector.ts +839 -0
  210. package/src/modules/debug/ErrorCollector.ts +4 -0
  211. package/src/modules/debug/I18nCollector.ts +9 -0
  212. package/src/modules/debug/LocalStorageAdapter.ts +7 -0
  213. package/src/modules/debug/RouterCollector.ts +449 -0
  214. package/src/modules/debug/SignalCollector.ts +4 -0
  215. package/src/modules/debug/ToastCollector.ts +4 -0
  216. package/src/modules/debug/ZonesCollector.ts +447 -0
  217. package/src/modules/debug/components/DebugBar.vue +31 -0
  218. package/src/modules/debug/components/adminPanelsConfig.ts +42 -0
  219. package/src/modules/debug/components/index.ts +9 -0
  220. package/src/modules/debug/components/panels/AuthPanel.vue +267 -0
  221. package/src/modules/debug/components/panels/EntitiesPanel.vue +572 -0
  222. package/src/modules/debug/components/panels/I18nPanel.vue +738 -0
  223. package/src/modules/debug/components/panels/RouterPanel.vue +440 -0
  224. package/src/modules/debug/components/panels/ZonesPanel.vue +133 -0
  225. package/src/modules/debug/components/panels/index.ts +16 -0
  226. package/src/modules/debug/index.ts +58 -0
  227. package/src/modules/debug/styles.scss +2671 -0
  228. package/src/notifications/NotificationBadge.vue +35 -0
  229. package/src/notifications/NotificationListener.vue +71 -0
  230. package/src/notifications/NotificationModule.ts +76 -0
  231. package/src/notifications/NotificationPanel.vue +478 -0
  232. package/src/notifications/NotificationStore.ts +288 -0
  233. package/src/notifications/index.ts +42 -0
  234. package/src/notifications/styles.scss +32 -0
  235. package/src/orchestrator/Orchestrator.ts +427 -0
  236. package/src/orchestrator/index.ts +8 -0
  237. package/src/orchestrator/useOrchestrator.ts +80 -0
  238. package/src/plugin.ts +251 -0
  239. package/src/query/FilterQuery.ts +306 -0
  240. package/src/query/QueryExecutor.ts +341 -0
  241. package/src/query/index.ts +16 -0
  242. package/src/security/EntityRolesProvider.ts +385 -0
  243. package/src/security/PermissionMatcher.ts +152 -0
  244. package/src/security/PermissionRegistry.ts +273 -0
  245. package/src/security/PersistableRolesProvider.ts +584 -0
  246. package/src/security/RolesManager.ts +136 -0
  247. package/src/security/RolesProvider.ts +167 -0
  248. package/src/security/RolesProviderStorage.ts +211 -0
  249. package/src/security/SecurityModule.ts +94 -0
  250. package/src/security/StaticRolesProvider.ts +117 -0
  251. package/src/security/UsersManager.ts +163 -0
  252. package/src/security/index.ts +77 -0
  253. package/src/security/pages/RoleForm.vue +276 -0
  254. package/src/security/pages/RoleList.vue +123 -0
  255. package/src/styles/_alerts.scss +95 -0
  256. package/src/styles/_buttons.scss +391 -0
  257. package/src/styles/_cards.scss +241 -0
  258. package/src/styles/_code.scss +78 -0
  259. package/src/styles/_dialogs.scss +55 -0
  260. package/src/styles/_filter-bar.scss +70 -0
  261. package/src/styles/_forms.scss +434 -0
  262. package/src/styles/_helpers.scss +153 -0
  263. package/src/styles/_lists.scss +225 -0
  264. package/src/styles/_main.scss +356 -0
  265. package/src/styles/_markdown.scss +88 -0
  266. package/src/styles/_responsive.scss +255 -0
  267. package/src/styles/_show-pages.scss +186 -0
  268. package/src/styles/_sidebar.scss +380 -0
  269. package/src/styles/_states.scss +115 -0
  270. package/src/styles/_stats.scss +47 -0
  271. package/src/styles/_variables.scss +224 -0
  272. package/src/styles/index.scss +38 -0
  273. package/src/styles/theme/_components.scss +331 -0
  274. package/src/styles/theme/_index.scss +10 -0
  275. package/src/styles/theme/_tokens.scss +147 -0
  276. package/src/styles/theme/_utilities.scss +175 -0
  277. package/src/toast/ToastBridgeModule.ts +68 -0
  278. package/src/toast/ToastListener.vue +55 -0
  279. package/src/toast/index.ts +26 -0
  280. package/src/toast/useSignalToast.ts +154 -0
  281. package/src/types/index.ts +285 -0
  282. package/src/types/pluralize.d.ts +19 -0
  283. package/src/types/quarkernel.d.ts +50 -0
  284. package/src/utils/formatters.ts +174 -0
  285. package/src/utils/index.ts +35 -0
  286. package/src/utils/transformers.ts +131 -0
  287. package/src/vite/qdadmDebugPlugin.ts +401 -0
  288. package/src/vite-env.d.ts +50 -0
  289. package/src/zones/ZoneRegistry.ts +934 -0
  290. package/src/zones/index.ts +29 -0
  291. package/src/zones/zones.ts +191 -0
@@ -0,0 +1,267 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * AuthPanel - Auth collector display with activity indicator
4
+ * Each event has its own timer and fades out before destruction
5
+ */
6
+ import { onMounted, ref, onUnmounted, inject } from 'vue'
7
+ import { ObjectTree } from '@quazardous/qddebug'
8
+
9
+ interface AuthEntry {
10
+ type: string
11
+ label?: string
12
+ message?: string
13
+ data?: Record<string, unknown>
14
+ }
15
+
16
+ interface AuthEvent {
17
+ id: string | number
18
+ type: string
19
+ timestamp: Date
20
+ data?: Record<string, unknown>
21
+ }
22
+
23
+ interface LocalEvent extends AuthEvent {
24
+ fading: boolean
25
+ }
26
+
27
+ interface AuthCollector {
28
+ markSeen?: () => void
29
+ onNotify?: (callback: () => void) => () => void
30
+ getRecentEvents?: () => AuthEvent[]
31
+ _eventTtl?: number
32
+ [key: string]: unknown
33
+ }
34
+
35
+ interface AuthAdapter {
36
+ destroySession?: () => void
37
+ [key: string]: unknown
38
+ }
39
+
40
+ interface EventTimers {
41
+ fade: ReturnType<typeof setTimeout>
42
+ destroy: ReturnType<typeof setTimeout>
43
+ }
44
+
45
+ const props = defineProps<{
46
+ collector: AuthCollector
47
+ entries: AuthEntry[]
48
+ }>()
49
+
50
+ // Inject auth adapter for token loss simulation
51
+ const authAdapter = inject<AuthAdapter | null>('authAdapter', null)
52
+
53
+ /**
54
+ * Destroy session without normal logout flow
55
+ * Simulates catastrophic token loss (server revocation, storage corruption)
56
+ */
57
+ function destroySession(): void {
58
+ if (authAdapter?.destroySession) {
59
+ authAdapter.destroySession()
60
+ }
61
+ }
62
+
63
+ // Local events with fade state
64
+ const localEvents = ref<LocalEvent[]>([])
65
+ const timers = new Map<string | number, EventTimers>()
66
+ let unsubscribe: (() => void) | null = null
67
+
68
+ // Mark events as seen when panel is viewed
69
+ onMounted(() => {
70
+ props.collector.markSeen?.()
71
+ syncEvents()
72
+
73
+ // Subscribe to collector changes
74
+ if (props.collector.onNotify) {
75
+ unsubscribe = props.collector.onNotify(syncEvents)
76
+ }
77
+ })
78
+
79
+ onUnmounted(() => {
80
+ // Unsubscribe from collector
81
+ if (unsubscribe) unsubscribe()
82
+
83
+ // Clear all timers
84
+ for (const timer of timers.values()) {
85
+ clearTimeout(timer.fade)
86
+ clearTimeout(timer.destroy)
87
+ }
88
+ timers.clear()
89
+ })
90
+
91
+ /**
92
+ * Sync local events with collector and setup timers
93
+ */
94
+ function syncEvents(): void {
95
+ const collectorEvents = props.collector.getRecentEvents?.() || []
96
+ const ttl = props.collector._eventTtl || 60000
97
+ const fadeTime = 3000 // Start fading 3s before destruction
98
+ const now = Date.now()
99
+
100
+ // Add new events
101
+ for (const event of collectorEvents) {
102
+ if (!localEvents.value.find((e: LocalEvent) => e.id === event.id)) {
103
+ const age = now - event.timestamp.getTime()
104
+ const remaining = ttl - age
105
+
106
+ if (remaining > 0) {
107
+ const localEvent: LocalEvent = { ...event, fading: false }
108
+ localEvents.value.unshift(localEvent)
109
+
110
+ // Setup fade timer
111
+ const fadeDelay = Math.max(0, remaining - fadeTime)
112
+ const fadeTimer = setTimeout(() => {
113
+ localEvent.fading = true
114
+ }, fadeDelay)
115
+
116
+ // Setup destroy timer
117
+ const destroyTimer = setTimeout(() => {
118
+ removeEvent(event.id)
119
+ }, remaining)
120
+
121
+ timers.set(event.id, { fade: fadeTimer, destroy: destroyTimer })
122
+ }
123
+ }
124
+ }
125
+
126
+ // Remove events that no longer exist in collector
127
+ const collectorIds = new Set(collectorEvents.map((e: AuthEvent) => e.id))
128
+ localEvents.value = localEvents.value.filter((e: LocalEvent) => {
129
+ if (!collectorIds.has(e.id)) {
130
+ clearEventTimers(e.id)
131
+ return false
132
+ }
133
+ return true
134
+ })
135
+ }
136
+
137
+ function removeEvent(id: string | number): void {
138
+ clearEventTimers(id)
139
+ localEvents.value = localEvents.value.filter((e: LocalEvent) => e.id !== id)
140
+ }
141
+
142
+ function clearEventTimers(id: string | number): void {
143
+ const timer = timers.get(id)
144
+ if (timer) {
145
+ clearTimeout(timer.fade)
146
+ clearTimeout(timer.destroy)
147
+ timers.delete(id)
148
+ }
149
+ }
150
+
151
+ function getIcon(type: string): string {
152
+ const icons: Record<string, string> = {
153
+ user: 'pi-user',
154
+ impersonated: 'pi-user-edit',
155
+ token: 'pi-key',
156
+ 'user-permissions': 'pi-shield',
157
+ permissions: 'pi-list',
158
+ hierarchy: 'pi-sitemap',
159
+ 'role-permissions': 'pi-lock',
160
+ adapter: 'pi-cog'
161
+ }
162
+ return icons[type] || 'pi-info-circle'
163
+ }
164
+
165
+ function formatTime(date: Date): string {
166
+ return date.toLocaleTimeString('en-US', { hour12: false })
167
+ }
168
+
169
+ function getEventIcon(type: string): string {
170
+ const icons: Record<string, string> = {
171
+ login: 'pi-sign-in',
172
+ logout: 'pi-sign-out',
173
+ impersonate: 'pi-user-edit',
174
+ 'impersonate-stop': 'pi-user',
175
+ 'login-error': 'pi-times-circle'
176
+ }
177
+ return icons[type] || 'pi-info-circle'
178
+ }
179
+
180
+ function getEventLabel(event: LocalEvent): string {
181
+ if (event.type === 'login' && event.data) {
182
+ const user = event.data.user as Record<string, unknown> | undefined
183
+ const username = user?.username || user?.name || user?.email
184
+ if (username) {
185
+ return `User ${username} logged in`
186
+ }
187
+ }
188
+ if (event.type === 'impersonate' && event.data) {
189
+ const data = (event.data.data || event.data) as Record<string, unknown>
190
+ const target = data.target as Record<string, unknown> | undefined
191
+ const username = target?.username
192
+ || data.username
193
+ || (typeof data === 'string' ? data : null)
194
+ if (username) {
195
+ return `Impersonating user ${username}`
196
+ }
197
+ }
198
+ if (event.type === 'impersonate-stop') {
199
+ const data = (event.data?.data || event.data) as Record<string, unknown> | undefined
200
+ const original = data?.original as Record<string, unknown> | undefined
201
+ const username = original?.username
202
+ if (username) {
203
+ return `Back to ${username}`
204
+ }
205
+ }
206
+ if (event.type === 'login-error' && event.data) {
207
+ const username = event.data.username as string | undefined
208
+ const error = (event.data.error as string) || 'Invalid credentials'
209
+ if (username) {
210
+ return `Login failed: ${username} - ${error}`
211
+ }
212
+ return `Login failed: ${error}`
213
+ }
214
+ const labels: Record<string, string> = {
215
+ login: 'User logged in',
216
+ logout: 'User logged out',
217
+ impersonate: 'Impersonating user',
218
+ 'impersonate-stop': 'Stopped impersonation',
219
+ 'login-error': 'Login failed'
220
+ }
221
+ return labels[event.type] || event.type
222
+ }
223
+ </script>
224
+
225
+ <template>
226
+ <div class="auth-panel">
227
+ <!-- Debug actions -->
228
+ <div class="debug-panel-toolbar">
229
+ <button class="debug-toolbar-btn debug-toolbar-btn--danger" @click="destroySession" title="Clear token without logout (simulate session loss)">
230
+ <i class="pi pi-power-off" />
231
+ Destroy Session
232
+ </button>
233
+ </div>
234
+
235
+ <div class="auth-panel-content">
236
+ <!-- Invariant entries (user, token, permissions, adapter) -->
237
+ <div
238
+ v-for="(entry, idx) in entries"
239
+ :key="idx"
240
+ class="auth-item"
241
+ :class="{ 'auth-item--impersonated': entry.type === 'impersonated' }"
242
+ >
243
+ <div class="auth-header" :class="{ 'auth-header--impersonated': entry.type === 'impersonated' }">
244
+ <i :class="['pi', getIcon(entry.type)]" />
245
+ <span class="auth-label">{{ entry.label || entry.type }}</span>
246
+ </div>
247
+ <div v-if="entry.message" class="auth-message">{{ entry.message }}</div>
248
+ <ObjectTree v-else-if="entry.data" :data="entry.data" :maxDepth="4" />
249
+ </div>
250
+
251
+ <!-- Recent auth events with individual timers -->
252
+ <TransitionGroup name="event">
253
+ <div
254
+ v-for="event in localEvents"
255
+ :key="event.id"
256
+ class="auth-activity"
257
+ :class="[event.type, { fading: event.fading }]"
258
+ >
259
+ <i :class="['pi', getEventIcon(event.type)]" />
260
+ <span>{{ getEventLabel(event) }}</span>
261
+ <span class="auth-time">{{ formatTime(event.timestamp) }}</span>
262
+ </div>
263
+ </TransitionGroup>
264
+ </div>
265
+ </div>
266
+ </template>
267
+