sst 2.11.0 → 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/cli/commands/bind.d.ts +4 -0
- package/cli/commands/bind.js +96 -86
- package/constructs/NextjsSite.js +1 -1
- package/package.json +1 -1
- package/sst.mjs +90 -89
package/cli/commands/bind.d.ts
CHANGED
|
@@ -12,6 +12,10 @@ export declare const bind: (program: Program) => import("yargs").Argv<{
|
|
|
12
12
|
role: string | undefined;
|
|
13
13
|
} & {
|
|
14
14
|
future: boolean | undefined;
|
|
15
|
+
} & {
|
|
16
|
+
site: boolean | undefined;
|
|
17
|
+
} & {
|
|
18
|
+
script: boolean | undefined;
|
|
15
19
|
} & {
|
|
16
20
|
command: (string | number)[] | undefined;
|
|
17
21
|
}>;
|
package/cli/commands/bind.js
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import { VisibleError } from "../../error.js";
|
|
3
|
-
class
|
|
3
|
+
class MetadataNotFoundError extends Error {
|
|
4
|
+
}
|
|
5
|
+
class MetadataOutdatedError extends Error {
|
|
4
6
|
}
|
|
5
7
|
export const bind = (program) => program
|
|
6
8
|
.command(["bind <command..>", "env <command..>"], "Bind your app's resources to a command", (yargs) => yargs
|
|
9
|
+
.option("site", {
|
|
10
|
+
type: "boolean",
|
|
11
|
+
describe: "Run in site mode",
|
|
12
|
+
})
|
|
13
|
+
.option("script", {
|
|
14
|
+
type: "boolean",
|
|
15
|
+
describe: "Run in script mode",
|
|
16
|
+
})
|
|
7
17
|
.array("command")
|
|
8
|
-
.example(`sst bind
|
|
9
|
-
.example(`sst bind
|
|
18
|
+
.example(`sst bind vitest run`, "Bind resources to your tests")
|
|
19
|
+
.example(`sst bind next dev`, "Bind resources to your site")
|
|
20
|
+
.example(`sst bind --script next build`, "Bind resources to your site before deployment"), async (args) => {
|
|
10
21
|
const { spawn } = await import("child_process");
|
|
11
22
|
const kill = await import("tree-kill");
|
|
12
23
|
const { useProject } = await import("../../project.js");
|
|
@@ -22,6 +33,7 @@ export const bind = (program) => program
|
|
|
22
33
|
const project = useProject();
|
|
23
34
|
const command = args.command?.join(" ");
|
|
24
35
|
const isSite = await isRunningInSite();
|
|
36
|
+
const mode = args.site ? "site" : args.script ? "script" : "auto";
|
|
25
37
|
let p;
|
|
26
38
|
let timer;
|
|
27
39
|
let siteConfigCache;
|
|
@@ -30,22 +42,12 @@ export const bind = (program) => program
|
|
|
30
42
|
throw new VisibleError(`Command is required, e.g. sst bind ${isSite ? "next dev" : "vitest run"}`);
|
|
31
43
|
}
|
|
32
44
|
// Bind script
|
|
33
|
-
if (!isSite) {
|
|
45
|
+
if (args.script || (!isSite && !args.site)) {
|
|
34
46
|
Logger.debug("Running in script mode.");
|
|
35
47
|
return await bindScript();
|
|
36
48
|
}
|
|
37
49
|
// Bind site
|
|
38
|
-
|
|
39
|
-
await bindSite("init");
|
|
40
|
-
}
|
|
41
|
-
catch (e) {
|
|
42
|
-
// Bind script (fallback)
|
|
43
|
-
if (e instanceof OutdatedMetadataError) {
|
|
44
|
-
Colors.line(Colors.warning("Warning: This was deployed with an old version of SST. Run `sst dev` or `sst deploy` to update."));
|
|
45
|
-
return await bindScript();
|
|
46
|
-
}
|
|
47
|
-
throw e;
|
|
48
|
-
}
|
|
50
|
+
await bindSite("init");
|
|
49
51
|
bus.subscribe("stacks.metadata.updated", () => bindSite("metadata_updated"));
|
|
50
52
|
bus.subscribe("stacks.metadata.deleted", () => bindSite("metadata_updated"));
|
|
51
53
|
bus.subscribe("config.secret.updated", (payload) => {
|
|
@@ -93,7 +95,25 @@ export const bind = (program) => program
|
|
|
93
95
|
}
|
|
94
96
|
async function bindSite(reason) {
|
|
95
97
|
// Get metadata
|
|
96
|
-
|
|
98
|
+
let siteMetadata;
|
|
99
|
+
try {
|
|
100
|
+
siteMetadata = await getSiteMetadata();
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
// unhandled error
|
|
104
|
+
if (!(e instanceof MetadataOutdatedError) &&
|
|
105
|
+
!(e instanceof MetadataNotFoundError)) {
|
|
106
|
+
throw e;
|
|
107
|
+
}
|
|
108
|
+
// ignore error if previously failed to fetch metadata
|
|
109
|
+
if (reason !== "init")
|
|
110
|
+
return;
|
|
111
|
+
// run in script mode
|
|
112
|
+
Colors.line(Colors.warning(e instanceof MetadataOutdatedError
|
|
113
|
+
? "Warning: This was deployed with an old version of SST. Run `sst dev` or `sst deploy` to update."
|
|
114
|
+
: "Warning: The site has not been deployed. Some resources might not be available."));
|
|
115
|
+
return await bindScript();
|
|
116
|
+
}
|
|
97
117
|
const siteConfig = await parseSiteMetadata(siteMetadata);
|
|
98
118
|
// Handle rebind due to metadata updated
|
|
99
119
|
if (reason === "metadata_updated") {
|
|
@@ -103,57 +123,26 @@ export const bind = (program) => program
|
|
|
103
123
|
}
|
|
104
124
|
siteConfigCache = siteConfig;
|
|
105
125
|
// Assume function's role credentials
|
|
106
|
-
if (siteConfig.role) {
|
|
107
|
-
const credentials = await assumeSsrRole(siteConfig.role);
|
|
108
|
-
if (credentials) {
|
|
109
|
-
// refresh crecentials 1 minute before expiration
|
|
110
|
-
const expireAt = credentials.Expiration.getTime() - 60000;
|
|
111
|
-
clearTimeout(timer);
|
|
112
|
-
timer = setTimeout(() => {
|
|
113
|
-
Colors.line(`\n`, `Your AWS session is about to expire. Creating a new session and restarting \`${command}\`...`);
|
|
114
|
-
bindSite("iam_expired");
|
|
115
|
-
}, expireAt - Date.now());
|
|
116
|
-
await runCommand({
|
|
117
|
-
...siteConfig.envs,
|
|
118
|
-
AWS_ACCESS_KEY_ID: credentials.AccessKeyId,
|
|
119
|
-
AWS_SECRET_ACCESS_KEY: credentials.SecretAccessKey,
|
|
120
|
-
AWS_SESSION_TOKEN: credentials.SessionToken,
|
|
121
|
-
});
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
126
|
// Fallback to use local IAM credentials
|
|
127
|
+
const credentials = (siteConfig.role &&
|
|
128
|
+
(await getLiveIamCredentials(siteConfig.role))) ||
|
|
129
|
+
(await getLocalIamCredentials());
|
|
126
130
|
await runCommand({
|
|
127
131
|
...siteConfig.envs,
|
|
128
|
-
...
|
|
132
|
+
...credentials,
|
|
129
133
|
});
|
|
130
134
|
}
|
|
131
135
|
async function bindScript() {
|
|
132
136
|
const { Config } = await import("../../config.js");
|
|
133
137
|
await runCommand({
|
|
134
138
|
...(await Config.env()),
|
|
135
|
-
...(await
|
|
139
|
+
...(await getLocalIamCredentials()),
|
|
136
140
|
});
|
|
137
141
|
}
|
|
138
|
-
async function getSiteMetadataUntilAvailable() {
|
|
139
|
-
const { createSpinner } = await import("../spinner.js");
|
|
140
|
-
const spinner = createSpinner({});
|
|
141
|
-
while (true) {
|
|
142
|
-
const data = await getSiteMetadata();
|
|
143
|
-
// Handle site metadata not found
|
|
144
|
-
if (!data) {
|
|
145
|
-
spinner.start("Make sure `sst dev` is running...");
|
|
146
|
-
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
spinner.isSpinning && spinner.stop().clear();
|
|
150
|
-
return data;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
142
|
async function getSiteMetadata() {
|
|
154
143
|
const { metadata } = await import("../../stacks/metadata.js");
|
|
155
144
|
const metadataData = await metadata();
|
|
156
|
-
|
|
145
|
+
const data = Object.values(metadataData)
|
|
157
146
|
.flat()
|
|
158
147
|
.filter((c) => [
|
|
159
148
|
"StaticSite",
|
|
@@ -170,10 +159,14 @@ export const bind = (program) => program
|
|
|
170
159
|
if (!c.data.path ||
|
|
171
160
|
(isSsr && !c.data.server) ||
|
|
172
161
|
(!isSsr && !c.data.environment)) {
|
|
173
|
-
throw new
|
|
162
|
+
throw new MetadataOutdatedError();
|
|
174
163
|
}
|
|
175
164
|
return (path.resolve(project.paths.root, c.data.path) === process.cwd());
|
|
176
165
|
});
|
|
166
|
+
if (!data) {
|
|
167
|
+
throw new MetadataNotFoundError();
|
|
168
|
+
}
|
|
169
|
+
return data;
|
|
177
170
|
}
|
|
178
171
|
async function parseSiteMetadata(metadata) {
|
|
179
172
|
const { LambdaClient, GetFunctionCommand } = await import("@aws-sdk/client-lambda");
|
|
@@ -194,40 +187,24 @@ export const bind = (program) => program
|
|
|
194
187
|
secrets: metadata.data.secrets,
|
|
195
188
|
};
|
|
196
189
|
}
|
|
197
|
-
async function
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
190
|
+
async function getLiveIamCredentials(roleArn) {
|
|
191
|
+
const credentials = await assumeSsrRole(roleArn);
|
|
192
|
+
if (!credentials)
|
|
193
|
+
return;
|
|
194
|
+
// refresh crecentials 1 minute before expiration
|
|
195
|
+
const expireAt = credentials.Expiration.getTime() - 60000;
|
|
196
|
+
clearTimeout(timer);
|
|
197
|
+
timer = setTimeout(() => {
|
|
198
|
+
Colors.line(`\n`, `Your AWS session is about to expire. Creating a new session and restarting \`${command}\`...`);
|
|
199
|
+
bindSite("iam_expired");
|
|
200
|
+
}, expireAt - Date.now());
|
|
201
|
+
return {
|
|
202
|
+
AWS_ACCESS_KEY_ID: credentials.AccessKeyId,
|
|
203
|
+
AWS_SECRET_ACCESS_KEY: credentials.SecretAccessKey,
|
|
204
|
+
AWS_SESSION_TOKEN: credentials.SessionToken,
|
|
208
205
|
};
|
|
209
|
-
// Assue role with max duration first. This can fail if chaining roles, or if
|
|
210
|
-
// the role has a max duration set. If it fails, assume role with 1 hour duration.
|
|
211
|
-
let err;
|
|
212
|
-
try {
|
|
213
|
-
return await assumeRole(43200);
|
|
214
|
-
}
|
|
215
|
-
catch (e) {
|
|
216
|
-
err = e;
|
|
217
|
-
}
|
|
218
|
-
if (err.name === "ValidationError" &&
|
|
219
|
-
err.message.startsWith("The requested DurationSeconds exceeds")) {
|
|
220
|
-
try {
|
|
221
|
-
return await assumeRole(3600);
|
|
222
|
-
}
|
|
223
|
-
catch (e) {
|
|
224
|
-
err = e;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
Colors.line("Using local IAM credentials since `sst dev` is not running.");
|
|
228
|
-
Logger.debug(`Failed to assume ${roleArn}.`, err);
|
|
229
206
|
}
|
|
230
|
-
async function
|
|
207
|
+
async function getLocalIamCredentials() {
|
|
231
208
|
const { useAWSCredentials } = await import("../../credentials.js");
|
|
232
209
|
const credentials = await useAWSCredentials();
|
|
233
210
|
return {
|
|
@@ -269,5 +246,38 @@ export const bind = (program) => program
|
|
|
269
246
|
return (Object.keys(envs1).length === Object.keys(envs2).length &&
|
|
270
247
|
Object.keys(envs1).every((key) => envs1[key] === envs2[key]));
|
|
271
248
|
}
|
|
249
|
+
async function assumeSsrRole(roleArn) {
|
|
250
|
+
const { STSClient, AssumeRoleCommand } = await import("@aws-sdk/client-sts");
|
|
251
|
+
const { useAWSClient } = await import("../../credentials.js");
|
|
252
|
+
const sts = useAWSClient(STSClient);
|
|
253
|
+
const assumeRole = async (duration) => {
|
|
254
|
+
const { Credentials: credentials } = await sts.send(new AssumeRoleCommand({
|
|
255
|
+
RoleArn: roleArn,
|
|
256
|
+
RoleSessionName: "dev-session",
|
|
257
|
+
DurationSeconds: duration,
|
|
258
|
+
}));
|
|
259
|
+
return credentials;
|
|
260
|
+
};
|
|
261
|
+
// Assue role with max duration first. This can fail if chaining roles, or if
|
|
262
|
+
// the role has a max duration set. If it fails, assume role with 1 hour duration.
|
|
263
|
+
let err;
|
|
264
|
+
try {
|
|
265
|
+
return await assumeRole(43200);
|
|
266
|
+
}
|
|
267
|
+
catch (e) {
|
|
268
|
+
err = e;
|
|
269
|
+
}
|
|
270
|
+
if (err.name === "ValidationError" &&
|
|
271
|
+
err.message.startsWith("The requested DurationSeconds exceeds")) {
|
|
272
|
+
try {
|
|
273
|
+
return await assumeRole(3600);
|
|
274
|
+
}
|
|
275
|
+
catch (e) {
|
|
276
|
+
err = e;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
Colors.line("Using local IAM credentials since `sst dev` is not running.");
|
|
280
|
+
Logger.debug(`Failed to assume ${roleArn}.`, err);
|
|
281
|
+
}
|
|
272
282
|
})
|
|
273
283
|
.strict(false);
|
package/constructs/NextjsSite.js
CHANGED
|
@@ -29,7 +29,7 @@ const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
|
29
29
|
export class NextjsSite extends SsrSite {
|
|
30
30
|
constructor(scope, id, props) {
|
|
31
31
|
super(scope, id, {
|
|
32
|
-
buildCommand: "npx --yes open-next
|
|
32
|
+
buildCommand: "npx --yes open-next@^1.3 build",
|
|
33
33
|
...props,
|
|
34
34
|
});
|
|
35
35
|
this.createWarmer();
|
package/package.json
CHANGED
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
|
|
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.
|
|
7177
|
-
|
|
7178
|
-
"
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
...
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
7386
|
-
const
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
const
|
|
7390
|
-
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
|
|
7394
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|