@open-mercato/core 0.6.7-develop.6842.1.8cd8a8883c → 0.6.7-develop.6859.1.e4727b568a

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.
Files changed (115) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/bootstrap.js +16 -1
  3. package/dist/bootstrap.js.map +2 -2
  4. package/dist/generated/entities/attachment_quota_reservation/index.js +33 -0
  5. package/dist/generated/entities/attachment_quota_reservation/index.js.map +7 -0
  6. package/dist/generated/entities.ids.generated.js +2 -1
  7. package/dist/generated/entities.ids.generated.js.map +2 -2
  8. package/dist/generated/entity-fields-registry.js +17 -0
  9. package/dist/generated/entity-fields-registry.js.map +2 -2
  10. package/dist/modules/attachments/api/route.js +104 -8
  11. package/dist/modules/attachments/api/route.js.map +2 -2
  12. package/dist/modules/attachments/data/entities.js +67 -1
  13. package/dist/modules/attachments/data/entities.js.map +2 -2
  14. package/dist/modules/attachments/di.js +7 -1
  15. package/dist/modules/attachments/di.js.map +2 -2
  16. package/dist/modules/attachments/lib/drivers/index.js.map +1 -1
  17. package/dist/modules/attachments/lib/drivers/localDriver.js +19 -6
  18. package/dist/modules/attachments/lib/drivers/localDriver.js.map +2 -2
  19. package/dist/modules/attachments/lib/quota-recovery-queue.js +9 -0
  20. package/dist/modules/attachments/lib/quota-recovery-queue.js.map +7 -0
  21. package/dist/modules/attachments/lib/quota-service.js +224 -0
  22. package/dist/modules/attachments/lib/quota-service.js.map +7 -0
  23. package/dist/modules/attachments/migrations/Migration20260709234741_attachments.js +13 -0
  24. package/dist/modules/attachments/migrations/Migration20260709234741_attachments.js.map +7 -0
  25. package/dist/modules/attachments/workers/quota-recovery.js +45 -0
  26. package/dist/modules/attachments/workers/quota-recovery.js.map +7 -0
  27. package/dist/modules/auth/lib/setup-app.js +16 -2
  28. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  29. package/dist/modules/dashboards/services/widgetDataService.js +3 -4
  30. package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
  31. package/dist/modules/entities/api/definitions.js +2 -0
  32. package/dist/modules/entities/api/definitions.js.map +2 -2
  33. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +18 -3
  34. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  35. package/dist/modules/entities/cli.js +193 -19
  36. package/dist/modules/entities/cli.js.map +2 -2
  37. package/dist/modules/entities/components/RecordListRelationCell.js +63 -0
  38. package/dist/modules/entities/components/RecordListRelationCell.js.map +7 -0
  39. package/dist/modules/entities/components/recordListRelationDisplays.js +80 -0
  40. package/dist/modules/entities/components/recordListRelationDisplays.js.map +7 -0
  41. package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js +14 -1
  42. package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js.map +2 -2
  43. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +22 -17
  44. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
  45. package/dist/modules/messages/api/[id]/route.js +15 -0
  46. package/dist/modules/messages/api/[id]/route.js.map +2 -2
  47. package/dist/modules/query_index/api/reindex.js +10 -0
  48. package/dist/modules/query_index/api/reindex.js.map +2 -2
  49. package/dist/modules/query_index/cli.js +125 -1
  50. package/dist/modules/query_index/cli.js.map +2 -2
  51. package/dist/modules/query_index/lib/coverage.js +19 -7
  52. package/dist/modules/query_index/lib/coverage.js.map +2 -2
  53. package/dist/modules/query_index/lib/reindexer.js +43 -37
  54. package/dist/modules/query_index/lib/reindexer.js.map +2 -2
  55. package/dist/modules/query_index/lib/subscriber-scope.js +2 -3
  56. package/dist/modules/query_index/lib/subscriber-scope.js.map +2 -2
  57. package/dist/modules/sales/commands/documents.js +137 -22
  58. package/dist/modules/sales/commands/documents.js.map +2 -2
  59. package/dist/modules/sales/data/validators.js +2 -0
  60. package/dist/modules/sales/data/validators.js.map +2 -2
  61. package/dist/modules/sales/workflows.js +10 -7
  62. package/dist/modules/sales/workflows.js.map +2 -2
  63. package/dist/modules/workflows/lib/activity-executor.js +27 -0
  64. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  65. package/dist/modules/workflows/widgets/injection/order-approval/context-keys.js +10 -0
  66. package/dist/modules/workflows/widgets/injection/order-approval/context-keys.js.map +7 -0
  67. package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js +10 -6
  68. package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js.map +2 -2
  69. package/generated/entities/attachment_quota_reservation/index.ts +15 -0
  70. package/generated/entities.ids.generated.ts +2 -1
  71. package/generated/entity-fields-registry.ts +17 -0
  72. package/package.json +7 -7
  73. package/src/bootstrap.ts +17 -2
  74. package/src/modules/attachments/api/route.ts +114 -7
  75. package/src/modules/attachments/data/entities.ts +59 -0
  76. package/src/modules/attachments/di.ts +9 -1
  77. package/src/modules/attachments/i18n/de.json +3 -0
  78. package/src/modules/attachments/i18n/en.json +3 -0
  79. package/src/modules/attachments/i18n/es.json +3 -0
  80. package/src/modules/attachments/i18n/pl.json +3 -0
  81. package/src/modules/attachments/lib/drivers/index.ts +1 -1
  82. package/src/modules/attachments/lib/drivers/localDriver.ts +23 -8
  83. package/src/modules/attachments/lib/drivers/types.ts +5 -0
  84. package/src/modules/attachments/lib/quota-recovery-queue.ts +16 -0
  85. package/src/modules/attachments/lib/quota-service.ts +442 -0
  86. package/src/modules/attachments/migrations/.snapshot-open-mercato.json +648 -120
  87. package/src/modules/attachments/migrations/Migration20260709234741_attachments.ts +12 -0
  88. package/src/modules/attachments/workers/quota-recovery.ts +68 -0
  89. package/src/modules/auth/lib/setup-app.ts +20 -2
  90. package/src/modules/dashboards/services/widgetDataService.ts +3 -6
  91. package/src/modules/entities/api/definitions.ts +4 -0
  92. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +94 -77
  93. package/src/modules/entities/cli.ts +238 -21
  94. package/src/modules/entities/components/RecordListRelationCell.tsx +90 -0
  95. package/src/modules/entities/components/recordListRelationDisplays.ts +109 -0
  96. package/src/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.ts +17 -1
  97. package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +21 -16
  98. package/src/modules/inbox_ops/components/proposals/types.ts +1 -0
  99. package/src/modules/messages/api/[id]/route.ts +21 -0
  100. package/src/modules/query_index/api/reindex.ts +15 -0
  101. package/src/modules/query_index/cli.ts +180 -1
  102. package/src/modules/query_index/lib/coverage.ts +38 -8
  103. package/src/modules/query_index/lib/reindexer.ts +62 -40
  104. package/src/modules/query_index/lib/subscriber-scope.ts +2 -7
  105. package/src/modules/sales/commands/documents.ts +237 -29
  106. package/src/modules/sales/data/validators.ts +2 -0
  107. package/src/modules/sales/workflows.ts +10 -7
  108. package/src/modules/workflows/i18n/de.json +1 -0
  109. package/src/modules/workflows/i18n/en.json +1 -0
  110. package/src/modules/workflows/i18n/es.json +1 -0
  111. package/src/modules/workflows/i18n/ko.json +1 -0
  112. package/src/modules/workflows/i18n/pl.json +1 -0
  113. package/src/modules/workflows/lib/activity-executor.ts +40 -1
  114. package/src/modules/workflows/widgets/injection/order-approval/context-keys.ts +18 -0
  115. package/src/modules/workflows/widgets/injection/order-approval/widget.client.tsx +15 -6
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/entities/api/definitions.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { CacheStrategy } from '@open-mercato/cache'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'\nimport { CustomEntity, CustomFieldDef } from '@open-mercato/core/modules/entities/data/entities'\nimport { upsertCustomFieldDefSchema, fieldsetCodeRegex } from '@open-mercato/core/modules/entities/data/validators'\nimport {\n createDefinitionsCacheKey,\n createDefinitionsCacheTags,\n invalidateDefinitionsCache,\n ENTITY_DEFINITIONS_CACHE_TTL_MS,\n} from './definitions.cache'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { filterSelectableSystemEntityIds, isSystemEntitySelectable } from '@open-mercato/shared/lib/entities/system-entities'\nimport { isOrmBackedSystemEntityId } from '@open-mercato/shared/lib/data/engine'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport { loadEntityFieldsetConfigs, CustomFieldsetDefinition } from '../lib/fieldsets'\nimport { installCustomEntitiesFromModules } from '../lib/install-from-ce'\nimport { normalizeCustomFieldOptions } from '@open-mercato/shared/modules/entities/options'\nimport { CURRENCY_OPTIONS_URL } from '@open-mercato/shared/modules/entities/kinds'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n beginEntitiesMutationGuard,\n FIELD_DEFINITION_RESOURCE_KIND,\n} from './definitions.mutation-guard'\nimport {\n canReadAllEntityMetadata,\n canReadEntityMetadata,\n getDeclaredCustomEntityRestriction,\n resolveEntityAclRequirement,\n} from '../lib/entityAcl'\nimport {\n createExactDefinitionWhere,\n createScopedDefinitionTombstone,\n createVisibleDefinitionWhere,\n markDefinitionTombstoned,\n resolveDefinitionScopeFromOrganizationScope,\n resolveDefinitionMutationScope,\n selectVisibleDefinitionWinner,\n} from '../lib/definition-scope'\nimport { resolveEntityDefinitionsVersion } from '../lib/definitions-version'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('entities').child({ component: 'definitions' })\n\n/**\n * Validate defaultValue against the field kind. Returns an error message string\n * if invalid, or null if valid. For dictionary and currency kinds, queries the\n * database to verify the token exists.\n */\nasync function validateDefaultValueByKind(\n value: unknown,\n kind: string,\n cfg: Record<string, unknown>,\n em: EntityManager,\n tenantContext: { tenantId: string | null; organizationId: string | null },\n): Promise<string | null> {\n switch (kind) {\n case 'boolean':\n if (typeof value !== 'boolean') return 'defaultValue for boolean fields must be true or false'\n return null\n case 'integer':\n if (typeof value !== 'number' || !Number.isInteger(value))\n return 'defaultValue for integer fields must be a whole number'\n return null\n case 'float':\n if (typeof value !== 'number' || !isFinite(value))\n return 'defaultValue for float fields must be a finite number'\n return null\n case 'text':\n case 'multiline':\n case 'date':\n case 'datetime':\n if (typeof value !== 'string')\n return `defaultValue for ${kind} fields must be a string`\n return null\n case 'dictionary': {\n if (typeof value !== 'string')\n return 'defaultValue for dictionary fields must be a string'\n const dictionaryId = typeof cfg.dictionaryId === 'string' ? cfg.dictionaryId.trim() : ''\n if (dictionaryId) {\n try {\n const { DictionaryEntry } = await import('@open-mercato/core/modules/dictionaries/data/entities')\n const entry = await em.findOne(DictionaryEntry, {\n dictionary: dictionaryId,\n value: value,\n ...(tenantContext.organizationId ? { organizationId: tenantContext.organizationId } : {}),\n ...(tenantContext.tenantId ? { tenantId: tenantContext.tenantId } : {}),\n })\n if (!entry) return `defaultValue \"${value}\" does not match any entry in the configured dictionary`\n } catch (err) {\n // If the dictionaries module is not available, skip entry validation\n logger.debug('Dictionary validation skipped \u2014 module not available', { err })\n }\n }\n return null\n }\n case 'currency': {\n if (typeof value !== 'string')\n return 'defaultValue for currency fields must be a string'\n try {\n const { Currency } = await import('@open-mercato/core/modules/currencies/data/entities')\n const where: Record<string, string> = { code: value as string }\n if (tenantContext.tenantId) where.tenantId = tenantContext.tenantId\n if (tenantContext.organizationId) where.organizationId = tenantContext.organizationId\n const currency = await em.findOne(Currency, where)\n if (!currency) return `defaultValue \"${value}\" does not match any available currency`\n } catch (err) {\n // If the currencies module is not available, skip currency validation\n logger.debug('Currency validation skipped \u2014 module not available', { err })\n }\n return null\n }\n case 'select': {\n if (typeof value !== 'string' && typeof value !== 'number')\n return 'defaultValue for select fields must be a string or number'\n const options = normalizeCustomFieldOptions(\n Array.isArray(cfg.options) ? cfg.options : [],\n )\n if (options.length > 0) {\n const match = options.some(\n (o) => o.value === value || String(o.value) === String(value),\n )\n if (!match) return 'defaultValue does not match any of the configured options'\n }\n return null\n }\n case 'relation':\n case 'attachment':\n return `defaultValue is not supported for ${kind} fields`\n default:\n return null\n }\n}\n\n/**\n * Normalize defaultValue to the canonical storage shape for the given kind.\n */\nfunction normalizeDefaultValueByKind(value: unknown, kind: string): unknown {\n switch (kind) {\n case 'boolean':\n return value === true\n case 'integer':\n return Math.round(Number(value))\n case 'float':\n return Number(value)\n default:\n return value\n }\n}\n\nexport const metadata = {\n // Reading definitions is needed by record forms; keep it auth-protected but accessible to all authenticated users\n GET: { requireAuth: true },\n // Mutations remain admin-only\n POST: { requireAuth: true, requireFeatures: ['entities.definitions.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['entities.definitions.manage'] },\n}\n\nfunction parseEntityIds(url: URL): string[] {\n const direct = url.searchParams.getAll('entityId').filter((id) => typeof id === 'string' && id.trim().length > 0)\n const combined = url.searchParams.get('entityIds')\n if (combined) {\n combined\n .split(',')\n .map((id) => id.trim())\n .filter((id) => id.length > 0)\n .forEach((id) => direct.push(id))\n }\n const unique: string[] = []\n const seen = new Set<string>()\n for (const id of direct) {\n if (seen.has(id)) continue\n seen.add(id)\n unique.push(id)\n }\n return unique\n}\n\nasync function resolveEntityDefaultEditor(em: any, entityId: string, tenantId: string | null | undefined): Promise<string | undefined> {\n try {\n const ent = await em.findOne(CustomEntity, {\n entityId,\n $and: [\n { $or: [ { tenantId: tenantId ?? undefined as any }, { tenantId: null } ] },\n ],\n } as any)\n if (ent && typeof (ent as any).defaultEditor === 'string') return (ent as any).defaultEditor\n } catch {}\n return undefined\n}\n\nfunction normalizeFieldGroup(raw: unknown): { code: string; title?: string; hint?: string } | undefined {\n if (!raw) return undefined\n if (typeof raw === 'string') {\n const code = raw.trim()\n return code ? { code } : undefined\n }\n if (typeof raw !== 'object') return undefined\n const entry = raw as Record<string, unknown>\n const code = typeof entry.code === 'string' ? entry.code.trim() : ''\n if (!code) return undefined\n const group: { code: string; title?: string; hint?: string } = { code }\n if (typeof entry.title === 'string' && entry.title.trim()) group.title = entry.title.trim()\n if (typeof entry.hint === 'string' && entry.hint.trim()) group.hint = entry.hint.trim()\n return group\n}\n\nfunction definitionMatchesReadScope(\n definition: { tenantId?: string | null; organizationId?: string | null },\n scope: { tenantId: string | null; organizationId: string | null },\n) {\n const definitionTenantId = definition.tenantId ?? null\n const definitionOrganizationId = definition.organizationId ?? null\n const tenantMatches = definitionTenantId === null || definitionTenantId === scope.tenantId\n const organizationMatches =\n definitionOrganizationId === null ||\n (scope.organizationId !== null && definitionOrganizationId === scope.organizationId)\n return tenantMatches && organizationMatches\n}\n\nexport async function GET(req: Request) {\n const url = new URL(req.url)\n const requestedEntityIds = parseEntityIds(url)\n if (!requestedEntityIds.length) {\n return NextResponse.json({ error: 'entityId is required' }, { status: 400 })\n }\n const requestedFieldset = url.searchParams.get('fieldset')\n const fieldsetFilter = requestedFieldset && requestedFieldset.trim().length ? requestedFieldset.trim() : null\n\n const auth = await getAuthFromRequest(req)\n if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const selectableEntityIds = filterSelectableSystemEntityIds(requestedEntityIds)\n if (!selectableEntityIds.length) {\n return NextResponse.json({ items: [] })\n }\n\n const container = await createRequestContainer()\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req })\n const definitionScope = resolveDefinitionScopeFromOrganizationScope(auth, scope)\n const tenantId = definitionScope.tenantId\n if (!tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const organizationId = definitionScope.organizationId\n const { resolve } = container\n const em = resolve('em') as any\n const rbac = resolve('rbacService') as RbacService\n const acl = await rbac.loadAcl(auth.sub ?? '', {\n tenantId,\n organizationId,\n })\n const designerCanRead = canReadAllEntityMetadata(acl)\n const customEntityRestrictions = new Map<string, boolean>()\n for (const entityId of selectableEntityIds) {\n if (isOrmBackedSystemEntityId(em, entityId)) continue\n const declaredRestriction = getDeclaredCustomEntityRestriction(entityId)\n if (declaredRestriction !== undefined) customEntityRestrictions.set(entityId, declaredRestriction)\n }\n if (!designerCanRead) {\n const unresolvedEntityIds = selectableEntityIds.filter(\n (entityId) => !resolveEntityAclRequirement(entityId) && !customEntityRestrictions.has(entityId),\n )\n if (unresolvedEntityIds.length) {\n const registrations = await em.find(CustomEntity as any, {\n entityId: { $in: unresolvedEntityIds },\n isActive: true,\n $and: [\n { $or: [{ tenantId }, { tenantId: null }] },\n { $or: [{ organizationId }, { organizationId: null }] },\n ],\n } as any)\n for (const registration of registrations as any[]) {\n const entityId = String(registration.entityId)\n if (!isOrmBackedSystemEntityId(em, entityId)) {\n customEntityRestrictions.set(entityId, registration.accessRestricted === true)\n }\n }\n }\n }\n const entityIds = selectableEntityIds.filter((entityId) => canReadEntityMetadata({\n entityId,\n isCustomEntity: customEntityRestrictions.has(entityId),\n isRestricted: customEntityRestrictions.get(entityId) === true,\n acl,\n }))\n if (!entityIds.length) {\n return NextResponse.json({ items: [], fieldsetsByEntity: {}, entitySettings: {} })\n }\n let cache: CacheStrategy | undefined\n try {\n cache = resolve('cache') as CacheStrategy\n } catch {}\n\n let canManageDefinitions = false\n if (typeof auth.sub === 'string' && auth.sub.length > 0) {\n try {\n canManageDefinitions = await rbac.userHasAllFeatures(auth.sub, ['entities.definitions.manage'], {\n tenantId,\n organizationId,\n })\n } catch {\n // RBAC service unavailable \u2014 fall back to read-only (no definition sync)\n }\n }\n\n if (canManageDefinitions) {\n try {\n await installCustomEntitiesFromModules(em, cache, {\n tenantIds: [tenantId],\n entityIds,\n includeGlobal: true,\n createOnly: true,\n })\n } catch (err) {\n logger.warn('Failed to synchronize module-backed definitions', {\n tenantId,\n entityIds,\n err,\n })\n }\n }\n\n let cacheKey: string | null = null\n if (cache && !fieldsetFilter) {\n cacheKey = createDefinitionsCacheKey({\n tenantId,\n organizationId,\n entityIds,\n })\n try {\n const cached = await cache.get(cacheKey)\n if (cached) {\n return NextResponse.json(cached)\n }\n } catch (err) {\n logger.warn('Failed to read cache', { err })\n }\n }\n\n const fieldsetConfigs = await loadEntityFieldsetConfigs(em, {\n entityIds,\n tenantId,\n organizationId,\n mode: 'public',\n })\n\n const tenantCandidates = [{ tenantId }, { tenantId: null as string | null }]\n const organizationCandidates = [{ organizationId: null as string | null }]\n if (organizationId) organizationCandidates.unshift({ organizationId })\n const readScope = { tenantId, organizationId }\n\n const whereActive = {\n entityId: { $in: entityIds as any },\n deletedAt: null,\n $and: [\n { $or: tenantCandidates },\n { $or: organizationCandidates },\n ],\n } as any\n const defs = (await em.find(CustomFieldDef, whereActive as any))\n .filter((definition: any) => definitionMatchesReadScope(definition, readScope))\n const tombstones = (await em.find(CustomFieldDef, {\n entityId: { $in: entityIds as any },\n deletedAt: { $ne: null } as any,\n $and: [\n { $or: tenantCandidates },\n { $or: organizationCandidates },\n ],\n } as any)).filter((definition: any) => definitionMatchesReadScope(definition, readScope))\n\n const tombstonedByEntity = new Map<string, Set<string>>()\n for (const entry of tombstones as any[]) {\n const eid = String(entry.entityId)\n if (!tombstonedByEntity.has(eid)) tombstonedByEntity.set(eid, new Set())\n tombstonedByEntity.get(eid)!.add(entry.key)\n }\n\n const scopeScore = (x: any) => (x.tenantId ? 2 : 0) + (x.organizationId ? 1 : 0)\n\n const definitionsByEntity = new Map<string, any[]>()\n for (const d of defs) {\n const eid = String(d.entityId)\n if (!definitionsByEntity.has(eid)) definitionsByEntity.set(eid, [])\n definitionsByEntity.get(eid)!.push(d)\n }\n\n const entityDefaultEditors = new Map<string, string | undefined>()\n for (const entityId of entityIds) {\n const editor = await resolveEntityDefaultEditor(em, entityId, tenantId ?? null)\n entityDefaultEditors.set(entityId, editor)\n }\n\n const items: any[] = []\n\n const entityOrder = new Map<string, number>()\n entityIds.forEach((id, idx) => entityOrder.set(id, idx))\n\n for (const entityId of entityIds) {\n const defsForEntity = definitionsByEntity.get(entityId) ?? []\n if (!defsForEntity.length) continue\n const tombstonedKeys = tombstonedByEntity.get(entityId) ?? new Set<string>()\n const byKey = new Map<string, any>()\n for (const d of defsForEntity) {\n const existing = byKey.get(d.key)\n if (!existing) { byKey.set(d.key, d); continue }\n const sNew = scopeScore(d)\n const sOld = scopeScore(existing)\n if (sNew > sOld) { byKey.set(d.key, d); continue }\n if (sNew < sOld) continue\n const tNew = (d.updatedAt instanceof Date) ? d.updatedAt.getTime() : new Date(d.updatedAt).getTime()\n const tOld = (existing.updatedAt instanceof Date) ? existing.updatedAt.getTime() : new Date(existing.updatedAt).getTime()\n if (tNew >= tOld) byKey.set(d.key, d)\n }\n\n const defaultEditor = entityDefaultEditors.get(entityId)\n const winning = Array.from(byKey.values()).filter((d: any) => (d.isActive !== false) && !tombstonedKeys.has(d.key))\n winning.sort((a: any, b: any) => ((a.configJson?.priority ?? 0) - (b.configJson?.priority ?? 0)))\n\n for (const d of winning) {\n const rawFieldset = typeof d.configJson?.fieldset === 'string' ? d.configJson.fieldset.trim() : ''\n const normalizedFieldset = rawFieldset.length > 0 ? rawFieldset : undefined\n const normalizedFieldsets = Array.isArray(d.configJson?.fieldsets)\n ? d.configJson.fieldsets\n .filter((entry: unknown): entry is string => typeof entry === 'string')\n .map((entry: string) => entry.trim())\n .filter((entry: string) => entry.length > 0)\n : []\n const effectiveFieldsets = normalizedFieldsets.length > 0\n ? normalizedFieldsets\n : (normalizedFieldset ? [normalizedFieldset] : [])\n if (fieldsetFilter && !effectiveFieldsets.includes(fieldsetFilter)) continue\n const groupInfo = normalizeFieldGroup(d.configJson?.group)\n const keyLower = String(d.key).toLowerCase()\n const candidateBase = {\n key: d.key,\n kind: d.kind,\n label: d.configJson?.label || d.key,\n description: d.configJson?.description || undefined,\n multi: Boolean(d.configJson?.multi),\n options: (() => {\n if (d.kind === 'currency') return undefined\n const normalizedOptions = normalizeCustomFieldOptions(d.configJson?.options)\n return normalizedOptions.length ? normalizedOptions : undefined\n })(),\n optionsUrl: (() => {\n if (d.kind === 'currency') return CURRENCY_OPTIONS_URL\n const dictionaryId = typeof d.configJson?.dictionaryId === 'string' ? d.configJson.dictionaryId : undefined\n if (dictionaryId) return `/api/dictionaries/${dictionaryId}/entries`\n return typeof d.configJson?.optionsUrl === 'string' ? d.configJson.optionsUrl : undefined\n })(),\n filterable: Boolean(d.configJson?.filterable),\n formEditable: d.configJson?.formEditable !== undefined ? Boolean(d.configJson.formEditable) : true,\n listVisible: d.configJson?.listVisible !== undefined ? Boolean(d.configJson.listVisible) : true,\n editor: typeof d.configJson?.editor === 'string'\n ? d.configJson.editor\n : (d.kind === 'multiline' ? defaultEditor : undefined),\n input: typeof d.configJson?.input === 'string' ? d.configJson.input : undefined,\n dictionaryId: typeof d.configJson?.dictionaryId === 'string' ? d.configJson.dictionaryId : undefined,\n dictionaryInlineCreate: d.configJson?.dictionaryInlineCreate !== undefined\n ? Boolean(d.configJson.dictionaryInlineCreate)\n : undefined,\n priority: typeof d.configJson?.priority === 'number' ? d.configJson.priority : 0,\n validation: Array.isArray(d.configJson?.validation) ? d.configJson.validation : undefined,\n defaultValue: d.configJson?.defaultValue !== undefined ? d.configJson.defaultValue : undefined,\n // attachments config passthrough\n maxAttachmentSizeMb: typeof d.configJson?.maxAttachmentSizeMb === 'number' ? d.configJson.maxAttachmentSizeMb : undefined,\n acceptExtensions: Array.isArray(d.configJson?.acceptExtensions) ? d.configJson.acceptExtensions : undefined,\n // phone config passthrough\n defaultCountryIso2: typeof d.configJson?.defaultCountryIso2 === 'string' ? d.configJson.defaultCountryIso2 : undefined,\n entityId,\n fieldset: normalizedFieldset ?? effectiveFieldsets[0],\n fieldsets: effectiveFieldsets.length > 0 ? effectiveFieldsets : undefined,\n group: groupInfo,\n } as any\n const metrics = computeDefinitionScore(d, candidateBase, entityOrder.get(entityId) ?? Number.MAX_SAFE_INTEGER)\n const candidate = { ...candidateBase, __score: metrics }\n const existing = (items as any[]).find((entry) => entry.key.toLowerCase() === keyLower)\n if (!existing) {\n items.push(candidate)\n continue\n }\n const existingScore = existing.__score as { base: number; penalty: number; entityIndex: number }\n const candidateScoreInfo = candidate.__score as { base: number; penalty: number; entityIndex: number }\n const better =\n candidateScoreInfo.base > existingScore.base ||\n (candidateScoreInfo.base === existingScore.base && candidateScoreInfo.penalty < existingScore.penalty) ||\n (candidateScoreInfo.base === existingScore.base && candidateScoreInfo.penalty === existingScore.penalty && candidateScoreInfo.entityIndex < existingScore.entityIndex)\n if (better) {\n const index = items.findIndex((entry) => entry.key.toLowerCase() === keyLower)\n if (index >= 0) items[index] = candidate\n }\n }\n }\n\n const sanitized = items.map((item: any) => {\n const { __score, ...rest } = item\n return rest\n })\n sanitized.sort((a: any, b: any) => ((a.priority ?? 0) - (b.priority ?? 0)))\n\n const fieldsetsByEntity: Record<string, CustomFieldsetDefinition[]> = {}\n const entitySettings: Record<string, { singleFieldsetPerRecord: boolean }> = {}\n for (const entityId of entityIds) {\n const cfg = fieldsetConfigs.get(entityId) ?? { fieldsets: [], singleFieldsetPerRecord: true }\n fieldsetsByEntity[entityId] = cfg.fieldsets\n entitySettings[entityId] = { singleFieldsetPerRecord: cfg.singleFieldsetPerRecord }\n }\n\n const responseBody = { items: sanitized, fieldsetsByEntity, entitySettings }\n\n if (cache && cacheKey && !fieldsetFilter) {\n const tags = createDefinitionsCacheTags({\n tenantId,\n organizationId,\n entityIds,\n })\n try {\n await cache.set(cacheKey, responseBody, {\n ttl: ENTITY_DEFINITIONS_CACHE_TTL_MS,\n tags,\n })\n } catch (err) {\n logger.warn('Failed to store cache entry', { err })\n }\n }\n\n return NextResponse.json(responseBody)\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.orgId) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n let body: any\n try { body = await req.json() } catch { return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 }) }\n const parsed = upsertCustomFieldDefSchema.safeParse(body)\n if (!parsed.success) return NextResponse.json({ error: 'Validation failed', details: parsed.error.flatten() }, { status: 400 })\n const input = parsed.data\n\n if (!isSystemEntitySelectable(input.entityId)) {\n return NextResponse.json({ error: 'Custom fields are not supported for this entity' }, { status: 400 })\n }\n\n if (input.kind === 'dictionary') {\n const dictionaryId = input.configJson?.dictionaryId\n if (typeof dictionaryId !== 'string' || dictionaryId.trim().length === 0) {\n return NextResponse.json({ error: 'dictionaryId is required for dictionary custom fields' }, { status: 400 })\n }\n }\n\n const container = await createRequestContainer()\n const scope = await resolveDefinitionMutationScope({ auth, container, request: req })\n const { resolve } = container\n const em = resolve('em') as any\n let cache: CacheStrategy | undefined\n try {\n cache = resolve('cache') as CacheStrategy\n } catch {}\n\n const where: any = createExactDefinitionWhere(input.entityId, input.key, scope)\n let def = await em.findOne(CustomFieldDef, where)\n\n const guard = await beginEntitiesMutationGuard({\n container,\n auth,\n req,\n resourceKind: FIELD_DEFINITION_RESOURCE_KIND,\n resourceId: def ? def.id : `${input.entityId}:${input.key}`,\n operation: def ? 'update' : 'create',\n mutationPayload: input as unknown as Record<string, unknown>,\n })\n if (guard.blockedResponse) return guard.blockedResponse\n\n if (!def) def = em.create(CustomFieldDef, { ...where, createdAt: new Date() })\n def.kind = input.kind\n const inCfg = (input as any).configJson ?? {}\n const cfg: Record<string, any> = { ...inCfg }\n if (cfg.label == null || String(cfg.label).trim() === '') cfg.label = input.key\n if (cfg.formEditable === undefined) cfg.formEditable = true\n if (cfg.listVisible === undefined) cfg.listVisible = true\n if (input.kind === 'dictionary') {\n const dictionaryId = typeof cfg.dictionaryId === 'string' ? cfg.dictionaryId.trim() : ''\n cfg.dictionaryId = dictionaryId\n cfg.dictionaryInlineCreate = cfg.dictionaryInlineCreate !== false\n }\n if (input.kind === 'currency') {\n cfg.optionsUrl = CURRENCY_OPTIONS_URL\n if (Array.isArray(cfg.options)) delete cfg.options\n }\n if (input.kind === 'multiline' && (cfg.editor == null || String(cfg.editor).trim() === '')) {\n cfg.editor = 'markdown'\n }\n // Validate and normalize defaultValue by kind before persisting\n if (cfg.defaultValue !== undefined && cfg.defaultValue !== null) {\n const validationError = await validateDefaultValueByKind(\n cfg.defaultValue, input.kind, cfg, em,\n { tenantId: scope.tenantId, organizationId: scope.organizationId },\n )\n if (validationError) {\n return NextResponse.json({ error: validationError }, { status: 400 })\n }\n cfg.defaultValue = normalizeDefaultValueByKind(cfg.defaultValue, input.kind)\n }\n def.configJson = cfg\n def.isActive = input.isActive ?? true\n def.deletedAt = def.isActive === false ? (def.deletedAt ?? new Date()) : null\n def.updatedAt = new Date()\n em.persist(def)\n await em.flush()\n await guard.runAfterSuccess()\n await invalidateDefinitionsCache(cache, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n entityIds: [input.entityId],\n })\n // Changing field definitions may impact forms but not sidebar items; no nav cache touch\n return NextResponse.json({ ok: true, item: { id: def.id, key: def.key, kind: def.kind, configJson: def.configJson, isActive: def.isActive } })\n}\n\nexport async function DELETE(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.orgId) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n let body: any\n try { body = await req.json() } catch { return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 }) }\n const { entityId, key } = body || {}\n if (!entityId || !key) return NextResponse.json({ error: 'entityId and key are required' }, { status: 400 })\n\n const container = await createRequestContainer()\n const scope = await resolveDefinitionMutationScope({ auth, container, request: req })\n const { resolve } = container\n const em = resolve('em') as any\n let cache: CacheStrategy | undefined\n try {\n cache = resolve('cache') as CacheStrategy\n } catch {}\n const where: any = createExactDefinitionWhere(entityId, key, scope)\n let def = await em.findOne(CustomFieldDef, where)\n let inherited: any | null = null\n if (!def) {\n inherited = selectVisibleDefinitionWinner(await em.find(CustomFieldDef, createVisibleDefinitionWhere(\n entityId,\n key,\n scope,\n { deletedAt: null, isActive: true },\n )))\n if (!inherited) return NextResponse.json({ error: 'Not found' }, { status: 404 })\n }\n\n const guard = await beginEntitiesMutationGuard({\n container,\n auth,\n req,\n resourceKind: FIELD_DEFINITION_RESOURCE_KIND,\n resourceId: def?.id ?? inherited?.id ?? `${entityId}:${key}`,\n operation: 'delete',\n mutationPayload: { entityId, key },\n })\n if (guard.blockedResponse) return guard.blockedResponse\n\n if (!def) {\n def = createScopedDefinitionTombstone(em, inherited, scope)\n } else {\n markDefinitionTombstoned(def)\n }\n em.persist(def)\n await em.flush()\n await guard.runAfterSuccess()\n await invalidateDefinitionsCache(cache, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n entityIds: [entityId],\n })\n // Changing field definitions may impact forms but not sidebar items; no nav cache touch\n // Return the post-delete aggregate version so the edit form keeps its optimistic-lock\n // token in sync after removing a field out-of-band (issue #3152).\n const version = await resolveEntityDefinitionsVersion(em, {\n entityId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n return NextResponse.json({ ok: true, version })\n}\n\nconst definitionsQuerySchema = z\n .object({\n entityId: z.union([z.string(), z.array(z.string())]).optional(),\n entityIds: z.string().optional(),\n fieldset: z.string().regex(fieldsetCodeRegex).optional(),\n })\n .refine(\n (value) => {\n if (value.entityId && typeof value.entityId === 'string' && value.entityId.trim().length > 0) return true\n if (Array.isArray(value.entityId) && value.entityId.length > 0) return true\n return typeof value.entityIds === 'string' && value.entityIds.trim().length > 0\n },\n { message: 'Provide at least one entityId or an entityIds list.' }\n )\n\nconst customFieldOptionValueSchema = z.union([z.string(), z.number()])\n\nconst customFieldDefinitionSchema = z.object({\n key: z.string(),\n kind: z.string(),\n label: z.string(),\n description: z.string().optional(),\n multi: z.boolean().optional(),\n options: z.array(customFieldOptionValueSchema).optional(),\n optionsUrl: z.string().optional(),\n filterable: z.boolean().optional(),\n formEditable: z.boolean().optional(),\n listVisible: z.boolean().optional(),\n editor: z.string().optional(),\n input: z.string().optional(),\n dictionaryId: z.string().optional(),\n dictionaryInlineCreate: z.boolean().optional(),\n priority: z.number().optional(),\n validation: z.array(z.any()).optional(),\n defaultValue: z.union([z.string(), z.number(), z.boolean(), z.null()]).optional(),\n maxAttachmentSizeMb: z.number().optional(),\n acceptExtensions: z.array(z.any()).optional(),\n entityId: z.string(),\n fieldset: z.string().optional(),\n group: z\n .object({\n code: z.string(),\n title: z.string().optional(),\n hint: z.string().optional(),\n })\n .optional(),\n})\n\nconst customFieldsetGroupResponseSchema = z.object({\n code: z.string(),\n title: z.string().optional(),\n hint: z.string().optional(),\n})\n\nconst entityFieldsetResponseSchema = z.object({\n code: z.string(),\n label: z.string(),\n icon: z.string().optional(),\n description: z.string().optional(),\n groups: z.array(customFieldsetGroupResponseSchema).optional(),\n})\n\nconst definitionsResponseSchema = z.object({\n items: z.array(customFieldDefinitionSchema),\n fieldsetsByEntity: z.record(z.string(), z.array(entityFieldsetResponseSchema)).optional(),\n entitySettings: z\n .record(\n z.string(),\n z.object({\n singleFieldsetPerRecord: z.boolean().optional(),\n })\n )\n .optional(),\n})\n\nconst upsertDefinitionResponseSchema = z.object({\n ok: z.literal(true),\n item: z.object({\n id: z.string().uuid(),\n key: z.string(),\n kind: z.string(),\n configJson: z.record(z.string(), z.any()),\n isActive: z.boolean().optional(),\n }),\n})\n\nconst deleteDefinitionRequestSchema = z.object({\n entityId: z.string(),\n key: z.string(),\n})\n\nconst deleteDefinitionResponseSchema = z.object({\n ok: z.literal(true),\n version: z.string().nullable().optional(),\n})\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Entities',\n summary: 'Manage custom field definitions',\n methods: {\n GET: {\n summary: 'List active custom field definitions',\n description: 'Returns active custom field definitions for the supplied entity ids, respecting tenant scope and tombstones.',\n query: definitionsQuerySchema,\n responses: [\n {\n status: 200,\n description: 'Definition list',\n schema: definitionsResponseSchema,\n },\n {\n status: 400,\n description: 'Missing entity id',\n schema: z.object({ error: z.string() }),\n },\n {\n status: 401,\n description: 'Missing authentication',\n schema: z.object({ error: z.string() }),\n },\n ],\n },\n POST: {\n summary: 'Upsert custom field definition',\n description: 'Creates or updates a custom field definition for the current tenant/org scope.',\n requestBody: {\n contentType: 'application/json',\n schema: upsertCustomFieldDefSchema,\n },\n responses: [\n {\n status: 200,\n description: 'Definition saved',\n schema: upsertDefinitionResponseSchema,\n },\n {\n status: 400,\n description: 'Validation failed',\n schema: z.object({\n error: z.string(),\n details: z.any().optional(),\n }),\n },\n {\n status: 401,\n description: 'Missing authentication',\n schema: z.object({ error: z.string() }),\n },\n ],\n },\n DELETE: {\n summary: 'Soft delete custom field definition',\n description: 'Marks the specified definition inactive and tombstones it for the current scope.',\n requestBody: {\n contentType: 'application/json',\n schema: deleteDefinitionRequestSchema,\n },\n responses: [\n {\n status: 200,\n description: 'Definition deleted',\n schema: deleteDefinitionResponseSchema,\n },\n {\n status: 400,\n description: 'Missing entity id or key',\n schema: z.object({ error: z.string() }),\n },\n {\n status: 401,\n description: 'Missing authentication',\n schema: z.object({ error: z.string() }),\n },\n {\n status: 404,\n description: 'Definition not found',\n schema: z.object({ error: z.string() }),\n },\n ],\n },\n },\n}\nconst computeDefinitionScore = (def: any, cfg: Record<string, any>, entityIndex: number) => {\n const listVisibleScore = cfg.listVisible === false ? 0 : 1\n const formEditableScore = cfg.formEditable === false ? 0 : 1\n const filterableScore = cfg.filterable ? 1 : 0\n const kindScore = (() => {\n switch (def.kind) {\n case 'dictionary':\n return 8\n case 'relation':\n return 6\n case 'select':\n case 'currency':\n return 4\n case 'multiline':\n return 3\n case 'boolean':\n case 'integer':\n case 'float':\n return 2\n default:\n return 1\n }\n })()\n const optionsBonus = Array.isArray(cfg.options) && cfg.options.length ? 2 : 0\n const dictionaryBonus = typeof cfg.dictionaryId === 'string' && cfg.dictionaryId.trim().length ? 5 : 0\n const base = (listVisibleScore * 16) + (formEditableScore * 8) + (filterableScore * 4) + kindScore + optionsBonus + dictionaryBonus\n const penalty = typeof cfg.priority === 'number' ? cfg.priority : 0\n return { base, penalty, entityIndex }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { CacheStrategy } from '@open-mercato/cache'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'\nimport { CustomEntity, CustomFieldDef } from '@open-mercato/core/modules/entities/data/entities'\nimport { upsertCustomFieldDefSchema, fieldsetCodeRegex } from '@open-mercato/core/modules/entities/data/validators'\nimport {\n createDefinitionsCacheKey,\n createDefinitionsCacheTags,\n invalidateDefinitionsCache,\n ENTITY_DEFINITIONS_CACHE_TTL_MS,\n} from './definitions.cache'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { filterSelectableSystemEntityIds, isSystemEntitySelectable } from '@open-mercato/shared/lib/entities/system-entities'\nimport { isOrmBackedSystemEntityId } from '@open-mercato/shared/lib/data/engine'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport { loadEntityFieldsetConfigs, CustomFieldsetDefinition } from '../lib/fieldsets'\nimport { installCustomEntitiesFromModules } from '../lib/install-from-ce'\nimport { normalizeCustomFieldOptions } from '@open-mercato/shared/modules/entities/options'\nimport { CURRENCY_OPTIONS_URL } from '@open-mercato/shared/modules/entities/kinds'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n beginEntitiesMutationGuard,\n FIELD_DEFINITION_RESOURCE_KIND,\n} from './definitions.mutation-guard'\nimport {\n canReadAllEntityMetadata,\n canReadEntityMetadata,\n getDeclaredCustomEntityRestriction,\n resolveEntityAclRequirement,\n} from '../lib/entityAcl'\nimport {\n createExactDefinitionWhere,\n createScopedDefinitionTombstone,\n createVisibleDefinitionWhere,\n markDefinitionTombstoned,\n resolveDefinitionScopeFromOrganizationScope,\n resolveDefinitionMutationScope,\n selectVisibleDefinitionWinner,\n} from '../lib/definition-scope'\nimport { resolveEntityDefinitionsVersion } from '../lib/definitions-version'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('entities').child({ component: 'definitions' })\n\n/**\n * Validate defaultValue against the field kind. Returns an error message string\n * if invalid, or null if valid. For dictionary and currency kinds, queries the\n * database to verify the token exists.\n */\nasync function validateDefaultValueByKind(\n value: unknown,\n kind: string,\n cfg: Record<string, unknown>,\n em: EntityManager,\n tenantContext: { tenantId: string | null; organizationId: string | null },\n): Promise<string | null> {\n switch (kind) {\n case 'boolean':\n if (typeof value !== 'boolean') return 'defaultValue for boolean fields must be true or false'\n return null\n case 'integer':\n if (typeof value !== 'number' || !Number.isInteger(value))\n return 'defaultValue for integer fields must be a whole number'\n return null\n case 'float':\n if (typeof value !== 'number' || !isFinite(value))\n return 'defaultValue for float fields must be a finite number'\n return null\n case 'text':\n case 'multiline':\n case 'date':\n case 'datetime':\n if (typeof value !== 'string')\n return `defaultValue for ${kind} fields must be a string`\n return null\n case 'dictionary': {\n if (typeof value !== 'string')\n return 'defaultValue for dictionary fields must be a string'\n const dictionaryId = typeof cfg.dictionaryId === 'string' ? cfg.dictionaryId.trim() : ''\n if (dictionaryId) {\n try {\n const { DictionaryEntry } = await import('@open-mercato/core/modules/dictionaries/data/entities')\n const entry = await em.findOne(DictionaryEntry, {\n dictionary: dictionaryId,\n value: value,\n ...(tenantContext.organizationId ? { organizationId: tenantContext.organizationId } : {}),\n ...(tenantContext.tenantId ? { tenantId: tenantContext.tenantId } : {}),\n })\n if (!entry) return `defaultValue \"${value}\" does not match any entry in the configured dictionary`\n } catch (err) {\n // If the dictionaries module is not available, skip entry validation\n logger.debug('Dictionary validation skipped \u2014 module not available', { err })\n }\n }\n return null\n }\n case 'currency': {\n if (typeof value !== 'string')\n return 'defaultValue for currency fields must be a string'\n try {\n const { Currency } = await import('@open-mercato/core/modules/currencies/data/entities')\n const where: Record<string, string> = { code: value as string }\n if (tenantContext.tenantId) where.tenantId = tenantContext.tenantId\n if (tenantContext.organizationId) where.organizationId = tenantContext.organizationId\n const currency = await em.findOne(Currency, where)\n if (!currency) return `defaultValue \"${value}\" does not match any available currency`\n } catch (err) {\n // If the currencies module is not available, skip currency validation\n logger.debug('Currency validation skipped \u2014 module not available', { err })\n }\n return null\n }\n case 'select': {\n if (typeof value !== 'string' && typeof value !== 'number')\n return 'defaultValue for select fields must be a string or number'\n const options = normalizeCustomFieldOptions(\n Array.isArray(cfg.options) ? cfg.options : [],\n )\n if (options.length > 0) {\n const match = options.some(\n (o) => o.value === value || String(o.value) === String(value),\n )\n if (!match) return 'defaultValue does not match any of the configured options'\n }\n return null\n }\n case 'relation':\n case 'attachment':\n return `defaultValue is not supported for ${kind} fields`\n default:\n return null\n }\n}\n\n/**\n * Normalize defaultValue to the canonical storage shape for the given kind.\n */\nfunction normalizeDefaultValueByKind(value: unknown, kind: string): unknown {\n switch (kind) {\n case 'boolean':\n return value === true\n case 'integer':\n return Math.round(Number(value))\n case 'float':\n return Number(value)\n default:\n return value\n }\n}\n\nexport const metadata = {\n // Reading definitions is needed by record forms; keep it auth-protected but accessible to all authenticated users\n GET: { requireAuth: true },\n // Mutations remain admin-only\n POST: { requireAuth: true, requireFeatures: ['entities.definitions.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['entities.definitions.manage'] },\n}\n\nfunction parseEntityIds(url: URL): string[] {\n const direct = url.searchParams.getAll('entityId').filter((id) => typeof id === 'string' && id.trim().length > 0)\n const combined = url.searchParams.get('entityIds')\n if (combined) {\n combined\n .split(',')\n .map((id) => id.trim())\n .filter((id) => id.length > 0)\n .forEach((id) => direct.push(id))\n }\n const unique: string[] = []\n const seen = new Set<string>()\n for (const id of direct) {\n if (seen.has(id)) continue\n seen.add(id)\n unique.push(id)\n }\n return unique\n}\n\nasync function resolveEntityDefaultEditor(em: any, entityId: string, tenantId: string | null | undefined): Promise<string | undefined> {\n try {\n const ent = await em.findOne(CustomEntity, {\n entityId,\n $and: [\n { $or: [ { tenantId: tenantId ?? undefined as any }, { tenantId: null } ] },\n ],\n } as any)\n if (ent && typeof (ent as any).defaultEditor === 'string') return (ent as any).defaultEditor\n } catch {}\n return undefined\n}\n\nfunction normalizeFieldGroup(raw: unknown): { code: string; title?: string; hint?: string } | undefined {\n if (!raw) return undefined\n if (typeof raw === 'string') {\n const code = raw.trim()\n return code ? { code } : undefined\n }\n if (typeof raw !== 'object') return undefined\n const entry = raw as Record<string, unknown>\n const code = typeof entry.code === 'string' ? entry.code.trim() : ''\n if (!code) return undefined\n const group: { code: string; title?: string; hint?: string } = { code }\n if (typeof entry.title === 'string' && entry.title.trim()) group.title = entry.title.trim()\n if (typeof entry.hint === 'string' && entry.hint.trim()) group.hint = entry.hint.trim()\n return group\n}\n\nfunction definitionMatchesReadScope(\n definition: { tenantId?: string | null; organizationId?: string | null },\n scope: { tenantId: string | null; organizationId: string | null },\n) {\n const definitionTenantId = definition.tenantId ?? null\n const definitionOrganizationId = definition.organizationId ?? null\n const tenantMatches = definitionTenantId === null || definitionTenantId === scope.tenantId\n const organizationMatches =\n definitionOrganizationId === null ||\n (scope.organizationId !== null && definitionOrganizationId === scope.organizationId)\n return tenantMatches && organizationMatches\n}\n\nexport async function GET(req: Request) {\n const url = new URL(req.url)\n const requestedEntityIds = parseEntityIds(url)\n if (!requestedEntityIds.length) {\n return NextResponse.json({ error: 'entityId is required' }, { status: 400 })\n }\n const requestedFieldset = url.searchParams.get('fieldset')\n const fieldsetFilter = requestedFieldset && requestedFieldset.trim().length ? requestedFieldset.trim() : null\n\n const auth = await getAuthFromRequest(req)\n if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const selectableEntityIds = filterSelectableSystemEntityIds(requestedEntityIds)\n if (!selectableEntityIds.length) {\n return NextResponse.json({ items: [] })\n }\n\n const container = await createRequestContainer()\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req })\n const definitionScope = resolveDefinitionScopeFromOrganizationScope(auth, scope)\n const tenantId = definitionScope.tenantId\n if (!tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const organizationId = definitionScope.organizationId\n const { resolve } = container\n const em = resolve('em') as any\n const rbac = resolve('rbacService') as RbacService\n const acl = await rbac.loadAcl(auth.sub ?? '', {\n tenantId,\n organizationId,\n })\n const designerCanRead = canReadAllEntityMetadata(acl)\n const customEntityRestrictions = new Map<string, boolean>()\n for (const entityId of selectableEntityIds) {\n if (isOrmBackedSystemEntityId(em, entityId)) continue\n const declaredRestriction = getDeclaredCustomEntityRestriction(entityId)\n if (declaredRestriction !== undefined) customEntityRestrictions.set(entityId, declaredRestriction)\n }\n if (!designerCanRead) {\n const unresolvedEntityIds = selectableEntityIds.filter(\n (entityId) => !resolveEntityAclRequirement(entityId) && !customEntityRestrictions.has(entityId),\n )\n if (unresolvedEntityIds.length) {\n const registrations = await em.find(CustomEntity as any, {\n entityId: { $in: unresolvedEntityIds },\n isActive: true,\n $and: [\n { $or: [{ tenantId }, { tenantId: null }] },\n { $or: [{ organizationId }, { organizationId: null }] },\n ],\n } as any)\n for (const registration of registrations as any[]) {\n const entityId = String(registration.entityId)\n if (!isOrmBackedSystemEntityId(em, entityId)) {\n customEntityRestrictions.set(entityId, registration.accessRestricted === true)\n }\n }\n }\n }\n const entityIds = selectableEntityIds.filter((entityId) => canReadEntityMetadata({\n entityId,\n isCustomEntity: customEntityRestrictions.has(entityId),\n isRestricted: customEntityRestrictions.get(entityId) === true,\n acl,\n }))\n if (!entityIds.length) {\n return NextResponse.json({ items: [], fieldsetsByEntity: {}, entitySettings: {} })\n }\n let cache: CacheStrategy | undefined\n try {\n cache = resolve('cache') as CacheStrategy\n } catch {}\n\n let canManageDefinitions = false\n if (typeof auth.sub === 'string' && auth.sub.length > 0) {\n try {\n canManageDefinitions = await rbac.userHasAllFeatures(auth.sub, ['entities.definitions.manage'], {\n tenantId,\n organizationId,\n })\n } catch {\n // RBAC service unavailable \u2014 fall back to read-only (no definition sync)\n }\n }\n\n if (canManageDefinitions) {\n try {\n await installCustomEntitiesFromModules(em, cache, {\n tenantIds: [tenantId],\n entityIds,\n includeGlobal: true,\n createOnly: true,\n })\n } catch (err) {\n logger.warn('Failed to synchronize module-backed definitions', {\n tenantId,\n entityIds,\n err,\n })\n }\n }\n\n let cacheKey: string | null = null\n if (cache && !fieldsetFilter) {\n cacheKey = createDefinitionsCacheKey({\n tenantId,\n organizationId,\n entityIds,\n })\n try {\n const cached = await cache.get(cacheKey)\n if (cached) {\n return NextResponse.json(cached)\n }\n } catch (err) {\n logger.warn('Failed to read cache', { err })\n }\n }\n\n const fieldsetConfigs = await loadEntityFieldsetConfigs(em, {\n entityIds,\n tenantId,\n organizationId,\n mode: 'public',\n })\n\n const tenantCandidates = [{ tenantId }, { tenantId: null as string | null }]\n const organizationCandidates = [{ organizationId: null as string | null }]\n if (organizationId) organizationCandidates.unshift({ organizationId })\n const readScope = { tenantId, organizationId }\n\n const whereActive = {\n entityId: { $in: entityIds as any },\n deletedAt: null,\n $and: [\n { $or: tenantCandidates },\n { $or: organizationCandidates },\n ],\n } as any\n const defs = (await em.find(CustomFieldDef, whereActive as any))\n .filter((definition: any) => definitionMatchesReadScope(definition, readScope))\n const tombstones = (await em.find(CustomFieldDef, {\n entityId: { $in: entityIds as any },\n deletedAt: { $ne: null } as any,\n $and: [\n { $or: tenantCandidates },\n { $or: organizationCandidates },\n ],\n } as any)).filter((definition: any) => definitionMatchesReadScope(definition, readScope))\n\n const tombstonedByEntity = new Map<string, Set<string>>()\n for (const entry of tombstones as any[]) {\n const eid = String(entry.entityId)\n if (!tombstonedByEntity.has(eid)) tombstonedByEntity.set(eid, new Set())\n tombstonedByEntity.get(eid)!.add(entry.key)\n }\n\n const scopeScore = (x: any) => (x.tenantId ? 2 : 0) + (x.organizationId ? 1 : 0)\n\n const definitionsByEntity = new Map<string, any[]>()\n for (const d of defs) {\n const eid = String(d.entityId)\n if (!definitionsByEntity.has(eid)) definitionsByEntity.set(eid, [])\n definitionsByEntity.get(eid)!.push(d)\n }\n\n const entityDefaultEditors = new Map<string, string | undefined>()\n for (const entityId of entityIds) {\n const editor = await resolveEntityDefaultEditor(em, entityId, tenantId ?? null)\n entityDefaultEditors.set(entityId, editor)\n }\n\n const items: any[] = []\n\n const entityOrder = new Map<string, number>()\n entityIds.forEach((id, idx) => entityOrder.set(id, idx))\n\n for (const entityId of entityIds) {\n const defsForEntity = definitionsByEntity.get(entityId) ?? []\n if (!defsForEntity.length) continue\n const tombstonedKeys = tombstonedByEntity.get(entityId) ?? new Set<string>()\n const byKey = new Map<string, any>()\n for (const d of defsForEntity) {\n const existing = byKey.get(d.key)\n if (!existing) { byKey.set(d.key, d); continue }\n const sNew = scopeScore(d)\n const sOld = scopeScore(existing)\n if (sNew > sOld) { byKey.set(d.key, d); continue }\n if (sNew < sOld) continue\n const tNew = (d.updatedAt instanceof Date) ? d.updatedAt.getTime() : new Date(d.updatedAt).getTime()\n const tOld = (existing.updatedAt instanceof Date) ? existing.updatedAt.getTime() : new Date(existing.updatedAt).getTime()\n if (tNew >= tOld) byKey.set(d.key, d)\n }\n\n const defaultEditor = entityDefaultEditors.get(entityId)\n const winning = Array.from(byKey.values()).filter((d: any) => (d.isActive !== false) && !tombstonedKeys.has(d.key))\n winning.sort((a: any, b: any) => ((a.configJson?.priority ?? 0) - (b.configJson?.priority ?? 0)))\n\n for (const d of winning) {\n const rawFieldset = typeof d.configJson?.fieldset === 'string' ? d.configJson.fieldset.trim() : ''\n const normalizedFieldset = rawFieldset.length > 0 ? rawFieldset : undefined\n const normalizedFieldsets = Array.isArray(d.configJson?.fieldsets)\n ? d.configJson.fieldsets\n .filter((entry: unknown): entry is string => typeof entry === 'string')\n .map((entry: string) => entry.trim())\n .filter((entry: string) => entry.length > 0)\n : []\n const effectiveFieldsets = normalizedFieldsets.length > 0\n ? normalizedFieldsets\n : (normalizedFieldset ? [normalizedFieldset] : [])\n if (fieldsetFilter && !effectiveFieldsets.includes(fieldsetFilter)) continue\n const groupInfo = normalizeFieldGroup(d.configJson?.group)\n const keyLower = String(d.key).toLowerCase()\n const candidateBase = {\n key: d.key,\n kind: d.kind,\n label: d.configJson?.label || d.key,\n description: d.configJson?.description || undefined,\n multi: Boolean(d.configJson?.multi),\n relatedEntityId: d.kind === 'relation' && typeof d.configJson?.relatedEntityId === 'string'\n ? d.configJson.relatedEntityId.trim() || undefined\n : undefined,\n options: (() => {\n if (d.kind === 'currency') return undefined\n const normalizedOptions = normalizeCustomFieldOptions(d.configJson?.options)\n return normalizedOptions.length ? normalizedOptions : undefined\n })(),\n optionsUrl: (() => {\n if (d.kind === 'currency') return CURRENCY_OPTIONS_URL\n const dictionaryId = typeof d.configJson?.dictionaryId === 'string' ? d.configJson.dictionaryId : undefined\n if (dictionaryId) return `/api/dictionaries/${dictionaryId}/entries`\n return typeof d.configJson?.optionsUrl === 'string' ? d.configJson.optionsUrl : undefined\n })(),\n filterable: Boolean(d.configJson?.filterable),\n formEditable: d.configJson?.formEditable !== undefined ? Boolean(d.configJson.formEditable) : true,\n listVisible: d.configJson?.listVisible !== undefined ? Boolean(d.configJson.listVisible) : true,\n editor: typeof d.configJson?.editor === 'string'\n ? d.configJson.editor\n : (d.kind === 'multiline' ? defaultEditor : undefined),\n input: typeof d.configJson?.input === 'string' ? d.configJson.input : undefined,\n dictionaryId: typeof d.configJson?.dictionaryId === 'string' ? d.configJson.dictionaryId : undefined,\n dictionaryInlineCreate: d.configJson?.dictionaryInlineCreate !== undefined\n ? Boolean(d.configJson.dictionaryInlineCreate)\n : undefined,\n priority: typeof d.configJson?.priority === 'number' ? d.configJson.priority : 0,\n validation: Array.isArray(d.configJson?.validation) ? d.configJson.validation : undefined,\n defaultValue: d.configJson?.defaultValue !== undefined ? d.configJson.defaultValue : undefined,\n // attachments config passthrough\n maxAttachmentSizeMb: typeof d.configJson?.maxAttachmentSizeMb === 'number' ? d.configJson.maxAttachmentSizeMb : undefined,\n acceptExtensions: Array.isArray(d.configJson?.acceptExtensions) ? d.configJson.acceptExtensions : undefined,\n // phone config passthrough\n defaultCountryIso2: typeof d.configJson?.defaultCountryIso2 === 'string' ? d.configJson.defaultCountryIso2 : undefined,\n entityId,\n fieldset: normalizedFieldset ?? effectiveFieldsets[0],\n fieldsets: effectiveFieldsets.length > 0 ? effectiveFieldsets : undefined,\n group: groupInfo,\n } as any\n const metrics = computeDefinitionScore(d, candidateBase, entityOrder.get(entityId) ?? Number.MAX_SAFE_INTEGER)\n const candidate = { ...candidateBase, __score: metrics }\n const existing = (items as any[]).find((entry) => entry.key.toLowerCase() === keyLower)\n if (!existing) {\n items.push(candidate)\n continue\n }\n const existingScore = existing.__score as { base: number; penalty: number; entityIndex: number }\n const candidateScoreInfo = candidate.__score as { base: number; penalty: number; entityIndex: number }\n const better =\n candidateScoreInfo.base > existingScore.base ||\n (candidateScoreInfo.base === existingScore.base && candidateScoreInfo.penalty < existingScore.penalty) ||\n (candidateScoreInfo.base === existingScore.base && candidateScoreInfo.penalty === existingScore.penalty && candidateScoreInfo.entityIndex < existingScore.entityIndex)\n if (better) {\n const index = items.findIndex((entry) => entry.key.toLowerCase() === keyLower)\n if (index >= 0) items[index] = candidate\n }\n }\n }\n\n const sanitized = items.map((item: any) => {\n const { __score, ...rest } = item\n return rest\n })\n sanitized.sort((a: any, b: any) => ((a.priority ?? 0) - (b.priority ?? 0)))\n\n const fieldsetsByEntity: Record<string, CustomFieldsetDefinition[]> = {}\n const entitySettings: Record<string, { singleFieldsetPerRecord: boolean }> = {}\n for (const entityId of entityIds) {\n const cfg = fieldsetConfigs.get(entityId) ?? { fieldsets: [], singleFieldsetPerRecord: true }\n fieldsetsByEntity[entityId] = cfg.fieldsets\n entitySettings[entityId] = { singleFieldsetPerRecord: cfg.singleFieldsetPerRecord }\n }\n\n const responseBody = { items: sanitized, fieldsetsByEntity, entitySettings }\n\n if (cache && cacheKey && !fieldsetFilter) {\n const tags = createDefinitionsCacheTags({\n tenantId,\n organizationId,\n entityIds,\n })\n try {\n await cache.set(cacheKey, responseBody, {\n ttl: ENTITY_DEFINITIONS_CACHE_TTL_MS,\n tags,\n })\n } catch (err) {\n logger.warn('Failed to store cache entry', { err })\n }\n }\n\n return NextResponse.json(responseBody)\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.orgId) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n let body: any\n try { body = await req.json() } catch { return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 }) }\n const parsed = upsertCustomFieldDefSchema.safeParse(body)\n if (!parsed.success) return NextResponse.json({ error: 'Validation failed', details: parsed.error.flatten() }, { status: 400 })\n const input = parsed.data\n\n if (!isSystemEntitySelectable(input.entityId)) {\n return NextResponse.json({ error: 'Custom fields are not supported for this entity' }, { status: 400 })\n }\n\n if (input.kind === 'dictionary') {\n const dictionaryId = input.configJson?.dictionaryId\n if (typeof dictionaryId !== 'string' || dictionaryId.trim().length === 0) {\n return NextResponse.json({ error: 'dictionaryId is required for dictionary custom fields' }, { status: 400 })\n }\n }\n\n const container = await createRequestContainer()\n const scope = await resolveDefinitionMutationScope({ auth, container, request: req })\n const { resolve } = container\n const em = resolve('em') as any\n let cache: CacheStrategy | undefined\n try {\n cache = resolve('cache') as CacheStrategy\n } catch {}\n\n const where: any = createExactDefinitionWhere(input.entityId, input.key, scope)\n let def = await em.findOne(CustomFieldDef, where)\n\n const guard = await beginEntitiesMutationGuard({\n container,\n auth,\n req,\n resourceKind: FIELD_DEFINITION_RESOURCE_KIND,\n resourceId: def ? def.id : `${input.entityId}:${input.key}`,\n operation: def ? 'update' : 'create',\n mutationPayload: input as unknown as Record<string, unknown>,\n })\n if (guard.blockedResponse) return guard.blockedResponse\n\n if (!def) def = em.create(CustomFieldDef, { ...where, createdAt: new Date() })\n def.kind = input.kind\n const inCfg = (input as any).configJson ?? {}\n const cfg: Record<string, any> = { ...inCfg }\n if (cfg.label == null || String(cfg.label).trim() === '') cfg.label = input.key\n if (cfg.formEditable === undefined) cfg.formEditable = true\n if (cfg.listVisible === undefined) cfg.listVisible = true\n if (input.kind === 'dictionary') {\n const dictionaryId = typeof cfg.dictionaryId === 'string' ? cfg.dictionaryId.trim() : ''\n cfg.dictionaryId = dictionaryId\n cfg.dictionaryInlineCreate = cfg.dictionaryInlineCreate !== false\n }\n if (input.kind === 'currency') {\n cfg.optionsUrl = CURRENCY_OPTIONS_URL\n if (Array.isArray(cfg.options)) delete cfg.options\n }\n if (input.kind === 'multiline' && (cfg.editor == null || String(cfg.editor).trim() === '')) {\n cfg.editor = 'markdown'\n }\n // Validate and normalize defaultValue by kind before persisting\n if (cfg.defaultValue !== undefined && cfg.defaultValue !== null) {\n const validationError = await validateDefaultValueByKind(\n cfg.defaultValue, input.kind, cfg, em,\n { tenantId: scope.tenantId, organizationId: scope.organizationId },\n )\n if (validationError) {\n return NextResponse.json({ error: validationError }, { status: 400 })\n }\n cfg.defaultValue = normalizeDefaultValueByKind(cfg.defaultValue, input.kind)\n }\n def.configJson = cfg\n def.isActive = input.isActive ?? true\n def.deletedAt = def.isActive === false ? (def.deletedAt ?? new Date()) : null\n def.updatedAt = new Date()\n em.persist(def)\n await em.flush()\n await guard.runAfterSuccess()\n await invalidateDefinitionsCache(cache, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n entityIds: [input.entityId],\n })\n // Changing field definitions may impact forms but not sidebar items; no nav cache touch\n return NextResponse.json({ ok: true, item: { id: def.id, key: def.key, kind: def.kind, configJson: def.configJson, isActive: def.isActive } })\n}\n\nexport async function DELETE(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.orgId) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n let body: any\n try { body = await req.json() } catch { return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 }) }\n const { entityId, key } = body || {}\n if (!entityId || !key) return NextResponse.json({ error: 'entityId and key are required' }, { status: 400 })\n\n const container = await createRequestContainer()\n const scope = await resolveDefinitionMutationScope({ auth, container, request: req })\n const { resolve } = container\n const em = resolve('em') as any\n let cache: CacheStrategy | undefined\n try {\n cache = resolve('cache') as CacheStrategy\n } catch {}\n const where: any = createExactDefinitionWhere(entityId, key, scope)\n let def = await em.findOne(CustomFieldDef, where)\n let inherited: any | null = null\n if (!def) {\n inherited = selectVisibleDefinitionWinner(await em.find(CustomFieldDef, createVisibleDefinitionWhere(\n entityId,\n key,\n scope,\n { deletedAt: null, isActive: true },\n )))\n if (!inherited) return NextResponse.json({ error: 'Not found' }, { status: 404 })\n }\n\n const guard = await beginEntitiesMutationGuard({\n container,\n auth,\n req,\n resourceKind: FIELD_DEFINITION_RESOURCE_KIND,\n resourceId: def?.id ?? inherited?.id ?? `${entityId}:${key}`,\n operation: 'delete',\n mutationPayload: { entityId, key },\n })\n if (guard.blockedResponse) return guard.blockedResponse\n\n if (!def) {\n def = createScopedDefinitionTombstone(em, inherited, scope)\n } else {\n markDefinitionTombstoned(def)\n }\n em.persist(def)\n await em.flush()\n await guard.runAfterSuccess()\n await invalidateDefinitionsCache(cache, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n entityIds: [entityId],\n })\n // Changing field definitions may impact forms but not sidebar items; no nav cache touch\n // Return the post-delete aggregate version so the edit form keeps its optimistic-lock\n // token in sync after removing a field out-of-band (issue #3152).\n const version = await resolveEntityDefinitionsVersion(em, {\n entityId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n return NextResponse.json({ ok: true, version })\n}\n\nconst definitionsQuerySchema = z\n .object({\n entityId: z.union([z.string(), z.array(z.string())]).optional(),\n entityIds: z.string().optional(),\n fieldset: z.string().regex(fieldsetCodeRegex).optional(),\n })\n .refine(\n (value) => {\n if (value.entityId && typeof value.entityId === 'string' && value.entityId.trim().length > 0) return true\n if (Array.isArray(value.entityId) && value.entityId.length > 0) return true\n return typeof value.entityIds === 'string' && value.entityIds.trim().length > 0\n },\n { message: 'Provide at least one entityId or an entityIds list.' }\n )\n\nconst customFieldOptionValueSchema = z.union([z.string(), z.number()])\n\nconst customFieldDefinitionSchema = z.object({\n key: z.string(),\n kind: z.string(),\n label: z.string(),\n description: z.string().optional(),\n multi: z.boolean().optional(),\n relatedEntityId: z.string().optional(),\n options: z.array(customFieldOptionValueSchema).optional(),\n optionsUrl: z.string().optional(),\n filterable: z.boolean().optional(),\n formEditable: z.boolean().optional(),\n listVisible: z.boolean().optional(),\n editor: z.string().optional(),\n input: z.string().optional(),\n dictionaryId: z.string().optional(),\n dictionaryInlineCreate: z.boolean().optional(),\n priority: z.number().optional(),\n validation: z.array(z.any()).optional(),\n defaultValue: z.union([z.string(), z.number(), z.boolean(), z.null()]).optional(),\n maxAttachmentSizeMb: z.number().optional(),\n acceptExtensions: z.array(z.any()).optional(),\n entityId: z.string(),\n fieldset: z.string().optional(),\n group: z\n .object({\n code: z.string(),\n title: z.string().optional(),\n hint: z.string().optional(),\n })\n .optional(),\n})\n\nconst customFieldsetGroupResponseSchema = z.object({\n code: z.string(),\n title: z.string().optional(),\n hint: z.string().optional(),\n})\n\nconst entityFieldsetResponseSchema = z.object({\n code: z.string(),\n label: z.string(),\n icon: z.string().optional(),\n description: z.string().optional(),\n groups: z.array(customFieldsetGroupResponseSchema).optional(),\n})\n\nconst definitionsResponseSchema = z.object({\n items: z.array(customFieldDefinitionSchema),\n fieldsetsByEntity: z.record(z.string(), z.array(entityFieldsetResponseSchema)).optional(),\n entitySettings: z\n .record(\n z.string(),\n z.object({\n singleFieldsetPerRecord: z.boolean().optional(),\n })\n )\n .optional(),\n})\n\nconst upsertDefinitionResponseSchema = z.object({\n ok: z.literal(true),\n item: z.object({\n id: z.string().uuid(),\n key: z.string(),\n kind: z.string(),\n configJson: z.record(z.string(), z.any()),\n isActive: z.boolean().optional(),\n }),\n})\n\nconst deleteDefinitionRequestSchema = z.object({\n entityId: z.string(),\n key: z.string(),\n})\n\nconst deleteDefinitionResponseSchema = z.object({\n ok: z.literal(true),\n version: z.string().nullable().optional(),\n})\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Entities',\n summary: 'Manage custom field definitions',\n methods: {\n GET: {\n summary: 'List active custom field definitions',\n description: 'Returns active custom field definitions for the supplied entity ids, respecting tenant scope and tombstones.',\n query: definitionsQuerySchema,\n responses: [\n {\n status: 200,\n description: 'Definition list',\n schema: definitionsResponseSchema,\n },\n {\n status: 400,\n description: 'Missing entity id',\n schema: z.object({ error: z.string() }),\n },\n {\n status: 401,\n description: 'Missing authentication',\n schema: z.object({ error: z.string() }),\n },\n ],\n },\n POST: {\n summary: 'Upsert custom field definition',\n description: 'Creates or updates a custom field definition for the current tenant/org scope.',\n requestBody: {\n contentType: 'application/json',\n schema: upsertCustomFieldDefSchema,\n },\n responses: [\n {\n status: 200,\n description: 'Definition saved',\n schema: upsertDefinitionResponseSchema,\n },\n {\n status: 400,\n description: 'Validation failed',\n schema: z.object({\n error: z.string(),\n details: z.any().optional(),\n }),\n },\n {\n status: 401,\n description: 'Missing authentication',\n schema: z.object({ error: z.string() }),\n },\n ],\n },\n DELETE: {\n summary: 'Soft delete custom field definition',\n description: 'Marks the specified definition inactive and tombstones it for the current scope.',\n requestBody: {\n contentType: 'application/json',\n schema: deleteDefinitionRequestSchema,\n },\n responses: [\n {\n status: 200,\n description: 'Definition deleted',\n schema: deleteDefinitionResponseSchema,\n },\n {\n status: 400,\n description: 'Missing entity id or key',\n schema: z.object({ error: z.string() }),\n },\n {\n status: 401,\n description: 'Missing authentication',\n schema: z.object({ error: z.string() }),\n },\n {\n status: 404,\n description: 'Definition not found',\n schema: z.object({ error: z.string() }),\n },\n ],\n },\n },\n}\nconst computeDefinitionScore = (def: any, cfg: Record<string, any>, entityIndex: number) => {\n const listVisibleScore = cfg.listVisible === false ? 0 : 1\n const formEditableScore = cfg.formEditable === false ? 0 : 1\n const filterableScore = cfg.filterable ? 1 : 0\n const kindScore = (() => {\n switch (def.kind) {\n case 'dictionary':\n return 8\n case 'relation':\n return 6\n case 'select':\n case 'currency':\n return 4\n case 'multiline':\n return 3\n case 'boolean':\n case 'integer':\n case 'float':\n return 2\n default:\n return 1\n }\n })()\n const optionsBonus = Array.isArray(cfg.options) && cfg.options.length ? 2 : 0\n const dictionaryBonus = typeof cfg.dictionaryId === 'string' && cfg.dictionaryId.trim().length ? 5 : 0\n const base = (listVisibleScore * 16) + (formEditableScore * 8) + (filterableScore * 4) + kindScore + optionsBonus + dictionaryBonus\n const penalty = typeof cfg.priority === 'number' ? cfg.priority : 0\n return { base, penalty, entityIndex }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["code"]
7
7
  }
@@ -20,6 +20,11 @@ import { useGuardedMutation } from "@open-mercato/ui/backend/injection/useGuarde
20
20
  import { useT } from "@open-mercato/shared/lib/i18n/context";
21
21
  import { ErrorMessage, LoadingMessage } from "@open-mercato/ui/backend/detail";
22
22
  import { useRecordsEntityGuard } from "@open-mercato/core/modules/entities/components/useRecordsEntityGuard";
23
+ import {
24
+ RelationCell,
25
+ RelationDisplaysProvider,
26
+ useRecordListRelationDisplays
27
+ } from "@open-mercato/core/modules/entities/components/RecordListRelationCell";
23
28
  function toCsvUrl(base, params) {
24
29
  const p = new URLSearchParams(params);
25
30
  p.set("format", "csv");
@@ -67,6 +72,13 @@ function RecordsPageInner({ params }) {
67
72
  enabled: Boolean(entityId),
68
73
  keyExtras: [scopeVersion]
69
74
  });
75
+ const relationDefinitions = React.useMemo(
76
+ () => filterCustomFieldDefs(cfDefs, "list").filter(
77
+ (definition) => definition.kind === "relation"
78
+ ),
79
+ [cfDefs]
80
+ );
81
+ const relationDisplaysByField = useRecordListRelationDisplays(relationDefinitions, rawData);
70
82
  const searchableFields = React.useMemo(() => {
71
83
  const fields = (columns || []).map((col) => col.accessorKey).filter((key) => typeof key === "string" && key.length > 0);
72
84
  return Array.from(/* @__PURE__ */ new Set(["id", ...fields]));
@@ -142,7 +154,10 @@ function RecordsPageInner({ params }) {
142
154
  meta: { priority: idx < 4 ? 1 : idx < 6 ? 2 : idx < 8 ? 3 : idx < maxVisible ? 4 : 5 },
143
155
  cell: ({ getValue }) => {
144
156
  const v = getValue();
145
- return /* @__PURE__ */ jsx("span", { className: "truncate max-w-[24ch] inline-block align-top", title: normalizeCell(v), children: normalizeCell(v) });
157
+ if (d.kind === "relation") {
158
+ return /* @__PURE__ */ jsx(RelationCell, { fieldKey: d.key, value: v, fallbackText: normalizeCell(v) });
159
+ }
160
+ return /* @__PURE__ */ jsx("span", { className: "inline-block max-w-60 truncate align-top", title: normalizeCell(v), children: normalizeCell(v) });
146
161
  }
147
162
  }));
148
163
  const hasIdCol = cols.some((c) => c.accessorKey === "id" || c.id === "id");
@@ -297,7 +312,7 @@ export RECORD_ID="<record uuid>"` }) }),
297
312
  ] })
298
313
  ] })
299
314
  ] }),
300
- /* @__PURE__ */ jsx(
315
+ /* @__PURE__ */ jsx(RelationDisplaysProvider, { displaysByField: relationDisplaysByField, children: /* @__PURE__ */ jsx(
301
316
  DataTable,
302
317
  {
303
318
  stickyActionsColumn: true,
@@ -384,7 +399,7 @@ export RECORD_ID="<record uuid>"` }) }),
384
399
  pagination: { page, pageSize, total, totalPages, onPageChange: setPage },
