@webiny/api-headless-cms-scheduler 0.0.0-unstable.2aaa1916d9
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.
- package/LICENSE +21 -0
- package/README.md +15 -0
- package/constants.d.ts +11 -0
- package/constants.js +19 -0
- package/constants.js.map +1 -0
- package/context.d.ts +7 -0
- package/context.js +68 -0
- package/context.js.map +1 -0
- package/graphql/index.d.ts +3 -0
- package/graphql/index.js +204 -0
- package/graphql/index.js.map +1 -0
- package/graphql/schema.d.ts +217 -0
- package/graphql/schema.js +87 -0
- package/graphql/schema.js.map +1 -0
- package/handler/Handler.d.ts +23 -0
- package/handler/Handler.js +74 -0
- package/handler/Handler.js.map +1 -0
- package/handler/actions/PublishHandlerAction.d.ts +13 -0
- package/handler/actions/PublishHandlerAction.js +64 -0
- package/handler/actions/PublishHandlerAction.js.map +1 -0
- package/handler/actions/UnpublishHandlerAction.d.ts +13 -0
- package/handler/actions/UnpublishHandlerAction.js +53 -0
- package/handler/actions/UnpublishHandlerAction.js.map +1 -0
- package/handler/index.d.ts +7 -0
- package/handler/index.js +64 -0
- package/handler/index.js.map +1 -0
- package/handler/types.d.ts +5 -0
- package/handler/types.js +7 -0
- package/handler/types.js.map +1 -0
- package/hooks/index.d.ts +7 -0
- package/hooks/index.js +58 -0
- package/hooks/index.js.map +1 -0
- package/index.d.ts +10 -0
- package/index.js +29 -0
- package/index.js.map +1 -0
- package/manifest.d.ts +17 -0
- package/manifest.js +47 -0
- package/manifest.js.map +1 -0
- package/package.json +45 -0
- package/scheduler/ScheduleExecutor.d.ts +16 -0
- package/scheduler/ScheduleExecutor.js +55 -0
- package/scheduler/ScheduleExecutor.js.map +1 -0
- package/scheduler/ScheduleFetcher.d.ts +16 -0
- package/scheduler/ScheduleFetcher.js +51 -0
- package/scheduler/ScheduleFetcher.js.map +1 -0
- package/scheduler/ScheduleRecord.d.ts +31 -0
- package/scheduler/ScheduleRecord.js +57 -0
- package/scheduler/ScheduleRecord.js.map +1 -0
- package/scheduler/Scheduler.d.ts +14 -0
- package/scheduler/Scheduler.js +27 -0
- package/scheduler/Scheduler.js.map +1 -0
- package/scheduler/actions/PublishScheduleAction.d.ts +26 -0
- package/scheduler/actions/PublishScheduleAction.js +196 -0
- package/scheduler/actions/PublishScheduleAction.js.map +1 -0
- package/scheduler/actions/UnpublishScheduleAction.d.ts +26 -0
- package/scheduler/actions/UnpublishScheduleAction.js +194 -0
- package/scheduler/actions/UnpublishScheduleAction.js.map +1 -0
- package/scheduler/createScheduleRecordId.d.ts +2 -0
- package/scheduler/createScheduleRecordId.js +33 -0
- package/scheduler/createScheduleRecordId.js.map +1 -0
- package/scheduler/createScheduler.d.ts +12 -0
- package/scheduler/createScheduler.js +65 -0
- package/scheduler/createScheduler.js.map +1 -0
- package/scheduler/dates.d.ts +7 -0
- package/scheduler/dates.js +27 -0
- package/scheduler/dates.js.map +1 -0
- package/scheduler/model.d.ts +1 -0
- package/scheduler/model.js +88 -0
- package/scheduler/model.js.map +1 -0
- package/scheduler/types.d.ts +88 -0
- package/scheduler/types.js +19 -0
- package/scheduler/types.js.map +1 -0
- package/service/SchedulerService.d.ts +23 -0
- package/service/SchedulerService.js +151 -0
- package/service/SchedulerService.js.map +1 -0
- package/service/types.d.ts +19 -0
- package/service/types.js +7 -0
- package/service/types.js.map +1 -0
- package/types.d.ts +11 -0
- package/types.js +7 -0
- package/types.js.map +1 -0
- package/utils/dateInTheFuture.d.ts +6 -0
- package/utils/dateInTheFuture.js +19 -0
- package/utils/dateInTheFuture.js.map +1 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { CmsEntryListSort, CmsEntryMeta, CmsIdentity, CmsModel } from "@webiny/api-headless-cms/types/index.js";
|
|
2
|
+
export declare enum ScheduleType {
|
|
3
|
+
publish = "publish",
|
|
4
|
+
unpublish = "unpublish"
|
|
5
|
+
}
|
|
6
|
+
export type DateISOString = `${number}-${number}-${number}T${number}:${number}:${number}.${number}Z`;
|
|
7
|
+
/**
|
|
8
|
+
* A date when the action is to be scheduled.
|
|
9
|
+
*/
|
|
10
|
+
export type ScheduledOnType = Date;
|
|
11
|
+
/**
|
|
12
|
+
* A custom date when the action is to be set as done (publishedOn and related dates).
|
|
13
|
+
*/
|
|
14
|
+
export type DateOnType = Date;
|
|
15
|
+
export interface ISchedulerInputImmediately {
|
|
16
|
+
immediately: true;
|
|
17
|
+
scheduleOn?: never;
|
|
18
|
+
type: ScheduleType;
|
|
19
|
+
}
|
|
20
|
+
export interface ISchedulerInputScheduled {
|
|
21
|
+
immediately?: false;
|
|
22
|
+
scheduleOn: ScheduledOnType;
|
|
23
|
+
type: ScheduleType;
|
|
24
|
+
}
|
|
25
|
+
export type ISchedulerInput = ISchedulerInputScheduled | ISchedulerInputImmediately;
|
|
26
|
+
export interface IScheduleRecord {
|
|
27
|
+
id: string;
|
|
28
|
+
targetId: string;
|
|
29
|
+
model: CmsModel;
|
|
30
|
+
scheduledBy: CmsIdentity;
|
|
31
|
+
publishOn: ScheduledOnType | undefined;
|
|
32
|
+
unpublishOn: ScheduledOnType | undefined;
|
|
33
|
+
type: ScheduleType;
|
|
34
|
+
title: string;
|
|
35
|
+
}
|
|
36
|
+
export interface ISchedulerListResponse {
|
|
37
|
+
data: IScheduleRecord[];
|
|
38
|
+
meta: CmsEntryMeta;
|
|
39
|
+
}
|
|
40
|
+
export interface ISchedulerListParamsWhere {
|
|
41
|
+
targetId?: string;
|
|
42
|
+
targetEntryId?: string;
|
|
43
|
+
type?: ScheduleType;
|
|
44
|
+
scheduledBy?: string;
|
|
45
|
+
scheduledOn?: DateISOString;
|
|
46
|
+
scheduledOn_gte?: DateISOString;
|
|
47
|
+
scheduledOn_lte?: DateISOString;
|
|
48
|
+
}
|
|
49
|
+
export interface ISchedulerListParams {
|
|
50
|
+
where: ISchedulerListParamsWhere;
|
|
51
|
+
sort: CmsEntryListSort | undefined;
|
|
52
|
+
limit: number | undefined;
|
|
53
|
+
after: string | undefined;
|
|
54
|
+
}
|
|
55
|
+
export interface IScheduler {
|
|
56
|
+
schedule(id: string, input: ISchedulerInput): Promise<IScheduleRecord>;
|
|
57
|
+
cancel(id: string): Promise<IScheduleRecord>;
|
|
58
|
+
getScheduled(id: string): Promise<IScheduleRecord | null>;
|
|
59
|
+
listScheduled(params: ISchedulerListParams): Promise<ISchedulerListResponse>;
|
|
60
|
+
}
|
|
61
|
+
export interface IScheduleEntryValues {
|
|
62
|
+
targetId: string;
|
|
63
|
+
targetModelId: string;
|
|
64
|
+
scheduledBy: CmsIdentity;
|
|
65
|
+
scheduledOn: DateISOString;
|
|
66
|
+
type: string;
|
|
67
|
+
title: string;
|
|
68
|
+
error?: string;
|
|
69
|
+
}
|
|
70
|
+
export interface IScheduleExecutor {
|
|
71
|
+
schedule(targetId: string, input: ISchedulerInput): Promise<IScheduleRecord>;
|
|
72
|
+
cancel(id: string): Promise<IScheduleRecord>;
|
|
73
|
+
}
|
|
74
|
+
export interface IScheduleFetcher {
|
|
75
|
+
getScheduled(targetId: string): Promise<IScheduleRecord | null>;
|
|
76
|
+
listScheduled(params: ISchedulerListParams): Promise<ISchedulerListResponse>;
|
|
77
|
+
}
|
|
78
|
+
export interface IScheduleActionScheduleParams {
|
|
79
|
+
targetId: string;
|
|
80
|
+
scheduleRecordId: string;
|
|
81
|
+
input: ISchedulerInput;
|
|
82
|
+
}
|
|
83
|
+
export interface IScheduleAction {
|
|
84
|
+
canHandle(input: Pick<ISchedulerInput, "type">): boolean;
|
|
85
|
+
schedule(params: IScheduleActionScheduleParams): Promise<IScheduleRecord>;
|
|
86
|
+
cancel(id: string): Promise<void>;
|
|
87
|
+
reschedule(original: IScheduleRecord, input: ISchedulerInput): Promise<IScheduleRecord>;
|
|
88
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.ScheduleType = void 0;
|
|
7
|
+
let ScheduleType = exports.ScheduleType = /*#__PURE__*/function (ScheduleType) {
|
|
8
|
+
ScheduleType["publish"] = "publish";
|
|
9
|
+
ScheduleType["unpublish"] = "unpublish";
|
|
10
|
+
return ScheduleType;
|
|
11
|
+
}({});
|
|
12
|
+
/**
|
|
13
|
+
* A date when the action is to be scheduled.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* A custom date when the action is to be set as done (publishedOn and related dates).
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["ScheduleType","exports"],"sources":["types.ts"],"sourcesContent":["import type {\n CmsEntryListSort,\n CmsEntryMeta,\n CmsIdentity,\n CmsModel\n} from \"@webiny/api-headless-cms/types/index.js\";\n\nexport enum ScheduleType {\n publish = \"publish\",\n unpublish = \"unpublish\"\n}\n\nexport type DateISOString =\n `${number}-${number}-${number}T${number}:${number}:${number}.${number}Z`;\n/**\n * A date when the action is to be scheduled.\n */\nexport type ScheduledOnType = Date;\n/**\n * A custom date when the action is to be set as done (publishedOn and related dates).\n */\nexport type DateOnType = Date;\n\nexport interface ISchedulerInputImmediately {\n immediately: true;\n scheduleOn?: never;\n type: ScheduleType;\n}\n\nexport interface ISchedulerInputScheduled {\n immediately?: false;\n scheduleOn: ScheduledOnType;\n type: ScheduleType;\n}\n\nexport type ISchedulerInput = ISchedulerInputScheduled | ISchedulerInputImmediately;\n\nexport interface IScheduleRecord {\n id: string;\n targetId: string;\n model: CmsModel;\n scheduledBy: CmsIdentity;\n // dateOn: DateOnType | undefined;\n publishOn: ScheduledOnType | undefined;\n unpublishOn: ScheduledOnType | undefined;\n type: ScheduleType;\n title: string;\n}\n\nexport interface ISchedulerListResponse {\n data: IScheduleRecord[];\n meta: CmsEntryMeta;\n}\n\nexport interface ISchedulerListParamsWhere {\n targetId?: string;\n targetEntryId?: string;\n type?: ScheduleType;\n scheduledBy?: string;\n scheduledOn?: DateISOString;\n scheduledOn_gte?: DateISOString;\n scheduledOn_lte?: DateISOString;\n}\n\nexport interface ISchedulerListParams {\n where: ISchedulerListParamsWhere;\n sort: CmsEntryListSort | undefined;\n limit: number | undefined;\n after: string | undefined;\n}\n\nexport interface IScheduler {\n schedule(id: string, input: ISchedulerInput): Promise<IScheduleRecord>;\n cancel(id: string): Promise<IScheduleRecord>;\n getScheduled(id: string): Promise<IScheduleRecord | null>;\n listScheduled(params: ISchedulerListParams): Promise<ISchedulerListResponse>;\n}\n\nexport interface IScheduleEntryValues {\n targetId: string;\n targetModelId: string;\n scheduledBy: CmsIdentity;\n // dateOn: DateISOString | undefined;\n scheduledOn: DateISOString;\n type: string;\n title: string;\n error?: string;\n}\n\nexport interface IScheduleExecutor {\n schedule(targetId: string, input: ISchedulerInput): Promise<IScheduleRecord>;\n cancel(id: string): Promise<IScheduleRecord>;\n}\n\nexport interface IScheduleFetcher {\n getScheduled(targetId: string): Promise<IScheduleRecord | null>;\n listScheduled(params: ISchedulerListParams): Promise<ISchedulerListResponse>;\n}\n\nexport interface IScheduleActionScheduleParams {\n targetId: string;\n scheduleRecordId: string;\n input: ISchedulerInput;\n}\nexport interface IScheduleAction {\n canHandle(input: Pick<ISchedulerInput, \"type\">): boolean;\n schedule(params: IScheduleActionScheduleParams): Promise<IScheduleRecord>;\n cancel(id: string): Promise<void>;\n reschedule(original: IScheduleRecord, input: ISchedulerInput): Promise<IScheduleRecord>;\n}\n"],"mappings":";;;;;;IAOYA,YAAY,GAAAC,OAAA,CAAAD,YAAA,0BAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAA,OAAZA,YAAY;AAAA;AAOxB;AACA;AACA;AAEA;AACA;AACA","ignoreList":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SchedulerClient, SchedulerClientConfig } from "@webiny/aws-sdk/client-scheduler/index.js";
|
|
2
|
+
import type { ISchedulerService, ISchedulerServiceCreateInput, ISchedulerServiceCreateResponse, ISchedulerServiceDeleteResponse, ISchedulerServiceUpdateInput, ISchedulerServiceUpdateResponse } from "./types.js";
|
|
3
|
+
export interface ISchedulerServiceParams {
|
|
4
|
+
getClient(config?: SchedulerClientConfig): Pick<SchedulerClient, "send">;
|
|
5
|
+
config: ISchedulerServiceConfig;
|
|
6
|
+
}
|
|
7
|
+
export interface ISchedulerServiceConfig {
|
|
8
|
+
lambdaArn: string;
|
|
9
|
+
roleArn: string;
|
|
10
|
+
}
|
|
11
|
+
export declare class SchedulerService implements ISchedulerService {
|
|
12
|
+
private readonly getClient;
|
|
13
|
+
private readonly config;
|
|
14
|
+
constructor(params: ISchedulerServiceParams);
|
|
15
|
+
create(params: ISchedulerServiceCreateInput): Promise<ISchedulerServiceCreateResponse>;
|
|
16
|
+
update(params: ISchedulerServiceUpdateInput): Promise<ISchedulerServiceUpdateResponse>;
|
|
17
|
+
delete(initialId: string): Promise<ISchedulerServiceDeleteResponse>;
|
|
18
|
+
exists(initialId: string): Promise<boolean>;
|
|
19
|
+
private createScheduleExpression;
|
|
20
|
+
private getTimeAt;
|
|
21
|
+
private getInput;
|
|
22
|
+
}
|
|
23
|
+
export declare const createSchedulerService: (params: ISchedulerServiceParams) => ISchedulerService;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createSchedulerService = exports.SchedulerService = void 0;
|
|
7
|
+
var _index = require("@webiny/aws-sdk/client-scheduler/index.js");
|
|
8
|
+
var _error = require("@webiny/error");
|
|
9
|
+
var _handlerGraphql = require("@webiny/handler-graphql");
|
|
10
|
+
var _dateInTheFuture = require("../utils/dateInTheFuture.js");
|
|
11
|
+
var _constants = require("../constants.js");
|
|
12
|
+
var _utils = require("@webiny/utils");
|
|
13
|
+
class SchedulerService {
|
|
14
|
+
constructor(params) {
|
|
15
|
+
this.getClient = params.getClient;
|
|
16
|
+
this.config = params.config;
|
|
17
|
+
}
|
|
18
|
+
async create(params) {
|
|
19
|
+
const {
|
|
20
|
+
id: initialId,
|
|
21
|
+
scheduleOn
|
|
22
|
+
} = params;
|
|
23
|
+
const {
|
|
24
|
+
id
|
|
25
|
+
} = (0, _utils.parseIdentifier)(initialId);
|
|
26
|
+
if ((0, _dateInTheFuture.dateInTheFuture)(scheduleOn) === false) {
|
|
27
|
+
throw new _error.WebinyError(`Cannot create a schedule for "${id}" with date in the past: ${scheduleOn.toISOString()}`, "SCHEDULE_DATE_IN_PAST", {
|
|
28
|
+
id,
|
|
29
|
+
dateOn: scheduleOn.toISOString()
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* There is a possibility that the schedule already exists, in which case we will just update it.
|
|
34
|
+
*
|
|
35
|
+
* TODO determine if we want to allow this behavior - or throw an error if the schedule already exists.
|
|
36
|
+
*/
|
|
37
|
+
const exists = await this.exists(id);
|
|
38
|
+
if (exists) {
|
|
39
|
+
return this.update(params);
|
|
40
|
+
}
|
|
41
|
+
const input = this.getInput(id, scheduleOn);
|
|
42
|
+
const command = new _index.CreateScheduleCommand(input);
|
|
43
|
+
try {
|
|
44
|
+
return await this.getClient().send(command);
|
|
45
|
+
} catch (ex) {
|
|
46
|
+
console.error(ex);
|
|
47
|
+
throw _error.WebinyError.from(ex);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async update(params) {
|
|
51
|
+
const {
|
|
52
|
+
id: initialId,
|
|
53
|
+
scheduleOn
|
|
54
|
+
} = params;
|
|
55
|
+
const {
|
|
56
|
+
id
|
|
57
|
+
} = (0, _utils.parseIdentifier)(initialId);
|
|
58
|
+
if ((0, _dateInTheFuture.dateInTheFuture)(scheduleOn) === false) {
|
|
59
|
+
throw new _error.WebinyError(`Cannot update an existing schedule for "${id}" with date in the past: ${scheduleOn.toISOString()}`, "SCHEDULE_DATE_IN_PAST", {
|
|
60
|
+
id,
|
|
61
|
+
dateOn: scheduleOn.toISOString()
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* If the schedule does not exist, we cannot update it.
|
|
66
|
+
*
|
|
67
|
+
* TODO determine if we want to create a new schedule in this case, or return the error.
|
|
68
|
+
*/
|
|
69
|
+
const exists = await this.exists(id);
|
|
70
|
+
if (!exists) {
|
|
71
|
+
throw new _handlerGraphql.NotFoundError(`Cannot update schedule "${id}" because it does not exist.`);
|
|
72
|
+
}
|
|
73
|
+
const input = this.getInput(id, scheduleOn);
|
|
74
|
+
const command = new _index.UpdateScheduleCommand(input);
|
|
75
|
+
try {
|
|
76
|
+
return await this.getClient().send(command);
|
|
77
|
+
} catch (ex) {
|
|
78
|
+
throw _error.WebinyError.from(ex);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async delete(initialId) {
|
|
82
|
+
const {
|
|
83
|
+
id
|
|
84
|
+
} = (0, _utils.parseIdentifier)(initialId);
|
|
85
|
+
const exists = await this.exists(id);
|
|
86
|
+
if (!exists) {
|
|
87
|
+
throw new _handlerGraphql.NotFoundError(`Cannot delete schedule "${id}" because it does not exist.`);
|
|
88
|
+
}
|
|
89
|
+
const input = {
|
|
90
|
+
Name: id
|
|
91
|
+
};
|
|
92
|
+
const command = new _index.DeleteScheduleCommand(input);
|
|
93
|
+
try {
|
|
94
|
+
return await this.getClient().send(command);
|
|
95
|
+
} catch (ex) {
|
|
96
|
+
throw _error.WebinyError.from(ex);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async exists(initialId) {
|
|
100
|
+
const {
|
|
101
|
+
id
|
|
102
|
+
} = (0, _utils.parseIdentifier)(initialId);
|
|
103
|
+
const input = {
|
|
104
|
+
Name: id
|
|
105
|
+
};
|
|
106
|
+
const command = new _index.GetScheduleCommand(input);
|
|
107
|
+
try {
|
|
108
|
+
const result = await this.getClient().send(command);
|
|
109
|
+
return result.$metadata?.httpStatusCode === 200;
|
|
110
|
+
} catch (ex) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
createScheduleExpression(input) {
|
|
115
|
+
return `at(${this.getTimeAt(input)})`;
|
|
116
|
+
}
|
|
117
|
+
getTimeAt(input) {
|
|
118
|
+
return input.toISOString().replace(".000Z", "");
|
|
119
|
+
}
|
|
120
|
+
getInput(initialId, scheduleOn) {
|
|
121
|
+
const {
|
|
122
|
+
id
|
|
123
|
+
} = (0, _utils.parseIdentifier)(initialId);
|
|
124
|
+
const values = {
|
|
125
|
+
id,
|
|
126
|
+
scheduleOn: scheduleOn.toISOString()
|
|
127
|
+
};
|
|
128
|
+
return {
|
|
129
|
+
Name: id,
|
|
130
|
+
ActionAfterCompletion: "DELETE",
|
|
131
|
+
ScheduleExpression: this.createScheduleExpression(scheduleOn),
|
|
132
|
+
FlexibleTimeWindow: {
|
|
133
|
+
Mode: "OFF"
|
|
134
|
+
},
|
|
135
|
+
Target: {
|
|
136
|
+
Arn: this.config.lambdaArn,
|
|
137
|
+
RoleArn: this.config.roleArn,
|
|
138
|
+
Input: JSON.stringify({
|
|
139
|
+
[_constants.SCHEDULED_CMS_ACTION_EVENT_IDENTIFIER]: values
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
exports.SchedulerService = SchedulerService;
|
|
146
|
+
const createSchedulerService = params => {
|
|
147
|
+
return new SchedulerService(params);
|
|
148
|
+
};
|
|
149
|
+
exports.createSchedulerService = createSchedulerService;
|
|
150
|
+
|
|
151
|
+
//# sourceMappingURL=SchedulerService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_index","require","_error","_handlerGraphql","_dateInTheFuture","_constants","_utils","SchedulerService","constructor","params","getClient","config","create","id","initialId","scheduleOn","parseIdentifier","dateInTheFuture","WebinyError","toISOString","dateOn","exists","update","input","getInput","command","CreateScheduleCommand","send","ex","console","error","from","NotFoundError","UpdateScheduleCommand","delete","Name","DeleteScheduleCommand","GetScheduleCommand","result","$metadata","httpStatusCode","createScheduleExpression","getTimeAt","replace","values","ActionAfterCompletion","ScheduleExpression","FlexibleTimeWindow","Mode","Target","Arn","lambdaArn","RoleArn","roleArn","Input","JSON","stringify","SCHEDULED_CMS_ACTION_EVENT_IDENTIFIER","exports","createSchedulerService"],"sources":["SchedulerService.ts"],"sourcesContent":["import type {\n CreateScheduleCommandInput,\n DeleteScheduleCommandInput,\n GetScheduleCommandInput,\n SchedulerClient,\n SchedulerClientConfig,\n UpdateScheduleCommandInput\n} from \"@webiny/aws-sdk/client-scheduler/index.js\";\nimport {\n CreateScheduleCommand,\n DeleteScheduleCommand,\n GetScheduleCommand,\n UpdateScheduleCommand\n} from \"@webiny/aws-sdk/client-scheduler/index.js\";\nimport type {\n ISchedulerService,\n ISchedulerServiceCreateInput,\n ISchedulerServiceCreateResponse,\n ISchedulerServiceDeleteResponse,\n ISchedulerServiceUpdateInput,\n ISchedulerServiceUpdateResponse\n} from \"./types.js\";\nimport { WebinyError } from \"@webiny/error\";\nimport { NotFoundError } from \"@webiny/handler-graphql\";\nimport { dateInTheFuture } from \"~/utils/dateInTheFuture.js\";\nimport { SCHEDULED_CMS_ACTION_EVENT_IDENTIFIER } from \"~/constants.js\";\nimport type { IWebinyScheduledCmsActionEventValues } from \"~/handler/Handler.js\";\nimport { parseIdentifier } from \"@webiny/utils\";\n\nexport interface ISchedulerServiceParams {\n getClient(config?: SchedulerClientConfig): Pick<SchedulerClient, \"send\">;\n config: ISchedulerServiceConfig;\n}\n\nexport interface ISchedulerServiceConfig {\n lambdaArn: string;\n roleArn: string;\n}\n\nexport class SchedulerService implements ISchedulerService {\n private readonly getClient: (config?: SchedulerClientConfig) => Pick<SchedulerClient, \"send\">;\n private readonly config: ISchedulerServiceConfig;\n\n public constructor(params: ISchedulerServiceParams) {\n this.getClient = params.getClient;\n this.config = params.config;\n }\n\n public async create(\n params: ISchedulerServiceCreateInput\n ): Promise<ISchedulerServiceCreateResponse> {\n const { id: initialId, scheduleOn } = params;\n\n const { id } = parseIdentifier(initialId);\n\n if (dateInTheFuture(scheduleOn) === false) {\n throw new WebinyError(\n `Cannot create a schedule for \"${id}\" with date in the past: ${scheduleOn.toISOString()}`,\n \"SCHEDULE_DATE_IN_PAST\",\n {\n id,\n dateOn: scheduleOn.toISOString()\n }\n );\n }\n /**\n * There is a possibility that the schedule already exists, in which case we will just update it.\n *\n * TODO determine if we want to allow this behavior - or throw an error if the schedule already exists.\n */\n const exists = await this.exists(id);\n if (exists) {\n return this.update(params);\n }\n const input: CreateScheduleCommandInput = this.getInput(id, scheduleOn);\n const command = new CreateScheduleCommand(input);\n try {\n return await this.getClient().send(command);\n } catch (ex) {\n console.error(ex);\n throw WebinyError.from(ex);\n }\n }\n\n public async update(\n params: ISchedulerServiceUpdateInput\n ): Promise<ISchedulerServiceUpdateResponse> {\n const { id: initialId, scheduleOn } = params;\n\n const { id } = parseIdentifier(initialId);\n\n if (dateInTheFuture(scheduleOn) === false) {\n throw new WebinyError(\n `Cannot update an existing schedule for \"${id}\" with date in the past: ${scheduleOn.toISOString()}`,\n \"SCHEDULE_DATE_IN_PAST\",\n {\n id,\n dateOn: scheduleOn.toISOString()\n }\n );\n }\n /**\n * If the schedule does not exist, we cannot update it.\n *\n * TODO determine if we want to create a new schedule in this case, or return the error.\n */\n const exists = await this.exists(id);\n if (!exists) {\n throw new NotFoundError(`Cannot update schedule \"${id}\" because it does not exist.`);\n }\n const input: UpdateScheduleCommandInput = this.getInput(id, scheduleOn);\n const command = new UpdateScheduleCommand(input);\n try {\n return await this.getClient().send(command);\n } catch (ex) {\n throw WebinyError.from(ex);\n }\n }\n\n public async delete(initialId: string): Promise<ISchedulerServiceDeleteResponse> {\n const { id } = parseIdentifier(initialId);\n\n const exists = await this.exists(id);\n if (!exists) {\n throw new NotFoundError(`Cannot delete schedule \"${id}\" because it does not exist.`);\n }\n\n const input: DeleteScheduleCommandInput = {\n Name: id\n };\n const command = new DeleteScheduleCommand(input);\n try {\n return await this.getClient().send(command);\n } catch (ex) {\n throw WebinyError.from(ex);\n }\n }\n\n public async exists(initialId: string): Promise<boolean> {\n const { id } = parseIdentifier(initialId);\n\n const input: GetScheduleCommandInput = {\n Name: id\n };\n const command = new GetScheduleCommand(input);\n try {\n const result = await this.getClient().send(command);\n return result.$metadata?.httpStatusCode === 200;\n } catch (ex) {\n return false;\n }\n }\n\n private createScheduleExpression(input: Date): string {\n return `at(${this.getTimeAt(input)})`;\n }\n\n private getTimeAt(input: Date): string {\n return input.toISOString().replace(\".000Z\", \"\");\n }\n\n private getInput(\n initialId: string,\n scheduleOn: Date\n ): CreateScheduleCommandInput | UpdateScheduleCommandInput {\n const { id } = parseIdentifier(initialId);\n\n const values: IWebinyScheduledCmsActionEventValues = {\n id,\n scheduleOn: scheduleOn.toISOString()\n };\n return {\n Name: id,\n ActionAfterCompletion: \"DELETE\",\n ScheduleExpression: this.createScheduleExpression(scheduleOn),\n FlexibleTimeWindow: {\n Mode: \"OFF\"\n },\n Target: {\n Arn: this.config.lambdaArn,\n RoleArn: this.config.roleArn,\n Input: JSON.stringify({\n [SCHEDULED_CMS_ACTION_EVENT_IDENTIFIER]: values\n })\n }\n };\n }\n}\n\nexport const createSchedulerService = (params: ISchedulerServiceParams): ISchedulerService => {\n return new SchedulerService(params);\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ScheduledOnType } from "../scheduler/types.js";
|
|
2
|
+
import type { CreateScheduleCommandOutput, DeleteScheduleCommandOutput, UpdateScheduleCommandOutput } from "@webiny/aws-sdk/client-scheduler";
|
|
3
|
+
export interface ISchedulerServiceCreateInput {
|
|
4
|
+
id: string;
|
|
5
|
+
scheduleOn: ScheduledOnType;
|
|
6
|
+
}
|
|
7
|
+
export interface ISchedulerServiceUpdateInput {
|
|
8
|
+
id: string;
|
|
9
|
+
scheduleOn: ScheduledOnType;
|
|
10
|
+
}
|
|
11
|
+
export type ISchedulerServiceCreateResponse = CreateScheduleCommandOutput;
|
|
12
|
+
export type ISchedulerServiceUpdateResponse = UpdateScheduleCommandOutput;
|
|
13
|
+
export type ISchedulerServiceDeleteResponse = DeleteScheduleCommandOutput;
|
|
14
|
+
export interface ISchedulerService {
|
|
15
|
+
create(params: ISchedulerServiceCreateInput): Promise<ISchedulerServiceCreateResponse>;
|
|
16
|
+
update(params: ISchedulerServiceUpdateInput): Promise<ISchedulerServiceUpdateResponse>;
|
|
17
|
+
delete(id: string): Promise<ISchedulerServiceDeleteResponse>;
|
|
18
|
+
exists(id: string): Promise<boolean>;
|
|
19
|
+
}
|
package/service/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type { ScheduledOnType } from \"~/scheduler/types.js\";\nimport type {\n CreateScheduleCommandOutput,\n DeleteScheduleCommandOutput,\n UpdateScheduleCommandOutput\n} from \"@webiny/aws-sdk/client-scheduler\";\n\nexport interface ISchedulerServiceCreateInput {\n id: string;\n scheduleOn: ScheduledOnType;\n}\n\nexport interface ISchedulerServiceUpdateInput {\n id: string;\n scheduleOn: ScheduledOnType;\n}\n\nexport type ISchedulerServiceCreateResponse = CreateScheduleCommandOutput;\n\nexport type ISchedulerServiceUpdateResponse = UpdateScheduleCommandOutput;\n\nexport type ISchedulerServiceDeleteResponse = DeleteScheduleCommandOutput;\n\nexport interface ISchedulerService {\n create(params: ISchedulerServiceCreateInput): Promise<ISchedulerServiceCreateResponse>;\n update(params: ISchedulerServiceUpdateInput): Promise<ISchedulerServiceUpdateResponse>;\n delete(id: string): Promise<ISchedulerServiceDeleteResponse>;\n exists(id: string): Promise<boolean>;\n}\n"],"mappings":"","ignoreList":[]}
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CmsContext, CmsModel, HeadlessCms } from "@webiny/api-headless-cms/types";
|
|
2
|
+
import type { IScheduler } from "./scheduler/types.js";
|
|
3
|
+
export interface CmsScheduleCallable {
|
|
4
|
+
(model: CmsModel): IScheduler;
|
|
5
|
+
}
|
|
6
|
+
export interface CmsSchedule {
|
|
7
|
+
scheduler: CmsScheduleCallable;
|
|
8
|
+
}
|
|
9
|
+
export interface ScheduleContext extends CmsContext {
|
|
10
|
+
cms: HeadlessCms & CmsSchedule;
|
|
11
|
+
}
|
package/types.js
ADDED
package/types.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type { CmsContext, CmsModel, HeadlessCms } from \"@webiny/api-headless-cms/types\";\nimport type { IScheduler } from \"~/scheduler/types.js\";\n\nexport interface CmsScheduleCallable {\n (model: CmsModel): IScheduler;\n}\n\nexport interface CmsSchedule {\n scheduler: CmsScheduleCallable;\n}\n\nexport interface ScheduleContext extends CmsContext {\n //\n cms: HeadlessCms & CmsSchedule;\n}\n"],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if the provided date is in the future.
|
|
3
|
+
* We need to ensure that the date is at least a SCHEDULE_MIN_FUTURE_MINUTES minutes in the future.
|
|
4
|
+
* Otherwise, we consider it as "immediate" and run the action right away.
|
|
5
|
+
*/
|
|
6
|
+
export declare const dateInTheFuture: (date: Date) => boolean;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.dateInTheFuture = void 0;
|
|
7
|
+
var _constants = require("../constants.js");
|
|
8
|
+
/**
|
|
9
|
+
* Check if the provided date is in the future.
|
|
10
|
+
* We need to ensure that the date is at least a SCHEDULE_MIN_FUTURE_MINUTES minutes in the future.
|
|
11
|
+
* Otherwise, we consider it as "immediate" and run the action right away.
|
|
12
|
+
*/
|
|
13
|
+
const dateInTheFuture = date => {
|
|
14
|
+
const minDate = new Date(Date.now() + _constants.SCHEDULE_MIN_FUTURE_SECONDS * 1000);
|
|
15
|
+
return date.getTime() >= minDate.getTime();
|
|
16
|
+
};
|
|
17
|
+
exports.dateInTheFuture = dateInTheFuture;
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=dateInTheFuture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_constants","require","dateInTheFuture","date","minDate","Date","now","SCHEDULE_MIN_FUTURE_SECONDS","getTime","exports"],"sources":["dateInTheFuture.ts"],"sourcesContent":["import { SCHEDULE_MIN_FUTURE_SECONDS } from \"~/constants.js\";\n\n/**\n * Check if the provided date is in the future.\n * We need to ensure that the date is at least a SCHEDULE_MIN_FUTURE_MINUTES minutes in the future.\n * Otherwise, we consider it as \"immediate\" and run the action right away.\n */\nexport const dateInTheFuture = (date: Date): boolean => {\n const minDate = new Date(Date.now() + SCHEDULE_MIN_FUTURE_SECONDS * 1000);\n\n return date.getTime() >= minDate.getTime();\n};\n"],"mappings":";;;;;;AAAA,IAAAA,UAAA,GAAAC,OAAA;AAEA;AACA;AACA;AACA;AACA;AACO,MAAMC,eAAe,GAAIC,IAAU,IAAc;EACpD,MAAMC,OAAO,GAAG,IAAIC,IAAI,CAACA,IAAI,CAACC,GAAG,CAAC,CAAC,GAAGC,sCAA2B,GAAG,IAAI,CAAC;EAEzE,OAAOJ,IAAI,CAACK,OAAO,CAAC,CAAC,IAAIJ,OAAO,CAACI,OAAO,CAAC,CAAC;AAC9C,CAAC;AAACC,OAAA,CAAAP,eAAA,GAAAA,eAAA","ignoreList":[]}
|