@awsless/awsless 0.0.16 → 0.0.18
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/README.MD +207 -1
- package/dist/bin.cjs +69 -49
- package/dist/bin.js +69 -49
- package/dist/index.cjs +5 -0
- package/dist/index.d.ts +413 -305
- package/dist/index.js +4 -0
- package/package.json +1 -4
package/README.MD
CHANGED
|
@@ -1,6 +1,212 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
TODO:
|
|
3
|
+
# TODO:
|
|
4
4
|
- onFailure for lambda, sqs, dynamodb streams
|
|
5
5
|
- add cache plugin & think about VPC lambda solutions
|
|
6
6
|
- add fargate container stuff for long lived services
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
---
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Features
|
|
14
|
+
|
|
15
|
+
- Domains
|
|
16
|
+
- Functions
|
|
17
|
+
- Database
|
|
18
|
+
- Tables
|
|
19
|
+
- Stores
|
|
20
|
+
- Caches
|
|
21
|
+
- Searchs
|
|
22
|
+
- Queues
|
|
23
|
+
- Topics
|
|
24
|
+
- Pubsub
|
|
25
|
+
- Crons
|
|
26
|
+
- API
|
|
27
|
+
- HTTP
|
|
28
|
+
- GraphQL
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## Domains
|
|
32
|
+
|
|
33
|
+
We use AWS Route53 to provide domain management.
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
{
|
|
37
|
+
domains: {
|
|
38
|
+
'example.com': [{
|
|
39
|
+
name: 'sub',
|
|
40
|
+
type: 'A',
|
|
41
|
+
records: [ ... ],
|
|
42
|
+
}],
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Functions
|
|
48
|
+
|
|
49
|
+
We use AWS Lambda to provide serverless functions.
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
{
|
|
53
|
+
defaults: {
|
|
54
|
+
function: {
|
|
55
|
+
// Setting default values for all functions...
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
stacks: [{
|
|
59
|
+
functions: {
|
|
60
|
+
FUNCTION_NAME: 'function.ts'
|
|
61
|
+
}
|
|
62
|
+
}]
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Tables
|
|
67
|
+
|
|
68
|
+
We use AWS DynamoDB to provide serverless tables.
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
{
|
|
72
|
+
stacks: [{
|
|
73
|
+
tables: {
|
|
74
|
+
TABLE_NAME: {
|
|
75
|
+
hash: 'id',
|
|
76
|
+
fields: {
|
|
77
|
+
id: 'string',
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}]
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Stores
|
|
86
|
+
|
|
87
|
+
We use AWS S3 to provide serverless key-value storage.
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
{
|
|
91
|
+
stacks: [{
|
|
92
|
+
stores: [ 'STORE_NAME' ]
|
|
93
|
+
}]
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Caches
|
|
98
|
+
|
|
99
|
+
We use AWS MemoryDB to provide __redis compatible__ in-memory storage.
|
|
100
|
+
|
|
101
|
+
_WORK IN PROGRESS..._
|
|
102
|
+
|
|
103
|
+
## Searchs
|
|
104
|
+
|
|
105
|
+
We use AWS Open Search Serverless to provide serverless search api.
|
|
106
|
+
|
|
107
|
+
```js
|
|
108
|
+
{
|
|
109
|
+
stacks: [{
|
|
110
|
+
searchs: [ 'SEARCH_NAME' ]
|
|
111
|
+
}]
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Queues
|
|
116
|
+
|
|
117
|
+
We use AWS SQS to provide serverless queues.
|
|
118
|
+
|
|
119
|
+
```js
|
|
120
|
+
{
|
|
121
|
+
stacks: [{
|
|
122
|
+
queues: {
|
|
123
|
+
QUEUE_NAME: 'queue-consumer.ts',
|
|
124
|
+
}
|
|
125
|
+
}]
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Topics
|
|
130
|
+
|
|
131
|
+
We use AWS SNS to provide serverless pubsub topics.
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
{
|
|
135
|
+
stacks: [{
|
|
136
|
+
topics: {
|
|
137
|
+
TOPIC_NAME: 'topic-consumer.ts',
|
|
138
|
+
}
|
|
139
|
+
}]
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Pubsub
|
|
144
|
+
|
|
145
|
+
We use AWS IoT to provide a serverless mqtt pubsub channel.
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
{
|
|
149
|
+
stacks: [{
|
|
150
|
+
pubsub: {
|
|
151
|
+
PUBSUB_NAME: {
|
|
152
|
+
sql: `SELECT * FROM '$aws/events/presence/connected/+'`,
|
|
153
|
+
consumer: 'pubsub-consumer.ts',
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}]
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Crons
|
|
161
|
+
|
|
162
|
+
We use AWS Event Bridge to provide serverless cron jobs.
|
|
163
|
+
|
|
164
|
+
```js
|
|
165
|
+
{
|
|
166
|
+
stacks: [{
|
|
167
|
+
crons: {
|
|
168
|
+
CRON_NAME: {
|
|
169
|
+
schedule: 'rate(1 day)',
|
|
170
|
+
consumer: 'cron-consumer.ts',
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}]
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## HTTP
|
|
178
|
+
|
|
179
|
+
We use AWS ELB to provide a REST HTTP API.
|
|
180
|
+
|
|
181
|
+
```js
|
|
182
|
+
{
|
|
183
|
+
stacks: [{
|
|
184
|
+
http: {
|
|
185
|
+
HTTP_API_NAME: {
|
|
186
|
+
'GET /posts': 'list-posts.ts',
|
|
187
|
+
'POST /posts': 'create-post.ts',
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}]
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## GraphQL
|
|
195
|
+
|
|
196
|
+
We use AWS AppSync to provide a serverless GraphQL API.
|
|
197
|
+
|
|
198
|
+
```js
|
|
199
|
+
{
|
|
200
|
+
stacks: [{
|
|
201
|
+
graphql: {
|
|
202
|
+
GRAPHQL_API_NAME: {
|
|
203
|
+
schema: 'schema.gql',
|
|
204
|
+
resolvers: {
|
|
205
|
+
'Query posts': 'list-posts.ts',
|
|
206
|
+
'Mutation createPost': 'create-post.ts',
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}]
|
|
211
|
+
}
|
|
212
|
+
```
|
package/dist/bin.cjs
CHANGED
|
@@ -932,6 +932,17 @@ var EventInvokeConfig = class extends Resource {
|
|
|
932
932
|
}
|
|
933
933
|
};
|
|
934
934
|
|
|
935
|
+
// src/plugins/on-failure/util.ts
|
|
936
|
+
var getGlobalOnFailure = ({ config, bootstrap: bootstrap2 }) => {
|
|
937
|
+
return hasOnFailure(config) ? bootstrap2.import("on-failure-queue-arn") : void 0;
|
|
938
|
+
};
|
|
939
|
+
var hasOnFailure = (config) => {
|
|
940
|
+
const onFailure = config.stacks.find((stack) => {
|
|
941
|
+
return typeof stack.onFailure !== "undefined";
|
|
942
|
+
});
|
|
943
|
+
return !!onFailure;
|
|
944
|
+
};
|
|
945
|
+
|
|
935
946
|
// src/plugins/function.ts
|
|
936
947
|
var MemorySizeSchema = SizeSchema.refine(sizeMin(Size.megaBytes(128)), "Minimum memory size is 128 MB").refine(sizeMax(Size.gigaBytes(10)), "Minimum memory size is 10 GB");
|
|
937
948
|
var TimeoutSchema = DurationSchema.refine(durationMin(Duration.seconds(10)), "Minimum timeout duration is 10 seconds").refine(durationMax(Duration.minutes(15)), "Maximum timeout duration is 15 minutes");
|
|
@@ -1054,9 +1065,16 @@ var functionPlugin = definePlugin({
|
|
|
1054
1065
|
name: "function",
|
|
1055
1066
|
schema,
|
|
1056
1067
|
onStack(ctx) {
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1068
|
+
const { config, stack } = ctx;
|
|
1069
|
+
for (const [id, fileOrProps] of Object.entries(ctx.stackConfig.functions || {})) {
|
|
1070
|
+
const props = typeof fileOrProps === "string" ? { ...config.defaults?.function, file: fileOrProps } : { ...config.defaults?.function, ...fileOrProps };
|
|
1071
|
+
const lambda = toLambdaFunction(ctx, id, fileOrProps);
|
|
1072
|
+
const invoke = new EventInvokeConfig(id, {
|
|
1073
|
+
functionName: lambda.name,
|
|
1074
|
+
retryAttempts: props.retryAttempts,
|
|
1075
|
+
onFailure: getGlobalOnFailure(ctx)
|
|
1076
|
+
}).dependsOn(lambda);
|
|
1077
|
+
stack.add(invoke, lambda);
|
|
1060
1078
|
}
|
|
1061
1079
|
}
|
|
1062
1080
|
});
|
|
@@ -1073,11 +1091,6 @@ var toLambdaFunction = (ctx, id, fileOrProps) => {
|
|
|
1073
1091
|
if (props.runtime.startsWith("nodejs")) {
|
|
1074
1092
|
lambda.addEnvironment("AWS_NODEJS_CONNECTION_REUSE_ENABLED", "1");
|
|
1075
1093
|
}
|
|
1076
|
-
const invoke = new EventInvokeConfig(id, {
|
|
1077
|
-
functionName: lambda.name,
|
|
1078
|
-
retryAttempts: props.retryAttempts
|
|
1079
|
-
}).dependsOn(lambda);
|
|
1080
|
-
ctx.stack.add(invoke);
|
|
1081
1094
|
return lambda;
|
|
1082
1095
|
};
|
|
1083
1096
|
|
|
@@ -1392,7 +1405,8 @@ var queuePlugin = definePlugin({
|
|
|
1392
1405
|
});
|
|
1393
1406
|
const lambda = toLambdaFunction(ctx, `queue-${id}`, props.consumer);
|
|
1394
1407
|
const source = new SqsEventSource(id, lambda, {
|
|
1395
|
-
queueArn: queue2.arn
|
|
1408
|
+
queueArn: queue2.arn,
|
|
1409
|
+
onFailure: getGlobalOnFailure(ctx)
|
|
1396
1410
|
});
|
|
1397
1411
|
stack.add(queue2, lambda, source);
|
|
1398
1412
|
bind((lambda2) => {
|
|
@@ -1448,6 +1462,26 @@ var Table = class extends Resource {
|
|
|
1448
1462
|
resources: [this.arn]
|
|
1449
1463
|
};
|
|
1450
1464
|
}
|
|
1465
|
+
attributeDefinitions() {
|
|
1466
|
+
const fields = this.props.fields || {};
|
|
1467
|
+
const attributes = new Set([
|
|
1468
|
+
this.props.hash,
|
|
1469
|
+
this.props.sort,
|
|
1470
|
+
...Object.values(this.props.indexes || {}).map((index) => [
|
|
1471
|
+
index.hash,
|
|
1472
|
+
index.sort
|
|
1473
|
+
])
|
|
1474
|
+
].flat().filter(Boolean));
|
|
1475
|
+
const types = {
|
|
1476
|
+
string: "S",
|
|
1477
|
+
number: "N",
|
|
1478
|
+
binary: "B"
|
|
1479
|
+
};
|
|
1480
|
+
return [...attributes].map((name) => ({
|
|
1481
|
+
AttributeName: name,
|
|
1482
|
+
AttributeType: types[fields[name] || "string"]
|
|
1483
|
+
}));
|
|
1484
|
+
}
|
|
1451
1485
|
properties() {
|
|
1452
1486
|
return {
|
|
1453
1487
|
TableName: this.name,
|
|
@@ -1460,10 +1494,7 @@ var Table = class extends Resource {
|
|
|
1460
1494
|
{ KeyType: "HASH", AttributeName: this.props.hash },
|
|
1461
1495
|
...this.props.sort ? [{ KeyType: "RANGE", AttributeName: this.props.sort }] : []
|
|
1462
1496
|
],
|
|
1463
|
-
AttributeDefinitions:
|
|
1464
|
-
AttributeName: name,
|
|
1465
|
-
AttributeType: type[0].toUpperCase()
|
|
1466
|
-
})),
|
|
1497
|
+
AttributeDefinitions: this.attributeDefinitions(),
|
|
1467
1498
|
...this.props.stream ? {
|
|
1468
1499
|
StreamSpecification: {
|
|
1469
1500
|
StreamViewType: (0, import_change_case4.constantCase)(this.props.stream)
|
|
@@ -1505,7 +1536,8 @@ var DynamoDBEventSource = class extends Group {
|
|
|
1505
1536
|
parallelizationFactor: props.parallelizationFactor ?? 1,
|
|
1506
1537
|
startingPosition: props.startingPosition,
|
|
1507
1538
|
startingPositionTimestamp: props.startingPositionTimestamp,
|
|
1508
|
-
tumblingWindow: props.tumblingWindow
|
|
1539
|
+
tumblingWindow: props.tumblingWindow,
|
|
1540
|
+
onFailure: props.onFailure
|
|
1509
1541
|
});
|
|
1510
1542
|
lambda.addPermissions({
|
|
1511
1543
|
actions: [
|
|
@@ -1547,6 +1579,7 @@ var tablePlugin = definePlugin({
|
|
|
1547
1579
|
/** Specifies the name of the range / sort key that makes up the primary key for the table. */
|
|
1548
1580
|
sort: KeySchema.optional(),
|
|
1549
1581
|
/** A list of attributes that describe the key schema for the table and indexes.
|
|
1582
|
+
* If no attribute field is defined we default to 'string'.
|
|
1550
1583
|
* @example
|
|
1551
1584
|
* {
|
|
1552
1585
|
* fields: {
|
|
@@ -1554,7 +1587,10 @@ var tablePlugin = definePlugin({
|
|
|
1554
1587
|
* }
|
|
1555
1588
|
* }
|
|
1556
1589
|
*/
|
|
1557
|
-
fields: import_zod9.z.record(
|
|
1590
|
+
fields: import_zod9.z.record(
|
|
1591
|
+
import_zod9.z.string(),
|
|
1592
|
+
import_zod9.z.enum(["string", "number", "binary"])
|
|
1593
|
+
).optional(),
|
|
1558
1594
|
/** The table class of the table.
|
|
1559
1595
|
* @default 'standard'
|
|
1560
1596
|
*/
|
|
@@ -1603,18 +1639,22 @@ var tablePlugin = definePlugin({
|
|
|
1603
1639
|
*/
|
|
1604
1640
|
projection: import_zod9.z.enum(["all", "keys-only"]).default("all")
|
|
1605
1641
|
})).optional()
|
|
1606
|
-
})
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1642
|
+
})
|
|
1643
|
+
// .refine(props => {
|
|
1644
|
+
// return (
|
|
1645
|
+
// // Check the hash key
|
|
1646
|
+
// props.fields.hasOwnProperty(props.hash) &&
|
|
1647
|
+
// // Check the sort key
|
|
1648
|
+
// (!props.sort || props.fields.hasOwnProperty(props.sort)) &&
|
|
1649
|
+
// // Check all indexes
|
|
1650
|
+
// !Object.values(props.indexes || {}).map(index => (
|
|
1651
|
+
// // Check the index hash key
|
|
1652
|
+
// props.fields.hasOwnProperty(index.hash) &&
|
|
1653
|
+
// // Check the index sort key
|
|
1654
|
+
// (!index.sort || props.fields.hasOwnProperty(index.sort))
|
|
1655
|
+
// )).includes(false)
|
|
1656
|
+
// )
|
|
1657
|
+
// }, 'Hash & Sort keys must be defined inside the table fields')
|
|
1618
1658
|
).optional()
|
|
1619
1659
|
}).array()
|
|
1620
1660
|
}),
|
|
@@ -1631,6 +1671,7 @@ var tablePlugin = definePlugin({
|
|
|
1631
1671
|
const lambda = toLambdaFunction(ctx, `stream-${id}`, props.stream.consumer);
|
|
1632
1672
|
const source = new DynamoDBEventSource(id, lambda, {
|
|
1633
1673
|
tableArn: table.arn,
|
|
1674
|
+
onFailure: getGlobalOnFailure(ctx),
|
|
1634
1675
|
...props.stream
|
|
1635
1676
|
});
|
|
1636
1677
|
stack.add(lambda, source);
|
|
@@ -2666,14 +2707,8 @@ var domainPlugin = definePlugin({
|
|
|
2666
2707
|
}
|
|
2667
2708
|
});
|
|
2668
2709
|
|
|
2669
|
-
// src/plugins/on-failure.ts
|
|
2710
|
+
// src/plugins/on-failure/index.ts
|
|
2670
2711
|
var import_zod16 = require("zod");
|
|
2671
|
-
var hasOnFailure = (config) => {
|
|
2672
|
-
const onFailure = config.stacks.find((stack) => {
|
|
2673
|
-
return typeof stack.onFailure !== "undefined";
|
|
2674
|
-
});
|
|
2675
|
-
return !!onFailure;
|
|
2676
|
-
};
|
|
2677
2712
|
var onFailurePlugin = definePlugin({
|
|
2678
2713
|
name: "on-failure",
|
|
2679
2714
|
schema: import_zod16.z.object({
|
|
@@ -2720,21 +2755,6 @@ var onFailurePlugin = definePlugin({
|
|
|
2720
2755
|
resources: [queueArn]
|
|
2721
2756
|
});
|
|
2722
2757
|
stack.add(lambda, source);
|
|
2723
|
-
},
|
|
2724
|
-
onResource({ config, resource, bootstrap: bootstrap2 }) {
|
|
2725
|
-
if (!hasOnFailure(config)) {
|
|
2726
|
-
return;
|
|
2727
|
-
}
|
|
2728
|
-
const queueArn = bootstrap2.import("on-failure-queue-arn");
|
|
2729
|
-
if (resource instanceof Queue) {
|
|
2730
|
-
resource.setDeadLetter(queueArn);
|
|
2731
|
-
}
|
|
2732
|
-
if (resource instanceof EventInvokeConfig) {
|
|
2733
|
-
resource.setOnFailure(queueArn);
|
|
2734
|
-
}
|
|
2735
|
-
if (resource instanceof EventSourceMapping) {
|
|
2736
|
-
resource.setOnFailure(queueArn);
|
|
2737
|
-
}
|
|
2738
2758
|
}
|
|
2739
2759
|
});
|
|
2740
2760
|
|
package/dist/bin.js
CHANGED
|
@@ -909,6 +909,17 @@ var EventInvokeConfig = class extends Resource {
|
|
|
909
909
|
}
|
|
910
910
|
};
|
|
911
911
|
|
|
912
|
+
// src/plugins/on-failure/util.ts
|
|
913
|
+
var getGlobalOnFailure = ({ config, bootstrap: bootstrap2 }) => {
|
|
914
|
+
return hasOnFailure(config) ? bootstrap2.import("on-failure-queue-arn") : void 0;
|
|
915
|
+
};
|
|
916
|
+
var hasOnFailure = (config) => {
|
|
917
|
+
const onFailure = config.stacks.find((stack) => {
|
|
918
|
+
return typeof stack.onFailure !== "undefined";
|
|
919
|
+
});
|
|
920
|
+
return !!onFailure;
|
|
921
|
+
};
|
|
922
|
+
|
|
912
923
|
// src/plugins/function.ts
|
|
913
924
|
var MemorySizeSchema = SizeSchema.refine(sizeMin(Size.megaBytes(128)), "Minimum memory size is 128 MB").refine(sizeMax(Size.gigaBytes(10)), "Minimum memory size is 10 GB");
|
|
914
925
|
var TimeoutSchema = DurationSchema.refine(durationMin(Duration.seconds(10)), "Minimum timeout duration is 10 seconds").refine(durationMax(Duration.minutes(15)), "Maximum timeout duration is 15 minutes");
|
|
@@ -1031,9 +1042,16 @@ var functionPlugin = definePlugin({
|
|
|
1031
1042
|
name: "function",
|
|
1032
1043
|
schema,
|
|
1033
1044
|
onStack(ctx) {
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1045
|
+
const { config, stack } = ctx;
|
|
1046
|
+
for (const [id, fileOrProps] of Object.entries(ctx.stackConfig.functions || {})) {
|
|
1047
|
+
const props = typeof fileOrProps === "string" ? { ...config.defaults?.function, file: fileOrProps } : { ...config.defaults?.function, ...fileOrProps };
|
|
1048
|
+
const lambda = toLambdaFunction(ctx, id, fileOrProps);
|
|
1049
|
+
const invoke = new EventInvokeConfig(id, {
|
|
1050
|
+
functionName: lambda.name,
|
|
1051
|
+
retryAttempts: props.retryAttempts,
|
|
1052
|
+
onFailure: getGlobalOnFailure(ctx)
|
|
1053
|
+
}).dependsOn(lambda);
|
|
1054
|
+
stack.add(invoke, lambda);
|
|
1037
1055
|
}
|
|
1038
1056
|
}
|
|
1039
1057
|
});
|
|
@@ -1050,11 +1068,6 @@ var toLambdaFunction = (ctx, id, fileOrProps) => {
|
|
|
1050
1068
|
if (props.runtime.startsWith("nodejs")) {
|
|
1051
1069
|
lambda.addEnvironment("AWS_NODEJS_CONNECTION_REUSE_ENABLED", "1");
|
|
1052
1070
|
}
|
|
1053
|
-
const invoke = new EventInvokeConfig(id, {
|
|
1054
|
-
functionName: lambda.name,
|
|
1055
|
-
retryAttempts: props.retryAttempts
|
|
1056
|
-
}).dependsOn(lambda);
|
|
1057
|
-
ctx.stack.add(invoke);
|
|
1058
1071
|
return lambda;
|
|
1059
1072
|
};
|
|
1060
1073
|
|
|
@@ -1369,7 +1382,8 @@ var queuePlugin = definePlugin({
|
|
|
1369
1382
|
});
|
|
1370
1383
|
const lambda = toLambdaFunction(ctx, `queue-${id}`, props.consumer);
|
|
1371
1384
|
const source = new SqsEventSource(id, lambda, {
|
|
1372
|
-
queueArn: queue2.arn
|
|
1385
|
+
queueArn: queue2.arn,
|
|
1386
|
+
onFailure: getGlobalOnFailure(ctx)
|
|
1373
1387
|
});
|
|
1374
1388
|
stack.add(queue2, lambda, source);
|
|
1375
1389
|
bind((lambda2) => {
|
|
@@ -1425,6 +1439,26 @@ var Table = class extends Resource {
|
|
|
1425
1439
|
resources: [this.arn]
|
|
1426
1440
|
};
|
|
1427
1441
|
}
|
|
1442
|
+
attributeDefinitions() {
|
|
1443
|
+
const fields = this.props.fields || {};
|
|
1444
|
+
const attributes = new Set([
|
|
1445
|
+
this.props.hash,
|
|
1446
|
+
this.props.sort,
|
|
1447
|
+
...Object.values(this.props.indexes || {}).map((index) => [
|
|
1448
|
+
index.hash,
|
|
1449
|
+
index.sort
|
|
1450
|
+
])
|
|
1451
|
+
].flat().filter(Boolean));
|
|
1452
|
+
const types = {
|
|
1453
|
+
string: "S",
|
|
1454
|
+
number: "N",
|
|
1455
|
+
binary: "B"
|
|
1456
|
+
};
|
|
1457
|
+
return [...attributes].map((name) => ({
|
|
1458
|
+
AttributeName: name,
|
|
1459
|
+
AttributeType: types[fields[name] || "string"]
|
|
1460
|
+
}));
|
|
1461
|
+
}
|
|
1428
1462
|
properties() {
|
|
1429
1463
|
return {
|
|
1430
1464
|
TableName: this.name,
|
|
@@ -1437,10 +1471,7 @@ var Table = class extends Resource {
|
|
|
1437
1471
|
{ KeyType: "HASH", AttributeName: this.props.hash },
|
|
1438
1472
|
...this.props.sort ? [{ KeyType: "RANGE", AttributeName: this.props.sort }] : []
|
|
1439
1473
|
],
|
|
1440
|
-
AttributeDefinitions:
|
|
1441
|
-
AttributeName: name,
|
|
1442
|
-
AttributeType: type[0].toUpperCase()
|
|
1443
|
-
})),
|
|
1474
|
+
AttributeDefinitions: this.attributeDefinitions(),
|
|
1444
1475
|
...this.props.stream ? {
|
|
1445
1476
|
StreamSpecification: {
|
|
1446
1477
|
StreamViewType: constantCase2(this.props.stream)
|
|
@@ -1482,7 +1513,8 @@ var DynamoDBEventSource = class extends Group {
|
|
|
1482
1513
|
parallelizationFactor: props.parallelizationFactor ?? 1,
|
|
1483
1514
|
startingPosition: props.startingPosition,
|
|
1484
1515
|
startingPositionTimestamp: props.startingPositionTimestamp,
|
|
1485
|
-
tumblingWindow: props.tumblingWindow
|
|
1516
|
+
tumblingWindow: props.tumblingWindow,
|
|
1517
|
+
onFailure: props.onFailure
|
|
1486
1518
|
});
|
|
1487
1519
|
lambda.addPermissions({
|
|
1488
1520
|
actions: [
|
|
@@ -1524,6 +1556,7 @@ var tablePlugin = definePlugin({
|
|
|
1524
1556
|
/** Specifies the name of the range / sort key that makes up the primary key for the table. */
|
|
1525
1557
|
sort: KeySchema.optional(),
|
|
1526
1558
|
/** A list of attributes that describe the key schema for the table and indexes.
|
|
1559
|
+
* If no attribute field is defined we default to 'string'.
|
|
1527
1560
|
* @example
|
|
1528
1561
|
* {
|
|
1529
1562
|
* fields: {
|
|
@@ -1531,7 +1564,10 @@ var tablePlugin = definePlugin({
|
|
|
1531
1564
|
* }
|
|
1532
1565
|
* }
|
|
1533
1566
|
*/
|
|
1534
|
-
fields: z9.record(
|
|
1567
|
+
fields: z9.record(
|
|
1568
|
+
z9.string(),
|
|
1569
|
+
z9.enum(["string", "number", "binary"])
|
|
1570
|
+
).optional(),
|
|
1535
1571
|
/** The table class of the table.
|
|
1536
1572
|
* @default 'standard'
|
|
1537
1573
|
*/
|
|
@@ -1580,18 +1616,22 @@ var tablePlugin = definePlugin({
|
|
|
1580
1616
|
*/
|
|
1581
1617
|
projection: z9.enum(["all", "keys-only"]).default("all")
|
|
1582
1618
|
})).optional()
|
|
1583
|
-
})
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1619
|
+
})
|
|
1620
|
+
// .refine(props => {
|
|
1621
|
+
// return (
|
|
1622
|
+
// // Check the hash key
|
|
1623
|
+
// props.fields.hasOwnProperty(props.hash) &&
|
|
1624
|
+
// // Check the sort key
|
|
1625
|
+
// (!props.sort || props.fields.hasOwnProperty(props.sort)) &&
|
|
1626
|
+
// // Check all indexes
|
|
1627
|
+
// !Object.values(props.indexes || {}).map(index => (
|
|
1628
|
+
// // Check the index hash key
|
|
1629
|
+
// props.fields.hasOwnProperty(index.hash) &&
|
|
1630
|
+
// // Check the index sort key
|
|
1631
|
+
// (!index.sort || props.fields.hasOwnProperty(index.sort))
|
|
1632
|
+
// )).includes(false)
|
|
1633
|
+
// )
|
|
1634
|
+
// }, 'Hash & Sort keys must be defined inside the table fields')
|
|
1595
1635
|
).optional()
|
|
1596
1636
|
}).array()
|
|
1597
1637
|
}),
|
|
@@ -1608,6 +1648,7 @@ var tablePlugin = definePlugin({
|
|
|
1608
1648
|
const lambda = toLambdaFunction(ctx, `stream-${id}`, props.stream.consumer);
|
|
1609
1649
|
const source = new DynamoDBEventSource(id, lambda, {
|
|
1610
1650
|
tableArn: table.arn,
|
|
1651
|
+
onFailure: getGlobalOnFailure(ctx),
|
|
1611
1652
|
...props.stream
|
|
1612
1653
|
});
|
|
1613
1654
|
stack.add(lambda, source);
|
|
@@ -2643,14 +2684,8 @@ var domainPlugin = definePlugin({
|
|
|
2643
2684
|
}
|
|
2644
2685
|
});
|
|
2645
2686
|
|
|
2646
|
-
// src/plugins/on-failure.ts
|
|
2687
|
+
// src/plugins/on-failure/index.ts
|
|
2647
2688
|
import { z as z16 } from "zod";
|
|
2648
|
-
var hasOnFailure = (config) => {
|
|
2649
|
-
const onFailure = config.stacks.find((stack) => {
|
|
2650
|
-
return typeof stack.onFailure !== "undefined";
|
|
2651
|
-
});
|
|
2652
|
-
return !!onFailure;
|
|
2653
|
-
};
|
|
2654
2689
|
var onFailurePlugin = definePlugin({
|
|
2655
2690
|
name: "on-failure",
|
|
2656
2691
|
schema: z16.object({
|
|
@@ -2697,21 +2732,6 @@ var onFailurePlugin = definePlugin({
|
|
|
2697
2732
|
resources: [queueArn]
|
|
2698
2733
|
});
|
|
2699
2734
|
stack.add(lambda, source);
|
|
2700
|
-
},
|
|
2701
|
-
onResource({ config, resource, bootstrap: bootstrap2 }) {
|
|
2702
|
-
if (!hasOnFailure(config)) {
|
|
2703
|
-
return;
|
|
2704
|
-
}
|
|
2705
|
-
const queueArn = bootstrap2.import("on-failure-queue-arn");
|
|
2706
|
-
if (resource instanceof Queue) {
|
|
2707
|
-
resource.setDeadLetter(queueArn);
|
|
2708
|
-
}
|
|
2709
|
-
if (resource instanceof EventInvokeConfig) {
|
|
2710
|
-
resource.setOnFailure(queueArn);
|
|
2711
|
-
}
|
|
2712
|
-
if (resource instanceof EventSourceMapping) {
|
|
2713
|
-
resource.setOnFailure(queueArn);
|
|
2714
|
-
}
|
|
2715
2735
|
}
|
|
2716
2736
|
});
|
|
2717
2737
|
|
package/dist/index.cjs
CHANGED
|
@@ -22,6 +22,7 @@ var src_exports = {};
|
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
defineAppConfig: () => defineAppConfig,
|
|
24
24
|
definePlugin: () => definePlugin,
|
|
25
|
+
defineStackConfig: () => defineStackConfig,
|
|
25
26
|
getFunctionName: () => getFunctionName,
|
|
26
27
|
getGlobalResourceName: () => getGlobalResourceName,
|
|
27
28
|
getLocalResourceName: () => getLocalResourceName,
|
|
@@ -51,6 +52,9 @@ var getQueueName = getLocalResourceName;
|
|
|
51
52
|
var getTopicName = getGlobalResourceName;
|
|
52
53
|
|
|
53
54
|
// src/index.ts
|
|
55
|
+
var defineStackConfig = (config) => {
|
|
56
|
+
return config;
|
|
57
|
+
};
|
|
54
58
|
var defineAppConfig = (config) => {
|
|
55
59
|
return config;
|
|
56
60
|
};
|
|
@@ -58,6 +62,7 @@ var defineAppConfig = (config) => {
|
|
|
58
62
|
0 && (module.exports = {
|
|
59
63
|
defineAppConfig,
|
|
60
64
|
definePlugin,
|
|
65
|
+
defineStackConfig,
|
|
61
66
|
getFunctionName,
|
|
62
67
|
getGlobalResourceName,
|
|
63
68
|
getLocalResourceName,
|