sst 2.3.0 → 2.3.2

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/bootstrap.js CHANGED
@@ -208,7 +208,6 @@ async function bootstrapCDK() {
208
208
  const identity = await useSTSIdentity();
209
209
  const credentials = await useAWSCredentials();
210
210
  const { region, profile, cdk } = useProject().config;
211
- cdk || {};
212
211
  await new Promise((resolve, reject) => {
213
212
  const proc = spawn([
214
213
  "npx",
@@ -228,6 +227,9 @@ async function bootstrapCDK() {
228
227
  ...(cdk?.fileAssetsBucketName
229
228
  ? ["--toolkit-bucket-name", cdk.fileAssetsBucketName]
230
229
  : []),
230
+ ...(cdk?.customPermissionsBoundary
231
+ ? ["--custom-permissions-boundary", cdk.customPermissionsBoundary]
232
+ : []),
231
233
  ].join(" "), {
232
234
  env: {
233
235
  ...process.env,
package/cli/colors.js CHANGED
@@ -15,7 +15,7 @@ export const Colors = {
15
15
  }
16
16
  },
17
17
  hex: chalk.hex,
18
- primary: chalk.hex("#E27152"),
18
+ primary: chalk.hex("#FF9000"),
19
19
  link: chalk.cyan,
20
20
  success: chalk.green,
21
21
  danger: chalk.red,
@@ -194,6 +194,9 @@ export const bind = (program) => program
194
194
  stdio: "inherit",
195
195
  shell: true,
196
196
  });
197
+ p.on("exit", (code) => {
198
+ process.exit();
199
+ });
197
200
  }
198
201
  function areEnvsSame(envs1, envs2) {
199
202
  return (Object.keys(envs1).length === Object.keys(envs2).length &&
@@ -23,6 +23,7 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
23
23
  const fs = await import("fs/promises");
24
24
  const crypto = await import("crypto");
25
25
  const { useFunctions } = await import("../../constructs/Function.js");
26
+ const { useSites } = await import("../../constructs/SsrSite.js");
26
27
  const { usePothosBuilder } = await import("./plugins/pothos.js");
27
28
  const { useKyselyTypeGenerator } = await import("./plugins/kysely.js");
28
29
  const { useRDSWarmer } = await import("./plugins/warmer.js");
@@ -172,9 +173,29 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
172
173
  component.clear();
173
174
  component.unmount();
174
175
  printDeploymentResults(assembly, results);
175
- // Update app state
176
+ // Run after initial deploy
176
177
  if (!lastDeployed) {
177
178
  await saveAppMetadata({ mode: "dev" });
179
+ // print start frontend commands
180
+ useSites()
181
+ .all.filter(({ props }) => props.dev?.deploy !== true)
182
+ .forEach(({ type, props }) => {
183
+ const framework = type === "AstroSite"
184
+ ? "Astro"
185
+ : type === "NextjsSite"
186
+ ? "Next.js"
187
+ : type === "RemixSite"
188
+ ? "Remix"
189
+ : type === "SolidStartSite"
190
+ ? "SolidStart"
191
+ : undefined;
192
+ if (framework) {
193
+ const cdCmd = path.resolve(props.path) === process.cwd()
194
+ ? ""
195
+ : `cd ${props.path} && `;
196
+ Colors.line(Colors.danger(`➜ `), Colors.bold(`Start ${framework}:`), `${cdCmd}npm run dev`);
197
+ }
198
+ });
178
199
  }
179
200
  lastDeployed = nextChecksum;
180
201
  // Write outputs.json
@@ -226,7 +247,8 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
226
247
  return;
227
248
  if (evt.properties.app !== project.config.name)
228
249
  return;
229
- Colors.line(Colors.danger(`➜ `), "Another sst dev session has been started up for this stage. Exiting");
250
+ Colors.gap();
251
+ Colors.line(Colors.danger(`➜ `), "Another `sst dev` session has been started for this stage. Exiting...");
230
252
  process.exit(0);
231
253
  });
232
254
  });
@@ -12,6 +12,7 @@ import { IServerlessCluster } from "aws-cdk-lib/aws-rds";
12
12
  import { ISecret } from "aws-cdk-lib/aws-secretsmanager";
13
13
  import { AwsIamConfig, BaseDataSource, CfnDomainName, GraphqlApi, GraphqlApiProps, IGraphqlApi, Resolver, ResolverProps } from "aws-cdk-lib/aws-appsync";
14
14
  import { ICertificate } from "aws-cdk-lib/aws-certificatemanager";
15
+ import { IDomain } from "aws-cdk-lib/aws-opensearchservice";
15
16
  export interface AppSyncApiDomainProps extends appSyncApiDomain.CustomDomainProps {
16
17
  }
17
18
  interface AppSyncApiBaseDataSourceProps {
@@ -89,7 +90,7 @@ export interface AppSyncApiDynamoDbDataSourceProps extends AppSyncApiBaseDataSou
89
90
  * dataSources: {
90
91
  * rds: {
91
92
  * type: "rds",
92
- * rds: MyRDSCluster
93
+ * rds: myRDSCluster
93
94
  * },
94
95
  * },
95
96
  * });
