{"version":3,"file":"index.js","sources":["../../../../src/packages/core/resources/apiTypeValidators.function.ts","../../../../src/packages/core/resources/resource.controller.ts","../../../../src/packages/core/resources/tryExecute.function.ts","../../../../src/packages/core/resources/tryExecuteAndNotify.function.ts"],"sourcesContent":["import type { ApiError, CancelError, CancelablePromise } from '@umbraco-cms/backoffice/external/backend-api';\r\n\r\n/**\r\n *\r\n * @param error\r\n */\r\nexport function isApiError(error: unknown): error is ApiError {\r\n\treturn (error as ApiError).name === 'ApiError';\r\n}\r\n\r\n/**\r\n *\r\n * @param error\r\n */\r\nexport function isCancelError(error: unknown): error is CancelError {\r\n\treturn (error as CancelError).name === 'CancelError';\r\n}\r\n\r\n/**\r\n *\r\n * @param promise\r\n */\r\nexport function isCancelablePromise(promise: unknown): promise is CancelablePromise {\r\n\treturn (promise as CancelablePromise).cancel !== undefined;\r\n}\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { UMB_AUTH_CONTEXT } from '../auth/index.js';\r\nimport { isApiError, isCancelError, isCancelablePromise } from './apiTypeValidators.function.js';\r\nimport type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';\r\nimport { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';\r\nimport { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';\r\nimport { UMB_NOTIFICATION_CONTEXT, type UmbNotificationOptions } from '@umbraco-cms/backoffice/notification';\r\nimport type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository';\r\nimport type { ProblemDetails } from '@umbraco-cms/backoffice/external/backend-api';\r\n\r\nexport class UmbResourceController extends UmbControllerBase {\r\n\t#promise: Promise;\r\n\r\n\t#notificationContext?: typeof UMB_NOTIFICATION_CONTEXT.TYPE;\r\n\r\n\t#authContext?: typeof UMB_AUTH_CONTEXT.TYPE;\r\n\r\n\tconstructor(host: UmbControllerHost, promise: Promise, alias?: string) {\r\n\t\tsuper(host, alias);\r\n\r\n\t\tthis.#promise = promise;\r\n\r\n\t\tnew UmbContextConsumerController(host, UMB_NOTIFICATION_CONTEXT, (_instance) => {\r\n\t\t\tthis.#notificationContext = _instance;\r\n\t\t});\r\n\r\n\t\tnew UmbContextConsumerController(host, UMB_AUTH_CONTEXT, (_instance) => {\r\n\t\t\tthis.#authContext = _instance;\r\n\t\t});\r\n\t}\r\n\r\n\toverride hostConnected(): void {\r\n\t\t// Do nothing\r\n\t}\r\n\r\n\toverride hostDisconnected(): void {\r\n\t\tthis.cancel();\r\n\t}\r\n\r\n\t/**\r\n\t * Base execute function with a try/catch block and return a tuple with the result and the error.\r\n\t * @param promise\r\n\t */\r\n\tstatic async tryExecute(promise: Promise): Promise> {\r\n\t\ttry {\r\n\t\t\treturn { data: await promise };\r\n\t\t} catch (error) {\r\n\t\t\tif (isApiError(error) || isCancelError(error)) {\r\n\t\t\t\treturn { error };\r\n\t\t\t}\r\n\r\n\t\t\tconsole.error('Unknown error', error);\r\n\t\t\tthrow new Error('Unknown error');\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Wrap the {tryExecute} function in a try/catch block and return the result.\r\n\t * If the executor function throws an error, then show the details in a notification.\r\n\t * @param options\r\n\t */\r\n\tasync tryExecuteAndNotify(options?: UmbNotificationOptions): Promise> {\r\n\t\tconst { data, error } = await UmbResourceController.tryExecute(this.#promise);\r\n\r\n\t\tif (error) {\r\n\t\t\t/**\r\n\t\t\t * Determine if we want to show a notification or just log the error to the console.\r\n\t\t\t * If the error is not a recognizable system error (i.e. a HttpError), then we will show a notification\r\n\t\t\t * with the error details using the default notification options.\r\n\t\t\t */\r\n\t\t\tif (isCancelError(error)) {\r\n\t\t\t\t// Cancelled - do nothing\r\n\t\t\t\treturn {};\r\n\t\t\t} else {\r\n\t\t\t\tconsole.group('ApiError caught in UmbResourceController');\r\n\t\t\t\tconsole.error('Request failed', error.request);\r\n\t\t\t\tconsole.error('Request body', error.body);\r\n\t\t\t\tconsole.error('Error', error);\r\n\r\n\t\t\t\tlet problemDetails: ProblemDetails | null = null;\r\n\r\n\t\t\t\t// ApiError - body could hold a ProblemDetails from the server\r\n\t\t\t\tif (typeof error.body !== 'undefined' && !!error.body) {\r\n\t\t\t\t\ttry {\r\n\t\t\t\t\t\t(error as any).body = problemDetails = typeof error.body === 'string' ? JSON.parse(error.body) : error.body;\r\n\t\t\t\t\t} catch (e) {\r\n\t\t\t\t\t\tconsole.error('Error parsing error body (expected JSON)', e);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t/**\r\n\t\t\t\t * Check if the operation status ends with `ByNotification` and if so, don't show a notification\r\n\t\t\t\t * This is a special case where the operation was cancelled by the server and the client gets a notification header instead.\r\n\t\t\t\t */\r\n\t\t\t\tlet isCancelledByNotification = false;\r\n\t\t\t\tif (\r\n\t\t\t\t\tproblemDetails?.operationStatus &&\r\n\t\t\t\t\ttypeof problemDetails.operationStatus === 'string' &&\r\n\t\t\t\t\tproblemDetails.operationStatus.endsWith('ByNotification')\r\n\t\t\t\t) {\r\n\t\t\t\t\tisCancelledByNotification = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Go through the error status codes and act accordingly\r\n\t\t\t\tswitch (error.status ?? 0) {\r\n\t\t\t\t\tcase 401: {\r\n\t\t\t\t\t\t// See if we can get the UmbAuthContext and let it know the user is timed out\r\n\t\t\t\t\t\tif (this.#authContext) {\r\n\t\t\t\t\t\t\tthis.#authContext.timeOut();\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t// If we can't get the auth context, show a notification\r\n\t\t\t\t\t\t\tthis.#notificationContext?.peek('warning', {\r\n\t\t\t\t\t\t\t\tdata: {\r\n\t\t\t\t\t\t\t\t\theadline: 'Session Expired',\r\n\t\t\t\t\t\t\t\t\tmessage: 'Your session has expired. Please refresh the page.',\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcase 500:\r\n\t\t\t\t\t\t// Server Error\r\n\r\n\t\t\t\t\t\tif (!isCancelledByNotification && this.#notificationContext) {\r\n\t\t\t\t\t\t\tlet headline = problemDetails?.title ?? error.name ?? 'Server Error';\r\n\t\t\t\t\t\t\tlet message = 'A fatal server error occurred. If this continues, please reach out to your administrator.';\r\n\r\n\t\t\t\t\t\t\t// Special handling for ObjectCacheAppCache corruption errors, which we are investigating\r\n\t\t\t\t\t\t\tif (\r\n\t\t\t\t\t\t\t\tproblemDetails?.detail?.includes('ObjectCacheAppCache') ||\r\n\t\t\t\t\t\t\t\tproblemDetails?.detail?.includes('Umbraco.Cms.Infrastructure.Scoping.Scope.DisposeLastScope()')\r\n\t\t\t\t\t\t\t) {\r\n\t\t\t\t\t\t\t\theadline = 'Please restart the server';\r\n\t\t\t\t\t\t\t\tmessage =\r\n\t\t\t\t\t\t\t\t\t'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.';\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tthis.#notificationContext.peek('danger', {\r\n\t\t\t\t\t\t\t\tdata: {\r\n\t\t\t\t\t\t\t\t\theadline,\r\n\t\t\t\t\t\t\t\t\tmessage,\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t...options,\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t// Other errors\r\n\t\t\t\t\t\tif (!isCancelledByNotification && this.#notificationContext) {\r\n\t\t\t\t\t\t\tthis.#notificationContext.peek('danger', {\r\n\t\t\t\t\t\t\t\tdata: {\r\n\t\t\t\t\t\t\t\t\theadline: problemDetails?.title ?? error.name ?? 'Server Error',\r\n\t\t\t\t\t\t\t\t\tmessage: problemDetails?.detail ?? error.message ?? 'Something went wrong',\r\n\t\t\t\t\t\t\t\t\tstructuredList: problemDetails?.errors\r\n\t\t\t\t\t\t\t\t\t\t? (problemDetails.errors as Record>)\r\n\t\t\t\t\t\t\t\t\t\t: undefined,\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t...options,\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconsole.groupEnd();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn { data, error };\r\n\t}\r\n\r\n\t/**\r\n\t * Cancel all resources that are currently being executed by this controller if they are cancelable.\r\n\t *\r\n\t * This works by checking if the promise is a CancelablePromise and if so, it will call the cancel method.\r\n\t *\r\n\t * This is useful when the controller is being disconnected from the DOM.\r\n\t * @see CancelablePromise\r\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal\r\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/AbortController\r\n\t */\r\n\tcancel(): void {\r\n\t\tif (isCancelablePromise(this.#promise)) {\r\n\t\t\tthis.#promise.cancel();\r\n\t\t}\r\n\t}\r\n\r\n\toverride destroy(): void {\r\n\t\tsuper.destroy();\r\n\t\tthis.cancel();\r\n\t}\r\n}\r\n","import { UmbResourceController } from './resource.controller.js';\r\nimport type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository';\r\n\r\n/**\r\n *\r\n * @param promise\r\n */\r\nexport function tryExecute(promise: Promise): Promise> {\r\n\treturn UmbResourceController.tryExecute(promise);\r\n}\r\n","import { UmbResourceController } from './resource.controller.js';\r\nimport type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';\r\nimport type { UmbNotificationOptions } from '@umbraco-cms/backoffice/notification';\r\nimport type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository';\r\n\r\n/**\r\n *\r\n * @param host\r\n * @param resource\r\n * @param options\r\n */\r\nexport function tryExecuteAndNotify(\r\n\thost: UmbControllerHost,\r\n\tresource: Promise,\r\n\toptions?: UmbNotificationOptions,\r\n): Promise> {\r\n\treturn new UmbResourceController(host, resource).tryExecuteAndNotify(options);\r\n}\r\n"],"names":["isApiError","error","isCancelError","isCancelablePromise","promise","UmbResourceController","UmbControllerBase","#promise","#notificationContext","#authContext","host","alias","UmbContextConsumerController","UMB_NOTIFICATION_CONTEXT","_instance","UMB_AUTH_CONTEXT","options","data","problemDetails","e","isCancelledByNotification","headline","message","tryExecute","tryExecuteAndNotify","resource"],"mappings":"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"}