sst 2.7.1 → 2.8.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.
Files changed (51) hide show
  1. package/cli/ci-info.d.ts +4 -0
  2. package/cli/ci-info.js +8 -0
  3. package/cli/commands/bind.js +1 -0
  4. package/cli/commands/deploy.js +2 -1
  5. package/cli/commands/dev.js +9 -3
  6. package/cli/commands/diff.js +20 -5
  7. package/cli/commands/update.js +1 -0
  8. package/cli/telemetry/environment.js +4 -4
  9. package/cli/ui/functions.js +3 -3
  10. package/config.js +2 -1
  11. package/constructs/AppSyncApi.d.ts +1 -2
  12. package/constructs/AppSyncApi.js +5 -15
  13. package/constructs/AstroSite.js +4 -8
  14. package/constructs/EdgeFunction.js +6 -6
  15. package/constructs/Function.d.ts +1 -1
  16. package/constructs/Function.js +10 -2
  17. package/constructs/RemixSite.js +4 -8
  18. package/constructs/SolidStartSite.js +4 -9
  19. package/constructs/SsrFunction.d.ts +10 -2
  20. package/constructs/SsrFunction.js +99 -32
  21. package/constructs/SsrSite.d.ts +5 -3
  22. package/constructs/SsrSite.js +23 -11
  23. package/constructs/SvelteKitSite.d.ts +27 -0
  24. package/constructs/SvelteKitSite.js +101 -0
  25. package/constructs/SvelteKitSite.tsdoc.d.ts +2 -0
  26. package/constructs/SvelteKitSite.tsdoc.js +2 -0
  27. package/constructs/deprecated/NextjsSite.js +1 -1
  28. package/constructs/deprecated/cross-region-helper.js +3 -3
  29. package/constructs/index.d.ts +1 -0
  30. package/constructs/index.js +1 -0
  31. package/constructs/static-file-list.d.ts +1 -0
  32. package/constructs/static-file-list.js +51 -0
  33. package/constructs/util/appSyncApiDomain.d.ts +14 -2
  34. package/constructs/util/appSyncApiDomain.js +56 -11
  35. package/node/config/index.js +0 -9
  36. package/node/site/index.d.ts +6 -6
  37. package/node/site/index.js +5 -5
  38. package/node/util/index.js +11 -0
  39. package/package.json +2 -2
  40. package/runtime/handlers.js +7 -0
  41. package/runtime/workers.js +4 -0
  42. package/sst.mjs +70 -16
  43. package/support/base-site-archiver.mjs +18 -18
  44. package/support/bootstrap-metadata-function/index.mjs +1345 -1409
  45. package/support/bridge/bridge.mjs +46 -35
  46. package/support/custom-resources/index.mjs +6468 -6532
  47. package/support/job-invoker/index.mjs +90 -907
  48. package/support/rds-migrator/index.mjs +16 -16
  49. package/support/script-function/index.mjs +90 -907
  50. package/support/ssr-site-function-archiver.mjs +9 -9
  51. /package/support/{sls-nextjs-site-function-stub → ssr-site-function-stub}/index.js +0 -0
@@ -1,5 +1,6 @@
1
- import { Token, Lazy } from "aws-cdk-lib";
1
+ import { Token } from "aws-cdk-lib";
2
2
  import * as route53 from "aws-cdk-lib/aws-route53";
3
+ import * as route53Targets from "aws-cdk-lib/aws-route53-targets";
3
4
  import * as acm from "aws-cdk-lib/aws-certificatemanager";
