@conduction/nextcloud-vue 2.137.0 → 2.138.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue.js +1 -1
  2. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +6 -4
  3. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  4. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  5. package/dist/esm/components/CnDetailCard/CnDetailCard.vue.js +1 -1
  6. package/dist/esm/components/CnDetailCard/CnDetailCard.vue2.js +6 -0
  7. package/dist/esm/components/CnDetailCard/CnDetailCard.vue2.js.map +1 -1
  8. package/dist/esm/components/CnDetailCard/CnDetailCard.vue3.js +24 -7
  9. package/dist/esm/components/CnDetailCard/CnDetailCard.vue3.js.map +1 -1
  10. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
  11. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +2 -0
  12. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  13. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  14. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
  15. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +43 -1
  16. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  17. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  18. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +34 -2
  19. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  20. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +23 -15
  21. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  22. package/dist/esm/components/CnMailTab/dashboardRegistration.js +4 -0
  23. package/dist/esm/components/CnMailTab/dashboardRegistration.js.map +1 -1
  24. package/dist/esm/components/CnNotificationMatrix/CnNotificationMatrix.vue.js +1 -1
  25. package/dist/esm/components/CnNotificationMatrix/CnNotificationMatrix.vue2.js.map +1 -1
  26. package/dist/esm/components/CnNotificationMatrix/CnNotificationMatrix.vue3.js.map +1 -1
  27. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue.js +1 -1
  28. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +2 -0
  29. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
  30. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +2 -1
  31. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
  32. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue.js +1 -1
  33. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js +6 -0
  34. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js.map +1 -1
  35. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js +3 -3
  36. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js.map +1 -1
  37. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  38. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +16 -0
  39. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  40. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +11 -5
  41. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  42. package/dist/esm/components/CnSavedViewMenuSettings/CnSavedViewMenuSettings.vue.js +1 -1
  43. package/dist/esm/components/CnSavedViewMenuSettings/CnSavedViewMenuSettings.vue2.js.map +1 -1
  44. package/dist/esm/components/CnSavedViewMenuSettings/CnSavedViewMenuSettings.vue3.js +1 -0
  45. package/dist/esm/components/CnSavedViewMenuSettings/CnSavedViewMenuSettings.vue3.js.map +1 -1
  46. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue.js +1 -1
  47. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js.map +1 -1
  48. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js.map +1 -1
  49. package/dist/esm/composables/indexSources.js +36 -9
  50. package/dist/esm/composables/indexSources.js.map +1 -1
  51. package/dist/esm/l10n/en.json.js +10 -1
  52. package/dist/esm/l10n/en.json.js.map +1 -1
  53. package/dist/esm/l10n/nl.json.js +10 -1
  54. package/dist/esm/l10n/nl.json.js.map +1 -1
  55. package/dist/esm/library-style.js +1 -1
  56. package/dist/esm/nextcloud-vue.css +431 -360
  57. package/dist/esm/utils/resolveFilterTokens.js +9 -0
  58. package/dist/esm/utils/resolveFilterTokens.js.map +1 -1
  59. package/dist/esm/utils/sentinelTokens.js +1 -1
  60. package/dist/esm/utils/sentinelTokens.js.map +1 -1
  61. package/dist/nextcloud-vue.cjs.js +418 -221
  62. package/dist/nextcloud-vue.cjs.js.map +2 -2
  63. package/dist/nextcloud-vue.css +431 -360
  64. package/l10n/en.json +10 -1
  65. package/l10n/nl.json +10 -1
  66. package/package.json +1 -1
  67. package/src/components/CnCellRenderer/CnCellRenderer.vue +6 -4
  68. package/src/components/CnDetailCard/CnDetailCard.md +1 -0
  69. package/src/components/CnDetailCard/CnDetailCard.vue +25 -1
  70. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +2 -0
  71. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +43 -1
  72. package/src/components/CnIndexPage/CnIndexPage.vue +34 -1
  73. package/src/components/CnMailTab/dashboardRegistration.js +4 -0
  74. package/src/components/CnNotificationMatrix/CnNotificationMatrix.vue +4 -0
  75. package/src/components/CnObjectSidebar/CnFilesTab.vue +3 -0
  76. package/src/components/CnOrderedListField/CnOrderedListField.vue +11 -1
  77. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +22 -3
  78. package/src/components/CnSavedViewMenuSettings/CnSavedViewMenuSettings.vue +1 -0
  79. package/src/components/CnUserSettingsDialog/CnUserSettingsDialog.vue +3 -0
  80. package/src/composables/indexSources.js +36 -9
  81. package/src/css/dialog.css +8 -0
  82. package/src/css/index-page.css +5 -0
  83. package/src/css/look-board-detail.css +12 -0
  84. package/src/css/look-board.css +26 -0
  85. package/src/utils/resolveFilterTokens.js +9 -0
  86. package/src/utils/sentinelTokens.js +1 -1
@@ -1,5 +1,6 @@
1
1
  import { getCurrentUser } from '@nextcloud/auth';
2
2
  import { peekMyTeam } from './myTeam.js';
3
+ import { readPath } from './readPath.js';
3
4
  import { TODAY_DELTA_RE } from './sentinelTokens.js';
4
5
  import { peekCurrentUserGroups } from './userGroupsPeek.js';
5
6
 
@@ -48,6 +49,9 @@ import { peekCurrentUserGroups } from './userGroupsPeek.js';
48
49
  * - `@object.<field>` → a field off the current detail-page object (needs `ctx`)
49
50
  * - `@workspace.<key>` → a value off the page-level workspace context (needs `ctx.workspace`)
50
51
  * - `@config.<key>` → a value off the page-level app config (needs `ctx.config`)
52
+ * - `@context.<name>.<path>` → a value off a record the detail page reads beside
53
+ * the loaded one (needs `ctx.context`); left as written
54
+ * while that record is not read
51
55
  *
52
56
  * `@objectId` / `@object.<field>` are OBJECT-CONTEXT tokens: they resolve only
53
57
  * when a `ctx` `{ objectId, object }` is supplied (a detail page provides it via
@@ -194,6 +198,11 @@ function resolveFilterValue(v, ctx) {
194
198
  }
195
199
  return v
196
200
  }
