@conduction/nextcloud-vue 2.108.0 → 2.109.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 (155) hide show
  1. package/dist/esm/components/CnAddressSearch/CnAddressSearch.vue.js +10 -0
  2. package/dist/esm/components/CnAddressSearch/CnAddressSearch.vue.js.map +1 -0
  3. package/dist/esm/components/CnAddressSearch/CnAddressSearch.vue2.js +305 -0
  4. package/dist/esm/components/CnAddressSearch/CnAddressSearch.vue2.js.map +1 -0
  5. package/dist/esm/components/CnAddressSearch/CnAddressSearch.vue3.js +38 -0
  6. package/dist/esm/components/CnAddressSearch/CnAddressSearch.vue3.js.map +1 -0
  7. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue.js +10 -0
  8. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue.js.map +1 -0
  9. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js +398 -0
  10. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js.map +1 -0
  11. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js +155 -0
  12. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js.map +1 -0
  13. package/dist/esm/components/CnDecisionListWidget/CnDecisionListWidget.vue.js +9 -0
  14. package/dist/esm/components/CnDecisionListWidget/CnDecisionListWidget.vue.js.map +1 -0
  15. package/dist/esm/components/CnDecisionListWidget/CnDecisionListWidget.vue2.js +281 -0
  16. package/dist/esm/components/CnDecisionListWidget/CnDecisionListWidget.vue2.js.map +1 -0
  17. package/dist/esm/components/CnDecisionListWidget/CnDecisionListWidget.vue3.js +137 -0
  18. package/dist/esm/components/CnDecisionListWidget/CnDecisionListWidget.vue3.js.map +1 -0
  19. package/dist/esm/components/CnDuplicateWarning/CnDuplicateWarning.vue.js +9 -0
  20. package/dist/esm/components/CnDuplicateWarning/CnDuplicateWarning.vue.js.map +1 -0
  21. package/dist/esm/components/CnDuplicateWarning/CnDuplicateWarning.vue2.js +225 -0
  22. package/dist/esm/components/CnDuplicateWarning/CnDuplicateWarning.vue2.js.map +1 -0
  23. package/dist/esm/components/CnDuplicateWarning/CnDuplicateWarning.vue3.js +110 -0
  24. package/dist/esm/components/CnDuplicateWarning/CnDuplicateWarning.vue3.js.map +1 -0
  25. package/dist/esm/components/CnFormDialog/CnFormDialog.vue.js +1 -1
  26. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +19 -3
  27. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
  28. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
  29. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +30 -0
  30. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  31. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +513 -481
  32. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  33. package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue.js +9 -0
  34. package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue.js.map +1 -0
  35. package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue2.js +181 -0
  36. package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue2.js.map +1 -0
  37. package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue3.js +50 -0
  38. package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue3.js.map +1 -0
  39. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue.js +1 -1
  40. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +102 -1
  41. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  42. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +6 -6
  43. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  44. package/dist/esm/components/CnPlanWidget/CnPlanWidget.vue.js +9 -0
  45. package/dist/esm/components/CnPlanWidget/CnPlanWidget.vue.js.map +1 -0
  46. package/dist/esm/components/CnPlanWidget/CnPlanWidget.vue2.js +190 -0
  47. package/dist/esm/components/CnPlanWidget/CnPlanWidget.vue2.js.map +1 -0
  48. package/dist/esm/components/CnPlanWidget/CnPlanWidget.vue3.js +91 -0
  49. package/dist/esm/components/CnPlanWidget/CnPlanWidget.vue3.js.map +1 -0
  50. package/dist/esm/components/CnPlanWidget/CnPlanWidgetRow.vue.js +9 -0
  51. package/dist/esm/components/CnPlanWidget/CnPlanWidgetRow.vue.js.map +1 -0
  52. package/dist/esm/components/CnPlanWidget/CnPlanWidgetRow.vue2.js +64 -0
  53. package/dist/esm/components/CnPlanWidget/CnPlanWidgetRow.vue2.js.map +1 -0
  54. package/dist/esm/components/CnPlanWidget/CnPlanWidgetRow.vue3.js +49 -0
  55. package/dist/esm/components/CnPlanWidget/CnPlanWidgetRow.vue3.js.map +1 -0
  56. package/dist/esm/components/CnRedactionEditor/CnRedactionEditor.vue.js +9 -0
  57. package/dist/esm/components/CnRedactionEditor/CnRedactionEditor.vue.js.map +1 -0
  58. package/dist/esm/components/CnRedactionEditor/CnRedactionEditor.vue2.js +382 -0
  59. package/dist/esm/components/CnRedactionEditor/CnRedactionEditor.vue2.js.map +1 -0
  60. package/dist/esm/components/CnRedactionEditor/CnRedactionEditor.vue3.js +285 -0
  61. package/dist/esm/components/CnRedactionEditor/CnRedactionEditor.vue3.js.map +1 -0
  62. package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue.js +9 -0
  63. package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue.js.map +1 -0
  64. package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue2.js +277 -0
  65. package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue2.js.map +1 -0
  66. package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue3.js +183 -0
  67. package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue3.js.map +1 -0
  68. package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +16 -14
  69. package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
  70. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +53 -22
  71. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  72. package/dist/esm/components/CnWorkQueue/CnWorkQueue.vue.js +9 -0
  73. package/dist/esm/components/CnWorkQueue/CnWorkQueue.vue.js.map +1 -0
  74. package/dist/esm/components/CnWorkQueue/CnWorkQueue.vue2.js +246 -0
  75. package/dist/esm/components/CnWorkQueue/CnWorkQueue.vue2.js.map +1 -0
  76. package/dist/esm/components/CnWorkQueue/CnWorkQueue.vue3.js +197 -0
  77. package/dist/esm/components/CnWorkQueue/CnWorkQueue.vue3.js.map +1 -0
  78. package/dist/esm/index.js +12 -0
  79. package/dist/esm/index.js.map +1 -1
  80. package/dist/esm/l10n/en.json.js +106 -1
  81. package/dist/esm/l10n/en.json.js.map +1 -1
  82. package/dist/esm/l10n/nl.json.js +105 -1
  83. package/dist/esm/l10n/nl.json.js.map +1 -1
  84. package/dist/esm/library-style.js +1 -1
  85. package/dist/esm/nextcloud-vue.css +495 -61
  86. package/dist/esm/utils/actionsDispatcher.js +6 -1
  87. package/dist/esm/utils/actionsDispatcher.js.map +1 -1
  88. package/dist/esm/utils/builtInModals.js +3 -1
  89. package/dist/esm/utils/builtInModals.js.map +1 -1
  90. package/dist/esm/utils/duplicateWarning.js +62 -0
  91. package/dist/esm/utils/duplicateWarning.js.map +1 -0
  92. package/dist/esm/utils/errors.js +4 -0
  93. package/dist/esm/utils/errors.js.map +1 -1
  94. package/dist/esm/utils/libraryWidgetKeys.js +4 -0
  95. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  96. package/dist/esm/utils/openDuplicateWarning.js +39 -0
  97. package/dist/esm/utils/openDuplicateWarning.js.map +1 -0
  98. package/dist/esm/utils/optionsFrom.js +69 -2
  99. package/dist/esm/utils/optionsFrom.js.map +1 -1
  100. package/dist/esm/utils/planTree.js +57 -0
  101. package/dist/esm/utils/planTree.js.map +1 -0
  102. package/dist/esm/utils/redactionSegments.js +53 -0
  103. package/dist/esm/utils/redactionSegments.js.map +1 -0
  104. package/dist/esm/utils/registerNcDashboardWidgets.js +61 -0
  105. package/dist/esm/utils/registerNcDashboardWidgets.js.map +1 -0
  106. package/dist/esm/utils/searchRefusal.js +62 -0
  107. package/dist/esm/utils/searchRefusal.js.map +1 -0
  108. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  109. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  110. package/dist/nextcloud-vue.cjs.js +17409 -12832
  111. package/dist/nextcloud-vue.cjs.js.map +2 -2
  112. package/dist/nextcloud-vue.css +495 -61
  113. package/l10n/en.json +106 -1
  114. package/l10n/nl.json +105 -1
  115. package/package.json +1 -1
  116. package/src/components/CnAddressSearch/CnAddressSearch.vue +343 -0
  117. package/src/components/CnAddressSearch/index.js +12 -0
  118. package/src/components/CnAssignDialog/CnAssignDialog.vue +525 -0
  119. package/src/components/CnAssignDialog/index.js +12 -0
  120. package/src/components/CnDecisionListWidget/CnDecisionListWidget.vue +388 -0
  121. package/src/components/CnDecisionListWidget/index.js +12 -0
  122. package/src/components/CnDuplicateWarning/CnDuplicateWarning.vue +318 -0
  123. package/src/components/CnDuplicateWarning/index.js +12 -0
  124. package/src/components/CnFormDialog/CnFormDialog.vue +19 -3
  125. package/src/components/CnIndexPage/CnIndexPage.vue +52 -0
  126. package/src/components/CnNcDashboardList/CnNcDashboardList.vue +218 -0
  127. package/src/components/CnNcDashboardList/index.js +12 -0
  128. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +107 -6
  129. package/src/components/CnPlanWidget/CnPlanWidget.vue +246 -0
  130. package/src/components/CnPlanWidget/CnPlanWidgetRow.vue +117 -0
  131. package/src/components/CnPlanWidget/index.js +12 -0
  132. package/src/components/CnRedactionEditor/CnRedactionEditor.vue +655 -0
  133. package/src/components/CnRedactionEditor/index.js +13 -0
  134. package/src/components/CnRetentionWidget/CnRetentionWidget.vue +413 -0
  135. package/src/components/CnRetentionWidget/index.js +12 -0
  136. package/src/components/CnWidgetGrid/builtInWidgets.js +2 -0
  137. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +31 -0
  138. package/src/components/CnWorkQueue/CnWorkQueue.vue +456 -0
  139. package/src/components/CnWorkQueue/index.js +12 -0
  140. package/src/components/index.js +9 -0
  141. package/src/css/index-page.css +24 -0
  142. package/src/index.js +12 -0
  143. package/src/schemas/app-manifest-v2.schema.json +119 -3
  144. package/src/utils/actionsDispatcher.js +6 -1
  145. package/src/utils/builtInModals.js +3 -1
  146. package/src/utils/duplicateWarning.js +59 -0
  147. package/src/utils/errors.js +4 -0
  148. package/src/utils/libraryWidgetKeys.js +4 -0
  149. package/src/utils/openDuplicateWarning.js +35 -0
  150. package/src/utils/optionsFrom.js +68 -1
  151. package/src/utils/planTree.js +54 -0
  152. package/src/utils/redactionSegments.js +50 -0
  153. package/src/utils/registerNcDashboardWidgets.js +57 -0
  154. package/src/utils/searchRefusal.js +59 -0
  155. package/src/utils/validateManifestV2.compiled.js +3 -3
@@ -1015,7 +1015,12 @@ function dispatchAction(action, context = {}) {
1015
1015
  if (op === 'delete') {
1016
1016
  return store.deleteObject(type, id)
1017
1017
  }
1018
- // patch: the row's object merged with the action's values.
1018
+ // patch: only the action's values, as a PATCH, so every other key
1019
+ // keeps its stored value. A store without patchObject writes the
1020
+ // row's object merged with the values.
1021
+ if (typeof store.patchObject === 'function') {
1022
+ return store.patchObject(type, id, { ...(action.values || {}) })
1023
+ }
1019
1024
  return store.saveObject(type, { ...row, ...(action.values || {}), id })
1020
1025
  }
1021
1026
 
