@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.
- package/LICENSE +21 -0
- package/README.md +111 -0
- package/package.json +101 -0
- package/src/assets/logo.svg +6 -0
- package/src/auth/SessionAuthAdapter.ts +459 -0
- package/src/auth/index.ts +15 -0
- package/src/chain/ActiveStack.ts +154 -0
- package/src/chain/StackHydrator.ts +292 -0
- package/src/chain/index.ts +25 -0
- package/src/chain/useActiveStack.ts +120 -0
- package/src/chain/useStackHydrator.ts +155 -0
- package/src/components/BoolCell.vue +34 -0
- package/src/components/InfoBanner.vue +73 -0
- package/src/components/QdadmRoot.vue +52 -0
- package/src/components/SeverityTag.vue +86 -0
- package/src/components/dialogs/BulkStatusDialog.vue +60 -0
- package/src/components/dialogs/MultiStepDialog.vue +331 -0
- package/src/components/dialogs/SimpleDialog.vue +122 -0
- package/src/components/dialogs/UnsavedChangesDialog.vue +80 -0
- package/src/components/display/BannerZone.vue +65 -0
- package/src/components/display/CardsGrid.vue +72 -0
- package/src/components/display/CopyableId.vue +84 -0
- package/src/components/display/EmptyState.vue +62 -0
- package/src/components/display/IntensityBar.vue +190 -0
- package/src/components/display/RichCardsGrid.vue +101 -0
- package/src/components/edit/FormActions.vue +78 -0
- package/src/components/edit/FormField.vue +82 -0
- package/src/components/edit/FormInput.vue +158 -0
- package/src/components/edit/FormPage.vue +260 -0
- package/src/components/edit/FormTab.vue +217 -0
- package/src/components/edit/FormTabs.vue +120 -0
- package/src/components/edit/LookupField.vue +406 -0
- package/src/components/edit/LookupPickerDialog.vue +230 -0
- package/src/components/editors/JsonEditorFoldable.vue +470 -0
- package/src/components/editors/JsonStructuredField.vue +264 -0
- package/src/components/editors/JsonViewer.vue +51 -0
- package/src/components/editors/KeyValueEditor.vue +314 -0
- package/src/components/editors/LanguageEditor.vue +259 -0
- package/src/components/editors/PermissionEditor.vue +558 -0
- package/src/components/editors/ScopeEditor.vue +372 -0
- package/src/components/editors/VanillaJsonEditor.vue +183 -0
- package/src/components/index.ts +83 -0
- package/src/components/item/FieldGroups.vue +392 -0
- package/src/components/layout/AppLayout.vue +1032 -0
- package/src/components/layout/BaseLayout.vue +190 -0
- package/src/components/layout/Breadcrumb.vue +55 -0
- package/src/components/layout/DashboardLayout.vue +104 -0
- package/src/components/layout/FormLayout.vue +256 -0
- package/src/components/layout/ListLayout.vue +278 -0
- package/src/components/layout/PageHeader.vue +156 -0
- package/src/components/layout/PageLayout.vue +126 -0
- package/src/components/layout/PageNav.vue +192 -0
- package/src/components/layout/SidebarBox.vue +87 -0
- package/src/components/layout/Zone.vue +182 -0
- package/src/components/layout/defaults/DefaultBreadcrumb.vue +149 -0
- package/src/components/layout/defaults/DefaultFooter.vue +89 -0
- package/src/components/layout/defaults/DefaultFormActions.vue +67 -0
- package/src/components/layout/defaults/DefaultHeader.vue +78 -0
- package/src/components/layout/defaults/DefaultMenu.vue +188 -0
- package/src/components/layout/defaults/DefaultPagination.vue +75 -0
- package/src/components/layout/defaults/DefaultTable.vue +137 -0
- package/src/components/layout/defaults/DefaultUserInfo.vue +111 -0
- package/src/components/layout/defaults/index.ts +16 -0
- package/src/components/lists/ActionButtons.vue +49 -0
- package/src/components/lists/ActionColumn.vue +40 -0
- package/src/components/lists/FilterBar.vue +54 -0
- package/src/components/lists/ListPage.vue +467 -0
- package/src/components/pages/LoginPage.vue +334 -0
- package/src/components/pages/NotFoundPage.vue +98 -0
- package/src/components/show/ShowDisplay.vue +343 -0
- package/src/components/show/ShowField.vue +67 -0
- package/src/components/show/ShowPage.vue +431 -0
- package/src/composables/index.ts +155 -0
- package/src/composables/useApp.ts +67 -0
- package/src/composables/useAuth.ts +98 -0
- package/src/composables/useBareForm.ts +319 -0
- package/src/composables/useBreadcrumb.ts +252 -0
- package/src/composables/useChildPage.ts +113 -0
- package/src/composables/useCurrentEntity.ts +60 -0
- package/src/composables/useDeferred.ts +94 -0
- package/src/composables/useDirtyState.ts +138 -0
- package/src/composables/useEntityItemFormPage.ts +942 -0
- package/src/composables/useEntityItemFormPage.types.ts +451 -0
- package/src/composables/useEntityItemPage.ts +438 -0
- package/src/composables/useEntityItemShowPage.ts +722 -0
- package/src/composables/useFieldManager.ts +692 -0
- package/src/composables/useForm.ts +544 -0
- package/src/composables/useGuardStore.ts +53 -0
- package/src/composables/useHooks.ts +56 -0
- package/src/composables/useInfoBanner.ts +217 -0
- package/src/composables/useJsonSyntax.ts +122 -0
- package/src/composables/useLayoutResolver.ts +329 -0
- package/src/composables/useListPage.ts +1535 -0
- package/src/composables/useListPage.types.ts +437 -0
- package/src/composables/useListPage.utils.ts +101 -0
- package/src/composables/useNavContext.ts +439 -0
- package/src/composables/useNavigation.ts +216 -0
- package/src/composables/useOptionsLookup.ts +323 -0
- package/src/composables/usePageTitle.ts +84 -0
- package/src/composables/useSSEBridge.ts +142 -0
- package/src/composables/useSemanticBreadcrumb.ts +222 -0
- package/src/composables/useSidebarState.ts +24 -0
- package/src/composables/useSignals.ts +52 -0
- package/src/composables/useUnsavedChangesGuard.ts +155 -0
- package/src/composables/useUserImpersonator.ts +317 -0
- package/src/composables/useZoneRegistry.ts +252 -0
- package/src/core/bundles.ts +558 -0
- package/src/core/decorator.ts +420 -0
- package/src/core/extension.ts +470 -0
- package/src/core/index.ts +59 -0
- package/src/deferred/DeferredRegistry.ts +353 -0
- package/src/deferred/index.ts +15 -0
- package/src/editors/index.ts +12 -0
- package/src/entity/EntityManager.cache.ts +530 -0
- package/src/entity/EntityManager.crud.ts +615 -0
- package/src/entity/EntityManager.interface.ts +78 -0
- package/src/entity/EntityManager.query.ts +221 -0
- package/src/entity/EntityManager.relations.ts +151 -0
- package/src/entity/EntityManager.ts +944 -0
- package/src/entity/EntityManager.types.ts +288 -0
- package/src/entity/auth/CompositeAuthAdapter.ts +194 -0
- package/src/entity/auth/EntityAuthAdapter.ts +119 -0
- package/src/entity/auth/PermissiveAdapter.ts +43 -0
- package/src/entity/auth/RoleHierarchy.ts +128 -0
- package/src/entity/auth/SecurityChecker.ts +202 -0
- package/src/entity/auth/factory.ts +203 -0
- package/src/entity/auth/index.ts +47 -0
- package/src/entity/factory.test.js +189 -0
- package/src/entity/factory.ts +146 -0
- package/src/entity/index.ts +49 -0
- package/src/entity/storage/ApiStorage.ts +228 -0
- package/src/entity/storage/IStorage.ts +100 -0
- package/src/entity/storage/LocalStorage.ts +200 -0
- package/src/entity/storage/MemoryStorage.ts +184 -0
- package/src/entity/storage/MockApiStorage.ts +318 -0
- package/src/entity/storage/SdkStorage.ts +377 -0
- package/src/entity/storage/factory.test.js +159 -0
- package/src/entity/storage/factory.ts +209 -0
- package/src/entity/storage/index.ts +75 -0
- package/src/gen/FieldMapper.ts +122 -0
- package/src/gen/StorageProfileFactory.ts +93 -0
- package/src/gen/connectors/BaseConnector.ts +150 -0
- package/src/gen/connectors/ManualConnector.test.js +499 -0
- package/src/gen/connectors/ManualConnector.ts +414 -0
- package/src/gen/connectors/OpenAPIConnector.test.js +836 -0
- package/src/gen/connectors/OpenAPIConnector.ts +693 -0
- package/src/gen/connectors/__fixtures__/sample-openapi.json +311 -0
- package/src/gen/connectors/index.ts +27 -0
- package/src/gen/createManagers.ts +245 -0
- package/src/gen/decorators.ts +134 -0
- package/src/gen/generateManagers.test.js +540 -0
- package/src/gen/generateManagers.ts +398 -0
- package/src/gen/index.ts +66 -0
- package/src/gen/schema.ts +248 -0
- package/src/gen/vite-plugin.ts +114 -0
- package/src/generated/managers/testManager.js +45 -0
- package/src/generated/managers/testManager.ts +46 -0
- package/src/hooks/HookRegistry.ts +16 -0
- package/src/hooks/index.ts +15 -0
- package/src/i18n/I18n.ts +344 -0
- package/src/i18n/IncrementalDomainProvider.ts +153 -0
- package/src/i18n/InlineTranslationProvider.ts +4 -0
- package/src/i18n/LazyTranslationProvider.ts +102 -0
- package/src/i18n/MessagesRegistry.ts +4 -0
- package/src/i18n/Resolver.ts +4 -0
- package/src/i18n/__tests__/I18n.test.ts +169 -0
- package/src/i18n/__tests__/IncrementalDomainProvider.test.ts +146 -0
- package/src/i18n/__tests__/LazyTranslationProvider.test.ts +100 -0
- package/src/i18n/__tests__/Resolver.test.ts +271 -0
- package/src/i18n/defaults/DefaultCoreProvider.ts +28 -0
- package/src/i18n/defaults/core.en.yml +55 -0
- package/src/i18n/defaults/core.fr.yml +55 -0
- package/src/i18n/index.ts +55 -0
- package/src/i18n/loaders/raw-modules.d.ts +15 -0
- package/src/i18n/loaders/yaml.ts +35 -0
- package/src/i18n/strategies.ts +4 -0
- package/src/i18n/types.ts +34 -0
- package/src/i18n/useI18n.ts +34 -0
- package/src/index.ts +453 -0
- package/src/kernel/EventRouter.ts +23 -0
- package/src/kernel/Kernel.api.ts +79 -0
- package/src/kernel/Kernel.auth.ts +120 -0
- package/src/kernel/Kernel.i18n.ts +29 -0
- package/src/kernel/Kernel.modules.ts +170 -0
- package/src/kernel/Kernel.registries.ts +237 -0
- package/src/kernel/Kernel.routing.ts +334 -0
- package/src/kernel/Kernel.ts +460 -0
- package/src/kernel/Kernel.types.ts +263 -0
- package/src/kernel/Kernel.vue.ts +304 -0
- package/src/kernel/KernelContext.entities.ts +80 -0
- package/src/kernel/KernelContext.events.ts +57 -0
- package/src/kernel/KernelContext.i18n.ts +37 -0
- package/src/kernel/KernelContext.permissions.ts +38 -0
- package/src/kernel/KernelContext.routing.ts +280 -0
- package/src/kernel/KernelContext.ts +252 -0
- package/src/kernel/KernelContext.types.ts +173 -0
- package/src/kernel/KernelContext.zones.ts +54 -0
- package/src/kernel/Module.ts +169 -0
- package/src/kernel/ModuleLoader.ts +645 -0
- package/src/kernel/SSEBridge.ts +11 -0
- package/src/kernel/SignalBus.ts +48 -0
- package/src/kernel/index.ts +56 -0
- package/src/module/index.ts +33 -0
- package/src/module/moduleRegistry.ts +492 -0
- package/src/modules/debug/AuthCollector.ts +501 -0
- package/src/modules/debug/Collector.ts +20 -0
- package/src/modules/debug/DebugBridge.ts +14 -0
- package/src/modules/debug/DebugModule.ts +220 -0
- package/src/modules/debug/EntitiesCollector.ts +839 -0
- package/src/modules/debug/ErrorCollector.ts +4 -0
- package/src/modules/debug/I18nCollector.ts +9 -0
- package/src/modules/debug/LocalStorageAdapter.ts +7 -0
- package/src/modules/debug/RouterCollector.ts +449 -0
- package/src/modules/debug/SignalCollector.ts +4 -0
- package/src/modules/debug/ToastCollector.ts +4 -0
- package/src/modules/debug/ZonesCollector.ts +447 -0
- package/src/modules/debug/components/DebugBar.vue +31 -0
- package/src/modules/debug/components/adminPanelsConfig.ts +42 -0
- package/src/modules/debug/components/index.ts +9 -0
- package/src/modules/debug/components/panels/AuthPanel.vue +267 -0
- package/src/modules/debug/components/panels/EntitiesPanel.vue +572 -0
- package/src/modules/debug/components/panels/I18nPanel.vue +738 -0
- package/src/modules/debug/components/panels/RouterPanel.vue +440 -0
- package/src/modules/debug/components/panels/ZonesPanel.vue +133 -0
- package/src/modules/debug/components/panels/index.ts +16 -0
- package/src/modules/debug/index.ts +58 -0
- package/src/modules/debug/styles.scss +2671 -0
- package/src/notifications/NotificationBadge.vue +35 -0
- package/src/notifications/NotificationListener.vue +71 -0
- package/src/notifications/NotificationModule.ts +76 -0
- package/src/notifications/NotificationPanel.vue +478 -0
- package/src/notifications/NotificationStore.ts +288 -0
- package/src/notifications/index.ts +42 -0
- package/src/notifications/styles.scss +32 -0
- package/src/orchestrator/Orchestrator.ts +427 -0
- package/src/orchestrator/index.ts +8 -0
- package/src/orchestrator/useOrchestrator.ts +80 -0
- package/src/plugin.ts +251 -0
- package/src/query/FilterQuery.ts +306 -0
- package/src/query/QueryExecutor.ts +341 -0
- package/src/query/index.ts +16 -0
- package/src/security/EntityRolesProvider.ts +385 -0
- package/src/security/PermissionMatcher.ts +152 -0
- package/src/security/PermissionRegistry.ts +273 -0
- package/src/security/PersistableRolesProvider.ts +584 -0
- package/src/security/RolesManager.ts +136 -0
- package/src/security/RolesProvider.ts +167 -0
- package/src/security/RolesProviderStorage.ts +211 -0
- package/src/security/SecurityModule.ts +94 -0
- package/src/security/StaticRolesProvider.ts +117 -0
- package/src/security/UsersManager.ts +163 -0
- package/src/security/index.ts +77 -0
- package/src/security/pages/RoleForm.vue +276 -0
- package/src/security/pages/RoleList.vue +123 -0
- package/src/styles/_alerts.scss +95 -0
- package/src/styles/_buttons.scss +391 -0
- package/src/styles/_cards.scss +241 -0
- package/src/styles/_code.scss +78 -0
- package/src/styles/_dialogs.scss +55 -0
- package/src/styles/_filter-bar.scss +70 -0
- package/src/styles/_forms.scss +434 -0
- package/src/styles/_helpers.scss +153 -0
- package/src/styles/_lists.scss +225 -0
- package/src/styles/_main.scss +356 -0
- package/src/styles/_markdown.scss +88 -0
- package/src/styles/_responsive.scss +255 -0
- package/src/styles/_show-pages.scss +186 -0
- package/src/styles/_sidebar.scss +380 -0
- package/src/styles/_states.scss +115 -0
- package/src/styles/_stats.scss +47 -0
- package/src/styles/_variables.scss +224 -0
- package/src/styles/index.scss +38 -0
- package/src/styles/theme/_components.scss +331 -0
- package/src/styles/theme/_index.scss +10 -0
- package/src/styles/theme/_tokens.scss +147 -0
- package/src/styles/theme/_utilities.scss +175 -0
- package/src/toast/ToastBridgeModule.ts +68 -0
- package/src/toast/ToastListener.vue +55 -0
- package/src/toast/index.ts +26 -0
- package/src/toast/useSignalToast.ts +154 -0
- package/src/types/index.ts +285 -0
- package/src/types/pluralize.d.ts +19 -0
- package/src/types/quarkernel.d.ts +50 -0
- package/src/utils/formatters.ts +174 -0
- package/src/utils/index.ts +35 -0
- package/src/utils/transformers.ts +131 -0
- package/src/vite/qdadmDebugPlugin.ts +401 -0
- package/src/vite-env.d.ts +50 -0
- package/src/zones/ZoneRegistry.ts +934 -0
- package/src/zones/index.ts +29 -0
- package/src/zones/zones.ts +191 -0
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* RouterPanel - Debug panel for Vue Router state
|
|
4
|
+
*
|
|
5
|
+
* Displays:
|
|
6
|
+
* - Current route (name, path, params, query, meta)
|
|
7
|
+
* - Computed breadcrumb
|
|
8
|
+
* - Navigation history (recent route changes)
|
|
9
|
+
* - All registered routes
|
|
10
|
+
*/
|
|
11
|
+
import { ref, computed, watch } from 'vue'
|
|
12
|
+
import { ObjectTree } from '@quazardous/qddebug'
|
|
13
|
+
|
|
14
|
+
interface RouteLocation {
|
|
15
|
+
name?: string
|
|
16
|
+
path: string
|
|
17
|
+
fullPath: string
|
|
18
|
+
params?: Record<string, string>
|
|
19
|
+
query?: Record<string, string>
|
|
20
|
+
hash?: string
|
|
21
|
+
meta?: Record<string, unknown>
|
|
22
|
+
matched?: MatchedRoute[]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface MatchedRoute {
|
|
26
|
+
name?: string
|
|
27
|
+
path: string
|
|
28
|
+
meta?: Record<string, unknown>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface NavigationEntry {
|
|
32
|
+
id: string | number
|
|
33
|
+
timestamp: number
|
|
34
|
+
from?: RouteLocation
|
|
35
|
+
to: RouteLocation
|
|
36
|
+
seen?: boolean
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface RouteEntry {
|
|
40
|
+
name: string
|
|
41
|
+
path: string
|
|
42
|
+
meta?: Record<string, unknown>
|
|
43
|
+
hasComponent?: boolean
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface StackLevel {
|
|
47
|
+
entity: string
|
|
48
|
+
param: string
|
|
49
|
+
id?: string
|
|
50
|
+
foreignKey?: string
|
|
51
|
+
loading?: boolean
|
|
52
|
+
hydrated?: boolean
|
|
53
|
+
hasData?: boolean
|
|
54
|
+
label?: string
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
interface ActiveStack {
|
|
58
|
+
depth: number
|
|
59
|
+
levels: StackLevel[]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface BreadcrumbItem {
|
|
63
|
+
kind: 'route' | 'entity'
|
|
64
|
+
route?: string
|
|
65
|
+
entity?: string
|
|
66
|
+
id?: string
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface Tab {
|
|
70
|
+
id: string
|
|
71
|
+
label: string
|
|
72
|
+
icon: string
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
interface RouterCollector {
|
|
76
|
+
navigate: (path: string) => Promise<void>
|
|
77
|
+
getActiveStack: () => ActiveStack | null
|
|
78
|
+
getCurrentRoute: () => RouteLocation | null
|
|
79
|
+
getBreadcrumb: () => BreadcrumbItem[]
|
|
80
|
+
getRoutes: () => RouteEntry[]
|
|
81
|
+
markSeen: () => void
|
|
82
|
+
getBadge: () => number
|
|
83
|
+
[key: string]: unknown
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const props = defineProps<{
|
|
87
|
+
collector: RouterCollector
|
|
88
|
+
entries: NavigationEntry[]
|
|
89
|
+
}>()
|
|
90
|
+
|
|
91
|
+
// Active tab
|
|
92
|
+
const activeTab = ref<string>('current')
|
|
93
|
+
const tabs: Tab[] = [
|
|
94
|
+
{ id: 'current', label: 'Current', icon: 'pi-map-marker' },
|
|
95
|
+
{ id: 'history', label: 'History', icon: 'pi-history' },
|
|
96
|
+
{ id: 'routes', label: 'Routes', icon: 'pi-sitemap' }
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
// Route filter for routes tab
|
|
100
|
+
const routeFilter = ref<string>('')
|
|
101
|
+
|
|
102
|
+
// Address bar for navigation
|
|
103
|
+
const addressInput = ref<string>('')
|
|
104
|
+
|
|
105
|
+
async function navigateTo(): Promise<void> {
|
|
106
|
+
const path = addressInput.value.trim()
|
|
107
|
+
if (!path) return
|
|
108
|
+
await props.collector.navigate(path)
|
|
109
|
+
addressInput.value = ''
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ActiveStack state
|
|
113
|
+
const activeStack = computed<ActiveStack | null>(() => {
|
|
114
|
+
void props.entries.length // trigger reactivity
|
|
115
|
+
return props.collector.getActiveStack()
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
// Max history - persisted in localStorage
|
|
119
|
+
const STORAGE_KEY_MAX = 'qdadm-router-max'
|
|
120
|
+
const maxHistory = ref<number>(parseInt(localStorage.getItem(STORAGE_KEY_MAX) || '20') || 20)
|
|
121
|
+
|
|
122
|
+
watch(maxHistory, (val) => {
|
|
123
|
+
localStorage.setItem(STORAGE_KEY_MAX, String(val))
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
// Current route (reactive via entries change)
|
|
127
|
+
const currentRoute = computed<RouteLocation | null>(() => {
|
|
128
|
+
// Trigger reactivity from entries
|
|
129
|
+
void props.entries.length
|
|
130
|
+
return props.collector.getCurrentRoute()
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
// Breadcrumb
|
|
134
|
+
const breadcrumb = computed<BreadcrumbItem[]>(() => {
|
|
135
|
+
void props.entries.length
|
|
136
|
+
return props.collector.getBreadcrumb()
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
// Matched routes with their individual metas
|
|
140
|
+
const matchedRoutes = computed<MatchedRoute[]>(() => {
|
|
141
|
+
void props.entries.length
|
|
142
|
+
return currentRoute.value?.matched ?? []
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
// Navigation history (already newest-first from collector, apply max limit)
|
|
146
|
+
const history = computed<NavigationEntry[]>(() => {
|
|
147
|
+
let result: NavigationEntry[] = props.entries
|
|
148
|
+
if (maxHistory.value > 0 && result.length > maxHistory.value) {
|
|
149
|
+
result = result.slice(0, maxHistory.value)
|
|
150
|
+
}
|
|
151
|
+
return result
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
// All routes filtered
|
|
155
|
+
const routes = computed<RouteEntry[]>(() => {
|
|
156
|
+
void props.entries.length // trigger
|
|
157
|
+
const all = props.collector.getRoutes()
|
|
158
|
+
if (!routeFilter.value) return all
|
|
159
|
+
const filter = routeFilter.value.toLowerCase()
|
|
160
|
+
return all.filter((r: RouteEntry) =>
|
|
161
|
+
r.name.toLowerCase().includes(filter) ||
|
|
162
|
+
r.path.toLowerCase().includes(filter)
|
|
163
|
+
)
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
// Mark history as seen when viewing history tab
|
|
167
|
+
watch(activeTab, (tab: string) => {
|
|
168
|
+
if (tab === 'history') {
|
|
169
|
+
props.collector.markSeen()
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
function formatTime(ts: number): string {
|
|
174
|
+
const d = new Date(ts)
|
|
175
|
+
return d.toLocaleTimeString('en-US', { hour12: false }) + '.' + String(d.getMilliseconds()).padStart(3, '0')
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function hasParams(obj: Record<string, unknown> | undefined): boolean {
|
|
179
|
+
return obj !== undefined && obj !== null && Object.keys(obj).length > 0
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Hydration state helpers
|
|
183
|
+
function getHydrationIcon(level: StackLevel): string {
|
|
184
|
+
if (level.loading) return '⏳'
|
|
185
|
+
if (level.hydrated) return level.hasData ? '✓' : '○'
|
|
186
|
+
return '…'
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function getHydrationClass(level: StackLevel): string {
|
|
190
|
+
if (level.loading) return 'hydration-badge-loading'
|
|
191
|
+
if (level.hydrated) return level.hasData ? 'hydration-badge-data' : 'hydration-badge-ready'
|
|
192
|
+
return 'hydration-badge-pending'
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function getHydrationTitle(level: StackLevel): string {
|
|
196
|
+
if (level.loading) return 'Loading entity data...'
|
|
197
|
+
if (level.hydrated && level.hasData) return 'Hydrated with data'
|
|
198
|
+
if (level.hydrated) return 'Hydrated (no data to fetch)'
|
|
199
|
+
return 'Pending hydration'
|
|
200
|
+
}
|
|
201
|
+
</script>
|
|
202
|
+
|
|
203
|
+
<template>
|
|
204
|
+
<div class="router-panel">
|
|
205
|
+
<!-- Address Bar -->
|
|
206
|
+
<div class="address-bar">
|
|
207
|
+
<i class="pi pi-compass" />
|
|
208
|
+
<input
|
|
209
|
+
v-model="addressInput"
|
|
210
|
+
type="text"
|
|
211
|
+
placeholder="Navigate to path..."
|
|
212
|
+
class="address-input"
|
|
213
|
+
@keyup.enter="navigateTo"
|
|
214
|
+
/>
|
|
215
|
+
<button class="address-go" @click="navigateTo" :disabled="!addressInput.trim()">
|
|
216
|
+
<i class="pi pi-arrow-right" />
|
|
217
|
+
</button>
|
|
218
|
+
</div>
|
|
219
|
+
|
|
220
|
+
<!-- Tabs -->
|
|
221
|
+
<div class="router-tabs">
|
|
222
|
+
<button
|
|
223
|
+
v-for="tab in tabs"
|
|
224
|
+
:key="tab.id"
|
|
225
|
+
class="router-tab"
|
|
226
|
+
:class="{ 'router-tab-active': activeTab === tab.id }"
|
|
227
|
+
@click="activeTab = tab.id"
|
|
228
|
+
>
|
|
229
|
+
<i :class="['pi', tab.icon]" />
|
|
230
|
+
{{ tab.label }}
|
|
231
|
+
<span v-if="tab.id === 'history' && collector.getBadge() > 0" class="tab-badge">
|
|
232
|
+
{{ collector.getBadge() }}
|
|
233
|
+
</span>
|
|
234
|
+
<span v-if="tab.id === 'routes'" class="tab-count">
|
|
235
|
+
{{ routes.length }}
|
|
236
|
+
</span>
|
|
237
|
+
</button>
|
|
238
|
+
</div>
|
|
239
|
+
|
|
240
|
+
<!-- Current Route -->
|
|
241
|
+
<div v-if="activeTab === 'current'" class="router-content">
|
|
242
|
+
<div v-if="currentRoute" class="route-current">
|
|
243
|
+
<!-- Route name and path -->
|
|
244
|
+
<div class="route-header">
|
|
245
|
+
<span class="route-name">{{ currentRoute.name }}</span>
|
|
246
|
+
<span class="route-path">{{ currentRoute.fullPath }}</span>
|
|
247
|
+
</div>
|
|
248
|
+
|
|
249
|
+
<!-- ActiveStack -->
|
|
250
|
+
<div v-if="activeStack" class="route-section">
|
|
251
|
+
<div class="section-label">Active Stack (depth: {{ activeStack.depth }})</div>
|
|
252
|
+
<div v-if="activeStack.levels.length === 0" class="stack-empty">
|
|
253
|
+
<i class="pi pi-inbox" />
|
|
254
|
+
<span>Stack empty (no entity with ID in route)</span>
|
|
255
|
+
</div>
|
|
256
|
+
<div v-else class="stack-list">
|
|
257
|
+
<div
|
|
258
|
+
v-for="(level, idx) in activeStack.levels"
|
|
259
|
+
:key="idx"
|
|
260
|
+
class="stack-entry"
|
|
261
|
+
:class="{
|
|
262
|
+
'stack-current': idx === activeStack.levels.length - 1,
|
|
263
|
+
'stack-loading': level.loading
|
|
264
|
+
}"
|
|
265
|
+
>
|
|
266
|
+
<div class="stack-entry-header">
|
|
267
|
+
<span class="stack-index">{{ idx }}</span>
|
|
268
|
+
<span class="stack-entity">{{ level.entity }}</span>
|
|
269
|
+
<span class="stack-hydration-badge" :class="getHydrationClass(level)" :title="getHydrationTitle(level)">
|
|
270
|
+
{{ getHydrationIcon(level) }}
|
|
271
|
+
</span>
|
|
272
|
+
</div>
|
|
273
|
+
<div class="stack-entry-props">
|
|
274
|
+
<span class="stack-prop">param: <code>{{ level.param }}</code></span>
|
|
275
|
+
<span class="stack-prop">id: <code>{{ level.id || '—' }}</code></span>
|
|
276
|
+
<span v-if="level.foreignKey" class="stack-prop">fk: <code>{{ level.foreignKey }}</code></span>
|
|
277
|
+
</div>
|
|
278
|
+
<div class="stack-entry-hydration">
|
|
279
|
+
<span v-if="level.loading" class="hydration-loading">⏳ loading...</span>
|
|
280
|
+
<span v-else-if="level.hydrated" class="hydration-ready">
|
|
281
|
+
<span class="hydration-label">{{ level.label || '(no label)' }}</span>
|
|
282
|
+
<span v-if="level.hasData" class="hydration-data">📦</span>
|
|
283
|
+
</span>
|
|
284
|
+
<span v-else class="hydration-pending">⏸ pending</span>
|
|
285
|
+
</div>
|
|
286
|
+
</div>
|
|
287
|
+
</div>
|
|
288
|
+
</div>
|
|
289
|
+
|
|
290
|
+
<!-- Breadcrumb -->
|
|
291
|
+
<div v-if="breadcrumb.length > 0" class="route-section">
|
|
292
|
+
<div class="section-label">Breadcrumb</div>
|
|
293
|
+
<div class="breadcrumb-list">
|
|
294
|
+
<div v-for="(item, idx) in breadcrumb" :key="idx" class="breadcrumb-entry" :class="'breadcrumb-' + item.kind">
|
|
295
|
+
<div class="breadcrumb-entry-header">
|
|
296
|
+
<span class="breadcrumb-index">{{ idx + 1 }}</span>
|
|
297
|
+
<span class="breadcrumb-kind">{{ item.kind }}</span>
|
|
298
|
+
</div>
|
|
299
|
+
<div class="breadcrumb-entry-props">
|
|
300
|
+
<template v-if="item.kind === 'route'">
|
|
301
|
+
<span class="breadcrumb-prop">route: <code>{{ item.route }}</code></span>
|
|
302
|
+
</template>
|
|
303
|
+
<template v-else>
|
|
304
|
+
<span class="breadcrumb-prop">entity: <code>{{ item.entity }}</code></span>
|
|
305
|
+
<span v-if="item.id" class="breadcrumb-prop">id: <code>{{ item.id }}</code></span>
|
|
306
|
+
</template>
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
</div>
|
|
310
|
+
</div>
|
|
311
|
+
|
|
312
|
+
<!-- Params -->
|
|
313
|
+
<div v-if="hasParams(currentRoute.params)" class="route-section">
|
|
314
|
+
<div class="section-label">Params</div>
|
|
315
|
+
<ObjectTree :data="currentRoute.params" :expanded="true" />
|
|
316
|
+
</div>
|
|
317
|
+
|
|
318
|
+
<!-- Query -->
|
|
319
|
+
<div v-if="hasParams(currentRoute.query)" class="route-section">
|
|
320
|
+
<div class="section-label">Query</div>
|
|
321
|
+
<ObjectTree :data="currentRoute.query" :expanded="true" />
|
|
322
|
+
</div>
|
|
323
|
+
|
|
324
|
+
<!-- Matched Routes -->
|
|
325
|
+
<div v-if="matchedRoutes.length > 0" class="route-section">
|
|
326
|
+
<div class="section-label">Matched Routes ({{ matchedRoutes.length }})</div>
|
|
327
|
+
<div class="matched-list">
|
|
328
|
+
<div v-for="(match, idx) in matchedRoutes" :key="idx" class="matched-entry">
|
|
329
|
+
<div class="matched-header">
|
|
330
|
+
<span class="matched-index">{{ idx }}</span>
|
|
331
|
+
<span class="matched-name">{{ match.name || '(unnamed)' }}</span>
|
|
332
|
+
</div>
|
|
333
|
+
<div class="matched-path">{{ match.path }}</div>
|
|
334
|
+
<div v-if="hasParams(match.meta)" class="matched-meta">
|
|
335
|
+
<ObjectTree :data="match.meta" :expanded="false" />
|
|
336
|
+
</div>
|
|
337
|
+
</div>
|
|
338
|
+
</div>
|
|
339
|
+
</div>
|
|
340
|
+
|
|
341
|
+
<!-- Hash -->
|
|
342
|
+
<div v-if="currentRoute.hash" class="route-section">
|
|
343
|
+
<div class="section-label">Hash</div>
|
|
344
|
+
<code class="route-hash">{{ currentRoute.hash }}</code>
|
|
345
|
+
</div>
|
|
346
|
+
</div>
|
|
347
|
+
<div v-else class="router-empty">
|
|
348
|
+
<i class="pi pi-compass" />
|
|
349
|
+
<span>No route active</span>
|
|
350
|
+
</div>
|
|
351
|
+
</div>
|
|
352
|
+
|
|
353
|
+
<!-- History -->
|
|
354
|
+
<div v-if="activeTab === 'history'" class="router-content">
|
|
355
|
+
<!-- Max selector -->
|
|
356
|
+
<div class="history-header-bar">
|
|
357
|
+
<span class="history-stats">{{ history.length }}/{{ entries.length }}</span>
|
|
358
|
+
<div class="history-max">
|
|
359
|
+
<label>Max:</label>
|
|
360
|
+
<select v-model.number="maxHistory" class="max-select">
|
|
361
|
+
<option :value="10">10</option>
|
|
362
|
+
<option :value="20">20</option>
|
|
363
|
+
<option :value="50">50</option>
|
|
364
|
+
<option :value="100">100</option>
|
|
365
|
+
</select>
|
|
366
|
+
</div>
|
|
367
|
+
</div>
|
|
368
|
+
<div v-if="history.length === 0" class="router-empty">
|
|
369
|
+
<i class="pi pi-history" />
|
|
370
|
+
<span>No navigation history</span>
|
|
371
|
+
</div>
|
|
372
|
+
<div v-else class="history-list">
|
|
373
|
+
<div
|
|
374
|
+
v-for="nav in history"
|
|
375
|
+
:key="nav.id"
|
|
376
|
+
class="history-entry"
|
|
377
|
+
:class="{ 'history-new': !nav.seen }"
|
|
378
|
+
>
|
|
379
|
+
<div class="history-header">
|
|
380
|
+
<span v-if="!nav.seen" class="history-dot" title="New" />
|
|
381
|
+
<span class="history-time">{{ formatTime(nav.timestamp) }}</span>
|
|
382
|
+
<span class="history-arrow">
|
|
383
|
+
<template v-if="nav.from">
|
|
384
|
+
{{ nav.from.name }}
|
|
385
|
+
<i class="pi pi-arrow-right" />
|
|
386
|
+
</template>
|
|
387
|
+
{{ nav.to.name }}
|
|
388
|
+
</span>
|
|
389
|
+
<button
|
|
390
|
+
class="history-nav-btn"
|
|
391
|
+
title="Navigate to this route"
|
|
392
|
+
@click="collector.navigate(nav.to.fullPath)"
|
|
393
|
+
>
|
|
394
|
+
<i class="pi pi-external-link" />
|
|
395
|
+
</button>
|
|
396
|
+
</div>
|
|
397
|
+
<div class="history-path">{{ nav.to.fullPath }}</div>
|
|
398
|
+
</div>
|
|
399
|
+
</div>
|
|
400
|
+
</div>
|
|
401
|
+
|
|
402
|
+
<!-- Routes -->
|
|
403
|
+
<div v-if="activeTab === 'routes'" class="router-content">
|
|
404
|
+
<div class="routes-filter">
|
|
405
|
+
<i class="pi pi-search" />
|
|
406
|
+
<input
|
|
407
|
+
v-model="routeFilter"
|
|
408
|
+
type="text"
|
|
409
|
+
placeholder="Filter routes..."
|
|
410
|
+
class="filter-input"
|
|
411
|
+
/>
|
|
412
|
+
</div>
|
|
413
|
+
<div class="routes-list">
|
|
414
|
+
<div
|
|
415
|
+
v-for="route in routes"
|
|
416
|
+
:key="route.path"
|
|
417
|
+
class="route-entry"
|
|
418
|
+
:class="{
|
|
419
|
+
'route-current-entry': currentRoute?.name === route.name,
|
|
420
|
+
'route-internal': route.name?.startsWith('_')
|
|
421
|
+
}"
|
|
422
|
+
>
|
|
423
|
+
<div class="route-entry-header">
|
|
424
|
+
<span class="route-entry-name">{{ route.name }}</span>
|
|
425
|
+
<span v-if="!route.hasComponent" class="route-no-component" title="No component">
|
|
426
|
+
<i class="pi pi-exclamation-triangle" />
|
|
427
|
+
</span>
|
|
428
|
+
</div>
|
|
429
|
+
<div class="route-entry-path">{{ route.path }}</div>
|
|
430
|
+
<div v-if="hasParams(route.meta)" class="route-entry-meta">
|
|
431
|
+
<span v-if="route.meta?.public" class="meta-tag meta-public">public</span>
|
|
432
|
+
<span v-if="route.meta?.entity" class="meta-tag meta-entity">{{ route.meta.entity }}</span>
|
|
433
|
+
<span v-if="route.meta?.permission" class="meta-tag meta-permission">{{ route.meta.permission }}</span>
|
|
434
|
+
</div>
|
|
435
|
+
</div>
|
|
436
|
+
</div>
|
|
437
|
+
</div>
|
|
438
|
+
</div>
|
|
439
|
+
</template>
|
|
440
|
+
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* ZonesPanel - Zones collector display
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
interface ZoneBlock {
|
|
7
|
+
id: string
|
|
8
|
+
component: string
|
|
9
|
+
weight: number
|
|
10
|
+
hasWrappers?: boolean
|
|
11
|
+
wrappersCount?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface ZoneEntry {
|
|
15
|
+
name: string
|
|
16
|
+
blocksCount: number
|
|
17
|
+
blocks: ZoneBlock[]
|
|
18
|
+
hasDefault?: boolean
|
|
19
|
+
defaultName?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface ZonesCollector {
|
|
23
|
+
toggleFilter?: () => void
|
|
24
|
+
toggleInternalFilter?: () => void
|
|
25
|
+
toggleHighlight?: (zoneName: string) => void
|
|
26
|
+
getHighlightedZone?: () => string | null
|
|
27
|
+
showCurrentPageOnly?: boolean
|
|
28
|
+
showInternalZones?: boolean
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface Props {
|
|
32
|
+
collector: ZonesCollector
|
|
33
|
+
entries: ZoneEntry[]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const props = defineProps<Props>()
|
|
37
|
+
|
|
38
|
+
const emit = defineEmits<{
|
|
39
|
+
update: []
|
|
40
|
+
}>()
|
|
41
|
+
|
|
42
|
+
function toggleFilter(): void {
|
|
43
|
+
if (props.collector.toggleFilter) {
|
|
44
|
+
props.collector.toggleFilter()
|
|
45
|
+
emit('update')
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function isFilterActive(): boolean {
|
|
50
|
+
return props.collector.showCurrentPageOnly ?? true
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function toggleInternalFilter(): void {
|
|
54
|
+
if (props.collector.toggleInternalFilter) {
|
|
55
|
+
props.collector.toggleInternalFilter()
|
|
56
|
+
emit('update')
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function showInternalZones(): boolean {
|
|
61
|
+
return props.collector.showInternalZones ?? false
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function highlightZone(zoneName: string): void {
|
|
65
|
+
if (props.collector.toggleHighlight) {
|
|
66
|
+
props.collector.toggleHighlight(zoneName)
|
|
67
|
+
emit('update')
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isHighlighted(zoneName: string): boolean {
|
|
72
|
+
return props.collector.getHighlightedZone?.() === zoneName
|
|
73
|
+
}
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<template>
|
|
77
|
+
<div class="zones-panel">
|
|
78
|
+
<div class="debug-panel-toolbar">
|
|
79
|
+
<button
|
|
80
|
+
class="debug-toolbar-btn"
|
|
81
|
+
:class="{ 'debug-toolbar-btn--active': !isFilterActive() }"
|
|
82
|
+
:title="isFilterActive() ? 'Click to show all zones' : 'Click to show current page only'"
|
|
83
|
+
@click="toggleFilter"
|
|
84
|
+
>
|
|
85
|
+
<i :class="['pi', isFilterActive() ? 'pi-filter-slash' : 'pi-filter']" />
|
|
86
|
+
All Pages
|
|
87
|
+
</button>
|
|
88
|
+
<button
|
|
89
|
+
class="debug-toolbar-btn"
|
|
90
|
+
:class="{ 'debug-toolbar-btn--active': showInternalZones() }"
|
|
91
|
+
:title="showInternalZones() ? 'Click to hide internal zones' : 'Click to show internal zones (prefixed with _)'"
|
|
92
|
+
@click="toggleInternalFilter"
|
|
93
|
+
>
|
|
94
|
+
<i :class="['pi', showInternalZones() ? 'pi-lock-open' : 'pi-lock']" />
|
|
95
|
+
Internal
|
|
96
|
+
</button>
|
|
97
|
+
</div>
|
|
98
|
+
<div class="zones-panel-content">
|
|
99
|
+
<div v-if="entries.length === 0" class="zones-empty">
|
|
100
|
+
<i class="pi pi-inbox" />
|
|
101
|
+
<span>No zones</span>
|
|
102
|
+
</div>
|
|
103
|
+
<div v-for="zone in entries" :key="zone.name" class="zone-item">
|
|
104
|
+
<div class="zone-header">
|
|
105
|
+
<button
|
|
106
|
+
class="zone-highlight"
|
|
107
|
+
:class="{ 'zone-highlight-active': isHighlighted(zone.name) }"
|
|
108
|
+
:title="isHighlighted(zone.name) ? 'Hide highlight' : 'Highlight zone'"
|
|
109
|
+
@click="highlightZone(zone.name)"
|
|
110
|
+
>
|
|
111
|
+
<i class="pi pi-eye" />
|
|
112
|
+
</button>
|
|
113
|
+
<span class="zone-name">{{ zone.name }}</span>
|
|
114
|
+
<span class="zone-count">{{ zone.blocksCount }} block(s)</span>
|
|
115
|
+
</div>
|
|
116
|
+
<div v-if="zone.blocks.length > 0" class="zone-blocks">
|
|
117
|
+
<div v-for="block in zone.blocks" :key="block.id" class="zone-block">
|
|
118
|
+
<span class="block-id">{{ block.id }}</span>
|
|
119
|
+
<span class="block-component">{{ block.component }}</span>
|
|
120
|
+
<span class="block-weight">w:{{ block.weight }}</span>
|
|
121
|
+
<span v-if="block.hasWrappers" class="block-wrappers">
|
|
122
|
+
<i class="pi pi-sitemap" :title="`${block.wrappersCount} wrapper(s)`" />
|
|
123
|
+
</span>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
<div v-else-if="zone.hasDefault" class="zone-default">
|
|
127
|
+
Default: {{ zone.defaultName || '(component)' }}
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
</template>
|
|
133
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug Panel Components — qdadm.
|
|
3
|
+
*
|
|
4
|
+
* Admin-specific panels live here; generic panels (Entries, Signals, Toasts)
|
|
5
|
+
* are re-exported from `@quazardous/qddebug` to preserve qdadm's public API.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Admin-specific panels
|
|
9
|
+
export { default as ZonesPanel } from './ZonesPanel.vue'
|
|
10
|
+
export { default as AuthPanel } from './AuthPanel.vue'
|
|
11
|
+
export { default as EntitiesPanel } from './EntitiesPanel.vue'
|
|
12
|
+
export { default as RouterPanel } from './RouterPanel.vue'
|
|
13
|
+
export { default as I18nPanel } from './I18nPanel.vue'
|
|
14
|
+
|
|
15
|
+
// Generic panels — re-exported from qddebug (single source of truth)
|
|
16
|
+
export { EntriesPanel, SignalsPanel, ToastsPanel } from '@quazardous/qddebug'
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug Module Exports
|
|
3
|
+
*
|
|
4
|
+
* Provides base classes and utilities for debug collectors
|
|
5
|
+
* used by the debug panel UI.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export { Collector, type CollectorEntry, type CollectorContext, type CollectorOptions } from './Collector'
|
|
9
|
+
export { SignalCollector, type SignalEntry } from './SignalCollector'
|
|
10
|
+
export { DebugBridge, createDebugBridge, type DebugBridgeOptions } from './DebugBridge'
|
|
11
|
+
export { ErrorCollector, type ErrorEntry } from './ErrorCollector'
|
|
12
|
+
export { ToastCollector, type ToastEntry } from './ToastCollector'
|
|
13
|
+
export { ZonesCollector, type ZoneEntry } from './ZonesCollector'
|
|
14
|
+
export {
|
|
15
|
+
AuthCollector,
|
|
16
|
+
type AuthEntry,
|
|
17
|
+
type AuthEvent,
|
|
18
|
+
type AuthEventType,
|
|
19
|
+
type AuthCollectorOptions
|
|
20
|
+
} from './AuthCollector'
|
|
21
|
+
export {
|
|
22
|
+
EntitiesCollector,
|
|
23
|
+
type EntityEntry,
|
|
24
|
+
type StorageInfo,
|
|
25
|
+
type CacheInfo,
|
|
26
|
+
type PermissionsInfo,
|
|
27
|
+
type StatsInfo
|
|
28
|
+
} from './EntitiesCollector'
|
|
29
|
+
export { RouterCollector, type NavigationEntry, type RouterCollectorOptions } from './RouterCollector'
|
|
30
|
+
export {
|
|
31
|
+
I18nCollector,
|
|
32
|
+
type MissingKeyEntry,
|
|
33
|
+
type LocaleChange,
|
|
34
|
+
type I18nCollectorOptions
|
|
35
|
+
} from './I18nCollector'
|
|
36
|
+
export { LocalStorageAdapter, createLocalStorageAdapter } from './LocalStorageAdapter'
|
|
37
|
+
|
|
38
|
+
// Module System v2 integration
|
|
39
|
+
export { DebugModule, DEBUG_BRIDGE_KEY, DEBUG_ZONE, QdadmDebugBar, type DebugModuleOptions } from './DebugModule'
|
|
40
|
+
|
|
41
|
+
// Components
|
|
42
|
+
export { DebugBar } from './components/index'
|
|
43
|
+
|
|
44
|
+
// Convenience export for Kernel debugBar option
|
|
45
|
+
import { DebugModule as _DebugModule, QdadmDebugBar as _QdadmDebugBar } from './DebugModule'
|
|
46
|
+
export const debugBar = {
|
|
47
|
+
module: _DebugModule,
|
|
48
|
+
component: _QdadmDebugBar
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Admin-specific panels + tab metadata, exposed for hosts that own a
|
|
52
|
+
// shared bridge and render a single `<DebugBar />` covering both
|
|
53
|
+
// qdadm and host-side (e.g. qdcms) collectors. Merge with your own
|
|
54
|
+
// panels and pass to `@quazardous/qddebug`'s `<DebugBar />`.
|
|
55
|
+
export {
|
|
56
|
+
adminPanels,
|
|
57
|
+
adminPanelsMeta,
|
|
58
|
+
} from './components/adminPanelsConfig'
|