ds-01 1.0.13 → 1.1.1

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.
@@ -17,83 +17,58 @@ export const init = new Command()
17
17
  const packageJsonPath = path.join(cwd, "package.json");
18
18
  const tsconfigPath = path.join(cwd, "tsconfig.json");
19
19
 
20
- // 1. Check for package.json
20
+ // runs only if package file missing
21
21
  if (!fs.existsSync(packageJsonPath)) {
22
22
  s.stop("Environment check failed.");
23
- cancel("No package.json found. Please run this command in the root of your project.");
23
+ cancel(
24
+ "No package.json found. Please run this command in the root of your project.",
25
+ );
24
26
  process.exit(1);
25
27
  }
26
28
 
27
29
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
28
- const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
30
+ const deps = {
31
+ ...packageJson.dependencies,
32
+ ...packageJson.devDependencies,
33
+ };
29
34
 
30
- // 2. Check strictly for React or Next.js
35
+ // Check strictly for React or Next.js
31
36
  if (!deps.react && !deps.next) {
32
37
  s.stop("Environment check failed.");
33
- cancel("DS01 strictly supports React and Next.js environments. Please run this in a supported project.");
38
+ cancel(
39
+ "DS01 strictly supports React and Next.js environments. Please run this in a supported project.",
40
+ );
34
41
  process.exit(1);
35
42
  }
36
43
 
37
- // 3. Check strictly for TypeScript
44
+ // Check strictly for TypeScript
38
45
  if (!fs.existsSync(tsconfigPath)) {
39
46
  s.stop("Environment check failed.");
40
- cancel("DS01 requires TypeScript. No tsconfig.json found in the project root.");
47
+ cancel(
48
+ "DS01 requires TypeScript. No tsconfig.json found in the project root.",
49
+ );
41
50
  process.exit(1);
42
51
  }
43
52
 
44
53
  s.stop(chalk.green("✔ React and TypeScript detected!"));
45
54
 
46
- // 4. Ask the user where their global CSS is located
47
- const cssPath = await text({
48
- message: "Where is your global CSS file?",
49
- placeholder: "app/globals.css",
50
- initialValue: "app/globals.css",
51
- });
52
-
53
- if (isCancel(cssPath)) {
54
- cancel("Setup cancelled.");
55
- process.exit(0);
56
- }
57
-
58
- // 5. Inject Dark Mode / Glassmorphic CSS variables
59
- const fullCssPath = path.join(cwd, cssPath as string);
60
- if (fs.existsSync(fullCssPath)) {
61
- const cssContent = fs.readFileSync(fullCssPath, "utf-8");
62
-
63
- if (!cssContent.includes("/* ds01-theme-start */")) {
64
- const variables = `
65
- /* ds01-theme-start */
66
- @layer base {
67
- :root {
68
- --ds-background: #0a0a0a; /* Deep charcoal */
69
- --ds-foreground: #ffffff;
70
- --ds-glass-border: rgba(255, 255, 255, 0.08);
71
- --ds-glass-blur: blur(16px);
72
- }
73
- }
74
- /* ds01-theme-end */
75
- `;
76
- fs.appendFileSync(fullCssPath, variables);
77
- console.log(chalk.green(`✔ Injected design tokens into ${cssPath}`));
78
- } else {
79
- console.log(chalk.gray(`- Design tokens already exist in ${cssPath}`));
80
- }
81
- } else {
82
- console.log(chalk.yellow(`⚠ Could not find ${cssPath}. You may need to add the CSS variables manually.`));
83
- }
55
+ // Create the local configuration file so the CLI remembers this project
56
+ //! Need to be understand
84
57
 
85
- // 6. Create the local configuration file so the CLI remembers this project
86
58
  const configPath = path.join(cwd, "ds01.config.json");
87
59
  const configData = {
88
60
  $schema: "https://ds-01.vercel.app/schema.json",
89
61
  style: "default",
90
62
  typescript: true,
91
- cssPath: cssPath,
92
- componentsPath: "components/ui" // This is where we will inject components later
63
+ componentsPath: "components/ui", // This is where we will inject components later
93
64
  };
94
-
65
+
95
66
  fs.writeFileSync(configPath, JSON.stringify(configData, null, 2));