@@ -1 +1 @@
1
- {"version":3,"file":"actionsDispatcher.js","sources":["../../../src/utils/actionsDispatcher.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2024 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * actionsDispatcher — unified action dispatcher for v2 manifest actions.\n *\n * Dispatches an action object against a context. All dispatch types are\n * handled without throwing — errors surface as console.warn calls.\n * Types: handler | open-modal | open-page | navigate | object-op (the\n * declarative OpenRegister mutation verb added by ADR-049 — dispatched\n * via the shared object store, intent-only, RBAC stays server-side) |\n * export (opens the shared CnMassExportDialog export launcher configured\n * via the action's `entities[]` / `formats[]` — Wave 1 of\n * nextcloud-vue#91; the host page provides `context.openExport`) |\n * open-form (Wave 3 — schema-driven create dialog; the rendering host\n * provides `context.openForm`) | refresh (Wave 3 — bumps the page-level\n * refresh signal on the `cn:page:refresh` event-bus channel) | api-call\n * (Wave 3 — POST/PUT a configured app endpoint with success/error toasts\n * and an automatic page refresh; any `confirm` on the action is INTENT\n * consumed by the rendering surface BEFORE dispatch, like object-op) |\n * agent (run a governed hermiq agent against the page object via\n * POST /apps/hermiq/api/agents/{agent}/run-on-object — hermiq#41; a\n * first-class companion to api-call that resolves the register/schema/\n * objectId context for the author and fail-closes when hermiq is absent) |\n * run-node (manifest-run-node-action — invoke ONE OpenRegister flow node\n * directly against a subject object via\n * POST /api/flows/{flowId}/nodes/{nodeId}/run; the rendering surface\n * provides context.openRunNode, mirroring open-form, and resolves the\n * node's own declared config form before opening a dialog — see or-flow-run-node).\n *\n * `api-call`'s request body prefers `payload` (DEEP @-token resolution at\n * any nesting depth — object/array, e.g. a Filinq-style\n * `{ dataRefs: [{ id: '@objectId' }] }` body) over the legacy `params`\n * (shallow, one-level filter-map resolution, kept for back-compat). Set\n * `download: true` to request a binary blob response and trigger a\n * browser file download instead of a JSON toast+refresh cycle (filename:\n * `Content-Disposition` header, else the token-resolved `filename`, else\n * `'download.pdf'`; no auto-refresh unless `refresh: true` is explicit).\n *\n * `toggle` (Wave 3) is deliberately NOT dispatchable: a toggle is a\n * stateful two-way control (GET state on mount, write on click) rendered\n * by the header-actions surface (CnActionButtons); dispatching it here\n * warns and no-ops.\n *\n * Spec: REQ-MVR-011 (manifest-v2-renderer) — unified actions dispatcher\n * / ADR-036 Decision 7 / ADR-049 Decision 2 / #91 Wave 3\n */\n\nimport { emit } from '@nextcloud/event-bus'\nimport { translate as t } from '@nextcloud/l10n'\nimport { parseDispositionFilename, triggerBlobDownload } from '../components/CnIndexPage/selfModeIO.js'\nimport { interpolateUrlTokens } from '../composables/useEndpointSource.js'\nimport { routeHref } from './actionLink.js'\nimport { resolveModalEntry } from './builtInModals.js'\nimport {\n\tdropOptionalUnresolved,\n\tdropOptionalUnresolvedDeep,\n\thasUnresolvedDeepTokens,\n\thasUnresolvedTokens,\n\tresolveDeepTokens,\n\tresolveFilterTokens,\n} from './resolveFilterTokens.js'\nimport { schemaRefSlug } from './schemaRefSlug.js'\n\n/** Event-bus channel the page-level Refresh signal broadcasts on (Wave 2). */\nconst PAGE_REFRESH_CHANNEL = 'cn:page:refresh'\n\n/**\n * Whether a `navigate` target leaves the app: it is `http(s)://`,\n * protocol-relative (`//`), or a `mailto:` / `tel:` link. Anything else is an\n * in-app path for the router.\n *\n * vue-router happily accepts an absolute URL as a PATH — `router.push` on\n * `https://youtu.be/x?v=1` matches no route and lands on the fallback with the\n * query carried over, which reads as the app ignoring the link.\n *\n * An allowlist, not a generic `<scheme>://` match: manifests are\n * admin-editable app-wide config, and an external target renders into an\n * anchor `href` and a dispatcher `window.open` — a generic scheme match would\n * accept `javascript://` too.\n *\n * @param {unknown} target The action target to test.\n * @return {boolean} True when the target is external.\n */\nexport function isExternalActionTarget(target) {\n\tif (typeof target !== 'string') {\n\t\treturn false\n\t}\n\treturn /^\\/\\//.test(target) || /^(https?|mailto|tel):/i.test(target)\n}\n\n/**\n * Resolve the object-store type slug for a widget `source` register/schema\n * pair. Reuses an already-registered type whose config matches (so an app's\n * own caches stay coherent); otherwise registers a deterministic\n * `<register>/<schema>` slug on the fly.\n *\n * `source.schema` is routed through {@link schemaRefSlug} before it ever\n * reaches the store or the objects API: a caller that passes a `$ref`\n * schema TITLE (`ReportPeriod`) rather than its slug (`report-period`)\n * would otherwise register — and fetch — a 404 (defect 7, learniq round\n * 1). Idempotent for a caller that already passes a correct slug.\n *\n * A caller that already holds the schema SLUG (not a `$ref` title) passes\n * `{ exactSchema: true }`: the slug is then used exactly as given. Kebab-casing\n * a real camelCase slug (`productCategory` -> `product-category`) asks the\n * objects API for a schema that does not exist and 404s (pipelinq review,\n * round two).\n *\n * @spec openspec/changes/review-round-two/specs/schema-utilities/spec.md\n *\n * A title is not always registered under its kebab form: learniq holds\n * `LearniqSettings` and `SubjectTeacherAssignment` as written. So a type\n * registered here for a value the kebab rule CHANGED also carries the value\n * as written as its `schemaFallback`, and the store retries with it once\n * when the kebab form answers 404 (keeping it from then on). The kebab form\n * is still tried first, so a schema registered under it costs nothing.\n *\n * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-a-schema-title-falls-back-to-its-written-form\n * @param {object} store The object store instance (useObjectStore shape).\n * @param {{register: (string|number), schema: (string|number)}} source The widget source.\n * @param {{exactSchema: (boolean|undefined)}} [options] `exactSchema: true` skips the title-to-slug step.\n * @return {string} The type slug to use for store CRUD calls.\n */\nexport function resolveObjectOpType(store, source, options = {}) {\n\tconst register = String(source.register)\n\tconst schema = options.exactSchema === true ? String(source.schema) : String(schemaRefSlug(source.schema))\n\tconst written = typeof source.schema === 'string'\n\t\t? source.schema.substring(source.schema.lastIndexOf('/') + 1)\n\t\t: ''\n\tconst registry = store.objectTypeRegistry || {}\n\tfor (const [slug, config] of Object.entries(registry)) {\n\t\tif (!config) {\n\t\t\tcontinue\n\t\t}\n\t\tif ((String(config.register) === register && String(config.schema) === schema)\n\t\t\t|| (config.registerSlug === register && config.schemaSlug === schema)) {\n\t\t\treturn slug\n\t\t}\n\t}\n\tconst slug = `${register}/${schema}`\n\tif (!registry[slug]) {\n\t\tstore.registerObjectType(slug, schema, register)\n\t\tif (written !== '' && written !== schema && typeof store.setSchemaFallback === 'function') {\n\t\t\tstore.setSchemaFallback(slug, written)\n\t\t}\n\t}\n\treturn slug\n}\n\n/**\n * Extract an OpenRegister object's id from a row (top-level `id` wins,\n * `@self.id` metadata fallback).\n *\n * @param {object} row The row object.\n * @return {string|number|null} The object id, or null when absent.\n */\nfunction rowObjectId(row) {\n\tif (!row || typeof row !== 'object') {\n\t\treturn null\n\t}\n\tif (row.id !== undefined && row.id !== null) {\n\t\treturn row.id\n\t}\n\tconst self = row['@self']\n\tif (self && typeof self === 'object' && self.id !== undefined && self.id !== null) {\n\t\treturn self.id\n\t}\n\treturn null\n}\n\n/**\n * Extract a saved OpenRegister object's id for a post-save deep-link:\n * top-level `id`, then `uuid`, then the `@self.id` metadata fallback.\n *\n * @param {object} saved The saved record returned by the object store.\n * @return {string|number|null} The object id, or null when absent.\n */\nexport function savedObjectId(saved) {\n\tif (!saved || typeof saved !== 'object') {\n\t\treturn null\n\t}\n\tif (saved.id !== undefined && saved.id !== null) {\n\t\treturn saved.id\n\t}\n\tif (saved.uuid !== undefined && saved.uuid !== null) {\n\t\treturn saved.uuid\n\t}\n\tconst self = saved['@self']\n\tif (self && typeof self === 'object' && self.id !== undefined && self.id !== null) {\n\t\treturn self.id\n\t}\n\treturn null\n}\n\n/**\n * Resolve a manifest-named FUNCTION out of the v2 registry, falling back to the\n * legacy customComponents map.\n *\n * A manifest names a behaviour the same way it names a component — by string —\n * so every surface that dispatches one (`actions[].handler`,\n * `bulkActions[].handler`, `headerActions[].handler`, `config.createOverride`)\n * has to agree on where that string is looked up and what counts as a match.\n * Recognised shapes, in order:\n * 1. a registry entry exposing the function as `.handler` / `.fn` (the\n * `kind: 'handler'` and `kind: 'create-override'` entries),\n * 2. a directly function-valued registry entry,\n * 3. a function-valued legacy `customComponents` entry.\n *\n * The legacy map stays last so an app that has not migrated is unchanged, and\n * so an app mid-migration can move its handlers over one at a time.\n *\n * @param {string} name The registered handler name.\n * @param {object} registry The v2 component registry.\n * @param {object} customComponents The legacy customComponents map.\n * @return {?((scope?: object) => unknown)} The handler, or null when nothing of that name is a function.\n */\nexport function resolveRegisteredHandler(name, registry, customComponents) {\n\tif (typeof name !== 'string' || name === '') {\n\t\treturn null\n\t}\n\tconst entry = (registry || {})[name]\n\tif (typeof entry === 'function') {\n\t\treturn entry\n\t}\n\tif (entry && typeof entry === 'object') {\n\t\tif (typeof entry.handler === 'function') {\n\t\t\treturn entry.handler\n\t\t}\n\t\tif (typeof entry.fn === 'function') {\n\t\t\treturn entry.fn\n\t\t}\n\t}\n\tconst legacy = (customComponents || {})[name]\n\treturn typeof legacy === 'function' ? legacy : null\n}\n\n/**\n * Resolve a named create-override handler out of the v2 registry (or the\n * legacy customComponents map) by value shape.\n *\n * A create-override is a plain async function that replaces the default\n * `objectStore.saveObject` persist path — needed whenever a schema requires a\n * field the create form cannot supply on its own (a server-minted foreign key,\n * say).\n *\n * Shared by CnPageRenderer (page-level `config.createOverride` → CnIndexPage's\n * prop) and CnActionButtons (per-action `createOverride` on an `open-form`), so\n * the two surfaces cannot drift on what counts as a valid handler.\n *\n * @param {string} name The registered handler name.\n * @param {object} registry The v2 component registry.\n * @param {object} customComponents The legacy customComponents map.\n * @return {?((props?: object) => Promise<unknown>)} The async create handler, or null when unresolved.\n */\nexport function resolveCreateOverrideHandler(name, registry, customComponents) {\n\treturn resolveRegisteredHandler(name, registry, customComponents)\n}\n\n/**\n * Build the vue-router push location for an `open-form` action's\n * `onSuccessRoute`, merging the saved object's id into the route params so\n * the post-save navigation can deep-link to the created object's detail page\n * (#91).\n *\n * `onSuccessRoute` may be:\n * - a STRING route NAME → `{ name, params: { id } }`. The saved id lands\n * under the default `id` param; a route without an `:id` segment simply\n * ignores the extra param, so a bare-name route keeps working unchanged\n * (backward compatible).\n * - an OBJECT `{ name, paramField?, objectParam? }` → the id is placed\n * under `paramField` (default `id`), and — when `objectParam` is set —\n * the whole saved object is passed under that param key too (so a\n * `props: true` detail route can render the record without a refetch).\n *\n * The id is read via {@link savedObjectId} (`saved.id` → `saved.uuid` →\n * `saved['@self'].id`). Returns `null` when no route name is resolvable, so\n * the caller can skip the navigation.\n *\n * @param {(string|{name: string, paramField?: string, objectParam?: string})} onSuccessRoute The action's onSuccessRoute config.\n * @param {object} saved The saved OpenRegister object.\n * @return {{name: string, params: object}|null} The router push location, or null.\n */\nexport function buildOnSuccessRoute(onSuccessRoute, saved) {\n\tconst spec = typeof onSuccessRoute === 'string'\n\t\t? { name: onSuccessRoute }\n\t\t: (onSuccessRoute && typeof onSuccessRoute === 'object' ? onSuccessRoute : null)\n\tif (!spec || typeof spec.name !== 'string' || spec.name === '') {\n\t\treturn null\n\t}\n\tconst params = {}\n\tconst id = savedObjectId(saved)\n\tif (id !== null && id !== undefined) {\n\t\tparams[spec.paramField || 'id'] = id\n\t}\n\tif (spec.objectParam && saved && typeof saved === 'object') {\n\t\tparams[spec.objectParam] = saved\n\t}\n\treturn { name: spec.name, params }\n}\n\n/**\n * Run a manifest-authored toast message through the host translate function.\n *\n * `successMessage` / `errorMessage` are English source strings authored in the\n * manifest (ADR-007), so they need the SAME translator the rest of the page\n * chrome uses — the consumer's bound `t()`, handed to the dispatcher by the\n * rendering surface as `context.translate` (which itself comes from the\n * `cnTranslate` CnAppRoot provides).\n *\n * A pure pass-through: with no translator, no message, or a catalogue that\n * lacks the key, the message is returned byte-identical. Server-supplied\n * messages are data and are never routed through here.\n *\n * @param {unknown} message The manifest-authored message (may be undefined).\n * @param {object} context The dispatch context (`context.translate` optional).\n * @return {unknown} The translated message, or the input unchanged.\n */\nfunction translateMessage(message, context) {\n\tconst fn = context && context.translate\n\tif (!message || typeof fn !== 'function') {\n\t\treturn message\n\t}\n\treturn fn(message)\n}\n\n/**\n * Interpolate the `api-call` URL/filename token grammar inside a string:\n * the `{objectId}` BRACE convention (a literal placeholder some manifests\n * use for path templates, matching the OpenRegister credential-broker path\n * style) as well as the full `@objectId` / `@object.<field>` /\n * `@workspace.<key>` / `@config.<key>` grammar {@link interpolateUrlTokens}\n * already understands. Unresolved `@`-tokens and an unresolved\n * `{objectId}` both collapse to an empty string (never leak a literal\n * placeholder into a request URL or a downloaded filename).\n *\n * @param {string} str The raw string (an action's `url` or `filename`).\n * @param {{objectId?: (string|number), object?: object, workspace?: object, config?: object}} ctx Token context.\n * @return {string} The interpolated string.\n */\nfunction interpolateActionString(str, ctx) {\n\tif (typeof str !== 'string') {\n\t\treturn str\n\t}\n\tconst braced = str.replace(/\\{objectId\\}/g, () => {\n\t\tconst id = ctx.objectId\n\t\treturn (id === undefined || id === null) ? '' : String(id)\n\t})\n\treturn interpolateUrlTokens(braced, ctx)\n}\n\n/**\n * Interpolate an action's `target` URL — the same grammar `url` runs.\n *\n * Exported because the rendering surface resolves a target BEFORE deciding\n * whether it is an external link, and that decision happens there rather than\n * in the dispatcher.\n *\n * @param {string} target The action's raw `target`.\n * @param {object} ctx Token context (`{ objectId?, object?, workspace?, config? }`).\n *\n * @return {string} The interpolated target.\n */\nexport function interpolateActionTarget(target, ctx) {\n\treturn interpolateActionString(target || '', ctx || {})\n}\n\n// The tokens interpolateActionString resolves; a bare `@` or `{` is not one.\nconst ACTION_TARGET_TOKEN = /@(?:objectId|object\\.|page\\.|workspace\\.|config\\.|range\\.)|\\{objectId\\}/\n\n/**\n * Whether an action target carries a token that interpolation would resolve,\n * so it can only be known once the page context is. A `mailto:` address or a\n * URL with an `@handle` in it has none.\n *\n * @param {string} target The action's raw `target`.\n * @return {boolean}\n */\nexport function hasActionTargetTokens(target) {\n\treturn typeof target === 'string' && ACTION_TARGET_TOKEN.test(target)\n}\n\n/**\n * The link an action renders as when its only job is to navigate to a target\n * known at render time: `navigate` (token-interpolated like the dispatcher)\n * and `open-page`. Anything else, a `confirm: true` action, or an in-app\n * target the router cannot resolve answers null and keeps dispatching.\n *\n * `to` is what a plain click hands the router (null for an external URL,\n * which the browser opens in a new tab like the dispatcher's `window.open`).\n *\n * @param {object} action The manifest action.\n * @param {{router?: object, tokenCtx?: object}} [context] The dispatch context.\n * @return {{href: string, to: (string|object|null), external: boolean}|null} The link, or null.\n */\nexport function actionLink(action, context = {}) {\n\tif (!action || typeof action !== 'object' || action.confirm) {\n\t\treturn null\n\t}\n\tif (action.type === 'navigate') {\n\t\tconst target = interpolateActionString(action.target || '', context.tokenCtx || {})\n\t\tif (!target) {\n\t\t\treturn null\n\t\t}\n\t\tif (isExternalActionTarget(target)) {\n\t\t\treturn { href: target, to: null, external: true }\n\t\t}\n\t\tconst href = routeHref(target, context.router)\n\t\treturn href ? { href, to: target, external: false } : null\n\t}\n\tif (action.type === 'open-page') {\n\t\tif (typeof action.target !== 'string' || action.target.length === 0) {\n\t\t\treturn null\n\t\t}\n\t\tconst to = { name: action.target }\n\t\tconst href = routeHref(to, context.router)\n\t\treturn href ? { href, to, external: false } : null\n\t}\n\treturn null\n}\n\n/**\n * Execute a Wave-3 `api-call` action: POST/PUT the configured app endpoint\n * (URL + body run the SAME @-token grammar endpoint sources use), toast the\n * outcome via @nextcloud/dialogs, then — unless `action.refresh` is `false`\n * (or, for a `download` action, unless `action.refresh` is explicitly\n * `true`) — bump the page-level refresh signal so every endpoint-bound\n * widget refetches. Confirm-gating is the RENDERING SURFACE's job (the\n * `confirm` field is intent, object-op precedent): this runs after any\n * confirmation already happened.\n *\n * The request body prefers `action.payload` (DEEP token resolution, any\n * nesting — {@link resolveDeepTokens}) over the legacy `action.params`\n * (shallow, one-level filter-map resolution — unchanged for back-compat).\n * A required token left unresolved anywhere in the body BLOCKS the call\n * (error toast) rather than sending a literal `@objectId` to the server.\n *\n * `action.download === true` requests the response as a binary blob\n * (`responseType: 'blob'`) and triggers a browser file download — the\n * filename comes from the response's `Content-Disposition` header, else\n * the token-resolved `action.filename`, else `'download.pdf'`.\n *\n * Never throws: a failed call resolves `{ ok: false, error }` after the\n * error toast (so a confirm dialog can await the outcome).\n *\n * @param {object} action The api-call action (`url`, `method?`, `payload?`,\n * `params?`, `download?`, `filename?`, `successMessage?`, `errorMessage?`,\n * `refresh?`).\n * @param {object} context Runtime context; `context.tokenCtx` is the token\n * context (`{ objectId?, object?, workspace?, config? }`) the URL/body\n * resolve against.\n * @return {Promise<{ok: boolean, data?: unknown, error?: unknown}>} The call outcome.\n */\nasync function executeApiCall(action, context) {\n\tconst tokenCtx = context.tokenCtx || {}\n\tconst url = interpolateActionString(action.url || '', tokenCtx)\n\n\tconst hasPayload = action.payload && typeof action.payload === 'object' && !Array.isArray(action.payload)\n\tconst body = hasPayload\n\t\t? dropOptionalUnresolvedDeep(resolveDeepTokens(action.payload, tokenCtx))\n\t\t: dropOptionalUnresolved(resolveFilterTokens(action.params || {}, tokenCtx))\n\tconst bodyBlocked = hasPayload ? hasUnresolvedDeepTokens(body) : hasUnresolvedTokens(body)\n\n\tif (!url || bodyBlocked) {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.warn('[dispatchAction] api-call is missing its url or a required token is unresolved — skipping.', action)\n\t\treturn { ok: false, error: new Error('api-call blocked') }\n\t}\n\tconst method = String(action.method || 'POST').toUpperCase() === 'PUT' ? 'put' : 'post'\n\tconst isDownload = action.download === true\n\tconst [{ default: axios }, { generateUrl }, dialogs] = await Promise.all([\n\t\timport('@nextcloud/axios'),\n\t\timport('@nextcloud/router'),\n\t\timport('@nextcloud/dialogs'),\n\t])\n\tconst target = /^https?:\\/\\//i.test(url) ? url : generateUrl(url)\n\ttry {\n\t\t// Only pass a third axios config arg for a download call — an\n\t\t// explicit `undefined` third argument would otherwise change the\n\t\t// call shape for every existing (non-download) api-call consumer/test.\n\t\tconst res = isDownload\n\t\t\t? await axios[method](target, body, { responseType: 'blob' })\n\t\t\t: await axios[method](target, body)\n\t\tif (isDownload) {\n\t\t\tconst filename = parseDispositionFilename(\n\t\t\t\tres && res.headers && res.headers['content-disposition'],\n\t\t\t\tinterpolateActionString(action.filename, tokenCtx) || 'download.pdf',\n\t\t\t)\n\t\t\ttriggerBlobDownload(res.data, filename)\n\t\t}\n\t\tif (typeof dialogs.showSuccess === 'function') {\n\t\t\tdialogs.showSuccess(translateMessage(action.successMessage, context) || t('nextcloud-vue', 'Action completed.'))\n\t\t}\n\t\tconst shouldRefresh = isDownload ? action.refresh === true : action.refresh !== false\n\t\tif (shouldRefresh) {\n\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t}\n\t\treturn { ok: true, data: res && res.data }\n\t} catch (error) {\n\t\tconst serverMessage = error && error.response && error.response.data\n\t\t\t&& (error.response.data.error || error.response.data.message)\n\t\tif (typeof dialogs.showError === 'function') {\n\t\t\tdialogs.showError(translateMessage(action.errorMessage, context) || serverMessage || t('nextcloud-vue', 'Action failed.'))\n\t\t}\n\t\treturn { ok: false, error }\n\t}\n}\n\n/**\n * Resolve an agent-action object reference (`register` / `schema` / `objectId`):\n * an explicitly-declared action value WINS (it may itself be an @-token string,\n * interpolated against the token context), otherwise it falls back to the page\n * object context default (`tokenCtx.register` / `.schema` / `.objectId`). An\n * unresolved token collapses to an empty string (never leaks a literal `@objectId`\n * to the server); a `{ slug | id }` object (a schema holder) is flattened to its\n * slug/id.\n *\n * @param {unknown} actionVal The action's explicit value (may be undefined or an @-token).\n * @param {unknown} ctxDefault The page-context default (`tokenCtx.<field>`).\n * @param {object} tokenCtx The token context the @-tokens resolve against.\n * @return {string} The resolved reference, or '' when unresolved/absent.\n */\nfunction resolveAgentRef(actionVal, ctxDefault, tokenCtx) {\n\tlet v = actionVal\n\tif (v === undefined || v === null || v === '') {\n\t\tv = ctxDefault\n\t} else if (typeof v === 'string') {\n\t\tv = interpolateActionString(v, tokenCtx)\n\t}\n\tif (v && typeof v === 'object') {\n\t\treturn String(v.slug || v.id || '')\n\t}\n\tif (v === undefined || v === null) {\n\t\treturn ''\n\t}\n\treturn String(v)\n}\n\n/**\n * Execute an `agent` action: run a governed hermiq agent against the page's\n * OpenRegister object. Resolves the object context (`register` / `schema` /\n * `objectId` — explicit action fields override, else default to the page's\n * `@register` / `@schema` / `@objectId` context) and POSTs\n * `{ register, schema, objectId, resultField?, skill?, prompt? }` to hermiq's\n * object-RBAC-scoped run endpoint `/apps/hermiq/api/agents/{agent}/run-on-object`\n * (hermiq#41), which dispatches the governed `AgentRunRequestedEvent`.\n *\n * A first-class companion to `type:\"api-call\"` — the author declares \"run agent\n * here\" without hand-wiring the URL/body. `type:\"api-call\"` remains the escape\n * hatch for a bespoke body.\n *\n * Fail-closed. An unresolved REQUIRED `@objectId` (or a missing agent/register/\n * schema) BLOCKS the call (warn) rather than POSTing a literal token. On the\n * server's 202 it toasts `successMessage` (default 'Run queued') and — unless\n * `refresh: false` — bumps the page refresh signal. A 403 / 404 with a structured\n * error body fail-closes with that message; a 404 with NO structured body is read\n * as \"hermiq absent\" and toasts a graceful 'agent runtime unavailable' — the\n * dispatcher NEVER hard-requires hermiq to be installed. Never throws.\n *\n * @param {object} action The agent action (`agent`, `skill?`, `prompt?`,\n * `resultField?`, `register?`, `schema?`, `objectId?`, `successMessage?`,\n * `errorMessage?`, `refresh?`).\n * @param {object} context Runtime context; `context.tokenCtx` is the token\n * context (`{ objectId?, object?, register?, schema?, workspace?, config? }`).\n * @return {Promise<{ok: boolean, data?: unknown, error?: unknown}>} The call outcome.\n */\nasync function executeAgentAction(action, context) {\n\tconst tokenCtx = context.tokenCtx || {}\n\tconst agent = resolveAgentRef(action.agent, undefined, tokenCtx)\n\tconst register = resolveAgentRef(action.register, tokenCtx.register, tokenCtx)\n\tconst schema = resolveAgentRef(action.schema, tokenCtx.schema, tokenCtx)\n\tconst objectId = resolveAgentRef(action.objectId, tokenCtx.objectId, tokenCtx)\n\n\tif (!agent || !register || !schema || !objectId) {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.warn('[dispatchAction] agent action is missing its agent or a required object-context token (register/schema/objectId) is unresolved — skipping.', action)\n\t\treturn { ok: false, error: new Error('agent action blocked') }\n\t}\n\n\tconst body = { register, schema, objectId }\n\tconst resultField = resolveAgentRef(action.resultField, undefined, tokenCtx)\n\tif (resultField) {\n\t\tbody.resultField = resultField\n\t}\n\tconst skill = resolveAgentRef(action.skill, undefined, tokenCtx)\n\tif (skill) {\n\t\tbody.skill = skill\n\t}\n\tif (typeof action.prompt === 'string' && action.prompt !== '') {\n\t\tbody.prompt = interpolateActionString(action.prompt, tokenCtx)\n\t}\n\n\tconst [{ default: axios }, { generateUrl }, dialogs] = await Promise.all([\n\t\timport('@nextcloud/axios'),\n\t\timport('@nextcloud/router'),\n\t\timport('@nextcloud/dialogs'),\n\t])\n\tconst target = generateUrl(`/apps/hermiq/api/agents/${encodeURIComponent(agent)}/run-on-object`)\n\ttry {\n\t\tconst res = await axios.post(target, body)\n\t\tif (typeof dialogs.showSuccess === 'function') {\n\t\t\tdialogs.showSuccess(translateMessage(action.successMessage, context) || t('nextcloud-vue', 'Run queued'))\n\t\t}\n\t\tif (action.refresh !== false) {\n\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t}\n\t\treturn { ok: true, data: res && res.data }\n\t} catch (error) {\n\t\tconst response = error && error.response\n\t\tconst status = response && response.status\n\t\tconst serverMessage = response && response.data\n\t\t\t&& (response.data.error || response.data.message)\n\t\t// A 404 with NO structured error body = hermiq is not installed (the app\n\t\t// route 404s at the NC level) — surface a graceful \"runtime unavailable\"\n\t\t// rather than a fail-closed authorization message.\n\t\tconst hermiqAbsent = status === 404 && !serverMessage\n\t\tif (typeof dialogs.showError === 'function') {\n\t\t\tconst msg = hermiqAbsent\n\t\t\t\t? t('nextcloud-vue', 'Agent runtime unavailable')\n\t\t\t\t: (translateMessage(action.errorMessage, context) || serverMessage || t('nextcloud-vue', 'Action failed.'))\n\t\t\tdialogs.showError(msg)\n\t\t}\n\t\treturn { ok: false, error }\n\t}\n}\n\n/**\n * POST the run-node call: `POST /apps/openregister/api/flows/{flowId}/nodes/{nodeId}/run`.\n *\n * This is the SECOND half of `run-node` (manifest-run-node-action / or-flow-run-node) —\n * the first half is `context.openRunNode` in the `dispatchAction` switch below, which\n * only OPENS the config dialog (or decides none is needed) and never itself waits for\n * the person. Once the rendering surface has a `config` object (from the dialog's\n * submit, or `{}` when the node's declared form was empty), it calls this directly —\n * it is not reached through `dispatchAction`'s switch, because by that point there is\n * no further \"type\" dispatch to do, only the call itself, same as `executeAgentAction`\n * is called directly by `case 'api-call'`'s sibling rather than re-entering the switch.\n *\n * Fail-closed exactly like `executeAgentAction`: an unresolved REQUIRED subject\n * (`action.subject`, defaulting to the page's `@objectId`) or a missing\n * `flowId`/`nodeId` BLOCKS the call (warn) rather than POSTing a literal token or an\n * incomplete subject reference. The subject sent is `{ uuid, register, schema }` —\n * OpenRegister's `FlowNodeRunController::resolveAuthorizedSubject()` needs all three\n * to resolve the object and evaluate the caller's object-RBAC permission on it; `register`\n * / `schema` default to the page's own `@register` / `@schema` context, the same\n * defaulting `agent` already uses.\n *\n * A 403 here means the caller holds no update permission on the subject\n * (OpenRegister's object-RBAC, evaluated server-side — RN-1(c)) — this function does not\n * special-case it beyond surfacing the server's message, the same fail-closed handling\n * `api-call` / `agent` already give a rejected call.\n *\n * @param {object} action The run-node action (`flowId`, `nodeId`, `subject?`,\n * `register?`, `schema?`, `successMessage?`, `errorMessage?`, `refresh?`).\n * @param {object} context Runtime context — needs `context.tokenCtx` and, for a\n * localised toast, `context.translate`.\n * @param {object} [config] The node's collected config (from its `configForm()`\n * dialog), or `{}` for a node with no declared fields.\n * @return {Promise<{ok: boolean, data?: object, error?: Error}>} The call outcome —\n * `data` is the created `FlowRun` on success.\n *\n * @spec openspec/changes/manifest-run-node-action/specs/manifest-run-node-action/spec.md#requirement-a-run-node-action-invokes-one-flow-node-against-the-page-object\n */\nexport async function postRunNode(action, context, config = {}) {\n\tconst tokenCtx = context.tokenCtx || {}\n\tconst flowId = resolveAgentRef(action.flowId, undefined, tokenCtx)\n\tconst nodeId = resolveAgentRef(action.nodeId, undefined, tokenCtx)\n\tconst uuid = resolveAgentRef(action.subject, tokenCtx.objectId, tokenCtx)\n\tconst register = resolveAgentRef(action.register, tokenCtx.register, tokenCtx)\n\tconst schema = resolveAgentRef(action.schema, tokenCtx.schema, tokenCtx)\n\n\tif (!flowId || !nodeId || !uuid || !register || !schema) {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.warn('[dispatchAction] run-node is missing flowId/nodeId or a required subject token (objectId/register/schema) is unresolved — skipping.', action)\n\t\treturn { ok: false, error: new Error('run-node blocked') }\n\t}\n\n\tconst [{ default: axios }, { generateUrl }, dialogs] = await Promise.all([\n\t\timport('@nextcloud/axios'),\n\t\timport('@nextcloud/router'),\n\t\timport('@nextcloud/dialogs'),\n\t])\n\tconst target = generateUrl(`/apps/openregister/api/flows/${encodeURIComponent(flowId)}/nodes/${encodeURIComponent(nodeId)}/run`)\n\ttry {\n\t\tconst res = await axios.post(target, { subject: { uuid, register, schema }, config: config || {} })\n\t\tif (typeof dialogs.showSuccess === 'function') {\n\t\t\tdialogs.showSuccess(translateMessage(action.successMessage, context) || t('nextcloud-vue', 'Run completed.'))\n\t\t}\n\t\tif (action.refresh !== false) {\n\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t}\n\t\treturn { ok: true, data: res && res.data }\n\t} catch (error) {\n\t\tconst response = error && error.response\n\t\tconst serverMessage = response && response.data\n\t\t\t&& (response.data.error || response.data.message)\n\t\tif (typeof dialogs.showError === 'function') {\n\t\t\tdialogs.showError(translateMessage(action.errorMessage, context) || serverMessage || t('nextcloud-vue', 'Action failed.'))\n\t\t}\n\t\treturn { ok: false, error }\n\t}\n}\n\n/**\n * Dispatch a v2 manifest action.\n *\n * @param {object} action The action object from the manifest.\n * @param {string} [action.type] Dispatch type: \"handler\" | \"open-modal\" | \"open-page\" | \"navigate\" |\n * \"object-op\" | \"export\" | \"open-form\" | \"refresh\" | \"api-call\" | \"agent\".\n * When absent, treated as \"handler\" for v1 backward compatibility.\n * @param {string} [action.handler] Registry key for \"handler\" type. For \"export\": the optional\n * handler invoked by the host with the dialog's confirm payload (`{ format, entity }`).\n * @param {Array} [action.args] Arguments spread to the handler function.\n * @param {string} [action.target] Target for \"open-modal\", \"open-page\", and \"navigate\" types.\n * @param {object} [action.props] Props forwarded to modal for \"open-modal\" type.\n * @param {string} [action.op] \"object-op\" only: mutation verb — \"patch\" | \"delete\" | \"create\".\n * @param {object} [action.values] \"object-op\" only: the verb's payload — the partial object\n * merged over the row for \"patch\", the new object's properties for \"create\"; ignored for \"delete\".\n * @param {boolean} [action.confirm] \"object-op\" only: confirm-gating INTENT consumed by the\n * rendering host (CnWidgetObjectTable routes it through CnConfirmDialog) — the dispatcher\n * itself never gates; it is called after any confirmation already happened.\n * @param {Array<{id: string, label: string}>} [action.entities] \"export\" only: selectable\n * entity types offered by the export launcher (e.g. Leads / Requests). Optional — when\n * absent the dialog shows only the format picker.\n * @param {Array<string|{id: string, label: string}>} [action.formats] \"export\" only: the\n * offered export formats (bare ids like \"csv\" or full `{id, label}` entries). Optional —\n * the dialog's built-in Excel/CSV defaults apply when absent.\n * @param {string} [action.description] \"export\" only: pre-translated description shown\n * above the pickers.\n * @param {string} [action.url] \"api-call\" only: the app endpoint — app-relative (routed\n * through generateUrl) or absolute. May interpolate the shared URL tokens\n * (`@objectId`, `@object.<field>`, `@workspace.<key>`, `@config.<key>`, and the\n * `{objectId}` brace form).\n * @param {string} [action.method] \"api-call\" only: \"POST\" (default) | \"PUT\".\n * @param {object} [action.payload] \"api-call\" only: the JSON body — preferred over `params`.\n * Values resolve the shared `@`-token grammar RECURSIVELY at any nesting depth (objects\n * and arrays of objects, e.g. `{ dataRefs: [{ id: '@objectId' }] }`); optional (`…?`)\n * tokens drop when unresolved anywhere in the tree, an unresolved REQUIRED token blocks\n * the call. When set, `params` is ignored.\n * @param {object} [action.params] \"api-call\" only: legacy JSON body (ignored when `payload`\n * is set). Values pass the shared filter-token grammar ONE level deep; optional (`…?`)\n * tokens drop when unresolved, an unresolved REQUIRED token blocks the call.\n * @param {boolean} [action.download] \"api-call\" only: request the response as a binary blob\n * (`responseType: 'blob'`) and trigger a browser file download instead of a JSON\n * toast+refresh cycle. Default `false`.\n * @param {string} [action.filename] \"api-call\" `download: true` only: fallback filename when\n * the response carries no `Content-Disposition` header (falls back further to\n * `'download.pdf'`). Interpolates the same token grammar as `url`.\n * @param {string} [action.successMessage] \"api-call\" / \"open-form\": pre-translated success\n * toast text (a library default applies when absent).\n * @param {string} [action.errorMessage] \"api-call\" / \"open-form\": pre-translated error toast\n * text (falls back to the server's `error`/`message`, then a library default).\n * @param {boolean} [action.refresh] \"api-call\" / \"agent\" only: bump the `cn:page:refresh` signal\n * after a successful call. Default `true` — EXCEPT for a `download: true` api-call, whose\n * default is `false` (a file download normally shouldn't also force-refetch every widget); set\n * the flag explicitly either way to override.\n * @param {string} [action.agent] \"agent\" only (REQUIRED): the hermiq agent uuid to run against\n * the page object. POSTed to `/apps/hermiq/api/agents/{agent}/run-on-object` (hermiq#41).\n * @param {string} [action.skill] \"agent\" only: optional skill id folded into the governed run.\n * @param {string} [action.prompt] \"agent\" only: optional prompt (interpolates the shared `@`-token\n * grammar inline — `@objectId`, `@object.<field>`, `@workspace.<key>`, `@config.<key>`).\n * @param {string} [action.resultField] \"agent\" only: object field the agent's result is written to.\n * @param {string} [action.register] \"agent\" / \"open-form\": OpenRegister register slug (agent:\n * defaults to the page object context's `@register`).\n * @param {string} [action.schema] \"agent\" / \"open-form\": OpenRegister schema slug (agent: defaults\n * to the page object context's `@schema`).\n * @param {string} [action.objectId] \"agent\" only: the target object id (defaults to the page\n * object context's `@objectId`). An unresolved required token BLOCKS the call (fail-closed).\n *\n * @param {object} context Runtime context.\n * @param {object} [context.router] Vue Router instance. Required for \"open-page\" and \"navigate\".\n * @param {object} [context.registry] Component registry (Record<string, { kind, component }>).\n * Required for \"open-modal\" type.\n * @param {object} [context.handlers] Map of handler name → function. Required for \"handler\" type.\n * @param {(key: string, props?: object) => void} [context.openModal] Opens a modal.\n * Required for \"open-modal\" type.\n * @param {(action: object) => void} [context.openExport] Opens the shared\n * CnMassExportDialog configured from the action. Required for \"export\" type —\n * CnPageRenderer pre-binds it in the `cnDispatchAction` context.\n * @param {(action: object) => void} [context.openForm] Opens the schema-driven\n * create dialog. Required for \"open-form\" type — the rendering surface\n * (CnActionButtons) provides it, mirroring `openExport`. On a successful save the\n * surface navigates to `action.onSuccessRoute` (a route NAME string, or\n * `{name, paramField?, objectParam?}`) via {@link buildOnSuccessRoute}, which merges\n * the saved object's id into the route params so the navigation can deep-link to the\n * created object.\n * @param {(action: object) => void} [context.openRunNode] Opens the\n * node-config dialog (or runs immediately for an empty config form) and\n * POSTs to OpenRegister's direct-invoke endpoint on submit. Required for\n * \"run-node\" type — the rendering surface (CnActionButtons) provides it,\n * mirroring `openForm`.\n * @param {{objectId?: (string|number), object?: object, workspace?: object, config?: object}} [context.tokenCtx]\n * Token context \"api-call\" URLs/params resolve against (the same shape\n * `resolveFilterTokens` / `interpolateUrlTokens` take).\n * @param {(app: string, text: string, vars?: object) => string} [context.translate] The consumer's bound `t()`, the same\n * `cnTranslate` CnAppRoot provides to the page chrome. Applied to the\n * manifest-authored `successMessage` / `errorMessage` of \"api-call\" and\n * \"agent\" so their toasts follow the user's language. Omitted (or a\n * catalogue miss) leaves the message byte-identical.\n * @param {object} [context.objectStore] Object store instance (useObjectStore shape).\n * Required for \"object-op\" type. All mutations go through `saveObject` / `deleteObject`\n * so store caches (and their no-mutation-on-error semantics) apply.\n * @param {{register: (string|number), schema: (string|number)}} [context.source] The widget's\n * declarative source the mutation targets. Required for \"object-op\" type.\n * @param {object} [context.row] The row object a row-scoped \"object-op\" (patch/delete) mutates.\n *\n * @return {Promise<object|boolean|null>|undefined} For \"object-op\": the store call's promise —\n * the saved object (or `null` on a rejected write) for patch/create, `true`/`false` for\n * delete. The store only mutates its local caches on SUCCESS, so a backend (RBAC) rejection\n * surfaces via the store's `errors[type]` without any local state change. For \"api-call\":\n * a promise of `{ ok, data?, error? }` (toasts + refresh already handled). All other types\n * return undefined.\n */\nexport function dispatchAction(action, context = {}) {\n\tif (!action || typeof action !== 'object') {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.warn('[dispatchAction] Received invalid action:', action)\n\t\treturn\n\t}\n\n\t// Missing type is treated as \"handler\" for v1 backward compatibility\n\tconst type = action.type || 'handler'\n\n\tswitch (type) {\n\t\tcase 'handler': {\n\t\t\tconst handlerName = action.handler\n\t\t\tconst handlers = context.handlers || {}\n\n\t\t\tif (!handlerName || typeof handlers[handlerName] !== 'function') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[dispatchAction] Handler \"${handlerName}\" not found in context.handlers.`)\n\t\t\t\treturn\n\t\t\t}\n\t\t\thandlers[handlerName](...(action.args ?? []))\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'open-modal': {\n\t\t\tconst target = action.target\n\t\t\tconst entry = resolveModalEntry(context.registry, target)\n\n\t\t\tif (!entry) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[dispatchAction] open-modal target \"${target}\" not found in registry.`)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (entry.kind !== 'modal') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[dispatchAction] open-modal target \"${target}\" has kind \"${entry.kind}\" (expected \"modal\").`)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (typeof context.openModal !== 'function') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] open-modal requires context.openModal to be a function.')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tcontext.openModal(target, action.props ?? {})\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'open-page': {\n\t\t\tif (!context.router) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] open-page requires context.router to be a Vue Router instance.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcontext.router.push({ name: action.target })\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'navigate': {\n\t\t\t// A target is a URL exactly as `url` is, so it runs the same token\n\t\t\t// grammar. Without this a manifest's `{objectId}` reached the router\n\t\t\t// as those nine literal characters and landed in the address bar.\n\t\t\tconst target = interpolateActionString(action.target || '', context.tokenCtx || {})\n\n\t\t\t// An external target is not a route. Rendering surfaces should give it\n\t\t\t// to the browser as a real link (CnActionButtons does); this is the\n\t\t\t// fallback for a programmatic dispatch, and it must not reach the\n\t\t\t// router — see isExternalActionTarget.\n\t\t\tif (isExternalActionTarget(target)) {\n\t\t\t\twindow.open(target, '_blank', 'noopener,noreferrer')\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (!context.router) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] navigate requires context.router to be a Vue Router instance.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcontext.router.push(target)\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'export': {\n\t\t// Export launcher (Wave 1, nextcloud-vue#91): the host page opens the\n\t\t// shared CnMassExportDialog configured via the action's entities[] /\n\t\t// formats[]; the dialog's confirm payload routes to the action's\n\t\t// optional `handler` (the app's export service does the download).\n\t\t\tif (typeof context.openExport !== 'function') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] export requires context.openExport to be a function.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcontext.openExport(action)\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'open-form': {\n\t\t// Schema-driven create dialog (Wave 3, nextcloud-vue#91): the\n\t\t// rendering surface (CnActionButtons) mounts the shared\n\t\t// CnAdvancedFormDialog and handles the save — mirroring how\n\t\t// `export` delegates to the host's CnMassExportDialog.\n\t\t\tif (typeof context.openForm !== 'function') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] open-form requires context.openForm to be a function.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcontext.openForm(action)\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'run-node': {\n\t\t// Direct flow-node invocation (manifest-run-node-action / RN-4):\n\t\t// SAME shape as open-form, deliberately — the rendering surface\n\t\t// (CnActionButtons) resolves the node's own config form, opens a\n\t\t// generic dialog when it has fields (skips it when empty), and\n\t\t// POSTs subject+config to OpenRegister's\n\t\t// /api/flows/{flowId}/nodes/{nodeId}/run on submit. This case\n\t\t// resolves as soon as the dialog OPENS (or the empty-form call\n\t\t// starts) — it does NOT wait for the person to answer, matching\n\t\t// every other consumer's assumption that dispatchAction's Promise\n\t\t// means \"the call happened\", not \"the human decided\" (see design.md\n\t\t// RN-4 for why an awaiting-on-UI shape was rejected).\n\t\t\tif (typeof context.openRunNode !== 'function') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] run-node requires context.openRunNode to be a function.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcontext.openRunNode(action)\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'refresh': {\n\t\t// Page-level refresh (Wave 3, nextcloud-vue#91): bump the SAME\n\t\t// `cn:page:refresh` event-bus signal the page overflow menu's\n\t\t// Refresh item broadcasts — every endpoint-bound / bus-subscribed\n\t\t// widget on the page force-refetches past its shared cache.\n\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'api-call': {\n\t\t// POST/PUT an app endpoint + toast + refresh (Wave 3). Any\n\t\t// `confirm` on the action is INTENT the rendering surface consumed\n\t\t// BEFORE calling the dispatcher (object-op precedent) — no gating\n\t\t// happens here.\n\t\t\treturn executeApiCall(action, context)\n\t\t}\n\n\t\tcase 'agent': {\n\t\t// Run a governed hermiq agent against the page object (hermiq#41). A\n\t\t// first-class companion to api-call: resolves the object context\n\t\t// (register/schema/objectId) and POSTs run-on-object. Any `confirm`\n\t\t// on the action is INTENT the rendering surface consumed BEFORE\n\t\t// dispatch (api-call / object-op precedent) — no gating here. hermiq\n\t\t// is NOT hard-required: an app-level 404 surfaces a graceful toast.\n\t\t\treturn executeAgentAction(action, context)\n\t\t}\n\n\t\tcase 'toggle': {\n\t\t// A toggle is a stateful two-way control (GET state on mount,\n\t\t// write on click) — it is RENDERED by the header-actions surface\n\t\t// (CnActionButtons), never dispatched as a one-shot action.\n\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn('[dispatchAction] \"toggle\" is a stateful header-actions control rendered by CnActionButtons — it cannot be dispatched.')\n\t\t\treturn\n\t\t}\n\n\t\tcase 'object-op': {\n\t\t// Declarative mutation of an OpenRegister object, dispatched via the\n\t\t// shared object store (ADR-049). The manifest declares INTENT only:\n\t\t// authorization-shaped fields on the action (`role`, `allow`, …) are\n\t\t// NEVER consulted here — OpenRegister RBAC is the single authority\n\t\t// (ADR-022 / ADR-023) and a forbidden mutation is rejected server-side.\n\t\t// The store mutates its caches only on success, so a rejected write\n\t\t// surfaces as an error with no local state change.\n\t\t\tconst op = action.op\n\t\t\tif (op !== 'patch' && op !== 'delete' && op !== 'create') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[dispatchAction] object-op has invalid op \"${op}\" (expected patch | delete | create).`)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst store = context.objectStore\n\t\t\tif (!store || typeof store.saveObject !== 'function' || typeof store.deleteObject !== 'function') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] object-op requires context.objectStore (useObjectStore shape).')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst source = context.source\n\t\t\tif (!source || !source.register || !source.schema) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] object-op requires context.source with register + schema.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst type = resolveObjectOpType(store, source)\n\n\t\t\tif (op === 'create') {\n\t\t\t\treturn store.saveObject(type, { ...(action.values || {}) })\n\t\t\t}\n\n\t\t\tconst row = context.row\n\t\t\tconst id = rowObjectId(row)\n\t\t\tif (id === null) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[dispatchAction] object-op \"${op}\" is row-scoped and requires context.row with an id.`)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (op === 'delete') {\n\t\t\t\treturn store.deleteObject(type, id)\n\t\t\t}\n\t\t\t// patch: the row's object merged with the action's values.\n\t\t\treturn store.saveObject(type, { ...row, ...(action.values || {}), id })\n\t\t}\n\n\t\tdefault:\n\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(`[dispatchAction] Unknown action type \"${type}\".`)\n\t}\n}\n"],"names":["t"],"mappings":"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AG;AACH,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;AAC7B,EAAE;AACF,CAAC;AACD;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;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;AACO,SAAS,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE;AACrD,CAAC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC5C;AACA,EAAE,OAAO,CAAC,IAAI,CAAC,2CAA2C,EAAE,MAAM,EAAC;AACnE,EAAE,MAAM;AACR,EAAE;AACF;AACA;AACA,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,UAAS;AACtC;AACA,CAAC,QAAQ,IAAI;AACb,EAAE,KAAK,SAAS,EAAE;AAClB,GAAG,MAAM,WAAW,GAAG,MAAM,CAAC,QAAO;AACrC,GAAG,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,GAAE;AAC1C;AACA,GAAG,IAAI,CAAC,WAAW,IAAI,OAAO,QAAQ,CAAC,WAAW,CAAC,KAAK,UAAU,EAAE;AACpE;AACA,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,0BAA0B,EAAE,WAAW,CAAC,gCAAgC,CAAC,EAAC;AAC5F,IAAI,MAAM;AACV,I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"}
1
+ {"version":3,"file":"actionsDispatcher.js","sources":["../../../src/utils/actionsDispatcher.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2024 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * actionsDispatcher — unified action dispatcher for v2 manifest actions.\n *\n * Dispatches an action object against a context. All dispatch types are\n * handled without throwing — errors surface as console.warn calls.\n * Types: handler | open-modal | open-page | navigate | object-op (the\n * declarative OpenRegister mutation verb added by ADR-049 — dispatched\n * via the shared object store, intent-only, RBAC stays server-side) |\n * export (opens the shared CnMassExportDialog export launcher configured\n * via the action's `entities[]` / `formats[]` — Wave 1 of\n * nextcloud-vue#91; the host page provides `context.openExport`) |\n * open-form (Wave 3 — schema-driven create dialog; the rendering host\n * provides `context.openForm`) | refresh (Wave 3 — bumps the page-level\n * refresh signal on the `cn:page:refresh` event-bus channel) | api-call\n * (Wave 3 — POST/PUT a configured app endpoint with success/error toasts\n * and an automatic page refresh; any `confirm` on the action is INTENT\n * consumed by the rendering surface BEFORE dispatch, like object-op) |\n * agent (run a governed hermiq agent against the page object via\n * POST /apps/hermiq/api/agents/{agent}/run-on-object — hermiq#41; a\n * first-class companion to api-call that resolves the register/schema/\n * objectId context for the author and fail-closes when hermiq is absent) |\n * run-node (manifest-run-node-action — invoke ONE OpenRegister flow node\n * directly against a subject object via\n * POST /api/flows/{flowId}/nodes/{nodeId}/run; the rendering surface\n * provides context.openRunNode, mirroring open-form, and resolves the\n * node's own declared config form before opening a dialog — see or-flow-run-node).\n *\n * `api-call`'s request body prefers `payload` (DEEP @-token resolution at\n * any nesting depth — object/array, e.g. a Filinq-style\n * `{ dataRefs: [{ id: '@objectId' }] }` body) over the legacy `params`\n * (shallow, one-level filter-map resolution, kept for back-compat). Set\n * `download: true` to request a binary blob response and trigger a\n * browser file download instead of a JSON toast+refresh cycle (filename:\n * `Content-Disposition` header, else the token-resolved `filename`, else\n * `'download.pdf'`; no auto-refresh unless `refresh: true` is explicit).\n *\n * `toggle` (Wave 3) is deliberately NOT dispatchable: a toggle is a\n * stateful two-way control (GET state on mount, write on click) rendered\n * by the header-actions surface (CnActionButtons); dispatching it here\n * warns and no-ops.\n *\n * Spec: REQ-MVR-011 (manifest-v2-renderer) — unified actions dispatcher\n * / ADR-036 Decision 7 / ADR-049 Decision 2 / #91 Wave 3\n */\n\nimport { emit } from '@nextcloud/event-bus'\nimport { translate as t } from '@nextcloud/l10n'\nimport { parseDispositionFilename, triggerBlobDownload } from '../components/CnIndexPage/selfModeIO.js'\nimport { interpolateUrlTokens } from '../composables/useEndpointSource.js'\nimport { routeHref } from './actionLink.js'\nimport { resolveModalEntry } from './builtInModals.js'\nimport {\n\tdropOptionalUnresolved,\n\tdropOptionalUnresolvedDeep,\n\thasUnresolvedDeepTokens,\n\thasUnresolvedTokens,\n\tresolveDeepTokens,\n\tresolveFilterTokens,\n} from './resolveFilterTokens.js'\nimport { schemaRefSlug } from './schemaRefSlug.js'\n\n/** Event-bus channel the page-level Refresh signal broadcasts on (Wave 2). */\nconst PAGE_REFRESH_CHANNEL = 'cn:page:refresh'\n\n/**\n * Whether a `navigate` target leaves the app: it is `http(s)://`,\n * protocol-relative (`//`), or a `mailto:` / `tel:` link. Anything else is an\n * in-app path for the router.\n *\n * vue-router happily accepts an absolute URL as a PATH — `router.push` on\n * `https://youtu.be/x?v=1` matches no route and lands on the fallback with the\n * query carried over, which reads as the app ignoring the link.\n *\n * An allowlist, not a generic `<scheme>://` match: manifests are\n * admin-editable app-wide config, and an external target renders into an\n * anchor `href` and a dispatcher `window.open` — a generic scheme match would\n * accept `javascript://` too.\n *\n * @param {unknown} target The action target to test.\n * @return {boolean} True when the target is external.\n */\nexport function isExternalActionTarget(target) {\n\tif (typeof target !== 'string') {\n\t\treturn false\n\t}\n\treturn /^\\/\\//.test(target) || /^(https?|mailto|tel):/i.test(target)\n}\n\n/**\n * Resolve the object-store type slug for a widget `source` register/schema\n * pair. Reuses an already-registered type whose config matches (so an app's\n * own caches stay coherent); otherwise registers a deterministic\n * `<register>/<schema>` slug on the fly.\n *\n * `source.schema` is routed through {@link schemaRefSlug} before it ever\n * reaches the store or the objects API: a caller that passes a `$ref`\n * schema TITLE (`ReportPeriod`) rather than its slug (`report-period`)\n * would otherwise register — and fetch — a 404 (defect 7, learniq round\n * 1). Idempotent for a caller that already passes a correct slug.\n *\n * A caller that already holds the schema SLUG (not a `$ref` title) passes\n * `{ exactSchema: true }`: the slug is then used exactly as given. Kebab-casing\n * a real camelCase slug (`productCategory` -> `product-category`) asks the\n * objects API for a schema that does not exist and 404s (pipelinq review,\n * round two).\n *\n * @spec openspec/changes/review-round-two/specs/schema-utilities/spec.md\n *\n * A title is not always registered under its kebab form: learniq holds\n * `LearniqSettings` and `SubjectTeacherAssignment` as written. So a type\n * registered here for a value the kebab rule CHANGED also carries the value\n * as written as its `schemaFallback`, and the store retries with it once\n * when the kebab form answers 404 (keeping it from then on). The kebab form\n * is still tried first, so a schema registered under it costs nothing.\n *\n * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-a-schema-title-falls-back-to-its-written-form\n * @param {object} store The object store instance (useObjectStore shape).\n * @param {{register: (string|number), schema: (string|number)}} source The widget source.\n * @param {{exactSchema: (boolean|undefined)}} [options] `exactSchema: true` skips the title-to-slug step.\n * @return {string} The type slug to use for store CRUD calls.\n */\nexport function resolveObjectOpType(store, source, options = {}) {\n\tconst register = String(source.register)\n\tconst schema = options.exactSchema === true ? String(source.schema) : String(schemaRefSlug(source.schema))\n\tconst written = typeof source.schema === 'string'\n\t\t? source.schema.substring(source.schema.lastIndexOf('/') + 1)\n\t\t: ''\n\tconst registry = store.objectTypeRegistry || {}\n\tfor (const [slug, config] of Object.entries(registry)) {\n\t\tif (!config) {\n\t\t\tcontinue\n\t\t}\n\t\tif ((String(config.register) === register && String(config.schema) === schema)\n\t\t\t|| (config.registerSlug === register && config.schemaSlug === schema)) {\n\t\t\treturn slug\n\t\t}\n\t}\n\tconst slug = `${register}/${schema}`\n\tif (!registry[slug]) {\n\t\tstore.registerObjectType(slug, schema, register)\n\t\tif (written !== '' && written !== schema && typeof store.setSchemaFallback === 'function') {\n\t\t\tstore.setSchemaFallback(slug, written)\n\t\t}\n\t}\n\treturn slug\n}\n\n/**\n * Extract an OpenRegister object's id from a row (top-level `id` wins,\n * `@self.id` metadata fallback).\n *\n * @param {object} row The row object.\n * @return {string|number|null} The object id, or null when absent.\n */\nfunction rowObjectId(row) {\n\tif (!row || typeof row !== 'object') {\n\t\treturn null\n\t}\n\tif (row.id !== undefined && row.id !== null) {\n\t\treturn row.id\n\t}\n\tconst self = row['@self']\n\tif (self && typeof self === 'object' && self.id !== undefined && self.id !== null) {\n\t\treturn self.id\n\t}\n\treturn null\n}\n\n/**\n * Extract a saved OpenRegister object's id for a post-save deep-link:\n * top-level `id`, then `uuid`, then the `@self.id` metadata fallback.\n *\n * @param {object} saved The saved record returned by the object store.\n * @return {string|number|null} The object id, or null when absent.\n */\nexport function savedObjectId(saved) {\n\tif (!saved || typeof saved !== 'object') {\n\t\treturn null\n\t}\n\tif (saved.id !== undefined && saved.id !== null) {\n\t\treturn saved.id\n\t}\n\tif (saved.uuid !== undefined && saved.uuid !== null) {\n\t\treturn saved.uuid\n\t}\n\tconst self = saved['@self']\n\tif (self && typeof self === 'object' && self.id !== undefined && self.id !== null) {\n\t\treturn self.id\n\t}\n\treturn null\n}\n\n/**\n * Resolve a manifest-named FUNCTION out of the v2 registry, falling back to the\n * legacy customComponents map.\n *\n * A manifest names a behaviour the same way it names a component — by string —\n * so every surface that dispatches one (`actions[].handler`,\n * `bulkActions[].handler`, `headerActions[].handler`, `config.createOverride`)\n * has to agree on where that string is looked up and what counts as a match.\n * Recognised shapes, in order:\n * 1. a registry entry exposing the function as `.handler` / `.fn` (the\n * `kind: 'handler'` and `kind: 'create-override'` entries),\n * 2. a directly function-valued registry entry,\n * 3. a function-valued legacy `customComponents` entry.\n *\n * The legacy map stays last so an app that has not migrated is unchanged, and\n * so an app mid-migration can move its handlers over one at a time.\n *\n * @param {string} name The registered handler name.\n * @param {object} registry The v2 component registry.\n * @param {object} customComponents The legacy customComponents map.\n * @return {?((scope?: object) => unknown)} The handler, or null when nothing of that name is a function.\n */\nexport function resolveRegisteredHandler(name, registry, customComponents) {\n\tif (typeof name !== 'string' || name === '') {\n\t\treturn null\n\t}\n\tconst entry = (registry || {})[name]\n\tif (typeof entry === 'function') {\n\t\treturn entry\n\t}\n\tif (entry && typeof entry === 'object') {\n\t\tif (typeof entry.handler === 'function') {\n\t\t\treturn entry.handler\n\t\t}\n\t\tif (typeof entry.fn === 'function') {\n\t\t\treturn entry.fn\n\t\t}\n\t}\n\tconst legacy = (customComponents || {})[name]\n\treturn typeof legacy === 'function' ? legacy : null\n}\n\n/**\n * Resolve a named create-override handler out of the v2 registry (or the\n * legacy customComponents map) by value shape.\n *\n * A create-override is a plain async function that replaces the default\n * `objectStore.saveObject` persist path — needed whenever a schema requires a\n * field the create form cannot supply on its own (a server-minted foreign key,\n * say).\n *\n * Shared by CnPageRenderer (page-level `config.createOverride` → CnIndexPage's\n * prop) and CnActionButtons (per-action `createOverride` on an `open-form`), so\n * the two surfaces cannot drift on what counts as a valid handler.\n *\n * @param {string} name The registered handler name.\n * @param {object} registry The v2 component registry.\n * @param {object} customComponents The legacy customComponents map.\n * @return {?((props?: object) => Promise<unknown>)} The async create handler, or null when unresolved.\n */\nexport function resolveCreateOverrideHandler(name, registry, customComponents) {\n\treturn resolveRegisteredHandler(name, registry, customComponents)\n}\n\n/**\n * Build the vue-router push location for an `open-form` action's\n * `onSuccessRoute`, merging the saved object's id into the route params so\n * the post-save navigation can deep-link to the created object's detail page\n * (#91).\n *\n * `onSuccessRoute` may be:\n * - a STRING route NAME → `{ name, params: { id } }`. The saved id lands\n * under the default `id` param; a route without an `:id` segment simply\n * ignores the extra param, so a bare-name route keeps working unchanged\n * (backward compatible).\n * - an OBJECT `{ name, paramField?, objectParam? }` → the id is placed\n * under `paramField` (default `id`), and — when `objectParam` is set —\n * the whole saved object is passed under that param key too (so a\n * `props: true` detail route can render the record without a refetch).\n *\n * The id is read via {@link savedObjectId} (`saved.id` → `saved.uuid` →\n * `saved['@self'].id`). Returns `null` when no route name is resolvable, so\n * the caller can skip the navigation.\n *\n * @param {(string|{name: string, paramField?: string, objectParam?: string})} onSuccessRoute The action's onSuccessRoute config.\n * @param {object} saved The saved OpenRegister object.\n * @return {{name: string, params: object}|null} The router push location, or null.\n */\nexport function buildOnSuccessRoute(onSuccessRoute, saved) {\n\tconst spec = typeof onSuccessRoute === 'string'\n\t\t? { name: onSuccessRoute }\n\t\t: (onSuccessRoute && typeof onSuccessRoute === 'object' ? onSuccessRoute : null)\n\tif (!spec || typeof spec.name !== 'string' || spec.name === '') {\n\t\treturn null\n\t}\n\tconst params = {}\n\tconst id = savedObjectId(saved)\n\tif (id !== null && id !== undefined) {\n\t\tparams[spec.paramField || 'id'] = id\n\t}\n\tif (spec.objectParam && saved && typeof saved === 'object') {\n\t\tparams[spec.objectParam] = saved\n\t}\n\treturn { name: spec.name, params }\n}\n\n/**\n * Run a manifest-authored toast message through the host translate function.\n *\n * `successMessage` / `errorMessage` are English source strings authored in the\n * manifest (ADR-007), so they need the SAME translator the rest of the page\n * chrome uses — the consumer's bound `t()`, handed to the dispatcher by the\n * rendering surface as `context.translate` (which itself comes from the\n * `cnTranslate` CnAppRoot provides).\n *\n * A pure pass-through: with no translator, no message, or a catalogue that\n * lacks the key, the message is returned byte-identical. Server-supplied\n * messages are data and are never routed through here.\n *\n * @param {unknown} message The manifest-authored message (may be undefined).\n * @param {object} context The dispatch context (`context.translate` optional).\n * @return {unknown} The translated message, or the input unchanged.\n */\nfunction translateMessage(message, context) {\n\tconst fn = context && context.translate\n\tif (!message || typeof fn !== 'function') {\n\t\treturn message\n\t}\n\treturn fn(message)\n}\n\n/**\n * Interpolate the `api-call` URL/filename token grammar inside a string:\n * the `{objectId}` BRACE convention (a literal placeholder some manifests\n * use for path templates, matching the OpenRegister credential-broker path\n * style) as well as the full `@objectId` / `@object.<field>` /\n * `@workspace.<key>` / `@config.<key>` grammar {@link interpolateUrlTokens}\n * already understands. Unresolved `@`-tokens and an unresolved\n * `{objectId}` both collapse to an empty string (never leak a literal\n * placeholder into a request URL or a downloaded filename).\n *\n * @param {string} str The raw string (an action's `url` or `filename`).\n * @param {{objectId?: (string|number), object?: object, workspace?: object, config?: object}} ctx Token context.\n * @return {string} The interpolated string.\n */\nfunction interpolateActionString(str, ctx) {\n\tif (typeof str !== 'string') {\n\t\treturn str\n\t}\n\tconst braced = str.replace(/\\{objectId\\}/g, () => {\n\t\tconst id = ctx.objectId\n\t\treturn (id === undefined || id === null) ? '' : String(id)\n\t})\n\treturn interpolateUrlTokens(braced, ctx)\n}\n\n/**\n * Interpolate an action's `target` URL — the same grammar `url` runs.\n *\n * Exported because the rendering surface resolves a target BEFORE deciding\n * whether it is an external link, and that decision happens there rather than\n * in the dispatcher.\n *\n * @param {string} target The action's raw `target`.\n * @param {object} ctx Token context (`{ objectId?, object?, workspace?, config? }`).\n *\n * @return {string} The interpolated target.\n */\nexport function interpolateActionTarget(target, ctx) {\n\treturn interpolateActionString(target || '', ctx || {})\n}\n\n// The tokens interpolateActionString resolves; a bare `@` or `{` is not one.\nconst ACTION_TARGET_TOKEN = /@(?:objectId|object\\.|page\\.|workspace\\.|config\\.|range\\.)|\\{objectId\\}/\n\n/**\n * Whether an action target carries a token that interpolation would resolve,\n * so it can only be known once the page context is. A `mailto:` address or a\n * URL with an `@handle` in it has none.\n *\n * @param {string} target The action's raw `target`.\n * @return {boolean}\n */\nexport function hasActionTargetTokens(target) {\n\treturn typeof target === 'string' && ACTION_TARGET_TOKEN.test(target)\n}\n\n/**\n * The link an action renders as when its only job is to navigate to a target\n * known at render time: `navigate` (token-interpolated like the dispatcher)\n * and `open-page`. Anything else, a `confirm: true` action, or an in-app\n * target the router cannot resolve answers null and keeps dispatching.\n *\n * `to` is what a plain click hands the router (null for an external URL,\n * which the browser opens in a new tab like the dispatcher's `window.open`).\n *\n * @param {object} action The manifest action.\n * @param {{router?: object, tokenCtx?: object}} [context] The dispatch context.\n * @return {{href: string, to: (string|object|null), external: boolean}|null} The link, or null.\n */\nexport function actionLink(action, context = {}) {\n\tif (!action || typeof action !== 'object' || action.confirm) {\n\t\treturn null\n\t}\n\tif (action.type === 'navigate') {\n\t\tconst target = interpolateActionString(action.target || '', context.tokenCtx || {})\n\t\tif (!target) {\n\t\t\treturn null\n\t\t}\n\t\tif (isExternalActionTarget(target)) {\n\t\t\treturn { href: target, to: null, external: true }\n\t\t}\n\t\tconst href = routeHref(target, context.router)\n\t\treturn href ? { href, to: target, external: false } : null\n\t}\n\tif (action.type === 'open-page') {\n\t\tif (typeof action.target !== 'string' || action.target.length === 0) {\n\t\t\treturn null\n\t\t}\n\t\tconst to = { name: action.target }\n\t\tconst href = routeHref(to, context.router)\n\t\treturn href ? { href, to, external: false } : null\n\t}\n\treturn null\n}\n\n/**\n * Execute a Wave-3 `api-call` action: POST/PUT the configured app endpoint\n * (URL + body run the SAME @-token grammar endpoint sources use), toast the\n * outcome via @nextcloud/dialogs, then — unless `action.refresh` is `false`\n * (or, for a `download` action, unless `action.refresh` is explicitly\n * `true`) — bump the page-level refresh signal so every endpoint-bound\n * widget refetches. Confirm-gating is the RENDERING SURFACE's job (the\n * `confirm` field is intent, object-op precedent): this runs after any\n * confirmation already happened.\n *\n * The request body prefers `action.payload` (DEEP token resolution, any\n * nesting — {@link resolveDeepTokens}) over the legacy `action.params`\n * (shallow, one-level filter-map resolution — unchanged for back-compat).\n * A required token left unresolved anywhere in the body BLOCKS the call\n * (error toast) rather than sending a literal `@objectId` to the server.\n *\n * `action.download === true` requests the response as a binary blob\n * (`responseType: 'blob'`) and triggers a browser file download — the\n * filename comes from the response's `Content-Disposition` header, else\n * the token-resolved `action.filename`, else `'download.pdf'`.\n *\n * Never throws: a failed call resolves `{ ok: false, error }` after the\n * error toast (so a confirm dialog can await the outcome).\n *\n * @param {object} action The api-call action (`url`, `method?`, `payload?`,\n * `params?`, `download?`, `filename?`, `successMessage?`, `errorMessage?`,\n * `refresh?`).\n * @param {object} context Runtime context; `context.tokenCtx` is the token\n * context (`{ objectId?, object?, workspace?, config? }`) the URL/body\n * resolve against.\n * @return {Promise<{ok: boolean, data?: unknown, error?: unknown}>} The call outcome.\n */\nasync function executeApiCall(action, context) {\n\tconst tokenCtx = context.tokenCtx || {}\n\tconst url = interpolateActionString(action.url || '', tokenCtx)\n\n\tconst hasPayload = action.payload && typeof action.payload === 'object' && !Array.isArray(action.payload)\n\tconst body = hasPayload\n\t\t? dropOptionalUnresolvedDeep(resolveDeepTokens(action.payload, tokenCtx))\n\t\t: dropOptionalUnresolved(resolveFilterTokens(action.params || {}, tokenCtx))\n\tconst bodyBlocked = hasPayload ? hasUnresolvedDeepTokens(body) : hasUnresolvedTokens(body)\n\n\tif (!url || bodyBlocked) {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.warn('[dispatchAction] api-call is missing its url or a required token is unresolved — skipping.', action)\n\t\treturn { ok: false, error: new Error('api-call blocked') }\n\t}\n\tconst method = String(action.method || 'POST').toUpperCase() === 'PUT' ? 'put' : 'post'\n\tconst isDownload = action.download === true\n\tconst [{ default: axios }, { generateUrl }, dialogs] = await Promise.all([\n\t\timport('@nextcloud/axios'),\n\t\timport('@nextcloud/router'),\n\t\timport('@nextcloud/dialogs'),\n\t])\n\tconst target = /^https?:\\/\\//i.test(url) ? url : generateUrl(url)\n\ttry {\n\t\t// Only pass a third axios config arg for a download call — an\n\t\t// explicit `undefined` third argument would otherwise change the\n\t\t// call shape for every existing (non-download) api-call consumer/test.\n\t\tconst res = isDownload\n\t\t\t? await axios[method](target, body, { responseType: 'blob' })\n\t\t\t: await axios[method](target, body)\n\t\tif (isDownload) {\n\t\t\tconst filename = parseDispositionFilename(\n\t\t\t\tres && res.headers && res.headers['content-disposition'],\n\t\t\t\tinterpolateActionString(action.filename, tokenCtx) || 'download.pdf',\n\t\t\t)\n\t\t\ttriggerBlobDownload(res.data, filename)\n\t\t}\n\t\tif (typeof dialogs.showSuccess === 'function') {\n\t\t\tdialogs.showSuccess(translateMessage(action.successMessage, context) || t('nextcloud-vue', 'Action completed.'))\n\t\t}\n\t\tconst shouldRefresh = isDownload ? action.refresh === true : action.refresh !== false\n\t\tif (shouldRefresh) {\n\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t}\n\t\treturn { ok: true, data: res && res.data }\n\t} catch (error) {\n\t\tconst serverMessage = error && error.response && error.response.data\n\t\t\t&& (error.response.data.error || error.response.data.message)\n\t\tif (typeof dialogs.showError === 'function') {\n\t\t\tdialogs.showError(translateMessage(action.errorMessage, context) || serverMessage || t('nextcloud-vue', 'Action failed.'))\n\t\t}\n\t\treturn { ok: false, error }\n\t}\n}\n\n/**\n * Resolve an agent-action object reference (`register` / `schema` / `objectId`):\n * an explicitly-declared action value WINS (it may itself be an @-token string,\n * interpolated against the token context), otherwise it falls back to the page\n * object context default (`tokenCtx.register` / `.schema` / `.objectId`). An\n * unresolved token collapses to an empty string (never leaks a literal `@objectId`\n * to the server); a `{ slug | id }` object (a schema holder) is flattened to its\n * slug/id.\n *\n * @param {unknown} actionVal The action's explicit value (may be undefined or an @-token).\n * @param {unknown} ctxDefault The page-context default (`tokenCtx.<field>`).\n * @param {object} tokenCtx The token context the @-tokens resolve against.\n * @return {string} The resolved reference, or '' when unresolved/absent.\n */\nfunction resolveAgentRef(actionVal, ctxDefault, tokenCtx) {\n\tlet v = actionVal\n\tif (v === undefined || v === null || v === '') {\n\t\tv = ctxDefault\n\t} else if (typeof v === 'string') {\n\t\tv = interpolateActionString(v, tokenCtx)\n\t}\n\tif (v && typeof v === 'object') {\n\t\treturn String(v.slug || v.id || '')\n\t}\n\tif (v === undefined || v === null) {\n\t\treturn ''\n\t}\n\treturn String(v)\n}\n\n/**\n * Execute an `agent` action: run a governed hermiq agent against the page's\n * OpenRegister object. Resolves the object context (`register` / `schema` /\n * `objectId` — explicit action fields override, else default to the page's\n * `@register` / `@schema` / `@objectId` context) and POSTs\n * `{ register, schema, objectId, resultField?, skill?, prompt? }` to hermiq's\n * object-RBAC-scoped run endpoint `/apps/hermiq/api/agents/{agent}/run-on-object`\n * (hermiq#41), which dispatches the governed `AgentRunRequestedEvent`.\n *\n * A first-class companion to `type:\"api-call\"` — the author declares \"run agent\n * here\" without hand-wiring the URL/body. `type:\"api-call\"` remains the escape\n * hatch for a bespoke body.\n *\n * Fail-closed. An unresolved REQUIRED `@objectId` (or a missing agent/register/\n * schema) BLOCKS the call (warn) rather than POSTing a literal token. On the\n * server's 202 it toasts `successMessage` (default 'Run queued') and — unless\n * `refresh: false` — bumps the page refresh signal. A 403 / 404 with a structured\n * error body fail-closes with that message; a 404 with NO structured body is read\n * as \"hermiq absent\" and toasts a graceful 'agent runtime unavailable' — the\n * dispatcher NEVER hard-requires hermiq to be installed. Never throws.\n *\n * @param {object} action The agent action (`agent`, `skill?`, `prompt?`,\n * `resultField?`, `register?`, `schema?`, `objectId?`, `successMessage?`,\n * `errorMessage?`, `refresh?`).\n * @param {object} context Runtime context; `context.tokenCtx` is the token\n * context (`{ objectId?, object?, register?, schema?, workspace?, config? }`).\n * @return {Promise<{ok: boolean, data?: unknown, error?: unknown}>} The call outcome.\n */\nasync function executeAgentAction(action, context) {\n\tconst tokenCtx = context.tokenCtx || {}\n\tconst agent = resolveAgentRef(action.agent, undefined, tokenCtx)\n\tconst register = resolveAgentRef(action.register, tokenCtx.register, tokenCtx)\n\tconst schema = resolveAgentRef(action.schema, tokenCtx.schema, tokenCtx)\n\tconst objectId = resolveAgentRef(action.objectId, tokenCtx.objectId, tokenCtx)\n\n\tif (!agent || !register || !schema || !objectId) {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.warn('[dispatchAction] agent action is missing its agent or a required object-context token (register/schema/objectId) is unresolved — skipping.', action)\n\t\treturn { ok: false, error: new Error('agent action blocked') }\n\t}\n\n\tconst body = { register, schema, objectId }\n\tconst resultField = resolveAgentRef(action.resultField, undefined, tokenCtx)\n\tif (resultField) {\n\t\tbody.resultField = resultField\n\t}\n\tconst skill = resolveAgentRef(action.skill, undefined, tokenCtx)\n\tif (skill) {\n\t\tbody.skill = skill\n\t}\n\tif (typeof action.prompt === 'string' && action.prompt !== '') {\n\t\tbody.prompt = interpolateActionString(action.prompt, tokenCtx)\n\t}\n\n\tconst [{ default: axios }, { generateUrl }, dialogs] = await Promise.all([\n\t\timport('@nextcloud/axios'),\n\t\timport('@nextcloud/router'),\n\t\timport('@nextcloud/dialogs'),\n\t])\n\tconst target = generateUrl(`/apps/hermiq/api/agents/${encodeURIComponent(agent)}/run-on-object`)\n\ttry {\n\t\tconst res = await axios.post(target, body)\n\t\tif (typeof dialogs.showSuccess === 'function') {\n\t\t\tdialogs.showSuccess(translateMessage(action.successMessage, context) || t('nextcloud-vue', 'Run queued'))\n\t\t}\n\t\tif (action.refresh !== false) {\n\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t}\n\t\treturn { ok: true, data: res && res.data }\n\t} catch (error) {\n\t\tconst response = error && error.response\n\t\tconst status = response && response.status\n\t\tconst serverMessage = response && response.data\n\t\t\t&& (response.data.error || response.data.message)\n\t\t// A 404 with NO structured error body = hermiq is not installed (the app\n\t\t// route 404s at the NC level) — surface a graceful \"runtime unavailable\"\n\t\t// rather than a fail-closed authorization message.\n\t\tconst hermiqAbsent = status === 404 && !serverMessage\n\t\tif (typeof dialogs.showError === 'function') {\n\t\t\tconst msg = hermiqAbsent\n\t\t\t\t? t('nextcloud-vue', 'Agent runtime unavailable')\n\t\t\t\t: (translateMessage(action.errorMessage, context) || serverMessage || t('nextcloud-vue', 'Action failed.'))\n\t\t\tdialogs.showError(msg)\n\t\t}\n\t\treturn { ok: false, error }\n\t}\n}\n\n/**\n * POST the run-node call: `POST /apps/openregister/api/flows/{flowId}/nodes/{nodeId}/run`.\n *\n * This is the SECOND half of `run-node` (manifest-run-node-action / or-flow-run-node) —\n * the first half is `context.openRunNode` in the `dispatchAction` switch below, which\n * only OPENS the config dialog (or decides none is needed) and never itself waits for\n * the person. Once the rendering surface has a `config` object (from the dialog's\n * submit, or `{}` when the node's declared form was empty), it calls this directly —\n * it is not reached through `dispatchAction`'s switch, because by that point there is\n * no further \"type\" dispatch to do, only the call itself, same as `executeAgentAction`\n * is called directly by `case 'api-call'`'s sibling rather than re-entering the switch.\n *\n * Fail-closed exactly like `executeAgentAction`: an unresolved REQUIRED subject\n * (`action.subject`, defaulting to the page's `@objectId`) or a missing\n * `flowId`/`nodeId` BLOCKS the call (warn) rather than POSTing a literal token or an\n * incomplete subject reference. The subject sent is `{ uuid, register, schema }` —\n * OpenRegister's `FlowNodeRunController::resolveAuthorizedSubject()` needs all three\n * to resolve the object and evaluate the caller's object-RBAC permission on it; `register`\n * / `schema` default to the page's own `@register` / `@schema` context, the same\n * defaulting `agent` already uses.\n *\n * A 403 here means the caller holds no update permission on the subject\n * (OpenRegister's object-RBAC, evaluated server-side — RN-1(c)) — this function does not\n * special-case it beyond surfacing the server's message, the same fail-closed handling\n * `api-call` / `agent` already give a rejected call.\n *\n * @param {object} action The run-node action (`flowId`, `nodeId`, `subject?`,\n * `register?`, `schema?`, `successMessage?`, `errorMessage?`, `refresh?`).\n * @param {object} context Runtime context — needs `context.tokenCtx` and, for a\n * localised toast, `context.translate`.\n * @param {object} [config] The node's collected config (from its `configForm()`\n * dialog), or `{}` for a node with no declared fields.\n * @return {Promise<{ok: boolean, data?: object, error?: Error}>} The call outcome —\n * `data` is the created `FlowRun` on success.\n *\n * @spec openspec/changes/manifest-run-node-action/specs/manifest-run-node-action/spec.md#requirement-a-run-node-action-invokes-one-flow-node-against-the-page-object\n */\nexport async function postRunNode(action, context, config = {}) {\n\tconst tokenCtx = context.tokenCtx || {}\n\tconst flowId = resolveAgentRef(action.flowId, undefined, tokenCtx)\n\tconst nodeId = resolveAgentRef(action.nodeId, undefined, tokenCtx)\n\tconst uuid = resolveAgentRef(action.subject, tokenCtx.objectId, tokenCtx)\n\tconst register = resolveAgentRef(action.register, tokenCtx.register, tokenCtx)\n\tconst schema = resolveAgentRef(action.schema, tokenCtx.schema, tokenCtx)\n\n\tif (!flowId || !nodeId || !uuid || !register || !schema) {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.warn('[dispatchAction] run-node is missing flowId/nodeId or a required subject token (objectId/register/schema) is unresolved — skipping.', action)\n\t\treturn { ok: false, error: new Error('run-node blocked') }\n\t}\n\n\tconst [{ default: axios }, { generateUrl }, dialogs] = await Promise.all([\n\t\timport('@nextcloud/axios'),\n\t\timport('@nextcloud/router'),\n\t\timport('@nextcloud/dialogs'),\n\t])\n\tconst target = generateUrl(`/apps/openregister/api/flows/${encodeURIComponent(flowId)}/nodes/${encodeURIComponent(nodeId)}/run`)\n\ttry {\n\t\tconst res = await axios.post(target, { subject: { uuid, register, schema }, config: config || {} })\n\t\tif (typeof dialogs.showSuccess === 'function') {\n\t\t\tdialogs.showSuccess(translateMessage(action.successMessage, context) || t('nextcloud-vue', 'Run completed.'))\n\t\t}\n\t\tif (action.refresh !== false) {\n\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t}\n\t\treturn { ok: true, data: res && res.data }\n\t} catch (error) {\n\t\tconst response = error && error.response\n\t\tconst serverMessage = response && response.data\n\t\t\t&& (response.data.error || response.data.message)\n\t\tif (typeof dialogs.showError === 'function') {\n\t\t\tdialogs.showError(translateMessage(action.errorMessage, context) || serverMessage || t('nextcloud-vue', 'Action failed.'))\n\t\t}\n\t\treturn { ok: false, error }\n\t}\n}\n\n/**\n * Dispatch a v2 manifest action.\n *\n * @param {object} action The action object from the manifest.\n * @param {string} [action.type] Dispatch type: \"handler\" | \"open-modal\" | \"open-page\" | \"navigate\" |\n * \"object-op\" | \"export\" | \"open-form\" | \"refresh\" | \"api-call\" | \"agent\".\n * When absent, treated as \"handler\" for v1 backward compatibility.\n * @param {string} [action.handler] Registry key for \"handler\" type. For \"export\": the optional\n * handler invoked by the host with the dialog's confirm payload (`{ format, entity }`).\n * @param {Array} [action.args] Arguments spread to the handler function.\n * @param {string} [action.target] Target for \"open-modal\", \"open-page\", and \"navigate\" types.\n * @param {object} [action.props] Props forwarded to modal for \"open-modal\" type.\n * @param {string} [action.op] \"object-op\" only: mutation verb — \"patch\" | \"delete\" | \"create\".\n * @param {object} [action.values] \"object-op\" only: the verb's payload — the partial object\n * merged over the row for \"patch\", the new object's properties for \"create\"; ignored for \"delete\".\n * @param {boolean} [action.confirm] \"object-op\" only: confirm-gating INTENT consumed by the\n * rendering host (CnWidgetObjectTable routes it through CnConfirmDialog) — the dispatcher\n * itself never gates; it is called after any confirmation already happened.\n * @param {Array<{id: string, label: string}>} [action.entities] \"export\" only: selectable\n * entity types offered by the export launcher (e.g. Leads / Requests). Optional — when\n * absent the dialog shows only the format picker.\n * @param {Array<string|{id: string, label: string}>} [action.formats] \"export\" only: the\n * offered export formats (bare ids like \"csv\" or full `{id, label}` entries). Optional —\n * the dialog's built-in Excel/CSV defaults apply when absent.\n * @param {string} [action.description] \"export\" only: pre-translated description shown\n * above the pickers.\n * @param {string} [action.url] \"api-call\" only: the app endpoint — app-relative (routed\n * through generateUrl) or absolute. May interpolate the shared URL tokens\n * (`@objectId`, `@object.<field>`, `@workspace.<key>`, `@config.<key>`, and the\n * `{objectId}` brace form).\n * @param {string} [action.method] \"api-call\" only: \"POST\" (default) | \"PUT\".\n * @param {object} [action.payload] \"api-call\" only: the JSON body — preferred over `params`.\n * Values resolve the shared `@`-token grammar RECURSIVELY at any nesting depth (objects\n * and arrays of objects, e.g. `{ dataRefs: [{ id: '@objectId' }] }`); optional (`…?`)\n * tokens drop when unresolved anywhere in the tree, an unresolved REQUIRED token blocks\n * the call. When set, `params` is ignored.\n * @param {object} [action.params] \"api-call\" only: legacy JSON body (ignored when `payload`\n * is set). Values pass the shared filter-token grammar ONE level deep; optional (`…?`)\n * tokens drop when unresolved, an unresolved REQUIRED token blocks the call.\n * @param {boolean} [action.download] \"api-call\" only: request the response as a binary blob\n * (`responseType: 'blob'`) and trigger a browser file download instead of a JSON\n * toast+refresh cycle. Default `false`.\n * @param {string} [action.filename] \"api-call\" `download: true` only: fallback filename when\n * the response carries no `Content-Disposition` header (falls back further to\n * `'download.pdf'`). Interpolates the same token grammar as `url`.\n * @param {string} [action.successMessage] \"api-call\" / \"open-form\": pre-translated success\n * toast text (a library default applies when absent).\n * @param {string} [action.errorMessage] \"api-call\" / \"open-form\": pre-translated error toast\n * text (falls back to the server's `error`/`message`, then a library default).\n * @param {boolean} [action.refresh] \"api-call\" / \"agent\" only: bump the `cn:page:refresh` signal\n * after a successful call. Default `true` — EXCEPT for a `download: true` api-call, whose\n * default is `false` (a file download normally shouldn't also force-refetch every widget); set\n * the flag explicitly either way to override.\n * @param {string} [action.agent] \"agent\" only (REQUIRED): the hermiq agent uuid to run against\n * the page object. POSTed to `/apps/hermiq/api/agents/{agent}/run-on-object` (hermiq#41).\n * @param {string} [action.skill] \"agent\" only: optional skill id folded into the governed run.\n * @param {string} [action.prompt] \"agent\" only: optional prompt (interpolates the shared `@`-token\n * grammar inline — `@objectId`, `@object.<field>`, `@workspace.<key>`, `@config.<key>`).\n * @param {string} [action.resultField] \"agent\" only: object field the agent's result is written to.\n * @param {string} [action.register] \"agent\" / \"open-form\": OpenRegister register slug (agent:\n * defaults to the page object context's `@register`).\n * @param {string} [action.schema] \"agent\" / \"open-form\": OpenRegister schema slug (agent: defaults\n * to the page object context's `@schema`).\n * @param {string} [action.objectId] \"agent\" only: the target object id (defaults to the page\n * object context's `@objectId`). An unresolved required token BLOCKS the call (fail-closed).\n *\n * @param {object} context Runtime context.\n * @param {object} [context.router] Vue Router instance. Required for \"open-page\" and \"navigate\".\n * @param {object} [context.registry] Component registry (Record<string, { kind, component }>).\n * Required for \"open-modal\" type.\n * @param {object} [context.handlers] Map of handler name → function. Required for \"handler\" type.\n * @param {(key: string, props?: object) => void} [context.openModal] Opens a modal.\n * Required for \"open-modal\" type.\n * @param {(action: object) => void} [context.openExport] Opens the shared\n * CnMassExportDialog configured from the action. Required for \"export\" type —\n * CnPageRenderer pre-binds it in the `cnDispatchAction` context.\n * @param {(action: object) => void} [context.openForm] Opens the schema-driven\n * create dialog. Required for \"open-form\" type — the rendering surface\n * (CnActionButtons) provides it, mirroring `openExport`. On a successful save the\n * surface navigates to `action.onSuccessRoute` (a route NAME string, or\n * `{name, paramField?, objectParam?}`) via {@link buildOnSuccessRoute}, which merges\n * the saved object's id into the route params so the navigation can deep-link to the\n * created object.\n * @param {(action: object) => void} [context.openRunNode] Opens the\n * node-config dialog (or runs immediately for an empty config form) and\n * POSTs to OpenRegister's direct-invoke endpoint on submit. Required for\n * \"run-node\" type — the rendering surface (CnActionButtons) provides it,\n * mirroring `openForm`.\n * @param {{objectId?: (string|number), object?: object, workspace?: object, config?: object}} [context.tokenCtx]\n * Token context \"api-call\" URLs/params resolve against (the same shape\n * `resolveFilterTokens` / `interpolateUrlTokens` take).\n * @param {(app: string, text: string, vars?: object) => string} [context.translate] The consumer's bound `t()`, the same\n * `cnTranslate` CnAppRoot provides to the page chrome. Applied to the\n * manifest-authored `successMessage` / `errorMessage` of \"api-call\" and\n * \"agent\" so their toasts follow the user's language. Omitted (or a\n * catalogue miss) leaves the message byte-identical.\n * @param {object} [context.objectStore] Object store instance (useObjectStore shape).\n * Required for \"object-op\" type. All mutations go through `saveObject` / `deleteObject`\n * so store caches (and their no-mutation-on-error semantics) apply.\n * @param {{register: (string|number), schema: (string|number)}} [context.source] The widget's\n * declarative source the mutation targets. Required for \"object-op\" type.\n * @param {object} [context.row] The row object a row-scoped \"object-op\" (patch/delete) mutates.\n *\n * @return {Promise<object|boolean|null>|undefined} For \"object-op\": the store call's promise —\n * the saved object (or `null` on a rejected write) for patch/create, `true`/`false` for\n * delete. The store only mutates its local caches on SUCCESS, so a backend (RBAC) rejection\n * surfaces via the store's `errors[type]` without any local state change. For \"api-call\":\n * a promise of `{ ok, data?, error? }` (toasts + refresh already handled). All other types\n * return undefined.\n */\nexport function dispatchAction(action, context = {}) {\n\tif (!action || typeof action !== 'object') {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.warn('[dispatchAction] Received invalid action:', action)\n\t\treturn\n\t}\n\n\t// Missing type is treated as \"handler\" for v1 backward compatibility\n\tconst type = action.type || 'handler'\n\n\tswitch (type) {\n\t\tcase 'handler': {\n\t\t\tconst handlerName = action.handler\n\t\t\tconst handlers = context.handlers || {}\n\n\t\t\tif (!handlerName || typeof handlers[handlerName] !== 'function') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[dispatchAction] Handler \"${handlerName}\" not found in context.handlers.`)\n\t\t\t\treturn\n\t\t\t}\n\t\t\thandlers[handlerName](...(action.args ?? []))\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'open-modal': {\n\t\t\tconst target = action.target\n\t\t\tconst entry = resolveModalEntry(context.registry, target)\n\n\t\t\tif (!entry) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[dispatchAction] open-modal target \"${target}\" not found in registry.`)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (entry.kind !== 'modal') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[dispatchAction] open-modal target \"${target}\" has kind \"${entry.kind}\" (expected \"modal\").`)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (typeof context.openModal !== 'function') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] open-modal requires context.openModal to be a function.')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tcontext.openModal(target, action.props ?? {})\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'open-page': {\n\t\t\tif (!context.router) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] open-page requires context.router to be a Vue Router instance.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcontext.router.push({ name: action.target })\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'navigate': {\n\t\t\t// A target is a URL exactly as `url` is, so it runs the same token\n\t\t\t// grammar. Without this a manifest's `{objectId}` reached the router\n\t\t\t// as those nine literal characters and landed in the address bar.\n\t\t\tconst target = interpolateActionString(action.target || '', context.tokenCtx || {})\n\n\t\t\t// An external target is not a route. Rendering surfaces should give it\n\t\t\t// to the browser as a real link (CnActionButtons does); this is the\n\t\t\t// fallback for a programmatic dispatch, and it must not reach the\n\t\t\t// router — see isExternalActionTarget.\n\t\t\tif (isExternalActionTarget(target)) {\n\t\t\t\twindow.open(target, '_blank', 'noopener,noreferrer')\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (!context.router) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] navigate requires context.router to be a Vue Router instance.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcontext.router.push(target)\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'export': {\n\t\t// Export launcher (Wave 1, nextcloud-vue#91): the host page opens the\n\t\t// shared CnMassExportDialog configured via the action's entities[] /\n\t\t// formats[]; the dialog's confirm payload routes to the action's\n\t\t// optional `handler` (the app's export service does the download).\n\t\t\tif (typeof context.openExport !== 'function') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] export requires context.openExport to be a function.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcontext.openExport(action)\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'open-form': {\n\t\t// Schema-driven create dialog (Wave 3, nextcloud-vue#91): the\n\t\t// rendering surface (CnActionButtons) mounts the shared\n\t\t// CnAdvancedFormDialog and handles the save — mirroring how\n\t\t// `export` delegates to the host's CnMassExportDialog.\n\t\t\tif (typeof context.openForm !== 'function') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] open-form requires context.openForm to be a function.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcontext.openForm(action)\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'run-node': {\n\t\t// Direct flow-node invocation (manifest-run-node-action / RN-4):\n\t\t// SAME shape as open-form, deliberately — the rendering surface\n\t\t// (CnActionButtons) resolves the node's own config form, opens a\n\t\t// generic dialog when it has fields (skips it when empty), and\n\t\t// POSTs subject+config to OpenRegister's\n\t\t// /api/flows/{flowId}/nodes/{nodeId}/run on submit. This case\n\t\t// resolves as soon as the dialog OPENS (or the empty-form call\n\t\t// starts) — it does NOT wait for the person to answer, matching\n\t\t// every other consumer's assumption that dispatchAction's Promise\n\t\t// means \"the call happened\", not \"the human decided\" (see design.md\n\t\t// RN-4 for why an awaiting-on-UI shape was rejected).\n\t\t\tif (typeof context.openRunNode !== 'function') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] run-node requires context.openRunNode to be a function.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcontext.openRunNode(action)\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'refresh': {\n\t\t// Page-level refresh (Wave 3, nextcloud-vue#91): bump the SAME\n\t\t// `cn:page:refresh` event-bus signal the page overflow menu's\n\t\t// Refresh item broadcasts — every endpoint-bound / bus-subscribed\n\t\t// widget on the page force-refetches past its shared cache.\n\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t\tbreak\n\t\t}\n\n\t\tcase 'api-call': {\n\t\t// POST/PUT an app endpoint + toast + refresh (Wave 3). Any\n\t\t// `confirm` on the action is INTENT the rendering surface consumed\n\t\t// BEFORE calling the dispatcher (object-op precedent) — no gating\n\t\t// happens here.\n\t\t\treturn executeApiCall(action, context)\n\t\t}\n\n\t\tcase 'agent': {\n\t\t// Run a governed hermiq agent against the page object (hermiq#41). A\n\t\t// first-class companion to api-call: resolves the object context\n\t\t// (register/schema/objectId) and POSTs run-on-object. Any `confirm`\n\t\t// on the action is INTENT the rendering surface consumed BEFORE\n\t\t// dispatch (api-call / object-op precedent) — no gating here. hermiq\n\t\t// is NOT hard-required: an app-level 404 surfaces a graceful toast.\n\t\t\treturn executeAgentAction(action, context)\n\t\t}\n\n\t\tcase 'toggle': {\n\t\t// A toggle is a stateful two-way control (GET state on mount,\n\t\t// write on click) — it is RENDERED by the header-actions surface\n\t\t// (CnActionButtons), never dispatched as a one-shot action.\n\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn('[dispatchAction] \"toggle\" is a stateful header-actions control rendered by CnActionButtons — it cannot be dispatched.')\n\t\t\treturn\n\t\t}\n\n\t\tcase 'object-op': {\n\t\t// Declarative mutation of an OpenRegister object, dispatched via the\n\t\t// shared object store (ADR-049). The manifest declares INTENT only:\n\t\t// authorization-shaped fields on the action (`role`, `allow`, …) are\n\t\t// NEVER consulted here — OpenRegister RBAC is the single authority\n\t\t// (ADR-022 / ADR-023) and a forbidden mutation is rejected server-side.\n\t\t// The store mutates its caches only on success, so a rejected write\n\t\t// surfaces as an error with no local state change.\n\t\t\tconst op = action.op\n\t\t\tif (op !== 'patch' && op !== 'delete' && op !== 'create') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[dispatchAction] object-op has invalid op \"${op}\" (expected patch | delete | create).`)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst store = context.objectStore\n\t\t\tif (!store || typeof store.saveObject !== 'function' || typeof store.deleteObject !== 'function') {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] object-op requires context.objectStore (useObjectStore shape).')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst source = context.source\n\t\t\tif (!source || !source.register || !source.schema) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[dispatchAction] object-op requires context.source with register + schema.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst type = resolveObjectOpType(store, source)\n\n\t\t\tif (op === 'create') {\n\t\t\t\treturn store.saveObject(type, { ...(action.values || {}) })\n\t\t\t}\n\n\t\t\tconst row = context.row\n\t\t\tconst id = rowObjectId(row)\n\t\t\tif (id === null) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[dispatchAction] object-op \"${op}\" is row-scoped and requires context.row with an id.`)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (op === 'delete') {\n\t\t\t\treturn store.deleteObject(type, id)\n\t\t\t}\n\t\t\t// patch: only the action's values, as a PATCH, so every other key\n\t\t\t// keeps its stored value. A store without patchObject writes the\n\t\t\t// row's object merged with the values.\n\t\t\tif (typeof store.patchObject === 'function') {\n\t\t\t\treturn store.patchObject(type, id, { ...(action.values || {}) })\n\t\t\t}\n\t\t\treturn store.saveObject(type, { ...row, ...(action.values || {}), id })\n\t\t}\n\n\t\tdefault:\n\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(`[dispatchAction] Unknown action type \"${type}\".`)\n\t}\n}\n"],"names":["t"],"mappings":"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AG;AACH,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;AAC7B,EAAE;AACF,CAAC;AACD;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;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;AACO,SAAS,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE;AACrD,CAAC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC5C;AACA,EAAE,OAAO,CAAC,IAAI,CAAC,2CAA2C,EAAE,MAAM,EAAC;AACnE,EAAE,MAAM;AACR,EAAE;AACF;AACA;AACA,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,UAAS;AACtC;AACA,CAAC,QAAQ,IAAI;AACb,EAAE,KAAK,SAAS,EAAE;AAClB,GAAG,MAAM,WAAW,GAAG,MAAM,CAAC,QAAO;AACrC,GAAG,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,GAAE;AAC1C;AACA,GAAG,IAAI,CAAC,WAAW,IAAI,OAAO,QAAQ,CAAC,WAAW,CAAC,KAAK,UAAU,EAAE;AACpE;AACA,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,0BAA0B,EAAE,WAAW,CAAC,gCAAgC,CAAC,EAAC;AAC5F,IAAI,MAAM;AACV,I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"}
@@ -14,13 +14,15 @@ import { defineAsyncComponent } from 'vue';
14
14
  /**
15
15
  * The built-in modals, as registry entries (`{ kind: 'modal', component }`):
16
16
  * `CnActionDialog`, the generic summary, checklist, reason and confirm dialog,
17
- * its `config` in the action's `props`. Loaded on first open.
17
+ * and `CnAssignDialog`, hand a record to another user or team; each takes its
18
+ * `config` in the action's `props`. Loaded on first open.
18
19
  *
19
20
  * @type {Readonly<Record<string, {kind: string, component: object}>>}
20
21
  * @spec openspec/changes/action-dialog/specs/action-dialog/spec.md#requirement-a-manifest-configures-an-action-dialog
21
22
  */