@@ -116,6 +117,36 @@ export interface AppSyncApiRdsDataSourceProps extends AppSyncApiBaseDataSourcePr
116
117
  };
117
118
  };
118
119
  }
120
+ /**
121
+ * Used to define a OpenSearch data source
122
+ *
123
+ * @example
124
+ * ```js
125
+ * new AppSyncApi(stack, "AppSync", {
126
+ * dataSources: {
127
+ * search: {
128
+ * type: "open_search",
129
+ * cdk: {
130
+ * dataSource: {
131
+ * domain: myOpenSearchDomain,
132
+ * }
133
+ * }
134
+ * }
135
+ * }
136
+ * });
137
+ * ```
138
+ */
139
+ export interface AppSyncApiOpenSearchDataSourceProps extends AppSyncApiBaseDataSourceProps {
140
+ /**
141
+ * String literal to signify that this data source is an OpenSearch domain
142
+ */
143
+ type: "open_search";
144
+ cdk: {
145
+ dataSource: {
146
+ domain: IDomain;
147
+ };
148
+ };
149
+ }
119
150
  /**
120
151
  * Used to define an http data source
121
152
  *
@@ -283,7 +314,7 @@ export interface AppSyncApiProps {
283
314
  * });
284
315
  * ```
285
316
  */
286
- dataSources?: Record<string, FunctionInlineDefinition | AppSyncApiLambdaDataSourceProps | AppSyncApiDynamoDbDataSourceProps | AppSyncApiRdsDataSourceProps | AppSyncApiHttpDataSourceProps | AppSyncApiNoneDataSourceProps>;
317
+ dataSources?: Record<string, FunctionInlineDefinition | AppSyncApiLambdaDataSourceProps | AppSyncApiDynamoDbDataSourceProps | AppSyncApiRdsDataSourceProps | AppSyncApiOpenSearchDataSourceProps | AppSyncApiHttpDataSourceProps | AppSyncApiNoneDataSourceProps>;
287
318
  /**
288
319
  * The resolvers for this API. Takes an object, with the key being the type name and field name as a string and the value is either a string with the name of existing data source.
289
320
  *
@@ -411,7 +442,7 @@ export declare class AppSyncApi extends Construct implements SSTConstruct {
411
442
  * ```
412
443
  */
