sst 2.10.4 → 2.11.1

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/sst.mjs CHANGED
@@ -7168,14 +7168,22 @@ Are you sure you want to run this stage in dev mode? [y/N] `,
7168
7168
  // src/cli/commands/bind.ts
7169
7169
  init_error();
7170
7170
  import path18 from "path";
7171
- var OutdatedMetadataError = class extends Error {
7171
+ var MetadataNotFoundError = class extends Error {
7172
+ };
7173
+ var MetadataOutdatedError = class extends Error {
7172
7174
  };
7173
7175
  var bind = (program2) => program2.command(
7174
7176
  ["bind <command..>", "env <command..>"],
7175
7177
  "Bind your app's resources to a command",
7176
- (yargs2) => yargs2.array("command").example(`sst bind "vitest run"`, "Bind your resources to your tests").example(
7177
- `sst bind "tsx scripts/myscript.ts"`,
7178
- "Bind your resources to a script"
7178
+ (yargs2) => yargs2.option("site", {
7179
+ type: "boolean",
7180
+ describe: "Run in site mode"
7181
+ }).option("script", {
7182
+ type: "boolean",
7183
+ describe: "Run in script mode"
7184
+ }).array("command").example(`sst bind vitest run`, "Bind resources to your tests").example(`sst bind next dev`, "Bind resources to your site").example(
7185
+ `sst bind --script next build`,
7186
+ "Bind resources to your site before deployment"
7179
7187
  ),
7180
7188
  async (args) => {
7181
7189
  const { spawn: spawn7 } = await import("child_process");
@@ -7199,6 +7207,7 @@ var bind = (program2) => program2.command(
7199
7207
  const project = useProject2();
7200
7208
  const command = args.command?.join(" ");
7201
7209
  const isSite = await isRunningInSite();
7210
+ const mode = args.site ? "site" : args.script ? "script" : "auto";
7202
7211
  let p;
7203
7212
  let timer;
7204
7213
  let siteConfigCache;
@@ -7207,23 +7216,11 @@ var bind = (program2) => program2.command(
7207
7216
  `Command is required, e.g. sst bind ${isSite ? "next dev" : "vitest run"}`
7208
7217
  );
7209
7218
  }
7210
- if (!isSite) {
7219
+ if (args.script || !isSite && !args.site) {
7211
7220
  Logger2.debug("Running in script mode.");
7212
7221
  return await bindScript();
7213
7222
  }
7214
- try {
7215
- await bindSite("init");
7216
- } catch (e) {
7217
- if (e instanceof OutdatedMetadataError) {
7218
- Colors2.line(
7219
- Colors2.warning(
7220
- "Warning: This was deployed with an old version of SST. Run `sst dev` or `sst deploy` to update."
7221
- )
7222
- );
7223
- return await bindScript();
7224
- }
7225
- throw e;
7226
- }
7223
+ await bindSite("init");
7227
7224
  bus.subscribe(
7228
7225
  "stacks.metadata.updated",
7229
7226
  () => bindSite("metadata_updated")
@@ -7282,7 +7279,22 @@ var bind = (program2) => program2.command(
7282
7279
  return results.some(Boolean);
7283
7280
  }
7284
7281
  async function bindSite(reason) {
7285
- const siteMetadata = await getSiteMetadataUntilAvailable();
7282
+ let siteMetadata;
7283
+ try {
7284
+ siteMetadata = await getSiteMetadata();
7285
+ } catch (e) {
7286
+ if (!(e instanceof MetadataOutdatedError) && !(e instanceof MetadataNotFoundError)) {
7287
+ throw e;
7288
+ }
7289
+ if (reason !== "init")
7290
+ return;
7291
+ Colors2.line(
7292
+ Colors2.warning(
7293
+ e instanceof MetadataOutdatedError ? "Warning: This was deployed with an old version of SST. Run `sst dev` or `sst deploy` to update." : "Warning: The site has not been deployed. Some resources might not be available."
7294
+ )
7295
+ );
7296
+ return await bindScript();
7297
+ }
7286
7298
  const siteConfig = await parseSiteMetadata(siteMetadata);
7287
7299
  if (reason === "metadata_updated") {
7288
7300
  if (areEnvsSame(siteConfig.envs, siteConfigCache?.envs || {}))
@@ -7294,58 +7306,23 @@ var bind = (program2) => program2.command(
7294
7306
  );
7295
7307
  }
7296
7308
  siteConfigCache = siteConfig;
7297
- if (siteConfig.role) {
7298
- const credentials = await assumeSsrRole(siteConfig.role);
7299
- if (credentials) {
7300
- const expireAt = credentials.Expiration.getTime() - 6e4;
7301
- clearTimeout(timer);
7302
- timer = setTimeout(() => {
7303
- Colors2.line(
7304
- `
7305
- `,
7306
- `Your AWS session is about to expire. Creating a new session and restarting \`${command}\`...`
7307
- );
7308
- bindSite("iam_expired");
7309
- }, expireAt - Date.now());
7310
- await runCommand({
7311
- ...siteConfig.envs,
7312
- AWS_ACCESS_KEY_ID: credentials.AccessKeyId,
7313
- AWS_SECRET_ACCESS_KEY: credentials.SecretAccessKey,
7314
- AWS_SESSION_TOKEN: credentials.SessionToken
7315
- });
7316
- return;
7317
- }
7318
- }
7309
+ const credentials = siteConfig.role && await getLiveIamCredentials(siteConfig.role) || await getLocalIamCredentials();
7319
7310
  await runCommand({
7320
7311
  ...siteConfig.envs,
7321
- ...await localIamCredentials()
7312
+ ...credentials
7322
7313
  });