96
67
  console.log(chalk.green(`✔ Created ds01.config.json`));
97
68
 
98
- outro(chalk.green.bold("DS01 successfully initialized! Ready to add components."));
99
- });
69
+ outro(
70
+ chalk.green.bold(
71
+ "DS01 successfully initialized! Ready to add components.",
72
+ ),
73
+ );
74
+ });
@@ -1,41 +1,26 @@
1
1
  import { Command } from "commander";
2
- import {
3
- intro,
4
- outro,
5
- spinner,
6
- note,
7
- cancel,
8
- } from "@clack/prompts";
2
+ import { intro, outro, spinner, note, cancel } from "@clack/prompts";
9
3
  import pc from "picocolors";
10
4
  import open from "open";
11
5
  import machineIdPkg from "node-machine-id";
12
-
13
6
  import { saveToken } from "../utils/config.js";
14
7
  import {
15
8
  createDeviceKey,
16
9
  getDevicePublicKey,
17
10
  } from "../utils/secureKeyStore.js";
18
11
 
19
- const API_BASE_URL =
20
- process.env.DS01_API_URL ||
21
- "https://ds-01.vercel.app";
12
+ const API_BASE_URL = process.env.DS01_API_URL || "https://ds-01.vercel.app";
22
13
 
23
14
  const { machineIdSync } = machineIdPkg;
24
15
 
25
16
  export const login = new Command()
26
17
  .name("login")
