ds-01 1.0.14 → 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.
- package/.turbo/turbo-build.log +3 -2
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +16 -61
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +11 -45
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +20 -60
- package/dist/commands/logout.d.ts.map +1 -1
- package/dist/commands/logout.js +0 -2
- package/dist/utils/secureKeyStore.d.ts +0 -5
- package/dist/utils/secureKeyStore.d.ts.map +1 -1
- package/dist/utils/secureKeyStore.js +13 -28
- package/package.json +1 -1
- package/src/commands/add.ts +66 -210
- package/src/commands/init.ts +26 -51
- package/src/commands/login.ts +71 -244
- package/src/commands/logout.ts +0 -2
- package/src/utils/secureKeyStore.ts +41 -88
- package/src/test-key.ts +0 -20
- package/src/utils/deviceKey.ts +0 -19
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
[6n[?9001h[?1004h[m]0;C:\WINDOWS\system32\cmd.exe[?25h[?25l
|
|
2
|
-
> ds-01@1.0.
|
|
3
|
-
> tsc[5;1H[?
|
|
2
|
+
> ds-01@1.0.14 build C:\Web-dev 2.0\Personal Projects\ds01\packages\cli
|
|
3
|
+
> tsc && node scripts/copy-native.js && node scripts/build-macos-helper.js[5;1H[?25hSkipping macOS native helper build.
|
|
4
|
+
[?9001l[?1004l
|
|
@@ -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;AA+EpC,eAAO,MAAM,GAAG,SA+LZ,CAAC"}
|
package/dist/commands/add.js
CHANGED
|
@@ -9,9 +9,7 @@ import { signWithDeviceKey } from "../utils/secureKeyStore.js";
|
|
|
9
9
|
import machineIdPkg from "node-machine-id";
|
|
10
10
|
const { machineIdSync } = machineIdPkg;
|
|
11
11
|
const API_BASE_URL = process.env.DS01_API_URL || "https://ds-01.vercel.app";
|
|
12
|
-
//
|
|
13
|
-
// Helper: Verify Tailwind exists
|
|
14
|
-
// ---------------------------------------------------------
|
|
12
|
+
// function for tailwind dependency check
|
|
15
13
|
function checkTailwindInstallation() {
|
|
16
14
|
const targetDir = process.cwd();
|
|
17
15
|
const pkgJsonPath = path.join(targetDir, "package.json");
|
|
@@ -34,11 +32,10 @@ function checkTailwindInstallation() {
|
|
|
34
32
|
process.exit(1);
|
|
35
33
|
}
|
|
36
34
|
}
|
|
37
|
-
//
|
|
38
|
-
// Helper: Find dependencies that are actually missing
|
|
39
|
-
// ---------------------------------------------------------
|
|
35
|
+
// function to Find dependencies that are actually missing
|
|
40
36
|
function getMissingDependencies(dependencies) {
|
|
41
37
|
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
38
|
+
// I cannot check what is installed, so treat all required dependencies as missing
|
|
42
39
|
if (!fs.existsSync(packageJsonPath)) {
|
|
43
40
|
return dependencies;
|
|
44
41
|
}
|
|
@@ -49,9 +46,6 @@ function getMissingDependencies(dependencies) {
|
|
|
49
46
|
};
|
|
50
47
|
return dependencies.filter((dependency) => !installedDependencies[dependency]);
|
|
51
48
|
}
|
|
52
|
-
// ---------------------------------------------------------
|
|
53
|
-
// ADD COMMAND
|
|
54
|
-
// ---------------------------------------------------------
|
|
55
49
|
export const add = new Command()
|
|
56
50
|
.name("add")
|
|
57
51
|
.description("Add a component from DS01 to your project")
|
|
@@ -59,9 +53,7 @@ export const add = new Command()
|
|
|
59
53
|
.action(async (componentName) => {
|
|
60
54
|
console.log();
|
|
61
55
|
intro(`${pc.bgWhite(pc.black(pc.bold(" DS01 ")))} ${pc.gray("Adding Component")}`);
|
|
62
|
-
//
|
|
63
|
-
// 1. Validate project
|
|
64
|
-
// -----------------------------------------------------
|
|
56
|
+
// validatin
|
|
65
57
|
checkTailwindInstallation();
|
|
66
58
|
const cwd = process.cwd();
|
|
67
59
|
const configPath = path.join(cwd, "ds01.config.json");
|
|
@@ -70,9 +62,7 @@ export const add = new Command()
|
|
|
70
62
|
process.exit(1);
|
|
71
63
|
}
|
|
72
64
|
const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
73
|
-
//
|
|
74
|
-
// 2. Authentication
|
|
75
|
-
// -----------------------------------------------------
|
|
65
|
+
// for auth
|
|
76
66
|
const token = getToken();
|
|
77
67
|
const machineId = machineIdSync();
|
|
78
68
|
if (!token || !machineId) {
|
|
@@ -82,9 +72,7 @@ export const add = new Command()
|
|
|
82
72
|
const s = spinner();
|
|
83
73
|
s.start(`Fetching ${pc.cyan(`<${componentName} />`)} from registry...`);
|
|
84
74
|
try {
|
|
85
|
-
//
|
|
86
|
-
// 3. Create request-specific signed message
|
|
87
|
-
// --------------------------------------------------
|
|
75
|
+
// Creating request-specific signed message
|
|
88
76
|
const timestamp = Date.now().toString();
|
|
89
77
|
const message = [
|
|
90
78
|
"GET",
|
|
@@ -92,14 +80,10 @@ export const add = new Command()
|
|
|
92
80
|
timestamp,
|
|
93
81
|
machineId,
|
|
94
82
|
].join("\n");
|
|
95
|
-
//
|
|
96
|
-
// 4. Sign request with secure device private key
|
|
97
|
-
// --------------------------------------------------
|
|
83
|
+
// Sign request with secure device private key
|
|
98
84
|
const signature = await signWithDeviceKey(new TextEncoder().encode(message));
|
|
99
85
|
const signatureBase64 = Buffer.from(signature).toString("base64");
|
|
100
|
-
//
|
|
101
|
-
// 5. Request component from registry
|
|
102
|
-
// --------------------------------------------------
|
|
86
|
+
// Request component from registry
|
|
103
87
|
const response = await fetch(`${API_BASE_URL}/api/registry/${componentName}`, {
|
|
104
88
|
method: "GET",
|
|
105
89
|
headers: {
|
|
@@ -109,33 +93,24 @@ export const add = new Command()
|
|
|
109
93
|
"X-DS01-Signature": signatureBase64,
|
|
110
94
|
},
|
|
111
95
|
});
|
|
112
|
-
//
|
|
113
|
-
// 6. Handle registry errors
|
|
114
|
-
// --------------------------------------------------
|
|
96
|
+
// Handle registry errors
|
|
115
97
|
if (!response.ok) {
|
|
116
98
|
const errorData = await response.json().catch(() => null);
|
|
117
99
|
s.stop(pc.red("Component fetch failed."));
|
|
118
|
-
cancel(errorData?.error ||
|
|
119
|
-
`Server returned HTTP ${response.status}`);
|
|
100
|
+
cancel(errorData?.error || `Server returned HTTP ${response.status}`);
|
|
120
101
|
process.exit(1);
|
|
121
102
|
}
|
|
122
103
|
const componentData = await response.json();
|
|
123
|
-
//
|
|
124
|
-
// 7. Create component directory
|
|
125
|
-
// --------------------------------------------------
|
|
104
|
+
// Create component directory
|
|
126
105
|
const targetDir = path.join(cwd, config.componentsPath, componentName);
|
|
127
106
|
if (!fs.existsSync(targetDir)) {
|
|
128
107
|
fs.mkdirSync(targetDir, {
|
|
129
108
|
recursive: true,
|
|
130
109
|
});
|
|
131
110
|
}
|
|
132
|
-
//
|
|
133
|
-
// 8. Extract bundled file names
|
|
134
|
-
// --------------------------------------------------
|
|
111
|
+
// Extract bundled file names
|
|
135
112
|
const bundledFileNames = componentData.files.map((file) => file.name.replace(/\.[^/.]+$/, ""));
|
|
136
|
-
//
|
|
137
|
-
// 9. Write component files
|
|
138
|
-
// --------------------------------------------------
|
|
113
|
+
// Write component files
|
|
139
114
|
for (const file of componentData.files) {
|
|
140
115
|
const filePath = path.join(targetDir, file.name);
|
|
141
116
|
let content = file.content;
|
|
@@ -146,9 +121,7 @@ export const add = new Command()
|
|
|
146
121
|
fs.writeFileSync(filePath, content);
|
|
147
122
|
}
|
|
148
123
|
s.stop(pc.green(`Downloaded ${componentData.files.length} files into ${pc.white(`/${config.componentsPath}/${componentName}`)}`));
|
|
149
|
-
//
|
|
150
|
-
// 10. Install ONLY missing dependencies
|
|
151
|
-
// --------------------------------------------------
|
|
124
|
+
// Install ONLY missing dependencies
|
|
152
125
|
const registryDependencies = Array.isArray(componentData.dependencies)
|
|
153
126
|
? componentData.dependencies
|
|
154
127
|
: [];
|
|
@@ -167,32 +140,14 @@ export const add = new Command()
|
|
|
167
140
|
note(`Please run: ${pc.cyan(`npm install ${depsToInstall}`)} manually.`, "Manual Action Required");
|
|
168
141
|
}
|
|
169
142
|
}
|
|
170
|
-
|
|
171
|
-
// 11. No dependencies needed
|
|
172
|
-
// --------------------------------------------------
|
|
173
|
-
// We intentionally don't show a spinner here.
|
|
174
|
-
//
|
|
175
|
-
// Example:
|
|
176
|
-
//
|
|
177
|
-
// DS01 requires ["motion"]
|
|
178
|
-
// package.json already contains "motion"
|
|
179
|
-
//
|
|
180
|
-
// → Nothing happens.
|
|
181
|
-
// → No npm install.
|
|
182
|
-
// → No unnecessary package changes.
|
|
183
|
-
// --------------------------------------------------
|
|
184
|
-
// 12. Success
|
|
185
|
-
// --------------------------------------------------
|
|
186
|
-
const mainFile = bundledFileNames.find((name) => name.toLowerCase() ===
|
|
187
|
-
componentName.toLowerCase()) || bundledFileNames[0];
|
|
143
|
+
const mainFile = bundledFileNames.find((name) => name.toLowerCase() === componentName.toLowerCase()) || bundledFileNames[0];
|
|
188
144
|
outro(`${pc.white("✔")} ${pc.bold(`Component <${componentName} /> is ready!`)}\n` +
|
|
189
145
|
pc.gray("Import it: ") +
|
|
190
146
|
pc.cyan(`import { ${mainFile} } from "@/${config.componentsPath}/${componentName}/${mainFile}"`));
|
|
191
147
|
}
|
|
192
148
|
catch (error) {
|
|
193
149
|
s.stop(pc.red("An error occurred during injection."));
|
|
194
|
-
cancel(pc.gray(error?.message ||
|
|
195
|
-
"Unknown CLI Error"));
|
|
150
|
+
cancel(pc.gray(error?.message || "Unknown CLI Error"));
|
|
196
151
|
process.exit(1);
|
|
197
152
|
}
|
|
198
153
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,IAAI,
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,IAAI,SAmEb,CAAC"}
|
package/dist/commands/init.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import { intro, outro, spinner,
|
|
4
|
+
import { intro, outro, spinner, cancel } from "@clack/prompts";
|
|
5
5
|
import chalk from "chalk";
|
|
6
6
|
export const init = new Command()
|
|
7
7
|
.name("init")
|
|
@@ -13,72 +13,38 @@ export const init = new Command()
|
|
|
13
13
|
const cwd = process.cwd();
|
|
14
14
|
const packageJsonPath = path.join(cwd, "package.json");
|
|
15
15
|
const tsconfigPath = path.join(cwd, "tsconfig.json");
|
|
16
|
-
//
|
|
16
|
+
// runs only if package file missing
|
|
17
17
|
if (!fs.existsSync(packageJsonPath)) {
|
|
18
18
|
s.stop("Environment check failed.");
|
|
19
19
|
cancel("No package.json found. Please run this command in the root of your project.");
|
|
20
20
|
process.exit(1);
|
|
21
21
|
}
|
|
22
22
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
23
|
-
const deps = {
|
|
24
|
-
|
|
23
|
+
const deps = {
|
|
24
|
+
...packageJson.dependencies,
|
|
25
|
+
...packageJson.devDependencies,
|
|
26
|
+
};
|
|
27
|
+
// Check strictly for React or Next.js
|
|
25
28
|
if (!deps.react && !deps.next) {
|
|
26
29
|
s.stop("Environment check failed.");
|
|
27
30
|
cancel("DS01 strictly supports React and Next.js environments. Please run this in a supported project.");
|
|
28
31
|
process.exit(1);
|
|
29
32
|
}
|
|
30
|
-
//
|
|
33
|
+
// Check strictly for TypeScript
|
|
31
34
|
if (!fs.existsSync(tsconfigPath)) {
|
|
32
35
|
s.stop("Environment check failed.");
|
|
33
36
|
cancel("DS01 requires TypeScript. No tsconfig.json found in the project root.");
|
|
34
37
|
process.exit(1);
|
|
35
38
|
}
|
|
36
39
|
s.stop(chalk.green("✔ React and TypeScript detected!"));
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
message: "Where is your global CSS file?",
|
|
40
|
-
placeholder: "app/globals.css",
|
|
41
|
-
initialValue: "app/globals.css",
|
|
42
|
-
});
|
|
43
|
-
if (isCancel(cssPath)) {
|
|
44
|
-
cancel("Setup cancelled.");
|
|
45
|
-
process.exit(0);
|
|
46
|
-
}
|
|
47
|
-
// 5. Inject Dark Mode / Glassmorphic CSS variables
|
|
48
|
-
const fullCssPath = path.join(cwd, cssPath);
|
|
49
|
-
if (fs.existsSync(fullCssPath)) {
|
|
50
|
-
const cssContent = fs.readFileSync(fullCssPath, "utf-8");
|
|
51
|
-
if (!cssContent.includes("/* ds01-theme-start */")) {
|
|
52
|
-
const variables = `
|
|
53
|
-
/* ds01-theme-start */
|
|
54
|
-
@layer base {
|
|
55
|
-
:root {
|
|
56
|
-
--ds-background: #0a0a0a; /* Deep charcoal */
|
|
57
|
-
--ds-foreground: #ffffff;
|
|
58
|
-
--ds-glass-border: rgba(255, 255, 255, 0.08);
|
|
59
|
-
--ds-glass-blur: blur(16px);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
/* ds01-theme-end */
|
|
63
|
-
`;
|
|
64
|
-
fs.appendFileSync(fullCssPath, variables);
|
|
65
|
-
console.log(chalk.green(`✔ Injected design tokens into ${cssPath}`));
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
console.log(chalk.gray(`- Design tokens already exist in ${cssPath}`));
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
console.log(chalk.yellow(`⚠ Could not find ${cssPath}. You may need to add the CSS variables manually.`));
|
|
73
|
-
}
|
|
74
|
-
// 6. Create the local configuration file so the CLI remembers this project
|
|
40
|
+
// Create the local configuration file so the CLI remembers this project
|
|
41
|
+
//! Need to be understand
|
|
75
42
|
const configPath = path.join(cwd, "ds01.config.json");
|
|
76
43
|
const configData = {
|
|
77
44
|
$schema: "https://ds-01.vercel.app/schema.json",
|
|
78
45
|
style: "default",
|
|
79
46
|
typescript: true,
|
|
80
|
-
|
|
81
|
-
componentsPath: "components/ui" // This is where we will inject components later
|
|
47
|
+
componentsPath: "components/ui", // This is where we will inject components later
|
|
82
48
|
};
|
|
83
49
|
fs.writeFileSync(configPath, JSON.stringify(configData, null, 2));
|
|
84
50
|
console.log(chalk.green(`✔ Created ds01.config.json`));
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC,eAAO,MAAM,KAAK,SAyJd,CAAC"}
|
package/dist/commands/login.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
import { intro, outro, spinner, note, cancel
|
|
2
|
+
import { intro, outro, spinner, note, cancel } from "@clack/prompts";
|
|
3
3
|
import pc from "picocolors";
|
|
4
4
|
import open from "open";
|
|
5
5
|
import machineIdPkg from "node-machine-id";
|
|
6
6
|
import { saveToken } from "../utils/config.js";
|
|
7
7
|
import { createDeviceKey, getDevicePublicKey, } from "../utils/secureKeyStore.js";
|
|
8
|
-
const API_BASE_URL = process.env.DS01_API_URL ||
|
|
9
|
-
"https://ds-01.vercel.app";
|
|
8
|
+
const API_BASE_URL = process.env.DS01_API_URL || "https://ds-01.vercel.app";
|
|
10
9
|
const { machineIdSync } = machineIdPkg;
|
|
11
10
|
export const login = new Command()
|
|
12
11
|
.name("login")
|
|
@@ -16,19 +15,12 @@ export const login = new Command()
|
|
|
16
15
|
intro(`${pc.bgWhite(pc.black(pc.bold(" DS01 ")))} ${pc.gray("v1.0.0 — Terminal Authentication")}`);
|
|
17
16
|
const s = spinner();
|
|
18
17
|
try {
|
|
19
|
-
// ==================================================
|
|
20
|
-
// 1. CREATE / LOAD SECURE DEVICE KEY
|
|
21
|
-
// ==================================================
|
|
22
18
|
s.start("Preparing secure device identity...");
|
|
23
19
|
await createDeviceKey();
|
|
24
20
|
const publicKey = await getDevicePublicKey();
|
|
25
21
|
const hardwareId = machineIdSync();
|
|
26
|
-
const publicKeyType = process.platform === "win32"
|
|
27
|
-
|
|
28
|
-
: "macos-ec";
|
|
29
|
-
// ==================================================
|
|
30
|
-
// 2. REQUEST DEVICE CODE
|
|
31
|
-
// ==================================================
|
|
22
|
+
const publicKeyType = process.platform === "win32" ? "windows-rsa" : "macos-ec";
|
|
23
|
+
// Req to my server with machineId and certificate for now but eventually will send the publicKey
|
|
32
24
|
s.start("Requesting pairing code...");
|
|
33
25
|
const initResponse = await fetch(`${API_BASE_URL}/api/auth/device/code`, {
|
|
34
26
|
method: "POST",
|
|
@@ -46,16 +38,12 @@ export const login = new Command()
|
|
|
46
38
|
cancel(`Server responded with HTTP ${initResponse.status}`);
|
|
47
39
|
process.exit(1);
|
|
48
40
|
}
|
|
49
|
-
const { deviceCode, userCode, verificationUrl, interval
|
|
50
|
-
if (!deviceCode ||
|
|
51
|
-
!userCode ||
|
|
52
|
-
!verificationUrl) {
|
|
41
|
+
const { deviceCode, userCode, verificationUrl, interval } = await initResponse.json();
|
|
42
|
+
if (!deviceCode || !userCode || !verificationUrl) {
|
|
53
43
|
throw new Error("Authorization server returned an invalid device response.");
|
|
54
44
|
}
|
|
55
45
|
s.stop(pc.green("Secure device identity registered."));
|
|
56
|
-
//
|
|
57
|
-
// 3. SHOW BROWSER AUTHORIZATION
|
|
58
|
-
// ==================================================
|
|
46
|
+
// Opening users browser with verification URL
|
|
59
47
|
note(`${pc.bold("Pairing Code:")} ${pc.cyan(pc.bold(` ${userCode} `))}\n` +
|
|
60
48
|
`${pc.bold("Verification URL:")} ${pc.underline(verificationUrl)}`, "Action Required");
|
|
61
49
|
try {
|
|
@@ -64,9 +52,7 @@ export const login = new Command()
|
|
|
64
52
|
catch {
|
|
65
53
|
// Browser launch failure is non-fatal.
|
|
66
54
|
}
|
|
67
|
-
//
|
|
68
|
-
// 4. POLL FOR AUTHORIZATION
|
|
69
|
-
// ==================================================
|
|
55
|
+
// we polling to one of my server endpoint to check wether the temporary req is approved or not ??
|
|
70
56
|
s.start("Waiting for web authorization...");
|
|
71
57
|
const pollInterval = (interval || 5) * 1000;
|
|
72
58
|
let token = null;
|
|
@@ -84,65 +70,40 @@ export const login = new Command()
|
|
|
84
70
|
});
|
|
85
71
|
let tokenData;
|
|
86
72
|
try {
|
|
87
|
-
tokenData =
|
|
88
|
-
await tokenResponse.json();
|
|
73
|
+
tokenData = await tokenResponse.json();
|
|
89
74
|
}
|
|
90
75
|
catch {
|
|
91
76
|
s.stop(pc.red("Authorization server returned invalid JSON."));
|
|
92
77
|
cancel("Unable to read authorization response.");
|
|
93
78
|
process.exit(1);
|
|
94
79
|
}
|
|
95
|
-
//
|
|
96
|
-
// AUTHORIZATION SUCCESS
|
|
97
|
-
// ==================================================
|
|
80
|
+
// Auth success stop polling
|
|
98
81
|
if (tokenResponse.ok &&
|
|
99
|
-
typeof tokenData.accessToken ===
|
|
100
|
-
"string" &&
|
|
82
|
+
typeof tokenData.accessToken === "string" &&
|
|
101
83
|
tokenData.accessToken.length > 0) {
|
|
102
|
-
token =
|
|
103
|
-
tokenData.accessToken;
|
|
84
|
+
token = tokenData.accessToken;
|
|
104
85
|
break;
|
|
105
86
|
}
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
// ==================================================
|
|
109
|
-
if (tokenData.error ===
|
|
110
|
-
"authorization_pending") {
|
|
87
|
+
// Still waiting keep polling
|
|
88
|
+
if (tokenData.error === "authorization_pending") {
|
|
111
89
|
continue;
|
|
112
90
|
}
|
|
113
|
-
//
|
|
114
|
-
// AUTHORIZATION FAILED
|
|
115
|
-
// ==================================================
|
|
91
|
+
// Authorization Failed
|
|
116
92
|
s.stop(pc.red("Authorization failed or expired."));
|
|
117
|
-
cancel(`Reason: ${tokenData.error ||
|
|
118
|
-
"Unknown authorization error"}`);
|
|
93
|
+
cancel(`Reason: ${tokenData.error || "Unknown authorization error"}`);
|
|
119
94
|
process.exit(1);
|
|
120
95
|
}
|
|
121
|
-
//
|
|
122
|
-
// 5. STOP POLLING SPINNER
|
|
123
|
-
// ==================================================
|
|
96
|
+
// outside the loop stop the spinner
|
|
124
97
|
s.stop(pc.green("Hardware signature linked & token verified!"));
|
|
125
|
-
//
|
|
126
|
-
// 6. ENSURE TOKEN EXISTS
|
|
127
|
-
// ==================================================
|
|
98
|
+
// ENSURE TOKEN EXISTS
|
|
128
99
|
if (!token) {
|
|
129
100
|
throw new Error("Authorization completed without receiving an access token.");
|
|
130
101
|
}
|
|
131
|
-
// ==================================================
|
|
132
|
-
// 7. SAVE TOKEN
|
|
133
|
-
// ==================================================
|
|
134
102
|
saveToken(token, hardwareId);
|
|
135
|
-
// ==================================================
|
|
136
|
-
// 8. SUCCESS
|
|
137
|
-
// ==================================================
|
|
138
103
|
outro(`${pc.white("✔")} ${pc.bold("Terminal synced successfully")}\n` +
|
|
139
104
|
pc.gray("Secure device key and session token are ready."));
|
|
140
|
-
//
|
|
141
|
-
// 9. HARD EXIT
|
|
142
|
-
// ==================================================
|
|
143
|
-
//
|
|
105
|
+
// Hard Exit
|
|
144
106
|
// The login command is completely finished.
|
|
145
|
-
//
|
|
146
107
|
// This prevents any lingering CLI handles
|
|
147
108
|
// (spinner timers, readline handles, etc.)
|
|
148
109
|
// from keeping the Node process alive.
|
|
@@ -151,8 +112,7 @@ export const login = new Command()
|
|
|
151
112
|
}
|
|
152
113
|
catch (error) {
|
|
153
114
|
s.stop(pc.red("An error occurred during login."));
|
|
154
|
-
cancel(pc.gray(error?.message ||
|
|
155
|
-
"Unknown CLI Error"));
|
|
115
|
+
cancel(pc.gray(error?.message || "Unknown CLI Error"));
|
|
156
116
|
process.exit(1);
|
|
157
117
|
}
|
|
158
118
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,eAAO,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,eAAO,MAAM,MAAM,SA+Cf,CAAC"}
|
package/dist/commands/logout.js
CHANGED
|
@@ -32,9 +32,7 @@ export const logout = new Command()
|
|
|
32
32
|
}
|
|
33
33
|
// NEW: Delete local credentials only after the server confirms
|
|
34
34
|
// that the CLI session has been revoked.
|
|
35
|
-
console.log("✅ Server confirmed CLI session was revoked.");
|
|
36
35
|
deleteToken();
|
|
37
|
-
console.log("✅ Local credentials deleted.");
|
|
38
36
|
spinner.succeed(chalk.green("Successfully logged out."));
|
|
39
37
|
console.log(chalk.gray("Your CLI session has been revoked and local credentials have been cleared."));
|
|
40
38
|
}
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ---------------------------------------------------------
|
|
3
|
-
* PUBLIC API
|
|
4
|
-
* ---------------------------------------------------------
|
|
5
|
-
*/
|
|
6
1
|
export declare function createDeviceKey(): Promise<void>;
|
|
7
2
|
export declare function getDevicePublicKey(): Promise<string>;
|
|
8
3
|
export declare function signWithDeviceKey(data: Uint8Array): Promise<Uint8Array>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secureKeyStore.d.ts","sourceRoot":"","sources":["../../src/utils/secureKeyStore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"secureKeyStore.d.ts","sourceRoot":"","sources":["../../src/utils/secureKeyStore.ts"],"names":[],"mappings":"AAoUA,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CASrD;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAQ1D;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAQ7E;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CASrD"}
|
|
@@ -7,7 +7,11 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
const execFileAsync = promisify(execFile);
|
|
8
8
|
const KEY_NAME = "DS01-CLI-Device-Key";
|
|
9
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
// import.meta.ur -- current module ka location URL form mein deta hai
|
|
10
11
|
const __dirname = path.dirname(__filename);
|
|
12
|
+
//C:\Projects\DS01\cli\dist\utils
|
|
13
|
+
// __filename = where is THIS FILE?
|
|
14
|
+
// __dirname = which folder contains THIS FILE?
|
|
11
15
|
function getMacHelperPath() {
|
|
12
16
|
return path.resolve(__dirname, "../native/macos-key-helper.swift");
|
|
13
17
|
}
|
|
@@ -17,11 +21,7 @@ function ensureSupportedOS() {
|
|
|
17
21
|
throw new Error("DS01 secure device keys currently support Windows and macOS.");
|
|
18
22
|
}
|
|
19
23
|
}
|
|
20
|
-
|
|
21
|
-
* ---------------------------------------------------------
|
|
22
|
-
* WINDOWS
|
|
23
|
-
* ---------------------------------------------------------
|
|
24
|
-
*/
|
|
24
|
+
// for windows
|
|
25
25
|
async function createWindowsDeviceKey() {
|
|
26
26
|
const script = `
|
|
27
27
|
$ErrorActionPreference = "Stop"
|
|
@@ -84,15 +84,6 @@ Write-Output "CREATED"
|
|
|
84
84
|
throw new Error("Failed to create Windows DS01 device key.");
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
-
/**
|
|
88
|
-
* Find exactly one valid DS01 certificate.
|
|
89
|
-
*
|
|
90
|
-
* We intentionally do not use Select-Object -First 1.
|
|
91
|
-
*
|
|
92
|
-
* 0 certificates -> error
|
|
93
|
-
* 1 certificate -> use it
|
|
94
|
-
* 2+ certificates -> error
|
|
95
|
-
*/
|
|
96
87
|
function getWindowsCertificateLookup() {
|
|
97
88
|
return `
|
|
98
89
|
$certificates = @(Get-ChildItem Cert:\\CurrentUser\\My |
|
|
@@ -113,6 +104,10 @@ if ($certificates.Count -gt 1) {
|
|
|
113
104
|
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]$certificates[0]
|
|
114
105
|
`;
|
|
115
106
|
}
|
|
107
|
+
// cert - just a variable holding the certificate object
|
|
108
|
+
// X509Certificate2 is a Windows/.NET certificate object
|
|
109
|
+
// that gives the code a standard way to work with the certificate and its associated key information
|
|
110
|
+
// X509Certificate2 a class/type, rather than simply a "format"
|
|
116
111
|
async function getWindowsPublicKey() {
|
|
117
112
|
const script = `
|
|
118
113
|
$ErrorActionPreference = "Stop"
|
|
@@ -218,11 +213,7 @@ Write-Output "DELETED"
|
|
|
218
213
|
windowsHide: true,
|
|
219
214
|
});
|
|
220
215
|
}
|
|
221
|
-
|
|
222
|
-
* ---------------------------------------------------------
|
|
223
|
-
* MACOS
|
|
224
|
-
* ---------------------------------------------------------
|
|
225
|
-
*/
|
|
216
|
+
// for Mac
|
|
226
217
|
async function runMacHelper(operation, data) {
|
|
227
218
|
const helper = getMacHelperPath();
|
|
228
219
|
const args = [helper, operation];
|
|
@@ -236,10 +227,8 @@ async function runMacHelper(operation, data) {
|
|
|
236
227
|
}
|
|
237
228
|
async function createMacDeviceKey() {
|
|
238
229
|
const result = await runMacHelper("create");
|
|
239
|
-
if (result !== "CREATED" &&
|
|
240
|
-
result
|
|
241
|
-
throw new Error(result ||
|
|
242
|
-
"Failed to create macOS Secure Enclave device key.");
|
|
230
|
+
if (result !== "CREATED" && result !== "EXISTS") {
|
|
231
|
+
throw new Error(result || "Failed to create macOS Secure Enclave device key.");
|
|
243
232
|
}
|
|
244
233
|
}
|
|
245
234
|
async function getMacPublicKey() {
|
|
@@ -259,11 +248,7 @@ async function signMacDeviceKey(data) {
|
|
|
259
248
|
async function deleteMacDeviceKey() {
|
|
260
249
|
await runMacHelper("delete");
|
|
261
250
|
}
|
|
262
|
-
|
|
263
|
-
* ---------------------------------------------------------
|
|
264
|
-
* PUBLIC API
|
|
265
|
-
* ---------------------------------------------------------
|
|
266
|
-
*/
|
|
251
|
+
// Public APIs which we use this for creating keys and certificate
|
|
267
252
|
export async function createDeviceKey() {
|
|
268
253
|
ensureSupportedOS();
|
|
269
254
|
if (os.platform() === "win32") {
|