@sekyuriti/attest 0.2.0 → 0.2.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.
Files changed (2) hide show
  1. package/bin/attest.js +102 -29
  2. package/package.json +1 -1
package/bin/attest.js CHANGED
@@ -334,15 +334,17 @@ async function cmdInit() {
334
334
  return;
335
335
  }
336
336
 
337
- // Check if .env exists
337
+ let steps = [];
338
+
339
+ // Step 1: Add .env variables
338
340
  const envPath = path.join(process.cwd(), ".env");
339
341
  const envLocalPath = path.join(process.cwd(), ".env.local");
340
- let targetPath = envLocalPath;
342
+ let targetEnvPath = envLocalPath;
341
343
 
342
344
  if (fs.existsSync(envLocalPath)) {
343
- targetPath = envLocalPath;
345
+ targetEnvPath = envLocalPath;
344
346
  } else if (fs.existsSync(envPath)) {
345
- targetPath = envPath;
347
+ targetEnvPath = envPath;
346
348
  }
347
349
 
348
350
  const envVars = `
@@ -351,40 +353,111 @@ NEXT_PUBLIC_ATTEST_KEY=${config.publicKey}
351
353
  ATTEST_SECRET_KEY=${config.apiKey}
352
354
  `.trim();
353
355
 
354
- if (fs.existsSync(targetPath)) {
355
- // Append to existing
356
- let content = fs.readFileSync(targetPath, "utf-8");
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
+ }
357
369
 
358
- if (content.includes("ATTEST_KEY")) {
359
- log(" ATTEST is already configured in your .env file.");
360
- log("");
361
- return;
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;
362
383
  }
384
+ }
385
+
386
+ const scriptTag = `<Script
387
+ src="https://sekyuriti.build/api/v2/attest/script/${config.publicKey}"
388
+ strategy="beforeInteractive"
389
+ />`;
363
390
 
364
- content += "\n\n" + envVars + "\n";
365
- fs.writeFileSync(targetPath, content);
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
+ }
366
407
 
367
- log(` ${c.bold}✓${c.reset} Added ATTEST config to ${path.basename(targetPath)}`);
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
+ }
368
420
  } else {
369
- // Create new .env.local
370
- fs.writeFileSync(envLocalPath, envVars + "\n");
371
- log(` ${c.bold}✓${c.reset} Created .env.local with ATTEST config`);
421
+ steps.push("No layout.tsx found - add script manually");
372
422
  }
373
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");
374
442
  log("");
375
- log(" Next steps:");
376
- log("");
377
- log(` ${c.dim}1.${c.reset} Add the script to your app:`);
378
- log("");
379
- log(` ${c.dim}<Script`);
380
- log(` src="https://sekyuriti.build/api/v2/attest/script/${config.publicKey}"`);
381
- log(` strategy="beforeInteractive"`);
382
- log(` />${c.reset}`);
383
- log("");
384
- log(` ${c.dim}2.${c.reset} Add the middleware (optional):`);
385
- log("");
386
- log(` ${c.dim}import { createAttestMiddleware } from '@sekyuriti/attest/middleware';${c.reset}`);
443
+
444
+ for (const step of steps) {
445
+ log(` ${c.bold}✓${c.reset} ${step}`);
446
+ }
447
+
387
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
+
388
461
  log(" Documentation: https://sekyuriti.build/docs/attest");
389
462
  log("");
390
463
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sekyuriti/attest",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
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",