@conduction/nextcloud-vue 2.76.0 → 2.77.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.
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js +18 -3
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js +49 -3
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +42 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +228 -203
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue.js +9 -0
- package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue.js.map +1 -0
- package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue2.js +50 -0
- package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue2.js.map +1 -0
- package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue3.js +13 -0
- package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue3.js.map +1 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +41 -4
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +90 -51
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +16 -28
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +12 -24
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnFavouriteToggle/CnFavouriteToggle.vue2.js +7 -2
- package/dist/esm/components/CnFavouriteToggle/CnFavouriteToggle.vue2.js.map +1 -1
- package/dist/esm/components/CnFavouriteToggle/CnFavouriteToggle.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +114 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +115 -62
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js +89 -7
- package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js.map +1 -1
- package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue3.js +62 -30
- package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +98 -13
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +13 -9
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js +199 -7
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js +155 -119
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +6 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +4 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +13 -0
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
- package/dist/esm/composables/useListView.js +4 -0
- package/dist/esm/composables/useListView.js.map +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +25 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +25 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +288 -74
- package/dist/esm/store/plugins/interactions.js +20 -10
- package/dist/esm/store/plugins/interactions.js.map +1 -1
- package/dist/esm/store/useObjectStore.js +17 -0
- package/dist/esm/store/useObjectStore.js.map +1 -1
- package/dist/esm/utils/builtInFormatters.js +15 -7
- package/dist/esm/utils/builtInFormatters.js.map +1 -1
- package/dist/esm/utils/groupAutocomplete.js +63 -1
- package/dist/esm/utils/groupAutocomplete.js.map +1 -1
- package/dist/esm/utils/lensAvailability.js +90 -0
- package/dist/esm/utils/lensAvailability.js.map +1 -0
- package/dist/esm/utils/personalLenses.js +13 -6
- package/dist/esm/utils/personalLenses.js.map +1 -1
- package/dist/esm/utils/recordInteractions.js +31 -13
- package/dist/esm/utils/recordInteractions.js.map +1 -1
- package/dist/esm/utils/resolveFilterTokens.js +46 -3
- package/dist/esm/utils/resolveFilterTokens.js.map +1 -1
- package/dist/esm/utils/schema.js +1 -1
- package/dist/esm/utils/schema.js.map +1 -1
- package/dist/esm/utils/sentinelTokens.js +4 -4
- package/dist/esm/utils/sentinelTokens.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/widgetVisibility.js +46 -1
- package/dist/esm/utils/widgetVisibility.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +3873 -2674
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +288 -74
- package/l10n/en.json +25 -1
- package/l10n/nl.json +25 -1
- package/package.json +1 -1
- package/src/components/CnAppNav/CnAppNav.vue +44 -5
- package/src/components/CnCellRenderer/CnCellRenderer.vue +56 -1
- package/src/components/CnCellRenderer/CnGroupNameCell.vue +61 -0
- package/src/components/CnDataTable/CnDataTable.md +9 -0
- package/src/components/CnDataTable/CnDataTable.vue +80 -20
- package/src/components/CnDetailPage/CnDetailPage.vue +10 -27
- package/src/components/CnFavouriteToggle/CnFavouriteToggle.vue +7 -2
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +204 -5
- package/src/components/CnFollowToggle/CnFollowToggle.vue +118 -13
- package/src/components/CnIndexPage/CnIndexPage.md +36 -0
- package/src/components/CnIndexPage/CnIndexPage.vue +106 -19
- package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +226 -2
- package/src/components/CnObjectSidebar/CnFilesTab.vue +9 -0
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +13 -0
- package/src/composables/useListView.js +4 -0
- package/src/css/look-board-detail.css +40 -2
- package/src/css/table.css +82 -17
- package/src/index.js +2 -1
- package/src/schemas/app-manifest-v2.schema.json +11 -7
- package/src/store/plugins/interactions.js +20 -10
- package/src/store/useObjectStore.js +17 -0
- package/src/utils/builtInFormatters.js +15 -7
- package/src/utils/groupAutocomplete.js +75 -0
- package/src/utils/index.js +1 -1
- package/src/utils/lensAvailability.js +86 -0
- package/src/utils/personalLenses.js +13 -6
- package/src/utils/recordInteractions.js +31 -13
- package/src/utils/resolveFilterTokens.js +45 -2
- package/src/utils/schema.js +1 -1
- package/src/utils/sentinelTokens.js +4 -4
- package/src/utils/validateManifestV2.compiled.js +2 -2
- package/src/utils/widgetVisibility.js +45 -0
|
@@ -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`, `@now`, `@today`, `@today±Nd`, `@monthStart`,\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))?|now|today|monthStart|quarterStart|yearStart)$|^@today[+-][0-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\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// 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 eight 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])\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 / relative dates).',\n\t\tmembers: ['@me', '@me.displayName', '@me.email', '@now', '@today', '@today±Nd', '@monthStart', '@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\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})\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":"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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`, `@now`, `@today`, `@today±Nd`, `@monthStart`,\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|now|today|monthStart|quarterStart|yearStart)$|^@today[+-][0-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\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// 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 eight 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])\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', '@now', '@today', '@today±Nd', '@monthStart', '@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\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})\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,iHAAiH;AAC1H,CAAC,MAAM,EAAE,oEAAoE;AAC7E,CAAC,MAAM,EAAE,+CAA+C;AACxD,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;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,EAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,mBAAmB,GAAG,MAAM,CAAC,MAAM,CAAC;AACjD,CAAC,MAAM,EAAE;AACT,EAAE,QAAQ,EAAE,qBAAqB;AACjC,EAAE,WAAW,EAAE,sGAAsG;AACrH,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,eAAe,EAAE,YAAY,CAAC;AAC5I,EAAE;AACF,CAAC,MAAM,EAAE;AACT,EAAE,QAAQ,EAAE,gDAAgD;AAC5D,EAAE,WAAW,EAAE,2HAA2H;AAC1I,EAAE,OAAO,EAAE,CAAC,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,CAAC;AAChE,EAAE;AACF,CAAC,MAAM,EAAE;AACT,EAAE,QAAQ,EAAE,qBAAqB;AACjC,EAAE,WAAW,EAAE,yFAAyF;AACxG,EAAE,OAAO,EAAE,CAAC,WAAW,EAAE,iBAAiB,CAAC;AAC3C,EAAE;AACF,CAAC,SAAS,EAAE;AACZ,EAAE,QAAQ,EAAE,qBAAqB;AACjC,EAAE,WAAW,EAAE,8GAA8G;AAC7H,EAAE,OAAO,EAAE,CAAC,kBAAkB,EAAE,mBAAmB,CAAC;AACpD,EAAE;AACF,CAAC,KAAK,EAAE;AACR,EAAE,QAAQ,EAAE,uBAAuB;AACnC,EAAE,WAAW,EAAE,+CAA+C;AAC9D,EAAE,OAAO,EAAE,CAAC,gBAAgB,CAAC;AAC7B,EAAE;AACF,CAAC,WAAW,EAAE;AACd,EAAE,QAAQ,EAAE,2CAA2C;AACvD,EAAE,WAAW,EAAE,+LAA+L;AAC9M,EAAE,OAAO,EAAE,CAAC,eAAe,EAAE,aAAa,EAAE,mBAAmB,CAAC;AAChE,EAAE;AACF,CAAC,WAAW,EAAE;AACd,EAAE,QAAQ,EAAE,4CAA4C;AACxD,EAAE,WAAW,EAAE,+KAA+K;AAC9L,EAAE,OAAO,EAAE,CAAC,QAAQ,CAAC;AACrB,EAAE;AACF,CAAC,MAAM,EAAE;AACT,EAAE,QAAQ,EAAE,0CAA0C;AACtD,EAAE,WAAW,EAAE,oEAAoE;AACnF,EAAE,OAAO,EAAE,CAAC,iBAAiB,CAAC;AAC9B,EAAE;AACF,CAAC,EAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,qBAAqB,GAAG,MAAM,CAAC,MAAM,CAAC;AACnD,CAAC,oBAAoB,EAAE;AACvB,EAAE,IAAI,EAAE,sBAAsB;AAC9B,EAAE,WAAW,EAAE,oBAAoB;AACnC,EAAE,OAAO,EAAE,YAAY;AACvB,EAAE,IAAI,EAAE,uGAAuG;AAC/G,EAAE;AACF,CAAC,aAAa,EAAE;AAChB,EAAE,IAAI,EAAE,gCAAgC;AACxC,EAAE,WAAW,EAAE,kBAAkB;AACjC,EAAE,OAAO,EAAE,YAAY;AACvB,EAAE,IAAI,EAAE,qGAAqG;AAC7G,EAAE;AACF,CAAC,UAAU,EAAE;AACb,EAAE,IAAI,EAAE,wCAAwC;AAChD,EAAE,WAAW,EAAE,IAAI;AACnB,EAAE,OAAO,EAAE,YAAY;AACvB,EAAE,IAAI,EAAE,0GAA0G;AAClH,EAAE;AACF,CAAC,EAAC;AACF;AACA;AACA;AACA;AACY,MAAC,gBAAgB,GAAG,gCAA+B;AAC/D;AACA;AACY,MAAC,cAAc,GAAG,qCAAoC;AAClE;AACA;AACY,MAAC,cAAc,GAAG,qBAAoB;AAClD;AACA;AACA,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAC;AACzI;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,iBAAiB,CAAC,KAAK,EAAE;AACzC,CAAC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG;AAC5D,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,SAAS,CAAC,KAAK,EAAE;AACjC,CAAC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAChC,EAAE,OAAO,IAAI;AACb,EAAE;AACF,CAAC,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE;AACtC,EAAE,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACnC,GAAG,OAAO,GAAG;AACb,GAAG;AACH,EAAE;AACF,CAAC,OAAO,IAAI;AACZ,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,YAAY,CAAC,KAAK,EAAE;AACpC,CAAC,OAAO,SAAS,CAAC,KAAK,CAAC,KAAK,IAAI;AACjC,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,gBAAgB,CAAC,KAAK,EAAE;AACxC,CAAC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAChC,EAAE,OAAO,IAAI;AACb,EAAE;AACF,CAAC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,EAAE;AACnE,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAC9B,GAAG,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE;AAC3F,GAAG;AACH,EAAE;AACF,CAAC,OAAO,IAAI;AACZ,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,aAAa,CAAC,KAAK,EAAE;AACrC,CAAC,MAAM,WAAW,GAAG,gBAAgB,CAAC,KAAK,EAAC;AAC5C,CAAC,IAAI,WAAW,EAAE;AAClB,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE;AAC7D,EAAE;AACF,CAAC,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,EAAC;AACjC,CAAC,IAAI,OAAO,EAAE;AACd,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE;AACxD,EAAE;AACF,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE;AAC/D,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,kBAAkB,CAAC,QAAQ,EAAE;AAC7C,CAAC,MAAM,OAAO,GAAG,GAAE;AACnB,CAAC,MAAM,UAAU,GAAG,GAAE;AACtB,CAAC,IAAI,KAAK,GAAG,EAAC;AACd;AACA,CAAC,MAAM,KAAK,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK;AAC/B,EAAE,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;AAChC,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE;AACjC,IAAI,MAAM;AACV,IAAI;AACJ,GAAG,MAAM,CAAC,GAAG,aAAa,CAAC,IAAI,EAAC;AAChC,GAAG,IAAI,CAAC,CAAC,MAAM,KAAK,YAAY,EAAE;AAClC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,EAAC;AAClH,IAAI,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE;AACtC,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAC;AACvC,IAAI,MAAM;AACV,IAAI,KAAK,IAAI,EAAC;AACd,IAAI;AACJ,GAAG,MAAM;AACT,GAAG;AACH,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;AAC3B,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAC;AAC1D,GAAG,MAAM;AACT,GAAG;AACH,EAAE,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;AACxC,GAAG,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;AAC9C,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAC;AAC5B,IAAI;AACJ,GAAG;AACH,GAAE;AACF;AACA,CAAC,MAAM,KAAK,GAAG,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,KAAK,GAAG,GAAE;AAC9E,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK;AAC5B,EAAE,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;AACzC,GAAG,MAAM;AACT,GAAG;AACH,EAAE,IAAI,IAAI,CAAC,MAAM,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE;AACtD,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAC;AAC3C,GAAG;AACH,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;AACnC,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,EAAC;AAC7C,GAAG;AACH,EAAE,EAAC;AACH;AACA,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE;AACtC;;;;"}
|