@kuckit/sdk-react 1.0.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.
@@ -0,0 +1,668 @@
1
+ import { ComponentType, JSX, ReactNode } from "react";
2
+ import { QueryClient } from "@tanstack/react-query";
3
+
4
+ //#region src/types.d.ts
5
+
6
+ /**
7
+ * Built-in capability types for common module features
8
+ */
9
+ type BuiltInCapability = 'nav.item' | 'settings.page' | 'dashboard.widget' | 'api.webhook' | 'api.public' | 'slot.provider';
10
+ /**
11
+ * Module capability type - built-in or custom
12
+ * Custom capabilities must be prefixed with 'custom.'
13
+ */
14
+ type ModuleCapability = BuiltInCapability | `custom.${string}`;
15
+ /**
16
+ * Module metadata for discovery and documentation
17
+ */
18
+ interface KuckitClientModuleMeta {
19
+ /** Unique identifier, e.g., 'kuckit.users' or 'acme.billing' */
20
+ id: string;
21
+ /** Human-readable name */
22
+ displayName?: string;
23
+ /** Module description */
24
+ description?: string;
25
+ /** Module version */
26
+ version?: string;
27
+ /** Capabilities this module provides */
28
+ capabilities?: ModuleCapability[];
29
+ }
30
+ /**
31
+ * Metadata for a route definition
32
+ */
33
+ interface RouteMeta {
34
+ /** Page title for document head */
35
+ title?: string;
36
+ /** Icon identifier (e.g., 'credit-card', 'users') */
37
+ icon?: string;
38
+ /** Whether this route requires authentication */
39
+ requiresAuth?: boolean;
40
+ /** Custom metadata */
41
+ [key: string]: unknown;
42
+ }
43
+ /**
44
+ * Route definition for module-provided routes
45
+ */
46
+ interface RouteDefinition {
47
+ /** Unique route identifier */
48
+ id: string;
49
+ /**
50
+ * URL path for the route.
51
+ *
52
+ * The path convention determines where the route is rendered:
53
+ * - `/some-path` → Root level route (outside dashboard, no layout wrapper)
54
+ * - `/dashboard/some-path` → Dashboard route (wrapped in dashboard layout)
55
+ *
56
+ * Root-level routes are public by default. Use `meta.requiresAuth: true`
57
+ * to require authentication for root routes.
58
+ *
59
+ * @example '/cli/activate' // Root level, no dashboard wrapper
60
+ * @example '/dashboard/settings/profile' // Dashboard route with layout
61
+ */
62
+ path: string;
63
+ /** React component to render for this route */
64
+ component: ComponentType<unknown>;
65
+ /** Parent route ID (defaults to '__root__' if not specified) */
66
+ parentRouteId?: string;
67
+ /** Route metadata */
68
+ meta?: RouteMeta;
69
+ }
70
+ /**
71
+ * Navigation item for sidebar/header menus
72
+ */
73
+ interface NavItem {
74
+ /** Unique identifier */
75
+ id: string;
76
+ /** Display label */
77
+ label: string;
78
+ /** Navigation path */
79
+ path: string;
80
+ /** Icon identifier (lucide-react icon name, e.g., 'credit-card', 'users') */
81
+ icon?: string;
82
+ /** Sort order (lower = higher priority) */
83
+ order?: number;
84
+ /** Parent nav item ID for nested navigation */
85
+ parentId?: string;
86
+ /** If true, show in main nav instead of "Modules" section */
87
+ showInMainNav?: boolean;
88
+ /** Badge text (e.g., "New", "Beta") */
89
+ badge?: string;
90
+ }
91
+ /**
92
+ * Options for slot registration
93
+ */
94
+ interface SlotOptions {
95
+ /** Sort order (lower = higher priority, default: 100) */
96
+ order?: number;
97
+ /** Props to pass to the component */
98
+ props?: Record<string, unknown>;
99
+ }
100
+ /**
101
+ * Internal representation of a registered slot component
102
+ */
103
+ interface SlotRegistration {
104
+ /** The slot name this component is registered to */
105
+ slotName: string;
106
+ /** The component to render */
107
+ component: ComponentType<unknown>;
108
+ /** Module that registered this component */
109
+ moduleId: string;
110
+ /** Sort order (lower = higher priority) */
111
+ order: number;
112
+ /** Props to pass to the component */
113
+ props?: Record<string, unknown>;
114
+ }
115
+ /**
116
+ * Context passed to client module hooks
117
+ */
118
+ interface KuckitClientModuleContext {
119
+ /** oRPC client instance */
120
+ orpc: unknown;
121
+ /** TanStack Query client */
122
+ queryClient: QueryClient;
123
+ /** Environment name (development, production, etc.) */
124
+ env: string;
125
+ /** Register a component for use in the application */
126
+ registerComponent: (name: string, component: ComponentType<unknown>) => void;
127
+ /** Register a route that will be injected into the router */
128
+ addRoute: (route: RouteDefinition) => void;
129
+ /** Register a navigation item for sidebar/header menus */
130
+ addNavItem: (item: NavItem) => void;
131
+ /** Register a component into a named slot */
132
+ registerSlot: (slotName: string, component: ComponentType<unknown>, options?: SlotOptions) => void;
133
+ }
134
+ /**
135
+ * Client module lifecycle hooks
136
+ */
137
+ interface KuckitClientModuleHooks {
138
+ /**
139
+ * Called when the module is registered
140
+ * Use this to register components, initialize state, etc.
141
+ */
142
+ register?(ctx: KuckitClientModuleContext): void | Promise<void>;
143
+ /**
144
+ * Called when the module is unloaded (optional)
145
+ * Use this for cleanup
146
+ */
147
+ onUnload?(): void | Promise<void>;
148
+ }
149
+ /**
150
+ * Complete client module definition combining metadata and hooks
151
+ */
152
+ interface KuckitClientModuleDefinition extends KuckitClientModuleMeta, KuckitClientModuleHooks {}
153
+ /**
154
+ * Client module specification in application config
155
+ *
156
+ * You can specify a module in two ways:
157
+ * 1. `module`: Direct reference to a module definition (preferred in monorepos)
158
+ * 2. `package`: NPM package path for dynamic import (for published packages)
159
+ */
160
+ interface ClientModuleSpec {
161
+ /** Direct module definition (preferred in monorepos for better type safety) */
162
+ module?: KuckitClientModuleDefinition;
163
+ /** NPM package path for dynamic import, e.g., '@acme/billing-module/client' */
164
+ package?: string;
165
+ /** Whether to skip this module */
166
+ disabled?: boolean;
167
+ }
168
+ /**
169
+ * Internal type for loaded modules
170
+ */
171
+ interface LoadedClientModule extends KuckitClientModuleDefinition {
172
+ _source: 'direct' | 'package';
173
+ }
174
+ //#endregion
175
+ //#region src/define-module.d.ts
176
+ /**
177
+ * Helper function to define a client module with type safety
178
+ *
179
+ * @example
180
+ * ```ts
181
+ * export const kuckitClientModule = defineKuckitClientModule({
182
+ * id: 'acme.billing',
183
+ * displayName: 'Billing',
184
+ * version: '1.0.0',
185
+ *
186
+ * register(ctx) {
187
+ * ctx.registerComponent('BillingDashboard', BillingDashboard)
188
+ * ctx.registerComponent('InvoiceList', InvoiceList)
189
+ * },
190
+ * })
191
+ * ```
192
+ */
193
+ declare function defineKuckitClientModule<T extends KuckitClientModuleDefinition>(mod: T): T;
194
+ //#endregion
195
+ //#region src/registry.d.ts
196
+ /**
197
+ * Registry for module-provided routes
198
+ *
199
+ * Collects route definitions during module loading and provides
200
+ * methods to build a TanStack Router route tree.
201
+ */
202
+ declare class RouteRegistry {
203
+ private routes;
204
+ private frozen;
205
+ /**
206
+ * Register a route definition
207
+ * @throws Error if registry is frozen or route ID already exists
208
+ */
209
+ add(route: RouteDefinition): void;
210
+ /**
211
+ * Get all registered routes
212
+ */
213
+ getAll(): RouteDefinition[];
214
+ /**
215
+ * Get a route by ID
216
+ */
217
+ get(id: string): RouteDefinition | undefined;
218
+ /**
219
+ * Check if a route is registered
220
+ */
221
+ has(id: string): boolean;
222
+ /**
223
+ * Get routes grouped by parent ID
224
+ */
225
+ getByParent(parentId?: string): RouteDefinition[];
226
+ /**
227
+ * Freeze the registry to prevent further modifications
228
+ */
229
+ freeze(): void;
230
+ /**
231
+ * Check if registry is frozen
232
+ */
233
+ isFrozen(): boolean;
234
+ /**
235
+ * Get the number of registered routes
236
+ */
237
+ get size(): number;
238
+ /**
239
+ * Clear all routes (only works if not frozen)
240
+ */
241
+ clear(): void;
242
+ }
243
+ /**
244
+ * Registry for module-provided navigation items
245
+ *
246
+ * Collects nav items during module loading and provides
247
+ * methods to build navigation menus.
248
+ */
249
+ declare class NavRegistry {
250
+ private items;
251
+ private frozen;
252
+ /**
253
+ * Register a navigation item
254
+ * @throws Error if registry is frozen or item ID already exists
255
+ */
256
+ add(item: NavItem): void;
257
+ /**
258
+ * Get all registered navigation items, sorted by order
259
+ */
260
+ getAll(): NavItem[];
261
+ /**
262
+ * Get a navigation item by ID
263
+ */
264
+ get(id: string): NavItem | undefined;
265
+ /**
266
+ * Check if a nav item is registered
267
+ */
268
+ has(id: string): boolean;
269
+ /**
270
+ * Get top-level navigation items (no parent)
271
+ */
272
+ getTopLevel(): NavItem[];
273
+ /**
274
+ * Get nav items that should appear in main navigation
275
+ * (items with showInMainNav === true)
276
+ */
277
+ getMainNavItems(): NavItem[];
278
+ /**
279
+ * Get module nav items (not in main nav)
280
+ * (items without showInMainNav or showInMainNav === false)
281
+ */
282
+ getModuleNavItems(): NavItem[];
283
+ /**
284
+ * Get child navigation items for a parent
285
+ */
286
+ getChildren(parentId: string): NavItem[];
287
+ /**
288
+ * Build a hierarchical navigation tree
289
+ */
290
+ buildTree(): NavTreeItem[];
291
+ private buildTreeItem;
292
+ /**
293
+ * Freeze the registry to prevent further modifications
294
+ */
295
+ freeze(): void;
296
+ /**
297
+ * Check if registry is frozen
298
+ */
299
+ isFrozen(): boolean;
300
+ /**
301
+ * Get the number of registered items
302
+ */
303
+ get size(): number;
304
+ /**
305
+ * Clear all items (only works if not frozen)
306
+ */
307
+ clear(): void;
308
+ }
309
+ /**
310
+ * Registry for module-provided slot components
311
+ *
312
+ * Collects components registered to named slots during module loading
313
+ * and provides methods to retrieve them for rendering.
314
+ */
315
+ declare class SlotRegistry {
316
+ private slots;
317
+ private frozen;
318
+ /**
319
+ * Register a component into a named slot
320
+ * @throws Error if registry is frozen
321
+ */
322
+ add(slotName: string, component: ComponentType<unknown>, moduleId: string, options?: SlotOptions): void;
323
+ /**
324
+ * Get all components registered to a slot, sorted by order
325
+ */
326
+ getSlot(name: string): SlotRegistration[];
327
+ /**
328
+ * Check if a slot has any components registered
329
+ */
330
+ hasSlot(name: string): boolean;
331
+ /**
332
+ * Get all slot names that have components registered
333
+ */
334
+ getSlotNames(): string[];
335
+ /**
336
+ * Get total number of registered components across all slots
337
+ */
338
+ get size(): number;
339
+ /**
340
+ * Freeze the registry to prevent further modifications
341
+ */
342
+ freeze(): void;
343
+ /**
344
+ * Check if registry is frozen
345
+ */
346
+ isFrozen(): boolean;
347
+ /**
348
+ * Clear all slots (only works if not frozen)
349
+ */
350
+ clear(): void;
351
+ }
352
+ /**
353
+ * Hierarchical navigation tree item
354
+ */
355
+ interface NavTreeItem extends NavItem {
356
+ children?: NavTreeItem[];
357
+ }
358
+ /**
359
+ * Provider component for Kuckit navigation
360
+ */
361
+ interface KuckitNavProviderProps {
362
+ registry: NavRegistry;
363
+ children: ReactNode;
364
+ }
365
+ declare function KuckitNavProvider({
366
+ registry,
367
+ children
368
+ }: KuckitNavProviderProps): ReactNode;
369
+ /**
370
+ * Hook to access navigation items
371
+ */
372
+ declare function useKuckitNav(): NavRegistry;
373
+ /**
374
+ * Hook to get sorted navigation items
375
+ */
376
+ declare function useNavItems(): NavItem[];
377
+ /**
378
+ * Hook to get hierarchical navigation tree
379
+ */
380
+ declare function useNavTree(): NavTreeItem[];
381
+ /**
382
+ * Create a component registry for storing named components
383
+ */
384
+ declare function createComponentRegistry(): ComponentRegistry;
385
+ interface ComponentRegistry {
386
+ register: (name: string, component: ComponentType<unknown>) => void;
387
+ get: (name: string) => ComponentType<unknown> | undefined;
388
+ has: (name: string) => boolean;
389
+ getAll: () => Map<string, ComponentType<unknown>>;
390
+ }
391
+ /**
392
+ * Information about a loaded client module
393
+ */
394
+ interface LoadedClientModuleInfo {
395
+ /** Module unique identifier */
396
+ id: string;
397
+ /** Human-readable name */
398
+ displayName?: string;
399
+ /** Module description */
400
+ description?: string;
401
+ /** Module version */
402
+ version?: string;
403
+ /** Capabilities this module provides */
404
+ capabilities: ModuleCapability[];
405
+ }
406
+ /**
407
+ * Registry for loaded Kuckit client modules
408
+ *
409
+ * Tracks all loaded modules and their capabilities for querying.
410
+ */
411
+ declare class ClientModuleRegistry {
412
+ private modules;
413
+ private frozen;
414
+ /**
415
+ * Register a loaded module
416
+ * @throws Error if registry is frozen or module ID already exists
417
+ */
418
+ register(module: KuckitClientModuleDefinition): void;
419
+ /**
420
+ * Get all registered modules
421
+ */
422
+ getAll(): LoadedClientModuleInfo[];
423
+ /**
424
+ * Get a module by ID
425
+ */
426
+ getById(id: string): LoadedClientModuleInfo | undefined;
427
+ /**
428
+ * Check if a module is registered
429
+ */
430
+ has(id: string): boolean;
431
+ /**
432
+ * Get all modules that have a specific capability
433
+ */
434
+ getWithCapability(capability: ModuleCapability): LoadedClientModuleInfo[];
435
+ /**
436
+ * Check if a specific module has a capability
437
+ */
438
+ hasCapability(moduleId: string, capability: ModuleCapability): boolean;
439
+ /**
440
+ * Get all unique capabilities across all modules
441
+ */
442
+ getAllCapabilities(): ModuleCapability[];
443
+ /**
444
+ * Freeze the registry to prevent further modifications
445
+ */
446
+ freeze(): void;
447
+ /**
448
+ * Check if registry is frozen
449
+ */
450
+ isFrozen(): boolean;
451
+ /**
452
+ * Get the number of registered modules
453
+ */
454
+ get size(): number;
455
+ /**
456
+ * Clear all modules (only works if not frozen)
457
+ */
458
+ clear(): void;
459
+ }
460
+ /**
461
+ * Get the global client module registry
462
+ * Creates one if it doesn't exist
463
+ */
464
+ declare function getClientModuleRegistry(): ClientModuleRegistry;
465
+ /**
466
+ * Get all client modules that have a specific capability
467
+ * Convenience function that uses the global registry
468
+ */
469
+ declare function getClientModulesWithCapability(capability: ModuleCapability): LoadedClientModuleInfo[];
470
+ /**
471
+ * Reset the global client registry (mainly for testing)
472
+ */
473
+ declare function resetClientModuleRegistry(): void;
474
+ /**
475
+ * Factory function to create fresh registries
476
+ */
477
+ declare function createRegistries(): {
478
+ routeRegistry: RouteRegistry;
479
+ navRegistry: NavRegistry;
480
+ componentRegistry: ComponentRegistry;
481
+ slotRegistry: SlotRegistry;
482
+ moduleRegistry: ClientModuleRegistry;
483
+ };
484
+ //#endregion
485
+ //#region src/loader.d.ts
486
+ interface LoadClientModulesOptions {
487
+ /** oRPC client instance */
488
+ orpc: unknown;
489
+ /** TanStack Query client */
490
+ queryClient: QueryClient;
491
+ /** Environment name (development, production, etc.) */
492
+ env: string;
493
+ /** List of client modules to load */
494
+ modules: ClientModuleSpec[];
495
+ /** Callback when a component is registered (deprecated, use result.componentRegistry) */
496
+ onRegisterComponent?: (name: string, component: ComponentType<unknown>) => void;
497
+ /** Callback when a route is registered (deprecated, use result.routeRegistry) */
498
+ onRegisterRoute?: (route: RouteDefinition) => void;
499
+ /** Callback when a nav item is registered (deprecated, use result.navRegistry) */
500
+ onRegisterNavItem?: (item: NavItem) => void;
501
+ /** Callback when a slot component is registered (deprecated, use result.slotRegistry) */
502
+ onRegisterSlot?: (slotName: string, component: ComponentType<unknown>, moduleId: string, options?: SlotOptions) => void;
503
+ /** Hook called when all modules are loaded */
504
+ onComplete?: (result: LoadClientModulesResult) => void | Promise<void>;
505
+ }
506
+ /**
507
+ * Result of loading client modules
508
+ */
509
+ interface LoadClientModulesResult {
510
+ /** All successfully loaded modules */
511
+ modules: LoadedClientModule[];
512
+ /** Registry containing all registered routes */
513
+ routeRegistry: RouteRegistry;
514
+ /** Registry containing all navigation items */
515
+ navRegistry: NavRegistry;
516
+ /** Registry containing all registered components */
517
+ componentRegistry: ComponentRegistry;
518
+ /** Registry containing all slot registrations */
519
+ slotRegistry: SlotRegistry;
520
+ /** Registry containing module info and capabilities */
521
+ moduleRegistry: ClientModuleRegistry;
522
+ }
523
+ /**
524
+ * Load and initialize Kuckit client modules
525
+ *
526
+ * This function orchestrates the client module loading lifecycle:
527
+ *
528
+ * 1. **Import Phase**: Dynamic import each module package (or use direct reference)
529
+ * 2. **Register Phase**: Run register() hooks with context (routes, nav, components, slots)
530
+ * 3. **Finalize Phase**: Freeze registries and call onComplete
531
+ *
532
+ * @example
533
+ * ```tsx
534
+ * const { modules, routeRegistry, navRegistry, slotRegistry, moduleRegistry } = await loadKuckitClientModules({
535
+ * orpc,
536
+ * queryClient,
537
+ * env: 'production',
538
+ * modules: [
539
+ * { package: '@acme/billing-module/client' },
540
+ * { module: myLocalModule },
541
+ * ],
542
+ * })
543
+ *
544
+ * // Use routeRegistry to build TanStack Router routes
545
+ * const moduleRoutes = routeRegistry.getAll()
546
+ *
547
+ * // Use navRegistry for sidebar navigation
548
+ * const navItems = navRegistry.getAll()
549
+ *
550
+ * // Use slotRegistry with KuckitSlot component
551
+ * <KuckitSlot name="dashboard.widgets" />
552
+ *
553
+ * // Query modules by capability
554
+ * const navModules = moduleRegistry.getWithCapability('nav.item')
555
+ * ```
556
+ */
557
+ declare const loadKuckitClientModules: (opts: LoadClientModulesOptions) => Promise<LoadClientModulesResult>;
558
+ /**
559
+ * Create an unload handler for loaded client modules
560
+ *
561
+ * Returns a function that calls onUnload() on all modules in reverse order.
562
+ *
563
+ * @example
564
+ * ```ts
565
+ * const unload = createClientModuleUnloadHandler(loadedModules)
566
+ *
567
+ * // When cleaning up (e.g., HMR, route unmount)
568
+ * await unload()
569
+ * ```
570
+ */
571
+ declare const createClientModuleUnloadHandler: (modules: LoadedClientModule[]) => (() => Promise<void>);
572
+ //#endregion
573
+ //#region src/slots.d.ts
574
+ /**
575
+ * Provider component for Kuckit slots
576
+ */
577
+ interface KuckitSlotProviderProps {
578
+ registry: SlotRegistry;
579
+ children: ReactNode;
580
+ }
581
+ declare function KuckitSlotProvider({
582
+ registry,
583
+ children
584
+ }: KuckitSlotProviderProps): ReactNode;
585
+ /**
586
+ * Hook to access the slot registry
587
+ */
588
+ declare function useSlotRegistry(): SlotRegistry;
589
+ /**
590
+ * Hook to get components registered to a specific slot
591
+ */
592
+ declare function useSlot(name: string): SlotRegistration[];
593
+ /**
594
+ * Hook to check if a slot has any components
595
+ */
596
+ declare function useHasSlot(name: string): boolean;
597
+ /**
598
+ * Props for the KuckitSlot component
599
+ */
600
+ interface KuckitSlotProps {
601
+ /** The name of the slot to render */
602
+ name: string;
603
+ /** Content to show when no components are registered */
604
+ fallback?: ReactNode;
605
+ /** CSS class name for the wrapper element */
606
+ wrapperClassName?: string;
607
+ /** Tag name for the wrapper element (default: none, renders fragments) */
608
+ wrapperTag?: keyof JSX.IntrinsicElements;
609
+ /** Additional props to pass to all slot components */
610
+ slotProps?: Record<string, unknown>;
611
+ }
612
+ /**
613
+ * Component that renders all components registered to a named slot
614
+ *
615
+ * @example
616
+ * ```tsx
617
+ * // In host app layout
618
+ * <KuckitSlot name="dashboard.widgets" />
619
+ *
620
+ * // With fallback
621
+ * <KuckitSlot name="settings.tabs" fallback={<EmptyState />} />
622
+ *
623
+ * // With wrapper
624
+ * <KuckitSlot name="nav.items" wrapperTag="nav" wrapperClassName="flex gap-2" />
625
+ * ```
626
+ */
627
+ declare function KuckitSlot({
628
+ name,
629
+ fallback,
630
+ wrapperClassName,
631
+ wrapperTag,
632
+ slotProps
633
+ }: KuckitSlotProps): ReactNode;
634
+ //#endregion
635
+ //#region src/rpc-context.d.ts
636
+ /**
637
+ * Provider component for Kuckit RPC client
638
+ */
639
+ interface KuckitRpcProviderProps {
640
+ /** The oRPC client instance */
641
+ client: unknown;
642
+ children: ReactNode;
643
+ }
644
+ declare function KuckitRpcProvider({
645
+ client,
646
+ children
647
+ }: KuckitRpcProviderProps): ReactNode;
648
+ /**
649
+ * Hook to access the RPC client
650
+ *
651
+ * @example
652
+ * ```tsx
653
+ * import { useRpc } from '@kuckit/sdk-react'
654
+ * import type { AppRouterClient } from '@kuckit/api/routers/index'
655
+ *
656
+ * function MyComponent() {
657
+ * const rpc = useRpc<AppRouterClient>()
658
+ * const result = await rpc.myRouter.myProcedure({ input: 'value' })
659
+ * }
660
+ * ```
661
+ */
662
+ declare function useRpc<T = unknown>(): T;
663
+ /**
664
+ * Hook to check if RPC client is available
665
+ */
666
+ declare function useHasRpc(): boolean;
667
+ //#endregion
668
+ export { type BuiltInCapability, ClientModuleRegistry, type ClientModuleSpec, type ComponentRegistry, type KuckitClientModuleContext, type KuckitClientModuleDefinition, type KuckitClientModuleHooks, type KuckitClientModuleMeta, KuckitNavProvider, KuckitRpcProvider, type KuckitRpcProviderProps, KuckitSlot, type KuckitSlotProps, KuckitSlotProvider, type KuckitSlotProviderProps, type LoadClientModulesOptions, type LoadClientModulesResult, type LoadedClientModule, type LoadedClientModuleInfo, type ModuleCapability, type NavItem, NavRegistry, type NavTreeItem, type RouteDefinition, type RouteMeta, RouteRegistry, type SlotOptions, type SlotRegistration, SlotRegistry, createClientModuleUnloadHandler, createComponentRegistry, createRegistries, defineKuckitClientModule, getClientModuleRegistry, getClientModulesWithCapability, loadKuckitClientModules, resetClientModuleRegistry, useHasRpc, useHasSlot, useKuckitNav, useNavItems, useNavTree, useRpc, useSlot, useSlotRegistry };