@awsless/awsless 0.0.270 → 0.0.272

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 +228 -228
  2. package/package.json +6 -6
package/dist/bin.js CHANGED
@@ -45,6 +45,215 @@ var logo = () => {
45
45
  return `${color.primary`AWS`}${color.primary.dim`LESS`}`;
46
46
  };
47
47
 
48
+ // src/util/aws.ts
49
+ import { GetCallerIdentityCommand, STSClient } from "@aws-sdk/client-sts";
50
+ import { fromIni } from "@aws-sdk/credential-providers";
51
+ var getCredentials = (profile) => {
52
+ return fromIni({ profile });
53
+ };
54
+ var getAccountId = async (credentials, region) => {
55
+ const client = new STSClient({ credentials, region });
56
+ const result = await client.send(new GetCallerIdentityCommand({}));
57
+ return result.Account;
58
+ };
59
+
60
+ // src/cli/ui/complex/bootstrap-awsless.ts
61
+ import {
62
+ BillingMode,
63
+ CreateTableCommand,
64
+ DescribeTableCommand,
65
+ DynamoDB,
66
+ KeyType,
67
+ ResourceNotFoundException,
68
+ ScalarAttributeType
69
+ } from "@aws-sdk/client-dynamodb";
70
+ import { CreateBucketCommand, HeadBucketCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
71
+ import { confirm, log } from "@clack/prompts";
72
+
73
+ // src/error.ts
74
+ var ConfigError = class extends Error {
75
+ constructor(file, error, data) {
76
+ super(error.message);
77
+ this.file = file;
78
+ this.error = error;
79
+ this.data = data;
80
+ }
81
+ };
82
+ var FileError = class extends Error {
83
+ constructor(file, message) {
84
+ super(message);
85
+ this.file = file;
86
+ }
87
+ };
88
+ var Cancelled = class extends Error {
89
+ constructor() {
90
+ super("Cancelled");
91
+ }
92
+ };
93
+
94
+ // src/cli/ui/util.ts
95
+ import wrapAnsi from "wrap-ansi";
96
+ import Table from "cli-table3";
97
+ import { capitalCase } from "change-case";
98
+ import { spinner } from "@clack/prompts";
99
+ var wrap = (lines, options) => {
100
+ return wrapAnsi(typeof lines === "string" ? lines : lines.join("\n"), process.stdout.columns - 8, options);
101
+ };
102
+ var padText = (texts) => {
103
+ const size = Math.max(...texts.map((text3) => text3.length));
104
+ return (text3, padding = 0, fill) => {
105
+ return text3.padEnd(size + padding, fill);
106
+ };
107
+ };
108
+ var task = async (message, cb) => {
109
+ let last = message;
110
+ const spin = spinner();
111
+ spin.start(last);
112
+ try {
113
+ const result = await cb((m) => {
114
+ spin.message(m);
115
+ last = m;
116
+ });
117
+ spin.stop(last);
118
+ return result;
119
+ } catch (error) {
120
+ spin.stop("Failed.", 2);
121
+ throw error;
122
+ }
123
+ };
124
+ var list = (data) => {
125
+ const padName = padText(Object.keys(data));
126
+ return Object.entries(data).map(([name, value]) => [color.label(padName(name + ":", 2)), value].join("")).join(char.br);
127
+ };
128
+ var table = (props) => {
129
+ console.log(color.line("\u2502"));
130
+ const table2 = new Table({
131
+ // wordWrap: true,
132
+ // wrapOnWordBoundary: false,
133
+ // truncate: '...',
134
+ // colWidths: props.colWidths,
135
+ // head: props.head.map(h => color.label(capitalCase(h))),
136
+ head: props.head.map((h) => "\n" + color.label(capitalCase(h))),
137
+ // colWidths: [100, 200],
138
+ style: {
139
+ "padding-left": 2,
140
+ "padding-right": 2
141
+ },
142
+ chars: {
143
+ "bottom-right": "\u256F",
144
+ "top-right": "\u256E",
145
+ "top-left": "\u251C",
146
+ "bottom-left": "\u251C"
147
+ // mid: '',
148
+ // 'mid-mid': '',
149
+ // 'left-mid': '',
150
+ // 'right-mid': '',
151
+ }
152
+ });
153
+ table2.push(
154
+ ...props.body.map(
155
+ (row) => row.map((v) => {
156
+ if (typeof v === "boolean") {
157
+ return v ? color.success("yes") : color.error("no");
158
+ }
159
+ return v;
160
+ })
161
+ )
162
+ );
163
+ return table2.toString();
164
+ };
165
+
166
+ // src/cli/ui/complex/bootstrap-awsless.ts
167
+ var hasLockTable = async (client) => {
168
+ try {
169
+ const result = await client.send(
170
+ new DescribeTableCommand({
171
+ TableName: "awsless-locks"
172
+ })
173
+ );
174
+ return !!result.Table;
175
+ } catch (error) {
176
+ if (error instanceof ResourceNotFoundException) {
177
+ return false;
178
+ }
179
+ throw error;
180
+ }
181
+ };
182
+ var hasStateBucket = async (client, accountId) => {
183
+ try {
184
+ const result = await client.send(
185
+ new HeadBucketCommand({
186
+ Bucket: `awsless-state-${accountId}`
187
+ })
188
+ );
189
+ return !!result.BucketRegion;
190
+ } catch (error) {
191
+ console.log(error);
192
+ if (error instanceof S3ServiceException) {
193
+ return false;
194
+ }
195
+ throw error;
196
+ }
197
+ };
198
+ var createLockTable = (client) => {
199
+ return client.send(
200
+ new CreateTableCommand({
201
+ TableName: "awsless-locks",
202
+ BillingMode: BillingMode.PAY_PER_REQUEST,
203
+ KeySchema: [
204
+ {
205
+ AttributeName: "urn",
206
+ KeyType: KeyType.HASH
207
+ }
208
+ ],
209
+ AttributeDefinitions: [
210
+ {
211
+ AttributeName: "urn",
212
+ AttributeType: ScalarAttributeType.S
213
+ }
214
+ ]
215
+ })
216
+ );
217
+ };
218
+ var createStateBucket = (client) => {
219
+ return client.send(
220
+ new CreateBucketCommand({
221
+ Bucket: "awsless-state"
222
+ })
223
+ );
224
+ };
225
+ var bootstrapAwsless = async (props) => {
226
+ const dynamo = new DynamoDB(props);
227
+ const s3 = new S3Client(props);
228
+ const [table2, bucket] = await Promise.all([
229
+ //
230
+ hasLockTable(dynamo),
231
+ hasStateBucket(s3, props.accountId)
232
+ ]);
233
+ if (!table2 || !bucket) {
234
+ log.warn(`Your Awsless hasn't been bootstrapped yet.`);
235
+ if (!process.env.SKIP_PROMPT) {
236
+ const confirmed = await confirm({
237
+ message: "Would you like to bootstrap now?"
238
+ });
239
+ if (!confirmed) {
240
+ throw new Cancelled();
241
+ }
242
+ }
243
+ await task("Bootstrapping", async (update) => {
244
+ if (!table2) {
245
+ await createLockTable(dynamo);
246
+ }
247
+ if (!bucket) {
248
+ await createStateBucket(s3);
249
+ }
250
+ update("Done deploying the bootstrap stack");
251
+ });
252
+ } else {
253
+ log.step("Awsless has already been bootstrapped.");
254
+ }
255
+ };
256
+
48
257
  // src/cli/ui/complex/layout.ts
49
258
  import { intro, outro } from "@clack/prompts";
50
259
 
@@ -1200,29 +1409,6 @@ import { basename, dirname, extname, join as join3 } from "path";
1200
1409
  import { readFile } from "fs/promises";
1201
1410
  import JSON5 from "json5";
1202
1411
  import merge from "deepmerge";
1203
-
1204
- // src/error.ts
1205
- var ConfigError = class extends Error {
1206
- constructor(file, error, data) {
1207
- super(error.message);
1208
- this.file = file;
1209
- this.error = error;
1210
- this.data = data;
1211
- }
1212
- };
1213
- var FileError = class extends Error {
1214
- constructor(file, message) {
1215
- super(message);
1216
- this.file = file;
1217
- }
1218
- };
1219
- var Cancelled = class extends Error {
1220
- constructor() {
1221
- super("Cancelled");
1222
- }
1223
- };
1224
-
1225
- // src/config/load/read.ts
1226
1412
  var readConfig = async (file) => {
1227
1413
  try {
1228
1414
  const json4 = await readFile(file, "utf8");
@@ -1305,80 +1491,6 @@ var loadStackConfigs = async (options) => {
1305
1491
 
1306
1492
  // src/cli/ui/app.ts
1307
1493
  import { note } from "@clack/prompts";
1308
-
1309
- // src/cli/ui/util.ts
1310
- import wrapAnsi from "wrap-ansi";
1311
- import Table from "cli-table3";
1312
- import { capitalCase } from "change-case";
1313
- import { spinner } from "@clack/prompts";
1314
- var wrap = (lines, options) => {
1315
- return wrapAnsi(typeof lines === "string" ? lines : lines.join("\n"), process.stdout.columns - 8, options);
1316
- };
1317
- var padText = (texts) => {
1318
- const size = Math.max(...texts.map((text3) => text3.length));
1319
- return (text3, padding = 0, fill) => {
1320
- return text3.padEnd(size + padding, fill);
1321
- };
1322
- };
1323
- var task = async (message, cb) => {
1324
- let last = message;
1325
- const spin = spinner();
1326
- spin.start(last);
1327
- try {
1328
- const result = await cb((m) => {
1329
- spin.message(m);
1330
- last = m;
1331
- });
1332
- spin.stop(last);
1333
- return result;
1334
- } catch (error) {
1335
- spin.stop("Failed.", 2);
1336
- throw error;
1337
- }
1338
- };
1339
- var list = (data) => {
1340
- const padName = padText(Object.keys(data));
1341
- return Object.entries(data).map(([name, value]) => [color.label(padName(name + ":", 2)), value].join("")).join(char.br);
1342
- };
1343
- var table = (props) => {
1344
- console.log(color.line("\u2502"));
1345
- const table2 = new Table({
1346
- // wordWrap: true,
1347
- // wrapOnWordBoundary: false,
1348
- // truncate: '...',
1349
- // colWidths: props.colWidths,
1350
- // head: props.head.map(h => color.label(capitalCase(h))),
1351
- head: props.head.map((h) => "\n" + color.label(capitalCase(h))),
1352
- // colWidths: [100, 200],
1353
- style: {
1354
- "padding-left": 2,
1355
- "padding-right": 2
1356
- },
1357
- chars: {
1358
- "bottom-right": "\u256F",
1359
- "top-right": "\u256E",
1360
- "top-left": "\u251C",
1361
- "bottom-left": "\u251C"
1362
- // mid: '',
1363
- // 'mid-mid': '',
1364
- // 'left-mid': '',
1365
- // 'right-mid': '',
1366
- }
1367
- });
1368
- table2.push(
1369
- ...props.body.map(
1370
- (row) => row.map((v) => {
1371
- if (typeof v === "boolean") {
1372
- return v ? color.success("yes") : color.error("no");
1373
- }
1374
- return v;
1375
- })
1376
- )
1377
- );
1378
- return table2.toString();
1379
- };
1380
-
1381
- // src/cli/ui/app.ts
1382
1494
  var logApp = (app) => {
1383
1495
  note(
1384
1496
  wrap(
@@ -1393,7 +1505,7 @@ var logApp = (app) => {
1393
1505
  };
1394
1506
 
1395
1507
  // src/cli/ui/error/error.ts
1396
- import { log as log5 } from "@clack/prompts";
1508
+ import { log as log6 } from "@clack/prompts";
1397
1509
 
1398
1510
  // src/cli/ui/error/config-error.ts
1399
1511
  import * as p from "@clack/prompts";
@@ -1483,7 +1595,7 @@ import { AppError as AppError2, StackError as StackError3 } from "@awsless/forma
1483
1595
 
1484
1596
  // src/cli/ui/error/stack-error.ts
1485
1597
  import { ResourceError } from "@awsless/formation";
1486
- import { log as log2 } from "@clack/prompts";
1598
+ import { log as log3 } from "@clack/prompts";
1487
1599
  import { capitalCase as capitalCase2 } from "change-case";
1488
1600
  var formatOperation = (operation) => {
1489
1601
  const value = ` ${capitalCase2(operation)} `;
@@ -1501,7 +1613,7 @@ var formatOperation = (operation) => {
1501
1613
  }
1502
1614
  };
1503
1615
  var logStackError = (error) => {
1504
- log2.message(
1616
+ log3.message(
1505
1617
  wrap([color.error(error.message), `Stack: ${error.stack}`].join("\n"), {
1506
1618
  hard: true
1507
1619
  }),
@@ -1509,7 +1621,7 @@ var logStackError = (error) => {
1509
1621
  );
1510
1622
  for (const issue of error.issues) {
1511
1623
  if (issue instanceof ResourceError) {
1512
- log2.message(
1624
+ log3.message(
1513
1625
  [
1514
1626
  formatOperation(issue.operation),
1515
1627
  "\n",
@@ -1523,7 +1635,7 @@ var logStackError = (error) => {
1523
1635
  { symbol: color.error(icon.error) }
1524
1636
  );
1525
1637
  } else if (issue instanceof Error) {
1526
- log2.message(wrap(color.error(issue.message), { hard: true }), {
1638
+ log3.message(wrap(color.error(issue.message), { hard: true }), {
1527
1639
  symbol: color.error(icon.error)
1528
1640
  });
1529
1641
  }
@@ -1531,9 +1643,9 @@ var logStackError = (error) => {
1531
1643
  };
1532
1644
 
1533
1645
  // src/cli/ui/error/file-error.ts
1534
- import { log as log3 } from "@clack/prompts";
1646
+ import { log as log4 } from "@clack/prompts";
1535
1647
  var logFileError = (error) => {
1536
- log3.message(
1648
+ log4.message(
1537
1649
  wrap([color.error(error.message), color.dim(error.file)].join("\n"), {
1538
1650
  hard: true
1539
1651
  }),
@@ -1543,9 +1655,9 @@ var logFileError = (error) => {
1543
1655
 
1544
1656
  // src/cli/ui/error/app-error.ts
1545
1657
  import { StackError as StackError2 } from "@awsless/formation";
1546
- import { log as log4 } from "@clack/prompts";
1658
+ import { log as log5 } from "@clack/prompts";
1547
1659
  var logAppError = (error) => {
1548
- log4.message(
1660
+ log5.message(
1549
1661
  wrap([color.error(error.message), `App: ${error.app}`].join("\n"), {
1550
1662
  hard: true
1551
1663
  }),
@@ -1555,7 +1667,7 @@ var logAppError = (error) => {
1555
1667
  if (issue instanceof StackError2) {
1556
1668
  logStackError(issue);
1557
1669
  } else if (issue instanceof Error) {
1558
- log4.message(wrap(color.error(issue.message), { hard: true }), {
1670
+ log5.message(wrap(color.error(issue.message), { hard: true }), {
1559
1671
  symbol: color.error(icon.error)
1560
1672
  });
1561
1673
  }
@@ -1567,7 +1679,7 @@ var logError = (error) => {
1567
1679
  if (error instanceof ConfigError) {
1568
1680
  logConfigError(error);
1569
1681
  } else if (error instanceof Cancelled) {
1570
- log5.message(color.error("Cancelled."), {
1682
+ log6.message(color.error("Cancelled."), {
1571
1683
  symbol: color.error(icon.error)
1572
1684
  });
1573
1685
  } else if (error instanceof AppError2) {
@@ -1579,18 +1691,18 @@ var logError = (error) => {
1579
1691
  } else if (error instanceof Error) {
1580
1692
  const message = `${error.name}: ${error.message}`;
1581
1693
  const stack = error.stack ? color.dim(error.stack.replace(message, "")) : "";
1582
- log5.message(
1694
+ log6.message(
1583
1695
  wrap([color.error(message), stack], {
1584
1696
  hard: true
1585
1697
  }),
1586
1698
  { symbol: color.error(icon.error) }
1587
1699
  );
1588
1700
  } else if (typeof error === "string") {
1589
- log5.message(wrap(color.error(error)), {
1701
+ log6.message(wrap(color.error(error)), {
1590
1702
  symbol: color.error(icon.error)
1591
1703
  });
1592
1704
  } else {
1593
- log5.message(wrap(color.error("Unknown error!")), {
1705
+ log6.message(wrap(color.error("Unknown error!")), {
1594
1706
  symbol: color.error(icon.error)
1595
1707
  });
1596
1708
  }
@@ -1617,128 +1729,16 @@ var layout = async (command, cb) => {
1617
1729
  }
1618
1730
  };
1619
1731
 
1620
- // src/cli/ui/complex/bootstrap-awsless.ts
1621
- import {
1622
- BillingMode,
1623
- CreateTableCommand,
1624
- DescribeTableCommand,
1625
- DynamoDB,
1626
- KeyType,
1627
- ResourceNotFoundException,
1628
- ScalarAttributeType
1629
- } from "@aws-sdk/client-dynamodb";
1630
- import { confirm, log as log6 } from "@clack/prompts";
1631
- import { CreateBucketCommand, HeadBucketCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
1632
- var hasLockTable = async (client) => {
1633
- try {
1634
- const result = await client.send(
1635
- new DescribeTableCommand({
1636
- TableName: "awsless-locks"
1637
- })
1638
- );
1639
- return !!result.Table;
1640
- } catch (error) {
1641
- if (error instanceof ResourceNotFoundException) {
1642
- return false;
1643
- }
1644
- throw error;
1645
- }
1646
- };
1647
- var hasStateBucket = async (client) => {
1648
- try {
1649
- const result = await client.send(
1650
- new HeadBucketCommand({
1651
- Bucket: "awsless-state"
1652
- })
1653
- );
1654
- return !!result.BucketRegion;
1655
- } catch (error) {
1656
- console.log(error);
1657
- if (error instanceof S3ServiceException) {
1658
- return false;
1659
- }
1660
- throw error;
1661
- }
1662
- };
1663
- var createLockTable = (client) => {
1664
- return client.send(
1665
- new CreateTableCommand({
1666
- TableName: "awsless-locks",
1667
- BillingMode: BillingMode.PAY_PER_REQUEST,
1668
- KeySchema: [
1669
- {
1670
- AttributeName: "urn",
1671
- KeyType: KeyType.HASH
1672
- }
1673
- ],
1674
- AttributeDefinitions: [
1675
- {
1676
- AttributeName: "urn",
1677
- AttributeType: ScalarAttributeType.S
1678
- }
1679
- ]
1680
- })
1681
- );
1682
- };
1683
- var createStateBucket = (client) => {
1684
- return client.send(
1685
- new CreateBucketCommand({
1686
- Bucket: "awsless-state"
1687
- })
1688
- );
1689
- };
1690
- var bootstrapAwsless = async (props) => {
1691
- const dynamo = new DynamoDB(props);
1692
- const s3 = new S3Client(props);
1693
- const [table2, bucket] = await Promise.all([
1694
- //
1695
- hasLockTable(dynamo),
1696
- hasStateBucket(s3)
1697
- ]);
1698
- if (!table2 || !bucket) {
1699
- log6.warn(`Your Awsless hasn't been bootstrapped yet.`);
1700
- if (!process.env.SKIP_PROMPT) {
1701
- const confirmed = await confirm({
1702
- message: "Would you like to bootstrap now?"
1703
- });
1704
- if (!confirmed) {
1705
- throw new Cancelled();
1706
- }
1707
- }
1708
- await task("Bootstrapping", async (update) => {
1709
- if (!table2) {
1710
- await createLockTable(dynamo);
1711
- }
1712
- if (!bucket) {
1713
- await createStateBucket(s3);
1714
- }
1715
- update("Done deploying the bootstrap stack");
1716
- });
1717
- } else {
1718
- log6.step("Awsless has already been bootstrapped.");
1719
- }
1720
- };
1721
-
1722
- // src/util/aws.ts
1723
- import { GetCallerIdentityCommand, STSClient } from "@aws-sdk/client-sts";
1724
- import { fromIni } from "@aws-sdk/credential-providers";
1725
- var getCredentials = (profile) => {
1726
- return fromIni({ profile });
1727
- };
1728
- var getAccountId = async (credentials, region) => {
1729
- const client = new STSClient({ credentials, region });
1730
- const result = await client.send(new GetCallerIdentityCommand({}));
1731
- return result.Account;
1732
- };
1733
-
1734
1732
  // src/cli/command/bootstrap.ts
1735
1733
  var bootstrap = (program2) => {
1736
1734
  program2.command("bootstrap").description("Create the awsless bootstrap stack").action(async () => {
1737
1735
  await layout("bootstrap", async ({ appConfig }) => {
1738
1736
  const credentials = getCredentials(appConfig.profile);
1737
+ const accountId = await getAccountId(credentials, appConfig.region);
1739
1738
  await bootstrapAwsless({
1740
1739
  credentials,
1741
- region: appConfig.region
1740
+ region: appConfig.region,
1741
+ accountId
1742
1742
  });
1743
1743
  return "Ready to go!";
1744
1744
  });
@@ -4933,7 +4933,7 @@ var createWorkSpace = (props) => {
4933
4933
  });
4934
4934
  const stateProvider = new aws22.s3.StateProvider({
4935
4935
  ...props,
4936
- bucket: "awsless-state"
4936
+ bucket: `awsless-state-${props.accountId}`
4937
4937
  });
4938
4938
  const cloudProviders = aws22.createCloudProviders({
4939
4939
  ...props,
@@ -5278,7 +5278,7 @@ var deploy = (program2) => {
5278
5278
  const region = appConfig.region;
5279
5279
  const credentials = getCredentials(appConfig.profile);
5280
5280
  const accountId = await getAccountId(credentials, region);
5281
- await bootstrapAwsless({ credentials, region });
5281
+ await bootstrapAwsless({ credentials, region, accountId });
5282
5282
  const { app, tests, builders } = createApp({ appConfig, stackConfigs, accountId }, filters);
5283
5283
  const stackNames = [...app.stacks].map((stack) => stack.name);
5284
5284
  const formattedFilter = stackNames.map((i) => color.info(i)).join(color.dim(", "));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awsless/awsless",
3
- "version": "0.0.270",
3
+ "version": "0.0.272",
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.19",
32
31
  "@awsless/open-search": "^0.0.12",
33
- "@awsless/redis": "^0.0.12",
32
+ "@awsless/lambda": "^0.0.19",
34
33
  "@awsless/s3": "^0.0.15",
34
+ "@awsless/redis": "^0.0.12",
35
+ "@awsless/sqs": "^0.0.7",
35
36
  "@awsless/sns": "^0.0.7",
36
37
  "@awsless/ssm": "^0.0.7",
37
- "@awsless/sqs": "^0.0.7",
38
38
  "@awsless/validate": "^0.0.14",
39
39
  "@awsless/weak-cache": "^0.0.1"
40
40
  },
@@ -102,11 +102,11 @@
102
102
  "zip-a-folder": "^3.1.6",
103
103
  "zod": "^3.21.4",
104
104
  "zod-to-json-schema": "^3.22.3",
105
- "@awsless/duration": "^0.0.1",
106
- "@awsless/formation": "^0.0.36",
107
105
  "@awsless/graphql": "^0.0.9",
108
106
  "@awsless/size": "^0.0.1",
107
+ "@awsless/formation": "^0.0.36",
109
108
  "@awsless/validate": "^0.0.14",
109
+ "@awsless/duration": "^0.0.1",
110
110
  "@awsless/code": "^0.0.10"
111
111
  },
112
112
  "scripts": {