201
+ if (v.startsWith('@context.')) {
202
+ // @spec openspec/changes/files-second-line-fields/specs/files-second-line-fields/spec.md#requirement-widget-props-can-read-the-detail-pages-context-records
203
+ const found = ctx && ctx.context ? readPath(ctx.context, v.slice('@context.'.length)) : undefined;
204
+ return found === undefined ? v : found
205
+ }
197
206
  if (v.startsWith('@workspace.')) {
198
207
  // A trailing `?` marks the token OPTIONAL: when unset the caller drops the
199
208
  // filter key (show all) instead of waiting (see hasUnresolvedTokens /
@@ -1 +1 @@
1
- {"version":3,"file":"resolveFilterTokens.js","sources":["../../../src/utils/resolveFilterTokens.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * Resolve dynamic `@`-tokens inside a widget filter at FETCH time, so manifest\n * filters can express \"relative to now / the current user\" without baking a\n * fixed value. The widgets call this just before sending the filter to\n * OpenRegister.\n *\n * Supported tokens:\n * - `@me` → the current Nextcloud user id (`getCurrentUser()` from\n * `@nextcloud/auth`; `window.OC.currentUser` fallback)\n * - `@myGroups` → the ids of the Nextcloud groups the current user is\n * in, as an ARRAY (an IN filter). `ctx.myGroups` wins;\n * otherwise a reactive peek over `getCurrentUserGroups`.\n * Stays UNRESOLVED while loading and when the user is\n * in no group, so the caller waits instead of sending\n * an empty IN list (which OpenRegister reads as \"no\n * constraint\"). Spread in place inside an IN-list array.\n * - `@myTeam` → the current user's primary team, a Nextcloud group id,\n * as the app answers it (`registerMyTeamSource`;\n * `ctx.myTeam` wins). Stays UNRESOLVED while it is read;\n * a user in no team gets `@myTeam?`, an optional token\n * the caller drops, so the filter goes away rather than\n * widening to all of the user's groups.\n * - `@now` → the current instant, ISO-8601\n * - `@today` → today at 00:00, `YYYY-MM-DD` (date-prefix comparable)\n * - `@today±Nd` → relative-date arithmetic at day granularity: N days\n * from today (e.g. `@today-30d`, `@today+7d`)\n * - `@monthStart` → first day of the current month, `YYYY-MM-DD`\n * - `@monthEnd` → last day of the current month, `YYYY-MM-DD`; on a\n * date-time field use `lt: '@nextMonthStart'` instead,\n * since `lte` a date stops at that day's midnight\n * - `@nextMonthStart` → first day of the next month, `YYYY-MM-DD`\n * - `@quarterStart` → first day of the current quarter, `YYYY-MM-DD`\n * - `@yearStart` → first day of the current year, `YYYY-MM-DD`\n * - `@currentFiscalYear` → the current calendar year as a number string, e.g. `2026`\n * - `@range.from` / `@range.to` / `@range.preset` → the active date range a\n * widget passes in `ctx.range` (CnStatWidget: its own\n * picker, else the dashboard's). A trailing `?` marks it\n * optional, as for `@workspace.<key>?`.\n * - `@objectId` → the current detail-page object's id (needs `ctx`)\n * - `@object.<field>` → a field off the current detail-page object (needs `ctx`)\n * - `@workspace.<key>` → a value off the page-level workspace context (needs `ctx.workspace`)\n * - `@config.<key>` → a value off the page-level app config (needs `ctx.config`)\n *\n * `@objectId` / `@object.<field>` are OBJECT-CONTEXT tokens: they resolve only\n * when a `ctx` `{ objectId, object }` is supplied (a detail page provides it via\n * the `cnObjectContext` inject). `@workspace.<key>` is a WORKSPACE-CONTEXT token:\n * it resolves a key off `ctx.workspace` (the reactive `cnWorkspaceContext` a\n * dashboard/workspace page provides) so a list widget can react to page-level\n * state another widget writes (e.g. a selected client). Without the matching\n * context the tokens pass through unchanged — and an UNRESOLVED `@workspace.*`\n * token signals \"no selection yet\" to the caller (see {@link hasUnresolvedTokens}).\n *\n * `@config.<key>` is an APP-CONFIG token: it resolves a key off `ctx.config` (the\n * page-level app config a dashboard/detail page provides via `cnAppConfig` — e.g.\n * a reporting `currency` captured by the setup wizard). Like `@workspace.<key>`, a\n * trailing `?` marks it optional. An UNRESOLVED required `@config.<key>` passes\n * through unchanged; this lets `format: { currency: '@config.currency' }` fall\n * back to a literal default when the config is unset.\n *\n * IN-lists: a filter value MAY be an ARRAY (`{ status: ['open', 'pending'] }`,\n * or the explicit operator form `{ status: { in: [...] } }`). Tokens inside the\n * array are resolved item-by-item (`{ assignee: ['@me', 'shared'] }` works).\n * OpenRegister expects an IN-list as repeated bracket params\n * (`status[]=open&status[]=pending` — the same shape `buildQueryString` /\n * `useObjectStore` send), so widget fetchers serialize a resolved array as\n * repeated `field[]` params, never as a JSON blob or a single joined string.\n *\n * @module utils/resolveFilterTokens\n */\n\nimport { getCurrentUser } from '@nextcloud/auth'\n// userGroupsPeek, not widgetVisibility: that one imports @nextcloud/axios, and\n// this resolver runs on public pages and in node (see userGroupsPeek.js).\nimport { peekMyTeam } from './myTeam.js'\nimport { TODAY_DELTA_RE } from './sentinelTokens.js'\nimport { peekCurrentUserGroups } from './userGroupsPeek.js'\n\n/** The filter token for the current user's group ids. */\nexport const MY_GROUPS_TOKEN = '@myGroups'\n\n/** The filter token for the current user's primary team. */\nexport const MY_TEAM_TOKEN = '@myTeam'\n\n/**\n * Resolve `@myTeam`: the team's group id; `@myTeam` while it is being read (the\n * caller waits); `@myTeam?` for a user in no team (the caller drops the key).\n *\n * @spec openspec/changes/saved-view-tokens-my-team/specs/schema-utilities/spec.md#requirement-myteam-resolves-to-the-current-users-primary-team\n * @param {{myTeam?: string}} [ctx] Optional context; `ctx.myTeam` wins.\n * @return {string} The group id or the token.\n */\nfunction resolveMyTeam(ctx) {\n\tconst team = ctx && typeof ctx.myTeam === 'string' ? ctx.myTeam : peekMyTeam()\n\tif (team === null) {\n\t\treturn MY_TEAM_TOKEN\n\t}\n\treturn team === '' ? `${MY_TEAM_TOKEN}?` : team\n}\n\n/**\n * Resolve `@myGroups`: the current user's group ids, or the token itself while\n * they are loading or when there are none (an empty IN list would match every\n * row, so \"no team\" must mean \"wait\", never \"everything\").\n *\n * @spec openspec/changes/nextcloud-group-surfaces/specs/schema-utilities/spec.md#requirement-mygroups-resolves-to-the-current-users-group-ids\n * @param {{myGroups?: string[]}} [ctx] Optional context; `ctx.myGroups` wins.\n * @return {string[]|string} The group ids, or `'@myGroups'` when unresolved.\n */\nfunction resolveMyGroups(ctx) {\n\tlet groups = ctx && Array.isArray(ctx.myGroups) ? ctx.myGroups : null\n\tif (groups === null) {\n\t\ttry {\n\t\t\tgroups = peekCurrentUserGroups()\n\t\t} catch {\n\t\t\tgroups = null\n\t\t}\n\t}\n\tconst ids = Array.isArray(groups)\n\t\t? groups.filter((g) => typeof g === 'string' && g !== '')\n\t\t: []\n\treturn ids.length > 0 ? [...ids] : MY_GROUPS_TOKEN\n}\n\n/**\n * Format a Date as `YYYY-MM-DD` (local).\n *\n * @param {Date} d The date.\n * @return {string} The date-only string.\n */\nfunction ymd(d) {\n\tconst m = String(d.getMonth() + 1).padStart(2, '0')\n\tconst day = String(d.getDate()).padStart(2, '0')\n\treturn `${d.getFullYear()}-${m}-${day}`\n}\n\n/**\n * Fill each `{@config.<key>}` inside a token from `ctx.config`, so a token can\n * take an admin setting (`@today-{@config.lead_stale_threshold_days}d`). The\n * token comes back unchanged when any key is missing from the config.\n *\n * @param {string} token The token.\n * @param {object} [ctx] The token context.\n * @return {string} The token with the config values in.\n * @spec openspec/changes/pl4-cell-rules/specs/pl4-cell-rules/spec.md#requirement-a-token-can-take-a-config-value\n */\nfunction fillConfigInToken(token, ctx) {\n\tconst config = (ctx && ctx.config) || {}\n\tlet missing = false\n\tconst filled = token.replace(/\\{@config\\.([A-Za-z0-9_.-]+)\\}/g, (whole, key) => {\n\t\tconst value = config[key]\n\t\tif (value === undefined || value === null || value === '') {\n\t\t\tmissing = true\n\t\t\treturn whole\n\t\t}\n\t\treturn String(value)\n\t})\n\treturn missing ? token : filled\n}\n\n/**\n * Resolve a single filter value if it is a dynamic `@`-token, else pass through.\n *\n * @param {unknown} v The candidate value.\n * @param {{objectId?: (string|number), object?: object, workspace?: object, config?: object, range?: object, myGroups?: string[]}} [ctx] Optional\n * context for `@objectId` / `@object.<field>` (detail page),\n * `@workspace.<key>` (page-level workspace state), and `@config.<key>`\n * (page-level app config) tokens.\n * @return {unknown} The resolved value.\n */\nexport function resolveFilterValue(v, ctx) {\n\tif (typeof v !== 'string' || v.charAt(0) !== '@') {\n\t\treturn v\n\t}\n\tif (v.includes('{@config.')) {\n\t\tconst filled = fillConfigInToken(v, ctx)\n\t\treturn filled === v ? v : resolveFilterValue(filled, ctx)\n\t}\n\tconst now = new Date()\n\tif (v === MY_GROUPS_TOKEN) {\n\t\treturn resolveMyGroups(ctx)\n\t}\n\tif (v === MY_TEAM_TOKEN) {\n\t\treturn resolveMyTeam(ctx)\n\t}\n\tif (v === '@objectId') {\n\t\treturn (ctx && ctx.objectId !== undefined && ctx.objectId !== null) ? String(ctx.objectId) : v\n\t}\n\tif (v.startsWith('@object.')) {\n\t\tconst field = v.slice('@object.'.length)\n\t\tif (ctx && ctx.object && field && ctx.object[field] !== undefined) {\n\t\t\treturn ctx.object[field]\n\t\t}\n\t\treturn v\n\t}\n\tif (v.startsWith('@workspace.')) {\n\t\t// A trailing `?` marks the token OPTIONAL: when unset the caller drops the\n\t\t// filter key (show all) instead of waiting (see hasUnresolvedTokens /\n\t\t// CnObjectListWidget). The `?` is stripped from the key lookup.\n\t\tconst raw = v.slice('@workspace.'.length)\n\t\tconst key = raw.endsWith('?') ? raw.slice(0, -1) : raw\n\t\tif (ctx && ctx.workspace && key && ctx.workspace[key] !== undefined\n\t\t\t&& ctx.workspace[key] !== null && ctx.workspace[key] !== '') {\n\t\t\treturn ctx.workspace[key]\n\t\t}\n\t\treturn v\n\t}\n\tif (v.startsWith('@config.')) {\n\t\t// A trailing `?` marks the token OPTIONAL (same convention as\n\t\t// `@workspace.<key>?`): an unset value lets the caller drop the key. A\n\t\t// required `@config.<key>` that is unset passes through unchanged so a\n\t\t// downstream consumer can fall back to a literal default (e.g.\n\t\t// `format.currency` → `'EUR'`).\n\t\tconst raw = v.slice('@config.'.length)\n\t\tconst key = raw.endsWith('?') ? raw.slice(0, -1) : raw\n\t\tif (ctx && ctx.config && key && ctx.config[key] !== undefined\n\t\t\t&& ctx.config[key] !== null && ctx.config[key] !== '') {\n\t\t\treturn ctx.config[key]\n\t\t}\n\t\treturn v\n\t}\n\tif (v.startsWith('@range.')) {\n\t\t// `@range.from` / `@range.to` / `@range.preset`: the active date range the\n\t\t// caller put in `ctx.range`. CnStatWidget documented these tokens and put\n\t\t// `range` in its endpoint context, but nothing resolved them, so the\n\t\t// literal token stayed in the params, hasUnresolvedTokens blocked the\n\t\t// request, and a card that used its own period picker never loaded. A\n\t\t// trailing `?` marks the token OPTIONAL, the same convention as\n\t\t// `@workspace.<key>?`: unset, the caller drops the key.\n\t\tconst raw = v.slice('@range.'.length)\n\t\tconst key = raw.endsWith('?') ? raw.slice(0, -1) : raw\n\t\tif (ctx && ctx.range && key && ctx.range[key] !== undefined\n\t\t\t&& ctx.range[key] !== null && ctx.range[key] !== '') {\n\t\t\treturn ctx.range[key]\n\t\t}\n\t\treturn v\n\t}\n\tif (v === '@me.displayName' || v === '@me.email') {\n\t\t// The form's own context wins (`ctx.me`, e.g. an email fetched from the\n\t\t// profile); @nextcloud/auth only knows the uid and display name.\n\t\tconst key = v.slice('@me.'.length)\n\t\tif (ctx && ctx.me && ctx.me[key] !== undefined && ctx.me[key] !== null && ctx.me[key] !== '') {\n\t\t\treturn ctx.me[key]\n\t\t}\n\t\ttry {\n\t\t\tconst user = getCurrentUser()\n\t\t\tif (user && user[key]) {\n\t\t\t\treturn user[key]\n\t\t\t}\n\t\t} catch {\n\t\t\t// not signed in: leave the token unresolved\n\t\t}\n\t\treturn v\n\t}\n\tif (v === '@me') {\n\t\t// Canonical source is @nextcloud/auth; window.OC is the fallback for\n\t\t// environments where the auth package can't read the page state (jsdom).\n\t\tlet uid\n\t\ttry {\n\t\t\tconst user = getCurrentUser()\n\t\t\tuid = user && user.uid\n\t\t} catch {\n\t\t\tuid = null\n\t\t}\n\t\treturn uid || (typeof window !== 'undefined' && window.OC && window.OC.currentUser) || ''\n\t}\n\tif (v === '@now') {\n\t\treturn now.toISOString()\n\t}\n\tif (v === '@today') {\n\t\tconst d = new Date(now)\n\t\td.setHours(0, 0, 0, 0)\n\t\treturn ymd(d)\n\t}\n\tif (v === '@monthStart') {\n\t\treturn ymd(new Date(now.getFullYear(), now.getMonth(), 1))\n\t}\n\tif (v === '@monthEnd') {\n\t\t// Day 0 of the next month is the last day of this one.\n\t\treturn ymd(new Date(now.getFullYear(), now.getMonth() + 1, 0))\n\t}\n\tif (v === '@nextMonthStart') {\n\t\treturn ymd(new Date(now.getFullYear(), now.getMonth() + 1, 1))\n\t}\n\tif (v === '@quarterStart') {\n\t\treturn ymd(new Date(now.getFullYear(), Math.floor(now.getMonth() / 3) * 3, 1))\n\t}\n\tif (v === '@yearStart') {\n\t\treturn ymd(new Date(now.getFullYear(), 0, 1))\n\t}\n\tif (v === '@currentFiscalYear') {\n\t\treturn String(now.getFullYear())\n\t}\n\tconst m = v.match(TODAY_DELTA_RE)\n\tif (m) {\n\t\tconst d = new Date(now)\n\t\td.setHours(0, 0, 0, 0)\n\t\td.setDate(d.getDate() + Number(m[1]))\n\t\treturn ymd(d)\n\t}\n\treturn v\n}\n\n/**\n * Whether a value is an UNRESOLVED OPTIONAL token — a string still shaped like\n * `@workspace.<key>?` or `@config.<key>?` after token resolution (the `?` marks\n * it as \"drop me when unset\"). Callers strip such keys from the filter so the\n * list shows all rows rather than waiting for a selection / a config value.\n *\n * @param {unknown} v A (possibly resolved) filter value.\n * @return {boolean}\n */\nexport function isOptionalUnresolved(v) {\n\treturn typeof v === 'string'\n\t\t&& (v.startsWith('@workspace.') || v.startsWith('@config.') || v.startsWith('@range.') || v === `${MY_TEAM_TOKEN}?`)\n\t\t&& v.endsWith('?')\n}\n\n/**\n * Return a copy of a resolved filter map with every UNRESOLVED OPTIONAL\n * workspace token (`@workspace.<key>?` left as-is) removed. Required tokens and\n * concrete values are kept untouched. Inside an IN-list array, unresolved\n * optional ITEMS are dropped; a key whose array empties out is dropped whole\n * (an empty IN-list means \"no constraint\", not \"match nothing\").\n *\n * @param {object} filter A filter map already passed through {@link resolveFilterTokens}.\n * @return {object} The filter without optional-unresolved keys.\n */\nexport function dropOptionalUnresolved(filter) {\n\tif (!filter || typeof filter !== 'object') {\n\t\treturn filter\n\t}\n\tconst out = {}\n\tfor (const [k, v] of Object.entries(filter)) {\n\t\tif (isOptionalUnresolved(v)) {\n\t\t\tcontinue\n\t\t}\n\t\tif (Array.isArray(v)) {\n\t\t\tconst items = v.filter((item) => !isOptionalUnresolved(item))\n\t\t\tif (items.length > 0) {\n\t\t\t\tout[k] = items\n\t\t\t}\n\t\t} else if (v && typeof v === 'object') {\n\t\t\tconst inner = {}\n\t\t\tfor (const [op, ov] of Object.entries(v)) {\n\t\t\t\tif (Array.isArray(ov)) {\n\t\t\t\t\tconst items = ov.filter((item) => !isOptionalUnresolved(item))\n\t\t\t\t\tif (items.length > 0) {\n\t\t\t\t\t\tinner[op] = items\n\t\t\t\t\t}\n\t\t\t\t} else if (!isOptionalUnresolved(ov)) {\n\t\t\t\t\tinner[op] = ov\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (Object.keys(inner).length > 0) {\n\t\t\t\tout[k] = inner\n\t\t\t}\n\t\t} else {\n\t\t\tout[k] = v\n\t\t}\n\t}\n\treturn out\n}\n\n/**\n * Whether a resolved filter map still carries an unresolved `@`-token. Used by\n * context-bound widgets to detect \"the page state this widget depends on isn't\n * set yet\" (e.g. a client-overview list whose `client` filter is still the raw\n * `@workspace.selectedClient` because no client is selected) and skip the query\n * / render a prompt instead of fetching the whole register.\n *\n * OPTIONAL tokens (`@workspace.<key>?`) are NOT counted — they are meant to be\n * dropped, not waited on (see {@link dropOptionalUnresolved}).\n *\n * @param {object} filter A filter map already passed through {@link resolveFilterTokens}.\n * @return {boolean} True when any value is still a (non-optional) string beginning with `@`.\n */\nexport function hasUnresolvedTokens(filter) {\n\tif (!filter || typeof filter !== 'object') {\n\t\treturn false\n\t}\n\tconst blocking = (x) => typeof x === 'string' && x.charAt(0) === '@' && !isOptionalUnresolved(x)\n\tconst anyBlocking = (v) => {\n\t\tif (blocking(v)) {\n\t\t\treturn true\n\t\t}\n\t\tif (Array.isArray(v)) {\n\t\t\treturn v.some(blocking)\n\t\t}\n\t\treturn false\n\t}\n\tfor (const v of Object.values(filter)) {\n\t\tif (anyBlocking(v)) {\n\t\t\treturn true\n\t\t}\n\t\tif (v && typeof v === 'object' && !Array.isArray(v)) {\n\t\t\tfor (const ov of Object.values(v)) {\n\t\t\t\tif (anyBlocking(ov)) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\n/**\n * Resolve every dynamic `@`-token in a filter map (equality, operator, and\n * IN-list array shapes). Array values resolve item-by-item so a list can mix\n * tokens and literals (`{ assignee: ['@me', 'shared'] }`).\n *\n * @param {object} filter The filter map (`{ field: value | value[] | { op: value | value[] } }`).\n * @param {{objectId?: (string|number), object?: object, workspace?: object, config?: object, range?: object}} [ctx] Optional\n * context forwarded to {@link resolveFilterValue} for `@objectId` /\n * `@object.<field>` / `@workspace.<key>` / `@config.<key>` tokens.\n * @return {object} A new filter map with tokens resolved.\n */\nexport function resolveFilterTokens(filter, ctx) {\n\tif (!filter || typeof filter !== 'object') {\n\t\treturn filter\n\t}\n\t// An item that resolves to a list (`@myGroups`) is spread in place, so\n\t// `['@myGroups', 'archive']` stays one flat IN list.\n\tconst resolveOne = (v) => (Array.isArray(v)\n\t\t? v.flatMap((item) => {\n\t\t\t\tconst r = resolveFilterValue(item, ctx)\n\t\t\t\treturn Array.isArray(r) ? r : [r]\n\t\t\t})\n\t\t: resolveFilterValue(v, ctx))\n\tconst out = {}\n\tfor (const [k, v] of Object.entries(filter)) {\n\t\tif (v && typeof v === 'object' && !Array.isArray(v)) {\n\t\t\tconst inner = {}\n\t\t\tfor (const [op, ov] of Object.entries(v)) {\n\t\t\t\tinner[op] = resolveOne(ov)\n\t\t\t}\n\t\t\tout[k] = inner\n\t\t} else {\n\t\t\tout[k] = resolveOne(v)\n\t\t}\n\t}\n\treturn out\n}\n\n/**\n * Recursively resolve `@`-tokens inside an arbitrary JSON value — objects\n * and arrays at ANY depth, unlike {@link resolveFilterTokens} which only\n * understands the flat filter-map shape (equality / operator / IN-list, one\n * level of nesting). Used by the `api-call` action's `payload`: a\n * Filinq-style generation body like\n * `{ dataRefs: [{ register: 'crm', schema: 'lead', id: '@objectId' }] }`\n * needs the token resolved inside a nested array of objects, which the\n * shallow filter-map resolver can't reach.\n *\n * @param {unknown} value The value to resolve — object / array / primitive.\n * @param {{objectId?: (string|number), object?: object, workspace?: object, config?: object, range?: object}} [ctx] Optional\n * context forwarded to {@link resolveFilterValue}.\n * @return {unknown} A new value with every string leaf token-resolved (structure preserved).\n */\nexport function resolveDeepTokens(value, ctx) {\n\tif (Array.isArray(value)) {\n\t\treturn value.map((v) => resolveDeepTokens(v, ctx))\n\t}\n\tif (value && typeof value === 'object') {\n\t\tconst out = {}\n\t\tfor (const [k, v] of Object.entries(value)) {\n\t\t\tout[k] = resolveDeepTokens(v, ctx)\n\t\t}\n\t\treturn out\n\t}\n\treturn resolveFilterValue(value, ctx)\n}\n\n/**\n * Deep-tree counterpart to {@link hasUnresolvedTokens}: whether an\n * already-{@link resolveDeepTokens}-resolved value still carries an\n * unresolved, non-optional `@`-token anywhere inside it (any depth). Used to\n * BLOCK an `api-call` whose `payload` has a required token (typically\n * `@objectId` / `@object.<field>`) that failed to resolve, instead of\n * silently sending the literal token string to the server.\n *\n * @param {unknown} value The (already deep-resolved) value.\n * @return {boolean} True when a required token is still unresolved.\n */\nexport function hasUnresolvedDeepTokens(value) {\n\tif (Array.isArray(value)) {\n\t\treturn value.some(hasUnresolvedDeepTokens)\n\t}\n\tif (value && typeof value === 'object') {\n\t\treturn Object.values(value).some(hasUnresolvedDeepTokens)\n\t}\n\treturn typeof value === 'string' && value.charAt(0) === '@' && !isOptionalUnresolved(value)\n}\n\n/**\n * Deep-tree counterpart to {@link dropOptionalUnresolved}: strips unresolved\n * OPTIONAL tokens (`@workspace.<key>?` / `@config.<key>?` left as-is after\n * resolution) out of an arbitrary JSON value at any depth. An object key\n * whose value is an unresolved optional token is dropped entirely; an array\n * item that resolves unresolved-optional is filtered out.\n *\n * @param {unknown} value The (already {@link resolveDeepTokens}-resolved) value.\n * @return {unknown} The value with unresolved-optional leaves removed.\n */\nexport function dropOptionalUnresolvedDeep(value) {\n\tif (Array.isArray(value)) {\n\t\treturn value\n\t\t\t.filter((v) => !isOptionalUnresolved(v))\n\t\t\t.map((v) => dropOptionalUnresolvedDeep(v))\n\t}\n\tif (value && typeof value === 'object') {\n\t\tconst out = {}\n\t\tfor (const [k, v] of Object.entries(value)) {\n\t\t\tif (isOptionalUnresolved(v)) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tout[k] = dropOptionalUnresolvedDeep(v)\n\t\t}\n\t\treturn out\n\t}\n\treturn value\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolveFilterTokens.js","sources":["../../../src/utils/resolveFilterTokens.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * Resolve dynamic `@`-tokens inside a widget filter at FETCH time, so manifest\n * filters can express \"relative to now / the current user\" without baking a\n * fixed value. The widgets call this just before sending the filter to\n * OpenRegister.\n *\n * Supported tokens:\n * - `@me` → the current Nextcloud user id (`getCurrentUser()` from\n * `@nextcloud/auth`; `window.OC.currentUser` fallback)\n * - `@myGroups` → the ids of the Nextcloud groups the current user is\n * in, as an ARRAY (an IN filter). `ctx.myGroups` wins;\n * otherwise a reactive peek over `getCurrentUserGroups`.\n * Stays UNRESOLVED while loading and when the user is\n * in no group, so the caller waits instead of sending\n * an empty IN list (which OpenRegister reads as \"no\n * constraint\"). Spread in place inside an IN-list array.\n * - `@myTeam` → the current user's primary team, a Nextcloud group id,\n * as the app answers it (`registerMyTeamSource`;\n * `ctx.myTeam` wins). Stays UNRESOLVED while it is read;\n * a user in no team gets `@myTeam?`, an optional token\n * the caller drops, so the filter goes away rather than\n * widening to all of the user's groups.\n * - `@now` → the current instant, ISO-8601\n * - `@today` → today at 00:00, `YYYY-MM-DD` (date-prefix comparable)\n * - `@today±Nd` → relative-date arithmetic at day granularity: N days\n * from today (e.g. `@today-30d`, `@today+7d`)\n * - `@monthStart` → first day of the current month, `YYYY-MM-DD`\n * - `@monthEnd` → last day of the current month, `YYYY-MM-DD`; on a\n * date-time field use `lt: '@nextMonthStart'` instead,\n * since `lte` a date stops at that day's midnight\n * - `@nextMonthStart` → first day of the next month, `YYYY-MM-DD`\n * - `@quarterStart` → first day of the current quarter, `YYYY-MM-DD`\n * - `@yearStart` → first day of the current year, `YYYY-MM-DD`\n * - `@currentFiscalYear` → the current calendar year as a number string, e.g. `2026`\n * - `@range.from` / `@range.to` / `@range.preset` → the active date range a\n * widget passes in `ctx.range` (CnStatWidget: its own\n * picker, else the dashboard's). A trailing `?` marks it\n * optional, as for `@workspace.<key>?`.\n * - `@objectId` → the current detail-page object's id (needs `ctx`)\n * - `@object.<field>` → a field off the current detail-page object (needs `ctx`)\n * - `@workspace.<key>` → a value off the page-level workspace context (needs `ctx.workspace`)\n * - `@config.<key>` → a value off the page-level app config (needs `ctx.config`)\n * - `@context.<name>.<path>` → a value off a record the detail page reads beside\n * the loaded one (needs `ctx.context`); left as written\n * while that record is not read\n *\n * `@objectId` / `@object.<field>` are OBJECT-CONTEXT tokens: they resolve only\n * when a `ctx` `{ objectId, object }` is supplied (a detail page provides it via\n * the `cnObjectContext` inject). `@workspace.<key>` is a WORKSPACE-CONTEXT token:\n * it resolves a key off `ctx.workspace` (the reactive `cnWorkspaceContext` a\n * dashboard/workspace page provides) so a list widget can react to page-level\n * state another widget writes (e.g. a selected client). Without the matching\n * context the tokens pass through unchanged — and an UNRESOLVED `@workspace.*`\n * token signals \"no selection yet\" to the caller (see {@link hasUnresolvedTokens}).\n *\n * `@config.<key>` is an APP-CONFIG token: it resolves a key off `ctx.config` (the\n * page-level app config a dashboard/detail page provides via `cnAppConfig` — e.g.\n * a reporting `currency` captured by the setup wizard). Like `@workspace.<key>`, a\n * trailing `?` marks it optional. An UNRESOLVED required `@config.<key>` passes\n * through unchanged; this lets `format: { currency: '@config.currency' }` fall\n * back to a literal default when the config is unset.\n *\n * IN-lists: a filter value MAY be an ARRAY (`{ status: ['open', 'pending'] }`,\n * or the explicit operator form `{ status: { in: [...] } }`). Tokens inside the\n * array are resolved item-by-item (`{ assignee: ['@me', 'shared'] }` works).\n * OpenRegister expects an IN-list as repeated bracket params\n * (`status[]=open&status[]=pending` — the same shape `buildQueryString` /\n * `useObjectStore` send), so widget fetchers serialize a resolved array as\n * repeated `field[]` params, never as a JSON blob or a single joined string.\n *\n * @module utils/resolveFilterTokens\n */\n\nimport { getCurrentUser } from '@nextcloud/auth'\n// userGroupsPeek, not widgetVisibility: that one imports @nextcloud/axios, and\n// this resolver runs on public pages and in node (see userGroupsPeek.js).\nimport { peekMyTeam } from './myTeam.js'\nimport { readPath } from './readPath.js'\nimport { TODAY_DELTA_RE } from './sentinelTokens.js'\nimport { peekCurrentUserGroups } from './userGroupsPeek.js'\n\n/** The filter token for the current user's group ids. */\nexport const MY_GROUPS_TOKEN = '@myGroups'\n\n/** The filter token for the current user's primary team. */\nexport const MY_TEAM_TOKEN = '@myTeam'\n\n/**\n * Resolve `@myTeam`: the team's group id; `@myTeam` while it is being read (the\n * caller waits); `@myTeam?` for a user in no team (the caller drops the key).\n *\n * @spec openspec/changes/saved-view-tokens-my-team/specs/schema-utilities/spec.md#requirement-myteam-resolves-to-the-current-users-primary-team\n * @param {{myTeam?: string}} [ctx] Optional context; `ctx.myTeam` wins.\n * @return {string} The group id or the token.\n */\nfunction resolveMyTeam(ctx) {\n\tconst team = ctx && typeof ctx.myTeam === 'string' ? ctx.myTeam : peekMyTeam()\n\tif (team === null) {\n\t\treturn MY_TEAM_TOKEN\n\t}\n\treturn team === '' ? `${MY_TEAM_TOKEN}?` : team\n}\n\n/**\n * Resolve `@myGroups`: the current user's group ids, or the token itself while\n * they are loading or when there are none (an empty IN list would match every\n * row, so \"no team\" must mean \"wait\", never \"everything\").\n *\n * @spec openspec/changes/nextcloud-group-surfaces/specs/schema-utilities/spec.md#requirement-mygroups-resolves-to-the-current-users-group-ids\n * @param {{myGroups?: string[]}} [ctx] Optional context; `ctx.myGroups` wins.\n * @return {string[]|string} The group ids, or `'@myGroups'` when unresolved.\n */\nfunction resolveMyGroups(ctx) {\n\tlet groups = ctx && Array.isArray(ctx.myGroups) ? ctx.myGroups : null\n\tif (groups === null) {\n\t\ttry {\n\t\t\tgroups = peekCurrentUserGroups()\n\t\t} catch {\n\t\t\tgroups = null\n\t\t}\n\t}\n\tconst ids = Array.isArray(groups)\n\t\t? groups.filter((g) => typeof g === 'string' && g !== '')\n\t\t: []\n\treturn ids.length > 0 ? [...ids] : MY_GROUPS_TOKEN\n}\n\n/**\n * Format a Date as `YYYY-MM-DD` (local).\n *\n * @param {Date} d The date.\n * @return {string} The date-only string.\n */\nfunction ymd(d) {\n\tconst m = String(d.getMonth() + 1).padStart(2, '0')\n\tconst day = String(d.getDate()).padStart(2, '0')\n\treturn `${d.getFullYear()}-${m}-${day}`\n}\n\n/**\n * Fill each `{@config.<key>}` inside a token from `ctx.config`, so a token can\n * take an admin setting (`@today-{@config.lead_stale_threshold_days}d`). The\n * token comes back unchanged when any key is missing from the config.\n *\n * @param {string} token The token.\n * @param {object} [ctx] The token context.\n * @return {string} The token with the config values in.\n * @spec openspec/changes/pl4-cell-rules/specs/pl4-cell-rules/spec.md#requirement-a-token-can-take-a-config-value\n */\nfunction fillConfigInToken(token, ctx) {\n\tconst config = (ctx && ctx.config) || {}\n\tlet missing = false\n\tconst filled = token.replace(/\\{@config\\.([A-Za-z0-9_.-]+)\\}/g, (whole, key) => {\n\t\tconst value = config[key]\n\t\tif (value === undefined || value === null || value === '') {\n\t\t\tmissing = true\n\t\t\treturn whole\n\t\t}\n\t\treturn String(value)\n\t})\n\treturn missing ? token : filled\n}\n\n/**\n * Resolve a single filter value if it is a dynamic `@`-token, else pass through.\n *\n * @param {unknown} v The candidate value.\n * @param {{objectId?: (string|number), object?: object, workspace?: object, config?: object, range?: object, myGroups?: string[]}} [ctx] Optional\n * context for `@objectId` / `@object.<field>` (detail page),\n * `@workspace.<key>` (page-level workspace state), and `@config.<key>`\n * (page-level app config) tokens.\n * @return {unknown} The resolved value.\n */\nexport function resolveFilterValue(v, ctx) {\n\tif (typeof v !== 'string' || v.charAt(0) !== '@') {\n\t\treturn v\n\t}\n\tif (v.includes('{@config.')) {\n\t\tconst filled = fillConfigInToken(v, ctx)\n\t\treturn filled === v ? v : resolveFilterValue(filled, ctx)\n\t}\n\tconst now = new Date()\n\tif (v === MY_GROUPS_TOKEN) {\n\t\treturn resolveMyGroups(ctx)\n\t}\n\tif (v === MY_TEAM_TOKEN) {\n\t\treturn resolveMyTeam(ctx)\n\t}\n\tif (v === '@objectId') {\n\t\treturn (ctx && ctx.objectId !== undefined && ctx.objectId !== null) ? String(ctx.objectId) : v\n\t}\n\tif (v.startsWith('@object.')) {\n\t\tconst field = v.slice('@object.'.length)\n\t\tif (ctx && ctx.object && field && ctx.object[field] !== undefined) {\n\t\t\treturn ctx.object[field]\n\t\t}\n\t\treturn v\n\t}\n\tif (v.startsWith('@context.')) {\n\t\t// @spec openspec/changes/files-second-line-fields/specs/files-second-line-fields/spec.md#requirement-widget-props-can-read-the-detail-pages-context-records\n\t\tconst found = ctx && ctx.context ? readPath(ctx.context, v.slice('@context.'.length)) : undefined\n\t\treturn found === undefined ? v : found\n\t}\n\tif (v.startsWith('@workspace.')) {\n\t\t// A trailing `?` marks the token OPTIONAL: when unset the caller drops the\n\t\t// filter key (show all) instead of waiting (see hasUnresolvedTokens /\n\t\t// CnObjectListWidget). The `?` is stripped from the key lookup.\n\t\tconst raw = v.slice('@workspace.'.length)\n\t\tconst key = raw.endsWith('?') ? raw.slice(0, -1) : raw\n\t\tif (ctx && ctx.workspace && key && ctx.workspace[key] !== undefined\n\t\t\t&& ctx.workspace[key] !== null && ctx.workspace[key] !== '') {\n\t\t\treturn ctx.workspace[key]\n\t\t}\n\t\treturn v\n\t}\n\tif (v.startsWith('@config.')) {\n\t\t// A trailing `?` marks the token OPTIONAL (same convention as\n\t\t// `@workspace.<key>?`): an unset value lets the caller drop the key. A\n\t\t// required `@config.<key>` that is unset passes through unchanged so a\n\t\t// downstream consumer can fall back to a literal default (e.g.\n\t\t// `format.currency` → `'EUR'`).\n\t\tconst raw = v.slice('@config.'.length)\n\t\tconst key = raw.endsWith('?') ? raw.slice(0, -1) : raw\n\t\tif (ctx && ctx.config && key && ctx.config[key] !== undefined\n\t\t\t&& ctx.config[key] !== null && ctx.config[key] !== '') {\n\t\t\treturn ctx.config[key]\n\t\t}\n\t\treturn v\n\t}\n\tif (v.startsWith('@range.')) {\n\t\t// `@range.from` / `@range.to` / `@range.preset`: the active date range the\n\t\t// caller put in `ctx.range`. CnStatWidget documented these tokens and put\n\t\t// `range` in its endpoint context, but nothing resolved them, so the\n\t\t// literal token stayed in the params, hasUnresolvedTokens blocked the\n\t\t// request, and a card that used its own period picker never loaded. A\n\t\t// trailing `?` marks the token OPTIONAL, the same convention as\n\t\t// `@workspace.<key>?`: unset, the caller drops the key.\n\t\tconst raw = v.slice('@range.'.length)\n\t\tconst key = raw.endsWith('?') ? raw.slice(0, -1) : raw\n\t\tif (ctx && ctx.range && key && ctx.range[key] !== undefined\n\t\t\t&& ctx.range[key] !== null && ctx.range[key] !== '') {\n\t\t\treturn ctx.range[key]\n\t\t}\n\t\treturn v\n\t}\n\tif (v === '@me.displayName' || v === '@me.email') {\n\t\t// The form's own context wins (`ctx.me`, e.g. an email fetched from the\n\t\t// profile); @nextcloud/auth only knows the uid and display name.\n\t\tconst key = v.slice('@me.'.length)\n\t\tif (ctx && ctx.me && ctx.me[key] !== undefined && ctx.me[key] !== null && ctx.me[key] !== '') {\n\t\t\treturn ctx.me[key]\n\t\t}\n\t\ttry {\n\t\t\tconst user = getCurrentUser()\n\t\t\tif (user && user[key]) {\n\t\t\t\treturn user[key]\n\t\t\t}\n\t\t} catch {\n\t\t\t// not signed in: leave the token unresolved\n\t\t}\n\t\treturn v\n\t}\n\tif (v === '@me') {\n\t\t// Canonical source is @nextcloud/auth; window.OC is the fallback for\n\t\t// environments where the auth package can't read the page state (jsdom).\n\t\tlet uid\n\t\ttry {\n\t\t\tconst user = getCurrentUser()\n\t\t\tuid = user && user.uid\n\t\t} catch {\n\t\t\tuid = null\n\t\t}\n\t\treturn uid || (typeof window !== 'undefined' && window.OC && window.OC.currentUser) || ''\n\t}\n\tif (v === '@now') {\n\t\treturn now.toISOString()\n\t}\n\tif (v === '@today') {\n\t\tconst d = new Date(now)\n\t\td.setHours(0, 0, 0, 0)\n\t\treturn ymd(d)\n\t}\n\tif (v === '@monthStart') {\n\t\treturn ymd(new Date(now.getFullYear(), now.getMonth(), 1))\n\t}\n\tif (v === '@monthEnd') {\n\t\t// Day 0 of the next month is the last day of this one.\n\t\treturn ymd(new Date(now.getFullYear(), now.getMonth() + 1, 0))\n\t}\n\tif (v === '@nextMonthStart') {\n\t\treturn ymd(new Date(now.getFullYear(), now.getMonth() + 1, 1))\n\t}\n\tif (v === '@quarterStart') {\n\t\treturn ymd(new Date(now.getFullYear(), Math.floor(now.getMonth() / 3) * 3, 1))\n\t}\n\tif (v === '@yearStart') {\n\t\treturn ymd(new Date(now.getFullYear(), 0, 1))\n\t}\n\tif (v === '@currentFiscalYear') {\n\t\treturn String(now.getFullYear())\n\t}\n\tconst m = v.match(TODAY_DELTA_RE)\n\tif (m) {\n\t\tconst d = new Date(now)\n\t\td.setHours(0, 0, 0, 0)\n\t\td.setDate(d.getDate() + Number(m[1]))\n\t\treturn ymd(d)\n\t}\n\treturn v\n}\n\n/**\n * Whether a value is an UNRESOLVED OPTIONAL token — a string still shaped like\n * `@workspace.<key>?` or `@config.<key>?` after token resolution (the `?` marks\n * it as \"drop me when unset\"). Callers strip such keys from the filter so the\n * list shows all rows rather than waiting for a selection / a config value.\n *\n * @param {unknown} v A (possibly resolved) filter value.\n * @return {boolean}\n */\nexport function isOptionalUnresolved(v) {\n\treturn typeof v === 'string'\n\t\t&& (v.startsWith('@workspace.') || v.startsWith('@config.') || v.startsWith('@range.') || v === `${MY_TEAM_TOKEN}?`)\n\t\t&& v.endsWith('?')\n}\n\n/**\n * Return a copy of a resolved filter map with every UNRESOLVED OPTIONAL\n * workspace token (`@workspace.<key>?` left as-is) removed. Required tokens and\n * concrete values are kept untouched. Inside an IN-list array, unresolved\n * optional ITEMS are dropped; a key whose array empties out is dropped whole\n * (an empty IN-list means \"no constraint\", not \"match nothing\").\n *\n * @param {object} filter A filter map already passed through {@link resolveFilterTokens}.\n * @return {object} The filter without optional-unresolved keys.\n */\nexport function dropOptionalUnresolved(filter) {\n\tif (!filter || typeof filter !== 'object') {\n\t\treturn filter\n\t}\n\tconst out = {}\n\tfor (const [k, v] of Object.entries(filter)) {\n\t\tif (isOptionalUnresolved(v)) {\n\t\t\tcontinue\n\t\t}\n\t\tif (Array.isArray(v)) {\n\t\t\tconst items = v.filter((item) => !isOptionalUnresolved(item))\n\t\t\tif (items.length > 0) {\n\t\t\t\tout[k] = items\n\t\t\t}\n\t\t} else if (v && typeof v === 'object') {\n\t\t\tconst inner = {}\n\t\t\tfor (const [op, ov] of Object.entries(v)) {\n\t\t\t\tif (Array.isArray(ov)) {\n\t\t\t\t\tconst items = ov.filter((item) => !isOptionalUnresolved(item))\n\t\t\t\t\tif (items.length > 0) {\n\t\t\t\t\t\tinner[op] = items\n\t\t\t\t\t}\n\t\t\t\t} else if (!isOptionalUnresolved(ov)) {\n\t\t\t\t\tinner[op] = ov\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (Object.keys(inner).length > 0) {\n\t\t\t\tout[k] = inner\n\t\t\t}\n\t\t} else {\n\t\t\tout[k] = v\n\t\t}\n\t}\n\treturn out\n}\n\n/**\n * Whether a resolved filter map still carries an unresolved `@`-token. Used by\n * context-bound widgets to detect \"the page state this widget depends on isn't\n * set yet\" (e.g. a client-overview list whose `client` filter is still the raw\n * `@workspace.selectedClient` because no client is selected) and skip the query\n * / render a prompt instead of fetching the whole register.\n *\n * OPTIONAL tokens (`@workspace.<key>?`) are NOT counted — they are meant to be\n * dropped, not waited on (see {@link dropOptionalUnresolved}).\n *\n * @param {object} filter A filter map already passed through {@link resolveFilterTokens}.\n * @return {boolean} True when any value is still a (non-optional) string beginning with `@`.\n */\nexport function hasUnresolvedTokens(filter) {\n\tif (!filter || typeof filter !== 'object') {\n\t\treturn false\n\t}\n\tconst blocking = (x) => typeof x === 'string' && x.charAt(0) === '@' && !isOptionalUnresolved(x)\n\tconst anyBlocking = (v) => {\n\t\tif (blocking(v)) {\n\t\t\treturn true\n\t\t}\n\t\tif (Array.isArray(v)) {\n\t\t\treturn v.some(blocking)\n\t\t}\n\t\treturn false\n\t}\n\tfor (const v of Object.values(filter)) {\n\t\tif (anyBlocking(v)) {\n\t\t\treturn true\n\t\t}\n\t\tif (v && typeof v === 'object' && !Array.isArray(v)) {\n\t\t\tfor (const ov of Object.values(v)) {\n\t\t\t\tif (anyBlocking(ov)) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\n/**\n * Resolve every dynamic `@`-token in a filter map (equality, operator, and\n * IN-list array shapes). Array values resolve item-by-item so a list can mix\n * tokens and literals (`{ assignee: ['@me', 'shared'] }`).\n *\n * @param {object} filter The filter map (`{ field: value | value[] | { op: value | value[] } }`).\n * @param {{objectId?: (string|number), object?: object, workspace?: object, config?: object, range?: object}} [ctx] Optional\n * context forwarded to {@link resolveFilterValue} for `@objectId` /\n * `@object.<field>` / `@workspace.<key>` / `@config.<key>` tokens.\n * @return {object} A new filter map with tokens resolved.\n */\nexport function resolveFilterTokens(filter, ctx) {\n\tif (!filter || typeof filter !== 'object') {\n\t\treturn filter\n\t}\n\t// An item that resolves to a list (`@myGroups`) is spread in place, so\n\t// `['@myGroups', 'archive']` stays one flat IN list.\n\tconst resolveOne = (v) => (Array.isArray(v)\n\t\t? v.flatMap((item) => {\n\t\t\t\tconst r = resolveFilterValue(item, ctx)\n\t\t\t\treturn Array.isArray(r) ? r : [r]\n\t\t\t})\n\t\t: resolveFilterValue(v, ctx))\n\tconst out = {}\n\tfor (const [k, v] of Object.entries(filter)) {\n\t\tif (v && typeof v === 'object' && !Array.isArray(v)) {\n\t\t\tconst inner = {}\n\t\t\tfor (const [op, ov] of Object.entries(v)) {\n\t\t\t\tinner[op] = resolveOne(ov)\n\t\t\t}\n\t\t\tout[k] = inner\n\t\t} else {\n\t\t\tout[k] = resolveOne(v)\n\t\t}\n\t}\n\treturn out\n}\n\n/**\n * Recursively resolve `@`-tokens inside an arbitrary JSON value — objects\n * and arrays at ANY depth, unlike {@link resolveFilterTokens} which only\n * understands the flat filter-map shape (equality / operator / IN-list, one\n * level of nesting). Used by the `api-call` action's `payload`: a\n * Filinq-style generation body like\n * `{ dataRefs: [{ register: 'crm', schema: 'lead', id: '@objectId' }] }`\n * needs the token resolved inside a nested array of objects, which the\n * shallow filter-map resolver can't reach.\n *\n * @param {unknown} value The value to resolve — object / array / primitive.\n * @param {{objectId?: (string|number), object?: object, workspace?: object, config?: object, range?: object}} [ctx] Optional\n * context forwarded to {@link resolveFilterValue}.\n * @return {unknown} A new value with every string leaf token-resolved (structure preserved).\n */\nexport function resolveDeepTokens(value, ctx) {\n\tif (Array.isArray(value)) {\n\t\treturn value.map((v) => resolveDeepTokens(v, ctx))\n\t}\n\tif (value && typeof value === 'object') {\n\t\tconst out = {}\n\t\tfor (const [k, v] of Object.entries(value)) {\n\t\t\tout[k] = resolveDeepTokens(v, ctx)\n\t\t}\n\t\treturn out\n\t}\n\treturn resolveFilterValue(value, ctx)\n}\n\n/**\n * Deep-tree counterpart to {@link hasUnresolvedTokens}: whether an\n * already-{@link resolveDeepTokens}-resolved value still carries an\n * unresolved, non-optional `@`-token anywhere inside it (any depth). Used to\n * BLOCK an `api-call` whose `payload` has a required token (typically\n * `@objectId` / `@object.<field>`) that failed to resolve, instead of\n * silently sending the literal token string to the server.\n *\n * @param {unknown} value The (already deep-resolved) value.\n * @return {boolean} True when a required token is still unresolved.\n */\nexport function hasUnresolvedDeepTokens(value) {\n\tif (Array.isArray(value)) {\n\t\treturn value.some(hasUnresolvedDeepTokens)\n\t}\n\tif (value && typeof value === 'object') {\n\t\treturn Object.values(value).some(hasUnresolvedDeepTokens)\n\t}\n\treturn typeof value === 'string' && value.charAt(0) === '@' && !isOptionalUnresolved(value)\n}\n\n/**\n * Deep-tree counterpart to {@link dropOptionalUnresolved}: strips unresolved\n * OPTIONAL tokens (`@workspace.<key>?` / `@config.<key>?` left as-is after\n * resolution) out of an arbitrary JSON value at any depth. An object key\n * whose value is an unresolved optional token is dropped entirely; an array\n * item that resolves unresolved-optional is filtered out.\n *\n * @param {unknown} value The (already {@link resolveDeepTokens}-resolved) value.\n * @return {unknown} The value with unresolved-optional leaves removed.\n */\nexport function dropOptionalUnresolvedDeep(value) {\n\tif (Array.isArray(value)) {\n\t\treturn value\n\t\t\t.filter((v) => !isOptionalUnresolved(v))\n\t\t\t.map((v) => dropOptionalUnresolvedDeep(v))\n\t}\n\tif (value && typeof value === 'object') {\n\t\tconst out = {}\n\t\tfor (const [k, v] of Object.entries(value)) {\n\t\t\tif (isOptionalUnresolved(v)) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tout[k] = dropOptionalUnresolvedDeep(v)\n\t\t}\n\t\treturn out\n\t}\n\treturn value\n}\n"],"names":[],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAQA;AACA;AACY,MAAC,eAAe,GAAG,YAAW;AAC1C;AACA;AACY,MAAC,aAAa,GAAG,UAAS;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,aAAa,CAAC,GAAG,EAAE;AAC5B,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,GAAG,GAAG,CAAC,MAAM,GAAG,UAAU,GAAE;AAC/E,CAAC,IAAI,IAAI,KAAK,IAAI,EAAE;AACpB,EAAE,OAAO,aAAa;AACtB,EAAE;AACF,CAAC,OAAO,IAAI,KAAK,EAAE,GAAG,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI;AAChD,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,eAAe,CAAC,GAAG,EAAE;AAC9B,CAAC,IAAI,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,QAAQ,GAAG,KAAI;AACtE,CAAC,IAAI,MAAM,KAAK,IAAI,EAAE;AACtB,EAAE,IAAI;AACN,GAAG,MAAM,GAAG,qBAAqB,GAAE;AACnC,GAAG,CAAC,MAAM;AACV,GAAG,MAAM,GAAG,KAAI;AAChB,GAAG;AACH,EAAE;AACF,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;AAClC,IAAI,MAAM,CAAC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"}
@@ -188,7 +188,7 @@ const SENTINEL_VOCABULARY = Object.freeze({
188
188
  members: ['@subject.<field>'],
189
189
  },
190
190
  context: {
191
- resolver: 'CnDetailPage visibilityContext (detailWidgetVisibility), read by a grid widget\'s or a tab\'s visibleWhen',
191
+ resolver: 'CnDetailPage visibilityContext (detailWidgetVisibility), read by a grid widget\'s or a tab\'s visibleWhen, and by a widget\'s props (CnDetailWidgetHost)',
192
192
  description: 'A record the detail page reads beside the loaded one, named in `config.visibilityContext` (a case\'s case type). A `visibleWhen` field reads it as `@context.<name>.<field>`, dot paths allowed (`@context.caseType.category`).',
193
193
  members: ['@context.<name>.<field>'],
194
194
  },
@@ -1 +1 @@
1
- {"version":3,"file":"sentinelTokens.js","sources":["../../../src/utils/sentinelTokens.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * Closed, context-partitioned manifest **sentinel-token vocabulary** — the\n * single source of truth for every `@`-prefixed dynamic value a manifest may\n * carry under `pages[].config` or a widget `filter`/`dataSource`.\n *\n * Before this module the token surface was scattered across four resolvers\n * (`resolveManifestSentinels`, `resolveFilterTokens`, `resolveRouteSentinels`,\n * `fetchAggregate`) plus ad-hoc single-app inventions (`@currentFiscalYear`,\n * `@page.*`, `@runtime`). This module declares the vocabulary ONCE so:\n *\n * 1. the JSON-Schema `$defs` in `app-manifest-v2.schema.json` reject an\n * out-of-vocabulary token (the pattern strings here are the exact strings\n * mirrored into the schema — a unit test enforces byte-equality);\n * 2. the shared resolver dispatch (`resolveManifestTokens.js`) and the four\n * resolvers import their token patterns from here rather than re-declaring\n * them, so the runtime and the schema cannot drift;\n * 3. a hydra manifest gate can `scanManifestTokens()` an app and FAIL an\n * unknown token / WARN a deprecated one, reusing this export (no hardcoded\n * copy).\n *\n * ## Context partitions\n *\n * A token is valid only in the context whose resolver runs on it:\n *\n * - **filter** — `resolveFilterTokens`, resolved at fetch time:\n * `@me`, `@myGroups`, `@myTeam`, `@now`, `@today`, `@today±Nd`, `@monthStart`, `@monthEnd`, `@nextMonthStart`,\n * `@quarterStart`, `@yearStart`.\n * - **config** — `IAppConfig`-sourced: `@resolve:<key>`, `@config.<key>`\n * (trailing `?` marks optional).\n * - **object** — detail-page object context: `@objectId`,\n * `@object.<field>`.\n * - **workspace** — page-level workspace state: `@workspace.<key>`\n * (trailing `?` optional).\n * - **route** — `resolveRouteSentinels`: `@route.<param>`.\n * - **declarative** — OpenRegister direction, resolved server-side:\n * `@self.<field>` (the object's own field in a\n * cross-object calc), `@ref:<path>`, `@aggregate:<expr>`.\n * - **visibleWhen** — the shared `visibleWhen` predicate's `source`-mode\n * collection-total marker, resolved client-side by\n * `evaluateVisibleWhen` (`utils/visibleWhen.js`):\n * `@total` (a `field: \"@total\"` — or omitted `field` —\n * compares the collection total rather than the first\n * result). Added for manifest-form-logic:\n * `config.fields[].visibleWhen` is the first\n * `visibleWhen` reachable through the\n * sentinelGuardedValue-guarded `pages[].config` subtree.\n *\n * `@ref`/`@aggregate` are first-class members even though currently unused\n * fleet-wide — they are the OR-declarative direction and belong in the closed\n * vocabulary so a future adopter validates rather than inventing a variant.\n *\n * @module utils/sentinelTokens\n */\n\n/**\n * Pattern STRINGS, one per context — the canonical source mirrored verbatim\n * into `app-manifest-v2.schema.json`'s `$defs`. A unit test asserts each schema\n * `$def`'s `pattern` equals the string here, so the two cannot drift.\n *\n * NOTE: these are JS string literals; a `\\\\.` here is the two-character\n * sequence `\\.` at runtime, which is exactly what the JSON schema stores after\n * its own `\\\\.` is parsed. Compare PARSED values, never raw source.\n *\n * @type {Readonly<Record<string, string>>}\n */\nexport const SENTINEL_TOKEN_PATTERNS = Object.freeze({\n\tfilter: '^@(?:me(?:\\\\.(?:displayName|email))?|myGroups|myTeam|now|today|monthStart|monthEnd|nextMonthStart|quarterStart|yearStart)$|^@today[+-](?:[0-9]+|\\\\{@config\\\\.[A-Za-z][A-Za-z0-9_.]*\\\\})d$',\n\tconfig: '^@resolve:[a-z][a-z0-9_-]*$|^@config\\\\.[A-Za-z][A-Za-z0-9_.]*\\\\??$',\n\tobject: '^@objectId$|^@object\\\\.[A-Za-z][A-Za-z0-9_]*$',\n\t// party-actions: a record field made a link (`@object.phone|tel`, `|mailto`, `|geo`).\n\tlink: '^@object\\\\.[A-Za-z][A-Za-z0-9_]*\\\\|(?:tel|mailto|geo)$',\n\tworkspace: '^@workspace\\\\.[A-Za-z][A-Za-z0-9_]*\\\\??$',\n\troute: '^@route\\\\.[A-Za-z][A-Za-z0-9_-]*$',\n\tdeclarative: '^@self\\\\.[A-Za-z][A-Za-z0-9_]*$|^@ref:[A-Za-z][A-Za-z0-9_./-]*$|^@aggregate:.+$',\n\t// manifest-form-logic: the shared visibleWhen predicate's source-mode\n\t// collection-total marker (`field: \"@total\"`), resolved client-side by\n\t// evaluateVisibleWhen — not one of the four IAppConfig/OpenRegister\n\t// resolvers, but a real pre-existing convention (already documented on\n\t// $defs.visibleWhen and the banner widget) now reachable through the\n\t// sentinelGuardedValue-guarded pages[].config subtree for the first time\n\t// via config.fields[].visibleWhen.\n\tvisibleWhen: '^@total$',\n\t// form-live-values: another answer in the same form, read by a field's `assign` rule.\n\tanswer: '^@answer\\\\.[A-Za-z][A-Za-z0-9_]*$',\n\t// A field of the row a row action is run on (`@row.<field>`, dot path), read by the\n\t// field-list widget's `rowActions` request URL and payload.\n\trow: '^@row\\\\.[A-Za-z][A-Za-z0-9_.@]*$',\n\t// A field of the record a start-here attention card names (`@subject.<field>`, dot path),\n\t// read by the banner widget's action routes.\n\tsubject: '^@subject\\\\.[A-Za-z][A-Za-z0-9_.]*$',\n\t// A record a detail page reads beside the loaded one (`visibilityContext`), read by a\n\t// grid widget's or a tab's `visibleWhen` as `@context.<name>.<field>` (dot path).\n\tcontext: '^@context\\\\.[A-Za-z][A-Za-z0-9_.]*$',\n\t// A field of the object a facts widget shows (`@source.<field>`, dot path), read by a\n\t// fact row's `route` params.\n\tsource: '^@source\\\\.[A-Za-z][A-Za-z0-9_.@]*$',\n\t// Deprecated-but-not-yet-removed tokens. Kept in the schema union so\n\t// deployed manifests still validate during the migration window; the gate\n\t// downgrades them to a WARN (see SENTINEL_DEPRECATIONS).\n\tdeprecated: '^@currentFiscalYear$|^@page\\\\.[A-Za-z][A-Za-z0-9_]*$|^@runtime(?:\\\\.[A-Za-z][A-Za-z0-9_]*)?$',\n})\n\n/**\n * The nine canonical context names (excludes `deprecated`, which is a\n * transitional overlay, not a resolution context).\n *\n * @type {string[]}\n */\nexport const SENTINEL_CONTEXTS = Object.freeze([\n\t'filter',\n\t'config',\n\t'object',\n\t'workspace',\n\t'route',\n\t'declarative',\n\t'visibleWhen',\n\t'answer',\n\t'row',\n\t'subject',\n\t'context',\n\t'source',\n])\n\n/**\n * Human-readable vocabulary: members + context + owning resolver + parameter\n * grammar. Documentation-facing (feeds audit item 16 schema-generated docs);\n * the machine-checkable truth is {@link SENTINEL_TOKEN_PATTERNS}.\n *\n * @type {Readonly<Record<string, {resolver: string, description: string, members: string[]}>>}\n */\nexport const SENTINEL_VOCABULARY = Object.freeze({\n\tfilter: {\n\t\tresolver: 'resolveFilterTokens',\n\t\tdescription: 'Relative fetch-time tokens (current user, the current user\\'s groups as an IN list, relative dates).',\n\t\tmembers: ['@me', '@me.displayName', '@me.email', '@myGroups', '@myTeam', '@now', '@today', '@today±Nd', '@monthStart', '@monthEnd', '@nextMonthStart', '@quarterStart', '@yearStart'],\n\t},\n\tconfig: {\n\t\tresolver: 'resolveManifestSentinels / resolveFilterTokens',\n\t\tdescription: 'IAppConfig-sourced values. `@resolve:<key>` at manifest-load time; `@config.<key>` (trailing `?` optional) at fetch time.',\n\t\tmembers: ['@resolve:<key>', '@config.<key>', '@config.<key>?'],\n\t},\n\tobject: {\n\t\tresolver: 'resolveFilterTokens',\n\t\tdescription: 'Detail-page object context. Resolve only when a `{ objectId, object }` ctx is supplied.',\n\t\tmembers: ['@objectId', '@object.<field>'],\n\t},\n\tlink: {\n\t\tresolver: 'CnPartyActionsWidget',\n\t\tdescription: 'A record field made a tel:, mailto: or geo: link, for an action target; the action is left out when the value makes no link.',\n\t\tmembers: ['@object.<field>|tel', '@object.<field>|mailto', '@object.<field>|geo'],\n\t},\n\tworkspace: {\n\t\tresolver: 'resolveFilterTokens',\n\t\tdescription: 'Page-level workspace state (e.g. a selected client / period). Trailing `?` marks optional (drop when unset).',\n\t\tmembers: ['@workspace.<key>', '@workspace.<key>?'],\n\t},\n\troute: {\n\t\tresolver: 'resolveRouteSentinels',\n\t\tdescription: 'vue-router param substitution at render time.',\n\t\tmembers: ['@route.<param>'],\n\t},\n\tdeclarative: {\n\t\tresolver: 'fetchAggregate (OpenRegister server-side)',\n\t\tdescription: 'OpenRegister declarative direction — resolved server-side. `@self.<field>` is the object\\'s own field in a cross-object calc; `@ref`/`@aggregate` are reserved (currently unused fleet-wide).',\n\t\tmembers: ['@self.<field>', '@ref:<path>', '@aggregate:<expr>'],\n\t},\n\tvisibleWhen: {\n\t\tresolver: 'evaluateVisibleWhen (utils/visibleWhen.js)',\n\t\tdescription: 'The shared visibleWhen predicate\\'s source-mode collection-total marker. `field: \"@total\"` (or an omitted `field`) compares the collection total instead of the first result.',\n\t\tmembers: ['@total'],\n\t},\n\tanswer: {\n\t\tresolver: 'resolveAssignValue (utils/formAssign.js)',\n\t\tdescription: 'Another answer in the same form, read by a field\\'s `assign` rule.',\n\t\tmembers: ['@answer.<field>'],\n\t},\n\trow: {\n\t\tresolver: 'CnFieldListWidget (rowActions request url and payload)',\n\t\tdescription: 'A field of the row a row action runs on, read by the field-list widget when it sends the action\\'s request. Dot paths are allowed (`@row.owner.id`).',\n\t\tmembers: ['@row.<field>'],\n\t},\n\tsubject: {\n\t\tresolver: 'CnBannerWidget (action route params and query)',\n\t\tdescription: 'A field of the record an attention card names (the first row of its ordered `visibleWhen` source query), read when the card builds an action\\'s route. Dot paths are allowed (`@subject.owner.id`).',\n\t\tmembers: ['@subject.<field>'],\n\t},\n\tcontext: {\n\t\tresolver: 'CnDetailPage visibilityContext (detailWidgetVisibility), read by a grid widget\\'s or a tab\\'s visibleWhen',\n\t\tdescription: 'A record the detail page reads beside the loaded one, named in `config.visibilityContext` (a case\\'s case type). A `visibleWhen` field reads it as `@context.<name>.<field>`, dot paths allowed (`@context.caseType.category`).',\n\t\tmembers: ['@context.<name>.<field>'],\n\t},\n\tsource: {\n\t\tresolver: 'CnFactsWidget (a fact row\\'s route params)',\n\t\tdescription: 'A field of the object a facts widget shows, read when a fact row builds its link. Dot paths are allowed (`@source.caseType.parentCaseType`).',\n\t\tmembers: ['@source.<field>'],\n\t},\n})\n\n/**\n * Machine-readable deprecation map: single-app inventions → canonical\n * replacement (or `null` for removal) + removal date. The shared resolver still\n * resolves a deprecated token during the window (emitting a one-time warn); the\n * gate WARNs (not fails) until `removal`. Each entry carries a `test` RegExp so\n * a parameterised deprecated token (`@page.period`) matches its family.\n *\n * @type {Readonly<Record<string, {test: RegExp, replacement: (string|null), removal: string, note: string}>>}\n */\nexport const SENTINEL_DEPRECATIONS = Object.freeze({\n\t'@currentFiscalYear': {\n\t\ttest: /^@currentFiscalYear$/,\n\t\treplacement: '@config.fiscalYear',\n\t\tremoval: '2026-10-01',\n\t\tnote: 'Single-app invention (shillinq). Source the fiscal year from IAppConfig instead of the calendar year.',\n\t},\n\t'@page.<key>': {\n\t\ttest: /^@page\\.[A-Za-z][A-Za-z0-9_]*$/,\n\t\treplacement: '@workspace.<key>',\n\t\tremoval: '2026-10-01',\n\t\tnote: 'Single-app invention (pipelinq). Page-context state is the workspace context; use @workspace.<key>.',\n\t},\n\t'@runtime': {\n\t\ttest: /^@runtime(?:\\.[A-Za-z][A-Za-z0-9_]*)?$/,\n\t\treplacement: null,\n\t\tremoval: '2026-10-01',\n\t\tnote: 'Single-app invention. No canonical equivalent — resolve via @workspace.<key> / @route.<param> or remove.',\n\t},\n})\n\n// --- Runtime RegExps (the resolvers import these — one source of truth) -----\n\n/** `@resolve:<key>` — full match with a captured key group. */\nexport const RESOLVE_TOKEN_RE = /^@resolve:([a-z][a-z0-9_-]*)$/\n\n/** `@route.<param>` — full match with a captured param group. */\nexport const ROUTE_TOKEN_RE = /^@route\\.([A-Za-z][A-Za-z0-9_-]*)$/\n\n/** `@today±Nd` — full match with a captured signed-day-delta group. */\nexport const TODAY_DELTA_RE = /^@today([+-]\\d+)d$/\n\n/** Compiled per-context matchers (anchored, from SENTINEL_TOKEN_PATTERNS). */\nconst CONTEXT_RE = Object.freeze(Object.fromEntries(Object.entries(SENTINEL_TOKEN_PATTERNS).map(([ctx, pat]) => [ctx, new RegExp(pat)])))\n\n/**\n * True when `value` is a string that begins with `@` (i.e. shaped like a\n * sentinel, regardless of membership).\n *\n * @param {unknown} value Candidate.\n * @return {boolean}\n */\nexport function looksLikeSentinel(value) {\n\treturn typeof value === 'string' && value.charAt(0) === '@'\n}\n\n/**\n * The canonical context a token belongs to, or `null` if it is not a member of\n * any canonical context. Deprecated tokens return `null` here (they are not a\n * canonical context) — use {@link matchDeprecation} to detect those.\n *\n * @param {string} token The `@`-prefixed token.\n * @return {(string|null)} A member of {@link SENTINEL_CONTEXTS} or null.\n */\nexport function contextOf(token) {\n\tif (typeof token !== 'string') {\n\t\treturn null\n\t}\n\tfor (const ctx of SENTINEL_CONTEXTS) {\n\t\tif (CONTEXT_RE[ctx].test(token)) {\n\t\t\treturn ctx\n\t\t}\n\t}\n\treturn null\n}\n\n/**\n * True when `token` is a member of the closed CANONICAL vocabulary (any\n * context). Deprecated tokens are NOT canonical (return false).\n *\n * @param {string} token The `@`-prefixed token.\n * @return {boolean}\n */\nexport function isKnownToken(token) {\n\treturn contextOf(token) !== null\n}\n\n/**\n * The deprecation entry matching `token`, or `null`. A deprecated token is\n * accepted by the schema (its pattern is in the union) but the gate + resolver\n * flag it.\n *\n * @param {string} token The `@`-prefixed token.\n * @return {({key: string, replacement: (string|null), removal: string, note: string}|null)}\n */\nexport function matchDeprecation(token) {\n\tif (typeof token !== 'string') {\n\t\treturn null\n\t}\n\tfor (const [key, entry] of Object.entries(SENTINEL_DEPRECATIONS)) {\n\t\tif (entry.test.test(token)) {\n\t\t\treturn { key, replacement: entry.replacement, removal: entry.removal, note: entry.note }\n\t\t}\n\t}\n\treturn null\n}\n\n/**\n * Classify a token for gate / dispatcher consumption.\n *\n * @param {string} token The `@`-prefixed token.\n * @return {{status: ('known'|'deprecated'|'unknown'), context: (string|null), deprecation: (object|null)}}\n */\nexport function classifyToken(token) {\n\tconst deprecation = matchDeprecation(token)\n\tif (deprecation) {\n\t\treturn { status: 'deprecated', context: null, deprecation }\n\t}\n\tconst context = contextOf(token)\n\tif (context) {\n\t\treturn { status: 'known', context, deprecation: null }\n\t}\n\treturn { status: 'unknown', context: null, deprecation: null }\n}\n\n/**\n * Scan a manifest's `pages[].config` and widget `filter`/`dataSource` string\n * leaves for `@`-prefixed values and bucket them. The reusable CORE of the\n * hydra token-vocabulary gate — the gate wraps this (diff-scope + exit code)\n * and MUST import it rather than hardcode the vocabulary.\n *\n * Only `@`-prefixed strings under `pages[]` are considered (router/registry\n * invariants elsewhere are out of scope, matching the schema `$def` placement).\n *\n * @param {object} manifest A parsed manifest object.\n * @return {{unknown: Array<{token: string, path: string}>,\n * deprecated: Array<{token: string, path: string, replacement: (string|null), removal: string}>,\n * known: number}}\n */\nexport function scanManifestTokens(manifest) {\n\tconst unknown = []\n\tconst deprecated = []\n\tlet known = 0\n\n\tconst visit = (node, path) => {\n\t\tif (typeof node === 'string') {\n\t\t\tif (!looksLikeSentinel(node)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst c = classifyToken(node)\n\t\t\tif (c.status === 'deprecated') {\n\t\t\t\tdeprecated.push({ token: node, path, replacement: c.deprecation.replacement, removal: c.deprecation.removal })\n\t\t\t} else if (c.status === 'unknown') {\n\t\t\t\tunknown.push({ token: node, path })\n\t\t\t} else {\n\t\t\t\tknown += 1\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tif (Array.isArray(node)) {\n\t\t\tnode.forEach((item, i) => visit(item, `${path}[${i}]`))\n\t\t\treturn\n\t\t}\n\t\tif (node && typeof node === 'object') {\n\t\t\tfor (const [k, v] of Object.entries(node)) {\n\t\t\t\tvisit(v, `${path}.${k}`)\n\t\t\t}\n\t\t}\n\t}\n\n\tconst pages = manifest && Array.isArray(manifest.pages) ? manifest.pages : []\n\tpages.forEach((page, i) => {\n\t\tif (!page || typeof page !== 'object') {\n\t\t\treturn\n\t\t}\n\t\tif (page.config && typeof page.config === 'object') {\n\t\t\tvisit(page.config, `pages[${i}].config`)\n\t\t}\n\t\tif (Array.isArray(page.widgets)) {\n\t\t\tvisit(page.widgets, `pages[${i}].widgets`)\n\t\t}\n\t})\n\n\treturn { unknown, deprecated, known }\n}\n"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,uBAAuB,GAAG,MAAM,CAAC,MAAM,CAAC;AACrD,CAAC,MAAM,EAAE,2LAA2L;AACpM,CAAC,MAAM,EAAE,oEAAoE;AAC7E,CAAC,MAAM,EAAE,+CAA+C;AACxD;AACA,CAAC,IAAI,EAAE,wDAAwD;AAC/D,CAAC,SAAS,EAAE,0CAA0C;AACtD,CAAC,KAAK,EAAE,mCAAmC;AAC3C,CAAC,WAAW,EAAE,iFAAiF;AAC/F;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,WAAW,EAAE,UAAU;AACxB;AACA,CAAC,MAAM,EAAE,mCAAmC;AAC5C;AACA;AACA,CAAC,GAAG,EAAE,kCAAkC;AACxC;AACA;AACA,CAAC,OAAO,EAAE,qCAAqC;AAC/C;AACA;AACA,CAAC,OAAO,EAAE,qCAAqC;AAC/C;AACA;AACA,CAAC,MAAM,EAAE,qCAAqC;AAC9C;AACA;AACA;AACA,CAAC,UAAU,EAAE,8FAA8F;AAC3G,CAAC,EAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC;AAC/C,CAAC,QAAQ;AACT,CAAC,QAAQ;AACT,CAAC,QAAQ;AACT,CAAC,WAAW;AACZ,CAAC,OAAO;AACR,CAAC,aAAa;AACd,CAAC,aAAa;AACd,CAAC,QAAQ;AACT,CAAC,KAAK;AACN,CAAC,SAAS;AACV,CAAC,SAAS;AACV,CAAC,QAAQ;AACT,CAAC,EAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA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"}
1
+ {"version":3,"file":"sentinelTokens.js","sources":["../../../src/utils/sentinelTokens.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * Closed, context-partitioned manifest **sentinel-token vocabulary** — the\n * single source of truth for every `@`-prefixed dynamic value a manifest may\n * carry under `pages[].config` or a widget `filter`/`dataSource`.\n *\n * Before this module the token surface was scattered across four resolvers\n * (`resolveManifestSentinels`, `resolveFilterTokens`, `resolveRouteSentinels`,\n * `fetchAggregate`) plus ad-hoc single-app inventions (`@currentFiscalYear`,\n * `@page.*`, `@runtime`). This module declares the vocabulary ONCE so:\n *\n * 1. the JSON-Schema `$defs` in `app-manifest-v2.schema.json` reject an\n * out-of-vocabulary token (the pattern strings here are the exact strings\n * mirrored into the schema — a unit test enforces byte-equality);\n * 2. the shared resolver dispatch (`resolveManifestTokens.js`) and the four\n * resolvers import their token patterns from here rather than re-declaring\n * them, so the runtime and the schema cannot drift;\n * 3. a hydra manifest gate can `scanManifestTokens()` an app and FAIL an\n * unknown token / WARN a deprecated one, reusing this export (no hardcoded\n * copy).\n *\n * ## Context partitions\n *\n * A token is valid only in the context whose resolver runs on it:\n *\n * - **filter** — `resolveFilterTokens`, resolved at fetch time:\n * `@me`, `@myGroups`, `@myTeam`, `@now`, `@today`, `@today±Nd`, `@monthStart`, `@monthEnd`, `@nextMonthStart`,\n * `@quarterStart`, `@yearStart`.\n * - **config** — `IAppConfig`-sourced: `@resolve:<key>`, `@config.<key>`\n * (trailing `?` marks optional).\n * - **object** — detail-page object context: `@objectId`,\n * `@object.<field>`.\n * - **workspace** — page-level workspace state: `@workspace.<key>`\n * (trailing `?` optional).\n * - **route** — `resolveRouteSentinels`: `@route.<param>`.\n * - **declarative** — OpenRegister direction, resolved server-side:\n * `@self.<field>` (the object's own field in a\n * cross-object calc), `@ref:<path>`, `@aggregate:<expr>`.\n * - **visibleWhen** — the shared `visibleWhen` predicate's `source`-mode\n * collection-total marker, resolved client-side by\n * `evaluateVisibleWhen` (`utils/visibleWhen.js`):\n * `@total` (a `field: \"@total\"` — or omitted `field` —\n * compares the collection total rather than the first\n * result). Added for manifest-form-logic:\n * `config.fields[].visibleWhen` is the first\n * `visibleWhen` reachable through the\n * sentinelGuardedValue-guarded `pages[].config` subtree.\n *\n * `@ref`/`@aggregate` are first-class members even though currently unused\n * fleet-wide — they are the OR-declarative direction and belong in the closed\n * vocabulary so a future adopter validates rather than inventing a variant.\n *\n * @module utils/sentinelTokens\n */\n\n/**\n * Pattern STRINGS, one per context — the canonical source mirrored verbatim\n * into `app-manifest-v2.schema.json`'s `$defs`. A unit test asserts each schema\n * `$def`'s `pattern` equals the string here, so the two cannot drift.\n *\n * NOTE: these are JS string literals; a `\\\\.` here is the two-character\n * sequence `\\.` at runtime, which is exactly what the JSON schema stores after\n * its own `\\\\.` is parsed. Compare PARSED values, never raw source.\n *\n * @type {Readonly<Record<string, string>>}\n */\nexport const SENTINEL_TOKEN_PATTERNS = Object.freeze({\n\tfilter: '^@(?:me(?:\\\\.(?:displayName|email))?|myGroups|myTeam|now|today|monthStart|monthEnd|nextMonthStart|quarterStart|yearStart)$|^@today[+-](?:[0-9]+|\\\\{@config\\\\.[A-Za-z][A-Za-z0-9_.]*\\\\})d$',\n\tconfig: '^@resolve:[a-z][a-z0-9_-]*$|^@config\\\\.[A-Za-z][A-Za-z0-9_.]*\\\\??$',\n\tobject: '^@objectId$|^@object\\\\.[A-Za-z][A-Za-z0-9_]*$',\n\t// party-actions: a record field made a link (`@object.phone|tel`, `|mailto`, `|geo`).\n\tlink: '^@object\\\\.[A-Za-z][A-Za-z0-9_]*\\\\|(?:tel|mailto|geo)$',\n\tworkspace: '^@workspace\\\\.[A-Za-z][A-Za-z0-9_]*\\\\??$',\n\troute: '^@route\\\\.[A-Za-z][A-Za-z0-9_-]*$',\n\tdeclarative: '^@self\\\\.[A-Za-z][A-Za-z0-9_]*$|^@ref:[A-Za-z][A-Za-z0-9_./-]*$|^@aggregate:.+$',\n\t// manifest-form-logic: the shared visibleWhen predicate's source-mode\n\t// collection-total marker (`field: \"@total\"`), resolved client-side by\n\t// evaluateVisibleWhen — not one of the four IAppConfig/OpenRegister\n\t// resolvers, but a real pre-existing convention (already documented on\n\t// $defs.visibleWhen and the banner widget) now reachable through the\n\t// sentinelGuardedValue-guarded pages[].config subtree for the first time\n\t// via config.fields[].visibleWhen.\n\tvisibleWhen: '^@total$',\n\t// form-live-values: another answer in the same form, read by a field's `assign` rule.\n\tanswer: '^@answer\\\\.[A-Za-z][A-Za-z0-9_]*$',\n\t// A field of the row a row action is run on (`@row.<field>`, dot path), read by the\n\t// field-list widget's `rowActions` request URL and payload.\n\trow: '^@row\\\\.[A-Za-z][A-Za-z0-9_.@]*$',\n\t// A field of the record a start-here attention card names (`@subject.<field>`, dot path),\n\t// read by the banner widget's action routes.\n\tsubject: '^@subject\\\\.[A-Za-z][A-Za-z0-9_.]*$',\n\t// A record a detail page reads beside the loaded one (`visibilityContext`), read by a\n\t// grid widget's or a tab's `visibleWhen` as `@context.<name>.<field>` (dot path).\n\tcontext: '^@context\\\\.[A-Za-z][A-Za-z0-9_.]*$',\n\t// A field of the object a facts widget shows (`@source.<field>`, dot path), read by a\n\t// fact row's `route` params.\n\tsource: '^@source\\\\.[A-Za-z][A-Za-z0-9_.@]*$',\n\t// Deprecated-but-not-yet-removed tokens. Kept in the schema union so\n\t// deployed manifests still validate during the migration window; the gate\n\t// downgrades them to a WARN (see SENTINEL_DEPRECATIONS).\n\tdeprecated: '^@currentFiscalYear$|^@page\\\\.[A-Za-z][A-Za-z0-9_]*$|^@runtime(?:\\\\.[A-Za-z][A-Za-z0-9_]*)?$',\n})\n\n/**\n * The nine canonical context names (excludes `deprecated`, which is a\n * transitional overlay, not a resolution context).\n *\n * @type {string[]}\n */\nexport const SENTINEL_CONTEXTS = Object.freeze([\n\t'filter',\n\t'config',\n\t'object',\n\t'workspace',\n\t'route',\n\t'declarative',\n\t'visibleWhen',\n\t'answer',\n\t'row',\n\t'subject',\n\t'context',\n\t'source',\n])\n\n/**\n * Human-readable vocabulary: members + context + owning resolver + parameter\n * grammar. Documentation-facing (feeds audit item 16 schema-generated docs);\n * the machine-checkable truth is {@link SENTINEL_TOKEN_PATTERNS}.\n *\n * @type {Readonly<Record<string, {resolver: string, description: string, members: string[]}>>}\n */\nexport const SENTINEL_VOCABULARY = Object.freeze({\n\tfilter: {\n\t\tresolver: 'resolveFilterTokens',\n\t\tdescription: 'Relative fetch-time tokens (current user, the current user\\'s groups as an IN list, relative dates).',\n\t\tmembers: ['@me', '@me.displayName', '@me.email', '@myGroups', '@myTeam', '@now', '@today', '@today±Nd', '@monthStart', '@monthEnd', '@nextMonthStart', '@quarterStart', '@yearStart'],\n\t},\n\tconfig: {\n\t\tresolver: 'resolveManifestSentinels / resolveFilterTokens',\n\t\tdescription: 'IAppConfig-sourced values. `@resolve:<key>` at manifest-load time; `@config.<key>` (trailing `?` optional) at fetch time.',\n\t\tmembers: ['@resolve:<key>', '@config.<key>', '@config.<key>?'],\n\t},\n\tobject: {\n\t\tresolver: 'resolveFilterTokens',\n\t\tdescription: 'Detail-page object context. Resolve only when a `{ objectId, object }` ctx is supplied.',\n\t\tmembers: ['@objectId', '@object.<field>'],\n\t},\n\tlink: {\n\t\tresolver: 'CnPartyActionsWidget',\n\t\tdescription: 'A record field made a tel:, mailto: or geo: link, for an action target; the action is left out when the value makes no link.',\n\t\tmembers: ['@object.<field>|tel', '@object.<field>|mailto', '@object.<field>|geo'],\n\t},\n\tworkspace: {\n\t\tresolver: 'resolveFilterTokens',\n\t\tdescription: 'Page-level workspace state (e.g. a selected client / period). Trailing `?` marks optional (drop when unset).',\n\t\tmembers: ['@workspace.<key>', '@workspace.<key>?'],\n\t},\n\troute: {\n\t\tresolver: 'resolveRouteSentinels',\n\t\tdescription: 'vue-router param substitution at render time.',\n\t\tmembers: ['@route.<param>'],\n\t},\n\tdeclarative: {\n\t\tresolver: 'fetchAggregate (OpenRegister server-side)',\n\t\tdescription: 'OpenRegister declarative direction — resolved server-side. `@self.<field>` is the object\\'s own field in a cross-object calc; `@ref`/`@aggregate` are reserved (currently unused fleet-wide).',\n\t\tmembers: ['@self.<field>', '@ref:<path>', '@aggregate:<expr>'],\n\t},\n\tvisibleWhen: {\n\t\tresolver: 'evaluateVisibleWhen (utils/visibleWhen.js)',\n\t\tdescription: 'The shared visibleWhen predicate\\'s source-mode collection-total marker. `field: \"@total\"` (or an omitted `field`) compares the collection total instead of the first result.',\n\t\tmembers: ['@total'],\n\t},\n\tanswer: {\n\t\tresolver: 'resolveAssignValue (utils/formAssign.js)',\n\t\tdescription: 'Another answer in the same form, read by a field\\'s `assign` rule.',\n\t\tmembers: ['@answer.<field>'],\n\t},\n\trow: {\n\t\tresolver: 'CnFieldListWidget (rowActions request url and payload)',\n\t\tdescription: 'A field of the row a row action runs on, read by the field-list widget when it sends the action\\'s request. Dot paths are allowed (`@row.owner.id`).',\n\t\tmembers: ['@row.<field>'],\n\t},\n\tsubject: {\n\t\tresolver: 'CnBannerWidget (action route params and query)',\n\t\tdescription: 'A field of the record an attention card names (the first row of its ordered `visibleWhen` source query), read when the card builds an action\\'s route. Dot paths are allowed (`@subject.owner.id`).',\n\t\tmembers: ['@subject.<field>'],\n\t},\n\tcontext: {\n\t\tresolver: 'CnDetailPage visibilityContext (detailWidgetVisibility), read by a grid widget\\'s or a tab\\'s visibleWhen, and by a widget\\'s props (CnDetailWidgetHost)',\n\t\tdescription: 'A record the detail page reads beside the loaded one, named in `config.visibilityContext` (a case\\'s case type). A `visibleWhen` field reads it as `@context.<name>.<field>`, dot paths allowed (`@context.caseType.category`).',\n\t\tmembers: ['@context.<name>.<field>'],\n\t},\n\tsource: {\n\t\tresolver: 'CnFactsWidget (a fact row\\'s route params)',\n\t\tdescription: 'A field of the object a facts widget shows, read when a fact row builds its link. Dot paths are allowed (`@source.caseType.parentCaseType`).',\n\t\tmembers: ['@source.<field>'],\n\t},\n})\n\n/**\n * Machine-readable deprecation map: single-app inventions → canonical\n * replacement (or `null` for removal) + removal date. The shared resolver still\n * resolves a deprecated token during the window (emitting a one-time warn); the\n * gate WARNs (not fails) until `removal`. Each entry carries a `test` RegExp so\n * a parameterised deprecated token (`@page.period`) matches its family.\n *\n * @type {Readonly<Record<string, {test: RegExp, replacement: (string|null), removal: string, note: string}>>}\n */\nexport const SENTINEL_DEPRECATIONS = Object.freeze({\n\t'@currentFiscalYear': {\n\t\ttest: /^@currentFiscalYear$/,\n\t\treplacement: '@config.fiscalYear',\n\t\tremoval: '2026-10-01',\n\t\tnote: 'Single-app invention (shillinq). Source the fiscal year from IAppConfig instead of the calendar year.',\n\t},\n\t'@page.<key>': {\n\t\ttest: /^@page\\.[A-Za-z][A-Za-z0-9_]*$/,\n\t\treplacement: '@workspace.<key>',\n\t\tremoval: '2026-10-01',\n\t\tnote: 'Single-app invention (pipelinq). Page-context state is the workspace context; use @workspace.<key>.',\n\t},\n\t'@runtime': {\n\t\ttest: /^@runtime(?:\\.[A-Za-z][A-Za-z0-9_]*)?$/,\n\t\treplacement: null,\n\t\tremoval: '2026-10-01',\n\t\tnote: 'Single-app invention. No canonical equivalent — resolve via @workspace.<key> / @route.<param> or remove.',\n\t},\n})\n\n// --- Runtime RegExps (the resolvers import these — one source of truth) -----\n\n/** `@resolve:<key>` — full match with a captured key group. */\nexport const RESOLVE_TOKEN_RE = /^@resolve:([a-z][a-z0-9_-]*)$/\n\n/** `@route.<param>` — full match with a captured param group. */\nexport const ROUTE_TOKEN_RE = /^@route\\.([A-Za-z][A-Za-z0-9_-]*)$/\n\n/** `@today±Nd` — full match with a captured signed-day-delta group. */\nexport const TODAY_DELTA_RE = /^@today([+-]\\d+)d$/\n\n/** Compiled per-context matchers (anchored, from SENTINEL_TOKEN_PATTERNS). */\nconst CONTEXT_RE = Object.freeze(Object.fromEntries(Object.entries(SENTINEL_TOKEN_PATTERNS).map(([ctx, pat]) => [ctx, new RegExp(pat)])))\n\n/**\n * True when `value` is a string that begins with `@` (i.e. shaped like a\n * sentinel, regardless of membership).\n *\n * @param {unknown} value Candidate.\n * @return {boolean}\n */\nexport function looksLikeSentinel(value) {\n\treturn typeof value === 'string' && value.charAt(0) === '@'\n}\n\n/**\n * The canonical context a token belongs to, or `null` if it is not a member of\n * any canonical context. Deprecated tokens return `null` here (they are not a\n * canonical context) — use {@link matchDeprecation} to detect those.\n *\n * @param {string} token The `@`-prefixed token.\n * @return {(string|null)} A member of {@link SENTINEL_CONTEXTS} or null.\n */\nexport function contextOf(token) {\n\tif (typeof token !== 'string') {\n\t\treturn null\n\t}\n\tfor (const ctx of SENTINEL_CONTEXTS) {\n\t\tif (CONTEXT_RE[ctx].test(token)) {\n\t\t\treturn ctx\n\t\t}\n\t}\n\treturn null\n}\n\n/**\n * True when `token` is a member of the closed CANONICAL vocabulary (any\n * context). Deprecated tokens are NOT canonical (return false).\n *\n * @param {string} token The `@`-prefixed token.\n * @return {boolean}\n */\nexport function isKnownToken(token) {\n\treturn contextOf(token) !== null\n}\n\n/**\n * The deprecation entry matching `token`, or `null`. A deprecated token is\n * accepted by the schema (its pattern is in the union) but the gate + resolver\n * flag it.\n *\n * @param {string} token The `@`-prefixed token.\n * @return {({key: string, replacement: (string|null), removal: string, note: string}|null)}\n */\nexport function matchDeprecation(token) {\n\tif (typeof token !== 'string') {\n\t\treturn null\n\t}\n\tfor (const [key, entry] of Object.entries(SENTINEL_DEPRECATIONS)) {\n\t\tif (entry.test.test(token)) {\n\t\t\treturn { key, replacement: entry.replacement, removal: entry.removal, note: entry.note }\n\t\t}\n\t}\n\treturn null\n}\n\n/**\n * Classify a token for gate / dispatcher consumption.\n *\n * @param {string} token The `@`-prefixed token.\n * @return {{status: ('known'|'deprecated'|'unknown'), context: (string|null), deprecation: (object|null)}}\n */\nexport function classifyToken(token) {\n\tconst deprecation = matchDeprecation(token)\n\tif (deprecation) {\n\t\treturn { status: 'deprecated', context: null, deprecation }\n\t}\n\tconst context = contextOf(token)\n\tif (context) {\n\t\treturn { status: 'known', context, deprecation: null }\n\t}\n\treturn { status: 'unknown', context: null, deprecation: null }\n}\n\n/**\n * Scan a manifest's `pages[].config` and widget `filter`/`dataSource` string\n * leaves for `@`-prefixed values and bucket them. The reusable CORE of the\n * hydra token-vocabulary gate — the gate wraps this (diff-scope + exit code)\n * and MUST import it rather than hardcode the vocabulary.\n *\n * Only `@`-prefixed strings under `pages[]` are considered (router/registry\n * invariants elsewhere are out of scope, matching the schema `$def` placement).\n *\n * @param {object} manifest A parsed manifest object.\n * @return {{unknown: Array<{token: string, path: string}>,\n * deprecated: Array<{token: string, path: string, replacement: (string|null), removal: string}>,\n * known: number}}\n */\nexport function scanManifestTokens(manifest) {\n\tconst unknown = []\n\tconst deprecated = []\n\tlet known = 0\n\n\tconst visit = (node, path) => {\n\t\tif (typeof node === 'string') {\n\t\t\tif (!looksLikeSentinel(node)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst c = classifyToken(node)\n\t\t\tif (c.status === 'deprecated') {\n\t\t\t\tdeprecated.push({ token: node, path, replacement: c.deprecation.replacement, removal: c.deprecation.removal })\n\t\t\t} else if (c.status === 'unknown') {\n\t\t\t\tunknown.push({ token: node, path })\n\t\t\t} else {\n\t\t\t\tknown += 1\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tif (Array.isArray(node)) {\n\t\t\tnode.forEach((item, i) => visit(item, `${path}[${i}]`))\n\t\t\treturn\n\t\t}\n\t\tif (node && typeof node === 'object') {\n\t\t\tfor (const [k, v] of Object.entries(node)) {\n\t\t\t\tvisit(v, `${path}.${k}`)\n\t\t\t}\n\t\t}\n\t}\n\n\tconst pages = manifest && Array.isArray(manifest.pages) ? manifest.pages : []\n\tpages.forEach((page, i) => {\n\t\tif (!page || typeof page !== 'object') {\n\t\t\treturn\n\t\t}\n\t\tif (page.config && typeof page.config === 'object') {\n\t\t\tvisit(page.config, `pages[${i}].config`)\n\t\t}\n\t\tif (Array.isArray(page.widgets)) {\n\t\t\tvisit(page.widgets, `pages[${i}].widgets`)\n\t\t}\n\t})\n\n\treturn { unknown, deprecated, known }\n}\n"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,uBAAuB,GAAG,MAAM,CAAC,MAAM,CAAC;AACrD,CAAC,MAAM,EAAE,2LAA2L;AACpM,CAAC,MAAM,EAAE,oEAAoE;AAC7E,CAAC,MAAM,EAAE,+CAA+C;AACxD;AACA,CAAC,IAAI,EAAE,wDAAwD;AAC/D,CAAC,SAAS,EAAE,0CAA0C;AACtD,CAAC,KAAK,EAAE,mCAAmC;AAC3C,CAAC,WAAW,EAAE,iFAAiF;AAC/F;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,WAAW,EAAE,UAAU;AACxB;AACA,CAAC,MAAM,EAAE,mCAAmC;AAC5C;AACA;AACA,CAAC,GAAG,EAAE,kCAAkC;AACxC;AACA;AACA,CAAC,OAAO,EAAE,qCAAqC;AAC/C;AACA;AACA,CAAC,OAAO,EAAE,qCAAqC;AAC/C;AACA;AACA,CAAC,MAAM,EAAE,qCAAqC;AAC9C;AACA;AACA;AACA,CAAC,UAAU,EAAE,8FAA8F;AAC3G,CAAC,EAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC;AAC/C,CAAC,QAAQ;AACT,CAAC,QAAQ;AACT,CAAC,QAAQ;AACT,CAAC,WAAW;AACZ,CAAC,OAAO;AACR,CAAC,aAAa;AACd,CAAC,aAAa;AACd,CAAC,QAAQ;AACT,CAAC,KAAK;AACN,CAAC,SAAS;AACV,CAAC,SAAS;AACV,CAAC,QAAQ;AACT,CAAC,EAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA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"}