onflyt-cli 1.0.1-beta.2 → 1.0.1-beta.3
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.
Potentially problematic release.
This version of onflyt-cli might be problematic. Click here for more details.
- package/dist/App.d.ts +3 -0
- package/dist/App.js +8 -0
- package/dist/commands/credits.d.ts +3 -0
- package/dist/commands/credits.js +101 -0
- package/dist/commands/delete.d.ts +7 -0
- package/dist/commands/delete.js +220 -0
- package/dist/commands/deploy.d.ts +6 -0
- package/dist/commands/deploy.js +715 -0
- package/dist/commands/deployments.d.ts +6 -0
- package/dist/commands/deployments.js +225 -0
- package/dist/commands/help.d.ts +3 -0
- package/dist/commands/help.js +76 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.js +422 -0
- package/dist/commands/login.d.ts +6 -0
- package/dist/commands/login.js +150 -0
- package/dist/commands/logout.d.ts +3 -0
- package/dist/commands/logout.js +19 -0
- package/dist/commands/logs.d.ts +7 -0
- package/dist/commands/logs.js +307 -0
- package/dist/commands/projects.d.ts +3 -0
- package/dist/commands/projects.js +203 -0
- package/dist/commands/rollback.d.ts +6 -0
- package/dist/commands/rollback.js +316 -0
- package/dist/commands/teams.d.ts +3 -0
- package/dist/commands/teams.js +81 -0
- package/dist/commands/whoami.d.ts +3 -0
- package/dist/commands/whoami.js +34 -0
- package/dist/components/Loading.d.ts +13 -0
- package/dist/components/Loading.js +42 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +77 -116
- package/dist/lib/api.d.ts +27 -0
- package/dist/lib/api.js +109 -0
- package/dist/lib/config.d.ts +32 -0
- package/dist/lib/config.js +52 -0
- package/dist/lib/deploy-api.d.ts +97 -0
- package/dist/lib/deploy-api.js +335 -0
- package/dist/lib/deploy.d.ts +36 -0
- package/dist/lib/deploy.js +181 -0
- package/dist/lib/framework.d.ts +27 -0
- package/dist/lib/framework.js +184 -0
- package/dist/lib/git.d.ts +25 -0
- package/dist/lib/git.js +149 -0
- package/dist/lib/scaffold.d.ts +21 -0
- package/dist/lib/scaffold.js +190 -0
- package/dist/shared/frameworks/registry.d.ts +21 -0
- package/dist/shared/frameworks/registry.js +196 -0
- package/dist/shared/index.d.ts +4 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/limits.d.ts +16 -0
- package/dist/shared/limits.js +44 -0
- package/dist/shared/pricing.d.ts +2 -0
- package/dist/shared/pricing.js +7 -0
- package/dist/shared/templates/registry.d.ts +9 -0
- package/dist/shared/templates/registry.js +47 -0
- package/package.json +2 -3
- package/src/App.tsx +1 -1
- package/src/commands/deploy.tsx +1 -1
- package/src/commands/help.tsx +1 -1
- package/src/commands/init.tsx +1 -1
- package/src/commands/projects.tsx +1 -1
- package/src/components/Loading.tsx +1 -1
- package/src/index.tsx +1 -1
- package/src/lib/deploy-api.ts +3 -3
- package/src/lib/framework.ts +2 -2
- package/src/lib/shared.ts +350 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { Text, Box, useInput } from "ink";
|
|
3
|
+
import { isLoggedIn, getConfig } from "../lib/config.js";
|
|
4
|
+
import { api } from "../lib/api.js";
|
|
5
|
+
import { Logo } from "../components/Loading.js";
|
|
6
|
+
import Spinner from "ink-spinner";
|
|
7
|
+
const Rollback = ({ deploymentId }) => {
|
|
8
|
+
const [step, setStep] = useState("loading");
|
|
9
|
+
const [teams, setTeams] = useState([]);
|
|
10
|
+
const [projects, setProjects] = useState([]);
|
|
11
|
+
const [deployments, setDeployments] = useState([]);
|
|
12
|
+
const [selectedTeamIndex, setSelectedTeamIndex] = useState(0);
|
|
13
|
+
const [selectedProjectIndex, setSelectedProjectIndex] = useState(0);
|
|
14
|
+
const [selectedDeployIndex, setSelectedDeployIndex] = useState(0);
|
|
15
|
+
const [targetProject, setTargetProject] = useState(null);
|
|
16
|
+
const [targetDeployment, setTargetDeployment] = useState(null);
|
|
17
|
+
const [errorMsg, setErrorMsg] = useState("");
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const handleSigInt = () => process.exit(0);
|
|
20
|
+
process.on("SIGINT", handleSigInt);
|
|
21
|
+
return () => {
|
|
22
|
+
process.off("SIGINT", handleSigInt);
|
|
23
|
+
};
|
|
24
|
+
}, []);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (step === "done" || step === "error") {
|
|
27
|
+
const timer = setTimeout(() => process.exit(0), 500);
|
|
28
|
+
return () => clearTimeout(timer);
|
|
29
|
+
}
|
|
30
|
+
}, [step]);
|
|
31
|
+
useInput((input, key) => {
|
|
32
|
+
if (input === "q" || input === "Q" || (key.ctrl && input === "c")) {
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
if (step === "team") {
|
|
36
|
+
if (key.upArrow) {
|
|
37
|
+
setSelectedTeamIndex((i) => Math.max(0, i - 1));
|
|
38
|
+
}
|
|
39
|
+
else if (key.downArrow) {
|
|
40
|
+
setSelectedTeamIndex((i) => Math.min(teams.length - 1, i + 1));
|
|
41
|
+
}
|
|
42
|
+
else if (key.return) {
|
|
43
|
+
setStep("loading-projects");
|
|
44
|
+
loadProjects(teams[selectedTeamIndex].team.id);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (step === "project") {
|
|
48
|
+
if (key.upArrow) {
|
|
49
|
+
setSelectedProjectIndex((i) => Math.max(0, i - 1));
|
|
50
|
+
}
|
|
51
|
+
else if (key.downArrow) {
|
|
52
|
+
setSelectedProjectIndex((i) => Math.min(projects.length - 1, i + 1));
|
|
53
|
+
}
|
|
54
|
+
else if (key.return) {
|
|
55
|
+
setStep("loading-deployments");
|
|
56
|
+
loadDeploymentsForProject(projects[selectedProjectIndex]);
|
|
57
|
+
}
|
|
58
|
+
else if (key.escape) {
|
|
59
|
+
setStep("team");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (step === "deploy") {
|
|
63
|
+
if (key.upArrow) {
|
|
64
|
+
setSelectedDeployIndex((i) => Math.max(0, i - 1));
|
|
65
|
+
}
|
|
66
|
+
else if (key.downArrow) {
|
|
67
|
+
setSelectedDeployIndex((i) => Math.min(deployments.length - 1, i + 1));
|
|
68
|
+
}
|
|
69
|
+
else if (key.return) {
|
|
70
|
+
setTargetDeployment(deployments[selectedDeployIndex]);
|
|
71
|
+
setStep("confirm");
|
|
72
|
+
}
|
|
73
|
+
else if (key.escape) {
|
|
74
|
+
setStep("project");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (step === "confirm") {
|
|
78
|
+
if (input === "y" || input === "Y" || key.return) {
|
|
79
|
+
performRollback(targetDeployment.id, targetProject.id);
|
|
80
|
+
}
|
|
81
|
+
else if (input === "n" || input === "N" || key.escape) {
|
|
82
|
+
setStep("deploy");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
if (!isLoggedIn()) {
|
|
88
|
+
setErrorMsg("Not logged in. Run 'onflyt login' first.");
|
|
89
|
+
setStep("error");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (deploymentId) {
|
|
93
|
+
setErrorMsg("Direct deployment rollback not yet supported. Please select from list.");
|
|
94
|
+
setStep("error");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
loadTeams();
|
|
98
|
+
}, []);
|
|
99
|
+
const loadTeams = async () => {
|
|
100
|
+
try {
|
|
101
|
+
const config = getConfig();
|
|
102
|
+
api.setToken(config.token);
|
|
103
|
+
const meData = await api.get("/auth/me");
|
|
104
|
+
const userTeams = meData.teams || [];
|
|
105
|
+
if (userTeams.length === 0) {
|
|
106
|
+
setErrorMsg("No teams found");
|
|
107
|
+
setStep("error");
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
setTeams(userTeams);
|
|
111
|
+
if (userTeams.length === 1) {
|
|
112
|
+
setSelectedTeamIndex(0);
|
|
113
|
+
setStep("loading-projects");
|
|
114
|
+
loadProjects(userTeams[0].team.id);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
setStep("team");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
setErrorMsg(err.message);
|
|
122
|
+
setStep("error");
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const loadProjects = async (teamId) => {
|
|
126
|
+
try {
|
|
127
|
+
const projectsRes = await api.get(`/projects/team/${teamId}`);
|
|
128
|
+
const teamProjects = projectsRes.projects || [];
|
|
129
|
+
if (teamProjects.length === 0) {
|
|
130
|
+
setErrorMsg("No projects found in this team");
|
|
131
|
+
setStep("error");
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
setProjects(teamProjects);
|
|
135
|
+
setSelectedProjectIndex(0);
|
|
136
|
+
setStep("project");
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
setErrorMsg(err.message);
|
|
140
|
+
setStep("error");
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
const loadDeploymentsForProject = async (project) => {
|
|
144
|
+
try {
|
|
145
|
+
setTargetProject(project);
|
|
146
|
+
const depsRes = await api.get(`/deployments/${project.id}?limit=50`);
|
|
147
|
+
const allDeployments = depsRes.deployments || [];
|
|
148
|
+
if (allDeployments.length === 0) {
|
|
149
|
+
setErrorMsg("No deployments found for this project");
|
|
150
|
+
setStep("error");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
setDeployments(allDeployments);
|
|
154
|
+
setSelectedDeployIndex(0);
|
|
155
|
+
setStep("deploy");
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
setErrorMsg(err.message);
|
|
159
|
+
setStep("error");
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
const performRollback = async (depId, projectId) => {
|
|
163
|
+
setStep("rolling");
|
|
164
|
+
try {
|
|
165
|
+
await api.post(`/deployments/${projectId}/${depId}/activate`);
|
|
166
|
+
setStep("done");
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
setErrorMsg(err.message);
|
|
170
|
+
setStep("error");
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
if (step === "loading") {
|
|
174
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
175
|
+
React.createElement(Logo, null),
|
|
176
|
+
React.createElement(Box, { marginTop: 1 },
|
|
177
|
+
React.createElement(Text, null, "Loading..."))));
|
|
178
|
+
}
|
|
179
|
+
if (step === "loading-projects") {
|
|
180
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
181
|
+
React.createElement(Logo, null),
|
|
182
|
+
React.createElement(Box, { marginTop: 1 },
|
|
183
|
+
React.createElement(Text, { bold: true }, "Rollback Deployment")),
|
|
184
|
+
React.createElement(Box, { marginTop: 1 },
|
|
185
|
+
React.createElement(Text, { dimColor: true }, "Loading projects...")),
|
|
186
|
+
React.createElement(Box, { marginTop: 1 },
|
|
187
|
+
React.createElement(Spinner, null))));
|
|
188
|
+
}
|
|
189
|
+
if (step === "loading-deployments") {
|
|
190
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
191
|
+
React.createElement(Logo, null),
|
|
192
|
+
React.createElement(Box, { marginTop: 1 },
|
|
193
|
+
React.createElement(Text, { bold: true }, "Rollback Deployment")),
|
|
194
|
+
React.createElement(Box, { marginTop: 1 },
|
|
195
|
+
React.createElement(Text, { dimColor: true }, "Loading deployments...")),
|
|
196
|
+
React.createElement(Box, { marginTop: 1 },
|
|
197
|
+
React.createElement(Spinner, null))));
|
|
198
|
+
}
|
|
199
|
+
if (step === "error") {
|
|
200
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
201
|
+
React.createElement(Logo, null),
|
|
202
|
+
React.createElement(Box, { marginTop: 1 },
|
|
203
|
+
React.createElement(Text, { bold: true, color: "red" }, "\u2716 Error")),
|
|
204
|
+
React.createElement(Box, { marginTop: 1 },
|
|
205
|
+
React.createElement(Text, { color: "red" }, errorMsg))));
|
|
206
|
+
}
|
|
207
|
+
if (step === "rolling") {
|
|
208
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
209
|
+
React.createElement(Logo, null),
|
|
210
|
+
React.createElement(Box, { marginTop: 1 },
|
|
211
|
+
React.createElement(Text, null, "Rolling back deployment..."))));
|
|
212
|
+
}
|
|
213
|
+
if (step === "done") {
|
|
214
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
215
|
+
React.createElement(Logo, null),
|
|
216
|
+
React.createElement(Box, { marginTop: 1 },
|
|
217
|
+
React.createElement(Text, { bold: true, color: "green" }, "\u2713 Rollback successful")),
|
|
218
|
+
React.createElement(Box, { marginTop: 1 },
|
|
219
|
+
React.createElement(Text, { dimColor: true }, "Run 'onflyt logs' to monitor progress"))));
|
|
220
|
+
}
|
|
221
|
+
if (step === "team") {
|
|
222
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
223
|
+
React.createElement(Logo, null),
|
|
224
|
+
React.createElement(Box, { marginTop: 1 },
|
|
225
|
+
React.createElement(Text, { bold: true }, "Rollback Deployment")),
|
|
226
|
+
React.createElement(Box, { marginTop: 1 },
|
|
227
|
+
React.createElement(Text, { dimColor: true }, "Step 1/3: Select Team (\u2191\u2193 navigate, Enter select)")),
|
|
228
|
+
React.createElement(Box, { marginTop: 1, flexDirection: "column" }, teams.map((t, idx) => (React.createElement(Box, { key: t.team.id, marginTop: 1 },
|
|
229
|
+
React.createElement(Text, { color: idx === selectedTeamIndex ? "cyan" : "gray" }, idx === selectedTeamIndex ? "▶ " : " "),
|
|
230
|
+
React.createElement(Text, { bold: idx === selectedTeamIndex }, t.team.name)))))));
|
|
231
|
+
}
|
|
232
|
+
if (step === "project") {
|
|
233
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
234
|
+
React.createElement(Logo, null),
|
|
235
|
+
React.createElement(Box, { marginTop: 1 },
|
|
236
|
+
React.createElement(Text, { bold: true }, "Rollback Deployment")),
|
|
237
|
+
React.createElement(Box, { marginTop: 1 },
|
|
238
|
+
React.createElement(Text, { dimColor: true },
|
|
239
|
+
"Step 2/3: Select Project - ",
|
|
240
|
+
teams[selectedTeamIndex]?.team.name)),
|
|
241
|
+
React.createElement(Box, { marginTop: 1 },
|
|
242
|
+
React.createElement(Text, { dimColor: true }, "(\u2191\u2193 navigate, Enter select, Esc go back)")),
|
|
243
|
+
React.createElement(Box, { marginTop: 1, flexDirection: "column" }, projects.map((p, idx) => (React.createElement(Box, { key: p.id, marginTop: 1 },
|
|
244
|
+
React.createElement(Text, { color: idx === selectedProjectIndex ? "cyan" : "gray" }, idx === selectedProjectIndex ? "▶ " : " "),
|
|
245
|
+
React.createElement(Text, { bold: idx === selectedProjectIndex }, p.name)))))));
|
|
246
|
+
}
|
|
247
|
+
if (step === "deploy") {
|
|
248
|
+
const formatDate = (dateStr) => {
|
|
249
|
+
const date = new Date(dateStr);
|
|
250
|
+
return date.toLocaleDateString() + " " + date.toLocaleTimeString();
|
|
251
|
+
};
|
|
252
|
+
const activeDepId = targetProject?.activeDeploymentId;
|
|
253
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
254
|
+
React.createElement(Logo, null),
|
|
255
|
+
React.createElement(Box, { marginTop: 1 },
|
|
256
|
+
React.createElement(Text, { bold: true }, "Rollback Deployment")),
|
|
257
|
+
React.createElement(Box, { marginTop: 1 },
|
|
258
|
+
React.createElement(Text, { dimColor: true },
|
|
259
|
+
"Step 3/3: Select Deployment - ",
|
|
260
|
+
targetProject?.name)),
|
|
261
|
+
React.createElement(Box, { marginTop: 1 },
|
|
262
|
+
React.createElement(Text, { dimColor: true }, "(\u2191\u2193 navigate, Enter select, Esc go back)")),
|
|
263
|
+
React.createElement(Box, { marginTop: 1, flexDirection: "column" }, deployments.map((dep, idx) => {
|
|
264
|
+
const isActive = dep.id === activeDepId;
|
|
265
|
+
const statusColor = isActive
|
|
266
|
+
? "green"
|
|
267
|
+
: dep.status === "live"
|
|
268
|
+
? "cyan"
|
|
269
|
+
: "gray";
|
|
270
|
+
const statusLabel = isActive
|
|
271
|
+
? " [ACTIVE]"
|
|
272
|
+
: dep.status === "live"
|
|
273
|
+
? " [DEPLOYED]"
|
|
274
|
+
: dep.status === "failed"
|
|
275
|
+
? " [FAILED]"
|
|
276
|
+
: ` [${dep.status.toUpperCase()}]`;
|
|
277
|
+
return (React.createElement(Box, { key: dep.id, marginTop: 1, flexDirection: "column" },
|
|
278
|
+
React.createElement(Box, null,
|
|
279
|
+
React.createElement(Text, { color: idx === selectedDeployIndex ? "cyan" : "gray" }, idx === selectedDeployIndex ? "▶ " : " "),
|
|
280
|
+
React.createElement(Text, { bold: idx === selectedDeployIndex }, dep.commitMessage || "Manual Upload"),
|
|
281
|
+
React.createElement(Text, { color: statusColor }, statusLabel)),
|
|
282
|
+
React.createElement(Box, { marginLeft: 2 },
|
|
283
|
+
React.createElement(Text, { dimColor: true },
|
|
284
|
+
"ID: ",
|
|
285
|
+
dep.id)),
|
|
286
|
+
React.createElement(Box, { marginLeft: 2 },
|
|
287
|
+
React.createElement(Text, { dimColor: true }, formatDate(dep.createdAt)))));
|
|
288
|
+
}))));
|
|
289
|
+
}
|
|
290
|
+
if (step === "confirm") {
|
|
291
|
+
const isActive = targetDeployment?.id === targetProject?.activeDeploymentId;
|
|
292
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
293
|
+
React.createElement(Logo, null),
|
|
294
|
+
React.createElement(Box, { marginTop: 1 },
|
|
295
|
+
React.createElement(Text, { bold: true, color: "yellow" }, "\u26A0 Confirm Rollback")),
|
|
296
|
+
React.createElement(Box, { marginTop: 1 },
|
|
297
|
+
React.createElement(Text, null,
|
|
298
|
+
"Project: ",
|
|
299
|
+
React.createElement(Text, { bold: true }, targetProject?.name))),
|
|
300
|
+
React.createElement(Box, { marginTop: 1 },
|
|
301
|
+
React.createElement(Text, null,
|
|
302
|
+
"Deployment:",
|
|
303
|
+
" ",
|
|
304
|
+
React.createElement(Text, { bold: true }, targetDeployment?.commitMessage || "Manual Upload"))),
|
|
305
|
+
React.createElement(Box, { marginTop: 1 },
|
|
306
|
+
React.createElement(Text, { dimColor: true },
|
|
307
|
+
"ID: ",
|
|
308
|
+
targetDeployment?.id)),
|
|
309
|
+
isActive && (React.createElement(Box, { marginTop: 1 },
|
|
310
|
+
React.createElement(Text, { color: "yellow" }, "\u26A0 This is the currently active deployment"))),
|
|
311
|
+
React.createElement(Box, { marginTop: 2 },
|
|
312
|
+
React.createElement(Text, null, "[Y] Yes, rollback [N] Cancel"))));
|
|
313
|
+
}
|
|
314
|
+
return null;
|
|
315
|
+
};
|
|
316
|
+
export default Rollback;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { api } from "../lib/api.js";
|
|
3
|
+
import { getConfig, isLoggedIn } from "../lib/config.js";
|
|
4
|
+
import { ErrorDisplay } from "../components/Loading.js";
|
|
5
|
+
const MAX_RETRIES = 3;
|
|
6
|
+
const Teams = () => {
|
|
7
|
+
const [state, setState] = useState("loading");
|
|
8
|
+
const [errorMsg, setErrorMsg] = useState("");
|
|
9
|
+
const [retryCount, setRetryCount] = useState(0);
|
|
10
|
+
const [teams, setTeams] = useState([]);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (state !== "done")
|
|
13
|
+
return;
|
|
14
|
+
console.log("\n");
|
|
15
|
+
console.log(" Your Teams\n");
|
|
16
|
+
console.log(" " + "─".repeat(50));
|
|
17
|
+
if (teams.length === 0) {
|
|
18
|
+
console.log(" No teams found. Create a team from the dashboard.");
|
|
19
|
+
console.log("");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
teams.forEach((team, index) => {
|
|
23
|
+
const isDefault = index === 0;
|
|
24
|
+
console.log(` ${index + 1}. ${team.team.name} ${isDefault ? "(default)" : ""}`);
|
|
25
|
+
console.log(` Role: ${team.role}`);
|
|
26
|
+
console.log(` ID: ${team.team.id}`);
|
|
27
|
+
console.log(` Slug: ${team.team.slug}`);
|
|
28
|
+
console.log(` Plan: ${team.team.plan}`);
|
|
29
|
+
console.log(` Created: ${new Date(team.team.createdAt).toLocaleDateString()}`);
|
|
30
|
+
console.log("");
|
|
31
|
+
});
|
|
32
|
+
console.log(" " + "─".repeat(50));
|
|
33
|
+
console.log("\n Use --team flag: onflyt deploy --team tm_xxx\n");
|
|
34
|
+
}, [state, teams]);
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (!isLoggedIn()) {
|
|
37
|
+
setErrorMsg("Not logged in. Run 'onflyt login' first.");
|
|
38
|
+
setState("error");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const fetchTeams = async () => {
|
|
42
|
+
let attempt = 0;
|
|
43
|
+
const attemptFetch = async () => {
|
|
44
|
+
attempt++;
|
|
45
|
+
try {
|
|
46
|
+
console.log(`\n Fetching teams...${attempt > 1 ? ` (retry ${attempt}/${MAX_RETRIES})` : ""}\n`);
|
|
47
|
+
const config = getConfig();
|
|
48
|
+
api.setToken(config.token);
|
|
49
|
+
const meData = await api.get("/auth/me");
|
|
50
|
+
const userTeams = meData.teams || [];
|
|
51
|
+
setTeams(userTeams);
|
|
52
|
+
setState("done");
|
|
53
|
+
return meData;
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
if (attempt < MAX_RETRIES) {
|
|
57
|
+
setRetryCount(attempt);
|
|
58
|
+
return attemptFetch();
|
|
59
|
+
}
|
|
60
|
+
throw err;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
try {
|
|
64
|
+
await attemptFetch();
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
setErrorMsg(err.message || "Failed to fetch teams");
|
|
68
|
+
setState("error");
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
fetchTeams();
|
|
72
|
+
}, []);
|
|
73
|
+
if (state === "loading") {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
if (state === "error") {
|
|
77
|
+
return React.createElement(ErrorDisplay, { message: errorMsg });
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
};
|
|
81
|
+
export default Teams;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Text, Box } from "ink";
|
|
3
|
+
import { getConfig, isLoggedIn } from "../lib/config.js";
|
|
4
|
+
import { Logo, ErrorDisplay } from "../components/Loading.js";
|
|
5
|
+
const WhoAmI = () => {
|
|
6
|
+
const config = getConfig();
|
|
7
|
+
if (!isLoggedIn()) {
|
|
8
|
+
return React.createElement(ErrorDisplay, { message: "Not logged in. Run 'onflyt login' first." });
|
|
9
|
+
}
|
|
10
|
+
const { user, token, lastLogin } = config;
|
|
11
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
12
|
+
React.createElement(Logo, null),
|
|
13
|
+
React.createElement(Box, { marginTop: 1 },
|
|
14
|
+
React.createElement(Text, { bold: true }, "Logged in as:")),
|
|
15
|
+
React.createElement(Box, { marginTop: 1 },
|
|
16
|
+
React.createElement(Text, null, "Name: "),
|
|
17
|
+
React.createElement(Text, { bold: true }, user?.name || "Unknown")),
|
|
18
|
+
React.createElement(Box, { marginTop: 1 },
|
|
19
|
+
React.createElement(Text, null, "Email: "),
|
|
20
|
+
React.createElement(Text, null, user?.email)),
|
|
21
|
+
user?.avatar && (React.createElement(Box, { marginTop: 1 },
|
|
22
|
+
React.createElement(Text, { dimColor: true },
|
|
23
|
+
"Avatar: ",
|
|
24
|
+
user.avatar))),
|
|
25
|
+
React.createElement(Box, { marginTop: 1 },
|
|
26
|
+
React.createElement(Text, { dimColor: true },
|
|
27
|
+
"User ID: ",
|
|
28
|
+
user?.id)),
|
|
29
|
+
lastLogin && (React.createElement(Box, { marginTop: 1 },
|
|
30
|
+
React.createElement(Text, { dimColor: true },
|
|
31
|
+
"Last login: ",
|
|
32
|
+
new Date(lastLogin).toLocaleString())))));
|
|
33
|
+
};
|
|
34
|
+
export default WhoAmI;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export declare const Logo: React.FC;
|
|
3
|
+
interface LoadingProps {
|
|
4
|
+
message: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const Loading: React.FC<LoadingProps>;
|
|
7
|
+
export declare const ErrorDisplay: React.FC<{
|
|
8
|
+
message: string;
|
|
9
|
+
}>;
|
|
10
|
+
export declare const Success: React.FC<{
|
|
11
|
+
message: string;
|
|
12
|
+
}>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Text, Box } from "ink";
|
|
3
|
+
const bigText = (str) => {
|
|
4
|
+
return str
|
|
5
|
+
.split("")
|
|
6
|
+
.map((c) => {
|
|
7
|
+
const code = c.toUpperCase().charCodeAt(0);
|
|
8
|
+
if (code >= 65 && code <= 90) {
|
|
9
|
+
return String.fromCharCode(0xff21 + code - 65);
|
|
10
|
+
}
|
|
11
|
+
return c;
|
|
12
|
+
})
|
|
13
|
+
.join("");
|
|
14
|
+
};
|
|
15
|
+
export const Logo = () => (React.createElement(Box, { flexDirection: "column" },
|
|
16
|
+
React.createElement(Box, { alignItems: "center" },
|
|
17
|
+
React.createElement(Box, { flexDirection: "column", marginRight: 0.5 },
|
|
18
|
+
React.createElement(Text, { color: "rgb(255,191,0)" }, " \u2B21 ")),
|
|
19
|
+
React.createElement(Text, { bold: true, color: "rgb(255,191,0)" }, bigText("Onflyt")),
|
|
20
|
+
React.createElement(Text, null, " "),
|
|
21
|
+
React.createElement(Text, { bold: true, color: "black", backgroundColor: "rgb(255,191,0)" },
|
|
22
|
+
" ",
|
|
23
|
+
"v1.0.1-beta.1",
|
|
24
|
+
" ")),
|
|
25
|
+
React.createElement(Box, { marginTop: 1 },
|
|
26
|
+
React.createElement(Text, { dimColor: true }, "─".repeat(30)))));
|
|
27
|
+
export const Loading = ({ message }) => (React.createElement(Box, { flexDirection: "column" },
|
|
28
|
+
React.createElement(Logo, null),
|
|
29
|
+
React.createElement(Box, { marginTop: 1 },
|
|
30
|
+
React.createElement(Text, null, message))));
|
|
31
|
+
export const ErrorDisplay = ({ message }) => (React.createElement(Box, { flexDirection: "column" },
|
|
32
|
+
React.createElement(Logo, null),
|
|
33
|
+
React.createElement(Box, { marginTop: 1 },
|
|
34
|
+
React.createElement(Text, { bold: true, color: "red" }, "\u2716 Error")),
|
|
35
|
+
React.createElement(Box, { marginTop: 1 },
|
|
36
|
+
React.createElement(Text, { color: "red" }, message))));
|
|
37
|
+
export const Success = ({ message }) => (React.createElement(Box, { flexDirection: "column" },
|
|
38
|
+
React.createElement(Logo, null),
|
|
39
|
+
React.createElement(Box, { marginTop: 1 },
|
|
40
|
+
React.createElement(Text, { bold: true, color: "green" },
|
|
41
|
+
"\u2713 ",
|
|
42
|
+
message))));
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|