{"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","../../../../src/packages/core/resources/tryXhrRequest.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 { UmbDeprecation } from '../utils/deprecation/deprecation.js';\r\nimport { isApiError, isCancelError, isCancelablePromise } from './apiTypeValidators.function.js';\r\nimport type { XhrRequestOptions } from './types.js';\r\nimport type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';\r\nimport { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';\r\nimport type { UmbNotificationOptions } from '@umbraco-cms/backoffice/notification';\r\nimport type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository';\r\nimport {\r\n\tApiError,\r\n\tCancelablePromise,\r\n\tCancelError,\r\n\ttype ProblemDetails,\r\n} from '@umbraco-cms/backoffice/external/backend-api';\r\n\r\nexport class UmbResourceController extends UmbControllerBase {\r\n\t#promise: Promise;\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\t}\r\n\r\n\toverride hostDisconnected(): void {\r\n\t\tsuper.hostDisconnected();\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\t// 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)\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\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n\tasync tryExecuteAndNotify(options?: UmbNotificationOptions): Promise> {\r\n\t\tconst { data, error } = await UmbResourceController.tryExecute(this.#promise);\r\n\r\n\t\tif (options) {\r\n\t\t\tnew UmbDeprecation({\r\n\t\t\t\tdeprecated: 'tryExecuteAndNotify `options` argument is deprecated.',\r\n\t\t\t\tremoveInVersion: '17.0.0',\r\n\t\t\t\tsolution: 'Use the method without arguments.',\r\n\t\t\t}).warn();\r\n\t\t}\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.groupCollapsed('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\t\t\t\tconsole.groupEnd();\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\tconst authContext = await this.getContext(UMB_AUTH_CONTEXT);\r\n\t\t\t\t\t\tauthContext.timeOut();\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) {\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\t// This late importing is done to avoid circular reference [NL]\r\n\t\t\t\t\t\t\t(await import('@umbraco-cms/backoffice/notification')).umbPeekError(this, {\r\n\t\t\t\t\t\t\t\theadline: headline,\r\n\t\t\t\t\t\t\t\tmessage: message,\r\n\t\t\t\t\t\t\t\tdetails: problemDetails?.errors ?? problemDetails?.detail,\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) {\r\n\t\t\t\t\t\t\t/*\r\n\t\t\t\t\t\t\tconst notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT);\r\n\t\t\t\t\t\t\tnotificationContext.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\t*/\r\n\t\t\t\t\t\t\tconst headline = problemDetails?.title ?? error.name ?? 'Server Error';\r\n\t\t\t\t\t\t\t// This late importing is done to avoid circular reference [NL]\r\n\t\t\t\t\t\t\t(await import('@umbraco-cms/backoffice/notification')).umbPeekError(this, {\r\n\t\t\t\t\t\t\t\tmessage: headline,\r\n\t\t\t\t\t\t\t\tdetails: problemDetails?.errors ?? problemDetails?.detail,\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\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 * Make an XHR request.\r\n\t * @param host The controller host for this controller to be appended to.\r\n\t * @param options The options for the XHR request.\r\n\t */\r\n\tstatic xhrRequest(options: XhrRequestOptions): CancelablePromise {\r\n\t\tconst baseUrl = options.baseUrl || '/umbraco';\r\n\r\n\t\tconst promise = new CancelablePromise(async (resolve, reject, onCancel) => {\r\n\t\t\tconst xhr = new XMLHttpRequest();\r\n\t\t\txhr.open(options.method, `${baseUrl}${options.url}`, true);\r\n\r\n\t\t\t// Set default headers\r\n\t\t\tif (options.token) {\r\n\t\t\t\tconst token = typeof options.token === 'function' ? await options.token() : options.token;\r\n\t\t\t\tif (token) {\r\n\t\t\t\t\txhr.setRequestHeader('Authorization', `Bearer ${token}`);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Infer Content-Type header based on body type\r\n\t\t\tif (options.body instanceof FormData) {\r\n\t\t\t\t// Note: 'multipart/form-data' is automatically set by the browser for FormData\r\n\t\t\t} else {\r\n\t\t\t\txhr.setRequestHeader('Content-Type', 'application/json');\r\n\t\t\t}\r\n\r\n\t\t\t// Set custom headers\r\n\t\t\tif (options.headers) {\r\n\t\t\t\tfor (const [key, value] of Object.entries(options.headers)) {\r\n\t\t\t\t\txhr.setRequestHeader(key, value);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\txhr.upload.onprogress = (event) => {\r\n\t\t\t\tif (options.onProgress) {\r\n\t\t\t\t\toptions.onProgress(event);\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\txhr.onload = () => {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tif (xhr.status >= 200 && xhr.status < 300) {\r\n\t\t\t\t\t\tif (options.responseHeader) {\r\n\t\t\t\t\t\t\tconst response = xhr.getResponseHeader(options.responseHeader);\r\n\t\t\t\t\t\t\tresolve(response as T);\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tresolve(JSON.parse(xhr.responseText));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\t// 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.\r\n\t\t\t\t\t\tconst error = new ApiError(\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tmethod: options.method,\r\n\t\t\t\t\t\t\t\turl: `${baseUrl}${options.url}`,\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tbody: xhr.responseText,\r\n\t\t\t\t\t\t\t\tok: false,\r\n\t\t\t\t\t\t\t\tstatus: xhr.status,\r\n\t\t\t\t\t\t\t\tstatusText: xhr.statusText,\r\n\t\t\t\t\t\t\t\turl: xhr.responseURL,\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\txhr.statusText,\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t\treject(error);\r\n\t\t\t\t\t}\r\n\t\t\t\t} catch {\r\n\t\t\t\t\t// This most likely happens when the response is not JSON\r\n\t\t\t\t\treject(new Error(`Failed to make request: ${xhr.statusText}`));\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\txhr.onerror = () => {\r\n\t\t\t\t// 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.\r\n\t\t\t\tconst error = new ApiError(\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmethod: options.method,\r\n\t\t\t\t\t\turl: `${baseUrl}${options.url}`,\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbody: xhr.responseText,\r\n\t\t\t\t\t\tok: false,\r\n\t\t\t\t\t\tstatus: xhr.status,\r\n\t\t\t\t\t\tstatusText: xhr.statusText,\r\n\t\t\t\t\t\turl: xhr.responseURL,\r\n\t\t\t\t\t},\r\n\t\t\t\t\txhr.statusText,\r\n\t\t\t\t);\r\n\t\t\t\treject(error);\r\n\t\t\t};\r\n\r\n\t\t\tif (!onCancel.isCancelled) {\r\n\t\t\t\t// Handle body based on Content-Type\r\n\t\t\t\tif (options.body instanceof FormData) {\r\n\t\t\t\t\txhr.send(options.body);\r\n\t\t\t\t} else {\r\n\t\t\t\t\txhr.send(JSON.stringify(options.body));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tonCancel(() => {\r\n\t\t\t\txhr.abort();\r\n\t\t\t\t// 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.\r\n\t\t\t\treject(new CancelError('Request was cancelled.'));\r\n\t\t\t});\r\n\t\t});\r\n\r\n\t\tif (options.abortSignal) {\r\n\t\t\toptions.abortSignal.addEventListener('abort', () => {\r\n\t\t\t\tpromise.cancel();\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\treturn promise;\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","import type { XhrRequestOptions } from './types.js';\r\nimport { UmbResourceController } from './resource.controller.js';\r\nimport { OpenAPI, type CancelablePromise } from '@umbraco-cms/backoffice/external/backend-api';\r\n\r\n/**\r\n * Make an XHR request.\r\n * @param {XhrRequestOptions} options The options for the XHR request.\r\n * @returns {CancelablePromise} A promise that can be cancelled.\r\n */\r\nexport function tryXhrRequest(options: XhrRequestOptions): CancelablePromise {\r\n\treturn UmbResourceController.xhrRequest({\r\n\t\t...options,\r\n\t\tbaseUrl: OpenAPI.BASE,\r\n\t\ttoken: OpenAPI.TOKEN as never,\r\n\t});\r\n}\r\n"],"names":["isApiError","error","isCancelError","isCancelablePromise","promise","UmbResourceController","UmbControllerBase","#promise","host","alias","options","data","UmbDeprecation","problemDetails","e","isCancelledByNotification","UMB_AUTH_CONTEXT","headline","message","baseUrl","CancelablePromise","resolve","reject","onCancel","xhr","token","key","value","event","response","ApiError","CancelError","tryExecute","tryExecuteAndNotify","resource","tryXhrRequest","OpenAPI"],"mappings":"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"}