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/constructs/Function.js +1 -1
- package/constructs/Job.d.ts +14 -0
- package/constructs/Job.js +18 -4
- package/iot.js +42 -14
- package/package.json +1 -1
- package/sst.mjs +959 -930
- package/support/base-site-archiver.mjs +16 -16
- package/support/bridge/bridge.mjs +70 -45
- package/support/ssr-site-function-archiver.mjs +15 -15
package/sst.mjs
CHANGED
|
@@ -2603,743 +2603,306 @@ var init_workers = __esm({
|
|
|
2603
2603
|
}
|
|
2604
2604
|
});
|
|
2605
2605
|
|
|
2606
|
-
// src/
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
const
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
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
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
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
|
-
|
|
2686
|
+
init_bootstrap();
|
|
2632
2687
|
init_credentials();
|
|
2633
|
-
|
|
2634
|
-
init_bus();
|
|
2635
|
-
init_project();
|
|
2688
|
+
init_context();
|
|
2636
2689
|
init_logger();
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
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/
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
}
|
|
2734
|
-
var
|
|
2735
|
-
|
|
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/
|
|
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
|
-
|
|
2715
|
+
DescribeStackEventsCommand
|
|
2778
2716
|
} from "@aws-sdk/client-cloudformation";
|
|
2779
|
-
import {
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
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
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
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
|
-
|
|
2833
|
-
new DescribeStacksCommand({
|
|
2834
|
-
StackName: stackName
|
|
2835
|
-
})
|
|
2836
|
-
);
|
|
2895
|
+
return await cb();
|
|
2837
2896
|
} catch (e) {
|
|
2838
|
-
if (e.
|
|
2839
|
-
return
|
|
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
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
4786
|
-
import
|
|
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 =
|
|
4394
|
+
const proc = spawn(
|
|
4832
4395
|
`dotnet`,
|
|
4833
4396
|
[
|
|
4834
4397
|
`exec`,
|
|
4835
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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) =>
|
|
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 =
|
|
4568
|
+
const relative = path9.relative(
|
|
5006
4569
|
project.paths.root,
|
|
5007
|
-
|
|
4570
|
+
path9.resolve(parsed.dir)
|
|
5008
4571
|
);
|
|
5009
4572
|
const extension = isESM ? ".mjs" : ".cjs";
|
|
5010
|
-
const target =
|
|
4573
|
+
const target = path9.join(
|
|
5011
4574
|
input.out,
|
|
5012
|
-
!relative.startsWith("..") && !
|
|
4575
|
+
!relative.startsWith("..") && !path9.isAbsolute(input.props.handler) ? relative : "",
|
|
5013
4576
|
parsed.name + extension
|
|
5014
4577
|
);
|
|
5015
|
-
const handler =
|
|
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(
|
|
4652
|
+
if (await fs10.access(path9.join(dir, target2)).then(() => true).catch(() => false))
|
|
5090
4653
|
return dir;
|
|
5091
|
-
return find2(
|
|
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(
|
|
4659
|
+
await fs10.readFile(path9.join(src, "package.json")).then((x) => x.toString())
|
|
5097
4660
|
);
|
|
5098
4661
|
fs10.writeFile(
|
|
5099
|
-
|
|
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 =
|
|
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
|
-
|
|
5128
|
-
|
|
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
|
|
4730
|
+
import path10 from "path";
|
|
5168
4731
|
import fs11 from "fs/promises";
|
|
5169
|
-
import { exec as exec3, spawn as
|
|
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(
|
|
4737
|
+
if (await fs11.access(path10.join(dir, target)).then(() => true).catch(() => false))
|
|
5175
4738
|
return dir;
|
|
5176
|
-
return find(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
4797
|
+
const src = path10.relative(project, input.props.handler);
|
|
5235
4798
|
if (input.mode === "start") {
|
|
5236
4799
|
try {
|
|
5237
|
-
const target =
|
|
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 =
|
|
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
|
|
4845
|
+
import path11 from "path";
|
|
5283
4846
|
import fs12 from "fs/promises";
|
|
5284
|
-
import { exec as exec4, spawn as
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
5362
|
-
|
|
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
|
-
|
|
5378
|
-
|
|
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
|
|
5397
|
-
import
|
|
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
|
-
|
|
5413
|
-
|
|
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 =
|
|
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(
|
|
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 =
|
|
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
|
|
5015
|
+
var __dirname, BUNDLER_DEPENDENCIES_CACHE;
|
|
5453
5016
|
var init_pythonBundling = __esm({
|
|
5454
5017
|
"src/runtime/handlers/pythonBundling.ts"() {
|
|
5455
5018
|
"use strict";
|
|
5456
|
-
|
|
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
|
|
5467
|
-
import { exec as exec5, spawn as
|
|
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
|
|
5032
|
+
import { Runtime } from "aws-cdk-lib/aws-lambda";
|
|
5470
5033
|
import os3 from "os";
|
|
5471
|
-
import
|
|
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":
|
|
5485
|
-
"python3.6":
|
|
5486
|
-
"python3.7":
|
|
5487
|
-
"python3.8":
|
|
5488
|
-
"python3.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 =
|
|
5517
|
-
const target = [...parsed.dir.split(
|
|
5518
|
-
const proc =
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
|
5596
|
-
import
|
|
5158
|
+
import { spawn as spawn5 } from "child_process";
|
|
5159
|
+
import url7 from "url";
|
|
5597
5160
|
async function getGradleBinary(srcPath) {
|
|
5598
|
-
const gradleWrapperPath =
|
|
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 =
|
|
5193
|
+
const proc = spawn5(
|
|
5631
5194
|
`java`,
|
|
5632
5195
|
[
|
|
5633
5196
|
`-cp`,
|
|
5634
5197
|
[
|
|
5635
|
-
|
|
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 =
|
|
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(
|
|
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
|
|
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 ||
|
|
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
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
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
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
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
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
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
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
);
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
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
|
-
|
|
5879
|
-
|
|
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
|
-
|
|
5780
|
+
init_context();
|
|
5882
5781
|
init_credentials();
|
|
5782
|
+
init_error();
|
|
5783
|
+
init_bus();
|
|
5784
|
+
init_project();
|
|
5883
5785
|
init_logger();
|
|
5884
|
-
|
|
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/
|
|
5889
|
-
var
|
|
5890
|
-
__export(
|
|
5891
|
-
|
|
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
|
|
5916
|
-
|
|
5924
|
+
var useIOTBridge;
|
|
5925
|
+
var init_iot2 = __esm({
|
|
5926
|
+
"src/runtime/iot.ts"() {
|
|
5917
5927
|
"use strict";
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
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
|
|