@webiny/background-tasks 6.6.0-alpha.0 → 6.6.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/admin/BackgroundTaskRoutes.js +16 -3
  2. package/admin/BackgroundTaskRoutes.js.map +1 -1
  3. package/admin/presentation/TaskDetail/components/TaskDetailDrawer.js +6 -0
  4. package/admin/presentation/TaskDetail/components/TaskDetailDrawer.js.map +1 -1
  5. package/admin/presentation/TaskExecutions/components/TaskExecutionsView.js +44 -24
  6. package/admin/presentation/TaskExecutions/components/TaskExecutionsView.js.map +1 -1
  7. package/api/BackgroundTasksFeature.js +2 -0
  8. package/api/BackgroundTasksFeature.js.map +1 -1
  9. package/api/crud/service.tasks.js +4 -2
  10. package/api/crud/service.tasks.js.map +1 -1
  11. package/api/decorators/RunnableTaskDecorator.d.ts +2 -1
  12. package/api/decorators/RunnableTaskDecorator.js +5 -6
  13. package/api/decorators/RunnableTaskDecorator.js.map +1 -1
  14. package/api/decorators/SelfCleaningTaskDecorator.d.ts +5 -2
  15. package/api/decorators/SelfCleaningTaskDecorator.js +14 -5
  16. package/api/decorators/SelfCleaningTaskDecorator.js.map +1 -1
  17. package/api/domain/errors.d.ts +10 -0
  18. package/api/domain/errors.js +11 -1
  19. package/api/domain/errors.js.map +1 -1
  20. package/api/features/GetTaskDefinition/GetTaskDefinitionUseCase.d.ts +6 -3
  21. package/api/features/GetTaskDefinition/GetTaskDefinitionUseCase.js +66 -5
  22. package/api/features/GetTaskDefinition/GetTaskDefinitionUseCase.js.map +1 -1
  23. package/api/features/GetTaskDefinition/abstractions.d.ts +2 -1
  24. package/api/features/GetTaskDefinition/abstractions.js.map +1 -1
  25. package/api/features/TaskHandlerResolver/TaskHandlerResolver.d.ts +12 -0
  26. package/api/features/TaskHandlerResolver/TaskHandlerResolver.js +19 -0
  27. package/api/features/TaskHandlerResolver/TaskHandlerResolver.js.map +1 -0
  28. package/api/features/TaskHandlerResolver/abstractions.d.ts +17 -0
  29. package/api/features/TaskHandlerResolver/abstractions.js +5 -0
  30. package/api/features/TaskHandlerResolver/abstractions.js.map +1 -0
  31. package/api/features/TaskHandlerResolver/feature.d.ts +9 -0
  32. package/api/features/TaskHandlerResolver/feature.js +11 -0
  33. package/api/features/TaskHandlerResolver/feature.js.map +1 -0
  34. package/api/features/TaskHandlerResolver/index.d.ts +2 -0
  35. package/api/features/TaskHandlerResolver/index.js +2 -0
  36. package/api/runner/TaskControl.d.ts +25 -1
  37. package/api/runner/TaskControl.js +28 -18
  38. package/api/runner/TaskControl.js.map +1 -1
  39. package/api/runner/TaskManager.d.ts +12 -1
  40. package/api/runner/TaskManager.js +8 -7
  41. package/api/runner/TaskManager.js.map +1 -1
  42. package/api/runner/TaskManagerStore.d.ts +7 -0
  43. package/api/runner/TaskManagerStore.js +3 -3
  44. package/api/runner/TaskManagerStore.js.map +1 -1
  45. package/api/runner/TaskRunner.js +25 -4
  46. package/api/runner/TaskRunner.js.map +1 -1
  47. package/api/tasks/testingRunTask.d.ts +10 -2
  48. package/api/tasks/testingRunTask.js +10 -3
  49. package/api/tasks/testingRunTask.js.map +1 -1
  50. package/package.json +26 -28
  51. package/testing/index.d.ts +3 -0
  52. package/testing/index.js +2 -0
  53. package/testing/mockTaskTriggerTransportPlugin.d.ts +2 -0
  54. package/testing/mockTaskTriggerTransportPlugin.js +18 -0
  55. package/testing/mockTaskTriggerTransportPlugin.js.map +1 -0
  56. package/testing/runner.d.ts +19 -0
  57. package/testing/runner.js +44 -0
  58. package/testing/runner.js.map +1 -0
