sst 2.1.32 → 2.1.34

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/sst.mjs CHANGED
@@ -2603,743 +2603,306 @@ var init_workers = __esm({
2603
2603
  }
2604
2604
  });
2605
2605
 
2606
- // src/iot.ts
2607
- var iot_exports = {};
2608
- __export(iot_exports, {
2609
- useIOT: () => useIOT,
2610
- useIOTEndpoint: () => useIOTEndpoint
2611
- });
2612
- import { IoTClient, DescribeEndpointCommand } from "@aws-sdk/client-iot";
2613
- import iot from "aws-iot-device-sdk";
2614
- function encode(input) {
2615
- const json = JSON.stringify(input);
2616
- const parts = json.match(/.{1,100000}/g);
2617
- if (!parts)
2618
- return [];
2619
- const id = Math.random().toString();
2620
- return parts.map((part, index) => ({
2621
- id,
2622
- index,
2623
- count: parts?.length,
2624
- data: part
2625
- }));
2606
+ // src/stacks/app-metadata.ts
2607
+ import {
2608
+ S3Client,
2609
+ GetObjectCommand,
2610
+ PutObjectCommand,
2611
+ DeleteObjectCommand
2612
+ } from "@aws-sdk/client-s3";
2613
+ async function metadata() {
2614
+ Logger.debug("Fetching app metadata");
2615
+ const [project, credentials, bootstrap] = await Promise.all([
2616
+ useProject(),
2617
+ useAWSCredentials(),
2618
+ useBootstrap()
2619
+ ]);
2620
+ const s3 = new S3Client({
2621
+ region: project.config.region,
2622
+ credentials
2623
+ });
2624
+ try {
2625
+ const result = await s3.send(
2626
+ new GetObjectCommand({
2627
+ Key: useS3Key(),
2628
+ Bucket: bootstrap.bucket
2629
+ })
2630
+ );
2631
+ const body = await result.Body.transformToString();
2632
+ return JSON.parse(body);
2633
+ } catch (ex) {
2634
+ Logger.debug("Fetching app metadata: not found");
2635
+ }
2626
2636
  }
2627
- var useIOTEndpoint, useIOT;
2628
- var init_iot = __esm({
2629
- "src/iot.ts"() {
2637
+ async function saveAppMetadata(data2) {
2638
+ Logger.debug("Saving app metadata");
2639
+ const [project, credentials, bootstrap] = await Promise.all([
2640
+ useProject(),
2641
+ useAWSCredentials(),
2642
+ useBootstrap()
2643
+ ]);
2644
+ const s3 = new S3Client({
2645
+ region: project.config.region,
2646
+ credentials
2647
+ });
2648
+ try {
2649
+ await s3.send(
2650
+ new PutObjectCommand({
2651
+ Key: useS3Key(),
2652
+ Bucket: bootstrap.bucket,
2653
+ Body: JSON.stringify(data2)
2654
+ })
2655
+ );
2656
+ } catch (ex) {
2657
+ Logger.debug("Saving app metadata: not found");
2658
+ }
2659
+ }
2660
+ async function clearAppMetadata() {
2661
+ Logger.debug("Clearing app metadata");
2662
+ const [project, credentials, bootstrap] = await Promise.all([
2663
+ useProject(),
2664
+ useAWSCredentials(),
2665
+ useBootstrap()
2666
+ ]);
2667
+ const s3 = new S3Client({
2668
+ region: project.config.region,
2669
+ credentials
2670
+ });
2671
+ await s3.send(
2672
+ new DeleteObjectCommand({
2673
+ Key: useS3Key(),
2674
+ Bucket: bootstrap.bucket
2675
+ })
2676
+ );
2677
+ }
2678
+ function useS3Key() {
2679
+ const project = useProject();
2680
+ return `appMetadata/app.${project.config.name}/stage.${project.config.stage}.json`;
2681
+ }
2682
+ var MetadataContext, useAppMetadata;
2683
+ var init_app_metadata = __esm({
2684
+ "src/stacks/app-metadata.ts"() {
2630
2685
  "use strict";
2631
- init_context();
2686
+ init_bootstrap();
2632
2687
  init_credentials();
2633
- init_error();
2634
- init_bus();
2635
- init_project();
2688
+ init_context();
2636
2689
  init_logger();
2637
- useIOTEndpoint = Context.memo(async () => {
2638
- const iot2 = useAWSClient(IoTClient);
2639
- Logger.debug("Getting IoT endpoint");
2640
- const response = await iot2.send(
2641
- new DescribeEndpointCommand({
2642
- endpointType: "iot:Data-ATS"
2643
- })
2644
- );
2645
- Logger.debug("Using IoT endpoint:", response.endpointAddress);
2646
- if (!response.endpointAddress)
2647
- throw new VisibleError("IoT Endpoint address not found");
2648
- return response.endpointAddress;
2649
- });
2650
- useIOT = Context.memo(async () => {
2651
- const bus = useBus();
2652
- const endpoint = await useIOTEndpoint();
2653
- const creds = await useAWSCredentials();
2654
- const project = useProject();
2655
- const device = new iot.device({
2656
- protocol: "wss",
2657
- host: endpoint,
2658
- region: project.config.region,
2659
- accessKeyId: creds.accessKeyId,
2660
- secretKey: creds.secretAccessKey,
2661
- sessionToken: creds.sessionToken,
2662
- reconnectPeriod: 1
2663
- });
2664
- const PREFIX2 = `/sst/${project.config.name}/${project.config.stage}`;
2665
- device.subscribe(`${PREFIX2}/events`, { qos: 1 });
2666
- const fragments = /* @__PURE__ */ new Map();
2667
- device.on("connect", () => {
2668
- Logger.debug("IoT connected");
2669
- });
2670
- device.on("error", (err) => {
2671
- Logger.debug("IoT error", err);
2672
- });
2673
- device.on("close", () => {
2674
- Logger.debug("IoT closed");
2675
- });
2676
- device.on("reconnect", () => {
2677
- Logger.debug("IoT reconnected");
2678
- });
2679
- device.on("message", (_topic, buffer) => {
2680
- const fragment = JSON.parse(buffer.toString());
2681
- if (!fragment.id) {
2682
- bus.publish(fragment.type, fragment.properties);
2683
- return;
2684
- }
2685
- let pending = fragments.get(fragment.id);
2686
- if (!pending) {
2687
- pending = /* @__PURE__ */ new Map();
2688
- fragments.set(fragment.id, pending);
2689
- }
2690
- pending.set(fragment.index, fragment);
2691
- if (pending.size === fragment.count) {
2692
- const data2 = [...pending.values()].sort((a, b) => a.index - b.index).map((item) => item.data).join("");
2693
- fragments.delete(fragment.id);
2694
- const evt = JSON.parse(data2);
2695
- if (evt.sourceID === bus.sourceID)
2696
- return;
2697
- bus.publish(evt.type, evt.properties);
2698
- }
2699
- });
2700
- return {
2701
- prefix: PREFIX2,
2702
- async publish(topic, type, properties) {
2703
- const payload = {
2704
- type,
2705
- properties,
2706
- sourceID: bus.sourceID
2707
- };
2708
- for (const fragment of encode(payload)) {
2709
- await new Promise((r) => {
2710
- device.publish(
2711
- topic,
2712
- JSON.stringify(fragment),
2713
- {
2714
- qos: 1
2715
- },
2716
- () => {
2717
- r();
2718
- }
2719
- );
2720
- });
2721
- }
2722
- Logger.debug("IOT Published", topic, type);
2723
- }
2724
- };
2690
+ init_project();
2691
+ MetadataContext = Context.create(async () => {
2692
+ const data2 = await metadata();
2693
+ return data2;
2725
2694
  });
2695
+ useAppMetadata = MetadataContext.use;
2726
2696
  }
2727
2697
  });
2728
2698
 
2729
- // src/runtime/iot.ts
2730
- var iot_exports2 = {};
2731
- __export(iot_exports2, {
2732
- useIOTBridge: () => useIOTBridge
2733
- });
2734
- var useIOTBridge;
2735
- var init_iot2 = __esm({
2736
- "src/runtime/iot.ts"() {
2699
+ // src/stacks/assembly.ts
2700
+ async function loadAssembly(from) {
2701
+ const { CloudAssembly } = await import("aws-cdk-lib/cx-api");
2702
+ return new CloudAssembly(from);
2703
+ }
2704
+ var init_assembly = __esm({
2705
+ "src/stacks/assembly.ts"() {
2737
2706
  "use strict";
2738
- init_context();
2739
- init_bus();
2740
- init_iot();
2741
- useIOTBridge = Context.memo(async () => {
2742
- const bus = useBus();
2743
- const iot2 = await useIOT();
2744
- const topic = `${iot2.prefix}/events`;
2745
- bus.subscribe("function.success", async (evt) => {
2746
- iot2.publish(
2747
- topic + "/" + evt.properties.workerID,
2748
- "function.success",
2749
- evt.properties
2750
- );
2751
- });
2752
- bus.subscribe("function.error", async (evt) => {
2753
- iot2.publish(
2754
- topic + "/" + evt.properties.workerID,
2755
- "function.error",
2756
- evt.properties
2757
- );
2758
- });
2759
- bus.subscribe("function.ack", async (evt) => {
2760
- iot2.publish(
2761
- topic + "/" + evt.properties.workerID,
2762
- "function.ack",
2763
- evt.properties
2764
- );
2765
- });
2766
- });
2767
2707
  }
2768
2708
  });
2769
2709
 
2770
- // src/bootstrap.ts
2771
- import url3 from "url";
2772
- import path8 from "path";
2773
- import { bold, dim } from "colorette";
2774
- import { spawn } from "child_process";
2710
+ // src/stacks/monitor.ts
2775
2711
  import {
2712
+ CloudFormationClient,
2713
+ DescribeStackResourcesCommand,
2776
2714
  DescribeStacksCommand,
2777
- CloudFormationClient
2715
+ DescribeStackEventsCommand
2778
2716
  } from "@aws-sdk/client-cloudformation";
2779
- import {
2780
- App,
2781
- DefaultStackSynthesizer,
2782
- CfnOutput,
2783
- Duration,
2784
- Tags,
2785
- Stack,
2786
- RemovalPolicy
2787
- } from "aws-cdk-lib";
2788
- import { Function, Runtime, Code } from "aws-cdk-lib/aws-lambda";
2789
- import { SqsEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
2790
- import { PolicyStatement } from "aws-cdk-lib/aws-iam";
2791
- import { Queue } from "aws-cdk-lib/aws-sqs";
2792
- import { Rule } from "aws-cdk-lib/aws-events";
2793
- import { SqsQueue } from "aws-cdk-lib/aws-events-targets";
2794
- import {
2795
- BlockPublicAccess,
2796
- Bucket,
2797
- BucketEncryption
2798
- } from "aws-cdk-lib/aws-s3";
2799
- async function loadCDKStatus() {
2800
- const { cdk } = useProject().config;
2801
- const client = useAWSClient(CloudFormationClient);
2802
- const stackName = cdk?.toolkitStackName || CDK_STACK_NAME;
2803
- try {
2804
- const { Stacks: stacks } = await client.send(
2805
- new DescribeStacksCommand({ StackName: stackName })
2806
- );
2807
- if (!stacks || stacks.length === 0)
2808
- return false;
2809
- if (!["CREATE_COMPLETE", "UPDATE_COMPLETE"].includes(stacks[0].StackStatus)) {
2810
- return false;
2811
- }
2812
- const output = stacks[0].Outputs?.find(
2813
- (o) => o.OutputKey === "BootstrapVersion"
2814
- );
2815
- if (!output || parseInt(output.OutputValue) < 14)
2816
- return false;
2817
- return true;
2818
- } catch (e) {
2819
- if (e.name === "ValidationError" && e.message === `Stack with id ${stackName} does not exist`) {
2820
- return false;
2821
- } else {
2822
- throw e;
2717
+ import { map, omitBy, pipe } from "remeda";
2718
+ function isFinal(input) {
2719
+ return STATUSES_SUCCESS.includes(input) || STATUSES_FAILED.includes(input);
2720
+ }
2721
+ function isFailed(input) {
2722
+ return STATUSES_FAILED.includes(input);
2723
+ }
2724
+ function isSuccess(input) {
2725
+ return STATUSES_SUCCESS.includes(input);
2726
+ }
2727
+ function isPending(input) {
2728
+ return STATUSES_PENDING.includes(input);
2729
+ }
2730
+ async function monitor(stack) {
2731
+ const [cfn, bus] = await Promise.all([
2732
+ useAWSClient(CloudFormationClient),
2733
+ useBus()
2734
+ ]);
2735
+ let lastStatus;
2736
+ const errors = {};
2737
+ let lastEvent;
2738
+ while (true) {
2739
+ try {
2740
+ const [describe, resources, events] = await Promise.all([
2741
+ cfn.send(
2742
+ new DescribeStacksCommand({
2743
+ StackName: stack
2744
+ })
2745
+ ),
2746
+ cfn.send(
2747
+ new DescribeStackResourcesCommand({
2748
+ StackName: stack
2749
+ })
2750
+ ),
2751
+ cfn.send(
2752
+ new DescribeStackEventsCommand({
2753
+ StackName: stack
2754
+ })
2755
+ )
2756
+ ]);
2757
+ Logger.debug("Stack description", describe);
2758
+ if (lastEvent) {
2759
+ const eventsReversed = [...events.StackEvents ?? []].reverse();
2760
+ for (const event of eventsReversed) {
2761
+ if (!event.Timestamp)
2762
+ continue;
2763
+ if (event.Timestamp.getTime() > lastEvent.getTime()) {
2764
+ bus.publish("stack.event", {
2765
+ event,
2766
+ stackID: stack
2767
+ });
2768
+ if (event.ResourceStatusReason) {
2769
+ if (event.ResourceStatusReason.includes(
2770
+ "Resource creation cancelled"
2771
+ ) || event.ResourceStatusReason.includes(
2772
+ "Resource update cancelled"
2773
+ ) || event.ResourceStatusReason.includes(
2774
+ "Resource creation Initiated"
2775
+ ) || event.ResourceStatusReason.startsWith(
2776
+ "The following resource(s) failed to"
2777
+ ))
2778
+ continue;
2779
+ errors[event.LogicalResourceId] = event.ResourceStatusReason;
2780
+ }
2781
+ }
2782
+ }
2783
+ Logger.debug("Last event set to", lastEvent);
2784
+ }
2785
+ lastEvent = events.StackEvents?.at(0)?.Timestamp;
2786
+ bus.publish("stack.resources", {
2787
+ stackID: stack,
2788
+ resources: resources.StackResources
2789
+ });
2790
+ for (const resource of resources.StackResources || []) {
2791
+ if (resource.ResourceStatusReason?.includes(
2792
+ "Resource creation cancelled"
2793
+ ) || resource.ResourceStatusReason?.includes(
2794
+ "Resource update cancelled"
2795
+ ) || resource.ResourceStatusReason?.includes(
2796
+ "Resource creation Initiated"
2797
+ ) || resource.ResourceStatusReason?.startsWith(
2798
+ "The following resource(s) failed to"
2799
+ ))
2800
+ continue;
2801
+ if (resource.ResourceStatusReason)
2802
+ errors[resource.LogicalResourceId] = resource.ResourceStatusReason;
2803
+ }
2804
+ const [first] = describe.Stacks || [];
2805
+ if (first) {
2806
+ if (lastStatus !== first.StackStatus && first.StackStatus) {
2807
+ lastStatus = first.StackStatus;
2808
+ bus.publish("stack.status", {
2809
+ stackID: stack,
2810
+ status: first.StackStatus
2811
+ });
2812
+ Logger.debug(first);
2813
+ if (isFinal(first.StackStatus)) {
2814
+ return {
2815
+ status: first.StackStatus,
2816
+ outputs: pipe(
2817
+ first.Outputs || [],
2818
+ map((o) => [o.OutputKey, o.OutputValue]),
2819
+ Object.fromEntries,
2820
+ filterOutputs
2821
+ ),
2822
+ errors: isFailed(first.StackStatus) ? errors : {}
2823
+ };
2824
+ }
2825
+ }
2826
+ }
2827
+ } catch (ex) {
2828
+ if (ex.message.includes("does not exist")) {
2829
+ bus.publish("stack.status", {
2830
+ stackID: stack,
2831
+ status: "DELETE_COMPLETE"
2832
+ });
2833
+ return {
2834
+ status: "DELETE_COMPLETE",
2835
+ outputs: {},
2836
+ errors: {}
2837
+ };
2838
+ }
2823
2839
  }
2840
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
2824
2841
  }
2825
2842
  }
2826
- async function loadSSTStatus() {
2827
- const { bootstrap } = useProject().config;
2828
- const cf = useAWSClient(CloudFormationClient);
2829
- const stackName = bootstrap?.stackName || SST_STACK_NAME;
2830
- let result;
2843
+ function filterOutputs(input) {
2844
+ return pipe(
2845
+ input,
2846
+ omitBy((_, key) => {
2847
+ return key.startsWith("Export") || key === "SSTMetadata";
2848
+ })
2849
+ );
2850
+ }
2851
+ var STATUSES_PENDING, STATUSES_SUCCESS, STATUSES_FAILED, STATUSES;
2852
+ var init_monitor = __esm({
2853
+ "src/stacks/monitor.ts"() {
2854
+ "use strict";
2855
+ init_bus();
2856
+ init_credentials();
2857
+ init_logger();
2858
+ STATUSES_PENDING = [
2859
+ "CREATE_IN_PROGRESS",
2860
+ "DELETE_IN_PROGRESS",
2861
+ "REVIEW_IN_PROGRESS",
2862
+ "ROLLBACK_IN_PROGRESS",
2863
+ "UPDATE_COMPLETE_CLEANUP_IN_PROGRESS",
2864
+ "UPDATE_IN_PROGRESS",
2865
+ "UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS",
2866
+ "UPDATE_ROLLBACK_IN_PROGRESS"
2867
+ ];
2868
+ STATUSES_SUCCESS = [
2869
+ "CREATE_COMPLETE",
2870
+ "UPDATE_COMPLETE",
2871
+ "DELETE_COMPLETE",
2872
+ "SKIPPED"
2873
+ ];
2874
+ STATUSES_FAILED = [
2875
+ "CREATE_FAILED",
2876
+ "DELETE_FAILED",
2877
+ "ROLLBACK_FAILED",
2878
+ "ROLLBACK_COMPLETE",
2879
+ "UPDATE_FAILED",
2880
+ "UPDATE_ROLLBACK_COMPLETE",
2881
+ "UPDATE_ROLLBACK_FAILED",
2882
+ "DEPENDENCY_FAILED"
2883
+ ];
2884
+ STATUSES = [
2885
+ ...STATUSES_PENDING,
2886
+ ...STATUSES_SUCCESS,
2887
+ ...STATUSES_FAILED
2888
+ ];
2889
+ }
2890
+ });
2891
+
2892
+ // src/cdk/util.ts
2893
+ async function callWithRetry(cb) {
2831
2894
  try {
2832
- result = await cf.send(
2833
- new DescribeStacksCommand({
2834
- StackName: stackName
2835
- })
2836
- );
2895
+ return await cb();
2837
2896
  } catch (e) {
2838
- if (e.Code === "ValidationError" && e.message === `Stack with id ${stackName} does not exist`) {
2839
- return null;
2897
+ if (e.code === "ThrottlingException" && e.message === "Rate exceeded" || e.code === "Throttling" && e.message === "Rate exceeded" || e.code === "TooManyRequestsException" && e.message === "Too Many Requests" || e.code === "OperationAbortedException" || e.code === "TimeoutError" || e.code === "NetworkingError") {
2898
+ return await callWithRetry(cb);
2840
2899
  }
2841
2900
  throw e;
2842
2901
  }
2843
- let version2, bucket;
2844
- (result.Stacks[0].Outputs || []).forEach((o) => {
2845
- if (o.OutputKey === OUTPUT_VERSION) {
2846
- version2 = o.OutputValue;
2847
- } else if (o.OutputKey === OUTPUT_BUCKET) {
2848
- bucket = o.OutputValue;
2849
- }
2850
- });
2851
- if (!version2 || !bucket) {
2852
- return null;
2853
- }
2854
- return { version: version2, bucket };
2855
2902
  }
2856
- async function bootstrapSST() {
2857
- const { region, bootstrap, cdk } = useProject().config;
2858
- const app = new App();
2859
- const stackName = bootstrap?.stackName || SST_STACK_NAME;
2860
- const stack = new Stack(app, stackName, {
2861
- env: {
2862
- region
2863
- },
2864
- synthesizer: new DefaultStackSynthesizer({
2865
- qualifier: cdk?.qualifier,
2866
- fileAssetsBucketName: cdk?.fileAssetsBucketName
2867
- })
2868
- });
2869
- for (const [key, value] of Object.entries(bootstrap?.tags || {})) {
2870
- Tags.of(app).add(key, value);
2871
- }
2872
- const bucket = new Bucket(stack, region, {
2873
- encryption: BucketEncryption.S3_MANAGED,
2874
- removalPolicy: RemovalPolicy.DESTROY,
2875
- autoDeleteObjects: true,
2876
- blockPublicAccess: cdk?.publicAccessBlockConfiguration !== false ? BlockPublicAccess.BLOCK_ALL : void 0
2877
- });
2878
- const fn = new Function(stack, "MetadataHandler", {
2879
- code: Code.fromAsset(
2880
- path8.resolve(__dirname, "support/bootstrap-metadata-function")
2881
- ),
2882
- handler: "index.handler",
2883
- runtime: region?.startsWith("us-gov-") ? Runtime.NODEJS_16_X : Runtime.NODEJS_18_X,
2884
- environment: {
2885
- BUCKET_NAME: bucket.bucketName
2886
- },
2887
- initialPolicy: [
2888
- new PolicyStatement({
2889
- actions: ["cloudformation:DescribeStacks"],
2890
- resources: ["*"]
2891
- }),
2892
- new PolicyStatement({
2893
- actions: ["s3:PutObject", "s3:DeleteObject"],
2894
- resources: [bucket.bucketArn + "/*"]
2895
- }),
2896
- new PolicyStatement({
2897
- actions: ["iot:Publish"],
2898
- resources: [
2899
- `arn:${stack.partition}:iot:${stack.region}:${stack.account}:topic//sst/*`
2900
- ]
2901
- })
2902
- ]
2903
- });
2904
- const queue = new Queue(stack, "MetadataQueue", {
2905
- visibilityTimeout: Duration.seconds(30),
2906
- retentionPeriod: Duration.minutes(2)
2907
- });
2908
- fn.addEventSource(new SqsEventSource(queue));
2909
- const rule = new Rule(stack, "MetadataRule", {
2910
- eventPattern: {
2911
- source: ["aws.cloudformation"],
2912
- detailType: ["CloudFormation Stack Status Change"],
2913
- detail: {
2914
- "status-details": {
2915
- status: [
2916
- "CREATE_COMPLETE",
2917
- "UPDATE_COMPLETE",
2918
- "UPDATE_ROLLBACK_COMPLETE",
2919
- "ROLLBACK_COMPLETE",
2920
- "DELETE_COMPLETE"
2921
- ]
2922
- }
2923
- }
2924
- }
2925
- });
2926
- rule.addTarget(
2927
- new SqsQueue(queue, {
2928
- retryAttempts: 10
2929
- })
2930
- );
2931
- new CfnOutput(stack, OUTPUT_VERSION, { value: LATEST_VERSION });
2932
- new CfnOutput(stack, OUTPUT_BUCKET, { value: bucket.bucketName });
2933
- const asm = app.synth();
2934
- const result = await stacks_exports.deploy(asm.stacks[0]);
2935
- if (stacks_exports.isFailed(result.status)) {
2936
- throw new VisibleError(
2937
- `Failed to deploy bootstrap stack:
2938
- ${JSON.stringify(
2939
- result.errors,
2940
- null,
2941
- 4
2942
- )}`
2943
- );
2944
- }
2945
- }
2946
- async function bootstrapCDK() {
2947
- const identity = await useSTSIdentity();
2948
- const credentials = await useAWSCredentials();
2949
- const { region, profile, cdk } = useProject().config;
2950
- cdk || {};
2951
- await new Promise((resolve, reject) => {
2952
- const proc = spawn(
2953
- [
2954
- "npx",
2955
- "cdk",
2956
- "bootstrap",
2957
- `aws://${identity.Account}/${region}`,
2958
- "--no-version-reporting",
2959
- ...cdk?.publicAccessBlockConfiguration === false ? ["--public-access-block-configuration", "false"] : cdk?.publicAccessBlockConfiguration === true ? ["--public-access-block-configuration", "false"] : [],
2960
- ...cdk?.toolkitStackName ? ["--toolkit-stack-name", cdk.toolkitStackName] : [],
2961
- ...cdk?.qualifier ? ["--qualifier", cdk.qualifier] : [],
2962
- ...cdk?.fileAssetsBucketName ? ["--toolkit-bucket-name", cdk.fileAssetsBucketName] : []
2963
- ].join(" "),
2964
- {
2965
- env: {
2966
- ...process.env,
2967
- AWS_ACCESS_KEY_ID: credentials.accessKeyId,
2968
- AWS_SECRET_ACCESS_KEY: credentials.secretAccessKey,
2969
- AWS_SESSION_TOKEN: credentials.sessionToken,
2970
- AWS_REGION: region,
2971
- AWS_PROFILE: profile
2972
- },
2973
- stdio: "pipe",
2974
- shell: true
2975
- }
2976
- );
2977
- let stderr = "";
2978
- proc.stdout.on("data", (data2) => {
2979
- Logger.debug(data2.toString());
2980
- });
2981
- proc.stderr.on("data", (data2) => {
2982
- Logger.debug(data2.toString());
2983
- stderr += data2;
2984
- });
2985
- proc.on("exit", (code) => {
2986
- Logger.debug("CDK bootstrap exited with code " + code);
2987
- if (code === 0) {
2988
- resolve();
2989
- } else {
2990
- console.log(bold(dim(stderr)));
2991
- reject(new VisibleError(`Failed to bootstrap`));
2992
- }
2993
- });
2994
- });
2995
- }
2996
- var CDK_STACK_NAME, SST_STACK_NAME, OUTPUT_VERSION, OUTPUT_BUCKET, LATEST_VERSION, __dirname, useBootstrap;
2997
- var init_bootstrap = __esm({
2998
- "src/bootstrap.ts"() {
2999
- "use strict";
3000
- init_project();
3001
- init_spinner();
3002
- init_context();
3003
- init_credentials();
3004
- init_error();
3005
- init_logger();
3006
- init_stacks();
3007
- CDK_STACK_NAME = "CDKToolkit";
3008
- SST_STACK_NAME = "SSTBootstrap";
3009
- OUTPUT_VERSION = "Version";
3010
- OUTPUT_BUCKET = "BucketName";
3011
- LATEST_VERSION = "7";
3012
- __dirname = url3.fileURLToPath(new URL(".", import.meta.url));
3013
- useBootstrap = Context.memo(async () => {
3014
- Logger.debug("Initializing bootstrap context");
3015
- let [cdkStatus, sstStatus] = await Promise.all([
3016
- loadCDKStatus(),
3017
- loadSSTStatus()
3018
- ]);
3019
- Logger.debug("Loaded bootstrap status");
3020
- const needToBootstrapCDK = !cdkStatus;
3021
- const needToBootstrapSST = !sstStatus || sstStatus.version !== LATEST_VERSION;
3022
- if (needToBootstrapCDK || needToBootstrapSST) {
3023
- const spinner = createSpinner(
3024
- "Deploying bootstrap stack, this only needs to happen once"
3025
- ).start();
3026
- if (needToBootstrapCDK) {
3027
- await bootstrapCDK();
3028
- }
3029
- if (needToBootstrapSST) {
3030
- await bootstrapSST();
3031
- sstStatus = await loadSSTStatus();
3032
- if (!sstStatus)
3033
- throw new VisibleError("Failed to load bootstrap stack status");
3034
- }
3035
- spinner.succeed();
3036
- }
3037
- Logger.debug("Bootstrap context initialized", sstStatus);
3038
- return sstStatus;
3039
- }, "Bootstrap");
3040
- }
3041
- });
3042
-
3043
- // src/stacks/app-metadata.ts
3044
- import {
3045
- S3Client,
3046
- GetObjectCommand,
3047
- PutObjectCommand,
3048
- DeleteObjectCommand
3049
- } from "@aws-sdk/client-s3";
3050
- async function metadata() {
3051
- Logger.debug("Fetching app metadata");
3052
- const [project, credentials, bootstrap] = await Promise.all([
3053
- useProject(),
3054
- useAWSCredentials(),
3055
- useBootstrap()
3056
- ]);
3057
- const s3 = new S3Client({
3058
- region: project.config.region,
3059
- credentials
3060
- });
3061
- try {
3062
- const result = await s3.send(
3063
- new GetObjectCommand({
3064
- Key: useS3Key(),
3065
- Bucket: bootstrap.bucket
3066
- })
3067
- );
3068
- const body = await result.Body.transformToString();
3069
- return JSON.parse(body);
3070
- } catch (ex) {
3071
- Logger.debug("Fetching app metadata: not found");
3072
- }
3073
- }
3074
- async function saveAppMetadata(data2) {
3075
- Logger.debug("Saving app metadata");
3076
- const [project, credentials, bootstrap] = await Promise.all([
3077
- useProject(),
3078
- useAWSCredentials(),
3079
- useBootstrap()
3080
- ]);
3081
- const s3 = new S3Client({
3082
- region: project.config.region,
3083
- credentials
3084
- });
3085
- try {
3086
- await s3.send(
3087
- new PutObjectCommand({
3088
- Key: useS3Key(),
3089
- Bucket: bootstrap.bucket,
3090
- Body: JSON.stringify(data2)
3091
- })
3092
- );
3093
- } catch (ex) {
3094
- Logger.debug("Saving app metadata: not found");
3095
- }
3096
- }
3097
- async function clearAppMetadata() {
3098
- Logger.debug("Clearing app metadata");
3099
- const [project, credentials, bootstrap] = await Promise.all([
3100
- useProject(),
3101
- useAWSCredentials(),
3102
- useBootstrap()
3103
- ]);
3104
- const s3 = new S3Client({
3105
- region: project.config.region,
3106
- credentials
3107
- });
3108
- await s3.send(
3109
- new DeleteObjectCommand({
3110
- Key: useS3Key(),
3111
- Bucket: bootstrap.bucket
3112
- })
3113
- );
3114
- }
3115
- function useS3Key() {
3116
- const project = useProject();
3117
- return `appMetadata/app.${project.config.name}/stage.${project.config.stage}.json`;
3118
- }
3119
- var MetadataContext, useAppMetadata;
3120
- var init_app_metadata = __esm({
3121
- "src/stacks/app-metadata.ts"() {
3122
- "use strict";
3123
- init_bootstrap();
3124
- init_credentials();
3125
- init_context();
3126
- init_logger();
3127
- init_project();
3128
- MetadataContext = Context.create(async () => {
3129
- const data2 = await metadata();
3130
- return data2;
3131
- });
3132
- useAppMetadata = MetadataContext.use;
3133
- }
3134
- });
3135
-
3136
- // src/stacks/assembly.ts
3137
- async function loadAssembly(from) {
3138
- const { CloudAssembly } = await import("aws-cdk-lib/cx-api");
3139
- return new CloudAssembly(from);
3140
- }
3141
- var init_assembly = __esm({
3142
- "src/stacks/assembly.ts"() {
3143
- "use strict";
3144
- }
3145
- });
3146
-
3147
- // src/stacks/monitor.ts
3148
- import {
3149
- CloudFormationClient as CloudFormationClient2,
3150
- DescribeStackResourcesCommand,
3151
- DescribeStacksCommand as DescribeStacksCommand2,
3152
- DescribeStackEventsCommand
3153
- } from "@aws-sdk/client-cloudformation";
3154
- import { map, omitBy, pipe } from "remeda";
3155
- function isFinal(input) {
3156
- return STATUSES_SUCCESS.includes(input) || STATUSES_FAILED.includes(input);
3157
- }
3158
- function isFailed(input) {
3159
- return STATUSES_FAILED.includes(input);
3160
- }
3161
- function isSuccess(input) {
3162
- return STATUSES_SUCCESS.includes(input);
3163
- }
3164
- function isPending(input) {
3165
- return STATUSES_PENDING.includes(input);
3166
- }
3167
- async function monitor(stack) {
3168
- const [cfn, bus] = await Promise.all([
3169
- useAWSClient(CloudFormationClient2),
3170
- useBus()
3171
- ]);
3172
- let lastStatus;
3173
- const errors = {};
3174
- let lastEvent;
3175
- while (true) {
3176
- try {
3177
- const [describe, resources, events] = await Promise.all([
3178
- cfn.send(
3179
- new DescribeStacksCommand2({
3180
- StackName: stack
3181
- })
3182
- ),
3183
- cfn.send(
3184
- new DescribeStackResourcesCommand({
3185
- StackName: stack
3186
- })
3187
- ),
3188
- cfn.send(
3189
- new DescribeStackEventsCommand({
3190
- StackName: stack
3191
- })
3192
- )
3193
- ]);
3194
- Logger.debug("Stack description", describe);
3195
- if (lastEvent) {
3196
- const eventsReversed = [...events.StackEvents ?? []].reverse();
3197
- for (const event of eventsReversed) {
3198
- if (!event.Timestamp)
3199
- continue;
3200
- if (event.Timestamp.getTime() > lastEvent.getTime()) {
3201
- bus.publish("stack.event", {
3202
- event,
3203
- stackID: stack
3204
- });
3205
- if (event.ResourceStatusReason) {
3206
- if (event.ResourceStatusReason.includes(
3207
- "Resource creation cancelled"
3208
- ) || event.ResourceStatusReason.includes(
3209
- "Resource update cancelled"
3210
- ) || event.ResourceStatusReason.includes(
3211
- "Resource creation Initiated"
3212
- ) || event.ResourceStatusReason.startsWith(
3213
- "The following resource(s) failed to"
3214
- ))
3215
- continue;
3216
- errors[event.LogicalResourceId] = event.ResourceStatusReason;
3217
- }
3218
- }
3219
- }
3220
- Logger.debug("Last event set to", lastEvent);
3221
- }
3222
- lastEvent = events.StackEvents?.at(0)?.Timestamp;
3223
- bus.publish("stack.resources", {
3224
- stackID: stack,
3225
- resources: resources.StackResources
3226
- });
3227
- for (const resource of resources.StackResources || []) {
3228
- if (resource.ResourceStatusReason?.includes(
3229
- "Resource creation cancelled"
3230
- ) || resource.ResourceStatusReason?.includes(
3231
- "Resource update cancelled"
3232
- ) || resource.ResourceStatusReason?.includes(
3233
- "Resource creation Initiated"
3234
- ) || resource.ResourceStatusReason?.startsWith(
3235
- "The following resource(s) failed to"
3236
- ))
3237
- continue;
3238
- if (resource.ResourceStatusReason)
3239
- errors[resource.LogicalResourceId] = resource.ResourceStatusReason;
3240
- }
3241
- const [first] = describe.Stacks || [];
3242
- if (first) {
3243
- if (lastStatus !== first.StackStatus && first.StackStatus) {
3244
- lastStatus = first.StackStatus;
3245
- bus.publish("stack.status", {
3246
- stackID: stack,
3247
- status: first.StackStatus
3248
- });
3249
- Logger.debug(first);
3250
- if (isFinal(first.StackStatus)) {
3251
- return {
3252
- status: first.StackStatus,
3253
- outputs: pipe(
3254
- first.Outputs || [],
3255
- map((o) => [o.OutputKey, o.OutputValue]),
3256
- Object.fromEntries,
3257
- filterOutputs
3258
- ),
3259
- errors: isFailed(first.StackStatus) ? errors : {}
3260
- };
3261
- }
3262
- }
3263
- }
3264
- } catch (ex) {
3265
- if (ex.message.includes("does not exist")) {
3266
- bus.publish("stack.status", {
3267
- stackID: stack,
3268
- status: "DELETE_COMPLETE"
3269
- });
3270
- return {
3271
- status: "DELETE_COMPLETE",
3272
- outputs: {},
3273
- errors: {}
3274
- };
3275
- }
3276
- }
3277
- await new Promise((resolve) => setTimeout(resolve, 1e3));
3278
- }
3279
- }
3280
- function filterOutputs(input) {
3281
- return pipe(
3282
- input,
3283
- omitBy((_, key) => {
3284
- return key.startsWith("Export") || key === "SSTMetadata";
3285
- })
3286
- );
3287
- }
3288
- var STATUSES_PENDING, STATUSES_SUCCESS, STATUSES_FAILED, STATUSES;
3289
- var init_monitor = __esm({
3290
- "src/stacks/monitor.ts"() {
3291
- "use strict";
3292
- init_bus();
3293
- init_credentials();
3294
- init_logger();
3295
- STATUSES_PENDING = [
3296
- "CREATE_IN_PROGRESS",
3297
- "DELETE_IN_PROGRESS",
3298
- "REVIEW_IN_PROGRESS",
3299
- "ROLLBACK_IN_PROGRESS",
3300
- "UPDATE_COMPLETE_CLEANUP_IN_PROGRESS",
3301
- "UPDATE_IN_PROGRESS",
3302
- "UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS",
3303
- "UPDATE_ROLLBACK_IN_PROGRESS"
3304
- ];
3305
- STATUSES_SUCCESS = [
3306
- "CREATE_COMPLETE",
3307
- "UPDATE_COMPLETE",
3308
- "DELETE_COMPLETE",
3309
- "SKIPPED"
3310
- ];
3311
- STATUSES_FAILED = [
3312
- "CREATE_FAILED",
3313
- "DELETE_FAILED",
3314
- "ROLLBACK_FAILED",
3315
- "ROLLBACK_COMPLETE",
3316
- "UPDATE_FAILED",
3317
- "UPDATE_ROLLBACK_COMPLETE",
3318
- "UPDATE_ROLLBACK_FAILED",
3319
- "DEPENDENCY_FAILED"
3320
- ];
3321
- STATUSES = [
3322
- ...STATUSES_PENDING,
3323
- ...STATUSES_SUCCESS,
3324
- ...STATUSES_FAILED
3325
- ];
3326
- }
3327
- });
3328
-
3329
- // src/cdk/util.ts
3330
- async function callWithRetry(cb) {
3331
- try {
3332
- return await cb();
3333
- } catch (e) {
3334
- if (e.code === "ThrottlingException" && e.message === "Rate exceeded" || e.code === "Throttling" && e.message === "Rate exceeded" || e.code === "TooManyRequestsException" && e.message === "Too Many Requests" || e.code === "OperationAbortedException" || e.code === "TimeoutError" || e.code === "NetworkingError") {
3335
- return await callWithRetry(cb);
3336
- }
3337
- throw e;
3338
- }
3339
- }
3340
- var init_util = __esm({
3341
- "src/cdk/util.ts"() {
3342
- "use strict";
2903
+ var init_util = __esm({
2904
+ "src/cdk/util.ts"() {
2905
+ "use strict";
3343
2906
  }
3344
2907
  });
3345
2908
 
@@ -4625,7 +4188,7 @@ var init_diff = __esm({
4625
4188
  });
4626
4189
 
4627
4190
  // src/cache.ts
4628
- import path9 from "path";
4191
+ import path8 from "path";
4629
4192
  import fs9 from "fs/promises";
4630
4193
  var useCache;
4631
4194
  var init_cache = __esm({
@@ -4636,17 +4199,17 @@ var init_cache = __esm({
4636
4199
  init_context();
4637
4200
  useCache = Context.memo(async () => {
4638
4201
  const project = useProject();
4639
- const cache = path9.join(project.paths.out, "cache");
4202
+ const cache = path8.join(project.paths.out, "cache");
4640
4203
  await fs9.mkdir(cache, {
4641
4204
  recursive: true
4642
4205
  });
4643
4206
  async function write(key, data2) {
4644
- const full = path9.join(cache, key);
4207
+ const full = path8.join(cache, key);
4645
4208
  Logger.debug("Writing cache", full, data2.length, "bytes");
4646
4209
  await fs9.writeFile(full, data2);
4647
4210
  }
4648
4211
  async function read(key) {
4649
- const full = path9.join(cache, key);
4212
+ const full = path8.join(cache, key);
4650
4213
  try {
4651
4214
  const data2 = await fs9.readFile(full);
4652
4215
  return data2.toString();
@@ -4782,8 +4345,8 @@ var init_process = __esm({
4782
4345
  });
4783
4346
 
4784
4347
  // src/runtime/handlers/dotnet.ts
4785
- import { spawn as spawn2 } from "child_process";
4786
- import url4 from "url";
4348
+ import { spawn } from "child_process";
4349
+ import url3 from "url";
4787
4350
  var FRAMEWORK_MAP, BOOTSTRAP_MAP, useDotnetHandler;
4788
4351
  var init_dotnet = __esm({
4789
4352
  "src/runtime/handlers/dotnet.ts"() {
@@ -4828,11 +4391,11 @@ var init_dotnet = __esm({
4828
4391
  canHandle: (input) => input.startsWith("dotnet"),
4829
4392
  startWorker: async (input) => {
4830
4393
  const name = input.handler.split(":")[0];
4831
- const proc = spawn2(
4394
+ const proc = spawn(
4832
4395
  `dotnet`,
4833
4396
  [
4834
4397
  `exec`,
4835
- url4.fileURLToPath(
4398
+ url3.fileURLToPath(
4836
4399
  new URL(
4837
4400
  `../../support/${BOOTSTRAP_MAP["dotnetcore3.1"]}/release/dotnet-bootstrap.dll`,
4838
4401
  import.meta.url
@@ -4915,12 +4478,12 @@ var node_exports = {};
4915
4478
  __export(node_exports, {
4916
4479
  useNodeHandler: () => useNodeHandler
4917
4480
  });
4918
- import path10 from "path";
4481
+ import path9 from "path";
4919
4482
  import fs10 from "fs/promises";
4920
4483
  import { exec as exec2 } from "child_process";
4921
4484
  import fsSync2 from "fs";
4922
4485
  import esbuild2 from "esbuild";
4923
- import url5 from "url";
4486
+ import url4 from "url";
4924
4487
  import { Worker } from "worker_threads";
4925
4488
  var useNodeHandler;
4926
4489
  var init_node = __esm({
@@ -4943,14 +4506,14 @@ var init_node = __esm({
4943
4506
  const result = cache[input.functionID];
4944
4507
  if (!result)
4945
4508
  return false;
4946
- const relative = path10.relative(project.paths.root, input.file).split(path10.sep).join(path10.posix.sep);
4509
+ const relative = path9.relative(project.paths.root, input.file).split(path9.sep).join(path9.posix.sep);
4947
4510
  return Boolean(result.metafile?.inputs[relative]);
4948
4511
  },
4949
4512
  canHandle: (input) => input.startsWith("nodejs"),
4950
4513
  startWorker: async (input) => {
4951
4514
  new Promise(async () => {
4952
4515
  const worker = new Worker(
4953
- url5.fileURLToPath(
4516
+ url4.fileURLToPath(
4954
4517
  new URL("../../support/nodejs-runtime/index.mjs", import.meta.url)
4955
4518
  ),
4956
4519
  {
@@ -4982,7 +4545,7 @@ var init_node = __esm({
4982
4545
  },
4983
4546
  build: async (input) => {
4984
4547
  const exists = cache[input.functionID];
4985
- const parsed = path10.parse(input.props.handler);
4548
+ const parsed = path9.parse(input.props.handler);
4986
4549
  const file = [
4987
4550
  ".ts",
4988
4551
  ".tsx",
@@ -4992,7 +4555,7 @@ var init_node = __esm({
4992
4555
  ".jsx",
4993
4556
  ".mjs",
4994
4557
  ".cjs"
4995
- ].map((ext) => path10.join(parsed.dir, parsed.name + ext)).find((file2) => {
4558
+ ].map((ext) => path9.join(parsed.dir, parsed.name + ext)).find((file2) => {
4996
4559
  return fsSync2.existsSync(file2);
4997
4560
  });
4998
4561
  if (!file)
@@ -5002,17 +4565,17 @@ var init_node = __esm({
5002
4565
  };
5003
4566
  const nodejs = input.props.nodejs || {};
5004
4567
  const isESM = (nodejs.format || "esm") === "esm";
5005
- const relative = path10.relative(
4568
+ const relative = path9.relative(
5006
4569
  project.paths.root,
5007
- path10.resolve(parsed.dir)
4570
+ path9.resolve(parsed.dir)
5008
4571
  );
5009
4572
  const extension = isESM ? ".mjs" : ".cjs";
5010
- const target = path10.join(
4573
+ const target = path9.join(
5011
4574
  input.out,
5012
- !relative.startsWith("..") && !path10.isAbsolute(input.props.handler) ? relative : "",
4575
+ !relative.startsWith("..") && !path9.isAbsolute(input.props.handler) ? relative : "",
5013
4576
  parsed.name + extension
5014
4577
  );
5015
- const handler = path10.relative(input.out, target.replace(extension, parsed.ext)).split(path10.sep).join(path10.posix.sep);
4578
+ const handler = path9.relative(input.out, target.replace(extension, parsed.ext)).split(path9.sep).join(path9.posix.sep);
5016
4579
  if (exists?.rebuild) {
5017
4580
  const result = await exists.rebuild();
5018
4581
  cache[input.functionID] = result;
@@ -5086,17 +4649,17 @@ var init_node = __esm({
5086
4649
  async function find2(dir, target2) {
5087
4650
  if (dir === "/")
5088
4651
  throw new VisibleError("Could not find a package.json file");
5089
- if (await fs10.access(path10.join(dir, target2)).then(() => true).catch(() => false))
4652
+ if (await fs10.access(path9.join(dir, target2)).then(() => true).catch(() => false))
5090
4653
  return dir;
5091
- return find2(path10.join(dir, ".."), target2);
4654
+ return find2(path9.join(dir, ".."), target2);
5092
4655
  }
5093
4656
  if (input.mode === "deploy" && installPackages) {
5094
4657
  const src = await find2(parsed.dir, "package.json");
5095
4658
  const json = JSON.parse(
5096
- await fs10.readFile(path10.join(src, "package.json")).then((x) => x.toString())
4659
+ await fs10.readFile(path9.join(src, "package.json")).then((x) => x.toString())
5097
4660
  );
5098
4661
  fs10.writeFile(
5099
- path10.join(input.out, "package.json"),
4662
+ path9.join(input.out, "package.json"),
5100
4663
  JSON.stringify({
5101
4664
  dependencies: Object.fromEntries(
5102
4665
  installPackages.map((x) => [x, json.dependencies?.[x] || "*"])
@@ -5118,14 +4681,14 @@ var init_node = __esm({
5118
4681
  });
5119
4682
  }
5120
4683
  if (input.mode === "start") {
5121
- const dir = path10.join(
4684
+ const dir = path9.join(
5122
4685
  await find2(parsed.dir, "package.json"),
5123
4686
  "node_modules"
5124
4687
  );
5125
4688
  try {
5126
4689
  await fs10.symlink(
5127
- path10.resolve(dir),
5128
- path10.resolve(path10.join(input.out, "node_modules")),
4690
+ path9.resolve(dir),
4691
+ path9.resolve(path9.join(input.out, "node_modules")),
5129
4692
  "dir"
5130
4693
  );
5131
4694
  } catch {
@@ -5164,16 +4727,16 @@ var go_exports = {};
5164
4727
  __export(go_exports, {
5165
4728
  useGoHandler: () => useGoHandler
5166
4729
  });
5167
- import path11 from "path";
4730
+ import path10 from "path";
5168
4731
  import fs11 from "fs/promises";
5169
- import { exec as exec3, spawn as spawn3 } from "child_process";
4732
+ import { exec as exec3, spawn as spawn2 } from "child_process";
5170
4733
  import { promisify as promisify2 } from "util";
5171
4734
  async function find(dir, target) {
5172
4735
  if (dir === "/")
5173
4736
  throw new VisibleError(`Could not find a ${target} file`);
5174
- if (await fs11.access(path11.join(dir, target)).then(() => true).catch(() => false))
4737
+ if (await fs11.access(path10.join(dir, target)).then(() => true).catch(() => false))
5175
4738
  return dir;
5176
- return find(path11.join(dir, ".."), target);
4739
+ return find(path10.join(dir, ".."), target);
5177
4740
  }
5178
4741
  var execAsync2, useGoHandler;
5179
4742
  var init_go = __esm({
@@ -5202,7 +4765,7 @@ var init_go = __esm({
5202
4765
  },
5203
4766
  canHandle: (input) => input.startsWith("go"),
5204
4767
  startWorker: async (input) => {
5205
- const proc = spawn3(path11.join(input.out, handlerName), {
4768
+ const proc = spawn2(path10.join(input.out, handlerName), {
5206
4769
  env: {
5207
4770
  ...process.env,
5208
4771
  ...input.environment,
@@ -5228,13 +4791,13 @@ var init_go = __esm({
5228
4791
  }
5229
4792
  },
5230
4793
  build: async (input) => {
5231
- const parsed = path11.parse(input.props.handler);
4794
+ const parsed = path10.parse(input.props.handler);
5232
4795
  const project = await find(parsed.dir, "go.mod");
5233
4796
  sources.set(input.functionID, project);
5234
- const src = path11.relative(project, input.props.handler);
4797
+ const src = path10.relative(project, input.props.handler);
5235
4798
  if (input.mode === "start") {
5236
4799
  try {
5237
- const target = path11.join(input.out, handlerName);
4800
+ const target = path10.join(input.out, handlerName);
5238
4801
  const result = await execAsync2(
5239
4802
  `go build -ldflags '-s -w' -o ${target} ./${src}`,
5240
4803
  {
@@ -5250,7 +4813,7 @@ var init_go = __esm({
5250
4813
  }
5251
4814
  if (input.mode === "deploy") {
5252
4815
  try {
5253
- const target = path11.join(input.out, "bootstrap");
4816
+ const target = path10.join(input.out, "bootstrap");
5254
4817
  await execAsync2(`go build -ldflags '-s -w' -o ${target} ./${src}`, {
5255
4818
  cwd: project,
5256
4819
  env: {
@@ -5279,9 +4842,9 @@ var rust_exports = {};
5279
4842
  __export(rust_exports, {
5280
4843
  useRustHandler: () => useRustHandler
5281
4844
  });
5282
- import path12 from "path";
4845
+ import path11 from "path";
5283
4846
  import fs12 from "fs/promises";
5284
- import { exec as exec4, spawn as spawn4 } from "child_process";
4847
+ import { exec as exec4, spawn as spawn3 } from "child_process";
5285
4848
  import { promisify as promisify3 } from "util";
5286
4849
  var execAsync3, useRustHandler;
5287
4850
  var init_rust = __esm({
@@ -5313,7 +4876,7 @@ var init_rust = __esm({
5313
4876
  },
5314
4877
  canHandle: (input) => input.startsWith("rust"),
5315
4878
  startWorker: async (input) => {
5316
- const proc = spawn4(path12.join(input.out, handlerName), {
4879
+ const proc = spawn3(path11.join(input.out, handlerName), {
5317
4880
  env: {
5318
4881
  ...process.env,
5319
4882
  ...input.environment,
@@ -5341,7 +4904,7 @@ var init_rust = __esm({
5341
4904
  }
5342
4905
  },
5343
4906
  build: async (input) => {
5344
- const parsed = path12.parse(input.props.handler);
4907
+ const parsed = path11.parse(input.props.handler);
5345
4908
  const project = await findAbove(parsed.dir, "Cargo.toml");
5346
4909
  if (!project)
5347
4910
  return {
@@ -5358,8 +4921,8 @@ var init_rust = __esm({
5358
4921
  }
5359
4922
  });
5360
4923
  await fs12.cp(
5361
- path12.join(project, `target/debug`, parsed.name),
5362
- path12.join(input.out, "handler")
4924
+ path11.join(project, `target/debug`, parsed.name),
4925
+ path11.join(input.out, "handler")
5363
4926
  );
5364
4927
  } catch (ex) {
5365
4928
  throw new VisibleError("Failed to build");
@@ -5374,8 +4937,8 @@ var init_rust = __esm({
5374
4937
  }
5375
4938
  });
5376
4939
  await fs12.cp(
5377
- path12.join(project, `target/lambda/`, parsed.name, "bootstrap"),
5378
- path12.join(input.out, "bootstrap")
4940
+ path11.join(project, `target/lambda/`, parsed.name, "bootstrap"),
4941
+ path11.join(input.out, "bootstrap")
5379
4942
  );
5380
4943
  } catch (ex) {
5381
4944
  throw new VisibleError("Failed to build");
@@ -5393,8 +4956,8 @@ var init_rust = __esm({
5393
4956
 
5394
4957
  // src/runtime/handlers/pythonBundling.ts
5395
4958
  import fs13 from "fs";
5396
- import url6 from "url";
5397
- import path13 from "path";
4959
+ import url5 from "url";
4960
+ import path12 from "path";
5398
4961
  import {
5399
4962
  DockerImage,
5400
4963
  FileSystem
@@ -5409,8 +4972,8 @@ function bundle(options) {
5409
4972
  );
5410
4973
  const dockerfile = hasInstallCommands ? "Dockerfile.custom" : hasDeps ? "Dockerfile.dependencies" : "Dockerfile";
5411
4974
  fs13.copyFileSync(
5412
- path13.join(__dirname2, "../../support/python-runtime", dockerfile),
5413
- path13.join(stagedir, dockerfile)
4975
+ path12.join(__dirname, "../../support/python-runtime", dockerfile),
4976
+ path12.join(stagedir, dockerfile)
5414
4977
  );
5415
4978
  const image = DockerImage.fromBuild(stagedir, {
5416
4979
  buildArgs: {
@@ -5418,7 +4981,7 @@ function bundle(options) {
5418
4981
  },
5419
4982
  file: dockerfile
5420
4983
  });
5421
- const outputPath = path13.join(options.out, outputPathSuffix);
4984
+ const outputPath = path12.join(options.out, outputPathSuffix);
5422
4985
  if (hasDeps || hasInstallCommands) {
5423
4986
  image.cp(`${BUNDLER_DEPENDENCIES_CACHE}/.`, outputPath);
5424
4987
  }
@@ -5432,7 +4995,7 @@ function stageDependencies(entry, stagedir) {
5432
4995
  for (const file of fs13.readdirSync(entry)) {
5433
4996
  for (const prefix of prefixes) {
5434
4997
  if (file.startsWith(prefix)) {
5435
- fs13.copyFileSync(path13.join(entry, file), path13.join(stagedir, file));
4998
+ fs13.copyFileSync(path12.join(entry, file), path12.join(stagedir, file));
5436
4999
  found = true;
5437
5000
  }
5438
5001
  }
@@ -5442,18 +5005,18 @@ function stageDependencies(entry, stagedir) {
5442
5005
  function stageInstallCommands(installCommands, stagedir) {
5443
5006
  let found = false;
5444
5007
  if (installCommands.length > 0) {
5445
- const filePath = path13.join(stagedir, "sst-deps-install-command.sh");
5008
+ const filePath = path12.join(stagedir, "sst-deps-install-command.sh");
5446
5009
  fs13.writeFileSync(filePath, installCommands.join(" && "));
5447
5010
  fs13.chmodSync(filePath, "755");
5448
5011
  found = true;
5449
5012
  }
5450
5013
  return found;
5451
5014
  }
5452
- var __dirname2, BUNDLER_DEPENDENCIES_CACHE;
5015
+ var __dirname, BUNDLER_DEPENDENCIES_CACHE;
5453
5016
  var init_pythonBundling = __esm({
5454
5017
  "src/runtime/handlers/pythonBundling.ts"() {
5455
5018
  "use strict";
5456
- __dirname2 = path13.dirname(url6.fileURLToPath(import.meta.url));
5019
+ __dirname = path12.dirname(url5.fileURLToPath(import.meta.url));
5457
5020
  BUNDLER_DEPENDENCIES_CACHE = "/var/dependencies";
5458
5021
  }
5459
5022
  });
@@ -5463,12 +5026,12 @@ var python_exports = {};
5463
5026
  __export(python_exports, {
5464
5027
  usePythonHandler: () => usePythonHandler
5465
5028
  });
5466
- import path14 from "path";
5467
- import { exec as exec5, spawn as spawn5 } from "child_process";
5029
+ import path13 from "path";
5030
+ import { exec as exec5, spawn as spawn4 } from "child_process";
5468
5031
  import { promisify as promisify4 } from "util";
5469
- import { Runtime as Runtime2 } from "aws-cdk-lib/aws-lambda";
5032
+ import { Runtime } from "aws-cdk-lib/aws-lambda";
5470
5033
  import os3 from "os";
5471
- import url7 from "url";
5034
+ import url6 from "url";
5472
5035
  var execAsync4, RUNTIME_MAP, usePythonHandler;
5473
5036
  var init_python = __esm({
5474
5037
  "src/runtime/handlers/python.ts"() {
@@ -5481,11 +5044,11 @@ var init_python = __esm({
5481
5044
  init_pythonBundling();
5482
5045
  execAsync4 = promisify4(exec5);
5483
5046
  RUNTIME_MAP = {
5484
- "python2.7": Runtime2.PYTHON_2_7,
5485
- "python3.6": Runtime2.PYTHON_3_6,
5486
- "python3.7": Runtime2.PYTHON_3_7,
5487
- "python3.8": Runtime2.PYTHON_3_8,
5488
- "python3.9": Runtime2.PYTHON_3_9
5047
+ "python2.7": Runtime.PYTHON_2_7,
5048
+ "python3.6": Runtime.PYTHON_3_6,
5049
+ "python3.7": Runtime.PYTHON_3_7,
5050
+ "python3.8": Runtime.PYTHON_3_8,
5051
+ "python3.9": Runtime.PYTHON_3_9
5489
5052
  };
5490
5053
  usePythonHandler = Context.memo(async () => {
5491
5054
  const workers = await useRuntimeWorkers();
@@ -5513,13 +5076,13 @@ var init_python = __esm({
5513
5076
  const src = await findSrc(input.handler);
5514
5077
  if (!src)
5515
5078
  throw new Error(`Could not find src for ${input.handler}`);
5516
- const parsed = path14.parse(path14.relative(src, input.handler));
5517
- const target = [...parsed.dir.split(path14.sep), parsed.name].join(".");
5518
- const proc = spawn5(
5079
+ const parsed = path13.parse(path13.relative(src, input.handler));
5080
+ const target = [...parsed.dir.split(path13.sep), parsed.name].join(".");
5081
+ const proc = spawn4(
5519
5082
  os3.platform() === "win32" ? "python.exe" : "python3",
5520
5083
  [
5521
5084
  "-u",
5522
- url7.fileURLToPath(
5085
+ url6.fileURLToPath(
5523
5086
  new URL("../../support/python-runtime/runtime.py", import.meta.url)
5524
5087
  ),
5525
5088
  target,
@@ -5575,7 +5138,7 @@ var init_python = __esm({
5575
5138
  });
5576
5139
  return {
5577
5140
  type: "success",
5578
- handler: path14.relative(src, path14.resolve(input.props.handler)).split(path14.sep).join(path14.posix.sep)
5141
+ handler: path13.relative(src, path13.resolve(input.props.handler)).split(path13.sep).join(path13.posix.sep)
5579
5142
  };
5580
5143
  }
5581
5144
  });
@@ -5588,14 +5151,14 @@ var java_exports = {};
5588
5151
  __export(java_exports, {
5589
5152
  useJavaHandler: () => useJavaHandler
5590
5153
  });
5591
- import path15 from "path";
5154
+ import path14 from "path";
5592
5155
  import fs14 from "fs/promises";
5593
5156
  import os4 from "os";
5594
5157
  import zipLocal from "zip-local";
5595
- import { spawn as spawn6 } from "child_process";
5596
- import url8 from "url";
5158
+ import { spawn as spawn5 } from "child_process";
5159
+ import url7 from "url";
5597
5160
  async function getGradleBinary(srcPath) {
5598
- const gradleWrapperPath = path15.resolve(path15.join(srcPath, "gradlew"));
5161
+ const gradleWrapperPath = path14.resolve(path14.join(srcPath, "gradlew"));
5599
5162
  return await existsAsync(gradleWrapperPath) ? gradleWrapperPath : "gradle";
5600
5163
  }
5601
5164
  var useJavaHandler;
@@ -5627,12 +5190,12 @@ var init_java = __esm({
5627
5190
  },
5628
5191
  canHandle: (input) => input.startsWith("java"),
5629
5192
  startWorker: async (input) => {
5630
- const proc = spawn6(
5193
+ const proc = spawn5(
5631
5194
  `java`,
5632
5195
  [
5633
5196
  `-cp`,
5634
5197
  [
5635
- url8.fileURLToPath(
5198
+ url7.fileURLToPath(
5636
5199
  new URL("../../support/java-runtime/release/*", import.meta.url)
5637
5200
  )
5638
5201
  ].join(os4.platform() === "win32" ? ";" : ":"),
@@ -5679,11 +5242,11 @@ var init_java = __esm({
5679
5242
  cwd: srcPath
5680
5243
  }
5681
5244
  );
5682
- const buildOutput = path15.join(srcPath, "build", outputDir);
5245
+ const buildOutput = path14.join(srcPath, "build", outputDir);
5683
5246
  const zip = (await fs14.readdir(buildOutput)).find(
5684
5247
  (f) => f.endsWith(".zip")
5685
5248
  );
5686
- zipLocal.sync.unzip(path15.join(buildOutput, zip)).save(input.out);
5249
+ zipLocal.sync.unzip(path14.join(buildOutput, zip)).save(input.out);
5687
5250
  return {
5688
5251
  type: "success",
5689
5252
  handler: input.props.handler
@@ -5702,7 +5265,7 @@ var init_java = __esm({
5702
5265
 
5703
5266
  // src/stacks/synth.ts
5704
5267
  import * as contextproviders from "aws-cdk/lib/context-providers/index.js";
5705
- import path16 from "path";
5268
+ import path15 from "path";
5706
5269
  async function synth(opts) {
5707
5270
  Logger.debug("Synthesizing stacks...");
5708
5271
  const { App: App2 } = await import("../src/constructs/App.js");
@@ -5722,7 +5285,7 @@ async function synth(opts) {
5722
5285
  const identity = await useSTSIdentity();
5723
5286
  opts = {
5724
5287
  ...opts,
5725
- buildDir: opts.buildDir || path16.join(project.paths.out, "dist")
5288
+ buildDir: opts.buildDir || path15.join(project.paths.out, "dist")
5726
5289
  };
5727
5290
  const cfg = new Configuration();
5728
5291
  await cfg.load();
@@ -5765,166 +5328,632 @@ async function synth(opts) {
5765
5328
  }
5766
5329
  continue;
5767
5330
  }
5768
- Logger.debug("Finished synthesizing");
5769
- return assembly;
5331
+ Logger.debug("Finished synthesizing");
5332
+ return assembly;
5333
+ }
5334
+ }
5335
+ function formatErrorMessage(message) {
5336
+ return formatCustomDomainError(message) || `Could not resolve context values for ${message}`;
5337
+ }
5338
+ function formatCustomDomainError(message) {
5339
+ const ret = message.match(/hosted-zone:account=\d+:domainName=(\S+):/);
5340
+ if (!ret) {
5341
+ return;
5342
+ }
5343
+ const hostedZone = ret && ret[1];
5344
+ return [
5345
+ `It seems you are configuring custom domains for you URL.`,
5346
+ hostedZone ? `And SST is not able to find the hosted zone "${hostedZone}" in your AWS Route 53 account.` : `And SST is not able to find the hosted zone in your AWS Route 53 account.`,
5347
+ `Please double check and make sure the zone exists, or pass in a different zone.`
5348
+ ].join(" ");
5349
+ }
5350
+ var init_synth = __esm({
5351
+ "src/stacks/synth.ts"() {
5352
+ "use strict";
5353
+ init_logger();
5354
+ init_project();
5355
+ init_credentials();
5356
+ init_error();
5357
+ init_dotnet();
5358
+ }
5359
+ });
5360
+
5361
+ // src/stacks/remove.ts
5362
+ import {
5363
+ CloudFormationClient as CloudFormationClient2,
5364
+ DeleteStackCommand
5365
+ } from "@aws-sdk/client-cloudformation";
5366
+ async function removeMany(stacks) {
5367
+ await useAWSProvider();
5368
+ const bus = useBus();
5369
+ const complete = /* @__PURE__ */ new Set();
5370
+ const todo = new Set(stacks.map((s) => s.id));
5371
+ const results = {};
5372
+ return new Promise((resolve) => {
5373
+ async function trigger() {
5374
+ for (const stack of stacks) {
5375
+ if (!todo.has(stack.id))
5376
+ continue;
5377
+ Logger.debug("Checking if", stack.id, "can be removed");
5378
+ const waiting = stacks.filter((dependant) => {
5379
+ if (dependant.id === stack.id)
5380
+ return false;
5381
+ if (complete.has(dependant.id))
5382
+ return false;
5383
+ return dependant.dependencies?.some((d) => d.id === stack.id);
5384
+ });
5385
+ if (waiting.length) {
5386
+ Logger.debug(
5387
+ "Waiting on",
5388
+ waiting.map((s) => s.id)
5389
+ );
5390
+ continue;
5391
+ }
5392
+ remove(stack).then((result) => {
5393
+ results[stack.id] = result;
5394
+ complete.add(stack.id);
5395
+ if (isFailed(result.status))
5396
+ stacks.forEach((s) => {
5397
+ if (todo.delete(s.stackName)) {
5398
+ complete.add(s.stackName);
5399
+ results[s.id] = {
5400
+ status: "DEPENDENCY_FAILED",
5401
+ outputs: {},
5402
+ errors: {}
5403
+ };
5404
+ bus.publish("stack.status", {
5405
+ stackID: s.id,
5406
+ status: "DEPENDENCY_FAILED"
5407
+ });
5408
+ }
5409
+ });
5410
+ if (complete.size === stacks.length) {
5411
+ resolve(results);
5412
+ }
5413
+ trigger();
5414
+ });
5415
+ todo.delete(stack.id);
5416
+ }
5417
+ }
5418
+ trigger();
5419
+ });
5420
+ }
5421
+ async function remove(stack) {
5422
+ Logger.debug("Removing stack", stack.id);
5423
+ const cfn = useAWSClient(CloudFormationClient2);
5424
+ try {
5425
+ await cfn.send(
5426
+ new DeleteStackCommand({
5427
+ StackName: stack.stackName
5428
+ })
5429
+ );
5430
+ return monitor(stack.stackName);
5431
+ } catch (ex) {
5432
+ return {
5433
+ errors: {
5434
+ stack: ex.message
5435
+ },
5436
+ outputs: {},
5437
+ status: "UPDATE_FAILED"
5438
+ };
5439
+ }
5440
+ }
5441
+ var init_remove = __esm({
5442
+ "src/stacks/remove.ts"() {
5443
+ "use strict";
5444
+ init_bus();
5445
+ init_credentials();
5446
+ init_logger();
5447
+ init_monitor();
5448
+ }
5449
+ });
5450
+
5451
+ // src/stacks/index.ts
5452
+ var stacks_exports = {};
5453
+ __export(stacks_exports, {
5454
+ STATUSES: () => STATUSES,
5455
+ Stacks: () => stacks_exports,
5456
+ clearAppMetadata: () => clearAppMetadata,
5457
+ deploy: () => deploy,
5458
+ deployMany: () => deployMany,
5459
+ diff: () => diff,
5460
+ filterOutputs: () => filterOutputs,
5461
+ isFailed: () => isFailed,
5462
+ isFinal: () => isFinal,
5463
+ isPending: () => isPending,
5464
+ isSuccess: () => isSuccess,
5465
+ load: () => load,
5466
+ loadAssembly: () => loadAssembly,
5467
+ metadata: () => metadata2,
5468
+ metadataForStack: () => metadataForStack,
5469
+ monitor: () => monitor,
5470
+ publishAssets: () => publishAssets4,
5471
+ remove: () => remove,
5472
+ removeMany: () => removeMany,
5473
+ saveAppMetadata: () => saveAppMetadata,
5474
+ synth: () => synth,
5475
+ useAppMetadata: () => useAppMetadata,
5476
+ useMetadata: () => useMetadata
5477
+ });
5478
+ var init_stacks = __esm({
5479
+ "src/stacks/index.ts"() {
5480
+ "use strict";
5481
+ init_app_metadata();
5482
+ init_assembly();
5483
+ init_build();
5484
+ init_deploy();
5485
+ init_diff();
5486
+ init_metadata();
5487
+ init_synth();
5488
+ init_monitor();
5489
+ init_remove();
5490
+ init_stacks();
5491
+ }
5492
+ });
5493
+
5494
+ // src/bootstrap.ts
5495
+ import url8 from "url";
5496
+ import path16 from "path";
5497
+ import { bold, dim } from "colorette";
5498
+ import { spawn as spawn6 } from "child_process";
5499
+ import {
5500
+ DescribeStacksCommand as DescribeStacksCommand2,
5501
+ CloudFormationClient as CloudFormationClient3
5502
+ } from "@aws-sdk/client-cloudformation";
5503
+ import {
5504
+ App,
5505
+ DefaultStackSynthesizer,
5506
+ CfnOutput,
5507
+ Duration,
5508
+ Tags,
5509
+ Stack,
5510
+ RemovalPolicy
5511
+ } from "aws-cdk-lib";
5512
+ import { Function, Runtime as Runtime2, Code } from "aws-cdk-lib/aws-lambda";
5513
+ import { SqsEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
5514
+ import { PolicyStatement } from "aws-cdk-lib/aws-iam";
5515
+ import { Queue } from "aws-cdk-lib/aws-sqs";
5516
+ import { Rule } from "aws-cdk-lib/aws-events";
5517
+ import { SqsQueue } from "aws-cdk-lib/aws-events-targets";
5518
+ import {
5519
+ BlockPublicAccess,
5520
+ Bucket,
5521
+ BucketEncryption
5522
+ } from "aws-cdk-lib/aws-s3";
5523
+ async function loadCDKStatus() {
5524
+ const { cdk } = useProject().config;
5525
+ const client = useAWSClient(CloudFormationClient3);
5526
+ const stackName = cdk?.toolkitStackName || CDK_STACK_NAME;
5527
+ try {
5528
+ const { Stacks: stacks } = await client.send(
5529
+ new DescribeStacksCommand2({ StackName: stackName })
5530
+ );
5531
+ if (!stacks || stacks.length === 0)
5532
+ return false;
5533
+ if (!["CREATE_COMPLETE", "UPDATE_COMPLETE"].includes(stacks[0].StackStatus)) {
5534
+ return false;
5535
+ }
5536
+ const output = stacks[0].Outputs?.find(
5537
+ (o) => o.OutputKey === "BootstrapVersion"
5538
+ );
5539
+ if (!output || parseInt(output.OutputValue) < 14)
5540
+ return false;
5541
+ return true;
5542
+ } catch (e) {
5543
+ if (e.name === "ValidationError" && e.message === `Stack with id ${stackName} does not exist`) {
5544
+ return false;
5545
+ } else {
5546
+ throw e;
5547
+ }
5770
5548
  }
5771
5549
  }
5772
- function formatErrorMessage(message) {
5773
- return formatCustomDomainError(message) || `Could not resolve context values for ${message}`;
5774
- }
5775
- function formatCustomDomainError(message) {
5776
- const ret = message.match(/hosted-zone:account=\d+:domainName=(\S+):/);
5777
- if (!ret) {
5778
- return;
5550
+ async function loadSSTStatus() {
5551
+ const { bootstrap } = useProject().config;
5552
+ const cf = useAWSClient(CloudFormationClient3);
5553
+ const stackName = bootstrap?.stackName || SST_STACK_NAME;
5554
+ let result;
5555
+ try {
5556
+ result = await cf.send(
5557
+ new DescribeStacksCommand2({
5558
+ StackName: stackName
5559
+ })
5560
+ );
5561
+ } catch (e) {
5562
+ if (e.Code === "ValidationError" && e.message === `Stack with id ${stackName} does not exist`) {
5563
+ return null;
5564
+ }
5565
+ throw e;
5779
5566
  }
5780
- const hostedZone = ret && ret[1];
5781
- return [
5782
- `It seems you are configuring custom domains for you URL.`,
5783
- hostedZone ? `And SST is not able to find the hosted zone "${hostedZone}" in your AWS Route 53 account.` : `And SST is not able to find the hosted zone in your AWS Route 53 account.`,
5784
- `Please double check and make sure the zone exists, or pass in a different zone.`
5785
- ].join(" ");
5567
+ let version2, bucket;
5568
+ (result.Stacks[0].Outputs || []).forEach((o) => {
5569
+ if (o.OutputKey === OUTPUT_VERSION) {
5570
+ version2 = o.OutputValue;
5571
+ } else if (o.OutputKey === OUTPUT_BUCKET) {
5572
+ bucket = o.OutputValue;
5573
+ }
5574
+ });
5575
+ if (!version2 || !bucket) {
5576
+ return null;
5577
+ }
5578
+ return { version: version2, bucket };
5786
5579
  }
5787
- var init_synth = __esm({
5788
- "src/stacks/synth.ts"() {
5789
- "use strict";
5790
- init_logger();
5791
- init_project();
5792
- init_credentials();
5793
- init_error();
5794
- init_dotnet();
5580
+ async function bootstrapSST() {
5581
+ const { region, bootstrap, cdk } = useProject().config;
5582
+ const app = new App();
5583
+ const stackName = bootstrap?.stackName || SST_STACK_NAME;
5584
+ const stack = new Stack(app, stackName, {
5585
+ env: {
5586
+ region
5587
+ },
5588
+ synthesizer: new DefaultStackSynthesizer({
5589
+ qualifier: cdk?.qualifier,
5590
+ fileAssetsBucketName: cdk?.fileAssetsBucketName
5591
+ })
5592
+ });
5593
+ for (const [key, value] of Object.entries(bootstrap?.tags || {})) {
5594
+ Tags.of(app).add(key, value);
5795
5595
  }
5796
- });
5797
-
5798
- // src/stacks/remove.ts
5799
- import {
5800
- CloudFormationClient as CloudFormationClient3,
5801
- DeleteStackCommand
5802
- } from "@aws-sdk/client-cloudformation";
5803
- async function removeMany(stacks) {
5804
- await useAWSProvider();
5805
- const bus = useBus();
5806
- const complete = /* @__PURE__ */ new Set();
5807
- const todo = new Set(stacks.map((s) => s.id));
5808
- const results = {};
5809
- return new Promise((resolve) => {
5810
- async function trigger() {
5811
- for (const stack of stacks) {
5812
- if (!todo.has(stack.id))
5813
- continue;
5814
- Logger.debug("Checking if", stack.id, "can be removed");
5815
- const waiting = stacks.filter((dependant) => {
5816
- if (dependant.id === stack.id)
5817
- return false;
5818
- if (complete.has(dependant.id))
5819
- return false;
5820
- return dependant.dependencies?.some((d) => d.id === stack.id);
5821
- });
5822
- if (waiting.length) {
5823
- Logger.debug(
5824
- "Waiting on",
5825
- waiting.map((s) => s.id)
5826
- );
5827
- continue;
5596
+ const bucket = new Bucket(stack, region, {
5597
+ encryption: BucketEncryption.S3_MANAGED,
5598
+ removalPolicy: RemovalPolicy.DESTROY,
5599
+ autoDeleteObjects: true,
5600
+ blockPublicAccess: cdk?.publicAccessBlockConfiguration !== false ? BlockPublicAccess.BLOCK_ALL : void 0
5601
+ });
5602
+ const fn = new Function(stack, "MetadataHandler", {
5603
+ code: Code.fromAsset(
5604
+ path16.resolve(__dirname2, "support/bootstrap-metadata-function")
5605
+ ),
5606
+ handler: "index.handler",
5607
+ runtime: region?.startsWith("us-gov-") ? Runtime2.NODEJS_16_X : Runtime2.NODEJS_18_X,
5608
+ environment: {
5609
+ BUCKET_NAME: bucket.bucketName
5610
+ },
5611
+ initialPolicy: [
5612
+ new PolicyStatement({
5613
+ actions: ["cloudformation:DescribeStacks"],
5614
+ resources: ["*"]
5615
+ }),
5616
+ new PolicyStatement({
5617
+ actions: ["s3:PutObject", "s3:DeleteObject"],
5618
+ resources: [bucket.bucketArn + "/*"]
5619
+ }),
5620
+ new PolicyStatement({
5621
+ actions: ["iot:Publish"],
5622
+ resources: [
5623
+ `arn:${stack.partition}:iot:${stack.region}:${stack.account}:topic//sst/*`
5624
+ ]
5625
+ })
5626
+ ]
5627
+ });
5628
+ const queue = new Queue(stack, "MetadataQueue", {
5629
+ visibilityTimeout: Duration.seconds(30),
5630
+ retentionPeriod: Duration.minutes(2)
5631
+ });
5632
+ fn.addEventSource(new SqsEventSource(queue));
5633
+ const rule = new Rule(stack, "MetadataRule", {
5634
+ eventPattern: {
5635
+ source: ["aws.cloudformation"],
5636
+ detailType: ["CloudFormation Stack Status Change"],
5637
+ detail: {
5638
+ "status-details": {
5639
+ status: [
5640
+ "CREATE_COMPLETE",
5641
+ "UPDATE_COMPLETE",
5642
+ "UPDATE_ROLLBACK_COMPLETE",
5643
+ "ROLLBACK_COMPLETE",
5644
+ "DELETE_COMPLETE"
5645
+ ]
5828
5646
  }
5829
- remove(stack).then((result) => {
5830
- results[stack.id] = result;
5831
- complete.add(stack.id);
5832
- if (isFailed(result.status))
5833
- stacks.forEach((s) => {
5834
- if (todo.delete(s.stackName)) {
5835
- complete.add(s.stackName);
5836
- results[s.id] = {
5837
- status: "DEPENDENCY_FAILED",
5838
- outputs: {},
5839
- errors: {}
5840
- };
5841
- bus.publish("stack.status", {
5842
- stackID: s.id,
5843
- status: "DEPENDENCY_FAILED"
5844
- });
5845
- }
5846
- });
5847
- if (complete.size === stacks.length) {
5848
- resolve(results);
5849
- }
5850
- trigger();
5851
- });
5852
- todo.delete(stack.id);
5853
5647
  }
5854
5648
  }
5855
- trigger();
5649
+ });
5650
+ rule.addTarget(
5651
+ new SqsQueue(queue, {
5652
+ retryAttempts: 10
5653
+ })
5654
+ );
5655
+ new CfnOutput(stack, OUTPUT_VERSION, { value: LATEST_VERSION });
5656
+ new CfnOutput(stack, OUTPUT_BUCKET, { value: bucket.bucketName });
5657
+ const asm = app.synth();
5658
+ const result = await stacks_exports.deploy(asm.stacks[0]);
5659
+ if (stacks_exports.isFailed(result.status)) {
5660
+ throw new VisibleError(
5661
+ `Failed to deploy bootstrap stack:
5662
+ ${JSON.stringify(
5663
+ result.errors,
5664
+ null,
5665
+ 4
5666
+ )}`
5667
+ );
5668
+ }
5669
+ }
5670
+ async function bootstrapCDK() {
5671
+ const identity = await useSTSIdentity();
5672
+ const credentials = await useAWSCredentials();
5673
+ const { region, profile, cdk } = useProject().config;
5674
+ cdk || {};
5675
+ await new Promise((resolve, reject) => {
5676
+ const proc = spawn6(
5677
+ [
5678
+ "npx",
5679
+ "cdk",
5680
+ "bootstrap",
5681
+ `aws://${identity.Account}/${region}`,
5682
+ "--no-version-reporting",
5683
+ ...cdk?.publicAccessBlockConfiguration === false ? ["--public-access-block-configuration", "false"] : cdk?.publicAccessBlockConfiguration === true ? ["--public-access-block-configuration", "false"] : [],
5684
+ ...cdk?.toolkitStackName ? ["--toolkit-stack-name", cdk.toolkitStackName] : [],
5685
+ ...cdk?.qualifier ? ["--qualifier", cdk.qualifier] : [],
5686
+ ...cdk?.fileAssetsBucketName ? ["--toolkit-bucket-name", cdk.fileAssetsBucketName] : []
5687
+ ].join(" "),
5688
+ {
5689
+ env: {
5690
+ ...process.env,
5691
+ AWS_ACCESS_KEY_ID: credentials.accessKeyId,
5692
+ AWS_SECRET_ACCESS_KEY: credentials.secretAccessKey,
5693
+ AWS_SESSION_TOKEN: credentials.sessionToken,
5694
+ AWS_REGION: region,
5695
+ AWS_PROFILE: profile
5696
+ },
5697
+ stdio: "pipe",
5698
+ shell: true
5699
+ }
5700
+ );
5701
+ let stderr = "";
5702
+ proc.stdout.on("data", (data2) => {
5703
+ Logger.debug(data2.toString());
5704
+ });
5705
+ proc.stderr.on("data", (data2) => {
5706
+ Logger.debug(data2.toString());
5707
+ stderr += data2;
5708
+ });
5709
+ proc.on("exit", (code) => {
5710
+ Logger.debug("CDK bootstrap exited with code " + code);
5711
+ if (code === 0) {
5712
+ resolve();
5713
+ } else {
5714
+ console.log(bold(dim(stderr)));
5715
+ reject(new VisibleError(`Failed to bootstrap`));
5716
+ }
5717
+ });
5856
5718
  });
5857
5719
  }
5858
- async function remove(stack) {
5859
- Logger.debug("Removing stack", stack.id);
5860
- const cfn = useAWSClient(CloudFormationClient3);
5861
- try {
5862
- await cfn.send(
5863
- new DeleteStackCommand({
5864
- StackName: stack.stackName
5865
- })
5866
- );
5867
- return monitor(stack.stackName);
5868
- } catch (ex) {
5869
- return {
5870
- errors: {
5871
- stack: ex.message
5872
- },
5873
- outputs: {},
5874
- status: "UPDATE_FAILED"
5875
- };
5720
+ var CDK_STACK_NAME, SST_STACK_NAME, OUTPUT_VERSION, OUTPUT_BUCKET, LATEST_VERSION, __dirname2, useBootstrap;
5721
+ var init_bootstrap = __esm({
5722
+ "src/bootstrap.ts"() {
5723
+ "use strict";
5724
+ init_project();
5725
+ init_spinner();
5726
+ init_context();
5727
+ init_credentials();
5728
+ init_error();
5729
+ init_logger();
5730
+ init_stacks();
5731
+ CDK_STACK_NAME = "CDKToolkit";
5732
+ SST_STACK_NAME = "SSTBootstrap";
5733
+ OUTPUT_VERSION = "Version";
5734
+ OUTPUT_BUCKET = "BucketName";
5735
+ LATEST_VERSION = "7";
5736
+ __dirname2 = url8.fileURLToPath(new URL(".", import.meta.url));
5737
+ useBootstrap = Context.memo(async () => {
5738
+ Logger.debug("Initializing bootstrap context");
5739
+ let [cdkStatus, sstStatus] = await Promise.all([
5740
+ loadCDKStatus(),
5741
+ loadSSTStatus()
5742
+ ]);
5743
+ Logger.debug("Loaded bootstrap status");
5744
+ const needToBootstrapCDK = !cdkStatus;
5745
+ const needToBootstrapSST = !sstStatus || sstStatus.version !== LATEST_VERSION;
5746
+ if (needToBootstrapCDK || needToBootstrapSST) {
5747
+ const spinner = createSpinner(
5748
+ "Deploying bootstrap stack, this only needs to happen once"
5749
+ ).start();
5750
+ if (needToBootstrapCDK) {
5751
+ await bootstrapCDK();
5752
+ }
5753
+ if (needToBootstrapSST) {
5754
+ await bootstrapSST();
5755
+ sstStatus = await loadSSTStatus();
5756
+ if (!sstStatus)
5757
+ throw new VisibleError("Failed to load bootstrap stack status");
5758
+ }
5759
+ spinner.succeed();
5760
+ }
5761
+ Logger.debug("Bootstrap context initialized", sstStatus);
5762
+ return sstStatus;
5763
+ }, "Bootstrap");
5876
5764
  }
5877
- }
5878
- var init_remove = __esm({
5879
- "src/stacks/remove.ts"() {
5765
+ });
5766
+
5767
+ // src/iot.ts
5768
+ var iot_exports = {};
5769
+ __export(iot_exports, {
5770
+ useIOT: () => useIOT,
5771
+ useIOTEndpoint: () => useIOTEndpoint
5772
+ });
5773
+ import { IoTClient, DescribeEndpointCommand } from "@aws-sdk/client-iot";
5774
+ import iot from "aws-iot-device-sdk";
5775
+ import { PutObjectCommand as PutObjectCommand2, S3Client as S3Client3 } from "@aws-sdk/client-s3";
5776
+ var useIOTEndpoint, useIOT;
5777
+ var init_iot = __esm({
5778
+ "src/iot.ts"() {
5880
5779
  "use strict";
5881
- init_bus();
5780
+ init_context();
5882
5781
  init_credentials();
5782
+ init_error();
5783
+ init_bus();
5784
+ init_project();
5883
5785
  init_logger();
5884
- init_monitor();
5786
+ init_bootstrap();
5787
+ useIOTEndpoint = Context.memo(async () => {
5788
+ const iot2 = useAWSClient(IoTClient);
5789
+ Logger.debug("Getting IoT endpoint");
5790
+ const response = await iot2.send(
5791
+ new DescribeEndpointCommand({
5792
+ endpointType: "iot:Data-ATS"
5793
+ })
5794
+ );
5795
+ Logger.debug("Using IoT endpoint:", response.endpointAddress);
5796
+ if (!response.endpointAddress)
5797
+ throw new VisibleError("IoT Endpoint address not found");
5798
+ return response.endpointAddress;
5799
+ });
5800
+ useIOT = Context.memo(async () => {
5801
+ const bus = useBus();
5802
+ const endpoint = await useIOTEndpoint();
5803
+ const creds = await useAWSCredentials();
5804
+ const project = useProject();
5805
+ const bootstrap = await useBootstrap();
5806
+ const s3 = useAWSClient(S3Client3);
5807
+ async function encode(input) {
5808
+ const id = Math.random().toString();
5809
+ const json = JSON.stringify(input);
5810
+ if (json.length > 1024 * 1024 * 3) {
5811
+ const key = `pointers/${id}`;
5812
+ await s3.send(
5813
+ new PutObjectCommand2({
5814
+ Bucket: bootstrap.bucket,
5815
+ Key: key,
5816
+ Body: json
5817
+ })
5818
+ );
5819
+ return [
5820
+ {
5821
+ id,
5822
+ index: 0,
5823
+ count: 1,
5824
+ data: JSON.stringify({
5825
+ type: "pointer",
5826
+ properties: {
5827
+ key,
5828
+ bucket: bootstrap.bucket
5829
+ }
5830
+ })
5831
+ }
5832
+ ];
5833
+ }
5834
+ const parts = json.match(/.{1,100000}/g);
5835
+ if (!parts)
5836
+ return [];
5837
+ Logger.debug("Encoded iot message into", parts?.length, "parts");
5838
+ return parts.map((part, index) => ({
5839
+ id,
5840
+ index,
5841
+ count: parts?.length,
5842
+ data: part
5843
+ }));
5844
+ }
5845
+ const device = new iot.device({
5846
+ protocol: "wss",
5847
+ host: endpoint,
5848
+ region: project.config.region,
5849
+ accessKeyId: creds.accessKeyId,
5850
+ secretKey: creds.secretAccessKey,
5851
+ sessionToken: creds.sessionToken,
5852
+ reconnectPeriod: 1
5853
+ });
5854
+ const PREFIX2 = `/sst/${project.config.name}/${project.config.stage}`;
5855
+ device.subscribe(`${PREFIX2}/events`, { qos: 1 });
5856
+ const fragments = /* @__PURE__ */ new Map();
5857
+ device.on("connect", () => {
5858
+ Logger.debug("IoT connected");
5859
+ });
5860
+ device.on("error", (err) => {
5861
+ Logger.debug("IoT error", err);
5862
+ });
5863
+ device.on("close", () => {
5864
+ Logger.debug("IoT closed");
5865
+ });
5866
+ device.on("reconnect", () => {
5867
+ Logger.debug("IoT reconnected");
5868
+ });
5869
+ device.on("message", (_topic, buffer) => {
5870
+ const fragment = JSON.parse(buffer.toString());
5871
+ if (!fragment.id) {
5872
+ bus.publish(fragment.type, fragment.properties);
5873
+ return;
5874
+ }
5875
+ let pending = fragments.get(fragment.id);
5876
+ if (!pending) {
5877
+ pending = /* @__PURE__ */ new Map();
5878
+ fragments.set(fragment.id, pending);
5879
+ }
5880
+ pending.set(fragment.index, fragment);
5881
+ if (pending.size === fragment.count) {
5882
+ const data2 = [...pending.values()].sort((a, b) => a.index - b.index).map((item) => item.data).join("");
5883
+ fragments.delete(fragment.id);
5884
+ const evt = JSON.parse(data2);
5885
+ if (evt.sourceID === bus.sourceID)
5886
+ return;
5887
+ bus.publish(evt.type, evt.properties);
5888
+ }
5889
+ });
5890
+ return {
5891
+ prefix: PREFIX2,
5892
+ async publish(topic, type, properties) {
5893
+ const payload = {
5894
+ type,
5895
+ properties,
5896
+ sourceID: bus.sourceID
5897
+ };
5898
+ for (const fragment of await encode(payload)) {
5899
+ await new Promise((r) => {
5900
+ device.publish(
5901
+ topic,
5902
+ JSON.stringify(fragment),
5903
+ {
5904
+ qos: 1
5905
+ },
5906
+ () => {
5907
+ r();
5908
+ }
5909
+ );
5910
+ });
5911
+ }
5912
+ Logger.debug("IOT Published", topic, type);
5913
+ }
5914
+ };
5915
+ });
5885
5916
  }
5886
5917
  });
5887
5918
 
5888
- // src/stacks/index.ts
5889
- var stacks_exports = {};
5890
- __export(stacks_exports, {
5891
- STATUSES: () => STATUSES,
5892
- Stacks: () => stacks_exports,
5893
- clearAppMetadata: () => clearAppMetadata,
5894
- deploy: () => deploy,
5895
- deployMany: () => deployMany,
5896
- diff: () => diff,
5897
- filterOutputs: () => filterOutputs,
5898
- isFailed: () => isFailed,
5899
- isFinal: () => isFinal,
5900
- isPending: () => isPending,
5901
- isSuccess: () => isSuccess,
5902
- load: () => load,
5903
- loadAssembly: () => loadAssembly,
5904
- metadata: () => metadata2,
5905
- metadataForStack: () => metadataForStack,
5906
- monitor: () => monitor,
5907
- publishAssets: () => publishAssets4,
5908
- remove: () => remove,
5909
- removeMany: () => removeMany,
5910
- saveAppMetadata: () => saveAppMetadata,
5911
- synth: () => synth,
5912
- useAppMetadata: () => useAppMetadata,
5913
- useMetadata: () => useMetadata
5919
+ // src/runtime/iot.ts
5920
+ var iot_exports2 = {};
5921
+ __export(iot_exports2, {
5922
+ useIOTBridge: () => useIOTBridge
5914
5923
  });
5915
- var init_stacks = __esm({
5916
- "src/stacks/index.ts"() {
5924
+ var useIOTBridge;
5925
+ var init_iot2 = __esm({
5926
+ "src/runtime/iot.ts"() {
5917
5927
  "use strict";
5918
- init_app_metadata();
5919
- init_assembly();
5920
- init_build();
5921
- init_deploy();
5922
- init_diff();
5923
- init_metadata();
5924
- init_synth();
5925
- init_monitor();
5926
- init_remove();
5927
- init_stacks();
5928
+ init_context();
5929
+ init_bus();
5930
+ init_iot();
5931
+ useIOTBridge = Context.memo(async () => {
5932
+ const bus = useBus();
5933
+ const iot2 = await useIOT();
5934
+ const topic = `${iot2.prefix}/events`;
5935
+ bus.subscribe("function.success", async (evt) => {
5936
+ iot2.publish(
5937
+ topic + "/" + evt.properties.workerID,
5938
+ "function.success",
5939
+ evt.properties
5940
+ );
5941
+ });
5942
+ bus.subscribe("function.error", async (evt) => {
5943
+ iot2.publish(
5944
+ topic + "/" + evt.properties.workerID,
5945
+ "function.error",
5946
+ evt.properties
5947
+ );
5948
+ });
5949
+ bus.subscribe("function.ack", async (evt) => {
5950
+ iot2.publish(
5951
+ topic + "/" + evt.properties.workerID,
5952
+ "function.ack",
5953
+ evt.properties
5954
+ );
5955
+ });
5956
+ });
5928
5957
  }
5929
5958
  });
5930
5959