sst 2.0.0-rc.35 → 2.0.0-rc.37

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 (45) hide show
  1. package/bootstrap.d.ts +5 -4
  2. package/bootstrap.js +57 -19
  3. package/cdk/cloudformation-deployments-wrapper.d.ts +2 -0
  4. package/cdk/cloudformation-deployments-wrapper.js +25 -0
  5. package/cdk/cloudformation-deployments.d.ts +18 -3
  6. package/cli/commands/bind.d.ts +2 -0
  7. package/cli/commands/build.d.ts +2 -0
  8. package/cli/commands/console.d.ts +2 -0
  9. package/cli/commands/deploy.d.ts +2 -0
  10. package/cli/commands/deploy.js +5 -3
  11. package/cli/commands/dev.d.ts +2 -0
  12. package/cli/commands/dev.js +1 -1
  13. package/cli/commands/diff.d.ts +2 -0
  14. package/cli/commands/env.d.ts +2 -0
  15. package/cli/commands/remove.d.ts +2 -0
  16. package/cli/commands/remove.js +2 -3
  17. package/cli/commands/secrets/get.d.ts +2 -0
  18. package/cli/commands/secrets/list.d.ts +2 -0
  19. package/cli/commands/secrets/remove.d.ts +2 -0
  20. package/cli/commands/secrets/set.d.ts +2 -0
  21. package/cli/commands/update.d.ts +2 -0
  22. package/cli/commands/version.d.ts +2 -0
  23. package/cli/program.d.ts +2 -0
  24. package/cli/program.js +4 -0
  25. package/cli/sst.js +2 -2
  26. package/cli/ui/functions.js +4 -0
  27. package/config.d.ts +1 -1
  28. package/config.js +3 -3
  29. package/constructs/App.d.ts +0 -4
  30. package/constructs/App.js +2 -4
  31. package/credentials.js +1 -0
  32. package/package.json +2 -1
  33. package/project.d.ts +2 -0
  34. package/project.js +3 -0
  35. package/sst.mjs +2859 -2726
  36. package/stacks/assembly.d.ts +1 -0
  37. package/stacks/assembly.js +4 -0
  38. package/stacks/deploy.d.ts +1 -0
  39. package/stacks/deploy.js +19 -4
  40. package/stacks/index.d.ts +1 -0
  41. package/stacks/index.js +1 -0
  42. package/stacks/metadata.d.ts +2 -0
  43. package/stacks/remove.js +0 -4
  44. package/stacks/synth.js +1 -6
  45. package/support/bootstrap-metadata-function/index.mjs +68032 -30124
package/bootstrap.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export declare const useBootstrap: () => Promise<{
2
- version: never;
3
- bucket: never;
4
- }>;
1
+ export declare const useBootstrap: () => {
2
+ version: string;
3
+ bucket: string;
4
+ };
5
+ export declare function initBootstrap(): Promise<void>;
package/bootstrap.js CHANGED
@@ -12,19 +12,25 @@ import { BlockPublicAccess, Bucket, BucketEncryption, } from "aws-cdk-lib/aws-s3
12
12
  import { useProject } from "./project.js";
13
13
  import { createSpinner } from "./cli/spinner.js";
14
14
  import { Context } from "./context/context.js";
15
- import { useAWSClient } from "./credentials.js";
15
+ import { useAWSClient, useAWSCredentials, useSTSIdentity, } from "./credentials.js";
16
16
  import { VisibleError } from "./error.js";
17
17
  import { Logger } from "./logger.js";
18
18
  import { Stacks } from "./stacks/index.js";
19
+ import { spawnSync } from "child_process";
19
20
  const STACK_NAME = "SSTBootstrap";
20
21
  const OUTPUT_VERSION = "Version";
21
22
  const OUTPUT_BUCKET = "BucketName";
22
- const LATEST_VERSION = "4";
23
+ const LATEST_VERSION = "5";
23
24
  const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
