diff --git a/src/Umbraco.Web.UI.Client/devops/eslint/rules/no-direct-api-import.cjs b/src/Umbraco.Web.UI.Client/devops/eslint/rules/no-direct-api-import.cjs index 9f3a3912dc..bd0b06de69 100644 --- a/src/Umbraco.Web.UI.Client/devops/eslint/rules/no-direct-api-import.cjs +++ b/src/Umbraco.Web.UI.Client/devops/eslint/rules/no-direct-api-import.cjs @@ -12,7 +12,7 @@ module.exports = { }, create: function (context) { return { - // If methods called on *Service classes are not already wrapped with `await tryExecuteAndNotify()`, then we should suggest to wrap them. + // If methods called on *Service classes are not already wrapped with `await tryExecute()`, then we should suggest to wrap them. CallExpression: function (node) { if ( node.callee.type === 'MemberExpression' && @@ -28,9 +28,9 @@ module.exports = { if (!hasTryExecuteAndNotify) { context.report({ node, - message: 'Wrap this call with `tryExecuteAndNotify()`. Make sure to `await` the result.', + message: 'Wrap this call with `tryExecute()`. Make sure to `await` the result.', fix: (fixer) => [ - fixer.insertTextBefore(node, 'tryExecuteAndNotify(this, '), + fixer.insertTextBefore(node, 'tryExecute(this, '), fixer.insertTextAfter(node, ')'), ], }); diff --git a/src/Umbraco.Web.UI.Client/devops/openapi-ts/openapi-ts.config.js b/src/Umbraco.Web.UI.Client/devops/openapi-ts/openapi-ts.config.js index a86fd9d426..0e27431a11 100644 --- a/src/Umbraco.Web.UI.Client/devops/openapi-ts/openapi-ts.config.js +++ b/src/Umbraco.Web.UI.Client/devops/openapi-ts/openapi-ts.config.js @@ -1,7 +1,6 @@ import { defineConfig } from '@hey-api/openapi-ts'; export default defineConfig({ - client: 'legacy/fetch', debug: true, input: '../Umbraco.Cms.Api.Management/OpenApi.json', output: { @@ -10,6 +9,7 @@ export default defineConfig({ lint: 'eslint', }, plugins: [ + 'legacy/fetch', { name: '@hey-api/typescript', enums: 'typescript' diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 03e0d8873f..775e79b7e9 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -42,7 +42,7 @@ "devDependencies": { "@babel/core": "^7.26.9", "@eslint/js": "^9.20.0", - "@hey-api/openapi-ts": "^0.61.3", + "@hey-api/openapi-ts": "^0.66.1", "@open-wc/testing": "^4.0.0", "@playwright/test": "^1.49.1", "@rollup/plugin-json": "^6.1.0", @@ -1032,9 +1032,9 @@ "license": "BSD-3-Clause" }, "node_modules/@hey-api/json-schema-ref-parser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@hey-api/json-schema-ref-parser/-/json-schema-ref-parser-1.0.1.tgz", - "integrity": "sha512-dBt0A7op9kf4BcK++x6HBYDmvCvnJUZEGe5QytghPFHnMXPyKwDKomwL/v5e9ERk6E0e1GzL/e/y6pWUso9zrQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@hey-api/json-schema-ref-parser/-/json-schema-ref-parser-1.0.4.tgz", + "integrity": "sha512-IaJ4yFgU5r63KZyeySHRKSM1bavFIda8KdwCFi5BxQCIklltzEByBksNOPms+yHXpWWfR+OopIusVZV8roycYg==", "dev": true, "license": "MIT", "dependencies": { @@ -1050,13 +1050,13 @@ } }, "node_modules/@hey-api/openapi-ts": { - "version": "0.61.3", - "resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.61.3.tgz", - "integrity": "sha512-Ls9MBRa5+vg7UHw6fIcfdgcCyZ9vKtRw63nWxwF9zjJIPlzVOZO6xKuzGmDc6o0Pb6XCdTz6lPV5hcV0R4b/ag==", + "version": "0.66.1", + "resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.66.1.tgz", + "integrity": "sha512-Mol3vuM76d8F7xLvcZi502UxM3taXy7TDZzZfFpUMT+VLMdPiGd9cTWfKfQde0kgi+SZPjejvqmad1zk4EIu7A==", "dev": true, "license": "MIT", "dependencies": { - "@hey-api/json-schema-ref-parser": "1.0.1", + "@hey-api/json-schema-ref-parser": "1.0.4", "c12": "2.0.1", "commander": "13.0.0", "handlebars": "4.7.8" @@ -1065,7 +1065,7 @@ "openapi-ts": "bin/index.cjs" }, "engines": { - "node": "^18.20.5 || ^20.11.1 || >=22.11.0" + "node": "^18.18.0 || ^20.9.0 || >=22.10.0" }, "funding": { "url": "https://github.com/sponsors/hey-api" diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index f12e4f31c6..e5d12aa78b 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -230,7 +230,7 @@ "devDependencies": { "@babel/core": "^7.26.9", "@eslint/js": "^9.20.0", - "@hey-api/openapi-ts": "^0.61.3", + "@hey-api/openapi-ts": "^0.66.1", "@open-wc/testing": "^4.0.0", "@playwright/test": "^1.49.1", "@rollup/plugin-json": "^6.1.0", diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/api-interceptor.controller.ts b/src/Umbraco.Web.UI.Client/src/apps/app/api-interceptor.controller.ts deleted file mode 100644 index 8c7bbcf6e8..0000000000 --- a/src/Umbraco.Web.UI.Client/src/apps/app/api-interceptor.controller.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { OpenAPI } from '@umbraco-cms/backoffice/external/backend-api'; -import { - extractUmbNotificationColor, - isUmbNotifications, - UMB_NOTIFICATION_CONTEXT, - UMB_NOTIFICATION_HEADER, -} from '@umbraco-cms/backoffice/notification'; - -/** - * Controller that adds interceptors to the OpenAPI client - */ -export class UmbApiInterceptorController extends UmbControllerBase { - constructor(host: UmbControllerHost) { - super(host); - this.#addUmbNotificationsInterceptor(); - } - - /** - * Interceptor which checks responses for the umb-notifications header and displays them as a notification if any. Removes the umb-notifications from the headers. - */ - #addUmbNotificationsInterceptor() { - OpenAPI.interceptors.response.use((response) => { - const umbNotifications = response.headers.get(UMB_NOTIFICATION_HEADER); - if (!umbNotifications) return response; - - const notifications = JSON.parse(umbNotifications); - if (!isUmbNotifications(notifications)) return response; - - this.getContext(UMB_NOTIFICATION_CONTEXT).then((notificationContext) => { - if (notificationContext === undefined) { - throw new Error('Notification context is not available'); - } - for (const notification of notifications) { - notificationContext.peek(extractUmbNotificationColor(notification.type), { - data: { headline: notification.category, message: notification.message }, - }); - } - }); - - const newHeader = new Headers(); - for (const header of response.headers.entries()) { - const [key, value] = header; - if (key !== UMB_NOTIFICATION_HEADER) newHeader.set(key, value); - } - - const newResponse = new Response(response.body, { - headers: newHeader, - status: response.status, - statusText: response.statusText, - }); - - return newResponse; - }); - } -} diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app-error.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app-error.element.ts index fc34f7156b..7d2b06a629 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/app/app-error.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/app/app-error.element.ts @@ -1,6 +1,6 @@ import { css, html, nothing, customElement, property } from '@umbraco-cms/backoffice/external/lit'; -import type { ProblemDetails } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import type { UmbProblemDetails } from '@umbraco-cms/backoffice/resources'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; /** @@ -26,7 +26,7 @@ export class UmbAppErrorElement extends UmbLitElement { * The error to display * @attr */ - @property() + @property({ attribute: false }) error?: unknown; /** @@ -133,7 +133,7 @@ export class UmbAppErrorElement extends UmbLitElement { } } - #renderProblemDetails = (problemDetails: ProblemDetails) => html` + #renderProblemDetails = (problemDetails: UmbProblemDetails) => html`

${problemDetails.title}

${problemDetails.detail}

${problemDetails.stack}
@@ -145,7 +145,7 @@ export class UmbAppErrorElement extends UmbLitElement {
${error.stack}
`; - #isProblemDetails(error: unknown): error is ProblemDetails { + #isProblemDetails(error: unknown): error is UmbProblemDetails { return typeof error === 'object' && error !== null && 'detail' in error && 'title' in error; } diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts index e77efa374b..40d1c3e3df 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts @@ -3,7 +3,6 @@ import type { UmbAppErrorElement } from './app-error.element.js'; import { UmbAppContext } from './app.context.js'; import { UmbServerConnection } from './server-connection.js'; import { UmbAppAuthController } from './app-auth.controller.js'; -import { UmbApiInterceptorController } from './api-interceptor.controller.js'; import type { UmbAppOauthElement } from './app-oauth.element.js'; import type { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth'; import { UmbAuthContext } from '@umbraco-cms/backoffice/auth'; @@ -21,6 +20,7 @@ import { } from '@umbraco-cms/backoffice/extension-registry'; import { filter, first, firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs'; import { hasOwnOpener, retrieveStoredPath } from '@umbraco-cms/backoffice/utils'; +import { UmbApiInterceptorController } from '@umbraco-cms/backoffice/resources'; import './app-oauth.element.js'; @@ -139,13 +139,14 @@ export class UmbAppElement extends UmbLitElement { #authContext?: typeof UMB_AUTH_CONTEXT.TYPE; #serverConnection?: UmbServerConnection; #authController = new UmbAppAuthController(this); + #apiInterceptorController = new UmbApiInterceptorController(this); constructor() { super(); OpenAPI.BASE = window.location.origin; - new UmbApiInterceptorController(this); + this.#apiInterceptorController.bindDefaultInterceptors(OpenAPI); new UmbBundleExtensionInitializer(this, umbExtensionsRegistry); @@ -160,7 +161,7 @@ export class UmbAppElement extends UmbLitElement { } async #setup() { - this.#serverConnection = await new UmbServerConnection(this.serverUrl).connect(); + this.#serverConnection = await new UmbServerConnection(this, this.serverUrl).connect(); this.#authContext = new UmbAuthContext(this, this.serverUrl, this.backofficePath, this.bypassAuth); new UmbAppContext(this, { diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/server-connection.ts b/src/Umbraco.Web.UI.Client/src/apps/app/server-connection.ts index 4365b643f0..1f22522350 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/app/server-connection.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/app/server-connection.ts @@ -1,8 +1,10 @@ +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { RuntimeLevelModel, ServerService } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbBooleanState, UmbNumberState } from '@umbraco-cms/backoffice/observable-api'; import { tryExecute } from '@umbraco-cms/backoffice/resources'; -export class UmbServerConnection { +export class UmbServerConnection extends UmbControllerBase { #url: string; #status: RuntimeLevelModel = RuntimeLevelModel.UNKNOWN; @@ -18,7 +20,8 @@ export class UmbServerConnection { #allowPasswordReset = new UmbBooleanState(false); allowPasswordReset = this.#allowPasswordReset.asObservable(); - constructor(serverUrl: string) { + constructor(host: UmbControllerHost, serverUrl: string) { + super(host); this.#url = serverUrl; } @@ -61,7 +64,9 @@ export class UmbServerConnection { } async #setStatus() { - const { data, error } = await tryExecute(ServerService.getServerStatus()); + const { data, error } = await tryExecute(this._host, ServerService.getServerStatus(), { + disableNotifications: true, + }); if (error) { throw error; } @@ -71,7 +76,9 @@ export class UmbServerConnection { } async #setServerConfiguration() { - const { data, error } = await tryExecute(ServerService.getServerConfiguration()); + const { data, error } = await tryExecute(this._host, ServerService.getServerConfiguration(), { + disableNotifications: true, + }); if (error) { throw error; } diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.context.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.context.ts index ff5086c83c..ee79a30bff 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.context.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.context.ts @@ -57,7 +57,7 @@ export class UmbBackofficeContext extends UmbContextBase { } async #getVersion() { - const { data } = await tryExecute(ServerService.getServerInformation()); + const { data } = await tryExecute(this._host, ServerService.getServerInformation(), { disableNotifications: true }); if (!data) return; // A quick semver parser (to remove the unwanted bits) [LK] diff --git a/src/Umbraco.Web.UI.Client/src/apps/installer/database/installer-database.element.ts b/src/Umbraco.Web.UI.Client/src/apps/installer/database/installer-database.element.ts index c09facb816..59fc0d0131 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/installer/database/installer-database.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/installer/database/installer-database.element.ts @@ -7,11 +7,10 @@ import { css, html, nothing, customElement, property, query, state } from '@umbr import type { DatabaseInstallRequestModel, DatabaseSettingsPresentationModel, - ProblemDetails, } from '@umbraco-cms/backoffice/external/backend-api'; -import { ApiError, InstallService } from '@umbraco-cms/backoffice/external/backend-api'; +import { InstallService } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { tryExecute } from '@umbraco-cms/backoffice/resources'; +import { tryExecute, UmbApiError, type UmbProblemDetails } from '@umbraco-cms/backoffice/resources'; @customElement('umb-installer-database') export class UmbInstallerDatabaseElement extends UmbLitElement { @@ -165,12 +164,14 @@ export class UmbInstallerDatabaseElement extends UmbLitElement { }; const { error } = await tryExecute( + this, InstallService.postInstallValidateDatabase({ requestBody: databaseDetails }), + { disableNotifications: true }, ); if (error) { this._validationErrorMessage = `The server could not validate the database connection. Details: ${ - error instanceof ApiError ? (error.body as any).detail : error.message + UmbApiError.isUmbApiError(error) ? error.problemDetails.detail : error.message }`; this._installButton.state = 'failed'; return; @@ -195,12 +196,13 @@ export class UmbInstallerDatabaseElement extends UmbLitElement { this._installerContext.nextStep(); - const { error: _error } = await tryExecute( + const { error } = await tryExecute( + this, InstallService.postInstallSetup({ requestBody: this._installerContext.getData() }), + { disableNotifications: true }, ); - const error = _error as ProblemDetails | undefined; if (error) { - this._handleRejected(error); + if (UmbApiError.isUmbApiError(error)) this._handleRejected(error.problemDetails); } else { this._handleFulfilled(); } @@ -213,7 +215,7 @@ export class UmbInstallerDatabaseElement extends UmbLitElement { history.replaceState(null, '', 'section/content'); } - private _handleRejected(e: ProblemDetails) { + private _handleRejected(e: UmbProblemDetails) { this._installerContext?.setInstallStatus(e); } diff --git a/src/Umbraco.Web.UI.Client/src/apps/installer/error/installer-error.element.ts b/src/Umbraco.Web.UI.Client/src/apps/installer/error/installer-error.element.ts index f5fa4e2cec..a7aad8e470 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/installer/error/installer-error.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/installer/error/installer-error.element.ts @@ -2,13 +2,13 @@ import type { UmbInstallerContext } from '../installer.context.js'; import { UMB_INSTALLER_CONTEXT } from '../installer.context.js'; import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import type { ProblemDetails } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import type { UmbProblemDetails } from '@umbraco-cms/backoffice/resources'; @customElement('umb-installer-error') export class UmbInstallerErrorElement extends UmbLitElement { @state() - _error?: ProblemDetails; + _error?: UmbProblemDetails; private _installerContext?: UmbInstallerContext; @@ -36,10 +36,10 @@ export class UmbInstallerErrorElement extends UmbLitElement { this._installerContext?.reset(); } - private _renderError(error: ProblemDetails) { + private _renderError(error: UmbProblemDetails) { return html`

Description: ${error.title}

- ${error.errors ? this._renderErrors(error.errors as any) : nothing} + ${error.errors ? this._renderErrors(error.errors) : nothing}

Details:

${error.detail ?? 'Unknown error'}

diff --git a/src/Umbraco.Web.UI.Client/src/apps/installer/installer.context.ts b/src/Umbraco.Web.UI.Client/src/apps/installer/installer.context.ts index 0193999416..cf51df93cb 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/installer/installer.context.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/installer/installer.context.ts @@ -1,11 +1,7 @@ import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import type { - InstallSettingsResponseModel, - ProblemDetails, - InstallRequestModel, -} from '@umbraco-cms/backoffice/external/backend-api'; +import type { InstallSettingsResponseModel, InstallRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import { InstallService, TelemetryLevelModel } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecute } from '@umbraco-cms/backoffice/resources'; +import { tryExecute, UmbApiError, type UmbProblemDetails } from '@umbraco-cms/backoffice/resources'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import { UmbObjectState, UmbNumberState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -29,7 +25,7 @@ export class UmbInstallerContext extends UmbContextBase(undefined); public readonly settings = this._settings.asObservable(); - private _installStatus = new UmbObjectState(null); + private _installStatus = new UmbObjectState(null); public readonly installStatus = this._installStatus.asObservable(); constructor(host: UmbControllerHost) { @@ -50,10 +46,10 @@ export class UmbInstallerContext extends UmbContextBase)} + * @returns {*} {(Observable)} * @memberof UmbInstallerContext */ - public installStatusChanges(): Observable { + public installStatusChanges(): Observable { return this.installStatus; } @@ -108,10 +104,10 @@ export class UmbInstallerContext extends UmbContextBase> { if (!model) { return { - error: new ApiError( - { - method: 'POST', - url: localstorageFakeUrl, - }, - { - ok: false, - status: 400, - statusText: 'Bad Request', - url: localstorageFakeUrl, - body: {}, - }, - 'Clipboard entry is missing', - ), + error: new UmbError('Clipboard entry is missing'), }; } @@ -78,20 +62,7 @@ export class UmbClipboardEntryDetailLocalStorageDataSource if (entry) { return { - error: new ApiError( - { - method: 'POST', - url: localstorageFakeUrl, - }, - { - ok: false, - status: 400, - statusText: 'Bad Request', - url: localstorageFakeUrl, - body: {}, - }, - 'Clipboard entry already exists', - ), + error: new UmbError('Clipboard entry already exists'), }; } @@ -117,20 +88,7 @@ export class UmbClipboardEntryDetailLocalStorageDataSource async read(unique: string): Promise> { if (!unique) { return { - error: new ApiError( - { - method: 'GET', - url: localstorageFakeUrl, - }, - { - ok: false, - status: 400, - statusText: 'Bad Request', - url: localstorageFakeUrl, - body: {}, - }, - 'Unique is missing', - ), + error: new UmbError('Unique is missing'), }; } @@ -139,20 +97,7 @@ export class UmbClipboardEntryDetailLocalStorageDataSource if (!entry) { return { - error: new ApiError( - { - method: 'GET', - url: localstorageFakeUrl, - }, - { - ok: false, - status: 404, - statusText: 'Not Found', - url: localstorageFakeUrl, - body: {}, - }, - 'Entry not found', - ), + error: new UmbError('Entry not found'), }; } @@ -168,20 +113,7 @@ export class UmbClipboardEntryDetailLocalStorageDataSource async update(model: UmbClipboardEntryDetailModel): Promise> { if (!model) { return { - error: new ApiError( - { - method: 'PUT', - url: localstorageFakeUrl, - }, - { - ok: false, - status: 400, - statusText: 'Bad Request', - url: localstorageFakeUrl, - body: {}, - }, - 'Clipboard entry is missing', - ), + error: new UmbError('Clipboard entry is missing'), }; } @@ -189,20 +121,7 @@ export class UmbClipboardEntryDetailLocalStorageDataSource const entry = await this.#localStorageManager.getEntry(model.unique); if (!entry) { return { - error: new ApiError( - { - method: 'GET', - url: localstorageFakeUrl, - }, - { - ok: false, - status: 404, - statusText: 'Not Found', - url: localstorageFakeUrl, - body: {}, - }, - 'Entry not found', - ), + error: new UmbError('Entry not found'), }; } @@ -234,20 +153,7 @@ export class UmbClipboardEntryDetailLocalStorageDataSource async delete(unique: string): Promise { if (!unique) { return { - error: new ApiError( - { - method: 'DELETE', - url: localstorageFakeUrl, - }, - { - ok: false, - status: 400, - statusText: 'Bad Request', - url: localstorageFakeUrl, - body: {}, - }, - 'Unique is missing', - ), + error: new UmbError('Unique is missing'), }; } @@ -256,20 +162,7 @@ export class UmbClipboardEntryDetailLocalStorageDataSource if (!entry) { return { - error: new ApiError( - { - method: 'GET', - url: localstorageFakeUrl, - }, - { - ok: false, - status: 404, - statusText: 'Not Found', - url: localstorageFakeUrl, - body: {}, - }, - 'Entry not found', - ), + error: new UmbError('Entry not found'), }; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts index d4f6827120..470f1f776c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts @@ -233,17 +233,18 @@ export class UmbAuthContext extends UmbContextBase { /** * Get the default OpenAPI configuration, which is set up to communicate with the Management API. - * @remark This is useful if you want to communicate with your own resources generated by the [openapi-typescript-codegen](https://github.com/ferdikoomen/openapi-typescript-codegen) library. + * @remark This is useful if you want to communicate with your own resources generated by the [@hey-api/openapi-ts](https://github.com/hey-api/openapi-ts) library. * @memberof UmbAuthContext * @example Using the default OpenAPI configuration * ```js - * const defaultOpenApi = authContext.getOpenApiConfiguration(); - * OpenAPI.BASE = defaultOpenApi.base; - * OpenAPI.WITH_CREDENTIALS = defaultOpenApi.withCredentials; - * OpenAPI.CREDENTIALS = defaultOpenApi.credentials; - * OpenAPI.TOKEN = defaultOpenApi.token; + * const defaultOpenApi = authContext.getOpenApiConfiguration(); + * client.setConfig({ + * base: defaultOpenApi.base, + * credentials: defaultOpenApi.credentials, + * auth: defaultOpenApi.token, + * }); * ``` - * @returns The default OpenAPI configuration + * @returns {UmbOpenApiConfiguration} The default OpenAPI configuration */ getOpenApiConfiguration(): UmbOpenApiConfiguration { return { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/repository/structure/content-type-structure-server-data-source-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/repository/structure/content-type-structure-server-data-source-base.ts index 4991c103b3..b370ae5681 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/repository/structure/content-type-structure-server-data-source-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/repository/structure/content-type-structure-server-data-source-base.ts @@ -2,7 +2,7 @@ import type { UmbPagedModel } from '../../../repository/types.js'; import type { UmbContentTypeStructureDataSource } from './content-type-structure-data-source.interface.js'; import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; // Keep this type internal type AllowedContentTypeBaseModel = { @@ -55,10 +55,7 @@ export abstract class UmbContentTypeStructureServerDataSourceBase< * @memberof UmbContentTypeStructureServerDataSourceBase */ async getAllowedChildrenOf(unique: string | null, parentContentUnique: string | null) { - const { data, error } = await tryExecuteAndNotify( - this.#host, - this.#getAllowedChildrenOf(unique, parentContentUnique), - ); + const { data, error } = await tryExecute(this.#host, this.#getAllowedChildrenOf(unique, parentContentUnique)); if (data) { const items = data.items.map((item) => this.#mapper(item)); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/culture/repository/sources/culture.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/core/culture/repository/sources/culture.server.data.ts index 14a3574c59..99343287d7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/culture/repository/sources/culture.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/culture/repository/sources/culture.server.data.ts @@ -1,7 +1,7 @@ import type { UmbCultureDataSource } from './index.js'; import { CultureService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Language that fetches data from the server @@ -29,6 +29,6 @@ export class UmbCultureServerDataSource implements UmbCultureDataSource { * @memberof UmbLanguageServerDataSource */ async getCollection({ skip, take }: { skip: number; take: number }) { - return tryExecuteAndNotify(this.#host, CultureService.getCulture({ skip, take })); + return tryExecute(this.#host, CultureService.getCulture({ skip, take })); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error.controller.ts index 2506371e27..cf102fa9c5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error.controller.ts @@ -12,7 +12,7 @@ export class UmbPeekErrorController extends UmbControllerBase { throw new Error('Could not get notification context'); } - context.peek('danger', { + context.peek(args.color ?? 'danger', { elementName: 'umb-peek-error-notification', data: args, }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/index.ts index 1d57e22f7d..526e0028f4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/index.ts @@ -1,6 +1,6 @@ import './layouts/default/index.js'; export * from './controllers/peek-error/index.js'; -export * from './extractUmbNotificationColor.function.js'; +export * from '../resources/extractUmbNotificationColor.function.js'; export * from './isUmbNotifications.function.js'; export * from './notification-handler.js'; export * from './notification.context.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/isUmbNotifications.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/isUmbNotifications.function.ts index 6c8b9b2895..ab861df6c2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/isUmbNotifications.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/isUmbNotifications.function.ts @@ -1,8 +1,7 @@ import { EventMessageTypeModel } from '@umbraco-cms/backoffice/external/backend-api'; /** - * - * @param notification + * @deprecated Import from `@umbraco-cms/backoffice/resources` instead. */ function objectIsUmbNotification(notification: unknown): notification is UmbNotificationsEventModel { if (typeof notification !== 'object' || notification === null) { @@ -17,6 +16,9 @@ function objectIsUmbNotification(notification: unknown): notification is UmbNoti ); } +/** + * @deprecated Import from `@umbraco-cms/backoffice/resources` instead. + */ export interface UmbNotificationsEventModel { category: string; message: string; @@ -24,11 +26,13 @@ export interface UmbNotificationsEventModel { } /** - * - * @param notifications + * @deprecated Import from `@umbraco-cms/backoffice/resources` instead. */ export function isUmbNotifications(notifications: Array): notifications is Array { return notifications.every(objectIsUmbNotification); } +/** + * @deprecated Import from `@umbraco-cms/backoffice/resources` instead. + */ export const UMB_NOTIFICATION_HEADER = 'umb-notifications'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/types.ts index 3ec0daea78..7e47cd5182 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/types.ts @@ -26,5 +26,7 @@ export interface UmbNotificationOptions extends UmbDataSourceErrorResponse { data?: T; } export interface UmbDataSourceErrorResponse { - // TODO: we should not rely on the ApiError and CancelError types from the backend-api package - // We need to be able to return a generic error type that can be used in the frontend - // Example: the clipboard is getting is data from local storage, so it should not use the ApiError type /** * The error that occurred when fetching the data. - * The {ApiError} and {CancelError} types will change in the future to be a more generic error type. */ - error?: ApiError | CancelError; + error?: UmbError | UmbApiError | UmbCancelError | Error; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/item/item-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/item/item-repository.interface.ts index 0585c9cf4f..c4a12f83a9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/item/item-repository.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/item/item-repository.interface.ts @@ -1,11 +1,11 @@ import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import type { ProblemDetails } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; +import type { UmbProblemDetails } from '@umbraco-cms/backoffice/resources'; export interface UmbItemRepository extends UmbApi { requestItems: (uniques: string[]) => Promise<{ data?: Array | undefined; - error?: ProblemDetails | undefined; + error?: UmbProblemDetails | undefined; asObservable?: () => Observable>; }>; items: (uniques: string[]) => Promise>>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/item/item-server-data-source-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/item/item-server-data-source-base.ts index 5f50233b78..9ae47938eb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/item/item-server-data-source-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/item/item-server-data-source-base.ts @@ -1,6 +1,6 @@ import type { UmbItemDataSource } from '@umbraco-cms/backoffice/repository'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; export interface UmbItemServerDataSourceBaseArgs { getItems: (uniques: Array) => Promise>; @@ -39,7 +39,7 @@ export abstract class UmbItemServerDataSourceBase) { if (!uniques) throw new Error('Uniques are missing'); - const { data, error } = await tryExecuteAndNotify(this.#host, this.#getItems(uniques)); + const { data, error } = await tryExecute(this.#host, this.#getItems(uniques)); if (data) { const items = data.map((item) => this.#mapper(item)); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/api-interceptor.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/api-interceptor.controller.ts new file mode 100644 index 0000000000..aa54c5f841 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/api-interceptor.controller.ts @@ -0,0 +1,129 @@ +import { extractUmbNotificationColor } from './extractUmbNotificationColor.function.js'; +import { isUmbNotifications, UMB_NOTIFICATION_HEADER } from './isUmbNotifications.function.js'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import type { OpenAPIConfig } from '@umbraco-cms/backoffice/external/backend-api'; +import { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth'; +import type { UmbNotificationColor } from '@umbraco-cms/backoffice/notification'; + +export class UmbApiInterceptorController extends UmbControllerBase { + /** + * Binds the default interceptors to the client. + * This includes the auth response interceptor, the error interceptor and the umb-notifications interceptor. + * @param {OpenAPIConfig} client The OpenAPI client to add the interceptor to. It can be any client supporting Response and Request interceptors. + */ + public bindDefaultInterceptors(client: OpenAPIConfig) { + this.addAuthResponseInterceptor(client); + this.addUmbNotificationsInterceptor(client); + this.addErrorInterceptor(client); + } + + /** + * Interceptor which checks responses for 401 errors and lets the UmbAuthContext know the user is timed out. + * @param {OpenAPIConfig} client The OpenAPI client to add the interceptor to. It can be any client supporting Response and Request interceptors. + * @internal + */ + addAuthResponseInterceptor(client: OpenAPIConfig) { + client.interceptors.response.use(async (response) => { + if (response.status === 401) { + // See if we can get the UmbAuthContext and let it know the user is timed out + const authContext = await this.getContext(UMB_AUTH_CONTEXT, { preventTimeout: true }); + if (!authContext) { + throw new Error('Could not get the auth context'); + } + authContext.timeOut(); + } + return response; + }); + } + + /** + * Interceptor which checks responses for 500 errors and displays them as a notification if any. + * @param {OpenAPIConfig} client The OpenAPI client to add the interceptor to. It can be any client supporting Response and Request interceptors. + * @internal + */ + addErrorInterceptor(client: OpenAPIConfig) { + client.interceptors.response.use(async (response) => { + if (response.ok) return response; + + // Clones the response to read the body + const origResponse = response.clone(); + const error = await origResponse.json(); + if (!error) return response; + + // If the error is not an UmbError, we check if it is a problem details object + // Check if the error is a problem details object + if (!('type' in error) || !('title' in error) || !('status' in error)) { + // If not, we just return the response + return response; + } + + // Handle 500 errors - we need to show a notification + if (origResponse.status === 500) { + let headline = error.title ?? error.name ?? 'Server Error'; + let message = 'A fatal server error occurred. If this continues, please reach out to your administrator.'; + + // Special handling for ObjectCacheAppCache corruption errors, which we are investigating + if ( + error.detail?.includes('ObjectCacheAppCache') || + error.detail?.includes('Umbraco.Cms.Infrastructure.Scoping.Scope.DisposeLastScope()') + ) { + headline = 'Please restart the server'; + message = + 'The Umbraco object cache is corrupt, but your action may still have been executed. Please restart the server to reset the cache. This is a work in progress.'; + } + + this.#peekError(headline, message, error.errors ?? error.detail); + } + + // Return original response + return response; + }); + } + + /** + * Interceptor which checks responses for the umb-notifications header and displays them as a notification if any. Removes the umb-notifications from the headers. + * @param {OpenAPIConfig} client The OpenAPI client to add the interceptor to. It can be any client supporting Response and Request interceptors. + * @internal + */ + addUmbNotificationsInterceptor(client: OpenAPIConfig) { + client.interceptors.response.use((response) => { + // Check if the response has the umb-notifications header + // If not, we just return the response + const umbNotifications = response.headers.get(UMB_NOTIFICATION_HEADER); + if (!umbNotifications) return response; + + // Parse the notifications from the header + // If the header is not a valid JSON, we just return the response + try { + const notifications = JSON.parse(umbNotifications); + if (!isUmbNotifications(notifications)) return response; + + for (const notification of notifications) { + this.#peekError( + notification.category, + notification.message, + null, + extractUmbNotificationColor(notification.type), + ); + } + } catch { + // Ignore JSON parse errors + } + + return response; + }); + } + + async #peekError(headline: string, message: string, details: unknown, color?: UmbNotificationColor) { + // Store the host for usage in the following async context + const host = this._host; + + // This late importing is done to avoid circular reference [NL] + (await import('@umbraco-cms/backoffice/notification')).umbPeekError(host, { + headline, + message, + details, + color, + }); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/apiTypeValidators.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/apiTypeValidators.function.ts index bb5ba98d23..94a003fee4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/apiTypeValidators.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/apiTypeValidators.function.ts @@ -1,25 +1,28 @@ -import type { ApiError, CancelError, CancelablePromise } from '@umbraco-cms/backoffice/external/backend-api'; - /** - * - * @param error + * Checks if the given error is an instance of ApiError. + * @param {*} error The error to check + * @returns {boolean} True if the error is an instance of ApiError, false otherwise + * @deprecated Use {UmbApiError.isUmbApiError} instead and map your object to {UmbApiError} if needed. */ -export function isApiError(error: unknown): error is ApiError { - return (error as ApiError).name === 'ApiError'; +export function isApiError(error: unknown): error is { body?: string; status?: number; request?: unknown } { + return typeof error === 'object' && error !== null && 'body' in error && 'status' in error && 'request' in error; } /** - * - * @param error + * Checks if the given error is an instance of CancelError. + * @param {*} error The error to check + * @returns {boolean} True if the error is an instance of CancelError, false otherwise + * @deprecated Use {UmbApiCancelError.isUmbApiCancelError}` instead and map your object to {UmbApiCancelError} if needed. */ -export function isCancelError(error: unknown): error is CancelError { - return (error as CancelError).name === 'CancelError'; +export function isCancelError(error: unknown): error is Error { + return error instanceof Error && (error.name === 'CancelError' || (error as Error).message === 'Request aborted'); } /** - * - * @param promise + * Checks if the given promise is cancelable, i.e. if it has a cancel method. + * @param {*} promise The promise to check + * @returns {boolean} True if the promise is cancelable, false otherwise */ -export function isCancelablePromise(promise: unknown): promise is CancelablePromise { - return (promise as CancelablePromise)?.cancel !== undefined; +export function isCancelablePromise(promise: unknown): promise is Promise & { cancel: () => void } { + return typeof (promise as Promise & { cancel: () => void }).cancel === 'function'; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/cancelable-promise.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/cancelable-promise.ts new file mode 100644 index 0000000000..a3454d7c6a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/cancelable-promise.ts @@ -0,0 +1,117 @@ +import { UmbCancelError } from './umb-error.js'; + +export interface OnCancel { + readonly isResolved: boolean; + readonly isRejected: boolean; + readonly isCancelled: boolean; + + (cancelHandler: () => void): void; +} + +export class UmbCancelablePromise implements Promise { + private _isResolved: boolean; + private _isRejected: boolean; + private _isCancelled: boolean; + readonly cancelHandlers: (() => void)[]; + readonly promise: Promise; + private _resolve?: (value: T | PromiseLike) => void; + private _reject?: (reason?: unknown) => void; + + constructor( + executor: ( + resolve: (value: T | PromiseLike) => void, + reject: (reason?: unknown) => void, + onCancel: OnCancel, + ) => void, + ) { + this._isResolved = false; + this._isRejected = false; + this._isCancelled = false; + this.cancelHandlers = []; + this.promise = new Promise((resolve, reject) => { + this._resolve = resolve; + this._reject = reject; + + const onResolve = (value: T | PromiseLike): void => { + if (this._isResolved || this._isRejected || this._isCancelled) { + return; + } + this._isResolved = true; + if (this._resolve) this._resolve(value); + }; + + const onReject = (reason?: unknown): void => { + if (this._isResolved || this._isRejected || this._isCancelled) { + return; + } + this._isRejected = true; + if (this._reject) this._reject(reason); + }; + + const onCancel = (cancelHandler: () => void): void => { + if (this._isResolved || this._isRejected || this._isCancelled) { + return; + } + this.cancelHandlers.push(cancelHandler); + }; + + Object.defineProperty(onCancel, 'isResolved', { + get: (): boolean => this._isResolved, + }); + + Object.defineProperty(onCancel, 'isRejected', { + get: (): boolean => this._isRejected, + }); + + Object.defineProperty(onCancel, 'isCancelled', { + get: (): boolean => this._isCancelled, + }); + + return executor(onResolve, onReject, onCancel as OnCancel); + }); + } + + get [Symbol.toStringTag]() { + return 'Cancellable Promise'; + } + + public then( + onFulfilled?: ((value: T) => TResult1 | PromiseLike) | null, + onRejected?: ((reason: unknown) => TResult2 | PromiseLike) | null, + ): Promise { + return this.promise.then(onFulfilled, onRejected); + } + + public catch( + onRejected?: ((reason: unknown) => TResult | PromiseLike) | null, + ): Promise { + return this.promise.catch(onRejected); + } + + public finally(onFinally?: (() => void) | null): Promise { + return this.promise.finally(onFinally); + } + + public cancel(): void { + if (this._isResolved || this._isRejected || this._isCancelled) { + return; + } + this._isCancelled = true; + if (this.cancelHandlers.length) { + try { + for (const cancelHandler of this.cancelHandlers) { + cancelHandler(); + } + } catch (error) { + console.warn('Cancellation threw an error', error); + return; + } + } + this.cancelHandlers.length = 0; + if (this._reject) this._reject(new UmbCancelError('Request aborted')); + } + + public get isCancelled(): boolean { + return this._isCancelled; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/extractUmbNotificationColor.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/extractUmbNotificationColor.function.ts similarity index 54% rename from src/Umbraco.Web.UI.Client/src/packages/core/notification/extractUmbNotificationColor.function.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/resources/extractUmbNotificationColor.function.ts index 492f7c76b7..c787e44e23 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/extractUmbNotificationColor.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/extractUmbNotificationColor.function.ts @@ -1,9 +1,12 @@ -import type { UmbNotificationColor } from './types.js'; +import type { UmbNotificationColor } from '../notification/types.js'; import { EventMessageTypeModel } from '@umbraco-cms/backoffice/external/backend-api'; /** - * - * @param type + * Extracts the UmbNotificationColor from the EventMessageTypeModel. + * @param {EventMessageTypeModel} type The EventMessageTypeModel to extract the color from. + * @returns {UmbNotificationColor} The corresponding UmbNotificationColor. + * @example + * const color = extractUmbNotificationColor(EventMessageTypeModel.ERROR); // color will be 'danger' */ export function extractUmbNotificationColor(type: EventMessageTypeModel): UmbNotificationColor { switch (type) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/index.ts index 6de800cccb..e1e1756111 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/index.ts @@ -1,7 +1,12 @@ +export * from './api-interceptor.controller.js'; export * from './resource.controller.js'; +export * from './try-execute.controller.js'; export * from './tryExecute.function.js'; export * from './tryExecuteAndNotify.function.js'; export * from './tryXhrRequest.function.js'; +export * from './extractUmbNotificationColor.function.js'; export * from './extractUmbColorVariable.function.js'; +export * from './isUmbNotifications.function.js'; export * from './apiTypeValidators.function.js'; +export * from './umb-error.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/isUmbNotifications.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/isUmbNotifications.function.ts new file mode 100644 index 0000000000..036185b355 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/isUmbNotifications.function.ts @@ -0,0 +1,26 @@ +import { EventMessageTypeModel } from '@umbraco-cms/backoffice/external/backend-api'; + +function objectIsUmbNotification(notification: unknown): notification is UmbNotificationsEventModel { + if (typeof notification !== 'object' || notification === null) { + return false; + } + const object = notification as UmbNotificationsEventModel; + return ( + typeof object.category === 'string' && + typeof object.message === 'string' && + typeof object.type === 'string' && + Object.values(EventMessageTypeModel).includes(object.type) + ); +} + +export interface UmbNotificationsEventModel { + category: string; + message: string; + type: EventMessageTypeModel; +} + +export function isUmbNotifications(notifications: Array): notifications is Array { + return notifications.every(objectIsUmbNotification); +} + +export const UMB_NOTIFICATION_HEADER = 'umb-notifications'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts index dc728b4291..7b22a4a41c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts @@ -1,290 +1,43 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { UMB_AUTH_CONTEXT } from '../auth/index.js'; -import { UmbDeprecation } from '../utils/deprecation/deprecation.js'; -import { isApiError, isCancelError, isCancelablePromise } from './apiTypeValidators.function.js'; -import type { XhrRequestOptions } from './types.js'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { isApiError, isCancelablePromise, isCancelError } from './apiTypeValidators.function.js'; +import type { UmbCancelablePromise } from './cancelable-promise.js'; +import { UmbApiError, UmbCancelError, UmbError } from './umb-error.js'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import type { UmbNotificationOptions } from '@umbraco-cms/backoffice/notification'; -import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; -import { - ApiError, - CancelablePromise, - CancelError, - type ProblemDetails, -} from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; export class UmbResourceController extends UmbControllerBase { - #promise: Promise; + /** + * The promise that is being executed. + * @protected + */ + protected _promise: UmbCancelablePromise | Promise; - constructor(host: UmbControllerHost, promise: Promise, alias?: string) { + constructor(host: UmbControllerHost, promise: Promise, alias?: string) { super(host, alias); - this.#promise = promise; - } - - override hostDisconnected(): void { - super.hostDisconnected(); - this.cancel(); + this._promise = promise; } /** - * Base execute function with a try/catch block and return a tuple with the result and the error. - * @param promise + * Maps any error to an UmbError. + * @internal + * @param {*} error The error to map + * @returns {*} The mapped error */ - static async tryExecute(promise: Promise): Promise> { - // TODO: tryExecute should not take a promise as argument, but should utilize the class property `#promise` instead. (In this way the promise can be cancelled when disconnected) - try { - return { data: await promise }; - } catch (error) { - if (isApiError(error) || isCancelError(error)) { - return { error }; - } - - console.error('Unknown error', error); - throw new Error('Unknown error'); + mapToUmbError(error: unknown): UmbApiError | UmbCancelError | UmbError { + if (isApiError(error)) { + return UmbApiError.fromLegacyApiError(error as any); + } else if (isCancelError(error)) { + return UmbCancelError.fromLegacyCancelError(error); + } else if (UmbCancelError.isUmbCancelError(error)) { + return error; + } else if (UmbApiError.isUmbApiError(error)) { + return error; + } else if (UmbError.isUmbError(error)) { + return error; } - } - - /** - * Wrap the {tryExecute} function in a try/catch block and return the result. - * If the executor function throws an error, then show the details in a notification. - * @param _options - * @param options - */ - - async tryExecuteAndNotify(options?: UmbNotificationOptions): Promise> { - const { data, error } = await UmbResourceController.tryExecute(this.#promise); - - if (options) { - new UmbDeprecation({ - deprecated: 'tryExecuteAndNotify `options` argument is deprecated.', - removeInVersion: '17.0.0', - solution: 'Use the method without arguments.', - }).warn(); - } - - if (error) { - /** - * Determine if we want to show a notification or just log the error to the console. - * If the error is not a recognizable system error (i.e. a HttpError), then we will show a notification - * with the error details using the default notification options. - */ - if (isCancelError(error)) { - // Cancelled - do nothing - return { error }; - } else { - console.groupCollapsed('ApiError caught in UmbResourceController'); - console.error('Request failed', error.request); - console.error('Request body', error.body); - console.error('Error', error); - console.groupEnd(); - - let problemDetails: ProblemDetails | null = null; - - // ApiError - body could hold a ProblemDetails from the server - if (typeof error.body !== 'undefined' && !!error.body) { - try { - (error as any).body = problemDetails = typeof error.body === 'string' ? JSON.parse(error.body) : error.body; - } catch (e) { - console.error('Error parsing error body (expected JSON)', e); - } - } - - /** - * Check if the operation status ends with `ByNotification` and if so, don't show a notification - * This is a special case where the operation was cancelled by the server and the client gets a notification header instead. - */ - let isCancelledByNotification = false; - if ( - problemDetails?.operationStatus && - typeof problemDetails.operationStatus === 'string' && - problemDetails.operationStatus.endsWith('ByNotification') - ) { - isCancelledByNotification = true; - } - - // Go through the error status codes and act accordingly - switch (error.status ?? 0) { - case 401: { - // See if we can get the UmbAuthContext and let it know the user is timed out - const authContext = await this.getContext(UMB_AUTH_CONTEXT, { preventTimeout: true }); - if (!authContext) { - throw new Error('Could not get the auth context'); - } - authContext.timeOut(); - break; - } - case 500: - // Server Error - - if (!isCancelledByNotification) { - let headline = problemDetails?.title ?? error.name ?? 'Server Error'; - let message = 'A fatal server error occurred. If this continues, please reach out to your administrator.'; - - // Special handling for ObjectCacheAppCache corruption errors, which we are investigating - if ( - problemDetails?.detail?.includes('ObjectCacheAppCache') || - problemDetails?.detail?.includes('Umbraco.Cms.Infrastructure.Scoping.Scope.DisposeLastScope()') - ) { - headline = 'Please restart the server'; - message = - 'The Umbraco object cache is corrupt, but your action may still have been executed. Please restart the server to reset the cache. This is a work in progress.'; - } - - // This late importing is done to avoid circular reference [NL] - (await import('@umbraco-cms/backoffice/notification')).umbPeekError(this, { - headline: headline, - message: message, - details: problemDetails?.errors ?? problemDetails?.detail, - }); - } - break; - default: - // Other errors - if (!isCancelledByNotification) { - /* - const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT); - notificationContext.peek('danger', { - data: { - headline: problemDetails?.title ?? error.name ?? 'Server Error', - message: problemDetails?.detail ?? error.message ?? 'Something went wrong', - structuredList: problemDetails?.errors - ? (problemDetails.errors as Record>) - : undefined, - }, - ...options, - }); - */ - const headline = problemDetails?.title ?? error.name ?? 'Server Error'; - // This late importing is done to avoid circular reference [NL] - (await import('@umbraco-cms/backoffice/notification')).umbPeekError(this, { - message: headline, - details: problemDetails?.errors ?? problemDetails?.detail, - }); - } - } - } - } - - return { data, error }; - } - - /** - * Make an XHR request. - * @param host The controller host for this controller to be appended to. - * @param options The options for the XHR request. - */ - static xhrRequest(options: XhrRequestOptions): CancelablePromise { - const baseUrl = options.baseUrl || '/umbraco'; - - const promise = new CancelablePromise(async (resolve, reject, onCancel) => { - const xhr = new XMLHttpRequest(); - xhr.open(options.method, `${baseUrl}${options.url}`, true); - - // Set default headers - if (options.token) { - const token = typeof options.token === 'function' ? await options.token() : options.token; - if (token) { - xhr.setRequestHeader('Authorization', `Bearer ${token}`); - } - } - - // Infer Content-Type header based on body type - if (options.body instanceof FormData) { - // Note: 'multipart/form-data' is automatically set by the browser for FormData - } else { - xhr.setRequestHeader('Content-Type', 'application/json'); - } - - // Set custom headers - if (options.headers) { - for (const [key, value] of Object.entries(options.headers)) { - xhr.setRequestHeader(key, value); - } - } - - xhr.upload.onprogress = (event) => { - if (options.onProgress) { - options.onProgress(event); - } - }; - - xhr.onload = () => { - try { - if (xhr.status >= 200 && xhr.status < 300) { - if (options.responseHeader) { - const response = xhr.getResponseHeader(options.responseHeader); - resolve(response as T); - } else { - resolve(JSON.parse(xhr.responseText)); - } - } else { - // TODO: [JOV] This has to be changed into our own error type, when we have a chance to introduce a breaking change in the future. - const error = new ApiError( - { - method: options.method, - url: `${baseUrl}${options.url}`, - }, - { - body: xhr.responseText, - ok: false, - status: xhr.status, - statusText: xhr.statusText, - url: xhr.responseURL, - }, - xhr.statusText, - ); - reject(error); - } - } catch { - // This most likely happens when the response is not JSON - reject(new Error(`Failed to make request: ${xhr.statusText}`)); - } - }; - - xhr.onerror = () => { - // TODO: [JOV] This has to be changed into our own error type, when we have a chance to introduce a breaking change in the future. - const error = new ApiError( - { - method: options.method, - url: `${baseUrl}${options.url}`, - }, - { - body: xhr.responseText, - ok: false, - status: xhr.status, - statusText: xhr.statusText, - url: xhr.responseURL, - }, - xhr.statusText, - ); - reject(error); - }; - - if (!onCancel.isCancelled) { - // Handle body based on Content-Type - if (options.body instanceof FormData) { - xhr.send(options.body); - } else { - xhr.send(JSON.stringify(options.body)); - } - } - - onCancel(() => { - xhr.abort(); - // TODO: [JOV] This has to be changed into our own error type, when we have a chance to introduce a breaking change in the future. - reject(new CancelError('Request was cancelled.')); - }); - }); - - if (options.abortSignal) { - options.abortSignal.addEventListener('abort', () => { - promise.cancel(); - }); - } - - return promise; + // If the error is not an UmbError, we will just return it as is + return new UmbError(error instanceof Error ? error.message : 'Unknown error'); } /** @@ -298,13 +51,30 @@ export class UmbResourceController extends UmbControllerBase { * @see https://developer.mozilla.org/en-US/docs/Web/API/AbortController */ cancel(): void { - if (isCancelablePromise(this.#promise)) { - this.#promise.cancel(); + if (isCancelablePromise(this._promise)) { + this._promise.cancel(); } } + override hostDisconnected(): void { + super.hostDisconnected(); + this.cancel(); + } + override destroy(): void { super.destroy(); this.cancel(); } + + protected async _peekError(headline: string, message: string, details: unknown) { + // Store the host for usage in the following async context + const host = this._host; + + // This late importing is done to avoid circular reference + (await import('@umbraco-cms/backoffice/notification')).umbPeekError(host, { + headline, + message, + details, + }); + } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/try-execute.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/try-execute.controller.ts new file mode 100644 index 0000000000..2df496efbe --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/try-execute.controller.ts @@ -0,0 +1,61 @@ +import { UmbResourceController } from './resource.controller.js'; +import type { UmbTryExecuteOptions } from './types.js'; +import { UmbApiError, UmbCancelError } from './umb-error.js'; +import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; + +export class UmbTryExecuteController extends UmbResourceController { + #abortSignal?: AbortSignal; + + async tryExecute(opts?: UmbTryExecuteOptions): Promise> { + try { + if (opts?.abortSignal) { + this.#abortSignal = opts.abortSignal; + this.#abortSignal.addEventListener('abort', () => this.cancel(), { once: true }); + } + + return { data: await this._promise }; + } catch (error) { + // Error might be a legacy error, so we need to check if it is an UmbError + const umbError = this.mapToUmbError(error); + + if (!opts?.disableNotifications) { + this.#notifyOnError(umbError); + } + + return { + error: umbError, + }; + } + } + + override destroy(): void { + if (this.#abortSignal) { + this.#abortSignal.removeEventListener('abort', this.cancel); + } + super.destroy(); + } + + #notifyOnError(error: unknown) { + if (UmbCancelError.isUmbCancelError(error)) { + // Cancel error, do not show notification + return; + } + + let headline = 'An error occurred'; + let message = 'An error occurred while trying to execute the request.'; + let details: Record = {}; + + if (UmbApiError.isUmbApiError(error)) { + // UmbApiError, show notification + headline = error.problemDetails.title ?? error.name; + message = error.problemDetails.detail ?? error.message; + details = error.problemDetails.errors ?? {}; + } else { + // Unknown error, show notification + headline = ''; + message = error instanceof Error ? error.message : 'An unknown error occurred.'; + } + + this._peekError(headline, message, details); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/tryExecute.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/tryExecute.function.ts index c4b8b60adf..ab96539486 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/tryExecute.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/tryExecute.function.ts @@ -1,10 +1,31 @@ -import { UmbResourceController } from './resource.controller.js'; +import { UmbTryExecuteController } from './try-execute.controller.js'; +import type { UmbTryExecuteOptions } from './types.js'; import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; /** - * - * @param promise + * Make a request and handle errors. + * @param {UmbControllerHost} host The host to use for the request and where notifications will be shown. + * @param {Promise} promise The promise to execute. + * @param {UmbTryExecuteOptions} opts Options for the request. + * @returns {Promise>} A promise that resolves with the response data or rejects with an error. + * @template T The type of the response data. + * @example + * const { data, error } = await tryExecute(this, myPromise, { + * abortSignal: myAbortSignal, + * disableNotifications: false, + * }); + * if (!error) { + * console.log('Success:', data); + * } */ -export function tryExecute(promise: Promise): Promise> { - return UmbResourceController.tryExecute(promise); +export async function tryExecute( + host: UmbControllerHost, + promise: Promise, + opts?: UmbTryExecuteOptions, +): Promise> { + const controller = new UmbTryExecuteController(host, promise); + const response = await controller.tryExecute(opts); + controller.destroy(); + return response as UmbDataSourceResponse; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/tryExecuteAndNotify.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/tryExecuteAndNotify.function.ts index 2e2b416704..46f9d3882c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/tryExecuteAndNotify.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/tryExecuteAndNotify.function.ts @@ -1,18 +1,30 @@ -import { UmbResourceController } from './resource.controller.js'; +import { UmbTryExecuteController } from './try-execute.controller.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import type { UmbNotificationOptions } from '@umbraco-cms/backoffice/notification'; import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; +import { UmbDeprecation } from '@umbraco-cms/backoffice/utils'; /** - * - * @param host - * @param resource - * @param options + * Make a request and notify the user of any errors. + * This function is a wrapper around the {@link tryExecute} function and will notify the user of any errors. + * It is useful for making requests where you want to handle errors in a consistent way. + * @param {UmbControllerHost} host The host to use for the request. + * @param {Promise} resource The resource to request. + * @returns {Promise>} A promise that resolves with the response data or rejects with an error. + * @template T The type of the response data. + * @deprecated Use the {@link tryExecute} function instead and handle the error in the caller. + * This function is kept for backwards compatibility and will be removed in a future version. */ -export function tryExecuteAndNotify( +export async function tryExecuteAndNotify( host: UmbControllerHost, resource: Promise, - options?: UmbNotificationOptions, ): Promise> { - return new UmbResourceController(host, resource).tryExecuteAndNotify(options); + new UmbDeprecation({ + deprecated: 'The tryExecuteAndNotify function is deprecated.', + removeInVersion: '18.0.0', + solution: 'Use the tryExecute function with options instead.', + }).warn(); + const controller = new UmbTryExecuteController(host, resource); + const response = await controller.tryExecute({ disableNotifications: false }); + controller.destroy(); + return response as UmbDataSourceResponse; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/tryXhrRequest.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/tryXhrRequest.function.ts index 749fafc729..68f2f222eb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/tryXhrRequest.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/tryXhrRequest.function.ts @@ -1,16 +1,126 @@ +import { UmbTryExecuteController } from './try-execute.controller.js'; +import { UmbCancelablePromise } from './cancelable-promise.js'; +import { UmbApiError } from './umb-error.js'; import type { XhrRequestOptions } from './types.js'; -import { UmbResourceController } from './resource.controller.js'; -import { OpenAPI, type CancelablePromise } from '@umbraco-cms/backoffice/external/backend-api'; +import { OpenAPI } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; /** * Make an XHR request. - * @param {XhrRequestOptions} options The options for the XHR request. - * @returns {CancelablePromise} A promise that can be cancelled. + * This function is a wrapper around XMLHttpRequest to provide a consistent API for making requests. + * It supports cancelable promises, progress events, and custom headers. + * @param {UmbControllerHost} host The host to use for the request. + * @param {XhrRequestOptions} options The options for the request. + * @returns {Promise>} A promise that resolves with the response data or rejects with an error. + * @template T The type of the response data. */ -export function tryXhrRequest(options: XhrRequestOptions): CancelablePromise { - return UmbResourceController.xhrRequest({ +export async function tryXhrRequest( + host: UmbControllerHost, + options: XhrRequestOptions, +): Promise> { + const promise = createXhrRequest({ ...options, baseUrl: OpenAPI.BASE, token: OpenAPI.TOKEN as never, }); + const controller = new UmbTryExecuteController(host, promise); + const response = await controller.tryExecute(options); + controller.destroy(); + return response as UmbDataSourceResponse; +} + +/** + * Create an XHR request. + * @param {XhrRequestOptions} options The options for the request. + * @returns {UmbCancelablePromise} A cancelable promise that resolves with the response data or rejects with an error. + * @template T The type of the response data. + * @internal + */ +function createXhrRequest(options: XhrRequestOptions): UmbCancelablePromise { + const baseUrl = options.baseUrl || '/umbraco'; + + return new UmbCancelablePromise(async (resolve, reject, onCancel) => { + const xhr = new XMLHttpRequest(); + xhr.open(options.method, `${baseUrl}${options.url}`, true); + + // Set default headers + if (options.token) { + const token = typeof options.token === 'function' ? await options.token() : options.token; + if (token) { + xhr.setRequestHeader('Authorization', `Bearer ${token}`); + } + } + + // Infer Content-Type header based on body type + if (options.body instanceof FormData) { + // Note: 'multipart/form-data' is automatically set by the browser for FormData + } else { + xhr.setRequestHeader('Content-Type', 'application/json'); + } + + // Set custom headers + if (options.headers) { + for (const [key, value] of Object.entries(options.headers)) { + xhr.setRequestHeader(key, value); + } + } + + xhr.upload.onprogress = (event) => { + if (options.onProgress) { + options.onProgress(event); + } + }; + + xhr.onload = () => { + try { + if (xhr.status >= 200 && xhr.status < 300) { + if (options.responseHeader) { + const response = xhr.getResponseHeader(options.responseHeader); + resolve(response as T); + } else { + resolve(JSON.parse(xhr.responseText)); + } + } else { + const error = new UmbApiError(xhr.statusText, xhr.status, xhr, { + title: xhr.statusText, + type: 'ApiError', + status: xhr.status, + }); + reject(error); + } + } catch { + // This most likely happens when the response is not JSON + reject( + new UmbApiError(`Failed to make request: ${xhr.statusText}`, xhr.status, xhr, { + title: xhr.statusText, + type: 'ApiError', + status: xhr.status, + }), + ); + } + }; + + xhr.onerror = () => { + const error = new UmbApiError(xhr.statusText, xhr.status, xhr, { + title: xhr.statusText, + type: 'ApiError', + status: xhr.status, + }); + reject(error); + }; + + if (!onCancel.isCancelled) { + // Handle body based on Content-Type + if (options.body instanceof FormData) { + xhr.send(options.body); + } else { + xhr.send(JSON.stringify(options.body)); + } + } + + onCancel(() => { + xhr.abort(); + }); + }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/types.ts index 8b5c34c3f1..bbdebf1d1e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/types.ts @@ -1,4 +1,4 @@ -export interface XhrRequestOptions { +export interface XhrRequestOptions extends UmbTryExecuteOptions { baseUrl?: string; method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'; url: string; @@ -7,5 +7,29 @@ export interface XhrRequestOptions { headers?: Record; responseHeader?: string; onProgress?: (event: ProgressEvent) => void; +} + +export interface UmbProblemDetails { + type: string; + title: string; + status: number; + stack?: unknown; + detail?: string; + instance?: string; + operationStatus?: string; + extensions?: Record; + errors?: Record; +} + +export interface UmbTryExecuteOptions { + /** + * If set to true, the controller will not show any notifications at all. + * @default false + */ + disableNotifications?: boolean; + + /** + * Signal object to cancel the request. + */ abortSignal?: AbortSignal; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/umb-error.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/umb-error.ts new file mode 100644 index 0000000000..0dd787b67f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/umb-error.ts @@ -0,0 +1,72 @@ +import type { UmbProblemDetails } from './types.js'; + +export class UmbError extends Error { + public override name = 'UmbError'; + + public static isUmbError(error: unknown): error is UmbError { + return error instanceof UmbError || (error as UmbError).name === 'UmbError'; + } +} + +export class UmbCancelError extends UmbError { + public override name = 'UmbCancelError'; + + public static isUmbCancelError(error: unknown): error is UmbCancelError { + return error instanceof UmbCancelError || (error as UmbCancelError).name === 'UmbCancelError'; + } + + /** + * Transforms a CancelError into an UmbCancelError. + * @param {*} error The CancelError to transform. + * @returns {UmbCancelError} The transformed UmbCancelError. + * @deprecated Use `UmbCancelError.isUmbCancelError` instead and map your object to `UmbCancelError` if needed. + */ + public static fromLegacyCancelError(error: Error): UmbCancelError { + return new UmbCancelError(error.message); + } +} + +/** + * UmbApiError is a class that extends UmbError and represents an error that occurs during an API call. + */ +export class UmbApiError extends UmbError { + public override name = 'UmbApiError'; + public status: number; + public request: unknown; + public problemDetails: UmbProblemDetails; + + public constructor(message: string, status: number, request: unknown, problemDetails: UmbProblemDetails) { + super(message); + this.status = status; + this.request = request; + this.problemDetails = problemDetails; + } + + public static isUmbApiError(error: unknown): error is UmbApiError { + return error instanceof UmbApiError || (error as UmbApiError).name === 'UmbApiError'; + } + + /** + * Transforms an ApiError into an UmbApiError. + * @param {*} error The ApiError to transform. + * @returns {UmbApiError} The transformed UmbApiError. + * @deprecated Use `UmbCancelError.isUmbApiError` instead and map your object to `UmbApiError` if needed. + */ + public static fromLegacyApiError(error: Error & { body?: string; status?: number; request?: unknown }): UmbApiError { + // ApiError - body could hold a ProblemDetails from the server + let problemDetails: UmbProblemDetails | null = null; + if (typeof error.body !== 'undefined' && !!error.body) { + try { + problemDetails = typeof error.body === 'string' ? JSON.parse(error.body) : error.body; + } catch (e) { + console.error('Error parsing error body (expected JSON)', e); + } + } + return new UmbApiError( + error.message, + error.status ?? 0, + error.request, + problemDetails ?? { title: error.message, type: 'ApiError', status: error.status ?? 0 }, + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/config/config.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/config/config.server.data-source.ts index 10d2db7a04..3f3ac52aa9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/config/config.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/config/config.server.data-source.ts @@ -1,6 +1,6 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { TemporaryFileService } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; export class UmbTemporaryFileConfigServerDataSource { #host; @@ -13,6 +13,6 @@ export class UmbTemporaryFileConfigServerDataSource { * Get the temporary file configuration. */ getConfig() { - return tryExecuteAndNotify(this.#host, TemporaryFileService.getTemporaryFileConfiguration()); + return tryExecute(this.#host, TemporaryFileService.getTemporaryFileConfiguration()); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/temporary-file.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/temporary-file.server.data-source.ts index 415995f20a..ff3642c385 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/temporary-file.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/temporary-file.server.data-source.ts @@ -1,7 +1,7 @@ import type { UmbDataSourceResponse } from '../repository/index.js'; import { TemporaryFileService, type PostTemporaryFileResponse } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify, tryXhrRequest } from '@umbraco-cms/backoffice/resources'; +import { tryExecute, tryXhrRequest } from '@umbraco-cms/backoffice/resources'; /** * A data source to upload temporary files to the server @@ -36,7 +36,7 @@ export class UmbTemporaryFileServerDataSource { const body = new FormData(); body.append('Id', id); body.append('File', file); - const xhrRequest = tryXhrRequest({ + const xhrRequest = tryXhrRequest(this.#host, { url: '/umbraco/management/api/v1/temporary-file', method: 'POST', responseHeader: 'Umb-Generated-Resource', @@ -44,7 +44,7 @@ export class UmbTemporaryFileServerDataSource { onProgress, abortSignal, }); - return tryExecuteAndNotify(this.#host, xhrRequest); + return xhrRequest; } /** @@ -55,7 +55,7 @@ export class UmbTemporaryFileServerDataSource { */ read(id: string) { if (!id) throw new Error('Id is missing'); - return tryExecuteAndNotify(this.#host, TemporaryFileService.getTemporaryFileById({ id })); + return tryExecute(this.#host, TemporaryFileService.getTemporaryFileById({ id })); } /** @@ -66,6 +66,6 @@ export class UmbTemporaryFileServerDataSource { */ delete(id: string) { if (!id) throw new Error('Id is missing'); - return tryExecuteAndNotify(this.#host, TemporaryFileService.deleteTemporaryFileById({ id })); + return tryExecute(this.#host, TemporaryFileService.deleteTemporaryFileById({ id })); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository-base.ts index 18baee61ce..ef62e28205 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository-base.ts @@ -8,10 +8,10 @@ import type { UmbTreeRootItemsRequestArgs, } from './types.js'; import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; -import type { ProblemDetails } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; import type { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import type { UmbProblemDetails } from '@umbraco-cms/backoffice/resources'; /** * Base class for a tree repository. @@ -70,7 +70,7 @@ export abstract class UmbTreeRepositoryBase< * @returns {*} * @memberof UmbTreeRepositoryBase */ - abstract requestTreeRoot(): Promise<{ data?: TreeRootType; error?: ProblemDetails }>; + abstract requestTreeRoot(): Promise<{ data?: TreeRootType; error?: UmbProblemDetails }>; /** * Requests root items of a tree diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository.interface.ts index 0331e90c77..afdb7226b2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository.interface.ts @@ -6,8 +6,8 @@ import type { } from './types.js'; import type { UmbPagedModel } from '@umbraco-cms/backoffice/repository'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import type { ProblemDetails } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; +import type { UmbProblemDetails } from '@umbraco-cms/backoffice/resources'; /** * Interface for a tree repository. @@ -29,7 +29,7 @@ export interface UmbTreeRepository< */ requestTreeRoot: () => Promise<{ data?: TreeRootType; - error?: ProblemDetails; + error?: UmbProblemDetails; }>; /** @@ -39,7 +39,7 @@ export interface UmbTreeRepository< */ requestTreeRootItems: (args: TreeRootItemsRequestArgsType) => Promise<{ data?: UmbPagedModel; - error?: ProblemDetails; + error?: UmbProblemDetails; asObservable?: () => Observable; }>; @@ -50,7 +50,7 @@ export interface UmbTreeRepository< */ requestTreeItemsOf: (args: TreeChildrenOfRequestArgsType) => Promise<{ data?: UmbPagedModel; - error?: ProblemDetails; + error?: UmbProblemDetails; asObservable?: () => Observable; }>; @@ -61,7 +61,7 @@ export interface UmbTreeRepository< */ requestTreeItemAncestors: ( args: TreeAncestorsOfRequestArgsType, - ) => Promise<{ data?: TreeItemType[]; error?: ProblemDetails; asObservable?: () => Observable }>; + ) => Promise<{ data?: TreeItemType[]; error?: UmbProblemDetails; asObservable?: () => Observable }>; /** * Returns an observable of the root items of the tree. diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-server-data-source-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-server-data-source-base.ts index ff035537a1..d8069603f2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-server-data-source-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-server-data-source-base.ts @@ -5,7 +5,7 @@ import type { UmbTreeChildrenOfRequestArgs, UmbTreeRootItemsRequestArgs, } from './types.js'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbPagedModel } from '@umbraco-cms/backoffice/repository'; @@ -77,7 +77,7 @@ export abstract class UmbTreeServerDataSourceBase< * @memberof UmbTreeServerDataSourceBase */ async getRootItems(args: TreeRootItemsRequestArgsType) { - const { data, error } = await tryExecuteAndNotify(this.#host, this.#getRootItems(args)); + const { data, error } = await tryExecute(this.#host, this.#getRootItems(args)); if (data) { const items = data?.items.map((item) => this.#mapper(item)); @@ -96,7 +96,7 @@ export abstract class UmbTreeServerDataSourceBase< async getChildrenOf(args: TreeChildrenOfRequestArgsType) { if (args.parent.unique === undefined) throw new Error('Parent unique is missing'); - const { data, error } = await tryExecuteAndNotify(this.#host, this.#getChildrenOf(args)); + const { data, error } = await tryExecute(this.#host, this.#getChildrenOf(args)); if (data) { const items = data?.items.map((item: ServerTreeItemType) => this.#mapper(item)); @@ -115,7 +115,7 @@ export abstract class UmbTreeServerDataSourceBase< async getAncestorsOf(args: TreeAncestorsOfRequestArgsType) { if (!args.treeItem.entityType) throw new Error('Parent unique is missing'); - const { data, error } = await tryExecuteAndNotify(this.#host, this.#getAncestorsOf(args)); + const { data, error } = await tryExecute(this.#host, this.#getAncestorsOf(args)); if (data) { const items = data?.map((item: ServerTreeItemType) => this.#mapper(item)); diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/collection/repository/data-type-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/collection/repository/data-type-collection.server.data-source.ts index b986141d01..637f8dde0e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/collection/repository/data-type-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/collection/repository/data-type-collection.server.data-source.ts @@ -1,7 +1,7 @@ import type { UmbDataTypeCollectionFilterModel } from '../types.js'; import type { UmbDataTypeItemModel } from '../../repository/index.js'; import { UMB_DATA_TYPE_ENTITY_TYPE } from '../../entity.js'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import { DataTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/collection'; import type { DataTypeItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; @@ -40,7 +40,7 @@ export class UmbDataTypeCollectionServerDataSource implements UmbCollectionDataS * @DataTypeof UmbDataTypeCollectionServerDataSource */ async getCollection(filter: UmbDataTypeCollectionFilterModel) { - const { data, error } = await tryExecuteAndNotify(this.#host, DataTypeService.getFilterDataType(filter)); + const { data, error } = await tryExecute(this.#host, DataTypeService.getFilterDataType(filter)); if (error) { return { error }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/duplicate/repository/data-type-duplicate.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/duplicate/repository/data-type-duplicate.server.data-source.ts index c95604577e..73899fb42a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/duplicate/repository/data-type-duplicate.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/duplicate/repository/data-type-duplicate.server.data-source.ts @@ -1,6 +1,6 @@ import { DataTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbDuplicateToDataSource, UmbDuplicateToRequestArgs } from '@umbraco-cms/backoffice/tree'; /** @@ -29,7 +29,7 @@ export class UmbDuplicateDataTypeServerDataSource implements UmbDuplicateToDataS if (!args.unique) throw new Error('Unique is missing'); if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, DataTypeService.postDataTypeByIdCopy({ id: args.unique, diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/data-type-move.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/data-type-move.server.data-source.ts index 524b71b541..22982c86c1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/data-type-move.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/entity-actions/move-to/repository/data-type-move.server.data-source.ts @@ -1,6 +1,6 @@ import { DataTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbMoveDataSource, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/tree'; /** @@ -31,7 +31,7 @@ export class UmbMoveDataTypeServerDataSource implements UmbMoveDataSource { if (!args.unique) throw new Error('Unique is missing'); if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, DataTypeService.putDataTypeByIdMove({ id: args.unique, diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/data-type-reference.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/data-type-reference.server.data.ts index b94f270e18..e6539a7294 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/data-type-reference.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/data-type-reference.server.data.ts @@ -1,4 +1,4 @@ -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import { DataTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -25,6 +25,6 @@ export class UmbDataTypeReferenceServerDataSource { * @memberof UmbDataTypeReferenceServerDataSource */ async getReferencedBy(id: string) { - return await tryExecuteAndNotify(this.#host, DataTypeService.getDataTypeByIdReferences({ id })); + return await tryExecute(this.#host, DataTypeService.getDataTypeByIdReferences({ id })); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts index 3eb91ed61f..d085fcfedd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts @@ -8,7 +8,7 @@ import type { } from '@umbraco-cms/backoffice/external/backend-api'; import { DataTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Data Type that fetches data from the server @@ -57,7 +57,7 @@ export class UmbDataTypeServerDataSource implements UmbDetailDataSource { diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/dictionary-move.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/dictionary-move.server.data-source.ts index a18f0f9916..247a15f6c4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/dictionary-move.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/entity-action/move-to/repository/dictionary-move.server.data-source.ts @@ -1,6 +1,6 @@ import { DictionaryService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbMoveDataSource, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/tree'; /** @@ -31,7 +31,7 @@ export class UmbMoveDictionaryServerDataSource implements UmbMoveDataSource { if (!args.unique) throw new Error('Unique is missing'); if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, DictionaryService.putDictionaryByIdMove({ id: args.unique, diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/repository/detail/dictionary-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/repository/detail/dictionary-detail.server.data-source.ts index de6a91d59d..d7f66fd676 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/repository/detail/dictionary-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/repository/detail/dictionary-detail.server.data-source.ts @@ -8,7 +8,7 @@ import type { } from '@umbraco-cms/backoffice/external/backend-api'; import { DictionaryService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Dictionary that fetches data from the server @@ -52,7 +52,7 @@ export class UmbDictionaryServerDataSource implements UmbDetailDataSource x.id !== id); @@ -127,10 +127,7 @@ export class UmbDashboardRedirectManagementElement extends UmbLitElement { async #trackerToggle() { const status = this._trackerEnabled ? RedirectStatusModel.DISABLED : RedirectStatusModel.ENABLED; - const { error } = await tryExecuteAndNotify( - this, - RedirectManagementService.postRedirectManagementStatus({ status }), - ); + const { error } = await tryExecute(this, RedirectManagementService.postRedirectManagementStatus({ status })); if (error) return; this._trackerEnabled = !this._trackerEnabled; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/duplicate/repository/document-type-duplicate.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/duplicate/repository/document-type-duplicate.server.data-source.ts index 25c78481f3..afc6c0a705 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/duplicate/repository/document-type-duplicate.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/duplicate/repository/document-type-duplicate.server.data-source.ts @@ -1,6 +1,6 @@ import { DocumentTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbDuplicateToDataSource, UmbDuplicateToRequestArgs } from '@umbraco-cms/backoffice/tree'; /** @@ -29,7 +29,7 @@ export class UmbDuplicateDocumentTypeServerDataSource implements UmbDuplicateToD if (!args.unique) throw new Error('Unique is missing'); if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, DocumentTypeService.postDocumentTypeByIdCopy({ id: args.unique, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/export/repository/document-type-export.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/export/repository/document-type-export.server.data-source.ts index c67e9bf0c5..abe26a3cc6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/export/repository/document-type-export.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/export/repository/document-type-export.server.data-source.ts @@ -1,6 +1,6 @@ import { DocumentTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * Export Document Server Data Source @@ -27,6 +27,6 @@ export class UmbExportDocumentTypeServerDataSource { async export(unique: string) { if (!unique) throw new Error('Unique is missing'); - return tryExecuteAndNotify(this.#host, DocumentTypeService.getDocumentTypeByIdExport({ id: unique })); + return tryExecute(this.#host, DocumentTypeService.getDocumentTypeByIdExport({ id: unique })); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/import/repository/document-type-import.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/import/repository/document-type-import.server.data-source.ts index bfba81e1ed..5a2f602f18 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/import/repository/document-type-import.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/import/repository/document-type-import.server.data-source.ts @@ -1,6 +1,6 @@ import { DocumentTypeService, type PostDocumentTypeImportData } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * Document Type Import Server Data Source @@ -32,6 +32,6 @@ export class UmbDocumentTypeImportServerDataSource { requestBody: { file: { id: temporaryUnique } }, }; - return tryExecuteAndNotify(this.#host, DocumentTypeService.postDocumentTypeImport(requestBody)); + return tryExecute(this.#host, DocumentTypeService.postDocumentTypeImport(requestBody)); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/document-type-move.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/document-type-move.server.data-source.ts index 16200f0089..ba8ba22bbb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/document-type-move.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/move-to/repository/document-type-move.server.data-source.ts @@ -1,6 +1,6 @@ import { DocumentTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbMoveDataSource, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/tree'; /** @@ -31,7 +31,7 @@ export class UmbMoveDocumentTypeServerDataSource implements UmbMoveDataSource { if (!args.unique) throw new Error('Unique is missing'); if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, DocumentTypeService.putDocumentTypeByIdMove({ id: args.unique, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/composition/document-type-composition.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/composition/document-type-composition.server.data-source.ts index 0609f5427f..6a257dc16b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/composition/document-type-composition.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/composition/document-type-composition.server.data-source.ts @@ -8,7 +8,7 @@ import { DocumentTypeService, } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbContentTypeCompositionDataSource } from '@umbraco-cms/backoffice/content-type'; /** @@ -40,7 +40,7 @@ export class UmbDocumentTypeCompositionServerDataSource * @memberof UmbDocumentTypeCompositionServerDataSource */ async getReferences(unique: string) { - const response = await tryExecuteAndNotify( + const response = await tryExecute( this.#host, DocumentTypeService.getDocumentTypeByIdCompositionReferences({ id: unique }), ); @@ -70,7 +70,7 @@ export class UmbDocumentTypeCompositionServerDataSource currentPropertyAliases: args.currentPropertyAliases, }; - const response = await tryExecuteAndNotify( + const response = await tryExecute( this.#host, DocumentTypeService.postDocumentTypeAvailableCompositions({ requestBody }), ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/detail/document-type-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/detail/document-type-detail.server.data-source.ts index 77f3ede548..aaf83ef177 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/detail/document-type-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/detail/document-type-detail.server.data-source.ts @@ -8,7 +8,7 @@ import type { } from '@umbraco-cms/backoffice/external/backend-api'; import { DocumentTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbPropertyContainerTypes, UmbPropertyTypeContainerModel } from '@umbraco-cms/backoffice/content-type'; /** @@ -74,10 +74,7 @@ export class UmbDocumentTypeDetailServerDataSource implements UmbDetailDataSourc async read(unique: string) { if (!unique) throw new Error('Unique is missing'); - const { data, error } = await tryExecuteAndNotify( - this.#host, - DocumentTypeService.getDocumentTypeById({ id: unique }), - ); + const { data, error } = await tryExecute(this.#host, DocumentTypeService.getDocumentTypeById({ id: unique })); if (error || !data) { return { error }; @@ -189,7 +186,7 @@ export class UmbDocumentTypeDetailServerDataSource implements UmbDetailDataSourc collection: model.collection?.unique ? { id: model.collection?.unique } : null, }; - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, DocumentTypeService.postDocumentType({ requestBody, @@ -265,7 +262,7 @@ export class UmbDocumentTypeDetailServerDataSource implements UmbDetailDataSourc collection: model.collection?.unique ? { id: model.collection?.unique } : null, }; - const { error } = await tryExecuteAndNotify( + const { error } = await tryExecute( this.#host, DocumentTypeService.putDocumentTypeById({ id: model.unique, @@ -289,7 +286,7 @@ export class UmbDocumentTypeDetailServerDataSource implements UmbDetailDataSourc async delete(unique: string) { if (!unique) throw new Error('Unique is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, DocumentTypeService.deleteDocumentTypeById({ id: unique, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/search/document-type-search.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/search/document-type-search.server.data-source.ts index 162b97fd31..784945fb45 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/search/document-type-search.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/search/document-type-search.server.data-source.ts @@ -3,7 +3,7 @@ import type { UmbDocumentTypeSearchItemModel } from './document-type.search-prov import type { UmbSearchDataSource, UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { DocumentTypeService } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Rollback that fetches data from the server @@ -29,7 +29,7 @@ export class UmbDocumentTypeSearchServerDataSource implements UmbSearchDataSourc * @memberof UmbDocumentTypeSearchServerDataSource */ async search(args: UmbSearchRequestArgs) { - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, DocumentTypeService.getItemDocumentTypeSearch({ query: args.query, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/folder/repository/document-type-folder.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/folder/repository/document-type-folder.server.data-source.ts index 0c30b4d911..ae37bfdf95 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/folder/repository/document-type-folder.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/folder/repository/document-type-folder.server.data-source.ts @@ -2,7 +2,7 @@ import { UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE } from '../entity.js'; import type { UmbFolderModel } from '@umbraco-cms/backoffice/tree'; import { DocumentTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; @@ -49,7 +49,7 @@ export class UmbDocumentTypeFolderServerDataSource implements UmbDetailDataSourc async read(unique: string) { if (!unique) throw new Error('Unique is missing'); - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, DocumentTypeService.getDocumentTypeFolderById({ id: unique, @@ -86,7 +86,7 @@ export class UmbDocumentTypeFolderServerDataSource implements UmbDetailDataSourc name: model.name, }; - const { error } = await tryExecuteAndNotify( + const { error } = await tryExecute( this.#host, DocumentTypeService.postDocumentTypeFolder({ requestBody, @@ -110,7 +110,7 @@ export class UmbDocumentTypeFolderServerDataSource implements UmbDetailDataSourc if (!model.unique) throw new Error('Unique is missing'); if (!model.name) throw new Error('Folder name is missing'); - const { error } = await tryExecuteAndNotify( + const { error } = await tryExecute( this.#host, DocumentTypeService.putDocumentTypeFolderById({ id: model.unique, @@ -133,7 +133,7 @@ export class UmbDocumentTypeFolderServerDataSource implements UmbDetailDataSourc */ async delete(unique: string) { if (!unique) throw new Error('Unique is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, DocumentTypeService.deleteDocumentTypeFolderById({ id: unique, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/repository/document-audit-log.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/repository/document-audit-log.server.data-source.ts index 08e2c765cc..6553e8ebd4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/repository/document-audit-log.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/repository/document-audit-log.server.data-source.ts @@ -4,7 +4,7 @@ import type { UmbAuditLogDataSource, UmbAuditLogRequestArgs } from '@umbraco-cms import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { DirectionModel } from '@umbraco-cms/backoffice/external/backend-api'; import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * Server data source for the document audit log @@ -29,7 +29,7 @@ export class UmbDocumentAuditLogServerDataSource implements UmbAuditLogDataSourc * @memberof UmbDocumentAuditLogServerDataSource */ async getAuditLog(args: UmbAuditLogRequestArgs) { - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, DocumentService.getDocumentByIdAuditLog({ id: args.unique, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts index 04977651d4..3085ee363b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/repository/document-collection.server.data-source.ts @@ -1,7 +1,7 @@ import type { UmbDocumentCollectionFilterModel, UmbDocumentCollectionItemModel } from '../types.js'; import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; import { DirectionModel, DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { DocumentCollectionResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/collection'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -29,7 +29,7 @@ export class UmbDocumentCollectionServerDataSource implements UmbCollectionDataS take: query.take || 100, }; - const { data, error } = await tryExecuteAndNotify(this.#host, DocumentService.getCollectionDocumentById(params)); + const { data, error } = await tryExecute(this.#host, DocumentService.getCollectionDocumentById(params)); if (data) { const items = data.items.map((item: DocumentCollectionResponseModel) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/document-create-blueprint.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/document-create-blueprint.server.data-source.ts index e01030eed5..3485ccfe05 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/document-create-blueprint.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/repository/document-create-blueprint.server.data-source.ts @@ -1,4 +1,4 @@ -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import { DocumentBlueprintService } from '@umbraco-cms/backoffice/external/backend-api'; import type { CreateDocumentBlueprintFromDocumentRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -27,6 +27,6 @@ export class UmbDocumentCreateBlueprintServerDataSource { * @memberof UmbDocumentCreateBlueprintServerDataSource */ async create(requestBody: CreateDocumentBlueprintFromDocumentRequestModel) { - return tryExecuteAndNotify(this.#host, DocumentBlueprintService.postDocumentBlueprintFromDocument({ requestBody })); + return tryExecute(this.#host, DocumentBlueprintService.postDocumentBlueprintFromDocument({ requestBody })); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames/repository/culture-and-hostnames.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames/repository/culture-and-hostnames.server.data.ts index 652dcec6a1..bcc8d00871 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames/repository/culture-and-hostnames.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames/repository/culture-and-hostnames.server.data.ts @@ -1,7 +1,7 @@ import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UpdateDomainsRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Document Culture and Hostnames that fetches data from the server @@ -27,7 +27,7 @@ export class UmbDocumentCultureAndHostnamesServerDataSource { */ async read(unique: string) { if (!unique) throw new Error('Unique is missing'); - return tryExecuteAndNotify(this.#host, DocumentService.getDocumentByIdDomains({ id: unique })); + return tryExecute(this.#host, DocumentService.getDocumentByIdDomains({ id: unique })); } /** @@ -38,6 +38,6 @@ export class UmbDocumentCultureAndHostnamesServerDataSource { */ async update(unique: string, data: UpdateDomainsRequestModel) { if (!unique) throw new Error('Unique is missing'); - return tryExecuteAndNotify(this.#host, DocumentService.putDocumentByIdDomains({ id: unique, requestBody: data })); + return tryExecute(this.#host, DocumentService.putDocumentByIdDomains({ id: unique, requestBody: data })); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/duplicate/repository/document-duplicate.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/duplicate/repository/document-duplicate.server.data-source.ts index e6c084e1b3..68e2002f6e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/duplicate/repository/document-duplicate.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/duplicate/repository/document-duplicate.server.data-source.ts @@ -1,7 +1,7 @@ import type { UmbDuplicateDocumentRequestArgs } from './types.js'; import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * Duplicate Document Server Data Source @@ -29,7 +29,7 @@ export class UmbDuplicateDocumentServerDataSource { if (!args.unique) throw new Error('Unique is missing'); if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, DocumentService.postDocumentByIdCopy({ id: args.unique, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/document-move.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/document-move.server.data-source.ts index 865dcef132..eb62d9e7b3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/document-move.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/repository/document-move.server.data-source.ts @@ -1,6 +1,6 @@ import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbMoveDataSource, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/tree'; /** @@ -31,7 +31,7 @@ export class UmbMoveDocumentServerDataSource implements UmbMoveDataSource { if (!args.unique) throw new Error('Unique is missing'); if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, DocumentService.putDocumentByIdMove({ id: args.unique, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/repository/document-notifications.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/repository/document-notifications.server.data.ts index be7cd0511c..21e76efb3e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/repository/document-notifications.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/repository/document-notifications.server.data.ts @@ -1,7 +1,7 @@ import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UpdateDocumentNotificationsRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Document Culture and Hostnames that fetches data from the server @@ -26,7 +26,7 @@ export class UmbDocumentNotificationsServerDataSource { */ async read(unique: string) { if (!unique) throw new Error('Unique is missing'); - return tryExecuteAndNotify(this.#host, DocumentService.getDocumentByIdNotifications({ id: unique })); + return tryExecute(this.#host, DocumentService.getDocumentByIdNotifications({ id: unique })); } /** @@ -37,9 +37,6 @@ export class UmbDocumentNotificationsServerDataSource { */ async update(unique: string, data: UpdateDocumentNotificationsRequestModel) { if (!unique) throw new Error('Unique is missing'); - return tryExecuteAndNotify( - this.#host, - DocumentService.putDocumentByIdNotifications({ id: unique, requestBody: data }), - ); + return tryExecute(this.#host, DocumentService.putDocumentByIdNotifications({ id: unique, requestBody: data })); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/repository/sort-children-of.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/repository/sort-children-of.server.data.ts index 6b51854ac4..2d93f98982 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/repository/sort-children-of.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/repository/sort-children-of.server.data.ts @@ -1,6 +1,6 @@ import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbSortChildrenOfArgs, UmbSortChildrenOfDataSource } from '@umbraco-cms/backoffice/tree'; /** @@ -30,7 +30,7 @@ export class UmbSortChildrenOfDocumentServerDataSource implements UmbSortChildre const sortingMapping = args.sorting.map((item) => ({ id: item.unique, sortOrder: item.sortOrder })); - return tryExecuteAndNotify( + return tryExecute( this.#host, DocumentService.putDocumentSort({ requestBody: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/document-configuration.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/document-configuration.context.ts index 8829599ee0..60fece6d0d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/document-configuration.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/document-configuration.context.ts @@ -3,7 +3,7 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; import { DocumentService, type DocumentConfigurationResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; // TODO: Turn this into a Repository with a Store that holds the cache [NL] /** @@ -36,7 +36,7 @@ export class UmbDocumentConfigurationContext * @returns A promise that resolves to the document configuration, or null if the configuration could not be fetched. */ async fetchDocumentConfiguration() { - const { data } = await tryExecuteAndNotify(this, DocumentService.getDocumentConfiguration()); + const { data } = await tryExecute(this, DocumentService.getDocumentConfiguration()); return data ?? null; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/repository/document-publishing.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/repository/document-publishing.server.data-source.ts index add5a266fa..95d5d25204 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/repository/document-publishing.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/repository/document-publishing.server.data-source.ts @@ -8,7 +8,7 @@ import type { } from '@umbraco-cms/backoffice/external/backend-api'; import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbVariantId } from '@umbraco-cms/backoffice/variant'; import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; @@ -54,7 +54,7 @@ export class UmbDocumentPublishingServerDataSource { publishSchedules, }; - return tryExecuteAndNotify(this.#host, DocumentService.putDocumentByIdPublish({ id: unique, requestBody })); + return tryExecute(this.#host, DocumentService.putDocumentByIdPublish({ id: unique, requestBody })); } /** @@ -77,14 +77,14 @@ export class UmbDocumentPublishingServerDataSource { cultures: null, }; - return tryExecuteAndNotify(this.#host, DocumentService.putDocumentByIdUnpublish({ id: unique, requestBody })); + return tryExecute(this.#host, DocumentService.putDocumentByIdUnpublish({ id: unique, requestBody })); } const requestBody: UnpublishDocumentRequestModel = { cultures: variantIds.map((variant) => variant.toCultureString()), }; - return tryExecuteAndNotify(this.#host, DocumentService.putDocumentByIdUnpublish({ id: unique, requestBody })); + return tryExecute(this.#host, DocumentService.putDocumentByIdUnpublish({ id: unique, requestBody })); } /** @@ -106,10 +106,7 @@ export class UmbDocumentPublishingServerDataSource { includeUnpublishedDescendants, }; - return tryExecuteAndNotify( - this.#host, - DocumentService.putDocumentByIdPublishWithDescendants({ id: unique, requestBody }), - ); + return tryExecute(this.#host, DocumentService.putDocumentByIdPublishWithDescendants({ id: unique, requestBody })); } /** @@ -121,10 +118,7 @@ export class UmbDocumentPublishingServerDataSource { async published(unique: string): Promise> { if (!unique) throw new Error('Unique is missing'); - const { data, error } = await tryExecuteAndNotify( - this.#host, - DocumentService.getDocumentByIdPublished({ id: unique }), - ); + const { data, error } = await tryExecute(this.#host, DocumentService.getDocumentByIdPublished({ id: unique })); if (error || !data) { return { error }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts index 4db3dbe660..c451890805 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/document-recycle-bin.server.data-source.ts @@ -6,7 +6,7 @@ import type { } from '@umbraco-cms/backoffice/recycle-bin'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; export class UmbDocumentRecycleBinServerDataSource implements UmbRecycleBinDataSource { #host: UmbControllerHost; @@ -16,11 +16,11 @@ export class UmbDocumentRecycleBinServerDataSource implements UmbRecycleBinDataS } trash(args: UmbRecycleBinTrashRequestArgs) { - return tryExecuteAndNotify(this.#host, DocumentService.putDocumentByIdMoveToRecycleBin({ id: args.unique })); + return tryExecute(this.#host, DocumentService.putDocumentByIdMoveToRecycleBin({ id: args.unique })); } restore(args: UmbRecycleBinRestoreRequestArgs) { - return tryExecuteAndNotify( + return tryExecute( this.#host, DocumentService.putRecycleBinDocumentByIdRestore({ id: args.unique, @@ -32,11 +32,11 @@ export class UmbDocumentRecycleBinServerDataSource implements UmbRecycleBinDataS } empty() { - return tryExecuteAndNotify(this.#host, DocumentService.deleteRecycleBinDocument()); + return tryExecute(this.#host, DocumentService.deleteRecycleBinDocument()); } async getOriginalParent(args: UmbRecycleBinOriginalParentRequestArgs) { - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, DocumentService.getRecycleBinDocumentByIdOriginalParent({ id: args.unique }), ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/reference/repository/document-reference.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/reference/repository/document-reference.server.data.ts index 3b2f7d3de7..94b37df7c6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/reference/repository/document-reference.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/reference/repository/document-reference.server.data.ts @@ -1,6 +1,6 @@ import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import type { UmbEntityReferenceDataSource, UmbReferenceItemModel } from '@umbraco-cms/backoffice/relations'; @@ -27,7 +27,7 @@ export class UmbDocumentReferenceServerDataSource extends UmbControllerBase impl skip = 0, take = 20, ): Promise>> { - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this, DocumentService.getDocumentByIdReferencedBy({ id: unique, skip, take }), ); @@ -68,7 +68,7 @@ export class UmbDocumentReferenceServerDataSource extends UmbControllerBase impl skip: number = 0, take: number = 20, ): Promise>> { - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this, DocumentService.getDocumentAreReferenced({ id: uniques, skip, take }), ); @@ -100,7 +100,7 @@ export class UmbDocumentReferenceServerDataSource extends UmbControllerBase impl skip: number = 0, take: number = 20, ): Promise>> { - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this, DocumentService.getDocumentByIdReferencedDescendants({ id: unique, skip, take }), ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts index 1b96b586c5..c6c3162b03 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts @@ -8,7 +8,7 @@ import type { } from '@umbraco-cms/backoffice/external/backend-api'; import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Document that fetches data from the server @@ -81,7 +81,7 @@ export class UmbDocumentServerDataSource implements UmbDetailDataSource { - await tryExecute(PreviewService.postPreview()); + await tryExecute(this, PreviewService.postPreview(), { disableNotifications: true }); return; } @@ -24,7 +24,7 @@ export class UmbDocumentPreviewRepository extends UmbRepositoryBase { * @memberof UmbDocumentPreviewRepository */ async exit(): Promise { - await tryExecute(PreviewService.deletePreview()); + await tryExecute(this, PreviewService.deletePreview(), { disableNotifications: true }); return; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/validation/document-validation.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/validation/document-validation.server.data-source.ts index 85ab9d7550..b8808d1e7a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/validation/document-validation.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/validation/document-validation.server.data-source.ts @@ -13,12 +13,10 @@ import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; * A server data source for Document Validation */ export class UmbDocumentValidationServerDataSource { - //#host: UmbControllerHost; + #host: UmbControllerHost; - // TODO: [v15]: ignoring unused var here here to prevent a breaking change - // eslint-disable-next-line @typescript-eslint/no-unused-vars constructor(host: UmbControllerHost) { - //this.#host = host; + this.#host = host; } /** @@ -44,10 +42,13 @@ export class UmbDocumentValidationServerDataSource { // Maybe use: tryExecuteAndNotify return tryExecute( - //this.#host, + this.#host, DocumentService.postDocumentValidate({ requestBody, }), + { + disableNotifications: true, + }, ); } @@ -72,11 +73,14 @@ export class UmbDocumentValidationServerDataSource { // Maybe use: tryExecuteAndNotify return tryExecute( - //this.#host, + this.#host, DocumentService.putUmbracoManagementApiV11DocumentByIdValidate11({ id: model.unique, requestBody, }), + { + disableNotifications: true, + }, ); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/rollback/repository/rollback.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/rollback/repository/rollback.server.data-source.ts index e223597ebb..f0c98c9fa8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/rollback/repository/rollback.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/rollback/repository/rollback.server.data-source.ts @@ -1,6 +1,6 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { DocumentVersionService } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Rollback that fetches data from the server @@ -27,7 +27,7 @@ export class UmbRollbackServerDataSource { * @memberof UmbRollbackServerDataSource */ getVersionsByDocumentId(id: string, culture?: string) { - return tryExecuteAndNotify(this.#host, DocumentVersionService.getDocumentVersion({ documentId: id, culture })); + return tryExecute(this.#host, DocumentVersionService.getDocumentVersion({ documentId: id, culture })); } /** @@ -37,20 +37,17 @@ export class UmbRollbackServerDataSource { * @memberof UmbRollbackServerDataSource */ getVersionById(versionId: string) { - return tryExecuteAndNotify(this.#host, DocumentVersionService.getDocumentVersionById({ id: versionId })); + return tryExecute(this.#host, DocumentVersionService.getDocumentVersionById({ id: versionId })); } setPreventCleanup(versionId: string, preventCleanup: boolean) { - return tryExecuteAndNotify( + return tryExecute( this.#host, DocumentVersionService.putDocumentVersionByIdPreventCleanup({ id: versionId, preventCleanup }), ); } rollback(versionId: string, culture?: string) { - return tryExecuteAndNotify( - this.#host, - DocumentVersionService.postDocumentVersionByIdRollback({ id: versionId, culture }), - ); + return tryExecute(this.#host, DocumentVersionService.postDocumentVersionByIdRollback({ id: versionId, culture })); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts index bfb561c99f..178c49c2a5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search.server.data-source.ts @@ -3,7 +3,7 @@ import type { UmbDocumentSearchItemModel, UmbDocumentSearchRequestArgs } from '. import type { UmbSearchDataSource } from '@umbraco-cms/backoffice/search'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Rollback that fetches data from the server @@ -31,7 +31,7 @@ export class UmbDocumentSearchServerDataSource * @memberof UmbDocumentSearchServerDataSource */ async search(args: UmbDocumentSearchRequestArgs) { - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, DocumentService.getItemDocumentSearch({ query: args.query, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/repository/document-permission.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/repository/document-permission.server.data.ts index 485fe23bbc..4d2cde0ffc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/repository/document-permission.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/repository/document-permission.server.data.ts @@ -1,5 +1,5 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * @class UmbUserGroupCollectionServerDataSource @@ -18,7 +18,7 @@ export class UmbDocumentPermissionServerDataSource { } requestPermissions(id: string) { - return tryExecuteAndNotify( + return tryExecute( this.#host, fetch(`/umbraco/management/api/v1/document/${id}/permissions`, { method: 'GET', diff --git a/src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/oembed.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/oembed.server.data.ts index 238408819f..3ce001b98b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/oembed.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/repository/oembed.server.data.ts @@ -1,6 +1,6 @@ import { OEmbedService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the OEmbed that fetches data from a given URL. @@ -25,6 +25,6 @@ export class UmbOEmbedServerDataSource { * @memberof UmbOEmbedServerDataSource */ async getOEmbedQuery({ url, maxWidth, maxHeight }: { url?: string; maxWidth?: number; maxHeight?: number }) { - return tryExecuteAndNotify(this.#host, OEmbedService.getOembedQuery({ url, maxWidth, maxHeight })); + return tryExecute(this.#host, OEmbedService.getOembedQuery({ url, maxWidth, maxHeight })); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.element.ts b/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.element.ts index fd5e06405f..9fc5cf33ea 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.element.ts @@ -7,7 +7,7 @@ import { HealthCheckService } from '@umbraco-cms/backoffice/external/backend-api import type { UmbRoute } from '@umbraco-cms/backoffice/router'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; @customElement('umb-dashboard-health-check') export class UmbDashboardHealthCheckElement extends UmbLitElement { @@ -47,7 +47,7 @@ export class UmbDashboardHealthCheckElement extends UmbLitElement { } #registerHealthChecks = async () => { - const { data } = await tryExecuteAndNotify(this, HealthCheckService.getHealthCheckGroup({ skip: 0, take: 9999 })); + const { data } = await tryExecute(this, HealthCheckService.getHealthCheckGroup({ skip: 0, take: 9999 })); if (!data) return; const manifests = this.#createManifests(data.items); this.#register(manifests); diff --git a/src/Umbraco.Web.UI.Client/src/packages/health-check/health-check.context.ts b/src/Umbraco.Web.UI.Client/src/packages/health-check/health-check.context.ts index 44316bc005..94efcc5863 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/health-check/health-check.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/health-check/health-check.context.ts @@ -3,7 +3,7 @@ import type { HealthCheckGroupWithResultResponseModel, } from '@umbraco-cms/backoffice/external/backend-api'; import { HealthCheckService } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; @@ -17,7 +17,7 @@ export class UmbHealthCheckContext extends UmbControllerBase implements UmbApi { public readonly results = this.#results.asObservable(); async getGroupChecks(name: string) { - const { data } = await tryExecuteAndNotify(this, HealthCheckService.getHealthCheckGroupByName({ name })); + const { data } = await tryExecute(this, HealthCheckService.getHealthCheckGroupByName({ name })); if (data) { this.#checks.setValue(data); @@ -27,7 +27,7 @@ export class UmbHealthCheckContext extends UmbControllerBase implements UmbApi { } async checkGroup(name: string) { - const { data } = await tryExecuteAndNotify(this, HealthCheckService.postHealthCheckGroupByNameCheck({ name })); + const { data } = await tryExecute(this, HealthCheckService.postHealthCheckGroupByNameCheck({ name })); if (data) { this.#results.setValue(data); diff --git a/src/Umbraco.Web.UI.Client/src/packages/health-check/views/health-check-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/health-check/views/health-check-action.element.ts index d5efa4c102..8a4e753c2b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/health-check/views/health-check-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/health-check/views/health-check-action.element.ts @@ -4,7 +4,7 @@ import { css, html, nothing, customElement, property, state, ifDefined } from '@ import type { HealthCheckActionRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import { HealthCheckService } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; @customElement('umb-dashboard-health-check-action') export class UmbDashboardHealthCheckActionElement extends UmbLitElement { @@ -17,7 +17,7 @@ export class UmbDashboardHealthCheckActionElement extends UmbLitElement { private async _onActionClick(e: SubmitEvent) { e.preventDefault(); this._buttonState = 'waiting'; - const { error } = await tryExecuteAndNotify( + const { error } = await tryExecute( this, HealthCheckService.postHealthCheckExecuteAction({ requestBody: this.action }), ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/collection/repository/language-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/language/collection/repository/language-collection.server.data-source.ts index 1ed9cc3e9a..e6be8d18f0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/collection/repository/language-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/collection/repository/language-collection.server.data-source.ts @@ -4,7 +4,7 @@ import { UMB_LANGUAGE_ENTITY_TYPE } from '../../entity.js'; import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/collection'; import { LanguageService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source that fetches the language collection data from the server. @@ -30,7 +30,7 @@ export class UmbLanguageCollectionServerDataSource implements UmbCollectionDataS * @memberof UmbLanguageCollectionServerDataSource */ async getCollection(filter: UmbLanguageCollectionFilterModel) { - const { data, error } = await tryExecuteAndNotify(this.#host, LanguageService.getLanguage(filter)); + const { data, error } = await tryExecute(this.#host, LanguageService.getLanguage(filter)); if (data) { const items = data.items.map((item) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/repository/detail/language-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/language/repository/detail/language-detail.server.data-source.ts index 975323b62b..e354bd8e55 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/repository/detail/language-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/repository/detail/language-detail.server.data-source.ts @@ -7,7 +7,7 @@ import type { } from '@umbraco-cms/backoffice/external/backend-api'; import { LanguageService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Language that fetches data from the server @@ -55,10 +55,7 @@ export class UmbLanguageServerDataSource implements UmbDetailDataSource, imagingModel?: UmbImagingResizeModel) { if (!uniques.length) throw new Error('Uniques are missing'); - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, ImagingService.getImagingResizeUrls({ id: uniques, ...imagingModel }), ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/duplicate/repository/media-type-duplicate.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/duplicate/repository/media-type-duplicate.server.data-source.ts index 08282ec757..c9113e0545 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/duplicate/repository/media-type-duplicate.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/duplicate/repository/media-type-duplicate.server.data-source.ts @@ -1,6 +1,6 @@ import { MediaTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbDuplicateToDataSource, UmbDuplicateToRequestArgs } from '@umbraco-cms/backoffice/tree'; /** @@ -29,7 +29,7 @@ export class UmbDuplicateMediaTypeServerDataSource implements UmbDuplicateToData if (!args.unique) throw new Error('Unique is missing'); if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, MediaTypeService.postMediaTypeByIdCopy({ id: args.unique, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/export/repository/media-type-export.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/export/repository/media-type-export.server.data-source.ts index 7a23bc2fe4..fd111609f8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/export/repository/media-type-export.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/export/repository/media-type-export.server.data-source.ts @@ -1,6 +1,6 @@ import { MediaTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * Export Media Server Data Source @@ -28,6 +28,6 @@ export class UmbExportMediaTypeServerDataSource { async export(unique: string) { if (!unique) throw new Error('Unique is missing'); - return tryExecuteAndNotify(this.#host, MediaTypeService.getMediaTypeByIdExport({ id: unique })); + return tryExecute(this.#host, MediaTypeService.getMediaTypeByIdExport({ id: unique })); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/import/repository/media-type-import.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/import/repository/media-type-import.server.data-source.ts index c71e44051d..716dd3ae1f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/import/repository/media-type-import.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/import/repository/media-type-import.server.data-source.ts @@ -1,6 +1,6 @@ import { MediaTypeService, type PostMediaTypeImportData } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * Media Type Import Server Data Source @@ -32,6 +32,6 @@ export class UmbMediaTypeImportServerDataSource { requestBody: { file: { id: temporaryUnique } }, }; - return tryExecuteAndNotify(this.#host, MediaTypeService.postMediaTypeImport(requestBody)); + return tryExecute(this.#host, MediaTypeService.postMediaTypeImport(requestBody)); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/media-type-move.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/media-type-move.server.data-source.ts index a48ce5662c..104b6f64b5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/media-type-move.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/move-to/repository/media-type-move.server.data-source.ts @@ -1,6 +1,6 @@ import { MediaTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbMoveDataSource, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/tree'; /** @@ -31,7 +31,7 @@ export class UmbMoveMediaTypeServerDataSource implements UmbMoveDataSource { if (!args.unique) throw new Error('Unique is missing'); if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, MediaTypeService.putMediaTypeByIdMove({ id: args.unique, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/media-type-composition.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/media-type-composition.server.data-source.ts index 81f353a70b..858a126804 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/media-type-composition.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/media-type-composition.server.data-source.ts @@ -5,7 +5,7 @@ import type { } from '../../types.js'; import { type MediaTypeCompositionRequestModel, MediaTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbContentTypeCompositionDataSource } from '@umbraco-cms/backoffice/content-type'; /** @@ -37,7 +37,7 @@ export class UmbMediaTypeCompositionServerDataSource * @memberof UmbMediaTypeCompositionServerDataSource */ async getReferences(unique: string) { - const response = await tryExecuteAndNotify( + const response = await tryExecute( this.#host, MediaTypeService.getMediaTypeByIdCompositionReferences({ id: unique }), ); @@ -66,10 +66,7 @@ export class UmbMediaTypeCompositionServerDataSource currentPropertyAliases: args.currentPropertyAliases, }; - const response = await tryExecuteAndNotify( - this.#host, - MediaTypeService.postMediaTypeAvailableCompositions({ requestBody }), - ); + const response = await tryExecute(this.#host, MediaTypeService.postMediaTypeAvailableCompositions({ requestBody })); const error = response.error; const data: Array | undefined = response.data?.map((composition) => { return { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.server.data-source.ts index 7fc5078ce8..19b01c623d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.server.data-source.ts @@ -8,7 +8,7 @@ import type { } from '@umbraco-cms/backoffice/external/backend-api'; import { MediaTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbPropertyContainerTypes } from '@umbraco-cms/backoffice/content-type'; /** @@ -66,7 +66,7 @@ export class UmbMediaTypeServerDataSource implements UmbDetailDataSource { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/media-move.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/media-move.server.data-source.ts index 8108f4e73c..8d24101fca 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/media-move.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/repository/media-move.server.data-source.ts @@ -1,6 +1,6 @@ import { MediaService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbMoveDataSource, UmbMoveToRequestArgs } from '@umbraco-cms/backoffice/tree'; /** @@ -31,7 +31,7 @@ export class UmbMoveMediaServerDataSource implements UmbMoveDataSource { if (!args.unique) throw new Error('Unique is missing'); if (args.destination.unique === undefined) throw new Error('Destination unique is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, MediaService.putMediaByIdMove({ id: args.unique, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/sort-children-of/repository/sort-children-of.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/sort-children-of/repository/sort-children-of.server.data.ts index 0dbf057bae..6b3f8acb9b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/sort-children-of/repository/sort-children-of.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/sort-children-of/repository/sort-children-of.server.data.ts @@ -1,6 +1,6 @@ import { MediaService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbSortChildrenOfArgs, UmbSortChildrenOfDataSource } from '@umbraco-cms/backoffice/tree'; /** @@ -30,7 +30,7 @@ export class UmbSortChildrenOfMediaServerDataSource implements UmbSortChildrenOf const sortingMapping = args.sorting.map((item) => ({ id: item.unique, sortOrder: item.sortOrder })); - return tryExecuteAndNotify( + return tryExecute( this.#host, MediaService.putMediaSort({ requestBody: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/media-recycle-bin.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/media-recycle-bin.server.data-source.ts index 6348f879fa..058d73469e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/media-recycle-bin.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/repository/media-recycle-bin.server.data-source.ts @@ -6,7 +6,7 @@ import type { } from '@umbraco-cms/backoffice/recycle-bin'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { MediaService } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; export class UmbMediaRecycleBinServerDataSource implements UmbRecycleBinDataSource { #host: UmbControllerHost; @@ -16,11 +16,11 @@ export class UmbMediaRecycleBinServerDataSource implements UmbRecycleBinDataSour } trash(args: UmbRecycleBinTrashRequestArgs) { - return tryExecuteAndNotify(this.#host, MediaService.putMediaByIdMoveToRecycleBin({ id: args.unique })); + return tryExecute(this.#host, MediaService.putMediaByIdMoveToRecycleBin({ id: args.unique })); } restore(args: UmbRecycleBinRestoreRequestArgs) { - return tryExecuteAndNotify( + return tryExecute( this.#host, MediaService.putRecycleBinMediaByIdRestore({ id: args.unique, @@ -32,11 +32,11 @@ export class UmbMediaRecycleBinServerDataSource implements UmbRecycleBinDataSour } empty() { - return tryExecuteAndNotify(this.#host, MediaService.deleteRecycleBinMedia()); + return tryExecute(this.#host, MediaService.deleteRecycleBinMedia()); } async getOriginalParent(args: UmbRecycleBinOriginalParentRequestArgs) { - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, MediaService.getRecycleBinMediaByIdOriginalParent({ id: args.unique }), ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/reference/repository/media-reference.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/reference/repository/media-reference.server.data.ts index 6f169f00c4..d7b8418cb2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/reference/repository/media-reference.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/reference/repository/media-reference.server.data.ts @@ -1,7 +1,7 @@ import { UMB_MEDIA_ENTITY_TYPE } from '../../entity.js'; import { MediaService } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbManagementApiDataMapper } from '@umbraco-cms/backoffice/repository'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import type { UmbEntityReferenceDataSource, UmbReferenceItemModel } from '@umbraco-cms/backoffice/relations'; @@ -27,10 +27,7 @@ export class UmbMediaReferenceServerDataSource extends UmbControllerBase impleme skip: number = 0, take: number = 20, ): Promise>> { - const { data, error } = await tryExecuteAndNotify( - this, - MediaService.getMediaByIdReferencedBy({ id: unique, skip, take }), - ); + const { data, error } = await tryExecute(this, MediaService.getMediaByIdReferencedBy({ id: unique, skip, take })); if (data) { const promises = data.items.map(async (item) => { @@ -68,10 +65,7 @@ export class UmbMediaReferenceServerDataSource extends UmbControllerBase impleme skip: number = 0, take: number = 20, ): Promise>> { - const { data, error } = await tryExecuteAndNotify( - this, - MediaService.getMediaAreReferenced({ id: uniques, skip, take }), - ); + const { data, error } = await tryExecute(this, MediaService.getMediaAreReferenced({ id: uniques, skip, take })); if (data) { const items: Array = data.items.map((item) => { @@ -100,7 +94,7 @@ export class UmbMediaReferenceServerDataSource extends UmbControllerBase impleme skip: number = 0, take: number = 20, ): Promise>> { - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this, MediaService.getMediaByIdReferencedDescendants({ id: unique, skip, take }), ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts index 34cdee7872..8dc85a8b0c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts @@ -5,7 +5,7 @@ import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; import type { CreateMediaRequestModel, UpdateMediaRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import { MediaService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Media that fetches data from the server @@ -66,7 +66,7 @@ export class UmbMediaServerDataSource implements UmbDetailDataSource mapper(item)); return { data: mapped, error }; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/validation/media-validation.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/validation/media-validation.server.data-source.ts index ef4d12057b..04243d21a8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/validation/media-validation.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/validation/media-validation.server.data-source.ts @@ -13,12 +13,10 @@ import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; * A server data source for Media Validation */ export class UmbMediaValidationServerDataSource { - //#host: UmbControllerHost; + #host: UmbControllerHost; - // TODO: [v15]: ignoring unused var here here to prevent a breaking change - // eslint-disable-next-line @typescript-eslint/no-unused-vars constructor(host: UmbControllerHost) { - //this.#host = host; + this.#host = host; } /** @@ -43,7 +41,7 @@ export class UmbMediaValidationServerDataSource { // Maybe use: tryExecuteAndNotify return tryExecute( - //this.#host, + this.#host, MediaService.postMediaValidate({ requestBody, }), @@ -70,7 +68,7 @@ export class UmbMediaValidationServerDataSource { // Maybe use: tryExecuteAndNotify return tryExecute( - //this.#host, + this.#host, MediaService.putMediaByIdValidate({ id: model.unique, requestBody, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/search/media-search.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/search/media-search.server.data-source.ts index 207406449d..fd782a1856 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/search/media-search.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/search/media-search.server.data-source.ts @@ -3,7 +3,7 @@ import type { UmbMediaSearchItemModel, UmbMediaSearchRequestArgs } from './types import type { UmbSearchDataSource } from '@umbraco-cms/backoffice/search'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { MediaService } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Rollback that fetches data from the server @@ -31,7 +31,7 @@ export class UmbMediaSearchServerDataSource * @memberof UmbMediaSearchServerDataSource */ async search(args: UmbMediaSearchRequestArgs) { - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, MediaService.getItemMediaSearch({ query: args.query, diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/collection/repository/member-group-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/collection/repository/member-group-collection.server.data-source.ts index 726bac656c..0433001568 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/collection/repository/member-group-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/collection/repository/member-group-collection.server.data-source.ts @@ -3,7 +3,7 @@ import type { UmbMemberGroupDetailModel } from '../../types.js'; import { UMB_MEMBER_GROUP_ENTITY_TYPE } from '../../entity.js'; import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/collection'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { MemberGroupResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; import { MemberGroupService } from '@umbraco-cms/backoffice/external/backend-api'; @@ -31,7 +31,7 @@ export class UmbMemberGroupCollectionServerDataSource implements UmbCollectionDa * @memberof UmbMemberGroupCollectionServerDataSource */ async getCollection(filter: UmbMemberGroupCollectionFilterModel) { - const { data, error } = await tryExecuteAndNotify(this.#host, MemberGroupService.getMemberGroup(filter)); + const { data, error } = await tryExecute(this.#host, MemberGroupService.getMemberGroup(filter)); if (error) { return { error }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/repository/detail/member-group-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/repository/detail/member-group-detail.server.data-source.ts index c5336bbab0..4e14ee3624 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/repository/detail/member-group-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/repository/detail/member-group-detail.server.data-source.ts @@ -3,7 +3,7 @@ import { UMB_MEMBER_GROUP_ENTITY_TYPE } from '../../entity.js'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { CreateMemberGroupRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import { MemberGroupService } from '@umbraco-cms/backoffice/external/backend-api'; @@ -49,10 +49,7 @@ export class UmbMemberGroupServerDataSource implements UmbDetailDataSource>> { - const { data, error } = await tryExecuteAndNotify( - this, - MemberService.getMemberByIdReferencedBy({ id: unique, skip, take }), - ); + const { data, error } = await tryExecute(this, MemberService.getMemberByIdReferencedBy({ id: unique, skip, take })); if (data) { const promises = data.items.map(async (item) => { @@ -68,10 +65,7 @@ export class UmbMemberReferenceServerDataSource extends UmbControllerBase implem skip: number = 0, take: number = 20, ): Promise>> { - const { data, error } = await tryExecuteAndNotify( - this, - MemberService.getMemberAreReferenced({ id: uniques, skip, take }), - ); + const { data, error } = await tryExecute(this, MemberService.getMemberAreReferenced({ id: uniques, skip, take })); if (data) { const items: Array = data.items.map((item) => { @@ -100,7 +94,7 @@ export class UmbMemberReferenceServerDataSource extends UmbControllerBase implem skip: number = 0, take: number = 20, ): Promise>> { - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this, MemberService.getMemberByIdReferencedDescendants({ id: unique, skip, take }), ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts index 30d4bddac9..1a2296ed58 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts @@ -6,7 +6,7 @@ import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; import type { CreateMemberRequestModel, UpdateMemberRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import { MemberService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Member that fetches data from the server @@ -75,7 +75,7 @@ export class UmbMemberServerDataSource implements UmbDetailDataSource setTimeout(resolve, this.#isFirstRebuildStatusPoll ? 1000 : 5000)); this.#isFirstRebuildStatusPoll = false; - const { data, error } = await tryExecuteAndNotify(this, PublishedCacheService.getPublishedCacheRebuildStatus()); + const { data, error } = await tryExecute(this, PublishedCacheService.getPublishedCacheRebuildStatus()); if (error || !data) { this._buttonStateRebuild = 'failed'; return; diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/collection/repository/relation-type-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/collection/repository/relation-type-collection.server.data-source.ts index d35c1861ef..5a9e7d8845 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/collection/repository/relation-type-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/collection/repository/relation-type-collection.server.data-source.ts @@ -4,7 +4,7 @@ import { UMB_RELATION_TYPE_ENTITY_TYPE } from '../../entity.js'; import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/collection'; import { RelationTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source that fetches the relation type collection data from the server. @@ -30,7 +30,7 @@ export class UmbRelationTypeCollectionServerDataSource implements UmbCollectionD * @memberof UmbRelationTypeCollectionServerDataSource */ async getCollection(filter: UmbRelationTypeCollectionFilterModel) { - const { data, error } = await tryExecuteAndNotify(this.#host, RelationTypeService.getRelationType(filter)); + const { data, error } = await tryExecute(this.#host, RelationTypeService.getRelationType(filter)); if (data) { const items = data.items.map((item) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/repository/detail/relation-type-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/repository/detail/relation-type-detail.server.data-source.ts index 86715b1f78..180dd186f6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/repository/detail/relation-type-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/repository/detail/relation-type-detail.server.data-source.ts @@ -2,7 +2,7 @@ import type { UmbRelationTypeDetailModel } from '../../types.js'; import { UMB_RELATION_TYPE_ENTITY_TYPE } from '../../entity.js'; import { RelationTypeService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { UmbReadDetailDataSource } from '@umbraco-cms/backoffice/repository'; /** @@ -31,10 +31,7 @@ export class UmbRelationTypeDetailServerDataSource implements UmbReadDetailDataS async read(unique: string) { if (!unique) throw new Error('Unique is missing'); - const { data, error } = await tryExecuteAndNotify( - this.#host, - RelationTypeService.getRelationTypeById({ id: unique }), - ); + const { data, error } = await tryExecute(this.#host, RelationTypeService.getRelationTypeById({ id: unique })); if (error || !data) { return { error }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/relations/collection/repository/relation-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/relations/collection/repository/relation-collection.server.data-source.ts index dc1506c738..f88f87ce9f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/relations/relations/collection/repository/relation-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/relations/relations/collection/repository/relation-collection.server.data-source.ts @@ -4,7 +4,7 @@ import { UMB_RELATION_ENTITY_TYPE } from '../../entity.js'; import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/collection'; import { RelationService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source that fetches the relation collection data from the server. @@ -36,10 +36,7 @@ export class UmbRelationCollectionServerDataSource implements UmbCollectionDataS id: filter.relationType.unique, }; - const { data, error } = await tryExecuteAndNotify( - this.#host, - RelationService.getRelationByRelationTypeId(requestBody), - ); + const { data, error } = await tryExecute(this.#host, RelationService.getRelationByRelationTypeId(requestBody)); if (data) { const items = data.items.map((item) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-indexers.ts b/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-indexers.ts index 0c16cd657d..16085ebee4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-indexers.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-indexers.ts @@ -4,7 +4,7 @@ import { umbConfirmModal } from '@umbraco-cms/backoffice/modal'; import type { HealthStatusResponseModel, IndexResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; import { HealthStatusModel, IndexerService } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import './section-view-examine-searchers.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @@ -40,10 +40,7 @@ export class UmbDashboardExamineIndexElement extends UmbLitElement { } async #getIndexData() { - const { data } = await tryExecuteAndNotify( - this, - IndexerService.getIndexerByIndexName({ indexName: this.indexName }), - ); + const { data } = await tryExecute(this, IndexerService.getIndexerByIndexName({ indexName: this.indexName })); return data; } @@ -76,7 +73,7 @@ export class UmbDashboardExamineIndexElement extends UmbLitElement { } private async _rebuild() { this._buttonState = 'waiting'; - const { error } = await tryExecuteAndNotify( + const { error } = await tryExecute( this, IndexerService.postIndexerByIndexNameRebuild({ indexName: this.indexName }), ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-overview.ts b/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-overview.ts index a375374906..34af67599a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-overview.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-overview.ts @@ -4,7 +4,7 @@ import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffic import type { IndexResponseModel, SearcherResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; import { HealthStatusModel, IndexerService, SearcherService } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; @customElement('umb-dashboard-examine-overview') export class UmbDashboardExamineOverviewElement extends UmbLitElement { @@ -28,14 +28,14 @@ export class UmbDashboardExamineOverviewElement extends UmbLitElement { private async _getIndexers() { this._loadingIndexers = true; - const { data } = await tryExecuteAndNotify(this, IndexerService.getIndexer({ take: 9999, skip: 0 })); + const { data } = await tryExecute(this, IndexerService.getIndexer({ take: 9999, skip: 0 })); this._indexers = data?.items ?? []; this._loadingIndexers = false; } private async _getSearchers() { this._loadingSearchers = true; - const { data } = await tryExecuteAndNotify(this, SearcherService.getSearcher({ take: 9999, skip: 0 })); + const { data } = await tryExecute(this, SearcherService.getSearcher({ take: 9999, skip: 0 })); this._searchers = data?.items ?? []; this._loadingSearchers = false; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-searchers.ts b/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-searchers.ts index cb3837558b..181f2f76fa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-searchers.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/views/section-view-examine-searchers.ts @@ -7,7 +7,7 @@ import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/rou import type { SearchResultResponseModel, FieldPresentationModel } from '@umbraco-cms/backoffice/external/backend-api'; import { SearcherService } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; interface ExposedSearchResultField { name: string; @@ -58,7 +58,7 @@ export class UmbDashboardExamineSearcherElement extends UmbLitElement { if (!this._searchInput.value.length) return; this._searchLoading = true; - const { data } = await tryExecuteAndNotify( + const { data } = await tryExecute( this, SearcherService.getSearcherBySearcherNameQuery({ searcherName: this.searcherName, diff --git a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/repository/sysinfo.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/repository/sysinfo.repository.ts index 5f5970d6a0..9108a962be 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/sysinfo/repository/sysinfo.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/sysinfo/repository/sysinfo.repository.ts @@ -1,7 +1,7 @@ import type { UmbServerUpgradeCheck } from '../types.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; -import { tryExecute, tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import { ServerService } from '@umbraco-cms/backoffice/external/backend-api'; import { UMB_APP_CONTEXT } from '@umbraco-cms/backoffice/app'; @@ -11,12 +11,12 @@ export class UmbSysinfoRepository extends UmbRepositoryBase { } async requestTroubleShooting() { - const { data } = await tryExecuteAndNotify(this, ServerService.getServerTroubleshooting()); + const { data } = await tryExecute(this, ServerService.getServerTroubleshooting(), { disableNotifications: true }); return data; } async requestServerInformation() { - const { data } = await tryExecuteAndNotify(this, ServerService.getServerInformation()); + const { data } = await tryExecute(this, ServerService.getServerInformation(), { disableNotifications: true }); return data; } @@ -108,7 +108,7 @@ export class UmbSysinfoRepository extends UmbRepositoryBase { currentVersion: string, ): Promise { // Check the server for an upgrade because we have no stored check or the stored check is invalid - const { data } = await tryExecute(ServerService.getServerUpgradeCheck()); + const { data } = await tryExecute(this, ServerService.getServerUpgradeCheck(), { disableNotifications: true }); if (data) { // Save the last check date including the data received diff --git a/src/Umbraco.Web.UI.Client/src/packages/tags/repository/sources/tag.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/tags/repository/sources/tag.server.data.ts index 9f697497a4..dfef822fb7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tags/repository/sources/tag.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tags/repository/sources/tag.server.data.ts @@ -1,6 +1,6 @@ import { TagService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Tag that fetches data from the server @@ -43,6 +43,6 @@ export class UmbTagServerDataSource { tagGroup?: string; culture?: string; }) { - return tryExecuteAndNotify(this.#host, TagService.getTag({ query, skip, take, tagGroup, culture })); + return tryExecute(this.#host, TagService.getTag({ query, skip, take, tagGroup, culture })); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/telemetry/dashboard-telemetry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/telemetry/dashboard-telemetry.element.ts index 08f885388a..2b16da0871 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/telemetry/dashboard-telemetry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/telemetry/dashboard-telemetry.element.ts @@ -1,9 +1,9 @@ import { css, html, customElement, state, unsafeHTML } from '@umbraco-cms/backoffice/external/lit'; import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui'; import type { TelemetryResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; -import { TelemetryLevelModel, TelemetryService, ApiError } from '@umbraco-cms/backoffice/external/backend-api'; +import { TelemetryLevelModel, TelemetryService } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute, UmbApiError } from '@umbraco-cms/backoffice/resources'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @customElement('umb-dashboard-telemetry') @@ -26,10 +26,10 @@ export class UmbDashboardTelemetryElement extends UmbLitElement { } private async _setup() { - const telemetryLevels = await tryExecuteAndNotify(this, TelemetryService.getTelemetry({ skip: 0, take: 3 })); + const telemetryLevels = await tryExecute(this, TelemetryService.getTelemetry({ skip: 0, take: 3 })); this._telemetryLevels = telemetryLevels.data?.items ?? []; - const telemetryLevel = await tryExecuteAndNotify(this, TelemetryService.getTelemetryLevel()); + const telemetryLevel = await tryExecute(this, TelemetryService.getTelemetryLevel()); this._telemetryFormData = telemetryLevel.data?.telemetryLevel ?? TelemetryLevelModel.BASIC; } @@ -38,7 +38,7 @@ export class UmbDashboardTelemetryElement extends UmbLitElement { this._buttonState = 'waiting'; - const { error } = await tryExecuteAndNotify( + const { error } = await tryExecute( this, TelemetryService.postTelemetryLevel({ requestBody: { telemetryLevel: this._telemetryFormData }, @@ -47,7 +47,8 @@ export class UmbDashboardTelemetryElement extends UmbLitElement { if (error) { this._buttonState = 'failed'; - this._errorMessage = error instanceof ApiError ? (error.body as any).detail : error.message; + this._errorMessage = + (UmbApiError.isUmbApiError(error) ? error.problemDetails.detail : error.message) ?? 'Unknown error'; return; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/snippet-modal/create-from-snippet-modal.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/snippet-modal/create-from-snippet-modal.ts index 5b12e3d58d..396b2e9208 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/snippet-modal/create-from-snippet-modal.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/snippet-modal/create-from-snippet-modal.ts @@ -1,7 +1,7 @@ import type { UmbCreatePartialViewFromSnippetModalData } from './index.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import type { PartialViewSnippetItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; import { PartialViewService } from '@umbraco-cms/backoffice/external/backend-api'; @@ -25,7 +25,7 @@ export class UmbPartialViewCreateFromSnippetModalElement extends UmbModalBaseEle } protected override async firstUpdated() { - const { data } = await tryExecuteAndNotify(this, PartialViewService.getPartialViewSnippet({ take: 10000 })); + const { data } = await tryExecute(this, PartialViewService.getPartialViewSnippet({ take: 10000 })); if (data) { this._snippets = data.items.map((snippet) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/rename/rename-partial-view.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/rename/rename-partial-view.server.data-source.ts index 92965afabb..5128a36559 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/rename/rename-partial-view.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/rename/rename-partial-view.server.data-source.ts @@ -6,7 +6,7 @@ import { import type { RenameStylesheetRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import { PartialViewService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; export class UmbRenamePartialViewServerDataSource { #host: UmbControllerHost; @@ -36,7 +36,7 @@ export class UmbRenamePartialViewServerDataSource { name: appendFileExtensionIfNeeded(name, '.cshtml'), }; - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, PartialViewService.putPartialViewByPathRename({ path: encodeURIComponent(path), diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/repository/item/partial-view-item.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/repository/item/partial-view-item.server.data-source.ts index 55e91bf34d..46997b7747 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/repository/item/partial-view-item.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/repository/item/partial-view-item.server.data-source.ts @@ -3,7 +3,7 @@ import type { UmbPartialViewItemModel } from '../../types.js'; import { UmbServerFilePathUniqueSerializer } from '@umbraco-cms/backoffice/server-file-system'; import type { UmbItemDataSource } from '@umbraco-cms/backoffice/repository'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import { PartialViewService } from '@umbraco-cms/backoffice/external/backend-api'; /** @@ -40,7 +40,7 @@ export class UmbPartialViewItemServerDataSource implements UmbItemDataSource x !== null) as string[]; - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, PartialViewService.getItemPartialView({ path: paths, diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/repository/partial-view-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/repository/partial-view-detail.server.data-source.ts index f884bab984..8cbe60d9dd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/repository/partial-view-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/repository/partial-view-detail.server.data-source.ts @@ -11,7 +11,7 @@ import type { import { PartialViewService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; export class UmbPartialViewDetailServerDataSource implements UmbDetailDataSource { #host: UmbControllerHost; @@ -46,7 +46,7 @@ export class UmbPartialViewDetailServerDataSource implements UmbDetailDataSource content: model.content, }; - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, PartialViewService.postPartialView({ requestBody, @@ -68,7 +68,7 @@ export class UmbPartialViewDetailServerDataSource implements UmbDetailDataSource const path = this.#serverFilePathUniqueSerializer.toServerPath(unique); if (!path) throw new Error('Path is missing'); - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, PartialViewService.getPartialViewByPath({ path: encodeURIComponent(path) }), ); @@ -97,7 +97,7 @@ export class UmbPartialViewDetailServerDataSource implements UmbDetailDataSource content: model.content, }; - const { error } = await tryExecuteAndNotify( + const { error } = await tryExecute( this.#host, PartialViewService.putPartialViewByPath({ path: encodeURIComponent(path), @@ -118,7 +118,7 @@ export class UmbPartialViewDetailServerDataSource implements UmbDetailDataSource const path = this.#serverFilePathUniqueSerializer.toServerPath(unique); if (!path) throw new Error('Path is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, PartialViewService.deletePartialViewByPath({ path: encodeURIComponent(path), diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/tree/folder/repository/partial-view-folder.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/tree/folder/repository/partial-view-folder.server.data-source.ts index e56ae5b048..60593bfb68 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/tree/folder/repository/partial-view-folder.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/tree/folder/repository/partial-view-folder.server.data-source.ts @@ -4,7 +4,7 @@ import type { UmbFolderModel } from '@umbraco-cms/backoffice/tree'; import type { CreatePartialViewFolderRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import { PartialViewService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; @@ -55,7 +55,7 @@ export class UmbPartialViewFolderServerDataSource implements UmbDetailDataSource const path = this.#serverFilePathUniqueSerializer.toServerPath(unique); if (!path) throw new Error('Cannot read partial view folder without a path'); - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, PartialViewService.getPartialViewFolderByPath({ path: encodeURIComponent(path), @@ -94,7 +94,7 @@ export class UmbPartialViewFolderServerDataSource implements UmbDetailDataSource name: model.name, }; - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, PartialViewService.postPartialViewFolder({ requestBody, @@ -122,7 +122,7 @@ export class UmbPartialViewFolderServerDataSource implements UmbDetailDataSource const path = this.#serverFilePathUniqueSerializer.toServerPath(unique); if (!path) throw new Error('Cannot delete partial view folder without a path'); - return tryExecuteAndNotify( + return tryExecute( this.#host, PartialViewService.deletePartialViewFolderByPath({ path: encodeURIComponent(path), diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts index a38bf0de2a..a9948c74c8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts @@ -14,7 +14,7 @@ import { UmbEntityNamedDetailWorkspaceContextBase, UmbWorkspaceIsNewRedirectController, } from '@umbraco-cms/backoffice/workspace'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import { PartialViewService } from '@umbraco-cms/backoffice/external/backend-api'; import type { IRoutingInfo, PageComponent } from '@umbraco-cms/backoffice/router'; import { UmbServerFileRenameWorkspaceRedirectController } from '@umbraco-cms/backoffice/server-file-system'; @@ -112,7 +112,7 @@ export class UmbPartialViewWorkspaceContext } #getSnippet(unique: string) { - return tryExecuteAndNotify( + return tryExecute( this, PartialViewService.getPartialViewSnippetById({ id: unique, diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/rename/rename-script.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/rename/rename-script.server.data-source.ts index 6aae06b1d4..13202d2666 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/rename/rename-script.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/rename/rename-script.server.data-source.ts @@ -6,7 +6,7 @@ import { import type { RenameStylesheetRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import { ScriptService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; export class UmbRenameScriptServerDataSource { #host: UmbControllerHost; @@ -36,7 +36,7 @@ export class UmbRenameScriptServerDataSource { name: appendFileExtensionIfNeeded(name, '.js'), }; - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, ScriptService.putScriptByPathRename({ path: encodeURIComponent(path), diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/repository/item/script-item.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/repository/item/script-item.server.data-source.ts index 257e195196..247a1b0680 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/repository/item/script-item.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/repository/item/script-item.server.data-source.ts @@ -3,7 +3,7 @@ import type { UmbScriptItemModel } from '../../types.js'; import { UmbServerFilePathUniqueSerializer } from '@umbraco-cms/backoffice/server-file-system'; import type { UmbItemDataSource } from '@umbraco-cms/backoffice/repository'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import { ScriptService } from '@umbraco-cms/backoffice/external/backend-api'; /** @@ -40,7 +40,7 @@ export class UmbScriptItemServerDataSource implements UmbItemDataSource x !== null) as string[]; - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, ScriptService.getItemScript({ path: paths, diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/repository/script-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/repository/script-detail.server.data-source.ts index 5fe28babb8..0cbcb8e4d7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/repository/script-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/repository/script-detail.server.data-source.ts @@ -8,7 +8,7 @@ import type { CreateScriptRequestModel, UpdateScriptRequestModel } from '@umbrac import { ScriptService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; export class UmbScriptDetailServerDataSource implements UmbDetailDataSource { #host: UmbControllerHost; @@ -43,7 +43,7 @@ export class UmbScriptDetailServerDataSource implements UmbDetailDataSource x !== null) as string[]; - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, StylesheetService.getItemStylesheet({ path: paths, diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet-detail.server.data-source.ts index ecfa531346..cc0ff55563 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet-detail.server.data-source.ts @@ -11,7 +11,7 @@ import type { import { StylesheetService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; export class UmbStylesheetDetailServerDataSource implements UmbDetailDataSource { #host: UmbControllerHost; @@ -46,7 +46,7 @@ export class UmbStylesheetDetailServerDataSource implements UmbDetailDataSource< content: model.content, }; - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, StylesheetService.postStylesheet({ requestBody, @@ -68,7 +68,7 @@ export class UmbStylesheetDetailServerDataSource implements UmbDetailDataSource< const path = this.#serverFilePathUniqueSerializer.toServerPath(unique); if (!path) throw new Error('Path is missing'); - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, StylesheetService.getStylesheetByPath({ path: encodeURIComponent(path) }), ); @@ -97,7 +97,7 @@ export class UmbStylesheetDetailServerDataSource implements UmbDetailDataSource< content: model.content, }; - const { error } = await tryExecuteAndNotify( + const { error } = await tryExecute( this.#host, StylesheetService.putStylesheetByPath({ path: encodeURIComponent(path), @@ -118,7 +118,7 @@ export class UmbStylesheetDetailServerDataSource implements UmbDetailDataSource< const path = this.#serverFilePathUniqueSerializer.toServerPath(unique); if (!path) throw new Error('Path is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, StylesheetService.deleteStylesheetByPath({ path: encodeURIComponent(path), diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/folder/repository/stylesheet-folder.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/folder/repository/stylesheet-folder.server.data-source.ts index aae714461f..6eaaada8e8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/folder/repository/stylesheet-folder.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/folder/repository/stylesheet-folder.server.data-source.ts @@ -4,7 +4,7 @@ import type { UmbFolderModel } from '@umbraco-cms/backoffice/tree'; import type { CreateStylesheetFolderRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import { StylesheetService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; @@ -49,7 +49,7 @@ export class UmbStylesheetFolderServerDataSource implements UmbDetailDataSource< const path = this.#serverFilePathUniqueSerializer.toServerPath(unique); if (!path) throw new Error('Cannot read stylesheet folder without a path'); - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, StylesheetService.getStylesheetFolderByPath({ path: encodeURIComponent(path), @@ -88,7 +88,7 @@ export class UmbStylesheetFolderServerDataSource implements UmbDetailDataSource< name: model.name, }; - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, StylesheetService.postStylesheetFolder({ requestBody, @@ -116,7 +116,7 @@ export class UmbStylesheetFolderServerDataSource implements UmbDetailDataSource< const path = this.#serverFilePathUniqueSerializer.toServerPath(unique); if (!path) throw new Error('Cannot delete stylesheet folder without a path'); - return tryExecuteAndNotify( + return tryExecute( this.#host, StylesheetService.deleteStylesheetFolderByPath({ path: encodeURIComponent(path), diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/repository/detail/template-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/repository/detail/template-detail.server.data-source.ts index 299da0b1ac..7bcbeb500a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/repository/detail/template-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/repository/detail/template-detail.server.data-source.ts @@ -8,7 +8,7 @@ import type { } from '@umbraco-cms/backoffice/external/backend-api'; import { TemplateService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Template that fetches data from the server @@ -59,7 +59,7 @@ export class UmbTemplateServerDataSource implements UmbDetailDataSource; +export type UmbMfaProviderConfigurationCallback = Promise<{ error?: UmbApiError | UmbCancelError }>; export interface UmbMfaProviderConfigurationElementProps { /** diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/collection/repository/user-group-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/collection/repository/user-group-collection.server.data-source.ts index 6bbf456370..311132132c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/collection/repository/user-group-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/collection/repository/user-group-collection.server.data-source.ts @@ -4,7 +4,7 @@ import { UMB_USER_GROUP_ENTITY_TYPE } from '../../entity.js'; import { UserGroupService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/collection'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the UserGroup that fetches data from the server @@ -24,7 +24,7 @@ export class UmbUserGroupCollectionServerDataSource implements UmbCollectionData } async getCollection(filter: UmbUserGroupCollectionFilterModel) { - const { data, error } = await tryExecuteAndNotify( + const { data, error } = await tryExecute( this.#host, UserGroupService.getFilterUserGroup({ skip: filter.skip, take: filter.take, filter: filter.query }), ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/repository/detail/user-group-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/repository/detail/user-group-detail.server.data-source.ts index fe1e4bef99..24437a14a5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/repository/detail/user-group-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/repository/detail/user-group-detail.server.data-source.ts @@ -8,7 +8,7 @@ import { UserGroupService } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the User Group that fetches data from the server @@ -65,7 +65,7 @@ export class UmbUserGroupServerDataSource implements UmbDetailDataSource { - return tryExecuteAndNotify(this.#host, UserService.deleteUserAvatarById({ id: unique })); + return tryExecute(this.#host, UserService.deleteUserAvatarById({ id: unique })); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/change-password/change-user-password.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/change-password/change-user-password.server.data-source.ts index ebe00ebe02..0dcb1c63f1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/change-password/change-user-password.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/change-password/change-user-password.server.data-source.ts @@ -1,6 +1,6 @@ import { UserService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A server data source for changing the password of a user @@ -28,7 +28,7 @@ export class UmbChangeUserPasswordServerDataSource { async changePassword(id: string, newPassword: string) { if (!id) throw new Error('User Id is missing'); - return tryExecuteAndNotify( + return tryExecute( this.#host, UserService.postUserByIdChangePassword({ id, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/config/current-user-config.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/config/current-user-config.server.data-source.ts index 5054a2b4b9..2ce7ef04d5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/config/current-user-config.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/config/current-user-config.server.data-source.ts @@ -1,6 +1,6 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UserService } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; export class UmbCurrentUserConfigServerDataSource { #host; @@ -14,6 +14,6 @@ export class UmbCurrentUserConfigServerDataSource { * @memberof UmbCurrentUserConfigServerDataSource */ getCurrentUserConfig() { - return tryExecuteAndNotify(this.#host, UserService.getUserCurrentConfiguration()); + return tryExecute(this.#host, UserService.getUserCurrentConfiguration()); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/config/user-config.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/config/user-config.server.data-source.ts index ced6f1cc52..27cd73eed8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/config/user-config.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/config/user-config.server.data-source.ts @@ -1,6 +1,6 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UserService } from '@umbraco-cms/backoffice/external/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; export class UmbUserConfigServerDataSource { #host; @@ -14,7 +14,7 @@ export class UmbUserConfigServerDataSource { * @memberof UmbUserConfigServerDataSource */ getUserConfig() { - return tryExecuteAndNotify(this.#host, UserService.getUserConfiguration()); + return tryExecute(this.#host, UserService.getUserConfiguration()); } /** @@ -22,6 +22,6 @@ export class UmbUserConfigServerDataSource { * @memberof UmbUserConfigServerDataSource */ getCurrentUserConfig() { - return tryExecuteAndNotify(this.#host, UserService.getUserCurrentConfiguration()); + return tryExecute(this.#host, UserService.getUserCurrentConfiguration()); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts index 6dfb702237..f33bebed5b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/detail/user-detail.server.data-source.ts @@ -10,7 +10,7 @@ import type { } from '@umbraco-cms/backoffice/external/backend-api'; import { UserService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { tryExecute } from '@umbraco-cms/backoffice/resources'; /** * A data source for the User that fetches data from the server @@ -72,7 +72,7 @@ export class UmbUserServerDataSource implements UmbDetailDataSource { - try { - const request = new Request('management/api/v1/security/back-office/login', { - method: 'POST', - body: JSON.stringify({ - username: data.username, - password: data.password, - }), - headers: { - 'Content-Type': 'application/json', - }, - }); + public async login(data: LoginRequestModel): Promise { + try { + const request = new Request('management/api/v1/security/back-office/login', { + method: 'POST', + body: JSON.stringify({ + username: data.username, + password: data.password, + }), + headers: { + 'Content-Type': 'application/json', + }, + }); - const response = await fetch(request); + const response = await fetch(request); - if (!response.ok) { - // If the response code is 402, it means that the user has enabled 2-factor authentication - if (response.status === 402) { - const responseData = await response.json(); - return { - status: response.status, - twoFactorView: responseData.twoFactorLoginView ?? '', - twoFactorProviders: responseData.enabledTwoFactorProviderNames ?? [], - }; - } + if (!response.ok) { + // If the response code is 402, it means that the user has enabled 2-factor authentication + if (response.status === 402) { + const responseData = await response.json(); + return { + status: response.status, + twoFactorView: responseData.twoFactorLoginView ?? '', + twoFactorProviders: responseData.enabledTwoFactorProviderNames ?? [], + }; + } - return { - status: response.status, - error: await this.#getErrorText(response), - }; - } + return { + status: response.status, + error: await this.#getErrorText(response), + }; + } - return { - status: response.status, - data: { - username: data.username, - }, - }; - } catch (error) { - return { - status: 500, - error: error instanceof Error ? error.message : this.#localize.term('auth_receivedErrorFromServer'), - }; - } - } + return { + status: response.status, + data: { + username: data.username, + }, + }; + } catch (error) { + return { + status: 500, + error: error instanceof Error ? error.message : this.#localize.term('auth_receivedErrorFromServer'), + }; + } + } - public async validateMfaCode(code: string, provider: string): Promise { - try { - const requestData = new Request('management/api/v1/security/back-office/verify-2fa', { - method: 'POST', - body: JSON.stringify({ - code, - provider, - }), - headers: { - 'Content-Type': 'application/json', - }, - }); + public async validateMfaCode(code: string, provider: string): Promise { + try { + const requestData = new Request('management/api/v1/security/back-office/verify-2fa', { + method: 'POST', + body: JSON.stringify({ + code, + provider, + }), + headers: { + 'Content-Type': 'application/json', + }, + }); - const response = await fetch(requestData); + const response = await fetch(requestData); - if (!response.ok) { - return { - error: response.status === 400 ? this.#localize.term('auth_mfaInvalidCode') : await this.#getErrorText(response), - }; - } + if (!response.ok) { + return { + error: + response.status === 400 ? this.#localize.term('auth_mfaInvalidCode') : await this.#getErrorText(response), + }; + } - return {}; - } catch (error) { - return { - error: error instanceof Error ? error.message : this.#localize.term('auth_receivedErrorFromServer'), - }; - } - } + return {}; + } catch (error) { + return { + error: error instanceof Error ? error.message : this.#localize.term('auth_receivedErrorFromServer'), + }; + } + } - public async resetPassword(email: string): Promise { - const response = await tryExecute(SecurityService.postSecurityForgotPassword({ - requestBody: { - email - } - })) + public async resetPassword(email: string): Promise { + const response = await tryExecuteAndNotify( + this, + SecurityService.postSecurityForgotPassword({ + requestBody: { + email, + }, + }) + ); - if (response.error) { - return { - error: this.#getApiErrorDetailText(response.error, 'Could not reset the password'), - }; - } + if (response.error) { + return { + error: this.#getApiErrorDetailText(response.error, 'Could not reset the password'), + }; + } - return {}; - } + return {}; + } - public async validatePasswordResetCode(userId: string, resetCode: string): Promise { - const { data, error } = await tryExecute(SecurityService.postSecurityForgotPasswordVerify({ - requestBody: { - user: { - id: userId - }, - resetCode - } - })); + public async validatePasswordResetCode( + userId: string, + resetCode: string + ): Promise { + const { data, error } = await tryExecuteAndNotify( + this, + SecurityService.postSecurityForgotPasswordVerify({ + requestBody: { + user: { + id: userId, + }, + resetCode, + }, + }) + ); - if (error || !data) { - return { - error: this.#getApiErrorDetailText(error, 'Could not validate the password reset code') - }; - } + if (error || !data) { + return { + error: this.#getApiErrorDetailText(error, 'Could not validate the password reset code'), + }; + } - return { - passwordConfiguration: (data as unknown as {passwordConfiguration: PasswordConfigurationModel}).passwordConfiguration // TODO: Fix this when the API schema has been updated - }; - } + return { + passwordConfiguration: (data as unknown as { passwordConfiguration: PasswordConfigurationModel }) + .passwordConfiguration, // TODO: Fix this when the API schema has been updated + }; + } - public async newPassword(password: string, resetCode: string, userId: string): Promise { - const response = await tryExecute(SecurityService.postSecurityForgotPasswordReset({ - requestBody: { - password, - resetCode, - user: { - id: userId - } - } - })); + public async newPassword(password: string, resetCode: string, userId: string): Promise { + const response = await tryExecuteAndNotify( + this, + SecurityService.postSecurityForgotPasswordReset({ + requestBody: { + password, + resetCode, + user: { + id: userId, + }, + }, + }) + ); - if (response.error) { - return { - error: this.#getApiErrorDetailText(response.error, 'Could not reset the password'), - }; - } + if (response.error) { + return { + error: this.#getApiErrorDetailText(response.error, 'Could not reset the password'), + }; + } - return {}; - } + return {}; + } - public async validateInviteCode(token: string, userId: string): Promise { - const { data, error } = await tryExecute(UserService.postUserInviteVerify({ - requestBody: { - token, - user: { - id: userId - } - } - })); + public async validateInviteCode(token: string, userId: string): Promise { + const { data, error } = await tryExecuteAndNotify( + this, + UserService.postUserInviteVerify({ + requestBody: { + token, + user: { + id: userId, + }, + }, + }) + ); - if (error || !data) { - return { - error: this.#getApiErrorDetailText(error, 'Could not validate the invite code') - }; - } + if (error || !data) { + return { + error: this.#getApiErrorDetailText(error, 'Could not validate the invite code'), + }; + } - return { - passwordConfiguration: (data as unknown as {passwordConfiguration: PasswordConfigurationModel}).passwordConfiguration // TODO: Fix this when the API schema has been updated - }; - } + return { + passwordConfiguration: (data as unknown as { passwordConfiguration: PasswordConfigurationModel }) + .passwordConfiguration, // TODO: Fix this when the API schema has been updated + }; + } - public async newInvitedUserPassword(password: string, token: string, userId: string): Promise { - const response = await tryExecute(UserService.postUserInviteCreatePassword({ - requestBody: { - password, - token, - user: { - id: userId - } - } - })); + public async newInvitedUserPassword(password: string, token: string, userId: string): Promise { + const response = await tryExecuteAndNotify( + this, + UserService.postUserInviteCreatePassword({ + requestBody: { + password, + token, + user: { + id: userId, + }, + }, + }) + ); - if (response.error) { - return { - error: this.#getApiErrorDetailText(response.error, 'Could not create a password for the invited user') - }; - } + if (response.error) { + return { + error: this.#getApiErrorDetailText(response.error, 'Could not create a password for the invited user'), + }; + } - return {}; - } + return {}; + } - #getApiErrorDetailText(error: ApiError | CancelError | undefined, fallbackText?: string): string | undefined { - if (error instanceof ApiError) { - // Try to parse the body - return typeof error.body === 'object' ? (error.body as ProblemDetails).title ?? fallbackText : fallbackText ?? 'An unknown error occurred.'; - } + #getApiErrorDetailText(error: ApiError | CancelError | undefined, fallbackText?: string): string | undefined { + if (error instanceof ApiError) { + // Try to parse the body + return typeof error.body === 'object' + ? (error.body as ProblemDetails).title ?? fallbackText + : fallbackText ?? 'An unknown error occurred.'; + } - // Ignore cancel errors (user cancelled the request) - if (error instanceof CancelError) { - return undefined; - } + // Ignore cancel errors (user cancelled the request) + if (error instanceof CancelError) { + return undefined; + } - return fallbackText ?? 'An unknown error occurred.'; - } + return fallbackText ?? 'An unknown error occurred.'; + } - async #getErrorText(response: Response): Promise { - switch (response.status) { - case 400: - case 401: - return this.#localize.term('auth_userFailedLogin'); + async #getErrorText(response: Response): Promise { + switch (response.status) { + case 400: + case 401: + return this.#localize.term('auth_userFailedLogin'); - case 402: - return this.#localize.term('auth_mfaText'); + case 402: + return this.#localize.term('auth_mfaText'); - case 403: - return this.#localize.term('auth_userLockedOut'); + case 403: + return this.#localize.term('auth_userLockedOut'); - default: - return ( - this.#localize.term('auth_receivedErrorFromServer') - ); - } - } + default: + return this.#localize.term('auth_receivedErrorFromServer'); + } + } }