feat: implement new feature for enhanced user experience

This commit is contained in:
2026-05-17 14:19:45 +00:00
parent db968ab318
commit f332c707b7
214 changed files with 424 additions and 2562 deletions
+70 -2
View File
@@ -16,6 +16,7 @@
import contentData from "../../mocking/content.json"
import medialibData from "../../mocking/medialib.json"
import navigationData from "../../mocking/navigation.json"
import commentsData from "../../mocking/comments.json"
type EJsonObjectId = {
$oid: string
@@ -25,6 +26,7 @@ const mockRegistry: Record<string, Record<string, unknown>[]> = {
content: normalizeMockCollection(contentData as Record<string, unknown>[]),
medialib: normalizeMockCollection(medialibData as Record<string, unknown>[]),
navigation: normalizeMockCollection(navigationData as Record<string, unknown>[]),
comments: normalizeMockCollection(commentsData as Record<string, unknown>[]),
}
function isEJsonObjectId(value: unknown): value is EJsonObjectId {
@@ -88,7 +90,11 @@ export function mockApiRequest(endpoint: string, options?: ApiOptions, _body?: u
// --- Single-item retrieval ---
if (itemId) {
const item = sourceData.find((e) => e.id === itemId || e._id === itemId)
const resultItem = item ? applyLookups(cloneEntry(item), options) : null
let resultItem = item ? cloneEntry(item) : null
if (resultItem) {
resultItem = applyAggregate(resultItem, options)
resultItem = applyLookups(resultItem, options)
}
return {
data: resultItem,
count: resultItem ? 1 : 0,
@@ -119,7 +125,12 @@ export function mockApiRequest(endpoint: string, options?: ApiOptions, _body?: u
results = results.slice(0, options.limit)
}
results = results.map((entry) => applyLookups(cloneEntry(entry), options))
results = results.map((entry) => {
let e = cloneEntry(entry)
e = applyAggregate(e, options)
e = applyLookups(e, options)
return e
})
// Projection
if (options?.projection) {
@@ -230,6 +241,63 @@ function cloneEntry<T>(entry: T): T {
return JSON.parse(JSON.stringify(entry)) as T
}
function applyAggregate(entry: Record<string, unknown>, options?: ApiOptions): Record<string, unknown> {
const rawAggregate = options?.params?.aggregate
if (!rawAggregate) return entry
const aggregates = Array.isArray(rawAggregate)
? rawAggregate
: typeof rawAggregate === "string"
? rawAggregate.split(",")
: []
if (!entry._aggregate) {
entry._aggregate = {}
}
for (const spec of aggregates) {
try {
// Check for json object first
if (spec.startsWith("{")) {
// Not supported in this simple mock
continue
}
// "comments:contentId:count"
const parts = spec.split(":")
if (parts.length < 3) continue
const targetCollection = parts[0]
const foreignField = parts[1]
const operator = parts[2]
const lookupSource = mockRegistry[targetCollection]
if (!lookupSource) continue
const localId = entry._id
? typeof (entry._id as any).$oid === "string"
? (entry._id as any).$oid
: entry._id.toString()
: null
if (operator === "count") {
const count = lookupSource.filter((item) => {
const itemForeignId = item[foreignField]
? typeof (item[foreignField] as any).$oid === "string"
? (item[foreignField] as any).$oid
: (item[foreignField] as any).toString()
: null
return itemForeignId === localId && item.active !== false // basic mock rule
}).length
;(entry._aggregate as any)[`${targetCollection}Count`] = count
}
} catch (e) {
console.warn("Mock aggregate error", e)
}
}
return entry
}
function applyLookups(entry: Record<string, unknown>, options?: ApiOptions): Record<string, unknown> {
const lookupSpecs = parseLookupSpecs(options)
if (!lookupSpecs.length) return entry