sst 2.0.0-rc.37 → 2.0.0-rc.39

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/bootstrap.js CHANGED
@@ -68,7 +68,9 @@ export async function initBootstrap() {
68
68
  }),
69
69
  new PolicyStatement({
70
70
  actions: ["iot:Publish"],
71
- resources: [`arn:${stack.partition}:iot:${stack.region}:${stack.account}:topic//sst/*`],
71
+ resources: [
72
+ `arn:${stack.partition}:iot:${stack.region}:${stack.account}:topic//sst/*`,
73
+ ],
72
74
  }),
73
75
  ],
74
76
  });
@@ -1,2 +1,3 @@
1
- import { CloudFormationDeployments, DeployStackOptions } from "./cloudformation-deployments.js";
2
- export declare function publishAssets(deployment: CloudFormationDeployments, options: DeployStackOptions): Promise<void>;
1
+ import { SdkProvider } from "aws-cdk/lib/api/aws-auth/sdk-provider.js";
2
+ import { DeployStackOptions as PublishStackAssetsOptions } from "./cloudformation-deployments.js";
3
+ export declare function publishDeployAssets(sdkProvider: SdkProvider, options: PublishStackAssetsOptions): Promise<any>;
@@ -1,7 +1,14 @@
1
+ import { debug } from "aws-cdk/lib/logging.js";
2
+ import { CloudFormationStack, TemplateParameters, waitForStackDelete, } from "aws-cdk/lib/api/util/cloudformation.js";
1
3
  import { ToolkitInfo } from "aws-cdk/lib/api/toolkit-info.js";
4
+ import { addMetadataAssetsToManifest } from "aws-cdk/lib/assets.js";
5
+ import { publishAssets } from "aws-cdk/lib/util/asset-publishing.js";
6
+ import { AssetManifestBuilder } from "aws-cdk/lib/util/asset-manifest-builder.js";
7
+ import { CloudFormationDeployments, } from "./cloudformation-deployments.js";
8
+ import { makeBodyParameter } from "./deploy-stack.js";
2
9
  import { Context } from "../context/context.js";
