@quazardous/qdadm 2.4.4 → 2.5.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.
@@ -21,9 +21,10 @@ import type {
21
21
  ParentConfig,
22
22
  RouteOptions,
23
23
  } from './KernelContext.types'
24
+ import type { KernelContext } from './KernelContext'
24
25
 
25
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
- type Self = any
26
+ // #1196 Phase B — this-typing against the real KernelContext shape (was Self = any)
27
+ type Self = KernelContext
27
28
 
28
29
  /** Singularize a plural word (simple English rules) */
29
30
  function singularize(plural: string): string {
@@ -128,9 +129,8 @@ function resolveParentParam(opts: {
128
129
  return namespaced
129
130
  }
130
131
 
131
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
132
- export function applyRoutingMethods(KernelContextClass: { prototype: any }): void {
133
- const proto = KernelContextClass.prototype as Self
132
+ export function applyRoutingMethods(KernelContextClass: { prototype: KernelContext }): void {
133
+ const proto = KernelContextClass.prototype
134
134
 
135
135
  proto.routes = function (
136
136
  this: Self,
@@ -20,6 +20,7 @@ import type { DeferredRegistry } from '../deferred/DeferredRegistry.js'
20
20
  import type { SecurityChecker } from '../entity/auth/SecurityChecker'
21
21
  import type { PermissionRegistry } from '../security/PermissionRegistry'
22
22
  import type { I18n } from '../i18n/I18n'
23
+ import type { RouteParamResolverContext } from './KernelContext.routing'
23
24
 
24
25
  // ─────────────────────────────────────────────────────────────────────────────
25
26
  // Internal types — shared across patch modules, not exposed by index.ts
@@ -41,6 +42,10 @@ export interface AuthAdapter {
41
42
  export interface KernelOptions {
42
43
  debug?: boolean
43
44
  authAdapter?: AuthAdapter | null
45
+ /** Parent route param naming policy for child CRUD families (#1201). */
46
+ parentParamMode?: 'auto' | 'always' | 'bare'
47
+ /** Custom parent route param name resolver (#1201) — wins over parentParamMode. */
48
+ routeParamResolver?: (ctx: RouteParamResolverContext) => string | undefined
44
49
  storageResolver?: unknown
45
50
  managerResolver?: unknown
46
51
  managerRegistry?: Record<string, unknown>
@@ -12,13 +12,13 @@
12
12
 
13
13
  import type { Component } from 'vue'
14
14
  import type { BlockConfig, ZoneOptions } from './KernelContext.types'
15
+ import type { KernelContext } from './KernelContext'
15
16
 
16
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
- type Self = any
17
+ // #1196 Phase B — this-typing against the real KernelContext shape (was Self = any)
18
+ type Self = KernelContext
18
19
 
19
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
- export function applyZoneMethods(KernelContextClass: { prototype: any }): void {
21
- const proto = KernelContextClass.prototype as Self
20
+ export function applyZoneMethods(KernelContextClass: { prototype: KernelContext }): void {
21
+ const proto = KernelContextClass.prototype
22
22
 
23
23
  proto.zone = function (this: Self, name: string, options: ZoneOptions = {}): Self {
24
24
  if (this._kernel.zoneRegistry) {
@@ -16,13 +16,24 @@ import { inject } from 'vue'
16
16
  import type { Orchestrator } from './Orchestrator'
17
17
  import type { EntityManager } from '../entity/EntityManager'
18
18
  import type { EntityRecord } from '../types'
19
+ // Type-only circular import: QdadmManagerRegistry must live in the package
20
+ // entry (module augmentation does not merge through re-export aliases).
21
+ import type { QdadmManagerRegistry } from '../index'
19
22
 
20
23
  /**
21
24
  * Return type for useOrchestrator
25
+ *
26
+ * `getManager` resolves through the consumer-augmentable
27
+ * QdadmManagerRegistry first (#1253): a declared entity name returns its
28
+ * concrete manager subclass; anything else falls back to the historical
29
+ * `EntityManager<T>` signature.
22
30
  */
23
31
  export interface UseOrchestratorReturn {
24
32
  orchestrator: Orchestrator
25
- getManager: <T extends EntityRecord = EntityRecord>(name: string) => EntityManager<T>
33
+ getManager: {
34
+ <K extends keyof QdadmManagerRegistry>(name: K): QdadmManagerRegistry[K]
35
+ <T extends EntityRecord = EntityRecord>(name: string): EntityManager<T>
36
+ }
26
37
  hasManager: (name: string) => boolean
27
38
  }
28
39
 
@@ -46,8 +57,10 @@ export function useOrchestrator(): UseOrchestratorReturn {
46
57
  * Get an EntityManager by name
47
58
  * @param name - Entity name
48
59
  */
49
- function getManager<T extends EntityRecord = EntityRecord>(name: string): EntityManager<T> {
50
- return orchestrator.get(name) as EntityManager<T>
60
+ function getManager<K extends keyof QdadmManagerRegistry>(name: K): QdadmManagerRegistry[K]
61
+ function getManager<T extends EntityRecord = EntityRecord>(name: string): EntityManager<T>
62
+ function getManager(name: string): unknown {
63
+ return orchestrator.get(name)
51
64
  }
52
65
 
53
66
  /**
@@ -74,7 +87,9 @@ export function useOrchestrator(): UseOrchestratorReturn {
74
87
  * const { items } = await users.list()
75
88
  * ```
76
89
  */
77
- export function useEntity<T extends EntityRecord = EntityRecord>(name: string): EntityManager<T> {
90
+ export function useEntity<K extends keyof QdadmManagerRegistry>(name: K): QdadmManagerRegistry[K]
91
+ export function useEntity<T extends EntityRecord = EntityRecord>(name: string): EntityManager<T>
92
+ export function useEntity(name: string): unknown {
78
93
  const { getManager } = useOrchestrator()
79
- return getManager<T>(name)
94
+ return getManager(name)
80
95
  }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Field-name humanization (#1255)
3
+ *
4
+ * Turns machine field names into presentable labels:
5
+ * 'botUuid' → 'Bot Uuid'
6
+ * 'created_at' → 'Created At'
7
+ * 'filter.botId' → 'Filter Bot Id'
8
+ *
9
+ * Shared by the list column binding helper (useListPage.column()) and the
10
+ * OpenAPI connector's opt-in label inference — dependency-free so the gen
11
+ * side (node) can import it too.
12
+ */
13
+
14
+ /**
15
+ * Humanize a field name: split camelCase, snake_case, kebab-case and dotted
16
+ * segments into words, then capitalize each word.
17
+ */
18
+ export function humanizeFieldName(field: string): string {
19
+ return field
20
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
21
+ .replace(/[_\-.]+/g, ' ')
22
+ .trim()
23
+ .split(/\s+/)
24
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
25
+ .join(' ')
26
+ }
@@ -21,6 +21,9 @@ export {
21
21
  // Error formatting
22
22
  export { formatFetchError, type FetchErrorLike } from './errors'
23
23
 
24
+ // Field-name humanization
25
+ export { humanizeFieldName } from './humanize'
26
+
24
27
  // Transformers
25
28
  export {
26
29
  toKeyValueArray,