@quazardous/qdadm 2.2.0 → 2.2.1
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/package.json +1 -1
- package/src/entity/EntityManager.cache.ts +4 -1
- package/src/entity/EntityManager.crud.ts +6 -0
- package/src/entity/EntityManager.query.ts +6 -3
- package/src/entity/EntityManager.ts +1 -0
- package/src/entity/EntityManager.types.ts +2 -0
- package/src/generated/managers/testManager.ts +0 -46
- package/src/kernel/Kernel.routing.ts +12 -3
package/package.json
CHANGED
|
@@ -90,7 +90,9 @@ export function applyCacheMethods(EntityManagerClass: { prototype: any }): void
|
|
|
90
90
|
Object.defineProperty(proto, 'overflow', {
|
|
91
91
|
get(this: Self): boolean {
|
|
92
92
|
const cache = this._cache
|
|
93
|
-
|
|
93
|
+
// overflowed: total exceeded effectiveThreshold, cache was never
|
|
94
|
+
// filled (#1204) — the cache is unusable either way.
|
|
95
|
+
return cache.overflowed === true || (cache.valid && cache.total > cache.items.length)
|
|
94
96
|
},
|
|
95
97
|
configurable: true,
|
|
96
98
|
})
|
|
@@ -398,6 +400,7 @@ export function applyCacheMethods(EntityManagerClass: { prototype: any }): void
|
|
|
398
400
|
cache.valid = false
|
|
399
401
|
cache.items = []
|
|
400
402
|
cache.total = 0
|
|
403
|
+
cache.overflowed = false
|
|
401
404
|
cache.loadedAt = null
|
|
402
405
|
this._cacheLoading = null
|
|
403
406
|
// Also clear detail cache
|
|
@@ -182,6 +182,7 @@ export function applyCrudMethods(EntityManagerClass: { prototype: any }): void {
|
|
|
182
182
|
cache.items = items
|
|
183
183
|
cache.total = total
|
|
184
184
|
cache.valid = true
|
|
185
|
+
cache.overflowed = false
|
|
185
186
|
cache.loadedAt = Date.now()
|
|
186
187
|
// Resolve parent fields for search (book.title, user.username, etc.)
|
|
187
188
|
await this._resolveSearchFields(items)
|
|
@@ -191,6 +192,11 @@ export function applyCrudMethods(EntityManagerClass: { prototype: any }): void {
|
|
|
191
192
|
// Fire-and-forget: load full cache in background
|
|
192
193
|
this._loadCacheInBackground()
|
|
193
194
|
}
|
|
195
|
+
} else if (canUseCache && this.isCacheEnabled && total > this.effectiveThreshold) {
|
|
196
|
+
// Entity outgrew the threshold: the cache can never hold it. Mark it
|
|
197
|
+
// so query() stops filtering an empty cache and goes to the API
|
|
198
|
+
// instead of returning an empty list (#1204).
|
|
199
|
+
cache.overflowed = true
|
|
194
200
|
}
|
|
195
201
|
|
|
196
202
|
return { items, total, fromCache: false }
|
|
@@ -31,7 +31,7 @@ export function applyQueryMethods(EntityManagerClass: { prototype: any }): void
|
|
|
31
31
|
// Ensure cache is filled (via list) — skip for dynamic endpoints
|
|
32
32
|
// since list() disables caching when resolveStorage provides an endpoint
|
|
33
33
|
const cache = this._cache
|
|
34
|
-
if (!isDynamicEndpoint && !cache.valid && this.isCacheEnabled) {
|
|
34
|
+
if (!isDynamicEndpoint && !cache.valid && !cache.overflowed && this.isCacheEnabled) {
|
|
35
35
|
await this.list(
|
|
36
36
|
{ page_size: this.effectiveThreshold },
|
|
37
37
|
routingContext ?? undefined
|
|
@@ -40,8 +40,11 @@ export function applyQueryMethods(EntityManagerClass: { prototype: any }): void
|
|
|
40
40
|
|
|
41
41
|
let result: ListResult<any>
|
|
42
42
|
|
|
43
|
-
// Dynamic endpoint, overflow,
|
|
44
|
-
|
|
43
|
+
// Dynamic endpoint, overflow, cache disabled, or cache still not
|
|
44
|
+
// valid (fill failed / threshold exceeded) → use API directly. The
|
|
45
|
+
// cache is an optional layer: it must never turn into an empty
|
|
46
|
+
// result when it can't hold the data (#1204).
|
|
47
|
+
if (isDynamicEndpoint || this.overflow || !this.isCacheEnabled || !cache.valid) {
|
|
45
48
|
result = await this.list(params, routingContext ?? undefined)
|
|
46
49
|
} else {
|
|
47
50
|
// Full cache available - filter locally
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TestManager - Auto-generated EntityManager
|
|
3
|
-
*
|
|
4
|
-
* Generated by qdadm/gen/generateManagers
|
|
5
|
-
* DO NOT EDIT MANUALLY - Changes will be overwritten
|
|
6
|
-
*
|
|
7
|
-
* Entity: test
|
|
8
|
-
* Endpoint: /test
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { EntityManager } from '@quazardous/qdadm'
|
|
12
|
-
import type { EntityRecord } from '@quazardous/qdadm'
|
|
13
|
-
import { ApiStorage } from '@quazardous/qdadm'
|
|
14
|
-
|
|
15
|
-
export interface TestEntity extends EntityRecord {
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Schema definition for test
|
|
20
|
-
*/
|
|
21
|
-
export const testSchema = {
|
|
22
|
-
name: "test",
|
|
23
|
-
endpoint: "/test",
|
|
24
|
-
fields: {}
|
|
25
|
-
} as const
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Storage options for test
|
|
29
|
-
*/
|
|
30
|
-
const storageOptions = {
|
|
31
|
-
endpoint: "/test"
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* TestManager instance
|
|
36
|
-
*
|
|
37
|
-
* Provides CRUD operations for test entity.
|
|
38
|
-
*/
|
|
39
|
-
export const testManager = new EntityManager<TestEntity>({
|
|
40
|
-
...{
|
|
41
|
-
name: "test",
|
|
42
|
-
idField: "id",
|
|
43
|
-
fields: {}
|
|
44
|
-
},
|
|
45
|
-
storage: new ApiStorage<TestEntity>(storageOptions)
|
|
46
|
-
})
|
|
@@ -212,7 +212,11 @@ export function applyRoutingMethods(KernelClass: { prototype: any }): void {
|
|
|
212
212
|
}
|
|
213
213
|
|
|
214
214
|
const entity = to.meta?.entity as string | undefined
|
|
215
|
-
|
|
215
|
+
// Entity not registered → nothing to check yet (e.g. child route
|
|
216
|
+
// declared before its manager loads) — allow. This is the ONLY
|
|
217
|
+
// allowed pass-through; a failing access check must fail CLOSED,
|
|
218
|
+
// not silently allow (#1190).
|
|
219
|
+
if (entity && this.orchestrator && this.orchestrator.isRegistered(entity)) {
|
|
216
220
|
try {
|
|
217
221
|
const manager = this.orchestrator.get(entity)
|
|
218
222
|
if (manager && !manager.canRead()) {
|
|
@@ -232,8 +236,13 @@ export function applyRoutingMethods(KernelClass: { prototype: any }): void {
|
|
|
232
236
|
next({ path: '/' })
|
|
233
237
|
return
|
|
234
238
|
}
|
|
235
|
-
} catch {
|
|
236
|
-
|
|
239
|
+
} catch (err) {
|
|
240
|
+
console.error(
|
|
241
|
+
`[qdadm] Access check failed for ${to.path} (entity: ${entity}) — denying navigation:`,
|
|
242
|
+
err
|
|
243
|
+
)
|
|
244
|
+
next({ path: '/' })
|
|
245
|
+
return
|
|
237
246
|
}
|
|
238
247
|
}
|
|
239
248
|
|