@awsless/cli 0.0.46-next.2 → 0.0.46-next.4

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.
Files changed (2) hide show
  1. package/dist/bin.js +145 -109
  2. package/package.json +9 -9
package/dist/bin.js CHANGED
@@ -173,7 +173,7 @@ import { DynamoDBClient as DynamoDBClient2, migrate } from "@awsless/dynamodb";
173
173
  // src/util/deployment.ts
174
174
  import { CloudFrontClient as CloudFrontClient2 } from "@aws-sdk/client-cloudfront";
175
175
  import { CloudFrontKeyValueStoreClient as CloudFrontKeyValueStoreClient2 } from "@aws-sdk/client-cloudfront-keyvaluestore";
176
- import { GetFunctionCommand, LambdaClient as LambdaClient3 } from "@aws-sdk/client-lambda";
176
+ import { DeleteFunctionCommand, GetFunctionCommand, LambdaClient as LambdaClient3 } from "@aws-sdk/client-lambda";
177
177
  import {
178
178
  define,
179
179
  deleteItem,
@@ -366,6 +366,7 @@ import {
366
366
  DeleteFunctionUrlConfigCommand,
367
367
  GetAliasCommand,
368
368
  LambdaClient,
369
+ ListAliasesCommand,
369
370
  UpdateAliasCommand,
370
371
  UpdateFunctionCodeCommand
371
372
  } from "@aws-sdk/client-lambda";
@@ -386,6 +387,22 @@ var getLambdaAlias = async (lambda, functionName, name) => {
386
387
  return;
387
388
  }
388
389
  };
