sst 2.24.15 → 2.24.16
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 +1 -0
- package/cli/commands/bind.js +302 -293
- package/cli/commands/bootstrap.js +8 -2
- package/cli/commands/build.js +16 -10
- package/cli/commands/connect.js +41 -34
- package/cli/commands/console.js +17 -11
- package/cli/commands/deploy.js +83 -72
- package/cli/commands/dev.js +294 -277
- package/cli/commands/diff.js +64 -58
- package/cli/commands/remove.js +46 -36
- package/cli/commands/secrets/get.d.ts +1 -1
- package/cli/commands/secrets/get.js +4 -1
- package/cli/commands/secrets/list.js +58 -51
- package/cli/commands/secrets/load.js +34 -28
- package/cli/commands/secrets/remove.js +4 -0
- package/cli/commands/secrets/secrets.d.ts +1 -1
- package/cli/commands/secrets/secrets.js +5 -5
- package/cli/commands/secrets/set.js +32 -26
- package/cli/commands/telemetry.js +13 -6
- package/cli/commands/transform.js +12 -5
- package/cli/commands/types.js +18 -12
- package/cli/commands/update.js +94 -88
- package/cli/commands/version.js +12 -5
- package/cli/program.d.ts +4 -0
- package/cli/program.js +36 -1
- package/cli/sst.js +8 -7
- package/cli/telemetry/telemetry.d.ts +16 -1
- package/cli/telemetry/telemetry.js +13 -3
- package/constructs/App.js +2 -5
- package/constructs/Function.js +1 -1
- package/constructs/SsrSite.js +1 -1
- package/constructs/deprecated/NextjsSite.js +3 -4
- package/error.d.ts +3 -0
- package/error.js +5 -0
- package/package.json +1 -1
package/cli/commands/diff.js
CHANGED
|
@@ -8,76 +8,82 @@ export const diff = (program) => program.command("diff", "Compare your app with
|
|
|
8
8
|
type: "string",
|
|
9
9
|
describe: "Output directory, defaults to .sst/dist",
|
|
10
10
|
}), async (args) => {
|
|
11
|
+
const { exit, exitWithError } = await import("../program.js");
|
|
11
12
|
const { useProject } = await import("../../project.js");
|
|
12
13
|
const { Stacks } = await import("../../stacks/index.js");
|
|
13
14
|
const { useAWSClient } = await import("../../credentials.js");
|
|
14
15
|
const { CloudFormationClient, GetTemplateCommand } = await import("@aws-sdk/client-cloudformation");
|
|
15
16
|
const { createSpinner } = await import("../spinner.js");
|
|
16
17
|
const { Colors } = await import("../colors.js");
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
18
|
+
try {
|
|
19
|
+
// Build app
|
|
20
|
+
const project = useProject();
|
|
21
|
+
const [_metafile, sstConfig] = await Stacks.load(project.paths.config);
|
|
22
|
+
const assembly = await Stacks.synth({
|
|
23
|
+
fn: sstConfig.stacks,
|
|
24
|
+
buildDir: args.to,
|
|
25
|
+
mode: args.dev ? "dev" : "deploy",
|
|
26
|
+
});
|
|
27
|
+
// Diff each stack
|
|
28
|
+
let changesAcc = 0;
|
|
29
|
+
let changedStacks = 0;
|
|
30
|
+
const cfn = useAWSClient(CloudFormationClient);
|
|
31
|
+
for (const stack of assembly.stacks) {
|
|
32
|
+
const spinner = createSpinner(`${stack.stackName}: Checking for changes...`);
|
|
33
|
+
// get old template
|
|
34
|
+
const oldTemplate = await getTemplate(stack.stackName);
|
|
35
|
+
if (!oldTemplate) {
|
|
36
|
+
spinner.clear();
|
|
37
|
+
Colors.line(`➜ ${Colors.dim.bold(stackNameToId(stack.stackName) + ":")} New stack`);
|
|
38
|
+
Colors.gap();
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
// generate diff
|
|
42
|
+
const { count, diff } = await Stacks.diff(stack, oldTemplate);
|
|
34
43
|
spinner.clear();
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
// print diff result
|
|
45
|
+
if (count === 0) {
|
|
46
|
+
Colors.line(`➜ ${Colors.dim.bold(stackNameToId(stack.stackName) + ":")} No changes`);
|
|
47
|
+
Colors.gap();
|
|
48
|
+
}
|
|
49
|
+
else if (count === 1) {
|
|
50
|
+
Colors.line(`➜ ${Colors.dim.bold(stackNameToId(stack.stackName) + ":")} ${count} change`);
|
|
51
|
+
Colors.gap();
|
|
52
|
+
console.log(diff);
|
|
53
|
+
changesAcc += count;
|
|
54
|
+
changedStacks++;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
Colors.line(`➜ ${Colors.dim.bold(stackNameToId(stack.stackName) + ":")} ${count} changes`);
|
|
58
|
+
Colors.gap();
|
|
59
|
+
console.log(diff);
|
|
60
|
+
changesAcc += count;
|
|
61
|
+
changedStacks++;
|
|
62
|
+
}
|
|
46
63
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Colors.
|
|
50
|
-
console.log(diff);
|
|
51
|
-
changesAcc += count;
|
|
52
|
-
changedStacks++;
|
|
64
|
+
// Handle no changes
|
|
65
|
+
if (changedStacks === 0) {
|
|
66
|
+
Colors.line(Colors.success(`✔`), Colors.bold(" Diff:"), "No changes");
|
|
53
67
|
}
|
|
54
68
|
else {
|
|
55
|
-
Colors.line(
|
|
56
|
-
Colors.gap();
|
|
57
|
-
console.log(diff);
|
|
58
|
-
changesAcc += count;
|
|
59
|
-
changedStacks++;
|
|
69
|
+
Colors.line(Colors.success(`✔`), Colors.bold(" Diff:"), changesAcc === 1 ? "1 change found in" : `${changesAcc} changes in`, changedStacks === 1 ? "1 stack" : `${changedStacks} stacks`);
|
|
60
70
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const response = await cfn.send(new GetTemplateCommand({ StackName: stackName }));
|
|
73
|
-
return JSON.parse(response.TemplateBody);
|
|
74
|
-
}
|
|
75
|
-
catch (e) {
|
|
76
|
-
if (e.name === "ValidationError" &&
|
|
77
|
-
e.message.includes("does not exist")) {
|
|
78
|
-
return;
|
|
71
|
+
async function getTemplate(stackName) {
|
|
72
|
+
try {
|
|
73
|
+
const response = await cfn.send(new GetTemplateCommand({ StackName: stackName }));
|
|
74
|
+
return JSON.parse(response.TemplateBody);
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
if (e.name === "ValidationError" &&
|
|
78
|
+
e.message.includes("does not exist")) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
throw e;
|
|
79
82
|
}
|
|
80
|
-
throw e;
|
|
81
83
|
}
|
|
84
|
+
await exit();
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
await exitWithError(e);
|
|
82
88
|
}
|
|
83
89
|
});
|
package/cli/commands/remove.js
CHANGED
|
@@ -4,49 +4,59 @@ export const remove = (program) => program.command("remove [filter]", "Remove yo
|
|
|
4
4
|
}), async (args) => {
|
|
5
5
|
const React = await import("react");
|
|
6
6
|
const { dim, blue, bold } = await import("colorette");
|
|
7
|
+
const { exit, exitWithError } = await import("../program.js");
|
|
7
8
|
const { useProject } = await import("../../project.js");
|
|
9
|
+
const { SilentError } = await import("../../error.js");
|
|
8
10
|
const { loadAssembly, clearAppMetadata, Stacks } = await import("../../stacks/index.js");
|
|
9
11
|
const { render } = await import("ink");
|
|
10
12
|
const { DeploymentUI } = await import("../ui/deploy.js");
|
|
11
13
|
const { printDeploymentResults } = await import("../ui/deploy.js");
|
|
12
14
|
const { Colors } = await import("../colors.js");
|
|
13
15
|
const { useSTSIdentity } = await import("../../credentials.js");
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
try {
|
|
17
|
+
const project = useProject();
|
|
18
|
+
const identity = await useSTSIdentity();
|
|
19
|
+
Colors.line(`${Colors.primary.bold(`SST v${project.version}`)}`);
|
|
20
|
+
Colors.gap();
|
|
21
|
+
Colors.line(`${Colors.primary(`➜`)} ${Colors.bold("App:")} ${project.config.name}`);
|
|
22
|
+
Colors.line(` ${Colors.bold("Stage:")} ${project.config.stage}`);
|
|
23
|
+
Colors.line(` ${Colors.bold("Region:")} ${project.config.region}`);
|
|
24
|
+
Colors.line(` ${Colors.bold("Account:")} ${identity.Account}`);
|
|
25
|
+
const assembly = await (async function () {
|
|
26
|
+
if (args.from) {
|
|
27
|
+
const result = await loadAssembly(args.from);
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
const [_metafile, sstConfig] = await Stacks.load(project.paths.config);
|
|
31
|
+
return await Stacks.synth({
|
|
32
|
+
fn: sstConfig.stacks,
|
|
33
|
+
mode: "remove",
|
|
34
|
+
});
|
|
35
|
+
})();
|
|
36
|
+
const target = assembly.stacks.filter((s) => !args.filter ||
|
|
37
|
+
s.id
|
|
38
|
+
.toLowerCase()
|
|
39
|
+
.replace(project.config.name.toLowerCase(), "")
|
|
40
|
+
.replace(project.config.stage.toLowerCase(), "")
|
|
41
|
+
.includes(args.filter.toLowerCase()));
|
|
42
|
+
if (!target.length) {
|
|
43
|
+
console.log(`No stacks found matching ${blue(args.filter)}`);
|
|
44
|
+
throw new SilentError(`No stacks found matching ${args.filter}`);
|
|
26
45
|
}
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
const component = render(React.createElement(DeploymentUI, { assembly: assembly, remove: true }));
|
|
47
|
+
const results = await Stacks.removeMany(target);
|
|
48
|
+
component.clear();
|
|
49
|
+
component.unmount();
|
|
50
|
+
printDeploymentResults(assembly, results, true);
|
|
51
|
+
// Check failed stacks
|
|
52
|
+
const failed = Object.values(results).find((result) => Stacks.isFailed(result.status));
|
|
53
|
+
if (failed) {
|
|
54
|
+
throw new SilentError(`CloudFormation status ${failed.status}`);
|
|
55
|
+
}
|
|
56
|
+
await clearAppMetadata();
|
|
57
|
+
await exit();
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
await exitWithError(e);
|
|
42
61
|
}
|
|
43
|
-
const component = render(React.createElement(DeploymentUI, { assembly: assembly, remove: true }));
|
|
44
|
-
const results = await Stacks.removeMany(target);
|
|
45
|
-
component.clear();
|
|
46
|
-
component.unmount();
|
|
47
|
-
printDeploymentResults(assembly, results, true);
|
|
48
|
-
if (Object.values(results).some((stack) => Stacks.isFailed(stack.status)))
|
|
49
|
-
process.exit(1);
|
|
50
|
-
await clearAppMetadata();
|
|
51
|
-
process.exit(0);
|
|
52
62
|
});
|
|
@@ -8,8 +8,9 @@ export const get = (program) => program.command("get <name>", "Get the value of
|
|
|
8
8
|
type: "boolean",
|
|
9
9
|
describe: "Get the fallback value",
|
|
10
10
|
}), async (args) => {
|
|
11
|
-
const {
|
|
11
|
+
const { exit, exitWithError } = await import("../../program.js");
|
|
12
12
|
const { Config } = await import("../../../config.js");
|
|
13
|
+
const { SilentError } = await import("../../../error.js");
|
|
13
14
|
const { Colors } = await import("../../colors.js");
|
|
14
15
|
try {
|
|
15
16
|
const result = await Config.getSecret({
|
|
@@ -17,8 +18,10 @@ export const get = (program) => program.command("get <name>", "Get the value of
|
|
|
17
18
|
fallback: args.fallback === true,
|
|
18
19
|
});
|
|
19
20
|
console.log(result);
|
|
21
|
+
await exit();
|
|
20
22
|
}
|
|
21
23
|
catch {
|
|
22
24
|
Colors.line(Colors.danger(`✖ `), `"${args.name}" is not set`);
|
|
25
|
+
await exitWithError(new SilentError(`"${args.name}" is not set`));
|
|
23
26
|
}
|
|
24
27
|
});
|
|
@@ -4,59 +4,66 @@ export const list = (program) => program.command("list [format]", "Fetch all the
|
|
|
4
4
|
choices: ["table", "env", "json"],
|
|
5
5
|
})
|
|
6
6
|
.boolean("fallback"), async (args) => {
|
|
7
|
-
const { Config } = await import("../../../config.js");
|
|
8
7
|
const { gray } = await import("colorette");
|
|
8
|
+
const { Config } = await import("../../../config.js");
|
|
9
|
+
const { exit, exitWithError } = await import("../../program.js");
|
|
9
10
|
const { Colors } = await import("../../colors.js");
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
try {
|
|
12
|
+
const configSecrets = await Config.secrets();
|
|
13
|
+
const secrets = !args.fallback
|
|
14
|
+
? configSecrets
|
|
15
|
+
: Object.entries(configSecrets).reduce((carry, [key, value]) => ({
|
|
16
|
+
...carry,
|
|
17
|
+
...(!value.value && !!value.fallback ? { [key]: value } : {}),
|
|
18
|
+
}), {});
|
|
19
|
+
if (Object.entries(secrets).length === 0) {
|
|
20
|
+
Colors.line("No secrets set");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
switch (args.format || "table") {
|
|
24
|
+
case "json":
|
|
25
|
+
const env = Object.fromEntries(Object.entries(secrets).map(([key, { value, fallback }]) => [
|
|
26
|
+
key,
|
|
27
|
+
value || fallback,
|
|
28
|
+
]));
|
|
29
|
+
console.log(JSON.stringify(env, null, 2));
|
|
30
|
+
break;
|
|
31
|
+
case "env":
|
|
32
|
+
for (const [key, value] of Object.entries(secrets)) {
|
|
33
|
+
console.log(`${key}=${value.value || `${value.fallback} #fallback`}`);
|
|
34
|
+
}
|
|
35
|
+
break;
|
|
36
|
+
case "table":
|
|
37
|
+
const keys = Object.keys(secrets);
|
|
38
|
+
const keyLen = Math.max("Secrets".length, ...keys.map((key) => key.length));
|
|
39
|
+
const valueLen = Math.max("Values".length, ...keys.map((key) => secrets[key].value
|
|
40
|
+
? secrets[key].value.length
|
|
41
|
+
: `${secrets[key].fallback} (fallback)`.length));
|
|
42
|
+
console.log("┌".padEnd(keyLen + 3, "─") +
|
|
43
|
+
"┬" +
|
|
44
|
+
"".padEnd(valueLen + 2, "─") +
|
|
45
|
+
"┐");
|
|
46
|
+
console.log(`│ ${"Secrets".padEnd(keyLen)} │ ${"Values".padEnd(valueLen)} │`);
|
|
47
|
+
console.log("├".padEnd(keyLen + 3, "─") +
|
|
48
|
+
"┼" +
|
|
49
|
+
"".padEnd(valueLen + 2, "─") +
|
|
50
|
+
"┤");
|
|
51
|
+
keys.sort().forEach((key) => {
|
|
52
|
+
const value = secrets[key].value
|
|
53
|
+
? secrets[key].value
|
|
54
|
+
: `${secrets[key].fallback} ${gray("(fallback)")}`;
|
|
55
|
+
const colourPadding = secrets[key].value ? 0 : gray("").length;
|
|
56
|
+
console.log(`│ ${key.padEnd(keyLen)} │ ${value.padEnd(valueLen + colourPadding)} │`);
|
|
57
|
+
});
|
|
58
|
+
console.log("└".padEnd(keyLen + 3, "─") +
|
|
59
|
+
"┴" +
|
|
60
|
+
"".padEnd(valueLen + 2, "─") +
|
|
61
|
+
"┘");
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
await exit();
|
|
20
65
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const env = Object.fromEntries(Object.entries(secrets).map(([key, { value, fallback }]) => [
|
|
24
|
-
key,
|
|
25
|
-
value || fallback,
|
|
26
|
-
]));
|
|
27
|
-
console.log(JSON.stringify(env, null, 2));
|
|
28
|
-
break;
|
|
29
|
-
case "env":
|
|
30
|
-
for (const [key, value] of Object.entries(secrets)) {
|
|
31
|
-
console.log(`${key}=${value.value || `${value.fallback} #fallback`}`);
|
|
32
|
-
}
|
|
33
|
-
break;
|
|
34
|
-
case "table":
|
|
35
|
-
const keys = Object.keys(secrets);
|
|
36
|
-
const keyLen = Math.max("Secrets".length, ...keys.map((key) => key.length));
|
|
37
|
-
const valueLen = Math.max("Values".length, ...keys.map((key) => secrets[key].value
|
|
38
|
-
? secrets[key].value.length
|
|
39
|
-
: `${secrets[key].fallback} (fallback)`.length));
|
|
40
|
-
console.log("┌".padEnd(keyLen + 3, "─") +
|
|
41
|
-
"┬" +
|
|
42
|
-
"".padEnd(valueLen + 2, "─") +
|
|
43
|
-
"┐");
|
|
44
|
-
console.log(`│ ${"Secrets".padEnd(keyLen)} │ ${"Values".padEnd(valueLen)} │`);
|
|
45
|
-
console.log("├".padEnd(keyLen + 3, "─") +
|
|
46
|
-
"┼" +
|
|
47
|
-
"".padEnd(valueLen + 2, "─") +
|
|
48
|
-
"┤");
|
|
49
|
-
keys.sort().forEach((key) => {
|
|
50
|
-
const value = secrets[key].value
|
|
51
|
-
? secrets[key].value
|
|
52
|
-
: `${secrets[key].fallback} ${gray("(fallback)")}`;
|
|
53
|
-
const colourPadding = secrets[key].value ? 0 : gray("").length;
|
|
54
|
-
console.log(`│ ${key.padEnd(keyLen)} │ ${value.padEnd(valueLen + colourPadding)} │`);
|
|
55
|
-
});
|
|
56
|
-
console.log("└".padEnd(keyLen + 3, "─") +
|
|
57
|
-
"┴" +
|
|
58
|
-
"".padEnd(valueLen + 2, "─") +
|
|
59
|
-
"┘");
|
|
60
|
-
break;
|
|
66
|
+
catch (e) {
|
|
67
|
+
await exitWithError(e);
|
|
61
68
|
}
|
|
62
69
|
});
|
|
@@ -2,40 +2,46 @@ export const load = (program) => program.command("load <filename>", "Loads secre
|
|
|
2
2
|
type: "string",
|
|
3
3
|
demandOption: true,
|
|
4
4
|
}), async (args) => {
|
|
5
|
+
const { exit, exitWithError } = await import("../../program.js");
|
|
5
6
|
const { Config } = await import("../../../config.js");
|
|
6
7
|
const { Colors } = await import("../../colors.js");
|
|
7
8
|
const { blue } = await import("colorette");
|
|
8
9
|
const { createSpinner } = await import("../../spinner.js");
|
|
9
10
|
const { parse } = await import("dotenv");
|
|
10
11
|
const fs = await import("fs/promises");
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
try {
|
|
13
|
+
// Parse .env file
|
|
14
|
+
const fileContent = await fs.readFile(args.filename, "utf-8");
|
|
15
|
+
const envVars = parse(fileContent);
|
|
16
|
+
// Set secrets
|
|
17
|
+
const setting = createSpinner(` Setting secrets from "${args.filename}"`).start();
|
|
18
|
+
for (const [key, value] of Object.entries(envVars)) {
|
|
19
|
+
await Config.setSecret({ key, value });
|
|
20
|
+
}
|
|
21
|
+
setting.succeed();
|
|
22
|
+
// Restart functions & sites
|
|
23
|
+
const envNames = Object.keys(envVars);
|
|
24
|
+
const restarting = createSpinner(` Restarting all resources using ${blue(envNames.join(", "))}...`).start();
|
|
25
|
+
const { edgeSites, sites, placeholderSites, functions } = await Config.restart(envNames);
|
|
26
|
+
restarting.stop().clear();
|
|
27
|
+
const siteCount = sites.length + placeholderSites.length;
|
|
28
|
+
if (siteCount > 0) {
|
|
29
|
+
Colors.line(Colors.success(`✔ `), siteCount === 1
|
|
30
|
+
? `Reloaded ${siteCount} site`
|
|
31
|
+
: `Reloaded ${siteCount} sites`);
|
|
32
|
+
}
|
|
33
|
+
const functionCount = functions.length;
|
|
34
|
+
if (functionCount > 0) {
|
|
35
|
+
Colors.line(Colors.success(`✔ `), functionCount === 1
|
|
36
|
+
? `Reloaded ${functionCount} function`
|
|
37
|
+
: `Reloaded ${functionCount} functions`);
|
|
38
|
+
}
|
|
39
|
+
edgeSites.forEach(({ id, type }) => {
|
|
40
|
+
Colors.line(Colors.primary(`➜ `), `Redeploy the "${id}" ${type} to use the new secret`);
|
|
41
|
+
});
|
|
42
|
+
await exit();
|
|
18
43
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const envNames = Object.keys(envVars);
|
|
22
|
-
const restarting = createSpinner(` Restarting all resources using ${blue(envNames.join(", "))}...`).start();
|
|
23
|
-
const { edgeSites, sites, placeholderSites, functions } = await Config.restart(envNames);
|
|
24
|
-
restarting.stop().clear();
|
|
25
|
-
const siteCount = sites.length + placeholderSites.length;
|
|
26
|
-
if (siteCount > 0) {
|
|
27
|
-
Colors.line(Colors.success(`✔ `), siteCount === 1
|
|
28
|
-
? `Reloaded ${siteCount} site`
|
|
29
|
-
: `Reloaded ${siteCount} sites`);
|
|
44
|
+
catch (e) {
|
|
45
|
+
await exitWithError(e);
|
|
30
46
|
}
|
|
31
|
-
const functionCount = functions.length;
|
|
32
|
-
if (functionCount > 0) {
|
|
33
|
-
Colors.line(Colors.success(`✔ `), functionCount === 1
|
|
34
|
-
? `Reloaded ${functionCount} function`
|
|
35
|
-
: `Reloaded ${functionCount} functions`);
|
|
36
|
-
}
|
|
37
|
-
edgeSites.forEach(({ id, type }) => {
|
|
38
|
-
Colors.line(Colors.primary(`➜ `), `Redeploy the "${id}" ${type} to use the new secret`);
|
|
39
|
-
});
|
|
40
|
-
process.exit(0);
|
|
41
47
|
});
|
|
@@ -9,6 +9,8 @@ export const remove = (program) => program.command("remove <name>", "Remove a se
|
|
|
9
9
|
describe: "Remove the fallback value",
|
|
10
10
|
}), async (args) => {
|
|
11
11
|
const { Config } = await import("../../../config.js");
|
|
12
|
+
const { exit, exitWithError } = await import("../../program.js");
|
|
13
|
+
const { SilentError } = await import("../../../error.js");
|
|
12
14
|
const { Colors } = await import("../../colors.js");
|
|
13
15
|
try {
|
|
14
16
|
await Config.removeSecret({
|
|
@@ -16,8 +18,10 @@ export const remove = (program) => program.command("remove <name>", "Remove a se
|
|
|
16
18
|
fallback: args.fallback === true,
|
|
17
19
|
});
|
|
18
20
|
Colors.line(Colors.success(`✔ `), `Removed "${args.name}"`);
|
|
21
|
+
await exit();
|
|
19
22
|
}
|
|
20
23
|
catch {
|
|
21
24
|
Colors.line(Colors.danger(`✖ `), `"${args.name}" is not set`);
|
|
25
|
+
await exitWithError(new SilentError(`"${args.name}" is not set`));
|
|
22
26
|
}
|
|
23
27
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Program } from "../../program.js";
|
|
1
|
+
import type { Program } from "../../program.js";
|
|
2
2
|
export declare function secrets(program: Program): void;
|
|
@@ -6,11 +6,11 @@ import { set } from "./set.js";
|
|
|
6
6
|
export function secrets(program) {
|
|
7
7
|
program.command("secrets", "Manage the secrets in your app", (yargs) => {
|
|
8
8
|
yargs.demandCommand(1);
|
|
9
|
-
set(
|
|
10
|
-
get(
|
|
11
|
-
load(
|
|
12
|
-
list(
|
|
13
|
-
remove(
|
|
9
|
+
set(program);
|
|
10
|
+
get(program);
|
|
11
|
+
load(program);
|
|
12
|
+
list(program);
|
|
13
|
+
remove(program);
|
|
14
14
|
return yargs;
|
|
15
15
|
});
|
|
16
16
|
}
|
|
@@ -13,36 +13,42 @@ export const set = (program) => program.command("set <name> <value>", "Set the v
|
|
|
13
13
|
type: "boolean",
|
|
14
14
|
describe: "Set the fallback value",
|
|
15
15
|
}), async (args) => {
|
|
16
|
+
const { exit, exitWithError } = await import("../../program.js");
|
|
16
17
|
const { Config } = await import("../../../config.js");
|
|
17
18
|
const { Colors } = await import("../../colors.js");
|
|
18
19
|
const { blue } = await import("colorette");
|
|
19
20
|
const { createSpinner } = await import("../../spinner.js");
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
21
|
+
try {
|
|
22
|
+
// Set secret value
|
|
23
|
+
const setting = createSpinner(` Setting "${args.name}"`).start();
|
|
24
|
+
await Config.setSecret({
|
|
25
|
+
key: args.name,
|
|
26
|
+
value: args.value,
|
|
27
|
+
fallback: args.fallback === true,
|
|
28
|
+
});
|
|
29
|
+
setting.succeed();
|
|
30
|
+
// Restart functions & sites
|
|
31
|
+
const restarting = createSpinner(` Reloading all resources using ${blue(args.name)}...`).start();
|
|
32
|
+
const { edgeSites, sites, placeholderSites, functions } = await Config.restart([args.name]);
|
|
33
|
+
restarting.stop().clear();
|
|
34
|
+
const siteCount = sites.length + placeholderSites.length;
|
|
35
|
+
if (siteCount > 0) {
|
|
36
|
+
Colors.line(Colors.success(`✔ `), siteCount === 1
|
|
37
|
+
? `Reloaded ${siteCount} site`
|
|
38
|
+
: `Reloaded ${siteCount} sites`);
|
|
39
|
+
}
|
|
40
|
+
const functionCount = functions.length;
|
|
41
|
+
if (functionCount > 0) {
|
|
42
|
+
Colors.line(Colors.success(`✔ `), functionCount === 1
|
|
43
|
+
? `Reloaded ${functionCount} function`
|
|
44
|
+
: `Reloaded ${functionCount} functions`);
|
|
45
|
+
}
|
|
46
|
+
edgeSites.forEach(({ id, type }) => {
|
|
47
|
+
Colors.line(Colors.primary(`➜ `), `Redeploy the "${id}" ${type} to use the new secret`);
|
|
48
|
+
});
|
|
49
|
+
await exit();
|
|
37
50
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
Colors.line(Colors.success(`✔ `), functionCount === 1
|
|
41
|
-
? `Reloaded ${functionCount} function`
|
|
42
|
-
: `Reloaded ${functionCount} functions`);
|
|
51
|
+
catch (e) {
|
|
52
|
+
await exitWithError(e);
|
|
43
53
|
}
|
|
44
|
-
edgeSites.forEach(({ id, type }) => {
|
|
45
|
-
Colors.line(Colors.primary(`➜ `), `Redeploy the "${id}" ${type} to use the new secret`);
|
|
46
|
-
});
|
|
47
|
-
process.exit(0);
|
|
48
54
|
});
|
|
@@ -6,12 +6,19 @@ export const telemetry = (program) => program.command("telemetry <action>", "Loa
|
|
|
6
6
|
demandOption: true,
|
|
7
7
|
}), async (args) => {
|
|
8
8
|
const { enable, disable } = await import("../telemetry/telemetry.js");
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const { exit, exitWithError } = await import("../program.js");
|
|
10
|
+
try {
|
|
11
|
+
if (args.action === "enable") {
|
|
12
|
+
enable();
|
|
13
|
+
Colors.line(Colors.success(`✔ `), `Telemetry enabled`);
|
|
14
|
+
}
|
|
15
|
+
if (args.action === "disable") {
|
|
16
|
+
disable();
|
|
17
|
+
Colors.line(Colors.success(`✔ `), `Telemetry disabled`);
|
|
18
|
+
}
|
|
19
|
+
await exit();
|
|
12
20
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Colors.line(Colors.success(`✔ `), `Telemetry disabled`);
|
|
21
|
+
catch (e) {
|
|
22
|
+
await exitWithError(e);
|
|
16
23
|
}
|
|
17
24
|
});
|
|
@@ -4,12 +4,19 @@ export const transform = (program) => program.command("transform <mod>", "Apply
|
|
|
4
4
|
demandOption: true,
|
|
5
5
|
}), async (args) => {
|
|
6
6
|
const { Colors } = await import("../colors.js");
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
const { exit, exitWithError } = await import("../program.js");
|
|
8
|
+
try {
|
|
9
|
+
if (args.mod === "resource-binding-secrets") {
|
|
10
|
+
await handleSecretsMigration();
|
|
11
|
+
Colors.line(Colors.success(`✔ `), `Transform "${args.mod}" applied successfully!`);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
Colors.line(Colors.danger(`✖ `), `Transform "${args.mod}" not found`);
|
|
15
|
+
await exit();
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
await exitWithError(e);
|
|
11
19
|
}
|
|
12
|
-
Colors.line(Colors.danger(`✖ `), `Transform "${args.mod}" not found`);
|
|
13
20
|
});
|
|
14
21
|
async function handleSecretsMigration() {
|
|
15
22
|
const { useProject } = await import("../../project.js");
|