sst 2.0.0-rc.40 → 2.0.0-rc.41
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/colors.d.ts +18 -0
- package/cli/colors.js +17 -0
- package/cli/commands/console.js +4 -2
- package/cli/commands/deploy.js +4 -8
- package/cli/commands/dev.js +56 -57
- package/cli/commands/diff.js +42 -2
- package/cli/commands/env.js +1 -1
- package/cli/local/server.d.ts +3 -1
- package/cli/local/server.js +11 -4
- package/cli/ui/deploy.js +16 -14
- package/cli/ui/header.d.ts +4 -0
- package/cli/ui/header.js +12 -0
- package/package.json +1 -1
- package/sst.mjs +718 -680
- package/stacks/build.js +30 -30
- package/stacks/diff.d.ts +8 -0
- package/stacks/diff.js +63 -0
- package/stacks/index.d.ts +1 -0
- package/stacks/index.js +1 -0
package/cli/colors.d.ts
CHANGED
|
@@ -1,7 +1,25 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
export declare const Colors: {
|
|
3
|
+
line: (message?: any, ...optionalParams: any[]) => void;
|
|
4
|
+
gap(): void;
|
|
5
|
+
hex: (color: string) => chalk.Chalk;
|
|
3
6
|
primary: chalk.Chalk;
|
|
4
7
|
link: chalk.Chalk;
|
|
5
8
|
success: chalk.Chalk;
|
|
6
9
|
danger: chalk.Chalk;
|
|
10
|
+
warning: chalk.Chalk;
|
|
11
|
+
dim: chalk.Chalk;
|
|
12
|
+
bold: chalk.Chalk;
|
|
13
|
+
all: chalk.Chalk & chalk.ChalkFunction & {
|
|
14
|
+
supportsColor: false | chalk.ColorSupport;
|
|
15
|
+
Level: chalk.Level;
|
|
16
|
+
Color: ("red" | "green" | "yellow" | "black" | "blue" | "magenta" | "cyan" | "white" | "gray" | "grey" | "blackBright" | "redBright" | "greenBright" | "yellowBright" | "blueBright" | "magentaBright" | "cyanBright" | "whiteBright") | ("bgBlack" | "bgRed" | "bgGreen" | "bgYellow" | "bgBlue" | "bgMagenta" | "bgCyan" | "bgWhite" | "bgGray" | "bgGrey" | "bgBlackBright" | "bgRedBright" | "bgGreenBright" | "bgYellowBright" | "bgBlueBright" | "bgMagentaBright" | "bgCyanBright" | "bgWhiteBright");
|
|
17
|
+
ForegroundColor: "red" | "green" | "yellow" | "black" | "blue" | "magenta" | "cyan" | "white" | "gray" | "grey" | "blackBright" | "redBright" | "greenBright" | "yellowBright" | "blueBright" | "magentaBright" | "cyanBright" | "whiteBright";
|
|
18
|
+
BackgroundColor: "bgBlack" | "bgRed" | "bgGreen" | "bgYellow" | "bgBlue" | "bgMagenta" | "bgCyan" | "bgWhite" | "bgGray" | "bgGrey" | "bgBlackBright" | "bgRedBright" | "bgGreenBright" | "bgYellowBright" | "bgBlueBright" | "bgMagentaBright" | "bgCyanBright" | "bgWhiteBright";
|
|
19
|
+
Modifiers: "bold" | "dim" | "reset" | "italic" | "underline" | "inverse" | "hidden" | "strikethrough" | "visible";
|
|
20
|
+
stderr: chalk.Chalk & {
|
|
21
|
+
supportsColor: false | chalk.ColorSupport;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
prefix: string;
|
|
7
25
|
};
|
package/cli/colors.js
CHANGED
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
+
let last = "gap";
|
|
2
3
|
export const Colors = {
|
|
4
|
+
line: (message, ...optionalParams) => {
|
|
5
|
+
last = "line";
|
|
6
|
+
console.log(message, ...optionalParams);
|
|
7
|
+
},
|
|
8
|
+
gap() {
|
|
9
|
+
if (last === "line") {
|
|
10
|
+
last = "gap";
|
|
11
|
+
console.log();
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
hex: chalk.hex,
|
|
3
15
|
primary: chalk.hex("#E27152"),
|
|
4
16
|
link: chalk.cyan,
|
|
5
17
|
success: chalk.green,
|
|
6
18
|
danger: chalk.red,
|
|
19
|
+
warning: chalk.yellow,
|
|
20
|
+
dim: chalk.dim,
|
|
21
|
+
bold: chalk.bold,
|
|
22
|
+
all: chalk,
|
|
23
|
+
prefix: chalk.bold("| "),
|
|
7
24
|
};
|
package/cli/commands/console.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { useLocalServerConfig } from "../local/server.js";
|
|
1
2
|
export const consoleCommand = async (program) => program.command("console", "Start the SST Console", (yargs) => yargs, async () => {
|
|
2
3
|
const { blue } = await import("colorette");
|
|
3
4
|
const { useRuntimeServer } = await import("../../runtime/server.js");
|
|
4
5
|
const { useLocalServer } = await import("../local/server.js");
|
|
5
|
-
|
|
6
|
+
await Promise.all([
|
|
6
7
|
useRuntimeServer(),
|
|
7
8
|
useLocalServer({
|
|
8
9
|
key: "",
|
|
@@ -10,5 +11,6 @@ export const consoleCommand = async (program) => program.command("console", "Sta
|
|
|
10
11
|
live: false,
|
|
11
12
|
}),
|
|
12
13
|
]);
|
|
13
|
-
|
|
14
|
+
const local = await useLocalServerConfig();
|
|
15
|
+
console.log(`Console started: ${local.url}`);
|
|
14
16
|
});
|
package/cli/commands/deploy.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Colors } from "../colors.js";
|
|
2
|
+
import { printHeader } from "../ui/header.js";
|
|
1
3
|
export const deploy = (program) => program.command("deploy [filter]", "Deploy your app to AWS", (yargs) => yargs
|
|
2
4
|
.option("from", {
|
|
3
5
|
type: "string",
|
|
@@ -15,13 +17,8 @@ export const deploy = (program) => program.command("deploy [filter]", "Deploy yo
|
|
|
15
17
|
const { loadAssembly, Stacks } = await import("../../stacks/index.js");
|
|
16
18
|
const { render } = await import("ink");
|
|
17
19
|
const { DeploymentUI } = await import("../ui/deploy.js");
|
|
18
|
-
const { Colors } = await import("../colors.js");
|
|
19
20
|
const project = useProject();
|
|
20
|
-
|
|
21
|
-
console.log(` ${Colors.primary(`${bold(`SST`)} v${project.version}`)}`);
|
|
22
|
-
console.log();
|
|
23
|
-
console.log(` ${Colors.primary(`➜`)} ${bold(`Stage:`)} ${dim(project.config.stage)}`);
|
|
24
|
-
console.log();
|
|
21
|
+
printHeader({});
|
|
25
22
|
// Generate cloud assembly
|
|
26
23
|
// - if --from is specified, we will use the existing cloud assembly
|
|
27
24
|
// - if --from is not specified, we will call synth to generate
|
|
@@ -32,7 +29,6 @@ export const deploy = (program) => program.command("deploy [filter]", "Deploy yo
|
|
|
32
29
|
}
|
|
33
30
|
const spinner = createSpinner({
|
|
34
31
|
text: " Building stacks",
|
|
35
|
-
indent: 2,
|
|
36
32
|
});
|
|
37
33
|
const result = await Stacks.synth({
|
|
38
34
|
fn: project.stacks,
|
|
@@ -45,7 +41,7 @@ export const deploy = (program) => program.command("deploy [filter]", "Deploy yo
|
|
|
45
41
|
const target = assembly.stacks.filter((s) => !args.filter ||
|
|
46
42
|
s.stackName.toLowerCase().includes(args.filter.toLowerCase()));
|
|
47
43
|
if (!target.length) {
|
|
48
|
-
|
|
44
|
+
Colors.line(`No stacks found matching ${blue(args.filter)}`);
|
|
49
45
|
process.exit(1);
|
|
50
46
|
}
|
|
51
47
|
const component = render(React.createElement(DeploymentUI, { stacks: assembly.stacks.map((s) => s.stackName) }));
|
package/cli/commands/dev.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { Colors } from "../colors.js";
|
|
3
|
+
import { printHeader } from "../ui/header.js";
|
|
3
4
|
export const dev = (program) => program.command(["dev", "start"], "Work on your app locally", (yargs) => yargs, async (args) => {
|
|
4
5
|
const { useRuntimeWorkers } = await import("../../runtime/workers.js");
|
|
5
6
|
const { useIOTBridge } = await import("../../runtime/iot.js");
|
|
@@ -27,70 +28,71 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
27
28
|
const { useRDSWarmer } = await import("./plugins/warmer.js");
|
|
28
29
|
const { useProject } = await import("../../project.js");
|
|
29
30
|
const { useMetadata } = await import("../../stacks/metadata.js");
|
|
30
|
-
const { Functions } = await import("../ui/functions.js");
|
|
31
31
|
if (args._[0] === "start") {
|
|
32
32
|
console.log(yellow(`Warning: ${bold(`sst start`)} has been renamed to ${bold(`sst dev`)}`));
|
|
33
33
|
}
|
|
34
34
|
const useFunctionLogger = Context.memo(async () => {
|
|
35
|
-
const component = render(React.createElement(Functions, null));
|
|
36
35
|
const bus = useBus();
|
|
37
|
-
|
|
36
|
+
const colors = ["#01cdfe", "#ff71ce", "#05ffa1", "#b967ff"];
|
|
37
|
+
let index = 0;
|
|
38
|
+
const pending = new Map();
|
|
39
|
+
function start(requestID) {
|
|
40
|
+
pending.set(requestID, {
|
|
41
|
+
requestID,
|
|
42
|
+
started: Date.now(),
|
|
43
|
+
color: colors[index % colors.length],
|
|
44
|
+
});
|
|
45
|
+
index++;
|
|
46
|
+
}
|
|
47
|
+
function prefix(requestID) {
|
|
48
|
+
return Colors.hex(pending.get(requestID).color)(Colors.prefix);
|
|
49
|
+
}
|
|
50
|
+
function end(requestID) {
|
|
51
|
+
// index--;
|
|
52
|
+
// if (index < 0) index = colors.length - 1;
|
|
53
|
+
pending.delete(requestID);
|
|
54
|
+
}
|
|
38
55
|
bus.subscribe("function.invoked", async (evt) => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
useFunctions().fromID(evt.properties.functionID).handler!
|
|
42
|
-
);
|
|
56
|
+
start(evt.properties.requestID);
|
|
57
|
+
Colors.line(prefix(evt.properties.requestID), Colors.dim.bold("Invoked"), Colors.dim(useFunctions().fromID(evt.properties.functionID).handler));
|
|
43
58
|
});
|
|
44
|
-
|
|
59
|
+
bus.subscribe("worker.stdout", async (evt) => {
|
|
60
|
+
const { started } = pending.get(evt.properties.requestID);
|
|
61
|
+
for (let line of evt.properties.message.split("\n")) {
|
|
62
|
+
Colors.line(prefix(evt.properties.requestID), Colors.dim(("+" + (Date.now() - started) + "ms").padEnd(7)), Colors.dim(line));
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
/*
|
|
45
66
|
bus.subscribe("function.build.success", async (evt) => {
|
|
46
67
|
console.log(
|
|
47
68
|
bold(gray(`Built `)),
|
|
48
69
|
useFunctions().fromID(evt.properties.functionID).handler!
|
|
49
70
|
);
|
|
50
71
|
});
|
|
72
|
+
*/
|
|
51
73
|
bus.subscribe("function.build.failed", async (evt) => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
console.log(dim(evt.properties.errors.join("\n")));
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
bus.subscribe("worker.stdout", async (evt) => {
|
|
60
|
-
const { message } = evt.properties;
|
|
61
|
-
const lines = message.split("\n");
|
|
62
|
-
for (let i = 0; i < lines.length; i++) {
|
|
63
|
-
const line = lines[i];
|
|
64
|
-
lines[i] = " " + line;
|
|
65
|
-
}
|
|
66
|
-
console.log(
|
|
67
|
-
bold(blue(` ➜ `)),
|
|
68
|
-
useFunctions().fromID(evt.properties.functionID).handler!
|
|
69
|
-
);
|
|
70
|
-
console.log(dim(lines.join("\n")));
|
|
74
|
+
Colors.line(Colors.danger(Colors.prefix), useFunctions().fromID(evt.properties.functionID).handler);
|
|
75
|
+
for (const line of evt.properties.errors) {
|
|
76
|
+
Colors.line(Colors.danger(Colors.prefix), line);
|
|
77
|
+
}
|
|
71
78
|
});
|
|
72
|
-
*/
|
|
73
|
-
/*
|
|
74
79
|
bus.subscribe("function.success", async (evt) => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
// stdout logs sometimes come in after
|
|
81
|
+
const req = pending.get(evt.properties.requestID);
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
Colors.line(prefix(evt.properties.requestID), Colors.dim(`Done in ${Date.now() - req.started - 100}ms`));
|
|
84
|
+
end(evt.properties.requestID);
|
|
85
|
+
}, 100);
|
|
80
86
|
});
|
|
81
|
-
*/
|
|
82
|
-
/*
|
|
83
87
|
bus.subscribe("function.error", async (evt) => {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
Colors.line(prefix(evt.properties.requestID), Colors.danger.bold("Error:"), Colors.danger.bold(evt.properties.errorMessage));
|
|
90
|
+
for (const line of evt.properties.trace || []) {
|
|
91
|
+
Colors.line(prefix(evt.properties.requestID), `${dim(line)}`);
|
|
92
|
+
}
|
|
93
|
+
end(evt.properties.requestID);
|
|
94
|
+
}, 100);
|
|
92
95
|
});
|
|
93
|
-
*/
|
|
94
96
|
});
|
|
95
97
|
const useStackBuilder = Context.memo(async () => {
|
|
96
98
|
const watcher = useWatcher();
|
|
@@ -100,8 +102,8 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
100
102
|
let pending;
|
|
101
103
|
let isDeploying = false;
|
|
102
104
|
async function build() {
|
|
105
|
+
Colors.gap();
|
|
103
106
|
const spinner = createSpinner({
|
|
104
|
-
indent: 2,
|
|
105
107
|
color: "gray",
|
|
106
108
|
text: lastDeployed
|
|
107
109
|
? ` Building stacks`
|
|
@@ -121,7 +123,7 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
121
123
|
Logger.debug("Checksum", "next", next, "old", lastDeployed);
|
|
122
124
|
if (next === lastDeployed) {
|
|
123
125
|
spinner.succeed(" No changes");
|
|
124
|
-
|
|
126
|
+
Colors.gap();
|
|
125
127
|
return;
|
|
126
128
|
}
|
|
127
129
|
if (!lastDeployed) {
|
|
@@ -137,10 +139,11 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
137
139
|
}
|
|
138
140
|
catch (ex) {
|
|
139
141
|
spinner.fail();
|
|
140
|
-
|
|
142
|
+
Colors.line(ex.stack
|
|
141
143
|
.split("\n")
|
|
142
|
-
.map((line) => "
|
|
144
|
+
.map((line) => " " + line)
|
|
143
145
|
.join("\n"));
|
|
146
|
+
Colors.gap();
|
|
144
147
|
}
|
|
145
148
|
}
|
|
146
149
|
async function deploy() {
|
|
@@ -152,12 +155,12 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
152
155
|
const assembly = pending;
|
|
153
156
|
const nextChecksum = await checksum(assembly.directory);
|
|
154
157
|
pending = undefined;
|
|
155
|
-
|
|
158
|
+
if (lastDeployed)
|
|
159
|
+
console.log();
|
|
156
160
|
const component = render(React.createElement(DeploymentUI, { stacks: assembly.stacks.map((s) => s.stackName) }));
|
|
157
161
|
const results = await Stacks.deployMany(assembly.stacks);
|
|
158
162
|
component.clear();
|
|
159
163
|
component.unmount();
|
|
160
|
-
render(React.createElement(Functions, null));
|
|
161
164
|
lastDeployed = nextChecksum;
|
|
162
165
|
printDeploymentResults(assembly, results);
|
|
163
166
|
const keys = await SiteEnv.keys();
|
|
@@ -208,17 +211,13 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
208
211
|
const project = useProject();
|
|
209
212
|
const primary = chalk.hex("#E27152");
|
|
210
213
|
const link = chalk.cyan;
|
|
211
|
-
|
|
214
|
+
await useLocalServer({
|
|
212
215
|
key: "",
|
|
213
216
|
cert: "",
|
|
214
217
|
live: true,
|
|
215
218
|
});
|
|
216
219
|
console.clear();
|
|
217
|
-
console
|
|
218
|
-
console.log(` ${Colors.primary(`${bold(`SST`)} v${project.version}`)} ${dim(`ready!`)}`);
|
|
219
|
-
console.log();
|
|
220
|
-
console.log(` ${primary(`➜`)} ${bold(`Stage:`)} ${dim(project.config.stage)}`);
|
|
221
|
-
console.log(` ${primary(`➜`)} ${bold(`Console:`)} ${link(local.url)}`);
|
|
220
|
+
await printHeader({ console: true });
|
|
222
221
|
/*
|
|
223
222
|
console.log(` ${primary(`➜`)} ${bold(dim(`Outputs:`))}`);
|
|
224
223
|
for (let i = 0; i < 3; i++) {
|
package/cli/commands/diff.js
CHANGED
|
@@ -2,12 +2,13 @@ export const diff = (program) => program.command("diff", "Compare your app with
|
|
|
2
2
|
type: "boolean",
|
|
3
3
|
describe: "Compare in dev mode",
|
|
4
4
|
}), async (args) => {
|
|
5
|
-
const { printStackDiff } = await import("aws-cdk/lib/diff.js");
|
|
6
5
|
const { useProject } = await import("../../project.js");
|
|
7
6
|
const { Stacks } = await import("../../stacks/index.js");
|
|
8
7
|
const { useAWSClient } = await import("../../credentials.js");
|
|
9
8
|
const { CloudFormationClient, GetTemplateCommand } = await import("@aws-sdk/client-cloudformation");
|
|
10
9
|
const { createSpinner } = await import("../spinner.js");
|
|
10
|
+
const { green } = await import("colorette");
|
|
11
|
+
// Build app
|
|
11
12
|
const spinner = createSpinner("Building stacks");
|
|
12
13
|
const project = useProject();
|
|
13
14
|
const assembly = await Stacks.synth({
|
|
@@ -15,12 +16,51 @@ export const diff = (program) => program.command("diff", "Compare your app with
|
|
|
15
16
|
mode: args.dev ? "dev" : "deploy",
|
|
16
17
|
});
|
|
17
18
|
spinner.succeed();
|
|
19
|
+
console.log("");
|
|
20
|
+
// Diff each stack
|
|
21
|
+
let changesAcc = 0;
|
|
22
|
+
let changedStacks = 0;
|
|
18
23
|
const cfn = useAWSClient(CloudFormationClient);
|
|
19
24
|
for (const stack of assembly.stacks) {
|
|
25
|
+
const spinner = createSpinner(`${stack.stackName}: Checking for changes...`);
|
|
26
|
+
// get old template
|
|
20
27
|
const response = await cfn.send(new GetTemplateCommand({
|
|
21
28
|
StackName: stack.stackName,
|
|
22
29
|
}));
|
|
23
|
-
|
|
30
|
+
const oldTemplate = JSON.parse(response.TemplateBody);
|
|
31
|
+
// generate diff
|
|
32
|
+
const { count, diff } = await Stacks.diff(stack, oldTemplate);
|
|
33
|
+
spinner.clear();
|
|
34
|
+
// print diff result
|
|
35
|
+
if (count === 0) {
|
|
36
|
+
console.log(`➜ ${stack.stackName}: No changes`);
|
|
37
|
+
console.log("");
|
|
38
|
+
}
|
|
39
|
+
else if (count === 1) {
|
|
40
|
+
console.log(`➜ ${stack.stackName}: ${count} change`);
|
|
41
|
+
console.log("");
|
|
42
|
+
console.log(diff);
|
|
43
|
+
changesAcc += count;
|
|
44
|
+
changedStacks++;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.log(`➜ ${stack.stackName}: ${count} changes`);
|
|
48
|
+
console.log("");
|
|
49
|
+
console.log(diff);
|
|
50
|
+
changesAcc += count;
|
|
51
|
+
changedStacks++;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Handle no changes
|
|
55
|
+
if (changedStacks === 0) {
|
|
56
|
+
console.log(green("✔"), " There were no changes");
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
console.log(green("✔"), changesAcc === 1
|
|
60
|
+
? "1 change found in"
|
|
61
|
+
: `${changesAcc} changes found in`, changedStacks === 1
|
|
62
|
+
? "1 stack"
|
|
63
|
+
: `${changedStacks} stacks`);
|
|
24
64
|
}
|
|
25
65
|
process.exit(0);
|
|
26
66
|
});
|
package/cli/commands/env.js
CHANGED
|
@@ -17,7 +17,7 @@ export const env = (program) => program.command("env <command>", "Load environme
|
|
|
17
17
|
.then(() => true)
|
|
18
18
|
.catch(() => false);
|
|
19
19
|
if (!exists) {
|
|
20
|
-
spinner = createSpinner("Waiting for SST to start").start();
|
|
20
|
+
spinner = createSpinner("Cannot find SST environment variables. Waiting for SST to start...").start();
|
|
21
21
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
22
22
|
continue;
|
|
23
23
|
}
|
package/cli/local/server.d.ts
CHANGED
|
@@ -11,9 +11,11 @@ declare module "../../bus.js" {
|
|
|
11
11
|
"local.patches": DendriformPatch[];
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
-
export declare
|
|
14
|
+
export declare const useLocalServerConfig: () => Promise<{
|
|
15
15
|
port: number;
|
|
16
16
|
url: string;
|
|
17
|
+
}>;
|
|
18
|
+
export declare function useLocalServer(opts: Opts): Promise<{
|
|
17
19
|
updateState: (cb: (draft: WritableDraft<State>) => void) => void;
|
|
18
20
|
updateFunction: (id: string, cb: (draft: WritableDraft<FunctionState>) => void) => void;
|
|
19
21
|
}>;
|
package/cli/local/server.js
CHANGED
|
@@ -12,11 +12,20 @@ import { sync } from "cross-spawn";
|
|
|
12
12
|
import { useProject } from "../../project.js";
|
|
13
13
|
import { useBus } from "../../bus.js";
|
|
14
14
|
import getPort from "get-port";
|
|
15
|
-
|
|
15
|
+
import { Context } from "../../context/context.js";
|
|
16
|
+
export const useLocalServerConfig = Context.memo(async () => {
|
|
16
17
|
const project = useProject();
|
|
17
18
|
const port = await getPort({
|
|
18
19
|
port: 13557,
|
|
19
20
|
});
|
|
21
|
+
return {
|
|
22
|
+
port,
|
|
23
|
+
url: `https://console.sst.dev/${project.config.name}/${project.config.stage}${port !== 13557 ? `?port=${port}` : ""}`,
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
export async function useLocalServer(opts) {
|
|
27
|
+
const cfg = await useLocalServerConfig();
|
|
28
|
+
const project = useProject();
|
|
20
29
|
let state = {
|
|
21
30
|
app: project.config.name,
|
|
22
31
|
stage: project.config.stage,
|
|
@@ -106,7 +115,7 @@ export async function useLocalServer(opts) {
|
|
|
106
115
|
console.log("Rejecting unauthorized connection from " + req.headers.origin);
|
|
107
116
|
socket.terminate();
|
|
108
117
|
});
|
|
109
|
-
server.listen(port);
|
|
118
|
+
server.listen(cfg.port);
|
|
110
119
|
const handler = applyWSSHandler({
|
|
111
120
|
wss,
|
|
112
121
|
router,
|
|
@@ -203,8 +212,6 @@ export async function useLocalServer(opts) {
|
|
|
203
212
|
});
|
|
204
213
|
});
|
|
205
214
|
const result = {
|
|
206
|
-
port,
|
|
207
|
-
url: `https://console.sst.dev/${project.config.name}/${project.config.stage}${port !== 13557 ? `?port=${port}` : ""}`,
|
|
208
215
|
updateState,
|
|
209
216
|
updateFunction,
|
|
210
217
|
};
|
package/cli/ui/deploy.js
CHANGED
|
@@ -3,7 +3,6 @@ import { Box, Text } from "ink";
|
|
|
3
3
|
import { useBus } from "../../bus.js";
|
|
4
4
|
import { Stacks } from "../../stacks/index.js";
|
|
5
5
|
import inkSpinner from "ink-spinner";
|
|
6
|
-
import { bold, dim, green, red } from "colorette";
|
|
7
6
|
import { Colors } from "../colors.js";
|
|
8
7
|
// @ts-ignore
|
|
9
8
|
const { default: Spinner } = inkSpinner;
|
|
@@ -12,7 +11,9 @@ export const DeploymentUI = (props) => {
|
|
|
12
11
|
const [resources, setResources] = useState({});
|
|
13
12
|
const [resources2, setResources2] = useState({});
|
|
14
13
|
useEffect(() => {
|
|
15
|
-
|
|
14
|
+
Colors.gap();
|
|
15
|
+
Colors.line(`${Colors.primary(`➜`)} ${Colors.bold(`Deploying...`)}`);
|
|
16
|
+
Colors.gap();
|
|
16
17
|
const bus = useBus();
|
|
17
18
|
const update = bus.subscribe("stack.updated", (payload) => {
|
|
18
19
|
setStacks((prev) => ({
|
|
@@ -32,9 +33,9 @@ export const DeploymentUI = (props) => {
|
|
|
32
33
|
return;
|
|
33
34
|
setResources2((previous) => {
|
|
34
35
|
if (Stacks.isFinal(event.ResourceStatus)) {
|
|
35
|
-
|
|
36
|
+
Colors.line(Colors.warning(Colors.prefix), Colors.dim(`${event.StackName} ${event.ResourceType} ${event.LogicalResourceId}`), Stacks.isFailed(event.ResourceStatus)
|
|
36
37
|
? Colors.danger(event.ResourceStatus)
|
|
37
|
-
: dim(event.ResourceStatus));
|
|
38
|
+
: Colors.dim(event.ResourceStatus));
|
|
38
39
|
const { [event.LogicalResourceId]: _, ...next } = previous;
|
|
39
40
|
return next;
|
|
40
41
|
}
|
|
@@ -61,7 +62,6 @@ export const DeploymentUI = (props) => {
|
|
|
61
62
|
Object.entries(resources2).map(([_, evt]) => {
|
|
62
63
|
return (React.createElement(Box, { key: evt.LogicalResourceId },
|
|
63
64
|
React.createElement(Text, null,
|
|
64
|
-
" ",
|
|
65
65
|
React.createElement(Spinner, null),
|
|
66
66
|
" ",
|
|
67
67
|
evt.StackName,
|
|
@@ -75,9 +75,11 @@ export const DeploymentUI = (props) => {
|
|
|
75
75
|
React.createElement(Box, null)));
|
|
76
76
|
};
|
|
77
77
|
export function printDeploymentResults(assembly, results) {
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
Colors.gap();
|
|
79
|
+
Colors.line(Colors.success(`✔`), Colors.bold(` Deployed`));
|
|
80
80
|
for (const [stack, result] of Object.entries(results)) {
|
|
81
|
+
if (Object.values(result.errors).length)
|
|
82
|
+
continue;
|
|
81
83
|
const outputs = Object.entries(result.outputs).filter(([key, _]) => {
|
|
82
84
|
if (key.startsWith("Export"))
|
|
83
85
|
return false;
|
|
@@ -87,22 +89,22 @@ export function printDeploymentResults(assembly, results) {
|
|
|
87
89
|
return false;
|
|
88
90
|
return true;
|
|
89
91
|
});
|
|
90
|
-
|
|
92
|
+
Colors.line(` ${Colors.dim(stack)}`);
|
|
91
93
|
if (outputs.length > 0) {
|
|
92
94
|
for (const key of Object.keys(Object.fromEntries(outputs)).sort()) {
|
|
93
95
|
const value = result.outputs[key];
|
|
94
|
-
|
|
96
|
+
Colors.line(` ${Colors.bold.dim(key)}: ${value}`);
|
|
95
97
|
}
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
|
-
|
|
100
|
+
Colors.gap();
|
|
99
101
|
if (Object.values(results).flatMap((s) => Object.keys(s.errors)).length) {
|
|
100
|
-
|
|
102
|
+
Colors.line(`${Colors.danger(`✖`)} ${Colors.bold.dim(`Errors`)}`);
|
|
101
103
|
for (const [stack, result] of Object.entries(results)) {
|
|
102
104
|
const hasErrors = Object.entries(result.errors).length > 0;
|
|
103
105
|
if (!hasErrors)
|
|
104
106
|
continue;
|
|
105
|
-
|
|
107
|
+
Colors.line(` ${Colors.dim(stack)}`);
|
|
106
108
|
for (const [id, error] of Object.entries(result.errors)) {
|
|
107
109
|
const found = Object.entries(assembly.manifest.artifacts?.[stack].metadata || {}).find(([_key, value]) => value[0]?.type === "aws:cdk:logicalId" && value[0]?.data === id)?.[0] || "";
|
|
108
110
|
const readable = found
|
|
@@ -110,9 +112,9 @@ export function printDeploymentResults(assembly, results) {
|
|
|
110
112
|
.filter(Boolean)
|
|
111
113
|
.slice(1, -1)
|
|
112
114
|
.join("/");
|
|
113
|
-
|
|
115
|
+
Colors.line(` ${Colors.danger.bold(readable)}: ${error}`);
|
|
114
116
|
}
|
|
115
|
-
console.log();
|
|
116
117
|
}
|
|
118
|
+
Colors.gap();
|
|
117
119
|
}
|
|
118
120
|
}
|
package/cli/ui/header.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Colors } from "../colors.js";
|
|
2
|
+
import { useLocalServerConfig } from "../local/server.js";
|
|
3
|
+
export async function printHeader(input) {
|
|
4
|
+
const local = await useLocalServerConfig();
|
|
5
|
+
Colors.line(`${Colors.primary.bold("SST v2.0.4")} ${Colors.dim(`ready!`)}`);
|
|
6
|
+
Colors.gap();
|
|
7
|
+
Colors.line(`${Colors.primary(`➜`)} ${Colors.bold("Stage:")} dev`);
|
|
8
|
+
if (input.console)
|
|
9
|
+
Colors.line(`${Colors.primary(`➜`)} ${Colors.bold("Console:")} ${Colors.link(local.url)}`);
|
|
10
|
+
Colors.gap();
|
|
11
|
+
}
|
|
12
|
+
export function printConsole() { }
|