@sekyuriti/attest 0.2.1 → 0.2.2

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.
Files changed (2) hide show
  1. package/bin/attest.js +110 -126
  2. package/package.json +1 -1
package/bin/attest.js CHANGED
@@ -139,7 +139,109 @@ function printHeader() {
139
139
  logBold(" █▀▀ █▀▀ █▄▀ █▄█ █ █ █▀█ █ ▀█▀ █");
140
140
  logBold(" ▄▄█ ██▄ █ █ █ █▄█ █▀▄ █ █ █");
141
141
  log("");
142
- logDim(" ATTEST CLI v0.2.0");
142
+ logDim(" ATTEST CLI v0.2.1");
143
+ log("");
144
+ }
145
+
146
+ // ═══════════════════════════════════════════════════════════════════
147
+ // INIT HELPER (used by both login and init commands)
148
+ // ═══════════════════════════════════════════════════════════════════
149
+
150
+ async function runInit(publicKey, apiKey) {
151
+ let steps = [];
152
+
153
+ // Step 1: Add .env variables
154
+ const envPath = path.join(process.cwd(), ".env");
155
+ const envLocalPath = path.join(process.cwd(), ".env.local");
156
+ let targetEnvPath = envLocalPath;
157
+
158
+ if (fs.existsSync(envLocalPath)) {
159
+ targetEnvPath = envLocalPath;
160
+ } else if (fs.existsSync(envPath)) {
161
+ targetEnvPath = envPath;
162
+ }
163
+
164
+ const envVars = `
165
+ # ATTEST Configuration
166
+ NEXT_PUBLIC_ATTEST_KEY=${publicKey}
167
+ ATTEST_SECRET_KEY=${apiKey}
168
+ `.trim();
169
+
170
+ if (fs.existsSync(targetEnvPath)) {
171
+ let content = fs.readFileSync(targetEnvPath, "utf-8");
172
+ if (!content.includes("ATTEST_KEY")) {
173
+ content += "\n\n" + envVars + "\n";
174
+ fs.writeFileSync(targetEnvPath, content);
175
+ steps.push(`Added ATTEST config to ${path.basename(targetEnvPath)}`);
176
+ } else {
177
+ steps.push(`ATTEST config already in ${path.basename(targetEnvPath)}`);
178
+ }
179
+ } else {
180
+ fs.writeFileSync(envLocalPath, envVars + "\n");
181
+ steps.push("Created .env.local with ATTEST config");
182
+ }
183
+
184
+ // Step 2: Find and update layout.tsx
185
+ const layoutPaths = [
186
+ path.join(process.cwd(), "src/app/layout.tsx"),
187
+ path.join(process.cwd(), "app/layout.tsx"),
188
+ path.join(process.cwd(), "src/app/layout.js"),
189
+ path.join(process.cwd(), "app/layout.js"),
190
+ ];
191
+
192
+ let layoutPath = null;
193
+ for (const p of layoutPaths) {
194
+ if (fs.existsSync(p)) {
195
+ layoutPath = p;
196
+ break;
197
+ }
198
+ }
199
+
200
+ const scriptTag = `<Script
201
+ src="https://sekyuriti.build/api/v2/attest/script/${publicKey}"
202
+ strategy="beforeInteractive"
203
+ />`;
204
+
205
+ if (layoutPath) {
206
+ let layoutContent = fs.readFileSync(layoutPath, "utf-8");
207
+
208
+ if (layoutContent.includes("sekyuriti.build/api/v2/attest/script")) {
209
+ steps.push("ATTEST script already in layout");
210
+ } else {
211
+ // Check if Script is already imported
212
+ const hasScriptImport = layoutContent.includes("from 'next/script'") || layoutContent.includes('from "next/script"');
213
+
214
+ if (!hasScriptImport) {
215
+ // Add Script import after the first import line
216
+ layoutContent = layoutContent.replace(
217
+ /(import .+ from ['"][^'"]+['"];?\n)/,
218
+ `$1import Script from "next/script";\n`
219
+ );
220
+ }
221
+
222
+ // Add script tag after <body> or <body className=...>
223
+ if (layoutContent.includes("<body")) {
224
+ layoutContent = layoutContent.replace(
225
+ /(<body[^>]*>)/,
226
+ `$1\n ${scriptTag}`
227
+ );
228
+ fs.writeFileSync(layoutPath, layoutContent);
229
+ steps.push(`Added ATTEST script to ${path.basename(layoutPath)}`);
230
+ } else {
231
+ steps.push("Could not find <body> tag in layout");
232
+ }
233
+ }
234
+ } else {
235
+ steps.push("No layout.tsx found - add script manually");
236
+ }
237
+
238
+ // Print results
239
+ for (const step of steps) {
240
+ log(` ${c.bold}✓${c.reset} ${step}`);
241
+ }
242
+
243
+ log("");
244
+ log(" Documentation: https://sekyuriti.build/docs/attest");
143
245
  log("");
144
246
  }
145
247
 
@@ -211,6 +313,11 @@ async function cmdLogin() {
211
313
  apiKey: data.apiKey,
212
314
  });
213
315
 
316
+ // Auto-run init after successful login
317
+ log(" Setting up your project...");
318
+ log("");
319
+ await runInit(data.publicKey, data.apiKey);
320
+
214
321
  return;
215
322
  }
216
323
  }
@@ -334,132 +441,9 @@ async function cmdInit() {
334
441
  return;
335
442
  }