@@ -1 +1 @@
1
- {"version":3,"file":"api/crud/service.tasks.js","sources":["../../../src/api/crud/service.tasks.ts"],"sourcesContent":["import WebinyError from \"@webiny/error\";\nimport type { Container } from \"@webiny/di\";\nimport type {\n ITaskAbortParams,\n ITaskCreateData,\n ITaskLog,\n ITasksContextServiceObject,\n ITaskTriggerParams\n} from \"~/api/types.js\";\nimport { TasksCrud } from \"~/api/TasksCrud.js\";\nimport { TaskDataStatus, TaskLogItemType } from \"~/api/types.js\";\nimport { NotFoundError } from \"@webiny/api-graphql\";\nimport { createService } from \"~/api/service/index.js\";\nimport type { IServiceInfo } from \"@webiny/api-core/features/task/TaskService/abstractions.js\";\nimport { TaskService } from \"@webiny/api-core/features/task/TaskService/index.js\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { BaseError, Result } from \"@webiny/feature/api\";\nimport {\n TaskAbortError,\n TaskDefinitionNotFoundError,\n TaskNotFoundError,\n TaskServiceInfoError\n} from \"~/api/domain/errors.js\";\n\nconst MAX_DELAY_DAYS = 355;\nconst MAX_DELAY_SECONDS = MAX_DELAY_DAYS * 24 * 60 * 60;\n\ninterface ValidateDelayParams<T extends TaskService.TaskInput> {\n input: ITaskCreateData<T>;\n delay?: number;\n}\n\nconst validateDelay = <T extends TaskService.TaskInput = TaskService.TaskInput>({\n input,\n delay\n}: ValidateDelayParams<T>): void => {\n if (!delay || delay < 0 || typeof delay !== \"number\" || Number.isInteger(delay) === false) {\n return;\n } else if (delay < MAX_DELAY_SECONDS) {\n return;\n }\n throw new WebinyError(\n `The maximum delay for a task is ${MAX_DELAY_DAYS} days.`,\n \"MAX_DELAY_ERROR\",\n {\n ...input,\n delay\n }\n );\n};\n\nexport const createServiceCrud = (container: Container): ITasksContextServiceObject => {\n return {\n trigger: async <\n T extends TaskService.TaskInput = TaskService.TaskInput,\n O extends TaskService.GenericOutput = TaskService.GenericOutput\n >(\n params: ITaskTriggerParams<T>\n ): Promise<Result<TaskService.Task<T, O>, BaseError>> => {\n const service = createService({ container });\n const { definition: id, input: inputValues, name, parent, delay = 0 } = params;\n const definition = container.resolve(TasksCrud).getDefinition(id);\n if (!definition) {\n throw new WebinyError(`Task definition was not found!`, \"TASK_DEFINITION_ERROR\", {\n id\n });\n }\n const input: TaskDefinition.TaskCreateData<T> = {\n name: name || definition.title,\n definitionId: id,\n input: inputValues || ({} as T),\n parentId: parent?.id\n };\n\n if (definition.onBeforeTrigger) {\n await definition.onBeforeTrigger({ data: input });\n }\n validateDelay<T>({\n input,\n delay\n });\n\n let task: TaskService.Task<T>;\n try {\n task = await container.resolve(TasksCrud).createTask<T>(input);\n } catch (ex) {\n console.log(\"Could not create the task.\", ex);\n throw ex;\n }\n\n let result: Awaited<ReturnType<typeof service.send>> | null = null;\n try {\n result = await service.send(task, delay);\n\n if (!result) {\n throw new WebinyError(\n `Could not trigger the step function!`,\n \"TRIGGER_STEP_FUNCTION_ERROR\",\n {\n task\n }\n );\n }\n } catch (ex) {\n console.log(\"Could not trigger the step function.\");\n console.error(ex);\n /**\n * In case of failure to create the Event Bridge Event, we need to delete the task that was meant to be created.\n * TODO maybe we can leave the task and update it as failed - with event bridge error?\n */\n await container.resolve(TasksCrud).deleteTask(task.id);\n throw ex;\n }\n\n const updatedTask = await container.resolve(TasksCrud).updateTask<T, O>(task.id, {\n eventResponse: result\n });\n\n return Result.ok(updatedTask);\n },\n fetchServiceInfo: async (\n input: TaskService.Task | string\n ): Promise<Result<IServiceInfo, BaseError<any>>> => {\n const service = createService({ container });\n const task =\n typeof input === \"object\"\n ? input\n : await container.resolve(TasksCrud).getTask(input);\n if (!task && typeof input === \"string\") {\n throw new NotFoundError(`Task \"${input}\" was not found!`);\n } else if (!task) {\n throw new WebinyError(`Task was not found!`, \"TASK_FETCH_ERROR\", {\n input\n });\n }\n\n try {\n const info = (await service.fetch(task)) as IServiceInfo | null;\n if (info) {\n return Result.ok(info);\n }\n\n return Result.fail(new TaskServiceInfoError());\n } catch (ex) {\n console.log(\"Service fetch error.\");\n console.error(ex);\n return Result.fail(new TaskServiceInfoError());\n }\n },\n abort: async <\n T extends TaskService.TaskInput = TaskService.TaskInput,\n O extends TaskService.GenericOutput = TaskService.GenericOutput\n >(\n params: ITaskAbortParams\n ): Promise<Result<TaskService.Task<T, O>, BaseError<any>>> => {\n const task = await container.resolve(TasksCrud).getTask<T, O>(params.id);\n if (!task) {\n return Result.fail(new TaskNotFoundError());\n }\n\n const definition = container.resolve(TasksCrud).getDefinition<T, O>(task.definitionId);\n if (!definition) {\n return Result.fail(new TaskDefinitionNotFoundError(task.definitionId));\n }\n /**\n * We should only be able to abort a task which is pending or running\n */\n if (\n [TaskDataStatus.PENDING, TaskDataStatus.RUNNING].includes(task.taskStatus) === false\n ) {\n return Result.fail(\n new TaskAbortError({\n id: params.id,\n status: task.taskStatus\n })\n );\n }\n let taskLog: ITaskLog | null = null;\n try {\n taskLog = await container.resolve(TasksCrud).getLatestLog(task.id);\n } catch {}\n if (!taskLog) {\n taskLog = await container.resolve(TasksCrud).createLog(task, {\n iteration: 1,\n executionName: task.executionName\n });\n }\n try {\n const updatedTask = await container.resolve(TasksCrud).updateTask<T, O>(task.id, {\n taskStatus: TaskDataStatus.ABORTED\n });\n await container.resolve(TasksCrud).updateLog(taskLog.id, {\n items: taskLog.items.concat([\n {\n message: params.message || \"Task aborted.\",\n type: TaskLogItemType.INFO,\n createdOn: new Date().toISOString()\n }\n ])\n });\n /**\n * TODO: determine when to kick off the onAbort hook\n */\n if (definition.onAbort) {\n await definition.onAbort({\n task: updatedTask\n });\n }\n\n return Result.ok(updatedTask);\n } catch (ex) {\n throw new WebinyError(`Could not abort the task!`, \"TASK_ABORT_ERROR\", {\n id: params.id,\n message: ex.message\n });\n }\n }\n };\n};\n"],"names":["MAX_DELAY_DAYS","MAX_DELAY_SECONDS","validateDelay","input","delay","Number","WebinyError","createServiceCrud","container","params","service","createService","id","inputValues","name","parent","definition","TasksCrud","task","ex","console","result","updatedTask","Result","NotFoundError","info","TaskServiceInfoError","TaskNotFoundError","TaskDefinitionNotFoundError","TaskDataStatus","TaskAbortError","taskLog","TaskLogItemType","Date"],"mappings":"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"}
1
+ {"version":3,"file":"api/crud/service.tasks.js","sources":["../../../src/api/crud/service.tasks.ts"],"sourcesContent":["import WebinyError from \"@webiny/error\";\nimport type { Container } from \"@webiny/di\";\nimport type {\n ITaskAbortParams,\n ITaskCreateData,\n ITaskLog,\n ITasksContextServiceObject,\n ITaskTriggerParams\n} from \"~/api/types.js\";\nimport { TasksCrud } from \"~/api/TasksCrud.js\";\nimport { TaskDataStatus, TaskLogItemType } from \"~/api/types.js\";\nimport { NotFoundError } from \"@webiny/api-graphql\";\nimport { createService } from \"~/api/service/index.js\";\nimport type { IServiceInfo } from \"@webiny/api-core/features/task/TaskService/abstractions.js\";\nimport { TaskService } from \"@webiny/api-core/features/task/TaskService/index.js\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { BaseError, Result } from \"@webiny/feature/api\";\nimport {\n TaskAbortError,\n TaskDefinitionNotFoundError,\n TaskNotFoundError,\n TaskServiceInfoError\n} from \"~/api/domain/errors.js\";\n\nconst MAX_DELAY_DAYS = 355;\nconst MAX_DELAY_SECONDS = MAX_DELAY_DAYS * 24 * 60 * 60;\n\ninterface ValidateDelayParams<T extends TaskService.TaskInput> {\n input: ITaskCreateData<T>;\n delay?: number;\n}\n\nconst validateDelay = <T extends TaskService.TaskInput = TaskService.TaskInput>({\n input,\n delay\n}: ValidateDelayParams<T>): void => {\n if (!delay || delay < 0 || typeof delay !== \"number\" || Number.isInteger(delay) === false) {\n return;\n } else if (delay < MAX_DELAY_SECONDS) {\n return;\n }\n throw new WebinyError(\n `The maximum delay for a task is ${MAX_DELAY_DAYS} days.`,\n \"MAX_DELAY_ERROR\",\n {\n ...input,\n delay\n }\n );\n};\n\nexport const createServiceCrud = (container: Container): ITasksContextServiceObject => {\n return {\n trigger: async <\n T extends TaskService.TaskInput = TaskService.TaskInput,\n O extends TaskService.GenericOutput = TaskService.GenericOutput\n >(\n params: ITaskTriggerParams<T>\n ): Promise<Result<TaskService.Task<T, O>, BaseError>> => {\n const service = createService({ container });\n const { definition: id, input: inputValues, name, parent, delay = 0 } = params;\n const definition = container.resolve(TasksCrud).getDefinition(id);\n if (!definition) {\n throw new WebinyError(`Task definition was not found!`, \"TASK_DEFINITION_ERROR\", {\n id\n });\n }\n const input: TaskDefinition.TaskCreateData<T> = {\n name: name || definition.title,\n definitionId: id,\n input: inputValues || ({} as T),\n parentId: parent?.id\n };\n\n if (definition.onBeforeTrigger) {\n await definition.onBeforeTrigger({ data: input, definition });\n }\n validateDelay<T>({\n input,\n delay\n });\n\n let task: TaskService.Task<T>;\n try {\n task = await container.resolve(TasksCrud).createTask<T>(input);\n } catch (ex) {\n console.log(\"Could not create the task.\", ex);\n throw ex;\n }\n\n let result: Awaited<ReturnType<typeof service.send>> | null = null;\n try {\n result = await service.send(task, delay);\n\n if (!result) {\n throw new WebinyError(\n `Could not trigger the step function!`,\n \"TRIGGER_STEP_FUNCTION_ERROR\",\n {\n task\n }\n );\n }\n } catch (ex) {\n console.log(\"Could not trigger the step function.\");\n console.error(ex);\n /**\n * In case of failure to create the Event Bridge Event, we need to delete the task that was meant to be created.\n * TODO maybe we can leave the task and update it as failed - with event bridge error?\n */\n await container.resolve(TasksCrud).deleteTask(task.id);\n throw ex;\n }\n\n const updatedTask = await container.resolve(TasksCrud).updateTask<T, O>(task.id, {\n eventResponse: result\n });\n\n return Result.ok(updatedTask);\n },\n fetchServiceInfo: async (\n input: TaskService.Task | string\n ): Promise<Result<IServiceInfo, BaseError<any>>> => {\n const service = createService({ container });\n const task =\n typeof input === \"object\"\n ? input\n : await container.resolve(TasksCrud).getTask(input);\n if (!task && typeof input === \"string\") {\n throw new NotFoundError(`Task \"${input}\" was not found!`);\n } else if (!task) {\n throw new WebinyError(`Task was not found!`, \"TASK_FETCH_ERROR\", {\n input\n });\n }\n\n try {\n const info = (await service.fetch(task)) as IServiceInfo | null;\n if (info) {\n return Result.ok(info);\n }\n\n return Result.fail(new TaskServiceInfoError());\n } catch (ex) {\n console.log(\"Service fetch error.\");\n console.error(ex);\n return Result.fail(new TaskServiceInfoError());\n }\n },\n abort: async <\n T extends TaskService.TaskInput = TaskService.TaskInput,\n O extends TaskService.GenericOutput = TaskService.GenericOutput\n >(\n params: ITaskAbortParams\n ): Promise<Result<TaskService.Task<T, O>, BaseError<any>>> => {\n const task = await container.resolve(TasksCrud).getTask<T, O>(params.id);\n if (!task) {\n return Result.fail(new TaskNotFoundError());\n }\n\n const definition = container.resolve(TasksCrud).getDefinition<T, O>(task.definitionId);\n if (!definition) {\n return Result.fail(new TaskDefinitionNotFoundError(task.definitionId));\n }\n /**\n * We should only be able to abort a task which is pending or running\n */\n if (\n [TaskDataStatus.PENDING, TaskDataStatus.RUNNING].includes(task.taskStatus) === false\n ) {\n return Result.fail(\n new TaskAbortError({\n id: params.id,\n status: task.taskStatus\n })\n );\n }\n let taskLog: ITaskLog | null = null;\n try {\n taskLog = await container.resolve(TasksCrud).getLatestLog(task.id);\n } catch {}\n if (!taskLog) {\n taskLog = await container.resolve(TasksCrud).createLog(task, {\n iteration: 1,\n executionName: task.executionName\n });\n }\n try {\n const updatedTask = await container.resolve(TasksCrud).updateTask<T, O>(task.id, {\n taskStatus: TaskDataStatus.ABORTED\n });\n await container.resolve(TasksCrud).updateLog(taskLog.id, {\n items: taskLog.items.concat([\n {\n message: params.message || \"Task aborted.\",\n type: TaskLogItemType.INFO,\n createdOn: new Date().toISOString()\n }\n ])\n });\n /**\n * TODO: determine when to kick off the onAbort hook\n */\n if (definition.onAbort) {\n await definition.onAbort({\n task: updatedTask,\n definition\n });\n }\n\n return Result.ok(updatedTask);\n } catch (ex) {\n throw new WebinyError(`Could not abort the task!`, \"TASK_ABORT_ERROR\", {\n id: params.id,\n message: ex.message\n });\n }\n }\n };\n};\n"],"names":["MAX_DELAY_DAYS","MAX_DELAY_SECONDS","validateDelay","input","delay","Number","WebinyError","createServiceCrud","container","params","service","createService","id","inputValues","name","parent","definition","TasksCrud","task","ex","console","result","updatedTask","Result","NotFoundError","info","TaskServiceInfoError","TaskNotFoundError","TaskDefinitionNotFoundError","TaskDataStatus","TaskAbortError","taskLog","TaskLogItemType","Date"],"mappings":"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"}
@@ -17,7 +17,8 @@ declare class RunnableTaskDecoratorImpl implements TaskDefinition.Interface {
17
17
  get maxIterations(): number;
18
18
  get selfCleanup(): import("@webiny/api-core/features/task/TaskDefinition/abstractions").ISelfCleanup | undefined;
19
19
  get createInputValidation(): ((params: import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskCreateInputValidationParams) => import("@webiny/api/types").GenericRecord<PropertyKey, import("zod").ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>> | import("zod").ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>) | undefined;
20
- get run(): (params: import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskRunParams<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>) => Promise<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskResult<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>>;
20
+ get handler(): import("@webiny/di").Constructor<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskHandler<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>> | undefined;
21
+ get run(): ((params: import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskRunParams<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>) => Promise<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskResult<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>>) | undefined;
21
22
  get onBeforeTrigger(): ((params: import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskBeforeTriggerParams<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput>) => Promise<void>) | undefined;
22
23
  get onDone(): ((params: import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskLifecycleHook<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>) => Promise<void>) | undefined;
23
24
  get onError(): ((params: import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskLifecycleHook<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>) => Promise<void>) | undefined;
@@ -31,8 +31,11 @@ class RunnableTaskDecoratorImpl {
31
31
  get createInputValidation() {
32
32
  return this.decoratee.createInputValidation;
33
33
  }
34
+ get handler() {
35
+ return this.decoratee.handler;
36
+ }
34
37
  get run() {
35
- return this.decoratee.run.bind(this.decoratee);
38
+ return this.decoratee.run?.bind(this.decoratee);
36
39
  }
37
40
  get onBeforeTrigger() {
38
41
  return this.decoratee.onBeforeTrigger?.bind(this.decoratee);
@@ -50,11 +53,7 @@ class RunnableTaskDecoratorImpl {
50
53
  return this.decoratee.onMaxIterations?.bind(this.decoratee);
51
54
  }
52
55
  validate() {
53
- if (camelCase(this.decoratee.id) !== this.decoratee.id) {
54
- const message = `Task ID "${this.decoratee.id}" is invalid. It must be in camelCase format, for example: "myCustomTask".`;
55
- console.log(message);
56
- throw new error(message);
57
- }
56
+ if (camelCase(this.decoratee.id) !== this.decoratee.id) throw new error(`Task ID "${this.decoratee.id}" is invalid. It must be in camelCase format, for example: "myCustomTask".`);
58
57
  }
59
58
  getTask() {
60
59
  return this;
@@ -1 +1 @@
1
- {"version":3,"file":"api/decorators/RunnableTaskDecorator.js","sources":["../../../src/api/decorators/RunnableTaskDecorator.ts"],"sourcesContent":["import camelCase from \"lodash/camelCase.js\";\nimport WebinyError from \"@webiny/error\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport type { ITaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\n\nconst DEFAULT_MAX_ITERATIONS = 50;\n\n/**\n * RunnableTaskDecorator adds runtime behavior to TaskDefinition:\n * - Applies default values (maxIterations, isPrivate, databaseLogs, fields)\n * - Validates task ID (must be camelCase)\n * - Provides field management methods\n */\nclass RunnableTaskDecoratorImpl implements TaskDefinition.Interface {\n constructor(private decoratee: TaskDefinition.Interface) {\n this.validate();\n }\n\n // Delegate simple properties\n get id() {\n return this.decoratee.id;\n }\n\n get title() {\n return this.decoratee.title;\n }\n\n get description() {\n return this.decoratee.description;\n }\n\n // Apply default values\n get isPrivate() {\n return this.decoratee.isPrivate || false;\n }\n\n get databaseLogs() {\n return this.decoratee.databaseLogs || false;\n }\n\n get maxIterations() {\n return this.decoratee.maxIterations || DEFAULT_MAX_ITERATIONS;\n }\n\n get selfCleanup() {\n return this.decoratee.selfCleanup;\n }\n\n get createInputValidation() {\n return this.decoratee.createInputValidation;\n }\n\n // Delegate lifecycle methods (bind to preserve context)\n get run() {\n return this.decoratee.run.bind(this.decoratee);\n }\n\n get onBeforeTrigger() {\n return this.decoratee.onBeforeTrigger?.bind(this.decoratee);\n }\n\n get onDone() {\n return this.decoratee.onDone?.bind(this.decoratee);\n }\n\n get onError() {\n return this.decoratee.onError?.bind(this.decoratee);\n }\n\n get onAbort() {\n return this.decoratee.onAbort?.bind(this.decoratee);\n }\n\n get onMaxIterations() {\n return this.decoratee.onMaxIterations?.bind(this.decoratee);\n }\n\n // Validation logic\n private validate(): void {\n if (camelCase(this.decoratee.id) !== this.decoratee.id) {\n const message = `Task ID \"${this.decoratee.id}\" is invalid. It must be in camelCase format, for example: \"myCustomTask\".`;\n console.log(message);\n throw new WebinyError(message);\n }\n }\n\n // Method to get the underlying task (for compatibility with existing code)\n public getTask(): ITaskDefinition {\n return this;\n }\n}\n\nexport const RunnableTaskDecorator = TaskDefinition.createDecorator({\n decorator: RunnableTaskDecoratorImpl,\n dependencies: []\n});\n"],"names":["DEFAULT_MAX_ITERATIONS","RunnableTaskDecoratorImpl","decoratee","camelCase","message","console","WebinyError","RunnableTaskDecorator","TaskDefinition"],"mappings":";;;AAKA,MAAMA,yBAAyB;AAQ/B,MAAMC;IACF,YAAoBC,SAAmC,CAAE;aAArCA,SAAS,GAATA;QAChB,IAAI,CAAC,QAAQ;IACjB;IAGA,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE;IAC5B;IAEA,IAAI,QAAQ;QACR,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK;IAC/B;IAEA,IAAI,cAAc;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW;IACrC;IAGA,IAAI,YAAY;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,IAAI;IACvC;IAEA,IAAI,eAAe;QACf,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,IAAI;IAC1C;IAEA,IAAI,gBAAgB;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,aAAa,IAAIF;IAC3C;IAEA,IAAI,cAAc;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW;IACrC;IAEA,IAAI,wBAAwB;QACxB,OAAO,IAAI,CAAC,SAAS,CAAC,qBAAqB;IAC/C;IAGA,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS;IACjD;IAEA,IAAI,kBAAkB;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,IAAI,CAAC,SAAS;IAC9D;IAEA,IAAI,SAAS;QACT,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,SAAS;IACrD;IAEA,IAAI,UAAU;QACV,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,IAAI,CAAC,SAAS;IACtD;IAEA,IAAI,UAAU;QACV,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,IAAI,CAAC,SAAS;IACtD;IAEA,IAAI,kBAAkB;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,IAAI,CAAC,SAAS;IAC9D;IAGQ,WAAiB;QACrB,IAAIG,UAAU,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE;YACpD,MAAMC,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,0EAA0E,CAAC;YACzHC,QAAQ,GAAG,CAACD;YACZ,MAAM,IAAIE,MAAYF;QAC1B;IACJ;IAGO,UAA2B;QAC9B,OAAO,IAAI;IACf;AACJ;AAEO,MAAMG,wBAAwBC,eAAe,eAAe,CAAC;IAChE,WAAWP;IACX,cAAc,EAAE;AACpB"}
1
+ {"version":3,"file":"api/decorators/RunnableTaskDecorator.js","sources":["../../../src/api/decorators/RunnableTaskDecorator.ts"],"sourcesContent":["import camelCase from \"lodash/camelCase.js\";\nimport WebinyError from \"@webiny/error\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport type { ITaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\n\nconst DEFAULT_MAX_ITERATIONS = 50;\n\n/**\n * RunnableTaskDecorator adds runtime behavior to TaskDefinition:\n * - Applies default values (maxIterations, isPrivate, databaseLogs, fields)\n * - Validates task ID (must be camelCase)\n * - Provides field management methods\n */\nclass RunnableTaskDecoratorImpl implements TaskDefinition.Interface {\n constructor(private decoratee: TaskDefinition.Interface) {\n this.validate();\n }\n\n // Delegate simple properties\n get id() {\n return this.decoratee.id;\n }\n\n get title() {\n return this.decoratee.title;\n }\n\n get description() {\n return this.decoratee.description;\n }\n\n // Apply default values\n get isPrivate() {\n return this.decoratee.isPrivate || false;\n }\n\n get databaseLogs() {\n return this.decoratee.databaseLogs || false;\n }\n\n get maxIterations() {\n return this.decoratee.maxIterations || DEFAULT_MAX_ITERATIONS;\n }\n\n get selfCleanup() {\n return this.decoratee.selfCleanup;\n }\n\n get createInputValidation() {\n return this.decoratee.createInputValidation;\n }\n\n // A definition that delegates to a `handler` class has no `run` of its own — the handler\n // supplies it, and GetTaskDefinitionUseCase merges the two halves after this decorator runs.\n get handler() {\n return this.decoratee.handler;\n }\n\n // Delegate lifecycle methods (bind to preserve context)\n get run() {\n return this.decoratee.run?.bind(this.decoratee);\n }\n\n get onBeforeTrigger() {\n return this.decoratee.onBeforeTrigger?.bind(this.decoratee);\n }\n\n get onDone() {\n return this.decoratee.onDone?.bind(this.decoratee);\n }\n\n get onError() {\n return this.decoratee.onError?.bind(this.decoratee);\n }\n\n get onAbort() {\n return this.decoratee.onAbort?.bind(this.decoratee);\n }\n\n get onMaxIterations() {\n return this.decoratee.onMaxIterations?.bind(this.decoratee);\n }\n\n // Validation logic\n private validate(): void {\n if (camelCase(this.decoratee.id) !== this.decoratee.id) {\n throw new WebinyError(\n `Task ID \"${this.decoratee.id}\" is invalid. It must be in camelCase format, for example: \"myCustomTask\".`\n );\n }\n }\n\n // Method to get the underlying task (for compatibility with existing code)\n public getTask(): ITaskDefinition {\n return this;\n }\n}\n\nexport const RunnableTaskDecorator = TaskDefinition.createDecorator({\n decorator: RunnableTaskDecoratorImpl,\n dependencies: []\n});\n"],"names":["DEFAULT_MAX_ITERATIONS","RunnableTaskDecoratorImpl","decoratee","camelCase","WebinyError","RunnableTaskDecorator","TaskDefinition"],"mappings":";;;AAKA,MAAMA,yBAAyB;AAQ/B,MAAMC;IACF,YAAoBC,SAAmC,CAAE;aAArCA,SAAS,GAATA;QAChB,IAAI,CAAC,QAAQ;IACjB;IAGA,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE;IAC5B;IAEA,IAAI,QAAQ;QACR,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK;IAC/B;IAEA,IAAI,cAAc;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW;IACrC;IAGA,IAAI,YAAY;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,IAAI;IACvC;IAEA,IAAI,eAAe;QACf,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,IAAI;IAC1C;IAEA,IAAI,gBAAgB;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,aAAa,IAAIF;IAC3C;IAEA,IAAI,cAAc;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW;IACrC;IAEA,IAAI,wBAAwB;QACxB,OAAO,IAAI,CAAC,SAAS,CAAC,qBAAqB;IAC/C;IAIA,IAAI,UAAU;QACV,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO;IACjC;IAGA,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,SAAS;IAClD;IAEA,IAAI,kBAAkB;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,IAAI,CAAC,SAAS;IAC9D;IAEA,IAAI,SAAS;QACT,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,SAAS;IACrD;IAEA,IAAI,UAAU;QACV,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,IAAI,CAAC,SAAS;IACtD;IAEA,IAAI,UAAU;QACV,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,IAAI,CAAC,SAAS;IACtD;IAEA,IAAI,kBAAkB;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,IAAI,CAAC,SAAS;IAC9D;IAGQ,WAAiB;QACrB,IAAIG,UAAU,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,EAClD,MAAM,IAAIC,MACN,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,0EAA0E,CAAC;IAGrH;IAGO,UAA2B;QAC9B,OAAO,IAAI;IACf;AACJ;AAEO,MAAMC,wBAAwBC,eAAe,eAAe,CAAC;IAChE,WAAWL;IACX,cAAc,EAAE;AACpB"}
@@ -1,12 +1,15 @@
1
1
  import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
2
+ import { Logger } from "@webiny/api-core/features/logger/index.js";
2
3
  import { CleanupTaskSubtreeUseCase } from "../../api/features/CleanupTaskSubtree/index.js";
3
4
  type LifecycleHook = TaskDefinition.Interface["onDone"];
4
5
  type HookParams = Parameters<NonNullable<LifecycleHook>>[0];
5
6
  export declare class SelfCleaningTaskDecoratorImpl implements TaskDefinition.Interface {
6
7
  private readonly cleanupTaskSubtree;
8
+ private readonly logger;
7
9
  private decoratee;
8
10
  private readonly events;
9
- constructor(cleanupTaskSubtree: CleanupTaskSubtreeUseCase.Interface, decoratee: TaskDefinition.Interface);
11
+ constructor(cleanupTaskSubtree: CleanupTaskSubtreeUseCase.Interface, logger: Logger.Interface, decoratee: TaskDefinition.Interface);
12
+ get handler(): import("@webiny/di").Constructor<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskHandler<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>> | undefined;
10
13
  get id(): string;
11
14
  get title(): string;
12
15
  get description(): string | undefined;
@@ -14,7 +17,7 @@ export declare class SelfCleaningTaskDecoratorImpl implements TaskDefinition.Int
14
17
  get maxIterations(): number | undefined;
15
18
  get selfCleanup(): import("@webiny/api-core/features/task/TaskDefinition/abstractions").ISelfCleanup | undefined;
16
19
  get createInputValidation(): ((params: import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskCreateInputValidationParams) => import("@webiny/api/types").GenericRecord<PropertyKey, import("zod").ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>> | import("zod").ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>) | undefined;
17
- get run(): (params: import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskRunParams<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>) => Promise<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskResult<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>>;
20
+ get run(): ((params: import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskRunParams<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>) => Promise<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskResult<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>>) | undefined;
18
21
  get onBeforeTrigger(): ((params: import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskBeforeTriggerParams<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput>) => Promise<void>) | undefined;
19
22
  get onMaxIterations(): ((params: import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskLifecycleHook<import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskInput, import("@webiny/api-core/features/task/TaskDefinition/abstractions").ITaskOutput>) => Promise<void>) | undefined;
20
23
  get databaseLogs(): boolean | undefined;
@@ -1,13 +1,18 @@
1
1
  import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
2
+ import { Logger } from "@webiny/api-core/features/logger/index.js";
2
3
  import { normalizeSelfCleanup } from "../utils/normalizeSelfCleanup.js";
3
4
  import { CleanupTaskSubtreeUseCase } from "../features/CleanupTaskSubtree/index.js";
4
5
  import { getErrorProperties } from "../utils/getErrorProperties.js";
5
6
  class SelfCleaningTaskDecoratorImpl {
6
- constructor(cleanupTaskSubtree, decoratee){
7
+ constructor(cleanupTaskSubtree, logger, decoratee){
7
8
  this.cleanupTaskSubtree = cleanupTaskSubtree;
9
+ this.logger = logger;
8
10
  this.decoratee = decoratee;
9
11
  this.events = normalizeSelfCleanup(decoratee.selfCleanup);
10
12
  }
13
+ get handler() {
14
+ return this.decoratee.handler;
15
+ }
11
16
  get id() {
12
17
  return this.decoratee.id;
13
18
  }
@@ -30,7 +35,7 @@ class SelfCleaningTaskDecoratorImpl {
30
35
  return this.decoratee.createInputValidation;
31
36
  }
32
37
  get run() {
33
- return this.decoratee.run.bind(this.decoratee);
38
+ return this.decoratee.run?.bind(this.decoratee);
34
39
  }
35
40
  get onBeforeTrigger() {
36
41
  return this.decoratee.onBeforeTrigger?.bind(this.decoratee);
@@ -68,15 +73,19 @@ class SelfCleaningTaskDecoratorImpl {
68
73
  try {
69
74
  await hook.call(this.decoratee, params);
70
75
  } catch (ex) {
71
- console.error(`Error executing ${name} hook for task "${params.task.id}".`);
72
- console.log(getErrorProperties(ex));
76
+ this.logger.error({
77
+ error: getErrorProperties(ex),
78
+ taskId: params.task.id,
79
+ hook: name
80
+ }, "Error executing task lifecycle hook.");
73
81
  }
74
82
  }
75
83
  }
76
84
  const SelfCleaningTaskDecorator = TaskDefinition.createDecorator({
77
85
  decorator: SelfCleaningTaskDecoratorImpl,
78
86
  dependencies: [
79
- CleanupTaskSubtreeUseCase
87
+ CleanupTaskSubtreeUseCase,
88
+ Logger
80
89
  ]
81
90
  });
82
91
  export { SelfCleaningTaskDecorator, SelfCleaningTaskDecoratorImpl };
@@ -1 +1 @@
1
- {"version":3,"file":"api/decorators/SelfCleaningTaskDecorator.js","sources":["../../../src/api/decorators/SelfCleaningTaskDecorator.ts"],"sourcesContent":["import { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport type { ISelfCleanupEvent } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { normalizeSelfCleanup } from \"~/api/utils/normalizeSelfCleanup.js\";\nimport { CleanupTaskSubtreeUseCase } from \"~/api/features/CleanupTaskSubtree/index.js\";\nimport { getErrorProperties } from \"~/api/utils/getErrorProperties.js\";\n\ntype LifecycleHook = TaskDefinition.Interface[\"onDone\"];\ntype HookParams = Parameters<NonNullable<LifecycleHook>>[0];\n\nexport class SelfCleaningTaskDecoratorImpl implements TaskDefinition.Interface {\n private readonly events: ReadonlySet<ISelfCleanupEvent>;\n\n public constructor(\n private readonly cleanupTaskSubtree: CleanupTaskSubtreeUseCase.Interface,\n private decoratee: TaskDefinition.Interface\n ) {\n this.events = normalizeSelfCleanup(decoratee.selfCleanup);\n }\n\n // Pass-through properties.\n get id() {\n return this.decoratee.id;\n }\n get title() {\n return this.decoratee.title;\n }\n get description() {\n return this.decoratee.description;\n }\n get isPrivate() {\n return this.decoratee.isPrivate;\n }\n get maxIterations() {\n return this.decoratee.maxIterations;\n }\n get selfCleanup() {\n return this.decoratee.selfCleanup;\n }\n get createInputValidation() {\n return this.decoratee.createInputValidation;\n }\n get run() {\n return this.decoratee.run.bind(this.decoratee);\n }\n get onBeforeTrigger() {\n return this.decoratee.onBeforeTrigger?.bind(this.decoratee);\n }\n get onMaxIterations() {\n return this.decoratee.onMaxIterations?.bind(this.decoratee);\n }\n\n // databaseLogs override — any non-empty event set forces false.\n get databaseLogs() {\n if (this.events.size > 0) {\n return false;\n }\n return this.decoratee.databaseLogs;\n }\n\n // Always-defined lifecycle hooks. Each runs the user's hook first, then\n // triggers cleanup if the matching event is in the set.\n get onDone() {\n return async (params: HookParams) => {\n await this.safeCall(this.decoratee.onDone, params, \"onDone\");\n if (this.events.has(\"onSuccess\")) {\n await this.runCleanup(params);\n }\n };\n }\n\n get onError() {\n return async (params: HookParams) => {\n await this.safeCall(this.decoratee.onError, params, \"onError\");\n if (this.events.has(\"onError\")) {\n await this.runCleanup(params);\n }\n };\n }\n\n get onAbort() {\n return async (params: HookParams) => {\n await this.safeCall(this.decoratee.onAbort, params, \"onAbort\");\n if (this.events.has(\"onAbort\")) {\n await this.runCleanup(params);\n }\n };\n }\n\n private async runCleanup(params: HookParams): Promise<void> {\n await this.cleanupTaskSubtree.execute(params.task.id);\n }\n\n private async safeCall(\n hook: LifecycleHook | undefined,\n params: HookParams,\n name: string\n ): Promise<void> {\n if (!hook) {\n return;\n }\n try {\n await hook.call(this.decoratee, params);\n } catch (ex) {\n console.error(`Error executing ${name} hook for task \"${params.task.id}\".`);\n console.log(getErrorProperties(ex));\n }\n }\n}\n\nexport const SelfCleaningTaskDecorator = TaskDefinition.createDecorator({\n decorator: SelfCleaningTaskDecoratorImpl,\n dependencies: [CleanupTaskSubtreeUseCase]\n});\n"],"names":["SelfCleaningTaskDecoratorImpl","cleanupTaskSubtree","decoratee","normalizeSelfCleanup","params","hook","name","ex","console","getErrorProperties","SelfCleaningTaskDecorator","TaskDefinition","CleanupTaskSubtreeUseCase"],"mappings":";;;;AASO,MAAMA;IAGT,YACqBC,kBAAuD,EAChEC,SAAmC,CAC7C;aAFmBD,kBAAkB,GAAlBA;aACTC,SAAS,GAATA;QAER,IAAI,CAAC,MAAM,GAAGC,qBAAqBD,UAAU,WAAW;IAC5D;IAGA,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE;IAC5B;IACA,IAAI,QAAQ;QACR,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK;IAC/B;IACA,IAAI,cAAc;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW;IACrC;IACA,IAAI,YAAY;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS;IACnC;IACA,IAAI,gBAAgB;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,aAAa;IACvC;IACA,IAAI,cAAc;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW;IACrC;IACA,IAAI,wBAAwB;QACxB,OAAO,IAAI,CAAC,SAAS,CAAC,qBAAqB;IAC/C;IACA,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS;IACjD;IACA,IAAI,kBAAkB;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,IAAI,CAAC,SAAS;IAC9D;IACA,IAAI,kBAAkB;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,IAAI,CAAC,SAAS;IAC9D;IAGA,IAAI,eAAe;QACf,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,GACnB,OAAO;QAEX,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY;IACtC;IAIA,IAAI,SAAS;QACT,OAAO,OAAOE;YACV,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAEA,QAAQ;YACnD,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAChB,MAAM,IAAI,CAAC,UAAU,CAACA;QAE9B;IACJ;IAEA,IAAI,UAAU;QACV,OAAO,OAAOA;YACV,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAEA,QAAQ;YACpD,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,YAChB,MAAM,IAAI,CAAC,UAAU,CAACA;QAE9B;IACJ;IAEA,IAAI,UAAU;QACV,OAAO,OAAOA;YACV,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAEA,QAAQ;YACpD,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,YAChB,MAAM,IAAI,CAAC,UAAU,CAACA;QAE9B;IACJ;IAEA,MAAc,WAAWA,MAAkB,EAAiB;QACxD,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAACA,OAAO,IAAI,CAAC,EAAE;IACxD;IAEA,MAAc,SACVC,IAA+B,EAC/BD,MAAkB,EAClBE,IAAY,EACC;QACb,IAAI,CAACD,MACD;QAEJ,IAAI;YACA,MAAMA,KAAK,IAAI,CAAC,IAAI,CAAC,SAAS,EAAED;QACpC,EAAE,OAAOG,IAAI;YACTC,QAAQ,KAAK,CAAC,CAAC,gBAAgB,EAAEF,KAAK,gBAAgB,EAAEF,OAAO,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAC1EI,QAAQ,GAAG,CAACC,mBAAmBF;QACnC;IACJ;AACJ;AAEO,MAAMG,4BAA4BC,eAAe,eAAe,CAAC;IACpE,WAAWX;IACX,cAAc;QAACY;KAA0B;AAC7C"}
1
+ {"version":3,"file":"api/decorators/SelfCleaningTaskDecorator.js","sources":["../../../src/api/decorators/SelfCleaningTaskDecorator.ts"],"sourcesContent":["import { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { Logger } from \"@webiny/api-core/features/logger/index.js\";\nimport type { ISelfCleanupEvent } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { normalizeSelfCleanup } from \"~/api/utils/normalizeSelfCleanup.js\";\nimport { CleanupTaskSubtreeUseCase } from \"~/api/features/CleanupTaskSubtree/index.js\";\nimport { getErrorProperties } from \"~/api/utils/getErrorProperties.js\";\n\ntype LifecycleHook = TaskDefinition.Interface[\"onDone\"];\ntype HookParams = Parameters<NonNullable<LifecycleHook>>[0];\n\nexport class SelfCleaningTaskDecoratorImpl implements TaskDefinition.Interface {\n private readonly events: ReadonlySet<ISelfCleanupEvent>;\n\n public constructor(\n private readonly cleanupTaskSubtree: CleanupTaskSubtreeUseCase.Interface,\n private readonly logger: Logger.Interface,\n private decoratee: TaskDefinition.Interface\n ) {\n this.events = normalizeSelfCleanup(decoratee.selfCleanup);\n }\n\n // A definition that delegates to a `handler` class has no `run` of its own.\n get handler() {\n return this.decoratee.handler;\n }\n\n // Pass-through properties.\n get id() {\n return this.decoratee.id;\n }\n get title() {\n return this.decoratee.title;\n }\n get description() {\n return this.decoratee.description;\n }\n get isPrivate() {\n return this.decoratee.isPrivate;\n }\n get maxIterations() {\n return this.decoratee.maxIterations;\n }\n get selfCleanup() {\n return this.decoratee.selfCleanup;\n }\n get createInputValidation() {\n return this.decoratee.createInputValidation;\n }\n get run() {\n return this.decoratee.run?.bind(this.decoratee);\n }\n get onBeforeTrigger() {\n return this.decoratee.onBeforeTrigger?.bind(this.decoratee);\n }\n get onMaxIterations() {\n return this.decoratee.onMaxIterations?.bind(this.decoratee);\n }\n\n // databaseLogs override — any non-empty event set forces false.\n get databaseLogs() {\n if (this.events.size > 0) {\n return false;\n }\n return this.decoratee.databaseLogs;\n }\n\n // Always-defined lifecycle hooks. Each runs the user's hook first, then\n // triggers cleanup if the matching event is in the set.\n get onDone() {\n return async (params: HookParams) => {\n await this.safeCall(this.decoratee.onDone, params, \"onDone\");\n if (this.events.has(\"onSuccess\")) {\n await this.runCleanup(params);\n }\n };\n }\n\n get onError() {\n return async (params: HookParams) => {\n await this.safeCall(this.decoratee.onError, params, \"onError\");\n if (this.events.has(\"onError\")) {\n await this.runCleanup(params);\n }\n };\n }\n\n get onAbort() {\n return async (params: HookParams) => {\n await this.safeCall(this.decoratee.onAbort, params, \"onAbort\");\n if (this.events.has(\"onAbort\")) {\n await this.runCleanup(params);\n }\n };\n }\n\n private async runCleanup(params: HookParams): Promise<void> {\n await this.cleanupTaskSubtree.execute(params.task.id);\n }\n\n private async safeCall(\n hook: LifecycleHook | undefined,\n params: HookParams,\n name: string\n ): Promise<void> {\n if (!hook) {\n return;\n }\n try {\n await hook.call(this.decoratee, params);\n } catch (ex) {\n this.logger.error(\n { error: getErrorProperties(ex), taskId: params.task.id, hook: name },\n \"Error executing task lifecycle hook.\"\n );\n }\n }\n}\n\nexport const SelfCleaningTaskDecorator = TaskDefinition.createDecorator({\n decorator: SelfCleaningTaskDecoratorImpl,\n dependencies: [CleanupTaskSubtreeUseCase, Logger]\n});\n"],"names":["SelfCleaningTaskDecoratorImpl","cleanupTaskSubtree","logger","decoratee","normalizeSelfCleanup","params","hook","name","ex","getErrorProperties","SelfCleaningTaskDecorator","TaskDefinition","CleanupTaskSubtreeUseCase","Logger"],"mappings":";;;;;AAUO,MAAMA;IAGT,YACqBC,kBAAuD,EACvDC,MAAwB,EACjCC,SAAmC,CAC7C;aAHmBF,kBAAkB,GAAlBA;aACAC,MAAM,GAANA;aACTC,SAAS,GAATA;QAER,IAAI,CAAC,MAAM,GAAGC,qBAAqBD,UAAU,WAAW;IAC5D;IAGA,IAAI,UAAU;QACV,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO;IACjC;IAGA,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE;IAC5B;IACA,IAAI,QAAQ;QACR,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK;IAC/B;IACA,IAAI,cAAc;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW;IACrC;IACA,IAAI,YAAY;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS;IACnC;IACA,IAAI,gBAAgB;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,aAAa;IACvC;IACA,IAAI,cAAc;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW;IACrC;IACA,IAAI,wBAAwB;QACxB,OAAO,IAAI,CAAC,SAAS,CAAC,qBAAqB;IAC/C;IACA,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,SAAS;IAClD;IACA,IAAI,kBAAkB;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,IAAI,CAAC,SAAS;IAC9D;IACA,IAAI,kBAAkB;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,IAAI,CAAC,SAAS;IAC9D;IAGA,IAAI,eAAe;QACf,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,GACnB,OAAO;QAEX,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY;IACtC;IAIA,IAAI,SAAS;QACT,OAAO,OAAOE;YACV,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAEA,QAAQ;YACnD,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAChB,MAAM,IAAI,CAAC,UAAU,CAACA;QAE9B;IACJ;IAEA,IAAI,UAAU;QACV,OAAO,OAAOA;YACV,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAEA,QAAQ;YACpD,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,YAChB,MAAM,IAAI,CAAC,UAAU,CAACA;QAE9B;IACJ;IAEA,IAAI,UAAU;QACV,OAAO,OAAOA;YACV,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAEA,QAAQ;YACpD,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,YAChB,MAAM,IAAI,CAAC,UAAU,CAACA;QAE9B;IACJ;IAEA,MAAc,WAAWA,MAAkB,EAAiB;QACxD,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAACA,OAAO,IAAI,CAAC,EAAE;IACxD;IAEA,MAAc,SACVC,IAA+B,EAC/BD,MAAkB,EAClBE,IAAY,EACC;QACb,IAAI,CAACD,MACD;QAEJ,IAAI;YACA,MAAMA,KAAK,IAAI,CAAC,IAAI,CAAC,SAAS,EAAED;QACpC,EAAE,OAAOG,IAAI;YACT,IAAI,CAAC,MAAM,CAAC,KAAK,CACb;gBAAE,OAAOC,mBAAmBD;gBAAK,QAAQH,OAAO,IAAI,CAAC,EAAE;gBAAE,MAAME;YAAK,GACpE;QAER;IACJ;AACJ;AAEO,MAAMG,4BAA4BC,eAAe,eAAe,CAAC;IACpE,WAAWX;IACX,cAAc;QAACY;QAA2BC;KAAO;AACrD"}
@@ -7,6 +7,16 @@ export declare class TaskDefinitionNotFoundError extends BaseError<{
7
7
  readonly code: "BackgroundTasks/TaskDefinition/NotFoundError";
8
8
  constructor(id: string);
9
9
  }
10
+ /**
11
+ * A definition was found by id but supplies no behaviour: neither a `handler` class nor its own
12
+ * `run()`. Only reachable while definitions are migrating from one shape to the other.
13
+ */
14
+ export declare class TaskDefinitionNotRunnableError extends BaseError<{
15
+ id: string;
16
+ }> {
17
+ readonly code: "BackgroundTasks/TaskDefinition/NotRunnableError";
18
+ constructor(id: string);
19
+ }
10
20
  export declare class TaskNotFoundError extends BaseError {
11
21
  readonly code: "BackgroundTasks/Task/NotFoundError";
12
22
  constructor();
@@ -10,6 +10,16 @@ class TaskDefinitionNotFoundError extends BaseError {
10
10
  }), this.code = "BackgroundTasks/TaskDefinition/NotFoundError";
11
11
  }
12
12
  }
13
+ class TaskDefinitionNotRunnableError extends BaseError {
14
+ constructor(id){
15
+ super({
16
+ message: `Task definition "${id}" defines neither a "handler" nor a "run" method.`,
17
+ data: {
18
+ id
19
+ }
20
+ }), this.code = "BackgroundTasks/TaskDefinition/NotRunnableError";
21
+ }
22
+ }
13
23
  class TaskNotFoundError extends BaseError {
14
24
  constructor(){
15
25
  super({
@@ -96,6 +106,6 @@ class BackgroundTaskNotAuthorizedError extends BaseError {
96
106
  }), this.code = "BackgroundTasks/NotAuthorized";
97
107
  }
98
108
  }
99
- export { BackgroundTaskModelNotFoundError, BackgroundTaskNotAuthorizedError, BackgroundTaskPersistenceError, BackgroundTaskValidationError, TaskAbortError, TaskDefinitionNotFoundError, TaskLogNotFoundError, TaskNotFoundError, TaskServiceInfoError };
109
+ export { BackgroundTaskModelNotFoundError, BackgroundTaskNotAuthorizedError, BackgroundTaskPersistenceError, BackgroundTaskValidationError, TaskAbortError, TaskDefinitionNotFoundError, TaskDefinitionNotRunnableError, TaskLogNotFoundError, TaskNotFoundError, TaskServiceInfoError };
100
110
 
101
111
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api/domain/errors.js","sources":["../../../src/api/domain/errors.ts"],"sourcesContent":["import { BaseError } from \"@webiny/feature/api\";\nimport type { ZodError } from \"zod\";\nimport { parseZodError } from \"@webiny/utils\";\nimport type { ValidationIssue } from \"@webiny/utils\";\n\nexport class TaskDefinitionNotFoundError extends BaseError<{ id: string }> {\n override readonly code = \"BackgroundTasks/TaskDefinition/NotFoundError\" as const;\n\n constructor(id: string) {\n super({\n message: \"Task definition not found.\",\n data: {\n id\n }\n });\n }\n}\n\nexport class TaskNotFoundError extends BaseError {\n override readonly code = \"BackgroundTasks/Task/NotFoundError\" as const;\n\n constructor() {\n super({\n message: \"Task not found.\"\n });\n }\n}\n\nexport class TaskAbortError extends BaseError<{ id: string; status: string }> {\n override readonly code = \"BackgroundTasks/Task/Abort\" as const;\n\n constructor(data: { id: string; status: string }) {\n super({\n message: \"Cannot abort a task that is not pending or running!\",\n data\n });\n }\n}\n\nexport class TaskLogNotFoundError extends BaseError {\n override readonly code = \"BackgroundTasks/Log/NotFoundError\" as const;\n\n constructor() {\n super({\n message: \"Task log not found.\"\n });\n }\n}\n\nexport class TaskServiceInfoError extends BaseError {\n override readonly code = \"BackgroundTasks/Service/InfoUnavailable\" as const;\n\n constructor() {\n super({\n message: \"Unable to fetch service info.\"\n });\n }\n}\n\ninterface BackgroundTaskValidationErrorData {\n issues: ValidationIssue[];\n}\n\nexport class BackgroundTaskValidationError extends BaseError<BackgroundTaskValidationErrorData> {\n override readonly code = \"BackgroundTasks/ValidationError\" as const;\n\n constructor(error: string | ZodError) {\n if (typeof error === \"string\") {\n super({ message: error, data: { issues: [] } });\n } else {\n const issues = parseZodError(error);\n super({ message: \"Validation failed.\", data: { issues } });\n }\n }\n}\n\ninterface BackgroundTaskPersistenceErrorData {\n originalMessage: string;\n originalCode?: string;\n originalData?: unknown;\n}\n\nexport class BackgroundTaskPersistenceError extends BaseError<BackgroundTaskPersistenceErrorData> {\n override readonly code = \"BackgroundTasks/PersistenceError\" as const;\n\n constructor(error: Error) {\n super({ message: error.message, data: { originalMessage: error.message } });\n }\n\n static from(error: unknown): BackgroundTaskPersistenceError {\n if (error instanceof Error) {\n const instance = new BackgroundTaskPersistenceError(error);\n const data: BackgroundTaskPersistenceErrorData = {\n originalMessage: error.message,\n originalCode: (error as any).code,\n originalData: (error as any).data\n };\n (instance as any).data = data;\n instance.stack = error.stack;\n return instance;\n }\n\n return new BackgroundTaskPersistenceError(new Error(String(error)));\n }\n}\n\nexport class BackgroundTaskModelNotFoundError extends BaseError {\n override readonly code = \"BackgroundTasks/ModelNotFound\" as const;\n\n constructor(modelId: string) {\n super({ message: `Background task model \"${modelId}\" was not found.` });\n }\n}\n\nexport class BackgroundTaskNotAuthorizedError extends BaseError {\n override readonly code = \"BackgroundTasks/NotAuthorized\" as const;\n\n constructor() {\n super({ message: \"Not authorized!\" });\n }\n}\n"],"names":["TaskDefinitionNotFoundError","BaseError","id","TaskNotFoundError","TaskAbortError","data","TaskLogNotFoundError","TaskServiceInfoError","BackgroundTaskValidationError","error","issues","parseZodError","BackgroundTaskPersistenceError","Error","instance","String","BackgroundTaskModelNotFoundError","modelId","BackgroundTaskNotAuthorizedError"],"mappings":";;AAKO,MAAMA,oCAAoCC;IAG7C,YAAYC,EAAU,CAAE;QACpB,KAAK,CAAC;YACF,SAAS;YACT,MAAM;gBACFA;YACJ;QACJ,SARc,IAAI,GAAG;IASzB;AACJ;AAEO,MAAMC,0BAA0BF;IAGnC,aAAc;QACV,KAAK,CAAC;YACF,SAAS;QACb,SALc,IAAI,GAAG;IAMzB;AACJ;AAEO,MAAMG,uBAAuBH;IAGhC,YAAYI,IAAoC,CAAE;QAC9C,KAAK,CAAC;YACF,SAAS;YACTA;QACJ,SANc,IAAI,GAAG;IAOzB;AACJ;AAEO,MAAMC,6BAA6BL;IAGtC,aAAc;QACV,KAAK,CAAC;YACF,SAAS;QACb,SALc,IAAI,GAAG;IAMzB;AACJ;AAEO,MAAMM,6BAA6BN;IAGtC,aAAc;QACV,KAAK,CAAC;YACF,SAAS;QACb,SALc,IAAI,GAAG;IAMzB;AACJ;AAMO,MAAMO,sCAAsCP;IAG/C,YAAYQ,KAAwB,CAAE;QAClC,IAAI,AAAiB,YAAjB,OAAOA,OACP,KAAK,CAAC;YAAE,SAASA;YAAO,MAAM;gBAAE,QAAQ,EAAE;YAAC;QAAE,SAJnC,IAAI,GAAG;aAKd;YACH,MAAMC,SAASC,cAAcF;YAC7B,KAAK,CAAC;gBAAE,SAAS;gBAAsB,MAAM;oBAAEC;gBAAO;YAAE,SAP9C,IAAI,GAAG;QAQrB;IACJ;AACJ;AAQO,MAAME,uCAAuCX;IAGhD,YAAYQ,KAAY,CAAE;QACtB,KAAK,CAAC;YAAE,SAASA,MAAM,OAAO;YAAE,MAAM;gBAAE,iBAAiBA,MAAM,OAAO;YAAC;QAAE,SAH3D,IAAI,GAAG;IAIzB;IAEA,OAAO,KAAKA,KAAc,EAAkC;QACxD,IAAIA,iBAAiBI,OAAO;YACxB,MAAMC,WAAW,IAAIF,+BAA+BH;YACpD,MAAMJ,OAA2C;gBAC7C,iBAAiBI,MAAM,OAAO;gBAC9B,cAAeA,MAAc,IAAI;gBACjC,cAAeA,MAAc,IAAI;YACrC;YACCK,SAAiB,IAAI,GAAGT;YACzBS,SAAS,KAAK,GAAGL,MAAM,KAAK;YAC5B,OAAOK;QACX;QAEA,OAAO,IAAIF,+BAA+B,IAAIC,MAAME,OAAON;IAC/D;AACJ;AAEO,MAAMO,yCAAyCf;IAGlD,YAAYgB,OAAe,CAAE;QACzB,KAAK,CAAC;YAAE,SAAS,CAAC,uBAAuB,EAAEA,QAAQ,gBAAgB,CAAC;QAAC,SAHvD,IAAI,GAAG;IAIzB;AACJ;AAEO,MAAMC,yCAAyCjB;IAGlD,aAAc;QACV,KAAK,CAAC;YAAE,SAAS;QAAkB,SAHrB,IAAI,GAAG;IAIzB;AACJ"}
1
+ {"version":3,"file":"api/domain/errors.js","sources":["../../../src/api/domain/errors.ts"],"sourcesContent":["import { BaseError } from \"@webiny/feature/api\";\nimport type { ZodError } from \"zod\";\nimport { parseZodError } from \"@webiny/utils\";\nimport type { ValidationIssue } from \"@webiny/utils\";\n\nexport class TaskDefinitionNotFoundError extends BaseError<{ id: string }> {\n override readonly code = \"BackgroundTasks/TaskDefinition/NotFoundError\" as const;\n\n constructor(id: string) {\n super({\n message: \"Task definition not found.\",\n data: {\n id\n }\n });\n }\n}\n\n/**\n * A definition was found by id but supplies no behaviour: neither a `handler` class nor its own\n * `run()`. Only reachable while definitions are migrating from one shape to the other.\n */\nexport class TaskDefinitionNotRunnableError extends BaseError<{ id: string }> {\n override readonly code = \"BackgroundTasks/TaskDefinition/NotRunnableError\" as const;\n\n constructor(id: string) {\n super({\n message: `Task definition \"${id}\" defines neither a \"handler\" nor a \"run\" method.`,\n data: {\n id\n }\n });\n }\n}\n\nexport class TaskNotFoundError extends BaseError {\n override readonly code = \"BackgroundTasks/Task/NotFoundError\" as const;\n\n constructor() {\n super({\n message: \"Task not found.\"\n });\n }\n}\n\nexport class TaskAbortError extends BaseError<{ id: string; status: string }> {\n override readonly code = \"BackgroundTasks/Task/Abort\" as const;\n\n constructor(data: { id: string; status: string }) {\n super({\n message: \"Cannot abort a task that is not pending or running!\",\n data\n });\n }\n}\n\nexport class TaskLogNotFoundError extends BaseError {\n override readonly code = \"BackgroundTasks/Log/NotFoundError\" as const;\n\n constructor() {\n super({\n message: \"Task log not found.\"\n });\n }\n}\n\nexport class TaskServiceInfoError extends BaseError {\n override readonly code = \"BackgroundTasks/Service/InfoUnavailable\" as const;\n\n constructor() {\n super({\n message: \"Unable to fetch service info.\"\n });\n }\n}\n\ninterface BackgroundTaskValidationErrorData {\n issues: ValidationIssue[];\n}\n\nexport class BackgroundTaskValidationError extends BaseError<BackgroundTaskValidationErrorData> {\n override readonly code = \"BackgroundTasks/ValidationError\" as const;\n\n constructor(error: string | ZodError) {\n if (typeof error === \"string\") {\n super({ message: error, data: { issues: [] } });\n } else {\n const issues = parseZodError(error);\n super({ message: \"Validation failed.\", data: { issues } });\n }\n }\n}\n\ninterface BackgroundTaskPersistenceErrorData {\n originalMessage: string;\n originalCode?: string;\n originalData?: unknown;\n}\n\nexport class BackgroundTaskPersistenceError extends BaseError<BackgroundTaskPersistenceErrorData> {\n override readonly code = \"BackgroundTasks/PersistenceError\" as const;\n\n constructor(error: Error) {\n super({ message: error.message, data: { originalMessage: error.message } });\n }\n\n static from(error: unknown): BackgroundTaskPersistenceError {\n if (error instanceof Error) {\n const instance = new BackgroundTaskPersistenceError(error);\n const data: BackgroundTaskPersistenceErrorData = {\n originalMessage: error.message,\n originalCode: (error as any).code,\n originalData: (error as any).data\n };\n (instance as any).data = data;\n instance.stack = error.stack;\n return instance;\n }\n\n return new BackgroundTaskPersistenceError(new Error(String(error)));\n }\n}\n\nexport class BackgroundTaskModelNotFoundError extends BaseError {\n override readonly code = \"BackgroundTasks/ModelNotFound\" as const;\n\n constructor(modelId: string) {\n super({ message: `Background task model \"${modelId}\" was not found.` });\n }\n}\n\nexport class BackgroundTaskNotAuthorizedError extends BaseError {\n override readonly code = \"BackgroundTasks/NotAuthorized\" as const;\n\n constructor() {\n super({ message: \"Not authorized!\" });\n }\n}\n"],"names":["TaskDefinitionNotFoundError","BaseError","id","TaskDefinitionNotRunnableError","TaskNotFoundError","TaskAbortError","data","TaskLogNotFoundError","TaskServiceInfoError","BackgroundTaskValidationError","error","issues","parseZodError","BackgroundTaskPersistenceError","Error","instance","String","BackgroundTaskModelNotFoundError","modelId","BackgroundTaskNotAuthorizedError"],"mappings":";;AAKO,MAAMA,oCAAoCC;IAG7C,YAAYC,EAAU,CAAE;QACpB,KAAK,CAAC;YACF,SAAS;YACT,MAAM;gBACFA;YACJ;QACJ,SARc,IAAI,GAAG;IASzB;AACJ;AAMO,MAAMC,uCAAuCF;IAGhD,YAAYC,EAAU,CAAE;QACpB,KAAK,CAAC;YACF,SAAS,CAAC,iBAAiB,EAAEA,GAAG,iDAAiD,CAAC;YAClF,MAAM;gBACFA;YACJ;QACJ,SARc,IAAI,GAAG;IASzB;AACJ;AAEO,MAAME,0BAA0BH;IAGnC,aAAc;QACV,KAAK,CAAC;YACF,SAAS;QACb,SALc,IAAI,GAAG;IAMzB;AACJ;AAEO,MAAMI,uBAAuBJ;IAGhC,YAAYK,IAAoC,CAAE;QAC9C,KAAK,CAAC;YACF,SAAS;YACTA;QACJ,SANc,IAAI,GAAG;IAOzB;AACJ;AAEO,MAAMC,6BAA6BN;IAGtC,aAAc;QACV,KAAK,CAAC;YACF,SAAS;QACb,SALc,IAAI,GAAG;IAMzB;AACJ;AAEO,MAAMO,6BAA6BP;IAGtC,aAAc;QACV,KAAK,CAAC;YACF,SAAS;QACb,SALc,IAAI,GAAG;IAMzB;AACJ;AAMO,MAAMQ,sCAAsCR;IAG/C,YAAYS,KAAwB,CAAE;QAClC,IAAI,AAAiB,YAAjB,OAAOA,OACP,KAAK,CAAC;YAAE,SAASA;YAAO,MAAM;gBAAE,QAAQ,EAAE;YAAC;QAAE,SAJnC,IAAI,GAAG;aAKd;YACH,MAAMC,SAASC,cAAcF;YAC7B,KAAK,CAAC;gBAAE,SAAS;gBAAsB,MAAM;oBAAEC;gBAAO;YAAE,SAP9C,IAAI,GAAG;QAQrB;IACJ;AACJ;AAQO,MAAME,uCAAuCZ;IAGhD,YAAYS,KAAY,CAAE;QACtB,KAAK,CAAC;YAAE,SAASA,MAAM,OAAO;YAAE,MAAM;gBAAE,iBAAiBA,MAAM,OAAO;YAAC;QAAE,SAH3D,IAAI,GAAG;IAIzB;IAEA,OAAO,KAAKA,KAAc,EAAkC;QACxD,IAAIA,iBAAiBI,OAAO;YACxB,MAAMC,WAAW,IAAIF,+BAA+BH;YACpD,MAAMJ,OAA2C;gBAC7C,iBAAiBI,MAAM,OAAO;gBAC9B,cAAeA,MAAc,IAAI;gBACjC,cAAeA,MAAc,IAAI;YACrC;YACCK,SAAiB,IAAI,GAAGT;YACzBS,SAAS,KAAK,GAAGL,MAAM,KAAK;YAC5B,OAAOK;QACX;QAEA,OAAO,IAAIF,+BAA+B,IAAIC,MAAME,OAAON;IAC/D;AACJ;AAEO,MAAMO,yCAAyChB;IAGlD,YAAYiB,OAAe,CAAE;QACzB,KAAK,CAAC;YAAE,SAAS,CAAC,uBAAuB,EAAEA,QAAQ,gBAAgB,CAAC;QAAC,SAHvD,IAAI,GAAG;IAIzB;AACJ;AAEO,MAAMC,yCAAyClB;IAGlD,aAAc;QACV,KAAK,CAAC;YAAE,SAAS;QAAkB,SAHrB,IAAI,GAAG;IAIzB;AACJ"}
@@ -1,12 +1,15 @@
1
1
  import { Result } from "@webiny/feature/api";
2
2
  import { GetTaskDefinitionUseCase as UseCaseAbstraction } from "./abstractions.js";
3
3
  import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
4
- declare class GetTaskDefinitionUseCaseImpl implements UseCaseAbstraction.Interface {
4
+ import { TaskHandlerResolver } from "../../../api/features/TaskHandlerResolver/index.js";
5
+ import { Logger } from "@webiny/api-core/features/logger/index.js";
6
+ export declare class GetTaskDefinitionUseCaseImpl implements UseCaseAbstraction.Interface {
5
7
  private definitions;
6
- constructor(definitions: TaskDefinition.Interface[]);
8
+ private handlerResolver;
9
+ private logger;
10
+ constructor(definitions: TaskDefinition.Interface[], handlerResolver: TaskHandlerResolver.Interface, logger: Logger.Interface);
7
11
  execute<I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput, O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput>(id: string): Result<TaskDefinition.Runnable<I, O>, UseCaseAbstraction.Error>;
8
12
  }
9
13
  export declare const GetTaskDefinitionUseCase: typeof GetTaskDefinitionUseCaseImpl & {
10
14
  __abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").IGetTaskDefinitionUseCase>;
11
15
  };
12
- export {};
@@ -1,16 +1,75 @@
1
1
  import { Result } from "@webiny/feature/api";
2
2
  import { GetTaskDefinitionUseCase } from "./abstractions.js";
3
3
  import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
4
- import { TaskDefinitionNotFoundError } from "../../domain/errors.js";
4
+ import { TaskHandlerResolver } from "../TaskHandlerResolver/index.js";
5
+ import { Logger } from "@webiny/api-core/features/logger/index.js";
6
+ import { TaskDefinitionNotFoundError, TaskDefinitionNotRunnableError } from "../../domain/errors.js";
5
7
  class GetTaskDefinitionUseCaseImpl {
6
- constructor(definitions){
8
+ constructor(definitions, handlerResolver, logger){
7
9
  this.definitions = definitions;
10
+ this.handlerResolver = handlerResolver;
11
+ this.logger = logger;
8
12
  }
9
13
  execute(id) {
10
- for (const definition of this.definitions)if (definition.id === id) return Result.ok(definition);
14
+ for (const definition of this.definitions)if (definition.id === id) {
15
+ if (definition.handler) {
16
+ const handlerClass = definition.handler;
17
+ const handler = this.handlerResolver.resolve(handlerClass);
18
+ const runnable = toRunnable(definition, handler, this.logger);
19
+ return Result.ok(runnable);
20
+ }
21
+ if ("function" == typeof definition.run) {
22
+ const runnable = definition;
23
+ return Result.ok(runnable);
24
+ }
25
+ return Result.fail(new TaskDefinitionNotRunnableError(id));
26
+ }
11
27
  return Result.fail(new TaskDefinitionNotFoundError(id));
12
28
  }
13
29
  }
30
+ const SWALLOWED_HOOKS = new Set([
31
+ "onDone",
32
+ "onError",
33
+ "onAbort"
34
+ ]);
35
+ const toRunnable = (definition, handler, logger)=>{
36
+ const chain = (name)=>{
37
+ const own = handler[name]?.bind(handler);
38
+ const decorated = definition[name]?.bind(definition);
39
+ if (!own && !decorated) return;
40
+ return async (params)=>{
41
+ let failure;
42
+ if (own) try {
43
+ await own(params);
44
+ } catch (error) {
45
+ if (SWALLOWED_HOOKS.has(name)) logger.error({
46
+ error,
47
+ taskId: definition.id,
48
+ hook: name
49
+ }, "Error executing task lifecycle hook.");
50
+ else failure = error;
51
+ }
52
+ await decorated?.(params);
53
+ if (failure) throw failure;
54
+ };
55
+ };
56
+ return {
57
+ id: definition.id,
58
+ title: definition.title,
59
+ description: definition.description,
60
+ isPrivate: definition.isPrivate,
61
+ databaseLogs: definition.databaseLogs,
62
+ maxIterations: definition.maxIterations,
63
+ selfCleanup: definition.selfCleanup,
64
+ run: handler.run.bind(handler),
65
+ onBeforeTrigger: chain("onBeforeTrigger"),
66
+ onDone: chain("onDone"),
67
+ onError: chain("onError"),
68
+ onAbort: chain("onAbort"),
69
+ onMaxIterations: chain("onMaxIterations"),
70
+ createInputValidation: handler.createInputValidation?.bind(handler)
71
+ };
72
+ };
14
73
  const GetTaskDefinitionUseCase_GetTaskDefinitionUseCase = GetTaskDefinitionUseCase.createImplementation({
15
74
  implementation: GetTaskDefinitionUseCaseImpl,
16
75
  dependencies: [
@@ -19,9 +78,11 @@ const GetTaskDefinitionUseCase_GetTaskDefinitionUseCase = GetTaskDefinitionUseCa
19
78
  {
20
79
  multiple: true
21
80
  }
22
- ]
81
+ ],
82
+ TaskHandlerResolver,
83
+ Logger
23
84
  ]
24
85
  });
25
- export { GetTaskDefinitionUseCase_GetTaskDefinitionUseCase as GetTaskDefinitionUseCase };
86
+ export { GetTaskDefinitionUseCaseImpl, GetTaskDefinitionUseCase_GetTaskDefinitionUseCase as GetTaskDefinitionUseCase };
26
87
 
27
88
  //# sourceMappingURL=GetTaskDefinitionUseCase.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api/features/GetTaskDefinition/GetTaskDefinitionUseCase.js","sources":["../../../../src/api/features/GetTaskDefinition/GetTaskDefinitionUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { GetTaskDefinitionUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { TaskDefinitionNotFoundError } from \"~/api/domain/errors.js\";\n\nclass GetTaskDefinitionUseCaseImpl implements UseCaseAbstraction.Interface {\n public constructor(private definitions: TaskDefinition.Interface[]) {}\n\n public execute<\n I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput,\n O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput\n >(id: string): Result<TaskDefinition.Runnable<I, O>, UseCaseAbstraction.Error> {\n for (const definition of this.definitions) {\n if (definition.id === id) {\n return Result.ok(definition as TaskDefinition.Runnable<I, O>);\n }\n }\n\n return Result.fail(new TaskDefinitionNotFoundError(id));\n }\n}\n\nexport const GetTaskDefinitionUseCase = UseCaseAbstraction.createImplementation({\n implementation: GetTaskDefinitionUseCaseImpl,\n dependencies: [[TaskDefinition, { multiple: true }]]\n});\n"],"names":["GetTaskDefinitionUseCaseImpl","definitions","id","definition","Result","TaskDefinitionNotFoundError","GetTaskDefinitionUseCase","UseCaseAbstraction","TaskDefinition"],"mappings":";;;;AAKA,MAAMA;IACF,YAA2BC,WAAuC,CAAE;aAAzCA,WAAW,GAAXA;IAA0C;IAE9D,QAGLC,EAAU,EAAmE;QAC3E,KAAK,MAAMC,cAAc,IAAI,CAAC,WAAW,CACrC,IAAIA,WAAW,EAAE,KAAKD,IAClB,OAAOE,OAAO,EAAE,CAACD;QAIzB,OAAOC,OAAO,IAAI,CAAC,IAAIC,4BAA4BH;IACvD;AACJ;AAEO,MAAMI,oDAA2BC,yBAAAA,oBAAuC,CAAC;IAC5E,gBAAgBP;IAChB,cAAc;QAAC;YAACQ;YAAgB;gBAAE,UAAU;YAAK;SAAE;KAAC;AACxD"}
1
+ {"version":3,"file":"api/features/GetTaskDefinition/GetTaskDefinitionUseCase.js","sources":["../../../../src/api/features/GetTaskDefinition/GetTaskDefinitionUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport type { Constructor } from \"@webiny/di\";\nimport { GetTaskDefinitionUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { TaskHandlerResolver } from \"~/api/features/TaskHandlerResolver/index.js\";\nimport { Logger } from \"@webiny/api-core/features/logger/index.js\";\nimport {\n TaskDefinitionNotFoundError,\n TaskDefinitionNotRunnableError\n} from \"~/api/domain/errors.js\";\n\nexport class GetTaskDefinitionUseCaseImpl implements UseCaseAbstraction.Interface {\n public constructor(\n private definitions: TaskDefinition.Interface[],\n private handlerResolver: TaskHandlerResolver.Interface,\n private logger: Logger.Interface\n ) {}\n\n public execute<\n I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput,\n O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput\n >(id: string): Result<TaskDefinition.Runnable<I, O>, UseCaseAbstraction.Error> {\n for (const definition of this.definitions) {\n if (definition.id !== id) {\n continue;\n }\n\n // New shape: the definition names a handler class, built only now that we know this is\n // the task being asked for. Its dependencies are never touched for the other 23.\n if (definition.handler) {\n // The registered definition is stored under the abstraction's default generics, so\n // its handler cannot be proven assignable to the caller's narrower <I, O>. Same\n // reason the legacy branch below casts.\n const handlerClass = definition.handler as Constructor<\n TaskDefinition.Handler<I, O>\n >;\n const handler = this.handlerResolver.resolve(handlerClass);\n const runnable = toRunnable<I, O>(definition, handler, this.logger);\n\n return Result.ok(runnable);\n }\n\n // Old shape: the definition carries `run()` and the hooks itself, so it IS the handler.\n if (typeof definition.run === \"function\") {\n const runnable = definition as TaskDefinition.Runnable<I, O>;\n\n return Result.ok(runnable);\n }\n\n return Result.fail(new TaskDefinitionNotRunnableError(id));\n }\n\n return Result.fail(new TaskDefinitionNotFoundError(id));\n }\n}\n\ntype HookName = \"onBeforeTrigger\" | \"onDone\" | \"onError\" | \"onAbort\" | \"onMaxIterations\";\n\n/** Hooks a single-object definition already swallows, via SelfCleaningTaskDecorator's safeCall. */\nconst SWALLOWED_HOOKS: ReadonlySet<HookName> = new Set([\"onDone\", \"onError\", \"onAbort\"]);\n\n/**\n * Present the two halves as the single object the runner and `context.tasks.getDefinition()` expect.\n * Metadata reads come from the definition, behaviour from the handler.\n *\n * Hooks come from BOTH, in that order, because they mean different things. The handler's hook is the\n * task author's, and the definition's is whatever a decorator added: `SelfCleaningTaskDecorator`\n * supplies an `onDone` that deletes the finished task. Taking only the handler's would silently drop\n * every definition-level decorator, and taking only the definition's would drop the task's own.\n *\n * A throwing handler hook must not stop the decorator's half from running, so the decorator's half\n * runs either way. What happens to the error afterwards follows what a single-object definition\n * already does, which differs per hook:\n *\n * - `onDone`, `onError`, `onAbort` are swallowed and logged, because `SelfCleaningTaskDecorator`\n * routes them through its own `safeCall` and does exactly that;\n * - `onBeforeTrigger` and `onMaxIterations` are rethrown, because the decorator passes those\n * straight through and their callers rely on the throw. A throwing `onBeforeTrigger` aborts the\n * trigger, and a throwing `onMaxIterations` is what makes `TaskManager` answer with \"Failed to\n * execute onMaxIterations handler.\" Swallowing either would silently change behaviour for a task\n * that moved to a handler.\n *\n * TRANSITIONAL. The chaining exists only because a definition can still carry hooks. It should not:\n * a hook needs dependencies, and dependencies on a definition are what make looking one up by id\n * expensive, which is the thing this whole split is removing. The final PR moves hooks onto handlers\n * only, at which point this function takes them from the handler and the definition contributes\n * metadata alone. `SelfCleaningTaskDecorator` splits to follow: its `databaseLogs` override stays a\n * definition decorator, and its cleanup hooks become a `TaskHandler` decorator reading\n * `params.definition.selfCleanup`.\n */\nconst toRunnable = <I extends TaskDefinition.TaskInput, O extends TaskDefinition.TaskOutput>(\n definition: TaskDefinition.Interface,\n handler: TaskDefinition.Handler<I, O>,\n logger: Logger.Interface\n): TaskDefinition.Runnable<I, O> => {\n const chain = (name: HookName) => {\n const own = handler[name]?.bind(handler);\n const decorated = definition[name]?.bind(definition);\n\n if (!own && !decorated) {\n return undefined;\n }\n\n return async (params: any) => {\n let failure: unknown;\n\n if (own) {\n try {\n await own(params);\n } catch (error) {\n if (SWALLOWED_HOOKS.has(name)) {\n logger.error(\n { error, taskId: definition.id, hook: name },\n \"Error executing task lifecycle hook.\"\n );\n } else {\n failure = error;\n }\n }\n }\n\n await decorated?.(params);\n\n if (failure) {\n throw failure;\n }\n };\n };\n\n return {\n id: definition.id,\n title: definition.title,\n description: definition.description,\n isPrivate: definition.isPrivate as boolean,\n databaseLogs: definition.databaseLogs as boolean,\n maxIterations: definition.maxIterations as number,\n selfCleanup: definition.selfCleanup,\n\n run: handler.run.bind(handler),\n onBeforeTrigger: chain(\"onBeforeTrigger\"),\n onDone: chain(\"onDone\"),\n onError: chain(\"onError\"),\n onAbort: chain(\"onAbort\"),\n onMaxIterations: chain(\"onMaxIterations\"),\n createInputValidation: handler.createInputValidation?.bind(handler)\n };\n};\n\nexport const GetTaskDefinitionUseCase = UseCaseAbstraction.createImplementation({\n implementation: GetTaskDefinitionUseCaseImpl,\n dependencies: [[TaskDefinition, { multiple: true }], TaskHandlerResolver, Logger]\n});\n"],"names":["GetTaskDefinitionUseCaseImpl","definitions","handlerResolver","logger","id","definition","handlerClass","handler","runnable","toRunnable","Result","TaskDefinitionNotRunnableError","TaskDefinitionNotFoundError","SWALLOWED_HOOKS","Set","chain","name","own","decorated","params","failure","error","GetTaskDefinitionUseCase","UseCaseAbstraction","TaskDefinition","TaskHandlerResolver","Logger"],"mappings":";;;;;;AAWO,MAAMA;IACT,YACYC,WAAuC,EACvCC,eAA8C,EAC9CC,MAAwB,CAClC;aAHUF,WAAW,GAAXA;aACAC,eAAe,GAAfA;aACAC,MAAM,GAANA;IACT;IAEI,QAGLC,EAAU,EAAmE;QAC3E,KAAK,MAAMC,cAAc,IAAI,CAAC,WAAW,CACrC,IAAIA,WAAW,EAAE,KAAKD;YAMtB,IAAIC,WAAW,OAAO,EAAE;gBAIpB,MAAMC,eAAeD,WAAW,OAAO;gBAGvC,MAAME,UAAU,IAAI,CAAC,eAAe,CAAC,OAAO,CAACD;gBAC7C,MAAME,WAAWC,WAAiBJ,YAAYE,SAAS,IAAI,CAAC,MAAM;gBAElE,OAAOG,OAAO,EAAE,CAACF;YACrB;YAGA,IAAI,AAA0B,cAA1B,OAAOH,WAAW,GAAG,EAAiB;gBACtC,MAAMG,WAAWH;gBAEjB,OAAOK,OAAO,EAAE,CAACF;YACrB;YAEA,OAAOE,OAAO,IAAI,CAAC,IAAIC,+BAA+BP;;QAG1D,OAAOM,OAAO,IAAI,CAAC,IAAIE,4BAA4BR;IACvD;AACJ;AAKA,MAAMS,kBAAyC,IAAIC,IAAI;IAAC;IAAU;IAAW;CAAU;AA+BvF,MAAML,aAAa,CACfJ,YACAE,SACAJ;IAEA,MAAMY,QAAQ,CAACC;QACX,MAAMC,MAAMV,OAAO,CAACS,KAAK,EAAE,KAAKT;QAChC,MAAMW,YAAYb,UAAU,CAACW,KAAK,EAAE,KAAKX;QAEzC,IAAI,CAACY,OAAO,CAACC,WACT;QAGJ,OAAO,OAAOC;YACV,IAAIC;YAEJ,IAAIH,KACA,IAAI;gBACA,MAAMA,IAAIE;YACd,EAAE,OAAOE,OAAO;gBACZ,IAAIR,gBAAgB,GAAG,CAACG,OACpBb,OAAO,KAAK,CACR;oBAAEkB;oBAAO,QAAQhB,WAAW,EAAE;oBAAE,MAAMW;gBAAK,GAC3C;qBAGJI,UAAUC;YAElB;YAGJ,MAAMH,YAAYC;YAElB,IAAIC,SACA,MAAMA;QAEd;IACJ;IAEA,OAAO;QACH,IAAIf,WAAW,EAAE;QACjB,OAAOA,WAAW,KAAK;QACvB,aAAaA,WAAW,WAAW;QACnC,WAAWA,WAAW,SAAS;QAC/B,cAAcA,WAAW,YAAY;QACrC,eAAeA,WAAW,aAAa;QACvC,aAAaA,WAAW,WAAW;QAEnC,KAAKE,QAAQ,GAAG,CAAC,IAAI,CAACA;QACtB,iBAAiBQ,MAAM;QACvB,QAAQA,MAAM;QACd,SAASA,MAAM;QACf,SAASA,MAAM;QACf,iBAAiBA,MAAM;QACvB,uBAAuBR,QAAQ,qBAAqB,EAAE,KAAKA;IAC/D;AACJ;AAEO,MAAMe,oDAA2BC,yBAAAA,oBAAuC,CAAC;IAC5E,gBAAgBvB;IAChB,cAAc;QAAC;YAACwB;YAAgB;gBAAE,UAAU;YAAK;SAAE;QAAEC;QAAqBC;KAAO;AACrF"}
@@ -1,11 +1,12 @@
1
1
  import type { Result } from "@webiny/feature/api";
2
2
  import type { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
3
- import type { TaskDefinitionNotFoundError } from "../../../api/domain/errors.js";
3
+ import type { TaskDefinitionNotFoundError, TaskDefinitionNotRunnableError } from "../../../api/domain/errors.js";
4
4
  export interface IGetTaskDefinitionUseCase {
5
5
  execute<I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput, O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput>(id: string): Result<TaskDefinition.Runnable<I, O>, UseCaseError>;
6
6
  }
7
7
  export interface IGetTaskDefinitionUseCaseErrors {
8
8
  notFound: TaskDefinitionNotFoundError;
9
+ notRunnable: TaskDefinitionNotRunnableError;
9
10
  }
10
11
  type UseCaseError = IGetTaskDefinitionUseCaseErrors[keyof IGetTaskDefinitionUseCaseErrors];
11
12
  export declare const GetTaskDefinitionUseCase: import("@webiny/di").Abstraction<IGetTaskDefinitionUseCase>;
@@ -1 +1 @@
1
- {"version":3,"file":"api/features/GetTaskDefinition/abstractions.js","sources":["../../../../src/api/features/GetTaskDefinition/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport type { Result } from \"@webiny/feature/api\";\nimport type { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport type { TaskDefinitionNotFoundError } from \"~/api/domain/errors.js\";\n\nexport interface IGetTaskDefinitionUseCase {\n execute<\n I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput,\n O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput\n >(\n id: string\n ): Result<TaskDefinition.Runnable<I, O>, UseCaseError>;\n}\n\nexport interface IGetTaskDefinitionUseCaseErrors {\n notFound: TaskDefinitionNotFoundError;\n}\n\ntype UseCaseError = IGetTaskDefinitionUseCaseErrors[keyof IGetTaskDefinitionUseCaseErrors];\n\nexport const GetTaskDefinitionUseCase = createAbstraction<IGetTaskDefinitionUseCase>(\n \"Tasks/GetTaskDefinitionUseCase\"\n);\n\nexport namespace GetTaskDefinitionUseCase {\n export type Interface = IGetTaskDefinitionUseCase;\n\n export type Error = UseCaseError;\n export type Return<\n I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput,\n O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput\n > = Result<TaskDefinition.Runnable<I, O>, UseCaseError>;\n}\n"],"names":["GetTaskDefinitionUseCase","createAbstraction"],"mappings":";AAoBO,MAAMA,2BAA2BC,kBACpC"}
1
+ {"version":3,"file":"api/features/GetTaskDefinition/abstractions.js","sources":["../../../../src/api/features/GetTaskDefinition/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport type { Result } from \"@webiny/feature/api\";\nimport type { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport type {\n TaskDefinitionNotFoundError,\n TaskDefinitionNotRunnableError\n} from \"~/api/domain/errors.js\";\n\nexport interface IGetTaskDefinitionUseCase {\n execute<\n I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput,\n O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput\n >(\n id: string\n ): Result<TaskDefinition.Runnable<I, O>, UseCaseError>;\n}\n\nexport interface IGetTaskDefinitionUseCaseErrors {\n notFound: TaskDefinitionNotFoundError;\n notRunnable: TaskDefinitionNotRunnableError;\n}\n\ntype UseCaseError = IGetTaskDefinitionUseCaseErrors[keyof IGetTaskDefinitionUseCaseErrors];\n\nexport const GetTaskDefinitionUseCase = createAbstraction<IGetTaskDefinitionUseCase>(\n \"Tasks/GetTaskDefinitionUseCase\"\n);\n\nexport namespace GetTaskDefinitionUseCase {\n export type Interface = IGetTaskDefinitionUseCase;\n\n export type Error = UseCaseError;\n export type Return<\n I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput,\n O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput\n > = Result<TaskDefinition.Runnable<I, O>, UseCaseError>;\n}\n"],"names":["GetTaskDefinitionUseCase","createAbstraction"],"mappings":";AAwBO,MAAMA,2BAA2BC,kBACpC"}
@@ -0,0 +1,12 @@
1
+ import type { Container, Constructor } from "@webiny/di";
2
+ import type { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
3
+ import { TaskHandlerResolver as Abstraction } from "./abstractions.js";
4
+ declare class ContainerTaskHandlerResolver implements Abstraction.Interface {
5
+ private readonly container;
6
+ constructor(container: Container);
7
+ resolve<I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput, O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput>(handler: Constructor<TaskDefinition.Handler<I, O>>): TaskDefinition.Handler<I, O>;
8
+ }
9
+ export declare const TaskHandlerResolver: typeof ContainerTaskHandlerResolver & {
10
+ __abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").ITaskHandlerResolver>;
11
+ };
12
+ export {};
@@ -0,0 +1,19 @@
1
+ import { RequestContainer } from "@webiny/event-handler-core/features/events/RequestContainer.js";
2
+ import { TaskHandlerResolver } from "./abstractions.js";
3
+ class ContainerTaskHandlerResolver {
4
+ constructor(container){
5
+ this.container = container;
6
+ }
7
+ resolve(handler) {
8
+ return this.container.resolveImplementation(handler);
9
+ }
10
+ }
11
+ const TaskHandlerResolver_TaskHandlerResolver = TaskHandlerResolver.createImplementation({
12
+ implementation: ContainerTaskHandlerResolver,
13
+ dependencies: [
14
+ RequestContainer
15
+ ]
16
+ });
17
+ export { TaskHandlerResolver_TaskHandlerResolver as TaskHandlerResolver };
18
+
19
+ //# sourceMappingURL=TaskHandlerResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/TaskHandlerResolver/TaskHandlerResolver.js","sources":["../../../../src/api/features/TaskHandlerResolver/TaskHandlerResolver.ts"],"sourcesContent":["import type { Container, Constructor } from \"@webiny/di\";\nimport { RequestContainer } from \"@webiny/event-handler-core/features/events/RequestContainer.js\";\nimport type { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\nimport { TaskHandlerResolver as Abstraction } from \"./abstractions.js\";\n\nclass ContainerTaskHandlerResolver implements Abstraction.Interface {\n public constructor(private readonly container: Container) {}\n\n public resolve<\n I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput,\n O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput\n >(handler: Constructor<TaskDefinition.Handler<I, O>>): TaskDefinition.Handler<I, O> {\n // `resolveImplementation` builds the class from its own dependency metadata and runs it\n // through the normal resolution path, so decorators registered against the handler still\n // apply. It deliberately ignores registrations, which is what we want here: the definition\n // names the class directly and nothing registers handlers against an abstraction.\n return this.container.resolveImplementation(handler);\n }\n}\n\nexport const TaskHandlerResolver = Abstraction.createImplementation({\n implementation: ContainerTaskHandlerResolver,\n dependencies: [RequestContainer]\n});\n"],"names":["ContainerTaskHandlerResolver","container","handler","TaskHandlerResolver","Abstraction","RequestContainer"],"mappings":";;AAKA,MAAMA;IACF,YAAoCC,SAAoB,CAAE;aAAtBA,SAAS,GAATA;IAAuB;IAEpD,QAGLC,OAAkD,EAAgC;QAKhF,OAAO,IAAI,CAAC,SAAS,CAAC,qBAAqB,CAACA;IAChD;AACJ;AAEO,MAAMC,0CAAsBC,oBAAAA,oBAAgC,CAAC;IAChE,gBAAgBJ;IAChB,cAAc;QAACK;KAAiB;AACpC"}
@@ -0,0 +1,17 @@
1
+ import type { Constructor } from "@webiny/di";
2
+ import type { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
3
+ export interface ITaskHandlerResolver {
4
+ resolve<I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput, O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput>(handler: Constructor<TaskDefinition.Handler<I, O>>): TaskDefinition.Handler<I, O>;
5
+ }
6
+ /**
7
+ * Builds the behaviour half of a task on demand.
8
+ *
9
+ * Something has to turn `definition.handler` (a class) into an instance, and that needs the
10
+ * container. Rather than injecting the container into a use case — which is the service-locator
11
+ * pattern we keep out of DI classes — it lives behind this one narrow abstraction. Everything else
12
+ * depends on `resolve(handler)` and stays testable with a stub.
13
+ */
14
+ export declare const TaskHandlerResolver: import("@webiny/di").Abstraction<ITaskHandlerResolver>;
15
+ export declare namespace TaskHandlerResolver {
16
+ type Interface = ITaskHandlerResolver;
17
+ }
@@ -0,0 +1,5 @@
1
+ import { createAbstraction } from "@webiny/feature/api";
2
+ const TaskHandlerResolver = createAbstraction("Tasks/TaskHandlerResolver");
3
+ export { TaskHandlerResolver };
4
+
5
+ //# sourceMappingURL=abstractions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/TaskHandlerResolver/abstractions.js","sources":["../../../../src/api/features/TaskHandlerResolver/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport type { Constructor } from \"@webiny/di\";\nimport type { TaskDefinition } from \"@webiny/api-core/features/task/TaskDefinition/index.js\";\n\nexport interface ITaskHandlerResolver {\n resolve<\n I extends TaskDefinition.TaskInput = TaskDefinition.TaskInput,\n O extends TaskDefinition.TaskOutput = TaskDefinition.TaskOutput\n >(\n handler: Constructor<TaskDefinition.Handler<I, O>>\n ): TaskDefinition.Handler<I, O>;\n}\n\n/**\n * Builds the behaviour half of a task on demand.\n *\n * Something has to turn `definition.handler` (a class) into an instance, and that needs the\n * container. Rather than injecting the container into a use case — which is the service-locator\n * pattern we keep out of DI classes — it lives behind this one narrow abstraction. Everything else\n * depends on `resolve(handler)` and stays testable with a stub.\n */\nexport const TaskHandlerResolver = createAbstraction<ITaskHandlerResolver>(\n \"Tasks/TaskHandlerResolver\"\n);\n\nexport namespace TaskHandlerResolver {\n export type Interface = ITaskHandlerResolver;\n}\n"],"names":["TaskHandlerResolver","createAbstraction"],"mappings":";AAqBO,MAAMA,sBAAsBC,kBAC/B"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Must be registered on the per-request container, which is what `registerApiRequestStack` does via
3
+ * `BackgroundTasksFeature`. The resolver depends on `RequestContainer`; registered on the root it
4
+ * would capture the root container and never see per-request registrations.
5
+ */
6
+ export declare const TaskHandlerResolverFeature: {
7
+ name: string;
8
+ register(container: import("@webiny/di").Container): void;
9
+ };
@@ -0,0 +1,11 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import { TaskHandlerResolver } from "./TaskHandlerResolver.js";
3
+ const TaskHandlerResolverFeature = createFeature({
4
+ name: "TaskHandlerResolver",
5
+ register (container) {
6
+ container.register(TaskHandlerResolver);
7
+ }
8
+ });
9
+ export { TaskHandlerResolverFeature };
10
+
11
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/TaskHandlerResolver/feature.js","sources":["../../../../src/api/features/TaskHandlerResolver/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { TaskHandlerResolver } from \"./TaskHandlerResolver.js\";\n\n/**\n * Must be registered on the per-request container, which is what `registerApiRequestStack` does via\n * `BackgroundTasksFeature`. The resolver depends on `RequestContainer`; registered on the root it\n * would capture the root container and never see per-request registrations.\n */\nexport const TaskHandlerResolverFeature = createFeature({\n name: \"TaskHandlerResolver\",\n register(container) {\n container.register(TaskHandlerResolver);\n }\n});\n"],"names":["TaskHandlerResolverFeature","createFeature","container","TaskHandlerResolver"],"mappings":";;AAQO,MAAMA,6BAA6BC,cAAc;IACpD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;IACvB;AACJ"}