4
5
  export function buildCustomDomainData(scope, customDomain) {
5
6
  if (customDomain === undefined) {
@@ -18,6 +19,14 @@ export function buildCustomDomainData(scope, customDomain) {
18
19
  // customDomain.domainName not exists
19
20
  throw new Error(`Missing "domainName" in sst.AppSyncApi's customDomain setting`);
20
21
  }
22
+ export function cleanup(scope, domainData) {
23
+ const cfnDomainName = getCfnDomainName(scope);
24
+ const cfnDomainNameApiAssociation = getCfnDomainNameApiAssociation(scope);
25
+ if (domainData.hostedZone) {
26
+ createRecords(scope, domainData.domainName, domainData.hostedZone, domainData.recordType, cfnDomainName);
27
+ }
28
+ fixDomainResourceDependencies(cfnDomainName, cfnDomainNameApiAssociation);
29
+ }
21
30
  function buildDataForStringInput(scope, customDomain) {
22
31
  // validate: customDomain is a TOKEN string
23
32
  // ie. imported SSM value: ssm.StringParameter.valueForStringParameter()
@@ -29,10 +38,10 @@ function buildDataForStringInput(scope, customDomain) {
29
38
  const hostedZoneDomain = domainName.split(".").slice(1).join(".");
30
39
  const hostedZone = lookupHostedZone(scope, hostedZoneDomain);
31
40
  const certificate = createCertificate(scope, domainName, hostedZone);
32
- createRecord(scope, hostedZone, domainName);
33
41
  return {
34
42
  certificate,
35
43
  domainName,
44
+ hostedZone,
36
45
  };
37
46
  }
38
47
  function buildDataForInternalDomainInput(scope, customDomain) {
@@ -69,10 +78,11 @@ function buildDataForInternalDomainInput(scope, customDomain) {
69
78
  const certificate = customDomain.cdk?.certificate
70
79
  ? customDomain.cdk.certificate
71
80
  : createCertificate(scope, domainName, hostedZone);
72
- createRecord(scope, hostedZone, domainName);
73
81
  return {
74
82
  certificate,
75
83
  domainName,
84
+ hostedZone,
85
+ recordType: customDomain.recordType,
76
86
  };
77
87
  }
78
88
  function buildDataForExternalDomainInput(scope, customDomain) {
@@ -103,25 +113,60 @@ function createCertificate(scope, domainName, hostedZone) {
103
113
  validation: acm.CertificateValidation.fromDns(hostedZone),
104
114
  });
105
115
  }
106
- function createRecord(scope, hostedZone, domainName) {
116
+ function createRecords(scope, domainName, hostedZone, recordType, cfnDomainName) {
107
117
  // create DNS record
108
- const record = new route53.CnameRecord(scope, "CnameRecord", {
118
+ const aRecordProps = {
109
119
  recordName: domainName,
110
120
  zone: hostedZone,
111
- domainName: Lazy.string({
112
- produce() {
113
- return scope._cfnDomainName.attrAppSyncDomainName;
121
+ target: route53.RecordTarget.fromAlias({
122
+ bind() {
123
+ return {
124
+ hostedZoneId: route53Targets.CloudFrontTarget.CLOUDFRONT_ZONE_ID,
125
+ dnsName: cfnDomainName.attrAppSyncDomainName,
126
+ };
114
127
  },
115
128
  }),
116
- });
129
+ };
130
+ const records = (recordType || "CNAME") === "CNAME"
131
+ ? [
132
+ new route53.CnameRecord(scope, "CnameRecord", {
133
+ recordName: domainName,
134
+ zone: hostedZone,
135
+ domainName: cfnDomainName.attrAppSyncDomainName,
136
+ }),
137
+ ]
138
+ : [
139
+ new route53.ARecord(scope, "AliasRecord", aRecordProps),
140
+ new route53.AaaaRecord(scope, "AliasRecordAAAA", aRecordProps),
141
+ ];
117
142
  // note: If domainName is a TOKEN string ie. ${TOKEN..}, the route53.ARecord
118
143
  // construct will append ".${hostedZoneName}" to the end of the domain.
119
144
  // This is because the construct tries to check if the record name
120
145
  // ends with the domain name. If not, it will append the domain name.
121
146
  // So, we need remove this behavior.
122
147
  if (Token.isUnresolved(domainName)) {
123
- const cfnRecord = record.node.defaultChild;
124
- cfnRecord.name = domainName;
148
+ records.forEach((record) => {
149
+ const cfnRecord = record.node.defaultChild;
150
+ cfnRecord.name = domainName;
151
+ });
152
+ }
153
+ }
154
+ function getCfnDomainName(scope) {
155
+ return scope.cdk.graphqlApi.node.children.find((child) => child.cfnResourceType === "AWS::AppSync::DomainName");
156
+ }
157
+ function getCfnDomainNameApiAssociation(scope) {
158
+ return scope.cdk.graphqlApi.node.children.find((child) => child.cfnResourceType ===
159
+ "AWS::AppSync::DomainNameApiAssociation");
160
+ }
161
+ function fixDomainResourceDependencies(cfnDomainName, cfnDomainNameApiAssociation) {
162
+ // note: As of CDK 2.20.0, the "AWS::AppSync::DomainNameApiAssociation" resource
163
+ // is not dependent on the "AWS::AppSync::DomainName" resource. This leads
164
+ // CloudFormation deploy error if DomainNameApiAssociation is created before
165
+ // DomainName is created.
166
+ // https://github.com/aws/aws-cdk/issues/18395#issuecomment-1099455502
167
+ // To workaround this issue, we need to add a dependency manually.
168
+ if (cfnDomainName && cfnDomainNameApiAssociation) {
169
+ cfnDomainNameApiAssociation.node.addDependency(cfnDomainName);
125
170
  }
126
171
  }
127
172
  function assertDomainNameIsLowerCase(domainName) {
@@ -8,15 +8,6 @@ Object.assign(Config, metadata, parameters, secrets);
8
8
  // Functions
9
9
  ///////////////
10
10
  function parseMetadataEnvironment() {
11
- // If SST_APP and SST_STAGE are not set, it is likely the
12
- // user is using an older version of SST.
13
- const errorMsg = "This is usually the case when you are using an older version of SST. Please update SST to the latest version to use the SST Config feature.";
14
- if (!process.env.SST_APP) {
15
- throw new Error(`Cannot find the SST_APP environment variable. ${errorMsg}`);
16
- }
17
- if (!process.env.SST_STAGE) {
18
- throw new Error(`Cannot find the SST_STAGE environment variable. ${errorMsg}`);
19
- }
20
11
  return {
21
12
  APP: process.env.SST_APP,
22
13
  STAGE: process.env.SST_STAGE,
@@ -1,18 +1,18 @@
1
1
  export interface StaticSiteResources {
2
2
  }
3
- export interface ReactStaticSiteResources {
4
- }
5
- export interface ViteStaticSiteResources {
6
- }
7
3
  export interface NextjsSiteResources {
8
4
  }
5
+ export interface AstroSiteResources {
6
+ }
9
7
  export interface RemixSiteResources {
10
8
  }
11
9
  export interface SolidStartSiteResources {
12
10
  }
11
+ export interface SvelteKitSiteResources {
12
+ }
13
13
  export declare const StaticSite: StaticSiteResources;
14
- export declare const ReactStaticSite: ReactStaticSiteResources;
15
- export declare const ViteStaticSite: ViteStaticSiteResources;
14
+ export declare const AstroSite: AstroSiteResources;
16
15
  export declare const RemixSite: RemixSiteResources;
17
16
  export declare const NextjsSite: NextjsSiteResources;
18
17
  export declare const SolidStartSite: SolidStartSiteResources;
18
+ export declare const SvelteKitSite: SvelteKitSiteResources;
@@ -1,12 +1,9 @@
1
1
  import { createProxy } from "../util/index.js";
2
2
  export const StaticSite =
3
3
  /* @__PURE__ */ createProxy("StaticSite");
4
- export const ReactStaticSite =
4
+ export const AstroSite =
5
5
  /* @__PURE__ */
6
- createProxy("ReactStaticSite");
7
- export const ViteStaticSite =
8
- /* @__PURE__ */
9
- createProxy("ViteStaticSite");
6
+ createProxy("AstroSite");
10
7
  export const RemixSite =
11
8
  /* @__PURE__ */
12
9
  createProxy("RemixSite");
@@ -16,3 +13,6 @@ createProxy("NextjsSite");
16
13
  export const SolidStartSite =
17
14
  /* @__PURE__ */
18
15
  createProxy("SolidStartSite");
16
+ export const SvelteKitSite =
17
+ /* @__PURE__ */
18
+ createProxy("SvelteKitSite");
@@ -17,6 +17,17 @@ export function createProxy(constructName) {
17
17
  const result = new Proxy({}, {
18
18
  get(target, prop) {
19
19
  if (typeof prop === "string") {
20
+ // If SST_APP and SST_STAGE are not set, it is likely the
21
+ // user is using an older version of SST.
22
+ // Note: cannot run this check at the top level b/c SvelteKit
23
+ // run code analysis after build. The code analysis runs
24
+ // the top level code, and would fail b/c "SST_APP" and
25
+ // "SST_STAGE" are undefined at build time.
26
+ for (const builtInEnv of ["SST_APP", "SST_STAGE"]) {
27
+ if (!process.env[builtInEnv]) {
28
+ throw new Error(`Cannot find the ${builtInEnv} environment variable. This is usually the case when you are using an older version of SST. Please update SST to the latest version to use the SST Config feature.`);
29
+ }
30
+ }
20
31
  // normalize prop to convert kebab cases like `my-table` to `my_table`
21
32
  const normProp = normalizeId(prop);
22
33
  if (!(normProp in target)) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "sideEffects": false,
3
3
  "name": "sst",
4
- "version": "2.7.1",
4
+ "version": "2.8.0",
5
5
  "bin": {
6
6
  "sst": "cli/sst.js"
7
7
  },
@@ -10,7 +10,7 @@
10
10
  "license": "MIT",
11
11
  "repository": {
12
12
  "type": "git",
13
- "url": "git+https://github.com/estyrke/serverless-stack.git",
13
+ "url": "git+https://github.com/serverless-stack/sst.git",
14
14
  "directory": "packages/cli"
15
15
  },
16
16
  "exports": {
@@ -25,6 +25,11 @@ export const useRuntimeHandlers = Context.memo(() => {
25
25
  async build(functionID, mode) {
26
26
  async function task() {
27
27
  const func = useFunctions().fromID(functionID);
28
+ if (!func)
29
+ return {
30
+ type: "error",
31
+ errors: [`Function with ID "${functionID}" not found`],
32
+ };
28
33
  const handler = result.for(func.runtime);
29
34
  const out = path.join(project.paths.artifacts, functionID);
30
35
  await fs.rm(out, { recursive: true, force: true });
@@ -100,6 +105,8 @@ export const useFunctionBuilder = Context.memo(() => {
100
105
  },
101
106
  build: async (functionID) => {
102
107
  const result = await handlers.build(functionID, "start");
108
+ if (!result)
109
+ return;
103
110
  if (result.type === "error")
104
111
  return;
105
112
  artifacts.set(functionID, result);
@@ -13,6 +13,8 @@ export const useRuntimeWorkers = Context.memo(async () => {
13
13
  for (const [_, worker] of workers) {
14
14
  if (worker.functionID === evt.properties.functionID) {
15
15
  const props = useFunctions().fromID(worker.functionID);
16
+ if (!props)
17
+ return;
16
18
  const handler = handlers.for(props.runtime);
17
19
  await handler?.stopWorker(worker.workerID);
18
20
  bus.publish("worker.stopped", worker);
@@ -30,6 +32,8 @@ export const useRuntimeWorkers = Context.memo(async () => {
30
32
  if (worker)
31
33
  return;
32
34
  const props = useFunctions().fromID(evt.properties.functionID);
35
+ if (!props)
36
+ return;
33
37
  const handler = handlers.for(props.runtime);
34
38
  if (!handler)
35
39
  return;
package/sst.mjs CHANGED
@@ -576,15 +576,33 @@ var init_project_id = __esm({
576
576
  }
577
577
  });
578
578
 
579
+ // src/cli/ci-info.ts
580
+ var ci_info_exports = {};
581
+ __export(ci_info_exports, {
582
+ getCiInfo: () => getCiInfo
583
+ });
584
+ import ciInfo from "ci-info";
585
+ function getCiInfo() {
586
+ const isSeed = !!process.env.SEED_APP_NAME;
587
+ return {
588
+ isCI: ciInfo.isCI || isSeed,
589
+ name: (isSeed ? "Seed" : ciInfo.name) || null
590
+ };
591
+ }
592
+ var init_ci_info = __esm({
593
+ "src/cli/ci-info.ts"() {
594
+ "use strict";
595
+ }
596
+ });
597
+
579
598
  // src/cli/telemetry/environment.ts
580
599
  import os2 from "os";
581
- import ciInfo from "ci-info";
582
600
  function getEnvironmentData() {
583
601
  if (data) {
584
602
  return data;
585
603
  }
586
604
  const cpus = os2.cpus() || [];
587
- const isSeed = !!process.env.SEED_APP_NAME;
605
+ const ciInfo2 = getCiInfo();
588
606
  data = {
589
607
  systemPlatform: os2.platform(),
590
608
  systemRelease: os2.release(),
@@ -593,8 +611,8 @@ function getEnvironmentData() {
593
611
  cpuModel: cpus.length ? cpus[0].model : null,
594
612
  cpuSpeed: cpus.length ? cpus[0].speed : null,
595
613
  memoryInMb: Math.trunc(os2.totalmem() / Math.pow(1024, 2)),
596
- isCI: ciInfo.isCI || isSeed,
597
- ciName: (isSeed ? "Seed" : ciInfo.name) || null,
614
+ isCI: ciInfo2.isCI,
615
+ ciName: ciInfo2.name,
598
616
  sstVersion: useProject().version
599
617
  };
600
618
  return data;
@@ -603,6 +621,7 @@ var data;
603
621
  var init_environment = __esm({
604
622
  "src/cli/telemetry/environment.ts"() {
605
623
  "use strict";
624
+ init_ci_info();
606
625
  init_project();
607
626
  }
608
627
  });
@@ -3569,6 +3588,11 @@ var init_handlers = __esm({
3569
3588
  async build(functionID, mode) {
3570
3589
  async function task() {
3571
3590
  const func = useFunctions().fromID(functionID);
3591
+ if (!func)
3592
+ return {
3593
+ type: "error",
3594
+ errors: [`Function with ID "${functionID}" not found`]
3595
+ };
3572
3596
  const handler = result.for(func.runtime);
3573
3597
  const out = path7.join(project.paths.artifacts, functionID);
3574
3598
  await fs7.rm(out, { recursive: true, force: true });
@@ -3647,6 +3671,8 @@ var init_handlers = __esm({
3647
3671
  },
3648
3672
  build: async (functionID) => {
3649
3673
  const result2 = await handlers.build(functionID, "start");
3674
+ if (!result2)
3675
+ return;
3650
3676
  if (result2.type === "error")
3651
3677
  return;
3652
3678
  artifacts.set(functionID, result2);
@@ -3896,6 +3922,8 @@ var init_workers = __esm({
3896
3922
  for (const [_, worker] of workers) {
3897
3923
  if (worker.functionID === evt.properties.functionID) {
3898
3924
  const props = useFunctions2().fromID(worker.functionID);
3925
+ if (!props)
3926
+ return;
3899
3927
  const handler = handlers.for(props.runtime);
3900
3928
  await handler?.stopWorker(worker.workerID);
3901
3929
  bus.publish("worker.stopped", worker);
@@ -3913,6 +3941,8 @@ var init_workers = __esm({
3913
3941
  if (worker)
3914
3942
  return;
3915
3943
  const props = useFunctions2().fromID(evt.properties.functionID);
3944
+ if (!props)
3945
+ return;
3916
3946
  const handler = handlers.for(props.runtime);
3917
3947
  if (!handler)
3918
3948
  return;
@@ -6701,7 +6731,7 @@ var init_config = __esm({
6701
6731
  async function restart(keys) {
6702
6732
  const metadata3 = await stacks_exports.metadata();
6703
6733
  const siteData = Object.values(metadata3).flat().filter(
6704
- (c) => c.type === "AstroSite" || c.type === "NextjsSite" || c.type === "RemixSite" || c.type === "SolidStartSite"
6734
+ (c) => c.type === "AstroSite" || c.type === "NextjsSite" || c.type === "RemixSite" || c.type === "SolidStartSite" || c.type === "SvelteKitSite"
6705
6735
  ).filter((c) => keys.some((key) => c.data.secrets.includes(key)));
6706
6736
  const siteDataPlaceholder = siteData.filter(
6707
6737
  (c) => c.data.mode === "placeholder"
@@ -6841,6 +6871,7 @@ var dev = (program2) => program2.command(
6841
6871
  const { useMetadata: useMetadata2 } = await Promise.resolve().then(() => (init_metadata(), metadata_exports));
6842
6872
  const { useIOT: useIOT2 } = await Promise.resolve().then(() => (init_iot(), iot_exports));
6843
6873
  const { clear: clear2 } = await Promise.resolve().then(() => (init_terminal(), terminal_exports));
6874
+ const { getCiInfo: getCiInfo2 } = await Promise.resolve().then(() => (init_ci_info(), ci_info_exports));
6844
6875
  if (args._[0] === "start") {
6845
6876
  console.log(
6846
6877
  yellow(
@@ -6893,12 +6924,16 @@ var dev = (program2) => program2.command(
6893
6924
  });
6894
6925
  bus.subscribe("function.build.success", async (evt) => {
6895
6926
  const info = useFunctions3().fromID(evt.properties.functionID);
6927
+ if (!info)
6928
+ return;
6896
6929
  if (info.enableLiveDev === false)
6897
6930
  return;
6898
6931
  Colors2.line(Colors2.dim(Colors2.prefix, "Built", info.handler));
6899
6932
  });
6900
6933
  bus.subscribe("function.build.failed", async (evt) => {
6901
6934
  const info = useFunctions3().fromID(evt.properties.functionID);
6935
+ if (!info)
6936
+ return;
6902
6937
  if (info.enableLiveDev === false)
6903
6938
  return;
6904
6939
  Colors2.gap();
@@ -6938,7 +6973,6 @@ var dev = (program2) => program2.command(
6938
6973
  const useStackBuilder = Context2.memo(async () => {
6939
6974
  const watcher = useWatcher2();
6940
6975
  const project = useProject2();
6941
- const bus = useBus2();
6942
6976
  let lastDeployed;
6943
6977
  let isWorking = false;
6944
6978
  let isDirty = false;
@@ -7004,7 +7038,7 @@ var dev = (program2) => program2.command(
7004
7038
  if (!lastDeployed) {
7005
7039
  await saveAppMetadata2({ mode: "dev" });
7006
7040
  useSites().all.filter(({ props }) => props.dev?.deploy !== true).forEach(({ type, props }) => {
7007
- const framework = type === "AstroSite" ? "Astro" : type === "NextjsSite" ? "Next.js" : type === "RemixSite" ? "Remix" : type === "SolidStartSite" ? "SolidStart" : void 0;
7041
+ const framework = type === "AstroSite" ? "Astro" : type === "NextjsSite" ? "Next.js" : type === "RemixSite" ? "Remix" : type === "SolidStartSite" ? "SolidStart" : type === "SvelteKitSite" ? "SvelteKit" : void 0;
7008
7042
  if (framework) {
7009
7043
  const cdCmd = path20.resolve(props.path) === process.cwd() ? "" : `cd ${props.path} && `;
7010
7044
  Colors2.line(
@@ -7108,7 +7142,7 @@ Are you sure you want to run this stage in dev mode? [y/N] `,
7108
7142
  );
7109
7143
  });
7110
7144
  }
7111
- if (appMetadata && appMetadata.mode !== "dev") {
7145
+ if (!getCiInfo2().isCI && appMetadata && appMetadata.mode !== "dev") {
7112
7146
  if (!await promptChangeMode()) {
7113
7147
  process.exit(0);
7114
7148
  }
@@ -7317,6 +7351,7 @@ var bind = (program2) => program2.command(
7317
7351
  "AstroSite",
7318
7352
  "RemixSite",
7319
7353
  "SolidStartSite",
7354
+ "SvelteKitSite",
7320
7355
  "SlsNextjsSite"
7321
7356
  ].includes(c.type)
7322
7357
  ).find((c) => {
@@ -7469,6 +7504,7 @@ var deploy2 = (program2) => program2.command(
7469
7504
  const { dim: dim2, blue: blue4, bold: bold2 } = await import("colorette");
7470
7505
  const { useProject: useProject2 } = await Promise.resolve().then(() => (init_project(), project_exports));
7471
7506
  const { loadAssembly: loadAssembly2, useAppMetadata: useAppMetadata2, saveAppMetadata: saveAppMetadata2, Stacks } = await Promise.resolve().then(() => (init_stacks(), stacks_exports));
7507
+ const { getCiInfo: getCiInfo2 } = await Promise.resolve().then(() => (init_ci_info(), ci_info_exports));
7472
7508
  const { render } = await import("ink");
7473
7509
  const { DeploymentUI: DeploymentUI2 } = await Promise.resolve().then(() => (init_deploy2(), deploy_exports));
7474
7510
  const { mapValues } = await import("remeda");
@@ -7496,7 +7532,7 @@ Are you sure you want to deploy to this stage? (y/N) `,
7496
7532
  );
7497
7533
  });
7498
7534
  }
7499
- if (appMetadata && appMetadata.mode !== "deploy") {
7535
+ if (!getCiInfo2().isCI && appMetadata && appMetadata.mode !== "deploy") {
7500
7536
  if (!await promptChangeMode()) {
7501
7537
  process.exit(0);
7502
7538
  }
@@ -7879,6 +7915,7 @@ var PACKAGE_MATCH = [
7879
7915
  "aws-cdk",
7880
7916
  "@aws-cdk",
7881
7917
  "constructs",
7918
+ "svelte-kit-sst",
7882
7919
  "solid-start-sst"
7883
7920
  ];
7884
7921
  var FIELDS = ["dependencies", "devDependencies"];
@@ -8066,7 +8103,6 @@ var diff2 = (program2) => program2.command(
8066
8103
  const { useAWSClient: useAWSClient2 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
8067
8104
  const { CloudFormationClient: CloudFormationClient4, GetTemplateCommand } = await import("@aws-sdk/client-cloudformation");
8068
8105
  const { createSpinner: createSpinner2 } = await Promise.resolve().then(() => (init_spinner(), spinner_exports));
8069
- const { green } = await import("colorette");
8070
8106
  const { Colors: Colors2 } = await Promise.resolve().then(() => (init_colors(), colors_exports));
8071
8107
  const project = useProject2();
8072
8108
  const assembly = await Stacks.synth({
@@ -8080,12 +8116,17 @@ var diff2 = (program2) => program2.command(
8080
8116
  const spinner = createSpinner2(
8081
8117
  `${stack.stackName}: Checking for changes...`
8082
8118
  );
8083
- const response = await cfn.send(
8084
- new GetTemplateCommand({
8085
- StackName: stack.stackName
8086
- })
8087
- );
8088
- const oldTemplate = JSON.parse(response.TemplateBody);
8119
+ const oldTemplate = await getTemplate(stack.stackName);
8120
+ if (!oldTemplate) {
8121
+ spinner.clear();
8122
+ Colors2.line(
8123
+ `\u279C ${Colors2.dim.bold(
8124
+ stackNameToId2(stack.stackName) + ":"
8125
+ )} New stack`
8126
+ );
8127
+ Colors2.gap();
8128
+ continue;
8129
+ }
8089
8130
  const { count, diff: diff3 } = await Stacks.diff(stack, oldTemplate);
8090
8131
  spinner.clear();
8091
8132
  if (count === 0) {
@@ -8128,6 +8169,19 @@ var diff2 = (program2) => program2.command(
8128
8169
  );
8129
8170
  }
8130
8171
  process.exit(0);
8172
+ async function getTemplate(stackName) {
8173
+ try {
8174
+ const response = await cfn.send(
8175
+ new GetTemplateCommand({ StackName: stackName })
8176
+ );
8177
+ return JSON.parse(response.TemplateBody);
8178
+ } catch (e) {
8179
+ if (e.name === "ValidationError" && e.message.includes("does not exist")) {
8180
+ return;
8181
+ }
8182
+ throw e;
8183
+ }
8184
+ }
8131
8185
  }
8132
8186
  );
8133
8187