onedeploy-cli 0.1.11 → 0.1.14

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/dist/nebula.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { execFile, spawn } from "node:child_process";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { access, chmod, mkdir, readFile, rm, writeFile, } from "node:fs/promises";
4
- import { createServer } from "node:http";
5
4
  import { tmpdir } from "node:os";
6
5
  import path from "node:path";
7
6
  import { Readable } from "node:stream";
@@ -9,7 +8,6 @@ import { promisify } from "node:util";
9
8
  import { parse } from "yaml";
10
9
  import { openBrowser } from "./browser.js";
11
10
  import { configDir } from "./config.js";
12
- import { successPage } from "./success.js";
13
11
  const getNebulaPackageName = () => {
14
12
  switch (process.platform) {
15
13
  case "linux":
@@ -124,51 +122,39 @@ export const getNebulaCert = async (instance, session) => {
124
122
  };
125
123
  export let isNebulaRunning = false;
126
124
  export let nebulaIp = null;
127
- export const getSession = (instance) => {
128
- return new Promise((resolve) => {
129
- const getServerAddr = () => {
130
- const addr = server.address();
131
- if (addr === null || typeof addr === "string") {
132
- // just a placeholder, should not happen
133
- return "http://localhost:70000";
134
- }
135
- return `http://localhost:${addr.port}`;
136
- };
137
- const server = createServer((req, res) => {
138
- const url = new URL(req.url ?? "/", "http://localhost");
139
- if (url.pathname === "/authenticated") {
140
- const token = url.searchParams.get("token");
141
- if (token === null) {
142
- throw new Error("Missing token in callback URL");
143
- }
144
- // authentication complete
145
- res.writeHead(200, "OK", {
146
- "content-type": "text/html",
147
- });
148
- res.write(successPage);
149
- res.end();
150
- server.close();
151
- resolve(token);
152
- }
153
- else {
154
- const target = `${getServerAddr()}/authenticated`;
155
- res.writeHead(302, {
156
- location: `${instance.url}/auth/nebula?redirect=${encodeURIComponent(target)}`,
157
- });
158
- res.end();
159
- }
160
- });
161
- server.on("listening", async () => {
162
- const addr = server.address();
163
- if (addr === null || typeof addr === "string") {
164
- throw new Error("Unexpected address type");
165
- }
166
- const authUrl = getServerAddr();
167
- console.log(`Visit ${authUrl} to authenticate (opened in browser)`);
168
- await openBrowser(authUrl);
169
- });
170
- server.listen();
125
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
126
+ export const getSession = async (instance) => {
127
+ const createRes = await fetch(`${instance.url}/api/auth/nebula/device`, {
128
+ method: "POST",
129
+ headers: { "content-type": "application/json" },
130
+ body: "{}",
171
131
  });
132
+ if (!createRes.ok) {
133
+ throw new Error(`Failed to create device code: ${createRes.status}`);
134
+ }
135
+ const { code, verificationUrl } = (await createRes.json());
136
+ console.log(`Visit ${verificationUrl} to authenticate`);
137
+ await openBrowser(verificationUrl);
138
+ const deadline = Date.now() + 10 * 60 * 1000;
139
+ while (Date.now() < deadline) {
140
+ await sleep(2000);
141
+ const pollRes = await fetch(`${instance.url}/api/auth/nebula/device/${code}`, {
142
+ method: "POST",
143
+ headers: { "content-type": "application/json" },
144
+ body: "{}",
145
+ });
146
+ if (pollRes.status === 404) {
147
+ throw new Error("Device code expired or not found.");
148
+ }
149
+ if (!pollRes.ok) {
150
+ throw new Error(`Poll failed: ${pollRes.status}`);
151
+ }
152
+ const result = (await pollRes.json());
153
+ if (result.status === "complete") {
154
+ return result.token;
155
+ }
156
+ }
157
+ throw new Error("Authentication timed out after 10 minutes.");
172
158
  };
173
159
  export const startNebula = async (instance, session) => {
174
160
  await getNebulaCert(instance, session);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "onedeploy-cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.14",
4
4
  "description": "CLI tool for connecting to OneDeploy via Nebula",
5
5
  "keywords": [
6
6
  "onedeploy",
package/dist/success.js DELETED
@@ -1,201 +0,0 @@
1
- export const successPage = `<!DOCTYPE html>
2
- <html lang="en">
3
-
4
- <head>
5
- <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>oneDeploy</title>
8
- <link rel="icon" type="image/svg+xml"
9
- href="data:image/svg+xml,%3Csvg width='48' height='48' viewBox='0 0 48 48' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='14' cy='27' r='14' fill='%2322C55E'/%3E%3Ccircle cx='38' cy='10' r='10' fill='%234ADE80'/%3E%3Ccircle cx='40' cy='40' r='8' fill='%2316A34A'/%3E%3Cline x1='26' y1='19' x2='30' y2='14' stroke='%2386EFAC' stroke-width='3' stroke-linecap='round'/%3E%3Cline x1='26' y1='36' x2='34' y2='38' stroke='%2386EFAC' stroke-width='3' stroke-linecap='round'/%3E%3Cpath d='M9 20V34L21 27L9 20Z' fill='white'/%3E%3C/svg%3E">
10
- <style>
11
- * {
12
- margin: 0;
13
- padding: 0;
14
- box-sizing: border-box;
15
- }
16
-
17
- body {
18
- font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
19
- margin: 0;
20
- padding: 0;
21
- }
22
-
23
- .page-container {
24
- min-height: 100vh;
25
- background-color: #0b0b0f;
26
- color: #f3f4f6;
27
- }
28
-
29
- .navbar {
30
- padding: 1rem;
31
- border-bottom: 1px solid rgba(255, 255, 255, 0.05);
32
- background-color: #0e0e14;
33
- }
34
-
35
- .logo-container {
36
- display: flex;
37
- align-items: center;
38
- gap: 0.75rem;
39
- }
40
-
41
- .logo-container img {
42
- width: 2.5rem;
43
- height: 2.5rem;
44
- }
45
-
46
- .logo-text {
47
- font-size: 1.5rem;
48
- font-weight: 700;
49
- letter-spacing: -0.025em;
50
- line-height: 1.2;
51
- }
52
-
53
- @media (min-width: 768px) {
54
- .logo-text {
55
- font-size: 1.875rem;
56
- }
57
- }
58
-
59
- .logo-one {
60
- color: #4ade80;
61
- }
62
-
63
- .logo-deploy {
64
- color: #f3f4f6;
65
- }
66
-
67
- .content-wrapper {
68
- padding: 1rem;
69
- }
70
-
71
- .container {
72
- min-height: 80vh;
73
- display: flex;
74
- align-items: center;
75
- justify-content: center;
76
- padding-left: 1rem;
77
- padding-right: 1rem;
78
- }
79
-
80
- .card {
81
- width: 100%;
82
- max-width: 28rem;
83
- background-color: #14141c;
84
- border: 1px solid rgba(255, 255, 255, 0.05);
85
- border-radius: 1rem;
86
- padding: 2rem;
87
- box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
88
- }
89
-
90
- .header {
91
- text-align: center;
92
- margin-bottom: 2rem;
93
- }
94
-
95
- .icon-container {
96
- display: inline-flex;
97
- align-items: center;
98
- justify-content: center;
99
- width: 4rem;
100
- height: 4rem;
101
- border-radius: 1rem;
102
- background-color: rgba(139, 92, 246, 0.1);
103
- color: #a78bfa;
104
- margin-bottom: 1.5rem;
105
- border: 1px solid rgba(255, 255, 255, 0.05);
106
- }
107
-
108
- .icon-container svg {
109
- width: 2rem;
110
- height: 2rem;
111
- }
112
-
113
- h1 {
114
- font-size: 1.875rem;
115
- font-weight: 700;
116
- color: #f3f4f6;
117
- letter-spacing: -0.025em;
118
- margin: 0 0 0.5rem 0;
119
- line-height: 2.25rem;
120
- text-align: center;
121
- }
122
-
123
- .description {
124
- color: #9ca3af;
125
- font-size: 1rem;
126
- line-height: 1.5rem;
127
- text-align: center;
128
- margin: 0;
129
- }
130
-
131
- .status-container {
132
- min-height: 60px;
133
- display: flex;
134
- align-items: center;
135
- justify-content: center;
136
- }
137
-
138
- .success-box {
139
- width: 100%;
140
- display: flex;
141
- align-items: center;
142
- justify-content: center;
143
- padding-top: 0.75rem;
144
- padding-bottom: 0.75rem;
145
- font-size: 1rem;
146
- font-weight: 500;
147
- background-color: rgba(34, 197, 94, 0.1);
148
- border: 1px solid rgba(34, 197, 94, 0.2);
149
- border-radius: 0.5rem;
150
- color: #4ade80;
151
- }
152
-
153
- .success-box svg {
154
- width: 1.25rem;
155
- height: 1.25rem;
156
- }
157
- </style>
158
- </head>
159
-
160
- <body>
161
- <div class="page-container">
162
- <div class="navbar">
163
- <div class="logo-container">
164
- <img alt="oneDeploy Logo"
165
- src="data:image/svg+xml,%3Csvg width='48' height='48' viewBox='0 0 48 48' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='14' cy='27' r='14' fill='%2322C55E'/%3E%3Ccircle cx='38' cy='10' r='10' fill='%234ADE80'/%3E%3Ccircle cx='40' cy='40' r='8' fill='%2316A34A'/%3E%3Cline x1='26' y1='19' x2='30' y2='14' stroke='%2386EFAC' stroke-width='3' stroke-linecap='round'/%3E%3Cline x1='26' y1='36' x2='34' y2='38' stroke='%2386EFAC' stroke-width='3' stroke-linecap='round'/%3E%3Cpath d='M9 20V34L21 27L9 20Z' fill='white'/%3E%3C/svg%3E">
166
- <div class="logo-text">
167
- <span class="logo-one">one</span><span class="logo-deploy">Deploy</span>
168
- </div>
169
- </div>
170
- </div>
171
- <div class="content-wrapper">
172
- <div class="container">
173
- <div class="card">
174
- <div class="header">
175
- <div class="icon-container">
176
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
177
- stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
178
- <circle cx="12" cy="12" r="10" />
179
- <line x1="2" y1="12" x2="22" y2="12" />
180
- <path
181
- d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" />
182
- </svg>
183
- </div>
184
- <h1>Network Access Request</h1>
185
- <p class="description">oneDeploy CLI is requesting access to the oneDeploy network</p>
186
- </div>
187
-
188
- <div class="status-container">
189
- <div class="success-box">
190
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
191
- stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
192
- <path d="M20 6 9 17l-5-5" />
193
- </svg>
194
- </div>
195
- </div>
196
- </div>
197
- </div>
198
- </div>
199
- </div>
200
- </body>
201
- `;