27
- .description(
28
- "Authenticate your terminal with DS01 via browser",
29
- )
18
+ .description("Authenticate your terminal with DS01 via browser")
30
19
  .action(async () => {
31
20
  console.log();
32
21
 
33
22
  intro(
34
- `${pc.bgWhite(
35
- pc.black(
36
- pc.bold(" DS01 "),
37
- ),
38
- )} ${pc.gray(
23
+ `${pc.bgWhite(pc.black(pc.bold(" DS01 ")))} ${pc.gray(
39
24
  "v1.0.0 — Terminal Authentication",
40
25
  )}`,
41
26
  );
@@ -43,300 +28,142 @@ export const login = new Command()
43
28
  const s = spinner();
44
29
 
45
30
  try {
46
- // ==================================================
47
- // 1. CREATE / LOAD SECURE DEVICE KEY
48
- // ==================================================
49
-
50
- s.start(
51
- "Preparing secure device identity...",
52
- );
31
+ s.start("Preparing secure device identity...");
53
32
 
54
33
  await createDeviceKey();
55
-
56
- const publicKey =
57
- await getDevicePublicKey();
58
-
59
- const hardwareId =
60
- machineIdSync();
61
-
34
+ const publicKey = await getDevicePublicKey();
35
+ const hardwareId = machineIdSync();
62
36
  const publicKeyType =
63
- process.platform === "win32"
64
- ? "windows-rsa"
65
- : "macos-ec";
66
-
67
- // ==================================================
68
- // 2. REQUEST DEVICE CODE
69
- // ==================================================
70
-
71
- s.start(
72
- "Requesting pairing code...",
73
- );
37
+ process.platform === "win32" ? "windows-rsa" : "macos-ec";
74
38
 
75
- const initResponse =
76
- await fetch(
77
- `${API_BASE_URL}/api/auth/device/code`,
78
- {
79
- method: "POST",
39
+ // Req to my server with machineId and certificate for now but eventually will send the publicKey
40
+ s.start("Requesting pairing code...");
80
41
 
81
- headers: {
82
- "Content-Type":
83
- "application/json",
84
- },
42
+ const initResponse = await fetch(`${API_BASE_URL}/api/auth/device/code`, {
43
+ method: "POST",
44
+ headers: {
45
+ "Content-Type": "application/json",
46
+ },
85
47
 
86
- body: JSON.stringify({
87
- machineId:
88
- hardwareId,
89
-
90
- publicKey,
91
-
92
- publicKeyType,
93
- }),
94
- },
95
- );
48
+ body: JSON.stringify({
49
+ machineId: hardwareId,
50
+ publicKey,
51
+ publicKeyType,
52
+ }),
53
+ });
96
54
 
97
55
  if (!initResponse.ok) {
98
- s.stop(
99
- pc.red(
100
- "Failed to reach DS01 authorization server.",
101
- ),
102
- );
103
-
104
- cancel(
105
- `Server responded with HTTP ${initResponse.status}`,
106
- );
107
-
56
+ s.stop(pc.red("Failed to reach DS01 authorization server."));
57
+ cancel(`Server responded with HTTP ${initResponse.status}`);
108
58
  process.exit(1);
109
59
  }
110
60
 
111
- const {
112
- deviceCode,
113
- userCode,
114
- verificationUrl,
115
- interval,
116
- } =
61
+ const { deviceCode, userCode, verificationUrl, interval } =
117
62
  await initResponse.json();
118
63
 
119
- if (
120
- !deviceCode ||
121
- !userCode ||
122
- !verificationUrl
123
- ) {
64
+ if (!deviceCode || !userCode || !verificationUrl) {
124
65
  throw new Error(
125
66
  "Authorization server returned an invalid device response.",
126
67
  );
127
68
  }
128
69
 
129
- s.stop(
130
- pc.green(
131
- "Secure device identity registered.",
132
- ),
133
- );
134
-
135
- // ==================================================
136
- // 3. SHOW BROWSER AUTHORIZATION
137
- // ==================================================
70
+ s.stop(pc.green("Secure device identity registered."));
138
71
 
72
+ // Opening users browser with verification URL
139
73
  note(
140
- `${pc.bold(
141
- "Pairing Code:",
142
- )} ${pc.cyan(
143
- pc.bold(
144
- ` ${userCode} `,
145
- ),
74
+ `${pc.bold("Pairing Code:")} ${pc.cyan(
75
+ pc.bold(` ${userCode} `),
146
76
  )}\n` +
147
- `${pc.bold(
148
- "Verification URL:",
149
- )} ${pc.underline(
150
- verificationUrl,
151
- )}`,
77
+ `${pc.bold("Verification URL:")} ${pc.underline(verificationUrl)}`,
152
78
  "Action Required",
153
79
  );
154
80
 
155
81
  try {
156
- await open(
157
- verificationUrl,
158
- );
82
+ await open(verificationUrl);
159
83
  } catch {
160
84
  // Browser launch failure is non-fatal.
161
85
  }
86
+
87
+ // we polling to one of my server endpoint to check wether the temporary req is approved or not ??
88
+ s.start("Waiting for web authorization...");
162
89
 
163
- // ==================================================
164
- // 4. POLL FOR AUTHORIZATION
165
- // ==================================================
166
-
167
- s.start(
168
- "Waiting for web authorization...",
169
- );
170
-
171
- const pollInterval =
172
- (interval || 5) * 1000;
173
-
174
- let token: string | null =
175
- null;
90
+ const pollInterval = (interval || 5) * 1000;
91
+ let token: string | null = null;
176
92
 
177
93
  while (true) {
178
- await new Promise(
179
- (resolve) =>
180
- setTimeout(
181
- resolve,
182
- pollInterval,
183
- ),
184
- );
185
-
186
- const tokenResponse =
187
- await fetch(
188
- `${API_BASE_URL}/api/auth/device/token`,
189
- {
190
- method: "POST",
94
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
191
95
 
192
- headers: {
193
- "Content-Type":
194
- "application/json",
195
- },
196
-
197
- body: JSON.stringify({
198
- deviceCode,
199
- machineId:
200
- hardwareId,
201
- }),
96
+ const tokenResponse = await fetch(
97
+ `${API_BASE_URL}/api/auth/device/token`,
98
+ {
99
+ method: "POST",
100
+ headers: {
101
+ "Content-Type": "application/json",
202
102
  },
203
- );
103
+ body: JSON.stringify({
104
+ deviceCode,
105
+ machineId: hardwareId,
106
+ }),
107
+ },
108
+ );
204
109
 
205
110
  let tokenData: any;
206
-
207
111
  try {
208
- tokenData =
209
- await tokenResponse.json();
112
+ tokenData = await tokenResponse.json();
210
113
  } catch {
211
- s.stop(
212
- pc.red(
213
- "Authorization server returned invalid JSON.",
214
- ),
215
- );
216
-
217
- cancel(
218
- "Unable to read authorization response.",
219
- );
220
-
114
+ s.stop(pc.red("Authorization server returned invalid JSON."));
115
+ cancel("Unable to read authorization response.");
221
116
  process.exit(1);
222
117
  }
223
118
 
224
- // ==================================================
225
- // AUTHORIZATION SUCCESS
226
- // ==================================================
227
-
119
+ // Auth success stop polling
228
120
  if (
229
121
  tokenResponse.ok &&
230
- typeof tokenData.accessToken ===
231
- "string" &&
122
+ typeof tokenData.accessToken === "string" &&
232
123
  tokenData.accessToken.length > 0
233
124
  ) {
234
- token =
235
- tokenData.accessToken;
236
-
125
+ token = tokenData.accessToken;
237
126
  break;
238
127
  }
239
128
 
240
- // ==================================================
241
- // STILL WAITING
242
- // ==================================================
243
-
244
- if (
245
- tokenData.error ===
246
- "authorization_pending"
247
- ) {
129
+ // Still waiting keep polling
130
+ if (tokenData.error === "authorization_pending") {
248
131
  continue;
249
132
  }
250
133
 
251
- // ==================================================
252
- // AUTHORIZATION FAILED
253
- // ==================================================
254
-
255
- s.stop(
256
- pc.red(
257
- "Authorization failed or expired.",
258
- ),
259
- );
260
-
261
- cancel(
262
- `Reason: ${
263
- tokenData.error ||
264
- "Unknown authorization error"
265
- }`,
266
- );
267
-
134
+ // Authorization Failed
135
+ s.stop(pc.red("Authorization failed or expired."));
136
+ cancel(`Reason: ${tokenData.error || "Unknown authorization error"}`);
268
137
  process.exit(1);
269
138
  }
270
139
 
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
- // ==================================================
140
+ // outside the loop stop the spinner
141
+ s.stop(pc.green("Hardware signature linked & token verified!"));
284
142
 
143
+ // ENSURE TOKEN EXISTS
285
144
  if (!token) {
286
145
  throw new Error(
287
146
  "Authorization completed without receiving an access token.",
288
147
  );
289
148
  }
290
149
 
291
- // ==================================================
292
- // 7. SAVE TOKEN
293
- // ==================================================
294
-
295
- saveToken(
296
- token,
297
- hardwareId,
298
- );
299
-
300
- // ==================================================
301
- // 8. SUCCESS
302
- // ==================================================
303
-
150
+ saveToken(token, hardwareId);
304
151
  outro(
305
- `${pc.white(
306
- "✔",
307
- )} ${pc.bold(
308
- "Terminal synced successfully",
309
- )}\n` +
310
- pc.gray(
311
- "Secure device key and session token are ready.",
312
- ),
152
+ `${pc.white("✔")} ${pc.bold("Terminal synced successfully")}\n` +
153
+ pc.gray("Secure device key and session token are ready."),
313
154
  );
314
155
 
315
- // ==================================================
316
- // 9. HARD EXIT
317
- // ==================================================
318
- //
156
+ // Hard Exit
319
157
  // The login command is completely finished.
320
- //
158
+
321
159
  // This prevents any lingering CLI handles
322
160
  // (spinner timers, readline handles, etc.)
323
161
  // from keeping the Node process alive.
324
162
  //
325
163
  process.exit(0);
326
164
  } catch (error: any) {
327
- s.stop(
328
- pc.red(
329
- "An error occurred during login.",
330
- ),
331
- );
332
-
333
- cancel(
334
- pc.gray(
335
- error?.message ||
336
- "Unknown CLI Error",
337
- ),
338
- );
339
-
165
+ s.stop(pc.red("An error occurred during login."));
166
+ cancel(pc.gray(error?.message || "Unknown CLI Error"));
340
167
  process.exit(1);
341
168
  }
342
- });
169
+ });
@@ -41,9 +41,7 @@ export const logout = new Command()
41
41
 
42
42
  // NEW: Delete local credentials only after the server confirms
43
43
  // that the CLI session has been revoked.
44
- console.log("✅ Server confirmed CLI session was revoked.");
45
44
  deleteToken();
46
- console.log("✅ Local credentials deleted.");
47
45
  spinner.succeed(chalk.green("Successfully logged out."));
48
46
  console.log(
49
47
  chalk.gray(