413
444
  addDataSources(scope: Construct, dataSources: {
414
- [key: string]: FunctionInlineDefinition | AppSyncApiLambdaDataSourceProps | AppSyncApiDynamoDbDataSourceProps | AppSyncApiRdsDataSourceProps | AppSyncApiHttpDataSourceProps | AppSyncApiNoneDataSourceProps;
445
+ [key: string]: FunctionInlineDefinition | AppSyncApiLambdaDataSourceProps | AppSyncApiDynamoDbDataSourceProps | AppSyncApiRdsDataSourceProps | AppSyncApiOpenSearchDataSourceProps | AppSyncApiHttpDataSourceProps | AppSyncApiNoneDataSourceProps;
415
446
  }): void;
416
447
  /**
417
448
  * Add resolvers the construct has been created
@@ -346,7 +346,7 @@ export class AppSyncApi extends Construct {
346
346
  description: dsValue.description,
347
347
  });
348
348
  }
349
- // Rds ds
349
+ // RDS ds
350
350
  else if (dsValue.type === "rds") {
351
351
  dataSource = this.cdk.graphqlApi.addRdsDataSource(dsKey, dsValue.rds
352
352
  ? dsValue.rds.cdk.cluster
@@ -359,6 +359,13 @@ export class AppSyncApi extends Construct {
359
359
  description: dsValue.description,
360
360
  });
361
361
  }
362
+ // OpenSearch ds
363
+ else if (dsValue.type === "open_search") {
364
+ dataSource = this.cdk.graphqlApi.addOpenSearchDataSource(dsKey, dsValue.cdk?.dataSource?.domain, {
365
+ name: dsValue.name,
366
+ description: dsValue.description,
367
+ });
368
+ }
362
369
  // Http ds
363
370
  else if (dsValue.type === "http") {
364
371
  dataSource = this.cdk.graphqlApi.addHttpDataSource(dsKey, dsValue.endpoint, {
@@ -13,6 +13,7 @@ import { Size } from "./util/size.js";
13
13
  import { Duration } from "./util/duration.js";
14
14
  import { Permissions } from "./util/permission.js";
15
15
  import { FunctionBindingProps } from "./util/functionBinding.js";
16
+ type SsrSiteType = "NextjsSite" | "RemixSite" | "AstroSite" | "SolidStartSite";
16
17
  export type SsrBuildConfig = {
17
18
  typesPath: string;
18
19
  serverBuildOutputFile: string;
@@ -174,6 +175,13 @@ export interface SsrSiteProps {
174
175
  server?: Pick<FunctionProps, "vpc" | "vpcSubnets" | "securityGroups" | "allowAllOutbound" | "allowPublicSubnet" | "architecture">;
175
176
  };
176
177
  }
178
+ type SsrSiteNormalizedProps = SsrSiteProps & {
179
+ path: Exclude<SsrSiteProps["path"], undefined>;
180
+ runtime: Exclude<SsrSiteProps["runtime"], undefined>;
181
+ timeout: Exclude<SsrSiteProps["timeout"], undefined>;
182
+ memorySize: Exclude<SsrSiteProps["memorySize"], undefined>;
183
+ waitForInvalidation: Exclude<SsrSiteProps["waitForInvalidation"], undefined>;
184
+ };
177
185
  /**
178
186
  * The `SsrSite` construct is a higher level CDK construct that makes it easy to create modern web apps with Server Side Rendering capabilities.
179
187
  * @example
@@ -187,13 +195,7 @@ export interface SsrSiteProps {
187
195
  */