385
400
  isLoading: loading
386
401
  }
387
- )
402
+ ) })
388
403
  ] }),
389
404
  ConfirmDialogElement
390
405
  ] });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../../src/modules/entities/backend/entities/user/%5BentityId%5D/records/page.tsx"],
4
- "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { resolveExtensionPointPattern } from '@open-mercato/shared/modules/widgets/extension-points'\nimport { extensionPoints } from '@open-mercato/core/modules/entities/extension-points'\nimport { useSearchParams } from 'next/navigation'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { filterCustomFieldDefs, useCustomFieldDefs } from '@open-mercato/ui/backend/utils/customFieldDefs'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable, type DataTableExportFormat } from '@open-mercato/ui/backend/DataTable'\nimport type { PreparedExport } from '@open-mercato/shared/lib/crud/exporters'\nimport type { FilterDef } from '@open-mercato/ui/backend/FilterBar'\nimport { ContextHelp } from '@open-mercato/ui/backend/ContextHelp'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport Link from 'next/link'\nimport { apiCall, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { ErrorMessage, LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { useRecordsEntityGuard } from '@open-mercato/core/modules/entities/components/useRecordsEntityGuard'\n\ntype RecordsResponse = {\n items: any[]\n total: number\n page: number\n pageSize: number\n totalPages: number\n}\n\nfunction toCsvUrl(base: string, params: URLSearchParams) {\n // Build a relative URL to avoid SSR/CSR origin mismatch hydration issues\n const p = new URLSearchParams(params)\n p.set('format', 'csv')\n const qs = p.toString()\n return qs ? `${base}?${qs}` : base\n}\n\nfunction normalizeCell(v: any): string {\n if (Array.isArray(v)) return v.filter((x) => x != null && x !== '').join(', ')\n if (v === true) return 'Yes'\n if (v === false) return 'No'\n if (v == null) return ''\n if (v instanceof Date) return v.toISOString()\n return String(v)\n}\n\nexport default function RecordsPage({ params }: { params: { entityId?: string } }) {\n const t = useT()\n const entityId = decodeURIComponent(params?.entityId || '')\n const guard = useRecordsEntityGuard(entityId)\n if (guard !== 'allowed') {\n return (\n <Page>\n <PageBody>\n {guard === 'blocked' ? (\n <ErrorMessage label={t('entities.userEntities.records.errors.systemEntity', 'This entity is system-managed. Records are available for custom entities only.')} />\n ) : (\n <LoadingMessage label={t('entities.userEntities.records.loading', 'Loading records...')} />\n )}\n </PageBody>\n </Page>\n )\n }\n return <RecordsPageInner params={params} />\n}\n\nfunction RecordsPageInner({ params }: { params: { entityId?: string } }) {\n const t = useT()\n const entityId = decodeURIComponent(params?.entityId || '')\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'id', desc: false }])\n const [page, setPage] = React.useState(1)\n const [pageSize, setPageSize] = React.useState(50)\n const [search, setSearch] = React.useState('')\n const [filterValues, setFilterValues] = React.useState<Record<string, any>>({})\n const [columns, setColumns] = React.useState<ColumnDef<any>[]>([])\n const [rawData, setRawData] = React.useState<any[]>([])\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [loading, setLoading] = React.useState(false)\n const scopeVersion = useOrganizationScopeVersion()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const deleteMutationContextId = `entities.user.records.${entityId}:single-delete`\n const { runMutation: runDeleteMutation, retryLastMutation: retryDeleteMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: deleteMutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const { data: cfDefs = [] } = useCustomFieldDefs(entityId, {\n enabled: Boolean(entityId),\n keyExtras: [scopeVersion],\n })\n\n // Fields searched server-side: every visible column plus the base `id`.\n const searchableFields = React.useMemo(() => {\n const fields = (columns || [])\n .map((col) => (col as any).accessorKey)\n .filter((key): key is string => typeof key === 'string' && key.length > 0)\n return Array.from(new Set(['id', ...fields]))\n }, [columns])\n\n // Fetch records whenever paging/sorting/filters/search change. Search is applied\n // server-side (before pagination) so totals and exports stay consistent (#3229).\n React.useEffect(() => {\n let cancelled = false\n const run = async () => {\n setLoading(true)\n try {\n const params = new URLSearchParams()\n params.set('entityId', entityId)\n params.set('page', String(page))\n params.set('pageSize', String(pageSize))\n const trimmedSearch = search.trim()\n if (trimmedSearch) {\n params.set('search', trimmedSearch)\n if (searchableFields.length) params.set('searchFields', searchableFields.join(','))\n }\n const s = sorting?.[0]\n if (s?.id) {\n params.set('sortField', String(s.id))\n params.set('sortDir', s.desc ? 'desc' : 'asc')\n }\n // Flatten filter values into query params\n for (const [k, v] of Object.entries(filterValues)) {\n if (v == null) continue\n if (Array.isArray(v)) {\n if (v.length) params.set(k, v.join(','))\n } else if (typeof v === 'object') {\n // dateRange-like shapes are not supported generically here; skip\n } else {\n params.set(k, String(v))\n }\n }\n const j = await readApiResultOrThrow<RecordsResponse>(\n `/api/entities/records?${params.toString()}`,\n undefined,\n {\n errorMessage: 'Failed to load records',\n fallback: {\n items: [],\n total: 0,\n page,\n pageSize,\n totalPages: 1,\n },\n },\n )\n if (!cancelled) {\n setRawData(j.items || [])\n setTotal(j.total)\n setTotalPages(j.totalPages)\n }\n } catch (e) {\n if (!cancelled) {\n setRawData([])\n setTotal(0)\n setTotalPages(1)\n }\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n if (entityId) run()\n return () => { cancelled = true }\n }, [entityId, page, pageSize, sorting, filterValues, scopeVersion, search, searchableFields])\n\n // Build columns from custom field definitions only (no data round-trip)\n React.useEffect(() => {\n const visibleDefs = filterCustomFieldDefs(cfDefs, 'list') as any\n const maxVisible = 10\n const cols: ColumnDef<any>[] = visibleDefs.map((d: any, idx: number) => ({\n accessorKey: d.key,\n header: d.label || d.key,\n meta: { priority: idx < 4 ? 1 : idx < 6 ? 2 : idx < 8 ? 3 : idx < maxVisible ? 4 : 5 },\n cell: ({ getValue }: { getValue: () => unknown }) => {\n const v = getValue() as any\n return <span className=\"truncate max-w-[24ch] inline-block align-top\" title={normalizeCell(v)}>{normalizeCell(v)}</span>\n },\n }))\n // Ensure hidden 'id' column exists for sorting/state\n const hasIdCol = cols.some((c) => (c as any).accessorKey === 'id' || (c as any).id === 'id')\n if (!hasIdCol) cols.unshift({ accessorKey: 'id', header: 'ID', meta: { hidden: true, priority: 6 } } as any)\n setColumns(cols)\n }, [cfDefs])\n\n // Search is server-side (see fetch effect); render the fetched page as-is so\n // pagination totals and exports stay consistent with the active search (#3229).\n const data = rawData\n\n const viewExportColumns = React.useMemo(() => {\n return (columns || [])\n .map((col) => {\n const accessorKey = (col as any).accessorKey\n if (!accessorKey || typeof accessorKey !== 'string') return null\n if ((col as any).meta?.hidden) return null\n const header = typeof col.header === 'string'\n ? col.header\n : accessorKey.startsWith('cf_')\n ? accessorKey.slice(3)\n : accessorKey\n return { field: accessorKey, header }\n })\n .filter((col): col is { field: string; header: string } => !!col)\n }, [columns])\n\n const buildFullExportUrl = React.useCallback((format: DataTableExportFormat) => {\n const qp = new URLSearchParams({\n entityId,\n format,\n exportScope: 'full',\n all: 'true',\n })\n const sort = sorting?.[0]\n if (sort?.id) {\n qp.set('sortField', String(sort.id))\n qp.set('sortDir', sort.desc ? 'desc' : 'asc')\n }\n const trimmedSearch = search.trim()\n if (trimmedSearch) {\n qp.set('search', trimmedSearch)\n if (searchableFields.length) qp.set('searchFields', searchableFields.join(','))\n }\n return `/api/entities/records?${qp.toString()}`\n }, [entityId, sorting, search, searchableFields])\n\n const exportConfig = React.useMemo(() => {\n const safeEntityId = entityId.replace(/[^a-z0-9_-]/gi, '_') || 'records'\n return {\n view: {\n description: 'Exports the current list respecting filters and column visibility.',\n prepare: async (): Promise<{ prepared: PreparedExport; filename: string }> => {\n const rowsForExport = data.map((row) => {\n const out: Record<string, unknown> = {}\n for (const col of viewExportColumns) {\n out[col.field] = (row as Record<string, unknown>)[col.field]\n }\n return out\n })\n const prepared: PreparedExport = {\n columns: viewExportColumns.map((col) => ({ field: col.field, header: col.header })),\n rows: rowsForExport,\n }\n return { prepared, filename: `${safeEntityId}_view` }\n },\n },\n full: {\n description: 'Exports raw records with every field and custom field included.',\n getUrl: (format: DataTableExportFormat) => buildFullExportUrl(format),\n filename: () => `${safeEntityId}_full`,\n },\n }\n }, [buildFullExportUrl, data, entityId, viewExportColumns])\n\n const hasAnyFormFields = React.useMemo(() => filterCustomFieldDefs(cfDefs, 'form').length > 0, [cfDefs])\n const actions = (\n <>\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href={`/backend/entities/user/${encodeURIComponent(entityId)}`}>\n Edit Entity Definition\n </Link>\n </Button>\n {hasAnyFormFields && (\n <Button asChild>\n <Link href={`/backend/entities/user/${encodeURIComponent(entityId)}/records/create`}>\n Create\n </Link>\n </Button>\n )}\n </>\n )\n\n // Ensure filters are visible even if no custom fields are marked filterable\n const baseFilters: FilterDef[] = React.useMemo(() => ([\n { id: 'id', label: 'ID', type: 'text' },\n ]), [])\n\n return (\n <Page>\n <PageBody>\n <ContextHelp bulb title=\"API: Manage Records via cURL\" className=\"mb-4\">\n <p className=\"mb-2\">\n Interact with this custom entity via the backend API using cURL. Use API keys for machine-to-machine access\u2014mint one from the{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/user-guide/api-keys\">\n Managing API keys guide\n </a>{' '}\n or the{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/cli/api-keys\">\n API keys CLI documentation\n </a>{' '}\n before running these calls.\n </p>\n <div className=\"space-y-2\">\n <div>\n <div className=\"font-medium mb-1\">1) Configure environment variables</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`export BASE_URL=\"http://localhost:3000/api\"\nexport API_KEY=\"<paste API key secret here>\" # scoped with entities.features\nexport ENTITY_ID=\"${entityId}\"\nexport RECORD_ID=\"<record uuid>\"`}</code></pre>\n <p className=\"text-muted-foreground mt-1\">\n Need a new key? Follow the{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/user-guide/api-keys\">\n Managing API keys\n </a>{' '}\n walkthrough or mint one via{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/cli/api-keys\">\n mercato api_keys add\n </a>\n .\n </p>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">2) List records</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -H \"X-Api-Key: $API_KEY\" \\\n \"$BASE_URL/entities/records?entityId=$ENTITY_ID\" | jq`}</code></pre>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">3) Read a single record (by id)</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -H \"X-Api-Key: $API_KEY\" \\\n \"$BASE_URL/entities/records?entityId=$ENTITY_ID&id=$RECORD_ID\" | jq`}</code></pre>\n <p className=\"text-muted-foreground mt-1\">Note: Response is a list; filter by <code>id</code> to get a single item.</p>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">4) Create a record</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -X POST \\\n -H \"X-Api-Key: $API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d \"{\n \\\\\"entityId\\\\\": \\\\\"$ENTITY_ID\\\\\",\n \\\\\"values\\\\\": {\n \\\\\"field_one\\\\\": \\\\\"Example\\\\\",\n \\\\\"field_two\\\\\": 123\n }\n }\" \\\n \"$BASE_URL/entities/records\" | jq`}</code></pre>\n <p className=\"text-muted-foreground mt-1\">For custom entities, send field keys without the <code>cf_</code> prefix. The API normalizes this server-side.</p>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">5) Update a record</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -X PUT \\\n -H \"X-Api-Key: $API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d \"{\n \\\\\"entityId\\\\\": \\\\\"$ENTITY_ID\\\\\",\n \\\\\"recordId\\\\\": \\\\\"$RECORD_ID\\\\\",\n \\\\\"values\\\\\": {\n \\\\\"field_one\\\\\": \\\\\"Updated\\\\\"\n }\n }\" \\\n \"$BASE_URL/entities/records\" | jq`}</code></pre>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">6) Delete a record</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -X DELETE \\\n -H \"X-Api-Key: $API_KEY\" \\\n \"$BASE_URL/entities/records?entityId=$ENTITY_ID&recordId=$RECORD_ID\" | jq`}</code></pre>\n </div>\n\n <div className=\"text-muted-foreground\">\n Security notes:\n <ul className=\"list-disc pl-5 mt-1 space-y-1\">\n <li>All endpoints require a valid API key. Keys inherit tenant, organization, and feature scope.</li>\n <li>Rotate keys regularly and delete unused ones in the admin UI.</li>\n <li>Store the secret in a secure vault; anyone with the header can act within the key&apos;s permissions.</li>\n </ul>\n </div>\n </div>\n </ContextHelp>\n <DataTable\n stickyActionsColumn\n title={`Records: ${entityId}`}\n entityId={entityId}\n actions={actions}\n columns={columns}\n data={data}\n perspective={{\n tableId: resolveExtensionPointPattern(extensionPoints.hosts.userRecordsTable.pattern, { entityId }),\n }}\n exporter={exportConfig}\n filters={baseFilters}\n filterValues={filterValues}\n rowActions={(row) => (\n <RowActions\n items={[\n { id: 'edit', label: 'Edit', href: `/backend/entities/user/${encodeURIComponent(entityId)}/records/${encodeURIComponent(String((row as any).id))}` },\n { id: 'delete', label: 'Delete', destructive: true, onSelect: async () => {\n const recordId = String((row as any).id)\n try {\n const confirmed = await confirm({\n title: 'Delete this record?',\n variant: 'destructive',\n })\n if (!confirmed) return\n await runDeleteMutation({\n operation: async () => {\n const deleteCall = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader((row as any).updatedAt),\n () => apiCall(\n `/api/entities/records?entityId=${encodeURIComponent(entityId)}&recordId=${encodeURIComponent(recordId)}`,\n { method: 'DELETE' },\n ),\n )\n if (!deleteCall.ok) {\n await raiseCrudError(deleteCall.response, 'Failed to delete record')\n }\n },\n context: {\n formId: deleteMutationContextId,\n resourceKind: 'entities.record',\n resourceId: recordId,\n retryLastMutation: retryDeleteMutation,\n },\n })\n const j = await readApiResultOrThrow<RecordsResponse>(\n `/api/entities/records?entityId=${encodeURIComponent(entityId)}&page=${page}&pageSize=${pageSize}`,\n undefined,\n {\n errorMessage: 'Failed to reload records',\n fallback: { items: [], total: 0, page, pageSize, totalPages: 1 },\n },\n )\n setRawData(j.items || [])\n setTotal(j.total || 0)\n setTotalPages(j.totalPages || 1)\n flash('Record has been removed', 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to delete record'\n flash(message, 'error')\n }\n } },\n ]}\n />\n )}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n searchValue={search}\n onSearchChange={(v) => { setSearch(v); setPage(1) }}\n onFiltersApply={(vals) => { setFilterValues(vals); setPage(1) }}\n onFiltersClear={() => { setFilterValues({}); setPage(1) }}\n pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}\n isLoading={loading}\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { resolveExtensionPointPattern } from '@open-mercato/shared/modules/widgets/extension-points'\nimport { extensionPoints } from '@open-mercato/core/modules/entities/extension-points'\nimport { useSearchParams } from 'next/navigation'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { filterCustomFieldDefs, useCustomFieldDefs, type CustomFieldDefDto } from '@open-mercato/ui/backend/utils/customFieldDefs'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable, type DataTableExportFormat } from '@open-mercato/ui/backend/DataTable'\nimport type { PreparedExport } from '@open-mercato/shared/lib/crud/exporters'\nimport type { FilterDef } from '@open-mercato/ui/backend/FilterBar'\nimport { ContextHelp } from '@open-mercato/ui/backend/ContextHelp'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport Link from 'next/link'\nimport { apiCall, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { ErrorMessage, LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { useRecordsEntityGuard } from '@open-mercato/core/modules/entities/components/useRecordsEntityGuard'\nimport {\n RelationCell,\n RelationDisplaysProvider,\n useRecordListRelationDisplays,\n} from '@open-mercato/core/modules/entities/components/RecordListRelationCell'\n\ntype RecordsResponse = {\n items: any[]\n total: number\n page: number\n pageSize: number\n totalPages: number\n}\n\nfunction toCsvUrl(base: string, params: URLSearchParams) {\n // Build a relative URL to avoid SSR/CSR origin mismatch hydration issues\n const p = new URLSearchParams(params)\n p.set('format', 'csv')\n const qs = p.toString()\n return qs ? `${base}?${qs}` : base\n}\n\nfunction normalizeCell(v: any): string {\n if (Array.isArray(v)) return v.filter((x) => x != null && x !== '').join(', ')\n if (v === true) return 'Yes'\n if (v === false) return 'No'\n if (v == null) return ''\n if (v instanceof Date) return v.toISOString()\n return String(v)\n}\n\nexport default function RecordsPage({ params }: { params: { entityId?: string } }) {\n const t = useT()\n const entityId = decodeURIComponent(params?.entityId || '')\n const guard = useRecordsEntityGuard(entityId)\n if (guard !== 'allowed') {\n return (\n <Page>\n <PageBody>\n {guard === 'blocked' ? (\n <ErrorMessage label={t('entities.userEntities.records.errors.systemEntity', 'This entity is system-managed. Records are available for custom entities only.')} />\n ) : (\n <LoadingMessage label={t('entities.userEntities.records.loading', 'Loading records...')} />\n )}\n </PageBody>\n </Page>\n )\n }\n return <RecordsPageInner params={params} />\n}\n\nfunction RecordsPageInner({ params }: { params: { entityId?: string } }) {\n const t = useT()\n const entityId = decodeURIComponent(params?.entityId || '')\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'id', desc: false }])\n const [page, setPage] = React.useState(1)\n const [pageSize, setPageSize] = React.useState(50)\n const [search, setSearch] = React.useState('')\n const [filterValues, setFilterValues] = React.useState<Record<string, any>>({})\n const [columns, setColumns] = React.useState<ColumnDef<any>[]>([])\n const [rawData, setRawData] = React.useState<any[]>([])\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [loading, setLoading] = React.useState(false)\n const scopeVersion = useOrganizationScopeVersion()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const deleteMutationContextId = `entities.user.records.${entityId}:single-delete`\n const { runMutation: runDeleteMutation, retryLastMutation: retryDeleteMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: deleteMutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const { data: cfDefs = [] } = useCustomFieldDefs(entityId, {\n enabled: Boolean(entityId),\n keyExtras: [scopeVersion],\n })\n const relationDefinitions = React.useMemo(\n () => filterCustomFieldDefs(cfDefs, 'list').filter(\n (definition): definition is CustomFieldDefDto => definition.kind === 'relation',\n ),\n [cfDefs],\n )\n const relationDisplaysByField = useRecordListRelationDisplays(relationDefinitions, rawData)\n\n // Fields searched server-side: every visible column plus the base `id`.\n const searchableFields = React.useMemo(() => {\n const fields = (columns || [])\n .map((col) => (col as any).accessorKey)\n .filter((key): key is string => typeof key === 'string' && key.length > 0)\n return Array.from(new Set(['id', ...fields]))\n }, [columns])\n\n // Fetch records whenever paging/sorting/filters/search change. Search is applied\n // server-side (before pagination) so totals and exports stay consistent (#3229).\n React.useEffect(() => {\n let cancelled = false\n const run = async () => {\n setLoading(true)\n try {\n const params = new URLSearchParams()\n params.set('entityId', entityId)\n params.set('page', String(page))\n params.set('pageSize', String(pageSize))\n const trimmedSearch = search.trim()\n if (trimmedSearch) {\n params.set('search', trimmedSearch)\n if (searchableFields.length) params.set('searchFields', searchableFields.join(','))\n }\n const s = sorting?.[0]\n if (s?.id) {\n params.set('sortField', String(s.id))\n params.set('sortDir', s.desc ? 'desc' : 'asc')\n }\n // Flatten filter values into query params\n for (const [k, v] of Object.entries(filterValues)) {\n if (v == null) continue\n if (Array.isArray(v)) {\n if (v.length) params.set(k, v.join(','))\n } else if (typeof v === 'object') {\n // dateRange-like shapes are not supported generically here; skip\n } else {\n params.set(k, String(v))\n }\n }\n const j = await readApiResultOrThrow<RecordsResponse>(\n `/api/entities/records?${params.toString()}`,\n undefined,\n {\n errorMessage: 'Failed to load records',\n fallback: {\n items: [],\n total: 0,\n page,\n pageSize,\n totalPages: 1,\n },\n },\n )\n if (!cancelled) {\n setRawData(j.items || [])\n setTotal(j.total)\n setTotalPages(j.totalPages)\n }\n } catch (e) {\n if (!cancelled) {\n setRawData([])\n setTotal(0)\n setTotalPages(1)\n }\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n if (entityId) run()\n return () => { cancelled = true }\n }, [entityId, page, pageSize, sorting, filterValues, scopeVersion, search, searchableFields])\n\n // Build columns from custom field definitions only (no data round-trip)\n React.useEffect(() => {\n const visibleDefs = filterCustomFieldDefs(cfDefs, 'list') as any\n const maxVisible = 10\n const cols: ColumnDef<any>[] = visibleDefs.map((d: any, idx: number) => ({\n accessorKey: d.key,\n header: d.label || d.key,\n meta: { priority: idx < 4 ? 1 : idx < 6 ? 2 : idx < 8 ? 3 : idx < maxVisible ? 4 : 5 },\n cell: ({ getValue }: { getValue: () => unknown }) => {\n const v = getValue() as any\n if (d.kind === 'relation') {\n return <RelationCell fieldKey={d.key} value={v} fallbackText={normalizeCell(v)} />\n }\n return <span className=\"inline-block max-w-60 truncate align-top\" title={normalizeCell(v)}>{normalizeCell(v)}</span>\n },\n }))\n // Ensure hidden 'id' column exists for sorting/state\n const hasIdCol = cols.some((c) => (c as any).accessorKey === 'id' || (c as any).id === 'id')\n if (!hasIdCol) cols.unshift({ accessorKey: 'id', header: 'ID', meta: { hidden: true, priority: 6 } } as any)\n setColumns(cols)\n }, [cfDefs])\n\n // Search is server-side (see fetch effect); render the fetched page as-is so\n // pagination totals and exports stay consistent with the active search (#3229).\n const data = rawData\n\n const viewExportColumns = React.useMemo(() => {\n return (columns || [])\n .map((col) => {\n const accessorKey = (col as any).accessorKey\n if (!accessorKey || typeof accessorKey !== 'string') return null\n if ((col as any).meta?.hidden) return null\n const header = typeof col.header === 'string'\n ? col.header\n : accessorKey.startsWith('cf_')\n ? accessorKey.slice(3)\n : accessorKey\n return { field: accessorKey, header }\n })\n .filter((col): col is { field: string; header: string } => !!col)\n }, [columns])\n\n const buildFullExportUrl = React.useCallback((format: DataTableExportFormat) => {\n const qp = new URLSearchParams({\n entityId,\n format,\n exportScope: 'full',\n all: 'true',\n })\n const sort = sorting?.[0]\n if (sort?.id) {\n qp.set('sortField', String(sort.id))\n qp.set('sortDir', sort.desc ? 'desc' : 'asc')\n }\n const trimmedSearch = search.trim()\n if (trimmedSearch) {\n qp.set('search', trimmedSearch)\n if (searchableFields.length) qp.set('searchFields', searchableFields.join(','))\n }\n return `/api/entities/records?${qp.toString()}`\n }, [entityId, sorting, search, searchableFields])\n\n const exportConfig = React.useMemo(() => {\n const safeEntityId = entityId.replace(/[^a-z0-9_-]/gi, '_') || 'records'\n return {\n view: {\n description: 'Exports the current list respecting filters and column visibility.',\n prepare: async (): Promise<{ prepared: PreparedExport; filename: string }> => {\n const rowsForExport = data.map((row) => {\n const out: Record<string, unknown> = {}\n for (const col of viewExportColumns) {\n out[col.field] = (row as Record<string, unknown>)[col.field]\n }\n return out\n })\n const prepared: PreparedExport = {\n columns: viewExportColumns.map((col) => ({ field: col.field, header: col.header })),\n rows: rowsForExport,\n }\n return { prepared, filename: `${safeEntityId}_view` }\n },\n },\n full: {\n description: 'Exports raw records with every field and custom field included.',\n getUrl: (format: DataTableExportFormat) => buildFullExportUrl(format),\n filename: () => `${safeEntityId}_full`,\n },\n }\n }, [buildFullExportUrl, data, entityId, viewExportColumns])\n\n const hasAnyFormFields = React.useMemo(() => filterCustomFieldDefs(cfDefs, 'form').length > 0, [cfDefs])\n const actions = (\n <>\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href={`/backend/entities/user/${encodeURIComponent(entityId)}`}>\n Edit Entity Definition\n </Link>\n </Button>\n {hasAnyFormFields && (\n <Button asChild>\n <Link href={`/backend/entities/user/${encodeURIComponent(entityId)}/records/create`}>\n Create\n </Link>\n </Button>\n )}\n </>\n )\n\n // Ensure filters are visible even if no custom fields are marked filterable\n const baseFilters: FilterDef[] = React.useMemo(() => ([\n { id: 'id', label: 'ID', type: 'text' },\n ]), [])\n\n return (\n <Page>\n <PageBody>\n <ContextHelp bulb title=\"API: Manage Records via cURL\" className=\"mb-4\">\n <p className=\"mb-2\">\n Interact with this custom entity via the backend API using cURL. Use API keys for machine-to-machine access\u2014mint one from the{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/user-guide/api-keys\">\n Managing API keys guide\n </a>{' '}\n or the{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/cli/api-keys\">\n API keys CLI documentation\n </a>{' '}\n before running these calls.\n </p>\n <div className=\"space-y-2\">\n <div>\n <div className=\"font-medium mb-1\">1) Configure environment variables</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`export BASE_URL=\"http://localhost:3000/api\"\nexport API_KEY=\"<paste API key secret here>\" # scoped with entities.features\nexport ENTITY_ID=\"${entityId}\"\nexport RECORD_ID=\"<record uuid>\"`}</code></pre>\n <p className=\"text-muted-foreground mt-1\">\n Need a new key? Follow the{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/user-guide/api-keys\">\n Managing API keys\n </a>{' '}\n walkthrough or mint one via{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/cli/api-keys\">\n mercato api_keys add\n </a>\n .\n </p>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">2) List records</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -H \"X-Api-Key: $API_KEY\" \\\n \"$BASE_URL/entities/records?entityId=$ENTITY_ID\" | jq`}</code></pre>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">3) Read a single record (by id)</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -H \"X-Api-Key: $API_KEY\" \\\n \"$BASE_URL/entities/records?entityId=$ENTITY_ID&id=$RECORD_ID\" | jq`}</code></pre>\n <p className=\"text-muted-foreground mt-1\">Note: Response is a list; filter by <code>id</code> to get a single item.</p>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">4) Create a record</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -X POST \\\n -H \"X-Api-Key: $API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d \"{\n \\\\\"entityId\\\\\": \\\\\"$ENTITY_ID\\\\\",\n \\\\\"values\\\\\": {\n \\\\\"field_one\\\\\": \\\\\"Example\\\\\",\n \\\\\"field_two\\\\\": 123\n }\n }\" \\\n \"$BASE_URL/entities/records\" | jq`}</code></pre>\n <p className=\"text-muted-foreground mt-1\">For custom entities, send field keys without the <code>cf_</code> prefix. The API normalizes this server-side.</p>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">5) Update a record</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -X PUT \\\n -H \"X-Api-Key: $API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d \"{\n \\\\\"entityId\\\\\": \\\\\"$ENTITY_ID\\\\\",\n \\\\\"recordId\\\\\": \\\\\"$RECORD_ID\\\\\",\n \\\\\"values\\\\\": {\n \\\\\"field_one\\\\\": \\\\\"Updated\\\\\"\n }\n }\" \\\n \"$BASE_URL/entities/records\" | jq`}</code></pre>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">6) Delete a record</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -X DELETE \\\n -H \"X-Api-Key: $API_KEY\" \\\n \"$BASE_URL/entities/records?entityId=$ENTITY_ID&recordId=$RECORD_ID\" | jq`}</code></pre>\n </div>\n\n <div className=\"text-muted-foreground\">\n Security notes:\n <ul className=\"list-disc pl-5 mt-1 space-y-1\">\n <li>All endpoints require a valid API key. Keys inherit tenant, organization, and feature scope.</li>\n <li>Rotate keys regularly and delete unused ones in the admin UI.</li>\n <li>Store the secret in a secure vault; anyone with the header can act within the key&apos;s permissions.</li>\n </ul>\n </div>\n </div>\n </ContextHelp>\n <RelationDisplaysProvider displaysByField={relationDisplaysByField}>\n <DataTable\n stickyActionsColumn\n title={`Records: ${entityId}`}\n entityId={entityId}\n actions={actions}\n columns={columns}\n data={data}\n perspective={{\n tableId: resolveExtensionPointPattern(extensionPoints.hosts.userRecordsTable.pattern, { entityId }),\n }}\n exporter={exportConfig}\n filters={baseFilters}\n filterValues={filterValues}\n rowActions={(row) => (\n <RowActions\n items={[\n { id: 'edit', label: 'Edit', href: `/backend/entities/user/${encodeURIComponent(entityId)}/records/${encodeURIComponent(String((row as any).id))}` },\n { id: 'delete', label: 'Delete', destructive: true, onSelect: async () => {\n const recordId = String((row as any).id)\n try {\n const confirmed = await confirm({\n title: 'Delete this record?',\n variant: 'destructive',\n })\n if (!confirmed) return\n await runDeleteMutation({\n operation: async () => {\n const deleteCall = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader((row as any).updatedAt),\n () => apiCall(\n `/api/entities/records?entityId=${encodeURIComponent(entityId)}&recordId=${encodeURIComponent(recordId)}`,\n { method: 'DELETE' },\n ),\n )\n if (!deleteCall.ok) {\n await raiseCrudError(deleteCall.response, 'Failed to delete record')\n }\n },\n context: {\n formId: deleteMutationContextId,\n resourceKind: 'entities.record',\n resourceId: recordId,\n retryLastMutation: retryDeleteMutation,\n },\n })\n const j = await readApiResultOrThrow<RecordsResponse>(\n `/api/entities/records?entityId=${encodeURIComponent(entityId)}&page=${page}&pageSize=${pageSize}`,\n undefined,\n {\n errorMessage: 'Failed to reload records',\n fallback: { items: [], total: 0, page, pageSize, totalPages: 1 },\n },\n )\n setRawData(j.items || [])\n setTotal(j.total || 0)\n setTotalPages(j.totalPages || 1)\n flash('Record has been removed', 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to delete record'\n flash(message, 'error')\n }\n } },\n ]}\n />\n )}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n searchValue={search}\n onSearchChange={(v) => { setSearch(v); setPage(1) }}\n onFiltersApply={(vals) => { setFilterValues(vals); setPage(1) }}\n onFiltersClear={() => { setFilterValues({}); setPage(1) }}\n pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}\n isLoading={loading}\n />\n </RelationDisplaysProvider>\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["params"]
7
7
  }