@awsless/awsless 0.0.383 → 0.0.385

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/dist/bin.js CHANGED
@@ -7563,7 +7563,7 @@ var debug = (...parts) => {
7563
7563
  };
7564
7564
 
7565
7565
  // src/config/app.ts
7566
- import { z as z21 } from "zod";
7566
+ import { z as z22 } from "zod";
7567
7567
 
7568
7568
  // src/feature/auth/schema.ts
7569
7569
  import { z as z7 } from "zod";
@@ -7996,37 +7996,51 @@ var InstancesSchema = z12.record(
7996
7996
  })
7997
7997
  ).optional().describe("Define the instances in your stack.");
7998
7998
 
7999
- // src/feature/log-subscription/schema.ts
8000
- var LogSubscriptionSchema2 = FunctionSchema.optional().describe(
8001
- "Log Subscription allow you to subscribe to a real-time stream of log events and have them delivered to a specific destination."
7999
+ // src/feature/on-failure/schema.ts
8000
+ var OnFailureDefaultSchema = FunctionSchema.optional().describe(
8001
+ "Defining a onFailure handler will add a global onFailure handler for the following resources:\n- Async lambda functions\n- SQS queues\n- DynamoDB streams"
8002
8002
  );
8003
8003
 
8004
- // src/feature/pubsub/schema.ts
8004
+ // src/feature/on-log/schema.ts
8005
8005
  import { z as z13 } from "zod";
8006
+ var FilterSchema = z13.enum(["trace", "debug", "info", "warn", "error", "fatal"]).array().describe("The log level that will gets delivered to the consumer.");
8007
+ var OnLogDefaultSchema = z13.union([
8008
+ FunctionSchema.transform((consumer) => ({
8009
+ consumer,
8010
+ filter: ["error", "fatal"]
8011
+ })),
8012
+ z13.object({
8013
+ consumer: FunctionSchema,
8014
+ filter: FilterSchema
8015
+ })
8016
+ ]).optional().describe("Define a subscription on all Lambda functions logs.");
8017
+
8018
+ // src/feature/pubsub/schema.ts
8019
+ import { z as z14 } from "zod";
8006
8020
  var DomainSchema = ResourceIdSchema.describe("The domain id to link your Pubsub API with.");
8007
- var PubSubDefaultSchema = z13.record(
8021
+ var PubSubDefaultSchema = z14.record(
8008
8022
  ResourceIdSchema,
8009
- z13.object({
8023
+ z14.object({
8010
8024
  domain: DomainSchema.optional(),
8011
- subDomain: z13.string().optional(),
8012
- auth: z13.union([
8025
+ subDomain: z14.string().optional(),
8026
+ auth: z14.union([
8013
8027
  ResourceIdSchema,
8014
- z13.object({
8028
+ z14.object({
8015
8029
  authorizer: FunctionSchema
8016
8030
  // ttl: AuthorizerTtl.default('1 hour'),
8017
8031
  })
8018
8032
  ]),
8019
- policy: z13.object({
8020
- publish: z13.array(z13.string()).optional(),
8021
- subscribe: z13.array(z13.string()).optional()
8033
+ policy: z14.object({
8034
+ publish: z14.array(z14.string()).optional(),
8035
+ subscribe: z14.array(z14.string()).optional()
8022
8036
  }).optional()
8023
8037
  })
8024
8038
  ).optional().describe("Define the pubsub subscriber in your stack.");
8025
- var PubSubSchema = z13.record(
8039
+ var PubSubSchema = z14.record(
8026
8040
  ResourceIdSchema,
8027
- z13.object({
8028
- sql: z13.string().describe("The SQL statement used to query the IOT topic."),
8029
- sqlVersion: z13.enum(["2015-10-08", "2016-03-23", "beta"]).default("2016-03-23").describe("The version of the SQL rules engine to use when evaluating the rule."),
8041
+ z14.object({
8042
+ sql: z14.string().describe("The SQL statement used to query the IOT topic."),
8043
+ sqlVersion: z14.enum(["2015-10-08", "2016-03-23", "beta"]).default("2016-03-23").describe("The version of the SQL rules engine to use when evaluating the rule."),
8030
8044
  consumer: FunctionSchema.describe("The consuming lambda function properties.")
8031
8045
  })
8032
8046
  ).optional().describe("Define the pubsub subscriber in your stack.");
@@ -8034,7 +8048,7 @@ var PubSubSchema = z13.record(
8034
8048
  // src/feature/queue/schema.ts
8035
8049
  import { days as days2, hours, minutes as minutes3, seconds as seconds2 } from "@awsless/duration";
8036
8050
  import { kibibytes } from "@awsless/size";
8037
- import { z as z14 } from "zod";
8051
+ import { z as z15 } from "zod";
8038
8052
  var RetentionPeriodSchema = DurationSchema.refine(
8039
8053
  durationMin(minutes3(1)),
8040
8054
  "Minimum retention period is 1 minute"
@@ -8062,10 +8076,10 @@ var ReceiveMessageWaitTimeSchema = DurationSchema.refine(
8062
8076
  var MaxMessageSizeSchema = SizeSchema.refine(sizeMin(kibibytes(1)), "Minimum max message size is 1 KB").refine(sizeMax(kibibytes(256)), "Maximum max message size is 256 KB").describe(
8063
8077
  "The limit of how many bytes that a message can contain before Amazon SQS rejects it. You can specify an size from 1 KB to 256 KB."
8064
8078
  );
8065
- var BatchSizeSchema = z14.number().int().min(1, "Minimum batch size is 1").max(1e4, "Maximum batch size is 10000").describe(
8079
+ var BatchSizeSchema = z15.number().int().min(1, "Minimum batch size is 1").max(1e4, "Maximum batch size is 10000").describe(
8066
8080
  "The maximum number of records in each batch that Lambda pulls from your queue and sends to your function. Lambda passes all of the records in the batch to the function in a single call, up to the payload limit for synchronous invocation (6 MB). You can specify an integer from 1 to 10000."
8067
8081
  );
8068
- var MaxConcurrencySchema = z14.number().int().min(2, "Minimum max concurrency is 2").max(1e3, "Maximum max concurrency is 1000").describe(
8082
+ var MaxConcurrencySchema = z15.number().int().min(2, "Minimum max concurrency is 2").max(1e3, "Maximum max concurrency is 1000").describe(
8069
8083
  "Limits the number of concurrent instances that the queue worker can invoke. You can specify an integer from 2 to 1000."
8070
8084
  );
8071
8085
  var MaxBatchingWindow = DurationSchema.refine(
@@ -8074,7 +8088,7 @@ var MaxBatchingWindow = DurationSchema.refine(
8074
8088
  ).describe(
8075
8089
  "The maximum amount of time, that Lambda spends gathering records before invoking the function. You can specify an duration from 0 seconds to 5 minutes."
8076
8090
  );
8077
- var QueueDefaultSchema = z14.object({
8091
+ var QueueDefaultSchema = z15.object({
8078
8092
  retentionPeriod: RetentionPeriodSchema.default("7 days"),
8079
8093
  visibilityTimeout: VisibilityTimeoutSchema.default("30 seconds"),
8080
8094
  deliveryDelay: DeliveryDelaySchema.default("0 seconds"),
@@ -8084,15 +8098,15 @@ var QueueDefaultSchema = z14.object({
8084
8098
  maxConcurrency: MaxConcurrencySchema.optional(),
8085
8099
  maxBatchingWindow: MaxBatchingWindow.optional()
8086
8100
  }).default({});
8087
- var QueuesSchema = z14.record(
8101
+ var QueuesSchema = z15.record(
8088
8102
  ResourceIdSchema,
8089
- z14.union([
8103
+ z15.union([
8090
8104
  LocalFileSchema.transform((file) => ({
8091
8105
  consumer: {
8092
8106
  file
8093
8107
  }
8094
8108
  })),
8095
- z14.object({
8109
+ z15.object({
8096
8110
  consumer: FunctionSchema.describe("The consuming lambda function properties."),
8097
8111
  retentionPeriod: RetentionPeriodSchema.optional(),
8098
8112
  visibilityTimeout: VisibilityTimeoutSchema.optional(),
@@ -8107,58 +8121,58 @@ var QueuesSchema = z14.record(
8107
8121
  ).optional().describe("Define the queues in your stack.");
8108
8122
 
8109
8123
  // src/feature/rest/schema.ts
8110
- import { z as z16 } from "zod";
8124
+ import { z as z17 } from "zod";
8111
8125
 
8112
8126
  // src/config/schema/route.ts
8113
- import { z as z15 } from "zod";
8114
- var RouteSchema2 = z15.union([
8115
- z15.string().regex(/^(POST|GET|PUT|DELETE|HEAD|OPTIONS)(\s\/[a-z0-9\+\_\-\/\{\}]*)$/gi, "Invalid route"),
8116
- z15.literal("$default")
8127
+ import { z as z16 } from "zod";
8128
+ var RouteSchema2 = z16.union([
8129
+ z16.string().regex(/^(POST|GET|PUT|DELETE|HEAD|OPTIONS)(\s\/[a-z0-9\+\_\-\/\{\}]*)$/gi, "Invalid route"),
8130
+ z16.literal("$default")
8117
8131
  ]);
8118
8132
 
8119
8133
  // src/feature/rest/schema.ts
8120
- var RestDefaultSchema = z16.record(
8134
+ var RestDefaultSchema = z17.record(
8121
8135
  ResourceIdSchema,
8122
- z16.object({
8136
+ z17.object({
8123
8137
  domain: ResourceIdSchema.describe("The domain id to link your API with.").optional(),
8124
- subDomain: z16.string().optional()
8138
+ subDomain: z17.string().optional()
8125
8139
  })
8126
8140
  ).optional().describe("Define your global REST API's.");
8127
- var RestSchema = z16.record(ResourceIdSchema, z16.record(RouteSchema2, FunctionSchema)).optional().describe("Define routes in your stack for your global REST API.");
8141
+ var RestSchema = z17.record(ResourceIdSchema, z17.record(RouteSchema2, FunctionSchema)).optional().describe("Define routes in your stack for your global REST API.");
8128
8142
 
8129
8143
  // src/feature/rpc/schema.ts
8130
- import { z as z17 } from "zod";
8131
- var RpcDefaultSchema = z17.record(
8144
+ import { z as z18 } from "zod";
8145
+ var RpcDefaultSchema = z18.record(
8132
8146
  ResourceIdSchema,
8133
- z17.object({
8147
+ z18.object({
8134
8148
  domain: ResourceIdSchema.describe("The domain id to link your RPC API with.").optional(),
8135
- subDomain: z17.string().optional(),
8149
+ subDomain: z18.string().optional(),
8136
8150
  auth: FunctionSchema.optional()
8137
8151
  })
8138
8152
  ).describe(`Define the global RPC API's.`).optional();
8139
- var RpcSchema = z17.record(ResourceIdSchema, z17.record(z17.string(), FunctionSchema).describe("The queries for your global RPC API.")).describe("Define the schema in your stack for your global RPC API.").optional();
8153
+ var RpcSchema = z18.record(ResourceIdSchema, z18.record(z18.string(), FunctionSchema).describe("The queries for your global RPC API.")).describe("Define the schema in your stack for your global RPC API.").optional();
8140
8154
 
8141
8155
  // src/feature/store/schema.ts
8142
- import { z as z18 } from "zod";
8143
- var DeletionProtectionSchema = z18.boolean().describe("Specifies if you want to protect the store from being deleted by awsless.");
8144
- var StoreDefaultSchema = z18.object({
8156
+ import { z as z19 } from "zod";
8157
+ var DeletionProtectionSchema = z19.boolean().describe("Specifies if you want to protect the store from being deleted by awsless.");
8158
+ var StoreDefaultSchema = z19.object({
8145
8159
  deletionProtection: DeletionProtectionSchema.optional()
8146
8160
  }).optional();
8147
- var StoresSchema = z18.union([
8148
- z18.array(ResourceIdSchema).transform((list4) => {
8161
+ var StoresSchema = z19.union([
8162
+ z19.array(ResourceIdSchema).transform((list4) => {
8149
8163
  const stores = {};
8150
8164
  for (const key of list4) {
8151
8165
  stores[key] = {};
8152
8166
  }
8153
8167
  return stores;
8154
8168
  }),
8155
- z18.record(
8169
+ z19.record(
8156
8170
  ResourceIdSchema,
8157
- z18.object({
8171
+ z19.object({
8158
8172
  // cors: CorsSchema,
8159
8173
  deletionProtection: DeletionProtectionSchema.optional(),
8160
- versioning: z18.boolean().default(false).describe("Enable versioning of your store."),
8161
- events: z18.object({
8174
+ versioning: z19.boolean().default(false).describe("Enable versioning of your store."),
8175
+ events: z19.object({
8162
8176
  // create
8163
8177
  "created:*": FunctionSchema.optional().describe(
8164
8178
  "Subscribe to notifications regardless of the API that was used to create an object."
@@ -8191,41 +8205,41 @@ var StoresSchema = z18.union([
8191
8205
  ]).optional().describe("Define the stores in your stack.");
8192
8206
 
8193
8207
  // src/feature/table/schema.ts
8194
- import { z as z19 } from "zod";
8195
- var KeySchema = z19.string().min(1).max(255);
8196
- var DeletionProtectionSchema2 = z19.boolean().describe("Specifies if you want to protect the table from being deleted by awsless.");
8197
- var TableDefaultSchema = z19.object({
8208
+ import { z as z20 } from "zod";
8209
+ var KeySchema = z20.string().min(1).max(255);
8210
+ var DeletionProtectionSchema2 = z20.boolean().describe("Specifies if you want to protect the table from being deleted by awsless.");
8211
+ var TableDefaultSchema = z20.object({
8198
8212
  deletionProtection: DeletionProtectionSchema2.optional()
8199
8213
  }).optional();
8200
- var TablesSchema = z19.record(
8214
+ var TablesSchema = z20.record(
8201
8215
  ResourceIdSchema,
8202
- z19.object({
8216
+ z20.object({
8203
8217
  hash: KeySchema.describe(
8204
8218
  "Specifies the name of the partition / hash key that makes up the primary key for the table."
8205
8219
  ),
8206
8220
  sort: KeySchema.optional().describe(
8207
8221
  "Specifies the name of the range / sort key that makes up the primary key for the table."
8208
8222
  ),
8209
- fields: z19.record(z19.string(), z19.enum(["string", "number", "binary"])).optional().describe(
8223
+ fields: z20.record(z20.string(), z20.enum(["string", "number", "binary"])).optional().describe(
8210
8224
  'A list of attributes that describe the key schema for the table and indexes. If no attribute field is defined we default to "string".'
8211
8225
  ),
8212
- class: z19.enum(["standard", "standard-infrequent-access"]).default("standard").describe("The table class of the table."),
8213
- pointInTimeRecovery: z19.boolean().default(false).describe("Indicates whether point in time recovery is enabled on the table."),
8226
+ class: z20.enum(["standard", "standard-infrequent-access"]).default("standard").describe("The table class of the table."),
8227
+ pointInTimeRecovery: z20.boolean().default(false).describe("Indicates whether point in time recovery is enabled on the table."),
8214
8228
  timeToLiveAttribute: KeySchema.optional().describe(
8215
8229
  "The name of the TTL attribute used to store the expiration time for items in the table. To update this property, you must first disable TTL and then enable TTL with the new attribute name."
8216
8230
  ),
8217
8231
  deletionProtection: DeletionProtectionSchema2.optional(),
8218
- stream: z19.object({
8219
- type: z19.enum(["keys-only", "new-image", "old-image", "new-and-old-images"]).describe(
8232
+ stream: z20.object({
8233
+ type: z20.enum(["keys-only", "new-image", "old-image", "new-and-old-images"]).describe(
8220
8234
  "When an item in the table is modified, stream.type determines what information is written to the stream for this table. Valid values are:\n- keys-only - Only the key attributes of the modified item are written to the stream.\n- new-image - The entire item, as it appears after it was modified, is written to the stream.\n- old-image - The entire item, as it appeared before it was modified, is written to the stream.\n- new-and-old-images - Both the new and the old item images of the item are written to the stream."
8221
8235
  ),
8222
8236
  consumer: FunctionSchema.describe("The consuming lambda function for the stream")
8223
8237
  }).optional().describe(
8224
8238
  "The settings for the DynamoDB table stream, which capture changes to items stored in the table."
8225
8239
  ),
8226
- indexes: z19.record(
8227
- z19.string(),
8228
- z19.object({
8240
+ indexes: z20.record(
8241
+ z20.string(),
8242
+ z20.object({
8229
8243
  /** Specifies the name of the partition / hash key that makes up the primary key for the global secondary index. */
8230
8244
  hash: KeySchema,
8231
8245
  /** Specifies the name of the range / sort key that makes up the primary key for the global secondary index. */
@@ -8235,14 +8249,14 @@ var TablesSchema = z19.record(
8235
8249
  * - keys-only - Only the index and primary keys are projected into the index.
8236
8250
  * @default 'all'
8237
8251
  */
8238
- projection: z19.enum(["all", "keys-only"]).default("all")
8252
+ projection: z20.enum(["all", "keys-only"]).default("all")
8239
8253
  })
8240
8254
  ).optional().describe("Specifies the global secondary indexes to be created on the table.")
8241
8255
  })
8242
8256
  ).optional().describe("Define the tables in your stack.");
8243
8257
 
8244
8258
  // src/config/schema/region.ts
8245
- import { z as z20 } from "zod";
8259
+ import { z as z21 } from "zod";
8246
8260
  var US = ["us-east-2", "us-east-1", "us-west-1", "us-west-2"];
8247
8261
  var AF = ["af-south-1"];
8248
8262
  var AP = [
@@ -8271,22 +8285,23 @@ var EU = [
8271
8285
  var ME = ["me-south-1", "me-central-1"];
8272
8286
  var SA = ["sa-east-1"];
8273
8287
  var regions = [...US, ...AF, ...AP, ...CA, ...EU, ...ME, ...SA];
8274
- var RegionSchema = z20.enum(regions);
8288
+ var RegionSchema = z21.enum(regions);
8275
8289
 
8276
8290
  // src/config/app.ts
8277
- var AppSchema = z21.object({
8278
- $schema: z21.string().optional(),
8291
+ var AppSchema = z22.object({
8292
+ $schema: z22.string().optional(),
8279
8293
  name: ResourceIdSchema.describe("App name."),
8280
8294
  region: RegionSchema.describe("The AWS region to deploy to."),
8281
- profile: z21.string().describe("The AWS profile to deploy to."),
8295
+ profile: z22.string().describe("The AWS profile to deploy to."),
8282
8296
  // stage: z
8283
8297
  // .string()
8284
8298
  // .regex(/^[a-z]+$/)
8285
8299
  // .default('prod')
8286
8300
  // .describe('The deployment stage.'),
8287
8301
  // onFailure: OnFailureSchema,
8288
- logSubscription: LogSubscriptionSchema2,
8289
- defaults: z21.object({
8302
+ defaults: z22.object({
8303
+ onFailure: OnFailureDefaultSchema,
8304
+ onLog: OnLogDefaultSchema,
8290
8305
  auth: AuthDefaultSchema,
8291
8306
  domains: DomainsDefaultSchema,
8292
8307
  function: FunctionDefaultSchema,
@@ -8304,11 +8319,11 @@ var AppSchema = z21.object({
8304
8319
  });
8305
8320
 
8306
8321
  // src/config/stack.ts
8307
- import { z as z33 } from "zod";
8322
+ import { z as z34 } from "zod";
8308
8323
 
8309
8324
  // src/feature/cache/schema.ts
8310
- import { z as z22 } from "zod";
8311
- var TypeSchema2 = z22.enum([
8325
+ import { z as z23 } from "zod";
8326
+ var TypeSchema2 = z23.enum([
8312
8327
  "t4g.small",
8313
8328
  "t4g.medium",
8314
8329
  "r6g.large",
@@ -8323,29 +8338,29 @@ var TypeSchema2 = z22.enum([
8323
8338
  "r6gd.4xlarge",
8324
8339
  "r6gd.8xlarge"
8325
8340
  ]);
8326
- var PortSchema = z22.number().int().min(1).max(5e4);
8327
- var ShardsSchema = z22.number().int().min(0).max(100);
8328
- var ReplicasPerShardSchema = z22.number().int().min(0).max(5);
8329
- var EngineSchema = z22.enum(["7.0", "6.2"]);
8330
- var CachesSchema = z22.record(
8341
+ var PortSchema = z23.number().int().min(1).max(5e4);
8342
+ var ShardsSchema = z23.number().int().min(0).max(100);
8343
+ var ReplicasPerShardSchema = z23.number().int().min(0).max(5);
8344
+ var EngineSchema = z23.enum(["7.0", "6.2"]);
8345
+ var CachesSchema = z23.record(
8331
8346
  ResourceIdSchema,
8332
- z22.object({
8347
+ z23.object({
8333
8348
  type: TypeSchema2.default("t4g.small"),
8334
8349
  port: PortSchema.default(6379),
8335
8350
  shards: ShardsSchema.default(1),
8336
8351
  replicasPerShard: ReplicasPerShardSchema.default(1),
8337
8352
  engine: EngineSchema.default("7.0"),
8338
- dataTiering: z22.boolean().default(false)
8353
+ dataTiering: z23.boolean().default(false)
8339
8354
  })
8340
8355
  ).optional().describe("Define the caches in your stack. For access to the cache put your functions inside the global VPC.");
8341
8356
 
8342
8357
  // src/feature/command/schema.ts
8343
- import { z as z23 } from "zod";
8344
- var CommandSchema2 = z23.union([
8345
- z23.object({
8358
+ import { z as z24 } from "zod";
8359
+ var CommandSchema2 = z24.union([
8360
+ z24.object({
8346
8361
  file: LocalFileSchema,
8347
- handler: z23.string().default("default").describe("The name of the handler that needs to run"),
8348
- description: z23.string().optional().describe("A description of the command")
8362
+ handler: z24.string().default("default").describe("The name of the handler that needs to run"),
8363
+ description: z24.string().optional().describe("A description of the command")
8349
8364
  // options: z.record(ResourceIdSchema, OptionSchema).optional(),
8350
8365
  // arguments: z.record(ResourceIdSchema, ArgumentSchema).optional(),
8351
8366
  }),
@@ -8355,22 +8370,22 @@ var CommandSchema2 = z23.union([
8355
8370
  description: void 0
8356
8371
  }))
8357
8372
  ]);
8358
- var CommandsSchema = z23.record(ResourceIdSchema, CommandSchema2).optional().describe("Define the custom commands for your stack.");
8373
+ var CommandsSchema = z24.record(ResourceIdSchema, CommandSchema2).optional().describe("Define the custom commands for your stack.");
8359
8374
 
8360
8375
  // src/feature/config/schema.ts
8361
- import { z as z24 } from "zod";
8362
- var ConfigNameSchema = z24.string().regex(/[a-z0-9\-]/g, "Invalid config name");
8363
- var ConfigsSchema = z24.array(ConfigNameSchema).optional().describe("Define the config values for your stack.");
8376
+ import { z as z25 } from "zod";
8377
+ var ConfigNameSchema = z25.string().regex(/[a-z0-9\-]/g, "Invalid config name");
8378
+ var ConfigsSchema = z25.array(ConfigNameSchema).optional().describe("Define the config values for your stack.");
8364
8379
 
8365
8380
  // src/feature/cron/schema/index.ts
8366
- import { z as z26 } from "zod";
8381
+ import { z as z27 } from "zod";
8367
8382
 
8368
8383
  // src/feature/cron/schema/schedule.ts
8369
- import { z as z25 } from "zod";
8384
+ import { z as z26 } from "zod";
8370
8385
  import { awsCronExpressionValidator } from "aws-cron-expression-validator";
8371
- var RateExpressionSchema = z25.custom(
8386
+ var RateExpressionSchema = z26.custom(
8372
8387
  (value) => {
8373
- return z25.string().regex(/^[0-9]+ (seconds?|minutes?|hours?|days?)$/).refine((rate) => {
8388
+ return z26.string().regex(/^[0-9]+ (seconds?|minutes?|hours?|days?)$/).refine((rate) => {
8374
8389
  const [str] = rate.split(" ");
8375
8390
  const number = parseInt(str);
8376
8391
  return number > 0;
@@ -8386,9 +8401,9 @@ var RateExpressionSchema = z25.custom(
8386
8401
  }
8387
8402
  return `rate(${rate})`;
8388
8403
  });
8389
- var CronExpressionSchema = z25.custom(
8404
+ var CronExpressionSchema = z26.custom(
8390
8405
  (value) => {
8391
- return z25.string().safeParse(value).success;
8406
+ return z26.string().safeParse(value).success;
8392
8407
  },
8393
8408
  { message: "Invalid cron expression" }
8394
8409
  ).superRefine((value, ctx) => {
@@ -8397,12 +8412,12 @@ var CronExpressionSchema = z25.custom(
8397
8412
  } catch (error) {
8398
8413
  if (error instanceof Error) {
8399
8414
  ctx.addIssue({
8400
- code: z25.ZodIssueCode.custom,
8415
+ code: z26.ZodIssueCode.custom,
8401
8416
  message: `Invalid cron expression: ${error.message}`
8402
8417
  });
8403
8418
  } else {
8404
8419
  ctx.addIssue({
8405
- code: z25.ZodIssueCode.custom,
8420
+ code: z26.ZodIssueCode.custom,
8406
8421
  message: "Invalid cron expression"
8407
8422
  });
8408
8423
  }
@@ -8413,28 +8428,23 @@ var CronExpressionSchema = z25.custom(
8413
8428
  var ScheduleExpressionSchema = RateExpressionSchema.or(CronExpressionSchema);
8414
8429
 
8415
8430
  // src/feature/cron/schema/index.ts
8416
- var CronsSchema = z26.record(
8431
+ var CronsSchema = z27.record(
8417
8432
  ResourceIdSchema,
8418
- z26.object({
8419
- enabled: z26.boolean().default(true).describe("If the cron is enabled."),
8433
+ z27.object({
8434
+ enabled: z27.boolean().default(true).describe("If the cron is enabled."),
8420
8435
  consumer: FunctionSchema.describe("The consuming lambda function properties."),
8421
8436
  schedule: ScheduleExpressionSchema.describe(
8422
8437
  'The scheduling expression.\n\nexample: "0 20 * * ? *"\nexample: "5 minutes"'
8423
8438
  ),
8424
- payload: z26.unknown().optional().describe("The JSON payload that will be passed to the consumer.")
8439
+ payload: z27.unknown().optional().describe("The JSON payload that will be passed to the consumer.")
8425
8440
  })
8426
8441
  ).optional().describe(`Define the cron jobs in your stack.`);
8427
8442
 
8428
- // src/feature/on-failure/schema.ts
8429
- var OnFailureSchema = FunctionSchema.optional().describe(
8430
- "Defining a onFailure handler will add a global onFailure handler for the following resources:\n- Async lambda functions\n- SQS queues\n- DynamoDB streams"
8431
- );
8432
-
8433
8443
  // src/feature/search/schema.ts
8434
8444
  import { gibibytes as gibibytes2 } from "@awsless/size";
8435
- import { z as z27 } from "zod";
8436
- var VersionSchema = z27.enum(["2.13", "2.11", "2.9", "2.7", "2.5", "2.3", "1.3"]);
8437
- var TypeSchema3 = z27.enum([
8445
+ import { z as z28 } from "zod";
8446
+ var VersionSchema = z28.enum(["2.13", "2.11", "2.9", "2.7", "2.5", "2.3", "1.3"]);
8447
+ var TypeSchema3 = z28.enum([
8438
8448
  "t3.small",
8439
8449
  "t3.medium",
8440
8450
  "m3.medium",
@@ -8509,41 +8519,41 @@ var TypeSchema3 = z27.enum([
8509
8519
  "r6gd.16xlarge"
8510
8520
  ]);
8511
8521
  var StorageSizeSchema = SizeSchema.refine(sizeMin(gibibytes2(10)), "Minimum storage size is 10 GB").refine(sizeMax(gibibytes2(100)), "Maximum storage size is 100 GB").describe("The size of the function's /tmp directory. You can specify a size value from 512 MB to 10 GiB.");
8512
- var SearchsSchema = z27.record(
8522
+ var SearchsSchema = z28.record(
8513
8523
  ResourceIdSchema,
8514
- z27.object({
8524
+ z28.object({
8515
8525
  type: TypeSchema3.default("t3.small"),
8516
- count: z27.number().int().min(1).default(1),
8526
+ count: z28.number().int().min(1).default(1),
8517
8527
  version: VersionSchema.default("2.13"),
8518
8528
  storage: StorageSizeSchema.default("10 GB"),
8519
- vpc: z27.boolean().default(false)
8529
+ vpc: z28.boolean().default(false)
8520
8530
  })
8521
8531
  ).optional().describe("Define the search instances in your stack. Backed by OpenSearch.");
8522
8532
 
8523
8533
  // src/feature/site/schema.ts
8524
- import { z as z28 } from "zod";
8525
- var ErrorResponsePathSchema = z28.string().describe(
8534
+ import { z as z29 } from "zod";
8535
+ var ErrorResponsePathSchema = z29.string().describe(
8526
8536
  "The path to the custom error page that you want to return to the viewer when your origin returns the HTTP status code specified.\n - We recommend that you store custom error pages in an Amazon S3 bucket. If you store custom error pages on an HTTP server and the server starts to return 5xx errors, CloudFront can't get the files that you want to return to viewers because the origin server is unavailable."
8527
8537
  );
8528
- var StatusCodeSchema = z28.number().int().positive().optional().describe(
8538
+ var StatusCodeSchema = z29.number().int().positive().optional().describe(
8529
8539
  "The HTTP status code that you want CloudFront to return to the viewer along with the custom error page. There are a variety of reasons that you might want CloudFront to return a status code different from the status code that your origin returned to CloudFront, for example:\n- Some Internet devices (some firewalls and corporate proxies, for example) intercept HTTP 4xx and 5xx and prevent the response from being returned to the viewer. If you substitute 200, the response typically won't be intercepted.\n- If you don't care about distinguishing among different client errors or server errors, you can specify 400 or 500 as the ResponseCode for all 4xx or 5xx errors.\n- You might want to return a 200 status code (OK) and static website so your customers don't know that your website is down."
8530
8540
  );
8531
8541
  var MinTTLSchema = DurationSchema.describe(
8532
8542
  "The minimum amount of time, that you want to cache the error response. When this time period has elapsed, CloudFront queries your origin to see whether the problem that caused the error has been resolved and the requested object is now available."
8533
8543
  );
8534
- var ErrorResponseSchema = z28.union([
8544
+ var ErrorResponseSchema = z29.union([
8535
8545
  ErrorResponsePathSchema,
8536
- z28.object({
8546
+ z29.object({
8537
8547
  path: ErrorResponsePathSchema,
8538
8548
  statusCode: StatusCodeSchema.optional(),
8539
8549
  minTTL: MinTTLSchema.optional()
8540
8550
  })
8541
8551
  ]).optional();
8542
- var SitesSchema = z28.record(
8552
+ var SitesSchema = z29.record(
8543
8553
  ResourceIdSchema,
8544
- z28.object({
8554
+ z29.object({
8545
8555
  domain: ResourceIdSchema.describe("The domain id to link your site with.").optional(),
8546
- subDomain: z28.string().optional(),
8556
+ subDomain: z29.string().optional(),
8547
8557
  // bind: z
8548
8558
  // .object({
8549
8559
  // auth: z.array(ResourceIdSchema),
@@ -8566,7 +8576,7 @@ var SitesSchema = z28.record(
8566
8576
  // build: z.string().optional(),
8567
8577
  // }),
8568
8578
  // ]),
8569
- errors: z28.object({
8579
+ errors: z29.object({
8570
8580
  400: ErrorResponseSchema.describe("Customize a `400 Bad Request` response."),
8571
8581
  403: ErrorResponseSchema.describe("Customize a `403 Forbidden` response."),
8572
8582
  404: ErrorResponseSchema.describe("Customize a `404 Not Found` response."),
@@ -8579,16 +8589,16 @@ var SitesSchema = z28.record(
8579
8589
  503: ErrorResponseSchema.describe("Customize a `503 Service Unavailable` response."),
8580
8590
  504: ErrorResponseSchema.describe("Customize a `504 Gateway Timeout` response.")
8581
8591
  }).optional().describe("Customize the error responses for specific HTTP status codes."),
8582
- cors: z28.object({
8583
- override: z28.boolean().default(false),
8592
+ cors: z29.object({
8593
+ override: z29.boolean().default(false),
8584
8594
  maxAge: DurationSchema.default("365 days"),
8585
- exposeHeaders: z28.string().array().optional(),
8586
- credentials: z28.boolean().default(false),
8587
- headers: z28.string().array().default(["*"]),
8588
- origins: z28.string().array().default(["*"]),
8589
- methods: z28.enum(["GET", "DELETE", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "ALL"]).array().default(["ALL"])
8595
+ exposeHeaders: z29.string().array().optional(),
8596
+ credentials: z29.boolean().default(false),
8597
+ headers: z29.string().array().default(["*"]),
8598
+ origins: z29.string().array().default(["*"]),
8599
+ methods: z29.enum(["GET", "DELETE", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "ALL"]).array().default(["ALL"])
8590
8600
  }).optional().describe("Define the cors headers."),
8591
- security: z28.object({
8601
+ security: z29.object({
8592
8602
  // contentSecurityPolicy: z.object({
8593
8603
  // override: z.boolean().default(false),
8594
8604
  // policy: z.string(),
@@ -8630,10 +8640,10 @@ var SitesSchema = z28.record(
8630
8640
  // reportUri?: string
8631
8641
  // }
8632
8642
  }).optional().describe("Define the security policy."),
8633
- cache: z28.object({
8634
- cookies: z28.string().array().optional().describe("Specifies the cookies that CloudFront includes in the cache key."),
8635
- headers: z28.string().array().optional().describe("Specifies the headers that CloudFront includes in the cache key."),
8636
- queries: z28.string().array().optional().describe("Specifies the query values that CloudFront includes in the cache key.")
8643
+ cache: z29.object({
8644
+ cookies: z29.string().array().optional().describe("Specifies the cookies that CloudFront includes in the cache key."),
8645
+ headers: z29.string().array().optional().describe("Specifies the headers that CloudFront includes in the cache key."),
8646
+ queries: z29.string().array().optional().describe("Specifies the query values that CloudFront includes in the cache key.")
8637
8647
  }).optional().describe(
8638
8648
  "Specifies the cookies, headers, and query values that CloudFront includes in the cache key."
8639
8649
  )
@@ -8641,22 +8651,22 @@ var SitesSchema = z28.record(
8641
8651
  ).optional().describe("Define the sites in your stack.");
8642
8652
 
8643
8653
  // src/feature/stream/schema.ts
8644
- import { z as z29 } from "zod";
8645
- var LatencyModeSchema = z29.enum(["low", "normal"]).describe(
8654
+ import { z as z30 } from "zod";
8655
+ var LatencyModeSchema = z30.enum(["low", "normal"]).describe(
8646
8656
  `Channel latency mode. Valid values:
8647
8657
  - normal: Use "normal" to broadcast and deliver live video up to Full HD.
8648
8658
  - low: Use "low" for near real-time interactions with viewers.`
8649
8659
  );
8650
- var TypeSchema4 = z29.enum(["standard", "basic", "advanced-sd", "advanced-hd"]).describe(`The channel type, which determines the allowable resolution and bitrate.
8660
+ var TypeSchema4 = z30.enum(["standard", "basic", "advanced-sd", "advanced-hd"]).describe(`The channel type, which determines the allowable resolution and bitrate.
8651
8661
  If you exceed the allowable resolution or bitrate, the stream probably will disconnect immediately. Valid values:
8652
8662
  - standard: Video is transcoded: multiple qualities are generated from the original input to automatically give viewers the best experience for their devices and network conditions. Transcoding allows higher playback quality across a range of download speeds. Resolution can be up to 1080p and bitrate can be up to 8.5 Mbps. Audio is transcoded only for renditions 360p and below; above that, audio is passed through.
8653
8663
  - basic: Video is transmuxed: Amazon IVS delivers the original input to viewers. The viewer's video-quality choice is limited to the original input. Resolution can be up to 1080p and bitrate can be up to 1.5 Mbps for 480p and up to 3.5 Mbps for resolutions between 480p and 1080p.
8654
8664
  - advanced-sd: Video is transcoded; multiple qualities are generated from the original input, to automatically give viewers the best experience for their devices and network conditions. Input resolution can be up to 1080p and bitrate can be up to 8.5 Mbps; output is capped at SD quality (480p). You can select an optional transcode preset (see below). Audio for all renditions is transcoded, and an audio-only rendition is available.
8655
8665
  - advanced-hd: Video is transcoded; multiple qualities are generated from the original input, to automatically give viewers the best experience for their devices and network conditions. Input resolution can be up to 1080p and bitrate can be up to 8.5 Mbps; output is capped at HD quality (720p). You can select an optional transcode preset (see below). Audio for all renditions is transcoded, and an audio-only rendition is available.
8656
8666
  `);
8657
- var StreamsSchema = z29.record(
8667
+ var StreamsSchema = z30.record(
8658
8668
  ResourceIdSchema,
8659
- z29.object({
8669
+ z30.object({
8660
8670
  type: TypeSchema4.default("standard"),
8661
8671
  // preset: PresetSchema.optional(),
8662
8672
  latencyMode: LatencyModeSchema.default("low")
@@ -8664,46 +8674,46 @@ var StreamsSchema = z29.record(
8664
8674
  ).optional().describe("Define the streams in your stack.");
8665
8675
 
8666
8676
  // src/feature/task/schema.ts
8667
- import { z as z30 } from "zod";
8668
- var RetryAttemptsSchema2 = z30.number().int().min(0).max(2).describe(
8677
+ import { z as z31 } from "zod";
8678
+ var RetryAttemptsSchema2 = z31.number().int().min(0).max(2).describe(
8669
8679
  "The maximum number of times to retry when the function returns an error. You can specify a number from 0 to 2."
8670
8680
  );
8671
- var TaskSchema = z30.union([
8681
+ var TaskSchema = z31.union([
8672
8682
  LocalFileSchema.transform((file) => ({
8673
8683
  consumer: { file },
8674
8684
  retryAttempts: void 0
8675
8685
  })),
8676
- z30.object({
8686
+ z31.object({
8677
8687
  consumer: FunctionSchema,
8678
8688
  retryAttempts: RetryAttemptsSchema2.optional()
8679
8689
  })
8680
8690
  ]);
8681
- var TasksSchema = z30.record(ResourceIdSchema, TaskSchema).optional().describe("Define the tasks in your stack.");
8691
+ var TasksSchema = z31.record(ResourceIdSchema, TaskSchema).optional().describe("Define the tasks in your stack.");
8682
8692
 
8683
8693
  // src/feature/test/schema.ts
8684
- import { z as z31 } from "zod";
8685
- var TestsSchema = z31.union([LocalDirectorySchema.transform((v) => [v]), LocalDirectorySchema.array()]).describe("Define the location of your tests for your stack.").optional();
8694
+ import { z as z32 } from "zod";
8695
+ var TestsSchema = z32.union([LocalDirectorySchema.transform((v) => [v]), LocalDirectorySchema.array()]).describe("Define the location of your tests for your stack.").optional();
8686
8696
 
8687
8697
  // src/feature/topic/schema.ts
8688
8698
  import { paramCase as paramCase2 } from "change-case";
8689
- import { z as z32 } from "zod";
8690
- var TopicNameSchema = z32.string().min(3).max(256).regex(/^[a-z0-9\-]+$/i, "Invalid topic name").transform((value) => paramCase2(value)).describe("Define event topic name.");
8691
- var TopicsSchema = z32.array(TopicNameSchema).refine((topics) => {
8699
+ import { z as z33 } from "zod";
8700
+ var TopicNameSchema = z33.string().min(3).max(256).regex(/^[a-z0-9\-]+$/i, "Invalid topic name").transform((value) => paramCase2(value)).describe("Define event topic name.");
8701
+ var TopicsSchema = z33.array(TopicNameSchema).refine((topics) => {
8692
8702
  return topics.length === new Set(topics).size;
8693
8703
  }, "Must be a list of unique topic names").optional().describe("Define the event topics to publish too in your stack.");
8694
- var SubscribersSchema = z32.record(TopicNameSchema, z32.union([EmailSchema, FunctionSchema])).optional().describe("Define the event topics to subscribe too in your stack.");
8704
+ var SubscribersSchema = z33.record(TopicNameSchema, z33.union([EmailSchema, FunctionSchema])).optional().describe("Define the event topics to subscribe too in your stack.");
8695
8705
 
8696
8706
  // src/config/stack.ts
8697
8707
  var DependsSchema = ResourceIdSchema.array().optional().describe("Define the stacks that this stack is depended on.");
8698
8708
  var NameSchema = ResourceIdSchema.refine((name) => !["base"].includes(name), {
8699
8709
  message: `Stack name can't be a reserved name.`
8700
8710
  }).describe("Stack name.");
8701
- var StackSchema = z33.object({
8702
- $schema: z33.string().optional(),
8711
+ var StackSchema = z34.object({
8712
+ $schema: z34.string().optional(),
8703
8713
  name: NameSchema,
8704
8714
  depends: DependsSchema,
8705
8715
  commands: CommandsSchema,
8706
- onFailure: OnFailureSchema,
8716
+ // onFailure: OnFailureSchema,
8707
8717
  auth: AuthSchema,
8708
8718
  graphql: GraphQLSchema,
8709
8719
  http: HttpSchema,
@@ -8766,13 +8776,13 @@ var readConfigWithStage = async (file, stage) => {
8766
8776
  };
8767
8777
 
8768
8778
  // src/config/load/validate.ts
8769
- import { z as z34 } from "zod";
8779
+ import { z as z35 } from "zod";
8770
8780
  var validateConfig = async (schema, file, data) => {
8771
8781
  try {
8772
8782
  const result = await schema.parseAsync(data);
8773
8783
  return result;
8774
8784
  } catch (error) {
8775
- if (error instanceof z34.ZodError) {
8785
+ if (error instanceof z35.ZodError) {
8776
8786
  throw new ConfigError(file, error, data);
8777
8787
  }
8778
8788
  throw error;
@@ -10425,13 +10435,7 @@ var formatByteSize = (size) => {
10425
10435
 
10426
10436
  // src/feature/on-failure/util.ts
10427
10437
  var getGlobalOnFailure = (ctx) => {
10428
- return hasOnFailure(ctx.stackConfigs) ? ctx.shared.get("on-failure-queue-arn") : void 0;
10429
- };
10430
- var hasOnFailure = (stacks) => {
10431
- const onFailure = stacks.find((stack) => {
10432
- return typeof stack.onFailure !== "undefined";
10433
- });
10434
- return !!onFailure;
10438
+ return ctx.appConfig.defaults.onFailure ? ctx.shared.get("on-failure-queue-arn") : void 0;
10435
10439
  };
10436
10440
 
10437
10441
  // src/feature/function/build/typescript/bundle.ts
@@ -10562,6 +10566,14 @@ var createTempFolder = async (name) => {
10562
10566
  };
10563
10567
  };
10564
10568
 
10569
+ // src/feature/on-log/util.ts
10570
+ var getGlobalOnLog = (ctx) => {
10571
+ return ctx.appConfig.defaults.onLog ? ctx.shared.get("on-log-consumer-arn") : void 0;
10572
+ };
10573
+ var formatFilterPattern = (filters) => {
10574
+ return `{${filters.map((filter) => `$.level = "${filter.toUpperCase()}"`).join(" || ")}}`;
10575
+ };
10576
+
10565
10577
  // src/feature/function/build/container/build.ts
10566
10578
  import { exec } from "promisify-child-process";
10567
10579
  var buildDockerImage = async (opts) => {
@@ -10728,12 +10740,13 @@ var createLambdaFunction = (group, ctx, ns, id, local2) => {
10728
10740
  resources: [logGroup.arn.apply((arn) => `${arn}:*`)]
10729
10741
  }
10730
10742
  );
10731
- const logSubscriptionArn = ctx.shared.get("log-subscription-destination-arn");
10732
- if (logSubscriptionArn) {
10733
- new aws2.cloudWatch.SubscriptionFilter(group, `log-subscription`, {
10734
- destinationArn: logSubscriptionArn,
10743
+ const onLogArn = getGlobalOnLog(ctx);
10744
+ if (onLogArn && ctx.appConfig.defaults.onLog) {
10745
+ const logFilter = ctx.appConfig.defaults.onLog.filter;
10746
+ new aws2.cloudWatch.SubscriptionFilter(group, `on-log`, {
10747
+ destinationArn: onLogArn,
10735
10748
  logGroupName: logGroup.name,
10736
- filterPattern: "{$.level = ERROR}"
10749
+ filterPattern: formatFilterPattern(logFilter)
10737
10750
  });
10738
10751
  }
10739
10752
  }
@@ -10810,10 +10823,11 @@ var createAsyncLambdaFunction = (group, ctx, ns, id, local2) => {
10810
10823
  onFailure: getGlobalOnFailure(ctx)
10811
10824
  });
10812
10825
  invokeConfig.dependsOn(result.policy);
10813
- if (hasOnFailure(ctx.stackConfigs)) {
10826
+ const onFailure = getGlobalOnFailure(ctx);
10827
+ if (onFailure) {
10814
10828
  result.policy.addStatement({
10815
10829
  actions: ["sqs:SendMessage", "sqs:GetQueueUrl"],
10816
- resources: [getGlobalOnFailure(ctx)]
10830
+ resources: [onFailure]
10817
10831
  });
10818
10832
  }
10819
10833
  return result;
@@ -11145,7 +11159,7 @@ var configFeature = defineFeature({
11145
11159
  }
11146
11160
  if (configs.length) {
11147
11161
  ctx.addEnv("CONFIG", configs.join(","));
11148
- ctx.onPolicy((policy) => {
11162
+ ctx.onStackPolicy((policy) => {
11149
11163
  policy.addStatement({
11150
11164
  actions: [
11151
11165
  "ssm:GetParameter",
@@ -11297,7 +11311,7 @@ var domainFeature = defineFeature({
11297
11311
  });
11298
11312
  }
11299
11313
  }
11300
- ctx.onPolicy(
11314
+ ctx.onGlobalPolicy(
11301
11315
  (policy) => policy.addStatement({
11302
11316
  actions: ["ses:*"],
11303
11317
  resources: [`arn:aws:ses:${ctx.appConfig.region}:${ctx.accountId}:identity/*`]
@@ -11381,7 +11395,10 @@ var functionFeature = defineFeature({
11381
11395
  types2.addInterface("FunctionMockResponse", mockResponses);
11382
11396
  await ctx.write("function.d.ts", types2, true);
11383
11397
  },
11384
- onApp(ctx) {
11398
+ // We are putting the resources for this feature in a onBefore hook
11399
+ // because we will need it for functions defined in the onApp hook
11400
+ // in different features
11401
+ onBefore(ctx) {
11385
11402
  const group = new Node6(ctx.base, "function", "asset");
11386
11403
  const bucket = new aws7.s3.Bucket(group, "bucket", {
11387
11404
  name: formatGlobalResourceName({
@@ -11410,7 +11427,9 @@ var functionFeature = defineFeature({
11410
11427
  });
11411
11428
  ctx.shared.set("function-repository-name", repository.name);
11412
11429
  ctx.shared.set("function-repository-uri", repository.uri);
11413
- ctx.onPolicy((policy) => {
11430
+ },
11431
+ onApp(ctx) {
11432
+ ctx.onGlobalPolicy((policy) => {
11414
11433
  policy.addStatement({
11415
11434
  actions: ["lambda:InvokeFunction", "lambda:InvokeAsync"],
11416
11435
  resources: [`arn:aws:lambda:*:*:function:${ctx.appConfig.name}--*`]
@@ -12115,70 +12134,30 @@ var instanceFeature = defineFeature({
12115
12134
  }
12116
12135
  });
12117
12136
 
12118
- // src/feature/log-subscription/index.ts
12137
+ // src/feature/on-log/index.ts
12119
12138
  import { Node as Node10, aws as aws11 } from "@awsless/formation";
12120
- var logSubscriptionFeature = defineFeature({
12121
- name: "log-subscription",
12139
+ var onLogFeature = defineFeature({
12140
+ name: "on-log",
12122
12141
  onApp(ctx) {
12123
- if (!ctx.appConfig.logSubscription) {
12142
+ if (!ctx.appConfig.defaults.onLog) {
12124
12143
  return;
12125
12144
  }
12126
- const group = new Node10(ctx.base, "log-subscription", "main");
12127
- const { lambda, policy } = createLambdaFunction(
12145
+ const group = new Node10(ctx.base, "on-log", "main");
12146
+ const { lambda } = createLambdaFunction(
12147
+ //
12128
12148
  group,
12129
12149
  ctx,
12130
- "log-subscription",
12131
- "main",
12132
- ctx.appConfig.logSubscription
12150
+ "on-log",
12151
+ "consumer",
12152
+ ctx.appConfig.defaults.onLog.consumer
12133
12153
  );
12134
- new aws11.lambda.Permission(group, "log-subscription-permission", {
12154
+ new aws11.lambda.Permission(group, "permission", {
12135
12155
  action: "lambda:InvokeFunction",
12136
12156
  principal: "logs.amazonaws.com",
12137
12157
  functionArn: lambda.arn,
12138
- sourceArn: `arn:aws:logs:${ctx.appConfig.region}:${ctx.accountId}:log-group:/aws/lambda/app-kennedy--*`
12158
+ sourceArn: `arn:aws:logs:${ctx.appConfig.region}:${ctx.accountId}:log-group:/aws/lambda/${ctx.app.name}--*`
12139
12159
  });
12140
- ctx.shared.set("log-subscription-destination-arn", lambda.arn);
12141
- for (const stack of ctx.stackConfigs) {
12142
- for (const id of stack.topics ?? []) {
12143
- policy.addStatement({
12144
- actions: ["sns:Publish"],
12145
- resources: [ctx.shared.get(`topic-${id}-arn`)]
12146
- });
12147
- }
12148
- for (const [id, props] of Object.entries(stack.tables ?? {})) {
12149
- const tableName = formatLocalResourceName({
12150
- appName: ctx.app.name,
12151
- stackName: stack.name,
12152
- resourceType: "table",
12153
- resourceName: id
12154
- });
12155
- policy.addStatement({
12156
- actions: [
12157
- "dynamodb:DescribeTable",
12158
- "dynamodb:PutItem",
12159
- "dynamodb:GetItem",
12160
- "dynamodb:UpdateItem",
12161
- "dynamodb:DeleteItem",
12162
- "dynamodb:TransactWrite",
12163
- "dynamodb:BatchWriteItem",
12164
- "dynamodb:BatchGetItem",
12165
- "dynamodb:ConditionCheckItem",
12166
- "dynamodb:Query",
12167
- "dynamodb:Scan"
12168
- ],
12169
- resources: [`arn:aws:dynamodb:${ctx.appConfig.region}:${ctx.accountId}:table/${tableName}`]
12170
- });
12171
- const indexes = Object.keys(props.indexes ?? {});
12172
- if (indexes.length) {
12173
- policy.addStatement({
12174
- actions: ["dynamodb:Query"],
12175
- resources: indexes.map(
12176
- (indexName) => `arn:aws:dynamodb:${ctx.appConfig.region}:${ctx.accountId}:table/${tableName}/index/${indexName}`
12177
- )
12178
- });
12179
- }
12180
- }
12181
- }
12160
+ ctx.shared.set("on-log-consumer-arn", lambda.arn);
12182
12161
  }
12183
12162
  });
12184
12163
 
@@ -12186,15 +12165,20 @@ var logSubscriptionFeature = defineFeature({
12186
12165
  import { Node as Node11, aws as aws12 } from "@awsless/formation";
12187
12166
  var onFailureFeature = defineFeature({
12188
12167
  name: "on-failure",
12168
+ // onValidate(ctx) {
12169
+ // // ----------------------------------------------------------------
12170
+ // // Only allow a on-failure single listener
12171
+ // const count = ctx.stackConfigs.filter(s => s.onFailure).length
12172
+ // if (count > 1) {
12173
+ // throw new TypeError('Only 1 onFailure configuration is allowed in your app.')
12174
+ // }
12175
+ // },
12189
12176
  onApp(ctx) {
12190
- if (!hasOnFailure(ctx.stackConfigs)) {
12177
+ if (!ctx.appConfig.defaults.onFailure) {
12191
12178
  return;
12192
12179
  }
12193
- const count = ctx.stackConfigs.filter((s) => s.onFailure).length;
12194
- if (count > 1) {
12195
- throw new TypeError("Only 1 onFailure configuration is allowed in your app.");
12196
- }
12197
- const queue2 = new aws12.sqs.Queue(ctx.base, "on-failure", {
12180
+ const group = new Node11(ctx.base, "on-failure", "main");
12181
+ const queue2 = new aws12.sqs.Queue(group, "on-failure", {
12198
12182
  name: formatGlobalResourceName({
12199
12183
  appName: ctx.app.name,
12200
12184
  resourceType: "on-failure",
@@ -12202,18 +12186,16 @@ var onFailureFeature = defineFeature({
12202
12186
  })
12203
12187
  });
12204
12188
  ctx.shared.set("on-failure-queue-arn", queue2.arn);
12205
- },
12206
- onStack(ctx) {
12207
- const onFailure = ctx.stackConfig.onFailure;
12208
- if (!onFailure) {
12209
- return;
12210
- }
12211
- const queueArn = ctx.shared.get("on-failure-queue-arn");
12212
- const group = new Node11(ctx.stack, "on-failure", "failure");
12213
- const { lambda, policy } = createLambdaFunction(group, ctx, "on-failure", "failure", onFailure);
12189
+ const { lambda, policy } = createLambdaFunction(
12190
+ group,
12191
+ ctx,
12192
+ "on-failure",
12193
+ "consumer",
12194
+ ctx.appConfig.defaults.onFailure
12195
+ );
12214
12196
  const source = new aws12.lambda.EventSourceMapping(group, "on-failure", {
12215
12197
  functionArn: lambda.arn,
12216
- sourceArn: queueArn,
12198
+ sourceArn: queue2.arn,
12217
12199
  batchSize: 10
12218
12200
  });
12219
12201
  source.dependsOn(policy);
@@ -12225,9 +12207,34 @@ var onFailureFeature = defineFeature({
12225
12207
  "sqs:GetQueueUrl",
12226
12208
  "sqs:GetQueueAttributes"
12227
12209
  ],
12228
- resources: [queueArn]
12210
+ resources: [queue2.arn]
12229
12211
  });
12230
12212
  }
12213
+ // onStack(ctx) {
12214
+ // const onFailure = ctx.stackConfig.onFailure
12215
+ // if (!onFailure) {
12216
+ // return
12217
+ // }
12218
+ // const queueArn = ctx.shared.get<aws.ARN>('on-failure-queue-arn')
12219
+ // const group = new Node(ctx.stack, 'on-failure', 'failure')
12220
+ // const { lambda, policy } = createLambdaFunction(group, ctx, 'on-failure', 'failure', onFailure)
12221
+ // const source = new aws.lambda.EventSourceMapping(group, 'on-failure', {
12222
+ // functionArn: lambda.arn,
12223
+ // sourceArn: queueArn,
12224
+ // batchSize: 10,
12225
+ // })
12226
+ // source.dependsOn(policy)
12227
+ // policy.addStatement({
12228
+ // actions: [
12229
+ // 'sqs:SendMessage',
12230
+ // 'sqs:DeleteMessage',
12231
+ // 'sqs:ReceiveMessage',
12232
+ // 'sqs:GetQueueUrl',
12233
+ // 'sqs:GetQueueAttributes',
12234
+ // ],
12235
+ // resources: [queueArn],
12236
+ // })
12237
+ // },
12231
12238
  });
12232
12239
 
12233
12240
  // src/feature/pubsub/index.ts
@@ -12283,7 +12290,7 @@ var pubsubFeature = defineFeature({
12283
12290
  ctx.bind(`PUBSUB_${constantCase6(id)}_ENDPOINT`, endpoint.address);
12284
12291
  }
12285
12292
  }
12286
- ctx.onPolicy((policy) => {
12293
+ ctx.onGlobalPolicy((policy) => {
12287
12294
  policy.addStatement({
12288
12295
  actions: [`iot:Publish`],
12289
12296
  resources: [`arn:aws:iot:${ctx.appConfig.region}:${ctx.accountId}:topic/*`]
@@ -12404,7 +12411,7 @@ var queueFeature = defineFeature({
12404
12411
  resources: [queue2.arn]
12405
12412
  });
12406
12413
  ctx.addEnv(`QUEUE_${constantCase7(ctx.stack.name)}_${constantCase7(id)}_URL`, queue2.url);
12407
- ctx.onPolicy((policy2) => {
12414
+ ctx.onStackPolicy((policy2) => {
12408
12415
  policy2.addStatement(queue2.permissions);
12409
12416
  });
12410
12417
  }
@@ -12868,7 +12875,7 @@ var searchFeature = defineFeature({
12868
12875
  });
12869
12876
  }
12870
12877
  ctx.addEnv(`SEARCH_${constantCase10(ctx.stack.name)}_${constantCase10(id)}_DOMAIN`, openSearch.domainEndpoint);
12871
- ctx.onPolicy((policy) => {
12878
+ ctx.onStackPolicy((policy) => {
12872
12879
  policy.addStatement({
12873
12880
  actions: ["es:ESHttp*"],
12874
12881
  resources: [openSearch.arn]
@@ -12972,7 +12979,7 @@ var siteFeature = defineFeature({
12972
12979
  }
12973
12980
  ]
12974
12981
  });
12975
- ctx.onPolicy((policy) => {
12982
+ ctx.onStackPolicy((policy) => {
12976
12983
  policy.addStatement(bucket.permissions);
12977
12984
  });
12978
12985
  bucket.deletionPolicy = "after-deployment";
@@ -13147,6 +13154,33 @@ var storeFeature = defineFeature({
13147
13154
  gen.addInterface("StoreResources", resources);
13148
13155
  await ctx.write("store.d.ts", gen, true);
13149
13156
  },
13157
+ onApp(ctx) {
13158
+ ctx.onAppPolicy((policy) => {
13159
+ const name = formatLocalResourceName({
13160
+ appName: ctx.app.name,
13161
+ stackName: "*",
13162
+ resourceType: "store",
13163
+ resourceName: "*"
13164
+ });
13165
+ policy.addStatement({
13166
+ actions: [
13167
+ "s3:ListBucket",
13168
+ "s3:ListBucketV2",
13169
+ "s3:HeadObject",
13170
+ "s3:GetObject",
13171
+ "s3:PutObject",
13172
+ "s3:DeleteObject",
13173
+ "s3:CopyObject",
13174
+ "s3:GetObjectAttributes"
13175
+ ],
13176
+ resources: [
13177
+ //
13178
+ `arn:aws:s3:::${name}`,
13179
+ `arn:aws:s3:::${name}/*`
13180
+ ]
13181
+ });
13182
+ });
13183
+ },
13150
13184
  onStack(ctx) {
13151
13185
  for (const [id, props] of Object.entries(ctx.stackConfig.stores ?? {})) {
13152
13186
  const group = new Node19(ctx.stack, "store", id);
@@ -13206,7 +13240,7 @@ var storeFeature = defineFeature({
13206
13240
  if (deletionProtection) {
13207
13241
  bucket.deletionPolicy = "retain";
13208
13242
  }
13209
- ctx.onPolicy((policy) => {
13243
+ ctx.onStackPolicy((policy) => {
13210
13244
  policy.addStatement(bucket.permissions);
13211
13245
  });
13212
13246
  }
@@ -13265,6 +13299,33 @@ var tableFeature = defineFeature({
13265
13299
  gen.addInterface("TableResources", resources);
13266
13300
  await ctx.write("table.d.ts", gen, true);
13267
13301
  },
13302
+ onApp(ctx) {
13303
+ ctx.onAppPolicy((policy) => {
13304
+ const name = formatLocalResourceName({
13305
+ appName: ctx.app.name,
13306
+ stackName: "*",
13307
+ resourceType: "table",
13308
+ resourceName: "*"
13309
+ });
13310
+ policy.addStatement({
13311
+ actions: [
13312
+ "dynamodb:PutItem",
13313
+ "dynamodb:UpdateItem",
13314
+ "dynamodb:DeleteItem",
13315
+ "dynamodb:BatchWriteItem",
13316
+ "dynamodb:GetItem",
13317
+ "dynamodb:BatchGetItem",
13318
+ "dynamodb:Scan",
13319
+ "dynamodb:Query",
13320
+ "dynamodb:ConditionCheckItem"
13321
+ ],
13322
+ resources: [
13323
+ `arn:aws:dynamodb:${ctx.appConfig.region}:*:table/${name}`,
13324
+ `arn:aws:dynamodb:${ctx.appConfig.region}:*:table/${name}/index/*`
13325
+ ]
13326
+ });
13327
+ });
13328
+ },
13268
13329
  onStack(ctx) {
13269
13330
  for (const [id, props] of Object.entries(ctx.stackConfig.tables ?? {})) {
13270
13331
  const group = new Node21(ctx.stack, "table", id);
@@ -13307,7 +13368,7 @@ var tableFeature = defineFeature({
13307
13368
  });
13308
13369
  }
13309
13370
  }
13310
- ctx.onPolicy((policy) => {
13371
+ ctx.onStackPolicy((policy) => {
13311
13372
  policy.addStatement(...table2.permissions);
13312
13373
  });
13313
13374
  }
@@ -13466,10 +13527,22 @@ var topicFeature = defineFeature({
13466
13527
  ctx.shared.set(`topic-${id}-arn`, topic.arn);
13467
13528
  }
13468
13529
  }
13530
+ ctx.onAppPolicy((policy) => {
13531
+ policy.addStatement({
13532
+ actions: ["sns:Publish"],
13533
+ resources: [
13534
+ `arn:aws:sns:${ctx.appConfig.region}:*:${formatGlobalResourceName({
13535
+ appName: ctx.app.name,
13536
+ resourceType: "topic",
13537
+ resourceName: "*"
13538
+ })}`
13539
+ ]
13540
+ });
13541
+ });
13469
13542
  },
13470
13543
  onStack(ctx) {
13471
13544
  for (const id of ctx.stackConfig.topics ?? []) {
13472
- ctx.onPolicy((policy) => {
13545
+ ctx.onStackPolicy((policy) => {
13473
13546
  policy.addStatement({
13474
13547
  actions: ["sns:Publish"],
13475
13548
  resources: [ctx.shared.get(`topic-${id}-arn`)]
@@ -13579,6 +13652,7 @@ var features = [
13579
13652
  domainFeature,
13580
13653
  commandFeature,
13581
13654
  onFailureFeature,
13655
+ onLogFeature,
13582
13656
  // 2
13583
13657
  authFeature,
13584
13658
  // 3
@@ -13601,8 +13675,6 @@ var features = [
13601
13675
  restFeature,
13602
13676
  siteFeature,
13603
13677
  // 4
13604
- logSubscriptionFeature,
13605
- // I think needs to be after s3 feature
13606
13678
  rpcFeature
13607
13679
  ];
13608
13680
 
@@ -13928,30 +14000,38 @@ var createApp = (props) => {
13928
14000
  const allLocalEnvListeners = {};
13929
14001
  const globalPolicies = [];
13930
14002
  const globalPoliciesListeners = [];
13931
- const allLocalPolicies = {};
13932
- const allLocalPolicyListeners = {};
14003
+ const appPolicies = [];
14004
+ const appPoliciesListeners = [];
14005
+ const allStackPolicies = {};
14006
+ const allStackPolicyListeners = {};
13933
14007
  for (const stackConfig of props.stackConfigs) {
13934
14008
  assertDepsExists(stackConfig, props.stackConfigs);
13935
14009
  }
14010
+ for (const feature of features) {
14011
+ feature.onBefore?.({
14012
+ ...props,
14013
+ app,
14014
+ appId,
14015
+ base: base2,
14016
+ shared
14017
+ });
14018
+ }
13936
14019
  for (const feature of features) {
13937
14020
  feature.onApp?.({
13938
14021
  ...props,
13939
14022
  app,
13940
14023
  appId,
13941
- // env,
13942
14024
  base: base2,
13943
14025
  shared,
13944
- onPolicy(callback) {
14026
+ onGlobalPolicy(callback) {
13945
14027
  globalPoliciesListeners.push(callback);
13946
14028
  },
13947
- // onFunction(callback) {
13948
- // allFunctionListeners.push(callback)
13949
- // },
13950
- // registerFunction(lambda) {
13951
- // allFunctions.push(lambda)
13952
- // },
14029
+ onAppPolicy(callback) {
14030
+ appPoliciesListeners.push(callback);
14031
+ },
13953
14032
  registerPolicy(policy) {
13954
14033
  globalPolicies.push(policy);
14034
+ appPolicies.push(policy);
13955
14035
  },
13956
14036
  registerBuild(type, name, builder) {
13957
14037
  builders.push({
@@ -13964,9 +14044,6 @@ var createApp = (props) => {
13964
14044
  registerCommand(command) {
13965
14045
  commands7.push(command);
13966
14046
  },
13967
- // registerSiteFunction(lambda) {
13968
- // siteFunctions.push(lambda)
13969
- // },
13970
14047
  bind(name, value) {
13971
14048
  binds.push({ name, value });
13972
14049
  },
@@ -13986,12 +14063,12 @@ var createApp = (props) => {
13986
14063
  }
13987
14064
  for (const stackConfig of props.stackConfigs) {
13988
14065
  const stack = new Stack(app, stackConfig.name);
13989
- const localPolicyListeners = [];
13990
- const localPolicies = [];
14066
+ const stackPolicyListeners = [];
14067
+ const stackPolicies = [];
13991
14068
  const localEnvListeners = [];
13992
14069
  const localEnv = [];
13993
- allLocalPolicyListeners[stack.name] = localPolicyListeners;
13994
- allLocalPolicies[stack.name] = localPolicies;
14070
+ allStackPolicyListeners[stack.name] = stackPolicyListeners;
14071
+ allStackPolicies[stack.name] = stackPolicies;
13995
14072
  allLocalEnvListeners[stack.name] = localEnvListeners;
13996
14073
  allLocalEnv[stack.name] = localEnv;
13997
14074
  for (const feature of features) {
@@ -14000,24 +14077,26 @@ var createApp = (props) => {
14000
14077
  stackConfig,
14001
14078
  app,
14002
14079
  appId,
14003
- // env,
14004
14080
  base: base2,
14005
14081
  stack,
14006
14082
  shared,
14007
- // onFunction(callback) {
14008
- // localFunctionListeners.push(callback)
14009
- // },
14010
- // registerFunction(lambda) {
14011
- // allFunctions.push(lambda)
14012
- // localFunctions.push(lambda)
14013
- // },
14014
- onPolicy(callback) {
14015
- localPolicyListeners.push(callback);
14083
+ onGlobalPolicy(callback) {
14084
+ globalPoliciesListeners.push(callback);
14085
+ },
14086
+ onAppPolicy(callback) {
14087
+ appPoliciesListeners.push(callback);
14088
+ },
14089
+ onStackPolicy(callback) {
14090
+ stackPolicyListeners.push(callback);
14016
14091
  },
14017
14092
  registerPolicy(policy) {
14018
14093
  globalPolicies.push(policy);
14019
- localPolicies.push(policy);
14094
+ stackPolicies.push(policy);
14020
14095
  },
14096
+ // registerPolicy(policy) {
14097
+ // globalPolicies.push(policy)
14098
+ // localPolicies.push(policy)
14099
+ // },
14021
14100
  registerTest(name, paths) {
14022
14101
  tests.push({
14023
14102
  stackName: stack.name,
@@ -14062,8 +14141,8 @@ var createApp = (props) => {
14062
14141
  }
14063
14142
  });
14064
14143
  }
14065
- for (const listener of localPolicyListeners) {
14066
- for (const policy of localPolicies) {
14144
+ for (const listener of stackPolicyListeners) {
14145
+ for (const policy of stackPolicies) {
14067
14146
  listener(policy);
14068
14147
  }
14069
14148
  }
@@ -14073,6 +14152,11 @@ var createApp = (props) => {
14073
14152
  }
14074
14153
  }
14075
14154
  }
14155
+ for (const listener of appPoliciesListeners) {
14156
+ for (const fn of appPolicies) {
14157
+ listener(fn);
14158
+ }
14159
+ }
14076
14160
  for (const listener of globalPoliciesListeners) {
14077
14161
  for (const fn of globalPolicies) {
14078
14162
  listener(fn);
@@ -14084,10 +14168,10 @@ var createApp = (props) => {
14084
14168
  }
14085
14169
  }
14086
14170
  for (const stackConfig of props.stackConfigs) {
14087
- const policies = allLocalPolicies[stackConfig.name];
14171
+ const policies = allStackPolicies[stackConfig.name];
14088
14172
  const envListeners = allLocalEnvListeners[stackConfig.name];
14089
14173
  for (const dependency of stackConfig.depends ?? []) {
14090
- const policyListeners = allLocalPolicyListeners[dependency];
14174
+ const policyListeners = allStackPolicyListeners[dependency];
14091
14175
  const env = allLocalEnv[dependency];
14092
14176
  for (const policy of policies) {
14093
14177
  for (const listener of policyListeners) {