@c-rex/services 0.3.0-build.38 → 0.3.0-build.40

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 (33) hide show
  1. package/dist/index.d.mts +3 -1
  2. package/dist/index.d.ts +3 -1
  3. package/dist/index.js +430 -147
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +411 -143
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/metadata-visibility-policy.d.mts +29 -0
  8. package/dist/metadata-visibility-policy.d.ts +29 -0
  9. package/dist/metadata-visibility-policy.js +129 -0
  10. package/dist/metadata-visibility-policy.js.map +1 -0
  11. package/dist/metadata-visibility-policy.mjs +95 -0
  12. package/dist/metadata-visibility-policy.mjs.map +1 -0
  13. package/dist/read-models/index.d.mts +17 -39
  14. package/dist/read-models/index.d.ts +17 -39
  15. package/dist/read-models/index.js +430 -149
  16. package/dist/read-models/index.js.map +1 -1
  17. package/dist/read-models/index.mjs +410 -144
  18. package/dist/read-models/index.mjs.map +1 -1
  19. package/dist/read-models/metadata-display-builder.d.mts +34 -0
  20. package/dist/read-models/metadata-display-builder.d.ts +34 -0
  21. package/dist/read-models/metadata-display-builder.js +521 -0
  22. package/dist/read-models/metadata-display-builder.js.map +1 -0
  23. package/dist/read-models/metadata-display-builder.mjs +489 -0
  24. package/dist/read-models/metadata-display-builder.mjs.map +1 -0
  25. package/dist/read-models/metadata-presentation-config.js +2 -2
  26. package/dist/read-models/metadata-presentation-config.js.map +1 -1
  27. package/dist/read-models/metadata-presentation-config.mjs +2 -2
  28. package/dist/read-models/metadata-presentation-config.mjs.map +1 -1
  29. package/dist/read-models/metadata-view-profile.js +63 -4
  30. package/dist/read-models/metadata-view-profile.js.map +1 -1
  31. package/dist/read-models/metadata-view-profile.mjs +63 -4
  32. package/dist/read-models/metadata-view-profile.mjs.map +1 -1
  33. package/package.json +19 -1