188
196
  export declare class SsrSite extends Construct implements SSTConstruct {
189
197
  readonly id: string;
190
- protected props: SsrSiteProps & {
191
- path: Exclude<SsrSiteProps["path"], undefined>;
192
- runtime: Exclude<SsrSiteProps["runtime"], undefined>;
193
- timeout: Exclude<SsrSiteProps["timeout"], undefined>;
194
- memorySize: Exclude<SsrSiteProps["memorySize"], undefined>;
195
- waitForInvalidation: Exclude<SsrSiteProps["waitForInvalidation"], undefined>;
196
- };
198
+ protected props: SsrSiteNormalizedProps;
197
199
  private doNotDeploy;
198
200
  protected buildConfig: SsrBuildConfig;
199
201
  private serverLambdaForEdge?;
@@ -235,7 +237,7 @@ export declare class SsrSite extends Construct implements SSTConstruct {
235
237
  attachPermissions(permissions: Permissions): void;
236
238
  /** @internal */
237
239
  getConstructMetadata(): {
238
- type: "NextjsSite" | "RemixSite" | "AstroSite" | "SolidStartSite";
240
+ type: SsrSiteType;
239
241
  data: {
240
242
  mode: "placeholder" | "deployed";
241
243
  path: string;
@@ -280,3 +282,12 @@ export declare class SsrSite extends Construct implements SSTConstruct {
280
282
  private writeTypesFile;
281
283
  protected generateBuildId(): string;
282
284
  }
285
+ export declare const useSites: () => {
286
+ add(name: string, type: SsrSiteType, props: SsrSiteNormalizedProps): void;
287
+ readonly all: {
288
+ name: string;
289
+ type: SsrSiteType;
290
+ props: SsrSiteNormalizedProps;
291
+ }[];
292
+ };
293
+ export {};
@@ -18,6 +18,7 @@ import { S3Origin, HttpOrigin } from "aws-cdk-lib/aws-cloudfront-origins";
18
18
  import { CloudFrontTarget } from "aws-cdk-lib/aws-route53-targets";
19
19
  import { Stack } from "./Stack.js";
20
20
  import { Logger } from "../logger.js";
21
+ import { createAppContext } from "./context.js";
21
22
  import { isCDKConstruct } from "./Construct.js";
22
23
  import { Function } from "./Function.js";
23
24
  import { Secret } from "./Secret.js";
@@ -69,6 +70,7 @@ export class SsrSite extends Construct {
69
70
  this.buildConfig = this.initBuildConfig();
70
71
  this.validateSiteExists();
71
72
  this.writeTypesFile();
73
+ useSites().add(id, this.constructor.name, this.props);
72
74
  if (this.doNotDeploy) {
73
75
  // @ts-ignore
74
76
  this.bucket = this.distribution = null;
@@ -820,3 +822,14 @@ function handler(event) {
820
822
  return buildId;
821
823
  }
822
824
  }
825
+ export const useSites = createAppContext(() => {
826
+ const sites = [];
827
+ return {
828
+ add(name, type, props) {
829
+ sites.push({ name, type, props });
830
+ },
831
+ get all() {
832
+ return sites;
833
+ },
834
+ };
835
+ });
@@ -119,7 +119,7 @@ export declare class Stack extends cdk.Stack {
119
119
  * });
120
120
  * ```
121
121
  */
122
- addOutputs(outputs: Record<string, string | cdk.CfnOutputProps>): void;
122
+ addOutputs(outputs: Record<string, string | cdk.CfnOutputProps | undefined>): void;
123
123
  private createCustomResourceHandler;
124
124
  private static buildSynthesizer;
125
125
  private static checkForPropsIsConstruct;
@@ -170,11 +170,9 @@ export class Stack extends cdk.Stack {
170
170
  * ```
171
171
  */
172
172
  addOutputs(outputs) {
173
- Object.keys(outputs).forEach((key) => {
174
- const value = outputs[key];
175
- if (value === undefined) {
176
- throw new Error(`The stack output "${key}" is undefined`);
177
- }
173
+ Object.entries(outputs)
174
+ .filter((e) => e[1] !== undefined)
175
+ .forEach(([key, value]) => {
178
176
  // Note: add "SSTStackOutput" prefix to the CfnOutput id to ensure the id
179
177
  // does not thrash w/ construct ids in the stack. So users can do this:
180
178
  // ```
@@ -16,7 +16,7 @@ export function getOrCreateBucket(scope) {
16
16
  }
17
17
  // Create provider
18
18
  const provider = new lambda.Function(stack, providerId, {
19
- code: lambda.Code.fromAsset(path.join(__dirname, "../../../../support/edge-function")),
19
+ code: lambda.Code.fromAsset(path.join(__dirname, "../../../support/edge-function")),
20
20
  handler: "s3-bucket.handler",
21
21
  runtime: lambda.Runtime.NODEJS_16_X,
22
22
  timeout: cdk.Duration.minutes(15),
@@ -48,7 +48,7 @@ export function createFunction(scope, name, role, bucketName, functionParams) {
48
48
  // Create provider if not already created
49
49
  if (!provider) {
50
50
  provider = new lambda.Function(stack, providerId, {
51
- code: lambda.Code.fromAsset(path.join(__dirname, "../../../../support/edge-function")),
51
+ code: lambda.Code.fromAsset(path.join(__dirname, "../../../support/edge-function")),
52
52
  handler: "edge-lambda.handler",
53
53
  runtime: lambda.Runtime.NODEJS_16_X,
54
54
  timeout: cdk.Duration.minutes(15),
@@ -86,7 +86,7 @@ export function createVersion(scope, name, functionArn) {
86
86
  // Create provider if not already created
87
87
  if (!provider) {
88
88
  provider = new lambda.Function(stack, providerId, {
89
- code: lambda.Code.fromAsset(path.join(__dirname, "../../../../support/edge-function")),
89
+ code: lambda.Code.fromAsset(path.join(__dirname, "../../../support/edge-function")),
90
90
  handler: "edge-lambda-version.handler",
91
91
  runtime: lambda.Runtime.NODEJS_16_X,
92
92
  timeout: cdk.Duration.minutes(15),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sst",
3
- "version": "2.3.0",
3
+ "version": "2.3.2",
4
4
  "bin": {
5
5
  "sst": "cli/sst.js"
6
6
  },
package/project.d.ts CHANGED
@@ -19,6 +19,7 @@ export interface ConfigOptions {
19
19
  toolkitStackName?: string;
20
20
  qualifier?: string;
21
21
  fileAssetsBucketName?: string;
22
+ customPermissionsBoundary?: string;
22
23
  publicAccessBlockConfiguration?: boolean;
23
24
  };
24
25
  }
package/sst.mjs CHANGED
@@ -713,7 +713,7 @@ var init_colors = __esm({
713
713
  }
714
714
  },
715
715
  hex: chalk.hex,
716
- primary: chalk.hex("#E27152"),
716
+ primary: chalk.hex("#FF9000"),
717
717
  link: chalk.cyan,
718
718
  success: chalk.green,
719
719
  danger: chalk.red,
@@ -1987,6 +1987,7 @@ async function monitor(stack) {
1987
1987
  errors: {}
1988
1988
  };
1989
1989
  }
1990
+ throw ex;
1990
1991
  }
1991
1992
  await new Promise((resolve) => setTimeout(resolve, 1e3));
1992
1993
  }
@@ -5270,7 +5271,6 @@ async function bootstrapCDK() {
5270
5271
  const identity = await useSTSIdentity();
5271
5272
  const credentials = await useAWSCredentials();
5272
5273
  const { region, profile, cdk } = useProject().config;
5273
- cdk || {};
5274
5274
  await new Promise((resolve, reject) => {
5275
5275
  const proc = spawn6(
5276
5276
  [
@@ -5282,7 +5282,8 @@ async function bootstrapCDK() {
5282
5282
  ...cdk?.publicAccessBlockConfiguration === false ? ["--public-access-block-configuration", "false"] : cdk?.publicAccessBlockConfiguration === true ? ["--public-access-block-configuration", "false"] : [],
5283
5283
  ...cdk?.toolkitStackName ? ["--toolkit-stack-name", cdk.toolkitStackName] : [],
5284
5284
  ...cdk?.qualifier ? ["--qualifier", cdk.qualifier] : [],
5285
- ...cdk?.fileAssetsBucketName ? ["--toolkit-bucket-name", cdk.fileAssetsBucketName] : []
5285
+ ...cdk?.fileAssetsBucketName ? ["--toolkit-bucket-name", cdk.fileAssetsBucketName] : [],
5286
+ ...cdk?.customPermissionsBoundary ? ["--custom-permissions-boundary", cdk.customPermissionsBoundary] : []
5286
5287
  ].join(" "),
5287
5288
  {
5288
5289
  env: {
@@ -6775,6 +6776,7 @@ var dev = (program2) => program2.command(
6775
6776
  const fs18 = await import("fs/promises");
6776
6777
  const crypto2 = await import("crypto");
6777
6778
  const { useFunctions: useFunctions3 } = await import("../src/constructs/Function.js");
6779
+ const { useSites } = await import("../src/constructs/SsrSite.js");
6778
6780
  const { usePothosBuilder: usePothosBuilder2 } = await Promise.resolve().then(() => (init_pothos2(), pothos_exports2));
6779
6781
  const { useKyselyTypeGenerator: useKyselyTypeGenerator2 } = await Promise.resolve().then(() => (init_kysely(), kysely_exports));
6780
6782
  const { useRDSWarmer: useRDSWarmer2 } = await Promise.resolve().then(() => (init_warmer(), warmer_exports));
@@ -6944,6 +6946,17 @@ var dev = (program2) => program2.command(
6944
6946
  printDeploymentResults2(assembly, results);
6945
6947
  if (!lastDeployed) {
6946
6948
  await saveAppMetadata2({ mode: "dev" });
6949
+ useSites().all.filter(({ props }) => props.dev?.deploy !== true).forEach(({ type, props }) => {
6950
+ const framework = type === "AstroSite" ? "Astro" : type === "NextjsSite" ? "Next.js" : type === "RemixSite" ? "Remix" : type === "SolidStartSite" ? "SolidStart" : void 0;
6951
+ if (framework) {
6952
+ const cdCmd = path20.resolve(props.path) === process.cwd() ? "" : `cd ${props.path} && `;
6953
+ Colors2.line(
6954
+ Colors2.danger(`\u279C `),
6955
+ Colors2.bold(`Start ${framework}:`),
6956
+ `${cdCmd}npm run dev`
6957
+ );
6958
+ }
6959
+ });
6947
6960
  }
6948
6961
  lastDeployed = nextChecksum;
6949
6962
  fs18.writeFile(
@@ -7002,9 +7015,10 @@ var dev = (program2) => program2.command(
7002
7015
  return;
7003
7016
  if (evt.properties.app !== project.config.name)
7004
7017
  return;
7018
+ Colors2.gap();
7005
7019
  Colors2.line(
7006
7020
  Colors2.danger(`\u279C `),
7007
- "Another sst dev session has been started up for this stage. Exiting"
7021
+ "Another `sst dev` session has been started for this stage. Exiting..."
7008
7022
  );
7009
7023
  process.exit(0);
7010
7024
  });
@@ -7281,6 +7295,9 @@ var bind = (program2) => program2.command(
7281
7295
  stdio: "inherit",
7282
7296
  shell: true
7283
7297
  });
7298
+ p.on("exit", (code) => {
7299
+ process.exit();
7300
+ });
7284
7301
  }
7285
7302
  function areEnvsSame(envs1, envs2) {
7286
7303
  return Object.keys(envs1).length === Object.keys(envs2).length && Object.keys(envs1).every((key) => envs1[key] === envs2[key]);
package/stacks/monitor.js CHANGED
@@ -137,6 +137,7 @@ export async function monitor(stack) {
137
137
  errors: {},
138
138
  };
139
139
  }
140
+ throw ex;
140
141
  }
141
142
  await new Promise((resolve) => setTimeout(resolve, 1000));
142
143
  }