7323
7314
  }
7324
7315
  async function bindScript() {
7325
7316
  const { Config: Config2 } = await Promise.resolve().then(() => (init_config(), config_exports));
7326
7317
  await runCommand({
7327
7318
  ...await Config2.env(),
7328
- ...await localIamCredentials()
7319
+ ...await getLocalIamCredentials()
7329
7320
  });
7330
7321
  }
7331
- async function getSiteMetadataUntilAvailable() {
7332
- const { createSpinner: createSpinner2 } = await Promise.resolve().then(() => (init_spinner(), spinner_exports));
7333
- const spinner = createSpinner2({});
7334
- while (true) {
7335
- const data2 = await getSiteMetadata();
7336
- if (!data2) {
7337
- spinner.start("Make sure `sst dev` is running...");
7338
- await new Promise((resolve) => setTimeout(resolve, 1e3));
7339
- continue;
7340
- }
7341
- spinner.isSpinning && spinner.stop().clear();
7342
- return data2;
7343
- }
7344
- }
7345
7322
  async function getSiteMetadata() {
7346
7323
  const { metadata: metadata3 } = await Promise.resolve().then(() => (init_metadata(), metadata_exports));
7347
7324
  const metadataData = await metadata3();
7348
- return Object.values(metadataData).flat().filter(
7325
+ const data2 = Object.values(metadataData).flat().filter(
7349
7326
  (c) => [
7350
7327
  "StaticSite",
7351
7328
  "NextjsSite",
@@ -7358,10 +7335,14 @@ var bind = (program2) => program2.command(
7358
7335
  ).find((c) => {
7359
7336
  const isSsr = c.type !== "StaticSite" && c.type !== "SlsNextjsSite";
7360
7337
  if (!c.data.path || isSsr && !c.data.server || !isSsr && !c.data.environment) {
7361
- throw new OutdatedMetadataError();
7338
+ throw new MetadataOutdatedError();
7362
7339
  }
7363
7340
  return path18.resolve(project.paths.root, c.data.path) === process.cwd();
7364
7341
  });
7342
+ if (!data2) {
7343
+ throw new MetadataNotFoundError();
7344
+ }
7345
+ return data2;
7365
7346
  }
7366
7347
  async function parseSiteMetadata(metadata3) {
7367
7348
  const { LambdaClient: LambdaClient2, GetFunctionCommand } = await import("@aws-sdk/client-lambda");
@@ -7382,39 +7363,27 @@ var bind = (program2) => program2.command(
7382
7363
  secrets: metadata3.data.secrets
7383
7364
  };
7384
7365
  }
7385
- async function assumeSsrRole(roleArn) {
7386
- const { STSClient: STSClient2, AssumeRoleCommand } = await import("@aws-sdk/client-sts");
7387
- const { useAWSClient: useAWSClient2 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
7388
- const sts = useAWSClient2(STSClient2);
7389
- const assumeRole = async (duration) => {
7390
- const { Credentials: credentials } = await sts.send(
7391
- new AssumeRoleCommand({
7392
- RoleArn: roleArn,
7393
- RoleSessionName: "dev-session",
7394
- DurationSeconds: duration
7395
- })
7366
+ async function getLiveIamCredentials(roleArn) {
7367
+ const credentials = await assumeSsrRole(roleArn);
7368
+ if (!credentials)
7369
+ return;
7370
+ const expireAt = credentials.Expiration.getTime() - 6e4;
7371
+ clearTimeout(timer);
7372
+ timer = setTimeout(() => {
7373
+ Colors2.line(
7374
+ `
7375
+ `,
7376
+ `Your AWS session is about to expire. Creating a new session and restarting \`${command}\`...`
7396
7377
  );
7397
- return credentials;
7378
+ bindSite("iam_expired");
7379
+ }, expireAt - Date.now());
7380
+ return {
7381
+ AWS_ACCESS_KEY_ID: credentials.AccessKeyId,
7382
+ AWS_SECRET_ACCESS_KEY: credentials.SecretAccessKey,
7383
+ AWS_SESSION_TOKEN: credentials.SessionToken
7398
7384
  };
7399
- let err;
7400
- try {
7401
- return await assumeRole(43200);
7402
- } catch (e) {
7403
- err = e;
7404
- }
7405
- if (err.name === "ValidationError" && err.message.startsWith("The requested DurationSeconds exceeds")) {
7406
- try {
7407
- return await assumeRole(3600);
7408
- } catch (e) {
7409
- err = e;
7410
- }
7411
- }
7412
- Colors2.line(
7413
- "Using local IAM credentials since `sst dev` is not running."
7414
- );
7415
- Logger2.debug(`Failed to assume ${roleArn}.`, err);
7416
7385
  }
7417
- async function localIamCredentials() {
7386
+ async function getLocalIamCredentials() {
7418
7387
  const { useAWSCredentials: useAWSCredentials2 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
7419
7388
  const credentials = await useAWSCredentials2();
7420
7389
  return {
@@ -7452,6 +7421,38 @@ var bind = (program2) => program2.command(
7452
7421
  function areEnvsSame(envs1, envs2) {
7453
7422
  return Object.keys(envs1).length === Object.keys(envs2).length && Object.keys(envs1).every((key) => envs1[key] === envs2[key]);
7454
7423
  }
7424
+ async function assumeSsrRole(roleArn) {
7425
+ const { STSClient: STSClient2, AssumeRoleCommand } = await import("@aws-sdk/client-sts");
7426
+ const { useAWSClient: useAWSClient2 } = await Promise.resolve().then(() => (init_credentials(), credentials_exports));
7427
+ const sts = useAWSClient2(STSClient2);
7428
+ const assumeRole = async (duration) => {
7429
+ const { Credentials: credentials } = await sts.send(
7430
+ new AssumeRoleCommand({
7431
+ RoleArn: roleArn,
7432
+ RoleSessionName: "dev-session",
7433
+ DurationSeconds: duration
7434
+ })
7435
+ );
7436
+ return credentials;
7437
+ };
7438
+ let err;
7439
+ try {
7440
+ return await assumeRole(43200);
7441
+ } catch (e) {
7442
+ err = e;
7443
+ }
7444
+ if (err.name === "ValidationError" && err.message.startsWith("The requested DurationSeconds exceeds")) {
7445
+ try {
7446
+ return await assumeRole(3600);
7447
+ } catch (e) {
7448
+ err = e;
7449
+ }
7450
+ }
7451
+ Colors2.line(
7452
+ "Using local IAM credentials since `sst dev` is not running."
7453
+ );
7454
+ Logger2.debug(`Failed to assume ${roleArn}.`, err);
7455
+ }
7455
7456
  }
7456
7457
  ).strict(false);
7457
7458
 
@@ -7707,12 +7708,19 @@ var list = (program2) => program2.command(
7707
7708
  (yargs2) => yargs2.positional("format", {
7708
7709
  type: "string",
7709
7710
  choices: ["table", "env", "json"]
7710
- }),
7711
+ }).boolean("fallback"),
7711
7712
  async (args) => {
7712
7713
  const { Config: Config2 } = await Promise.resolve().then(() => (init_config(), config_exports));
7713
7714
  const { gray } = await import("colorette");
7714
7715
  const { Colors: Colors2 } = await Promise.resolve().then(() => (init_colors(), colors_exports));
7715
- const secrets2 = await Config2.secrets();
7716
+ const configSecrets = await Config2.secrets();
7717
+ const secrets2 = !args.fallback ? configSecrets : Object.entries(configSecrets).reduce(
7718
+ (carry, [key, value]) => ({
7719
+ ...carry,
7720
+ ...!value.value && !!value.fallback ? { [key]: value } : {}
7721
+ }),
7722
+ {}
7723
+ );
7716
7724
  if (Object.entries(secrets2).length === 0) {
7717
7725
  Colors2.line("No secrets set");
7718
7726
  return;
@@ -7729,7 +7737,9 @@ var list = (program2) => program2.command(
7729
7737
  break;
7730
7738
  case "env":
7731
7739
  for (const [key, value] of Object.entries(secrets2)) {
7732
- console.log(`${key}=${value.value || value.fallback}`);
7740
+ console.log(
7741
+ `${key}=${value.value || `${value.fallback} #fallback`}`
7742
+ );
7733
7743
  }
7734
7744
  break;
7735
7745
  case "table":
@@ -7755,8 +7765,11 @@ var list = (program2) => program2.command(
7755
7765
  );
7756
7766
  keys.sort().forEach((key) => {
7757
7767
  const value = secrets2[key].value ? secrets2[key].value : `${secrets2[key].fallback} ${gray("(fallback)")}`;
7768
+ const colourPadding = secrets2[key].value ? 0 : gray("").length;
7758
7769
  console.log(
7759
- `\u2502 ${key.padEnd(keyLen)} \u2502 ${value.padEnd(valueLen)} \u2502`
7770
+ `\u2502 ${key.padEnd(keyLen)} \u2502 ${value.padEnd(
7771
+ valueLen + colourPadding
7772
+ )} \u2502`
7760
7773
  );
7761
7774
  });
7762
7775
  console.log(