@webiny/api-scheduler-aws 0.0.0-unstable.0156a4c312
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 +11 -0
- package/SchedulerAwsFeature.d.ts +10 -0
- package/SchedulerAwsFeature.js +14 -0
- package/SchedulerAwsFeature.js.map +1 -0
- package/context.d.ts +16 -0
- package/context.js +8 -0
- package/context.js.map +1 -0
- package/createEventHandler.d.ts +10 -0
- package/createEventHandler.js +0 -0
- package/features/SchedulerService/EventBridgeSchedulerService.d.ts +21 -0
- package/features/SchedulerService/EventBridgeSchedulerService.js +116 -0
- package/features/SchedulerService/EventBridgeSchedulerService.js.map +1 -0
- package/features/SchedulerService/LazySchedulerService.d.ts +4 -0
- package/features/SchedulerService/LazySchedulerService.js +32 -0
- package/features/SchedulerService/LazySchedulerService.js.map +1 -0
- package/index.d.ts +3 -0
- package/index.js +2 -0
- package/manifest.d.ts +13 -0
- package/manifest.js +34 -0
- package/manifest.js.map +1 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Webiny
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# @webiny/api-scheduler-aws
|
|
2
|
+
|
|
3
|
+
> [!NOTE]
|
|
4
|
+
> This package is part of the [Webiny](https://www.webiny.com) monorepo.
|
|
5
|
+
> Itβs **included in every Webiny project by default** and is not meant to be used as a standalone package.
|
|
6
|
+
|
|
7
|
+
π **Documentation:** [https://www.webiny.com/docs](https://www.webiny.com/docs)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
_This README file is automatically generated during the publish process._
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS (EventBridge Scheduler) transport. Wraps `registerSchedulerAwsExtension` with the default
|
|
3
|
+
* scheduler client so the handler's `transports` wiring reads uniformly
|
|
4
|
+
* (`SchedulerAwsFeature.register(c)`), matching the other transport adapters. Callers that need a
|
|
5
|
+
* custom client can still use `registerSchedulerAwsExtension` directly.
|
|
6
|
+
*/
|
|
7
|
+
export declare const SchedulerAwsFeature: {
|
|
8
|
+
name: string;
|
|
9
|
+
register(container: import("@webiny/di").Container): void;
|
|
10
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createFeature } from "@webiny/feature/api";
|
|
2
|
+
import { createSchedulerClient } from "@webiny/aws-sdk/client-scheduler/index.js";
|
|
3
|
+
import { registerSchedulerAwsExtension } from "./context.js";
|
|
4
|
+
const SchedulerAwsFeature = createFeature({
|
|
5
|
+
name: "SchedulerAws",
|
|
6
|
+
register (container) {
|
|
7
|
+
registerSchedulerAwsExtension(container, {
|
|
8
|
+
getClient: (config)=>createSchedulerClient(config)
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
export { SchedulerAwsFeature };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=SchedulerAwsFeature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchedulerAwsFeature.js","sources":["../src/SchedulerAwsFeature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { createSchedulerClient } from \"@webiny/aws-sdk/client-scheduler/index.js\";\nimport { registerSchedulerAwsExtension } from \"./context.js\";\n\n/**\n * AWS (EventBridge Scheduler) transport. Wraps `registerSchedulerAwsExtension` with the default\n * scheduler client so the handler's `transports` wiring reads uniformly\n * (`SchedulerAwsFeature.register(c)`), matching the other transport adapters. Callers that need a\n * custom client can still use `registerSchedulerAwsExtension` directly.\n */\nexport const SchedulerAwsFeature = createFeature({\n name: \"SchedulerAws\",\n register(container) {\n registerSchedulerAwsExtension(container, {\n getClient: config => createSchedulerClient(config)\n });\n }\n});\n"],"names":["SchedulerAwsFeature","createFeature","container","registerSchedulerAwsExtension","config","createSchedulerClient"],"mappings":";;;AAUO,MAAMA,sBAAsBC,cAAc;IAC7C,MAAM;IACN,UAASC,SAAS;QACdC,8BAA8BD,WAAW;YACrC,WAAWE,CAAAA,SAAUC,sBAAsBD;QAC/C;IACJ;AACJ"}
|
package/context.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Container } from "@webiny/di";
|
|
2
|
+
import type { SchedulerClient, SchedulerClientConfig } from "@webiny/aws-sdk/client-scheduler/index.js";
|
|
3
|
+
export interface IRegisterSchedulerAwsExtensionParams {
|
|
4
|
+
getClient(config?: SchedulerClientConfig): Pick<SchedulerClient, "send">;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Registers the AWS (EventBridge Scheduler) transport for the scheduler.
|
|
8
|
+
*
|
|
9
|
+
* `SchedulerService` is bound at register time to a lazy implementation that reads the deployed
|
|
10
|
+
* scheduler manifest on first use and delegates to either the EventBridge service or the no-op Void
|
|
11
|
+
* service. Previously this was a per-request `RequestContextInitializer`, because the manifest read
|
|
12
|
+
* is async and DI resolution is not β along with a `getTenant()` guard, since a fixed-time hook can
|
|
13
|
+
* fire before the tenant is established. Neither is needed once the async work moves into the
|
|
14
|
+
* methods, which were already async.
|
|
15
|
+
*/
|
|
16
|
+
export declare const registerSchedulerAwsExtension: (container: Container, params: IRegisterSchedulerAwsExtensionParams) => void;
|
package/context.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SchedulerService } from "@webiny/api-scheduler/shared/abstractions.js";
|
|
2
|
+
import { createLazySchedulerService } from "./features/SchedulerService/LazySchedulerService.js";
|
|
3
|
+
const registerSchedulerAwsExtension = (container, params)=>{
|
|
4
|
+
container.registerInstance(SchedulerService, createLazySchedulerService(params.getClient));
|
|
5
|
+
};
|
|
6
|
+
export { registerSchedulerAwsExtension };
|
|
7
|
+
|
|
8
|
+
//# sourceMappingURL=context.js.map
|
package/context.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sources":["../src/context.ts"],"sourcesContent":["import type { Container } from \"@webiny/di\";\nimport type {\n SchedulerClient,\n SchedulerClientConfig\n} from \"@webiny/aws-sdk/client-scheduler/index.js\";\nimport { SchedulerService } from \"@webiny/api-scheduler/shared/abstractions.js\";\nimport { createLazySchedulerService } from \"~/features/SchedulerService/LazySchedulerService.js\";\n\nexport interface IRegisterSchedulerAwsExtensionParams {\n getClient(config?: SchedulerClientConfig): Pick<SchedulerClient, \"send\">;\n}\n\n/**\n * Registers the AWS (EventBridge Scheduler) transport for the scheduler.\n *\n * `SchedulerService` is bound at register time to a lazy implementation that reads the deployed\n * scheduler manifest on first use and delegates to either the EventBridge service or the no-op Void\n * service. Previously this was a per-request `RequestContextInitializer`, because the manifest read\n * is async and DI resolution is not β along with a `getTenant()` guard, since a fixed-time hook can\n * fire before the tenant is established. Neither is needed once the async work moves into the\n * methods, which were already async.\n */\nexport const registerSchedulerAwsExtension = (\n container: Container,\n params: IRegisterSchedulerAwsExtensionParams\n) => {\n container.registerInstance(SchedulerService, createLazySchedulerService(params.getClient));\n};\n"],"names":["registerSchedulerAwsExtension","container","params","SchedulerService","createLazySchedulerService"],"mappings":";;AAsBO,MAAMA,gCAAgC,CACzCC,WACAC;IAEAD,UAAU,gBAAgB,CAACE,kBAAkBC,2BAA2BF,OAAO,SAAS;AAC5F"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SCHEDULED_ACTION_EVENT_IDENTIFIER } from "@webiny/api-scheduler/constants.js";
|
|
2
|
+
export interface IScheduledActionEventPayload {
|
|
3
|
+
namespace: string;
|
|
4
|
+
id: string;
|
|
5
|
+
scheduleFor: string;
|
|
6
|
+
tenant: string;
|
|
7
|
+
}
|
|
8
|
+
export interface IScheduledActionEvent {
|
|
9
|
+
[SCHEDULED_ACTION_EVENT_IDENTIFIER]: IScheduledActionEventPayload;
|
|
10
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SchedulerService } from "@webiny/api-scheduler/shared/abstractions.js";
|
|
2
|
+
import { type SchedulerClient } from "@webiny/aws-sdk/client-scheduler/index.js";
|
|
3
|
+
export interface ISchedulerConfig {
|
|
4
|
+
lambdaArn: string;
|
|
5
|
+
roleArn: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class EventBridgeSchedulerService implements SchedulerService.Interface {
|
|
8
|
+
private getClient;
|
|
9
|
+
private config;
|
|
10
|
+
constructor(getClient: (config?: any) => Pick<SchedulerClient, "send">, config: ISchedulerConfig);
|
|
11
|
+
create(params: SchedulerService.CreateParams): Promise<void>;
|
|
12
|
+
update(params: SchedulerService.UpdateParams): Promise<void>;
|
|
13
|
+
private sendCreate;
|
|
14
|
+
private sendUpdate;
|
|
15
|
+
delete(params: SchedulerService.DeleteParams): Promise<void>;
|
|
16
|
+
exists(params: SchedulerService.ExistsParams): Promise<boolean>;
|
|
17
|
+
private createScheduleExpression;
|
|
18
|
+
private createScheduledActionEventInput;
|
|
19
|
+
private createScheduledActionEventPayload;
|
|
20
|
+
private createScheduleName;
|
|
21
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { WebinyError } from "@webiny/error";
|
|
2
|
+
import { CreateScheduleCommand, DeleteScheduleCommand, GetScheduleCommand, UpdateScheduleCommand } from "@webiny/aws-sdk/client-scheduler/index.js";
|
|
3
|
+
import { SCHEDULED_ACTION_EVENT_IDENTIFIER } from "@webiny/api-scheduler/constants.js";
|
|
4
|
+
class EventBridgeSchedulerService {
|
|
5
|
+
constructor(getClient, config){
|
|
6
|
+
this.getClient = getClient;
|
|
7
|
+
this.config = config;
|
|
8
|
+
}
|
|
9
|
+
async create(params) {
|
|
10
|
+
const { id, scheduleFor, tenant, namespace } = params;
|
|
11
|
+
if (scheduleFor <= new Date()) throw new WebinyError(`Cannot create a schedule for "${id}" with date in the past`, "INVALID_SCHEDULE_DATE", {
|
|
12
|
+
scheduleFor,
|
|
13
|
+
tenant,
|
|
14
|
+
id
|
|
15
|
+
});
|
|
16
|
+
const exists = await this.exists({
|
|
17
|
+
id,
|
|
18
|
+
tenant,
|
|
19
|
+
namespace
|
|
20
|
+
});
|
|
21
|
+
if (exists) return this.sendUpdate(params);
|
|
22
|
+
return this.sendCreate(params);
|
|
23
|
+
}
|
|
24
|
+
async update(params) {
|
|
25
|
+
const { id, scheduleFor } = params;
|
|
26
|
+
if (scheduleFor <= new Date()) throw new WebinyError(`Cannot update an existing schedule for "${id}" with date in the past`, "INVALID_SCHEDULE_DATE", {
|
|
27
|
+
scheduleFor,
|
|
28
|
+
id
|
|
29
|
+
});
|
|
30
|
+
const exists = await this.exists(params);
|
|
31
|
+
if (!exists) return this.sendCreate(params);
|
|
32
|
+
return this.sendUpdate(params);
|
|
33
|
+
}
|
|
34
|
+
async sendCreate(params) {
|
|
35
|
+
const client = this.getClient();
|
|
36
|
+
await client.send(new CreateScheduleCommand({
|
|
37
|
+
Name: this.createScheduleName(params),
|
|
38
|
+
ScheduleExpression: this.createScheduleExpression(params.scheduleFor),
|
|
39
|
+
FlexibleTimeWindow: {
|
|
40
|
+
Mode: "OFF"
|
|
41
|
+
},
|
|
42
|
+
Target: {
|
|
43
|
+
Arn: this.config.lambdaArn,
|
|
44
|
+
RoleArn: this.config.roleArn,
|
|
45
|
+
Input: this.createScheduledActionEventInput(params)
|
|
46
|
+
},
|
|
47
|
+
ActionAfterCompletion: "DELETE"
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
async sendUpdate(params) {
|
|
51
|
+
const client = this.getClient();
|
|
52
|
+
await client.send(new UpdateScheduleCommand({
|
|
53
|
+
Name: this.createScheduleName(params),
|
|
54
|
+
ScheduleExpression: this.createScheduleExpression(params.scheduleFor),
|
|
55
|
+
FlexibleTimeWindow: {
|
|
56
|
+
Mode: "OFF"
|
|
57
|
+
},
|
|
58
|
+
Target: {
|
|
59
|
+
Arn: this.config.lambdaArn,
|
|
60
|
+
RoleArn: this.config.roleArn,
|
|
61
|
+
Input: this.createScheduledActionEventInput(params)
|
|
62
|
+
},
|
|
63
|
+
ActionAfterCompletion: "DELETE"
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
async delete(params) {
|
|
67
|
+
const client = this.getClient();
|
|
68
|
+
const exists = await this.exists(params);
|
|
69
|
+
if (!exists) throw new WebinyError(`Cannot delete schedule "${params.id}", tenant "${params.tenant}", because it does not exist.`);
|
|
70
|
+
const name = this.createScheduleName(params);
|
|
71
|
+
try {
|
|
72
|
+
await client.send(new DeleteScheduleCommand({
|
|
73
|
+
Name: name
|
|
74
|
+
}));
|
|
75
|
+
} catch (ex) {
|
|
76
|
+
if ("ResourceNotFoundException" === ex.name) return;
|
|
77
|
+
throw WebinyError.from(ex);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async exists(params) {
|
|
81
|
+
const client = this.getClient();
|
|
82
|
+
const name = this.createScheduleName(params);
|
|
83
|
+
try {
|
|
84
|
+
await client.send(new GetScheduleCommand({
|
|
85
|
+
Name: name
|
|
86
|
+
}));
|
|
87
|
+
return true;
|
|
88
|
+
} catch (ex) {
|
|
89
|
+
if ("ResourceNotFoundException" === ex.name) return false;
|
|
90
|
+
throw ex;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
createScheduleExpression(scheduleFor) {
|
|
94
|
+
return `at(${scheduleFor.toISOString().replace(/\.\d{3}Z$/, "")})`;
|
|
95
|
+
}
|
|
96
|
+
createScheduledActionEventInput(params) {
|
|
97
|
+
return JSON.stringify({
|
|
98
|
+
[SCHEDULED_ACTION_EVENT_IDENTIFIER]: this.createScheduledActionEventPayload(params)
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
createScheduledActionEventPayload(params) {
|
|
102
|
+
const { id, scheduleFor, tenant, namespace } = params;
|
|
103
|
+
return {
|
|
104
|
+
id,
|
|
105
|
+
tenant,
|
|
106
|
+
namespace,
|
|
107
|
+
scheduleFor: scheduleFor.toISOString()
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
createScheduleName(params) {
|
|
111
|
+
return params.id;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export { EventBridgeSchedulerService };
|
|
115
|
+
|
|
116
|
+
//# sourceMappingURL=EventBridgeSchedulerService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features/SchedulerService/EventBridgeSchedulerService.js","sources":["../../../src/features/SchedulerService/EventBridgeSchedulerService.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport {\n type ISchedulerServiceCreateParams,\n type ISchedulerServiceUpdateParams,\n SchedulerService\n} from \"@webiny/api-scheduler/shared/abstractions.js\";\nimport {\n CreateScheduleCommand,\n DeleteScheduleCommand,\n GetScheduleCommand,\n type SchedulerClient,\n UpdateScheduleCommand\n} from \"@webiny/aws-sdk/client-scheduler/index.js\";\nimport { SCHEDULED_ACTION_EVENT_IDENTIFIER } from \"@webiny/api-scheduler/constants.js\";\nimport type { IScheduledActionEventPayload } from \"~/createEventHandler.js\";\n\nexport interface ISchedulerConfig {\n lambdaArn: string;\n roleArn: string;\n}\n\nexport class EventBridgeSchedulerService implements SchedulerService.Interface {\n public constructor(\n private getClient: (config?: any) => Pick<SchedulerClient, \"send\">,\n private config: ISchedulerConfig\n ) {}\n\n public async create(params: SchedulerService.CreateParams): Promise<void> {\n const { id, scheduleFor, tenant, namespace } = params;\n\n if (scheduleFor <= new Date()) {\n throw new WebinyError(\n `Cannot create a schedule for \"${id}\" with date in the past`,\n \"INVALID_SCHEDULE_DATE\",\n {\n scheduleFor,\n tenant,\n id\n }\n );\n }\n\n const exists = await this.exists({\n id,\n tenant,\n namespace\n });\n if (exists) {\n return this.sendUpdate(params);\n }\n\n return this.sendCreate(params);\n }\n\n public async update(params: SchedulerService.UpdateParams): Promise<void> {\n const { id, scheduleFor } = params;\n\n if (scheduleFor <= new Date()) {\n throw new WebinyError(\n `Cannot update an existing schedule for \"${id}\" with date in the past`,\n \"INVALID_SCHEDULE_DATE\",\n {\n scheduleFor,\n id\n }\n );\n }\n\n /*\n * The schedule can be gone while the scheduled action still exists, for example after a\n * failed or manual cleanup. UpdateScheduleCommand would then fail, so create it instead.\n */\n const exists = await this.exists(params);\n if (!exists) {\n return this.sendCreate(params);\n }\n\n return this.sendUpdate(params);\n }\n\n private async sendCreate(params: SchedulerService.CreateParams): Promise<void> {\n const client = this.getClient();\n\n await client.send(\n new CreateScheduleCommand({\n Name: this.createScheduleName(params),\n ScheduleExpression: this.createScheduleExpression(params.scheduleFor),\n FlexibleTimeWindow: {\n Mode: \"OFF\"\n },\n Target: {\n Arn: this.config.lambdaArn,\n RoleArn: this.config.roleArn,\n Input: this.createScheduledActionEventInput(params)\n },\n ActionAfterCompletion: \"DELETE\"\n })\n );\n }\n\n private async sendUpdate(params: SchedulerService.UpdateParams): Promise<void> {\n const client = this.getClient();\n\n await client.send(\n new UpdateScheduleCommand({\n Name: this.createScheduleName(params),\n ScheduleExpression: this.createScheduleExpression(params.scheduleFor),\n FlexibleTimeWindow: {\n Mode: \"OFF\"\n },\n Target: {\n Arn: this.config.lambdaArn,\n RoleArn: this.config.roleArn,\n Input: this.createScheduledActionEventInput(params)\n },\n ActionAfterCompletion: \"DELETE\"\n })\n );\n }\n\n public async delete(params: SchedulerService.DeleteParams): Promise<void> {\n const client = this.getClient();\n\n const exists = await this.exists(params);\n if (!exists) {\n throw new WebinyError(\n `Cannot delete schedule \"${params.id}\", tenant \"${params.tenant}\", because it does not exist.`\n );\n }\n\n const name = this.createScheduleName(params);\n\n try {\n await client.send(new DeleteScheduleCommand({ Name: name }));\n } catch (ex) {\n if (ex.name === \"ResourceNotFoundException\") {\n return;\n }\n throw WebinyError.from(ex);\n }\n }\n\n public async exists(params: SchedulerService.ExistsParams): Promise<boolean> {\n const client = this.getClient();\n\n const name = this.createScheduleName(params);\n\n try {\n await client.send(new GetScheduleCommand({ Name: name }));\n return true;\n } catch (ex) {\n if (ex.name === \"ResourceNotFoundException\") {\n return false;\n }\n throw ex;\n }\n }\n\n private createScheduleExpression(scheduleFor: Date): string {\n return `at(${scheduleFor.toISOString().replace(/\\.\\d{3}Z$/, \"\")})`;\n }\n\n private createScheduledActionEventInput(\n params: ISchedulerServiceCreateParams | ISchedulerServiceUpdateParams\n ): string {\n return JSON.stringify({\n [SCHEDULED_ACTION_EVENT_IDENTIFIER]: this.createScheduledActionEventPayload(params)\n });\n }\n\n private createScheduledActionEventPayload(\n params: SchedulerService.CreateParams | SchedulerService.UpdateParams\n ): IScheduledActionEventPayload {\n const { id, scheduleFor, tenant, namespace } = params;\n\n return {\n id,\n tenant,\n namespace,\n scheduleFor: scheduleFor.toISOString()\n };\n }\n\n private createScheduleName(params: SchedulerService.ExistsParams): string {\n // AWS EventBridge Scheduler names must match [0-9a-zA-Z-_.]+ and be <= 64 chars. `id`\n // (ScheduledActionId: \"wby-schedule-<hash>\") already satisfies both and is unique per\n // namespace + action type + target, so use it verbatim. Do NOT interpolate `namespace`\n // (contains \"/\", e.g. \"Cms/Entry/<modelId>\") or `tenant` β that produced names with illegal\n // characters that exceeded the length limit (ValidationException).\n return params.id;\n }\n}\n"],"names":["EventBridgeSchedulerService","getClient","config","params","id","scheduleFor","tenant","namespace","Date","WebinyError","exists","client","CreateScheduleCommand","UpdateScheduleCommand","name","DeleteScheduleCommand","ex","GetScheduleCommand","JSON","SCHEDULED_ACTION_EVENT_IDENTIFIER"],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SchedulerClient, SchedulerClientConfig } from "@webiny/aws-sdk/client-scheduler/index.js";
|
|
2
|
+
import { SchedulerService } from "@webiny/api-scheduler/shared/abstractions.js";
|
|
3
|
+
export type GetSchedulerClient = (config?: SchedulerClientConfig) => Pick<SchedulerClient, "send">;
|
|
4
|
+
export declare const createLazySchedulerService: (getClient: GetSchedulerClient) => SchedulerService.Interface;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { VoidSchedulerService } from "@webiny/api-scheduler/features/SchedulerService/VoidSchedulerService.js";
|
|
2
|
+
import { getManifest } from "../../manifest.js";
|
|
3
|
+
import { EventBridgeSchedulerService } from "./EventBridgeSchedulerService.js";
|
|
4
|
+
class LazySchedulerServiceImpl {
|
|
5
|
+
constructor(getClient){
|
|
6
|
+
this.getClient = getClient;
|
|
7
|
+
}
|
|
8
|
+
async service() {
|
|
9
|
+
const manifest = await getManifest();
|
|
10
|
+
if (manifest.error) return new VoidSchedulerService();
|
|
11
|
+
return new EventBridgeSchedulerService(this.getClient, {
|
|
12
|
+
lambdaArn: manifest.data.lambdaArn,
|
|
13
|
+
roleArn: manifest.data.roleArn
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
async create(params) {
|
|
17
|
+
return (await this.service()).create(params);
|
|
18
|
+
}
|
|
19
|
+
async update(params) {
|
|
20
|
+
return (await this.service()).update(params);
|
|
21
|
+
}
|
|
22
|
+
async delete(params) {
|
|
23
|
+
return (await this.service()).delete(params);
|
|
24
|
+
}
|
|
25
|
+
async exists(params) {
|
|
26
|
+
return (await this.service()).exists(params);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const createLazySchedulerService = (getClient)=>new LazySchedulerServiceImpl(getClient);
|
|
30
|
+
export { createLazySchedulerService };
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=LazySchedulerService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features/SchedulerService/LazySchedulerService.js","sources":["../../../src/features/SchedulerService/LazySchedulerService.ts"],"sourcesContent":["import type {\n SchedulerClient,\n SchedulerClientConfig\n} from \"@webiny/aws-sdk/client-scheduler/index.js\";\nimport { SchedulerService } from \"@webiny/api-scheduler/shared/abstractions.js\";\nimport { VoidSchedulerService } from \"@webiny/api-scheduler/features/SchedulerService/VoidSchedulerService.js\";\nimport { getManifest } from \"~/manifest.js\";\nimport { EventBridgeSchedulerService } from \"./EventBridgeSchedulerService.js\";\n\nexport type GetSchedulerClient = (config?: SchedulerClientConfig) => Pick<SchedulerClient, \"send\">;\n\n/**\n * Picks the real EventBridge service or the no-op Void service, deciding on first use rather than\n * up front.\n *\n * The choice depends on the deployed scheduler manifest, and reading it is async β which is why\n * this used to be a per-request `RequestContextInitializer` that resolved the manifest and then\n * registered whichever service it implied. Every method here is already async, so the decision can\n * simply be awaited at the point of use instead.\n *\n * No memoization: `ServiceDiscovery.load()` caches the manifest in a process-wide static, so\n * `getManifest()` is cheap after the first call.\n */\nclass LazySchedulerServiceImpl implements SchedulerService.Interface {\n constructor(private getClient: GetSchedulerClient) {}\n\n private async service(): Promise<SchedulerService.Interface> {\n const manifest = await getManifest();\n\n if (manifest.error) {\n return new VoidSchedulerService();\n }\n\n return new EventBridgeSchedulerService(this.getClient, {\n lambdaArn: manifest.data.lambdaArn,\n roleArn: manifest.data.roleArn\n });\n }\n\n async create(params: SchedulerService.CreateParams): Promise<void> {\n return (await this.service()).create(params);\n }\n\n async update(params: SchedulerService.UpdateParams): Promise<void> {\n return (await this.service()).update(params);\n }\n\n async delete(params: SchedulerService.DeleteParams): Promise<void> {\n return (await this.service()).delete(params);\n }\n\n async exists(params: SchedulerService.ExistsParams): Promise<boolean> {\n return (await this.service()).exists(params);\n }\n}\n\nexport const createLazySchedulerService = (\n getClient: GetSchedulerClient\n): SchedulerService.Interface => new LazySchedulerServiceImpl(getClient);\n"],"names":["LazySchedulerServiceImpl","getClient","manifest","getManifest","VoidSchedulerService","EventBridgeSchedulerService","params","createLazySchedulerService"],"mappings":";;;AAuBA,MAAMA;IACF,YAAoBC,SAA6B,CAAE;aAA/BA,SAAS,GAATA;IAAgC;IAEpD,MAAc,UAA+C;QACzD,MAAMC,WAAW,MAAMC;QAEvB,IAAID,SAAS,KAAK,EACd,OAAO,IAAIE;QAGf,OAAO,IAAIC,4BAA4B,IAAI,CAAC,SAAS,EAAE;YACnD,WAAWH,SAAS,IAAI,CAAC,SAAS;YAClC,SAASA,SAAS,IAAI,CAAC,OAAO;QAClC;IACJ;IAEA,MAAM,OAAOI,MAAqC,EAAiB;QAC/D,OAAQ,OAAM,IAAI,CAAC,OAAO,EAAC,EAAG,MAAM,CAACA;IACzC;IAEA,MAAM,OAAOA,MAAqC,EAAiB;QAC/D,OAAQ,OAAM,IAAI,CAAC,OAAO,EAAC,EAAG,MAAM,CAACA;IACzC;IAEA,MAAM,OAAOA,MAAqC,EAAiB;QAC/D,OAAQ,OAAM,IAAI,CAAC,OAAO,EAAC,EAAG,MAAM,CAACA;IACzC;IAEA,MAAM,OAAOA,MAAqC,EAAoB;QAClE,OAAQ,OAAM,IAAI,CAAC,OAAO,EAAC,EAAG,MAAM,CAACA;IACzC;AACJ;AAEO,MAAMC,6BAA6B,CACtCN,YAC6B,IAAID,yBAAyBC"}
|
package/index.d.ts
ADDED
package/index.js
ADDED
package/manifest.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface IGetManifestErrorResult {
|
|
2
|
+
error: Error;
|
|
3
|
+
data?: never;
|
|
4
|
+
}
|
|
5
|
+
export interface IGetManifestSuccessResult {
|
|
6
|
+
data: {
|
|
7
|
+
lambdaArn: string;
|
|
8
|
+
roleArn: string;
|
|
9
|
+
};
|
|
10
|
+
error?: never;
|
|
11
|
+
}
|
|
12
|
+
export type IGetManifestResult = IGetManifestSuccessResult | IGetManifestErrorResult;
|
|
13
|
+
export declare const getManifest: () => Promise<IGetManifestResult>;
|
package/manifest.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ServiceDiscovery } from "@webiny/api-core/features/serviceDiscovery/index.js";
|
|
2
|
+
import { createZodError } from "@webiny/utils";
|
|
3
|
+
import zod from "zod";
|
|
4
|
+
const schema = zod.object({
|
|
5
|
+
scheduler: zod.object({
|
|
6
|
+
lambdaArn: zod.string(),
|
|
7
|
+
roleArn: zod.string()
|
|
8
|
+
})
|
|
9
|
+
});
|
|
10
|
+
const getManifest = async ()=>{
|
|
11
|
+
try {
|
|
12
|
+
const manifest = await ServiceDiscovery.load();
|
|
13
|
+
if (!manifest) return {
|
|
14
|
+
error: new Error("Manifest could not be loaded.")
|
|
15
|
+
};
|
|
16
|
+
else if (!manifest.scheduler) return {
|
|
17
|
+
error: new Error("Scheduler not found in the Manifest.")
|
|
18
|
+
};
|
|
19
|
+
const result = await schema.safeParseAsync(manifest);
|
|
20
|
+
if (!result.success) return {
|
|
21
|
+
error: createZodError(result.error)
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
data: result.data.scheduler
|
|
25
|
+
};
|
|
26
|
+
} catch (ex) {
|
|
27
|
+
return {
|
|
28
|
+
error: ex
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
export { getManifest };
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=manifest.js.map
|
package/manifest.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sources":["../src/manifest.ts"],"sourcesContent":["import { ServiceDiscovery } from \"@webiny/api-core/features/serviceDiscovery/index.js\";\nimport { createZodError } from \"@webiny/utils\";\nimport zod from \"zod\";\n\nconst schema = zod.object({\n scheduler: zod.object({\n lambdaArn: zod.string(),\n roleArn: zod.string()\n })\n});\n\nexport interface IGetManifestErrorResult {\n error: Error;\n data?: never;\n}\n\nexport interface IGetManifestSuccessResult {\n data: {\n lambdaArn: string;\n roleArn: string;\n };\n error?: never;\n}\n\nexport type IGetManifestResult = IGetManifestSuccessResult | IGetManifestErrorResult;\n\nexport const getManifest = async (): Promise<IGetManifestResult> => {\n try {\n const manifest = await ServiceDiscovery.load();\n if (!manifest) {\n return {\n error: new Error(\"Manifest could not be loaded.\")\n };\n } else if (!manifest.scheduler) {\n return {\n error: new Error(\"Scheduler not found in the Manifest.\")\n };\n }\n\n const result = await schema.safeParseAsync(manifest);\n if (!result.success) {\n return {\n error: createZodError(result.error)\n };\n }\n\n return {\n data: result.data.scheduler\n };\n } catch (ex) {\n return {\n error: ex\n };\n }\n};\n"],"names":["schema","zod","getManifest","manifest","ServiceDiscovery","Error","result","createZodError","ex"],"mappings":";;;AAIA,MAAMA,SAASC,IAAI,MAAM,CAAC;IACtB,WAAWA,IAAI,MAAM,CAAC;QAClB,WAAWA,IAAI,MAAM;QACrB,SAASA,IAAI,MAAM;IACvB;AACJ;AAiBO,MAAMC,cAAc;IACvB,IAAI;QACA,MAAMC,WAAW,MAAMC,iBAAiB,IAAI;QAC5C,IAAI,CAACD,UACD,OAAO;YACH,OAAO,IAAIE,MAAM;QACrB;aACG,IAAI,CAACF,SAAS,SAAS,EAC1B,OAAO;YACH,OAAO,IAAIE,MAAM;QACrB;QAGJ,MAAMC,SAAS,MAAMN,OAAO,cAAc,CAACG;QAC3C,IAAI,CAACG,OAAO,OAAO,EACf,OAAO;YACH,OAAOC,eAAeD,OAAO,KAAK;QACtC;QAGJ,OAAO;YACH,MAAMA,OAAO,IAAI,CAAC,SAAS;QAC/B;IACJ,EAAE,OAAOE,IAAI;QACT,OAAO;YACH,OAAOA;QACX;IACJ;AACJ"}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@webiny/api-scheduler-aws",
|
|
3
|
+
"version": "0.0.0-unstable.0156a4c312",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./index.js",
|
|
7
|
+
"./*": "./*"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/webiny/webiny-js.git",
|
|
12
|
+
"directory": "packages/api-scheduler-aws"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"scheduler:aws"
|
|
16
|
+
],
|
|
17
|
+
"author": "Webiny Ltd",
|
|
18
|
+
"description": "AWS EventBridge implementation for the Webiny action scheduler.",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@webiny/api": "0.0.0-unstable.0156a4c312",
|
|
22
|
+
"@webiny/api-core": "0.0.0-unstable.0156a4c312",
|
|
23
|
+
"@webiny/api-headless-cms": "0.0.0-unstable.0156a4c312",
|
|
24
|
+
"@webiny/api-scheduler": "0.0.0-unstable.0156a4c312",
|
|
25
|
+
"@webiny/aws-sdk": "0.0.0-unstable.0156a4c312",
|
|
26
|
+
"@webiny/error": "0.0.0-unstable.0156a4c312",
|
|
27
|
+
"@webiny/utils": "0.0.0-unstable.0156a4c312",
|
|
28
|
+
"zod": "4.6.7"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@webiny/api-core": "0.0.0-unstable.0156a4c312",
|
|
32
|
+
"@webiny/api-core-testing": "0.0.0-unstable.0156a4c312",
|
|
33
|
+
"@webiny/api-graphql": "0.0.0-unstable.0156a4c312",
|
|
34
|
+
"@webiny/api-headless-cms": "0.0.0-unstable.0156a4c312",
|
|
35
|
+
"@webiny/build-tools": "0.0.0-unstable.0156a4c312",
|
|
36
|
+
"@webiny/db-dynamodb": "0.0.0-unstable.0156a4c312",
|
|
37
|
+
"@webiny/di": "2.0.0",
|
|
38
|
+
"@webiny/event-handler-aws": "0.0.0-unstable.0156a4c312",
|
|
39
|
+
"@webiny/event-handler-core": "0.0.0-unstable.0156a4c312",
|
|
40
|
+
"@webiny/feature": "0.0.0-unstable.0156a4c312",
|
|
41
|
+
"@webiny/handler": "0.0.0-unstable.0156a4c312",
|
|
42
|
+
"@webiny/logger": "0.0.0-unstable.0156a4c312",
|
|
43
|
+
"@webiny/wcp": "0.0.0-unstable.0156a4c312",
|
|
44
|
+
"aws-sdk-client-mock": "4.1.0",
|
|
45
|
+
"graphql": "16.14.2",
|
|
46
|
+
"typescript": "7.0.2",
|
|
47
|
+
"vitest": "5.0.5"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
},
|
|
52
|
+
"webiny": {
|
|
53
|
+
"publishFrom": "dist"
|
|
54
|
+
}
|
|
55
|
+
}
|