@awsless/awsless 0.0.189 → 0.0.190

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
@@ -165,6 +165,9 @@ var directories = {
165
165
  get cache() {
166
166
  return join(this.output, "cache");
167
167
  },
168
+ get state() {
169
+ return join(this.output, "state");
170
+ },
168
171
  get build() {
169
172
  return join(this.output, "build");
170
173
  },
@@ -1462,11 +1465,12 @@ import {
1462
1465
  ScalarAttributeType
1463
1466
  } from "@aws-sdk/client-dynamodb";
1464
1467
  import { confirm, log as log6 } from "@clack/prompts";
1465
- var hasStateTable = async (client) => {
1468
+ import { CreateBucketCommand, HeadBucketCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
1469
+ var hasLockTable = async (client) => {
1466
1470
  try {
1467
1471
  const result = await client.send(
1468
1472
  new DescribeTableCommand({
1469
- TableName: "awsless-state"
1473
+ TableName: "awsless-locks"
1470
1474
  })
1471
1475
  );
1472
1476
  return !!result.Table;
@@ -1477,10 +1481,26 @@ var hasStateTable = async (client) => {
1477
1481
  throw error;
1478
1482
  }
1479
1483
  };
1480
- var createStateTable = (client) => {
1484
+ var hasStateBucket = async (client) => {
1485
+ try {
1486
+ const result = await client.send(
1487
+ new HeadBucketCommand({
1488
+ Bucket: "awsless-state"
1489
+ })
1490
+ );
1491
+ return !!result.BucketRegion;
1492
+ } catch (error) {
1493
+ console.log(error);
1494
+ if (error instanceof S3ServiceException) {
1495
+ return false;
1496
+ }
1497
+ throw error;
1498
+ }
1499
+ };
1500
+ var createLockTable = (client) => {
1481
1501
  return client.send(
1482
1502
  new CreateTableCommand({
1483
- TableName: "awsless-state",
1503
+ TableName: "awsless-locks",
1484
1504
  BillingMode: BillingMode.PAY_PER_REQUEST,
1485
1505
  KeySchema: [
1486
1506
  {
@@ -1497,10 +1517,22 @@ var createStateTable = (client) => {
1497
1517
  })
1498
1518
  );
1499
1519
  };
1500
- var bootstrapAwsless = async (opts) => {
1501
- const client = new DynamoDB(opts);
1502
- const table2 = await hasStateTable(client);
1503
- if (!table2) {
1520
+ var createStateBucket = (client) => {
1521
+ return client.send(
1522
+ new CreateBucketCommand({
1523
+ Bucket: "awsless-state"
1524
+ })
1525
+ );
1526
+ };
1527
+ var bootstrapAwsless = async (props) => {
1528
+ const dynamo = new DynamoDB(props);
1529
+ const s3 = new S3Client(props);
1530
+ const [table2, bucket] = await Promise.all([
1531
+ //
1532
+ hasLockTable(dynamo),
1533
+ hasStateBucket(s3)
1534
+ ]);
1535
+ if (!table2 || !bucket) {
1504
1536
  log6.warn(`Your Awsless hasn't been bootstrapped yet.`);
1505
1537
  if (!process.env.SKIP_PROMPT) {
1506
1538
  const confirmed = await confirm({
@@ -1511,7 +1543,12 @@ var bootstrapAwsless = async (opts) => {
1511
1543
  }
1512
1544
  }
1513
1545
  await task("Bootstrapping", async (update) => {
1514
- await createStateTable(client);
1546
+ if (!table2) {
1547
+ await createLockTable(dynamo);
1548
+ }
1549
+ if (!bucket) {
1550
+ await createStateBucket(s3);
1551
+ }
1515
1552
  update("Done deploying the bootstrap stack");
1516
1553
  });
1517
1554
  } else {
@@ -1991,14 +2028,14 @@ var build = (type, name, builder) => {
1991
2028
  };
1992
2029
 
1993
2030
  // src/feature/function/util.ts
1994
- var createLambdaFunction = (group, ctx, ns, id, local) => {
2031
+ var createLambdaFunction = (group, ctx, ns, id, local2) => {
1995
2032
  let name;
1996
2033
  if ("stackConfig" in ctx) {
1997
2034
  name = formatLocalResourceName(ctx.appConfig.name, ctx.stackConfig.name, ns, id);
1998
2035
  } else {
1999
2036
  name = formatGlobalResourceName(ctx.appConfig.name, ns, id);
2000
2037
  }
2001
- const props = deepmerge(ctx.appConfig.defaults.function, local);
2038
+ const props = deepmerge(ctx.appConfig.defaults.function, local2);
2002
2039
  ctx.registerBuild("function", name, async (build3) => {
2003
2040
  const version = await fingerprintFromFile(props.file);
2004
2041
  return build3(version, async (write) => {
@@ -2073,8 +2110,8 @@ var createLambdaFunction = (group, ctx, ns, id, local) => {
2073
2110
  if (ctx.appConfig.defaults.function.permissions) {
2074
2111
  policy.addStatement(...ctx.appConfig.defaults.function.permissions);
2075
2112
  }
2076
- if ("permissions" in local && local.permissions) {
2077
- policy.addStatement(...local.permissions);
2113
+ if ("permissions" in local2 && local2.permissions) {
2114
+ policy.addStatement(...local2.permissions);
2078
2115
  }
2079
2116
  if (props.warm) {
2080
2117
  const rule = new aws2.events.Rule(group, "warm", {
@@ -3037,8 +3074,8 @@ var queueFeature = defineFeature({
3037
3074
  await ctx.write("queue.d.ts", gen, true);
3038
3075
  },
3039
3076
  onStack(ctx) {
3040
- for (const [id, local] of Object.entries(ctx.stackConfig.queues || {})) {
3041
- const props = deepmerge2(ctx.appConfig.defaults.queue, local);
3077
+ for (const [id, local2] of Object.entries(ctx.stackConfig.queues || {})) {
3078
+ const props = deepmerge2(ctx.appConfig.defaults.queue, local2);
3042
3079
  const group = new Node9(ctx.stack, "queue", id);
3043
3080
  const queue2 = new aws9.sqs.Queue(group, "queue", {
3044
3081
  name: formatLocalResourceName(ctx.appConfig.name, ctx.stack.name, "queue", id),
@@ -4162,8 +4199,50 @@ var config = (program2) => {
4162
4199
 
4163
4200
  // src/cli/command/delete.ts
4164
4201
  import { confirm as confirm3 } from "@clack/prompts";
4165
- import { WorkSpace, aws as aws18 } from "@awsless/formation";
4202
+
4203
+ // src/util/workspace.ts
4204
+ import { WorkSpace, aws as aws18, local } from "@awsless/formation";
4166
4205
  import { minutes as minutes4 } from "@awsless/duration";
4206
+ import { dirname as dirname8, join as join9 } from "path";
4207
+ import { mkdir as mkdir2, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
4208
+ var createWorkSpace = (props) => {
4209
+ const lockProvider = new aws18.dynamodb.LockProvider({
4210
+ ...props,
4211
+ tableName: "awsless-locks"
4212
+ });
4213
+ const stateProvider = new aws18.s3.StateProvider({
4214
+ ...props,
4215
+ bucket: "awsless-state"
4216
+ });
4217
+ const cloudProviders = aws18.createCloudProviders({
4218
+ ...props,
4219
+ timeout: minutes4(60)
4220
+ });
4221
+ const workspace = new WorkSpace({
4222
+ lockProvider,
4223
+ stateProvider,
4224
+ cloudProviders
4225
+ });
4226
+ return {
4227
+ workspace,
4228
+ lockProvider,
4229
+ stateProvider
4230
+ };
4231
+ };
4232
+ var pullRemoteState = async (app, stateProvider) => {
4233
+ const file = join9(directories.state, `${app.urn}.json`);
4234
+ const state2 = await stateProvider.get(app.urn);
4235
+ await mkdir2(dirname8(file), { recursive: true });
4236
+ await writeFile2(file, JSON.stringify(state2, void 0, 2));
4237
+ };
4238
+ var pushRemoteState = async (app, stateProvider) => {
4239
+ const file = join9(directories.state, `${app.urn}.json`);
4240
+ const data = await readFile6(file, "utf8");
4241
+ const state2 = JSON.parse(data);
4242
+ await stateProvider.update(app.urn, state2);
4243
+ };
4244
+
4245
+ // src/cli/command/delete.ts
4167
4246
  var del2 = (program2) => {
4168
4247
  program2.command("delete").argument("[stacks...]", "Optionally filter stacks to delete").description("Delete your app from AWS").action(async (filters) => {
4169
4248
  await layout("delete", async ({ appConfig, stackConfigs }) => {
@@ -4186,20 +4265,13 @@ var del2 = (program2) => {
4186
4265
  throw new Cancelled();
4187
4266
  }
4188
4267
  }
4189
- const workspace = new WorkSpace({
4190
- stateProvider: new aws18.dynamodb.StateProvider({
4191
- credentials,
4192
- region,
4193
- tableName: "awsless-state"
4194
- }),
4195
- cloudProviders: aws18.createCloudProviders({
4196
- credentials,
4197
- region: appConfig.region,
4198
- timeout: minutes4(30)
4199
- })
4268
+ const { workspace, stateProvider } = createWorkSpace({
4269
+ credentials,
4270
+ region
4200
4271
  });
4201
4272
  await task("Deleting the stacks to AWS", async (update) => {
4202
4273
  await workspace.deleteApp(app);
4274
+ await pullRemoteState(app, stateProvider);
4203
4275
  update("Done deleting the stacks to AWS.");
4204
4276
  });
4205
4277
  return "Your app has been deleted!";
@@ -4208,12 +4280,11 @@ var del2 = (program2) => {
4208
4280
  };
4209
4281
 
4210
4282
  // src/cli/command/deploy.ts
4211
- import { WorkSpace as WorkSpace2, aws as aws19 } from "@awsless/formation";
4212
4283
  import { confirm as confirm4 } from "@clack/prompts";
4213
4284
 
4214
4285
  // src/cli/ui/complex/run-tests.ts
4215
- import { join as join9 } from "path";
4216
- import { mkdir as mkdir2, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
4286
+ import { join as join10 } from "path";
4287
+ import { mkdir as mkdir3, readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
4217
4288
 
4218
4289
  // src/test/reporter.ts
4219
4290
  import { getSuites, getTests } from "@vitest/runner/utils";
@@ -4397,12 +4468,12 @@ var logTestErrors = (event) => {
4397
4468
  });
4398
4469
  };
4399
4470
  var runTest = async (stack, dir, filters) => {
4400
- await mkdir2(directories.test, { recursive: true });
4471
+ await mkdir3(directories.test, { recursive: true });
4401
4472
  const fingerprint = await fingerprintFromDirectory(dir);
4402
- const file = join9(directories.test, `${stack}.json`);
4473
+ const file = join10(directories.test, `${stack}.json`);
4403
4474
  const exists = await fileExist(file);
4404
4475
  if (exists && !process.env.NO_CACHE) {
4405
- const raw = await readFile6(file, { encoding: "utf8" });
4476
+ const raw = await readFile7(file, { encoding: "utf8" });
4406
4477
  const data = JSON.parse(raw);
4407
4478
  if (data.fingerprint === fingerprint) {
4408
4479
  log8.step(
@@ -4443,7 +4514,7 @@ var runTest = async (stack, dir, filters) => {
4443
4514
  });
4444
4515
  logTestLogs(result);
4445
4516
  logTestErrors(result);
4446
- await writeFile2(
4517
+ await writeFile3(
4447
4518
  file,
4448
4519
  JSON.stringify({
4449
4520
  ...result,
@@ -4465,7 +4536,6 @@ var runTests = async (tests, filters = []) => {
4465
4536
  };
4466
4537
 
4467
4538
  // src/cli/command/deploy.ts
4468
- import { minutes as minutes5 } from "@awsless/duration";
4469
4539
  var deploy = (program2) => {
4470
4540
  program2.command("deploy").argument("[stacks...]", "Optionally filter stacks to deploy").description("Deploy your app to AWS").action(async (filters) => {
4471
4541
  await layout("deploy", async ({ appConfig, stackConfigs }) => {
@@ -4492,20 +4562,13 @@ var deploy = (program2) => {
4492
4562
  throw new Cancelled();
4493
4563
  }
4494
4564
  await buildAssets(builders);
4495
- const workspace = new WorkSpace2({
4496
- stateProvider: new aws19.dynamodb.StateProvider({
4497
- credentials,
4498
- region,
4499
- tableName: "awsless-state"
4500
- }),
4501
- cloudProviders: aws19.createCloudProviders({
4502
- credentials,
4503
- region: appConfig.region,
4504
- timeout: minutes5(60)
4505
- })
4565
+ const { workspace, stateProvider } = createWorkSpace({
4566
+ credentials,
4567
+ region
4506
4568
  });
4507
4569
  await task("Deploying the stacks to AWS", async (update) => {
4508
4570
  await workspace.deployApp(app);
4571
+ await pullRemoteState(app, stateProvider);
4509
4572
  update("Done deploying the stacks to AWS.");
4510
4573
  });
4511
4574
  return "Your app is ready!";
@@ -4514,7 +4577,7 @@ var deploy = (program2) => {
4514
4577
  };
4515
4578
 
4516
4579
  // src/cli/command/diff.ts
4517
- import { WorkSpace as WorkSpace3, aws as aws20 } from "@awsless/formation";
4580
+ import { WorkSpace as WorkSpace2, aws as aws19 } from "@awsless/formation";
4518
4581
  import chalk7 from "chalk";
4519
4582
  var diff = (program2) => {
4520
4583
  program2.command("diff").description("Diff your app with AWS").action(async (filters) => {
@@ -4525,13 +4588,13 @@ var diff = (program2) => {
4525
4588
  await bootstrapAwsless({ credentials, region });
4526
4589
  const { app, builders } = createApp({ appConfig, stackConfigs, accountId }, filters);
4527
4590
  await buildAssets(builders);
4528
- const workspace = new WorkSpace3({
4529
- stateProvider: new aws20.dynamodb.DynamoDBStateProvider({
4591
+ const workspace = new WorkSpace2({
4592
+ stateProvider: new aws19.dynamodb.DynamoDBStateProvider({
4530
4593
  credentials,
4531
4594
  region,
4532
4595
  tableName: "awsless-state"
4533
4596
  }),
4534
- cloudProviders: aws20.createCloudProviders({
4597
+ cloudProviders: aws19.createCloudProviders({
4535
4598
  credentials,
4536
4599
  region: appConfig.region
4537
4600
  })
@@ -4586,8 +4649,8 @@ var diff = (program2) => {
4586
4649
  import { log as log9 } from "@clack/prompts";
4587
4650
 
4588
4651
  // src/type-gen/generate.ts
4589
- import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
4590
- import { dirname as dirname8, join as join10, relative as relative4 } from "path";
4652
+ import { mkdir as mkdir4, writeFile as writeFile4 } from "fs/promises";
4653
+ import { dirname as dirname9, join as join11, relative as relative4 } from "path";
4591
4654
  var generateTypes = async (props) => {
4592
4655
  const files = [];
4593
4656
  await Promise.all(
@@ -4596,13 +4659,13 @@ var generateTypes = async (props) => {
4596
4659
  ...props,
4597
4660
  async write(file, data, include = false) {
4598
4661
  const code = data?.toString("utf8");
4599
- const path = join10(directories.types, file);
4662
+ const path = join11(directories.types, file);
4600
4663
  if (code) {
4601
4664
  if (include) {
4602
4665
  files.push(relative4(directories.root, path));
4603
4666
  }
4604
- await mkdir3(dirname8(path), { recursive: true });
4605
- await writeFile3(path, code);
4667
+ await mkdir4(dirname9(path), { recursive: true });
4668
+ await writeFile4(path, code);
4606
4669
  }
4607
4670
  }
4608
4671
  });
@@ -4610,7 +4673,7 @@ var generateTypes = async (props) => {
4610
4673
  );
4611
4674
  if (files.length) {
4612
4675
  const code = files.map((file) => `/// <reference path='${file}' />`).join("\n");
4613
- await writeFile3(join10(directories.root, `awsless.d.ts`), code);
4676
+ await writeFile4(join11(directories.root, `awsless.d.ts`), code);
4614
4677
  }
4615
4678
  };
4616
4679
 
@@ -4736,8 +4799,53 @@ var dev = (program2) => {
4736
4799
  });
4737
4800
  };
4738
4801
 
4802
+ // src/cli/command/state/pull.ts
4803
+ var pull = (program2) => {
4804
+ program2.command("pull").description("Pull the remote state and store it locally").action(async () => {
4805
+ await layout("state pull", async ({ appConfig, stackConfigs }) => {
4806
+ const region = appConfig.region;
4807
+ const credentials = getCredentials(appConfig.profile);
4808
+ const accountId = await getAccountId(credentials, region);
4809
+ const { app } = createApp({ appConfig, stackConfigs, accountId });
4810
+ const { stateProvider } = createWorkSpace({ credentials, region });
4811
+ await pullRemoteState(app, stateProvider);
4812
+ return "State pull was successful.";
4813
+ });
4814
+ });
4815
+ };
4816
+
4817
+ // src/cli/command/state/push.ts
4818
+ import { confirm as confirm5 } from "@clack/prompts";
4819
+ var push = (program2) => {
4820
+ program2.command("push").description("Push the local state to the remote server").action(async () => {
4821
+ await layout("state pull", async ({ appConfig, stackConfigs }) => {
4822
+ const region = appConfig.region;
4823
+ const credentials = getCredentials(appConfig.profile);
4824
+ const accountId = await getAccountId(credentials, region);
4825
+ const { app } = createApp({ appConfig, stackConfigs, accountId });
4826
+ const { stateProvider } = createWorkSpace({ credentials, region });
4827
+ const ok = await confirm5({
4828
+ message: "Pushing up the local state might corrupt your remote state. Are you sure?",
4829
+ initialValue: false
4830
+ });
4831
+ if (!ok) {
4832
+ throw new Cancelled();
4833
+ }
4834
+ await pushRemoteState(app, stateProvider);
4835
+ return "State push was successful.";
4836
+ });
4837
+ });
4838
+ };
4839
+
4840
+ // src/cli/command/state/index.ts
4841
+ var commands3 = [pull, push];
4842
+ var state = (program2) => {
4843
+ const command = program2.command("state").description(`Manage app state`);
4844
+ commands3.forEach((cb) => cb(command));
4845
+ };
4846
+
4739
4847
  // src/cli/command/index.ts
4740
- var commands3 = [
4848
+ var commands4 = [
4741
4849
  bootstrap,
4742
4850
  types,
4743
4851
  build2,
@@ -4746,6 +4854,7 @@ var commands3 = [
4746
4854
  del2,
4747
4855
  dev,
4748
4856
  // bind,
4857
+ state,
4749
4858
  resource,
4750
4859
  config,
4751
4860
  test
@@ -4771,7 +4880,7 @@ program.on("option:skip-prompt", () => {
4771
4880
  program.on("option:no-cache", () => {
4772
4881
  process.env.NO_CACHE = program.opts().noCache ? "1" : void 0;
4773
4882
  });
4774
- commands3.forEach((fn) => fn(program));
4883
+ commands4.forEach((fn) => fn(program));
4775
4884
 
4776
4885
  // src/bin.ts
4777
4886
  program.parse(process.argv);
@@ -42,6 +42,9 @@ var directories = {
42
42
  get cache() {
43
43
  return join(this.output, "cache");
44
44
  },
45
+ get state() {
46
+ return join(this.output, "state");
47
+ },
45
48
  get build() {
46
49
  return join(this.output, "build");
47
50
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awsless/awsless",
3
- "version": "0.0.189",
3
+ "version": "0.0.190",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -28,13 +28,13 @@
28
28
  }
29
29
  },
30
30
  "peerDependencies": {
31
- "@awsless/lambda": "^0.0.18",
32
31
  "@awsless/redis": "^0.0.12",
33
32
  "@awsless/s3": "^0.0.10",
33
+ "@awsless/lambda": "^0.0.18",
34
+ "@awsless/sns": "^0.0.7",
34
35
  "@awsless/sqs": "^0.0.7",
35
- "@awsless/validate": "^0.0.13",
36
36
  "@awsless/ssm": "^0.0.7",
37
- "@awsless/sns": "^0.0.7",
37
+ "@awsless/validate": "^0.0.13",
38
38
  "@awsless/weak-cache": "^0.0.1"
39
39
  },
40
40
  "dependencies": {
@@ -96,12 +96,12 @@
96
96
  "wrap-ansi": "^8.1.0",
97
97
  "zod": "^3.21.4",
98
98
  "zod-to-json-schema": "^3.22.3",
99
- "@awsless/code": "^0.0.10",
100
99
  "@awsless/duration": "^0.0.1",
101
- "@awsless/graphql": "^0.0.9",
102
- "@awsless/formation": "^0.0.12",
100
+ "@awsless/formation": "^0.0.13",
103
101
  "@awsless/size": "^0.0.1",
104
- "@awsless/validate": "^0.0.13"
102
+ "@awsless/validate": "^0.0.13",
103
+ "@awsless/graphql": "^0.0.9",
104
+ "@awsless/code": "^0.0.10"
105
105
  },
106
106
  "scripts": {
107
107
  "test": "pnpm code test",