@webiny/api-scheduler 0.0.0-unstable.61c048f412

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 (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +11 -0
  3. package/constants.d.ts +8 -0
  4. package/constants.js +10 -0
  5. package/constants.js.map +1 -0
  6. package/context.d.ts +7 -0
  7. package/context.js +41 -0
  8. package/context.js.map +1 -0
  9. package/createEventHandler.d.ts +13 -0
  10. package/createEventHandler.js +50 -0
  11. package/createEventHandler.js.map +1 -0
  12. package/createScheduler.d.ts +6 -0
  13. package/createScheduler.js +11 -0
  14. package/createScheduler.js.map +1 -0
  15. package/domain/SchedulePrivateModel.d.ts +8 -0
  16. package/domain/SchedulePrivateModel.js +29 -0
  17. package/domain/SchedulePrivateModel.js.map +1 -0
  18. package/domain/ScheduledActionId.d.ts +8 -0
  19. package/domain/ScheduledActionId.js +9 -0
  20. package/domain/ScheduledActionId.js.map +1 -0
  21. package/domain/ScheduledActionIdWithVersion.d.ts +3 -0
  22. package/domain/ScheduledActionIdWithVersion.js +10 -0
  23. package/domain/ScheduledActionIdWithVersion.js.map +1 -0
  24. package/domain/errors.d.ts +37 -0
  25. package/domain/errors.js +63 -0
  26. package/domain/errors.js.map +1 -0
  27. package/domain/isValidDate.d.ts +6 -0
  28. package/domain/isValidDate.js +13 -0
  29. package/domain/isValidDate.js.map +1 -0
  30. package/features/CancelScheduledAction/CancelScheduledActionUseCase.d.ts +26 -0
  31. package/features/CancelScheduledAction/CancelScheduledActionUseCase.js +74 -0
  32. package/features/CancelScheduledAction/CancelScheduledActionUseCase.js.map +1 -0
  33. package/features/CancelScheduledAction/abstractions.d.ts +24 -0
  34. package/features/CancelScheduledAction/abstractions.js +13 -0
  35. package/features/CancelScheduledAction/abstractions.js.map +1 -0
  36. package/features/CancelScheduledAction/feature.d.ts +7 -0
  37. package/features/CancelScheduledAction/feature.js +17 -0
  38. package/features/CancelScheduledAction/feature.js.map +1 -0
  39. package/features/CancelScheduledAction/index.d.ts +1 -0
  40. package/features/CancelScheduledAction/index.js +3 -0
  41. package/features/CancelScheduledAction/index.js.map +1 -0
  42. package/features/ExecuteScheduledAction/ExecuteScheduledActionUseCase.d.ts +33 -0
  43. package/features/ExecuteScheduledAction/ExecuteScheduledActionUseCase.js +106 -0
  44. package/features/ExecuteScheduledAction/ExecuteScheduledActionUseCase.js.map +1 -0
  45. package/features/ExecuteScheduledAction/ScheduledActionHandlerComposite.d.ts +19 -0
  46. package/features/ExecuteScheduledAction/ScheduledActionHandlerComposite.js +32 -0
  47. package/features/ExecuteScheduledAction/ScheduledActionHandlerComposite.js.map +1 -0
  48. package/features/ExecuteScheduledAction/abstractions.d.ts +46 -0
  49. package/features/ExecuteScheduledAction/abstractions.js +41 -0
  50. package/features/ExecuteScheduledAction/abstractions.js.map +1 -0
  51. package/features/ExecuteScheduledAction/feature.d.ts +7 -0
  52. package/features/ExecuteScheduledAction/feature.js +19 -0
  53. package/features/ExecuteScheduledAction/feature.js.map +1 -0
  54. package/features/ExecuteScheduledAction/index.d.ts +1 -0
  55. package/features/ExecuteScheduledAction/index.js +3 -0
  56. package/features/ExecuteScheduledAction/index.js.map +1 -0
  57. package/features/GetScheduledAction/GetScheduledActionUseCase.d.ts +24 -0
  58. package/features/GetScheduledAction/GetScheduledActionUseCase.js +49 -0
  59. package/features/GetScheduledAction/GetScheduledActionUseCase.js.map +1 -0
  60. package/features/GetScheduledAction/abstractions.d.ts +26 -0
  61. package/features/GetScheduledAction/abstractions.js +14 -0
  62. package/features/GetScheduledAction/abstractions.js.map +1 -0
  63. package/features/GetScheduledAction/feature.d.ts +7 -0
  64. package/features/GetScheduledAction/feature.js +17 -0
  65. package/features/GetScheduledAction/feature.js.map +1 -0
  66. package/features/GetScheduledAction/index.d.ts +1 -0
  67. package/features/GetScheduledAction/index.js +3 -0
  68. package/features/GetScheduledAction/index.js.map +1 -0
  69. package/features/ListScheduledActions/ListScheduledActionsUseCase.d.ts +27 -0
  70. package/features/ListScheduledActions/ListScheduledActionsUseCase.js +77 -0
  71. package/features/ListScheduledActions/ListScheduledActionsUseCase.js.map +1 -0
  72. package/features/ListScheduledActions/abstractions.d.ts +49 -0
  73. package/features/ListScheduledActions/abstractions.js +15 -0
  74. package/features/ListScheduledActions/abstractions.js.map +1 -0
  75. package/features/ListScheduledActions/feature.d.ts +7 -0
  76. package/features/ListScheduledActions/feature.js +17 -0
  77. package/features/ListScheduledActions/feature.js.map +1 -0
  78. package/features/ListScheduledActions/index.d.ts +1 -0
  79. package/features/ListScheduledActions/index.js +3 -0
  80. package/features/ListScheduledActions/index.js.map +1 -0
  81. package/features/RunAction/RunActionUseCase.d.ts +23 -0
  82. package/features/RunAction/RunActionUseCase.js +37 -0
  83. package/features/RunAction/RunActionUseCase.js.map +1 -0
  84. package/features/RunAction/abstractions.d.ts +35 -0
  85. package/features/RunAction/abstractions.js +15 -0
  86. package/features/RunAction/abstractions.js.map +1 -0
  87. package/features/RunAction/feature.d.ts +7 -0
  88. package/features/RunAction/feature.js +17 -0
  89. package/features/RunAction/feature.js.map +1 -0
  90. package/features/RunAction/index.d.ts +1 -0
  91. package/features/RunAction/index.js +3 -0
  92. package/features/RunAction/index.js.map +1 -0
  93. package/features/ScheduleAction/ScheduleActionUseCase.d.ts +45 -0
  94. package/features/ScheduleAction/ScheduleActionUseCase.js +164 -0
  95. package/features/ScheduleAction/ScheduleActionUseCase.js.map +1 -0
  96. package/features/ScheduleAction/abstractions.d.ts +35 -0
  97. package/features/ScheduleAction/abstractions.js +13 -0
  98. package/features/ScheduleAction/abstractions.js.map +1 -0
  99. package/features/ScheduleAction/feature.d.ts +7 -0
  100. package/features/ScheduleAction/feature.js +17 -0
  101. package/features/ScheduleAction/feature.js.map +1 -0
  102. package/features/ScheduleAction/index.d.ts +1 -0
  103. package/features/ScheduleAction/index.js +3 -0
  104. package/features/ScheduleAction/index.js.map +1 -0
  105. package/features/SchedulerFeature.d.ts +8 -0
  106. package/features/SchedulerFeature.js +29 -0
  107. package/features/SchedulerFeature.js.map +1 -0
  108. package/features/SchedulerService/EventBridgeSchedulerService.d.ts +26 -0
  109. package/features/SchedulerService/EventBridgeSchedulerService.js +131 -0
  110. package/features/SchedulerService/EventBridgeSchedulerService.js.map +1 -0
  111. package/features/SchedulerService/VoidSchedulerService.d.ts +15 -0
  112. package/features/SchedulerService/VoidSchedulerService.js +31 -0
  113. package/features/SchedulerService/VoidSchedulerService.js.map +1 -0
  114. package/index.d.ts +10 -0
  115. package/index.js +13 -0
  116. package/index.js.map +1 -0
  117. package/manifest.d.ts +17 -0
  118. package/manifest.js +39 -0
  119. package/manifest.js.map +1 -0
  120. package/package.json +55 -0
  121. package/shared/abstractions.d.ts +77 -0
  122. package/shared/abstractions.js +32 -0
  123. package/shared/abstractions.js.map +1 -0
@@ -0,0 +1,77 @@
1
+ import { Result } from "@webiny/feature/api";
2
+ import { ListLatestEntriesUseCase } from "@webiny/api-headless-cms/features/contentEntry/ListEntries/abstractions.js";
3
+ import { ListScheduledActionsUseCase as UseCaseAbstraction } from "./abstractions.js";
4
+ import { ScheduledActionModel } from "../../shared/abstractions.js";
5
+ import { ScheduledActionPersistenceError } from "../../domain/errors.js";
6
+ import { CmsSortMapper, CmsWhereMapper } from "@webiny/api-headless-cms";
7
+ /**
8
+ * Lists scheduled actions with optional filtering
9
+ *
10
+ * Flow:
11
+ * 1. Build query filters based on where params (namespace, actionType, targetId, etc.)
12
+ * 2. Fetch entries from CMS storage with pagination and sorting
13
+ * 3. Transform CMS entries to IScheduledAction format
14
+ * 4. Return paginated results with metadata
15
+ */
16
+ class ListScheduledActionsUseCaseImpl {
17
+ constructor(listEntriesUseCase, model, cmsWhereMapper, cmsSortMapper) {
18
+ this.listEntriesUseCase = listEntriesUseCase;
19
+ this.model = model;
20
+ this.cmsWhereMapper = cmsWhereMapper;
21
+ this.cmsSortMapper = cmsSortMapper;
22
+ }
23
+ async execute(params) {
24
+ const {
25
+ where,
26
+ sort: sortInput,
27
+ limit,
28
+ after
29
+ } = params;
30
+ const sort = this.cmsSortMapper.map({
31
+ input: sortInput,
32
+ fields: this.model.fields
33
+ });
34
+ // List entries from CMS
35
+ const listResult = await this.listEntriesUseCase.execute(this.model, {
36
+ where: this.cmsWhereMapper.map({
37
+ input: where,
38
+ fields: this.model.fields
39
+ }),
40
+ sort,
41
+ limit,
42
+ after
43
+ });
44
+ if (listResult.isFail()) {
45
+ return Result.fail(new ScheduledActionPersistenceError(listResult.error));
46
+ }
47
+ const {
48
+ entries,
49
+ meta
50
+ } = listResult.value;
51
+
52
+ // Transform entries to IScheduledAction format
53
+ const scheduledActions = entries.map(entry => {
54
+ return {
55
+ id: entry.entryId,
56
+ title: entry.values.title,
57
+ namespace: entry.values.namespace,
58
+ actionType: entry.values.actionType,
59
+ targetId: entry.values.targetId,
60
+ scheduledBy: entry.values.scheduledBy,
61
+ scheduledFor: entry.values.scheduledFor,
62
+ payload: entry.values.payload,
63
+ error: entry.values.error
64
+ };
65
+ });
66
+ return Result.ok({
67
+ items: scheduledActions,
68
+ meta
69
+ });
70
+ }
71
+ }
72
+ export const ListScheduledActionsUseCase = UseCaseAbstraction.createImplementation({
73
+ implementation: ListScheduledActionsUseCaseImpl,
74
+ dependencies: [ListLatestEntriesUseCase, ScheduledActionModel, CmsWhereMapper, CmsSortMapper]
75
+ });
76
+
77
+ //# sourceMappingURL=ListScheduledActionsUseCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Result","ListLatestEntriesUseCase","ListScheduledActionsUseCase","UseCaseAbstraction","ScheduledActionModel","ScheduledActionPersistenceError","CmsSortMapper","CmsWhereMapper","ListScheduledActionsUseCaseImpl","constructor","listEntriesUseCase","model","cmsWhereMapper","cmsSortMapper","execute","params","where","sort","sortInput","limit","after","map","input","fields","listResult","isFail","fail","error","entries","meta","value","scheduledActions","entry","id","entryId","title","values","namespace","actionType","targetId","scheduledBy","scheduledFor","payload","ok","items","createImplementation","implementation","dependencies"],"sources":["ListScheduledActionsUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { ListLatestEntriesUseCase } from \"@webiny/api-headless-cms/features/contentEntry/ListEntries/abstractions.js\";\nimport {\n IListScheduledActionsParams,\n IListScheduledActionsResponse,\n ListScheduledActionsUseCase as UseCaseAbstraction\n} from \"./abstractions.js\";\nimport type { IScheduledAction } from \"~/shared/abstractions.js\";\nimport { ScheduledActionModel } from \"~/shared/abstractions.js\";\nimport { ScheduledActionPersistenceError } from \"~/domain/errors.js\";\nimport { CmsSortMapper, CmsWhereMapper } from \"@webiny/api-headless-cms\";\nimport type { GenericRecord } from \"@webiny/api/types.js\";\n\n/**\n * Lists scheduled actions with optional filtering\n *\n * Flow:\n * 1. Build query filters based on where params (namespace, actionType, targetId, etc.)\n * 2. Fetch entries from CMS storage with pagination and sorting\n * 3. Transform CMS entries to IScheduledAction format\n * 4. Return paginated results with metadata\n */\nclass ListScheduledActionsUseCaseImpl implements UseCaseAbstraction.Interface {\n constructor(\n private listEntriesUseCase: ListLatestEntriesUseCase.Interface,\n private model: ScheduledActionModel.Interface,\n private cmsWhereMapper: CmsWhereMapper.Interface,\n private cmsSortMapper: CmsSortMapper.Interface\n ) {}\n\n async execute<T extends GenericRecord>(\n params: IListScheduledActionsParams\n ): Promise<Result<IListScheduledActionsResponse<T>, UseCaseAbstraction.Error>> {\n const { where, sort: sortInput, limit, after } = params;\n\n const sort = this.cmsSortMapper.map({\n input: sortInput,\n fields: this.model.fields\n });\n // List entries from CMS\n const listResult = await this.listEntriesUseCase.execute<IScheduledAction<T>>(this.model, {\n where: this.cmsWhereMapper.map({\n input: where,\n fields: this.model.fields\n }),\n sort,\n limit,\n after\n });\n\n if (listResult.isFail()) {\n return Result.fail(new ScheduledActionPersistenceError(listResult.error));\n }\n\n const { entries, meta } = listResult.value;\n\n // Transform entries to IScheduledAction format\n const scheduledActions: IScheduledAction<T>[] = entries.map(entry => {\n return {\n id: entry.entryId,\n title: entry.values.title,\n namespace: entry.values.namespace,\n actionType: entry.values.actionType,\n targetId: entry.values.targetId,\n scheduledBy: entry.values.scheduledBy,\n scheduledFor: entry.values.scheduledFor,\n payload: entry.values.payload,\n error: entry.values.error\n };\n });\n\n return Result.ok({\n items: scheduledActions,\n meta\n });\n }\n}\n\nexport const ListScheduledActionsUseCase = UseCaseAbstraction.createImplementation({\n implementation: ListScheduledActionsUseCaseImpl,\n dependencies: [ListLatestEntriesUseCase, ScheduledActionModel, CmsWhereMapper, CmsSortMapper]\n});\n"],"mappings":"AAAA,SAASA,MAAM,QAAQ,qBAAqB;AAC5C,SAASC,wBAAwB,QAAQ,4EAA4E;AACrH,SAGIC,2BAA2B,IAAIC,kBAAkB;AAGrD,SAASC,oBAAoB;AAC7B,SAASC,+BAA+B;AACxC,SAASC,aAAa,EAAEC,cAAc,QAAQ,0BAA0B;AAGxE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,+BAA+B,CAAyC;EAC1EC,WAAWA,CACCC,kBAAsD,EACtDC,KAAqC,EACrCC,cAAwC,EACxCC,aAAsC,EAChD;IAAA,KAJUH,kBAAsD,GAAtDA,kBAAsD;IAAA,KACtDC,KAAqC,GAArCA,KAAqC;IAAA,KACrCC,cAAwC,GAAxCA,cAAwC;IAAA,KACxCC,aAAsC,GAAtCA,aAAsC;EAC/C;EAEH,MAAMC,OAAOA,CACTC,MAAmC,EACwC;IAC3E,MAAM;MAAEC,KAAK;MAAEC,IAAI,EAAEC,SAAS;MAAEC,KAAK;MAAEC;IAAM,CAAC,GAAGL,MAAM;IAEvD,MAAME,IAAI,GAAG,IAAI,CAACJ,aAAa,CAACQ,GAAG,CAAC;MAChCC,KAAK,EAAEJ,SAAS;MAChBK,MAAM,EAAE,IAAI,CAACZ,KAAK,CAACY;IACvB,CAAC,CAAC;IACF;IACA,MAAMC,UAAU,GAAG,MAAM,IAAI,CAACd,kBAAkB,CAACI,OAAO,CAAsB,IAAI,CAACH,KAAK,EAAE;MACtFK,KAAK,EAAE,IAAI,CAACJ,cAAc,CAACS,GAAG,CAAC;QAC3BC,KAAK,EAAEN,KAAK;QACZO,MAAM,EAAE,IAAI,CAACZ,KAAK,CAACY;MACvB,CAAC,CAAC;MACFN,IAAI;MACJE,KAAK;MACLC;IACJ,CAAC,CAAC;IAEF,IAAII,UAAU,CAACC,MAAM,CAAC,CAAC,EAAE;MACrB,OAAOzB,MAAM,CAAC0B,IAAI,CAAC,IAAIrB,+BAA+B,CAACmB,UAAU,CAACG,KAAK,CAAC,CAAC;IAC7E;IAEA,MAAM;MAAEC,OAAO;MAAEC;IAAK,CAAC,GAAGL,UAAU,CAACM,KAAK;;IAE1C;IACA,MAAMC,gBAAuC,GAAGH,OAAO,CAACP,GAAG,CAACW,KAAK,IAAI;MACjE,OAAO;QACHC,EAAE,EAAED,KAAK,CAACE,OAAO;QACjBC,KAAK,EAAEH,KAAK,CAACI,MAAM,CAACD,KAAK;QACzBE,SAAS,EAAEL,KAAK,CAACI,MAAM,CAACC,SAAS;QACjCC,UAAU,EAAEN,KAAK,CAACI,MAAM,CAACE,UAAU;QACnCC,QAAQ,EAAEP,KAAK,CAACI,MAAM,CAACG,QAAQ;QAC/BC,WAAW,EAAER,KAAK,CAACI,MAAM,CAACI,WAAW;QACrCC,YAAY,EAAET,KAAK,CAACI,MAAM,CAACK,YAAY;QACvCC,OAAO,EAAEV,KAAK,CAACI,MAAM,CAACM,OAAO;QAC7Bf,KAAK,EAAEK,KAAK,CAACI,MAAM,CAACT;MACxB,CAAC;IACL,CAAC,CAAC;IAEF,OAAO3B,MAAM,CAAC2C,EAAE,CAAC;MACbC,KAAK,EAAEb,gBAAgB;MACvBF;IACJ,CAAC,CAAC;EACN;AACJ;AAEA,OAAO,MAAM3B,2BAA2B,GAAGC,kBAAkB,CAAC0C,oBAAoB,CAAC;EAC/EC,cAAc,EAAEtC,+BAA+B;EAC/CuC,YAAY,EAAE,CAAC9C,wBAAwB,EAAEG,oBAAoB,EAAEG,cAAc,EAAED,aAAa;AAChG,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,49 @@
1
+ import { Result } from "@webiny/feature/api";
2
+ import type { IScheduledAction } from "../../shared/abstractions.js";
3
+ import { ScheduledActionPersistenceError } from "../../domain/errors.js";
4
+ import type { CmsEntryListSort, CmsEntryMeta } from "@webiny/api-headless-cms/types/index.js";
5
+ import type { GenericRecord } from "@webiny/api/types.js";
6
+ /**
7
+ * ListScheduledActionsUseCase - List scheduled actions with optional filtering
8
+ *
9
+ * Used to retrieve all scheduled actions for a namespace (e.g., all actions for Article model)
10
+ * or all actions of a specific type across namespaces.
11
+ *
12
+ * This is critical for CMS CRUD views where we need to show ALL scheduled actions
13
+ * (publish, unpublish, delete) for a specific content model.
14
+ */
15
+ export type DateISOString = `${number}-${number}-${number}T${number}:${number}:${number}.${number}Z`;
16
+ export interface IListScheduledActionsWhere {
17
+ namespace?: string;
18
+ namespace_startsWith?: string;
19
+ actionType?: string;
20
+ targetId?: string;
21
+ targetId_startsWith?: string;
22
+ scheduledBy?: string;
23
+ scheduledFor?: DateISOString;
24
+ scheduledFor_gte?: DateISOString;
25
+ scheduledFor_lte?: DateISOString;
26
+ }
27
+ export interface IListScheduledActionsParams {
28
+ where: IListScheduledActionsWhere;
29
+ sort?: CmsEntryListSort;
30
+ limit?: number;
31
+ after?: string;
32
+ }
33
+ export interface IListScheduledActionsResponse<T extends GenericRecord> {
34
+ items: IScheduledAction<T>[];
35
+ meta: CmsEntryMeta;
36
+ }
37
+ export interface IListScheduledActionsErrors {
38
+ persistence: ScheduledActionPersistenceError;
39
+ }
40
+ type ListScheduledActionsError = IListScheduledActionsErrors[keyof IListScheduledActionsErrors];
41
+ export interface IListScheduledActionsUseCase {
42
+ execute<T extends GenericRecord>(params: IListScheduledActionsParams): Promise<Result<IListScheduledActionsResponse<T>, ListScheduledActionsError>>;
43
+ }
44
+ export declare const ListScheduledActionsUseCase: import("@webiny/di").Abstraction<IListScheduledActionsUseCase>;
45
+ export declare namespace ListScheduledActionsUseCase {
46
+ type Interface = IListScheduledActionsUseCase;
47
+ type Error = ListScheduledActionsError;
48
+ }
49
+ export {};
@@ -0,0 +1,15 @@
1
+ import { createAbstraction } from "@webiny/feature/api";
2
+
3
+ /**
4
+ * ListScheduledActionsUseCase - List scheduled actions with optional filtering
5
+ *
6
+ * Used to retrieve all scheduled actions for a namespace (e.g., all actions for Article model)
7
+ * or all actions of a specific type across namespaces.
8
+ *
9
+ * This is critical for CMS CRUD views where we need to show ALL scheduled actions
10
+ * (publish, unpublish, delete) for a specific content model.
11
+ */
12
+
13
+ export const ListScheduledActionsUseCase = createAbstraction("ListScheduledActionsUseCase");
14
+
15
+ //# sourceMappingURL=abstractions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createAbstraction","ListScheduledActionsUseCase"],"sources":["abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport { Result } from \"@webiny/feature/api\";\nimport type { IScheduledAction } from \"~/shared/abstractions.js\";\nimport { ScheduledActionPersistenceError } from \"~/domain/errors.js\";\nimport type { CmsEntryListSort, CmsEntryMeta } from \"@webiny/api-headless-cms/types/index.js\";\nimport type { GenericRecord } from \"@webiny/api/types.js\";\n\n/**\n * ListScheduledActionsUseCase - List scheduled actions with optional filtering\n *\n * Used to retrieve all scheduled actions for a namespace (e.g., all actions for Article model)\n * or all actions of a specific type across namespaces.\n *\n * This is critical for CMS CRUD views where we need to show ALL scheduled actions\n * (publish, unpublish, delete) for a specific content model.\n */\n\nexport type DateISOString =\n `${number}-${number}-${number}T${number}:${number}:${number}.${number}Z`;\n\nexport interface IListScheduledActionsWhere {\n namespace?: string;\n namespace_startsWith?: string;\n actionType?: string;\n targetId?: string;\n targetId_startsWith?: string;\n scheduledBy?: string;\n scheduledFor?: DateISOString;\n scheduledFor_gte?: DateISOString;\n scheduledFor_lte?: DateISOString;\n}\n\nexport interface IListScheduledActionsParams {\n where: IListScheduledActionsWhere;\n sort?: CmsEntryListSort;\n limit?: number;\n after?: string;\n}\n\nexport interface IListScheduledActionsResponse<T extends GenericRecord> {\n items: IScheduledAction<T>[];\n meta: CmsEntryMeta;\n}\n\nexport interface IListScheduledActionsErrors {\n persistence: ScheduledActionPersistenceError;\n}\n\ntype ListScheduledActionsError = IListScheduledActionsErrors[keyof IListScheduledActionsErrors];\n\nexport interface IListScheduledActionsUseCase {\n execute<T extends GenericRecord>(\n params: IListScheduledActionsParams\n ): Promise<Result<IListScheduledActionsResponse<T>, ListScheduledActionsError>>;\n}\n\nexport const ListScheduledActionsUseCase = createAbstraction<IListScheduledActionsUseCase>(\n \"ListScheduledActionsUseCase\"\n);\n\nexport namespace ListScheduledActionsUseCase {\n export type Interface = IListScheduledActionsUseCase;\n export type Error = ListScheduledActionsError;\n}\n"],"mappings":"AAAA,SAASA,iBAAiB,QAAQ,qBAAqB;;AAOvD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAyCA,OAAO,MAAMC,2BAA2B,GAAGD,iBAAiB,CACxD,6BACJ,CAAC","ignoreList":[]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * ListScheduledActions Feature
3
+ *
4
+ * Provides the ability to list scheduled actions with optional filtering by namespace or actionType.
5
+ * Critical for CMS CRUD views showing all scheduled actions for a content model.
6
+ */
7
+ export declare const ListScheduledActionsFeature: import("@webiny/feature/api/createFeature.js").FeatureDefinition<unknown>;
@@ -0,0 +1,17 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import { ListScheduledActionsUseCase } from "./ListScheduledActionsUseCase.js";
3
+
4
+ /**
5
+ * ListScheduledActions Feature
6
+ *
7
+ * Provides the ability to list scheduled actions with optional filtering by namespace or actionType.
8
+ * Critical for CMS CRUD views showing all scheduled actions for a content model.
9
+ */
10
+ export const ListScheduledActionsFeature = createFeature({
11
+ name: "ListScheduledActions",
12
+ register(container) {
13
+ container.register(ListScheduledActionsUseCase);
14
+ }
15
+ });
16
+
17
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createFeature","ListScheduledActionsUseCase","ListScheduledActionsFeature","name","register","container"],"sources":["feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { ListScheduledActionsUseCase } from \"./ListScheduledActionsUseCase.js\";\n\n/**\n * ListScheduledActions Feature\n *\n * Provides the ability to list scheduled actions with optional filtering by namespace or actionType.\n * Critical for CMS CRUD views showing all scheduled actions for a content model.\n */\nexport const ListScheduledActionsFeature = createFeature({\n name: \"ListScheduledActions\",\n register(container) {\n container.register(ListScheduledActionsUseCase);\n }\n});\n"],"mappings":"AAAA,SAASA,aAAa,QAAQ,qBAAqB;AACnD,SAASC,2BAA2B;;AAEpC;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,2BAA2B,GAAGF,aAAa,CAAC;EACrDG,IAAI,EAAE,sBAAsB;EAC5BC,QAAQA,CAACC,SAAS,EAAE;IAChBA,SAAS,CAACD,QAAQ,CAACH,2BAA2B,CAAC;EACnD;AACJ,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export * from "./abstractions.js";
@@ -0,0 +1,3 @@
1
+ export * from "./abstractions.js";
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./abstractions.js\";\n"],"mappings":"AAAA","ignoreList":[]}
@@ -0,0 +1,23 @@
1
+ import { Result } from "@webiny/feature/api";
2
+ import { RunActionUseCase as UseCaseAbstraction } from "./abstractions.js";
3
+ import { ScheduleActionUseCase } from "../../features/ScheduleAction/abstractions.js";
4
+ import type { IScheduledAction } from "../../shared/abstractions.js";
5
+ import type { GenericRecord } from "@webiny/api/types.js";
6
+ /**
7
+ * Schedules an action for immediate execution
8
+ *
9
+ * Flow:
10
+ * 1. Calculate the closest possible execution time
11
+ * 2. Delegate to ScheduleAction use case with calculated time
12
+ *
13
+ * Note: We add a small buffer to ensure EventBridge has time to process the schedule
14
+ */
15
+ declare class RunActionUseCaseImpl implements UseCaseAbstraction.Interface {
16
+ private scheduleActionUseCase;
17
+ constructor(scheduleActionUseCase: ScheduleActionUseCase.Interface);
18
+ execute<T extends GenericRecord>(params: UseCaseAbstraction.Params<T>): Promise<Result<IScheduledAction<T>, UseCaseAbstraction.Error>>;
19
+ }
20
+ export declare const RunActionUseCase: typeof RunActionUseCaseImpl & {
21
+ __abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").IRunActionUseCase>;
22
+ };
23
+ export {};
@@ -0,0 +1,37 @@
1
+ import { Result } from "@webiny/feature/api";
2
+ import { RunActionUseCase as UseCaseAbstraction } from "./abstractions.js";
3
+ import { ScheduleActionUseCase } from "../ScheduleAction/abstractions.js";
4
+ /**
5
+ * Schedules an action for immediate execution
6
+ *
7
+ * Flow:
8
+ * 1. Calculate the closest possible execution time
9
+ * 2. Delegate to ScheduleAction use case with calculated time
10
+ *
11
+ * Note: We add a small buffer to ensure EventBridge has time to process the schedule
12
+ */
13
+ class RunActionUseCaseImpl {
14
+ constructor(scheduleActionUseCase) {
15
+ this.scheduleActionUseCase = scheduleActionUseCase;
16
+ }
17
+ async execute(params) {
18
+ // Delegate to ScheduleAction
19
+ const result = await this.scheduleActionUseCase.execute({
20
+ ...params,
21
+ title: "Unknown title",
22
+ // Calculate the soonest possible execution time.
23
+ // Add at least 90 seconds of buffer to ensure EventBridge can process the schedule.
24
+ scheduleFor: new Date(Date.now() + 90000).toISOString()
25
+ });
26
+ if (result.isFail()) {
27
+ return Result.fail(result.error);
28
+ }
29
+ return Result.ok(result.value);
30
+ }
31
+ }
32
+ export const RunActionUseCase = UseCaseAbstraction.createImplementation({
33
+ implementation: RunActionUseCaseImpl,
34
+ dependencies: [ScheduleActionUseCase]
35
+ });
36
+
37
+ //# sourceMappingURL=RunActionUseCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Result","RunActionUseCase","UseCaseAbstraction","ScheduleActionUseCase","RunActionUseCaseImpl","constructor","scheduleActionUseCase","execute","params","result","title","scheduleFor","Date","now","toISOString","isFail","fail","error","ok","value","createImplementation","implementation","dependencies"],"sources":["RunActionUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { RunActionUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport { ScheduleActionUseCase } from \"~/features/ScheduleAction/abstractions.js\";\nimport type { IScheduledAction } from \"~/shared/abstractions.js\";\nimport type { GenericRecord } from \"@webiny/api/types.js\";\n\n/**\n * Schedules an action for immediate execution\n *\n * Flow:\n * 1. Calculate the closest possible execution time\n * 2. Delegate to ScheduleAction use case with calculated time\n *\n * Note: We add a small buffer to ensure EventBridge has time to process the schedule\n */\nclass RunActionUseCaseImpl implements UseCaseAbstraction.Interface {\n constructor(private scheduleActionUseCase: ScheduleActionUseCase.Interface) {}\n\n async execute<T extends GenericRecord>(\n params: UseCaseAbstraction.Params<T>\n ): Promise<Result<IScheduledAction<T>, UseCaseAbstraction.Error>> {\n // Delegate to ScheduleAction\n const result = await this.scheduleActionUseCase.execute({\n ...params,\n title: \"Unknown title\",\n // Calculate the soonest possible execution time.\n // Add at least 90 seconds of buffer to ensure EventBridge can process the schedule.\n scheduleFor: new Date(Date.now() + 90000).toISOString()\n });\n\n if (result.isFail()) {\n return Result.fail(result.error);\n }\n\n return Result.ok(result.value);\n }\n}\n\nexport const RunActionUseCase = UseCaseAbstraction.createImplementation({\n implementation: RunActionUseCaseImpl,\n dependencies: [ScheduleActionUseCase]\n});\n"],"mappings":"AAAA,SAASA,MAAM,QAAQ,qBAAqB;AAC5C,SAASC,gBAAgB,IAAIC,kBAAkB;AAC/C,SAASC,qBAAqB;AAI9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,oBAAoB,CAAyC;EAC/DC,WAAWA,CAASC,qBAAsD,EAAE;IAAA,KAAxDA,qBAAsD,GAAtDA,qBAAsD;EAAG;EAE7E,MAAMC,OAAOA,CACTC,MAAoC,EAC0B;IAC9D;IACA,MAAMC,MAAM,GAAG,MAAM,IAAI,CAACH,qBAAqB,CAACC,OAAO,CAAC;MACpD,GAAGC,MAAM;MACTE,KAAK,EAAE,eAAe;MACtB;MACA;MACAC,WAAW,EAAE,IAAIC,IAAI,CAACA,IAAI,CAACC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAACC,WAAW,CAAC;IAC1D,CAAC,CAAC;IAEF,IAAIL,MAAM,CAACM,MAAM,CAAC,CAAC,EAAE;MACjB,OAAOf,MAAM,CAACgB,IAAI,CAACP,MAAM,CAACQ,KAAK,CAAC;IACpC;IAEA,OAAOjB,MAAM,CAACkB,EAAE,CAACT,MAAM,CAACU,KAAK,CAAC;EAClC;AACJ;AAEA,OAAO,MAAMlB,gBAAgB,GAAGC,kBAAkB,CAACkB,oBAAoB,CAAC;EACpEC,cAAc,EAAEjB,oBAAoB;EACpCkB,YAAY,EAAE,CAACnB,qBAAqB;AACxC,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,35 @@
1
+ import { Result } from "@webiny/feature/api";
2
+ import type { IScheduledAction } from "../../shared/abstractions.js";
3
+ import { InvalidScheduleDateError, ScheduledActionPersistenceError, SchedulerServiceError } from "../../domain/errors.js";
4
+ import type { GenericRecord } from "@webiny/api/types.js";
5
+ /**
6
+ * RunActionUseCase - Schedule an action for immediate execution
7
+ *
8
+ * This is a convenience use case that wraps ScheduleAction and automatically
9
+ * calculates the closest possible execution time (current time + small buffer).
10
+ *
11
+ * Use this when you want to execute an action "immediately" without having to manually
12
+ * calculate the schedule date.
13
+ */
14
+ export interface IRunActionErrors {
15
+ persistence: ScheduledActionPersistenceError;
16
+ invalidDate: InvalidScheduleDateError;
17
+ schedulerService: SchedulerServiceError;
18
+ }
19
+ type RunActionError = IRunActionErrors[keyof IRunActionErrors];
20
+ interface IRunActionParams<T extends GenericRecord> {
21
+ namespace: string;
22
+ actionType: string;
23
+ targetId: string;
24
+ payload: T;
25
+ }
26
+ export interface IRunActionUseCase {
27
+ execute<T extends GenericRecord>(params: IRunActionParams<T>): Promise<Result<IScheduledAction<T>, RunActionError>>;
28
+ }
29
+ export declare const RunActionUseCase: import("@webiny/di").Abstraction<IRunActionUseCase>;
30
+ export declare namespace RunActionUseCase {
31
+ type Interface = IRunActionUseCase;
32
+ type Params<T extends GenericRecord> = IRunActionParams<T>;
33
+ type Error = RunActionError;
34
+ }
35
+ export {};
@@ -0,0 +1,15 @@
1
+ import { createAbstraction } from "@webiny/feature/api";
2
+
3
+ /**
4
+ * RunActionUseCase - Schedule an action for immediate execution
5
+ *
6
+ * This is a convenience use case that wraps ScheduleAction and automatically
7
+ * calculates the closest possible execution time (current time + small buffer).
8
+ *
9
+ * Use this when you want to execute an action "immediately" without having to manually
10
+ * calculate the schedule date.
11
+ */
12
+
13
+ export const RunActionUseCase = createAbstraction("RunActionUseCase");
14
+
15
+ //# sourceMappingURL=abstractions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createAbstraction","RunActionUseCase"],"sources":["abstractions.ts"],"sourcesContent":["import { createAbstraction, Result } from \"@webiny/feature/api\";\nimport type { IScheduledAction } from \"~/shared/abstractions.js\";\nimport {\n InvalidScheduleDateError,\n ScheduledActionPersistenceError,\n SchedulerServiceError\n} from \"~/domain/errors.js\";\nimport type { GenericRecord } from \"@webiny/api/types.js\";\n\n/**\n * RunActionUseCase - Schedule an action for immediate execution\n *\n * This is a convenience use case that wraps ScheduleAction and automatically\n * calculates the closest possible execution time (current time + small buffer).\n *\n * Use this when you want to execute an action \"immediately\" without having to manually\n * calculate the schedule date.\n */\n\nexport interface IRunActionErrors {\n persistence: ScheduledActionPersistenceError;\n invalidDate: InvalidScheduleDateError;\n schedulerService: SchedulerServiceError;\n}\n\ntype RunActionError = IRunActionErrors[keyof IRunActionErrors];\n\ninterface IRunActionParams<T extends GenericRecord> {\n namespace: string;\n actionType: string;\n targetId: string;\n payload: T;\n}\n\nexport interface IRunActionUseCase {\n execute<T extends GenericRecord>(\n params: IRunActionParams<T>\n ): Promise<Result<IScheduledAction<T>, RunActionError>>;\n}\n\nexport const RunActionUseCase = createAbstraction<IRunActionUseCase>(\"RunActionUseCase\");\n\nexport namespace RunActionUseCase {\n export type Interface = IRunActionUseCase;\n export type Params<T extends GenericRecord> = IRunActionParams<T>;\n export type Error = RunActionError;\n}\n"],"mappings":"AAAA,SAASA,iBAAiB,QAAgB,qBAAqB;;AAS/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAuBA,OAAO,MAAMC,gBAAgB,GAAGD,iBAAiB,CAAoB,kBAAkB,CAAC","ignoreList":[]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * RunAction Feature
3
+ *
4
+ * Provides the ability to schedule an action for immediate execution
5
+ * without having to manually calculate the schedule date.
6
+ */
7
+ export declare const RunActionFeature: import("@webiny/feature/api/createFeature.js").FeatureDefinition<unknown>;
@@ -0,0 +1,17 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import { RunActionUseCase } from "./RunActionUseCase.js";
3
+
4
+ /**
5
+ * RunAction Feature
6
+ *
7
+ * Provides the ability to schedule an action for immediate execution
8
+ * without having to manually calculate the schedule date.
9
+ */
10
+ export const RunActionFeature = createFeature({
11
+ name: "RunAction",
12
+ register(container) {
13
+ container.register(RunActionUseCase);
14
+ }
15
+ });
16
+
17
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createFeature","RunActionUseCase","RunActionFeature","name","register","container"],"sources":["feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { RunActionUseCase } from \"./RunActionUseCase.js\";\n\n/**\n * RunAction Feature\n *\n * Provides the ability to schedule an action for immediate execution\n * without having to manually calculate the schedule date.\n */\nexport const RunActionFeature = createFeature({\n name: \"RunAction\",\n register(container) {\n container.register(RunActionUseCase);\n }\n});\n"],"mappings":"AAAA,SAASA,aAAa,QAAQ,qBAAqB;AACnD,SAASC,gBAAgB;;AAEzB;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,gBAAgB,GAAGF,aAAa,CAAC;EAC1CG,IAAI,EAAE,WAAW;EACjBC,QAAQA,CAACC,SAAS,EAAE;IAChBA,SAAS,CAACD,QAAQ,CAACH,gBAAgB,CAAC;EACxC;AACJ,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export * from "./abstractions.js";
@@ -0,0 +1,3 @@
1
+ export * from "./abstractions.js";
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./abstractions.js\";\n"],"mappings":"AAAA","ignoreList":[]}
@@ -0,0 +1,45 @@
1
+ import { Result } from "@webiny/feature/api";
2
+ import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
3
+ import { CreateEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/CreateEntry/index.js";
4
+ import { UpdateEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/UpdateEntry/index.js";
5
+ import { DeleteEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/DeleteEntry/index.js";
6
+ import { ScheduleActionUseCase as UseCaseAbstraction } from "./abstractions.js";
7
+ import { GetScheduledActionUseCase } from "../../features/GetScheduledAction/abstractions.js";
8
+ import type { IScheduledAction } from "../../shared/abstractions.js";
9
+ import { ScheduledActionModel, SchedulerService } from "../../shared/abstractions.js";
10
+ import type { GenericRecord } from "@webiny/api/types.js";
11
+ /**
12
+ * Schedules an action for future execution
13
+ *
14
+ * Flow:
15
+ * 1. Generate unique schedule ID from namespace+actionType+targetId
16
+ * 2. Check if schedule already exists (for rescheduling logic)
17
+ * 3. If exists: UPDATE schedule entry + EventBridge schedule
18
+ * 4. If new: CREATE schedule entry + EventBridge schedule
19
+ * 5. Rollback schedule entry if EventBridge fails
20
+ *
21
+ * Note: Does NOT handle immediate execution - apps use direct use cases for that
22
+ */
23
+ declare class ScheduleActionUseCaseImpl implements UseCaseAbstraction.Interface {
24
+ private identityContext;
25
+ private model;
26
+ private schedulerService;
27
+ private getScheduledAction;
28
+ private createEntryUseCase;
29
+ private updateEntryUseCase;
30
+ private deleteEntryUseCase;
31
+ constructor(identityContext: IdentityContext.Interface, model: ScheduledActionModel.Interface, schedulerService: SchedulerService.Interface, getScheduledAction: GetScheduledActionUseCase.Interface, createEntryUseCase: CreateEntryUseCase.Interface, updateEntryUseCase: UpdateEntryUseCase.Interface, deleteEntryUseCase: DeleteEntryUseCase.Interface);
32
+ execute<T extends GenericRecord>(params: UseCaseAbstraction.Params<T>): Promise<Result<IScheduledAction<T>, UseCaseAbstraction.Error>>;
33
+ /**
34
+ * Creates a new schedule
35
+ */
36
+ private createSchedule;
37
+ /**
38
+ * Updates an existing schedule (reschedule)
39
+ */
40
+ private reschedule;
41
+ }
42
+ export declare const ScheduleActionUseCase: typeof ScheduleActionUseCaseImpl & {
43
+ __abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").IScheduleActionUseCase>;
44
+ };
45
+ export {};
@@ -0,0 +1,164 @@
1
+ import { Result } from "@webiny/feature/api";
2
+ import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
3
+ import { CreateEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/CreateEntry/index.js";
4
+ import { UpdateEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/UpdateEntry/index.js";
5
+ import { DeleteEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/DeleteEntry/index.js";
6
+ import { parseIdentifier } from "@webiny/utils";
7
+ import { ScheduleActionUseCase as UseCaseAbstraction } from "./abstractions.js";
8
+ import { GetScheduledActionUseCase } from "../GetScheduledAction/abstractions.js";
9
+ import { ScheduledActionModel, SchedulerService } from "../../shared/abstractions.js";
10
+ import { InvalidScheduleDateError, ScheduledActionPersistenceError, SchedulerServiceError } from "../../domain/errors.js";
11
+ import { ScheduledActionId } from "../../domain/ScheduledActionId.js";
12
+ import { ScheduledActionIdWithVersion } from "../../domain/ScheduledActionIdWithVersion.js";
13
+ import { isValidDate } from "../../domain/isValidDate.js";
14
+ /**
15
+ * Schedules an action for future execution
16
+ *
17
+ * Flow:
18
+ * 1. Generate unique schedule ID from namespace+actionType+targetId
19
+ * 2. Check if schedule already exists (for rescheduling logic)
20
+ * 3. If exists: UPDATE schedule entry + EventBridge schedule
21
+ * 4. If new: CREATE schedule entry + EventBridge schedule
22
+ * 5. Rollback schedule entry if EventBridge fails
23
+ *
24
+ * Note: Does NOT handle immediate execution - apps use direct use cases for that
25
+ */
26
+ class ScheduleActionUseCaseImpl {
27
+ constructor(identityContext, model, schedulerService, getScheduledAction, createEntryUseCase, updateEntryUseCase, deleteEntryUseCase) {
28
+ this.identityContext = identityContext;
29
+ this.model = model;
30
+ this.schedulerService = schedulerService;
31
+ this.getScheduledAction = getScheduledAction;
32
+ this.createEntryUseCase = createEntryUseCase;
33
+ this.updateEntryUseCase = updateEntryUseCase;
34
+ this.deleteEntryUseCase = deleteEntryUseCase;
35
+ }
36
+ async execute(params) {
37
+ const identity = this.identityContext.getIdentity();
38
+ if (!isValidDate(params.scheduleFor)) {
39
+ return Result.fail(new InvalidScheduleDateError(params.scheduleFor));
40
+ }
41
+
42
+ // Generate unique schedule ID
43
+ const actionId = ScheduledActionId.from(params);
44
+ const scheduleId = ScheduledActionIdWithVersion.from(actionId);
45
+ const existingResult = await this.getScheduledAction.execute(scheduleId);
46
+ if (existingResult.isFail()) {
47
+ const error = existingResult.error;
48
+
49
+ // NotFound means the action was not yet scheduled
50
+ if (error.code === "Scheduler/ScheduledAction/NotFound") {
51
+ return this.createSchedule(scheduleId, params.title, params.namespace, params.actionType, params.targetId, params.scheduleFor, identity, params.payload);
52
+ }
53
+ if (error.code === "Scheduler/ScheduledAction/PersistenceError") {
54
+ return Result.fail(error);
55
+ }
56
+ }
57
+
58
+ // Reschedule existing action
59
+ const scheduledAction = existingResult.value;
60
+ return this.reschedule(scheduledAction, params.scheduleFor, identity, params.payload);
61
+ }
62
+
63
+ /**
64
+ * Creates a new schedule
65
+ */
66
+ async createSchedule(id, title, namespace, actionType, targetId, scheduleFor, identity, payload) {
67
+ const {
68
+ id: scheduleId
69
+ } = parseIdentifier(id);
70
+ const scheduledAction = {
71
+ id: scheduleId,
72
+ title,
73
+ namespace,
74
+ actionType,
75
+ targetId,
76
+ scheduledBy: {
77
+ id: identity.id,
78
+ type: identity.type,
79
+ displayName: identity.displayName
80
+ },
81
+ scheduledFor: scheduleFor,
82
+ payload
83
+ };
84
+
85
+ // Create CMS entry
86
+ const createResult = await this.createEntryUseCase.execute(this.model, {
87
+ id: scheduleId,
88
+ values: scheduledAction
89
+ });
90
+ if (createResult.isFail()) {
91
+ return Result.fail(new ScheduledActionPersistenceError(new Error(createResult.error.message)));
92
+ }
93
+
94
+ // Create EventBridge schedule
95
+ try {
96
+ await this.schedulerService.create({
97
+ id: scheduleId,
98
+ scheduleFor: new Date(scheduleFor)
99
+ });
100
+ } catch (error) {
101
+ // Rollback - delete CMS entry if EventBridge fails
102
+ console.error(`Failed to create EventBridge schedule: ${scheduleId}. Rolling back...`);
103
+ await this.deleteEntryUseCase.execute(this.model, scheduleId, {
104
+ force: true,
105
+ permanently: true
106
+ });
107
+ return Result.fail(new SchedulerServiceError(error));
108
+ }
109
+ return Result.ok(scheduledAction);
110
+ }
111
+
112
+ /**
113
+ * Updates an existing schedule (reschedule)
114
+ */
115
+ async reschedule(existing, scheduleFor, identity, payload) {
116
+ // Make sure we don't unset the existing payload.
117
+ if (!payload && existing.payload) {
118
+ payload = existing.payload;
119
+ }
120
+
121
+ // Update CMS entry
122
+ const existingEntryId = ScheduledActionIdWithVersion.from(existing.id);
123
+ const updateResult = await this.updateEntryUseCase.execute(this.model, existingEntryId, {
124
+ values: {
125
+ scheduledBy: {
126
+ id: identity.id,
127
+ type: identity.type,
128
+ displayName: identity.displayName
129
+ },
130
+ scheduledFor: scheduleFor,
131
+ payload
132
+ }
133
+ });
134
+ if (updateResult.isFail()) {
135
+ return Result.fail(new ScheduledActionPersistenceError(new Error(updateResult.error.message)));
136
+ }
137
+
138
+ // Update EventBridge schedule
139
+ try {
140
+ await this.schedulerService.update({
141
+ id: existing.id,
142
+ scheduleFor: new Date(scheduleFor)
143
+ });
144
+ } catch (error) {
145
+ return Result.fail(new SchedulerServiceError(error));
146
+ }
147
+ return Result.ok({
148
+ ...existing,
149
+ scheduledBy: {
150
+ id: identity.id,
151
+ type: identity.type,
152
+ displayName: identity.displayName
153
+ },
154
+ scheduledFor: scheduleFor,
155
+ payload
156
+ });
157
+ }
158
+ }
159
+ export const ScheduleActionUseCase = UseCaseAbstraction.createImplementation({
160
+ implementation: ScheduleActionUseCaseImpl,
161
+ dependencies: [IdentityContext, ScheduledActionModel, SchedulerService, GetScheduledActionUseCase, CreateEntryUseCase, UpdateEntryUseCase, DeleteEntryUseCase]
162
+ });
163
+
164
+ //# sourceMappingURL=ScheduleActionUseCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Result","IdentityContext","CreateEntryUseCase","UpdateEntryUseCase","DeleteEntryUseCase","parseIdentifier","ScheduleActionUseCase","UseCaseAbstraction","GetScheduledActionUseCase","ScheduledActionModel","SchedulerService","InvalidScheduleDateError","ScheduledActionPersistenceError","SchedulerServiceError","ScheduledActionId","ScheduledActionIdWithVersion","isValidDate","ScheduleActionUseCaseImpl","constructor","identityContext","model","schedulerService","getScheduledAction","createEntryUseCase","updateEntryUseCase","deleteEntryUseCase","execute","params","identity","getIdentity","scheduleFor","fail","actionId","from","scheduleId","existingResult","isFail","error","code","createSchedule","title","namespace","actionType","targetId","payload","scheduledAction","value","reschedule","id","scheduledBy","type","displayName","scheduledFor","createResult","values","Error","message","create","Date","console","force","permanently","ok","existing","existingEntryId","updateResult","update","createImplementation","implementation","dependencies"],"sources":["ScheduleActionUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { CreateEntryUseCase } from \"@webiny/api-headless-cms/features/contentEntry/CreateEntry/index.js\";\nimport { UpdateEntryUseCase } from \"@webiny/api-headless-cms/features/contentEntry/UpdateEntry/index.js\";\nimport { DeleteEntryUseCase } from \"@webiny/api-headless-cms/features/contentEntry/DeleteEntry/index.js\";\nimport { parseIdentifier } from \"@webiny/utils\";\nimport { ScheduleActionUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport { GetScheduledActionUseCase } from \"~/features/GetScheduledAction/abstractions.js\";\nimport type { Identity, IScheduledAction } from \"~/shared/abstractions.js\";\nimport { ScheduledActionModel, SchedulerService } from \"~/shared/abstractions.js\";\nimport {\n InvalidScheduleDateError,\n ScheduledActionPersistenceError,\n SchedulerServiceError\n} from \"~/domain/errors.js\";\nimport { ScheduledActionId } from \"~/domain/ScheduledActionId.js\";\nimport { ScheduledActionIdWithVersion } from \"~/domain/ScheduledActionIdWithVersion.js\";\nimport { isValidDate } from \"~/domain/isValidDate.js\";\nimport type { GenericRecord } from \"@webiny/api/types.js\";\n\n/**\n * Schedules an action for future execution\n *\n * Flow:\n * 1. Generate unique schedule ID from namespace+actionType+targetId\n * 2. Check if schedule already exists (for rescheduling logic)\n * 3. If exists: UPDATE schedule entry + EventBridge schedule\n * 4. If new: CREATE schedule entry + EventBridge schedule\n * 5. Rollback schedule entry if EventBridge fails\n *\n * Note: Does NOT handle immediate execution - apps use direct use cases for that\n */\nclass ScheduleActionUseCaseImpl implements UseCaseAbstraction.Interface {\n constructor(\n private identityContext: IdentityContext.Interface,\n private model: ScheduledActionModel.Interface,\n private schedulerService: SchedulerService.Interface,\n private getScheduledAction: GetScheduledActionUseCase.Interface,\n private createEntryUseCase: CreateEntryUseCase.Interface,\n private updateEntryUseCase: UpdateEntryUseCase.Interface,\n private deleteEntryUseCase: DeleteEntryUseCase.Interface\n ) {}\n\n async execute<T extends GenericRecord>(\n params: UseCaseAbstraction.Params<T>\n ): Promise<Result<IScheduledAction<T>, UseCaseAbstraction.Error>> {\n const identity = this.identityContext.getIdentity();\n\n if (!isValidDate(params.scheduleFor)) {\n return Result.fail(new InvalidScheduleDateError(params.scheduleFor));\n }\n\n // Generate unique schedule ID\n const actionId = ScheduledActionId.from(params);\n const scheduleId = ScheduledActionIdWithVersion.from(actionId);\n\n const existingResult = await this.getScheduledAction.execute(scheduleId);\n\n if (existingResult.isFail()) {\n const error = existingResult.error;\n\n // NotFound means the action was not yet scheduled\n if (error.code === \"Scheduler/ScheduledAction/NotFound\") {\n return this.createSchedule(\n scheduleId,\n params.title,\n params.namespace,\n params.actionType,\n params.targetId,\n params.scheduleFor,\n identity,\n params.payload\n );\n }\n\n if (error.code === \"Scheduler/ScheduledAction/PersistenceError\") {\n return Result.fail(error);\n }\n }\n\n // Reschedule existing action\n const scheduledAction = existingResult.value;\n\n return this.reschedule(scheduledAction, params.scheduleFor, identity, params.payload);\n }\n\n /**\n * Creates a new schedule\n */\n private async createSchedule<T extends GenericRecord>(\n id: string,\n title: string,\n namespace: string,\n actionType: string,\n targetId: string,\n scheduleFor: string,\n identity: Identity,\n payload: T\n ): Promise<Result<IScheduledAction<T>, UseCaseAbstraction.Error>> {\n const { id: scheduleId } = parseIdentifier(id);\n\n const scheduledAction: IScheduledAction<T> = {\n id: scheduleId,\n title,\n namespace,\n actionType,\n targetId,\n scheduledBy: {\n id: identity.id,\n type: identity.type,\n displayName: identity.displayName\n },\n scheduledFor: scheduleFor,\n payload\n };\n\n // Create CMS entry\n const createResult = await this.createEntryUseCase.execute<IScheduledAction<T>>(\n this.model,\n {\n id: scheduleId,\n values: scheduledAction\n }\n );\n\n if (createResult.isFail()) {\n return Result.fail(\n new ScheduledActionPersistenceError(new Error(createResult.error.message))\n );\n }\n\n // Create EventBridge schedule\n try {\n await this.schedulerService.create({\n id: scheduleId,\n scheduleFor: new Date(scheduleFor)\n });\n } catch (error) {\n // Rollback - delete CMS entry if EventBridge fails\n console.error(`Failed to create EventBridge schedule: ${scheduleId}. Rolling back...`);\n\n await this.deleteEntryUseCase.execute(this.model, scheduleId, {\n force: true,\n permanently: true\n });\n\n return Result.fail(new SchedulerServiceError(error as Error));\n }\n\n return Result.ok(scheduledAction);\n }\n\n /**\n * Updates an existing schedule (reschedule)\n */\n private async reschedule<T extends GenericRecord>(\n existing: IScheduledAction<T>,\n scheduleFor: string,\n identity: Identity,\n payload?: any\n ): Promise<Result<IScheduledAction<T>, UseCaseAbstraction.Error>> {\n // Make sure we don't unset the existing payload.\n if (!payload && existing.payload) {\n payload = existing.payload;\n }\n\n // Update CMS entry\n const existingEntryId = ScheduledActionIdWithVersion.from(existing.id);\n const updateResult = await this.updateEntryUseCase.execute<IScheduledAction<T>>(\n this.model,\n existingEntryId,\n {\n values: {\n scheduledBy: {\n id: identity.id,\n type: identity.type,\n displayName: identity.displayName\n },\n scheduledFor: scheduleFor,\n payload\n }\n }\n );\n\n if (updateResult.isFail()) {\n return Result.fail(\n new ScheduledActionPersistenceError(new Error(updateResult.error.message))\n );\n }\n\n // Update EventBridge schedule\n try {\n await this.schedulerService.update({\n id: existing.id,\n scheduleFor: new Date(scheduleFor)\n });\n } catch (error) {\n return Result.fail(new SchedulerServiceError(error as Error));\n }\n\n return Result.ok({\n ...existing,\n scheduledBy: {\n id: identity.id,\n type: identity.type,\n displayName: identity.displayName\n },\n scheduledFor: scheduleFor,\n payload\n });\n }\n}\n\nexport const ScheduleActionUseCase = UseCaseAbstraction.createImplementation({\n implementation: ScheduleActionUseCaseImpl,\n dependencies: [\n IdentityContext,\n ScheduledActionModel,\n SchedulerService,\n GetScheduledActionUseCase,\n CreateEntryUseCase,\n UpdateEntryUseCase,\n DeleteEntryUseCase\n ]\n});\n"],"mappings":"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","ignoreList":[]}