sst 2.3.1 → 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
  // ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sst",
3
- "version": "2.3.1",
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,
@@ -5271,7 +5271,6 @@ async function bootstrapCDK() {
5271
5271
  const identity = await useSTSIdentity();
5272
5272
  const credentials = await useAWSCredentials();
5273
5273
  const { region, profile, cdk } = useProject().config;
5274
- cdk || {};
5275
5274
  await new Promise((resolve, reject) => {
5276
5275
  const proc = spawn6(
5277
5276
  [
@@ -5283,7 +5282,8 @@ async function bootstrapCDK() {
5283
5282
  ...cdk?.publicAccessBlockConfiguration === false ? ["--public-access-block-configuration", "false"] : cdk?.publicAccessBlockConfiguration === true ? ["--public-access-block-configuration", "false"] : [],
5284
5283
  ...cdk?.toolkitStackName ? ["--toolkit-stack-name", cdk.toolkitStackName] : [],
5285
5284
  ...cdk?.qualifier ? ["--qualifier", cdk.qualifier] : [],
5286
- ...cdk?.fileAssetsBucketName ? ["--toolkit-bucket-name", cdk.fileAssetsBucketName] : []
5285
+ ...cdk?.fileAssetsBucketName ? ["--toolkit-bucket-name", cdk.fileAssetsBucketName] : [],
5286
+ ...cdk?.customPermissionsBoundary ? ["--custom-permissions-boundary", cdk.customPermissionsBoundary] : []
5287
5287
  ].join(" "),
5288
5288
  {
5289
5289
  env: {
@@ -6776,6 +6776,7 @@ var dev = (program2) => program2.command(
6776
6776
  const fs18 = await import("fs/promises");
6777
6777
  const crypto2 = await import("crypto");
6778
6778
  const { useFunctions: useFunctions3 } = await import("../src/constructs/Function.js");
6779
+ const { useSites } = await import("../src/constructs/SsrSite.js");
6779
6780
  const { usePothosBuilder: usePothosBuilder2 } = await Promise.resolve().then(() => (init_pothos2(), pothos_exports2));
6780
6781
  const { useKyselyTypeGenerator: useKyselyTypeGenerator2 } = await Promise.resolve().then(() => (init_kysely(), kysely_exports));
6781
6782
  const { useRDSWarmer: useRDSWarmer2 } = await Promise.resolve().then(() => (init_warmer(), warmer_exports));
@@ -6945,6 +6946,17 @@ var dev = (program2) => program2.command(
6945
6946
  printDeploymentResults2(assembly, results);
6946
6947
  if (!lastDeployed) {
6947
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
+ });
6948
6960
  }
6949
6961
  lastDeployed = nextChecksum;
6950
6962
  fs18.writeFile(
@@ -7003,9 +7015,10 @@ var dev = (program2) => program2.command(
7003
7015
  return;
7004
7016
  if (evt.properties.app !== project.config.name)
7005
7017
  return;
7018
+ Colors2.gap();
7006
7019
  Colors2.line(
7007
7020
  Colors2.danger(`\u279C `),
7008
- "Another sst dev session has been started up for this stage. Exiting"
7021
+ "Another `sst dev` session has been started for this stage. Exiting..."
7009
7022
  );
7010
7023
  process.exit(0);
7011
7024
  });
@@ -7282,6 +7295,9 @@ var bind = (program2) => program2.command(
7282
7295
  stdio: "inherit",
7283
7296
  shell: true
7284
7297
  });
7298
+ p.on("exit", (code) => {
7299
+ process.exit();
7300
+ });
7285
7301
  }
7286
7302
  function areEnvsSame(envs1, envs2) {
7287
7303
  return Object.keys(envs1).length === Object.keys(envs2).length && Object.keys(envs1).every((key) => envs1[key] === envs2[key]);