390
+ var listLambdaAliases = async (lambda, functionName, functionVersion) => {
391
+ const aliases = [];
392
+ let marker;
393
+ do {
394
+ const result = await lambda.send(
395
+ new ListAliasesCommand({
396
+ FunctionName: functionName,
397
+ FunctionVersion: functionVersion,
398
+ Marker: marker
399
+ })
400
+ );
401
+ aliases.push(...result.Aliases ?? []);
402
+ marker = result.NextMarker;
403
+ } while (marker);
404
+ return aliases;
405
+ };
389
406
  var upsertLambdaAlias = async (lambda, props) => {
390
407
  const input = {
391
408
  FunctionName: props.functionName,
@@ -809,17 +826,18 @@ var createLambdaProvider = ({ credentials, region }) => {
809
826
  await configureVersion(proposed);
810
827
  const url = await createDeploymentUrl(proposed.functionName, deploymentAlias, proposed.sourceAccount);
811
828
  if (proposed.sourceAccount && prior.sourceAccount !== proposed.sourceAccount) {
812
- await Promise.all(
813
- deploymentAliases.filter((name) => name !== deploymentAlias).map(
814
- (name) => createDeploymentUrl(proposed.functionName, name, proposed.sourceAccount).catch(
815
- (error) => {
816
- if (!isError(error, "ResourceNotFoundException")) {
817
- throw error;
818
- }
819
- }
820
- )
821
- )
822
- );
829
+ for (const name of deploymentAliases) {
830
+ if (name === deploymentAlias) {
831
+ continue;
832
+ }
833
+ try {
834
+ await createDeploymentUrl(proposed.functionName, name, proposed.sourceAccount);
835
+ } catch (error) {
836
+ if (!isError(error, "ResourceNotFoundException")) {
837
+ throw error;
838
+ }
839
+ }
840
+ }
823
841
  }
824
842
  return {
825
843
  ...proposed,
@@ -1310,6 +1328,60 @@ var markPromoted = async (client, appId, id) => {
1310
1328
  var removeDeployment = async (client, appId, id) => {
1311
1329
  await deleteItem(table, { appId, id }, { client });
1312
1330
  };
1331
+ var selectPrunableDeployments = (items, liveId, options) => {
1332
+ const rollbackTarget = items.filter((item) => item.promotedAt && item.id !== liveId).sort((a, b) => b.promotedAt.localeCompare(a.promotedAt))[0];
1333
+ const keep = Math.max(1, Number(options.keep) || 10);
1334
+ const mainSlug = slugifyBranch(options.main);
1335
+ const keptMain = new Set(
1336
+ items.filter((item) => item.branch === mainSlug && item.functionVersion).map((item) => item.seq).sort((a, b) => b - a).slice(0, keep)
1337
+ );
1338
+ const dayAgo = new Date(Date.now() - 24 * 60 * 60 * 1e3).toISOString();
1339
+ return items.filter((item) => {
1340
+ if (item.id === liveId || item.id === rollbackTarget?.id) {
1341
+ return false;
1342
+ }
1343
+ if (options.branch) {
1344
+ return item.branch === slugifyBranch(options.branch);
1345
+ }
1346
+ if (!item.functionVersion) {
1347
+ return item.createdAt < dayAgo;
1348
+ }
1349
+ if (item.branch === mainSlug) {
1350
+ return !keptMain.has(item.seq);
1351
+ }
1352
+ return item.commit ? isCommitMerged(item.commit, options.main) : false;
1353
+ });
1354
+ };
1355
+ var pruneFunctionVersion = async (lambda, functionName, version) => {
1356
+ for (const alias of await listLambdaAliases(lambda, functionName, version)) {
1357
+ if (alias.Name && alias.Name !== LIVE_LAMBDA_ALIAS) {
1358
+ await deleteLambdaAlias(lambda, functionName, alias.Name);
1359
+ }
1360
+ }
1361
+ try {
1362
+ await lambda.send(
1363
+ new DeleteFunctionCommand({
1364
+ FunctionName: functionName,
1365
+ Qualifier: version
1366
+ })
1367
+ );
1368
+ } catch (error) {
1369
+ if (!isError(error, "ResourceNotFoundException")) {
1370
+ throw error;
1371
+ }
1372
+ }
1373
+ };
1374
+ var selectPrunableVersions = async (props) => {
1375
+ const surviving = props.items.filter((item) => !props.prunable.includes(item));
1376
+ const kept = new Set(surviving.map((item) => item.functionVersion));
1377
+ const live = await getLambdaAlias(props.lambda, props.functionName, LIVE_LAMBDA_ALIAS);
1378
+ if (live?.FunctionVersion) {
1379
+ kept.add(live.FunctionVersion);
1380
+ }
1381
+ return new Set(
1382
+ props.prunable.map((item) => item.functionVersion).filter((version) => Boolean(version && !kept.has(version)))
1383
+ );
1384
+ };
1313
1385
  var readLiveDeploymentId = async (lambda, functionName) => {
1314
1386
  return (await getLambdaAlias(lambda, functionName, LIVE_LAMBDA_ALIAS))?.Description || void 0;
1315
1387
  };
@@ -1326,17 +1398,21 @@ var readDeployedFunctionVersion = (state2) => {
1326
1398
  return;
1327
1399
  };
1328
1400
  var formatDeploymentSummary = (props) => {
1329
- let previewUrl;
1401
+ const previewUrls = /* @__PURE__ */ new Map();
1330
1402
  for (const [urn, node] of readStateNodes(props.state)) {
1331
1403
  if (node.type === "aws_cloudfront_distribution" && urn.endsWith(":{preview}")) {
1332
- previewUrl = `https://${node.output.domainName}`;
1404
+ const router = urn.match(/router:\{([^}]+)\}/)?.[1];
1405
+ if (router) {
1406
+ previewUrls.set(router, `https://${node.output.domainName}`);
1407
+ }
1333
1408
  }
1334
1409
  }
1335
- return Object.keys(props.appConfig.defaults.router ?? {}).map((routerId, index) => {
1410
+ return Object.keys(props.appConfig.defaults.router ?? {}).map((routerId) => {
1411
+ const previewUrl = previewUrls.get(routerId);
1336
1412
  return [
1337
1413
  `${routerId}: deployment #${props.id}`,
1338
- index === 0 ? previewUrl : void 0,
1339
- index === 0 && previewUrl ? `${previewUrl}/?awsless-deployment=${props.id}` : void 0
1414
+ previewUrl,
1415
+ previewUrl ? `${previewUrl}/?awsless-deployment=${props.id}` : void 0
1340
1416
  ].filter(Boolean).join("\n");
1341
1417
  });
1342
1418
  };
@@ -3900,25 +3976,10 @@ var bundleTypeScriptWithRolldown = async ({
3900
3976
  return importee.startsWith("@aws-sdk") || importee.startsWith("aws-sdk") || external?.includes(importee);
3901
3977
  },
3902
3978
  treeshake: {
3903
- // The @awsless packages are pure clients, but their entry points
3904
- // also export test helpers that pull in local server
3905
- // implementations like dynamo-db-local, which crash the ESM
3906
- // runtime with CJS globals like __dirname. Treating the scope as
3907
- // side-effect free prunes those unused chains from production
3908
- // bundles, while every other dependency keeps its import side
3909
- // effects, like the fs patching of graceful-fs.
3910
- moduleSideEffects: (id, isExternal) => {
3911
- if (isExternal) {
3912
- return external?.includes(id) === true;
3913
- }
3914
- if (id.includes("/node_modules/@awsless/")) {
3915
- return false;
3916
- }
3917
- if (id.includes("/node_modules/")) {
3918
- return true;
3919
- }
3920
- return id.startsWith(`${directories.root}/`);
3921
- }
3979
+ // Dependencies are treated as side-effect free, so unused imports
3980
+ // like the local test servers never reach the production bundle.
3981
+ // The bundle guard below fails the build if one slips through.
3982
+ moduleSideEffects: (id, isExternal) => isExternal ? external?.includes(id) === true : id.startsWith(`${directories.root}/`) && !id.includes("/node_modules/")
3922
3983
  },
3923
3984
  onwarn: (error) => {
3924
3985
  debugError(error.message);
@@ -4119,6 +4180,11 @@ var bundleFeature = defineFeature({
4119
4180
  const addLayer = (layer) => {
4120
4181
  layers.push(layer);
4121
4182
  };
4183
+ const layerIds = Object.keys(ctx.appConfig.defaults.layers ?? {});
4184
+ const layerPackages = layerIds.flatMap((id) => ctx.shared.entry("layer", "packages", id));
4185
+ for (const id of layerIds) {
4186
+ addLayer(ctx.shared.entry("layer", "arn", id));
4187
+ }
4122
4188
  const name = getBundleFunctionName(ctx.app.name);
4123
4189
  const shortName = formatGlobalResourceName({
4124
4190
  appName: ctx.app.name,
@@ -4132,7 +4198,7 @@ var bundleFeature = defineFeature({
4132
4198
  name,
4133
4199
  handlers,
4134
4200
  minify: defaults.minify,
4135
- external: defaults.external
4201
+ external: [...defaults.external ?? [], ...layerPackages]
4136
4202
  })
4137
4203
  );
4138
4204
  const sourceHash = new Output3(envDeps, async (resolve2) => {
@@ -7004,14 +7070,15 @@ var siteFeature = defineFeature({
7004
7070
  env,
7005
7071
  stdout: "pipe",
7006
7072
  stderr: "pipe"
7007
- // stdout: 'ignore',
7008
- // stderr: ''
7009
- // stdout: 'inherit',
7010
- // stderr: 'inherit',
7011
7073
  });
7012
- await instance.exited;
7074
+ const [output, errors] = await Promise.all([
7075
+ new Response(instance.stdout).text(),
7076
+ new Response(instance.stderr).text(),
7077
+ instance.exited
7078
+ ]);
7013
7079
  if (instance.exitCode !== null && instance.exitCode > 0) {
7014
- throw new Error("Site build failed");
7080
+ throw new ExpectedError(`Site build failed:
7081
+ ${(errors.trim() || output.trim()).slice(-2e3)}`);
7015
7082
  }
7016
7083
  await write("HASH", fingerprint);
7017
7084
  return {
@@ -9254,7 +9321,7 @@ var PASSWORD_AUTH_CHECK = (password) => `
9254
9321
  authMethods.push('Password realm="Protected"');
9255
9322
 
9256
9323
  if(!isAuthorized) {
9257
- if(authHeader && authHeader.startsWith('Password ') && authHeader.slice(9) === '${password}') {
9324
+ if(authHeader && authHeader.startsWith('Password ') && authHeader.slice(9) === ${JSON.stringify(password)}) {
9258
9325
  isAuthorized = true;
9259
9326
  }
9260
9327
  }
@@ -9280,7 +9347,7 @@ try {
9280
9347
  : { statusCode: 503, statusDescription: 'Service Unavailable' };
9281
9348
  }
9282
9349
 
9283
- if (request.querystring['awsless-deployment']) {
9350
+ if (deployment && request.querystring['awsless-deployment']) {
9284
9351
  delete request.querystring['awsless-deployment'];
9285
9352
 
9286
9353
  const query = [];
@@ -9289,8 +9356,9 @@ if (request.querystring['awsless-deployment']) {
9289
9356
  const entry = request.querystring[key];
9290
9357
 
9291
9358
  if (entry.multiValue) {
9292
- for (const item of entry.multiValue) {
9293
- query.push(key + '=' + item.value);
9359
+ // The CloudFront js runtime doesn't support for...of.
9360
+ for (const i in entry.multiValue) {
9361
+ query.push(key + '=' + entry.multiValue[i].value);
9294
9362
  }
9295
9363
  } else {
9296
9364
  query.push(key + '=' + entry.value);
@@ -9584,7 +9652,6 @@ var routerFeature = defineFeature({
9584
9652
  const distributionIds = [];
9585
9653
  let hasLambdaRoutes = false;
9586
9654
  let routeStore;
9587
- let previewDistribution;
9588
9655
  for (const [id, props] of routers) {
9589
9656
  const group = new Group29(ctx.base, "router", id);
9590
9657
  const name = formatGlobalResourceName({
@@ -9921,7 +9988,7 @@ var routerFeature = defineFeature({
9921
9988
  ],
9922
9989
  webAclId: waf?.arn
9923
9990
  });
9924
- if (id === defaultRouter) {
9991
+ {
9925
9992
  const previewFunction = new aws30.cloudfront.Function(group, "preview-function", {
9926
9993
  name: `${name.slice(0, 55)}--preview`,
9927
9994
  runtime: "cloudfront-js-2.0",
@@ -9934,7 +10001,7 @@ var routerFeature = defineFeature({
9934
10001
  publish: true,
9935
10002
  keyValueStoreAssociations: [routeStore.arn]
9936
10003
  });
9937
- previewDistribution = new aws30.cloudfront.Distribution(group, "preview", {
10004
+ const previewDistribution = new aws30.cloudfront.Distribution(group, "preview", {
9938
10005
  tags: {
9939
10006
  name: `${name}-preview`
9940
10007
  },
@@ -9998,6 +10065,9 @@ var routerFeature = defineFeature({
9998
10065
  webAclId: waf?.arn
9999
10066
  });
10000
10067
  distributionIds.push(previewDistribution.id);
10068
+ ctx.shared.add("router", "preview-id", id, previewDistribution.id);
10069
+ }
10070
+ if (id === defaultRouter) {
10001
10071
  ctx.onReadyLast(() => {
10002
10072
  const bundle = ctx.shared.get("bundle", "main");
10003
10073
  let lambdaUrlHost;
@@ -10039,7 +10109,6 @@ var routerFeature = defineFeature({
10039
10109
  });
10040
10110
  }
10041
10111
  ctx.shared.add("router", "id", id, distribution.id);
10042
- ctx.shared.add("router", "preview-id", id, previewDistribution.id);
10043
10112
  distributionIds.push(distribution.id);
10044
10113
  if (props.domain) {
10045
10114
  const domainName = formatFullDomainName(ctx.appConfig, props.domain, props.subDomain);
@@ -10783,6 +10852,7 @@ var buildAssets = async (builders, stackFilters, showResult = false) => {
10783
10852
  if (filteredBuilders.length === 0) {
10784
10853
  return;
10785
10854
  }
10855
+ filteredBuilders.sort((a, b) => Number(a.type === "bundle") - Number(b.type === "bundle"));
10786
10856
  const results = [];
10787
10857
  await log10.task({
10788
10858
  initialMessage: `Building assets...`,
@@ -11602,9 +11672,10 @@ var deploy = (program2) => {
11602
11672
  }
11603
11673
  });
11604
11674
  playSuccessSound();
11605
- const details = deployments2.length > 0 ? `
11606
- ${deployments2.join("\n")}` : "";
11607
- return `Deployment #${deployment.id} is live.${details}`;
11675
+ for (const summary of deployments2) {
11676
+ log20.message(summary);
11677
+ }
11678
+ return `Deployment #${deployment.id} is live.`;
11608
11679
  });
11609
11680
  });
11610
11681
  };
@@ -12095,7 +12166,7 @@ var bind = (program2) => {
12095
12166
  stderr: "inherit"
12096
12167
  });
12097
12168
  await instance.exited;
12098
- process.exit(0);
12169
+ process.exit(instance.exitCode ?? 1);
12099
12170
  });
12100
12171
  });
12101
12172
  };
@@ -12215,7 +12286,7 @@ var resources = (program2) => {
12215
12286
  return `${color.dim("{")}${color.warning(v)}${color.dim("}")}`;
12216
12287
  }).replaceAll(":", color.dim(":"));
12217
12288
  };
12218
- const formatStatus = (status) => {
12289
+ const formatStatus2 = (status) => {
12219
12290
  if (status === "created") {
12220
12291
  return color.success(status);
12221
12292
  }
@@ -12240,7 +12311,7 @@ var resources = (program2) => {
12240
12311
  stack.resources.map((r) => {
12241
12312
  return [
12242
12313
  //
12243
- formatStatus(r.status),
12314
+ formatStatus2(r.status),
12244
12315
  color.dim(icon.arrow.right),
12245
12316
  formatResource(stack.urn, r.urn)
12246
12317
  ].join(" ");
@@ -13166,7 +13237,7 @@ var activity = (program2) => {
13166
13237
  // src/cli/command/deployment.ts
13167
13238
  import { CloudFrontClient as CloudFrontClient6 } from "@aws-sdk/client-cloudfront";
13168
13239
  import { CloudFrontKeyValueStoreClient as CloudFrontKeyValueStoreClient3 } from "@aws-sdk/client-cloudfront-keyvaluestore";
13169
- import { DeleteFunctionCommand, LambdaClient as LambdaClient7 } from "@aws-sdk/client-lambda";
13240
+ import { LambdaClient as LambdaClient7 } from "@aws-sdk/client-lambda";
13170
13241
  import { log as log35, prompt as prompt19 } from "@awsless/clui";
13171
13242
  import { DynamoDBClient as DynamoDBClient6 } from "@awsless/dynamodb";
13172
13243
  var createClients = async (appConfig) => {
@@ -13189,6 +13260,12 @@ var formatAge = (iso) => {
13189
13260
  if (minutes8 < 60 * 24) return `${Math.floor(minutes8 / 60)}h ago`;
13190
13261
  return `${Math.floor(minutes8 / (60 * 24))}d ago`;
13191
13262
  };
13263
+ var formatStatus = (item, liveId) => {
13264
+ if (item.id === liveId) return color.success("live ");
13265
+ if (item.promotedAt) return "promoted";
13266
+ if (item.functionVersion) return color.info("staged ");
13267
+ return color.dim("pending ");
13268
+ };
13192
13269
  var deployments = (program2) => {
13193
13270
  program2.command("deployments").description("List the deployment history of your app").action(async () => {
13194
13271
  await layout("deployments", async ({ appConfig }) => {
@@ -13202,17 +13279,16 @@ var deployments = (program2) => {
13202
13279
  }
13203
13280
  const idWidth = Math.max(...items.map((item) => item.id.length));
13204
13281
  log35.message(
13205
- items.map((item) => {
13206
- const status = item.id === liveId ? color.success("live ") : item.promotedAt ? "promoted" : item.functionVersion ? color.info("staged ") : color.dim("pending ");
13207
- return [
13282
+ items.map(
13283
+ (item) => [
13208
13284
  color.label(item.id.padEnd(idWidth)),
13209
- status,
13285
+ formatStatus(item, liveId),
13210
13286
  formatAge(item.createdAt).padEnd(8),
13211
13287
  color.dim(item.commit?.slice(0, 7) ?? "-------"),
13212
13288
  (item.message ?? "").slice(0, 50).padEnd(50),
13213
13289
  color.dim(item.user ?? "")
13214
- ].join(" ");
13215
- }).join("\n")
13290
+ ].join(" ")
13291
+ ).join("\n")
13216
13292
  );
13217
13293
  return `Found ${items.length} deployments.`;
13218
13294
  });
@@ -13226,28 +13302,7 @@ var prune = (program2) => {
13226
13302
  listDeployments(dynamo, appId),
13227
13303
  readLiveDeploymentId(lambda, functionName)
13228
13304
  ]);
13229
- const rollbackTarget = items.filter((item) => item.promotedAt && item.id !== liveId).sort((a, b) => b.promotedAt.localeCompare(a.promotedAt))[0];
13230
- const keep = Math.max(1, Number(options.keep) || 10);
13231
- const mainSlug = slugifyBranch(options.main);
13232
- const keptMain = new Set(
13233
- items.filter((item) => item.branch === mainSlug && item.functionVersion).map((item) => item.seq).sort((a, b) => b - a).slice(0, keep)
13234
- );
13235
- const dayAgo = new Date(Date.now() - 24 * 60 * 60 * 1e3).toISOString();
13236
- const prunable = items.filter((item) => {
13237
- if (item.id === liveId || item.id === rollbackTarget?.id) {
13238
- return false;
13239
- }
13240
- if (options.branch) {
13241
- return item.branch === slugifyBranch(options.branch);
13242
- }
13243
- if (!item.functionVersion) {
13244
- return item.createdAt < dayAgo;
13245
- }
13246
- if (item.branch === mainSlug) {
13247
- return !keptMain.has(item.seq);
13248
- }
13249
- return item.commit ? isCommitMerged(item.commit, options.main) : false;
13250
- });
13305
+ const prunable = selectPrunableDeployments(items, liveId, options);
13251
13306
  if (prunable.length === 0) {
13252
13307
  return `Nothing to prune.`;
13253
13308
  }
@@ -13267,28 +13322,9 @@ var prune = (program2) => {
13267
13322
  for (const item of prunable) {
13268
13323
  await deleteLambdaAlias(lambda, functionName, getDeploymentLambdaAliasName(item.id));
13269
13324
  }
13270
- const surviving = items.filter((item) => !prunable.includes(item));
13271
- const keepVersions = new Set(surviving.map((item) => item.functionVersion));
13272
- const live = await getLambdaAlias(lambda, functionName, LIVE_LAMBDA_ALIAS);
13273
- if (live?.FunctionVersion) {
13274
- keepVersions.add(live.FunctionVersion);
13275
- }
13276
- const versions = new Set(
13277
- prunable.map((item) => item.functionVersion).filter((version) => version && !keepVersions.has(version))
13278
- );
13325
+ const versions = await selectPrunableVersions({ lambda, functionName, items, prunable });
13279
13326
  for (const version of versions) {
13280
- try {
13281
- await lambda.send(
13282
- new DeleteFunctionCommand({
13283
- FunctionName: functionName,
13284
- Qualifier: version
13285
- })
13286
- );
13287
- } catch (error) {
13288
- if (!isError(error, "ResourceNotFoundException") && !isError(error, "ResourceConflictException")) {
13289
- throw error;
13290
- }
13291
- }
13327
+ await pruneFunctionVersion(lambda, functionName, version);
13292
13328
  }
13293
13329
  const storeArn = await getRouteStoreArn(
13294
13330
  cloudfront,
@@ -13374,8 +13410,8 @@ program.option("--stage <string>", "The stage to use");
13374
13410
  program.option("-c --no-cache", "Always build & test without the cache");
13375
13411
  program.option("-s --skip-prompt", "Skip prompts");
13376
13412
  program.option("-v --verbose", "Print verbose logs");
13377
- program.exitOverride(() => {
13378
- process.exit(0);
13413
+ program.exitOverride((error) => {
13414
+ process.exit(error.exitCode);
13379
13415
  });
13380
13416
  program.on("option:verbose", () => {
13381
13417
  process.env.VERBOSE = program.opts().verbose ? "1" : void 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awsless/cli",
3
- "version": "0.0.46-next.2",
3
+ "version": "0.0.46-next.4",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -83,23 +83,23 @@
83
83
  "zod": "^3.24.2",
84
84
  "zod-to-json-schema": "^3.24.3",
85
85
  "@awsless/big-float": "^0.1.7",
86
+ "@awsless/clui": "^0.0.9",
86
87
  "@awsless/cloudwatch": "^0.0.1",
87
- "@awsless/duration": "^0.0.4",
88
- "@awsless/clui": "^0.0.8",
89
88
  "@awsless/dynamodb": "^0.3.21",
90
89
  "@awsless/iot": "^0.0.5",
91
90
  "@awsless/json": "^0.0.11",
92
- "@awsless/s3": "^0.0.21",
93
91
  "@awsless/lambda": "^0.0.45",
94
92
  "@awsless/redis": "^0.1.13",
95
93
  "@awsless/scheduler": "^0.0.4",
96
- "@awsless/sns": "^0.0.10",
97
- "@awsless/sqs": "^0.0.24",
94
+ "@awsless/s3": "^0.0.21",
95
+ "@awsless/size": "^0.0.2",
98
96
  "@awsless/ts-file-cache": "^0.0.16",
99
- "@awsless/validate": "^0.1.7",
100
- "@awsless/weak-cache": "^0.0.1",
97
+ "@awsless/sqs": "^0.0.24",
101
98
  "awsless": "^0.0.15-next.0",
102
- "@awsless/size": "^0.0.2"
99
+ "@awsless/weak-cache": "^0.0.1",
100
+ "@awsless/sns": "^0.0.10",
101
+ "@awsless/validate": "^0.1.7",
102
+ "@awsless/duration": "^0.0.4"
103
103
  },
104
104
  "devDependencies": {
105
105
  "@hono/node-server": "1.19.9",