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