22
23
  const BUILT_IN_MODALS = Object.freeze({
23
24
  CnActionDialog: { kind: 'modal', component: defineAsyncComponent(() => import('../components/CnActionDialog/CnActionDialog.vue.js')) },
25
+ CnAssignDialog: { kind: 'modal', component: defineAsyncComponent(() => import('../components/CnAssignDialog/CnAssignDialog.vue.js')) },
24
26
  });
25
27
 
26
28
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"builtInModals.js","sources":["../../../src/utils/builtInModals.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * Modals every app can open by name with an `open-modal` action, without\n * registering them. An app's own registry entry of the same name wins.\n *\n * @module utils/builtInModals\n */\n\nimport { defineAsyncComponent } from 'vue'\n\n/**\n * The built-in modals, as registry entries (`{ kind: 'modal', component }`):\n * `CnActionDialog`, the generic summary, checklist, reason and confirm dialog,\n * its `config` in the action's `props`. Loaded on first open.\n *\n * @type {Readonly<Record<string, {kind: string, component: object}>>}\n * @spec openspec/changes/action-dialog/specs/action-dialog/spec.md#requirement-a-manifest-configures-an-action-dialog\n */\nexport const BUILT_IN_MODALS = Object.freeze({\n\tCnActionDialog: { kind: 'modal', component: defineAsyncComponent(() => import('../components/CnActionDialog/CnActionDialog.vue')) },\n})\n\n/**\n * The registry entry for a modal name: the app's own, else a built-in one.\n *\n * @param {object|null} registry The app's registry.\n * @param {string} name The modal's name.\n * @return {object|null} The entry, or null.\n */\nexport function resolveModalEntry(registry, name) {\n\tconst own = registry && typeof registry === 'object' ? registry[name] : undefined\n\treturn own || BUILT_IN_MODALS[name] || null\n}\n"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC;AAC7C,CAAC,cAAc,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,oBAAoB,CAAC,MAAM,OAAO,oDAAiD,CAAC,CAAC,EAAE;AACpI,CAAC,EAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,iBAAiB,CAAC,QAAQ,EAAE,IAAI,EAAE;AAClD,CAAC,MAAM,GAAG,GAAG,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,UAAS;AAClF,CAAC,OAAO,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,IAAI;AAC5C;;;;"}
1
+ {"version":3,"file":"builtInModals.js","sources":["../../../src/utils/builtInModals.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * Modals every app can open by name with an `open-modal` action, without\n * registering them. An app's own registry entry of the same name wins.\n *\n * @module utils/builtInModals\n */\n\nimport { defineAsyncComponent } from 'vue'\n\n/**\n * The built-in modals, as registry entries (`{ kind: 'modal', component }`):\n * `CnActionDialog`, the generic summary, checklist, reason and confirm dialog,\n * and `CnAssignDialog`, hand a record to another user or team; each takes its\n * `config` in the action's `props`. Loaded on first open.\n *\n * @type {Readonly<Record<string, {kind: string, component: object}>>}\n * @spec openspec/changes/action-dialog/specs/action-dialog/spec.md#requirement-a-manifest-configures-an-action-dialog\n */\nexport const BUILT_IN_MODALS = Object.freeze({\n\tCnActionDialog: { kind: 'modal', component: defineAsyncComponent(() => import('../components/CnActionDialog/CnActionDialog.vue')) },\n\tCnAssignDialog: { kind: 'modal', component: defineAsyncComponent(() => import('../components/CnAssignDialog/CnAssignDialog.vue')) },\n})\n\n/**\n * The registry entry for a modal name: the app's own, else a built-in one.\n *\n * @param {object|null} registry The app's registry.\n * @param {string} name The modal's name.\n * @return {object|null} The entry, or null.\n */\nexport function resolveModalEntry(registry, name) {\n\tconst own = registry && typeof registry === 'object' ? registry[name] : undefined\n\treturn own || BUILT_IN_MODALS[name] || null\n}\n"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC;AAC7C,CAAC,cAAc,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,oBAAoB,CAAC,MAAM,OAAO,oDAAiD,CAAC,CAAC,EAAE;AACpI,CAAC,cAAc,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,oBAAoB,CAAC,MAAM,OAAO,oDAAiD,CAAC,CAAC,EAAE;AACpI,CAAC,EAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,iBAAiB,CAAC,QAAQ,EAAE,IAAI,EAAE;AAClD,CAAC,MAAM,GAAG,GAAG,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,UAAS;AAClF,CAAC,OAAO,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,IAAI;AAC5C;;;;"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * SPDX-FileCopyrightText: 2026 Conduction B.V.
3
+ * SPDX-License-Identifier: EUPL-1.2
4
+ *
5
+ * What a duplicate warning offers, decided in one place, and the candidate an
6
+ * app sends to OpenRegister's duplicate check. None of this enforces
7
+ * anything: the server refuses a duplicate on the write. These helpers make
8
+ * sure the user is told before pressing Create rather than after.
9
+ *
10
+ * @module utils/duplicateWarning
11
+ */
12
+
13
+ /**
14
+ * What the duplicate warning shows and which buttons it offers.
15
+ *
16
+ * A policy other than `block` reads as `warn`, as on the server. `checked:
17
+ * false` means the check never answered: nothing is shown, because the write
18
+ * still refuses a real duplicate.
19
+ *
20
+ * @spec openspec/changes/duplicate-warning/specs/duplicate-warning/spec.md#requirement-a-generic-duplicate-warning
21
+ * @param {object} state The state to decide from.
22
+ * @param {Array<object>} [state.matches] The scored matches.
23
+ * @param {boolean} [state.checked] Whether the check ran (default true).
24
+ * @param {string} [state.policy] `warn` or `block`.
25
+ * @param {boolean} [state.mayOverride] Whether this account may file over a block.
26
+ * @return {{show: boolean, blocked: boolean, mayContinue: boolean, needsReason: boolean}} What to draw.
27
+ */
28
+ function duplicateAffordances(state) {
29
+ const source = state || {};
30
+ const matches = Array.isArray(source.matches) ? source.matches : [];
31
+ const show = source.checked !== false && matches.length > 0;
32
+ const blocked = show && source.policy === 'block';
33
+ const mayOverride = source.mayOverride === true;
34
+ return {
35
+ show,
36
+ blocked,
37
+ mayContinue: show && (!blocked || mayOverride),
38
+ needsReason: blocked && mayOverride,
39
+ }
40
+ }
41
+
42
+ /**
43
+ * The candidate to send to the duplicate check, without blank fields.
44
+ *
45
+ * OpenRegister scores two empty strings as a match, and a form sends `''`
46
+ * for every field nobody filled in, so blanks would match almost everything.
47
+ *
48
+ * @spec openspec/changes/duplicate-warning/specs/duplicate-warning/spec.md#requirement-a-generic-duplicate-warning
49
+ * @param {object} payload The form's values.
50
+ * @return {object} The candidate.
51
+ */
52
+ function candidateWithoutBlanks(payload) {
53
+ return Object.fromEntries(Object.entries(payload || {}).filter(([, value]) => {
54
+ if (value === null || value === undefined || value === '') {
55
+ return false
56
+ }
57
+ return !Array.isArray(value) || value.length > 0
58
+ }))
59
+ }
60
+
61
+ export { candidateWithoutBlanks, duplicateAffordances };
62
+ //# sourceMappingURL=duplicateWarning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duplicateWarning.js","sources":["../../../src/utils/duplicateWarning.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * What a duplicate warning offers, decided in one place, and the candidate an\n * app sends to OpenRegister's duplicate check. None of this enforces\n * anything: the server refuses a duplicate on the write. These helpers make\n * sure the user is told before pressing Create rather than after.\n *\n * @module utils/duplicateWarning\n */\n\n/**\n * What the duplicate warning shows and which buttons it offers.\n *\n * A policy other than `block` reads as `warn`, as on the server. `checked:\n * false` means the check never answered: nothing is shown, because the write\n * still refuses a real duplicate.\n *\n * @spec openspec/changes/duplicate-warning/specs/duplicate-warning/spec.md#requirement-a-generic-duplicate-warning\n * @param {object} state The state to decide from.\n * @param {Array<object>} [state.matches] The scored matches.\n * @param {boolean} [state.checked] Whether the check ran (default true).\n * @param {string} [state.policy] `warn` or `block`.\n * @param {boolean} [state.mayOverride] Whether this account may file over a block.\n * @return {{show: boolean, blocked: boolean, mayContinue: boolean, needsReason: boolean}} What to draw.\n */\nexport function duplicateAffordances(state) {\n\tconst source = state || {}\n\tconst matches = Array.isArray(source.matches) ? source.matches : []\n\tconst show = source.checked !== false && matches.length > 0\n\tconst blocked = show && source.policy === 'block'\n\tconst mayOverride = source.mayOverride === true\n\treturn {\n\t\tshow,\n\t\tblocked,\n\t\tmayContinue: show && (!blocked || mayOverride),\n\t\tneedsReason: blocked && mayOverride,\n\t}\n}\n\n/**\n * The candidate to send to the duplicate check, without blank fields.\n *\n * OpenRegister scores two empty strings as a match, and a form sends `''`\n * for every field nobody filled in, so blanks would match almost everything.\n *\n * @spec openspec/changes/duplicate-warning/specs/duplicate-warning/spec.md#requirement-a-generic-duplicate-warning\n * @param {object} payload The form's values.\n * @return {object} The candidate.\n */\nexport function candidateWithoutBlanks(payload) {\n\treturn Object.fromEntries(Object.entries(payload || {}).filter(([, value]) => {\n\t\tif (value === null || value === undefined || value === '') {\n\t\t\treturn false\n\t\t}\n\t\treturn !Array.isArray(value) || value.length > 0\n\t}))\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;AACO,SAAS,oBAAoB,CAAC,KAAK,EAAE;AAC5C,CAAC,MAAM,MAAM,GAAG,KAAK,IAAI,GAAE;AAC3B,CAAC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,GAAG,GAAE;AACpE,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,KAAK,KAAK,IAAI,OAAO,CAAC,MAAM,GAAG,EAAC;AAC5D,CAAC,MAAM,OAAO,GAAG,IAAI,IAAI,MAAM,CAAC,MAAM,KAAK,QAAO;AAClD,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,KAAK,KAAI;AAChD,CAAC,OAAO;AACR,EAAE,IAAI;AACN,EAAE,OAAO;AACT,EAAE,WAAW,EAAE,IAAI,KAAK,CAAC,OAAO,IAAI,WAAW,CAAC;AAChD,EAAE,WAAW,EAAE,OAAO,IAAI,WAAW;AACrC,EAAE;AACF,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,sBAAsB,CAAC,OAAO,EAAE;AAChD,CAAC,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK;AAC/E,EAAE,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE;AAC7D,GAAG,OAAO,KAAK;AACf,GAAG;AACH,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;AAClD,EAAE,CAAC,CAAC;AACJ;;;;"}
@@ -9,6 +9,7 @@ import { translateValidationMessage } from './validationMessages.js';
9
9
  * @property {object|null} details Validation errors or additional details
10
10
  * @property {boolean} isValidation Whether this is a validation error (400/422)
11
11
  * @property {object|null} fields Per-field validation errors
12
+ * @property {number|null} [position] The 1-based character a refused search term stopped at (400 only)
12
13
  */
13
14
 
14
15
  /**
@@ -62,6 +63,7 @@ async function parseResponseError(response, type) {
62
63
  const status = response.status;
63
64
  let details = null;
64
65
  let fields = null;
66
+ let position = null;
65
67
  let message;
66
68
 
67
69
  try {
@@ -74,6 +76,7 @@ async function parseResponseError(response, type) {
74
76
  } else if (body && typeof body === 'object') {
75
77
  details = body.errors || body.error || body.message || null;
76
78
  fields = body.validationErrors || body.errors || null;
79
+ position = Number.isInteger(body.position) && body.position > 0 ? body.position : null;
77
80
  }
78
81
  } catch {
79
82
  // Response body is not JSON
@@ -88,6 +91,7 @@ async function parseResponseError(response, type) {
88
91
  details,
89
92
  isValidation: true,
90
93
  fields,
94
+ position,
91
95
  toString() {
92
96
  return this.message
93
97
  },
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sources":["../../../src/utils/errors.js"],"sourcesContent":["import { translateValidationMessage } from './validationMessages.js'\n\n/**\n * Unified error shape returned by all store actions.\n *\n * @typedef {object} ApiError\n * @property {number} status HTTP status code (0 for network errors)\n * @property {string} message Human-readable error message\n * @property {object|null} details Validation errors or additional details\n * @property {boolean} isValidation Whether this is a validation error (400/422)\n * @property {object|null} fields Per-field validation errors\n */\n\n/**\n * Extract a human-readable message from a validation-error payload.\n *\n * The backend may express validation errors as a plain string, an array of\n * strings, an array of `{ property, message }` objects (OpenRegister), or an\n * object map of `field → message`. Pull every available message out so the\n * actual problem is shown instead of a generic fallback.\n *\n * @param {string|Array|object|null} errors The raw error payload\n * @return {string|null} Joined message string, or null when nothing usable\n */\nfunction extractValidationMessage(errors) {\n\tif (typeof errors === 'string') {\n\t\treturn translateValidationMessage(errors)\n\t}\n\n\tconst pick = (entry) => {\n\t\tif (typeof entry === 'string') {\n\t\t\treturn entry\n\t\t}\n\t\tif (entry && typeof entry === 'object') {\n\t\t\treturn entry.message || entry.error || null\n\t\t}\n\t\treturn null\n\t}\n\n\tlet messages = []\n\tif (Array.isArray(errors)) {\n\t\tmessages = errors.map(pick)\n\t} else if (errors && typeof errors === 'object') {\n\t\tmessages = Object.values(errors).map(pick)\n\t}\n\n\tmessages = messages.filter(Boolean).map(translateValidationMessage)\n\treturn messages.length ? messages.join('\\n') : null\n}\n\n/**\n * Parse an HTTP error response into a unified ApiError shape.\n *\n * Merges the best of Pipelinq's _parseResponseError (field extraction)\n * and Dossiq's _parseError (status-specific messages, isValidation flag).\n *\n * @param {Response} response The fetch Response object\n * @param {string} type The object type slug (used in error messages)\n * @return {Promise<ApiError>} Parsed error object\n */\nexport async function parseResponseError(response, type) {\n\tconst status = response.status\n\tlet details = null\n\tlet fields = null\n\tlet message\n\n\ttry {\n\t\tconst body = await response.json()\n\t\tif (typeof body === 'string') {\n\t\t\t// Some endpoints return the error as a bare JSON string rather than\n\t\t\t// an object (e.g. OpenRegister object-save returns the validation\n\t\t\t// message directly: `new JSONResponse(data: $e->getMessage())`).\n\t\t\tdetails = body\n\t\t} else if (body && typeof body === 'object') {\n\t\t\tdetails = body.errors || body.error || body.message || null\n\t\t\tfields = body.validationErrors || body.errors || null\n\t\t}\n\t} catch {\n\t\t// Response body is not JSON\n\t}\n\n\tswitch (true) {\n\t\tcase status === 400 || status === 422:\n\t\t\tmessage = extractValidationMessage(details) || `Validation failed for ${type}`\n\t\t\treturn {\n\t\t\t\tstatus,\n\t\t\t\tmessage,\n\t\t\t\tdetails,\n\t\t\t\tisValidation: true,\n\t\t\t\tfields,\n\t\t\t\ttoString() {\n\t\t\t\t\treturn this.message\n\t\t\t\t},\n\t\t\t}\n\t\tcase status === 401:\n\t\t\tmessage = 'Session expired, please log in again'\n\t\t\tbreak\n\t\tcase status === 403:\n\t\t\tmessage = 'You do not have permission to perform this action'\n\t\t\tbreak\n\t\tcase status === 404:\n\t\t\tmessage = `The requested ${type} could not be found`\n\t\t\tbreak\n\t\tcase status === 409:\n\t\t\tmessage = `This ${type} was modified by another user. Please reload.`\n\t\t\tbreak\n\t\tcase status >= 500:\n\t\t\tmessage = 'An unexpected server error occurred. Please try again.'\n\t\t\tbreak\n\t\tdefault:\n\t\t\tmessage = response.statusText || 'An unexpected error occurred'\n\t}\n\n\treturn {\n\t\tstatus,\n\t\tmessage,\n\t\tdetails,\n\t\tisValidation: false,\n\t\tfields,\n\t\ttoString() {\n\t\t\treturn this.message\n\t\t},\n\t}\n}\n\n/**\n * Unpack an AXIOS error into the parts a caller needs to explain itself.\n *\n * `parseResponseError` above takes a fetch `Response` (and awaits `.json()`).\n * Axios has already parsed the body onto `error.response.data`, and its\n * `error.message` is only ever the useless generic \"Request failed with status\n * code 409\" — so a `catch (e) { this.error = e.message }` throws away whatever\n * the server actually said. This pulls that back out.\n *\n * OpenRegister returns machine-readable refusals such as\n * `{ error: 'schema-has-objects', objectCount: 3 }`; `code` carries that slug so\n * a caller can render a specific, actionable message (and offer a way forward)\n * instead of echoing an HTTP status at the user.\n *\n * @param {object} error The caught axios error.\n * @return {{status: number, code: string|null, message: string|null, data: object|null}}\n * `code` is the server's error slug when it sent one; `message` is the best\n * human-readable string available from the body, or null when it sent none.\n */\nexport function parseAxiosError(error) {\n\tconst response = (error && error.response) || null\n\tconst status = (response && response.status) || 0\n\tconst data = (response && response.data) || null\n\n\t// The body may be a bare string, or an object carrying `error` / `message`.\n\tlet code = null\n\tlet message = null\n\tif (typeof data === 'string' && data !== '') {\n\t\tmessage = data\n\t} else if (data && typeof data === 'object') {\n\t\tif (typeof data.error === 'string') {\n\t\t\tcode = data.error\n\t\t}\n\t\tmessage = (typeof data.message === 'string' && data.message)\n\t\t\t|| (typeof data.error === 'string' && data.error)\n\t\t\t|| null\n\t}\n\n\treturn { status, code, message, data }\n}\n\n/**\n * Create a network error object for fetch failures (no response).\n *\n * @param {Error} error The caught error\n * @return {ApiError} Network error object\n */\nexport function networkError(error) {\n\treturn {\n\t\tstatus: 0,\n\t\tmessage: error.message || 'A network error occurred. Check your connection and try again.',\n\t\tdetails: null,\n\t\tisValidation: false,\n\t\tfields: null,\n\t\ttoString() {\n\t\t\treturn this.message\n\t\t},\n\t}\n}\n\n/**\n * Create a generic error object from a caught exception.\n *\n * @param {Error} error The caught error\n * @return {ApiError} Generic error object\n */\nexport function genericError(error) {\n\treturn {\n\t\tstatus: null,\n\t\tmessage: error.message,\n\t\tdetails: null,\n\t\tisValidation: false,\n\t\tfields: null,\n\t\ttoString() {\n\t\t\treturn this.message\n\t\t},\n\t}\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sources":["../../../src/utils/errors.js"],"sourcesContent":["import { translateValidationMessage } from './validationMessages.js'\n\n/**\n * Unified error shape returned by all store actions.\n *\n * @typedef {object} ApiError\n * @property {number} status HTTP status code (0 for network errors)\n * @property {string} message Human-readable error message\n * @property {object|null} details Validation errors or additional details\n * @property {boolean} isValidation Whether this is a validation error (400/422)\n * @property {object|null} fields Per-field validation errors\n * @property {number|null} [position] The 1-based character a refused search term stopped at (400 only)\n */\n\n/**\n * Extract a human-readable message from a validation-error payload.\n *\n * The backend may express validation errors as a plain string, an array of\n * strings, an array of `{ property, message }` objects (OpenRegister), or an\n * object map of `field → message`. Pull every available message out so the\n * actual problem is shown instead of a generic fallback.\n *\n * @param {string|Array|object|null} errors The raw error payload\n * @return {string|null} Joined message string, or null when nothing usable\n */\nfunction extractValidationMessage(errors) {\n\tif (typeof errors === 'string') {\n\t\treturn translateValidationMessage(errors)\n\t}\n\n\tconst pick = (entry) => {\n\t\tif (typeof entry === 'string') {\n\t\t\treturn entry\n\t\t}\n\t\tif (entry && typeof entry === 'object') {\n\t\t\treturn entry.message || entry.error || null\n\t\t}\n\t\treturn null\n\t}\n\n\tlet messages = []\n\tif (Array.isArray(errors)) {\n\t\tmessages = errors.map(pick)\n\t} else if (errors && typeof errors === 'object') {\n\t\tmessages = Object.values(errors).map(pick)\n\t}\n\n\tmessages = messages.filter(Boolean).map(translateValidationMessage)\n\treturn messages.length ? messages.join('\\n') : null\n}\n\n/**\n * Parse an HTTP error response into a unified ApiError shape.\n *\n * Merges the best of Pipelinq's _parseResponseError (field extraction)\n * and Dossiq's _parseError (status-specific messages, isValidation flag).\n *\n * @param {Response} response The fetch Response object\n * @param {string} type The object type slug (used in error messages)\n * @return {Promise<ApiError>} Parsed error object\n */\nexport async function parseResponseError(response, type) {\n\tconst status = response.status\n\tlet details = null\n\tlet fields = null\n\tlet position = null\n\tlet message\n\n\ttry {\n\t\tconst body = await response.json()\n\t\tif (typeof body === 'string') {\n\t\t\t// Some endpoints return the error as a bare JSON string rather than\n\t\t\t// an object (e.g. OpenRegister object-save returns the validation\n\t\t\t// message directly: `new JSONResponse(data: $e->getMessage())`).\n\t\t\tdetails = body\n\t\t} else if (body && typeof body === 'object') {\n\t\t\tdetails = body.errors || body.error || body.message || null\n\t\t\tfields = body.validationErrors || body.errors || null\n\t\t\tposition = Number.isInteger(body.position) && body.position > 0 ? body.position : null\n\t\t}\n\t} catch {\n\t\t// Response body is not JSON\n\t}\n\n\tswitch (true) {\n\t\tcase status === 400 || status === 422:\n\t\t\tmessage = extractValidationMessage(details) || `Validation failed for ${type}`\n\t\t\treturn {\n\t\t\t\tstatus,\n\t\t\t\tmessage,\n\t\t\t\tdetails,\n\t\t\t\tisValidation: true,\n\t\t\t\tfields,\n\t\t\t\tposition,\n\t\t\t\ttoString() {\n\t\t\t\t\treturn this.message\n\t\t\t\t},\n\t\t\t}\n\t\tcase status === 401:\n\t\t\tmessage = 'Session expired, please log in again'\n\t\t\tbreak\n\t\tcase status === 403:\n\t\t\tmessage = 'You do not have permission to perform this action'\n\t\t\tbreak\n\t\tcase status === 404:\n\t\t\tmessage = `The requested ${type} could not be found`\n\t\t\tbreak\n\t\tcase status === 409:\n\t\t\tmessage = `This ${type} was modified by another user. Please reload.`\n\t\t\tbreak\n\t\tcase status >= 500:\n\t\t\tmessage = 'An unexpected server error occurred. Please try again.'\n\t\t\tbreak\n\t\tdefault:\n\t\t\tmessage = response.statusText || 'An unexpected error occurred'\n\t}\n\n\treturn {\n\t\tstatus,\n\t\tmessage,\n\t\tdetails,\n\t\tisValidation: false,\n\t\tfields,\n\t\ttoString() {\n\t\t\treturn this.message\n\t\t},\n\t}\n}\n\n/**\n * Unpack an AXIOS error into the parts a caller needs to explain itself.\n *\n * `parseResponseError` above takes a fetch `Response` (and awaits `.json()`).\n * Axios has already parsed the body onto `error.response.data`, and its\n * `error.message` is only ever the useless generic \"Request failed with status\n * code 409\" — so a `catch (e) { this.error = e.message }` throws away whatever\n * the server actually said. This pulls that back out.\n *\n * OpenRegister returns machine-readable refusals such as\n * `{ error: 'schema-has-objects', objectCount: 3 }`; `code` carries that slug so\n * a caller can render a specific, actionable message (and offer a way forward)\n * instead of echoing an HTTP status at the user.\n *\n * @param {object} error The caught axios error.\n * @return {{status: number, code: string|null, message: string|null, data: object|null}}\n * `code` is the server's error slug when it sent one; `message` is the best\n * human-readable string available from the body, or null when it sent none.\n */\nexport function parseAxiosError(error) {\n\tconst response = (error && error.response) || null\n\tconst status = (response && response.status) || 0\n\tconst data = (response && response.data) || null\n\n\t// The body may be a bare string, or an object carrying `error` / `message`.\n\tlet code = null\n\tlet message = null\n\tif (typeof data === 'string' && data !== '') {\n\t\tmessage = data\n\t} else if (data && typeof data === 'object') {\n\t\tif (typeof data.error === 'string') {\n\t\t\tcode = data.error\n\t\t}\n\t\tmessage = (typeof data.message === 'string' && data.message)\n\t\t\t|| (typeof data.error === 'string' && data.error)\n\t\t\t|| null\n\t}\n\n\treturn { status, code, message, data }\n}\n\n/**\n * Create a network error object for fetch failures (no response).\n *\n * @param {Error} error The caught error\n * @return {ApiError} Network error object\n */\nexport function networkError(error) {\n\treturn {\n\t\tstatus: 0,\n\t\tmessage: error.message || 'A network error occurred. Check your connection and try again.',\n\t\tdetails: null,\n\t\tisValidation: false,\n\t\tfields: null,\n\t\ttoString() {\n\t\t\treturn this.message\n\t\t},\n\t}\n}\n\n/**\n * Create a generic error object from a caught exception.\n *\n * @param {Error} error The caught error\n * @return {ApiError} Generic error object\n */\nexport function genericError(error) {\n\treturn {\n\t\tstatus: null,\n\t\tmessage: error.message,\n\t\tdetails: null,\n\t\tisValidation: false,\n\t\tfields: null,\n\t\ttoString() {\n\t\t\treturn this.message\n\t\t},\n\t}\n}\n"],"names":[],"mappings":"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"}
@@ -60,6 +60,7 @@ const BUILT_IN_WIDGET_KEYS = Object.freeze([
60
60
  'form-renderer',
61
61
  'map-viewer',
62
62
  'notice',
63
+ 'decision-list',
63
64
  'object-geo',
64
65
  'card-grid',
65
66
  'nav-card-grid',
@@ -135,10 +136,12 @@ const DASHBOARD_CATALOG_WIDGET_KEYS = Object.freeze([
135
136
  'object-table',
136
137
  'party-actions',
137
138
  'people',
139
+ 'plan',
138
140
  'quicklinks',
139
141
  'radio-cards',
140
142
  'record-list',
141
143
  'related',
144
+ 'retention',
142
145
  'saved-view',
143
146
  'saved-views',
144
147
  'sections',
@@ -160,6 +163,7 @@ const DASHBOARD_CATALOG_WIDGET_KEYS = Object.freeze([
160
163
  'video',
161
164
  'week-strip',
162
165
  'working-calendar',
166
+ 'work-queue',
163
167
  'workspace-filter',
164
168
  ]);
165
169