package/dist/index.js CHANGED
@@ -27,6 +27,7 @@ __export(index_exports, {
27
27
  InformationUnitsService: () => InformationUnitsService,
28
28
  LanguageService: () => LanguageService,
29
29
  METADATA_VIEW_PROFILES: () => METADATA_VIEW_PROFILES,
30
+ METADATA_VISIBILITY_POLICY: () => METADATA_VISIBILITY_POLICY,
30
31
  READMODEL_CACHE_POLICY: () => READMODEL_CACHE_POLICY,
31
32
  RenditionsService: () => RenditionsService,
32
33
  TopicsService: () => TopicsService,
@@ -38,11 +39,13 @@ __export(index_exports, {
38
39
  afterUsesGetAllServer: () => afterUsesGetAllServer,
39
40
  afterUsesGetByIdClientService: () => afterUsesGetByIdClientService,
40
41
  afterUsesGetByIdServer: () => afterUsesGetByIdServer,
42
+ buildMetadataDisplayRows: () => buildMetadataDisplayRows,
41
43
  buildTelephoneEntries: () => buildTelephoneEntries,
42
44
  categoriesGetAllClientService: () => categoriesGetAllClientService,
43
45
  categoriesGetAllServer: () => categoriesGetAllServer,
44
46
  categoriesGetByIdClientService: () => categoriesGetByIdClientService,
45
47
  categoriesGetByIdServer: () => categoriesGetByIdServer,
48
+ clearMetadataCacheFamilyRuntimeSuppression: () => clearMetadataCacheFamilyRuntimeSuppression,
46
49
  collectionsGetAllClientService: () => collectionsGetAllClientService,
47
50
  collectionsGetAllServer: () => collectionsGetAllServer,
48
51
  collectionsGetByIdClientService: () => collectionsGetByIdClientService,
@@ -137,8 +140,10 @@ __export(index_exports, {
137
140
  getIndividualProfileById: () => getIndividualProfileById,
138
141
  getIndividualsProfiles: () => getIndividualsProfiles,
139
142
  getInformationSubjects: () => getInformationSubjects,
143
+ getMetadataCacheFamily: () => getMetadataCacheFamily,
140
144
  getMetadataDisplayRows: () => getMetadataDisplayRows,
141
145
  getMetadataFacetLabelOverrides: () => getMetadataFacetLabelOverrides,
146
+ getMetadataFacetPresentation: () => getMetadataFacetPresentation,
142
147
  getMetadataPropertyResolvers: () => getMetadataPropertyResolvers,
143
148
  getOrganizationBranding: () => getOrganizationBranding,
144
149
  getOrganizationProfile: () => getOrganizationProfile,
@@ -151,6 +156,7 @@ __export(index_exports, {
151
156
  getProductMetadata: () => getProductMetadata,
152
157
  getProductVariants: () => getProductVariants,
153
158
  getQualifications: () => getQualifications,
159
+ getRuntimeSuppressedMetadataFamilies: () => getRuntimeSuppressedMetadataFamilies,
154
160
  getServerConfig: () => getServerConfig,
155
161
  getSupplies: () => getSupplies,
156
162
  getTopicTypes: () => getTopicTypes,
@@ -194,6 +200,8 @@ __export(index_exports, {
194
200
  informationUnitsGetByIdServer: () => informationUnitsGetByIdServer,
195
201
  informationUnitsLanguagesClientService: () => informationUnitsLanguagesClientService,
196
202
  informationUnitsLanguagesServer: () => informationUnitsLanguagesServer,
203
+ isMetadataGroupDenied: () => isMetadataGroupDenied,
204
+ isMetadataPropertyRuntimeSuppressed: () => isMetadataPropertyRuntimeSuppressed,
197
205
  learningsGetAllClientService: () => learningsGetAllClientService,
198
206
  learningsGetAllServer: () => learningsGetAllServer,
199
207
  learningsGetByIdClientService: () => learningsGetByIdClientService,
@@ -283,9 +291,15 @@ __export(index_exports, {
283
291
  renditionsGetByIdServer: () => renditionsGetByIdServer,
284
292
  renditionsGetWithBinaryWithBinaryPathClientService: () => renditionsGetWithBinaryWithBinaryPathClientService,
285
293
  renditionsGetWithBinaryWithBinaryPathServer: () => renditionsGetWithBinaryWithBinaryPathServer,
294
+ resetRuntimeSuppressedMetadataFamiliesForTests: () => resetRuntimeSuppressedMetadataFamiliesForTests,
295
+ resolveFacetPresentationProperties: () => resolveFacetPresentationProperties,
286
296
  resolveFacetTags: () => resolveFacetTags,
297
+ resolveLiteralLabel: () => resolveLiteralLabel,
287
298
  resolveLogoSource: () => resolveLogoSource,
288
299
  resolveMetadataDisplayProperties: () => resolveMetadataDisplayProperties,
300
+ resolveObjectRefClassLabel: () => resolveObjectRefClassLabel,
301
+ resolveObjectRefLabel: () => resolveObjectRefLabel,
302
+ resolveOverrideProperties: () => resolveOverrideProperties,
289
303
  resolveSocialProviderLabel: () => resolveSocialProviderLabel,
290
304
  resolveTypedSocialLinks: () => resolveTypedSocialLinks,
291
305
  resolveUiLanguage: () => resolveUiLanguage,
@@ -329,6 +343,7 @@ __export(index_exports, {
329
343
  suppliesGetAllServer: () => suppliesGetAllServer,
330
344
  suppliesGetByIdClientService: () => suppliesGetByIdClientService,
331
345
  suppliesGetByIdServer: () => suppliesGetByIdServer,
346
+ suppressMetadataCacheFamilyRuntime: () => suppressMetadataCacheFamilyRuntime,
332
347
  tasksGetAllClientService: () => tasksGetAllClientService,
333
348
  tasksGetAllServer: () => tasksGetAllServer,
334
349
  tasksGetByIdClientService: () => tasksGetByIdClientService,
@@ -1782,7 +1797,109 @@ var getVCardProfiles = async (query) => {
1782
1797
 
1783
1798
  // src/read-models/metadata-read-models.ts
1784
1799
  var import_requests3 = require("@c-rex/core/requests");
1800
+ var import_logger = require("@c-rex/core/logger");
1785
1801
  var import_cache2 = require("next/cache");
1802
+
1803
+ // src/read-models/metadata-visibility-policy.ts
1804
+ var CONTENT_LICENSE_CLASS_ID = "https://ids.c-crex.net/ns/iirds/ext#ContentLicense";
1805
+ var METADATA_VISIBILITY_POLICY = {
1806
+ parties: {
1807
+ cacheFamily: "parties"
1808
+ },
1809
+ components: {
1810
+ cacheFamily: "components"
1811
+ },
1812
+ informationSubjects: {
1813
+ cacheFamily: "informationSubjects"
1814
+ },
1815
+ topicTypes: {
1816
+ cacheFamily: "topicTypes"
1817
+ },
1818
+ documentTypes: {
1819
+ cacheFamily: "documentTypes"
1820
+ },
1821
+ contentLifeCycleStatus: {
1822
+ cacheFamily: "contentLifeCycleStatus"
1823
+ },
1824
+ applicableForTypes: {
1825
+ cacheFamily: "documentTypes"
1826
+ },
1827
+ planningTimes: {
1828
+ cacheFamily: "planningTimes"
1829
+ },
1830
+ functionalMetadata: {
1831
+ cacheFamily: "functionalMetadata"
1832
+ },
1833
+ productFeatures: {
1834
+ cacheFamily: "productFeatures"
1835
+ },
1836
+ productLifeCyclePhases: {
1837
+ cacheFamily: "productLifeCyclePhases"
1838
+ },
1839
+ productMetadata: {
1840
+ cacheFamily: "productMetadata"
1841
+ },
1842
+ productVariants: {
1843
+ cacheFamily: "productVariants"
1844
+ },
1845
+ qualifications: {
1846
+ cacheFamily: "qualifications",
1847
+ deniedClassIds: [CONTENT_LICENSE_CLASS_ID]
1848
+ },
1849
+ supplies: {
1850
+ cacheFamily: "supplies"
1851
+ }
1852
+ };
1853
+ var runtimeSuppressedFamilies = /* @__PURE__ */ new Map();
1854
+ var getMetadataCacheFamily = (property) => METADATA_VISIBILITY_POLICY[property]?.cacheFamily;
1855
+ var isMetadataGroupDenied = (property, options) => {
1856
+ const policy = METADATA_VISIBILITY_POLICY[property];
1857
+ const classId = options.classId?.trim();
1858
+ const partyRoleId = options.partyRoleId?.trim();
1859
+ if (classId && policy?.deniedClassIds?.includes(classId)) {
1860
+ return true;
1861
+ }
1862
+ if (partyRoleId && policy?.deniedPartyRoleIds?.includes(partyRoleId)) {
1863
+ return true;
1864
+ }
1865
+ return false;
1866
+ };
1867
+ var suppressMetadataCacheFamilyRuntime = (family, entry) => {
1868
+ runtimeSuppressedFamilies.set(family, {
1869
+ family,
1870
+ reason: "cache-overflow",
1871
+ bytes: entry.bytes,
1872
+ limitBytes: entry.limitBytes,
1873
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1874
+ });
1875
+ };
1876
+ var clearMetadataCacheFamilyRuntimeSuppression = (family) => {
1877
+ runtimeSuppressedFamilies.delete(family);
1878
+ };
1879
+ var isMetadataPropertyRuntimeSuppressed = (property) => {
1880
+ const family = getMetadataCacheFamily(property);
1881
+ return family ? runtimeSuppressedFamilies.has(family) : false;
1882
+ };
1883
+ var getRuntimeSuppressedMetadataFamilies = () => Array.from(runtimeSuppressedFamilies.values());
1884
+ var resetRuntimeSuppressedMetadataFamiliesForTests = () => {
1885
+ runtimeSuppressedFamilies.clear();
1886
+ };
1887
+
1888
+ // src/read-models/metadata-read-models.ts
1889
+ var DEFAULT_METADATA_CACHE_MAX_BYTES = 15e5;
1890
+ var resolveMetadataCacheMaxBytes = () => {
1891
+ const value = Number(process.env.CREX_CACHE_METADATA_MAX_BYTES);
1892
+ return Number.isFinite(value) && value > 0 ? value : DEFAULT_METADATA_CACHE_MAX_BYTES;
1893
+ };
1894
+ var measureSerializedBytes = (value) => Buffer.byteLength(JSON.stringify(value), "utf8");
1895
+ var logCacheOverflow = async (family, bytes, limitBytes, cacheKey) => {
1896
+ const logger = new import_logger.CrexLogger();
1897
+ await logger.log({
1898
+ level: "warning",
1899
+ category: "Scenario",
1900
+ message: `[MetadataCacheOverflow] family=${family} bytes=${bytes} limitBytes=${limitBytes} cacheKey=${cacheKey}`
1901
+ });
1902
+ };
1786
1903
  var resolveLocalizedLabel = (labels, uiLanguage) => {
1787
1904
  if (!labels || labels.length === 0) return void 0;
1788
1905
  const normalizedUiLanguage = uiLanguage.trim().toLowerCase();
@@ -1841,12 +1958,39 @@ var toEntityRef = (entity, uiLanguage) => {
1841
1958
  const label = resolveLocalizedLabel(entity.labels || [], uiLanguage) || entity.shortId?.trim() || id;
1842
1959
  return { id, shortId: entity.shortId?.trim() || void 0, label };
1843
1960
  };
1844
- var toClassRef = (classRef, uiLanguage) => {
1961
+ var toClassRef = (classRef, uiLanguage, classLabelsById) => {
1845
1962
  const id = classRef?.id?.trim();
1846
1963
  if (!id) return void 0;
1847
- const label = resolveLocalizedLabel(classRef?.labels || [], uiLanguage) || classRef?.shortId?.trim() || id;
1964
+ const label = resolveLocalizedLabel(classRef?.labels || [], uiLanguage) || classLabelsById?.[id] || classRef?.shortId?.trim() || id;
1848
1965
  return { id, shortId: classRef?.shortId?.trim() || void 0, label };
1849
1966
  };
1967
+ var isNotFoundError = (error) => {
1968
+ if (!(error instanceof Error)) {
1969
+ return false;
1970
+ }
1971
+ return error.message.includes("HTTP error! status: 404");
1972
+ };
1973
+ var resolveMissingClassLabels = async (items, uiLanguage) => {
1974
+ const classIds = Array.from(new Set(
1975
+ items.map((item) => item.class?.id?.trim()).filter((id) => Boolean(id)).filter((id) => !resolveLocalizedLabel(items.find((item) => item.class?.id?.trim() === id)?.class?.labels || [], uiLanguage))
1976
+ ));
1977
+ const result = {};
1978
+ await Promise.all(classIds.map(async (classId) => {
1979
+ try {
1980
+ const entity = await withServerRequestContext(
1981
+ { skipCookieTokenLookup: true },
1982
+ () => domainEntitiesGetByIdServer({ id: classId }, { Fields: ["labels"] })
1983
+ );
1984
+ result[classId] = resolveLocalizedLabel(entity.labels || [], uiLanguage);
1985
+ } catch (error) {
1986
+ if (!isNotFoundError(error)) {
1987
+ throw error;
1988
+ }
1989
+ result[classId] = void 0;
1990
+ }
1991
+ }));
1992
+ return result;
1993
+ };
1850
1994
  var deriveParentIds = (entity) => {
1851
1995
  const directParents = (entity.parents || []).map((parent) => getRefId(parent)).filter((value) => Boolean(value));
1852
1996
  if (directParents.length > 0) {
@@ -1855,10 +1999,6 @@ var deriveParentIds = (entity) => {
1855
1999
  const ancestorParents = (entity.ancestors || []).map((path) => path[path.length - 1]).map((parent) => getRefId(parent)).filter((value) => Boolean(value));
1856
2000
  return Array.from(new Set(ancestorParents));
1857
2001
  };
1858
- var deriveAncestorIds = (entity) => {
1859
- const ids = (entity.ancestors || []).flatMap((path) => path).map((item) => getRefId(item)).filter((value) => Boolean(value));
1860
- return Array.from(new Set(ids));
1861
- };
1862
2002
  var buildTaxonomyTree = (items, options) => {
1863
2003
  const nodesById = {};
1864
2004
  const parentLinks = /* @__PURE__ */ new Map();
@@ -1867,48 +2007,13 @@ var buildTaxonomyTree = (items, options) => {
1867
2007
  if (!entityRef) continue;
1868
2008
  nodesById[entityRef.id] = {
1869
2009
  ...entityRef,
1870
- classRef: toClassRef(item.class, options.uiLanguage),
1871
- hasInformationUnits: item.hasInformationUnits === true || item.hasInformationUnitReferences === true,
1872
- parentIds: deriveParentIds(item),
1873
- ancestorIds: deriveAncestorIds(item),
1874
- children: []
2010
+ classRef: toClassRef(item.class, options.uiLanguage, options.classLabelsById),
2011
+ parentIds: deriveParentIds(item)
1875
2012
  };
1876
2013
  }
1877
2014
  Object.values(nodesById).forEach((node) => {
1878
2015
  parentLinks.set(node.id, node.parentIds.filter((id) => Boolean(nodesById[id])));
1879
2016
  });
1880
- if (options.includeOnlyUsed) {
1881
- const keepIds = new Set(
1882
- Object.values(nodesById).filter((node) => node.hasInformationUnits === true).map((node) => node.id)
1883
- );
1884
- let changed = true;
1885
- while (changed) {
1886
- changed = false;
1887
- Array.from(keepIds).forEach((nodeId) => {
1888
- const parentIds = parentLinks.get(nodeId) || [];
1889
- parentIds.forEach((parentId) => {
1890
- if (!keepIds.has(parentId)) {
1891
- keepIds.add(parentId);
1892
- changed = true;
1893
- }
1894
- });
1895
- });
1896
- }
1897
- Object.keys(nodesById).forEach((nodeId) => {
1898
- if (!keepIds.has(nodeId)) {
1899
- delete nodesById[nodeId];
1900
- parentLinks.delete(nodeId);
1901
- }
1902
- });
1903
- }
1904
- Object.values(nodesById).forEach((node) => {
1905
- const parents = parentLinks.get(node.id) || [];
1906
- parents.forEach((parentId) => {
1907
- if (nodesById[parentId]) {
1908
- nodesById[parentId].children.push(node);
1909
- }
1910
- });
1911
- });
1912
2017
  const roots = Object.values(nodesById).filter((node) => (parentLinks.get(node.id) || []).length === 0);
1913
2018
  if (!options.groupRootsByClass) {
1914
2019
  return {
@@ -1918,13 +2023,12 @@ var buildTaxonomyTree = (items, options) => {
1918
2023
  };
1919
2024
  }
1920
2025
  const groupedRoots = /* @__PURE__ */ new Map();
2026
+ const groupedRootCounts = /* @__PURE__ */ new Map();
1921
2027
  const ungroupedRootId = "class:ungrouped";
1922
2028
  groupedRoots.set(ungroupedRootId, {
1923
2029
  id: ungroupedRootId,
1924
2030
  label: "Ungrouped",
1925
2031
  parentIds: [],
1926
- ancestorIds: [],
1927
- children: [],
1928
2032
  isVirtualGroup: true
1929
2033
  });
1930
2034
  roots.forEach((root) => {
@@ -1935,17 +2039,12 @@ var buildTaxonomyTree = (items, options) => {
1935
2039
  shortId: root.classRef?.shortId,
1936
2040
  label: root.classRef?.label || "Ungrouped",
1937
2041
  parentIds: [],
1938
- ancestorIds: [],
1939
- children: [],
1940
2042
  isVirtualGroup: true
1941
2043
  });
1942
2044
  }
1943
- groupedRoots.get(classId)?.children.push(root);
2045
+ groupedRootCounts.set(classId, (groupedRootCounts.get(classId) || 0) + 1);
1944
2046
  });
1945
- const groupedRootNodes = Array.from(groupedRoots.values()).filter((group) => group.children.length > 0).map((group) => ({
1946
- ...group,
1947
- children: [...group.children].sort((a, b) => a.label.localeCompare(b.label))
1948
- })).sort((a, b) => a.label.localeCompare(b.label));
2047
+ const groupedRootNodes = Array.from(groupedRoots.values()).filter((group) => (groupedRootCounts.get(group.id) || 0) > 0).sort((a, b) => a.label.localeCompare(b.label));
1949
2048
  return {
1950
2049
  roots: groupedRootNodes,
1951
2050
  nodesById,
@@ -1958,15 +2057,29 @@ var defaultTreeOptions = (uiLanguage) => ({
1958
2057
  });
1959
2058
  var createTaxonomyResolver = (options) => {
1960
2059
  const cached = (0, import_cache2.unstable_cache)(
1961
- async (_queryKey, query, uiLanguage, readOptions) => {
2060
+ async (_queryKey, query, uiLanguage) => {
1962
2061
  const items = await withServerRequestContext(
1963
2062
  { skipCookieTokenLookup: true },
1964
2063
  () => fetchAllPages(options.fetch, query)
1965
2064
  );
1966
- return buildTaxonomyTree(items, {
2065
+ const classLabelsById = await resolveMissingClassLabels(items, uiLanguage);
2066
+ const result = buildTaxonomyTree(items, {
1967
2067
  ...defaultTreeOptions(uiLanguage),
1968
- includeOnlyUsed: readOptions.includeOnlyUsed
2068
+ classLabelsById
1969
2069
  });
2070
+ const bytes = measureSerializedBytes(result);
2071
+ const limitBytes = resolveMetadataCacheMaxBytes();
2072
+ if (bytes > limitBytes) {
2073
+ suppressMetadataCacheFamilyRuntime(options.cacheFamily, { bytes, limitBytes });
2074
+ await logCacheOverflow(options.cacheFamily, bytes, limitBytes, options.cacheKey);
2075
+ return {
2076
+ roots: [],
2077
+ nodesById: {},
2078
+ generatedAt: result.generatedAt
2079
+ };
2080
+ }
2081
+ clearMetadataCacheFamilyRuntimeSuppression(options.cacheFamily);
2082
+ return result;
1970
2083
  },
1971
2084
  ["read-model", options.cacheKey],
1972
2085
  {
@@ -1979,101 +2092,116 @@ var createTaxonomyResolver = (options) => {
1979
2092
  ]
1980
2093
  }
1981
2094
  );
1982
- return async (query, readOptions) => {
2095
+ return async (query) => {
1983
2096
  const uiLanguage = resolveUiLanguage();
1984
2097
  const normalizedQuery = { ...options.defaultQuery, ...query || {} };
1985
- const normalizedReadOptions = {
1986
- includeOnlyUsed: readOptions?.includeOnlyUsed === true
1987
- };
1988
- const cacheKey = stableSerialize({ normalizedQuery, uiLanguage, normalizedReadOptions });
1989
- return cached(cacheKey, normalizedQuery, uiLanguage, normalizedReadOptions);
2098
+ const cacheKey = stableSerialize({ normalizedQuery, uiLanguage });
2099
+ return cached(cacheKey, normalizedQuery, uiLanguage);
1990
2100
  };
1991
2101
  };
1992
2102
  var defaultMetadataQuery = {
1993
2103
  PageNumber: 1,
1994
2104
  PageSize: READMODEL_PAGE_SIZE,
1995
- Fields: ["labels", "class", "hasInformationUnits"],
2105
+ Fields: ["labels", "class"],
1996
2106
  Sort: ["shortId"]
1997
2107
  };
1998
2108
  var getCategoriesCached = createTaxonomyResolver({
1999
2109
  cacheKey: "categories",
2110
+ cacheFamily: "informationSubjects",
2000
2111
  tags: [import_requests3.CREX_READMODEL_CACHE_INFORMATION_SUBJECTS_TAG],
2001
- defaultQuery: defaultMetadataQuery,
2112
+ defaultQuery: {
2113
+ ...defaultMetadataQuery,
2114
+ Fields: ["labels", "class", "parents", "ancestors", "ancestorsOrSelf"]
2115
+ },
2002
2116
  fetch: categoriesGetAllServer
2003
2117
  });
2004
2118
  var getInformationSubjectsLegacyCached = createTaxonomyResolver({
2005
2119
  cacheKey: "information-subjects-legacy",
2120
+ cacheFamily: "informationSubjects",
2006
2121
  tags: [import_requests3.CREX_READMODEL_CACHE_INFORMATION_SUBJECTS_TAG],
2007
2122
  defaultQuery: defaultMetadataQuery,
2008
2123
  fetch: informationSubjectsGetAllServer
2009
2124
  });
2010
2125
  var getDocumentTypesCached = createTaxonomyResolver({
2011
2126
  cacheKey: "document-types",
2127
+ cacheFamily: "documentTypes",
2012
2128
  tags: [import_requests3.CREX_READMODEL_CACHE_DOCUMENT_TYPES_TAG],
2013
2129
  defaultQuery: defaultMetadataQuery,
2014
2130
  fetch: documentTypesGetAllServer
2015
2131
  });
2016
2132
  var getComponentsCached = createTaxonomyResolver({
2017
2133
  cacheKey: "components",
2134
+ cacheFamily: "components",
2018
2135
  tags: [import_requests3.CREX_READMODEL_CACHE_COMPONENTS_TAG],
2019
2136
  defaultQuery: {
2020
2137
  ...defaultMetadataQuery,
2021
- Fields: ["labels", "class", "parents", "ancestors", "ancestorsOrSelf", "hasInformationUnits"]
2138
+ Fields: ["labels", "class", "parents", "ancestors", "ancestorsOrSelf"]
2022
2139
  },
2023
2140
  fetch: componentsGetAllServer
2024
2141
  });
2025
2142
  var getTopicTypesCached = createTaxonomyResolver({
2026
2143
  cacheKey: "topic-types",
2144
+ cacheFamily: "topicTypes",
2027
2145
  defaultQuery: defaultMetadataQuery,
2028
2146
  fetch: topicTypesGetAllServer
2029
2147
  });
2030
2148
  var getContentLifeCycleStatusCached = createTaxonomyResolver({
2031
2149
  cacheKey: "content-life-cycle-status",
2150
+ cacheFamily: "contentLifeCycleStatus",
2032
2151
  defaultQuery: defaultMetadataQuery,
2033
2152
  fetch: contentLifeCycleStatusGetAllServer
2034
2153
  });
2035
2154
  var getApplicableForTypesCached = createTaxonomyResolver({
2036
2155
  cacheKey: "applicable-for-types",
2156
+ cacheFamily: "documentTypes",
2037
2157
  defaultQuery: defaultMetadataQuery,
2038
2158
  fetch: informationTypesGetAllServer
2039
2159
  });
2040
2160
  var getPlanningTimesCached = createTaxonomyResolver({
2041
2161
  cacheKey: "planning-times",
2162
+ cacheFamily: "planningTimes",
2042
2163
  defaultQuery: defaultMetadataQuery,
2043
2164
  fetch: planningTimesGetAllServer
2044
2165
  });
2045
2166
  var getFunctionalMetadataCached = createTaxonomyResolver({
2046
2167
  cacheKey: "functional-metadata",
2168
+ cacheFamily: "functionalMetadata",
2047
2169
  defaultQuery: defaultMetadataQuery,
2048
2170
  fetch: functionalMetadatasGetAllServer
2049
2171
  });
2050
2172
  var getProductFeaturesCached = createTaxonomyResolver({
2051
2173
  cacheKey: "product-features",
2174
+ cacheFamily: "productFeatures",
2052
2175
  defaultQuery: defaultMetadataQuery,
2053
2176
  fetch: productFeaturesGetAllServer
2054
2177
  });
2055
2178
  var getProductLifeCyclePhasesCached = createTaxonomyResolver({
2056
2179
  cacheKey: "product-life-cycle-phases",
2180
+ cacheFamily: "productLifeCyclePhases",
2057
2181
  defaultQuery: defaultMetadataQuery,
2058
2182
  fetch: productLifeCyclePhasesGetAllServer
2059
2183
  });
2060
2184
  var getProductMetadataCached = createTaxonomyResolver({
2061
2185
  cacheKey: "product-metadata",
2186
+ cacheFamily: "productMetadata",
2062
2187
  defaultQuery: defaultMetadataQuery,
2063
2188
  fetch: productMetadataGetAllServer
2064
2189
  });
2065
2190
  var getProductVariantsCached = createTaxonomyResolver({
2066
2191
  cacheKey: "product-variants",
2192
+ cacheFamily: "productVariants",
2067
2193
  defaultQuery: defaultMetadataQuery,
2068
2194
  fetch: productVariantsGetAllServer
2069
2195
  });
2070
2196
  var getQualificationsCached = createTaxonomyResolver({
2071
2197
  cacheKey: "qualifications",
2198
+ cacheFamily: "qualifications",
2072
2199
  defaultQuery: defaultMetadataQuery,
2073
2200
  fetch: qualificationsGetAllServer
2074
2201
  });
2075
2202
  var getSuppliesCached = createTaxonomyResolver({
2076
2203
  cacheKey: "supplies",
2204
+ cacheFamily: "supplies",
2077
2205
  defaultQuery: defaultMetadataQuery,
2078
2206
  fetch: suppliesGetAllServer
2079
2207
  });
@@ -2086,6 +2214,18 @@ var toRoleRef = (party, uiLanguage) => {
2086
2214
  label: resolveLocalizedLabel(role?.labels || [], uiLanguage) || role?.shortId?.trim() || "Unknown role"
2087
2215
  };
2088
2216
  };
2217
+ var mergeRoleRef = (current, candidate) => {
2218
+ if (current.id !== candidate.id) {
2219
+ return current;
2220
+ }
2221
+ const preferCurrentLabel = current.label.trim().length > 0 && current.label !== "Unknown role";
2222
+ const preferCurrentShortId = Boolean(current.shortId?.trim());
2223
+ return {
2224
+ id: current.id,
2225
+ shortId: preferCurrentShortId ? current.shortId : candidate.shortId,
2226
+ label: preferCurrentLabel ? current.label : candidate.label
2227
+ };
2228
+ };
2089
2229
  var getPartiesCached = (0, import_cache2.unstable_cache)(
2090
2230
  async (_queryKey, query, uiLanguage) => {
2091
2231
  const items = await withServerRequestContext(
@@ -2097,15 +2237,23 @@ var getPartiesCached = (0, import_cache2.unstable_cache)(
2097
2237
  const id = party.id?.trim();
2098
2238
  if (!id) return;
2099
2239
  const role = toRoleRef(party, uiLanguage);
2100
- if (!groups.has(role.id)) {
2240
+ const existingGroup = groups.get(role.id);
2241
+ if (!existingGroup) {
2101
2242
  groups.set(role.id, { role, parties: [] });
2243
+ } else {
2244
+ const mergedRole = mergeRoleRef(existingGroup.role, role);
2245
+ existingGroup.role = mergedRole;
2246
+ existingGroup.parties.forEach((groupedParty) => {
2247
+ groupedParty.role = mergedRole;
2248
+ });
2102
2249
  }
2103
2250
  const label = resolveLocalizedLabel(party.labels || [], uiLanguage) || party.shortId?.trim() || id;
2251
+ const resolvedRole = groups.get(role.id)?.role || role;
2104
2252
  groups.get(role.id)?.parties.push({
2105
2253
  id,
2106
2254
  shortId: party.shortId?.trim() || void 0,
2107
2255
  label,
2108
- role,
2256
+ role: resolvedRole,
2109
2257
  vcardId: party.vcard?.id?.trim() || void 0
2110
2258
  });
2111
2259
  });
@@ -2123,17 +2271,19 @@ var getPartiesCached = (0, import_cache2.unstable_cache)(
2123
2271
  tags: [import_requests3.CREX_API_CACHE_TAG, import_requests3.CREX_READMODEL_CACHE_TAG, import_requests3.CREX_READMODEL_CACHE_METADATA_TAG, import_requests3.CREX_READMODEL_CACHE_PARTIES_TAG]
2124
2272
  }
2125
2273
  );
2126
- var getInformationSubjects = async (options) => {
2127
- const readOptions = { includeOnlyUsed: options?.includeOnlyUsed === true };
2274
+ var getInformationSubjects = async () => {
2128
2275
  try {
2129
- const categories = await getCategoriesCached(void 0, readOptions);
2276
+ const categories = await getCategoriesCached();
2277
+ if (isMetadataPropertyRuntimeSuppressed("informationSubjects")) {
2278
+ return categories;
2279
+ }
2130
2280
  if (categories.roots.length > 0) {
2131
2281
  return categories;
2132
2282
  }
2133
2283
  } catch (error) {
2134
2284
  console.warn("[MetadataReadModels] Categories endpoint unavailable, falling back to InformationSubjects.", error);
2135
2285
  }
2136
- return getInformationSubjectsLegacyCached(void 0, readOptions);
2286
+ return getInformationSubjectsLegacyCached();
2137
2287
  };
2138
2288
  var getDocumentTypes = async () => {
2139
2289
  return getDocumentTypesCached();
@@ -2147,8 +2297,7 @@ var getParties = async () => {
2147
2297
  PageNumber: 1,
2148
2298
  PageSize: READMODEL_PAGE_SIZE,
2149
2299
  Fields: ["labels", "partyRole", "vcard", "class"],
2150
- Sort: ["shortId"],
2151
- Embed: ["vcard"]
2300
+ Sort: ["shortId"]
2152
2301
  };
2153
2302
  return getPartiesCached(stableSerialize({ query, uiLanguage }), query, uiLanguage);
2154
2303
  };
@@ -2347,8 +2496,8 @@ var INFORMATION_UNIT_PROPERTY_PRESENTATION = {
2347
2496
  },
2348
2497
  applicableForTypes: {
2349
2498
  valueKind: "objectRefArray",
2350
- facet: { supported: true, sectionStrategy: "class" },
2351
- metadataDisplay: { supported: true, sectionStrategy: "class" }
2499
+ facet: { supported: true, sectionStrategy: "none" },
2500
+ metadataDisplay: { supported: true, sectionStrategy: "none" }
2352
2501
  },
2353
2502
  planningTimes: {
2354
2503
  valueKind: "objectRefArray",
@@ -2405,23 +2554,70 @@ var INFORMATION_UNIT_PROPERTY_PRESENTATION = {
2405
2554
  // src/read-models/metadata-presentation.ts
2406
2555
  var import_cache3 = require("next/cache");
2407
2556
  var import_requests4 = require("@c-rex/core/requests");
2408
- var addTaxonomyNodeOverride = (node, map, sectionLabel) => {
2409
- if (!node.shortId) return;
2410
- map[node.shortId] = {
2557
+ var UNKNOWN_SECTION_LABELS = {
2558
+ en: {
2559
+ components: "Unknown component",
2560
+ informationSubjects: "Unknown information subject",
2561
+ topicTypes: "Unknown topic type",
2562
+ documentTypes: "Unknown document type",
2563
+ contentLifeCycleStatus: "Unknown content life cycle status",
2564
+ applicableForTypes: "Unknown document type",
2565
+ planningTimes: "Unknown planning time",
2566
+ functionalMetadata: "Unknown functional metadata",
2567
+ productFeatures: "Unknown product feature",
2568
+ productLifeCyclePhases: "Unknown product life cycle phase",
2569
+ productMetadata: "Unknown product metadata",
2570
+ productVariants: "Unknown product variant",
2571
+ qualifications: "Unknown qualification",
2572
+ supplies: "Unknown supply"
2573
+ },
2574
+ de: {
2575
+ components: "Unbekannte Komponente",
2576
+ informationSubjects: "Unbekanntes Informationsthema",
2577
+ topicTypes: "Unbekannter Topictyp",
2578
+ documentTypes: "Unbekannte Dokumentart",
2579
+ contentLifeCycleStatus: "Unbekannter Inhaltslebenszyklusstatus",
2580
+ applicableForTypes: "Unbekannte Dokumentart",
2581
+ planningTimes: "Unbekannte Planungszeit",
2582
+ functionalMetadata: "Unbekannte funktionale Metadaten",
2583
+ productFeatures: "Unbekanntes Produktmerkmal",
2584
+ productLifeCyclePhases: "Unbekannte Produktlebenszyklusphase",
2585
+ productMetadata: "Unbekannte Produktmetadaten",
2586
+ productVariants: "Unbekannte Produktvariante",
2587
+ qualifications: "Unbekannte Qualifikation",
2588
+ supplies: "Unbekannter Lieferumfang"
2589
+ }
2590
+ };
2591
+ var resolveUnknownSectionLabel = (property, uiLanguage) => {
2592
+ const normalizedLanguage = uiLanguage.toLowerCase();
2593
+ const baseLanguage = normalizedLanguage.split("-")[0];
2594
+ return UNKNOWN_SECTION_LABELS[baseLanguage]?.[property] || UNKNOWN_SECTION_LABELS.en[property] || "Unknown metadata";
2595
+ };
2596
+ var addTaxonomyNodePresentation = (node, map, sectionLabel, options) => {
2597
+ const presentation = {
2411
2598
  label: node.label,
2412
- sectionLabel
2599
+ sectionLabel,
2600
+ hidden: options?.hidden
2413
2601
  };
2602
+ if (node.shortId) {
2603
+ map[node.shortId] = presentation;
2604
+ }
2605
+ if (node.id) {
2606
+ map[node.id] = presentation;
2607
+ }
2414
2608
  };
2415
- var createClassSectionOverrides = (nodes, options) => {
2416
- const overrides = {};
2609
+ var createClassSectionPresentation = (property, nodes, uiLanguage, options) => {
2610
+ const presentation = {};
2611
+ const unknownSectionLabel = resolveUnknownSectionLabel(property, uiLanguage);
2417
2612
  Object.values(nodes).forEach((node) => {
2418
2613
  const classId = node.classRef?.id?.trim();
2419
- const sectionLabel = node.classRef?.label || (classId ? options?.classLabelsById?.[classId] : void 0);
2420
- addTaxonomyNodeOverride(node, overrides, sectionLabel);
2614
+ const hidden = isMetadataGroupDenied(property, { classId });
2615
+ const sectionLabel = node.classRef?.label || (classId ? options?.classLabelsById?.[classId] : void 0) || unknownSectionLabel;
2616
+ addTaxonomyNodePresentation(node, presentation, sectionLabel, { hidden });
2421
2617
  });
2422
- return overrides;
2618
+ return presentation;
2423
2619
  };
2424
- var resolveMissingClassLabels = async (nodes, uiLanguage) => {
2620
+ var resolveMissingClassLabels2 = async (nodes, uiLanguage) => {
2425
2621
  const classIds = Array.from(
2426
2622
  new Set(
2427
2623
  Object.values(nodes).map((node) => node.classRef?.id?.trim()).filter((value) => Boolean(value))
@@ -2459,7 +2655,7 @@ var resolveLocalizedLabel2 = (labels, uiLanguage) => {
2459
2655
  if (english) return english;
2460
2656
  return normalized[0]?.value;
2461
2657
  };
2462
- var isNotFoundError = (error) => {
2658
+ var isNotFoundError2 = (error) => {
2463
2659
  if (!(error instanceof Error)) {
2464
2660
  return false;
2465
2661
  }
@@ -2476,7 +2672,7 @@ var getDomainEntitySectionLabelUncached = async (id, uiLanguage) => {
2476
2672
  );
2477
2673
  return resolveLocalizedLabel2(entity.labels || [], uiLanguage);
2478
2674
  } catch (error) {
2479
- if (isNotFoundError(error)) {
2675
+ if (isNotFoundError2(error)) {
2480
2676
  return void 0;
2481
2677
  }
2482
2678
  throw error;
@@ -2501,7 +2697,7 @@ var getDomainEntitySectionLabel = async (id, uiLanguage) => {
2501
2697
  inFlightDomainEntityLabelRequests.set(inFlightKey, promise);
2502
2698
  return promise;
2503
2699
  };
2504
- var getMetadataFacetLabelOverrides = async (properties, uiLanguage = "en-US", options) => {
2700
+ var getMetadataFacetPresentation = async (properties, uiLanguage = "en-US", options) => {
2505
2701
  const defaultProperties = Object.keys(INFORMATION_UNIT_PROPERTY_PRESENTATION).filter((property) => INFORMATION_UNIT_PROPERTY_PRESENTATION[property].facet.supported);
2506
2702
  const propertySet = new Set(properties && properties.length > 0 ? properties : defaultProperties);
2507
2703
  const result = {};
@@ -2509,7 +2705,10 @@ var getMetadataFacetLabelOverrides = async (properties, uiLanguage = "en-US", op
2509
2705
  components: getComponents,
2510
2706
  informationSubjects: getInformationSubjects,
2511
2707
  documentTypes: getDocumentTypes,
2512
- applicableForTypes: getApplicableForTypes,
2708
+ // API facets for `applicableForTypes` contain document type refs.
2709
+ // Resolve them through DocumentTypes so section labels come from the
2710
+ // referenced object class instead of the predicate label.
2711
+ applicableForTypes: getDocumentTypes,
2513
2712
  planningTimes: getPlanningTimes,
2514
2713
  functionalMetadata: getFunctionalMetadata,
2515
2714
  contentLifeCycleStatus: getContentLifeCycleStatus,
@@ -2527,43 +2726,56 @@ var getMetadataFacetLabelOverrides = async (properties, uiLanguage = "en-US", op
2527
2726
  const config = INFORMATION_UNIT_PROPERTY_PRESENTATION[property];
2528
2727
  if (!config?.facet.supported) continue;
2529
2728
  if (config.facet.sectionStrategy === "partyRole" && property === "parties") {
2729
+ if (isMetadataPropertyRuntimeSuppressed("parties")) {
2730
+ continue;
2731
+ }
2530
2732
  partiesTask = (async () => {
2531
2733
  const parties = await getParties();
2532
- const partyOverrides = {};
2734
+ const partyPresentation = {};
2533
2735
  parties.groups.forEach((group) => {
2736
+ const hidden = isMetadataGroupDenied("parties", { partyRoleId: group.role.id });
2534
2737
  const sectionLabel = group.role.label;
2535
2738
  group.parties.forEach((party) => {
2536
2739
  if (!party.shortId) return;
2537
- partyOverrides[party.shortId] = {
2740
+ partyPresentation[party.shortId] = {
2538
2741
  label: party.label,
2539
- sectionLabel
2742
+ sectionLabel,
2743
+ hidden
2540
2744
  };
2745
+ if (party.id) {
2746
+ partyPresentation[party.id] = {
2747
+ label: party.label,
2748
+ sectionLabel,
2749
+ hidden
2750
+ };
2751
+ }
2541
2752
  });
2542
2753
  });
2543
- result.parties = partyOverrides;
2754
+ result.parties = partyPresentation;
2544
2755
  })();
2545
2756
  continue;
2546
2757
  }
2547
2758
  if (config.facet.sectionStrategy === "class") {
2759
+ if (isMetadataPropertyRuntimeSuppressed(property)) {
2760
+ continue;
2761
+ }
2548
2762
  const resolver = classResolvers[property];
2549
2763
  if (!resolver) continue;
2550
2764
  classTasks.push(
2551
2765
  (async () => {
2552
- const taxonomy = property === "informationSubjects" && options?.includeOnlyUsedByProperty?.informationSubjects === true ? await getInformationSubjects({ includeOnlyUsed: true }) : await resolver();
2766
+ const taxonomy = await resolver();
2553
2767
  if (property === "topicTypes" || property === "contentLifeCycleStatus") {
2554
2768
  const domainEntityId = property === "topicTypes" ? TOPIC_TYPE_DOMAIN_ENTITY_ID : CONTENT_LIFECYCLE_STATUS_DOMAIN_ENTITY_ID;
2555
- const sectionLabel = await getDomainEntitySectionLabel(domainEntityId, uiLanguage);
2556
- const overrides = createClassSectionOverrides(taxonomy.nodesById);
2557
- if (sectionLabel) {
2558
- Object.values(overrides).forEach((entry) => {
2559
- entry.sectionLabel = sectionLabel;
2560
- });
2561
- }
2562
- result[property] = overrides;
2769
+ const sectionLabel = await getDomainEntitySectionLabel(domainEntityId, uiLanguage) || resolveUnknownSectionLabel(property, uiLanguage);
2770
+ const presentation = createClassSectionPresentation(property, taxonomy.nodesById, uiLanguage);
2771
+ Object.values(presentation).forEach((entry) => {
2772
+ entry.sectionLabel = sectionLabel;
2773
+ });
2774
+ result[property] = presentation;
2563
2775
  return;
2564
2776
  }
2565
- const classLabelsById = await resolveMissingClassLabels(taxonomy.nodesById, uiLanguage);
2566
- result[property] = createClassSectionOverrides(taxonomy.nodesById, { classLabelsById });
2777
+ const classLabelsById = await resolveMissingClassLabels2(taxonomy.nodesById, uiLanguage);
2778
+ result[property] = createClassSectionPresentation(property, taxonomy.nodesById, uiLanguage, { classLabelsById });
2567
2779
  })()
2568
2780
  );
2569
2781
  }
@@ -2571,13 +2783,54 @@ var getMetadataFacetLabelOverrides = async (properties, uiLanguage = "en-US", op
2571
2783
  await Promise.all([...classTasks, ...partiesTask ? [partiesTask] : []]);
2572
2784
  return result;
2573
2785
  };
2786
+ var getMetadataFacetLabelOverrides = getMetadataFacetPresentation;
2574
2787
 
2575
- // src/read-models/metadata-display.ts
2576
- var import_utils = require("@c-rex/utils");
2788
+ // src/read-models/metadata-display-builder.ts
2789
+ var DEFAULT_IGNORED_FORMATS = [
2790
+ "application/xhtml+xml",
2791
+ "application/json",
2792
+ "application/llm+xml",
2793
+ "text/html"
2794
+ ];
2795
+ var normalizeLanguageCode = (value) => {
2796
+ const trimmed = value.trim();
2797
+ if (!trimmed) return trimmed;
2798
+ const [rawLang, rawCountry, ...rest] = trimmed.split("-");
2799
+ const lang = (rawLang || "").toLowerCase();
2800
+ if (!rawCountry) return lang;
2801
+ const country = rawCountry.toUpperCase();
2802
+ const suffix = rest.length > 0 ? `-${rest.join("-")}` : "";
2803
+ return `${lang}-${country}${suffix}`;
2804
+ };
2805
+ var sortAndDeduplicateLanguages = (languages) => {
2806
+ const normalized = languages.map((item) => (item || "").trim()).filter((item) => item.length > 0).map((item) => normalizeLanguageCode(item));
2807
+ return Array.from(new Set(normalized)).sort((a, b) => a.localeCompare(b));
2808
+ };
2809
+ var resolvePreferredLanguage = (languages, uiLanguage) => {
2810
+ if (!languages || languages.length === 0) return void 0;
2811
+ const normalizedUiLanguage = normalizeLanguageCode(uiLanguage);
2812
+ const baseLanguage = normalizedUiLanguage.split("-")[0];
2813
+ const normalized = sortAndDeduplicateLanguages(languages);
2814
+ const exact = normalized.find((item) => item === normalizedUiLanguage);
2815
+ if (exact) return exact;
2816
+ const base = normalized.find((item) => item === baseLanguage || item.startsWith(`${baseLanguage}-`));
2817
+ if (base) return base;
2818
+ const english = normalized.find((item) => item === "en" || item === "en-US" || item.startsWith("en-"));
2819
+ if (english) return english;
2820
+ return normalized[0];
2821
+ };
2822
+ var getFirstLinkByRel = (item, rel) => item.links?.find((link) => link.rel === rel)?.href;
2823
+ var hasRenderableFileRenditions = (renditions) => {
2824
+ if (!renditions || renditions.length === 0) return false;
2825
+ return renditions.some((item) => {
2826
+ if (!item.format || DEFAULT_IGNORED_FORMATS.includes(item.format)) return false;
2827
+ return Boolean(getFirstLinkByRel(item, "download") || getFirstLinkByRel(item, "view"));
2828
+ });
2829
+ };
2577
2830
  var resolveLiteralLabel = (labels, uiLanguage) => {
2578
2831
  if (!labels || labels.length === 0) return void 0;
2579
2832
  const language = uiLanguage || "en";
2580
- const preferred = (0, import_utils.resolvePreferredLanguage)(
2833
+ const preferred = resolvePreferredLanguage(
2581
2834
  labels.map((item) => item.language || ""),
2582
2835
  language
2583
2836
  );
@@ -2590,6 +2843,9 @@ var resolveLiteralLabel = (labels, uiLanguage) => {
2590
2843
  var resolveObjectRefLabel = (item, uiLanguage) => {
2591
2844
  return resolveLiteralLabel(item.labels || [], uiLanguage) || item.shortId || item.id || void 0;
2592
2845
  };
2846
+ var resolveObjectRefClassLabel = (item, uiLanguage) => {
2847
+ return resolveLiteralLabel(item.class?.labels || [], uiLanguage) || item.class?.shortId || item.class?.id || void 0;
2848
+ };
2593
2849
  var asObjectRefArray = (value) => {
2594
2850
  if (!Array.isArray(value)) return [];
2595
2851
  return value.filter((item) => Boolean(item && typeof item === "object"));
@@ -2598,29 +2854,27 @@ var asLiteralArray = (value) => {
2598
2854
  if (!Array.isArray(value)) return [];
2599
2855
  return value.filter((item) => Boolean(item && typeof item === "object"));
2600
2856
  };
2601
- var shouldUseOverrides = (strategy) => {
2857
+ var shouldUseFacetPresentation = (strategy) => {
2602
2858
  return strategy === "class" || strategy === "partyRole";
2603
2859
  };
2604
- var getMetadataDisplayRows = async (data, options) => {
2605
- const includeProperties = options.includeProperties || Object.keys(INFORMATION_UNIT_PROPERTY_PRESENTATION);
2606
- const uiLanguage = options.uiLanguage;
2607
- const preferredTitle = resolveLiteralLabel(data.titles || [], uiLanguage) || resolveLiteralLabel(data.labels || [], uiLanguage);
2608
- const objectRefProperties = includeProperties.filter((key) => {
2860
+ var resolveFacetPresentationProperties = (includeProperties) => {
2861
+ return includeProperties.filter((key) => {
2609
2862
  const config = INFORMATION_UNIT_PROPERTY_PRESENTATION[key];
2610
2863
  if (!config?.metadataDisplay?.supported) return false;
2611
- return config.valueKind === "objectRefArray" || config.valueKind === "objectRef";
2864
+ if (config.valueKind !== "objectRefArray" && config.valueKind !== "objectRef") return false;
2865
+ return shouldUseFacetPresentation(config.metadataDisplay.sectionStrategy);
2612
2866
  });
2613
- const overrideProperties = objectRefProperties.filter(
2614
- (key) => shouldUseOverrides(INFORMATION_UNIT_PROPERTY_PRESENTATION[key].metadataDisplay.sectionStrategy)
2615
- );
2616
- const labelOverrides = options.overrides || (overrideProperties.length > 0 ? await getMetadataFacetLabelOverrides(overrideProperties, uiLanguage) : {});
2867
+ };
2868
+ var resolveOverrideProperties = resolveFacetPresentationProperties;
2869
+ var buildMetadataDisplayRows = (data, options) => {
2870
+ const uiLanguage = options.uiLanguage;
2871
+ const preferredTitle = resolveLiteralLabel(data.titles || [], uiLanguage) || resolveLiteralLabel(data.labels || [], uiLanguage);
2617
2872
  const rows = [];
2618
- for (const key of includeProperties) {
2873
+ for (const key of options.includeProperties) {
2619
2874
  const config = INFORMATION_UNIT_PROPERTY_PRESENTATION[key];
2620
2875
  if (!config?.metadataDisplay?.supported) continue;
2621
- if (key === "labels") {
2622
- continue;
2623
- }
2876
+ if (isMetadataPropertyRuntimeSuppressed(key)) continue;
2877
+ if (key === "labels") continue;
2624
2878
  if (key === "titles") {
2625
2879
  if (preferredTitle) {
2626
2880
  rows.push({
@@ -2636,7 +2890,7 @@ var getMetadataDisplayRows = async (data, options) => {
2636
2890
  const value = data[key];
2637
2891
  if (value === null || value === void 0) continue;
2638
2892
  if (key === "languages") {
2639
- const languages = (0, import_utils.sortAndDeduplicateLanguages)(value || []);
2893
+ const languages = sortAndDeduplicateLanguages(value || []);
2640
2894
  if (languages.length > 0) {
2641
2895
  rows.push({
2642
2896
  key,
@@ -2659,7 +2913,7 @@ var getMetadataDisplayRows = async (data, options) => {
2659
2913
  continue;
2660
2914
  }
2661
2915
  if (config.valueKind === "stringArray") {
2662
- const values = Array.from(new Set(value.map((item) => String(item)).filter((item) => item.length > 0)));
2916
+ const values = Array.from(new Set(value.map((item) => String(item)).filter(Boolean)));
2663
2917
  if (values.length > 0) {
2664
2918
  rows.push({
2665
2919
  key,
@@ -2672,8 +2926,7 @@ var getMetadataDisplayRows = async (data, options) => {
2672
2926
  continue;
2673
2927
  }
2674
2928
  if (config.valueKind === "literalArray") {
2675
- const literals = asLiteralArray(value);
2676
- const preferred = resolveLiteralLabel(literals, uiLanguage);
2929
+ const preferred = resolveLiteralLabel(asLiteralArray(value), uiLanguage);
2677
2930
  if (preferred) {
2678
2931
  rows.push({
2679
2932
  key,
@@ -2686,8 +2939,7 @@ var getMetadataDisplayRows = async (data, options) => {
2686
2939
  continue;
2687
2940
  }
2688
2941
  if (config.valueKind === "objectRef") {
2689
- const ref = value;
2690
- const label = resolveObjectRefLabel(ref, uiLanguage);
2942
+ const label = resolveObjectRefLabel(value, uiLanguage);
2691
2943
  if (label) {
2692
2944
  rows.push({
2693
2945
  key,
@@ -2702,26 +2954,28 @@ var getMetadataDisplayRows = async (data, options) => {
2702
2954
  if (config.valueKind === "objectRefArray") {
2703
2955
  const refs = asObjectRefArray(value);
2704
2956
  if (refs.length === 0) continue;
2705
- const grouped = /* @__PURE__ */ new Map();
2706
- const strategy = config.metadataDisplay.sectionStrategy;
2957
+ const groupedValues = /* @__PURE__ */ new Map();
2707
2958
  refs.forEach((ref) => {
2708
2959
  const shortId = ref.shortId || "";
2709
- const override = shortId ? labelOverrides[key]?.[shortId] : void 0;
2710
- const label = override?.label || resolveObjectRefLabel(ref, uiLanguage);
2711
- if (!label) return;
2712
- const section = strategy === "none" ? key : override?.sectionLabel || key;
2713
- if (!grouped.has(section)) grouped.set(section, []);
2714
- grouped.get(section)?.push(label);
2960
+ const presentationMap = (options.presentation || options.overrides)?.[key];
2961
+ const presentationItem = (shortId ? presentationMap?.[shortId] : void 0) || (ref.id ? presentationMap?.[ref.id] : void 0);
2962
+ if (presentationItem?.hidden) return;
2963
+ if (isMetadataGroupDenied(key, { classId: ref.class?.id })) return;
2964
+ const valueLabel = presentationItem?.label || resolveObjectRefLabel(ref, uiLanguage);
2965
+ if (!valueLabel) return;
2966
+ const sectionLabel = config.metadataDisplay.sectionStrategy === "none" ? key : presentationItem?.sectionLabel || resolveObjectRefClassLabel(ref, uiLanguage) || key;
2967
+ const existing = groupedValues.get(sectionLabel) || /* @__PURE__ */ new Set();
2968
+ existing.add(valueLabel);
2969
+ groupedValues.set(sectionLabel, existing);
2715
2970
  });
2716
- Array.from(grouped.entries()).sort((a, b) => a[0].localeCompare(b[0])).forEach(([section, values]) => {
2717
- const uniqueValues = Array.from(new Set(values)).sort((a, b) => a.localeCompare(b));
2718
- if (uniqueValues.length === 0) return;
2719
- const isDirect = section !== key;
2971
+ Array.from(groupedValues.entries()).sort(([left], [right]) => left.localeCompare(right)).forEach(([sectionLabel, valueSet]) => {
2972
+ const values = Array.from(valueSet).sort((a, b) => a.localeCompare(b));
2973
+ if (values.length === 0) return;
2720
2974
  rows.push({
2721
2975
  key,
2722
- label: section,
2723
- labelSource: isDirect ? "direct" : "translationKey",
2724
- values: uniqueValues,
2976
+ label: sectionLabel,
2977
+ labelSource: sectionLabel === key ? "translationKey" : "direct",
2978
+ values,
2725
2979
  valueType: "text"
2726
2980
  });
2727
2981
  });
@@ -2730,7 +2984,7 @@ var getMetadataDisplayRows = async (data, options) => {
2730
2984
  if (config.valueKind === "renditionArray") {
2731
2985
  const renditions = Array.isArray(value) ? value.filter((item) => Boolean(item && typeof item === "object")) : [];
2732
2986
  if (renditions.length === 0) continue;
2733
- if ((0, import_utils.getFileRenditionGroups)({ renditions }).length === 0) continue;
2987
+ if (!hasRenderableFileRenditions(renditions)) continue;
2734
2988
  rows.push({
2735
2989
  key,
2736
2990
  label: "files",
@@ -2744,9 +2998,21 @@ var getMetadataDisplayRows = async (data, options) => {
2744
2998
  return rows;
2745
2999
  };
2746
3000
 
3001
+ // src/read-models/metadata-display.ts
3002
+ var getMetadataDisplayRows = async (data, options) => {
3003
+ const includeProperties = options.includeProperties || Object.keys(INFORMATION_UNIT_PROPERTY_PRESENTATION);
3004
+ const presentationProperties = resolveFacetPresentationProperties(includeProperties);
3005
+ const facetPresentation = options.presentation || options.overrides || (presentationProperties.length > 0 ? await getMetadataFacetPresentation(presentationProperties, options.uiLanguage) : {});
3006
+ return buildMetadataDisplayRows(data, {
3007
+ uiLanguage: options.uiLanguage,
3008
+ includeProperties,
3009
+ presentation: facetPresentation
3010
+ });
3011
+ };
3012
+
2747
3013
  // src/read-models/version-availability.ts
2748
3014
  var import_requests5 = require("@c-rex/core/requests");
2749
- var import_utils2 = require("@c-rex/utils");
3015
+ var import_utils = require("@c-rex/utils");
2750
3016
  var import_cache4 = require("next/cache");
2751
3017
  var stableSerialize2 = (value) => {
2752
3018
  const normalize = (input) => {
@@ -2767,7 +3033,7 @@ var normalizeVersionItems = (items, uiLanguage) => {
2767
3033
  items.forEach((item) => {
2768
3034
  const shortId = item.shortId?.trim();
2769
3035
  if (!shortId) return;
2770
- const language = (0, import_utils2.resolvePreferredLanguage)(item.languages, uiLanguage);
3036
+ const language = (0, import_utils.resolvePreferredLanguage)(item.languages, uiLanguage);
2771
3037
  if (!language) return;
2772
3038
  uniqueByShortId.set(shortId, {
2773
3039
  shortId,
@@ -2877,7 +3143,9 @@ var resolveFacetTags = (options) => {
2877
3143
  toInformationUnitPropertyKeys(options?.includeProperties),
2878
3144
  toInformationUnitPropertyKeys(options?.excludeProperties)
2879
3145
  );
2880
- const tagSet = new Set(runtimeScoped);
3146
+ const tagSet = new Set(
3147
+ runtimeScoped.filter((property) => !isMetadataPropertyRuntimeSuppressed(property))
3148
+ );
2881
3149
  (facetConfig?.extraTags || []).forEach((tag) => tagSet.add(tag));
2882
3150
  (options?.extraTags || []).forEach((tag) => tagSet.add(tag));
2883
3151
  return Array.from(tagSet);
@@ -2895,7 +3163,7 @@ var resolveMetadataDisplayProperties = (options) => {
2895
3163
  profileScoped,
2896
3164
  toInformationUnitPropertyKeys(options?.includeProperties),
2897
3165
  toInformationUnitPropertyKeys(options?.excludeProperties)
2898
- );
3166
+ ).filter((property) => !isMetadataPropertyRuntimeSuppressed(property));
2899
3167
  };
2900
3168
 
2901
3169
  // src/index.ts
@@ -2970,6 +3238,7 @@ var LanguageService = class {
2970
3238
  InformationUnitsService,
2971
3239
  LanguageService,
2972
3240
  METADATA_VIEW_PROFILES,
3241
+ METADATA_VISIBILITY_POLICY,
2973
3242
  READMODEL_CACHE_POLICY,
2974
3243
  RenditionsService,
2975
3244
  TopicsService,
@@ -2981,11 +3250,13 @@ var LanguageService = class {
2981
3250
  afterUsesGetAllServer,
2982
3251
  afterUsesGetByIdClientService,
2983
3252
  afterUsesGetByIdServer,
3253
+ buildMetadataDisplayRows,
2984
3254
  buildTelephoneEntries,
2985
3255
  categoriesGetAllClientService,
2986
3256
  categoriesGetAllServer,
2987
3257
  categoriesGetByIdClientService,
2988
3258
  categoriesGetByIdServer,
3259
+ clearMetadataCacheFamilyRuntimeSuppression,
2989
3260
  collectionsGetAllClientService,
2990
3261
  collectionsGetAllServer,
2991
3262
  collectionsGetByIdClientService,
@@ -3080,8 +3351,10 @@ var LanguageService = class {
3080
3351
  getIndividualProfileById,
3081
3352
  getIndividualsProfiles,
3082
3353
  getInformationSubjects,
3354
+ getMetadataCacheFamily,
3083
3355
  getMetadataDisplayRows,
3084
3356
  getMetadataFacetLabelOverrides,
3357
+ getMetadataFacetPresentation,
3085
3358
  getMetadataPropertyResolvers,
3086
3359
  getOrganizationBranding,
3087
3360
  getOrganizationProfile,
@@ -3094,6 +3367,7 @@ var LanguageService = class {
3094
3367
  getProductMetadata,
3095
3368
  getProductVariants,
3096
3369
  getQualifications,
3370
+ getRuntimeSuppressedMetadataFamilies,
3097
3371
  getServerConfig,
3098
3372
  getSupplies,
3099
3373
  getTopicTypes,
@@ -3137,6 +3411,8 @@ var LanguageService = class {
3137
3411
  informationUnitsGetByIdServer,
3138
3412
  informationUnitsLanguagesClientService,
3139
3413
  informationUnitsLanguagesServer,
3414
+ isMetadataGroupDenied,
3415
+ isMetadataPropertyRuntimeSuppressed,
3140
3416
  learningsGetAllClientService,
3141
3417
  learningsGetAllServer,
3142
3418
  learningsGetByIdClientService,
@@ -3226,9 +3502,15 @@ var LanguageService = class {
3226
3502
  renditionsGetByIdServer,
3227
3503
  renditionsGetWithBinaryWithBinaryPathClientService,
3228
3504
  renditionsGetWithBinaryWithBinaryPathServer,
3505
+ resetRuntimeSuppressedMetadataFamiliesForTests,
3506
+ resolveFacetPresentationProperties,
3229
3507
  resolveFacetTags,
3508
+ resolveLiteralLabel,
3230
3509
  resolveLogoSource,
3231
3510
  resolveMetadataDisplayProperties,
3511
+ resolveObjectRefClassLabel,
3512
+ resolveObjectRefLabel,
3513
+ resolveOverrideProperties,
3232
3514
  resolveSocialProviderLabel,
3233
3515
  resolveTypedSocialLinks,
3234
3516
  resolveUiLanguage,
@@ -3272,6 +3554,7 @@ var LanguageService = class {
3272
3554
  suppliesGetAllServer,
3273
3555
  suppliesGetByIdClientService,
3274
3556
  suppliesGetByIdServer,
3557
+ suppressMetadataCacheFamilyRuntime,
3275
3558
  tasksGetAllClientService,
3276
3559
  tasksGetAllServer,
3277
3560
  tasksGetByIdClientService,