ds-01 1.0.6 → 1.0.8
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/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +5 -7
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +45 -42
- package/package.json +1 -1
- package/src/commands/add.ts +44 -125
- package/src/commands/login.ts +54 -48
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuDpC,eAAO,MAAM,GAAG,SA0MZ,CAAC"}
|
package/dist/commands/add.js
CHANGED
|
@@ -84,8 +84,9 @@ export const add = new Command()
|
|
|
84
84
|
},
|
|
85
85
|
});
|
|
86
86
|
if (!response.ok) {
|
|
87
|
+
const errorData = await response.json().catch(() => null);
|
|
87
88
|
s.stop(pc.red("Component fetch failed."));
|
|
88
|
-
cancel(
|
|
89
|
+
cancel(errorData?.error || `Server returned HTTP ${response.status}`);
|
|
89
90
|
process.exit(1);
|
|
90
91
|
}
|
|
91
92
|
const componentData = await response.json();
|
|
@@ -118,8 +119,7 @@ export const add = new Command()
|
|
|
118
119
|
// --------------------------------------------------
|
|
119
120
|
// 7. Install dependencies
|
|
120
121
|
// --------------------------------------------------
|
|
121
|
-
if (componentData.dependencies &&
|
|
122
|
-
componentData.dependencies.length > 0) {
|
|
122
|
+
if (componentData.dependencies && componentData.dependencies.length > 0) {
|
|
123
123
|
const depsToInstall = componentData.dependencies.join(" ");
|
|
124
124
|
s.start(`Installing missing dependencies: ${pc.cyan(depsToInstall)}...`);
|
|
125
125
|
try {
|
|
@@ -136,16 +136,14 @@ export const add = new Command()
|
|
|
136
136
|
// --------------------------------------------------
|
|
137
137
|
// 8. Success
|
|
138
138
|
// --------------------------------------------------
|
|
139
|
-
const mainFile = bundledFileNames.find((name) => name.toLowerCase() ===
|
|
140
|
-
componentName.toLowerCase()) || bundledFileNames[0];
|
|
139
|
+
const mainFile = bundledFileNames.find((name) => name.toLowerCase() === componentName.toLowerCase()) || bundledFileNames[0];
|
|
141
140
|
outro(`${pc.white("✔")} ${pc.bold(`Component <${componentName} /> is ready!`)}\n` +
|
|
142
141
|
pc.gray("Import it: ") +
|
|
143
142
|
pc.cyan(`import { ${mainFile} } from "@/${config.componentsPath}/${componentName}/${mainFile}"`));
|
|
144
143
|
}
|
|
145
144
|
catch (error) {
|
|
146
145
|
s.stop(pc.red("An error occurred during injection."));
|
|
147
|
-
cancel(pc.gray(error?.message ||
|
|
148
|
-
"Unknown CLI Error"));
|
|
146
|
+
cancel(pc.gray(error?.message || "Unknown CLI Error"));
|
|
149
147
|
process.exit(1);
|
|
150
148
|
}
|
|
151
149
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwBpC,eAAO,MAAM,KAAK,
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwBpC,eAAO,MAAM,KAAK,SA6Td,CAAC"}
|
package/dist/commands/login.js
CHANGED
|
@@ -16,23 +16,19 @@ export const login = new Command()
|
|
|
16
16
|
intro(`${pc.bgWhite(pc.black(pc.bold(" DS01 ")))} ${pc.gray("v1.0.0 — Terminal Authentication")}`);
|
|
17
17
|
const s = spinner();
|
|
18
18
|
try {
|
|
19
|
-
//
|
|
20
|
-
// 1.
|
|
21
|
-
//
|
|
19
|
+
// ==================================================
|
|
20
|
+
// 1. CREATE / LOAD SECURE DEVICE KEY
|
|
21
|
+
// ==================================================
|
|
22
22
|
s.start("Preparing secure device identity...");
|
|
23
23
|
await createDeviceKey();
|
|
24
|
-
// Only the PUBLIC key/certificate leaves
|
|
25
|
-
// the user's machine.
|
|
26
24
|
const publicKey = await getDevicePublicKey();
|
|
27
|
-
// Existing machine fingerprint.
|
|
28
25
|
const hardwareId = machineIdSync();
|
|
29
|
-
// Detect the cryptographic key type.
|
|
30
26
|
const publicKeyType = process.platform === "win32"
|
|
31
27
|
? "windows-rsa"
|
|
32
28
|
: "macos-ec";
|
|
33
|
-
//
|
|
34
|
-
// 2.
|
|
35
|
-
//
|
|
29
|
+
// ==================================================
|
|
30
|
+
// 2. REQUEST DEVICE CODE
|
|
31
|
+
// ==================================================
|
|
36
32
|
s.start("Requesting pairing code...");
|
|
37
33
|
const initResponse = await fetch(`${API_BASE_URL}/api/auth/device/code`, {
|
|
38
34
|
method: "POST",
|
|
@@ -57,21 +53,20 @@ export const login = new Command()
|
|
|
57
53
|
throw new Error("Authorization server returned an invalid device response.");
|
|
58
54
|
}
|
|
59
55
|
s.stop(pc.green("Secure device identity registered."));
|
|
60
|
-
//
|
|
61
|
-
// 3.
|
|
62
|
-
//
|
|
56
|
+
// ==================================================
|
|
57
|
+
// 3. SHOW BROWSER AUTHORIZATION
|
|
58
|
+
// ==================================================
|
|
63
59
|
note(`${pc.bold("Pairing Code:")} ${pc.cyan(pc.bold(` ${userCode} `))}\n` +
|
|
64
60
|
`${pc.bold("Verification URL:")} ${pc.underline(verificationUrl)}`, "Action Required");
|
|
65
61
|
try {
|
|
66
62
|
await open(verificationUrl);
|
|
67
63
|
}
|
|
68
64
|
catch {
|
|
69
|
-
// Browser launch failure
|
|
70
|
-
// is non-fatal.
|
|
65
|
+
// Browser launch failure is non-fatal.
|
|
71
66
|
}
|
|
72
|
-
//
|
|
73
|
-
// 4.
|
|
74
|
-
//
|
|
67
|
+
// ==================================================
|
|
68
|
+
// 4. POLL FOR AUTHORIZATION
|
|
69
|
+
// ==================================================
|
|
75
70
|
s.start("Waiting for web authorization...");
|
|
76
71
|
const pollInterval = (interval || 5) * 1000;
|
|
77
72
|
let token = null;
|
|
@@ -97,56 +92,64 @@ export const login = new Command()
|
|
|
97
92
|
cancel("Unable to read authorization response.");
|
|
98
93
|
process.exit(1);
|
|
99
94
|
}
|
|
100
|
-
//
|
|
101
|
-
// SUCCESS
|
|
102
|
-
//
|
|
95
|
+
// ==================================================
|
|
96
|
+
// AUTHORIZATION SUCCESS
|
|
97
|
+
// ==================================================
|
|
103
98
|
if (tokenResponse.ok &&
|
|
104
99
|
typeof tokenData.accessToken ===
|
|
105
100
|
"string" &&
|
|
106
101
|
tokenData.accessToken.length > 0) {
|
|
107
102
|
token =
|
|
108
103
|
tokenData.accessToken;
|
|
109
|
-
// IMPORTANT:
|
|
110
|
-
// Stop the spinner immediately.
|
|
111
|
-
s.stop(pc.green("Hardware signature linked & token verified!"));
|
|
112
|
-
// IMPORTANT:
|
|
113
|
-
// Leave the polling loop immediately.
|
|
114
104
|
break;
|
|
115
105
|
}
|
|
116
|
-
//
|
|
106
|
+
// ==================================================
|
|
117
107
|
// STILL WAITING
|
|
118
|
-
//
|
|
108
|
+
// ==================================================
|
|
119
109
|
if (tokenData.error ===
|
|
120
110
|
"authorization_pending") {
|
|
121
111
|
continue;
|
|
122
112
|
}
|
|
123
|
-
//
|
|
124
|
-
// FAILED
|
|
125
|
-
//
|
|
113
|
+
// ==================================================
|
|
114
|
+
// AUTHORIZATION FAILED
|
|
115
|
+
// ==================================================
|
|
126
116
|
s.stop(pc.red("Authorization failed or expired."));
|
|
127
117
|
cancel(`Reason: ${tokenData.error ||
|
|
128
118
|
"Unknown authorization error"}`);
|
|
129
119
|
process.exit(1);
|
|
130
120
|
}
|
|
131
|
-
//
|
|
132
|
-
// 5.
|
|
133
|
-
//
|
|
121
|
+
// ==================================================
|
|
122
|
+
// 5. STOP POLLING SPINNER
|
|
123
|
+
// ==================================================
|
|
124
|
+
s.stop(pc.green("Hardware signature linked & token verified!"));
|
|
125
|
+
// ==================================================
|
|
126
|
+
// 6. ENSURE TOKEN EXISTS
|
|
127
|
+
// ==================================================
|
|
134
128
|
if (!token) {
|
|
135
129
|
throw new Error("Authorization completed without receiving an access token.");
|
|
136
130
|
}
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
//
|
|
131
|
+
// ==================================================
|
|
132
|
+
// 7. SAVE TOKEN
|
|
133
|
+
// ==================================================
|
|
140
134
|
saveToken(token, hardwareId);
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
135
|
+
// ==================================================
|
|
136
|
+
// 8. SUCCESS
|
|
137
|
+
// ==================================================
|
|
144
138
|
outro(`${pc.white("✔")} ${pc.bold("Terminal synced successfully")}\n` +
|
|
145
139
|
pc.gray("Secure device key and session token are ready."));
|
|
140
|
+
// ==================================================
|
|
141
|
+
// 9. HARD EXIT
|
|
142
|
+
// ==================================================
|
|
143
|
+
//
|
|
144
|
+
// The login command is completely finished.
|
|
145
|
+
//
|
|
146
|
+
// This prevents any lingering CLI handles
|
|
147
|
+
// (spinner timers, readline handles, etc.)
|
|
148
|
+
// from keeping the Node process alive.
|
|
149
|
+
//
|
|
150
|
+
process.exit(0);
|
|
146
151
|
}
|
|
147
152
|
catch (error) {
|
|
148
|
-
// Only stop the spinner if it is
|
|
149
|
-
// still running.
|
|
150
153
|
s.stop(pc.red("An error occurred during login."));
|
|
151
154
|
cancel(pc.gray(error?.message ||
|
|
152
155
|
"Unknown CLI Error"));
|
package/package.json
CHANGED
package/src/commands/add.ts
CHANGED
|
@@ -12,8 +12,7 @@ import machineIdPkg from "node-machine-id";
|
|
|
12
12
|
|
|
13
13
|
const { machineIdSync } = machineIdPkg;
|
|
14
14
|
|
|
15
|
-
const API_BASE_URL =
|
|
16
|
-
process.env.DS01_API_URL || "https://ds-01.vercel.app";
|
|
15
|
+
const API_BASE_URL = process.env.DS01_API_URL || "https://ds-01.vercel.app";
|
|
17
16
|
|
|
18
17
|
// Helper to verify Tailwind exists before doing anything
|
|
19
18
|
function checkTailwindInstallation() {
|
|
@@ -29,9 +28,7 @@ function checkTailwindInstallation() {
|
|
|
29
28
|
process.exit(1);
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
const pkgJson = JSON.parse(
|
|
33
|
-
fs.readFileSync(pkgJsonPath, "utf-8"),
|
|
34
|
-
);
|
|
31
|
+
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
|
|
35
32
|
|
|
36
33
|
const allDeps = {
|
|
37
34
|
...pkgJson.dependencies,
|
|
@@ -40,22 +37,16 @@ function checkTailwindInstallation() {
|
|
|
40
37
|
|
|
41
38
|
if (!allDeps["tailwindcss"]) {
|
|
42
39
|
cancel(
|
|
43
|
-
pc.red(
|
|
44
|
-
"Tailwind CSS is missing from your project dependencies.\n",
|
|
45
|
-
) +
|
|
40
|
+
pc.red("Tailwind CSS is missing from your project dependencies.\n") +
|
|
46
41
|
pc.gray(
|
|
47
42
|
"DS01 components rely strictly on Tailwind CSS for styling.\n\n",
|
|
48
43
|
) +
|
|
49
44
|
pc.white(
|
|
50
45
|
"Kindly install it and configure your project, then retry:\n",
|
|
51
46
|
) +
|
|
52
|
-
pc.cyan(
|
|
53
|
-
" npm install tailwindcss @tailwindcss/postcss postcss\n\n",
|
|
54
|
-
) +
|
|
47
|
+
pc.cyan(" npm install tailwindcss @tailwindcss/postcss postcss\n\n") +
|
|
55
48
|
pc.gray("Official Setup Guide: ") +
|
|
56
|
-
pc.underline(
|
|
57
|
-
"https://tailwindcss.com/docs/installation",
|
|
58
|
-
),
|
|
49
|
+
pc.underline("https://tailwindcss.com/docs/installation"),
|
|
59
50
|
);
|
|
60
51
|
|
|
61
52
|
process.exit(1);
|
|
@@ -65,10 +56,7 @@ function checkTailwindInstallation() {
|
|
|
65
56
|
export const add = new Command()
|
|
66
57
|
.name("add")
|
|
67
58
|
.description("Add a component from DS01 to your project")
|
|
68
|
-
.argument(
|
|
69
|
-
"<component>",
|
|
70
|
-
"The name of the component (e.g., premium-section)",
|
|
71
|
-
)
|
|
59
|
+
.argument("<component>", "The name of the component (e.g., premium-section)")
|
|
72
60
|
.action(async (componentName: string) => {
|
|
73
61
|
console.log();
|
|
74
62
|
|
|
@@ -82,45 +70,28 @@ export const add = new Command()
|
|
|
82
70
|
|
|
83
71
|
const cwd = process.cwd();
|
|
84
72
|
|
|
85
|
-
const configPath = path.join(
|
|
86
|
-
cwd,
|
|
87
|
-
"ds01.config.json",
|
|
88
|
-
);
|
|
73
|
+
const configPath = path.join(cwd, "ds01.config.json");
|
|
89
74
|
|
|
90
75
|
if (!fs.existsSync(configPath)) {
|
|
91
|
-
cancel(
|
|
92
|
-
pc.red(
|
|
93
|
-
"ds01.config.json not found. Run 'npx ds-01 init' first.",
|
|
94
|
-
),
|
|
95
|
-
);
|
|
76
|
+
cancel(pc.red("ds01.config.json not found. Run 'npx ds-01 init' first."));
|
|
96
77
|
|
|
97
78
|
process.exit(1);
|
|
98
79
|
}
|
|
99
80
|
|
|
100
|
-
const config = JSON.parse(
|
|
101
|
-
fs.readFileSync(configPath, "utf-8"),
|
|
102
|
-
);
|
|
81
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
103
82
|
|
|
104
83
|
const token = getToken();
|
|
105
84
|
const machineId = machineIdSync();
|
|
106
85
|
|
|
107
86
|
if (!token || !machineId) {
|
|
108
|
-
cancel(
|
|
109
|
-
pc.red(
|
|
110
|
-
"You are not authenticated. Run 'npx ds-01 login' first.",
|
|
111
|
-
),
|
|
112
|
-
);
|
|
87
|
+
cancel(pc.red("You are not authenticated. Run 'npx ds-01 login' first."));
|
|
113
88
|
|
|
114
89
|
process.exit(1);
|
|
115
90
|
}
|
|
116
91
|
|
|
117
92
|
const s = spinner();
|
|
118
93
|
|
|
119
|
-
s.start(
|
|
120
|
-
`Fetching ${pc.cyan(
|
|
121
|
-
`<${componentName} />`,
|
|
122
|
-
)} from registry...`,
|
|
123
|
-
);
|
|
94
|
+
s.start(`Fetching ${pc.cyan(`<${componentName} />`)} from registry...`);
|
|
124
95
|
|
|
125
96
|
try {
|
|
126
97
|
// --------------------------------------------------
|
|
@@ -144,8 +115,7 @@ export const add = new Command()
|
|
|
144
115
|
new TextEncoder().encode(message),
|
|
145
116
|
);
|
|
146
117
|
|
|
147
|
-
const signatureBase64 =
|
|
148
|
-
Buffer.from(signature).toString("base64");
|
|
118
|
+
const signatureBase64 = Buffer.from(signature).toString("base64");
|
|
149
119
|
|
|
150
120
|
// --------------------------------------------------
|
|
151
121
|
// 3. Send token + machine ID + signature
|
|
@@ -169,29 +139,22 @@ export const add = new Command()
|
|
|
169
139
|
);
|
|
170
140
|
|
|
171
141
|
if (!response.ok) {
|
|
172
|
-
|
|
173
|
-
pc.red("Component fetch failed."),
|
|
174
|
-
);
|
|
142
|
+
const errorData = await response.json().catch(() => null);
|
|
175
143
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
);
|
|
144
|
+
s.stop(pc.red("Component fetch failed."));
|
|
145
|
+
|
|
146
|
+
cancel(errorData?.error || `Server returned HTTP ${response.status}`);
|
|
179
147
|
|
|
180
148
|
process.exit(1);
|
|
181
149
|
}
|
|
182
150
|
|
|
183
|
-
const componentData =
|
|
184
|
-
await response.json();
|
|
151
|
+
const componentData = await response.json();
|
|
185
152
|
|
|
186
153
|
// --------------------------------------------------
|
|
187
154
|
// 4. Create component folder
|
|
188
155
|
// --------------------------------------------------
|
|
189
156
|
|
|
190
|
-
const targetDir = path.join(
|
|
191
|
-
cwd,
|
|
192
|
-
config.componentsPath,
|
|
193
|
-
componentName,
|
|
194
|
-
);
|
|
157
|
+
const targetDir = path.join(cwd, config.componentsPath, componentName);
|
|
195
158
|
|
|
196
159
|
if (!fs.existsSync(targetDir)) {
|
|
197
160
|
fs.mkdirSync(targetDir, {
|
|
@@ -203,45 +166,29 @@ export const add = new Command()
|
|
|
203
166
|
// 5. Extract bundled file names
|
|
204
167
|
// --------------------------------------------------
|
|
205
168
|
|
|
206
|
-
const bundledFileNames =
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
file.name.replace(
|
|
210
|
-
/\.[^/.]+$/,
|
|
211
|
-
"",
|
|
212
|
-
),
|
|
213
|
-
);
|
|
169
|
+
const bundledFileNames = componentData.files.map((file: any) =>
|
|
170
|
+
file.name.replace(/\.[^/.]+$/, ""),
|
|
171
|
+
);
|
|
214
172
|
|
|
215
173
|
// --------------------------------------------------
|
|
216
174
|
// 6. Write component files
|
|
217
175
|
// --------------------------------------------------
|
|
218
176
|
|
|
219
177
|
for (const file of componentData.files) {
|
|
220
|
-
const filePath = path.join(
|
|
221
|
-
targetDir,
|
|
222
|
-
file.name,
|
|
223
|
-
);
|
|
178
|
+
const filePath = path.join(targetDir, file.name);
|
|
224
179
|
|
|
225
180
|
let content = file.content;
|
|
226
181
|
|
|
227
|
-
bundledFileNames.forEach(
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
);
|
|
233
|
-
|
|
234
|
-
content = content.replace(
|
|
235
|
-
regex,
|
|
236
|
-
`from "./${fileName}"`,
|
|
237
|
-
);
|
|
238
|
-
},
|
|
239
|
-
);
|
|
182
|
+
bundledFileNames.forEach((fileName: string) => {
|
|
183
|
+
const regex = new RegExp(
|
|
184
|
+
`from\\s+["']\\.[^"']*?\\/${fileName}["']`,
|
|
185
|
+
"g",
|
|
186
|
+
);
|
|
240
187
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
);
|
|
188
|
+
content = content.replace(regex, `from "./${fileName}"`);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
fs.writeFileSync(filePath, content);
|
|
245
192
|
}
|
|
246
193
|
|
|
247
194
|
s.stop(
|
|
@@ -256,45 +203,28 @@ export const add = new Command()
|
|
|
256
203
|
// 7. Install dependencies
|
|
257
204
|
// --------------------------------------------------
|
|
258
205
|
|
|
259
|
-
if (
|
|
260
|
-
componentData.dependencies
|
|
261
|
-
componentData.dependencies.length > 0
|
|
262
|
-
) {
|
|
263
|
-
const depsToInstall =
|
|
264
|
-
componentData.dependencies.join(" ");
|
|
206
|
+
if (componentData.dependencies && componentData.dependencies.length > 0) {
|
|
207
|
+
const depsToInstall = componentData.dependencies.join(" ");
|
|
265
208
|
|
|
266
209
|
s.start(
|
|
267
|
-
`Installing missing dependencies: ${pc.cyan(
|
|
268
|
-
depsToInstall,
|
|
269
|
-
)}...`,
|
|
210
|
+
`Installing missing dependencies: ${pc.cyan(depsToInstall)}...`,
|
|
270
211
|
);
|
|
271
212
|
|
|
272
213
|
try {
|
|
273
|
-
execSync(
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
stdio: "ignore",
|
|
277
|
-
},
|
|
278
|
-
);
|
|
214
|
+
execSync(`npm install ${depsToInstall}`, {
|
|
215
|
+
stdio: "ignore",
|
|
216
|
+
});
|
|
279
217
|
|
|
280
218
|
s.stop(
|
|
281
219
|
pc.green(
|
|
282
|
-
`Dependencies installed successfully: ${pc.gray(
|
|
283
|
-
depsToInstall,
|
|
284
|
-
)}`,
|
|
220
|
+
`Dependencies installed successfully: ${pc.gray(depsToInstall)}`,
|
|
285
221
|
),
|
|
286
222
|
);
|
|
287
223
|
} catch {
|
|
288
|
-
s.stop(
|
|
289
|
-
pc.red(
|
|
290
|
-
"Failed to auto-install dependencies.",
|
|
291
|
-
),
|
|
292
|
-
);
|
|
224
|
+
s.stop(pc.red("Failed to auto-install dependencies."));
|
|
293
225
|
|
|
294
226
|
note(
|
|
295
|
-
`Please run: ${pc.cyan(
|
|
296
|
-
`npm install ${depsToInstall}`,
|
|
297
|
-
)} manually.`,
|
|
227
|
+
`Please run: ${pc.cyan(`npm install ${depsToInstall}`)} manually.`,
|
|
298
228
|
"Manual Action Required",
|
|
299
229
|
);
|
|
300
230
|
}
|
|
@@ -306,9 +236,7 @@ export const add = new Command()
|
|
|
306
236
|
|
|
307
237
|
const mainFile =
|
|
308
238
|
bundledFileNames.find(
|
|
309
|
-
(name: string) =>
|
|
310
|
-
name.toLowerCase() ===
|
|
311
|
-
componentName.toLowerCase(),
|
|
239
|
+
(name: string) => name.toLowerCase() === componentName.toLowerCase(),
|
|
312
240
|
) || bundledFileNames[0];
|
|
313
241
|
|
|
314
242
|
outro(
|
|
@@ -321,19 +249,10 @@ export const add = new Command()
|
|
|
321
249
|
),
|
|
322
250
|
);
|
|
323
251
|
} catch (error: any) {
|
|
324
|
-
s.stop(
|
|
325
|
-
pc.red(
|
|
326
|
-
"An error occurred during injection.",
|
|
327
|
-
),
|
|
328
|
-
);
|
|
252
|
+
s.stop(pc.red("An error occurred during injection."));
|
|
329
253
|
|
|
330
|
-
cancel(
|
|
331
|
-
pc.gray(
|
|
332
|
-
error?.message ||
|
|
333
|
-
"Unknown CLI Error",
|
|
334
|
-
),
|
|
335
|
-
);
|
|
254
|
+
cancel(pc.gray(error?.message || "Unknown CLI Error"));
|
|
336
255
|
|
|
337
256
|
process.exit(1);
|
|
338
257
|
}
|
|
339
|
-
});
|
|
258
|
+
});
|
package/src/commands/login.ts
CHANGED
|
@@ -43,9 +43,9 @@ export const login = new Command()
|
|
|
43
43
|
const s = spinner();
|
|
44
44
|
|
|
45
45
|
try {
|
|
46
|
-
//
|
|
47
|
-
// 1.
|
|
48
|
-
//
|
|
46
|
+
// ==================================================
|
|
47
|
+
// 1. CREATE / LOAD SECURE DEVICE KEY
|
|
48
|
+
// ==================================================
|
|
49
49
|
|
|
50
50
|
s.start(
|
|
51
51
|
"Preparing secure device identity...",
|
|
@@ -53,24 +53,20 @@ export const login = new Command()
|
|
|
53
53
|
|
|
54
54
|
await createDeviceKey();
|
|
55
55
|
|
|
56
|
-
// Only the PUBLIC key/certificate leaves
|
|
57
|
-
// the user's machine.
|
|
58
56
|
const publicKey =
|
|
59
57
|
await getDevicePublicKey();
|
|
60
58
|
|
|
61
|
-
// Existing machine fingerprint.
|
|
62
59
|
const hardwareId =
|
|
63
60
|
machineIdSync();
|
|
64
61
|
|
|
65
|
-
// Detect the cryptographic key type.
|
|
66
62
|
const publicKeyType =
|
|
67
63
|
process.platform === "win32"
|
|
68
64
|
? "windows-rsa"
|
|
69
65
|
: "macos-ec";
|
|
70
66
|
|
|
71
|
-
//
|
|
72
|
-
// 2.
|
|
73
|
-
//
|
|
67
|
+
// ==================================================
|
|
68
|
+
// 2. REQUEST DEVICE CODE
|
|
69
|
+
// ==================================================
|
|
74
70
|
|
|
75
71
|
s.start(
|
|
76
72
|
"Requesting pairing code...",
|
|
@@ -117,7 +113,8 @@ export const login = new Command()
|
|
|
117
113
|
userCode,
|
|
118
114
|
verificationUrl,
|
|
119
115
|
interval,
|
|
120
|
-
} =
|
|
116
|
+
} =
|
|
117
|
+
await initResponse.json();
|
|
121
118
|
|
|
122
119
|
if (
|
|
123
120
|
!deviceCode ||
|
|
@@ -135,9 +132,9 @@ export const login = new Command()
|
|
|
135
132
|
),
|
|
136
133
|
);
|
|
137
134
|
|
|
138
|
-
//
|
|
139
|
-
// 3.
|
|
140
|
-
//
|
|
135
|
+
// ==================================================
|
|
136
|
+
// 3. SHOW BROWSER AUTHORIZATION
|
|
137
|
+
// ==================================================
|
|
141
138
|
|
|
142
139
|
note(
|
|
143
140
|
`${pc.bold(
|
|
@@ -160,13 +157,12 @@ export const login = new Command()
|
|
|
160
157
|
verificationUrl,
|
|
161
158
|
);
|
|
162
159
|
} catch {
|
|
163
|
-
// Browser launch failure
|
|
164
|
-
// is non-fatal.
|
|
160
|
+
// Browser launch failure is non-fatal.
|
|
165
161
|
}
|
|
166
162
|
|
|
167
|
-
//
|
|
168
|
-
// 4.
|
|
169
|
-
//
|
|
163
|
+
// ==================================================
|
|
164
|
+
// 4. POLL FOR AUTHORIZATION
|
|
165
|
+
// ==================================================
|
|
170
166
|
|
|
171
167
|
s.start(
|
|
172
168
|
"Waiting for web authorization...",
|
|
@@ -225,9 +221,9 @@ export const login = new Command()
|
|
|
225
221
|
process.exit(1);
|
|
226
222
|
}
|
|
227
223
|
|
|
228
|
-
//
|
|
229
|
-
// SUCCESS
|
|
230
|
-
//
|
|
224
|
+
// ==================================================
|
|
225
|
+
// AUTHORIZATION SUCCESS
|
|
226
|
+
// ==================================================
|
|
231
227
|
|
|
232
228
|
if (
|
|
233
229
|
tokenResponse.ok &&
|
|
@@ -238,22 +234,12 @@ export const login = new Command()
|
|
|
238
234
|
token =
|
|
239
235
|
tokenData.accessToken;
|
|
240
236
|
|
|
241
|
-
// IMPORTANT:
|
|
242
|
-
// Stop the spinner immediately.
|
|
243
|
-
s.stop(
|
|
244
|
-
pc.green(
|
|
245
|
-
"Hardware signature linked & token verified!",
|
|
246
|
-
),
|
|
247
|
-
);
|
|
248
|
-
|
|
249
|
-
// IMPORTANT:
|
|
250
|
-
// Leave the polling loop immediately.
|
|
251
237
|
break;
|
|
252
238
|
}
|
|
253
239
|
|
|
254
|
-
//
|
|
240
|
+
// ==================================================
|
|
255
241
|
// STILL WAITING
|
|
256
|
-
//
|
|
242
|
+
// ==================================================
|
|
257
243
|
|
|
258
244
|
if (
|
|
259
245
|
tokenData.error ===
|
|
@@ -262,9 +248,9 @@ export const login = new Command()
|
|
|
262
248
|
continue;
|
|
263
249
|
}
|
|
264
250
|
|
|
265
|
-
//
|
|
266
|
-
// FAILED
|
|
267
|
-
//
|
|
251
|
+
// ==================================================
|
|
252
|
+
// AUTHORIZATION FAILED
|
|
253
|
+
// ==================================================
|
|
268
254
|
|
|
269
255
|
s.stop(
|
|
270
256
|
pc.red(
|
|
@@ -282,9 +268,19 @@ export const login = new Command()
|
|
|
282
268
|
process.exit(1);
|
|
283
269
|
}
|
|
284
270
|
|
|
285
|
-
//
|
|
286
|
-
// 5.
|
|
287
|
-
//
|
|
271
|
+
// ==================================================
|
|
272
|
+
// 5. STOP POLLING SPINNER
|
|
273
|
+
// ==================================================
|
|
274
|
+
|
|
275
|
+
s.stop(
|
|
276
|
+
pc.green(
|
|
277
|
+
"Hardware signature linked & token verified!",
|
|
278
|
+
),
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
// ==================================================
|
|
282
|
+
// 6. ENSURE TOKEN EXISTS
|
|
283
|
+
// ==================================================
|
|
288
284
|
|
|
289
285
|
if (!token) {
|
|
290
286
|
throw new Error(
|
|
@@ -292,18 +288,18 @@ export const login = new Command()
|
|
|
292
288
|
);
|
|
293
289
|
}
|
|
294
290
|
|
|
295
|
-
//
|
|
296
|
-
//
|
|
297
|
-
//
|
|
291
|
+
// ==================================================
|
|
292
|
+
// 7. SAVE TOKEN
|
|
293
|
+
// ==================================================
|
|
298
294
|
|
|
299
295
|
saveToken(
|
|
300
296
|
token,
|
|
301
297
|
hardwareId,
|
|
302
298
|
);
|
|
303
299
|
|
|
304
|
-
//
|
|
305
|
-
//
|
|
306
|
-
//
|
|
300
|
+
// ==================================================
|
|
301
|
+
// 8. SUCCESS
|
|
302
|
+
// ==================================================
|
|
307
303
|
|
|
308
304
|
outro(
|
|
309
305
|
`${pc.white(
|
|
@@ -315,9 +311,19 @@ export const login = new Command()
|
|
|
315
311
|
"Secure device key and session token are ready.",
|
|
316
312
|
),
|
|
317
313
|
);
|
|
314
|
+
|
|
315
|
+
// ==================================================
|
|
316
|
+
// 9. HARD EXIT
|
|
317
|
+
// ==================================================
|
|
318
|
+
//
|
|
319
|
+
// The login command is completely finished.
|
|
320
|
+
//
|
|
321
|
+
// This prevents any lingering CLI handles
|
|
322
|
+
// (spinner timers, readline handles, etc.)
|
|
323
|
+
// from keeping the Node process alive.
|
|
324
|
+
//
|
|
325
|
+
process.exit(0);
|
|
318
326
|
} catch (error: any) {
|
|
319
|
-
// Only stop the spinner if it is
|
|
320
|
-
// still running.
|
|
321
327
|
s.stop(
|
|
322
328
|
pc.red(
|
|
323
329
|
"An error occurred during login.",
|