24
- export const useBootstrap = Context.memo(async () => {
25
+ const BootstrapContext = Context.create();
26
+ export const useBootstrap = BootstrapContext.use;
27
+ export async function initBootstrap() {
25
28
  Logger.debug("Initializing bootstrap context");
26
- let status = await loadBootstrapStatus();
27
- if (!status || status.version !== LATEST_VERSION) {
29
+ await assertCDKToolkit();
30
+ const status = await (async () => {
31
+ const status = await load();
32
+ if (status && status.version === LATEST_VERSION)
33
+ return status;
28
34
  const project = useProject();
29
35
  const spinner = createSpinner("Deploying bootstrap stack, this only needs to happen once").start();
30
36
  // Create bootstrap stack
@@ -50,7 +56,7 @@ export const useBootstrap = Context.memo(async () => {
50
56
  const fn = new Function(stack, "MetadataHandler", {
51
57
  code: Code.fromAsset(path.resolve(__dirname, "support/bootstrap-metadata-function")),
52
58
  handler: "index.handler",
53
- runtime: Runtime.NODEJS_16_X,
59
+ runtime: Runtime.NODEJS_18_X,
54
60
  initialPolicy: [
55
61
  new PolicyStatement({
56
62
  actions: ["cloudformation:DescribeStacks"],
@@ -60,6 +66,10 @@ export const useBootstrap = Context.memo(async () => {
60
66
  actions: ["s3:PutObject", "s3:DeleteObject"],
61
67
  resources: [bucket.bucketArn + "/*"],
62
68
  }),
69
+ new PolicyStatement({
70
+ actions: ["iot:Publish"],
71
+ resources: [`arn:${stack.partition}:iot:${stack.region}:${stack.account}:topic//sst/*`],
72
+ }),
63
73
  ],
64
74
  });
65
75
  const queue = new Queue(stack, "MetadataQueue");
@@ -77,9 +87,9 @@ export const useBootstrap = Context.memo(async () => {
77
87
  "ROLLBACK_COMPLETE",
78
88
  "DELETE_COMPLETE",
79
89
  ],
80
- }
81
- }
82
- }
90
+ },
91
+ },
92
+ },
83
93
  });
84
94
  rule.addTarget(new SqsQueue(queue, {
85
95
  retryAttempts: 10,
@@ -95,15 +105,43 @@ export const useBootstrap = Context.memo(async () => {
95
105
  }
96
106
  spinner.succeed();
97
107
  // Fetch bootstrap status
98
- status = await loadBootstrapStatus();
99
- if (!status) {
100
- throw new VisibleError("Failed to deploy bootstrap stack");
101
- }
108
+ const ret = await load();
109
+ if (!ret)
110
+ throw new VisibleError("Failed to load bootstrap stack status");
111
+ return ret;
112
+ })();
113
+ BootstrapContext.provide(status);
114
+ Logger.debug("Bootstrap context initialized", status);
115
+ }
116
+ async function assertCDKToolkit() {
117
+ const client = useAWSClient(CloudFormationClient);
118
+ const { Stacks: stacks } = await client.send(new DescribeStacksCommand({
119
+ StackName: "CDKToolkit",
120
+ }));
121
+ if (!stacks || stacks.length === 0) {
122
+ const identity = await useSTSIdentity();
123
+ const credentials = await useAWSCredentials();
124
+ const project = useProject();
125
+ spawnSync([
126
+ "npx",
127
+ "cdk",
128
+ "bootstrap",
129
+ `aws://${identity.Account}/${useProject().config.region}`,
130
+ ].join(" "), {
131
+ env: {
132
+ ...process.env,
133
+ AWS_ACCESS_KEY_ID: credentials.accessKeyId,
134
+ AWS_SECRET_ACCESS_KEY: credentials.secretAccessKey,
135
+ AWS_SESSION_TOKEN: credentials.sessionToken,
136
+ AWS_REGION: project.config.region,
137
+ AWS_PROFILE: project.config.profile,
138
+ },
139
+ stdio: "inherit",
140
+ shell: process.env.SHELL || true,
141
+ });
102
142
  }
103
- Logger.debug("Loaded bootstrap info: ", JSON.stringify(status));
104
- return status;
105
- });
106
- async function loadBootstrapStatus() {
143
+ }
144
+ async function load() {
107
145
  // Get bootstrap CloudFormation stack
108
146
  const cf = useAWSClient(CloudFormationClient);
109
147
  let result;
@@ -113,8 +151,8 @@ async function loadBootstrapStatus() {
113
151
  }));
114
152
  }
115
153
  catch (e) {
116
- if (e.Code === "ValidationError"
117
- && e.message === `Stack with id ${STACK_NAME} does not exist`) {
154
+ if (e.Code === "ValidationError" &&
155
+ e.message === `Stack with id ${STACK_NAME} does not exist`) {
118
156
  return null;
119
157
  }
120
158
  throw e;
@@ -0,0 +1,2 @@
1
+ import { CloudFormationDeployments, DeployStackOptions } from "./cloudformation-deployments.js";
2
+ export declare function publishAssets(deployment: CloudFormationDeployments, options: DeployStackOptions): Promise<void>;
@@ -0,0 +1,25 @@
1
+ import { ToolkitInfo } from "aws-cdk/lib/api/toolkit-info.js";
2
+ import { Context } from "../context/context.js";
3
+ export async function publishAssets(deployment, options) {
4
+ const toolkitInfo = await useToolkitInfo().lookup(deployment, options);
5
+ await deployment.publishStackAssets(options.stack, toolkitInfo, {
6
+ buildAssets: options.buildAssets ?? true,
7
+ publishOptions: {
8
+ quiet: options.quiet,
9
+ parallel: options.assetParallelism,
10
+ },
11
+ });
12
+ }
13
+ const useToolkitInfo = Context.memo(() => {
14
+ const state = new Map();
15
+ return {
16
+ async lookup(deployment, options) {
17
+ if (state.has(deployment))
18
+ return state.get(deployment);
19
+ const { stackSdk, resolvedEnvironment } = await deployment.prepareSdkFor(options.stack, options.roleArn);
20
+ const toolkitInfo = await ToolkitInfo.lookup(resolvedEnvironment, stackSdk, options.toolkitStackName);
21
+ state.set(deployment, toolkitInfo);
22
+ return toolkitInfo;
23
+ }
24
+ };
25
+ });
@@ -1,9 +1,11 @@
1
1
  import * as cxapi from "@aws-cdk/cx-api";
2
2
  import { Tag } from "aws-cdk/lib/cdk-toolkit.js";
3
- import { BuildAssetsOptions } from "aws-cdk/lib/util/asset-publishing.js";
3
+ import { BuildAssetsOptions, PublishAssetsOptions } from "aws-cdk/lib/util/asset-publishing.js";
4
+ import { Mode } from "aws-cdk/lib/api/aws-auth/credentials.js";
4
5
  import { ISDK } from "aws-cdk/lib/api/aws-auth/sdk.js";
5
6
  import { SdkProvider } from "aws-cdk/lib/api/aws-auth/sdk-provider.js";
6
7
  import { DeployStackResult, DeploymentMethod } from "./deploy-stack.js";
8
+ import { ToolkitInfo } from "aws-cdk/lib/api/toolkit-info.js";
7
9
  import { Template, ResourcesToImport, ResourceIdentifierSummaries } from "aws-cdk/lib/api/util/cloudformation.js";
8
10
  import { StackActivityProgress } from "aws-cdk/lib/api/util/cloudformation/stack-activity-monitor.js";
9
11
  /**
@@ -203,6 +205,18 @@ export interface BuildStackAssetsOptions {
203
205
  */
204
206
  readonly buildOptions?: BuildAssetsOptions;
205
207
  }
208
+ interface PublishStackAssetsOptions {
209
+ /**
210
+ * Whether to build assets before publishing.
211
+ *
212
+ * @default true To remain backward compatible.
213
+ */
214
+ readonly buildAssets?: boolean;
215
+ /**
216
+ * Options to pass on to `publishAsests()` function
217
+ */
218
+ readonly publishOptions?: Omit<PublishAssetsOptions, "buildAssets">;
219
+ }
206
220
  export interface DestroyStackOptions {
207
221
  stack: cxapi.CloudFormationStackArtifact;
208
222
  deployName?: string;
@@ -264,7 +278,7 @@ export declare class CloudFormationDeployments {
264
278
  * - SDK loaded with the right credentials for calling `CreateChangeSet`.
265
279
  * - The Execution Role that should be passed to CloudFormation.
266
280
  */
267
- private prepareSdkFor;
281
+ prepareSdkFor(stack: cxapi.CloudFormationStackArtifact, roleArn?: string, mode?: Mode): Promise<PreparedSdkForEnvironment>;
268
282
  /**
269
283
  * Build a stack's assets.
270
284
  */
@@ -272,9 +286,10 @@ export declare class CloudFormationDeployments {
272
286
  /**
273
287
  * Publish all asset manifests that are referenced by the given stack
274
288
  */
275
- private publishStackAssets;
289
+ publishStackAssets(stack: cxapi.CloudFormationStackArtifact, toolkitInfo: ToolkitInfo, options?: PublishStackAssetsOptions): Promise<void>;
276
290
  /**
277
291
  * Validate that the bootstrap stack has the right version for this stack
278
292
  */
279
293
  private validateBootstrapStackVersion;
280
294
  }
295
+ export {};
@@ -8,6 +8,8 @@ export declare const bind: (program: Program) => import("yargs").Argv<{
8
8
  region: string | undefined;
9
9
  } & {
10
10
  verbose: boolean | undefined;
11
+ } & {
12
+ role: string | undefined;
11
13
  } & {
12
14
  command: string;
13
15
  }>;
@@ -8,6 +8,8 @@ export declare const build: (program: Program) => import("yargs").Argv<{
8
8
  region: string | undefined;
9
9
  } & {
10
10
  verbose: boolean | undefined;
11
+ } & {
12
+ role: string | undefined;
11
13
  } & {
12
14
  to: string | undefined;
13
15
  }>;
@@ -8,4 +8,6 @@ export declare const consoleCommand: (program: Program) => Promise<import("yargs
8
8
  region: string | undefined;
9
9
  } & {
10
10
  verbose: boolean | undefined;
11
+ } & {
12
+ role: string | undefined;
11
13
  }>>;
@@ -8,6 +8,8 @@ export declare const deploy: (program: Program) => import("yargs").Argv<{
8
8
  region: string | undefined;
9
9
  } & {
10
10
  verbose: boolean | undefined;
11
+ } & {
12
+ role: string | undefined;
11
13
  } & {
12
14
  from: string | undefined;
13
15
  } & {
@@ -10,10 +10,9 @@ export const deploy = (program) => program.command("deploy [filter]", "Deploy yo
10
10
  const React = await import("react");
11
11
  const { printDeploymentResults } = await import("../ui/deploy.js");
12
12
  const { createSpinner } = await import("../spinner.js");
13
- const { CloudAssembly } = await import("aws-cdk-lib/cx-api");
14
13
  const { dim, blue, bold } = await import("colorette");
15
14
  const { useProject } = await import("../../project.js");
16
- const { Stacks } = await import("../../stacks/index.js");
15
+ const { loadAssembly, Stacks } = await import("../../stacks/index.js");
17
16
  const { render } = await import("ink");
18
17
  const { DeploymentUI } = await import("../ui/deploy.js");
19
18
  const { Colors } = await import("../colors.js");
@@ -23,9 +22,12 @@ export const deploy = (program) => program.command("deploy [filter]", "Deploy yo
23
22
  console.log();
24
23
  console.log(` ${Colors.primary(`➜`)} ${bold(`Stage:`)} ${dim(project.config.stage)}`);
25
24
  console.log();
25
+ // Generate cloud assembly
26
+ // - if --from is specified, we will use the existing cloud assembly
27
+ // - if --from is not specified, we will call synth to generate
26
28
  const assembly = await (async function () {
27
29
  if (args.from) {
28
- const result = new CloudAssembly(args.from);
30
+ const result = await loadAssembly(args.from);
29
31
  return result;
30
32
  }
31
33
  const spinner = createSpinner({
@@ -8,4 +8,6 @@ export declare const dev: (program: Program) => import("yargs").Argv<{
8
8
  region: string | undefined;
9
9
  } & {
10
10
  verbose: boolean | undefined;
11
+ } & {
12
+ role: string | undefined;
11
13
  }>;
@@ -1,6 +1,5 @@
1
1
  import chalk from "chalk";
2
2
  import { Colors } from "../colors.js";
3
- import { Functions } from "../ui/functions.js";
4
3
  export const dev = (program) => program.command(["dev", "start"], "Work on your app locally", (yargs) => yargs, async (args) => {
5
4
  const { useRuntimeWorkers } = await import("../../runtime/workers.js");
6
5
  const { useIOTBridge } = await import("../../runtime/iot.js");
@@ -28,6 +27,7 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
28
27
  const { useRDSWarmer } = await import("./plugins/warmer.js");
29
28
  const { useProject } = await import("../../project.js");
30
29
  const { useMetadata } = await import("../../stacks/metadata.js");
30
+ const { Functions } = await import("../ui/functions.js");
31
31
  if (args._[0] === "start") {
32
32
  console.log(yellow(`Warning: ${bold(`sst start`)} has been renamed to ${bold(`sst dev`)}`));
33
33
  }
@@ -8,6 +8,8 @@ export declare const diff: (program: Program) => import("yargs").Argv<{
8
8
  region: string | undefined;
9
9
  } & {
10
10
  verbose: boolean | undefined;
11
+ } & {
12
+ role: string | undefined;
11
13
  } & {
12
14
  dev: boolean | undefined;
13
15
  }>;
@@ -8,6 +8,8 @@ export declare const env: (program: Program) => import("yargs").Argv<{
8
8
  region: string | undefined;
9
9
  } & {
10
10
  verbose: boolean | undefined;
11
+ } & {
12
+ role: string | undefined;
11
13
  } & {
12
14
  command: string;
13
15
  }>;
@@ -8,6 +8,8 @@ export declare const remove: (program: Program) => import("yargs").Argv<{
8
8
  region: string | undefined;
9
9
  } & {
10
10
  verbose: boolean | undefined;
11
+ } & {
12
+ role: string | undefined;
11
13
  } & {
12
14
  from: string | undefined;
13
15
  } & {
@@ -3,10 +3,9 @@ export const remove = (program) => program.command("remove [filter]", "Remove yo
3
3
  describe: "Optionally filter stacks to remove",
4
4
  }), async (args) => {
5
5
  const React = await import("react");
6
- const { CloudAssembly } = await import("aws-cdk-lib/cx-api");
7
6
  const { dim, blue, bold } = await import("colorette");
8
7
  const { useProject } = await import("../../project.js");
9
- const { Stacks } = await import("../../stacks/index.js");
8
+ const { loadAssembly, Stacks } = await import("../../stacks/index.js");
10
9
  const { render } = await import("ink");
11
10
  const { DeploymentUI } = await import("../ui/deploy.js");
12
11
  const { printDeploymentResults } = await import("../ui/deploy.js");
@@ -19,7 +18,7 @@ export const remove = (program) => program.command("remove [filter]", "Remove yo
19
18
  console.log();
20
19
  const assembly = await (async function () {
21
20
  if (args.from) {
22
- const result = new CloudAssembly(args.from);
21
+ const result = await loadAssembly(args.from);
23
22
  return result;
24
23
  }
25
24
  return await Stacks.synth({
@@ -8,6 +8,8 @@ export declare const get: (program: Program) => import("yargs").Argv<{
8
8
  region: string | undefined;
9
9
  } & {
10
10
  verbose: boolean | undefined;
11
+ } & {
12
+ role: string | undefined;
11
13
  } & {
12
14
  name: string;
13
15
  } & {
@@ -8,6 +8,8 @@ export declare const list: (program: Program) => import("yargs").Argv<{
8
8
  region: string | undefined;
9
9
  } & {
10
10
  verbose: boolean | undefined;
11
+ } & {
12
+ role: string | undefined;
11
13
  } & {
12
14
  format: string | undefined;
13
15
  }>;
@@ -8,6 +8,8 @@ export declare const remove: (program: Program) => import("yargs").Argv<{
8
8
  region: string | undefined;
9
9
  } & {
10
10
  verbose: boolean | undefined;
11
+ } & {
12
+ role: string | undefined;
11
13
  } & {
12
14
  name: string;
13
15
  } & {
@@ -8,6 +8,8 @@ export declare const set: (program: Program) => import("yargs").Argv<{
8
8
  region: string | undefined;
9
9
  } & {
10
10
  verbose: boolean | undefined;
11
+ } & {
12
+ role: string | undefined;
11
13
  } & {
12
14
  name: string;
13
15
  } & {
@@ -8,6 +8,8 @@ export declare const update: (program: Program) => import("yargs").Argv<{
8
8
  region: string | undefined;
9
9
  } & {
10
10
  verbose: boolean | undefined;
11
+ } & {
12
+ role: string | undefined;
11
13
  } & {
12
14
  version: string | undefined;
13
15
  }>;
@@ -8,6 +8,8 @@ export declare const env: (program: Program) => import("yargs").Argv<{
8
8
  region: string | undefined;
9
9
  } & {
10
10
  verbose: boolean | undefined;
11
+ } & {
12
+ role: string | undefined;
11
13
  } & {
12
14
  command: string;
13
15
  }>;
package/cli/program.d.ts CHANGED
@@ -7,5 +7,7 @@ export declare const program: import("yargs").Argv<{
7
7
  region: string | undefined;
8
8
  } & {
9
9
  verbose: boolean | undefined;
10
+ } & {
11
+ role: string | undefined;
10
12
  }>;
11
13
  export type Program = typeof program;
package/cli/program.js CHANGED
@@ -17,6 +17,10 @@ export const program = yargs(hideBin(process.argv))
17
17
  .option("verbose", {
18
18
  type: "boolean",
19
19
  describe: "Print verbose logs",
20
+ })
21
+ .option("role", {
22
+ type: "string",
23
+ describe: "ARN of the IAM role to use when invoking AWS",
20
24
  })
21
25
  .group(["stage", "profile", "region", "help"], "Global:")
22
26
  .middleware(async (argv) => {
package/cli/sst.js CHANGED
@@ -3,8 +3,9 @@ import { blue, red } from "colorette";
3
3
  import { program } from "./program.js";
4
4
  import { VisibleError } from "../error.js";
5
5
  import { useSpinners } from "./spinner.js";
6
- import dotenv from "dotenv";
7
6
  import { Logger } from "../logger.js";
7
+ import dotenv from "dotenv";
8
+ dotenv.config();
8
9
  import { env } from "./commands/env.js";
9
10
  import { dev } from "./commands/dev.js";
10
11
  import { bind } from "./commands/bind.js";
@@ -15,7 +16,6 @@ import { consoleCommand } from "./commands/console.js";
15
16
  import { secrets } from "./commands/secrets/secrets.js";
16
17
  import { update } from "./commands/update.js";
17
18
  import { diff } from "./commands/diff.js";
18
- dotenv.config();
19
19
  dev(program);
20
20
  deploy(program);
21
21
  build(program);
@@ -60,6 +60,8 @@ export function Functions() {
60
60
  }
61
61
  setFunctions((functions) => {
62
62
  const { [evt.properties.requestID]: existing, ...next } = functions;
63
+ if (!existing)
64
+ return functions;
63
65
  const diff = Date.now() - existing.started;
64
66
  if (diff > 500 && diff < 1500) {
65
67
  setTimeout(() => {
@@ -91,6 +93,8 @@ export function Functions() {
91
93
  }
92
94
  setFunctions((functions) => {
93
95
  const { [evt.properties.requestID]: existing, ...next } = functions;
96
+ if (!existing)
97
+ return functions;
94
98
  const diff = Date.now() - existing.started;
95
99
  if (diff > 500 && diff < 1500) {
96
100
  setTimeout(() => {
package/config.d.ts CHANGED
@@ -6,7 +6,7 @@ export declare namespace Config {
6
6
  function parameters(): Promise<({
7
7
  type: string;
8
8
  id: string;
9
- prop: string[];
9
+ prop: string;
10
10
  } & {
11
11
  value: string;
12
12
  })[]>;
package/config.js CHANGED
@@ -30,7 +30,7 @@ export var Config;
30
30
  }
31
31
  Config.parameters = parameters;
32
32
  function envFor(input) {
33
- return `SST_${input.type}_${input.prop}_${input.id}`;
33
+ return `SST_${input.type}_${input.prop}_${normalizeID(input.id)}`;
34
34
  }
35
35
  Config.envFor = envFor;
36
36
  function pathFor(input) {
@@ -64,7 +64,7 @@ export var Config;
64
64
  const env = {
65
65
  SST_APP: project.config.name,
66
66
  SST_STAGE: project.config.stage,
67
- ...pipe(parameters, map((p) => [`SST_${p.type}_${p.prop}_${p.id}`, p.value]), Object.fromEntries),
67
+ ...pipe(parameters, map((p) => [envFor(p), p.value]), Object.fromEntries),
68
68
  };
69
69
  return env;
70
70
  }
@@ -168,6 +168,6 @@ function parse(ssmName) {
168
168
  return {
169
169
  type: parts[4],
170
170
  id: parts[5],
171
- prop: parts.slice(6),
171
+ prop: parts.slice(6).join("/"),
172
172
  };
173
173
  }
@@ -7,7 +7,6 @@ import * as Config from "./Config.js";
7
7
  import { Permissions } from "./util/permission.js";
8
8
  import { StackProps } from "./Stack.js";
9
9
  import { FunctionalStack } from "./FunctionalStack.js";
10
- import { useBootstrap } from "../bootstrap.js";
11
10
  /**
12
11
  * @internal
13
12
  */
@@ -40,7 +39,6 @@ export interface AppDeployProps {
40
39
  readonly debugBridge?: string;
41
40
  readonly debugIncreaseTimeout?: boolean;
42
41
  readonly mode: "deploy" | "dev" | "remove";
43
- readonly bootstrap: Awaited<ReturnType<typeof useBootstrap>>;
44
42
  }
45
43
  type AppRemovalPolicy = Lowercase<keyof typeof cdk.RemovalPolicy>;
46
44
  export type AppProps = cdk.AppProps;
@@ -87,8 +85,6 @@ export declare class App extends cdk.App {
87
85
  /** @internal */
88
86
  readonly appPath: string;
89
87
  /** @internal */
90
- readonly bootstrap: AppDeployProps["bootstrap"];
91
- /** @internal */
92
88
  defaultFunctionProps: (FunctionProps | ((stack: cdk.Stack) => FunctionProps))[];
93
89
  private _defaultRemovalPolicy?;
94
90
  /** @internal */
package/constructs/App.js CHANGED
@@ -14,6 +14,7 @@ import { createRequire } from "module";
14
14
  import { Auth } from "./Auth.js";
15
15
  import { useDeferredTasks } from "./deferred_task.js";
16
16
  import { AppContext } from "./context.js";
17
+ import { useBootstrap } from "../bootstrap.js";
17
18
  import { useProject } from "../project.js";
18
19
  import { Logger } from "../logger.js";
19
20
  import { SiteEnv } from "../site-env.js";
@@ -65,8 +66,6 @@ export class App extends cdk.App {
65
66
  /** @internal */
66
67
  appPath;
67
68
  /** @internal */
68
- bootstrap;
69
- /** @internal */
70
69
  defaultFunctionProps;
71
70
  _defaultRemovalPolicy;
72
71
  /** @internal */
@@ -93,7 +92,6 @@ export class App extends cdk.App {
93
92
  super(props);
94
93
  AppContext.provide(this);
95
94
  SiteEnv.reset();
96
- this.bootstrap = deployProps.bootstrap;
97
95
  this.appPath = process.cwd();
98
96
  this.mode = deployProps.mode;
99
97
  this.local = this.mode === "dev";
@@ -309,7 +307,7 @@ export class App extends cdk.App {
309
307
  app: this.name,
310
308
  stage: this.stage,
311
309
  version: useProject().version,
312
- bootstrapBucket: this.bootstrap.bucket,
310
+ bootstrapBucket: useBootstrap().bucket,
313
311
  metadata: byStack[stackName] || [],
314
312
  }),
315
313
  });
package/credentials.js CHANGED
@@ -10,6 +10,7 @@ export const useAWSCredentialsProvider = Context.memo(() => {
10
10
  Logger.debug("Using AWS profile", project.config.profile);
11
11
  const provider = fromNodeProviderChain({
12
12
  profile: project.config.profile,
13
+ roleArn: project.config.role,
13
14
  });
14
15
  return provider;
15
16
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sst",
3
- "version": "2.0.0-rc.35",
3
+ "version": "2.0.0-rc.37",
4
4
  "bin": {
5
5
  "sst": "cli/sst.js"
6
6
  },
@@ -32,6 +32,7 @@
32
32
  "@aws-cdk/region-info": "2.55.0",
33
33
  "@aws-sdk/client-cloudformation": "3.208.0",
34
34
  "@aws-sdk/client-iot": "3.208.0",
35
+ "@aws-sdk/client-iot-data-plane": "3.208.0",
35
36
  "@aws-sdk/client-lambda": "3.208.0",
36
37
  "@aws-sdk/client-rds-data": "3.208.0",
37
38
  "@aws-sdk/client-s3": "3.208.0",
package/project.d.ts CHANGED
@@ -9,6 +9,7 @@ export interface ConfigOptions {
9
9
  region?: string;
10
10
  stage?: string;
11
11
  profile?: string;
12
+ role?: string;
12
13
  ssmPrefix?: string;
13
14
  }
14
15
  declare const DEFAULTS: {
@@ -36,6 +37,7 @@ export declare const ProjectContext: {
36
37
  export declare function useProject(): Project;
37
38
  interface GlobalOptions {
38
39
  profile?: string;
40
+ role?: string;
39
41
  stage?: string;
40
42
  root?: string;
41
43
  region?: string;
package/project.js CHANGED
@@ -64,6 +64,7 @@ export async function initProject(globals) {
64
64
  stage,
65
65
  profile: config.profile || globals.profile,
66
66
  region: config.region || globals.region,
67
+ role: config.role || globals.role,
67
68
  ssmPrefix: config.ssmPrefix || `/sst/${config.name}/${stage}/`,
68
69
  },
69
70
  stacks: sstConfig.stacks,
@@ -76,6 +77,8 @@ export async function initProject(globals) {
76
77
  },
77
78
  };
78
79
  ProjectContext.provide(project);
80
+ const { initBootstrap } = await import("./bootstrap.js");
81
+ await initBootstrap();
79
82
  dotenv.config({
80
83
  path: path.join(project.paths.root, `.env.${project.config.stage}`),
81
84
  });