@awsless/cli 0.1.14 → 0.1.15

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 +98 -83
  2. package/package.json +13 -13
package/dist/bin.js CHANGED
@@ -149982,6 +149982,7 @@ var preflightDeployment = async (props) => {
149982
149982
  }
149983
149983
  };
149984
149984
  var promoteDeployment = async (props) => {
149985
+ const stores = props.stores ?? [];
149985
149986
  const deployment = await getDeployment(props.dynamo, props.appId, props.id);
149986
149987
  const functionVersion = deployment?.functionVersion;
149987
149988
  if (!deployment) {
@@ -149990,13 +149991,19 @@ var promoteDeployment = async (props) => {
149990
149991
  if (!functionVersion) {
149991
149992
  throw new ExpectedError(`Deployment "${props.id}" hasn't finished deploying.`);
149992
149993
  }
149993
- if (props.store && props.store.deployment.functionVersion !== functionVersion) {
149994
- throw new ExpectedError(`The routes don't share the deployed function version.`);
149994
+ for (const store of stores) {
149995
+ if (store.deployment.functionVersion !== functionVersion) {
149996
+ throw new ExpectedError(`The routes don't share the deployed function version.`);
149997
+ }
149995
149998
  }
149996
149999
  const alias = await getLambdaAlias(props.lambda, props.functionName, LIVE_LAMBDA_ALIAS);
149997
150000
  const liveId = alias?.Description || undefined;
149998
- const activeId = props.store ? await readActiveDeploymentId(props.kvs, props.store.arn) : undefined;
149999
- const active = props.store && activeId !== undefined ? await readRouteDeployment(props.kvs, props.store.arn, activeId) : undefined;
150001
+ const activeRoutes = new Map;
150002
+ for (const store of stores) {
150003
+ const activeId = await readActiveDeploymentId(props.kvs, store.arn);
150004
+ const active = activeId !== undefined ? await readRouteDeployment(props.kvs, store.arn, activeId) : undefined;
150005
+ activeRoutes.set(store.arn, active);
150006
+ }
150000
150007
  if (props.rejectStale && liveId && liveId !== props.id) {
150001
150008
  const live = await getDeployment(props.dynamo, props.appId, liveId);
150002
150009
  if (live?.promotedAt && live.promotedAt > deployment.createdAt) {
@@ -150014,8 +150021,8 @@ var promoteDeployment = async (props) => {
150014
150021
  }
150015
150022
  throw error3;
150016
150023
  }
150017
- let routesUpdateStarted = false;
150018
150024
  let aliasUpdateStarted = false;
150025
+ const flippedStores = [];
150019
150026
  const flipped = [];
150020
150027
  try {
150021
150028
  for (const name of await listLambdaFunctions(props.lambda, getAppNamePrefix(props.appName))) {
@@ -150042,9 +150049,11 @@ var promoteDeployment = async (props) => {
150042
150049
  description: props.id
150043
150050
  });
150044
150051
  }
150045
- if (props.store && active?.id !== props.store.deployment.id) {
150046
- routesUpdateStarted = true;
150047
- await setActiveRouteDeployment(props.kvs, props.store.arn, props.store.deployment);
150052
+ for (const store of stores) {
150053
+ if (activeRoutes.get(store.arn)?.id !== store.deployment.id) {
150054
+ flippedStores.push(store);
150055
+ await setActiveRouteDeployment(props.kvs, store.arn, store.deployment);
150056
+ }
150048
150057
  }
150049
150058
  if (alias?.FunctionVersion !== functionVersion || alias?.Description !== props.id) {
150050
150059
  aliasUpdateStarted = true;
@@ -150058,7 +150067,7 @@ var promoteDeployment = async (props) => {
150058
150067
  await markPromoted(props.dynamo, props.appId, props.id);
150059
150068
  } catch (error3) {
150060
150069
  const rollback = [
150061
- ...routesUpdateStarted && props.store ? [setActiveRouteDeployment(props.kvs, props.store.arn, active)] : [],
150070
+ ...flippedStores.map((store) => setActiveRouteDeployment(props.kvs, store.arn, activeRoutes.get(store.arn))),
150062
150071
  ...aliasUpdateStarted && alias?.FunctionVersion ? [
150063
150072
  upsertLambdaAlias(props.lambda, {
150064
150073
  functionName: props.functionName,
@@ -150092,21 +150101,21 @@ var activateDeployment = async (props) => {
150092
150101
  const dynamo = new DynamoDBClient({ credentials: credentials2, region });
150093
150102
  const functionName = getBundleFunctionName(props.appConfig.name);
150094
150103
  const id = props.id ?? await previousDeploymentId({ lambda, dynamo, appId, functionName });
150095
- let store;
150096
- if (Object.keys(props.appConfig.router ?? {}).length > 0) {
150104
+ const stores = [];
150105
+ for (const routerId of Object.keys(props.appConfig.router ?? {})) {
150097
150106
  const storeArn = await getRouteStoreArn(cloudfront, formatGlobalResourceName({
150098
150107
  appName: props.appConfig.name,
150099
150108
  resourceType: "router",
150100
- resourceName: "store"
150109
+ resourceName: routerId
150101
150110
  }));
150102
150111
  if (!storeArn) {
150103
- throw new ExpectedError(`The router hasn't been deployed yet. Run "awsless deploy" first.`);
150112
+ throw new ExpectedError(`The "${routerId}" router hasn't been deployed yet. Run "awsless deploy" first.`);
150104
150113
  }
150105
150114
  const routes = await readRouteDeployment(kvs, storeArn, id);
150106
150115
  if (!routes) {
150107
- throw new ExpectedError(`Deployment "${id}" doesn't exist.`);
150116
+ throw new ExpectedError(`Deployment "${id}" doesn't exist for the "${routerId}" router.`);
150108
150117
  }
150109
- store = { arn: storeArn, deployment: routes };
150118
+ stores.push({ arn: storeArn, deployment: routes });
150110
150119
  }
150111
150120
  await promoteDeployment({
150112
150121
  kvs,
@@ -150116,7 +150125,7 @@ var activateDeployment = async (props) => {
150116
150125
  appName: props.appConfig.name,
150117
150126
  functionName,
150118
150127
  id,
150119
- store,
150128
+ stores,
150120
150129
  rejectStale: props.rejectStale
150121
150130
  });
150122
150131
  return id;
@@ -162683,39 +162692,30 @@ var routerFeature = defineFeature({
162683
162692
  name: "router",
162684
162693
  onApp(ctx) {
162685
162694
  const routers = Object.entries(ctx.appConfig.router ?? {});
162686
- const defaultRouter = routers[0]?.[0];
162687
162695
  const routes = {};
162688
- const routeDependencies = new Set;
162696
+ const routeDependencies = {};
162697
+ const routeStores = {};
162698
+ const routerGroups = {};
162689
162699
  const distributionIds = [];
162690
162700
  let hasLambdaRoutes = false;
162691
- let routeStore;
162692
- let sharedGroup;
162693
- if (routers.length > 0) {
162694
- const storeName = formatGlobalResourceName({
162695
- appName: ctx.app.name,
162696
- resourceType: "router",
162697
- resourceName: "store"
162698
- });
162699
- sharedGroup = new Group(ctx.base, "router", "shared");
162700
- routeStore = new aws2.cloudfront.KeyValueStore(sharedGroup, "routes", {
162701
- name: storeName,
162702
- comment: "Store for routes"
162703
- }, {
162704
- replaceOnChanges: ["name"],
162705
- createBeforeReplace: true,
162706
- import: ctx.import ? storeName : undefined
162707
- });
162708
- }
162709
162701
  for (const [id, props] of routers) {
162710
162702
  const group4 = new Group(ctx.base, "router", id);
162703
+ routerGroups[id] = group4;
162704
+ routes[id] = {};
162705
+ routeDependencies[id] = new Set;
162711
162706
  const name = formatGlobalResourceName({
162712
162707
  appName: ctx.app.name,
162713
162708
  resourceType: "router",
162714
162709
  resourceName: id
162715
162710
  });
162716
- const productionFunctionName = `${name.slice(0, 52)}--production`;
162717
- const productionFunction = new aws2.cloudfront.Function(group4, "production-function", {
162718
- name: productionFunctionName,
162711
+ const routeStore = new aws2.cloudfront.KeyValueStore(group4, "routes", { name }, {
162712
+ replaceOnChanges: ["name"],
162713
+ createBeforeReplace: true,
162714
+ import: ctx.import ? name : undefined
162715
+ });
162716
+ routeStores[id] = routeStore;
162717
+ const cfFunction = new aws2.cloudfront.Function(group4, "function", {
162718
+ name,
162719
162719
  runtime: "cloudfront-js-2.0",
162720
162720
  code: getViewerRequestFunctionCode({
162721
162721
  router: id,
@@ -162727,18 +162727,19 @@ var routerFeature = defineFeature({
162727
162727
  publish: true,
162728
162728
  keyValueStoreAssociations: [routeStore.arn]
162729
162729
  }, {
162730
- import: ctx.import ? productionFunctionName : undefined
162730
+ import: ctx.import ? name : undefined
162731
162731
  });
162732
162732
  ctx.shared.add("router", "addRoutes", id, (newRoutes, options) => {
162733
+ const routerRoutes = routes[id];
162733
162734
  for (const [key, route] of Object.entries(newRoutes)) {
162734
- if (Object.hasOwn(routes, `${id}:${key}`)) {
162735
+ if (Object.hasOwn(routerRoutes, `${id}:${key}`)) {
162735
162736
  throw new ExpectedError(`Duplicate route key: ${key} in the "${id}" router`);
162736
162737
  }
162737
162738
  assertRouteValueSize(`${id}:${key}`, route);
162738
- routes[`${id}:${key}`] = route;
162739
+ routerRoutes[`${id}:${key}`] = route;
162739
162740
  }
162740
162741
  for (const dependency of options?.dependsOn ?? []) {
162741
- routeDependencies.add(dependency);
162742
+ routeDependencies[id].add(dependency);
162742
162743
  }
162743
162744
  if (Object.values(newRoutes).flat().some((route) => route.type === "lambda" && !route.domainName)) {
162744
162745
  hasLambdaRoutes = true;
@@ -163001,7 +163002,7 @@ var routerFeature = defineFeature({
163001
163002
  functionAssociation: [
163002
163003
  {
163003
163004
  eventType: "viewer-request",
163004
- functionArn: productionFunction.arn
163005
+ functionArn: cfFunction.arn
163005
163006
  }
163006
163007
  ],
163007
163008
  originRequestPolicyId: originRequest.id,
@@ -163018,38 +163019,6 @@ var routerFeature = defineFeature({
163018
163019
  ],
163019
163020
  webAclId: waf?.arn
163020
163021
  });
163021
- if (id === defaultRouter) {
163022
- ctx.onReadyLast(() => {
163023
- const bundle = ctx.shared.get("bundle", "main");
163024
- let lambdaUrlHost;
163025
- if (hasLambdaRoutes) {
163026
- const deployment = new FunctionDeployment(sharedGroup, "function-deployment", {
163027
- functionName: bundle.lambda.functionName,
163028
- id: ctx.deploymentId ?? "local-0",
163029
- sourceArns: distributionIds.map((distributionId) => distributionId.pipe((id2) => `arn:aws:cloudfront::${ctx.accountId}:distribution/${id2}`))
163030
- }, {
163031
- dependsOn: [bundle.deployment]
163032
- });
163033
- lambdaUrlHost = deployment.url.pipe((url) => url.split("/")[2]);
163034
- routeDependencies.add(bundle.policy);
163035
- routeDependencies.add(bundle.alias);
163036
- routeDependencies.add(deployment);
163037
- }
163038
- new RouteDeployment(sharedGroup, "deployment", {
163039
- deploymentId: ctx.deploymentId ?? "local-0",
163040
- storeArn: routeStore.arn,
163041
- functionVersion: bundle.lambda.version,
163042
- routes: $resolve([routes, lambdaUrlHost], (routes2, lambdaUrlHost2) => {
163043
- const withOrigin = (route) => {
163044
- return route.type === "lambda" && !route.domainName ? { ...route, domainName: lambdaUrlHost2 } : route;
163045
- };
163046
- return Object.entries(routes2).flatMap(([key, route]) => createRouteStoreEntries(key, Array.isArray(route) ? route.map(withOrigin) : withOrigin(route)));
163047
- })
163048
- }, {
163049
- dependsOn: Array.from(routeDependencies)
163050
- });
163051
- });
163052
- }
163053
163022
  ctx.shared.add("router", "id", id, distribution.id);
163054
163023
  distributionIds.push(distribution.id);
163055
163024
  if (props.domain) {
@@ -163105,6 +163074,44 @@ var routerFeature = defineFeature({
163105
163074
  ctx.shared.add("router", "endpoint", id, domainName);
163106
163075
  }
163107
163076
  }
163077
+ if (routers.length > 0) {
163078
+ ctx.onReadyLast(() => {
163079
+ const bundle = ctx.shared.get("bundle", "main");
163080
+ const sharedDependencies = [];
163081
+ let lambdaUrlHost;
163082
+ if (hasLambdaRoutes) {
163083
+ const sharedGroup = new Group(ctx.base, "router", "shared");
163084
+ const deployment = new FunctionDeployment(sharedGroup, "function-deployment", {
163085
+ functionName: bundle.lambda.functionName,
163086
+ id: ctx.deploymentId ?? "local-0",
163087
+ sourceArns: distributionIds.map((distributionId) => distributionId.pipe((id) => `arn:aws:cloudfront::${ctx.accountId}:distribution/${id}`))
163088
+ }, {
163089
+ dependsOn: [bundle.deployment]
163090
+ });
163091
+ lambdaUrlHost = deployment.url.pipe((url) => url.split("/")[2]);
163092
+ sharedDependencies.push(bundle.policy, bundle.alias, deployment);
163093
+ }
163094
+ for (const [id] of routers) {
163095
+ const dependencies = routeDependencies[id];
163096
+ for (const dependency of sharedDependencies) {
163097
+ dependencies.add(dependency);
163098
+ }
163099
+ new RouteDeployment(routerGroups[id], "deployment", {
163100
+ deploymentId: ctx.deploymentId ?? "local-0",
163101
+ storeArn: routeStores[id].arn,
163102
+ functionVersion: bundle.lambda.version,
163103
+ routes: $resolve([routes[id], lambdaUrlHost], (routes2, lambdaUrlHost2) => {
163104
+ const withOrigin = (route) => {
163105
+ return route.type === "lambda" && !route.domainName ? { ...route, domainName: lambdaUrlHost2 } : route;
163106
+ };
163107
+ return Object.entries(routes2).flatMap(([key, route]) => createRouteStoreEntries(key, Array.isArray(route) ? route.map(withOrigin) : withOrigin(route)));
163108
+ })
163109
+ }, {
163110
+ dependsOn: Array.from(dependencies)
163111
+ });
163112
+ }
163113
+ });
163114
+ }
163108
163115
  },
163109
163116
  onStack(ctx) {
163110
163117
  for (const [id, patterns] of Object.entries(ctx.stackConfig.routes ?? {})) {
@@ -187353,13 +187360,21 @@ var prune = (program3) => {
187353
187360
  await pruneFunctionVersion(lambda, name, version2);
187354
187361
  }
187355
187362
  }
187356
- const storeArn = await getRouteStoreArn(cloudfront, formatGlobalResourceName({
187357
- appName: appConfig.name,
187358
- resourceType: "router",
187359
- resourceName: "store"
187360
- }));
187361
- if (storeArn) {
187362
- const survivingRoutes = await pruneStoreDeployments(kvs, storeArn, prune2.map((item) => item.id));
187363
+ const survivingRoutes = [];
187364
+ let sweptStores = false;
187365
+ for (const routerId of Object.keys(appConfig.router ?? {})) {
187366
+ const storeArn = await getRouteStoreArn(cloudfront, formatGlobalResourceName({
187367
+ appName: appConfig.name,
187368
+ resourceType: "router",
187369
+ resourceName: routerId
187370
+ }));
187371
+ if (!storeArn) {
187372
+ continue;
187373
+ }
187374
+ sweptStores = true;
187375
+ survivingRoutes.push(...await pruneStoreDeployments(kvs, storeArn, prune2.map((item) => item.id)));
187376
+ }
187377
+ if (sweptStores) {
187363
187378
  await pruneSiteVersions({
187364
187379
  s3,
187365
187380
  bucket: formatGlobalResourceName({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awsless/cli",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -43,14 +43,14 @@
43
43
  },
44
44
  "peerDependencies": {
45
45
  "@awsless/big-float": "^0.1.7",
46
+ "@awsless/json": "^0.0.11",
46
47
  "@awsless/duration": "^0.0.4",
47
48
  "@awsless/dynamodb": "^0.3.25",
48
- "@awsless/json": "^0.0.11",
49
49
  "@awsless/lambda": "^0.0.48",
50
- "@awsless/validate": "^0.2.0",
50
+ "@awsless/s3": "^0.0.22",
51
51
  "@awsless/weak-cache": "^0.0.1",
52
- "awsless": "^0.1.4",
53
- "@awsless/s3": "^0.0.22"
52
+ "@awsless/validate": "^0.2.0",
53
+ "awsless": "^0.1.4"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@aws-sdk/client-cloudformation": "^3.369.0",
@@ -110,23 +110,23 @@
110
110
  "zod-to-json-schema": "^3.24.3",
111
111
  "@awsless/cloudwatch": "^0.0.1",
112
112
  "@awsless/big-float": "^0.1.7",
113
- "@awsless/clui": "^0.0.9",
114
- "@awsless/duration": "^0.0.4",
115
113
  "@awsless/dynamodb": "^0.3.25",
116
- "@awsless/iot": "^0.0.5",
117
114
  "@awsless/json": "^0.0.11",
118
115
  "@awsless/lambda": "^0.0.48",
119
- "@awsless/open-search": "^0.0.28",
116
+ "@awsless/iot": "^0.0.5",
117
+ "@awsless/duration": "^0.0.4",
120
118
  "@awsless/redis": "^0.1.13",
119
+ "@awsless/clui": "^0.0.9",
121
120
  "@awsless/s3": "^0.0.22",
122
121
  "@awsless/scheduler": "^0.0.5",
123
122
  "@awsless/size": "^0.0.2",
124
- "@awsless/sns": "^0.0.11",
125
- "@awsless/ssm": "^0.0.8",
126
- "@awsless/weak-cache": "^0.0.1",
127
123
  "@awsless/sqs": "^0.0.24",
124
+ "@awsless/open-search": "^0.0.28",
125
+ "@awsless/validate": "^0.2.0",
126
+ "@awsless/ssm": "^0.0.8",
127
+ "@awsless/sns": "^0.0.11",
128
128
  "awsless": "^0.1.4",
129
- "@awsless/validate": "^0.2.0"
129
+ "@awsless/weak-cache": "^0.0.1"
130
130
  },
131
131
  "scripts": {
132
132
  "test": "bun cli/build-handlers.ts && pnpm vitest",