3
- export async function publishAssets(deployment, options) {
4
- const toolkitInfo = await useToolkitInfo().lookup(deployment, options);
10
+ export async function publishDeployAssets(sdkProvider, options) {
11
+ const { deployment, toolkitInfo, stackSdk, resolvedEnvironment, cloudFormationRoleArn, } = await useDeployment().get(sdkProvider, options);
5
12
  await deployment.publishStackAssets(options.stack, toolkitInfo, {
6
13
  buildAssets: options.buildAssets ?? true,
7
14
  publishOptions: {
@@ -9,17 +16,97 @@ export async function publishAssets(deployment, options) {
9
16
  parallel: options.assetParallelism,
10
17
  },
11
18
  });
19
+ return deployStack({
20
+ stack: options.stack,
21
+ noMonitor: true,
22
+ resolvedEnvironment,
23
+ deployName: options.deployName,
24
+ notificationArns: options.notificationArns,
25
+ quiet: options.quiet,
26
+ sdk: stackSdk,
27
+ sdkProvider,
28
+ roleArn: cloudFormationRoleArn,
29
+ reuseAssets: options.reuseAssets,
30
+ toolkitInfo,
31
+ tags: options.tags,
32
+ deploymentMethod: options.deploymentMethod,
33
+ force: options.force,
34
+ parameters: options.parameters,
35
+ usePreviousParameters: options.usePreviousParameters,
36
+ progress: options.progress,
37
+ ci: options.ci,
38
+ rollback: options.rollback,
39
+ hotswap: options.hotswap,
40
+ extraUserAgent: options.extraUserAgent,
41
+ resourcesToImport: options.resourcesToImport,
42
+ overrideTemplate: options.overrideTemplate,
43
+ assetParallelism: options.assetParallelism,
44
+ });
12
45
  }
13
- const useToolkitInfo = Context.memo(() => {
46
+ const useDeployment = Context.memo(() => {
14
47
  const state = new Map();
15
48
  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;
49
+ async get(sdkProvider, options) {
50
+ if (!state.has(sdkProvider)) {
51
+ const deployment = new CloudFormationDeployments({ sdkProvider });
52
+ const { stackSdk, resolvedEnvironment, cloudFormationRoleArn } = await deployment.prepareSdkFor(options.stack, options.roleArn);
53
+ const toolkitInfo = await ToolkitInfo.lookup(resolvedEnvironment, stackSdk, options.toolkitStackName);
54
+ // Do a verification of the bootstrap stack version
55
+ await deployment.validateBootstrapStackVersion(options.stack.stackName, options.stack.requiresBootstrapStackVersion, options.stack.bootstrapStackVersionSsmParameter, toolkitInfo);
56
+ state.set(sdkProvider, {
57
+ deployment,
58
+ toolkitInfo,
59
+ stackSdk,
60
+ resolvedEnvironment,
61
+ cloudFormationRoleArn,
62
+ });
63
+ }
64
+ return state.get(sdkProvider);
23
65
  }
24
66
  };
25
67
  });
68
+ async function deployStack(options) {
69
+ const stackArtifact = options.stack;
70
+ const stackEnv = options.resolvedEnvironment;
71
+ options.sdk.appendCustomUserAgent(options.extraUserAgent);
72
+ const cfn = options.sdk.cloudFormation();
73
+ const deployName = options.deployName || stackArtifact.stackName;
74
+ let cloudFormationStack = await CloudFormationStack.lookup(cfn, deployName);
75
+ if (cloudFormationStack.stackStatus.isCreationFailure) {
76
+ debug(`Found existing stack ${deployName} that had previously failed creation. Deleting it before attempting to re-create it.`);
77
+ await cfn.deleteStack({ StackName: deployName }).promise();
78
+ const deletedStack = await waitForStackDelete(cfn, deployName);
79
+ if (deletedStack && deletedStack.stackStatus.name !== "DELETE_COMPLETE") {
80
+ throw new Error(`Failed deleting stack ${deployName} that had previously failed creation (current state: ${deletedStack.stackStatus})`);
81
+ }
82
+ // Update variable to mark that the stack does not exist anymore, but avoid
83
+ // doing an actual lookup in CloudFormation (which would be silly to do if
84
+ // we just deleted it).
85
+ cloudFormationStack = CloudFormationStack.doesNotExist(cfn, deployName);
86
+ }
87
+ // Detect "legacy" assets (which remain in the metadata) and publish them via
88
+ // an ad-hoc asset manifest, while passing their locations via template
89
+ // parameters.
90
+ const legacyAssets = new AssetManifestBuilder();
91
+ const assetParams = await addMetadataAssetsToManifest(stackArtifact, legacyAssets, options.toolkitInfo, options.reuseAssets);
92
+ const finalParameterValues = { ...options.parameters, ...assetParams };
93
+ const templateParams = TemplateParameters.fromTemplate(stackArtifact.template);
94
+ const stackParams = options.usePreviousParameters
95
+ ? templateParams.updateExisting(finalParameterValues, cloudFormationStack.parameters)
96
+ : templateParams.supplyAll(finalParameterValues);
97
+ const bodyParameter = await makeBodyParameter(stackArtifact, options.resolvedEnvironment, legacyAssets, options.toolkitInfo, options.sdk, options.overrideTemplate);
98
+ await publishAssets(legacyAssets.toManifest(stackArtifact.assembly.directory), options.sdkProvider, stackEnv, {
99
+ parallel: options.assetParallelism,
100
+ });
101
+ return {
102
+ isUpdate: cloudFormationStack.exists && cloudFormationStack.stackStatus.name !== 'REVIEW_IN_PROGRESS',
103
+ params: {
104
+ StackName: deployName,
105
+ TemplateBody: bodyParameter.TemplateBody,
106
+ TemplateURL: bodyParameter.TemplateURL,
107
+ Parameters: stackParams.apiParameters,
108
+ Capabilities: ['CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND'],
109
+ Tags: options.tags,
110
+ },
111
+ };
112
+ }
@@ -290,6 +290,6 @@ export declare class CloudFormationDeployments {
290
290
  /**
291
291
  * Validate that the bootstrap stack has the right version for this stack
292
292
  */
293
- private validateBootstrapStackVersion;
293
+ validateBootstrapStackVersion(stackName: string, requiresBootstrapStackVersion: number | undefined, bootstrapStackVersionSsmParameter: string | undefined, toolkitInfo: ToolkitInfo): Promise<void>;
294
294
  }
295
295
  export {};
@@ -1,5 +1,6 @@
1
1
  import * as cxapi from "@aws-cdk/cx-api";
2
2
  import { Tag } from "aws-cdk/lib/cdk-toolkit.js";
3
+ import { AssetManifestBuilder } from "aws-cdk/lib/util/asset-manifest-builder.js";
3
4
  import { ISDK, SdkProvider } from "aws-cdk/lib/api/aws-auth/index.js";
4
5
  import { ToolkitInfo } from "aws-cdk/lib/api/toolkit-info.js";
5
6
  import { ResourcesToImport } from "aws-cdk/lib/api/util/cloudformation.js";
@@ -185,6 +186,20 @@ export interface ChangeSetDeploymentMethod {
185
186
  readonly changeSetName?: string;
186
187
  }
187
188
  export declare function deployStack(options: DeployStackOptions): Promise<DeployStackResult | undefined>;
189
+ /**
190
+ * Prepares the body parameter for +CreateChangeSet+.
191
+ *
192
+ * If the template is small enough to be inlined into the API call, just return
193
+ * it immediately.
194
+ *
195
+ * Otherwise, add it to the asset manifest to get uploaded to the staging
196
+ * bucket and return its coordinates. If there is no staging bucket, an error
197
+ * is thrown.
198
+ *
199
+ * @param stack the synthesized stack that provides the CloudFormation template
200
+ * @param toolkitInfo information about the toolkit stack
201
+ */
202
+ export declare function makeBodyParameter(stack: cxapi.CloudFormationStackArtifact, resolvedEnvironment: cxapi.Environment, assetManifest: AssetManifestBuilder, toolkitInfo: ToolkitInfo, sdk: ISDK, overrideTemplate?: any): Promise<TemplateBodyParameter>;
188
203
  /**
189
204
  * Prepare a body parameter for CFN, performing the upload
190
205
  *
@@ -340,7 +340,7 @@ class FullCloudFormationDeployment {
340
340
  * @param stack the synthesized stack that provides the CloudFormation template
341
341
  * @param toolkitInfo information about the toolkit stack
342
342
  */
343
- async function makeBodyParameter(stack, resolvedEnvironment, assetManifest, toolkitInfo, sdk, overrideTemplate) {
343
+ export async function makeBodyParameter(stack, resolvedEnvironment, assetManifest, toolkitInfo, sdk, overrideTemplate) {
344
344
  // If the template has already been uploaded to S3, just use it from there.
345
345
  if (stack.stackTemplateAssetObjectUrl && !overrideTemplate) {
346
346
  return {
@@ -1,11 +1,14 @@
1
+ import { get } from "./get.js";
2
+ import { list } from "./list.js";
3
+ import { remove } from "./remove.js";
1
4
  import { set } from "./set.js";
2
5
  export function secrets(program) {
3
6
  program.command("secrets", "Manage the secrets in your app", (yargs) => {
4
7
  yargs.demandCommand(1);
5
8
  set(yargs);
6
- // get(yargs);
7
- // list(yargs);
8
- // remove(yargs);
9
+ get(yargs);
10
+ list(yargs);
11
+ remove(yargs);
9
12
  return yargs;
10
13
  });
11
14
  }
package/cli/program.js CHANGED
@@ -22,7 +22,7 @@ export const program = yargs(hideBin(process.argv))
22
22
  type: "string",
23
23
  describe: "ARN of the IAM role to use when invoking AWS",
24
24
  })
25
- .group(["stage", "profile", "region", "help"], "Global:")
25
+ .group(["stage", "profile", "region", "help", "verbose", "role"], "Global:")
26
26
  .middleware(async (argv) => {
27
27
  if (argv.verbose) {
28
28
  process.env.SST_VERBOSE = "1";
package/iot.js CHANGED
@@ -37,6 +37,10 @@ export const useIOT = Context.memo(async () => {
37
37
  });
38
38
  device.on("message", (_topic, buffer) => {
39
39
  const fragment = JSON.parse(buffer.toString());
40
+ if (!fragment.id) {
41
+ bus.publish(fragment.type, fragment.properties);
42
+ return;
43
+ }
40
44
  let pending = fragments.get(fragment.id);
41
45
  if (!pending) {
42
46
  pending = new Map();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sst",
3
- "version": "2.0.0-rc.37",
3
+ "version": "2.0.0-rc.39",
4
4
  "bin": {
5
5
  "sst": "cli/sst.js"
6
6
  },
package/sst.mjs CHANGED
@@ -2120,11 +2120,26 @@ var init_cloudformation_deployments = __esm({
2120
2120
  // src/cdk/cloudformation-deployments-wrapper.ts
2121
2121
  var cloudformation_deployments_wrapper_exports = {};
2122
2122
  __export(cloudformation_deployments_wrapper_exports, {
2123
- publishAssets: () => publishAssets3
2123
+ publishDeployAssets: () => publishDeployAssets
2124
2124
  });
2125
+ import { debug as debug3 } from "aws-cdk/lib/logging.js";
2126
+ import {
2127
+ CloudFormationStack as CloudFormationStack3,
2128
+ TemplateParameters as TemplateParameters2,
2129
+ waitForStackDelete as waitForStackDelete2
2130
+ } from "aws-cdk/lib/api/util/cloudformation.js";
2125
2131
  import { ToolkitInfo as ToolkitInfo2 } from "aws-cdk/lib/api/toolkit-info.js";
2126
- async function publishAssets3(deployment, options) {
2127
- const toolkitInfo = await useToolkitInfo().lookup(deployment, options);
2132
+ import { addMetadataAssetsToManifest as addMetadataAssetsToManifest2 } from "aws-cdk/lib/assets.js";
2133
+ import { publishAssets as publishAssets3 } from "aws-cdk/lib/util/asset-publishing.js";
2134
+ import { AssetManifestBuilder as AssetManifestBuilder2 } from "aws-cdk/lib/util/asset-manifest-builder.js";
2135
+ async function publishDeployAssets(sdkProvider, options) {
2136
+ const {
2137
+ deployment,
2138
+ toolkitInfo,
2139
+ stackSdk,
2140
+ resolvedEnvironment,
2141
+ cloudFormationRoleArn
2142
+ } = await useDeployment().get(sdkProvider, options);
2128
2143
  await deployment.publishStackAssets(options.stack, toolkitInfo, {
2129
2144
  buildAssets: options.buildAssets ?? true,
2130
2145
  publishOptions: {
@@ -2132,26 +2147,130 @@ async function publishAssets3(deployment, options) {
2132
2147
  parallel: options.assetParallelism
2133
2148
  }
2134
2149
  });
2150
+ return deployStack2({
2151
+ stack: options.stack,
2152
+ noMonitor: true,
2153
+ resolvedEnvironment,
2154
+ deployName: options.deployName,
2155
+ notificationArns: options.notificationArns,
2156
+ quiet: options.quiet,
2157
+ sdk: stackSdk,
2158
+ sdkProvider,
2159
+ roleArn: cloudFormationRoleArn,
2160
+ reuseAssets: options.reuseAssets,
2161
+ toolkitInfo,
2162
+ tags: options.tags,
2163
+ deploymentMethod: options.deploymentMethod,
2164
+ force: options.force,
2165
+ parameters: options.parameters,
2166
+ usePreviousParameters: options.usePreviousParameters,
2167
+ progress: options.progress,
2168
+ ci: options.ci,
2169
+ rollback: options.rollback,
2170
+ hotswap: options.hotswap,
2171
+ extraUserAgent: options.extraUserAgent,
2172
+ resourcesToImport: options.resourcesToImport,
2173
+ overrideTemplate: options.overrideTemplate,
2174
+ assetParallelism: options.assetParallelism
2175
+ });
2135
2176
  }
2136
- var useToolkitInfo;
2177
+ async function deployStack2(options) {
2178
+ const stackArtifact = options.stack;
2179
+ const stackEnv = options.resolvedEnvironment;
2180
+ options.sdk.appendCustomUserAgent(options.extraUserAgent);
2181
+ const cfn = options.sdk.cloudFormation();
2182
+ const deployName = options.deployName || stackArtifact.stackName;
2183
+ let cloudFormationStack = await CloudFormationStack3.lookup(cfn, deployName);
2184
+ if (cloudFormationStack.stackStatus.isCreationFailure) {
2185
+ debug3(
2186
+ `Found existing stack ${deployName} that had previously failed creation. Deleting it before attempting to re-create it.`
2187
+ );
2188
+ await cfn.deleteStack({ StackName: deployName }).promise();
2189
+ const deletedStack = await waitForStackDelete2(cfn, deployName);
2190
+ if (deletedStack && deletedStack.stackStatus.name !== "DELETE_COMPLETE") {
2191
+ throw new Error(
2192
+ `Failed deleting stack ${deployName} that had previously failed creation (current state: ${deletedStack.stackStatus})`
2193
+ );
2194
+ }
2195
+ cloudFormationStack = CloudFormationStack3.doesNotExist(cfn, deployName);
2196
+ }
2197
+ const legacyAssets = new AssetManifestBuilder2();
2198
+ const assetParams = await addMetadataAssetsToManifest2(
2199
+ stackArtifact,
2200
+ legacyAssets,
2201
+ options.toolkitInfo,
2202
+ options.reuseAssets
2203
+ );
2204
+ const finalParameterValues = { ...options.parameters, ...assetParams };
2205
+ const templateParams = TemplateParameters2.fromTemplate(
2206
+ stackArtifact.template
2207
+ );
2208
+ const stackParams = options.usePreviousParameters ? templateParams.updateExisting(
2209
+ finalParameterValues,
2210
+ cloudFormationStack.parameters
2211
+ ) : templateParams.supplyAll(finalParameterValues);
2212
+ const bodyParameter = await makeBodyParameter(
2213
+ stackArtifact,
2214
+ options.resolvedEnvironment,
2215
+ legacyAssets,
2216
+ options.toolkitInfo,
2217
+ options.sdk,
2218
+ options.overrideTemplate
2219
+ );
2220
+ await publishAssets3(
2221
+ legacyAssets.toManifest(stackArtifact.assembly.directory),
2222
+ options.sdkProvider,
2223
+ stackEnv,
2224
+ {
2225
+ parallel: options.assetParallelism
2226
+ }
2227
+ );
2228
+ return {
2229
+ isUpdate: cloudFormationStack.exists && cloudFormationStack.stackStatus.name !== "REVIEW_IN_PROGRESS",
2230
+ params: {
2231
+ StackName: deployName,
2232
+ TemplateBody: bodyParameter.TemplateBody,
2233
+ TemplateURL: bodyParameter.TemplateURL,
2234
+ Parameters: stackParams.apiParameters,
2235
+ Capabilities: ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM", "CAPABILITY_AUTO_EXPAND"],
2236
+ Tags: options.tags
2237
+ }
2238
+ };
2239
+ }
2240
+ var useDeployment;
2137
2241
  var init_cloudformation_deployments_wrapper = __esm({
2138
2242
  "src/cdk/cloudformation-deployments-wrapper.ts"() {
2139
2243
  "use strict";
2244
+ init_cloudformation_deployments();
2245
+ init_deploy_stack();
2140
2246
  init_context();
2141
- useToolkitInfo = Context.memo(() => {
2247
+ useDeployment = Context.memo(() => {
2142
2248
  const state2 = /* @__PURE__ */ new Map();
2143
2249
  return {
2144
- async lookup(deployment, options) {
2145
- if (state2.has(deployment))
2146
- return state2.get(deployment);
2147
- const { stackSdk, resolvedEnvironment } = await deployment.prepareSdkFor(options.stack, options.roleArn);
2148
- const toolkitInfo = await ToolkitInfo2.lookup(
2149
- resolvedEnvironment,
2150
- stackSdk,
2151
- options.toolkitStackName
2152
- );
2153
- state2.set(deployment, toolkitInfo);
2154
- return toolkitInfo;
2250
+ async get(sdkProvider, options) {
2251
+ if (!state2.has(sdkProvider)) {
2252
+ const deployment = new CloudFormationDeployments({ sdkProvider });
2253
+ const { stackSdk, resolvedEnvironment, cloudFormationRoleArn } = await deployment.prepareSdkFor(options.stack, options.roleArn);
2254
+ const toolkitInfo = await ToolkitInfo2.lookup(
2255
+ resolvedEnvironment,
2256
+ stackSdk,
2257
+ options.toolkitStackName
2258
+ );
2259
+ await deployment.validateBootstrapStackVersion(
2260
+ options.stack.stackName,
2261
+ options.stack.requiresBootstrapStackVersion,
2262
+ options.stack.bootstrapStackVersionSsmParameter,
2263
+ toolkitInfo
2264
+ );
2265
+ state2.set(sdkProvider, {
2266
+ deployment,
2267
+ toolkitInfo,
2268
+ stackSdk,
2269
+ resolvedEnvironment,
2270
+ cloudFormationRoleArn
2271
+ });
2272
+ }
2273
+ return state2.get(sdkProvider);
2155
2274
  }
2156
2275
  };
2157
2276
  });
@@ -2162,23 +2281,22 @@ var init_cloudformation_deployments_wrapper = __esm({
2162
2281
  async function publishAssets4(stacks) {
2163
2282
  Logger.debug("Publishing assets");
2164
2283
  const provider = await useAWSProvider();
2165
- const { CloudFormationDeployments: CloudFormationDeployments2 } = await Promise.resolve().then(() => (init_cloudformation_deployments(), cloudformation_deployments_exports));
2166
- const { publishAssets: publishAssets5 } = await Promise.resolve().then(() => (init_cloudformation_deployments_wrapper(), cloudformation_deployments_wrapper_exports));
2167
- const deployment = new CloudFormationDeployments2({
2168
- sdkProvider: provider
2169
- });
2284
+ const { publishDeployAssets: publishDeployAssets2 } = await Promise.resolve().then(() => (init_cloudformation_deployments_wrapper(), cloudformation_deployments_wrapper_exports));
2285
+ const results = {};
2170
2286
  for (const stack of stacks) {
2171
- await publishAssets5(
2172
- deployment,
2287
+ const result = await publishDeployAssets2(
2288
+ provider,
2173
2289
  {
2174
2290
  stack,
2175
- quiet: true,
2291
+ quiet: false,
2176
2292
  deploymentMethod: {
2177
2293
  method: "direct"
2178
2294
  }
2179
2295
  }
2180
2296
  );
2297
+ results[stack.stackName] = result;
2181
2298
  }
2299
+ return results;
2182
2300
  }
2183
2301
  async function deployMany(stacks) {
2184
2302
  Logger.debug(
@@ -2352,7 +2470,7 @@ async function metadata() {
2352
2470
  credentials
2353
2471
  });
2354
2472
  const key = `stackMetadata/app.${project.config.name}/stage.${project.config.stage}/`;
2355
- const list = await s3.send(
2473
+ const list2 = await s3.send(
2356
2474
  new ListObjectsV2Command({
2357
2475
  Prefix: key,
2358
2476
  Bucket: bootstrap.bucket
@@ -2360,7 +2478,7 @@ async function metadata() {
2360
2478
  );
2361
2479
  const result = Object.fromEntries(
2362
2480
  await Promise.all(
2363
- list.Contents?.map(async (obj) => {
2481
+ list2.Contents?.map(async (obj) => {
2364
2482
  const stackID = obj.Key?.split("/").pop();
2365
2483
  const result2 = await s3.send(
2366
2484
  new GetObjectCommand({
@@ -2372,7 +2490,7 @@ async function metadata() {
2372
2490
  }) || []
2373
2491
  )
2374
2492
  );
2375
- Logger.debug("Fetched metadata from", list.KeyCount, "stacks");
2493
+ Logger.debug("Fetched metadata from", list2.KeyCount, "stacks");
2376
2494
  return result;
2377
2495
  }
2378
2496
  async function metadataForStack(stackID) {
@@ -2409,22 +2527,23 @@ var init_metadata = __esm({
2409
2527
  init_cache();
2410
2528
  init_context();
2411
2529
  init_bus();
2412
- init_stacks();
2413
2530
  init_logger();
2414
2531
  init_project();
2415
2532
  MetadataContext = Context.create(async () => {
2416
2533
  const bus = useBus();
2417
2534
  const cache = await useCache();
2418
2535
  const data2 = await metadata();
2419
- bus.subscribe("stack.status", async (evt) => {
2420
- if (!stacks_exports.isSuccess(evt.properties.status))
2421
- return;
2422
- const meta = await metadataForStack(evt.properties.stackID);
2423
- Logger.debug("Got metadata", meta);
2424
- data2[evt.properties.stackID] = meta;
2425
- await cache.write(`metadata.json`, JSON.stringify(data2));
2426
- bus.publish("stacks.metadata", data2);
2427
- MetadataContext.provide(Promise.resolve(data2));
2536
+ bus.subscribe("stacks.metadata.updated", async () => {
2537
+ const data3 = await metadata();
2538
+ await cache.write(`metadata.json`, JSON.stringify(data3));
2539
+ bus.publish("stacks.metadata", data3);
2540
+ MetadataContext.provide(Promise.resolve(data3));
2541
+ });
2542
+ bus.subscribe("stacks.metadata.deleted", async () => {
2543
+ const data3 = await metadata();
2544
+ await cache.write(`metadata.json`, JSON.stringify(data3));
2545
+ bus.publish("stacks.metadata", data3);
2546
+ MetadataContext.provide(Promise.resolve(data3));
2428
2547
  });
2429
2548
  return data2;
2430
2549
  });
@@ -3851,7 +3970,9 @@ async function initBootstrap() {
3851
3970
  }),
3852
3971
  new PolicyStatement({
3853
3972
  actions: ["iot:Publish"],
3854
- resources: [`arn:${stack.partition}:iot:${stack.region}:${stack.account}:topic//sst/*`]
3973
+ resources: [
3974
+ `arn:${stack.partition}:iot:${stack.region}:${stack.account}:topic//sst/*`
3975
+ ]
3855
3976
  })
3856
3977
  ]
3857
3978
  });
@@ -4484,6 +4605,10 @@ var init_iot = __esm({
4484
4605
  });
4485
4606
  device.on("message", (_topic, buffer) => {
4486
4607
  const fragment = JSON.parse(buffer.toString());
4608
+ if (!fragment.id) {
4609
+ bus.publish(fragment.type, fragment.properties);
4610
+ return;
4611
+ }
4487
4612
  let pending = fragments.get(fragment.id);
4488
4613
  if (!pending) {
4489
4614
  pending = /* @__PURE__ */ new Map();
@@ -5706,7 +5831,7 @@ var program = yargs(hideBin(process.argv)).scriptName("sst").option("stage", {
5706
5831
  }).option("role", {
5707
5832
  type: "string",
5708
5833
  describe: "ARN of the IAM role to use when invoking AWS"
5709
- }).group(["stage", "profile", "region", "help"], "Global:").middleware(async (argv) => {
5834
+ }).group(["stage", "profile", "region", "help", "verbose", "role"], "Global:").middleware(async (argv) => {
5710
5835
  if (argv.verbose) {
5711
5836
  process.env.SST_VERBOSE = "1";
5712
5837
  }
@@ -6181,6 +6306,108 @@ var consoleCommand = async (program2) => program2.command(
6181
6306
  }
6182
6307
  );
6183
6308
 
6309
+ // src/cli/commands/secrets/get.ts
6310
+ var get = (program2) => program2.command(
6311
+ "get <name>",
6312
+ "Get the value of a secret",
6313
+ (yargs2) => yargs2.positional("name", {
6314
+ type: "string",
6315
+ describe: "Name of the secret",
6316
+ demandOption: true
6317
+ }).option("fallback", {
6318
+ type: "boolean",
6319
+ describe: "Get the fallback value"
6320
+ }),
6321
+ async (args) => {
6322
+ const { red: red3 } = await import("colorette");
6323
+ const { Config: Config2 } = await Promise.resolve().then(() => (init_config(), config_exports));
6324
+ const { bold: bold2 } = await import("colorette");
6325
+ try {
6326
+ const result = await Config2.getSecret({
6327
+ key: args.name,
6328
+ fallback: args.fallback === true
6329
+ });
6330
+ console.log(bold2(result));
6331
+ } catch {
6332
+ console.log(red3(`${bold2(args.name)} is not set`));
6333
+ }
6334
+ }
6335
+ );
6336
+
6337
+ // src/cli/commands/secrets/list.ts
6338
+ var list = (program2) => program2.command(
6339
+ "list [format]",
6340
+ "Fetch all the secrets",
6341
+ (yargs2) => yargs2.positional("format", {
6342
+ type: "string",
6343
+ choices: ["table", "env"]
6344
+ }),
6345
+ async (args) => {
6346
+ const { Config: Config2 } = await Promise.resolve().then(() => (init_config(), config_exports));
6347
+ const { gray } = await import("colorette");
6348
+ const secrets2 = await Config2.secrets();
6349
+ switch (args.format || "table") {
6350
+ case "env":
6351
+ for (const [key, value] of Object.entries(secrets2)) {
6352
+ console.log(`${key}=${value.value || value.fallback}`);
6353
+ }
6354
+ break;
6355
+ case "table":
6356
+ const keys2 = Object.keys(secrets2);
6357
+ const keyLen = Math.max(
6358
+ "Secrets".length,
6359
+ ...keys2.map((key) => key.length)
6360
+ );
6361
+ const valueLen = Math.max(
6362
+ "Values".length,
6363
+ ...keys2.map(
6364
+ (key) => secrets2[key].value ? secrets2[key].value.length : `${secrets2[key].fallback} (fallback)`.length
6365
+ )
6366
+ );
6367
+ console.log(
6368
+ "\u250C".padEnd(keyLen + 3, "\u2500") + "\u252C" + "".padEnd(valueLen + 2, "\u2500") + "\u2510"
6369
+ );
6370
+ console.log(
6371
+ `\u2502 ${"Secrets".padEnd(keyLen)} \u2502 ${"Values".padEnd(valueLen)} \u2502`
6372
+ );
6373
+ console.log(
6374
+ "\u251C".padEnd(keyLen + 3, "\u2500") + "\u253C" + "".padEnd(valueLen + 2, "\u2500") + "\u2524"
6375
+ );
6376
+ keys2.sort().forEach((key) => {
6377
+ const value = secrets2[key].value ? secrets2[key].value : `${secrets2[key].fallback} ${gray("(fallback)")}`;
6378
+ console.log(
6379
+ `\u2502 ${key.padEnd(keyLen)} \u2502 ${value.padEnd(valueLen)} \u2502`
6380
+ );
6381
+ });
6382
+ console.log(
6383
+ "\u2514".padEnd(keyLen + 3, "\u2500") + "\u2534" + "".padEnd(valueLen + 2, "\u2500") + "\u2518"
6384
+ );
6385
+ break;
6386
+ }
6387
+ }
6388
+ );
6389
+
6390
+ // src/cli/commands/secrets/remove.ts
6391
+ var remove3 = (program2) => program2.command(
6392
+ "remove <name>",
6393
+ "Remove a secret",
6394
+ (yargs2) => yargs2.positional("name", {
6395
+ describe: "Name of the secret",
6396
+ type: "string",
6397
+ demandOption: true
6398
+ }).option("fallback", {
6399
+ type: "boolean",
6400
+ describe: "Remove the fallback value"
6401
+ }),
6402
+ async (args) => {
6403
+ const { Config: Config2 } = await Promise.resolve().then(() => (init_config(), config_exports));
6404
+ await Config2.removeSecret({
6405
+ key: args.name,
6406
+ fallback: args.fallback === true
6407
+ });
6408
+ }
6409
+ );
6410
+
6184
6411
  // src/cli/commands/secrets/set.ts
6185
6412
  var set = (program2) => program2.command(
6186
6413
  "set <name> <value>",
@@ -6223,6 +6450,9 @@ function secrets(program2) {
6223
6450
  program2.command("secrets", "Manage the secrets in your app", (yargs2) => {
6224
6451
  yargs2.demandCommand(1);
6225
6452
  set(yargs2);
6453
+ get(yargs2);
6454
+ list(yargs2);
6455
+ remove3(yargs2);
6226
6456
  return yargs2;
6227
6457
  });
6228
6458
  }
@@ -1,6 +1,6 @@
1
1
  import type { CloudFormationStackArtifact } from "aws-cdk-lib/cx-api";
2
2
  import { StackDeploymentResult } from "./monitor.js";
3
- export declare function publishAssets(stacks: CloudFormationStackArtifact[]): Promise<void>;
3
+ export declare function publishAssets(stacks: CloudFormationStackArtifact[]): Promise<Record<string, any>>;
4
4
  export declare function deployMany(stacks: CloudFormationStackArtifact[]): Promise<Record<string, {
5
5
  status: string;
6
6
  outputs: Record<string, string>;
package/stacks/deploy.js CHANGED
@@ -3,23 +3,21 @@ import { useAWSProvider } from "../credentials.js";
3
3
  import { Logger } from "../logger.js";
4
4
  import { isFailed, monitor } from "./monitor.js";
5
5
  export async function publishAssets(stacks) {
6
- // TODO: use memo in cloudformation-deployments.ts
7
6
  Logger.debug("Publishing assets");
8
7
  const provider = await useAWSProvider();
9
- const { CloudFormationDeployments } = await import("../cdk/cloudformation-deployments.js");
10
- const { publishAssets } = await import("../cdk/cloudformation-deployments-wrapper.js");
11
- const deployment = new CloudFormationDeployments({
12
- sdkProvider: provider,
13
- });
8
+ const { publishDeployAssets } = await import("../cdk/cloudformation-deployments-wrapper.js");
9
+ const results = {};
14
10
  for (const stack of stacks) {
15
- await publishAssets(deployment, {
11
+ const result = await publishDeployAssets(provider, {
16
12
  stack: stack,
17
- quiet: true,
13
+ quiet: false,
18
14
  deploymentMethod: {
19
15
  method: "direct",
20
16
  },
21
17
  });
18
+ results[stack.stackName] = result;
22
19
  }
20
+ return results;
23
21
  }
24
22
  export async function deployMany(stacks) {
25
23
  Logger.debug("Deploying stacks", stacks.map((s) => s.stackName));
@@ -5,7 +5,6 @@ import { json } from "stream/consumers";
5
5
  import { useCache } from "../cache.js";
6
6
  import { Context } from "../context/context.js";
7
7
  import { useBus } from "../bus.js";
8
- import { Stacks } from "./index.js";
9
8
  import { Logger } from "../logger.js";
10
9
  import { useProject } from "../project.js";
11
10
  export async function metadata() {
@@ -67,12 +66,14 @@ const MetadataContext = Context.create(async () => {
67
66
  const bus = useBus();
68
67
  const cache = await useCache();
69
68
  const data = await metadata();
70
- bus.subscribe("stack.status", async (evt) => {
71
- if (!Stacks.isSuccess(evt.properties.status))
72
- return;
73
- const meta = await metadataForStack(evt.properties.stackID);
74
- Logger.debug("Got metadata", meta);
75
- data[evt.properties.stackID] = meta;
69
+ bus.subscribe("stacks.metadata.updated", async () => {
70
+ const data = await metadata();
71
+ await cache.write(`metadata.json`, JSON.stringify(data));
72
+ bus.publish("stacks.metadata", data);
73
+ MetadataContext.provide(Promise.resolve(data));
74
+ });
75
+ bus.subscribe("stacks.metadata.deleted", async () => {
76
+ const data = await metadata();
76
77
  await cache.write(`metadata.json`, JSON.stringify(data));
77
78
  bus.publish("stacks.metadata", data);
78
79
  MetadataContext.provide(Promise.resolve(data));