sst 2.2.7 → 2.3.0
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/cli/commands/bind.js +191 -19
- package/cli/commands/{env.d.ts → bootstrap.d.ts} +1 -3
- package/cli/commands/bootstrap.js +5 -0
- package/cli/commands/dev.js +2 -17
- package/cli/commands/secrets/set.js +22 -5
- package/cli/sst.js +2 -2
- package/cli/ui/deploy.d.ts +1 -1
- package/cli/ui/deploy.js +3 -6
- package/cli/ui/functions.d.ts +1 -1
- package/config.d.ts +14 -1
- package/config.js +68 -31
- package/constructs/App.d.ts +2 -2
- package/constructs/App.js +2 -4
- package/constructs/AstroSite.d.ts +1 -0
- package/constructs/AstroSite.js +1 -0
- package/constructs/Function.d.ts +1 -1
- package/constructs/Metadata.d.ts +5 -1
- package/constructs/NextjsSite.d.ts +1 -0
- package/constructs/NextjsSite.js +1 -0
- package/constructs/RemixSite.d.ts +1 -0
- package/constructs/RemixSite.js +1 -0
- package/constructs/SolidStartSite.d.ts +1 -0
- package/constructs/SolidStartSite.js +1 -0
- package/constructs/SsrSite.d.ts +15 -7
- package/constructs/SsrSite.js +52 -21
- package/constructs/StaticSite.d.ts +2 -1
- package/constructs/StaticSite.js +3 -15
- package/constructs/deprecated/NextjsSite.d.ts +5 -2
- package/constructs/deprecated/NextjsSite.js +4 -16
- package/package.json +1 -1
- package/sst.mjs +2170 -2071
- package/stacks/metadata.d.ts +0 -1
- package/stacks/metadata.js +1 -26
- package/support/bootstrap-metadata-function/index.mjs +2 -2
- package/cli/commands/env.js +0 -48
- package/site-env.d.ts +0 -13
- package/site-env.js +0 -48
package/sst.mjs
CHANGED
|
@@ -177,6 +177,13 @@ var init_module = __esm({
|
|
|
177
177
|
});
|
|
178
178
|
|
|
179
179
|
// src/util/fs.ts
|
|
180
|
+
var fs_exports = {};
|
|
181
|
+
__export(fs_exports, {
|
|
182
|
+
existsAsync: () => existsAsync,
|
|
183
|
+
findAbove: () => findAbove,
|
|
184
|
+
findBelow: () => findBelow,
|
|
185
|
+
isChild: () => isChild
|
|
186
|
+
});
|
|
180
187
|
import fs2 from "fs/promises";
|
|
181
188
|
import path2 from "path";
|
|
182
189
|
async function findAbove(dir, target) {
|
|
@@ -746,65 +753,6 @@ var init_spinner = __esm({
|
|
|
746
753
|
}
|
|
747
754
|
});
|
|
748
755
|
|
|
749
|
-
// src/site-env.ts
|
|
750
|
-
var site_env_exports = {};
|
|
751
|
-
__export(site_env_exports, {
|
|
752
|
-
SiteEnv: () => site_env_exports,
|
|
753
|
-
append: () => append,
|
|
754
|
-
keys: () => keys,
|
|
755
|
-
reset: () => reset2,
|
|
756
|
-
values: () => values,
|
|
757
|
-
valuesFile: () => valuesFile,
|
|
758
|
-
writeValues: () => writeValues
|
|
759
|
-
});
|
|
760
|
-
import fs5 from "fs";
|
|
761
|
-
import path5 from "path";
|
|
762
|
-
function keysFile() {
|
|
763
|
-
return path5.join(useProject().paths.out, "site-environment-keys.jsonl");
|
|
764
|
-
}
|
|
765
|
-
function valuesFile() {
|
|
766
|
-
return path5.join(useProject().paths.out, "site-environment-values.json");
|
|
767
|
-
}
|
|
768
|
-
async function keys() {
|
|
769
|
-
try {
|
|
770
|
-
const file = keysFile();
|
|
771
|
-
const data2 = await fs5.promises.readFile(file).then((x) => x.toString().split("\n"));
|
|
772
|
-
return data2.filter(Boolean).map((x) => JSON.parse(x));
|
|
773
|
-
} catch {
|
|
774
|
-
return [];
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
async function values() {
|
|
778
|
-
try {
|
|
779
|
-
const file = valuesFile();
|
|
780
|
-
const data2 = await fs5.promises.readFile(file).then((x) => JSON.parse(x.toString()));
|
|
781
|
-
return data2;
|
|
782
|
-
} catch {
|
|
783
|
-
return {};
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
async function writeValues(input) {
|
|
787
|
-
const file = valuesFile();
|
|
788
|
-
await fs5.promises.writeFile(file, JSON.stringify(input));
|
|
789
|
-
}
|
|
790
|
-
function append(input) {
|
|
791
|
-
input.path = path5.resolve(useProject().paths.root, input.path);
|
|
792
|
-
fs5.appendFileSync(keysFile(), JSON.stringify(input) + "\n");
|
|
793
|
-
}
|
|
794
|
-
function reset2() {
|
|
795
|
-
fs5.rmSync(keysFile(), {
|
|
796
|
-
force: true,
|
|
797
|
-
recursive: true
|
|
798
|
-
});
|
|
799
|
-
}
|
|
800
|
-
var init_site_env = __esm({
|
|
801
|
-
"src/site-env.ts"() {
|
|
802
|
-
"use strict";
|
|
803
|
-
init_site_env();
|
|
804
|
-
init_project();
|
|
805
|
-
}
|
|
806
|
-
});
|
|
807
|
-
|
|
808
756
|
// ../../node_modules/.pnpm/tslib@2.5.0/node_modules/tslib/tslib.es6.js
|
|
809
757
|
var tslib_es6_exports = {};
|
|
810
758
|
__export(tslib_es6_exports, {
|
|
@@ -1742,6 +1690,110 @@ var init_credentials = __esm({
|
|
|
1742
1690
|
}
|
|
1743
1691
|
});
|
|
1744
1692
|
|
|
1693
|
+
// src/stacks/app-metadata.ts
|
|
1694
|
+
import {
|
|
1695
|
+
S3Client,
|
|
1696
|
+
GetObjectCommand,
|
|
1697
|
+
PutObjectCommand,
|
|
1698
|
+
DeleteObjectCommand
|
|
1699
|
+
} from "@aws-sdk/client-s3";
|
|
1700
|
+
async function metadata() {
|
|
1701
|
+
Logger.debug("Fetching app metadata");
|
|
1702
|
+
const [project, credentials, bootstrap2] = await Promise.all([
|
|
1703
|
+
useProject(),
|
|
1704
|
+
useAWSCredentials(),
|
|
1705
|
+
useBootstrap()
|
|
1706
|
+
]);
|
|
1707
|
+
const s3 = new S3Client({
|
|
1708
|
+
region: project.config.region,
|
|
1709
|
+
credentials
|
|
1710
|
+
});
|
|
1711
|
+
try {
|
|
1712
|
+
const result = await s3.send(
|
|
1713
|
+
new GetObjectCommand({
|
|
1714
|
+
Key: useS3Key(),
|
|
1715
|
+
Bucket: bootstrap2.bucket
|
|
1716
|
+
})
|
|
1717
|
+
);
|
|
1718
|
+
const body = await result.Body.transformToString();
|
|
1719
|
+
return JSON.parse(body);
|
|
1720
|
+
} catch (ex) {
|
|
1721
|
+
Logger.debug("Fetching app metadata: not found");
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
async function saveAppMetadata(data2) {
|
|
1725
|
+
Logger.debug("Saving app metadata");
|
|
1726
|
+
const [project, credentials, bootstrap2] = await Promise.all([
|
|
1727
|
+
useProject(),
|
|
1728
|
+
useAWSCredentials(),
|
|
1729
|
+
useBootstrap()
|
|
1730
|
+
]);
|
|
1731
|
+
const s3 = new S3Client({
|
|
1732
|
+
region: project.config.region,
|
|
1733
|
+
credentials
|
|
1734
|
+
});
|
|
1735
|
+
try {
|
|
1736
|
+
await s3.send(
|
|
1737
|
+
new PutObjectCommand({
|
|
1738
|
+
Key: useS3Key(),
|
|
1739
|
+
Bucket: bootstrap2.bucket,
|
|
1740
|
+
Body: JSON.stringify(data2)
|
|
1741
|
+
})
|
|
1742
|
+
);
|
|
1743
|
+
} catch (ex) {
|
|
1744
|
+
Logger.debug("Saving app metadata: not found");
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
async function clearAppMetadata() {
|
|
1748
|
+
Logger.debug("Clearing app metadata");
|
|
1749
|
+
const [project, credentials, bootstrap2] = await Promise.all([
|
|
1750
|
+
useProject(),
|
|
1751
|
+
useAWSCredentials(),
|
|
1752
|
+
useBootstrap()
|
|
1753
|
+
]);
|
|
1754
|
+
const s3 = new S3Client({
|
|
1755
|
+
region: project.config.region,
|
|
1756
|
+
credentials
|
|
1757
|
+
});
|
|
1758
|
+
await s3.send(
|
|
1759
|
+
new DeleteObjectCommand({
|
|
1760
|
+
Key: useS3Key(),
|
|
1761
|
+
Bucket: bootstrap2.bucket
|
|
1762
|
+
})
|
|
1763
|
+
);
|
|
1764
|
+
}
|
|
1765
|
+
function useS3Key() {
|
|
1766
|
+
const project = useProject();
|
|
1767
|
+
return `appMetadata/app.${project.config.name}/stage.${project.config.stage}.json`;
|
|
1768
|
+
}
|
|
1769
|
+
var MetadataContext, useAppMetadata;
|
|
1770
|
+
var init_app_metadata = __esm({
|
|
1771
|
+
"src/stacks/app-metadata.ts"() {
|
|
1772
|
+
"use strict";
|
|
1773
|
+
init_bootstrap();
|
|
1774
|
+
init_credentials();
|
|
1775
|
+
init_context();
|
|
1776
|
+
init_logger();
|
|
1777
|
+
init_project();
|
|
1778
|
+
MetadataContext = Context.create(async () => {
|
|
1779
|
+
const data2 = await metadata();
|
|
1780
|
+
return data2;
|
|
1781
|
+
});
|
|
1782
|
+
useAppMetadata = MetadataContext.use;
|
|
1783
|
+
}
|
|
1784
|
+
});
|
|
1785
|
+
|
|
1786
|
+
// src/stacks/assembly.ts
|
|
1787
|
+
async function loadAssembly(from) {
|
|
1788
|
+
const { CloudAssembly } = await import("aws-cdk-lib/cx-api");
|
|
1789
|
+
return new CloudAssembly(from);
|
|
1790
|
+
}
|
|
1791
|
+
var init_assembly = __esm({
|
|
1792
|
+
"src/stacks/assembly.ts"() {
|
|
1793
|
+
"use strict";
|
|
1794
|
+
}
|
|
1795
|
+
});
|
|
1796
|
+
|
|
1745
1797
|
// src/bus.ts
|
|
1746
1798
|
var bus_exports = {};
|
|
1747
1799
|
__export(bus_exports, {
|
|
@@ -1806,1282 +1858,366 @@ var init_bus = __esm({
|
|
|
1806
1858
|
}
|
|
1807
1859
|
});
|
|
1808
1860
|
|
|
1809
|
-
// src/
|
|
1810
|
-
import
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1861
|
+
// src/stacks/monitor.ts
|
|
1862
|
+
import {
|
|
1863
|
+
CloudFormationClient,
|
|
1864
|
+
DescribeStackResourcesCommand,
|
|
1865
|
+
DescribeStacksCommand,
|
|
1866
|
+
DescribeStackEventsCommand
|
|
1867
|
+
} from "@aws-sdk/client-cloudformation";
|
|
1868
|
+
import { map, omitBy, pipe } from "remeda";
|
|
1869
|
+
function isFinal(input) {
|
|
1870
|
+
return STATUSES_SUCCESS.includes(input) || STATUSES_FAILED.includes(input);
|
|
1871
|
+
}
|
|
1872
|
+
function isFailed(input) {
|
|
1873
|
+
return STATUSES_FAILED.includes(input);
|
|
1874
|
+
}
|
|
1875
|
+
function isSuccess(input) {
|
|
1876
|
+
return STATUSES_SUCCESS.includes(input);
|
|
1877
|
+
}
|
|
1878
|
+
function isPending(input) {
|
|
1879
|
+
return STATUSES_PENDING.includes(input);
|
|
1880
|
+
}
|
|
1881
|
+
async function monitor(stack) {
|
|
1882
|
+
const [cfn, bus] = await Promise.all([
|
|
1883
|
+
useAWSClient(CloudFormationClient),
|
|
1884
|
+
useBus()
|
|
1885
|
+
]);
|
|
1886
|
+
let lastStatus;
|
|
1887
|
+
const errors = {};
|
|
1888
|
+
let lastEvent;
|
|
1889
|
+
while (true) {
|
|
1890
|
+
try {
|
|
1891
|
+
const [describe, resources, events] = await Promise.all([
|
|
1892
|
+
cfn.send(
|
|
1893
|
+
new DescribeStacksCommand({
|
|
1894
|
+
StackName: stack
|
|
1895
|
+
})
|
|
1896
|
+
),
|
|
1897
|
+
cfn.send(
|
|
1898
|
+
new DescribeStackResourcesCommand({
|
|
1899
|
+
StackName: stack
|
|
1900
|
+
})
|
|
1901
|
+
),
|
|
1902
|
+
cfn.send(
|
|
1903
|
+
new DescribeStackEventsCommand({
|
|
1904
|
+
StackName: stack
|
|
1905
|
+
})
|
|
1906
|
+
)
|
|
1907
|
+
]);
|
|
1908
|
+
Logger.debug("Stack description", describe);
|
|
1909
|
+
if (lastEvent) {
|
|
1910
|
+
const eventsReversed = [...events.StackEvents ?? []].reverse();
|
|
1911
|
+
for (const event of eventsReversed) {
|
|
1912
|
+
if (!event.Timestamp)
|
|
1913
|
+
continue;
|
|
1914
|
+
if (event.Timestamp.getTime() > lastEvent.getTime()) {
|
|
1915
|
+
bus.publish("stack.event", {
|
|
1916
|
+
event,
|
|
1917
|
+
stackID: stack
|
|
1918
|
+
});
|
|
1919
|
+
if (event.ResourceStatusReason) {
|
|
1920
|
+
if (event.ResourceStatusReason.includes(
|
|
1921
|
+
"Resource creation cancelled"
|
|
1922
|
+
) || event.ResourceStatusReason.includes(
|
|
1923
|
+
"Resource update cancelled"
|
|
1924
|
+
) || event.ResourceStatusReason.includes(
|
|
1925
|
+
"Resource creation Initiated"
|
|
1926
|
+
) || event.ResourceStatusReason.startsWith(
|
|
1927
|
+
"The following resource(s) failed to"
|
|
1928
|
+
))
|
|
1929
|
+
continue;
|
|
1930
|
+
errors[event.LogicalResourceId] = event.ResourceStatusReason;
|
|
1931
|
+
}
|
|
1828
1932
|
}
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
}).query("getState", {
|
|
1832
|
-
async resolve({ ctx }) {
|
|
1833
|
-
return ctx.state;
|
|
1933
|
+
}
|
|
1934
|
+
Logger.debug("Last event set to", lastEvent);
|
|
1834
1935
|
}
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1936
|
+
lastEvent = events.StackEvents?.at(0)?.Timestamp;
|
|
1937
|
+
bus.publish("stack.resources", {
|
|
1938
|
+
stackID: stack,
|
|
1939
|
+
resources: resources.StackResources
|
|
1940
|
+
});
|
|
1941
|
+
for (const resource of resources.StackResources || []) {
|
|
1942
|
+
if (resource.ResourceStatusReason?.includes(
|
|
1943
|
+
"Resource creation cancelled"
|
|
1944
|
+
) || resource.ResourceStatusReason?.includes(
|
|
1945
|
+
"Resource update cancelled"
|
|
1946
|
+
) || resource.ResourceStatusReason?.includes(
|
|
1947
|
+
"Resource creation Initiated"
|
|
1948
|
+
) || resource.ResourceStatusReason?.startsWith(
|
|
1949
|
+
"The following resource(s) failed to"
|
|
1950
|
+
))
|
|
1951
|
+
continue;
|
|
1952
|
+
if (resource.ResourceStatusReason)
|
|
1953
|
+
errors[resource.LogicalResourceId] = resource.ResourceStatusReason;
|
|
1838
1954
|
}
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1955
|
+
const [first] = describe.Stacks || [];
|
|
1956
|
+
if (first) {
|
|
1957
|
+
if (lastStatus !== first.StackStatus && first.StackStatus) {
|
|
1958
|
+
lastStatus = first.StackStatus;
|
|
1959
|
+
bus.publish("stack.status", {
|
|
1960
|
+
stackID: stack,
|
|
1961
|
+
status: first.StackStatus
|
|
1845
1962
|
});
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1963
|
+
Logger.debug(first);
|
|
1964
|
+
if (isFinal(first.StackStatus)) {
|
|
1965
|
+
return {
|
|
1966
|
+
status: first.StackStatus,
|
|
1967
|
+
outputs: pipe(
|
|
1968
|
+
first.Outputs || [],
|
|
1969
|
+
map((o) => [o.OutputKey, o.OutputValue]),
|
|
1970
|
+
Object.fromEntries,
|
|
1971
|
+
filterOutputs
|
|
1972
|
+
),
|
|
1973
|
+
errors: isFailed(first.StackStatus) ? errors : {}
|
|
1974
|
+
};
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1850
1977
|
}
|
|
1851
|
-
})
|
|
1978
|
+
} catch (ex) {
|
|
1979
|
+
if (ex.message.includes("does not exist")) {
|
|
1980
|
+
bus.publish("stack.status", {
|
|
1981
|
+
stackID: stack,
|
|
1982
|
+
status: "DELETE_COMPLETE"
|
|
1983
|
+
});
|
|
1984
|
+
return {
|
|
1985
|
+
status: "DELETE_COMPLETE",
|
|
1986
|
+
outputs: {},
|
|
1987
|
+
errors: {}
|
|
1988
|
+
};
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
function filterOutputs(input) {
|
|
1995
|
+
return pipe(
|
|
1996
|
+
input,
|
|
1997
|
+
omitBy((_, key) => {
|
|
1998
|
+
return key.startsWith("Export") || key === "SSTMetadata";
|
|
1999
|
+
})
|
|
2000
|
+
);
|
|
2001
|
+
}
|
|
2002
|
+
var STATUSES_PENDING, STATUSES_SUCCESS, STATUSES_FAILED, STATUSES;
|
|
2003
|
+
var init_monitor = __esm({
|
|
2004
|
+
"src/stacks/monitor.ts"() {
|
|
2005
|
+
"use strict";
|
|
2006
|
+
init_bus();
|
|
2007
|
+
init_credentials();
|
|
2008
|
+
init_logger();
|
|
2009
|
+
STATUSES_PENDING = [
|
|
2010
|
+
"CREATE_IN_PROGRESS",
|
|
2011
|
+
"DELETE_IN_PROGRESS",
|
|
2012
|
+
"REVIEW_IN_PROGRESS",
|
|
2013
|
+
"ROLLBACK_IN_PROGRESS",
|
|
2014
|
+
"UPDATE_COMPLETE_CLEANUP_IN_PROGRESS",
|
|
2015
|
+
"UPDATE_IN_PROGRESS",
|
|
2016
|
+
"UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS",
|
|
2017
|
+
"UPDATE_ROLLBACK_IN_PROGRESS"
|
|
2018
|
+
];
|
|
2019
|
+
STATUSES_SUCCESS = [
|
|
2020
|
+
"CREATE_COMPLETE",
|
|
2021
|
+
"UPDATE_COMPLETE",
|
|
2022
|
+
"DELETE_COMPLETE",
|
|
2023
|
+
"SKIPPED"
|
|
2024
|
+
];
|
|
2025
|
+
STATUSES_FAILED = [
|
|
2026
|
+
"CREATE_FAILED",
|
|
2027
|
+
"DELETE_FAILED",
|
|
2028
|
+
"ROLLBACK_FAILED",
|
|
2029
|
+
"ROLLBACK_COMPLETE",
|
|
2030
|
+
"UPDATE_FAILED",
|
|
2031
|
+
"UPDATE_ROLLBACK_COMPLETE",
|
|
2032
|
+
"UPDATE_ROLLBACK_FAILED",
|
|
2033
|
+
"DEPENDENCY_FAILED"
|
|
2034
|
+
];
|
|
2035
|
+
STATUSES = [
|
|
2036
|
+
...STATUSES_PENDING,
|
|
2037
|
+
...STATUSES_SUCCESS,
|
|
2038
|
+
...STATUSES_FAILED
|
|
2039
|
+
];
|
|
1852
2040
|
}
|
|
1853
2041
|
});
|
|
1854
2042
|
|
|
1855
|
-
// src/
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
2043
|
+
// src/cdk/util.ts
|
|
2044
|
+
async function callWithRetry(cb) {
|
|
2045
|
+
try {
|
|
2046
|
+
return await cb();
|
|
2047
|
+
} catch (e) {
|
|
2048
|
+
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") {
|
|
2049
|
+
return await callWithRetry(cb);
|
|
2050
|
+
}
|
|
2051
|
+
throw e;
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
var init_util = __esm({
|
|
2055
|
+
"src/cdk/util.ts"() {
|
|
2056
|
+
"use strict";
|
|
2057
|
+
}
|
|
1860
2058
|
});
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
import
|
|
1864
|
-
import
|
|
1865
|
-
import
|
|
1866
|
-
import
|
|
1867
|
-
import {
|
|
1868
|
-
import {
|
|
1869
|
-
import {
|
|
1870
|
-
import
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
const
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
2059
|
+
|
|
2060
|
+
// src/cdk/deploy-stack.ts
|
|
2061
|
+
import * as cxapi from "@aws-cdk/cx-api";
|
|
2062
|
+
import fs5 from "fs/promises";
|
|
2063
|
+
import * as uuid from "uuid";
|
|
2064
|
+
import { addMetadataAssetsToManifest } from "sst-aws-cdk/lib/assets.js";
|
|
2065
|
+
import { debug, error, print } from "sst-aws-cdk/lib/logging.js";
|
|
2066
|
+
import { toYAML } from "sst-aws-cdk/lib/serialize.js";
|
|
2067
|
+
import { AssetManifestBuilder } from "sst-aws-cdk/lib/util/asset-manifest-builder.js";
|
|
2068
|
+
import { publishAssets } from "sst-aws-cdk/lib/util/asset-publishing.js";
|
|
2069
|
+
import { contentHash } from "sst-aws-cdk/lib/util/content-hash.js";
|
|
2070
|
+
import { CfnEvaluationException } from "sst-aws-cdk/lib/api/evaluate-cloudformation-template.js";
|
|
2071
|
+
import { tryHotswapDeployment } from "sst-aws-cdk/lib/api/hotswap-deployments.js";
|
|
2072
|
+
import {
|
|
2073
|
+
changeSetHasNoChanges,
|
|
2074
|
+
CloudFormationStack,
|
|
2075
|
+
TemplateParameters,
|
|
2076
|
+
waitForChangeSet,
|
|
2077
|
+
waitForStackDeploy,
|
|
2078
|
+
waitForStackDelete
|
|
2079
|
+
} from "sst-aws-cdk/lib/api/util/cloudformation.js";
|
|
2080
|
+
import { blue as blue2 } from "colorette";
|
|
2081
|
+
async function deployStack(options) {
|
|
2082
|
+
const stackArtifact = options.stack;
|
|
2083
|
+
const stackEnv = options.resolvedEnvironment;
|
|
2084
|
+
options.sdk.appendCustomUserAgent(options.extraUserAgent);
|
|
2085
|
+
const cfn = options.sdk.cloudFormation();
|
|
2086
|
+
const deployName = options.deployName || stackArtifact.stackName;
|
|
2087
|
+
let cloudFormationStack = await callWithRetry(
|
|
2088
|
+
() => CloudFormationStack.lookup(cfn, deployName)
|
|
2089
|
+
);
|
|
2090
|
+
if (cloudFormationStack.stackStatus.isCreationFailure) {
|
|
2091
|
+
debug(
|
|
2092
|
+
`Found existing stack ${deployName} that had previously failed creation. Deleting it before attempting to re-create it.`
|
|
1891
2093
|
);
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
type: "*/*",
|
|
1898
|
-
limit: "1024mb"
|
|
1899
|
-
}),
|
|
1900
|
-
(req, res) => {
|
|
1901
|
-
res.header("Access-Control-Allow-Origin", "*");
|
|
1902
|
-
res.header(
|
|
1903
|
-
"Access-Control-Allow-Methods",
|
|
1904
|
-
"GET, PUT, PATCH, POST, DELETE"
|
|
1905
|
-
);
|
|
1906
|
-
res.header(
|
|
1907
|
-
"Access-Control-Allow-Headers",
|
|
1908
|
-
req.header("access-control-request-headers")
|
|
1909
|
-
);
|
|
1910
|
-
if (req.method === "OPTIONS")
|
|
1911
|
-
return res.send();
|
|
1912
|
-
const u = new URL(req.url.substring(7));
|
|
1913
|
-
const forward = https2.request(
|
|
1914
|
-
u,
|
|
1915
|
-
{
|
|
1916
|
-
headers: {
|
|
1917
|
-
...req.headers,
|
|
1918
|
-
host: u.hostname
|
|
1919
|
-
},
|
|
1920
|
-
method: req.method
|
|
1921
|
-
},
|
|
1922
|
-
(proxied) => {
|
|
1923
|
-
res.status(proxied.statusCode);
|
|
1924
|
-
for (const [key, value] of Object.entries(proxied.headers)) {
|
|
1925
|
-
res.header(key, value);
|
|
1926
|
-
}
|
|
1927
|
-
proxied.pipe(res);
|
|
1928
|
-
}
|
|
2094
|
+
await cfn.deleteStack({ StackName: deployName }).promise();
|
|
2095
|
+
const deletedStack = await waitForStackDelete(cfn, deployName);
|
|
2096
|
+
if (deletedStack && deletedStack.stackStatus.name !== "DELETE_COMPLETE") {
|
|
2097
|
+
throw new Error(
|
|
2098
|
+
`Failed deleting stack ${deployName} that had previously failed creation (current state: ${deletedStack.stackStatus})`
|
|
1929
2099
|
);
|
|
1930
|
-
if (req.method !== "GET" && req.method !== "DELETE" && req.method !== "HEAD" && req.body)
|
|
1931
|
-
forward.write(req.body);
|
|
1932
|
-
forward.end();
|
|
1933
|
-
forward.on("error", (e) => {
|
|
1934
|
-
console.log(e.message);
|
|
1935
|
-
});
|
|
1936
2100
|
}
|
|
2101
|
+
cloudFormationStack = CloudFormationStack.doesNotExist(cfn, deployName);
|
|
2102
|
+
}
|
|
2103
|
+
const legacyAssets = new AssetManifestBuilder();
|
|
2104
|
+
const assetParams = await addMetadataAssetsToManifest(
|
|
2105
|
+
stackArtifact,
|
|
2106
|
+
legacyAssets,
|
|
2107
|
+
options.toolkitInfo,
|
|
2108
|
+
options.reuseAssets
|
|
1937
2109
|
);
|
|
1938
|
-
const
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
]);
|
|
1954
|
-
return https2.createServer(
|
|
1955
|
-
{
|
|
1956
|
-
key,
|
|
1957
|
-
cert
|
|
1958
|
-
},
|
|
1959
|
-
rest
|
|
1960
|
-
);
|
|
2110
|
+
const finalParameterValues = { ...options.parameters, ...assetParams };
|
|
2111
|
+
const templateParams = TemplateParameters.fromTemplate(
|
|
2112
|
+
stackArtifact.template
|
|
2113
|
+
);
|
|
2114
|
+
const stackParams = options.usePreviousParameters ? templateParams.updateExisting(
|
|
2115
|
+
finalParameterValues,
|
|
2116
|
+
cloudFormationStack.parameters
|
|
2117
|
+
) : templateParams.supplyAll(finalParameterValues);
|
|
2118
|
+
if (await canSkipDeploy(
|
|
2119
|
+
options,
|
|
2120
|
+
cloudFormationStack,
|
|
2121
|
+
stackParams.hasChanges(cloudFormationStack.parameters)
|
|
2122
|
+
)) {
|
|
2123
|
+
debug(`${deployName}: skipping deployment (use --force to override)`);
|
|
2124
|
+
if (options.hotswap) {
|
|
1961
2125
|
}
|
|
1962
|
-
return
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
return;
|
|
1970
|
-
if (req.headers.origin?.endsWith("console.serverless-stack.com"))
|
|
1971
|
-
return;
|
|
1972
|
-
if (req.headers.origin?.endsWith("console.sst.dev"))
|
|
1973
|
-
return;
|
|
1974
|
-
if (req.headers.origin?.endsWith("--sst-console.netlify.app"))
|
|
1975
|
-
return;
|
|
1976
|
-
console.log("Rejecting unauthorized connection from " + req.headers.origin);
|
|
1977
|
-
socket.terminate();
|
|
1978
|
-
});
|
|
1979
|
-
server.listen(cfg.port);
|
|
1980
|
-
const handler = applyWSSHandler({
|
|
1981
|
-
wss,
|
|
1982
|
-
router: router2,
|
|
1983
|
-
createContext() {
|
|
1984
|
-
return {
|
|
1985
|
-
state: state2
|
|
1986
|
-
};
|
|
1987
|
-
}
|
|
1988
|
-
});
|
|
1989
|
-
process.on("SIGTERM", () => {
|
|
1990
|
-
handler.broadcastReconnectNotification();
|
|
1991
|
-
wss.close();
|
|
1992
|
-
});
|
|
1993
|
-
const bus = useBus();
|
|
1994
|
-
const pending = [];
|
|
1995
|
-
function updateState(cb) {
|
|
1996
|
-
const [next, patches] = produceWithPatches(state2, cb);
|
|
1997
|
-
if (!patches.length)
|
|
1998
|
-
return;
|
|
1999
|
-
const scheduled = pending.length;
|
|
2000
|
-
pending.push(...optimise(state2, patches));
|
|
2001
|
-
if (!scheduled)
|
|
2002
|
-
setTimeout(() => {
|
|
2003
|
-
bus.publish("local.patches", pending);
|
|
2004
|
-
pending.splice(0, pending.length);
|
|
2005
|
-
}, 0);
|
|
2006
|
-
state2 = next;
|
|
2007
|
-
}
|
|
2008
|
-
function updateFunction(id, cb) {
|
|
2009
|
-
return updateState((draft) => {
|
|
2010
|
-
let func = draft.functions[id];
|
|
2011
|
-
if (!func) {
|
|
2012
|
-
func = {
|
|
2013
|
-
warm: true,
|
|
2014
|
-
state: "idle",
|
|
2015
|
-
issues: {},
|
|
2016
|
-
invocations: []
|
|
2017
|
-
};
|
|
2018
|
-
draft.functions[id] = func;
|
|
2019
|
-
}
|
|
2020
|
-
cb(func);
|
|
2021
|
-
});
|
|
2126
|
+
return {
|
|
2127
|
+
noOp: true,
|
|
2128
|
+
outputs: cloudFormationStack.outputs,
|
|
2129
|
+
stackArn: cloudFormationStack.stackId
|
|
2130
|
+
};
|
|
2131
|
+
} else {
|
|
2132
|
+
debug(`${deployName}: deploying...`);
|
|
2022
2133
|
}
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2134
|
+
const bodyParameter = await makeBodyParameter(
|
|
2135
|
+
stackArtifact,
|
|
2136
|
+
options.resolvedEnvironment,
|
|
2137
|
+
legacyAssets,
|
|
2138
|
+
options.toolkitInfo,
|
|
2139
|
+
options.sdk,
|
|
2140
|
+
options.overrideTemplate
|
|
2141
|
+
);
|
|
2142
|
+
await publishAssets(
|
|
2143
|
+
legacyAssets.toManifest(stackArtifact.assembly.directory),
|
|
2144
|
+
options.sdkProvider,
|
|
2145
|
+
stackEnv,
|
|
2146
|
+
{
|
|
2147
|
+
parallel: options.assetParallelism
|
|
2148
|
+
}
|
|
2149
|
+
);
|
|
2150
|
+
if (options.hotswap) {
|
|
2151
|
+
try {
|
|
2152
|
+
const hotswapDeploymentResult = await tryHotswapDeployment(
|
|
2153
|
+
options.sdkProvider,
|
|
2154
|
+
assetParams,
|
|
2155
|
+
cloudFormationStack,
|
|
2156
|
+
stackArtifact
|
|
2041
2157
|
);
|
|
2042
|
-
if (
|
|
2043
|
-
return;
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
});
|
|
2049
|
-
});
|
|
2050
|
-
bus.subscribe("function.success", (evt) => {
|
|
2051
|
-
updateFunction(evt.properties.functionID, (draft) => {
|
|
2052
|
-
const invocation = draft.invocations.find(
|
|
2053
|
-
(x) => x.id === evt.properties.requestID
|
|
2158
|
+
if (hotswapDeploymentResult) {
|
|
2159
|
+
return hotswapDeploymentResult;
|
|
2160
|
+
}
|
|
2161
|
+
print(
|
|
2162
|
+
"Could not perform a hotswap deployment, as the stack %s contains non-Asset changes",
|
|
2163
|
+
stackArtifact.displayName
|
|
2054
2164
|
);
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
});
|
|
2063
|
-
});
|
|
2064
|
-
bus.subscribe("function.error", (evt) => {
|
|
2065
|
-
updateFunction(evt.properties.functionID, (draft) => {
|
|
2066
|
-
const invocation = draft.invocations.find(
|
|
2067
|
-
(x) => x.id === evt.properties.requestID
|
|
2165
|
+
} catch (e) {
|
|
2166
|
+
if (!(e instanceof CfnEvaluationException)) {
|
|
2167
|
+
throw e;
|
|
2168
|
+
}
|
|
2169
|
+
print(
|
|
2170
|
+
"Could not perform a hotswap deployment, because the CloudFormation template could not be resolved: %s",
|
|
2171
|
+
e.message
|
|
2068
2172
|
);
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
const result = {
|
|
2082
|
-
updateState,
|
|
2083
|
-
updateFunction
|
|
2084
|
-
};
|
|
2085
|
-
return result;
|
|
2173
|
+
}
|
|
2174
|
+
print("Falling back to doing a full deployment");
|
|
2175
|
+
options.sdk.appendCustomUserAgent("cdk-hotswap/fallback");
|
|
2176
|
+
}
|
|
2177
|
+
const fullDeployment = new FullCloudFormationDeployment(
|
|
2178
|
+
options,
|
|
2179
|
+
cloudFormationStack,
|
|
2180
|
+
stackArtifact,
|
|
2181
|
+
stackParams,
|
|
2182
|
+
bodyParameter
|
|
2183
|
+
);
|
|
2184
|
+
return fullDeployment.performDeployment();
|
|
2086
2185
|
}
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
useLocalServerConfig = Context.memo(async () => {
|
|
2097
|
-
const project = useProject();
|
|
2098
|
-
const port = await getPort({
|
|
2099
|
-
port: 13557
|
|
2100
|
-
});
|
|
2101
|
-
return {
|
|
2102
|
-
port,
|
|
2103
|
-
url: `https://console.sst.dev/${project.config.name}/${project.config.stage}${port !== 13557 ? `?_port=${port}` : ""}`
|
|
2104
|
-
};
|
|
2105
|
-
});
|
|
2186
|
+
async function makeBodyParameter(stack, resolvedEnvironment, assetManifest, toolkitInfo, sdk, overrideTemplate) {
|
|
2187
|
+
if (stack.stackTemplateAssetObjectUrl && !overrideTemplate) {
|
|
2188
|
+
return {
|
|
2189
|
+
TemplateURL: restUrlFromManifest(
|
|
2190
|
+
stack.stackTemplateAssetObjectUrl,
|
|
2191
|
+
resolvedEnvironment,
|
|
2192
|
+
sdk
|
|
2193
|
+
)
|
|
2194
|
+
};
|
|
2106
2195
|
}
|
|
2107
|
-
|
|
2196
|
+
const templateJson = toYAML(overrideTemplate ?? stack.template);
|
|
2197
|
+
if (templateJson.length <= LARGE_TEMPLATE_SIZE_KB * 1024) {
|
|
2198
|
+
return { TemplateBody: templateJson };
|
|
2199
|
+
}
|
|
2200
|
+
if (!toolkitInfo.found) {
|
|
2201
|
+
error(
|
|
2202
|
+
`The template for stack "${stack.displayName}" is ${Math.round(
|
|
2203
|
+
templateJson.length / 1024
|
|
2204
|
+
)}KiB. Templates larger than ${LARGE_TEMPLATE_SIZE_KB}KiB must be uploaded to S3.
|
|
2205
|
+
Run the following command in order to setup an S3 bucket in this environment, and then re-deploy:
|
|
2108
2206
|
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
async function printHeader(input) {
|
|
2116
|
-
const project = useProject();
|
|
2117
|
-
Colors.line(
|
|
2118
|
-
`${Colors.primary.bold(`SST v${project.version}`)} ${input.hint ? Colors.dim(`ready!`) : ""}`
|
|
2119
|
-
);
|
|
2120
|
-
Colors.gap();
|
|
2121
|
-
Colors.line(
|
|
2122
|
-
`${Colors.primary(`\u279C`)} ${Colors.bold("App:")} ${project.config.name}`
|
|
2123
|
-
);
|
|
2124
|
-
Colors.line(
|
|
2125
|
-
`${Colors.primary(` `)} ${Colors.bold("Stage:")} ${project.config.stage}`
|
|
2126
|
-
);
|
|
2127
|
-
if (input.console) {
|
|
2128
|
-
const local = await useLocalServerConfig();
|
|
2129
|
-
Colors.line(
|
|
2130
|
-
`${Colors.primary(` `)} ${Colors.bold("Console:")} ${Colors.link(
|
|
2131
|
-
local.url
|
|
2132
|
-
)}`
|
|
2207
|
+
`,
|
|
2208
|
+
blue2(` $ cdk bootstrap ${resolvedEnvironment.name}
|
|
2209
|
+
`)
|
|
2210
|
+
);
|
|
2211
|
+
throw new Error(
|
|
2212
|
+
'Template too large to deploy ("cdk bootstrap" is required)'
|
|
2133
2213
|
);
|
|
2134
2214
|
}
|
|
2135
|
-
|
|
2136
|
-
}
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
"use strict";
|
|
2142
|
-
init_project();
|
|
2143
|
-
init_colors();
|
|
2144
|
-
init_server();
|
|
2145
|
-
}
|
|
2146
|
-
});
|
|
2147
|
-
|
|
2148
|
-
// src/watcher.ts
|
|
2149
|
-
var watcher_exports = {};
|
|
2150
|
-
__export(watcher_exports, {
|
|
2151
|
-
useWatcher: () => useWatcher
|
|
2152
|
-
});
|
|
2153
|
-
import chokidar from "chokidar";
|
|
2154
|
-
import path6 from "path";
|
|
2155
|
-
var useWatcher;
|
|
2156
|
-
var init_watcher = __esm({
|
|
2157
|
-
"src/watcher.ts"() {
|
|
2158
|
-
"use strict";
|
|
2159
|
-
init_context();
|
|
2160
|
-
init_bus();
|
|
2161
|
-
init_project();
|
|
2162
|
-
useWatcher = Context.memo(() => {
|
|
2163
|
-
const project = useProject();
|
|
2164
|
-
const bus = useBus();
|
|
2165
|
-
const watcher = chokidar.watch([project.paths.root], {
|
|
2166
|
-
persistent: true,
|
|
2167
|
-
ignoreInitial: true,
|
|
2168
|
-
followSymlinks: false,
|
|
2169
|
-
disableGlobbing: false,
|
|
2170
|
-
ignored: [
|
|
2171
|
-
"**/node_modules/**",
|
|
2172
|
-
"**/.build/**",
|
|
2173
|
-
"**/.sst/**",
|
|
2174
|
-
"**/debug.log"
|
|
2175
|
-
],
|
|
2176
|
-
awaitWriteFinish: {
|
|
2177
|
-
pollInterval: 100,
|
|
2178
|
-
stabilityThreshold: 20
|
|
2179
|
-
}
|
|
2180
|
-
});
|
|
2181
|
-
watcher.on("change", (file) => {
|
|
2182
|
-
bus.publish("file.changed", {
|
|
2183
|
-
file,
|
|
2184
|
-
relative: path6.relative(project.paths.root, file)
|
|
2185
|
-
});
|
|
2186
|
-
});
|
|
2187
|
-
return {
|
|
2188
|
-
subscribe: bus.forward("file.changed")
|
|
2189
|
-
};
|
|
2190
|
-
});
|
|
2191
|
-
}
|
|
2192
|
-
});
|
|
2193
|
-
|
|
2194
|
-
// src/runtime/handlers.ts
|
|
2195
|
-
import path7 from "path";
|
|
2196
|
-
import fs7 from "fs/promises";
|
|
2197
|
-
import { useFunctions } from "../src/constructs/Function.js";
|
|
2198
|
-
var useRuntimeHandlers, useFunctionBuilder;
|
|
2199
|
-
var init_handlers = __esm({
|
|
2200
|
-
"src/runtime/handlers.ts"() {
|
|
2201
|
-
"use strict";
|
|
2202
|
-
init_context();
|
|
2203
|
-
init_logger();
|
|
2204
|
-
init_watcher();
|
|
2205
|
-
init_bus();
|
|
2206
|
-
init_project();
|
|
2207
|
-
useRuntimeHandlers = Context.memo(() => {
|
|
2208
|
-
const handlers = [];
|
|
2209
|
-
const project = useProject();
|
|
2210
|
-
const bus = useBus();
|
|
2211
|
-
const pendingBuilds = /* @__PURE__ */ new Map();
|
|
2212
|
-
const result = {
|
|
2213
|
-
subscribe: bus.forward("function.build.success", "function.build.failed"),
|
|
2214
|
-
register: (handler) => {
|
|
2215
|
-
handlers.push(handler);
|
|
2216
|
-
},
|
|
2217
|
-
for: (runtime) => {
|
|
2218
|
-
const result2 = handlers.find((x) => x.canHandle(runtime));
|
|
2219
|
-
if (!result2)
|
|
2220
|
-
throw new Error(`${runtime} runtime is unsupported`);
|
|
2221
|
-
return result2;
|
|
2222
|
-
},
|
|
2223
|
-
async build(functionID, mode) {
|
|
2224
|
-
async function task() {
|
|
2225
|
-
const func = useFunctions().fromID(functionID);
|
|
2226
|
-
const handler = result.for(func.runtime);
|
|
2227
|
-
const out = path7.join(project.paths.artifacts, functionID);
|
|
2228
|
-
await fs7.rm(out, { recursive: true, force: true });
|
|
2229
|
-
await fs7.mkdir(out, { recursive: true });
|
|
2230
|
-
if (func.hooks?.beforeBuild)
|
|
2231
|
-
await func.hooks.beforeBuild(func, out);
|
|
2232
|
-
const built = await handler.build({
|
|
2233
|
-
functionID,
|
|
2234
|
-
out,
|
|
2235
|
-
mode,
|
|
2236
|
-
props: func
|
|
2237
|
-
});
|
|
2238
|
-
if (built.type === "error") {
|
|
2239
|
-
bus.publish("function.build.failed", {
|
|
2240
|
-
functionID,
|
|
2241
|
-
errors: built.errors
|
|
2242
|
-
});
|
|
2243
|
-
return built;
|
|
2244
|
-
}
|
|
2245
|
-
if (func.copyFiles) {
|
|
2246
|
-
await Promise.all(
|
|
2247
|
-
func.copyFiles.map(async (entry) => {
|
|
2248
|
-
const fromPath = path7.join(project.paths.root, entry.from);
|
|
2249
|
-
const to = entry.to || entry.from;
|
|
2250
|
-
if (path7.isAbsolute(to))
|
|
2251
|
-
throw new Error(
|
|
2252
|
-
`Copy destination path "${to}" must be relative`
|
|
2253
|
-
);
|
|
2254
|
-
const toPath = path7.join(out, to);
|
|
2255
|
-
if (mode === "deploy")
|
|
2256
|
-
await fs7.cp(fromPath, toPath, {
|
|
2257
|
-
recursive: true
|
|
2258
|
-
});
|
|
2259
|
-
if (mode === "start") {
|
|
2260
|
-
const dir = path7.dirname(toPath);
|
|
2261
|
-
await fs7.mkdir(dir, { recursive: true });
|
|
2262
|
-
await fs7.symlink(fromPath, toPath);
|
|
2263
|
-
}
|
|
2264
|
-
})
|
|
2265
|
-
);
|
|
2266
|
-
}
|
|
2267
|
-
if (func.hooks?.afterBuild)
|
|
2268
|
-
await func.hooks.afterBuild(func, out);
|
|
2269
|
-
bus.publish("function.build.success", { functionID });
|
|
2270
|
-
return {
|
|
2271
|
-
...built,
|
|
2272
|
-
out
|
|
2273
|
-
};
|
|
2274
|
-
}
|
|
2275
|
-
if (pendingBuilds.has(functionID)) {
|
|
2276
|
-
Logger.debug("Waiting on pending build", functionID);
|
|
2277
|
-
return pendingBuilds.get(functionID);
|
|
2278
|
-
}
|
|
2279
|
-
const promise = task();
|
|
2280
|
-
pendingBuilds.set(functionID, promise);
|
|
2281
|
-
Logger.debug("Building function", functionID);
|
|
2282
|
-
const r = await promise;
|
|
2283
|
-
pendingBuilds.delete(functionID);
|
|
2284
|
-
return r;
|
|
2285
|
-
}
|
|
2286
|
-
};
|
|
2287
|
-
return result;
|
|
2288
|
-
});
|
|
2289
|
-
useFunctionBuilder = Context.memo(() => {
|
|
2290
|
-
const artifacts = /* @__PURE__ */ new Map();
|
|
2291
|
-
const handlers = useRuntimeHandlers();
|
|
2292
|
-
const result = {
|
|
2293
|
-
artifact: (functionID) => {
|
|
2294
|
-
if (artifacts.has(functionID))
|
|
2295
|
-
return artifacts.get(functionID);
|
|
2296
|
-
return result.build(functionID);
|
|
2297
|
-
},
|
|
2298
|
-
build: async (functionID) => {
|
|
2299
|
-
const result2 = await handlers.build(functionID, "start");
|
|
2300
|
-
if (result2.type === "error")
|
|
2301
|
-
return;
|
|
2302
|
-
artifacts.set(functionID, result2);
|
|
2303
|
-
return artifacts.get(functionID);
|
|
2304
|
-
}
|
|
2305
|
-
};
|
|
2306
|
-
const watcher = useWatcher();
|
|
2307
|
-
watcher.subscribe("file.changed", async (evt) => {
|
|
2308
|
-
try {
|
|
2309
|
-
const functions = useFunctions();
|
|
2310
|
-
for (const [functionID, props] of Object.entries(functions.all)) {
|
|
2311
|
-
const handler = handlers.for(props.runtime);
|
|
2312
|
-
if (!handler?.shouldBuild({
|
|
2313
|
-
functionID,
|
|
2314
|
-
file: evt.properties.file
|
|
2315
|
-
}))
|
|
2316
|
-
continue;
|
|
2317
|
-
await result.build(functionID);
|
|
2318
|
-
Logger.debug("Rebuilt function", functionID);
|
|
2319
|
-
}
|
|
2320
|
-
} catch {
|
|
2321
|
-
}
|
|
2322
|
-
});
|
|
2323
|
-
return result;
|
|
2324
|
-
});
|
|
2325
|
-
}
|
|
2326
|
-
});
|
|
2327
|
-
|
|
2328
|
-
// src/runtime/server.ts
|
|
2329
|
-
var server_exports2 = {};
|
|
2330
|
-
__export(server_exports2, {
|
|
2331
|
-
useRuntimeServer: () => useRuntimeServer,
|
|
2332
|
-
useRuntimeServerConfig: () => useRuntimeServerConfig
|
|
2333
|
-
});
|
|
2334
|
-
import express2 from "express";
|
|
2335
|
-
import https3 from "https";
|
|
2336
|
-
import getPort2 from "get-port";
|
|
2337
|
-
var useRuntimeServerConfig, useRuntimeServer;
|
|
2338
|
-
var init_server2 = __esm({
|
|
2339
|
-
"src/runtime/server.ts"() {
|
|
2340
|
-
"use strict";
|
|
2341
|
-
init_context();
|
|
2342
|
-
init_bus();
|
|
2343
|
-
init_logger();
|
|
2344
|
-
init_workers();
|
|
2345
|
-
useRuntimeServerConfig = Context.memo(async () => {
|
|
2346
|
-
const port = await getPort2({
|
|
2347
|
-
port: 12557
|
|
2348
|
-
});
|
|
2349
|
-
return {
|
|
2350
|
-
API_VERSION: "2018-06-01",
|
|
2351
|
-
port,
|
|
2352
|
-
url: `http://localhost:${port}`
|
|
2353
|
-
};
|
|
2354
|
-
});
|
|
2355
|
-
useRuntimeServer = Context.memo(async () => {
|
|
2356
|
-
const bus = useBus();
|
|
2357
|
-
const app = express2();
|
|
2358
|
-
const workers = await useRuntimeWorkers();
|
|
2359
|
-
const cfg = await useRuntimeServerConfig();
|
|
2360
|
-
const workersWaiting = /* @__PURE__ */ new Map();
|
|
2361
|
-
const invocationsQueued = /* @__PURE__ */ new Map();
|
|
2362
|
-
function next(workerID) {
|
|
2363
|
-
const queue = invocationsQueued.get(workerID);
|
|
2364
|
-
const value = queue?.shift();
|
|
2365
|
-
if (value)
|
|
2366
|
-
return value;
|
|
2367
|
-
return new Promise((resolve, reject) => {
|
|
2368
|
-
workersWaiting.set(workerID, resolve);
|
|
2369
|
-
});
|
|
2370
|
-
}
|
|
2371
|
-
workers.subscribe("worker.exited", async (evt) => {
|
|
2372
|
-
const waiting = workersWaiting.get(evt.properties.workerID);
|
|
2373
|
-
if (!waiting)
|
|
2374
|
-
return;
|
|
2375
|
-
workersWaiting.delete(evt.properties.workerID);
|
|
2376
|
-
});
|
|
2377
|
-
bus.subscribe("function.invoked", async (evt) => {
|
|
2378
|
-
const worker = workersWaiting.get(evt.properties.workerID);
|
|
2379
|
-
if (worker) {
|
|
2380
|
-
workersWaiting.delete(evt.properties.workerID);
|
|
2381
|
-
worker(evt.properties);
|
|
2382
|
-
return;
|
|
2383
|
-
}
|
|
2384
|
-
let arr = invocationsQueued.get(evt.properties.workerID);
|
|
2385
|
-
if (!arr) {
|
|
2386
|
-
arr = [];
|
|
2387
|
-
invocationsQueued.set(evt.properties.workerID, arr);
|
|
2388
|
-
}
|
|
2389
|
-
arr.push(evt.properties);
|
|
2390
|
-
});
|
|
2391
|
-
app.post(
|
|
2392
|
-
`/:workerID/${cfg.API_VERSION}/runtime/init/error`,
|
|
2393
|
-
express2.json({
|
|
2394
|
-
strict: false,
|
|
2395
|
-
type: ["application/json", "application/*+json"],
|
|
2396
|
-
limit: "10mb"
|
|
2397
|
-
}),
|
|
2398
|
-
async (req, res) => {
|
|
2399
|
-
const worker = workers.fromID(req.params.workerID);
|
|
2400
|
-
bus.publish("function.error", {
|
|
2401
|
-
requestID: workers.getCurrentRequestID(worker.workerID),
|
|
2402
|
-
workerID: worker.workerID,
|
|
2403
|
-
functionID: worker.functionID,
|
|
2404
|
-
...req.body
|
|
2405
|
-
});
|
|
2406
|
-
res.json("ok");
|
|
2407
|
-
}
|
|
2408
|
-
);
|
|
2409
|
-
app.get(
|
|
2410
|
-
`/:workerID/${cfg.API_VERSION}/runtime/invocation/next`,
|
|
2411
|
-
async (req, res) => {
|
|
2412
|
-
Logger.debug(
|
|
2413
|
-
"Worker",
|
|
2414
|
-
req.params.workerID,
|
|
2415
|
-
"is waiting for next invocation"
|
|
2416
|
-
);
|
|
2417
|
-
const payload = await next(req.params.workerID);
|
|
2418
|
-
Logger.debug("Worker", req.params.workerID, "sending next payload");
|
|
2419
|
-
res.set({
|
|
2420
|
-
"Lambda-Runtime-Aws-Request-Id": payload.context.awsRequestId,
|
|
2421
|
-
"Lambda-Runtime-Deadline-Ms": Date.now() + payload.deadline,
|
|
2422
|
-
"Lambda-Runtime-Invoked-Function-Arn": payload.context.invokedFunctionArn,
|
|
2423
|
-
"Lambda-Runtime-Client-Context": JSON.stringify(
|
|
2424
|
-
payload.context.clientContext || null
|
|
2425
|
-
),
|
|
2426
|
-
"Lambda-Runtime-Cognito-Identity": JSON.stringify(
|
|
2427
|
-
payload.context.identity || null
|
|
2428
|
-
),
|
|
2429
|
-
"Lambda-Runtime-Log-Group-Name": payload.context.logGroupName,
|
|
2430
|
-
"Lambda-Runtime-Log-Stream-Name": payload.context.logStreamName
|
|
2431
|
-
});
|
|
2432
|
-
res.json(payload.event);
|
|
2433
|
-
}
|
|
2434
|
-
);
|
|
2435
|
-
app.post(
|
|
2436
|
-
`/:workerID/${cfg.API_VERSION}/runtime/invocation/:awsRequestId/response`,
|
|
2437
|
-
express2.json({
|
|
2438
|
-
strict: false,
|
|
2439
|
-
type() {
|
|
2440
|
-
return true;
|
|
2441
|
-
},
|
|
2442
|
-
limit: "10mb"
|
|
2443
|
-
}),
|
|
2444
|
-
(req, res) => {
|
|
2445
|
-
Logger.debug("Worker", req.params.workerID, "got response", req.body);
|
|
2446
|
-
const worker = workers.fromID(req.params.workerID);
|
|
2447
|
-
bus.publish("function.success", {
|
|
2448
|
-
workerID: worker.workerID,
|
|
2449
|
-
functionID: worker.functionID,
|
|
2450
|
-
requestID: req.params.awsRequestId,
|
|
2451
|
-
body: req.body
|
|
2452
|
-
});
|
|
2453
|
-
res.status(202).send();
|
|
2454
|
-
}
|
|
2455
|
-
);
|
|
2456
|
-
app.all(
|
|
2457
|
-
`/proxy*`,
|
|
2458
|
-
express2.raw({
|
|
2459
|
-
type: "*/*",
|
|
2460
|
-
limit: "1024mb"
|
|
2461
|
-
}),
|
|
2462
|
-
(req, res) => {
|
|
2463
|
-
res.header("Access-Control-Allow-Origin", "*");
|
|
2464
|
-
res.header(
|
|
2465
|
-
"Access-Control-Allow-Methods",
|
|
2466
|
-
"GET, PUT, PATCH, POST, DELETE"
|
|
2467
|
-
);
|
|
2468
|
-
res.header(
|
|
2469
|
-
"Access-Control-Allow-Headers",
|
|
2470
|
-
req.header("access-control-request-headers")
|
|
2471
|
-
);
|
|
2472
|
-
if (req.method === "OPTIONS")
|
|
2473
|
-
return res.send();
|
|
2474
|
-
const u = new URL(req.url.substring(7));
|
|
2475
|
-
const forward = https3.request(
|
|
2476
|
-
u,
|
|
2477
|
-
{
|
|
2478
|
-
headers: {
|
|
2479
|
-
...req.headers,
|
|
2480
|
-
host: u.hostname
|
|
2481
|
-
},
|
|
2482
|
-
method: req.method
|
|
2483
|
-
},
|
|
2484
|
-
(proxied) => {
|
|
2485
|
-
res.status(proxied.statusCode);
|
|
2486
|
-
for (const [key, value] of Object.entries(proxied.headers)) {
|
|
2487
|
-
res.header(key, value);
|
|
2488
|
-
}
|
|
2489
|
-
proxied.pipe(res);
|
|
2490
|
-
}
|
|
2491
|
-
);
|
|
2492
|
-
if (req.method !== "GET" && req.method !== "DELETE" && req.method !== "HEAD" && req.body)
|
|
2493
|
-
forward.write(req.body);
|
|
2494
|
-
forward.end();
|
|
2495
|
-
forward.on("error", (e) => {
|
|
2496
|
-
console.log(e.message);
|
|
2497
|
-
});
|
|
2498
|
-
}
|
|
2499
|
-
);
|
|
2500
|
-
app.post(
|
|
2501
|
-
`/:workerID/${cfg.API_VERSION}/runtime/invocation/:awsRequestId/error`,
|
|
2502
|
-
express2.json({
|
|
2503
|
-
strict: false,
|
|
2504
|
-
type: ["application/json", "application/*+json"],
|
|
2505
|
-
limit: "10mb"
|
|
2506
|
-
}),
|
|
2507
|
-
(req, res) => {
|
|
2508
|
-
const worker = workers.fromID(req.params.workerID);
|
|
2509
|
-
bus.publish("function.error", {
|
|
2510
|
-
workerID: worker.workerID,
|
|
2511
|
-
functionID: worker.functionID,
|
|
2512
|
-
errorType: req.body.errorType,
|
|
2513
|
-
errorMessage: req.body.errorMessage,
|
|
2514
|
-
requestID: req.params.awsRequestId,
|
|
2515
|
-
trace: req.body.trace
|
|
2516
|
-
});
|
|
2517
|
-
res.status(202).send();
|
|
2518
|
-
}
|
|
2519
|
-
);
|
|
2520
|
-
app.listen(cfg.port);
|
|
2521
|
-
});
|
|
2522
|
-
}
|
|
2523
|
-
});
|
|
2524
|
-
|
|
2525
|
-
// src/runtime/workers.ts
|
|
2526
|
-
var workers_exports = {};
|
|
2527
|
-
__export(workers_exports, {
|
|
2528
|
-
useRuntimeWorkers: () => useRuntimeWorkers
|
|
2529
|
-
});
|
|
2530
|
-
import { useFunctions as useFunctions2 } from "../src/constructs/Function.js";
|
|
2531
|
-
var useRuntimeWorkers;
|
|
2532
|
-
var init_workers = __esm({
|
|
2533
|
-
"src/runtime/workers.ts"() {
|
|
2534
|
-
"use strict";
|
|
2535
|
-
init_context();
|
|
2536
|
-
init_bus();
|
|
2537
|
-
init_handlers();
|
|
2538
|
-
init_server2();
|
|
2539
|
-
useRuntimeWorkers = Context.memo(async () => {
|
|
2540
|
-
const workers = /* @__PURE__ */ new Map();
|
|
2541
|
-
const bus = useBus();
|
|
2542
|
-
const handlers = useRuntimeHandlers();
|
|
2543
|
-
const builder = useFunctionBuilder();
|
|
2544
|
-
const server = await useRuntimeServerConfig();
|
|
2545
|
-
handlers.subscribe("function.build.success", async (evt) => {
|
|
2546
|
-
for (const [_, worker] of workers) {
|
|
2547
|
-
if (worker.functionID === evt.properties.functionID) {
|
|
2548
|
-
const props = useFunctions2().fromID(worker.functionID);
|
|
2549
|
-
const handler = handlers.for(props.runtime);
|
|
2550
|
-
await handler?.stopWorker(worker.workerID);
|
|
2551
|
-
bus.publish("worker.stopped", worker);
|
|
2552
|
-
}
|
|
2553
|
-
}
|
|
2554
|
-
});
|
|
2555
|
-
const lastRequestId = /* @__PURE__ */ new Map();
|
|
2556
|
-
bus.subscribe("function.invoked", async (evt) => {
|
|
2557
|
-
bus.publish("function.ack", {
|
|
2558
|
-
functionID: evt.properties.functionID,
|
|
2559
|
-
workerID: evt.properties.workerID
|
|
2560
|
-
});
|
|
2561
|
-
lastRequestId.set(evt.properties.workerID, evt.properties.requestID);
|
|
2562
|
-
let worker = workers.get(evt.properties.workerID);
|
|
2563
|
-
if (worker)
|
|
2564
|
-
return;
|
|
2565
|
-
const props = useFunctions2().fromID(evt.properties.functionID);
|
|
2566
|
-
const handler = handlers.for(props.runtime);
|
|
2567
|
-
if (!handler)
|
|
2568
|
-
return;
|
|
2569
|
-
const build2 = await builder.artifact(evt.properties.functionID);
|
|
2570
|
-
if (!build2)
|
|
2571
|
-
return;
|
|
2572
|
-
await handler.startWorker({
|
|
2573
|
-
...build2,
|
|
2574
|
-
workerID: evt.properties.workerID,
|
|
2575
|
-
environment: evt.properties.env,
|
|
2576
|
-
url: `${server.url}/${evt.properties.workerID}/${server.API_VERSION}`
|
|
2577
|
-
});
|
|
2578
|
-
workers.set(evt.properties.workerID, {
|
|
2579
|
-
workerID: evt.properties.workerID,
|
|
2580
|
-
functionID: evt.properties.functionID
|
|
2581
|
-
});
|
|
2582
|
-
bus.publish("worker.started", {
|
|
2583
|
-
workerID: evt.properties.workerID,
|
|
2584
|
-
functionID: evt.properties.functionID
|
|
2585
|
-
});
|
|
2586
|
-
});
|
|
2587
|
-
return {
|
|
2588
|
-
fromID(workerID) {
|
|
2589
|
-
return workers.get(workerID);
|
|
2590
|
-
},
|
|
2591
|
-
getCurrentRequestID(workerID) {
|
|
2592
|
-
return lastRequestId.get(workerID);
|
|
2593
|
-
},
|
|
2594
|
-
stdout(workerID, message) {
|
|
2595
|
-
const worker = workers.get(workerID);
|
|
2596
|
-
bus.publish("worker.stdout", {
|
|
2597
|
-
...worker,
|
|
2598
|
-
message: message.trim(),
|
|
2599
|
-
requestID: lastRequestId.get(workerID)
|
|
2600
|
-
});
|
|
2601
|
-
},
|
|
2602
|
-
exited(workerID) {
|
|
2603
|
-
const existing = workers.get(workerID);
|
|
2604
|
-
if (!existing)
|
|
2605
|
-
return;
|
|
2606
|
-
workers.delete(workerID);
|
|
2607
|
-
lastRequestId.delete(workerID);
|
|
2608
|
-
bus.publish("worker.exited", existing);
|
|
2609
|
-
},
|
|
2610
|
-
subscribe: bus.forward(
|
|
2611
|
-
"worker.started",
|
|
2612
|
-
"worker.stopped",
|
|
2613
|
-
"worker.exited",
|
|
2614
|
-
"worker.stdout"
|
|
2615
|
-
)
|
|
2616
|
-
};
|
|
2617
|
-
});
|
|
2618
|
-
}
|
|
2619
|
-
});
|
|
2620
|
-
|
|
2621
|
-
// src/stacks/app-metadata.ts
|
|
2622
|
-
import {
|
|
2623
|
-
S3Client,
|
|
2624
|
-
GetObjectCommand,
|
|
2625
|
-
PutObjectCommand,
|
|
2626
|
-
DeleteObjectCommand
|
|
2627
|
-
} from "@aws-sdk/client-s3";
|
|
2628
|
-
async function metadata() {
|
|
2629
|
-
Logger.debug("Fetching app metadata");
|
|
2630
|
-
const [project, credentials, bootstrap] = await Promise.all([
|
|
2631
|
-
useProject(),
|
|
2632
|
-
useAWSCredentials(),
|
|
2633
|
-
useBootstrap()
|
|
2634
|
-
]);
|
|
2635
|
-
const s3 = new S3Client({
|
|
2636
|
-
region: project.config.region,
|
|
2637
|
-
credentials
|
|
2638
|
-
});
|
|
2639
|
-
try {
|
|
2640
|
-
const result = await s3.send(
|
|
2641
|
-
new GetObjectCommand({
|
|
2642
|
-
Key: useS3Key(),
|
|
2643
|
-
Bucket: bootstrap.bucket
|
|
2644
|
-
})
|
|
2645
|
-
);
|
|
2646
|
-
const body = await result.Body.transformToString();
|
|
2647
|
-
return JSON.parse(body);
|
|
2648
|
-
} catch (ex) {
|
|
2649
|
-
Logger.debug("Fetching app metadata: not found");
|
|
2650
|
-
}
|
|
2651
|
-
}
|
|
2652
|
-
async function saveAppMetadata(data2) {
|
|
2653
|
-
Logger.debug("Saving app metadata");
|
|
2654
|
-
const [project, credentials, bootstrap] = await Promise.all([
|
|
2655
|
-
useProject(),
|
|
2656
|
-
useAWSCredentials(),
|
|
2657
|
-
useBootstrap()
|
|
2658
|
-
]);
|
|
2659
|
-
const s3 = new S3Client({
|
|
2660
|
-
region: project.config.region,
|
|
2661
|
-
credentials
|
|
2662
|
-
});
|
|
2663
|
-
try {
|
|
2664
|
-
await s3.send(
|
|
2665
|
-
new PutObjectCommand({
|
|
2666
|
-
Key: useS3Key(),
|
|
2667
|
-
Bucket: bootstrap.bucket,
|
|
2668
|
-
Body: JSON.stringify(data2)
|
|
2669
|
-
})
|
|
2670
|
-
);
|
|
2671
|
-
} catch (ex) {
|
|
2672
|
-
Logger.debug("Saving app metadata: not found");
|
|
2673
|
-
}
|
|
2674
|
-
}
|
|
2675
|
-
async function clearAppMetadata() {
|
|
2676
|
-
Logger.debug("Clearing app metadata");
|
|
2677
|
-
const [project, credentials, bootstrap] = await Promise.all([
|
|
2678
|
-
useProject(),
|
|
2679
|
-
useAWSCredentials(),
|
|
2680
|
-
useBootstrap()
|
|
2681
|
-
]);
|
|
2682
|
-
const s3 = new S3Client({
|
|
2683
|
-
region: project.config.region,
|
|
2684
|
-
credentials
|
|
2685
|
-
});
|
|
2686
|
-
await s3.send(
|
|
2687
|
-
new DeleteObjectCommand({
|
|
2688
|
-
Key: useS3Key(),
|
|
2689
|
-
Bucket: bootstrap.bucket
|
|
2690
|
-
})
|
|
2691
|
-
);
|
|
2692
|
-
}
|
|
2693
|
-
function useS3Key() {
|
|
2694
|
-
const project = useProject();
|
|
2695
|
-
return `appMetadata/app.${project.config.name}/stage.${project.config.stage}.json`;
|
|
2696
|
-
}
|
|
2697
|
-
var MetadataContext, useAppMetadata;
|
|
2698
|
-
var init_app_metadata = __esm({
|
|
2699
|
-
"src/stacks/app-metadata.ts"() {
|
|
2700
|
-
"use strict";
|
|
2701
|
-
init_bootstrap();
|
|
2702
|
-
init_credentials();
|
|
2703
|
-
init_context();
|
|
2704
|
-
init_logger();
|
|
2705
|
-
init_project();
|
|
2706
|
-
MetadataContext = Context.create(async () => {
|
|
2707
|
-
const data2 = await metadata();
|
|
2708
|
-
return data2;
|
|
2709
|
-
});
|
|
2710
|
-
useAppMetadata = MetadataContext.use;
|
|
2711
|
-
}
|
|
2712
|
-
});
|
|
2713
|
-
|
|
2714
|
-
// src/stacks/assembly.ts
|
|
2715
|
-
async function loadAssembly(from) {
|
|
2716
|
-
const { CloudAssembly } = await import("aws-cdk-lib/cx-api");
|
|
2717
|
-
return new CloudAssembly(from);
|
|
2718
|
-
}
|
|
2719
|
-
var init_assembly = __esm({
|
|
2720
|
-
"src/stacks/assembly.ts"() {
|
|
2721
|
-
"use strict";
|
|
2722
|
-
}
|
|
2723
|
-
});
|
|
2724
|
-
|
|
2725
|
-
// src/stacks/monitor.ts
|
|
2726
|
-
import {
|
|
2727
|
-
CloudFormationClient,
|
|
2728
|
-
DescribeStackResourcesCommand,
|
|
2729
|
-
DescribeStacksCommand,
|
|
2730
|
-
DescribeStackEventsCommand
|
|
2731
|
-
} from "@aws-sdk/client-cloudformation";
|
|
2732
|
-
import { map, omitBy, pipe } from "remeda";
|
|
2733
|
-
function isFinal(input) {
|
|
2734
|
-
return STATUSES_SUCCESS.includes(input) || STATUSES_FAILED.includes(input);
|
|
2735
|
-
}
|
|
2736
|
-
function isFailed(input) {
|
|
2737
|
-
return STATUSES_FAILED.includes(input);
|
|
2738
|
-
}
|
|
2739
|
-
function isSuccess(input) {
|
|
2740
|
-
return STATUSES_SUCCESS.includes(input);
|
|
2741
|
-
}
|
|
2742
|
-
function isPending(input) {
|
|
2743
|
-
return STATUSES_PENDING.includes(input);
|
|
2744
|
-
}
|
|
2745
|
-
async function monitor(stack) {
|
|
2746
|
-
const [cfn, bus] = await Promise.all([
|
|
2747
|
-
useAWSClient(CloudFormationClient),
|
|
2748
|
-
useBus()
|
|
2749
|
-
]);
|
|
2750
|
-
let lastStatus;
|
|
2751
|
-
const errors = {};
|
|
2752
|
-
let lastEvent;
|
|
2753
|
-
while (true) {
|
|
2754
|
-
try {
|
|
2755
|
-
const [describe, resources, events] = await Promise.all([
|
|
2756
|
-
cfn.send(
|
|
2757
|
-
new DescribeStacksCommand({
|
|
2758
|
-
StackName: stack
|
|
2759
|
-
})
|
|
2760
|
-
),
|
|
2761
|
-
cfn.send(
|
|
2762
|
-
new DescribeStackResourcesCommand({
|
|
2763
|
-
StackName: stack
|
|
2764
|
-
})
|
|
2765
|
-
),
|
|
2766
|
-
cfn.send(
|
|
2767
|
-
new DescribeStackEventsCommand({
|
|
2768
|
-
StackName: stack
|
|
2769
|
-
})
|
|
2770
|
-
)
|
|
2771
|
-
]);
|
|
2772
|
-
Logger.debug("Stack description", describe);
|
|
2773
|
-
if (lastEvent) {
|
|
2774
|
-
const eventsReversed = [...events.StackEvents ?? []].reverse();
|
|
2775
|
-
for (const event of eventsReversed) {
|
|
2776
|
-
if (!event.Timestamp)
|
|
2777
|
-
continue;
|
|
2778
|
-
if (event.Timestamp.getTime() > lastEvent.getTime()) {
|
|
2779
|
-
bus.publish("stack.event", {
|
|
2780
|
-
event,
|
|
2781
|
-
stackID: stack
|
|
2782
|
-
});
|
|
2783
|
-
if (event.ResourceStatusReason) {
|
|
2784
|
-
if (event.ResourceStatusReason.includes(
|
|
2785
|
-
"Resource creation cancelled"
|
|
2786
|
-
) || event.ResourceStatusReason.includes(
|
|
2787
|
-
"Resource update cancelled"
|
|
2788
|
-
) || event.ResourceStatusReason.includes(
|
|
2789
|
-
"Resource creation Initiated"
|
|
2790
|
-
) || event.ResourceStatusReason.startsWith(
|
|
2791
|
-
"The following resource(s) failed to"
|
|
2792
|
-
))
|
|
2793
|
-
continue;
|
|
2794
|
-
errors[event.LogicalResourceId] = event.ResourceStatusReason;
|
|
2795
|
-
}
|
|
2796
|
-
}
|
|
2797
|
-
}
|
|
2798
|
-
Logger.debug("Last event set to", lastEvent);
|
|
2799
|
-
}
|
|
2800
|
-
lastEvent = events.StackEvents?.at(0)?.Timestamp;
|
|
2801
|
-
bus.publish("stack.resources", {
|
|
2802
|
-
stackID: stack,
|
|
2803
|
-
resources: resources.StackResources
|
|
2804
|
-
});
|
|
2805
|
-
for (const resource of resources.StackResources || []) {
|
|
2806
|
-
if (resource.ResourceStatusReason?.includes(
|
|
2807
|
-
"Resource creation cancelled"
|
|
2808
|
-
) || resource.ResourceStatusReason?.includes(
|
|
2809
|
-
"Resource update cancelled"
|
|
2810
|
-
) || resource.ResourceStatusReason?.includes(
|
|
2811
|
-
"Resource creation Initiated"
|
|
2812
|
-
) || resource.ResourceStatusReason?.startsWith(
|
|
2813
|
-
"The following resource(s) failed to"
|
|
2814
|
-
))
|
|
2815
|
-
continue;
|
|
2816
|
-
if (resource.ResourceStatusReason)
|
|
2817
|
-
errors[resource.LogicalResourceId] = resource.ResourceStatusReason;
|
|
2818
|
-
}
|
|
2819
|
-
const [first] = describe.Stacks || [];
|
|
2820
|
-
if (first) {
|
|
2821
|
-
if (lastStatus !== first.StackStatus && first.StackStatus) {
|
|
2822
|
-
lastStatus = first.StackStatus;
|
|
2823
|
-
bus.publish("stack.status", {
|
|
2824
|
-
stackID: stack,
|
|
2825
|
-
status: first.StackStatus
|
|
2826
|
-
});
|
|
2827
|
-
Logger.debug(first);
|
|
2828
|
-
if (isFinal(first.StackStatus)) {
|
|
2829
|
-
return {
|
|
2830
|
-
status: first.StackStatus,
|
|
2831
|
-
outputs: pipe(
|
|
2832
|
-
first.Outputs || [],
|
|
2833
|
-
map((o) => [o.OutputKey, o.OutputValue]),
|
|
2834
|
-
Object.fromEntries,
|
|
2835
|
-
filterOutputs
|
|
2836
|
-
),
|
|
2837
|
-
errors: isFailed(first.StackStatus) ? errors : {}
|
|
2838
|
-
};
|
|
2839
|
-
}
|
|
2840
|
-
}
|
|
2841
|
-
}
|
|
2842
|
-
} catch (ex) {
|
|
2843
|
-
if (ex.message.includes("does not exist")) {
|
|
2844
|
-
bus.publish("stack.status", {
|
|
2845
|
-
stackID: stack,
|
|
2846
|
-
status: "DELETE_COMPLETE"
|
|
2847
|
-
});
|
|
2848
|
-
return {
|
|
2849
|
-
status: "DELETE_COMPLETE",
|
|
2850
|
-
outputs: {},
|
|
2851
|
-
errors: {}
|
|
2852
|
-
};
|
|
2853
|
-
}
|
|
2854
|
-
}
|
|
2855
|
-
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
2856
|
-
}
|
|
2857
|
-
}
|
|
2858
|
-
function filterOutputs(input) {
|
|
2859
|
-
return pipe(
|
|
2860
|
-
input,
|
|
2861
|
-
omitBy((_, key) => {
|
|
2862
|
-
return key.startsWith("Export") || key === "SSTMetadata";
|
|
2863
|
-
})
|
|
2864
|
-
);
|
|
2865
|
-
}
|
|
2866
|
-
var STATUSES_PENDING, STATUSES_SUCCESS, STATUSES_FAILED, STATUSES;
|
|
2867
|
-
var init_monitor = __esm({
|
|
2868
|
-
"src/stacks/monitor.ts"() {
|
|
2869
|
-
"use strict";
|
|
2870
|
-
init_bus();
|
|
2871
|
-
init_credentials();
|
|
2872
|
-
init_logger();
|
|
2873
|
-
STATUSES_PENDING = [
|
|
2874
|
-
"CREATE_IN_PROGRESS",
|
|
2875
|
-
"DELETE_IN_PROGRESS",
|
|
2876
|
-
"REVIEW_IN_PROGRESS",
|
|
2877
|
-
"ROLLBACK_IN_PROGRESS",
|
|
2878
|
-
"UPDATE_COMPLETE_CLEANUP_IN_PROGRESS",
|
|
2879
|
-
"UPDATE_IN_PROGRESS",
|
|
2880
|
-
"UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS",
|
|
2881
|
-
"UPDATE_ROLLBACK_IN_PROGRESS"
|
|
2882
|
-
];
|
|
2883
|
-
STATUSES_SUCCESS = [
|
|
2884
|
-
"CREATE_COMPLETE",
|
|
2885
|
-
"UPDATE_COMPLETE",
|
|
2886
|
-
"DELETE_COMPLETE",
|
|
2887
|
-
"SKIPPED"
|
|
2888
|
-
];
|
|
2889
|
-
STATUSES_FAILED = [
|
|
2890
|
-
"CREATE_FAILED",
|
|
2891
|
-
"DELETE_FAILED",
|
|
2892
|
-
"ROLLBACK_FAILED",
|
|
2893
|
-
"ROLLBACK_COMPLETE",
|
|
2894
|
-
"UPDATE_FAILED",
|
|
2895
|
-
"UPDATE_ROLLBACK_COMPLETE",
|
|
2896
|
-
"UPDATE_ROLLBACK_FAILED",
|
|
2897
|
-
"DEPENDENCY_FAILED"
|
|
2898
|
-
];
|
|
2899
|
-
STATUSES = [
|
|
2900
|
-
...STATUSES_PENDING,
|
|
2901
|
-
...STATUSES_SUCCESS,
|
|
2902
|
-
...STATUSES_FAILED
|
|
2903
|
-
];
|
|
2904
|
-
}
|
|
2905
|
-
});
|
|
2906
|
-
|
|
2907
|
-
// src/cdk/util.ts
|
|
2908
|
-
async function callWithRetry(cb) {
|
|
2909
|
-
try {
|
|
2910
|
-
return await cb();
|
|
2911
|
-
} catch (e) {
|
|
2912
|
-
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") {
|
|
2913
|
-
return await callWithRetry(cb);
|
|
2914
|
-
}
|
|
2915
|
-
throw e;
|
|
2916
|
-
}
|
|
2917
|
-
}
|
|
2918
|
-
var init_util = __esm({
|
|
2919
|
-
"src/cdk/util.ts"() {
|
|
2920
|
-
"use strict";
|
|
2921
|
-
}
|
|
2922
|
-
});
|
|
2923
|
-
|
|
2924
|
-
// src/cdk/deploy-stack.ts
|
|
2925
|
-
import * as cxapi from "@aws-cdk/cx-api";
|
|
2926
|
-
import fs8 from "fs/promises";
|
|
2927
|
-
import * as uuid from "uuid";
|
|
2928
|
-
import { addMetadataAssetsToManifest } from "sst-aws-cdk/lib/assets.js";
|
|
2929
|
-
import { debug, error, print } from "sst-aws-cdk/lib/logging.js";
|
|
2930
|
-
import { toYAML } from "sst-aws-cdk/lib/serialize.js";
|
|
2931
|
-
import { AssetManifestBuilder } from "sst-aws-cdk/lib/util/asset-manifest-builder.js";
|
|
2932
|
-
import { publishAssets } from "sst-aws-cdk/lib/util/asset-publishing.js";
|
|
2933
|
-
import { contentHash } from "sst-aws-cdk/lib/util/content-hash.js";
|
|
2934
|
-
import { CfnEvaluationException } from "sst-aws-cdk/lib/api/evaluate-cloudformation-template.js";
|
|
2935
|
-
import { tryHotswapDeployment } from "sst-aws-cdk/lib/api/hotswap-deployments.js";
|
|
2936
|
-
import {
|
|
2937
|
-
changeSetHasNoChanges,
|
|
2938
|
-
CloudFormationStack,
|
|
2939
|
-
TemplateParameters,
|
|
2940
|
-
waitForChangeSet,
|
|
2941
|
-
waitForStackDeploy,
|
|
2942
|
-
waitForStackDelete
|
|
2943
|
-
} from "sst-aws-cdk/lib/api/util/cloudformation.js";
|
|
2944
|
-
import { blue as blue2 } from "colorette";
|
|
2945
|
-
async function deployStack(options) {
|
|
2946
|
-
const stackArtifact = options.stack;
|
|
2947
|
-
const stackEnv = options.resolvedEnvironment;
|
|
2948
|
-
options.sdk.appendCustomUserAgent(options.extraUserAgent);
|
|
2949
|
-
const cfn = options.sdk.cloudFormation();
|
|
2950
|
-
const deployName = options.deployName || stackArtifact.stackName;
|
|
2951
|
-
let cloudFormationStack = await callWithRetry(
|
|
2952
|
-
() => CloudFormationStack.lookup(cfn, deployName)
|
|
2953
|
-
);
|
|
2954
|
-
if (cloudFormationStack.stackStatus.isCreationFailure) {
|
|
2955
|
-
debug(
|
|
2956
|
-
`Found existing stack ${deployName} that had previously failed creation. Deleting it before attempting to re-create it.`
|
|
2957
|
-
);
|
|
2958
|
-
await cfn.deleteStack({ StackName: deployName }).promise();
|
|
2959
|
-
const deletedStack = await waitForStackDelete(cfn, deployName);
|
|
2960
|
-
if (deletedStack && deletedStack.stackStatus.name !== "DELETE_COMPLETE") {
|
|
2961
|
-
throw new Error(
|
|
2962
|
-
`Failed deleting stack ${deployName} that had previously failed creation (current state: ${deletedStack.stackStatus})`
|
|
2963
|
-
);
|
|
2964
|
-
}
|
|
2965
|
-
cloudFormationStack = CloudFormationStack.doesNotExist(cfn, deployName);
|
|
2966
|
-
}
|
|
2967
|
-
const legacyAssets = new AssetManifestBuilder();
|
|
2968
|
-
const assetParams = await addMetadataAssetsToManifest(
|
|
2969
|
-
stackArtifact,
|
|
2970
|
-
legacyAssets,
|
|
2971
|
-
options.toolkitInfo,
|
|
2972
|
-
options.reuseAssets
|
|
2973
|
-
);
|
|
2974
|
-
const finalParameterValues = { ...options.parameters, ...assetParams };
|
|
2975
|
-
const templateParams = TemplateParameters.fromTemplate(
|
|
2976
|
-
stackArtifact.template
|
|
2977
|
-
);
|
|
2978
|
-
const stackParams = options.usePreviousParameters ? templateParams.updateExisting(
|
|
2979
|
-
finalParameterValues,
|
|
2980
|
-
cloudFormationStack.parameters
|
|
2981
|
-
) : templateParams.supplyAll(finalParameterValues);
|
|
2982
|
-
if (await canSkipDeploy(
|
|
2983
|
-
options,
|
|
2984
|
-
cloudFormationStack,
|
|
2985
|
-
stackParams.hasChanges(cloudFormationStack.parameters)
|
|
2986
|
-
)) {
|
|
2987
|
-
debug(`${deployName}: skipping deployment (use --force to override)`);
|
|
2988
|
-
if (options.hotswap) {
|
|
2989
|
-
}
|
|
2990
|
-
return {
|
|
2991
|
-
noOp: true,
|
|
2992
|
-
outputs: cloudFormationStack.outputs,
|
|
2993
|
-
stackArn: cloudFormationStack.stackId
|
|
2994
|
-
};
|
|
2995
|
-
} else {
|
|
2996
|
-
debug(`${deployName}: deploying...`);
|
|
2997
|
-
}
|
|
2998
|
-
const bodyParameter = await makeBodyParameter(
|
|
2999
|
-
stackArtifact,
|
|
3000
|
-
options.resolvedEnvironment,
|
|
3001
|
-
legacyAssets,
|
|
3002
|
-
options.toolkitInfo,
|
|
3003
|
-
options.sdk,
|
|
3004
|
-
options.overrideTemplate
|
|
3005
|
-
);
|
|
3006
|
-
await publishAssets(
|
|
3007
|
-
legacyAssets.toManifest(stackArtifact.assembly.directory),
|
|
3008
|
-
options.sdkProvider,
|
|
3009
|
-
stackEnv,
|
|
3010
|
-
{
|
|
3011
|
-
parallel: options.assetParallelism
|
|
3012
|
-
}
|
|
3013
|
-
);
|
|
3014
|
-
if (options.hotswap) {
|
|
3015
|
-
try {
|
|
3016
|
-
const hotswapDeploymentResult = await tryHotswapDeployment(
|
|
3017
|
-
options.sdkProvider,
|
|
3018
|
-
assetParams,
|
|
3019
|
-
cloudFormationStack,
|
|
3020
|
-
stackArtifact
|
|
3021
|
-
);
|
|
3022
|
-
if (hotswapDeploymentResult) {
|
|
3023
|
-
return hotswapDeploymentResult;
|
|
3024
|
-
}
|
|
3025
|
-
print(
|
|
3026
|
-
"Could not perform a hotswap deployment, as the stack %s contains non-Asset changes",
|
|
3027
|
-
stackArtifact.displayName
|
|
3028
|
-
);
|
|
3029
|
-
} catch (e) {
|
|
3030
|
-
if (!(e instanceof CfnEvaluationException)) {
|
|
3031
|
-
throw e;
|
|
3032
|
-
}
|
|
3033
|
-
print(
|
|
3034
|
-
"Could not perform a hotswap deployment, because the CloudFormation template could not be resolved: %s",
|
|
3035
|
-
e.message
|
|
3036
|
-
);
|
|
3037
|
-
}
|
|
3038
|
-
print("Falling back to doing a full deployment");
|
|
3039
|
-
options.sdk.appendCustomUserAgent("cdk-hotswap/fallback");
|
|
3040
|
-
}
|
|
3041
|
-
const fullDeployment = new FullCloudFormationDeployment(
|
|
3042
|
-
options,
|
|
3043
|
-
cloudFormationStack,
|
|
3044
|
-
stackArtifact,
|
|
3045
|
-
stackParams,
|
|
3046
|
-
bodyParameter
|
|
3047
|
-
);
|
|
3048
|
-
return fullDeployment.performDeployment();
|
|
3049
|
-
}
|
|
3050
|
-
async function makeBodyParameter(stack, resolvedEnvironment, assetManifest, toolkitInfo, sdk, overrideTemplate) {
|
|
3051
|
-
if (stack.stackTemplateAssetObjectUrl && !overrideTemplate) {
|
|
3052
|
-
return {
|
|
3053
|
-
TemplateURL: restUrlFromManifest(
|
|
3054
|
-
stack.stackTemplateAssetObjectUrl,
|
|
3055
|
-
resolvedEnvironment,
|
|
3056
|
-
sdk
|
|
3057
|
-
)
|
|
3058
|
-
};
|
|
3059
|
-
}
|
|
3060
|
-
const templateJson = toYAML(overrideTemplate ?? stack.template);
|
|
3061
|
-
if (templateJson.length <= LARGE_TEMPLATE_SIZE_KB * 1024) {
|
|
3062
|
-
return { TemplateBody: templateJson };
|
|
3063
|
-
}
|
|
3064
|
-
if (!toolkitInfo.found) {
|
|
3065
|
-
error(
|
|
3066
|
-
`The template for stack "${stack.displayName}" is ${Math.round(
|
|
3067
|
-
templateJson.length / 1024
|
|
3068
|
-
)}KiB. Templates larger than ${LARGE_TEMPLATE_SIZE_KB}KiB must be uploaded to S3.
|
|
3069
|
-
Run the following command in order to setup an S3 bucket in this environment, and then re-deploy:
|
|
3070
|
-
|
|
3071
|
-
`,
|
|
3072
|
-
blue2(` $ cdk bootstrap ${resolvedEnvironment.name}
|
|
3073
|
-
`)
|
|
3074
|
-
);
|
|
3075
|
-
throw new Error(
|
|
3076
|
-
'Template too large to deploy ("cdk bootstrap" is required)'
|
|
3077
|
-
);
|
|
3078
|
-
}
|
|
3079
|
-
const templateHash = contentHash(templateJson);
|
|
3080
|
-
const key = `cdk/${stack.id}/${templateHash}.yml`;
|
|
3081
|
-
let templateFile = stack.templateFile;
|
|
3082
|
-
if (overrideTemplate) {
|
|
3083
|
-
templateFile = `${stack.templateFile}-${templateHash}.yaml`;
|
|
3084
|
-
await fs8.writeFile(templateFile, templateJson, { encoding: "utf-8" });
|
|
2215
|
+
const templateHash = contentHash(templateJson);
|
|
2216
|
+
const key = `cdk/${stack.id}/${templateHash}.yml`;
|
|
2217
|
+
let templateFile = stack.templateFile;
|
|
2218
|
+
if (overrideTemplate) {
|
|
2219
|
+
templateFile = `${stack.templateFile}-${templateHash}.yaml`;
|
|
2220
|
+
await fs5.writeFile(templateFile, templateJson, { encoding: "utf-8" });
|
|
3085
2221
|
}
|
|
3086
2222
|
assetManifest.addFileAsset(
|
|
3087
2223
|
templateHash,
|
|
@@ -4129,13 +3265,13 @@ async function listImports(exportName) {
|
|
|
4129
3265
|
}
|
|
4130
3266
|
}
|
|
4131
3267
|
async function getLocalTemplate(stack) {
|
|
4132
|
-
const
|
|
4133
|
-
const fileContent = await
|
|
3268
|
+
const fs18 = await import("fs/promises");
|
|
3269
|
+
const fileContent = await fs18.readFile(stack.templateFullPath);
|
|
4134
3270
|
return fileContent.toString();
|
|
4135
3271
|
}
|
|
4136
3272
|
async function saveLocalTemplate(stack, content) {
|
|
4137
|
-
const
|
|
4138
|
-
await
|
|
3273
|
+
const fs18 = await import("fs/promises");
|
|
3274
|
+
await fs18.writeFile(stack.templateFullPath, content);
|
|
4139
3275
|
}
|
|
4140
3276
|
var init_deploy = __esm({
|
|
4141
3277
|
"src/stacks/deploy.ts"() {
|
|
@@ -4194,157 +3330,603 @@ async function buildLogicalToPathMap(stack) {
|
|
|
4194
3330
|
)) {
|
|
4195
3331
|
map3[md.data] = md.path;
|
|
4196
3332
|
}
|
|
4197
|
-
return map3;
|
|
4198
|
-
}
|
|
4199
|
-
var init_diff = __esm({
|
|
4200
|
-
"src/stacks/diff.ts"() {
|
|
3333
|
+
return map3;
|
|
3334
|
+
}
|
|
3335
|
+
var init_diff = __esm({
|
|
3336
|
+
"src/stacks/diff.ts"() {
|
|
3337
|
+
"use strict";
|
|
3338
|
+
}
|
|
3339
|
+
});
|
|
3340
|
+
|
|
3341
|
+
// src/cache.ts
|
|
3342
|
+
import path5 from "path";
|
|
3343
|
+
import fs6 from "fs/promises";
|
|
3344
|
+
var useCache;
|
|
3345
|
+
var init_cache = __esm({
|
|
3346
|
+
"src/cache.ts"() {
|
|
3347
|
+
"use strict";
|
|
3348
|
+
init_project();
|
|
3349
|
+
init_logger();
|
|
3350
|
+
init_context();
|
|
3351
|
+
useCache = Context.memo(async () => {
|
|
3352
|
+
const project = useProject();
|
|
3353
|
+
const cache = path5.join(project.paths.out, "cache");
|
|
3354
|
+
await fs6.mkdir(cache, {
|
|
3355
|
+
recursive: true
|
|
3356
|
+
});
|
|
3357
|
+
async function write(key, data2) {
|
|
3358
|
+
const full = path5.join(cache, key);
|
|
3359
|
+
Logger.debug("Writing cache", full, data2.length, "bytes");
|
|
3360
|
+
await fs6.writeFile(full, data2);
|
|
3361
|
+
}
|
|
3362
|
+
async function read(key) {
|
|
3363
|
+
const full = path5.join(cache, key);
|
|
3364
|
+
try {
|
|
3365
|
+
const data2 = await fs6.readFile(full);
|
|
3366
|
+
return data2.toString();
|
|
3367
|
+
} catch {
|
|
3368
|
+
return null;
|
|
3369
|
+
}
|
|
3370
|
+
}
|
|
3371
|
+
return {
|
|
3372
|
+
write,
|
|
3373
|
+
read
|
|
3374
|
+
};
|
|
3375
|
+
});
|
|
3376
|
+
}
|
|
3377
|
+
});
|
|
3378
|
+
|
|
3379
|
+
// src/stacks/metadata.ts
|
|
3380
|
+
var metadata_exports = {};
|
|
3381
|
+
__export(metadata_exports, {
|
|
3382
|
+
metadata: () => metadata2,
|
|
3383
|
+
useMetadata: () => useMetadata
|
|
3384
|
+
});
|
|
3385
|
+
import {
|
|
3386
|
+
S3Client as S3Client2,
|
|
3387
|
+
GetObjectCommand as GetObjectCommand2,
|
|
3388
|
+
ListObjectsV2Command
|
|
3389
|
+
} from "@aws-sdk/client-s3";
|
|
3390
|
+
async function metadata2() {
|
|
3391
|
+
Logger.debug("Fetching all metadata");
|
|
3392
|
+
const project = useProject();
|
|
3393
|
+
const [credentials, bootstrap2] = await Promise.all([
|
|
3394
|
+
useAWSCredentials(),
|
|
3395
|
+
useBootstrap()
|
|
3396
|
+
]);
|
|
3397
|
+
const s3 = new S3Client2({
|
|
3398
|
+
region: project.config.region,
|
|
3399
|
+
credentials
|
|
3400
|
+
});
|
|
3401
|
+
const key = `stackMetadata/app.${project.config.name}/stage.${project.config.stage}/`;
|
|
3402
|
+
const list2 = await s3.send(
|
|
3403
|
+
new ListObjectsV2Command({
|
|
3404
|
+
Prefix: key,
|
|
3405
|
+
Bucket: bootstrap2.bucket
|
|
3406
|
+
})
|
|
3407
|
+
);
|
|
3408
|
+
const result = Object.fromEntries(
|
|
3409
|
+
await Promise.all(
|
|
3410
|
+
list2.Contents?.map(async (obj) => {
|
|
3411
|
+
const stackID = obj.Key?.split("/").pop();
|
|
3412
|
+
const result2 = await s3.send(
|
|
3413
|
+
new GetObjectCommand2({
|
|
3414
|
+
Key: obj.Key,
|
|
3415
|
+
Bucket: bootstrap2.bucket
|
|
3416
|
+
})
|
|
3417
|
+
);
|
|
3418
|
+
const body = await result2.Body.transformToString();
|
|
3419
|
+
return [stackID, JSON.parse(body)];
|
|
3420
|
+
}) || []
|
|
3421
|
+
)
|
|
3422
|
+
);
|
|
3423
|
+
Logger.debug("Fetched metadata from", list2.KeyCount, "stacks");
|
|
3424
|
+
return result;
|
|
3425
|
+
}
|
|
3426
|
+
var MetadataContext2, useMetadata;
|
|
3427
|
+
var init_metadata = __esm({
|
|
3428
|
+
"src/stacks/metadata.ts"() {
|
|
3429
|
+
"use strict";
|
|
3430
|
+
init_bootstrap();
|
|
3431
|
+
init_credentials();
|
|
3432
|
+
init_cache();
|
|
3433
|
+
init_context();
|
|
3434
|
+
init_bus();
|
|
3435
|
+
init_logger();
|
|
3436
|
+
init_project();
|
|
3437
|
+
MetadataContext2 = Context.create(async () => {
|
|
3438
|
+
const bus = useBus();
|
|
3439
|
+
const cache = await useCache();
|
|
3440
|
+
const data2 = await metadata2();
|
|
3441
|
+
bus.publish("stacks.metadata", data2);
|
|
3442
|
+
bus.subscribe("stacks.metadata.updated", async () => {
|
|
3443
|
+
const data3 = await metadata2();
|
|
3444
|
+
await cache.write(`metadata.json`, JSON.stringify(data3));
|
|
3445
|
+
bus.publish("stacks.metadata", data3);
|
|
3446
|
+
MetadataContext2.provide(Promise.resolve(data3));
|
|
3447
|
+
});
|
|
3448
|
+
bus.subscribe("stacks.metadata.deleted", async () => {
|
|
3449
|
+
const data3 = await metadata2();
|
|
3450
|
+
await cache.write(`metadata.json`, JSON.stringify(data3));
|
|
3451
|
+
bus.publish("stacks.metadata", data3);
|
|
3452
|
+
MetadataContext2.provide(Promise.resolve(data3));
|
|
3453
|
+
});
|
|
3454
|
+
return data2;
|
|
3455
|
+
});
|
|
3456
|
+
useMetadata = MetadataContext2.use;
|
|
3457
|
+
}
|
|
3458
|
+
});
|
|
3459
|
+
|
|
3460
|
+
// src/watcher.ts
|
|
3461
|
+
var watcher_exports = {};
|
|
3462
|
+
__export(watcher_exports, {
|
|
3463
|
+
useWatcher: () => useWatcher
|
|
3464
|
+
});
|
|
3465
|
+
import chokidar from "chokidar";
|
|
3466
|
+
import path6 from "path";
|
|
3467
|
+
var useWatcher;
|
|
3468
|
+
var init_watcher = __esm({
|
|
3469
|
+
"src/watcher.ts"() {
|
|
3470
|
+
"use strict";
|
|
3471
|
+
init_context();
|
|
3472
|
+
init_bus();
|
|
3473
|
+
init_project();
|
|
3474
|
+
useWatcher = Context.memo(() => {
|
|
3475
|
+
const project = useProject();
|
|
3476
|
+
const bus = useBus();
|
|
3477
|
+
const watcher = chokidar.watch([project.paths.root], {
|
|
3478
|
+
persistent: true,
|
|
3479
|
+
ignoreInitial: true,
|
|
3480
|
+
followSymlinks: false,
|
|
3481
|
+
disableGlobbing: false,
|
|
3482
|
+
ignored: [
|
|
3483
|
+
"**/node_modules/**",
|
|
3484
|
+
"**/.build/**",
|
|
3485
|
+
"**/.sst/**",
|
|
3486
|
+
"**/debug.log"
|
|
3487
|
+
],
|
|
3488
|
+
awaitWriteFinish: {
|
|
3489
|
+
pollInterval: 100,
|
|
3490
|
+
stabilityThreshold: 20
|
|
3491
|
+
}
|
|
3492
|
+
});
|
|
3493
|
+
watcher.on("change", (file) => {
|
|
3494
|
+
bus.publish("file.changed", {
|
|
3495
|
+
file,
|
|
3496
|
+
relative: path6.relative(project.paths.root, file)
|
|
3497
|
+
});
|
|
3498
|
+
});
|
|
3499
|
+
return {
|
|
3500
|
+
subscribe: bus.forward("file.changed")
|
|
3501
|
+
};
|
|
3502
|
+
});
|
|
3503
|
+
}
|
|
3504
|
+
});
|
|
3505
|
+
|
|
3506
|
+
// src/runtime/handlers.ts
|
|
3507
|
+
import path7 from "path";
|
|
3508
|
+
import fs7 from "fs/promises";
|
|
3509
|
+
import { useFunctions } from "../src/constructs/Function.js";
|
|
3510
|
+
var useRuntimeHandlers, useFunctionBuilder;
|
|
3511
|
+
var init_handlers = __esm({
|
|
3512
|
+
"src/runtime/handlers.ts"() {
|
|
4201
3513
|
"use strict";
|
|
3514
|
+
init_context();
|
|
3515
|
+
init_logger();
|
|
3516
|
+
init_watcher();
|
|
3517
|
+
init_bus();
|
|
3518
|
+
init_project();
|
|
3519
|
+
useRuntimeHandlers = Context.memo(() => {
|
|
3520
|
+
const handlers = [];
|
|
3521
|
+
const project = useProject();
|
|
3522
|
+
const bus = useBus();
|
|
3523
|
+
const pendingBuilds = /* @__PURE__ */ new Map();
|
|
3524
|
+
const result = {
|
|
3525
|
+
subscribe: bus.forward("function.build.success", "function.build.failed"),
|
|
3526
|
+
register: (handler) => {
|
|
3527
|
+
handlers.push(handler);
|
|
3528
|
+
},
|
|
3529
|
+
for: (runtime) => {
|
|
3530
|
+
const result2 = handlers.find((x) => x.canHandle(runtime));
|
|
3531
|
+
if (!result2)
|
|
3532
|
+
throw new Error(`${runtime} runtime is unsupported`);
|
|
3533
|
+
return result2;
|
|
3534
|
+
},
|
|
3535
|
+
async build(functionID, mode) {
|
|
3536
|
+
async function task() {
|
|
3537
|
+
const func = useFunctions().fromID(functionID);
|
|
3538
|
+
const handler = result.for(func.runtime);
|
|
3539
|
+
const out = path7.join(project.paths.artifacts, functionID);
|
|
3540
|
+
await fs7.rm(out, { recursive: true, force: true });
|
|
3541
|
+
await fs7.mkdir(out, { recursive: true });
|
|
3542
|
+
if (func.hooks?.beforeBuild)
|
|
3543
|
+
await func.hooks.beforeBuild(func, out);
|
|
3544
|
+
const built = await handler.build({
|
|
3545
|
+
functionID,
|
|
3546
|
+
out,
|
|
3547
|
+
mode,
|
|
3548
|
+
props: func
|
|
3549
|
+
});
|
|
3550
|
+
if (built.type === "error") {
|
|
3551
|
+
bus.publish("function.build.failed", {
|
|
3552
|
+
functionID,
|
|
3553
|
+
errors: built.errors
|
|
3554
|
+
});
|
|
3555
|
+
return built;
|
|
3556
|
+
}
|
|
3557
|
+
if (func.copyFiles) {
|
|
3558
|
+
await Promise.all(
|
|
3559
|
+
func.copyFiles.map(async (entry) => {
|
|
3560
|
+
const fromPath = path7.join(project.paths.root, entry.from);
|
|
3561
|
+
const to = entry.to || entry.from;
|
|
3562
|
+
if (path7.isAbsolute(to))
|
|
3563
|
+
throw new Error(
|
|
3564
|
+
`Copy destination path "${to}" must be relative`
|
|
3565
|
+
);
|
|
3566
|
+
const toPath = path7.join(out, to);
|
|
3567
|
+
if (mode === "deploy")
|
|
3568
|
+
await fs7.cp(fromPath, toPath, {
|
|
3569
|
+
recursive: true
|
|
3570
|
+
});
|
|
3571
|
+
if (mode === "start") {
|
|
3572
|
+
const dir = path7.dirname(toPath);
|
|
3573
|
+
await fs7.mkdir(dir, { recursive: true });
|
|
3574
|
+
await fs7.symlink(fromPath, toPath);
|
|
3575
|
+
}
|
|
3576
|
+
})
|
|
3577
|
+
);
|
|
3578
|
+
}
|
|
3579
|
+
if (func.hooks?.afterBuild)
|
|
3580
|
+
await func.hooks.afterBuild(func, out);
|
|
3581
|
+
bus.publish("function.build.success", { functionID });
|
|
3582
|
+
return {
|
|
3583
|
+
...built,
|
|
3584
|
+
out
|
|
3585
|
+
};
|
|
3586
|
+
}
|
|
3587
|
+
if (pendingBuilds.has(functionID)) {
|
|
3588
|
+
Logger.debug("Waiting on pending build", functionID);
|
|
3589
|
+
return pendingBuilds.get(functionID);
|
|
3590
|
+
}
|
|
3591
|
+
const promise = task();
|
|
3592
|
+
pendingBuilds.set(functionID, promise);
|
|
3593
|
+
Logger.debug("Building function", functionID);
|
|
3594
|
+
const r = await promise;
|
|
3595
|
+
pendingBuilds.delete(functionID);
|
|
3596
|
+
return r;
|
|
3597
|
+
}
|
|
3598
|
+
};
|
|
3599
|
+
return result;
|
|
3600
|
+
});
|
|
3601
|
+
useFunctionBuilder = Context.memo(() => {
|
|
3602
|
+
const artifacts = /* @__PURE__ */ new Map();
|
|
3603
|
+
const handlers = useRuntimeHandlers();
|
|
3604
|
+
const result = {
|
|
3605
|
+
artifact: (functionID) => {
|
|
3606
|
+
if (artifacts.has(functionID))
|
|
3607
|
+
return artifacts.get(functionID);
|
|
3608
|
+
return result.build(functionID);
|
|
3609
|
+
},
|
|
3610
|
+
build: async (functionID) => {
|
|
3611
|
+
const result2 = await handlers.build(functionID, "start");
|
|
3612
|
+
if (result2.type === "error")
|
|
3613
|
+
return;
|
|
3614
|
+
artifacts.set(functionID, result2);
|
|
3615
|
+
return artifacts.get(functionID);
|
|
3616
|
+
}
|
|
3617
|
+
};
|
|
3618
|
+
const watcher = useWatcher();
|
|
3619
|
+
watcher.subscribe("file.changed", async (evt) => {
|
|
3620
|
+
try {
|
|
3621
|
+
const functions = useFunctions();
|
|
3622
|
+
for (const [functionID, props] of Object.entries(functions.all)) {
|
|
3623
|
+
const handler = handlers.for(props.runtime);
|
|
3624
|
+
if (!handler?.shouldBuild({
|
|
3625
|
+
functionID,
|
|
3626
|
+
file: evt.properties.file
|
|
3627
|
+
}))
|
|
3628
|
+
continue;
|
|
3629
|
+
await result.build(functionID);
|
|
3630
|
+
Logger.debug("Rebuilt function", functionID);
|
|
3631
|
+
}
|
|
3632
|
+
} catch {
|
|
3633
|
+
}
|
|
3634
|
+
});
|
|
3635
|
+
return result;
|
|
3636
|
+
});
|
|
4202
3637
|
}
|
|
4203
3638
|
});
|
|
4204
3639
|
|
|
4205
|
-
// src/
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
3640
|
+
// src/runtime/server.ts
|
|
3641
|
+
var server_exports = {};
|
|
3642
|
+
__export(server_exports, {
|
|
3643
|
+
useRuntimeServer: () => useRuntimeServer,
|
|
3644
|
+
useRuntimeServerConfig: () => useRuntimeServerConfig
|
|
3645
|
+
});
|
|
3646
|
+
import express from "express";
|
|
3647
|
+
import https2 from "https";
|
|
3648
|
+
import getPort from "get-port";
|
|
3649
|
+
var useRuntimeServerConfig, useRuntimeServer;
|
|
3650
|
+
var init_server = __esm({
|
|
3651
|
+
"src/runtime/server.ts"() {
|
|
4211
3652
|
"use strict";
|
|
4212
|
-
init_project();
|
|
4213
|
-
init_logger();
|
|
4214
3653
|
init_context();
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
3654
|
+
init_bus();
|
|
3655
|
+
init_logger();
|
|
3656
|
+
init_workers();
|
|
3657
|
+
useRuntimeServerConfig = Context.memo(async () => {
|
|
3658
|
+
const port = await getPort({
|
|
3659
|
+
port: 12557
|
|
4220
3660
|
});
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
3661
|
+
return {
|
|
3662
|
+
API_VERSION: "2018-06-01",
|
|
3663
|
+
port,
|
|
3664
|
+
url: `http://localhost:${port}`
|
|
3665
|
+
};
|
|
3666
|
+
});
|
|
3667
|
+
useRuntimeServer = Context.memo(async () => {
|
|
3668
|
+
const bus = useBus();
|
|
3669
|
+
const app = express();
|
|
3670
|
+
const workers = await useRuntimeWorkers();
|
|
3671
|
+
const cfg = await useRuntimeServerConfig();
|
|
3672
|
+
const workersWaiting = /* @__PURE__ */ new Map();
|
|
3673
|
+
const invocationsQueued = /* @__PURE__ */ new Map();
|
|
3674
|
+
function next(workerID) {
|
|
3675
|
+
const queue = invocationsQueued.get(workerID);
|
|
3676
|
+
const value = queue?.shift();
|
|
3677
|
+
if (value)
|
|
3678
|
+
return value;
|
|
3679
|
+
return new Promise((resolve, reject) => {
|
|
3680
|
+
workersWaiting.set(workerID, resolve);
|
|
3681
|
+
});
|
|
4225
3682
|
}
|
|
4226
|
-
async
|
|
4227
|
-
const
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
3683
|
+
workers.subscribe("worker.exited", async (evt) => {
|
|
3684
|
+
const waiting = workersWaiting.get(evt.properties.workerID);
|
|
3685
|
+
if (!waiting)
|
|
3686
|
+
return;
|
|
3687
|
+
workersWaiting.delete(evt.properties.workerID);
|
|
3688
|
+
});
|
|
3689
|
+
bus.subscribe("function.invoked", async (evt) => {
|
|
3690
|
+
const worker = workersWaiting.get(evt.properties.workerID);
|
|
3691
|
+
if (worker) {
|
|
3692
|
+
workersWaiting.delete(evt.properties.workerID);
|
|
3693
|
+
worker(evt.properties);
|
|
3694
|
+
return;
|
|
3695
|
+
}
|
|
3696
|
+
let arr = invocationsQueued.get(evt.properties.workerID);
|
|
3697
|
+
if (!arr) {
|
|
3698
|
+
arr = [];
|
|
3699
|
+
invocationsQueued.set(evt.properties.workerID, arr);
|
|
3700
|
+
}
|
|
3701
|
+
arr.push(evt.properties);
|
|
3702
|
+
});
|
|
3703
|
+
app.post(
|
|
3704
|
+
`/:workerID/${cfg.API_VERSION}/runtime/init/error`,
|
|
3705
|
+
express.json({
|
|
3706
|
+
strict: false,
|
|
3707
|
+
type: ["application/json", "application/*+json"],
|
|
3708
|
+
limit: "10mb"
|
|
3709
|
+
}),
|
|
3710
|
+
async (req, res) => {
|
|
3711
|
+
const worker = workers.fromID(req.params.workerID);
|
|
3712
|
+
bus.publish("function.error", {
|
|
3713
|
+
requestID: workers.getCurrentRequestID(worker.workerID),
|
|
3714
|
+
workerID: worker.workerID,
|
|
3715
|
+
functionID: worker.functionID,
|
|
3716
|
+
...req.body
|
|
3717
|
+
});
|
|
3718
|
+
res.json("ok");
|
|
3719
|
+
}
|
|
3720
|
+
);
|
|
3721
|
+
app.get(
|
|
3722
|
+
`/:workerID/${cfg.API_VERSION}/runtime/invocation/next`,
|
|
3723
|
+
async (req, res) => {
|
|
3724
|
+
Logger.debug(
|
|
3725
|
+
"Worker",
|
|
3726
|
+
req.params.workerID,
|
|
3727
|
+
"is waiting for next invocation"
|
|
3728
|
+
);
|
|
3729
|
+
const payload = await next(req.params.workerID);
|
|
3730
|
+
Logger.debug("Worker", req.params.workerID, "sending next payload");
|
|
3731
|
+
res.set({
|
|
3732
|
+
"Lambda-Runtime-Aws-Request-Id": payload.context.awsRequestId,
|
|
3733
|
+
"Lambda-Runtime-Deadline-Ms": Date.now() + payload.deadline,
|
|
3734
|
+
"Lambda-Runtime-Invoked-Function-Arn": payload.context.invokedFunctionArn,
|
|
3735
|
+
"Lambda-Runtime-Client-Context": JSON.stringify(
|
|
3736
|
+
payload.context.clientContext || null
|
|
3737
|
+
),
|
|
3738
|
+
"Lambda-Runtime-Cognito-Identity": JSON.stringify(
|
|
3739
|
+
payload.context.identity || null
|
|
3740
|
+
),
|
|
3741
|
+
"Lambda-Runtime-Log-Group-Name": payload.context.logGroupName,
|
|
3742
|
+
"Lambda-Runtime-Log-Stream-Name": payload.context.logStreamName
|
|
3743
|
+
});
|
|
3744
|
+
res.json(payload.event);
|
|
3745
|
+
}
|
|
3746
|
+
);
|
|
3747
|
+
app.post(
|
|
3748
|
+
`/:workerID/${cfg.API_VERSION}/runtime/invocation/:awsRequestId/response`,
|
|
3749
|
+
express.json({
|
|
3750
|
+
strict: false,
|
|
3751
|
+
type() {
|
|
3752
|
+
return true;
|
|
3753
|
+
},
|
|
3754
|
+
limit: "10mb"
|
|
3755
|
+
}),
|
|
3756
|
+
(req, res) => {
|
|
3757
|
+
Logger.debug("Worker", req.params.workerID, "got response", req.body);
|
|
3758
|
+
const worker = workers.fromID(req.params.workerID);
|
|
3759
|
+
bus.publish("function.success", {
|
|
3760
|
+
workerID: worker.workerID,
|
|
3761
|
+
functionID: worker.functionID,
|
|
3762
|
+
requestID: req.params.awsRequestId,
|
|
3763
|
+
body: req.body
|
|
3764
|
+
});
|
|
3765
|
+
res.status(202).send();
|
|
4233
3766
|
}
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
3767
|
+
);
|
|
3768
|
+
app.all(
|
|
3769
|
+
`/proxy*`,
|
|
3770
|
+
express.raw({
|
|
3771
|
+
type: "*/*",
|
|
3772
|
+
limit: "1024mb"
|
|
3773
|
+
}),
|
|
3774
|
+
(req, res) => {
|
|
3775
|
+
res.header("Access-Control-Allow-Origin", "*");
|
|
3776
|
+
res.header(
|
|
3777
|
+
"Access-Control-Allow-Methods",
|
|
3778
|
+
"GET, PUT, PATCH, POST, DELETE"
|
|
3779
|
+
);
|
|
3780
|
+
res.header(
|
|
3781
|
+
"Access-Control-Allow-Headers",
|
|
3782
|
+
req.header("access-control-request-headers")
|
|
3783
|
+
);
|
|
3784
|
+
if (req.method === "OPTIONS")
|
|
3785
|
+
return res.send();
|
|
3786
|
+
const u = new URL(req.url.substring(7));
|
|
3787
|
+
const forward = https2.request(
|
|
3788
|
+
u,
|
|
3789
|
+
{
|
|
3790
|
+
headers: {
|
|
3791
|
+
...req.headers,
|
|
3792
|
+
host: u.hostname
|
|
3793
|
+
},
|
|
3794
|
+
method: req.method
|
|
3795
|
+
},
|
|
3796
|
+
(proxied) => {
|
|
3797
|
+
res.status(proxied.statusCode);
|
|
3798
|
+
for (const [key, value] of Object.entries(proxied.headers)) {
|
|
3799
|
+
res.header(key, value);
|
|
3800
|
+
}
|
|
3801
|
+
proxied.pipe(res);
|
|
3802
|
+
}
|
|
3803
|
+
);
|
|
3804
|
+
if (req.method !== "GET" && req.method !== "DELETE" && req.method !== "HEAD" && req.body)
|
|
3805
|
+
forward.write(req.body);
|
|
3806
|
+
forward.end();
|
|
3807
|
+
forward.on("error", (e) => {
|
|
3808
|
+
console.log(e.message);
|
|
3809
|
+
});
|
|
3810
|
+
}
|
|
3811
|
+
);
|
|
3812
|
+
app.post(
|
|
3813
|
+
`/:workerID/${cfg.API_VERSION}/runtime/invocation/:awsRequestId/error`,
|
|
3814
|
+
express.json({
|
|
3815
|
+
strict: false,
|
|
3816
|
+
type: ["application/json", "application/*+json"],
|
|
3817
|
+
limit: "10mb"
|
|
3818
|
+
}),
|
|
3819
|
+
(req, res) => {
|
|
3820
|
+
const worker = workers.fromID(req.params.workerID);
|
|
3821
|
+
bus.publish("function.error", {
|
|
3822
|
+
workerID: worker.workerID,
|
|
3823
|
+
functionID: worker.functionID,
|
|
3824
|
+
errorType: req.body.errorType,
|
|
3825
|
+
errorMessage: req.body.errorMessage,
|
|
3826
|
+
requestID: req.params.awsRequestId,
|
|
3827
|
+
trace: req.body.trace
|
|
3828
|
+
});
|
|
3829
|
+
res.status(202).send();
|
|
3830
|
+
}
|
|
3831
|
+
);
|
|
3832
|
+
app.listen(cfg.port);
|
|
4239
3833
|
});
|
|
4240
3834
|
}
|
|
4241
3835
|
});
|
|
4242
3836
|
|
|
4243
|
-
// src/
|
|
4244
|
-
var
|
|
4245
|
-
__export(
|
|
4246
|
-
|
|
4247
|
-
metadataForStack: () => metadataForStack,
|
|
4248
|
-
useMetadata: () => useMetadata
|
|
3837
|
+
// src/runtime/workers.ts
|
|
3838
|
+
var workers_exports = {};
|
|
3839
|
+
__export(workers_exports, {
|
|
3840
|
+
useRuntimeWorkers: () => useRuntimeWorkers
|
|
4249
3841
|
});
|
|
4250
|
-
import {
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
} from "@aws-sdk/client-s3";
|
|
4255
|
-
async function metadata2() {
|
|
4256
|
-
Logger.debug("Fetching all metadata");
|
|
4257
|
-
const project = useProject();
|
|
4258
|
-
const [credentials, bootstrap] = await Promise.all([
|
|
4259
|
-
useAWSCredentials(),
|
|
4260
|
-
useBootstrap()
|
|
4261
|
-
]);
|
|
4262
|
-
const s3 = new S3Client2({
|
|
4263
|
-
region: project.config.region,
|
|
4264
|
-
credentials
|
|
4265
|
-
});
|
|
4266
|
-
const key = `stackMetadata/app.${project.config.name}/stage.${project.config.stage}/`;
|
|
4267
|
-
const list2 = await s3.send(
|
|
4268
|
-
new ListObjectsV2Command({
|
|
4269
|
-
Prefix: key,
|
|
4270
|
-
Bucket: bootstrap.bucket
|
|
4271
|
-
})
|
|
4272
|
-
);
|
|
4273
|
-
const result = Object.fromEntries(
|
|
4274
|
-
await Promise.all(
|
|
4275
|
-
list2.Contents?.map(async (obj) => {
|
|
4276
|
-
const stackID = obj.Key?.split("/").pop();
|
|
4277
|
-
const result2 = await s3.send(
|
|
4278
|
-
new GetObjectCommand2({
|
|
4279
|
-
Key: obj.Key,
|
|
4280
|
-
Bucket: bootstrap.bucket
|
|
4281
|
-
})
|
|
4282
|
-
);
|
|
4283
|
-
const body = await result2.Body.transformToString();
|
|
4284
|
-
return [stackID, JSON.parse(body)];
|
|
4285
|
-
}) || []
|
|
4286
|
-
)
|
|
4287
|
-
);
|
|
4288
|
-
Logger.debug("Fetched metadata from", list2.KeyCount, "stacks");
|
|
4289
|
-
return result;
|
|
4290
|
-
}
|
|
4291
|
-
async function metadataForStack(stackID) {
|
|
4292
|
-
const [project, credentials, bootstrap] = await Promise.all([
|
|
4293
|
-
useProject(),
|
|
4294
|
-
useAWSCredentialsProvider(),
|
|
4295
|
-
useBootstrap()
|
|
4296
|
-
]);
|
|
4297
|
-
const s3 = new S3Client2({
|
|
4298
|
-
region: project.config.region,
|
|
4299
|
-
credentials
|
|
4300
|
-
});
|
|
4301
|
-
const key = `stackMetadata/app.${project.config.name}/stage.${project.config.stage}/stack.${stackID}.json`;
|
|
4302
|
-
Logger.debug("Getting metadata", key, "from", bootstrap.bucket);
|
|
4303
|
-
try {
|
|
4304
|
-
const result = await s3.send(
|
|
4305
|
-
new GetObjectCommand2({
|
|
4306
|
-
Key: key,
|
|
4307
|
-
Bucket: bootstrap.bucket
|
|
4308
|
-
})
|
|
4309
|
-
);
|
|
4310
|
-
const body = await result.Body.transformToString();
|
|
4311
|
-
return JSON.parse(body);
|
|
4312
|
-
} catch (ex) {
|
|
4313
|
-
console.error(ex);
|
|
4314
|
-
return [];
|
|
4315
|
-
}
|
|
4316
|
-
}
|
|
4317
|
-
var MetadataContext2, useMetadata;
|
|
4318
|
-
var init_metadata = __esm({
|
|
4319
|
-
"src/stacks/metadata.ts"() {
|
|
3842
|
+
import { useFunctions as useFunctions2 } from "../src/constructs/Function.js";
|
|
3843
|
+
var useRuntimeWorkers;
|
|
3844
|
+
var init_workers = __esm({
|
|
3845
|
+
"src/runtime/workers.ts"() {
|
|
4320
3846
|
"use strict";
|
|
4321
|
-
init_bootstrap();
|
|
4322
|
-
init_credentials();
|
|
4323
|
-
init_cache();
|
|
4324
3847
|
init_context();
|
|
4325
3848
|
init_bus();
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
3849
|
+
init_handlers();
|
|
3850
|
+
init_server();
|
|
3851
|
+
useRuntimeWorkers = Context.memo(async () => {
|
|
3852
|
+
const workers = /* @__PURE__ */ new Map();
|
|
4329
3853
|
const bus = useBus();
|
|
4330
|
-
const
|
|
4331
|
-
const
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
const
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
3854
|
+
const handlers = useRuntimeHandlers();
|
|
3855
|
+
const builder = useFunctionBuilder();
|
|
3856
|
+
const server = await useRuntimeServerConfig();
|
|
3857
|
+
handlers.subscribe("function.build.success", async (evt) => {
|
|
3858
|
+
for (const [_, worker] of workers) {
|
|
3859
|
+
if (worker.functionID === evt.properties.functionID) {
|
|
3860
|
+
const props = useFunctions2().fromID(worker.functionID);
|
|
3861
|
+
const handler = handlers.for(props.runtime);
|
|
3862
|
+
await handler?.stopWorker(worker.workerID);
|
|
3863
|
+
bus.publish("worker.stopped", worker);
|
|
3864
|
+
}
|
|
3865
|
+
}
|
|
4338
3866
|
});
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
3867
|
+
const lastRequestId = /* @__PURE__ */ new Map();
|
|
3868
|
+
bus.subscribe("function.invoked", async (evt) => {
|
|
3869
|
+
bus.publish("function.ack", {
|
|
3870
|
+
functionID: evt.properties.functionID,
|
|
3871
|
+
workerID: evt.properties.workerID
|
|
3872
|
+
});
|
|
3873
|
+
lastRequestId.set(evt.properties.workerID, evt.properties.requestID);
|
|
3874
|
+
let worker = workers.get(evt.properties.workerID);
|
|
3875
|
+
if (worker)
|
|
3876
|
+
return;
|
|
3877
|
+
const props = useFunctions2().fromID(evt.properties.functionID);
|
|
3878
|
+
const handler = handlers.for(props.runtime);
|
|
3879
|
+
if (!handler)
|
|
3880
|
+
return;
|
|
3881
|
+
const build2 = await builder.artifact(evt.properties.functionID);
|
|
3882
|
+
if (!build2)
|
|
3883
|
+
return;
|
|
3884
|
+
await handler.startWorker({
|
|
3885
|
+
...build2,
|
|
3886
|
+
workerID: evt.properties.workerID,
|
|
3887
|
+
environment: evt.properties.env,
|
|
3888
|
+
url: `${server.url}/${evt.properties.workerID}/${server.API_VERSION}`
|
|
3889
|
+
});
|
|
3890
|
+
workers.set(evt.properties.workerID, {
|
|
3891
|
+
workerID: evt.properties.workerID,
|
|
3892
|
+
functionID: evt.properties.functionID
|
|
3893
|
+
});
|
|
3894
|
+
bus.publish("worker.started", {
|
|
3895
|
+
workerID: evt.properties.workerID,
|
|
3896
|
+
functionID: evt.properties.functionID
|
|
3897
|
+
});
|
|
4344
3898
|
});
|
|
4345
|
-
return
|
|
3899
|
+
return {
|
|
3900
|
+
fromID(workerID) {
|
|
3901
|
+
return workers.get(workerID);
|
|
3902
|
+
},
|
|
3903
|
+
getCurrentRequestID(workerID) {
|
|
3904
|
+
return lastRequestId.get(workerID);
|
|
3905
|
+
},
|
|
3906
|
+
stdout(workerID, message) {
|
|
3907
|
+
const worker = workers.get(workerID);
|
|
3908
|
+
bus.publish("worker.stdout", {
|
|
3909
|
+
...worker,
|
|
3910
|
+
message: message.trim(),
|
|
3911
|
+
requestID: lastRequestId.get(workerID)
|
|
3912
|
+
});
|
|
3913
|
+
},
|
|
3914
|
+
exited(workerID) {
|
|
3915
|
+
const existing = workers.get(workerID);
|
|
3916
|
+
if (!existing)
|
|
3917
|
+
return;
|
|
3918
|
+
workers.delete(workerID);
|
|
3919
|
+
lastRequestId.delete(workerID);
|
|
3920
|
+
bus.publish("worker.exited", existing);
|
|
3921
|
+
},
|
|
3922
|
+
subscribe: bus.forward(
|
|
3923
|
+
"worker.started",
|
|
3924
|
+
"worker.stopped",
|
|
3925
|
+
"worker.exited",
|
|
3926
|
+
"worker.stdout"
|
|
3927
|
+
)
|
|
3928
|
+
};
|
|
4346
3929
|
});
|
|
4347
|
-
useMetadata = MetadataContext2.use;
|
|
4348
3930
|
}
|
|
4349
3931
|
});
|
|
4350
3932
|
|
|
@@ -4369,7 +3951,7 @@ var init_dotnet = __esm({
|
|
|
4369
3951
|
init_handlers();
|
|
4370
3952
|
init_workers();
|
|
4371
3953
|
init_context();
|
|
4372
|
-
|
|
3954
|
+
init_server();
|
|
4373
3955
|
init_fs();
|
|
4374
3956
|
init_project();
|
|
4375
3957
|
init_process();
|
|
@@ -4493,8 +4075,8 @@ var node_exports = {};
|
|
|
4493
4075
|
__export(node_exports, {
|
|
4494
4076
|
useNodeHandler: () => useNodeHandler
|
|
4495
4077
|
});
|
|
4496
|
-
import
|
|
4497
|
-
import
|
|
4078
|
+
import path8 from "path";
|
|
4079
|
+
import fs8 from "fs/promises";
|
|
4498
4080
|
import { exec as exec2 } from "child_process";
|
|
4499
4081
|
import fsSync2 from "fs";
|
|
4500
4082
|
import esbuild2 from "esbuild";
|
|
@@ -4521,7 +4103,7 @@ var init_node = __esm({
|
|
|
4521
4103
|
const result = cache[input.functionID];
|
|
4522
4104
|
if (!result)
|
|
4523
4105
|
return false;
|
|
4524
|
-
const relative =
|
|
4106
|
+
const relative = path8.relative(project.paths.root, input.file).split(path8.sep).join(path8.posix.sep);
|
|
4525
4107
|
return Boolean(result.metafile?.inputs[relative]);
|
|
4526
4108
|
},
|
|
4527
4109
|
canHandle: (input) => input.startsWith("nodejs"),
|
|
@@ -4559,7 +4141,7 @@ var init_node = __esm({
|
|
|
4559
4141
|
},
|
|
4560
4142
|
build: async (input) => {
|
|
4561
4143
|
const exists = cache[input.functionID];
|
|
4562
|
-
const parsed =
|
|
4144
|
+
const parsed = path8.parse(input.props.handler);
|
|
4563
4145
|
const file = [
|
|
4564
4146
|
".ts",
|
|
4565
4147
|
".tsx",
|
|
@@ -4569,7 +4151,7 @@ var init_node = __esm({
|
|
|
4569
4151
|
".jsx",
|
|
4570
4152
|
".mjs",
|
|
4571
4153
|
".cjs"
|
|
4572
|
-
].map((ext) =>
|
|
4154
|
+
].map((ext) => path8.join(parsed.dir, parsed.name + ext)).find((file2) => {
|
|
4573
4155
|
return fsSync2.existsSync(file2);
|
|
4574
4156
|
});
|
|
4575
4157
|
if (!file)
|
|
@@ -4579,17 +4161,17 @@ var init_node = __esm({
|
|
|
4579
4161
|
};
|
|
4580
4162
|
const nodejs = input.props.nodejs || {};
|
|
4581
4163
|
const isESM = (nodejs.format || "esm") === "esm";
|
|
4582
|
-
const relative =
|
|
4164
|
+
const relative = path8.relative(
|
|
4583
4165
|
project.paths.root,
|
|
4584
|
-
|
|
4166
|
+
path8.resolve(parsed.dir)
|
|
4585
4167
|
);
|
|
4586
4168
|
const extension = isESM ? ".mjs" : ".cjs";
|
|
4587
|
-
const target =
|
|
4169
|
+
const target = path8.join(
|
|
4588
4170
|
input.out,
|
|
4589
|
-
!relative.startsWith("..") && !
|
|
4171
|
+
!relative.startsWith("..") && !path8.isAbsolute(input.props.handler) ? relative : "",
|
|
4590
4172
|
parsed.name + extension
|
|
4591
4173
|
);
|
|
4592
|
-
const handler =
|
|
4174
|
+
const handler = path8.relative(input.out, target.replace(extension, parsed.ext)).split(path8.sep).join(path8.posix.sep);
|
|
4593
4175
|
if (exists?.rebuild) {
|
|
4594
4176
|
const result = await exists.rebuild();
|
|
4595
4177
|
cache[input.functionID] = result;
|
|
@@ -4663,17 +4245,17 @@ var init_node = __esm({
|
|
|
4663
4245
|
async function find2(dir, target2) {
|
|
4664
4246
|
if (dir === "/")
|
|
4665
4247
|
throw new VisibleError("Could not find a package.json file");
|
|
4666
|
-
if (await
|
|
4248
|
+
if (await fs8.access(path8.join(dir, target2)).then(() => true).catch(() => false))
|
|
4667
4249
|
return dir;
|
|
4668
|
-
return find2(
|
|
4250
|
+
return find2(path8.join(dir, ".."), target2);
|
|
4669
4251
|
}
|
|
4670
4252
|
if (input.mode === "deploy" && installPackages) {
|
|
4671
4253
|
const src = await find2(parsed.dir, "package.json");
|
|
4672
4254
|
const json = JSON.parse(
|
|
4673
|
-
await
|
|
4255
|
+
await fs8.readFile(path8.join(src, "package.json")).then((x) => x.toString())
|
|
4674
4256
|
);
|
|
4675
|
-
|
|
4676
|
-
|
|
4257
|
+
fs8.writeFile(
|
|
4258
|
+
path8.join(input.out, "package.json"),
|
|
4677
4259
|
JSON.stringify({
|
|
4678
4260
|
dependencies: Object.fromEntries(
|
|
4679
4261
|
installPackages.map((x) => [x, json.dependencies?.[x] || "*"])
|
|
@@ -4695,14 +4277,14 @@ var init_node = __esm({
|
|
|
4695
4277
|
});
|
|
4696
4278
|
}
|
|
4697
4279
|
if (input.mode === "start") {
|
|
4698
|
-
const dir =
|
|
4280
|
+
const dir = path8.join(
|
|
4699
4281
|
await find2(parsed.dir, "package.json"),
|
|
4700
4282
|
"node_modules"
|
|
4701
4283
|
);
|
|
4702
4284
|
try {
|
|
4703
|
-
await
|
|
4704
|
-
|
|
4705
|
-
|
|
4285
|
+
await fs8.symlink(
|
|
4286
|
+
path8.resolve(dir),
|
|
4287
|
+
path8.resolve(path8.join(input.out, "node_modules")),
|
|
4706
4288
|
"dir"
|
|
4707
4289
|
);
|
|
4708
4290
|
} catch {
|
|
@@ -4741,15 +4323,15 @@ var go_exports = {};
|
|
|
4741
4323
|
__export(go_exports, {
|
|
4742
4324
|
useGoHandler: () => useGoHandler
|
|
4743
4325
|
});
|
|
4744
|
-
import
|
|
4745
|
-
import
|
|
4326
|
+
import path9 from "path";
|
|
4327
|
+
import fs9 from "fs/promises";
|
|
4746
4328
|
import { spawn as spawn2 } from "child_process";
|
|
4747
4329
|
async function find(dir, target) {
|
|
4748
4330
|
if (dir === "/")
|
|
4749
4331
|
throw new VisibleError(`Could not find a ${target} file`);
|
|
4750
|
-
if (await
|
|
4332
|
+
if (await fs9.access(path9.join(dir, target)).then(() => true).catch(() => false))
|
|
4751
4333
|
return dir;
|
|
4752
|
-
return find(
|
|
4334
|
+
return find(path9.join(dir, ".."), target);
|
|
4753
4335
|
}
|
|
4754
4336
|
var useGoHandler;
|
|
4755
4337
|
var init_go = __esm({
|
|
@@ -4759,7 +4341,7 @@ var init_go = __esm({
|
|
|
4759
4341
|
init_workers();
|
|
4760
4342
|
init_context();
|
|
4761
4343
|
init_error();
|
|
4762
|
-
|
|
4344
|
+
init_server();
|
|
4763
4345
|
init_fs();
|
|
4764
4346
|
init_process();
|
|
4765
4347
|
useGoHandler = Context.memo(async () => {
|
|
@@ -4778,7 +4360,7 @@ var init_go = __esm({
|
|
|
4778
4360
|
},
|
|
4779
4361
|
canHandle: (input) => input.startsWith("go"),
|
|
4780
4362
|
startWorker: async (input) => {
|
|
4781
|
-
const proc = spawn2(
|
|
4363
|
+
const proc = spawn2(path9.join(input.out, handlerName), {
|
|
4782
4364
|
env: {
|
|
4783
4365
|
...process.env,
|
|
4784
4366
|
...input.environment,
|
|
@@ -4804,13 +4386,13 @@ var init_go = __esm({
|
|
|
4804
4386
|
}
|
|
4805
4387
|
},
|
|
4806
4388
|
build: async (input) => {
|
|
4807
|
-
const parsed =
|
|
4389
|
+
const parsed = path9.parse(input.props.handler);
|
|
4808
4390
|
const project = await find(parsed.dir, "go.mod");
|
|
4809
4391
|
sources.set(input.functionID, project);
|
|
4810
|
-
const src =
|
|
4392
|
+
const src = path9.relative(project, input.props.handler);
|
|
4811
4393
|
if (input.mode === "start") {
|
|
4812
4394
|
try {
|
|
4813
|
-
const target =
|
|
4395
|
+
const target = path9.join(input.out, handlerName);
|
|
4814
4396
|
const result = await execAsync(
|
|
4815
4397
|
`go build -ldflags '-s -w' -o '${target}' ./${src}`,
|
|
4816
4398
|
{
|
|
@@ -4826,7 +4408,7 @@ var init_go = __esm({
|
|
|
4826
4408
|
}
|
|
4827
4409
|
if (input.mode === "deploy") {
|
|
4828
4410
|
try {
|
|
4829
|
-
const target =
|
|
4411
|
+
const target = path9.join(input.out, "bootstrap");
|
|
4830
4412
|
await execAsync(`go build -ldflags '-s -w' -o '${target}' ./${src}`, {
|
|
4831
4413
|
cwd: project,
|
|
4832
4414
|
env: {
|
|
@@ -4855,8 +4437,8 @@ var rust_exports = {};
|
|
|
4855
4437
|
__export(rust_exports, {
|
|
4856
4438
|
useRustHandler: () => useRustHandler
|
|
4857
4439
|
});
|
|
4858
|
-
import
|
|
4859
|
-
import
|
|
4440
|
+
import path10 from "path";
|
|
4441
|
+
import fs10 from "fs/promises";
|
|
4860
4442
|
import { exec as exec4, spawn as spawn3 } from "child_process";
|
|
4861
4443
|
import { promisify as promisify2 } from "util";
|
|
4862
4444
|
var execAsync2, useRustHandler;
|
|
@@ -4867,7 +4449,7 @@ var init_rust = __esm({
|
|
|
4867
4449
|
init_workers();
|
|
4868
4450
|
init_context();
|
|
4869
4451
|
init_error();
|
|
4870
|
-
|
|
4452
|
+
init_server();
|
|
4871
4453
|
init_fs();
|
|
4872
4454
|
execAsync2 = promisify2(exec4);
|
|
4873
4455
|
useRustHandler = Context.memo(async () => {
|
|
@@ -4889,7 +4471,7 @@ var init_rust = __esm({
|
|
|
4889
4471
|
},
|
|
4890
4472
|
canHandle: (input) => input.startsWith("rust"),
|
|
4891
4473
|
startWorker: async (input) => {
|
|
4892
|
-
const proc = spawn3(
|
|
4474
|
+
const proc = spawn3(path10.join(input.out, handlerName), {
|
|
4893
4475
|
env: {
|
|
4894
4476
|
...process.env,
|
|
4895
4477
|
...input.environment,
|
|
@@ -4917,7 +4499,7 @@ var init_rust = __esm({
|
|
|
4917
4499
|
}
|
|
4918
4500
|
},
|
|
4919
4501
|
build: async (input) => {
|
|
4920
|
-
const parsed =
|
|
4502
|
+
const parsed = path10.parse(input.props.handler);
|
|
4921
4503
|
const project = await findAbove(parsed.dir, "Cargo.toml");
|
|
4922
4504
|
if (!project)
|
|
4923
4505
|
return {
|
|
@@ -4933,9 +4515,9 @@ var init_rust = __esm({
|
|
|
4933
4515
|
...process.env
|
|
4934
4516
|
}
|
|
4935
4517
|
});
|
|
4936
|
-
await
|
|
4937
|
-
|
|
4938
|
-
|
|
4518
|
+
await fs10.cp(
|
|
4519
|
+
path10.join(project, `target/debug`, parsed.name),
|
|
4520
|
+
path10.join(input.out, "handler")
|
|
4939
4521
|
);
|
|
4940
4522
|
} catch (ex) {
|
|
4941
4523
|
throw new VisibleError("Failed to build");
|
|
@@ -4949,9 +4531,9 @@ var init_rust = __esm({
|
|
|
4949
4531
|
...process.env
|
|
4950
4532
|
}
|
|
4951
4533
|
});
|
|
4952
|
-
await
|
|
4953
|
-
|
|
4954
|
-
|
|
4534
|
+
await fs10.cp(
|
|
4535
|
+
path10.join(project, `target/lambda/`, parsed.name, "bootstrap"),
|
|
4536
|
+
path10.join(input.out, "bootstrap")
|
|
4955
4537
|
);
|
|
4956
4538
|
} catch (ex) {
|
|
4957
4539
|
throw new VisibleError("Failed to build");
|
|
@@ -4968,9 +4550,9 @@ var init_rust = __esm({
|
|
|
4968
4550
|
});
|
|
4969
4551
|
|
|
4970
4552
|
// src/runtime/handlers/pythonBundling.ts
|
|
4971
|
-
import
|
|
4553
|
+
import fs11 from "fs";
|
|
4972
4554
|
import url5 from "url";
|
|
4973
|
-
import
|
|
4555
|
+
import path11 from "path";
|
|
4974
4556
|
import {
|
|
4975
4557
|
DockerImage,
|
|
4976
4558
|
FileSystem
|
|
@@ -4984,9 +4566,9 @@ function bundle(options) {
|
|
|
4984
4566
|
stagedir
|
|
4985
4567
|
);
|
|
4986
4568
|
const dockerfile = hasInstallCommands ? "Dockerfile.custom" : hasDeps ? "Dockerfile.dependencies" : "Dockerfile";
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4569
|
+
fs11.copyFileSync(
|
|
4570
|
+
path11.join(__dirname, "../../support/python-runtime", dockerfile),
|
|
4571
|
+
path11.join(stagedir, dockerfile)
|
|
4990
4572
|
);
|
|
4991
4573
|
const image = DockerImage.fromBuild(stagedir, {
|
|
4992
4574
|
buildArgs: {
|
|
@@ -4994,21 +4576,21 @@ function bundle(options) {
|
|
|
4994
4576
|
},
|
|
4995
4577
|
file: dockerfile
|
|
4996
4578
|
});
|
|
4997
|
-
const outputPath =
|
|
4579
|
+
const outputPath = path11.join(options.out, outputPathSuffix);
|
|
4998
4580
|
if (hasDeps || hasInstallCommands) {
|
|
4999
4581
|
image.cp(`${BUNDLER_DEPENDENCIES_CACHE}/.`, outputPath);
|
|
5000
4582
|
}
|
|
5001
|
-
|
|
4583
|
+
fs11.cpSync(entry, outputPath, {
|
|
5002
4584
|
recursive: true
|
|
5003
4585
|
});
|
|
5004
4586
|
}
|
|
5005
4587
|
function stageDependencies(entry, stagedir) {
|
|
5006
4588
|
const prefixes = ["Pipfile", "pyproject", "poetry", "requirements.txt"];
|
|
5007
4589
|
let found = false;
|
|
5008
|
-
for (const file of
|
|
4590
|
+
for (const file of fs11.readdirSync(entry)) {
|
|
5009
4591
|
for (const prefix of prefixes) {
|
|
5010
4592
|
if (file.startsWith(prefix)) {
|
|
5011
|
-
|
|
4593
|
+
fs11.copyFileSync(path11.join(entry, file), path11.join(stagedir, file));
|
|
5012
4594
|
found = true;
|
|
5013
4595
|
}
|
|
5014
4596
|
}
|
|
@@ -5018,9 +4600,9 @@ function stageDependencies(entry, stagedir) {
|
|
|
5018
4600
|
function stageInstallCommands(installCommands, stagedir) {
|
|
5019
4601
|
let found = false;
|
|
5020
4602
|
if (installCommands.length > 0) {
|
|
5021
|
-
const filePath =
|
|
5022
|
-
|
|
5023
|
-
|
|
4603
|
+
const filePath = path11.join(stagedir, "sst-deps-install-command.sh");
|
|
4604
|
+
fs11.writeFileSync(filePath, installCommands.join(" && "));
|
|
4605
|
+
fs11.chmodSync(filePath, "755");
|
|
5024
4606
|
found = true;
|
|
5025
4607
|
}
|
|
5026
4608
|
return found;
|
|
@@ -5029,7 +4611,7 @@ var __dirname, BUNDLER_DEPENDENCIES_CACHE;
|
|
|
5029
4611
|
var init_pythonBundling = __esm({
|
|
5030
4612
|
"src/runtime/handlers/pythonBundling.ts"() {
|
|
5031
4613
|
"use strict";
|
|
5032
|
-
__dirname =
|
|
4614
|
+
__dirname = path11.dirname(url5.fileURLToPath(import.meta.url));
|
|
5033
4615
|
BUNDLER_DEPENDENCIES_CACHE = "/var/dependencies";
|
|
5034
4616
|
}
|
|
5035
4617
|
});
|
|
@@ -5039,7 +4621,7 @@ var python_exports = {};
|
|
|
5039
4621
|
__export(python_exports, {
|
|
5040
4622
|
usePythonHandler: () => usePythonHandler
|
|
5041
4623
|
});
|
|
5042
|
-
import
|
|
4624
|
+
import path12 from "path";
|
|
5043
4625
|
import { exec as exec5, spawn as spawn4 } from "child_process";
|
|
5044
4626
|
import { promisify as promisify3 } from "util";
|
|
5045
4627
|
import { Runtime } from "aws-cdk-lib/aws-lambda";
|
|
@@ -5052,7 +4634,7 @@ var init_python = __esm({
|
|
|
5052
4634
|
init_handlers();
|
|
5053
4635
|
init_workers();
|
|
5054
4636
|
init_context();
|
|
5055
|
-
|
|
4637
|
+
init_server();
|
|
5056
4638
|
init_fs();
|
|
5057
4639
|
init_pythonBundling();
|
|
5058
4640
|
execAsync3 = promisify3(exec5);
|
|
@@ -5089,8 +4671,8 @@ var init_python = __esm({
|
|
|
5089
4671
|
const src = await findSrc(input.handler);
|
|
5090
4672
|
if (!src)
|
|
5091
4673
|
throw new Error(`Could not find src for ${input.handler}`);
|
|
5092
|
-
const parsed =
|
|
5093
|
-
const target = [...parsed.dir.split(
|
|
4674
|
+
const parsed = path12.parse(path12.relative(src, input.handler));
|
|
4675
|
+
const target = [...parsed.dir.split(path12.sep), parsed.name].join(".");
|
|
5094
4676
|
const proc = spawn4(
|
|
5095
4677
|
os3.platform() === "win32" ? "python.exe" : "python3",
|
|
5096
4678
|
[
|
|
@@ -5151,7 +4733,7 @@ var init_python = __esm({
|
|
|
5151
4733
|
});
|
|
5152
4734
|
return {
|
|
5153
4735
|
type: "success",
|
|
5154
|
-
handler:
|
|
4736
|
+
handler: path12.relative(src, path12.resolve(input.props.handler)).split(path12.sep).join(path12.posix.sep)
|
|
5155
4737
|
};
|
|
5156
4738
|
}
|
|
5157
4739
|
});
|
|
@@ -5164,14 +4746,14 @@ var java_exports = {};
|
|
|
5164
4746
|
__export(java_exports, {
|
|
5165
4747
|
useJavaHandler: () => useJavaHandler
|
|
5166
4748
|
});
|
|
5167
|
-
import
|
|
5168
|
-
import
|
|
4749
|
+
import path13 from "path";
|
|
4750
|
+
import fs12 from "fs/promises";
|
|
5169
4751
|
import os4 from "os";
|
|
5170
4752
|
import zipLocal from "zip-local";
|
|
5171
4753
|
import { spawn as spawn5 } from "child_process";
|
|
5172
4754
|
import url7 from "url";
|
|
5173
4755
|
async function getGradleBinary(srcPath) {
|
|
5174
|
-
const gradleWrapperPath =
|
|
4756
|
+
const gradleWrapperPath = path13.resolve(path13.join(srcPath, "gradlew"));
|
|
5175
4757
|
return await existsAsync(gradleWrapperPath) ? gradleWrapperPath : "gradle";
|
|
5176
4758
|
}
|
|
5177
4759
|
var useJavaHandler;
|
|
@@ -5181,7 +4763,7 @@ var init_java = __esm({
|
|
|
5181
4763
|
init_handlers();
|
|
5182
4764
|
init_workers();
|
|
5183
4765
|
init_context();
|
|
5184
|
-
|
|
4766
|
+
init_server();
|
|
5185
4767
|
init_fs();
|
|
5186
4768
|
init_project();
|
|
5187
4769
|
init_process();
|
|
@@ -5255,11 +4837,11 @@ var init_java = __esm({
|
|
|
5255
4837
|
cwd: srcPath
|
|
5256
4838
|
}
|
|
5257
4839
|
);
|
|
5258
|
-
const buildOutput =
|
|
5259
|
-
const zip = (await
|
|
4840
|
+
const buildOutput = path13.join(srcPath, "build", outputDir);
|
|
4841
|
+
const zip = (await fs12.readdir(buildOutput)).find(
|
|
5260
4842
|
(f) => f.endsWith(".zip")
|
|
5261
4843
|
);
|
|
5262
|
-
zipLocal.sync.unzip(
|
|
4844
|
+
zipLocal.sync.unzip(path13.join(buildOutput, zip)).save(input.out);
|
|
5263
4845
|
return {
|
|
5264
4846
|
type: "success",
|
|
5265
4847
|
handler: input.props.handler
|
|
@@ -5278,7 +4860,7 @@ var init_java = __esm({
|
|
|
5278
4860
|
|
|
5279
4861
|
// src/stacks/synth.ts
|
|
5280
4862
|
import * as contextproviders from "sst-aws-cdk/lib/context-providers/index.js";
|
|
5281
|
-
import
|
|
4863
|
+
import path14 from "path";
|
|
5282
4864
|
async function synth(opts) {
|
|
5283
4865
|
Logger.debug("Synthesizing stacks...");
|
|
5284
4866
|
const { App: App2 } = await import("../src/constructs/App.js");
|
|
@@ -5298,7 +4880,7 @@ async function synth(opts) {
|
|
|
5298
4880
|
const identity = await useSTSIdentity();
|
|
5299
4881
|
opts = {
|
|
5300
4882
|
...opts,
|
|
5301
|
-
buildDir: opts.buildDir ||
|
|
4883
|
+
buildDir: opts.buildDir || path14.join(project.paths.out, "dist")
|
|
5302
4884
|
};
|
|
5303
4885
|
const cfg = new Configuration();
|
|
5304
4886
|
await cfg.load();
|
|
@@ -5360,420 +4942,763 @@ function formatCustomDomainError(message) {
|
|
|
5360
4942
|
`Please double check and make sure the zone exists, or pass in a different zone.`
|
|
5361
4943
|
].join(" ");
|
|
5362
4944
|
}
|
|
5363
|
-
var init_synth = __esm({
|
|
5364
|
-
"src/stacks/synth.ts"() {
|
|
5365
|
-
"use strict";
|
|
5366
|
-
init_logger();
|
|
5367
|
-
init_project();
|
|
5368
|
-
init_credentials();
|
|
5369
|
-
init_error();
|
|
5370
|
-
init_dotnet();
|
|
4945
|
+
var init_synth = __esm({
|
|
4946
|
+
"src/stacks/synth.ts"() {
|
|
4947
|
+
"use strict";
|
|
4948
|
+
init_logger();
|
|
4949
|
+
init_project();
|
|
4950
|
+
init_credentials();
|
|
4951
|
+
init_error();
|
|
4952
|
+
init_dotnet();
|
|
4953
|
+
}
|
|
4954
|
+
});
|
|
4955
|
+
|
|
4956
|
+
// src/stacks/remove.ts
|
|
4957
|
+
import {
|
|
4958
|
+
CloudFormationClient as CloudFormationClient2,
|
|
4959
|
+
DeleteStackCommand
|
|
4960
|
+
} from "@aws-sdk/client-cloudformation";
|
|
4961
|
+
async function removeMany(stacks) {
|
|
4962
|
+
await useAWSProvider();
|
|
4963
|
+
const bus = useBus();
|
|
4964
|
+
const complete = /* @__PURE__ */ new Set();
|
|
4965
|
+
const todo = new Set(stacks.map((s) => s.id));
|
|
4966
|
+
const results = {};
|
|
4967
|
+
return new Promise((resolve) => {
|
|
4968
|
+
async function trigger() {
|
|
4969
|
+
for (const stack of stacks) {
|
|
4970
|
+
if (!todo.has(stack.id))
|
|
4971
|
+
continue;
|
|
4972
|
+
Logger.debug("Checking if", stack.id, "can be removed");
|
|
4973
|
+
const waiting = stacks.filter((dependant) => {
|
|
4974
|
+
if (dependant.id === stack.id)
|
|
4975
|
+
return false;
|
|
4976
|
+
if (complete.has(dependant.id))
|
|
4977
|
+
return false;
|
|
4978
|
+
return dependant.dependencies?.some((d) => d.id === stack.id);
|
|
4979
|
+
});
|
|
4980
|
+
if (waiting.length) {
|
|
4981
|
+
Logger.debug(
|
|
4982
|
+
"Waiting on",
|
|
4983
|
+
waiting.map((s) => s.id)
|
|
4984
|
+
);
|
|
4985
|
+
continue;
|
|
4986
|
+
}
|
|
4987
|
+
remove(stack).then((result) => {
|
|
4988
|
+
results[stack.id] = result;
|
|
4989
|
+
complete.add(stack.id);
|
|
4990
|
+
if (isFailed(result.status))
|
|
4991
|
+
stacks.forEach((s) => {
|
|
4992
|
+
if (todo.delete(s.stackName)) {
|
|
4993
|
+
complete.add(s.stackName);
|
|
4994
|
+
results[s.id] = {
|
|
4995
|
+
status: "DEPENDENCY_FAILED",
|
|
4996
|
+
outputs: {},
|
|
4997
|
+
errors: {}
|
|
4998
|
+
};
|
|
4999
|
+
bus.publish("stack.status", {
|
|
5000
|
+
stackID: s.id,
|
|
5001
|
+
status: "DEPENDENCY_FAILED"
|
|
5002
|
+
});
|
|
5003
|
+
}
|
|
5004
|
+
});
|
|
5005
|
+
if (complete.size === stacks.length) {
|
|
5006
|
+
resolve(results);
|
|
5007
|
+
}
|
|
5008
|
+
trigger();
|
|
5009
|
+
});
|
|
5010
|
+
todo.delete(stack.id);
|
|
5011
|
+
}
|
|
5012
|
+
}
|
|
5013
|
+
trigger();
|
|
5014
|
+
});
|
|
5015
|
+
}
|
|
5016
|
+
async function remove(stack) {
|
|
5017
|
+
Logger.debug("Removing stack", stack.id);
|
|
5018
|
+
const cfn = useAWSClient(CloudFormationClient2);
|
|
5019
|
+
try {
|
|
5020
|
+
await cfn.send(
|
|
5021
|
+
new DeleteStackCommand({
|
|
5022
|
+
StackName: stack.stackName
|
|
5023
|
+
})
|
|
5024
|
+
);
|
|
5025
|
+
return monitor(stack.stackName);
|
|
5026
|
+
} catch (ex) {
|
|
5027
|
+
return {
|
|
5028
|
+
errors: {
|
|
5029
|
+
stack: ex.message
|
|
5030
|
+
},
|
|
5031
|
+
outputs: {},
|
|
5032
|
+
status: "UPDATE_FAILED"
|
|
5033
|
+
};
|
|
5034
|
+
}
|
|
5035
|
+
}
|
|
5036
|
+
var init_remove = __esm({
|
|
5037
|
+
"src/stacks/remove.ts"() {
|
|
5038
|
+
"use strict";
|
|
5039
|
+
init_bus();
|
|
5040
|
+
init_credentials();
|
|
5041
|
+
init_logger();
|
|
5042
|
+
init_monitor();
|
|
5043
|
+
}
|
|
5044
|
+
});
|
|
5045
|
+
|
|
5046
|
+
// src/stacks/index.ts
|
|
5047
|
+
var stacks_exports = {};
|
|
5048
|
+
__export(stacks_exports, {
|
|
5049
|
+
STATUSES: () => STATUSES,
|
|
5050
|
+
Stacks: () => stacks_exports,
|
|
5051
|
+
clearAppMetadata: () => clearAppMetadata,
|
|
5052
|
+
deploy: () => deploy,
|
|
5053
|
+
deployMany: () => deployMany,
|
|
5054
|
+
diff: () => diff,
|
|
5055
|
+
filterOutputs: () => filterOutputs,
|
|
5056
|
+
isFailed: () => isFailed,
|
|
5057
|
+
isFinal: () => isFinal,
|
|
5058
|
+
isPending: () => isPending,
|
|
5059
|
+
isSuccess: () => isSuccess,
|
|
5060
|
+
load: () => load,
|
|
5061
|
+
loadAssembly: () => loadAssembly,
|
|
5062
|
+
metadata: () => metadata2,
|
|
5063
|
+
monitor: () => monitor,
|
|
5064
|
+
publishAssets: () => publishAssets4,
|
|
5065
|
+
remove: () => remove,
|
|
5066
|
+
removeMany: () => removeMany,
|
|
5067
|
+
saveAppMetadata: () => saveAppMetadata,
|
|
5068
|
+
synth: () => synth,
|
|
5069
|
+
useAppMetadata: () => useAppMetadata,
|
|
5070
|
+
useMetadata: () => useMetadata
|
|
5071
|
+
});
|
|
5072
|
+
var init_stacks = __esm({
|
|
5073
|
+
"src/stacks/index.ts"() {
|
|
5074
|
+
"use strict";
|
|
5075
|
+
init_app_metadata();
|
|
5076
|
+
init_assembly();
|
|
5077
|
+
init_build();
|
|
5078
|
+
init_deploy();
|
|
5079
|
+
init_diff();
|
|
5080
|
+
init_metadata();
|
|
5081
|
+
init_synth();
|
|
5082
|
+
init_monitor();
|
|
5083
|
+
init_remove();
|
|
5084
|
+
init_stacks();
|
|
5085
|
+
}
|
|
5086
|
+
});
|
|
5087
|
+
|
|
5088
|
+
// src/bootstrap.ts
|
|
5089
|
+
var bootstrap_exports = {};
|
|
5090
|
+
__export(bootstrap_exports, {
|
|
5091
|
+
bootstrapSST: () => bootstrapSST,
|
|
5092
|
+
useBootstrap: () => useBootstrap
|
|
5093
|
+
});
|
|
5094
|
+
import url8 from "url";
|
|
5095
|
+
import path15 from "path";
|
|
5096
|
+
import { bold, dim } from "colorette";
|
|
5097
|
+
import { spawn as spawn6 } from "child_process";
|
|
5098
|
+
import {
|
|
5099
|
+
DescribeStacksCommand as DescribeStacksCommand2,
|
|
5100
|
+
CloudFormationClient as CloudFormationClient3
|
|
5101
|
+
} from "@aws-sdk/client-cloudformation";
|
|
5102
|
+
import {
|
|
5103
|
+
App,
|
|
5104
|
+
DefaultStackSynthesizer,
|
|
5105
|
+
CfnOutput,
|
|
5106
|
+
Duration,
|
|
5107
|
+
Tags,
|
|
5108
|
+
Stack,
|
|
5109
|
+
RemovalPolicy
|
|
5110
|
+
} from "aws-cdk-lib";
|
|
5111
|
+
import { Function, Runtime as Runtime2, Code } from "aws-cdk-lib/aws-lambda";
|
|
5112
|
+
import { SqsEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
|
|
5113
|
+
import { PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
5114
|
+
import { Queue } from "aws-cdk-lib/aws-sqs";
|
|
5115
|
+
import { Rule } from "aws-cdk-lib/aws-events";
|
|
5116
|
+
import { SqsQueue } from "aws-cdk-lib/aws-events-targets";
|
|
5117
|
+
import {
|
|
5118
|
+
BlockPublicAccess,
|
|
5119
|
+
Bucket,
|
|
5120
|
+
BucketEncryption
|
|
5121
|
+
} from "aws-cdk-lib/aws-s3";
|
|
5122
|
+
async function loadCDKStatus() {
|
|
5123
|
+
const { cdk } = useProject().config;
|
|
5124
|
+
const client = useAWSClient(CloudFormationClient3);
|
|
5125
|
+
const stackName = cdk?.toolkitStackName || CDK_STACK_NAME;
|
|
5126
|
+
try {
|
|
5127
|
+
const { Stacks: stacks } = await client.send(
|
|
5128
|
+
new DescribeStacksCommand2({ StackName: stackName })
|
|
5129
|
+
);
|
|
5130
|
+
if (!stacks || stacks.length === 0)
|
|
5131
|
+
return false;
|
|
5132
|
+
if (!["CREATE_COMPLETE", "UPDATE_COMPLETE"].includes(stacks[0].StackStatus)) {
|
|
5133
|
+
return false;
|
|
5134
|
+
}
|
|
5135
|
+
const output = stacks[0].Outputs?.find(
|
|
5136
|
+
(o) => o.OutputKey === "BootstrapVersion"
|
|
5137
|
+
);
|
|
5138
|
+
if (!output || parseInt(output.OutputValue) < 14)
|
|
5139
|
+
return false;
|
|
5140
|
+
return true;
|
|
5141
|
+
} catch (e) {
|
|
5142
|
+
if (e.name === "ValidationError" && e.message === `Stack with id ${stackName} does not exist`) {
|
|
5143
|
+
return false;
|
|
5144
|
+
} else {
|
|
5145
|
+
throw e;
|
|
5146
|
+
}
|
|
5147
|
+
}
|
|
5148
|
+
}
|
|
5149
|
+
async function loadSSTStatus() {
|
|
5150
|
+
const { bootstrap: bootstrap2 } = useProject().config;
|
|
5151
|
+
const cf = useAWSClient(CloudFormationClient3);
|
|
5152
|
+
const stackName = bootstrap2?.stackName || SST_STACK_NAME;
|
|
5153
|
+
let result;
|
|
5154
|
+
try {
|
|
5155
|
+
result = await cf.send(
|
|
5156
|
+
new DescribeStacksCommand2({
|
|
5157
|
+
StackName: stackName
|
|
5158
|
+
})
|
|
5159
|
+
);
|
|
5160
|
+
} catch (e) {
|
|
5161
|
+
if (e.Code === "ValidationError" && e.message === `Stack with id ${stackName} does not exist`) {
|
|
5162
|
+
return null;
|
|
5163
|
+
}
|
|
5164
|
+
throw e;
|
|
5165
|
+
}
|
|
5166
|
+
let version2, bucket;
|
|
5167
|
+
(result.Stacks[0].Outputs || []).forEach((o) => {
|
|
5168
|
+
if (o.OutputKey === OUTPUT_VERSION) {
|
|
5169
|
+
version2 = o.OutputValue;
|
|
5170
|
+
} else if (o.OutputKey === OUTPUT_BUCKET) {
|
|
5171
|
+
bucket = o.OutputValue;
|
|
5172
|
+
}
|
|
5173
|
+
});
|
|
5174
|
+
if (!version2 || !bucket) {
|
|
5175
|
+
return null;
|
|
5176
|
+
}
|
|
5177
|
+
return { version: version2, bucket };
|
|
5178
|
+
}
|
|
5179
|
+
async function bootstrapSST() {
|
|
5180
|
+
const { region, bootstrap: bootstrap2, cdk } = useProject().config;
|
|
5181
|
+
const app = new App();
|
|
5182
|
+
const stackName = bootstrap2?.stackName || SST_STACK_NAME;
|
|
5183
|
+
const stack = new Stack(app, stackName, {
|
|
5184
|
+
env: {
|
|
5185
|
+
region
|
|
5186
|
+
},
|
|
5187
|
+
synthesizer: new DefaultStackSynthesizer({
|
|
5188
|
+
qualifier: cdk?.qualifier,
|
|
5189
|
+
fileAssetsBucketName: cdk?.fileAssetsBucketName
|
|
5190
|
+
})
|
|
5191
|
+
});
|
|
5192
|
+
for (const [key, value] of Object.entries(bootstrap2?.tags || {})) {
|
|
5193
|
+
Tags.of(app).add(key, value);
|
|
5371
5194
|
}
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5195
|
+
const bucket = new Bucket(stack, region, {
|
|
5196
|
+
encryption: BucketEncryption.S3_MANAGED,
|
|
5197
|
+
removalPolicy: RemovalPolicy.DESTROY,
|
|
5198
|
+
autoDeleteObjects: true,
|
|
5199
|
+
blockPublicAccess: cdk?.publicAccessBlockConfiguration !== false ? BlockPublicAccess.BLOCK_ALL : void 0
|
|
5200
|
+
});
|
|
5201
|
+
const fn = new Function(stack, "MetadataHandler", {
|
|
5202
|
+
code: Code.fromAsset(
|
|
5203
|
+
path15.resolve(__dirname2, "support/bootstrap-metadata-function")
|
|
5204
|
+
),
|
|
5205
|
+
handler: "index.handler",
|
|
5206
|
+
runtime: region?.startsWith("us-gov-") || region?.startsWith("cn-") ? Runtime2.NODEJS_16_X : Runtime2.NODEJS_18_X,
|
|
5207
|
+
environment: {
|
|
5208
|
+
BUCKET_NAME: bucket.bucketName
|
|
5209
|
+
},
|
|
5210
|
+
initialPolicy: [
|
|
5211
|
+
new PolicyStatement({
|
|
5212
|
+
actions: ["cloudformation:DescribeStacks"],
|
|
5213
|
+
resources: ["*"]
|
|
5214
|
+
}),
|
|
5215
|
+
new PolicyStatement({
|
|
5216
|
+
actions: ["s3:PutObject", "s3:DeleteObject"],
|
|
5217
|
+
resources: [bucket.bucketArn + "/*"]
|
|
5218
|
+
}),
|
|
5219
|
+
new PolicyStatement({
|
|
5220
|
+
actions: ["iot:Publish"],
|
|
5221
|
+
resources: [
|
|
5222
|
+
`arn:${stack.partition}:iot:${stack.region}:${stack.account}:topic//sst/*`
|
|
5223
|
+
]
|
|
5224
|
+
})
|
|
5225
|
+
]
|
|
5226
|
+
});
|
|
5227
|
+
const queue = new Queue(stack, "MetadataQueue", {
|
|
5228
|
+
visibilityTimeout: Duration.seconds(30),
|
|
5229
|
+
retentionPeriod: Duration.minutes(2)
|
|
5230
|
+
});
|
|
5231
|
+
fn.addEventSource(new SqsEventSource(queue));
|
|
5232
|
+
const rule = new Rule(stack, "MetadataRule", {
|
|
5233
|
+
eventPattern: {
|
|
5234
|
+
source: ["aws.cloudformation"],
|
|
5235
|
+
detailType: ["CloudFormation Stack Status Change"],
|
|
5236
|
+
detail: {
|
|
5237
|
+
"status-details": {
|
|
5238
|
+
status: [
|
|
5239
|
+
"CREATE_COMPLETE",
|
|
5240
|
+
"UPDATE_COMPLETE",
|
|
5241
|
+
"UPDATE_ROLLBACK_COMPLETE",
|
|
5242
|
+
"ROLLBACK_COMPLETE",
|
|
5243
|
+
"DELETE_COMPLETE"
|
|
5244
|
+
]
|
|
5404
5245
|
}
|
|
5405
|
-
remove(stack).then((result) => {
|
|
5406
|
-
results[stack.id] = result;
|
|
5407
|
-
complete.add(stack.id);
|
|
5408
|
-
if (isFailed(result.status))
|
|
5409
|
-
stacks.forEach((s) => {
|
|
5410
|
-
if (todo.delete(s.stackName)) {
|
|
5411
|
-
complete.add(s.stackName);
|
|
5412
|
-
results[s.id] = {
|
|
5413
|
-
status: "DEPENDENCY_FAILED",
|
|
5414
|
-
outputs: {},
|
|
5415
|
-
errors: {}
|
|
5416
|
-
};
|
|
5417
|
-
bus.publish("stack.status", {
|
|
5418
|
-
stackID: s.id,
|
|
5419
|
-
status: "DEPENDENCY_FAILED"
|
|
5420
|
-
});
|
|
5421
|
-
}
|
|
5422
|
-
});
|
|
5423
|
-
if (complete.size === stacks.length) {
|
|
5424
|
-
resolve(results);
|
|
5425
|
-
}
|
|
5426
|
-
trigger();
|
|
5427
|
-
});
|
|
5428
|
-
todo.delete(stack.id);
|
|
5429
5246
|
}
|
|
5430
5247
|
}
|
|
5431
|
-
trigger();
|
|
5432
5248
|
});
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5249
|
+
rule.addTarget(
|
|
5250
|
+
new SqsQueue(queue, {
|
|
5251
|
+
retryAttempts: 10
|
|
5252
|
+
})
|
|
5253
|
+
);
|
|
5254
|
+
new CfnOutput(stack, OUTPUT_VERSION, { value: LATEST_VERSION });
|
|
5255
|
+
new CfnOutput(stack, OUTPUT_BUCKET, { value: bucket.bucketName });
|
|
5256
|
+
const asm = app.synth();
|
|
5257
|
+
const result = await stacks_exports.deploy(asm.stacks[0]);
|
|
5258
|
+
if (stacks_exports.isFailed(result.status)) {
|
|
5259
|
+
throw new VisibleError(
|
|
5260
|
+
`Failed to deploy bootstrap stack:
|
|
5261
|
+
${JSON.stringify(
|
|
5262
|
+
result.errors,
|
|
5263
|
+
null,
|
|
5264
|
+
4
|
|
5265
|
+
)}`
|
|
5442
5266
|
);
|
|
5443
|
-
return monitor(stack.stackName);
|
|
5444
|
-
} catch (ex) {
|
|
5445
|
-
return {
|
|
5446
|
-
errors: {
|
|
5447
|
-
stack: ex.message
|
|
5448
|
-
},
|
|
5449
|
-
outputs: {},
|
|
5450
|
-
status: "UPDATE_FAILED"
|
|
5451
|
-
};
|
|
5452
5267
|
}
|
|
5453
5268
|
}
|
|
5454
|
-
|
|
5455
|
-
|
|
5269
|
+
async function bootstrapCDK() {
|
|
5270
|
+
const identity = await useSTSIdentity();
|
|
5271
|
+
const credentials = await useAWSCredentials();
|
|
5272
|
+
const { region, profile, cdk } = useProject().config;
|
|
5273
|
+
cdk || {};
|
|
5274
|
+
await new Promise((resolve, reject) => {
|
|
5275
|
+
const proc = spawn6(
|
|
5276
|
+
[
|
|
5277
|
+
"npx",
|
|
5278
|
+
"cdk",
|
|
5279
|
+
"bootstrap",
|
|
5280
|
+
`aws://${identity.Account}/${region}`,
|
|
5281
|
+
"--no-version-reporting",
|
|
5282
|
+
...cdk?.publicAccessBlockConfiguration === false ? ["--public-access-block-configuration", "false"] : cdk?.publicAccessBlockConfiguration === true ? ["--public-access-block-configuration", "false"] : [],
|
|
5283
|
+
...cdk?.toolkitStackName ? ["--toolkit-stack-name", cdk.toolkitStackName] : [],
|
|
5284
|
+
...cdk?.qualifier ? ["--qualifier", cdk.qualifier] : [],
|
|
5285
|
+
...cdk?.fileAssetsBucketName ? ["--toolkit-bucket-name", cdk.fileAssetsBucketName] : []
|
|
5286
|
+
].join(" "),
|
|
5287
|
+
{
|
|
5288
|
+
env: {
|
|
5289
|
+
...process.env,
|
|
5290
|
+
AWS_ACCESS_KEY_ID: credentials.accessKeyId,
|
|
5291
|
+
AWS_SECRET_ACCESS_KEY: credentials.secretAccessKey,
|
|
5292
|
+
AWS_SESSION_TOKEN: credentials.sessionToken,
|
|
5293
|
+
AWS_REGION: region,
|
|
5294
|
+
AWS_PROFILE: profile
|
|
5295
|
+
},
|
|
5296
|
+
stdio: "pipe",
|
|
5297
|
+
shell: true
|
|
5298
|
+
}
|
|
5299
|
+
);
|
|
5300
|
+
let stderr = "";
|
|
5301
|
+
proc.stdout.on("data", (data2) => {
|
|
5302
|
+
Logger.debug(data2.toString());
|
|
5303
|
+
});
|
|
5304
|
+
proc.stderr.on("data", (data2) => {
|
|
5305
|
+
Logger.debug(data2.toString());
|
|
5306
|
+
stderr += data2;
|
|
5307
|
+
});
|
|
5308
|
+
proc.on("exit", (code) => {
|
|
5309
|
+
Logger.debug("CDK bootstrap exited with code " + code);
|
|
5310
|
+
if (code === 0) {
|
|
5311
|
+
resolve();
|
|
5312
|
+
} else {
|
|
5313
|
+
console.log(bold(dim(stderr)));
|
|
5314
|
+
reject(new VisibleError(`Failed to bootstrap`));
|
|
5315
|
+
}
|
|
5316
|
+
});
|
|
5317
|
+
});
|
|
5318
|
+
}
|
|
5319
|
+
var CDK_STACK_NAME, SST_STACK_NAME, OUTPUT_VERSION, OUTPUT_BUCKET, LATEST_VERSION, __dirname2, useBootstrap;
|
|
5320
|
+
var init_bootstrap = __esm({
|
|
5321
|
+
"src/bootstrap.ts"() {
|
|
5456
5322
|
"use strict";
|
|
5457
|
-
|
|
5323
|
+
init_project();
|
|
5324
|
+
init_spinner();
|
|
5325
|
+
init_context();
|
|
5458
5326
|
init_credentials();
|
|
5327
|
+
init_error();
|
|
5459
5328
|
init_logger();
|
|
5460
|
-
|
|
5329
|
+
init_stacks();
|
|
5330
|
+
CDK_STACK_NAME = "CDKToolkit";
|
|
5331
|
+
SST_STACK_NAME = "SSTBootstrap";
|
|
5332
|
+
OUTPUT_VERSION = "Version";
|
|
5333
|
+
OUTPUT_BUCKET = "BucketName";
|
|
5334
|
+
LATEST_VERSION = "7";
|
|
5335
|
+
__dirname2 = url8.fileURLToPath(new URL(".", import.meta.url));
|
|
5336
|
+
useBootstrap = Context.memo(async () => {
|
|
5337
|
+
Logger.debug("Initializing bootstrap context");
|
|
5338
|
+
let [cdkStatus, sstStatus] = await Promise.all([
|
|
5339
|
+
loadCDKStatus(),
|
|
5340
|
+
loadSSTStatus()
|
|
5341
|
+
]);
|
|
5342
|
+
Logger.debug("Loaded bootstrap status");
|
|
5343
|
+
const needToBootstrapCDK = !cdkStatus;
|
|
5344
|
+
const needToBootstrapSST = !sstStatus || sstStatus.version !== LATEST_VERSION;
|
|
5345
|
+
if (needToBootstrapCDK || needToBootstrapSST) {
|
|
5346
|
+
const spinner = createSpinner(
|
|
5347
|
+
"Deploying bootstrap stack, this only needs to happen once"
|
|
5348
|
+
).start();
|
|
5349
|
+
if (needToBootstrapCDK) {
|
|
5350
|
+
await bootstrapCDK();
|
|
5351
|
+
}
|
|
5352
|
+
if (needToBootstrapSST) {
|
|
5353
|
+
await bootstrapSST();
|
|
5354
|
+
sstStatus = await loadSSTStatus();
|
|
5355
|
+
if (!sstStatus)
|
|
5356
|
+
throw new VisibleError("Failed to load bootstrap stack status");
|
|
5357
|
+
}
|
|
5358
|
+
spinner.succeed();
|
|
5359
|
+
}
|
|
5360
|
+
Logger.debug("Bootstrap context initialized", sstStatus);
|
|
5361
|
+
return sstStatus;
|
|
5362
|
+
}, "Bootstrap");
|
|
5461
5363
|
}
|
|
5462
5364
|
});
|
|
5463
5365
|
|
|
5464
|
-
// src/
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
clearAppMetadata: () => clearAppMetadata,
|
|
5470
|
-
deploy: () => deploy,
|
|
5471
|
-
deployMany: () => deployMany,
|
|
5472
|
-
diff: () => diff,
|
|
5473
|
-
filterOutputs: () => filterOutputs,
|
|
5474
|
-
isFailed: () => isFailed,
|
|
5475
|
-
isFinal: () => isFinal,
|
|
5476
|
-
isPending: () => isPending,
|
|
5477
|
-
isSuccess: () => isSuccess,
|
|
5478
|
-
load: () => load,
|
|
5479
|
-
loadAssembly: () => loadAssembly,
|
|
5480
|
-
metadata: () => metadata2,
|
|
5481
|
-
metadataForStack: () => metadataForStack,
|
|
5482
|
-
monitor: () => monitor,
|
|
5483
|
-
publishAssets: () => publishAssets4,
|
|
5484
|
-
remove: () => remove,
|
|
5485
|
-
removeMany: () => removeMany,
|
|
5486
|
-
saveAppMetadata: () => saveAppMetadata,
|
|
5487
|
-
synth: () => synth,
|
|
5488
|
-
useAppMetadata: () => useAppMetadata,
|
|
5489
|
-
useMetadata: () => useMetadata
|
|
5490
|
-
});
|
|
5491
|
-
var init_stacks = __esm({
|
|
5492
|
-
"src/stacks/index.ts"() {
|
|
5366
|
+
// src/cli/local/router.ts
|
|
5367
|
+
import * as trpc from "@trpc/server";
|
|
5368
|
+
var router2;
|
|
5369
|
+
var init_router = __esm({
|
|
5370
|
+
"src/cli/local/router.ts"() {
|
|
5493
5371
|
"use strict";
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5372
|
+
init_project();
|
|
5373
|
+
init_bus();
|
|
5374
|
+
init_credentials();
|
|
5375
|
+
router2 = trpc.router().query("getCredentials", {
|
|
5376
|
+
async resolve({ ctx }) {
|
|
5377
|
+
const project = useProject();
|
|
5378
|
+
const credentials = await useAWSCredentials();
|
|
5379
|
+
return {
|
|
5380
|
+
region: project.config.region,
|
|
5381
|
+
credentials: {
|
|
5382
|
+
accessKeyId: credentials.accessKeyId,
|
|
5383
|
+
secretAccessKey: credentials.secretAccessKey,
|
|
5384
|
+
sessionToken: credentials.sessionToken
|
|
5385
|
+
}
|
|
5386
|
+
};
|
|
5387
|
+
}
|
|
5388
|
+
}).query("getState", {
|
|
5389
|
+
async resolve({ ctx }) {
|
|
5390
|
+
return ctx.state;
|
|
5391
|
+
}
|
|
5392
|
+
}).mutation("deploy", {
|
|
5393
|
+
async resolve() {
|
|
5394
|
+
return;
|
|
5395
|
+
}
|
|
5396
|
+
}).subscription("onStateChange", {
|
|
5397
|
+
async resolve({ ctx }) {
|
|
5398
|
+
const bus = useBus();
|
|
5399
|
+
return new trpc.Subscription((emit) => {
|
|
5400
|
+
const sub = bus.subscribe("local.patches", (evt) => {
|
|
5401
|
+
emit.data(evt.properties);
|
|
5402
|
+
});
|
|
5403
|
+
return () => {
|
|
5404
|
+
bus.unsubscribe(sub);
|
|
5405
|
+
};
|
|
5406
|
+
});
|
|
5407
|
+
}
|
|
5408
|
+
});
|
|
5504
5409
|
}
|
|
5505
5410
|
});
|
|
5506
5411
|
|
|
5507
|
-
// src/
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
import {
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
}
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
);
|
|
5544
|
-
if (!stacks || stacks.length === 0)
|
|
5545
|
-
return false;
|
|
5546
|
-
if (!["CREATE_COMPLETE", "UPDATE_COMPLETE"].includes(stacks[0].StackStatus)) {
|
|
5547
|
-
return false;
|
|
5548
|
-
}
|
|
5549
|
-
const output = stacks[0].Outputs?.find(
|
|
5550
|
-
(o) => o.OutputKey === "BootstrapVersion"
|
|
5412
|
+
// src/cli/local/server.ts
|
|
5413
|
+
var server_exports2 = {};
|
|
5414
|
+
__export(server_exports2, {
|
|
5415
|
+
useLocalServer: () => useLocalServer,
|
|
5416
|
+
useLocalServerConfig: () => useLocalServerConfig
|
|
5417
|
+
});
|
|
5418
|
+
import { produceWithPatches, enablePatches } from "immer";
|
|
5419
|
+
import express2 from "express";
|
|
5420
|
+
import fs13 from "fs/promises";
|
|
5421
|
+
import { WebSocketServer } from "ws";
|
|
5422
|
+
import https3 from "https";
|
|
5423
|
+
import http from "http";
|
|
5424
|
+
import { applyWSSHandler } from "@trpc/server/adapters/ws/dist/trpc-server-adapters-ws.cjs.js";
|
|
5425
|
+
import { optimise } from "dendriform-immer-patch-optimiser";
|
|
5426
|
+
import { sync } from "cross-spawn";
|
|
5427
|
+
import getPort2 from "get-port";
|
|
5428
|
+
async function useLocalServer(opts) {
|
|
5429
|
+
const cfg = await useLocalServerConfig();
|
|
5430
|
+
const project = useProject();
|
|
5431
|
+
let state2 = {
|
|
5432
|
+
app: project.config.name,
|
|
5433
|
+
stage: project.config.stage,
|
|
5434
|
+
bootstrap: project.config.bootstrap,
|
|
5435
|
+
live: opts.live,
|
|
5436
|
+
stacks: {
|
|
5437
|
+
status: "idle"
|
|
5438
|
+
},
|
|
5439
|
+
functions: {}
|
|
5440
|
+
};
|
|
5441
|
+
const rest = express2();
|
|
5442
|
+
rest.all(`/ping`, (req, res) => {
|
|
5443
|
+
res.header("Access-Control-Allow-Origin", "*");
|
|
5444
|
+
res.header("Access-Control-Allow-Methods", "GET, PUT, PATCH, POST, DELETE");
|
|
5445
|
+
res.header(
|
|
5446
|
+
"Access-Control-Allow-Headers",
|
|
5447
|
+
req.header("access-control-request-headers")
|
|
5551
5448
|
);
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5449
|
+
res.sendStatus(200);
|
|
5450
|
+
});
|
|
5451
|
+
rest.all(
|
|
5452
|
+
`/proxy*`,
|
|
5453
|
+
express2.raw({
|
|
5454
|
+
type: "*/*",
|
|
5455
|
+
limit: "1024mb"
|
|
5456
|
+
}),
|
|
5457
|
+
(req, res) => {
|
|
5458
|
+
res.header("Access-Control-Allow-Origin", "*");
|
|
5459
|
+
res.header(
|
|
5460
|
+
"Access-Control-Allow-Methods",
|
|
5461
|
+
"GET, PUT, PATCH, POST, DELETE"
|
|
5462
|
+
);
|
|
5463
|
+
res.header(
|
|
5464
|
+
"Access-Control-Allow-Headers",
|
|
5465
|
+
req.header("access-control-request-headers")
|
|
5466
|
+
);
|
|
5467
|
+
if (req.method === "OPTIONS")
|
|
5468
|
+
return res.send();
|
|
5469
|
+
const u = new URL(req.url.substring(7));
|
|
5470
|
+
const forward = https3.request(
|
|
5471
|
+
u,
|
|
5472
|
+
{
|
|
5473
|
+
headers: {
|
|
5474
|
+
...req.headers,
|
|
5475
|
+
host: u.hostname
|
|
5476
|
+
},
|
|
5477
|
+
method: req.method
|
|
5478
|
+
},
|
|
5479
|
+
(proxied) => {
|
|
5480
|
+
res.status(proxied.statusCode);
|
|
5481
|
+
for (const [key, value] of Object.entries(proxied.headers)) {
|
|
5482
|
+
res.header(key, value);
|
|
5483
|
+
}
|
|
5484
|
+
proxied.pipe(res);
|
|
5485
|
+
}
|
|
5486
|
+
);
|
|
5487
|
+
if (req.method !== "GET" && req.method !== "DELETE" && req.method !== "HEAD" && req.body)
|
|
5488
|
+
forward.write(req.body);
|
|
5489
|
+
forward.end();
|
|
5490
|
+
forward.on("error", (e) => {
|
|
5491
|
+
console.log(e.message);
|
|
5492
|
+
});
|
|
5560
5493
|
}
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5494
|
+
);
|
|
5495
|
+
const server = await (async () => {
|
|
5496
|
+
const result2 = sync("mkcert", ["--help"]);
|
|
5497
|
+
const KEY_PATH = ".sst/localhost-key.pem";
|
|
5498
|
+
const CERT_PATH = ".sst/localhost.pem";
|
|
5499
|
+
if (result2.status === 0) {
|
|
5500
|
+
try {
|
|
5501
|
+
await Promise.all([fs13.access(KEY_PATH), fs13.access(CERT_PATH)]);
|
|
5502
|
+
} catch (e) {
|
|
5503
|
+
sync("mkcert", ["localhost"], {
|
|
5504
|
+
cwd: ".sst"
|
|
5505
|
+
});
|
|
5506
|
+
}
|
|
5507
|
+
const [key, cert] = await Promise.all([
|
|
5508
|
+
fs13.readFile(KEY_PATH),
|
|
5509
|
+
fs13.readFile(CERT_PATH)
|
|
5510
|
+
]);
|
|
5511
|
+
return https3.createServer(
|
|
5512
|
+
{
|
|
5513
|
+
key,
|
|
5514
|
+
cert
|
|
5515
|
+
},
|
|
5516
|
+
rest
|
|
5517
|
+
);
|
|
5577
5518
|
}
|
|
5578
|
-
|
|
5579
|
-
}
|
|
5580
|
-
|
|
5581
|
-
(
|
|
5582
|
-
if (
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5519
|
+
return http.createServer({}, rest);
|
|
5520
|
+
})();
|
|
5521
|
+
const wss = new WebSocketServer({ server });
|
|
5522
|
+
wss.on("connection", (socket, req) => {
|
|
5523
|
+
if (req.headers.origin?.endsWith("localhost:3000"))
|
|
5524
|
+
return;
|
|
5525
|
+
if (req.headers.origin?.endsWith("localhost:3001"))
|
|
5526
|
+
return;
|
|
5527
|
+
if (req.headers.origin?.endsWith("console.serverless-stack.com"))
|
|
5528
|
+
return;
|
|
5529
|
+
if (req.headers.origin?.endsWith("console.sst.dev"))
|
|
5530
|
+
return;
|
|
5531
|
+
if (req.headers.origin?.endsWith("--sst-console.netlify.app"))
|
|
5532
|
+
return;
|
|
5533
|
+
console.log("Rejecting unauthorized connection from " + req.headers.origin);
|
|
5534
|
+
socket.terminate();
|
|
5535
|
+
});
|
|
5536
|
+
server.listen(cfg.port);
|
|
5537
|
+
const handler = applyWSSHandler({
|
|
5538
|
+
wss,
|
|
5539
|
+
router: router2,
|
|
5540
|
+
createContext() {
|
|
5541
|
+
return {
|
|
5542
|
+
state: state2
|
|
5543
|
+
};
|
|
5586
5544
|
}
|
|
5587
5545
|
});
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
return { version: version2, bucket };
|
|
5592
|
-
}
|
|
5593
|
-
async function bootstrapSST() {
|
|
5594
|
-
const { region, bootstrap, cdk } = useProject().config;
|
|
5595
|
-
const app = new App();
|
|
5596
|
-
const stackName = bootstrap?.stackName || SST_STACK_NAME;
|
|
5597
|
-
const stack = new Stack(app, stackName, {
|
|
5598
|
-
env: {
|
|
5599
|
-
region
|
|
5600
|
-
},
|
|
5601
|
-
synthesizer: new DefaultStackSynthesizer({
|
|
5602
|
-
qualifier: cdk?.qualifier,
|
|
5603
|
-
fileAssetsBucketName: cdk?.fileAssetsBucketName
|
|
5604
|
-
})
|
|
5546
|
+
process.on("SIGTERM", () => {
|
|
5547
|
+
handler.broadcastReconnectNotification();
|
|
5548
|
+
wss.close();
|
|
5605
5549
|
});
|
|
5606
|
-
|
|
5607
|
-
|
|
5550
|
+
const bus = useBus();
|
|
5551
|
+
const pending = [];
|
|
5552
|
+
function updateState(cb) {
|
|
5553
|
+
const [next, patches] = produceWithPatches(state2, cb);
|
|
5554
|
+
if (!patches.length)
|
|
5555
|
+
return;
|
|
5556
|
+
const scheduled = pending.length;
|
|
5557
|
+
pending.push(...optimise(state2, patches));
|
|
5558
|
+
if (!scheduled)
|
|
5559
|
+
setTimeout(() => {
|
|
5560
|
+
bus.publish("local.patches", pending);
|
|
5561
|
+
pending.splice(0, pending.length);
|
|
5562
|
+
}, 0);
|
|
5563
|
+
state2 = next;
|
|
5608
5564
|
}
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5565
|
+
function updateFunction(id, cb) {
|
|
5566
|
+
return updateState((draft) => {
|
|
5567
|
+
let func = draft.functions[id];
|
|
5568
|
+
if (!func) {
|
|
5569
|
+
func = {
|
|
5570
|
+
warm: true,
|
|
5571
|
+
state: "idle",
|
|
5572
|
+
issues: {},
|
|
5573
|
+
invocations: []
|
|
5574
|
+
};
|
|
5575
|
+
draft.functions[id] = func;
|
|
5576
|
+
}
|
|
5577
|
+
cb(func);
|
|
5578
|
+
});
|
|
5579
|
+
}
|
|
5580
|
+
bus.subscribe("function.invoked", (evt) => {
|
|
5581
|
+
updateFunction(evt.properties.functionID, (draft) => {
|
|
5582
|
+
if (draft.invocations.length >= 25)
|
|
5583
|
+
draft.invocations.pop();
|
|
5584
|
+
draft.invocations.unshift({
|
|
5585
|
+
id: evt.properties.context.awsRequestId,
|
|
5586
|
+
request: evt.properties.event,
|
|
5587
|
+
times: {
|
|
5588
|
+
start: Date.now()
|
|
5589
|
+
},
|
|
5590
|
+
logs: []
|
|
5591
|
+
});
|
|
5592
|
+
});
|
|
5614
5593
|
});
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
resources: ["*"]
|
|
5628
|
-
}),
|
|
5629
|
-
new PolicyStatement({
|
|
5630
|
-
actions: ["s3:PutObject", "s3:DeleteObject"],
|
|
5631
|
-
resources: [bucket.bucketArn + "/*"]
|
|
5632
|
-
}),
|
|
5633
|
-
new PolicyStatement({
|
|
5634
|
-
actions: ["iot:Publish"],
|
|
5635
|
-
resources: [
|
|
5636
|
-
`arn:${stack.partition}:iot:${stack.region}:${stack.account}:topic//sst/*`
|
|
5637
|
-
]
|
|
5638
|
-
})
|
|
5639
|
-
]
|
|
5594
|
+
bus.subscribe("worker.stdout", (evt) => {
|
|
5595
|
+
updateFunction(evt.properties.functionID, (draft) => {
|
|
5596
|
+
const entry = draft.invocations.find(
|
|
5597
|
+
(i) => i.id === evt.properties.requestID
|
|
5598
|
+
);
|
|
5599
|
+
if (!entry)
|
|
5600
|
+
return;
|
|
5601
|
+
entry.logs.push({
|
|
5602
|
+
timestamp: Date.now(),
|
|
5603
|
+
message: evt.properties.message
|
|
5604
|
+
});
|
|
5605
|
+
});
|
|
5640
5606
|
});
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5607
|
+
bus.subscribe("function.success", (evt) => {
|
|
5608
|
+
updateFunction(evt.properties.functionID, (draft) => {
|
|
5609
|
+
const invocation = draft.invocations.find(
|
|
5610
|
+
(x) => x.id === evt.properties.requestID
|
|
5611
|
+
);
|
|
5612
|
+
if (!invocation)
|
|
5613
|
+
return;
|
|
5614
|
+
invocation.response = {
|
|
5615
|
+
type: "success",
|
|
5616
|
+
data: evt.properties.body
|
|
5617
|
+
};
|
|
5618
|
+
invocation.times.end = Date.now();
|
|
5619
|
+
});
|
|
5644
5620
|
});
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
"DELETE_COMPLETE"
|
|
5658
|
-
]
|
|
5621
|
+
bus.subscribe("function.error", (evt) => {
|
|
5622
|
+
updateFunction(evt.properties.functionID, (draft) => {
|
|
5623
|
+
const invocation = draft.invocations.find(
|
|
5624
|
+
(x) => x.id === evt.properties.requestID
|
|
5625
|
+
);
|
|
5626
|
+
if (!invocation)
|
|
5627
|
+
return;
|
|
5628
|
+
invocation.response = {
|
|
5629
|
+
type: "failure",
|
|
5630
|
+
error: {
|
|
5631
|
+
errorMessage: evt.properties.errorMessage,
|
|
5632
|
+
stackTrace: evt.properties.trace || []
|
|
5659
5633
|
}
|
|
5660
|
-
}
|
|
5661
|
-
|
|
5634
|
+
};
|
|
5635
|
+
invocation.times.end = Date.now();
|
|
5636
|
+
});
|
|
5662
5637
|
});
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
new CfnOutput(stack, OUTPUT_VERSION, { value: LATEST_VERSION });
|
|
5669
|
-
new CfnOutput(stack, OUTPUT_BUCKET, { value: bucket.bucketName });
|
|
5670
|
-
const asm = app.synth();
|
|
5671
|
-
const result = await stacks_exports.deploy(asm.stacks[0]);
|
|
5672
|
-
if (stacks_exports.isFailed(result.status)) {
|
|
5673
|
-
throw new VisibleError(
|
|
5674
|
-
`Failed to deploy bootstrap stack:
|
|
5675
|
-
${JSON.stringify(
|
|
5676
|
-
result.errors,
|
|
5677
|
-
null,
|
|
5678
|
-
4
|
|
5679
|
-
)}`
|
|
5680
|
-
);
|
|
5681
|
-
}
|
|
5638
|
+
const result = {
|
|
5639
|
+
updateState,
|
|
5640
|
+
updateFunction
|
|
5641
|
+
};
|
|
5642
|
+
return result;
|
|
5682
5643
|
}
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
{
|
|
5702
|
-
env: {
|
|
5703
|
-
...process.env,
|
|
5704
|
-
AWS_ACCESS_KEY_ID: credentials.accessKeyId,
|
|
5705
|
-
AWS_SECRET_ACCESS_KEY: credentials.secretAccessKey,
|
|
5706
|
-
AWS_SESSION_TOKEN: credentials.sessionToken,
|
|
5707
|
-
AWS_REGION: region,
|
|
5708
|
-
AWS_PROFILE: profile
|
|
5709
|
-
},
|
|
5710
|
-
stdio: "pipe",
|
|
5711
|
-
shell: true
|
|
5712
|
-
}
|
|
5713
|
-
);
|
|
5714
|
-
let stderr = "";
|
|
5715
|
-
proc.stdout.on("data", (data2) => {
|
|
5716
|
-
Logger.debug(data2.toString());
|
|
5717
|
-
});
|
|
5718
|
-
proc.stderr.on("data", (data2) => {
|
|
5719
|
-
Logger.debug(data2.toString());
|
|
5720
|
-
stderr += data2;
|
|
5721
|
-
});
|
|
5722
|
-
proc.on("exit", (code) => {
|
|
5723
|
-
Logger.debug("CDK bootstrap exited with code " + code);
|
|
5724
|
-
if (code === 0) {
|
|
5725
|
-
resolve();
|
|
5726
|
-
} else {
|
|
5727
|
-
console.log(bold(dim(stderr)));
|
|
5728
|
-
reject(new VisibleError(`Failed to bootstrap`));
|
|
5729
|
-
}
|
|
5644
|
+
var useLocalServerConfig;
|
|
5645
|
+
var init_server2 = __esm({
|
|
5646
|
+
"src/cli/local/server.ts"() {
|
|
5647
|
+
"use strict";
|
|
5648
|
+
init_router();
|
|
5649
|
+
init_project();
|
|
5650
|
+
init_bus();
|
|
5651
|
+
init_context();
|
|
5652
|
+
enablePatches();
|
|
5653
|
+
useLocalServerConfig = Context.memo(async () => {
|
|
5654
|
+
const project = useProject();
|
|
5655
|
+
const port = await getPort2({
|
|
5656
|
+
port: 13557
|
|
5657
|
+
});
|
|
5658
|
+
return {
|
|
5659
|
+
port,
|
|
5660
|
+
url: `https://console.sst.dev/${project.config.name}/${project.config.stage}${port !== 13557 ? `?_port=${port}` : ""}`
|
|
5661
|
+
};
|
|
5730
5662
|
});
|
|
5731
|
-
}
|
|
5663
|
+
}
|
|
5664
|
+
});
|
|
5665
|
+
|
|
5666
|
+
// src/cli/ui/header.ts
|
|
5667
|
+
var header_exports = {};
|
|
5668
|
+
__export(header_exports, {
|
|
5669
|
+
printConsole: () => printConsole,
|
|
5670
|
+
printHeader: () => printHeader
|
|
5671
|
+
});
|
|
5672
|
+
async function printHeader(input) {
|
|
5673
|
+
const project = useProject();
|
|
5674
|
+
Colors.line(
|
|
5675
|
+
`${Colors.primary.bold(`SST v${project.version}`)} ${input.hint ? Colors.dim(`ready!`) : ""}`
|
|
5676
|
+
);
|
|
5677
|
+
Colors.gap();
|
|
5678
|
+
Colors.line(
|
|
5679
|
+
`${Colors.primary(`\u279C`)} ${Colors.bold("App:")} ${project.config.name}`
|
|
5680
|
+
);
|
|
5681
|
+
Colors.line(
|
|
5682
|
+
`${Colors.primary(` `)} ${Colors.bold("Stage:")} ${project.config.stage}`
|
|
5683
|
+
);
|
|
5684
|
+
if (input.console) {
|
|
5685
|
+
const local = await useLocalServerConfig();
|
|
5686
|
+
Colors.line(
|
|
5687
|
+
`${Colors.primary(` `)} ${Colors.bold("Console:")} ${Colors.link(
|
|
5688
|
+
local.url
|
|
5689
|
+
)}`
|
|
5690
|
+
);
|
|
5691
|
+
}
|
|
5692
|
+
Colors.gap();
|
|
5732
5693
|
}
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5694
|
+
function printConsole() {
|
|
5695
|
+
}
|
|
5696
|
+
var init_header = __esm({
|
|
5697
|
+
"src/cli/ui/header.ts"() {
|
|
5736
5698
|
"use strict";
|
|
5737
5699
|
init_project();
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
init_credentials();
|
|
5741
|
-
init_error();
|
|
5742
|
-
init_logger();
|
|
5743
|
-
init_stacks();
|
|
5744
|
-
CDK_STACK_NAME = "CDKToolkit";
|
|
5745
|
-
SST_STACK_NAME = "SSTBootstrap";
|
|
5746
|
-
OUTPUT_VERSION = "Version";
|
|
5747
|
-
OUTPUT_BUCKET = "BucketName";
|
|
5748
|
-
LATEST_VERSION = "7";
|
|
5749
|
-
__dirname2 = url8.fileURLToPath(new URL(".", import.meta.url));
|
|
5750
|
-
useBootstrap = Context.memo(async () => {
|
|
5751
|
-
Logger.debug("Initializing bootstrap context");
|
|
5752
|
-
let [cdkStatus, sstStatus] = await Promise.all([
|
|
5753
|
-
loadCDKStatus(),
|
|
5754
|
-
loadSSTStatus()
|
|
5755
|
-
]);
|
|
5756
|
-
Logger.debug("Loaded bootstrap status");
|
|
5757
|
-
const needToBootstrapCDK = !cdkStatus;
|
|
5758
|
-
const needToBootstrapSST = !sstStatus || sstStatus.version !== LATEST_VERSION;
|
|
5759
|
-
if (needToBootstrapCDK || needToBootstrapSST) {
|
|
5760
|
-
const spinner = createSpinner(
|
|
5761
|
-
"Deploying bootstrap stack, this only needs to happen once"
|
|
5762
|
-
).start();
|
|
5763
|
-
if (needToBootstrapCDK) {
|
|
5764
|
-
await bootstrapCDK();
|
|
5765
|
-
}
|
|
5766
|
-
if (needToBootstrapSST) {
|
|
5767
|
-
await bootstrapSST();
|
|
5768
|
-
sstStatus = await loadSSTStatus();
|
|
5769
|
-
if (!sstStatus)
|
|
5770
|
-
throw new VisibleError("Failed to load bootstrap stack status");
|
|
5771
|
-
}
|
|
5772
|
-
spinner.succeed();
|
|
5773
|
-
}
|
|
5774
|
-
Logger.debug("Bootstrap context initialized", sstStatus);
|
|
5775
|
-
return sstStatus;
|
|
5776
|
-
}, "Bootstrap");
|
|
5700
|
+
init_colors();
|
|
5701
|
+
init_server2();
|
|
5777
5702
|
}
|
|
5778
5703
|
});
|
|
5779
5704
|
|
|
@@ -5815,7 +5740,7 @@ var init_iot = __esm({
|
|
|
5815
5740
|
const endpoint = await useIOTEndpoint();
|
|
5816
5741
|
const creds = await useAWSCredentials();
|
|
5817
5742
|
const project = useProject();
|
|
5818
|
-
const
|
|
5743
|
+
const bootstrap2 = await useBootstrap();
|
|
5819
5744
|
const s3 = useAWSClient(S3Client3);
|
|
5820
5745
|
async function encode(input) {
|
|
5821
5746
|
const id = Math.random().toString();
|
|
@@ -5824,7 +5749,7 @@ var init_iot = __esm({
|
|
|
5824
5749
|
const key = `pointers/${id}`;
|
|
5825
5750
|
await s3.send(
|
|
5826
5751
|
new PutObjectCommand2({
|
|
5827
|
-
Bucket:
|
|
5752
|
+
Bucket: bootstrap2.bucket,
|
|
5828
5753
|
Key: key,
|
|
5829
5754
|
Body: json
|
|
5830
5755
|
})
|
|
@@ -5838,7 +5763,7 @@ var init_iot = __esm({
|
|
|
5838
5763
|
type: "pointer",
|
|
5839
5764
|
properties: {
|
|
5840
5765
|
key,
|
|
5841
|
-
bucket:
|
|
5766
|
+
bucket: bootstrap2.bucket
|
|
5842
5767
|
}
|
|
5843
5768
|
})
|
|
5844
5769
|
}
|
|
@@ -5990,15 +5915,10 @@ function printDeploymentResults(assembly, results, remove4) {
|
|
|
5990
5915
|
Colors.bold(remove4 ? ` Removed:` : ` Deployed:`)
|
|
5991
5916
|
);
|
|
5992
5917
|
for (const [stack, result] of success) {
|
|
5993
|
-
const outputs = Object.entries(result.outputs).filter(
|
|
5994
|
-
([key, _]) => !key.includes("SstSiteEnv")
|
|
5995
|
-
);
|
|
5996
5918
|
Colors.line(` ${Colors.dim(stackNameToId(stack))}`);
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
Colors.line(` ${Colors.bold.dim(key + ":")} ${value}`);
|
|
6001
|
-
}
|
|
5919
|
+
for (const key of Object.keys(result.outputs).sort()) {
|
|
5920
|
+
const value = result.outputs[key];
|
|
5921
|
+
Colors.line(` ${Colors.bold.dim(key + ":")} ${value}`);
|
|
6002
5922
|
}
|
|
6003
5923
|
}
|
|
6004
5924
|
Colors.gap();
|
|
@@ -6137,16 +6057,16 @@ __export(pothos_exports, {
|
|
|
6137
6057
|
import babel from "@babel/core";
|
|
6138
6058
|
import generator from "@babel/generator";
|
|
6139
6059
|
import esbuild3 from "esbuild";
|
|
6140
|
-
import
|
|
6141
|
-
import
|
|
6060
|
+
import fs14 from "fs/promises";
|
|
6061
|
+
import path16 from "path";
|
|
6142
6062
|
import url9 from "url";
|
|
6143
6063
|
async function generate(opts) {
|
|
6144
6064
|
const { printSchema, lexicographicSortSchema } = await import("graphql");
|
|
6145
6065
|
const contents = await extractSchema(opts);
|
|
6146
|
-
const out =
|
|
6147
|
-
await
|
|
6066
|
+
const out = path16.join(path16.dirname(opts.schema), "out.mjs");
|
|
6067
|
+
await fs14.writeFile(out, contents, "utf8");
|
|
6148
6068
|
const { schema } = await import(url9.pathToFileURL(out).href + "?bust=" + Date.now());
|
|
6149
|
-
await
|
|
6069
|
+
await fs14.rm(out);
|
|
6150
6070
|
const schemaAsString = printSchema(lexicographicSortSchema(schema));
|
|
6151
6071
|
return schemaAsString;
|
|
6152
6072
|
}
|
|
@@ -6294,10 +6214,10 @@ var pothos_exports2 = {};
|
|
|
6294
6214
|
__export(pothos_exports2, {
|
|
6295
6215
|
usePothosBuilder: () => usePothosBuilder
|
|
6296
6216
|
});
|
|
6297
|
-
import
|
|
6217
|
+
import fs15 from "fs/promises";
|
|
6298
6218
|
import { exec as exec6 } from "child_process";
|
|
6299
6219
|
import { promisify as promisify4 } from "util";
|
|
6300
|
-
import
|
|
6220
|
+
import path17 from "path";
|
|
6301
6221
|
var execAsync4, usePothosBuilder;
|
|
6302
6222
|
var init_pothos2 = __esm({
|
|
6303
6223
|
"src/cli/commands/plugins/pothos.ts"() {
|
|
@@ -6315,7 +6235,7 @@ var init_pothos2 = __esm({
|
|
|
6315
6235
|
const schema = await pothos_exports.generate({
|
|
6316
6236
|
schema: route.schema
|
|
6317
6237
|
});
|
|
6318
|
-
await
|
|
6238
|
+
await fs15.writeFile(route.output, schema);
|
|
6319
6239
|
if (Array.isArray(route.commands) && route.commands.length > 0) {
|
|
6320
6240
|
await Promise.all(route.commands.map((cmd) => execAsync4(cmd)));
|
|
6321
6241
|
}
|
|
@@ -6331,9 +6251,9 @@ var init_pothos2 = __esm({
|
|
|
6331
6251
|
if (evt.properties.file.endsWith("out.mjs"))
|
|
6332
6252
|
return;
|
|
6333
6253
|
for (const route of routes) {
|
|
6334
|
-
const dir =
|
|
6335
|
-
const relative =
|
|
6336
|
-
if (relative && !relative.startsWith("..") && !
|
|
6254
|
+
const dir = path17.dirname(route.schema);
|
|
6255
|
+
const relative = path17.relative(dir, evt.properties.file);
|
|
6256
|
+
if (relative && !relative.startsWith("..") && !path17.isAbsolute(relative))
|
|
6337
6257
|
build2(route);
|
|
6338
6258
|
}
|
|
6339
6259
|
});
|
|
@@ -6359,7 +6279,7 @@ __export(kysely_exports, {
|
|
|
6359
6279
|
import { Kysely } from "kysely";
|
|
6360
6280
|
import { DataApiDialect } from "kysely-data-api";
|
|
6361
6281
|
import { RDSData } from "@aws-sdk/client-rds-data";
|
|
6362
|
-
import * as
|
|
6282
|
+
import * as fs16 from "fs/promises";
|
|
6363
6283
|
import {
|
|
6364
6284
|
DatabaseMetadata,
|
|
6365
6285
|
EnumCollection,
|
|
@@ -6431,7 +6351,7 @@ var init_kysely = __esm({
|
|
|
6431
6351
|
};
|
|
6432
6352
|
const serializer = new Serializer();
|
|
6433
6353
|
const data2 = serializer.serialize(nodes);
|
|
6434
|
-
await
|
|
6354
|
+
await fs16.writeFile(db.types.path, data2);
|
|
6435
6355
|
}
|
|
6436
6356
|
bus.subscribe("stacks.metadata", (evt) => {
|
|
6437
6357
|
const constructs = Object.values(evt.properties).flat();
|
|
@@ -6568,12 +6488,39 @@ function parse(ssmName) {
|
|
|
6568
6488
|
prop: parts.slice(6).join("/")
|
|
6569
6489
|
};
|
|
6570
6490
|
}
|
|
6491
|
+
async function restartFunction(arn) {
|
|
6492
|
+
const lambda = useAWSClient(LambdaClient);
|
|
6493
|
+
try {
|
|
6494
|
+
const config = await lambda.send(
|
|
6495
|
+
new GetFunctionConfigurationCommand({
|
|
6496
|
+
FunctionName: arn
|
|
6497
|
+
})
|
|
6498
|
+
);
|
|
6499
|
+
await lambda.send(
|
|
6500
|
+
new UpdateFunctionConfigurationCommand({
|
|
6501
|
+
FunctionName: arn,
|
|
6502
|
+
Environment: {
|
|
6503
|
+
Variables: {
|
|
6504
|
+
...config.Environment?.Variables || {},
|
|
6505
|
+
[SECRET_UPDATED_AT_ENV]: Date.now().toString()
|
|
6506
|
+
}
|
|
6507
|
+
}
|
|
6508
|
+
})
|
|
6509
|
+
);
|
|
6510
|
+
return true;
|
|
6511
|
+
} catch (e) {
|
|
6512
|
+
if (e.name === "ResourceNotFoundException" && e.message.startsWith("Function not found")) {
|
|
6513
|
+
return;
|
|
6514
|
+
}
|
|
6515
|
+
}
|
|
6516
|
+
}
|
|
6571
6517
|
var Config, FALLBACK_STAGE, SECRET_UPDATED_AT_ENV, PREFIX;
|
|
6572
6518
|
var init_config = __esm({
|
|
6573
6519
|
"src/config.ts"() {
|
|
6574
6520
|
"use strict";
|
|
6575
6521
|
init_project();
|
|
6576
6522
|
init_credentials();
|
|
6523
|
+
init_iot();
|
|
6577
6524
|
init_stacks();
|
|
6578
6525
|
((Config2) => {
|
|
6579
6526
|
async function parameters() {
|
|
@@ -6628,10 +6575,10 @@ var init_config = __esm({
|
|
|
6628
6575
|
return result;
|
|
6629
6576
|
}
|
|
6630
6577
|
Config2.secrets = secrets2;
|
|
6631
|
-
async function
|
|
6578
|
+
async function env() {
|
|
6632
6579
|
const project = useProject();
|
|
6633
6580
|
const parameters2 = await Config2.parameters();
|
|
6634
|
-
const
|
|
6581
|
+
const env2 = {
|
|
6635
6582
|
SST_APP: project.config.name,
|
|
6636
6583
|
SST_STAGE: project.config.stage,
|
|
6637
6584
|
...pipe2(
|
|
@@ -6640,12 +6587,12 @@ var init_config = __esm({
|
|
|
6640
6587
|
Object.fromEntries
|
|
6641
6588
|
)
|
|
6642
6589
|
};
|
|
6643
|
-
return
|
|
6590
|
+
return env2;
|
|
6644
6591
|
}
|
|
6645
|
-
Config2.env =
|
|
6592
|
+
Config2.env = env;
|
|
6646
6593
|
async function setSecret(input) {
|
|
6647
6594
|
const ssm = useAWSClient(SSMClient);
|
|
6648
|
-
|
|
6595
|
+
await ssm.send(
|
|
6649
6596
|
new PutParameterCommand({
|
|
6650
6597
|
Name: pathFor({
|
|
6651
6598
|
id: input.key,
|
|
@@ -6658,6 +6605,9 @@ var init_config = __esm({
|
|
|
6658
6605
|
Overwrite: true
|
|
6659
6606
|
})
|
|
6660
6607
|
);
|
|
6608
|
+
const iot2 = await useIOT();
|
|
6609
|
+
const topic = `${iot2.prefix}/events`;
|
|
6610
|
+
await iot2.publish(topic, "config.secret.updated", { name: input.key });
|
|
6661
6611
|
}
|
|
6662
6612
|
Config2.setSecret = setSecret;
|
|
6663
6613
|
async function getSecret(input) {
|
|
@@ -6691,37 +6641,35 @@ var init_config = __esm({
|
|
|
6691
6641
|
}
|
|
6692
6642
|
Config2.removeSecret = removeSecret;
|
|
6693
6643
|
async function restart(key) {
|
|
6694
|
-
const lambda = useAWSClient(LambdaClient);
|
|
6695
6644
|
const metadata3 = await stacks_exports.metadata();
|
|
6696
|
-
const
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
new GetFunctionConfigurationCommand({
|
|
6702
|
-
FunctionName: f.data.arn
|
|
6703
|
-
})
|
|
6704
|
-
);
|
|
6705
|
-
await lambda.send(
|
|
6706
|
-
new UpdateFunctionConfigurationCommand({
|
|
6707
|
-
FunctionName: f.data.arn,
|
|
6708
|
-
Environment: {
|
|
6709
|
-
Variables: {
|
|
6710
|
-
...config.Environment?.Variables || {},
|
|
6711
|
-
[SECRET_UPDATED_AT_ENV]: Date.now().toString()
|
|
6712
|
-
}
|
|
6713
|
-
}
|
|
6714
|
-
})
|
|
6715
|
-
);
|
|
6716
|
-
return true;
|
|
6717
|
-
} catch (e) {
|
|
6718
|
-
if (e.name === "ResourceNotFoundException" && e.message.startsWith("Function not found")) {
|
|
6719
|
-
return;
|
|
6720
|
-
}
|
|
6721
|
-
}
|
|
6722
|
-
})
|
|
6645
|
+
const siteData = Object.values(metadata3).flat().filter(
|
|
6646
|
+
(c) => c.type === "AstroSite" || c.type === "NextjsSite" || c.type === "RemixSite" || c.type === "SolidStartSite"
|
|
6647
|
+
).filter((c) => c.data.secrets.includes(key));
|
|
6648
|
+
const siteDataPlaceholder = siteData.filter(
|
|
6649
|
+
(c) => c.data.mode === "placeholder"
|
|
6723
6650
|
);
|
|
6724
|
-
|
|
6651
|
+
const siteDataEdge = siteData.filter((c) => c.data.mode === "deployed").filter((c) => c.data.edge);
|
|
6652
|
+
const siteDataRegional = siteData.filter((c) => c.data.mode === "deployed").filter((c) => !c.data.edge);
|
|
6653
|
+
const regionalSiteArns = siteData.map((s) => s.data.server);
|
|
6654
|
+
const functionData = Object.values(metadata3).flat().filter((c) => c.type === "Function").filter((c) => !regionalSiteArns.includes(c.data.arn)).filter((c) => c.data.secrets.includes(key));
|
|
6655
|
+
const restartedSites = (await Promise.all(
|
|
6656
|
+
siteDataRegional.map(async (s) => {
|
|
6657
|
+
const restarted = await restartFunction(s.data.server);
|
|
6658
|
+
return restarted ? s : restarted;
|
|
6659
|
+
})
|
|
6660
|
+
)).filter((c) => Boolean(c));
|
|
6661
|
+
const restartedFunctions = (await Promise.all(
|
|
6662
|
+
functionData.map(async (f) => {
|
|
6663
|
+
const restarted = await restartFunction(f.data.arn);
|
|
6664
|
+
return restarted ? f : restarted;
|
|
6665
|
+
})
|
|
6666
|
+
)).filter((c) => Boolean(c));
|
|
6667
|
+
return {
|
|
6668
|
+
edgeSites: siteDataEdge,
|
|
6669
|
+
sites: restartedSites,
|
|
6670
|
+
placeholderSites: siteDataPlaceholder,
|
|
6671
|
+
functions: restartedFunctions
|
|
6672
|
+
};
|
|
6725
6673
|
}
|
|
6726
6674
|
Config2.restart = restart;
|
|
6727
6675
|
})(Config || (Config = {}));
|
|
@@ -6785,62 +6733,17 @@ init_spinner();
|
|
|
6785
6733
|
init_logger();
|
|
6786
6734
|
import dotenv2 from "dotenv";
|
|
6787
6735
|
|
|
6788
|
-
// src/cli/commands/
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
"
|
|
6792
|
-
|
|
6793
|
-
(
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
`sst env "vite dev"`,
|
|
6798
|
-
"Start Vite with your environment variables"
|
|
6799
|
-
),
|
|
6800
|
-
async (args) => {
|
|
6801
|
-
const { createSpinner: createSpinner2 } = await Promise.resolve().then(() => (init_spinner(), spinner_exports));
|
|
6802
|
-
const fs19 = await import("fs/promises");
|
|
6803
|
-
const { SiteEnv } = await Promise.resolve().then(() => (init_site_env(), site_env_exports));
|
|
6804
|
-
const { spawnSync } = await import("child_process");
|
|
6805
|
-
const { useAWSCredentials: useAWSCredentials3 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
|
|
6806
|
-
const { useProject: useProject2 } = await Promise.resolve().then(() => (init_project(), project_exports));
|
|
6807
|
-
let spinner;
|
|
6808
|
-
while (true) {
|
|
6809
|
-
const exists = await fs19.access(SiteEnv.valuesFile()).then(() => true).catch(() => false);
|
|
6810
|
-
if (!exists) {
|
|
6811
|
-
spinner = createSpinner2(
|
|
6812
|
-
"Cannot find SST environment variables. Waiting for SST to start..."
|
|
6813
|
-
).start();
|
|
6814
|
-
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
6815
|
-
continue;
|
|
6816
|
-
}
|
|
6817
|
-
spinner?.succeed();
|
|
6818
|
-
const sites = await SiteEnv.values();
|
|
6819
|
-
const env2 = sites[process.cwd()] || {};
|
|
6820
|
-
const project = useProject2();
|
|
6821
|
-
const credentials = await useAWSCredentials3();
|
|
6822
|
-
const joined = args.command?.join(" ");
|
|
6823
|
-
if (!joined)
|
|
6824
|
-
throw new VisibleError(
|
|
6825
|
-
"Command is required, e.g. sst env vite dev"
|
|
6826
|
-
);
|
|
6827
|
-
const result = spawnSync(joined, {
|
|
6828
|
-
env: {
|
|
6829
|
-
...process.env,
|
|
6830
|
-
...env2,
|
|
6831
|
-
AWS_ACCESS_KEY_ID: credentials.accessKeyId,
|
|
6832
|
-
AWS_SECRET_ACCESS_KEY: credentials.secretAccessKey,
|
|
6833
|
-
AWS_SESSION_TOKEN: credentials.sessionToken,
|
|
6834
|
-
AWS_REGION: project.config.region
|
|
6835
|
-
},
|
|
6836
|
-
stdio: "inherit",
|
|
6837
|
-
shell: true
|
|
6838
|
-
});
|
|
6839
|
-
process.exitCode = result.status || void 0;
|
|
6840
|
-
break;
|
|
6841
|
-
}
|
|
6736
|
+
// src/cli/commands/bootstrap.ts
|
|
6737
|
+
var bootstrap = (program2) => program2.command(
|
|
6738
|
+
"bootstrap",
|
|
6739
|
+
"Create the SST bootstrap stack",
|
|
6740
|
+
(yargs2) => yargs2,
|
|
6741
|
+
async () => {
|
|
6742
|
+
const { useBootstrap: useBootstrap2 } = await Promise.resolve().then(() => (init_bootstrap(), bootstrap_exports));
|
|
6743
|
+
await useBootstrap2();
|
|
6744
|
+
process.exit(0);
|
|
6842
6745
|
}
|
|
6843
|
-
)
|
|
6746
|
+
);
|
|
6844
6747
|
|
|
6845
6748
|
// src/cli/commands/dev.tsx
|
|
6846
6749
|
var dev = (program2) => program2.command(
|
|
@@ -6853,11 +6756,11 @@ var dev = (program2) => program2.command(
|
|
|
6853
6756
|
async (args) => {
|
|
6854
6757
|
const { Colors: Colors2 } = await Promise.resolve().then(() => (init_colors(), colors_exports));
|
|
6855
6758
|
const { printHeader: printHeader2 } = await Promise.resolve().then(() => (init_header(), header_exports));
|
|
6856
|
-
const { mapValues
|
|
6759
|
+
const { mapValues } = await import("remeda");
|
|
6857
6760
|
const path20 = await import("path");
|
|
6858
6761
|
const { useRuntimeWorkers: useRuntimeWorkers2 } = await Promise.resolve().then(() => (init_workers(), workers_exports));
|
|
6859
6762
|
const { useIOTBridge: useIOTBridge2 } = await Promise.resolve().then(() => (init_iot2(), iot_exports2));
|
|
6860
|
-
const { useRuntimeServer: useRuntimeServer2 } = await Promise.resolve().then(() => (
|
|
6763
|
+
const { useRuntimeServer: useRuntimeServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
6861
6764
|
const { useBus: useBus2 } = await Promise.resolve().then(() => (init_bus(), bus_exports));
|
|
6862
6765
|
const { useWatcher: useWatcher2 } = await Promise.resolve().then(() => (init_watcher(), watcher_exports));
|
|
6863
6766
|
const { useAppMetadata: useAppMetadata2, saveAppMetadata: saveAppMetadata2, Stacks } = await Promise.resolve().then(() => (init_stacks(), stacks_exports));
|
|
@@ -6868,11 +6771,10 @@ var dev = (program2) => program2.command(
|
|
|
6868
6771
|
const React2 = await import("react");
|
|
6869
6772
|
const { Context: Context2 } = await Promise.resolve().then(() => (init_context(), context_exports));
|
|
6870
6773
|
const { printDeploymentResults: printDeploymentResults2, DeploymentUI: DeploymentUI2 } = await Promise.resolve().then(() => (init_deploy2(), deploy_exports));
|
|
6871
|
-
const { useLocalServer: useLocalServer2 } = await Promise.resolve().then(() => (
|
|
6872
|
-
const
|
|
6774
|
+
const { useLocalServer: useLocalServer2 } = await Promise.resolve().then(() => (init_server2(), server_exports2));
|
|
6775
|
+
const fs18 = await import("fs/promises");
|
|
6873
6776
|
const crypto2 = await import("crypto");
|
|
6874
6777
|
const { useFunctions: useFunctions3 } = await import("../src/constructs/Function.js");
|
|
6875
|
-
const { SiteEnv } = await Promise.resolve().then(() => (init_site_env(), site_env_exports));
|
|
6876
6778
|
const { usePothosBuilder: usePothosBuilder2 } = await Promise.resolve().then(() => (init_pothos2(), pothos_exports2));
|
|
6877
6779
|
const { useKyselyTypeGenerator: useKyselyTypeGenerator2 } = await Promise.resolve().then(() => (init_kysely(), kysely_exports));
|
|
6878
6780
|
const { useRDSWarmer: useRDSWarmer2 } = await Promise.resolve().then(() => (init_warmer(), warmer_exports));
|
|
@@ -7044,27 +6946,10 @@ var dev = (program2) => program2.command(
|
|
|
7044
6946
|
await saveAppMetadata2({ mode: "dev" });
|
|
7045
6947
|
}
|
|
7046
6948
|
lastDeployed = nextChecksum;
|
|
7047
|
-
|
|
7048
|
-
const result = {};
|
|
7049
|
-
for (const key of keys2) {
|
|
7050
|
-
const stack = results[key.stack];
|
|
7051
|
-
const value = stack.outputs[key.output];
|
|
7052
|
-
let existing = result[key.path];
|
|
7053
|
-
if (!existing) {
|
|
7054
|
-
result[key.path] = existing;
|
|
7055
|
-
existing = result[key.path] = {};
|
|
7056
|
-
}
|
|
7057
|
-
existing[key.environment] = value;
|
|
7058
|
-
}
|
|
7059
|
-
await SiteEnv.writeValues(result);
|
|
7060
|
-
fs19.writeFile(
|
|
6949
|
+
fs18.writeFile(
|
|
7061
6950
|
path20.join(project.paths.out, "outputs.json"),
|
|
7062
6951
|
JSON.stringify(
|
|
7063
|
-
|
|
7064
|
-
results,
|
|
7065
|
-
omitBy2((_, key) => key.includes("SstSiteEnv")),
|
|
7066
|
-
mapValues((val) => val.outputs)
|
|
7067
|
-
),
|
|
6952
|
+
mapValues(results, (val) => val.outputs),
|
|
7068
6953
|
null,
|
|
7069
6954
|
2
|
|
7070
6955
|
)
|
|
@@ -7076,7 +6961,7 @@ var dev = (program2) => program2.command(
|
|
|
7076
6961
|
async function checksum(cdkOutPath) {
|
|
7077
6962
|
const manifestPath = path20.join(cdkOutPath, "manifest.json");
|
|
7078
6963
|
const cdkManifest = JSON.parse(
|
|
7079
|
-
await
|
|
6964
|
+
await fs18.readFile(manifestPath).then((x) => x.toString())
|
|
7080
6965
|
);
|
|
7081
6966
|
const checksumData = await Promise.all(
|
|
7082
6967
|
Object.keys(cdkManifest.artifacts).filter(
|
|
@@ -7084,7 +6969,7 @@ var dev = (program2) => program2.command(
|
|
|
7084
6969
|
).map(async (key) => {
|
|
7085
6970
|
const { templateFile } = cdkManifest.artifacts[key].properties;
|
|
7086
6971
|
const templatePath = path20.join(cdkOutPath, templateFile);
|
|
7087
|
-
const templateContent = await
|
|
6972
|
+
const templateContent = await fs18.readFile(templatePath);
|
|
7088
6973
|
return templateContent;
|
|
7089
6974
|
})
|
|
7090
6975
|
).then((x) => x.join("\n"));
|
|
@@ -7175,37 +7060,231 @@ Are you sure you want to run this stage in dev mode? [y/N] `,
|
|
|
7175
7060
|
|
|
7176
7061
|
// src/cli/commands/bind.ts
|
|
7177
7062
|
init_error();
|
|
7063
|
+
import path18 from "path";
|
|
7064
|
+
var SITE_CONFIG = {
|
|
7065
|
+
NextjsSite: "next.config",
|
|
7066
|
+
AstroSite: "astro.config",
|
|
7067
|
+
RemixSite: "remix.config",
|
|
7068
|
+
SolidStartSite: "vite.config",
|
|
7069
|
+
StaticSite: "vite.config",
|
|
7070
|
+
SlsNextjsSite: "next.config"
|
|
7071
|
+
};
|
|
7178
7072
|
var bind = (program2) => program2.command(
|
|
7179
|
-
"bind <command..>",
|
|
7073
|
+
["bind <command..>", "env <command..>"],
|
|
7180
7074
|
"Bind your app's resources to a command",
|
|
7181
7075
|
(yargs2) => yargs2.array("command").example(`sst bind "vitest run"`, "Bind your resources to your tests").example(
|
|
7182
7076
|
`sst bind "tsx scripts/myscript.ts"`,
|
|
7183
7077
|
"Bind your resources to a script"
|
|
7184
7078
|
),
|
|
7185
7079
|
async (args) => {
|
|
7186
|
-
const {
|
|
7187
|
-
const { spawnSync } = await import("child_process");
|
|
7188
|
-
const { useAWSCredentials: useAWSCredentials3 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
|
|
7080
|
+
const { spawn: spawn7 } = await import("child_process");
|
|
7189
7081
|
const { useProject: useProject2 } = await Promise.resolve().then(() => (init_project(), project_exports));
|
|
7190
|
-
const
|
|
7082
|
+
const { useBus: useBus2 } = await Promise.resolve().then(() => (init_bus(), bus_exports));
|
|
7083
|
+
const { useIOT: useIOT2 } = await Promise.resolve().then(() => (init_iot(), iot_exports));
|
|
7084
|
+
const { Colors: Colors2 } = await Promise.resolve().then(() => (init_colors(), colors_exports));
|
|
7085
|
+
if (args._[0] === "env") {
|
|
7086
|
+
Colors2.line(
|
|
7087
|
+
Colors2.warning(
|
|
7088
|
+
`Warning: ${Colors2.bold(
|
|
7089
|
+
`sst env`
|
|
7090
|
+
)} has been renamed to ${Colors2.bold(`sst bind`)}`
|
|
7091
|
+
)
|
|
7092
|
+
);
|
|
7093
|
+
}
|
|
7094
|
+
await useIOT2();
|
|
7095
|
+
const bus = useBus2();
|
|
7191
7096
|
const project = useProject2();
|
|
7192
|
-
const
|
|
7193
|
-
const
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
|
|
7197
|
-
|
|
7198
|
-
|
|
7199
|
-
|
|
7097
|
+
const command = args.command?.join(" ");
|
|
7098
|
+
const isFrontend = await isRunningInFrontend();
|
|
7099
|
+
let p;
|
|
7100
|
+
let timer;
|
|
7101
|
+
let metadataCache;
|
|
7102
|
+
if (!command) {
|
|
7103
|
+
throw new VisibleError(
|
|
7104
|
+
`Command is required, e.g. sst bind ${isFrontend ? "next dev" : "env"}`
|
|
7105
|
+
);
|
|
7106
|
+
}
|
|
7107
|
+
const initialMetadata = await getSiteMetadata();
|
|
7108
|
+
if (!initialMetadata) {
|
|
7109
|
+
return await bindScript();
|
|
7110
|
+
}
|
|
7111
|
+
await bindSite("init");
|
|
7112
|
+
bus.subscribe(
|
|
7113
|
+
"stacks.metadata.updated",
|
|
7114
|
+
() => bindSite("metadata_updated")
|
|
7115
|
+
);
|
|
7116
|
+
bus.subscribe(
|
|
7117
|
+
"stacks.metadata.deleted",
|
|
7118
|
+
() => bindSite("metadata_updated")
|
|
7119
|
+
);
|
|
7120
|
+
bus.subscribe("config.secret.updated", (payload) => {
|
|
7121
|
+
const secretName = payload.properties.name;
|
|
7122
|
+
if (metadataCache?.secrets === void 0)
|
|
7123
|
+
return;
|
|
7124
|
+
if (!metadataCache.secrets.includes(secretName))
|
|
7125
|
+
return;
|
|
7126
|
+
Colors2.line(
|
|
7127
|
+
`
|
|
7128
|
+
`,
|
|
7129
|
+
`SST secrets have been updated. Restarting \`${command}\`...`
|
|
7130
|
+
);
|
|
7131
|
+
bindSite("secrets_updated");
|
|
7132
|
+
});
|
|
7133
|
+
async function isRunningInFrontend() {
|
|
7134
|
+
const { existsAsync: existsAsync3 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
7135
|
+
const results = await Promise.all(
|
|
7136
|
+
Object.values(SITE_CONFIG).map(
|
|
7137
|
+
(config) => [".js", ".cjs", ".mjs", ".ts"].map(
|
|
7138
|
+
(ext) => existsAsync3(`${config}${ext}`)
|
|
7139
|
+
)
|
|
7140
|
+
).flat()
|
|
7141
|
+
);
|
|
7142
|
+
return results.some(Boolean);
|
|
7143
|
+
}
|
|
7144
|
+
async function bindSite(reason) {
|
|
7145
|
+
const metadata3 = reason === "init" ? initialMetadata : await getSiteMetadata();
|
|
7146
|
+
if (reason === "metadata_updated") {
|
|
7147
|
+
if (areEnvsSame(metadata3.envs, metadataCache?.envs || {}))
|
|
7148
|
+
return;
|
|
7149
|
+
Colors2.line(
|
|
7150
|
+
`
|
|
7151
|
+
`,
|
|
7152
|
+
`SST resources have been updated. Restarting \`${command}\`...`
|
|
7153
|
+
);
|
|
7154
|
+
}
|
|
7155
|
+
metadataCache = metadata3;
|
|
7156
|
+
if (metadata3.role) {
|
|
7157
|
+
const credentials = await assumeSsrRole(metadata3.role);
|
|
7158
|
+
if (credentials) {
|
|
7159
|
+
const expireAt = credentials.Expiration.getTime() - 6e4;
|
|
7160
|
+
clearTimeout(timer);
|
|
7161
|
+
timer = setTimeout(() => {
|
|
7162
|
+
Colors2.line(
|
|
7163
|
+
`
|
|
7164
|
+
`,
|
|
7165
|
+
`Your AWS session is about to expire. Creating a new session and restarting \`${command}\`...`
|
|
7166
|
+
);
|
|
7167
|
+
bindSite("iam_expired");
|
|
7168
|
+
}, expireAt - Date.now());
|
|
7169
|
+
runCommand({
|
|
7170
|
+
...metadata3.envs,
|
|
7171
|
+
AWS_ACCESS_KEY_ID: credentials.AccessKeyId,
|
|
7172
|
+
AWS_SECRET_ACCESS_KEY: credentials.SecretAccessKey,
|
|
7173
|
+
AWS_SESSION_TOKEN: credentials.SessionToken
|
|
7174
|
+
});
|
|
7175
|
+
return;
|
|
7176
|
+
}
|
|
7177
|
+
}
|
|
7178
|
+
runCommand({
|
|
7179
|
+
...metadata3.envs,
|
|
7180
|
+
...await localIamCredentials()
|
|
7181
|
+
});
|
|
7182
|
+
}
|
|
7183
|
+
async function bindScript() {
|
|
7184
|
+
const { Config: Config2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
7185
|
+
runCommand({
|
|
7186
|
+
...await Config2.env(),
|
|
7187
|
+
...await localIamCredentials()
|
|
7188
|
+
});
|
|
7189
|
+
}
|
|
7190
|
+
async function getSiteMetadata() {
|
|
7191
|
+
const { metadata: metadata3 } = await Promise.resolve().then(() => (init_metadata(), metadata_exports));
|
|
7192
|
+
const { createSpinner: createSpinner2 } = await Promise.resolve().then(() => (init_spinner(), spinner_exports));
|
|
7193
|
+
const { LambdaClient: LambdaClient2, GetFunctionCommand } = await import("@aws-sdk/client-lambda");
|
|
7194
|
+
const { useAWSClient: useAWSClient2 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
|
|
7195
|
+
const spinner = createSpinner2({});
|
|
7196
|
+
while (true) {
|
|
7197
|
+
const metadataData = await metadata3();
|
|
7198
|
+
const data2 = Object.values(metadataData).flat().filter(
|
|
7199
|
+
(c) => Boolean(c)
|
|
7200
|
+
).filter((c) => Boolean(SITE_CONFIG[c.type])).find(
|
|
7201
|
+
(c) => path18.resolve(project.paths.root, c.data.path) === process.cwd()
|
|
7202
|
+
);
|
|
7203
|
+
if (!data2 && !isFrontend) {
|
|
7204
|
+
return;
|
|
7205
|
+
}
|
|
7206
|
+
if (!data2) {
|
|
7207
|
+
spinner.start(
|
|
7208
|
+
"Make sure `sst dev` is running..."
|
|
7209
|
+
);
|
|
7210
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
7211
|
+
continue;
|
|
7212
|
+
}
|
|
7213
|
+
const isBindSupported = data2.type !== "StaticSite" && data2.type !== "SlsNextjsSite";
|
|
7214
|
+
if (isBindSupported && !data2.data.server || !isBindSupported && !data2.data.environment) {
|
|
7215
|
+
spinner.start(
|
|
7216
|
+
"This was deployed with an old version of SST. Make sure to restart `sst dev`..."
|
|
7217
|
+
);
|
|
7218
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
7219
|
+
continue;
|
|
7220
|
+
}
|
|
7221
|
+
spinner.isSpinning && spinner.stop().clear();
|
|
7222
|
+
if (!isBindSupported) {
|
|
7223
|
+
return { envs: data2.data.environment };
|
|
7224
|
+
}
|
|
7225
|
+
const lambda = useAWSClient2(LambdaClient2);
|
|
7226
|
+
const { Configuration: functionConfig } = await lambda.send(
|
|
7227
|
+
new GetFunctionCommand({
|
|
7228
|
+
FunctionName: data2.data.server
|
|
7229
|
+
})
|
|
7230
|
+
);
|
|
7231
|
+
return {
|
|
7232
|
+
role: functionConfig?.Role,
|
|
7233
|
+
envs: functionConfig?.Environment?.Variables || {},
|
|
7234
|
+
secrets: data2.data.secrets
|
|
7235
|
+
};
|
|
7236
|
+
}
|
|
7237
|
+
}
|
|
7238
|
+
async function assumeSsrRole(roleArn) {
|
|
7239
|
+
const { STSClient: STSClient2, AssumeRoleCommand } = await import("@aws-sdk/client-sts");
|
|
7240
|
+
const { Logger: Logger2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
|
|
7241
|
+
const { useAWSClient: useAWSClient2 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
|
|
7242
|
+
const sts = useAWSClient2(STSClient2);
|
|
7243
|
+
try {
|
|
7244
|
+
const { Credentials: credentials } = await sts.send(
|
|
7245
|
+
new AssumeRoleCommand({
|
|
7246
|
+
RoleArn: roleArn,
|
|
7247
|
+
RoleSessionName: "dev-session",
|
|
7248
|
+
DurationSeconds: 43200
|
|
7249
|
+
})
|
|
7250
|
+
);
|
|
7251
|
+
return credentials;
|
|
7252
|
+
} catch (e) {
|
|
7253
|
+
Colors2.line(
|
|
7254
|
+
Colors2.warning(
|
|
7255
|
+
`Failed to assume SSR role ${roleArn}. Falling back to using local IAM credentials.`
|
|
7256
|
+
)
|
|
7257
|
+
);
|
|
7258
|
+
Logger2.debug(`Failed to assume ${roleArn}.`, e);
|
|
7259
|
+
}
|
|
7260
|
+
}
|
|
7261
|
+
async function localIamCredentials() {
|
|
7262
|
+
const { useAWSCredentials: useAWSCredentials3 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
|
|
7263
|
+
const credentials = await useAWSCredentials3();
|
|
7264
|
+
return {
|
|
7200
7265
|
AWS_ACCESS_KEY_ID: credentials.accessKeyId,
|
|
7201
7266
|
AWS_SECRET_ACCESS_KEY: credentials.secretAccessKey,
|
|
7202
|
-
AWS_SESSION_TOKEN: credentials.sessionToken
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7208
|
-
|
|
7267
|
+
AWS_SESSION_TOKEN: credentials.sessionToken
|
|
7268
|
+
};
|
|
7269
|
+
}
|
|
7270
|
+
function runCommand(envs) {
|
|
7271
|
+
Colors2.gap();
|
|
7272
|
+
if (p) {
|
|
7273
|
+
p.kill();
|
|
7274
|
+
}
|
|
7275
|
+
p = spawn7(command, {
|
|
7276
|
+
env: {
|
|
7277
|
+
...process.env,
|
|
7278
|
+
...envs,
|
|
7279
|
+
AWS_REGION: project.config.region
|
|
7280
|
+
},
|
|
7281
|
+
stdio: "inherit",
|
|
7282
|
+
shell: true
|
|
7283
|
+
});
|
|
7284
|
+
}
|
|
7285
|
+
function areEnvsSame(envs1, envs2) {
|
|
7286
|
+
return Object.keys(envs1).length === Object.keys(envs2).length && Object.keys(envs1).every((key) => envs1[key] === envs2[key]);
|
|
7287
|
+
}
|
|
7209
7288
|
}
|
|
7210
7289
|
).strict(false);
|
|
7211
7290
|
|
|
@@ -7240,7 +7319,7 @@ var build = (program2) => program2.command(
|
|
|
7240
7319
|
// src/cli/commands/deploy.tsx
|
|
7241
7320
|
init_credentials();
|
|
7242
7321
|
init_colors();
|
|
7243
|
-
import
|
|
7322
|
+
import fs17 from "fs/promises";
|
|
7244
7323
|
import path19 from "path";
|
|
7245
7324
|
var deploy2 = (program2) => program2.command(
|
|
7246
7325
|
"deploy [filter]",
|
|
@@ -7329,7 +7408,7 @@ Are you sure you want to deploy to this stage? (y/N) `,
|
|
|
7329
7408
|
printDeploymentResults2(assembly, results);
|
|
7330
7409
|
if (Object.values(results).some((stack) => Stacks.isFailed(stack.status)))
|
|
7331
7410
|
process.exit(1);
|
|
7332
|
-
|
|
7411
|
+
fs17.writeFile(
|
|
7333
7412
|
path19.join(project.paths.out, "outputs.json"),
|
|
7334
7413
|
JSON.stringify(
|
|
7335
7414
|
mapValues(results, (val) => val.outputs),
|
|
@@ -7408,8 +7487,8 @@ var consoleCommand = async (program2) => program2.command(
|
|
|
7408
7487
|
(yargs2) => yargs2,
|
|
7409
7488
|
async () => {
|
|
7410
7489
|
const { blue: blue4 } = await import("colorette");
|
|
7411
|
-
const { useRuntimeServer: useRuntimeServer2 } = await Promise.resolve().then(() => (
|
|
7412
|
-
const { useLocalServer: useLocalServer2 } = await Promise.resolve().then(() => (
|
|
7490
|
+
const { useRuntimeServer: useRuntimeServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
7491
|
+
const { useLocalServer: useLocalServer2 } = await Promise.resolve().then(() => (init_server2(), server_exports2));
|
|
7413
7492
|
const { printHeader: printHeader2 } = await Promise.resolve().then(() => (init_header(), header_exports));
|
|
7414
7493
|
const { clear: clear2 } = await Promise.resolve().then(() => (init_terminal(), terminal_exports));
|
|
7415
7494
|
await Promise.all([
|
|
@@ -7477,14 +7556,14 @@ var list = (program2) => program2.command(
|
|
|
7477
7556
|
}
|
|
7478
7557
|
break;
|
|
7479
7558
|
case "table":
|
|
7480
|
-
const
|
|
7559
|
+
const keys = Object.keys(secrets2);
|
|
7481
7560
|
const keyLen = Math.max(
|
|
7482
7561
|
"Secrets".length,
|
|
7483
|
-
...
|
|
7562
|
+
...keys.map((key) => key.length)
|
|
7484
7563
|
);
|
|
7485
7564
|
const valueLen = Math.max(
|
|
7486
7565
|
"Values".length,
|
|
7487
|
-
...
|
|
7566
|
+
...keys.map(
|
|
7488
7567
|
(key) => secrets2[key].value ? secrets2[key].value.length : `${secrets2[key].fallback} (fallback)`.length
|
|
7489
7568
|
)
|
|
7490
7569
|
);
|
|
@@ -7497,7 +7576,7 @@ var list = (program2) => program2.command(
|
|
|
7497
7576
|
console.log(
|
|
7498
7577
|
"\u251C".padEnd(keyLen + 3, "\u2500") + "\u253C" + "".padEnd(valueLen + 2, "\u2500") + "\u2524"
|
|
7499
7578
|
);
|
|
7500
|
-
|
|
7579
|
+
keys.sort().forEach((key) => {
|
|
7501
7580
|
const value = secrets2[key].value ? secrets2[key].value : `${secrets2[key].fallback} ${gray("(fallback)")}`;
|
|
7502
7581
|
console.log(
|
|
7503
7582
|
`\u2502 ${key.padEnd(keyLen)} \u2502 ${value.padEnd(valueLen)} \u2502`
|
|
@@ -7556,6 +7635,7 @@ var set = (program2) => program2.command(
|
|
|
7556
7635
|
}),
|
|
7557
7636
|
async (args) => {
|
|
7558
7637
|
const { Config: Config2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
7638
|
+
const { Colors: Colors2 } = await Promise.resolve().then(() => (init_colors(), colors_exports));
|
|
7559
7639
|
const { blue: blue4 } = await import("colorette");
|
|
7560
7640
|
const { createSpinner: createSpinner2 } = await Promise.resolve().then(() => (init_spinner(), spinner_exports));
|
|
7561
7641
|
const setting = createSpinner2(` Setting "${args.name}"`).start();
|
|
@@ -7566,12 +7646,31 @@ var set = (program2) => program2.command(
|
|
|
7566
7646
|
});
|
|
7567
7647
|
setting.succeed();
|
|
7568
7648
|
const restarting = createSpinner2(
|
|
7569
|
-
`
|
|
7649
|
+
` Reloading all resources using ${blue4(args.name)}...`
|
|
7570
7650
|
).start();
|
|
7571
|
-
const
|
|
7572
|
-
restarting.
|
|
7573
|
-
|
|
7574
|
-
)
|
|
7651
|
+
const { edgeSites, sites, placeholderSites, functions } = await Config2.restart(args.name);
|
|
7652
|
+
restarting.stop().clear();
|
|
7653
|
+
const siteCount = sites.length + placeholderSites.length;
|
|
7654
|
+
if (siteCount > 0) {
|
|
7655
|
+
Colors2.line(
|
|
7656
|
+
Colors2.success(`\u2714 `),
|
|
7657
|
+
siteCount === 1 ? `Reloaded ${siteCount} site` : `Reloaded ${siteCount} sites`
|
|
7658
|
+
);
|
|
7659
|
+
}
|
|
7660
|
+
const functionCount = functions.length;
|
|
7661
|
+
if (functionCount > 0) {
|
|
7662
|
+
Colors2.line(
|
|
7663
|
+
Colors2.success(`\u2714 `),
|
|
7664
|
+
functionCount === 1 ? `Reloaded ${functionCount} function` : `Reloaded ${functionCount} functions`
|
|
7665
|
+
);
|
|
7666
|
+
}
|
|
7667
|
+
edgeSites.forEach(({ id, type }) => {
|
|
7668
|
+
Colors2.line(
|
|
7669
|
+
Colors2.danger(`\u279C `),
|
|
7670
|
+
`Redeploy the "${id}" ${type} to use the new secret`
|
|
7671
|
+
);
|
|
7672
|
+
});
|
|
7673
|
+
process.exit(0);
|
|
7575
7674
|
}
|
|
7576
7675
|
);
|
|
7577
7676
|
|
|
@@ -7599,13 +7698,13 @@ var update = (program2) => program2.command(
|
|
|
7599
7698
|
}),
|
|
7600
7699
|
async (args) => {
|
|
7601
7700
|
const { green, yellow } = await import("colorette");
|
|
7602
|
-
const
|
|
7701
|
+
const fs18 = await import("fs/promises");
|
|
7603
7702
|
const path20 = await import("path");
|
|
7604
7703
|
const { fetch } = await import("undici");
|
|
7605
7704
|
const { useProject: useProject2 } = await Promise.resolve().then(() => (init_project(), project_exports));
|
|
7606
7705
|
const { Colors: Colors2 } = await Promise.resolve().then(() => (init_colors(), colors_exports));
|
|
7607
7706
|
async function find2(dir) {
|
|
7608
|
-
const children = await
|
|
7707
|
+
const children = await fs18.readdir(dir);
|
|
7609
7708
|
const tasks2 = children.map(async (item) => {
|
|
7610
7709
|
if (item === "node_modules")
|
|
7611
7710
|
return [];
|
|
@@ -7614,7 +7713,7 @@ var update = (program2) => program2.command(
|
|
|
7614
7713
|
const full = path20.join(dir, item);
|
|
7615
7714
|
if (item === "package.json")
|
|
7616
7715
|
return [full];
|
|
7617
|
-
const stat = await
|
|
7716
|
+
const stat = await fs18.stat(full);
|
|
7618
7717
|
if (stat.isDirectory())
|
|
7619
7718
|
return find2(full);
|
|
7620
7719
|
return [];
|
|
@@ -7628,7 +7727,7 @@ var update = (program2) => program2.command(
|
|
|
7628
7727
|
).then((resp) => resp.json());
|
|
7629
7728
|
const results = /* @__PURE__ */ new Map();
|
|
7630
7729
|
const tasks = files.map(async (file) => {
|
|
7631
|
-
const data2 = await
|
|
7730
|
+
const data2 = await fs18.readFile(file).then((x) => x.toString()).then(JSON.parse);
|
|
7632
7731
|
for (const field of FIELDS) {
|
|
7633
7732
|
const deps = data2[field];
|
|
7634
7733
|
if (!deps)
|
|
@@ -7657,7 +7756,7 @@ var update = (program2) => program2.command(
|
|
|
7657
7756
|
}
|
|
7658
7757
|
}
|
|
7659
7758
|
if (results.has(file)) {
|
|
7660
|
-
await
|
|
7759
|
+
await fs18.writeFile(file, JSON.stringify(data2, null, 2));
|
|
7661
7760
|
}
|
|
7662
7761
|
});
|
|
7663
7762
|
await Promise.all(tasks);
|
|
@@ -7885,11 +7984,11 @@ dotenv2.config({
|
|
|
7885
7984
|
path: ".env.local",
|
|
7886
7985
|
override: true
|
|
7887
7986
|
});
|
|
7987
|
+
bootstrap(program);
|
|
7888
7988
|
dev(program);
|
|
7889
7989
|
deploy2(program);
|
|
7890
7990
|
build(program);
|
|
7891
7991
|
bind(program);
|
|
7892
|
-
env(program);
|
|
7893
7992
|
secrets(program);
|
|
7894
7993
|
remove2(program);
|
|
7895
7994
|
update(program);
|