336
443
 
337
- let steps = [];
338
-
339
- // Step 1: Add .env variables
340
- const envPath = path.join(process.cwd(), ".env");
341
- const envLocalPath = path.join(process.cwd(), ".env.local");
342
- let targetEnvPath = envLocalPath;
343
-
344
- if (fs.existsSync(envLocalPath)) {
345
- targetEnvPath = envLocalPath;
346
- } else if (fs.existsSync(envPath)) {
347
- targetEnvPath = envPath;
348
- }
349
-
350
- const envVars = `
351
- # ATTEST Configuration
352
- NEXT_PUBLIC_ATTEST_KEY=${config.publicKey}
353
- ATTEST_SECRET_KEY=${config.apiKey}
354
- `.trim();
355
-
356
- if (fs.existsSync(targetEnvPath)) {
357
- let content = fs.readFileSync(targetEnvPath, "utf-8");
358
- if (!content.includes("ATTEST_KEY")) {
359
- content += "\n\n" + envVars + "\n";
360
- fs.writeFileSync(targetEnvPath, content);
361
- steps.push(`Added ATTEST config to ${path.basename(targetEnvPath)}`);
362
- } else {
363
- steps.push(`ATTEST config already in ${path.basename(targetEnvPath)}`);
364
- }
365
- } else {
366
- fs.writeFileSync(envLocalPath, envVars + "\n");
367
- steps.push("Created .env.local with ATTEST config");
368
- }
369
-
370
- // Step 2: Find and update layout.tsx
371
- const layoutPaths = [
372
- path.join(process.cwd(), "src/app/layout.tsx"),
373
- path.join(process.cwd(), "app/layout.tsx"),
374
- path.join(process.cwd(), "src/app/layout.js"),
375
- path.join(process.cwd(), "app/layout.js"),
376
- ];
377
-
378
- let layoutPath = null;
379
- for (const p of layoutPaths) {
380
- if (fs.existsSync(p)) {
381
- layoutPath = p;
382
- break;
383
- }
384
- }
385
-
386
- const scriptTag = `<Script
387
- src="https://sekyuriti.build/api/v2/attest/script/${config.publicKey}"
388
- strategy="beforeInteractive"
389
- />`;
390
-
391
- if (layoutPath) {
392
- let layoutContent = fs.readFileSync(layoutPath, "utf-8");
393
-
394
- if (layoutContent.includes("sekyuriti.build/api/v2/attest/script")) {
395
- steps.push("ATTEST script already in layout");
396
- } else {
397
- // Check if Script is already imported
398
- const hasScriptImport = layoutContent.includes("from 'next/script'") || layoutContent.includes('from "next/script"');
399
-
400
- if (!hasScriptImport) {
401
- // Add Script import after the first import line
402
- layoutContent = layoutContent.replace(
403
- /(import .+ from ['"][^'"]+['"];?\n)/,
404
- `$1import Script from "next/script";\n`
405
- );
406
- }
407
-
408
- // Add script tag after <body> or <body className=...>
409
- if (layoutContent.includes("<body")) {
410
- layoutContent = layoutContent.replace(
411
- /(<body[^>]*>)/,
412
- `$1\n ${scriptTag}`
413
- );
414
- fs.writeFileSync(layoutPath, layoutContent);
415
- steps.push(`Added ATTEST script to ${path.basename(layoutPath)}`);
416
- } else {
417
- steps.push("Could not find <body> tag in layout");
418
- }
419
- }
420
- } else {
421
- steps.push("No layout.tsx found - add script manually");
422
- }
423
-
424
- // Step 3: Check for middleware.ts and offer to add verification
425
- const middlewarePaths = [
426
- path.join(process.cwd(), "middleware.ts"),
427
- path.join(process.cwd(), "src/middleware.ts"),
428
- path.join(process.cwd(), "middleware.js"),
429
- path.join(process.cwd(), "src/middleware.js"),
430
- ];
431
-
432
- let hasMiddleware = false;
433
- for (const p of middlewarePaths) {
434
- if (fs.existsSync(p)) {
435
- hasMiddleware = true;
436
- break;
437
- }
438
- }
439
-
440
- // Print results
441
- log(" SETUP COMPLETE");
442
- log("");
443
-
444
- for (const step of steps) {
445
- log(` ${c.bold}✓${c.reset} ${step}`);
446
- }
447
-
448
- log("");
449
-
450
- if (!hasMiddleware) {
451
- log(" Optional: Add middleware for server-side verification:");
452
- log("");
453
- log(` ${c.dim}// middleware.ts${c.reset}`);
454
- log(` ${c.dim}import { createAttestMiddleware } from '@sekyuriti/attest/middleware';${c.reset}`);
455
- log(` ${c.dim}export default createAttestMiddleware({${c.reset}`);
456
- log(` ${c.dim} protectedPaths: ['/api/'],${c.reset}`);
457
- log(` ${c.dim}});${c.reset}`);
458
- log("");
459
- }
460
-
461
- log(" Documentation: https://sekyuriti.build/docs/attest");
444
+ log(" Setting up ATTEST...");
462
445
  log("");
446
+ await runInit(config.publicKey, config.apiKey);
463
447
  }
464
448
 
465
449
  // ═══════════════════════════════════════════════════════════════════
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sekyuriti/attest",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "API protection middleware for Next.js - verify requests with ATTEST",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",