@awsless/awsless 0.0.323 → 0.0.326

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
@@ -322,7 +322,7 @@ var bootstrapAwsless = async (props) => {
322
322
  hasStateBucket(s3, props.accountId)
323
323
  ]);
324
324
  if (!table2 || !bucket) {
325
- log.warn(`Your Awsless hasn't been bootstrapped yet.`);
325
+ log.warn(`Awsless hasn't been bootstrapped yet.`);
326
326
  if (!process.env.SKIP_PROMPT) {
327
327
  const confirmed = await confirm({
328
328
  message: "Would you like to bootstrap now?"
@@ -338,7 +338,7 @@ var bootstrapAwsless = async (props) => {
338
338
  if (!bucket) {
339
339
  await createStateBucket(s3, props.accountId);
340
340
  }
341
- update("Done deploying the bootstrap stack");
341
+ update("Done deploying the bootstrap stack.");
342
342
  });
343
343
  } else {
344
344
  log.step("Awsless has already been bootstrapped.");
@@ -370,7 +370,7 @@ var debug = (...parts) => {
370
370
  };
371
371
 
372
372
  // src/config/app.ts
373
- import { z as z18 } from "zod";
373
+ import { z as z20 } from "zod";
374
374
 
375
375
  // src/feature/auth/schema.ts
376
376
  import { z as z7 } from "zod";
@@ -915,8 +915,111 @@ var RestDefaultSchema = z16.record(
915
915
  ).optional().describe("Define your global REST API's.");
916
916
  var RestSchema = z16.record(ResourceIdSchema, z16.record(RouteSchema2, FunctionSchema)).optional().describe("Define routes in your stack for your global REST API.");
917
917
 
918
- // src/config/schema/region.ts
918
+ // src/feature/store/schema.ts
919
919
  import { z as z17 } from "zod";
920
+ var DeletionProtectionSchema = z17.boolean().describe("Specifies if you want to protect the store from being deleted by awsless.");
921
+ var StoreDefaultSchema = z17.object({
922
+ deletionProtection: DeletionProtectionSchema.optional()
923
+ }).optional();
924
+ var StoresSchema = z17.union([
925
+ z17.array(ResourceIdSchema).transform((list4) => {
926
+ const stores = {};
927
+ for (const key of list4) {
928
+ stores[key] = {};
929
+ }
930
+ return stores;
931
+ }),
932
+ z17.record(
933
+ ResourceIdSchema,
934
+ z17.object({
935
+ // cors: CorsSchema,
936
+ deletionProtection: DeletionProtectionSchema.optional(),
937
+ versioning: z17.boolean().default(false).describe("Enable versioning of your store."),
938
+ events: z17.object({
939
+ // create
940
+ "created:*": FunctionSchema.optional().describe(
941
+ "Subscribe to notifications regardless of the API that was used to create an object."
942
+ ),
943
+ "created:put": FunctionSchema.optional().describe(
944
+ "Subscribe to notifications when an object is created using the PUT API operation."
945
+ ),
946
+ "created:post": FunctionSchema.optional().describe(
947
+ "Subscribe to notifications when an object is created using the POST API operation."
948
+ ),
949
+ "created:copy": FunctionSchema.optional().describe(
950
+ "Subscribe to notifications when an object is created using the COPY API operation."
951
+ ),
952
+ "created:upload": FunctionSchema.optional().describe(
953
+ "Subscribe to notifications when an object multipart upload has been completed."
954
+ ),
955
+ // remove
956
+ "removed:*": FunctionSchema.optional().describe(
957
+ "Subscribe to notifications when an object is deleted or a delete marker for a versioned object is created."
958
+ ),
959
+ "removed:delete": FunctionSchema.optional().describe(
960
+ "Subscribe to notifications when an object is deleted"
961
+ ),
962
+ "removed:marker": FunctionSchema.optional().describe(
963
+ "Subscribe to notifications when a delete marker for a versioned object is created."
964
+ )
965
+ }).optional().describe("Describes the store events you want to subscribe too.")
966
+ })
967
+ )
968
+ ]).optional().describe("Define the stores in your stack.");
969
+
970
+ // src/feature/table/schema.ts
971
+ import { z as z18 } from "zod";
972
+ var KeySchema = z18.string().min(1).max(255);
973
+ var DeletionProtectionSchema2 = z18.boolean().describe("Specifies if you want to protect the table from being deleted by awsless.");
974
+ var TableDefaultSchema = z18.object({
975
+ deletionProtection: DeletionProtectionSchema2.optional()
976
+ }).optional();
977
+ var TablesSchema = z18.record(
978
+ ResourceIdSchema,
979
+ z18.object({
980
+ hash: KeySchema.describe(
981
+ "Specifies the name of the partition / hash key that makes up the primary key for the table."
982
+ ),
983
+ sort: KeySchema.optional().describe(
984
+ "Specifies the name of the range / sort key that makes up the primary key for the table."
985
+ ),
986
+ fields: z18.record(z18.string(), z18.enum(["string", "number", "binary"])).optional().describe(
987
+ 'A list of attributes that describe the key schema for the table and indexes. If no attribute field is defined we default to "string".'
988
+ ),
989
+ class: z18.enum(["standard", "standard-infrequent-access"]).default("standard").describe("The table class of the table."),
990
+ pointInTimeRecovery: z18.boolean().default(false).describe("Indicates whether point in time recovery is enabled on the table."),
991
+ timeToLiveAttribute: KeySchema.optional().describe(
992
+ "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."
993
+ ),
994
+ deletionProtection: DeletionProtectionSchema2.optional(),
995
+ stream: z18.object({
996
+ type: z18.enum(["keys-only", "new-image", "old-image", "new-and-old-images"]).describe(
997
+ "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."
998
+ ),
999
+ consumer: FunctionSchema.describe("The consuming lambda function for the stream")
1000
+ }).optional().describe(
1001
+ "The settings for the DynamoDB table stream, which capture changes to items stored in the table."
1002
+ ),
1003
+ indexes: z18.record(
1004
+ z18.string(),
1005
+ z18.object({
1006
+ /** Specifies the name of the partition / hash key that makes up the primary key for the global secondary index. */
1007
+ hash: KeySchema,
1008
+ /** Specifies the name of the range / sort key that makes up the primary key for the global secondary index. */
1009
+ sort: KeySchema.optional(),
1010
+ /** The set of attributes that are projected into the index:
1011
+ * - all - All of the table attributes are projected into the index.
1012
+ * - keys-only - Only the index and primary keys are projected into the index.
1013
+ * @default 'all'
1014
+ */
1015
+ projection: z18.enum(["all", "keys-only"]).default("all")
1016
+ })
1017
+ ).optional().describe("Specifies the global secondary indexes to be created on the table.")
1018
+ })
1019
+ ).optional().describe("Define the tables in your stack.");
1020
+
1021
+ // src/config/schema/region.ts
1022
+ import { z as z19 } from "zod";
920
1023
  var US = ["us-east-2", "us-east-1", "us-west-1", "us-west-2"];
921
1024
  var AF = ["af-south-1"];
922
1025
  var AP = [
@@ -945,20 +1048,20 @@ var EU = [
945
1048
  var ME = ["me-south-1", "me-central-1"];
946
1049
  var SA = ["sa-east-1"];
947
1050
  var regions = [...US, ...AF, ...AP, ...CA, ...EU, ...ME, ...SA];
948
- var RegionSchema = z17.enum(regions);
1051
+ var RegionSchema = z19.enum(regions);
949
1052
 
950
1053
  // src/config/app.ts
951
- var AppSchema = z18.object({
952
- $schema: z18.string().optional(),
1054
+ var AppSchema = z20.object({
1055
+ $schema: z20.string().optional(),
953
1056
  name: ResourceIdSchema.describe("App name."),
954
1057
  region: RegionSchema.describe("The AWS region to deploy to."),
955
- profile: z18.string().describe("The AWS profile to deploy to."),
1058
+ profile: z20.string().describe("The AWS profile to deploy to."),
956
1059
  // stage: z
957
1060
  // .string()
958
1061
  // .regex(/^[a-z]+$/)
959
1062
  // .default('prod')
960
1063
  // .describe('The deployment stage.'),
961
- defaults: z18.object({
1064
+ defaults: z20.object({
962
1065
  auth: AuthDefaultSchema,
963
1066
  domains: DomainsDefaultSchema,
964
1067
  function: FunctionDefaultSchema,
@@ -967,7 +1070,10 @@ var AppSchema = z18.object({
967
1070
  graphql: GraphQLDefaultSchema,
968
1071
  http: HttpDefaultSchema,
969
1072
  rest: RestDefaultSchema,
970
- pubsub: PubSubDefaultSchema
1073
+ pubsub: PubSubDefaultSchema,
1074
+ table: TableDefaultSchema,
1075
+ store: StoreDefaultSchema
1076
+ // dataRetention: z.boolean().describe('Configure how your resources are handled on delete.').default(false),
971
1077
  }).default({}).describe("Default properties")
972
1078
  });
973
1079
 
@@ -975,8 +1081,8 @@ var AppSchema = z18.object({
975
1081
  import { z as z32 } from "zod";
976
1082
 
977
1083
  // src/feature/cache/schema.ts
978
- import { z as z19 } from "zod";
979
- var TypeSchema2 = z19.enum([
1084
+ import { z as z21 } from "zod";
1085
+ var TypeSchema2 = z21.enum([
980
1086
  "t4g.small",
981
1087
  "t4g.medium",
982
1088
  "r6g.large",
@@ -991,29 +1097,29 @@ var TypeSchema2 = z19.enum([
991
1097
  "r6gd.4xlarge",
992
1098
  "r6gd.8xlarge"
993
1099
  ]);
994
- var PortSchema = z19.number().int().min(1).max(5e4);
995
- var ShardsSchema = z19.number().int().min(0).max(100);
996
- var ReplicasPerShardSchema = z19.number().int().min(0).max(5);
997
- var EngineSchema = z19.enum(["7.0", "6.2"]);
998
- var CachesSchema = z19.record(
1100
+ var PortSchema = z21.number().int().min(1).max(5e4);
1101
+ var ShardsSchema = z21.number().int().min(0).max(100);
1102
+ var ReplicasPerShardSchema = z21.number().int().min(0).max(5);
1103
+ var EngineSchema = z21.enum(["7.0", "6.2"]);
1104
+ var CachesSchema = z21.record(
999
1105
  ResourceIdSchema,
1000
- z19.object({
1106
+ z21.object({
1001
1107
  type: TypeSchema2.default("t4g.small"),
1002
1108
  port: PortSchema.default(6379),
1003
1109
  shards: ShardsSchema.default(1),
1004
1110
  replicasPerShard: ReplicasPerShardSchema.default(1),
1005
1111
  engine: EngineSchema.default("7.0"),
1006
- dataTiering: z19.boolean().default(false)
1112
+ dataTiering: z21.boolean().default(false)
1007
1113
  })
1008
1114
  ).optional().describe("Define the caches in your stack. For access to the cache put your functions inside the global VPC.");
1009
1115
 
1010
1116
  // src/feature/command/schema.ts
1011
- import { z as z20 } from "zod";
1012
- var CommandSchema2 = z20.union([
1013
- z20.object({
1117
+ import { z as z22 } from "zod";
1118
+ var CommandSchema2 = z22.union([
1119
+ z22.object({
1014
1120
  file: LocalFileSchema,
1015
- handler: z20.string().default("default").describe("The name of the handler that needs to run"),
1016
- description: z20.string().optional().describe("A description of the command")
1121
+ handler: z22.string().default("default").describe("The name of the handler that needs to run"),
1122
+ description: z22.string().optional().describe("A description of the command")
1017
1123
  // options: z.record(ResourceIdSchema, OptionSchema).optional(),
1018
1124
  // arguments: z.record(ResourceIdSchema, ArgumentSchema).optional(),
1019
1125
  }),
@@ -1023,22 +1129,22 @@ var CommandSchema2 = z20.union([
1023
1129
  description: void 0
1024
1130
  }))
1025
1131
  ]);
1026
- var CommandsSchema = z20.record(ResourceIdSchema, CommandSchema2).optional().describe("Define the custom commands for your stack.");
1132
+ var CommandsSchema = z22.record(ResourceIdSchema, CommandSchema2).optional().describe("Define the custom commands for your stack.");
1027
1133
 
1028
1134
  // src/feature/config/schema.ts
1029
- import { z as z21 } from "zod";
1030
- var ConfigNameSchema = z21.string().regex(/[a-z0-9\-]/g, "Invalid config name");
1031
- var ConfigsSchema = z21.array(ConfigNameSchema).optional().describe("Define the config values for your stack.");
1135
+ import { z as z23 } from "zod";
1136
+ var ConfigNameSchema = z23.string().regex(/[a-z0-9\-]/g, "Invalid config name");
1137
+ var ConfigsSchema = z23.array(ConfigNameSchema).optional().describe("Define the config values for your stack.");
1032
1138
 
1033
1139
  // src/feature/cron/schema/index.ts
1034
- import { z as z23 } from "zod";
1140
+ import { z as z25 } from "zod";
1035
1141
 
1036
1142
  // src/feature/cron/schema/schedule.ts
1037
- import { z as z22 } from "zod";
1143
+ import { z as z24 } from "zod";
1038
1144
  import { awsCronExpressionValidator } from "aws-cron-expression-validator";
1039
- var RateExpressionSchema = z22.custom(
1145
+ var RateExpressionSchema = z24.custom(
1040
1146
  (value) => {
1041
- return z22.string().regex(/^[0-9]+ (seconds?|minutes?|hours?|days?)$/).refine((rate) => {
1147
+ return z24.string().regex(/^[0-9]+ (seconds?|minutes?|hours?|days?)$/).refine((rate) => {
1042
1148
  const [str] = rate.split(" ");
1043
1149
  const number = parseInt(str);
1044
1150
  return number > 0;
@@ -1054,9 +1160,9 @@ var RateExpressionSchema = z22.custom(
1054
1160
  }
1055
1161
  return `rate(${rate})`;
1056
1162
  });
1057
- var CronExpressionSchema = z22.custom(
1163
+ var CronExpressionSchema = z24.custom(
1058
1164
  (value) => {
1059
- return z22.string().safeParse(value).success;
1165
+ return z24.string().safeParse(value).success;
1060
1166
  },
1061
1167
  { message: "Invalid cron expression" }
1062
1168
  ).superRefine((value, ctx) => {
@@ -1065,12 +1171,12 @@ var CronExpressionSchema = z22.custom(
1065
1171
  } catch (error) {
1066
1172
  if (error instanceof Error) {
1067
1173
  ctx.addIssue({
1068
- code: z22.ZodIssueCode.custom,
1174
+ code: z24.ZodIssueCode.custom,
1069
1175
  message: `Invalid cron expression: ${error.message}`
1070
1176
  });
1071
1177
  } else {
1072
1178
  ctx.addIssue({
1073
- code: z22.ZodIssueCode.custom,
1179
+ code: z24.ZodIssueCode.custom,
1074
1180
  message: "Invalid cron expression"
1075
1181
  });
1076
1182
  }
@@ -1081,15 +1187,15 @@ var CronExpressionSchema = z22.custom(
1081
1187
  var ScheduleExpressionSchema = RateExpressionSchema.or(CronExpressionSchema);
1082
1188
 
1083
1189
  // src/feature/cron/schema/index.ts
1084
- var CronsSchema = z23.record(
1190
+ var CronsSchema = z25.record(
1085
1191
  ResourceIdSchema,
1086
- z23.object({
1087
- enabled: z23.boolean().default(true).describe("If the cron is enabled."),
1192
+ z25.object({
1193
+ enabled: z25.boolean().default(true).describe("If the cron is enabled."),
1088
1194
  consumer: FunctionSchema.describe("The consuming lambda function properties."),
1089
1195
  schedule: ScheduleExpressionSchema.describe(
1090
1196
  'The scheduling expression.\n\nexample: "0 20 * * ? *"\nexample: "5 minutes"'
1091
1197
  ),
1092
- payload: z23.unknown().optional().describe("The JSON payload that will be passed to the consumer.")
1198
+ payload: z25.unknown().optional().describe("The JSON payload that will be passed to the consumer.")
1093
1199
  })
1094
1200
  ).optional().describe(`Define the cron jobs in your stack.`);
1095
1201
 
@@ -1100,9 +1206,9 @@ var OnFailureSchema = FunctionSchema.optional().describe(
1100
1206
 
1101
1207
  // src/feature/search/schema.ts
1102
1208
  import { gibibytes as gibibytes2 } from "@awsless/size";
1103
- import { z as z24 } from "zod";
1104
- var VersionSchema = z24.enum(["2.13", "2.11", "2.9", "2.7", "2.5", "2.3", "1.3"]);
1105
- var TypeSchema3 = z24.enum([
1209
+ import { z as z26 } from "zod";
1210
+ var VersionSchema = z26.enum(["2.13", "2.11", "2.9", "2.7", "2.5", "2.3", "1.3"]);
1211
+ var TypeSchema3 = z26.enum([
1106
1212
  "t3.small",
1107
1213
  "t3.medium",
1108
1214
  "m3.medium",
@@ -1177,41 +1283,41 @@ var TypeSchema3 = z24.enum([
1177
1283
  "r6gd.16xlarge"
1178
1284
  ]);
1179
1285
  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.");
1180
- var SearchsSchema = z24.record(
1286
+ var SearchsSchema = z26.record(
1181
1287
  ResourceIdSchema,
1182
- z24.object({
1288
+ z26.object({
1183
1289
  type: TypeSchema3.default("t3.small"),
1184
- count: z24.number().int().min(1).default(1),
1290
+ count: z26.number().int().min(1).default(1),
1185
1291
  version: VersionSchema.default("2.13"),
1186
1292
  storage: StorageSizeSchema.default("10 GB"),
1187
- vpc: z24.boolean().default(false)
1293
+ vpc: z26.boolean().default(false)
1188
1294
  })
1189
1295
  ).optional().describe("Define the search instances in your stack. Backed by OpenSearch.");
1190
1296
 
1191
1297
  // src/feature/site/schema.ts
1192
- import { z as z25 } from "zod";
1193
- var ErrorResponsePathSchema = z25.string().describe(
1298
+ import { z as z27 } from "zod";
1299
+ var ErrorResponsePathSchema = z27.string().describe(
1194
1300
  "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."
1195
1301
  );
1196
- var StatusCodeSchema = z25.number().int().positive().optional().describe(
1302
+ var StatusCodeSchema = z27.number().int().positive().optional().describe(
1197
1303
  "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."
1198
1304
  );
1199
1305
  var MinTTLSchema = DurationSchema.describe(
1200
1306
  "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."
1201
1307
  );
1202
- var ErrorResponseSchema = z25.union([
1308
+ var ErrorResponseSchema = z27.union([
1203
1309
  ErrorResponsePathSchema,
1204
- z25.object({
1310
+ z27.object({
1205
1311
  path: ErrorResponsePathSchema,
1206
1312
  statusCode: StatusCodeSchema.optional(),
1207
1313
  minTTL: MinTTLSchema.optional()
1208
1314
  })
1209
1315
  ]).optional();
1210
- var SitesSchema = z25.record(
1316
+ var SitesSchema = z27.record(
1211
1317
  ResourceIdSchema,
1212
- z25.object({
1318
+ z27.object({
1213
1319
  domain: ResourceIdSchema.describe("The domain id to link your site with.").optional(),
1214
- subDomain: z25.string().optional(),
1320
+ subDomain: z27.string().optional(),
1215
1321
  // bind: z
1216
1322
  // .object({
1217
1323
  // auth: z.array(ResourceIdSchema),
@@ -1234,7 +1340,7 @@ var SitesSchema = z25.record(
1234
1340
  // build: z.string().optional(),
1235
1341
  // }),
1236
1342
  // ]),
1237
- errors: z25.object({
1343
+ errors: z27.object({
1238
1344
  400: ErrorResponseSchema.describe("Customize a `400 Bad Request` response."),
1239
1345
  403: ErrorResponseSchema.describe("Customize a `403 Forbidden` response."),
1240
1346
  404: ErrorResponseSchema.describe("Customize a `404 Not Found` response."),
@@ -1247,16 +1353,16 @@ var SitesSchema = z25.record(
1247
1353
  503: ErrorResponseSchema.describe("Customize a `503 Service Unavailable` response."),
1248
1354
  504: ErrorResponseSchema.describe("Customize a `504 Gateway Timeout` response.")
1249
1355
  }).optional().describe("Customize the error responses for specific HTTP status codes."),
1250
- cors: z25.object({
1251
- override: z25.boolean().default(false),
1356
+ cors: z27.object({
1357
+ override: z27.boolean().default(false),
1252
1358
  maxAge: DurationSchema.default("365 days"),
1253
- exposeHeaders: z25.string().array().optional(),
1254
- credentials: z25.boolean().default(false),
1255
- headers: z25.string().array().default(["*"]),
1256
- origins: z25.string().array().default(["*"]),
1257
- methods: z25.enum(["GET", "DELETE", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "ALL"]).array().default(["ALL"])
1359
+ exposeHeaders: z27.string().array().optional(),
1360
+ credentials: z27.boolean().default(false),
1361
+ headers: z27.string().array().default(["*"]),
1362
+ origins: z27.string().array().default(["*"]),
1363
+ methods: z27.enum(["GET", "DELETE", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "ALL"]).array().default(["ALL"])
1258
1364
  }).optional().describe("Define the cors headers."),
1259
- security: z25.object({
1365
+ security: z27.object({
1260
1366
  // contentSecurityPolicy: z.object({
1261
1367
  // override: z.boolean().default(false),
1262
1368
  // policy: z.string(),
@@ -1298,132 +1404,39 @@ var SitesSchema = z25.record(
1298
1404
  // reportUri?: string
1299
1405
  // }
1300
1406
  }).optional().describe("Define the security policy."),
1301
- cache: z25.object({
1302
- cookies: z25.string().array().optional().describe("Specifies the cookies that CloudFront includes in the cache key."),
1303
- headers: z25.string().array().optional().describe("Specifies the headers that CloudFront includes in the cache key."),
1304
- queries: z25.string().array().optional().describe("Specifies the query values that CloudFront includes in the cache key.")
1407
+ cache: z27.object({
1408
+ cookies: z27.string().array().optional().describe("Specifies the cookies that CloudFront includes in the cache key."),
1409
+ headers: z27.string().array().optional().describe("Specifies the headers that CloudFront includes in the cache key."),
1410
+ queries: z27.string().array().optional().describe("Specifies the query values that CloudFront includes in the cache key.")
1305
1411
  }).optional().describe(
1306
1412
  "Specifies the cookies, headers, and query values that CloudFront includes in the cache key."
1307
1413
  )
1308
1414
  })
1309
1415
  ).optional().describe("Define the sites in your stack.");
1310
1416
 
1311
- // src/feature/store/schema.ts
1312
- import { z as z26 } from "zod";
1313
- var StoresSchema = z26.union([
1314
- z26.array(ResourceIdSchema).transform((list4) => {
1315
- const stores = {};
1316
- for (const key of list4) {
1317
- stores[key] = {};
1318
- }
1319
- return stores;
1320
- }),
1321
- z26.record(
1322
- ResourceIdSchema,
1323
- z26.object({
1324
- // cors: CorsSchema,
1325
- versioning: z26.boolean().default(false).describe("Enable versioning of your store."),
1326
- events: z26.object({
1327
- // create
1328
- "created:*": FunctionSchema.optional().describe(
1329
- "Subscribe to notifications regardless of the API that was used to create an object."
1330
- ),
1331
- "created:put": FunctionSchema.optional().describe(
1332
- "Subscribe to notifications when an object is created using the PUT API operation."
1333
- ),
1334
- "created:post": FunctionSchema.optional().describe(
1335
- "Subscribe to notifications when an object is created using the POST API operation."
1336
- ),
1337
- "created:copy": FunctionSchema.optional().describe(
1338
- "Subscribe to notifications when an object is created using the COPY API operation."
1339
- ),
1340
- "created:upload": FunctionSchema.optional().describe(
1341
- "Subscribe to notifications when an object multipart upload has been completed."
1342
- ),
1343
- // remove
1344
- "removed:*": FunctionSchema.optional().describe(
1345
- "Subscribe to notifications when an object is deleted or a delete marker for a versioned object is created."
1346
- ),
1347
- "removed:delete": FunctionSchema.optional().describe(
1348
- "Subscribe to notifications when an object is deleted"
1349
- ),
1350
- "removed:marker": FunctionSchema.optional().describe(
1351
- "Subscribe to notifications when a delete marker for a versioned object is created."
1352
- )
1353
- }).optional().describe("Describes the store events you want to subscribe too.")
1354
- })
1355
- )
1356
- ]).optional().describe("Define the stores in your stack.");
1357
-
1358
1417
  // src/feature/stream/schema.ts
1359
- import { z as z27 } from "zod";
1360
- var LatencyModeSchema = z27.enum(["low", "normal"]).describe(
1418
+ import { z as z28 } from "zod";
1419
+ var LatencyModeSchema = z28.enum(["low", "normal"]).describe(
1361
1420
  `Channel latency mode. Valid values:
1362
1421
  - normal: Use "normal" to broadcast and deliver live video up to Full HD.
1363
1422
  - low: Use "low" for near real-time interactions with viewers.`
1364
1423
  );
1365
- var TypeSchema4 = z27.enum(["standard", "basic", "advanced-sd", "advanced-hd"]).describe(`The channel type, which determines the allowable resolution and bitrate.
1424
+ var TypeSchema4 = z28.enum(["standard", "basic", "advanced-sd", "advanced-hd"]).describe(`The channel type, which determines the allowable resolution and bitrate.
1366
1425
  If you exceed the allowable resolution or bitrate, the stream probably will disconnect immediately. Valid values:
1367
1426
  - 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.
1368
1427
  - 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.
1369
1428
  - 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.
1370
1429
  - 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.
1371
1430
  `);
1372
- var StreamsSchema = z27.record(
1431
+ var StreamsSchema = z28.record(
1373
1432
  ResourceIdSchema,
1374
- z27.object({
1433
+ z28.object({
1375
1434
  type: TypeSchema4.default("standard"),
1376
1435
  // preset: PresetSchema.optional(),
1377
1436
  latencyMode: LatencyModeSchema.default("low")
1378
1437
  })
1379
1438
  ).optional().describe("Define the streams in your stack.");
1380
1439
 
1381
- // src/feature/table/schema.ts
1382
- import { z as z28 } from "zod";
1383
- var KeySchema = z28.string().min(1).max(255);
1384
- var TablesSchema = z28.record(
1385
- ResourceIdSchema,
1386
- z28.object({
1387
- hash: KeySchema.describe(
1388
- "Specifies the name of the partition / hash key that makes up the primary key for the table."
1389
- ),
1390
- sort: KeySchema.optional().describe(
1391
- "Specifies the name of the range / sort key that makes up the primary key for the table."
1392
- ),
1393
- fields: z28.record(z28.string(), z28.enum(["string", "number", "binary"])).optional().describe(
1394
- 'A list of attributes that describe the key schema for the table and indexes. If no attribute field is defined we default to "string".'
1395
- ),
1396
- class: z28.enum(["standard", "standard-infrequent-access"]).default("standard").describe("The table class of the table."),
1397
- pointInTimeRecovery: z28.boolean().default(false).describe("Indicates whether point in time recovery is enabled on the table."),
1398
- timeToLiveAttribute: KeySchema.optional().describe(
1399
- "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."
1400
- ),
1401
- stream: z28.object({
1402
- type: z28.enum(["keys-only", "new-image", "old-image", "new-and-old-images"]).describe(
1403
- "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."
1404
- ),
1405
- consumer: FunctionSchema.describe("The consuming lambda function for the stream")
1406
- }).optional().describe(
1407
- "The settings for the DynamoDB table stream, which capture changes to items stored in the table."
1408
- ),
1409
- indexes: z28.record(
1410
- z28.string(),
1411
- z28.object({
1412
- /** Specifies the name of the partition / hash key that makes up the primary key for the global secondary index. */
1413
- hash: KeySchema,
1414
- /** Specifies the name of the range / sort key that makes up the primary key for the global secondary index. */
1415
- sort: KeySchema.optional(),
1416
- /** The set of attributes that are projected into the index:
1417
- * - all - All of the table attributes are projected into the index.
1418
- * - keys-only - Only the index and primary keys are projected into the index.
1419
- * @default 'all'
1420
- */
1421
- projection: z28.enum(["all", "keys-only"]).default("all")
1422
- })
1423
- ).optional().describe("Specifies the global secondary indexes to be created on the table.")
1424
- })
1425
- ).optional().describe("Define the tables in your stack.");
1426
-
1427
1440
  // src/feature/task/schema.ts
1428
1441
  import { z as z29 } from "zod";
1429
1442
  var RetryAttemptsSchema2 = z29.number().int().min(0).max(2).describe(
@@ -1958,22 +1971,30 @@ var TypeObject = class {
1958
1971
 
1959
1972
  // src/util/name.ts
1960
1973
  import { paramCase as paramCase3 } from "change-case";
1961
- var formatGlobalResourceName = (appName, ns, id, seperator = "--") => {
1974
+ import { createHmac } from "crypto";
1975
+ var formatGlobalResourceName = (opt) => {
1962
1976
  return [
1963
1977
  //
1964
- appName,
1965
- ns,
1966
- id
1967
- ].map((v) => paramCase3(v)).join(seperator);
1978
+ opt.prefix,
1979
+ opt.appName,
1980
+ opt.resourceType,
1981
+ opt.resourceName,
1982
+ opt.postfix
1983
+ ].filter((v) => typeof v === "string").map((v) => paramCase3(v)).join(opt.seperator ?? "--");
1968
1984
  };
1969
- var formatLocalResourceName = (appName, stackName, ns, id, seperator = "--") => {
1985
+ var formatLocalResourceName = (opt) => {
1970
1986
  return [
1971
1987
  //
1972
- appName,
1973
- stackName,
1974
- ns,
1975
- id
1976
- ].map((v) => paramCase3(v)).join(seperator);
1988
+ opt.prefix,
1989
+ opt.appName,
1990
+ opt.stackName,
1991
+ opt.resourceType,
1992
+ opt.resourceName,
1993
+ opt.postfix
1994
+ ].filter((v) => typeof v === "string").map((v) => paramCase3(v)).join(opt.seperator ?? "--");
1995
+ };
1996
+ var generateGlobalAppId = (opt) => {
1997
+ return createHmac("sha1", "awsless").update(opt.accountId).update(opt.region).update(opt.appName).digest("hex").substring(0, 8);
1977
1998
  };
1978
1999
 
1979
2000
  // src/feature/function/util.ts
@@ -2173,10 +2194,19 @@ var zipFiles = (files) => {
2173
2194
  import { hashElement } from "folder-hash";
2174
2195
  var createLambdaFunction = (group, ctx, ns, id, local2) => {
2175
2196
  let name;
2176
- if ("stackConfig" in ctx) {
2177
- name = formatLocalResourceName(ctx.appConfig.name, ctx.stackConfig.name, ns, id);
2197
+ if ("stack" in ctx) {
2198
+ name = formatLocalResourceName({
2199
+ appName: ctx.app.name,
2200
+ stackName: ctx.stack.name,
2201
+ resourceType: ns,
2202
+ resourceName: id
2203
+ });
2178
2204
  } else {
2179
- name = formatGlobalResourceName(ctx.appConfig.name, ns, id);
2205
+ name = formatGlobalResourceName({
2206
+ appName: ctx.appConfig.name,
2207
+ resourceType: ns,
2208
+ resourceName: id
2209
+ });
2180
2210
  }
2181
2211
  const props = deepmerge(ctx.appConfig.defaults.function, local2);
2182
2212
  let code;
@@ -2190,7 +2220,12 @@ var createLambdaFunction = (group, ctx, ns, id, local2) => {
2190
2220
  }
2191
2221
  });
2192
2222
  return build3(version.hash + props.architecture, async (write) => {
2193
- const repoName = formatGlobalResourceName(ctx.appConfig.name, "function", "repository", "-");
2223
+ const repoName = formatGlobalResourceName({
2224
+ appName: ctx.app.name,
2225
+ resourceType: "function",
2226
+ resourceName: "repository",
2227
+ seperator: "-"
2228
+ });
2194
2229
  const platform = props.architecture === "arm64" ? "linux/arm64" : "linux/amd64";
2195
2230
  await exec(`docker buildx build --platform ${platform} -t ${name} .`, {
2196
2231
  cwd: basePath2
@@ -2277,6 +2312,7 @@ var createLambdaFunction = (group, ctx, ns, id, local2) => {
2277
2312
  });
2278
2313
  ctx.registerPolicy(policy);
2279
2314
  lambda.addEnvironment("APP", ctx.appConfig.name);
2315
+ lambda.addEnvironment("APP_ID", ctx.appId);
2280
2316
  if ("stackConfig" in ctx) {
2281
2317
  lambda.addEnvironment("STACK", ctx.stackConfig.name);
2282
2318
  }
@@ -2457,7 +2493,11 @@ var authFeature = defineFeature({
2457
2493
  from: props.messaging.fromName ? `${props.messaging.fromName} <${props.messaging.fromEmail}>` : props.messaging.fromEmail
2458
2494
  };
2459
2495
  }
2460
- const name = formatGlobalResourceName(ctx.appConfig.name, "auth", id);
2496
+ const name = formatGlobalResourceName({
2497
+ appName: ctx.app.name,
2498
+ resourceType: "auth",
2499
+ resourceName: id
2500
+ });
2461
2501
  const userPool = new aws3.cognito.UserPool(group, "user-pool", {
2462
2502
  name,
2463
2503
  // deletionProtection: true,
@@ -2517,7 +2557,13 @@ var cacheFeature = defineFeature({
2517
2557
  onStack(ctx) {
2518
2558
  for (const [id, props] of Object.entries(ctx.stackConfig.caches ?? {})) {
2519
2559
  const group = new Node3(ctx.stack, this.name, id);
2520
- const name = formatLocalResourceName(ctx.appConfig.name, ctx.stack.name, this.name, id, "-");
2560
+ const name = formatLocalResourceName({
2561
+ appName: ctx.app.name,
2562
+ stackName: ctx.stack.name,
2563
+ resourceType: "cache",
2564
+ resourceName: id,
2565
+ seperator: "-"
2566
+ });
2521
2567
  const subnetGroup = new aws4.memorydb.SubnetGroup(group, "subnets", {
2522
2568
  name,
2523
2569
  subnetIds: [
@@ -2715,7 +2761,12 @@ var cronFeature = defineFeature({
2715
2761
  const group = new Node4(ctx.stack, "cron", id);
2716
2762
  const { lambda } = createAsyncLambdaFunction(group, ctx, "cron", id, props.consumer);
2717
2763
  const rule = new aws5.events.Rule(group, "rule", {
2718
- name: formatLocalResourceName(ctx.app.name, ctx.stack.name, this.name, id),
2764
+ name: formatLocalResourceName({
2765
+ appName: ctx.app.name,
2766
+ stackName: ctx.stack.name,
2767
+ resourceType: "cron",
2768
+ resourceName: id
2769
+ }),
2719
2770
  schedule: props.schedule,
2720
2771
  enabled: props.enabled,
2721
2772
  targets: [
@@ -2889,7 +2940,12 @@ var functionFeature = defineFeature({
2889
2940
  for (const [name, local2] of Object.entries(stack.functions || {})) {
2890
2941
  const props = deepmerge2(ctx.appConfig.defaults.function, local2);
2891
2942
  const varName = camelCase3(`${stack.name}-${name}`);
2892
- const funcName = formatLocalResourceName(ctx.appConfig.name, stack.name, "function", name);
2943
+ const funcName = formatLocalResourceName({
2944
+ appName: ctx.appConfig.name,
2945
+ stackName: stack.name,
2946
+ resourceType: "function",
2947
+ resourceName: name
2948
+ });
2893
2949
  const relFile = relative(directories.types, props.file);
2894
2950
  if (props.runtime === "container") {
2895
2951
  resource2.addType(name, `Invoke<'${funcName}', Func>`);
@@ -2915,13 +2971,23 @@ var functionFeature = defineFeature({
2915
2971
  onApp(ctx) {
2916
2972
  const group = new Node6(ctx.base, "function", "asset");
2917
2973
  const bucket = new aws7.s3.Bucket(group, "bucket", {
2918
- name: formatGlobalResourceName(ctx.appConfig.name, "function", "assets"),
2974
+ name: formatGlobalResourceName({
2975
+ appName: ctx.app.name,
2976
+ resourceType: "function",
2977
+ resourceName: "assets",
2978
+ postfix: ctx.appId
2979
+ }),
2919
2980
  versioning: true,
2920
2981
  forceDelete: true
2921
2982
  });
2922
2983
  ctx.shared.set("function-bucket-name", bucket.name);
2923
2984
  const repository = new aws7.ecr.Repository(group, "repository", {
2924
- name: formatGlobalResourceName(ctx.appConfig.name, "function", "repository", "-"),
2985
+ name: formatGlobalResourceName({
2986
+ appName: ctx.app.name,
2987
+ resourceType: "function",
2988
+ resourceName: "repository",
2989
+ seperator: "-"
2990
+ }),
2925
2991
  imageTagMutability: true
2926
2992
  });
2927
2993
  ctx.shared.set("function-repository-name", repository.name);
@@ -3125,7 +3191,11 @@ var graphqlFeature = defineFeature({
3125
3191
  const { lambda } = createLambdaFunction(group, ctx, "graphql-auth", id, props.auth.authorizer);
3126
3192
  authorizer = lambda;
3127
3193
  }
3128
- const name = formatGlobalResourceName(ctx.app.name, "graphql", id);
3194
+ const name = formatGlobalResourceName({
3195
+ appName: ctx.app.name,
3196
+ resourceType: "graphql",
3197
+ resourceName: id
3198
+ });
3129
3199
  const api = new aws8.appsync.GraphQLApi(group, "api", {
3130
3200
  name,
3131
3201
  type: "graphql",
@@ -3379,7 +3449,11 @@ var httpFeature = defineFeature({
3379
3449
  const group = new Node8(ctx.base, "http", "main");
3380
3450
  const securityGroup = new aws9.ec2.SecurityGroup(group, "http", {
3381
3451
  vpcId: ctx.shared.get(`vpc-id`),
3382
- name: formatGlobalResourceName(ctx.app.name, "http", "http"),
3452
+ name: formatGlobalResourceName({
3453
+ appName: ctx.app.name,
3454
+ resourceType: "http",
3455
+ resourceName: "http"
3456
+ }),
3383
3457
  description: `Global security group for HTTP api.`
3384
3458
  });
3385
3459
  const port = aws9.ec2.Port.tcp(443);
@@ -3388,7 +3462,11 @@ var httpFeature = defineFeature({
3388
3462
  for (const [id, props] of Object.entries(ctx.appConfig.defaults?.http ?? {})) {
3389
3463
  const group2 = new Node8(ctx.base, "http", id);
3390
3464
  const loadBalancer = new aws9.elb.LoadBalancer(group2, "balancer", {
3391
- name: formatGlobalResourceName(ctx.app.name, "http", id),
3465
+ name: formatGlobalResourceName({
3466
+ appName: ctx.app.name,
3467
+ resourceType: "http",
3468
+ resourceName: id
3469
+ }),
3392
3470
  type: "application",
3393
3471
  securityGroups: [securityGroup.id],
3394
3472
  subnets: [
@@ -3442,7 +3520,12 @@ var httpFeature = defineFeature({
3442
3520
  ...routeProps,
3443
3521
  description: routeKey
3444
3522
  });
3445
- const name = formatLocalResourceName(ctx.app.name, ctx.stack.name, "http", routeId);
3523
+ const name = formatLocalResourceName({
3524
+ appName: ctx.app.name,
3525
+ stackName: ctx.stack.name,
3526
+ resourceType: "http",
3527
+ resourceName: routeId
3528
+ });
3446
3529
  const permission = new aws9.lambda.Permission(routeGroup, id, {
3447
3530
  action: "lambda:InvokeFunction",
3448
3531
  principal: "elasticloadbalancing.amazonaws.com",
@@ -3480,13 +3563,18 @@ var instanceFeature = defineFeature({
3480
3563
  onApp(ctx) {
3481
3564
  const group = new Node9(ctx.base, "instance", "asset");
3482
3565
  const bucket = new aws10.s3.Bucket(group, "bucket", {
3483
- name: formatGlobalResourceName(ctx.appConfig.name, "instance", "assets"),
3566
+ name: formatGlobalResourceName({
3567
+ appName: ctx.app.name,
3568
+ resourceType: "instance",
3569
+ resourceName: "assets",
3570
+ postfix: ctx.appId
3571
+ }),
3484
3572
  forceDelete: true
3485
3573
  });
3486
3574
  ctx.shared.set("instance-bucket-name", bucket.name);
3487
3575
  if (ctx.appConfig.defaults.instance.connect) {
3488
3576
  new aws10.ec2.InstanceConnectEndpoint(group, "connect", {
3489
- name: ctx.appConfig.name,
3577
+ name: ctx.app.name,
3490
3578
  subnetId: ctx.shared.get(`vpc-public-subnet-id-1`),
3491
3579
  securityGroupIds: [ctx.shared.get("vpc-security-group-id")]
3492
3580
  });
@@ -3495,10 +3583,16 @@ var instanceFeature = defineFeature({
3495
3583
  onStack(ctx) {
3496
3584
  for (const [id, props] of Object.entries(ctx.stackConfig.instances ?? {})) {
3497
3585
  const group = new Node9(ctx.stack, "instance", id);
3498
- const name = formatLocalResourceName(ctx.appConfig.name, ctx.stack.name, "instance", id);
3586
+ const name = formatLocalResourceName({
3587
+ appName: ctx.app.name,
3588
+ stackName: ctx.stack.name,
3589
+ resourceType: "instance",
3590
+ resourceName: id
3591
+ });
3499
3592
  const env = {
3500
- APP: ctx.appConfig.name,
3501
- STACK: ctx.stackConfig.name
3593
+ APP: ctx.app.name,
3594
+ APP_ID: ctx.appId,
3595
+ STACK: ctx.stack.name
3502
3596
  };
3503
3597
  ctx.onEnv((name2, value) => {
3504
3598
  env[name2] = value;
@@ -3621,7 +3715,11 @@ var onFailureFeature = defineFeature({
3621
3715
  throw new TypeError("Only 1 onFailure configuration is allowed in your app.");
3622
3716
  }
3623
3717
  const queue2 = new aws11.sqs.Queue(ctx.base, "on-failure", {
3624
- name: formatGlobalResourceName(ctx.appConfig.name, "on-failure", "failure")
3718
+ name: formatGlobalResourceName({
3719
+ appName: ctx.app.name,
3720
+ resourceType: "on-failure",
3721
+ resourceName: "failure"
3722
+ })
3625
3723
  });
3626
3724
  ctx.shared.set("on-failure-queue-arn", queue2.arn);
3627
3725
  },
@@ -3664,7 +3762,11 @@ var pubsubFeature = defineFeature({
3664
3762
  const { lambda } = createLambdaFunction(group, ctx, "pubsub-authorizer", id, functionProps);
3665
3763
  lambda.addEnvironment("PUBSUB_POLICY", JSON.stringify(props.policy));
3666
3764
  lambda.addEnvironment("AWS_ACCOUNT_ID", ctx.accountId);
3667
- const name = formatGlobalResourceName(ctx.app.name, "pubsub", id);
3765
+ const name = formatGlobalResourceName({
3766
+ appName: ctx.app.name,
3767
+ resourceType: "pubsub",
3768
+ resourceName: id
3769
+ });
3668
3770
  const authorizer = new aws12.iot.Authorizer(group, "authorizer", {
3669
3771
  name,
3670
3772
  functionArn: lambda.arn
@@ -3713,7 +3815,12 @@ var pubsubFeature = defineFeature({
3713
3815
  for (const [id, props] of Object.entries(ctx.stackConfig.pubsub ?? {})) {
3714
3816
  const group = new Node11(ctx.stack, "pubsub", id);
3715
3817
  const { lambda } = createAsyncLambdaFunction(group, ctx, `pubsub`, id, props.consumer);
3716
- const name = formatLocalResourceName(ctx.app.name, ctx.stack.name, "pubsub", id);
3818
+ const name = formatLocalResourceName({
3819
+ appName: ctx.app.name,
3820
+ stackName: ctx.stack.name,
3821
+ resourceType: "pubsub",
3822
+ resourceName: id
3823
+ });
3717
3824
  const topic = new aws12.iot.TopicRule(group, "rule", {
3718
3825
  name: name.replaceAll("-", "_"),
3719
3826
  sql: props.sql,
@@ -3765,7 +3872,12 @@ var queueFeature = defineFeature({
3765
3872
  const mockResponse = new TypeObject(2);
3766
3873
  for (const [name, fileOrProps] of Object.entries(stack.queues || {})) {
3767
3874
  const varName = camelCase5(`${stack.name}-${name}`);
3768
- const queueName = formatLocalResourceName(ctx.appConfig.name, stack.name, "queue", name);
3875
+ const queueName = formatLocalResourceName({
3876
+ appName: ctx.appConfig.name,
3877
+ stackName: stack.name,
3878
+ resourceType: "queue",
3879
+ resourceName: name
3880
+ });
3769
3881
  const file = typeof fileOrProps === "string" ? fileOrProps : typeof fileOrProps.consumer === "string" ? fileOrProps.consumer : fileOrProps.consumer.file;
3770
3882
  const relFile = relative3(directories.types, file);
3771
3883
  gen.addImport(varName, relFile);
@@ -3787,8 +3899,14 @@ var queueFeature = defineFeature({
3787
3899
  for (const [id, local2] of Object.entries(ctx.stackConfig.queues || {})) {
3788
3900
  const props = deepmerge3(ctx.appConfig.defaults.queue, local2);
3789
3901
  const group = new Node12(ctx.stack, "queue", id);
3902
+ const name = formatLocalResourceName({
3903
+ appName: ctx.app.name,
3904
+ stackName: ctx.stack.name,
3905
+ resourceType: "queue",
3906
+ resourceName: id
3907
+ });
3790
3908
  const queue2 = new aws13.sqs.Queue(group, "queue", {
3791
- name: formatLocalResourceName(ctx.appConfig.name, ctx.stack.name, "queue", id),
3909
+ name,
3792
3910
  deadLetterArn: getGlobalOnFailure(ctx),
3793
3911
  ...props
3794
3912
  });
@@ -3821,8 +3939,13 @@ var restFeature = defineFeature({
3821
3939
  onApp(ctx) {
3822
3940
  for (const [id, props] of Object.entries(ctx.appConfig.defaults?.rest ?? {})) {
3823
3941
  const group = new Node13(ctx.base, "rest", id);
3942
+ const name = formatGlobalResourceName({
3943
+ appName: ctx.app.name,
3944
+ resourceType: "rest",
3945
+ resourceName: id
3946
+ });
3824
3947
  const api = new aws14.apiGatewayV2.Api(group, "api", {
3825
- name: formatGlobalResourceName(ctx.app.name, "rest", id),
3948
+ name,
3826
3949
  protocolType: "HTTP"
3827
3950
  });
3828
3951
  const stage = new aws14.apiGatewayV2.Stage(group, "stage", {
@@ -4002,7 +4125,12 @@ var siteFeature = defineFeature({
4002
4125
  onStack(ctx) {
4003
4126
  for (const [id, props] of Object.entries(ctx.stackConfig.sites ?? {})) {
4004
4127
  const group = new Node15(ctx.stack, "site", id);
4005
- const name = formatLocalResourceName(ctx.app.name, ctx.stack.name, "site", id);
4128
+ const name = formatLocalResourceName({
4129
+ appName: ctx.app.name,
4130
+ stackName: ctx.stack.name,
4131
+ resourceType: "site",
4132
+ resourceName: id
4133
+ });
4006
4134
  const origins = [];
4007
4135
  const originGroups = [];
4008
4136
  let bucket;
@@ -4037,7 +4165,13 @@ var siteFeature = defineFeature({
4037
4165
  }
4038
4166
  if (props.static) {
4039
4167
  bucket = new aws16.s3.Bucket(group, "bucket", {
4040
- name,
4168
+ name: formatLocalResourceName({
4169
+ appName: ctx.app.name,
4170
+ stackName: ctx.stack.name,
4171
+ resourceType: "site",
4172
+ resourceName: id,
4173
+ postfix: ctx.appId
4174
+ }),
4041
4175
  forceDelete: true,
4042
4176
  website: {
4043
4177
  indexDocument: "index.html",
@@ -4213,7 +4347,12 @@ var storeFeature = defineFeature({
4213
4347
  for (const stack of ctx.stackConfigs) {
4214
4348
  const list4 = new TypeObject(2);
4215
4349
  for (const id of Object.keys(stack.stores ?? {})) {
4216
- const storeName = formatLocalResourceName(ctx.appConfig.name, stack.name, "store", id);
4350
+ const storeName = formatLocalResourceName({
4351
+ appName: ctx.appConfig.name,
4352
+ stackName: stack.name,
4353
+ resourceType: "store",
4354
+ resourceName: id
4355
+ });
4217
4356
  list4.addType(id, `Store<'${storeName}'>`);
4218
4357
  }
4219
4358
  resources.addType(stack.name, list4);
@@ -4222,10 +4361,19 @@ var storeFeature = defineFeature({
4222
4361
  gen.addInterface("StoreResources", resources);
4223
4362
  await ctx.write("store.d.ts", gen, true);
4224
4363
  },
4364
+ onApp(ctx) {
4365
+ ctx.addEnv("STORE_POSTFIX", ctx.appId);
4366
+ },
4225
4367
  onStack(ctx) {
4226
4368
  for (const [id, props] of Object.entries(ctx.stackConfig.stores ?? {})) {
4227
4369
  const group = new Node16(ctx.stack, "store", id);
4228
- const bucketName = formatLocalResourceName(ctx.appConfig.name, ctx.stack.name, "store", id);
4370
+ const name = formatLocalResourceName({
4371
+ appName: ctx.app.name,
4372
+ stackName: ctx.stack.name,
4373
+ resourceType: "store",
4374
+ resourceName: id,
4375
+ postfix: ctx.appId
4376
+ });
4229
4377
  const lambdaConfigs = [];
4230
4378
  const eventMap = {
4231
4379
  "created:*": "s3:ObjectCreated:*",
@@ -4248,7 +4396,7 @@ var storeFeature = defineFeature({
4248
4396
  action: "lambda:InvokeFunction",
4249
4397
  principal: "s3.amazonaws.com",
4250
4398
  functionArn: lambda.arn,
4251
- sourceArn: `arn:aws:s3:::${bucketName}`
4399
+ sourceArn: `arn:aws:s3:::${name}`
4252
4400
  });
4253
4401
  lambdaConfigs.push({
4254
4402
  event: eventMap[event],
@@ -4256,7 +4404,7 @@ var storeFeature = defineFeature({
4256
4404
  });
4257
4405
  }
4258
4406
  const bucket = new aws17.s3.Bucket(group, "store", {
4259
- name: bucketName,
4407
+ name,
4260
4408
  versioning: props.versioning,
4261
4409
  forceDelete: true,
4262
4410
  lambdaConfigs,
@@ -4271,6 +4419,10 @@ var storeFeature = defineFeature({
4271
4419
  // ---------------------------------------------
4272
4420
  ]
4273
4421
  });
4422
+ const deletionProtection = props.deletionProtection ?? ctx.appConfig.defaults.store?.deletionProtection;
4423
+ if (deletionProtection) {
4424
+ bucket.deletionPolicy = "retain";
4425
+ }
4274
4426
  ctx.onPolicy((policy) => {
4275
4427
  policy.addStatement(bucket.permissions);
4276
4428
  });
@@ -4286,7 +4438,12 @@ var streamFeature = defineFeature({
4286
4438
  onStack(ctx) {
4287
4439
  for (const [id, props] of Object.entries(ctx.stackConfig.streams ?? {})) {
4288
4440
  const group = new Node17(ctx.stack, "stream", id);
4289
- const name = formatLocalResourceName(ctx.appConfig.name, ctx.stack.name, "stream", id);
4441
+ const name = formatLocalResourceName({
4442
+ appName: ctx.app.name,
4443
+ stackName: ctx.stack.name,
4444
+ resourceType: "stream",
4445
+ resourceName: id
4446
+ });
4290
4447
  const channel = new aws18.ivs.Channel(group, "channel", {
4291
4448
  name,
4292
4449
  ...props
@@ -4312,7 +4469,12 @@ var tableFeature = defineFeature({
4312
4469
  for (const stack of ctx.stackConfigs) {
4313
4470
  const list4 = new TypeObject(2);
4314
4471
  for (const name of Object.keys(stack.tables || {})) {
4315
- const tableName = formatLocalResourceName(ctx.appConfig.name, stack.name, "table", name);
4472
+ const tableName = formatLocalResourceName({
4473
+ appName: ctx.appConfig.name,
4474
+ stackName: stack.name,
4475
+ resourceType: "table",
4476
+ resourceName: name
4477
+ });
4316
4478
  list4.addType(name, `'${tableName}'`);
4317
4479
  }
4318
4480
  resources.addType(stack.name, list4);
@@ -4323,11 +4485,22 @@ var tableFeature = defineFeature({
4323
4485
  onStack(ctx) {
4324
4486
  for (const [id, props] of Object.entries(ctx.stackConfig.tables ?? {})) {
4325
4487
  const group = new Node18(ctx.stack, "table", id);
4488
+ const name = formatLocalResourceName({
4489
+ appName: ctx.app.name,
4490
+ stackName: ctx.stack.name,
4491
+ resourceType: "table",
4492
+ resourceName: id
4493
+ });
4494
+ const deletionProtection = props.deletionProtection ?? ctx.appConfig.defaults.table?.deletionProtection;
4326
4495
  const table2 = new aws19.dynamodb.Table(group, "table", {
4327
4496
  ...props,
4328
- name: formatLocalResourceName(ctx.appConfig.name, ctx.stackConfig.name, "table", id),
4329
- stream: props.stream?.type
4497
+ name,
4498
+ stream: props.stream?.type,
4499
+ deletionProtection
4330
4500
  });
4501
+ if (deletionProtection) {
4502
+ table2.deletionPolicy = "retain";
4503
+ }
4331
4504
  if (props.stream) {
4332
4505
  const { lambda, policy } = createLambdaFunction(group, ctx, "table", id, props.stream.consumer);
4333
4506
  lambda.addEnvironment("LOG_VIEWABLE_ERROR", "1");
@@ -4397,7 +4570,12 @@ var taskFeature = defineFeature({
4397
4570
  const mockResponse = new TypeObject(2);
4398
4571
  for (const [name, props] of Object.entries(stack.tasks || {})) {
4399
4572
  const varName = camelCase6(`${stack.name}-${name}`);
4400
- const funcName = formatLocalResourceName(ctx.appConfig.name, stack.name, "task", name);
4573
+ const funcName = formatLocalResourceName({
4574
+ appName: ctx.appConfig.name,
4575
+ stackName: stack.name,
4576
+ resourceType: "task",
4577
+ resourceName: name
4578
+ });
4401
4579
  const relFile = relative4(directories.types, props.consumer.file);
4402
4580
  types2.addImport(varName, relFile);
4403
4581
  resource2.addType(name, `Invoke<'${funcName}', typeof ${varName}>`);
@@ -4455,7 +4633,11 @@ var topicFeature = defineFeature({
4455
4633
  const mockResponses = new TypeObject(1);
4456
4634
  for (const stack of ctx.stackConfigs) {
4457
4635
  for (const topic of stack.topics || []) {
4458
- const name = formatGlobalResourceName(ctx.appConfig.name, "topic", topic);
4636
+ const name = formatGlobalResourceName({
4637
+ appName: ctx.appConfig.name,
4638
+ resourceType: "topic",
4639
+ resourceName: topic
4640
+ });
4459
4641
  mockResponses.addType(topic, "Mock");
4460
4642
  resources.addType(topic, `Publish<'${name}'>`);
4461
4643
  mocks.addType(topic, `MockBuilder`);
@@ -4471,8 +4653,13 @@ var topicFeature = defineFeature({
4471
4653
  for (const stack of ctx.stackConfigs) {
4472
4654
  for (const id of stack.topics ?? []) {
4473
4655
  const group = new Node20(ctx.base, "topic", id);
4656
+ const name = formatGlobalResourceName({
4657
+ appName: ctx.appConfig.name,
4658
+ resourceType: "topic",
4659
+ resourceName: id
4660
+ });
4474
4661
  const topic = new aws20.sns.Topic(group, "topic", {
4475
- name: formatGlobalResourceName(ctx.appConfig.name, "topic", id)
4662
+ name
4476
4663
  });
4477
4664
  ctx.shared.set(`topic-${id}-arn`, topic.arn);
4478
4665
  }
@@ -4656,6 +4843,11 @@ var createApp = (props, filters = []) => {
4656
4843
  const app = new App2(props.appConfig.name);
4657
4844
  const base = new Stack(app, "base");
4658
4845
  const shared = new SharedData();
4846
+ const appId = generateGlobalAppId({
4847
+ accountId: props.accountId,
4848
+ region: props.appConfig.region,
4849
+ appName: props.appConfig.name
4850
+ });
4659
4851
  const commands7 = [];
4660
4852
  const configs = /* @__PURE__ */ new Set();
4661
4853
  const tests = [];
@@ -4678,6 +4870,7 @@ var createApp = (props, filters = []) => {
4678
4870
  feature.onApp?.({
4679
4871
  ...props,
4680
4872
  app,
4873
+ appId,
4681
4874
  // env,
4682
4875
  base,
4683
4876
  shared,
@@ -4742,6 +4935,7 @@ var createApp = (props, filters = []) => {
4742
4935
  ...props,
4743
4936
  stackConfig,
4744
4937
  app,
4938
+ appId,
4745
4939
  // env,
4746
4940
  base,
4747
4941
  stack,