design-lazyyy-cli 0.2.1 → 0.3.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/package.json +1 -1
- package/src/index.js +105 -5
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -11,6 +11,13 @@ import { createInterface } from 'readline';
|
|
|
11
11
|
import { homedir, platform } from 'os';
|
|
12
12
|
import { FigJamClient } from './figjam-client.js';
|
|
13
13
|
|
|
14
|
+
// Auth — offline hash-based verification
|
|
15
|
+
import { createHash } from 'crypto';
|
|
16
|
+
const VALID_TOKEN_HASHES = [
|
|
17
|
+
// SHA-256 hashes of valid tokens (add more with: echo -n "token" | shasum -a 256)
|
|
18
|
+
'065ea2d80d8e1e61025f115d01d08518b00615047a3ec14bd4e6f7d4f8813929',
|
|
19
|
+
];
|
|
20
|
+
|
|
14
21
|
// Platform detection
|
|
15
22
|
const IS_WINDOWS = platform() === 'win32';
|
|
16
23
|
const IS_MAC = platform() === 'darwin';
|
|
@@ -95,10 +102,56 @@ function saveConfig(config) {
|
|
|
95
102
|
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
96
103
|
}
|
|
97
104
|
|
|
98
|
-
//
|
|
105
|
+
// Helper: Hash token with SHA-256
|
|
106
|
+
function hashToken(token) {
|
|
107
|
+
return createHash('sha256').update(token).digest('hex');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Helper: Verify token offline against known hashes
|
|
111
|
+
function verifyToken(token) {
|
|
112
|
+
return VALID_TOKEN_HASHES.includes(hashToken(token));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Helper: Check API key (gate all commands)
|
|
116
|
+
function checkApiKey() {
|
|
117
|
+
const config = loadConfig();
|
|
118
|
+
if (!config.token) {
|
|
119
|
+
console.log(chalk.red('\n✗ Token required.\n'));
|
|
120
|
+
console.log(chalk.white(' Get a token from plugin87, then run:\n'));
|
|
121
|
+
console.log(chalk.cyan(' design-lazyyy-cli login <token>\n'));
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
if (!verifyToken(config.token)) {
|
|
125
|
+
console.log(chalk.red('\n✗ Token invalid or revoked.\n'));
|
|
126
|
+
console.log(chalk.white(' Get a new token from plugin87, then run:\n'));
|
|
127
|
+
console.log(chalk.cyan(' design-lazyyy-cli login <token>\n'));
|
|
128
|
+
delete config.token;
|
|
129
|
+
saveConfig(config);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Resolve engine binary path (check local then walk up for hoisted deps)
|
|
99
136
|
const __filename2 = fileURLToPath(import.meta.url);
|
|
100
137
|
const __pkgRoot = dirname(dirname(__filename2));
|
|
101
|
-
|
|
138
|
+
|
|
139
|
+
function findEngineBin() {
|
|
140
|
+
// Check local node_modules first
|
|
141
|
+
const local = resolve(__pkgRoot, 'node_modules', '.bin', 'figma-use');
|
|
142
|
+
if (existsSync(local)) return local;
|
|
143
|
+
// Walk up directories to find hoisted binary
|
|
144
|
+
let dir = __pkgRoot;
|
|
145
|
+
while (true) {
|
|
146
|
+
const parent = dirname(dir);
|
|
147
|
+
const candidate = resolve(parent, 'node_modules', '.bin', 'figma-use');
|
|
148
|
+
if (existsSync(candidate)) return candidate;
|
|
149
|
+
if (parent === dir) break;
|
|
150
|
+
dir = parent;
|
|
151
|
+
}
|
|
152
|
+
return local; // fallback
|
|
153
|
+
}
|
|
154
|
+
const ENGINE_BIN = findEngineBin();
|
|
102
155
|
|
|
103
156
|
// Helper: Run engine command
|
|
104
157
|
function figmaUse(args, options = {}) {
|
|
@@ -115,8 +168,9 @@ function figmaUse(args, options = {}) {
|
|
|
115
168
|
}
|
|
116
169
|
}
|
|
117
170
|
|
|
118
|
-
// Helper: Check connection
|
|
171
|
+
// Helper: Check connection (also gates on API key)
|
|
119
172
|
function checkConnection() {
|
|
173
|
+
checkApiKey();
|
|
120
174
|
const result = figmaUse('status', { silent: true });
|
|
121
175
|
if (!result || result.includes('Not connected')) {
|
|
122
176
|
console.log(chalk.red('\n✗ Not connected to Figma\n'));
|
|
@@ -178,11 +232,13 @@ program
|
|
|
178
232
|
program.action(async () => {
|
|
179
233
|
const config = loadConfig();
|
|
180
234
|
|
|
235
|
+
// Auth gate
|
|
236
|
+
checkApiKey();
|
|
237
|
+
|
|
181
238
|
// First time? Run init
|
|
182
239
|
if (!config.patched || !checkDependencies(true)) {
|
|
183
240
|
showBanner();
|
|
184
241
|
console.log(chalk.white(' Welcome! Let\'s get you set up.\n'));
|
|
185
|
-
console.log(chalk.gray(' This takes about 30 seconds. No API key needed.\n'));
|
|
186
242
|
|
|
187
243
|
// Step 1: Check Node version
|
|
188
244
|
console.log(chalk.blue('Step 1/4: ') + 'Checking Node.js...');
|
|
@@ -338,10 +394,10 @@ program
|
|
|
338
394
|
.command('init')
|
|
339
395
|
.description('Interactive setup wizard')
|
|
340
396
|
.action(async () => {
|
|
397
|
+
checkApiKey();
|
|
341
398
|
showBanner();
|
|
342
399
|
|
|
343
400
|
console.log(chalk.white(' Welcome! Let\'s get you set up.\n'));
|
|
344
|
-
console.log(chalk.gray(' This takes about 30 seconds. No API key needed.\n'));
|
|
345
401
|
|
|
346
402
|
// Step 1: Check Node version
|
|
347
403
|
console.log(chalk.blue('Step 1/4: ') + 'Checking Node.js...');
|
|
@@ -447,12 +503,55 @@ program
|
|
|
447
503
|
execSync('design-lazyyy-cli init', { stdio: 'inherit' });
|
|
448
504
|
});
|
|
449
505
|
|
|
506
|
+
// ============ LOGIN ============
|
|
507
|
+
|
|
508
|
+
program
|
|
509
|
+
.command('login [token]')
|
|
510
|
+
.description('Authenticate with a token from plugin87')
|
|
511
|
+
.action(async (token) => {
|
|
512
|
+
if (!token) {
|
|
513
|
+
token = await prompt(chalk.white('Enter token: '));
|
|
514
|
+
}
|
|
515
|
+
token = token.trim();
|
|
516
|
+
if (!token) {
|
|
517
|
+
console.log(chalk.red('\n✗ Token cannot be empty.\n'));
|
|
518
|
+
process.exit(1);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (!verifyToken(token)) {
|
|
522
|
+
console.log(chalk.red('\n✗ Invalid token.\n'));
|
|
523
|
+
process.exit(1);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const config = loadConfig();
|
|
527
|
+
config.token = token;
|
|
528
|
+
saveConfig(config);
|
|
529
|
+
console.log(chalk.green('\n✓ Token verified! Welcome.\n'));
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
// ============ LOGOUT ============
|
|
533
|
+
|
|
534
|
+
program
|
|
535
|
+
.command('logout')
|
|
536
|
+
.description('Remove saved token')
|
|
537
|
+
.action(() => {
|
|
538
|
+
const config = loadConfig();
|
|
539
|
+
if (!config.token) {
|
|
540
|
+
console.log(chalk.yellow('\nNo token saved.\n'));
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
delete config.token;
|
|
544
|
+
saveConfig(config);
|
|
545
|
+
console.log(chalk.green('\n✓ Token removed. You are logged out.\n'));
|
|
546
|
+
});
|
|
547
|
+
|
|
450
548
|
// ============ STATUS ============
|
|
451
549
|
|
|
452
550
|
program
|
|
453
551
|
.command('status')
|
|
454
552
|
.description('Check connection to Figma')
|
|
455
553
|
.action(() => {
|
|
554
|
+
checkApiKey();
|
|
456
555
|
// Check if first run
|
|
457
556
|
const config = loadConfig();
|
|
458
557
|
if (!config.patched && !checkDependencies(true)) {
|
|
@@ -469,6 +568,7 @@ program
|
|
|
469
568
|
.command('connect')
|
|
470
569
|
.description('Start Figma with remote debugging enabled')
|
|
471
570
|
.action(async () => {
|
|
571
|
+
checkApiKey();
|
|
472
572
|
// Check if first run
|
|
473
573
|
const config = loadConfig();
|
|
474
574
|
if (!config.patched) {
|