create-pulsekit 1.0.0 → 1.0.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.
package/dist/index.js CHANGED
@@ -23,6 +23,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  mod
24
24
  ));
25
25
 
26
+ // src/index.ts
27
+ var import_node_fs6 = __toESM(require("fs"));
28
+ var import_node_path6 = __toESM(require("path"));
29
+
26
30
  // src/detect.ts
27
31
  var import_node_fs = __toESM(require("fs"));
28
32
  var import_node_path = __toESM(require("path"));
@@ -174,11 +178,29 @@ async function Dashboard() {
174
178
 
175
179
  export default function AnalyticsPage() {
176
180
  return (
177
- <PulseAuthGate secret={process.env.PULSE_SECRET}>
178
- <Suspense fallback={<div className="flex items-center justify-center min-h-screen p-6"><Spinner className="size-6" /></div>}>
181
+ <Suspense fallback={<div className="flex items-center justify-center min-h-screen p-6"><Spinner className="size-6" /></div>}>
182
+ <PulseAuthGate secret={process.env.PULSE_SECRET}>
179
183
  <Dashboard />
180
- </Suspense>
181
- </PulseAuthGate>
184
+ </PulseAuthGate>
185
+ </Suspense>
186
+ );
187
+ }
188
+ `;
189
+ const trackerWrapper = `import { PulseTracker } from "@pulsekit/next/client";
190
+ import { createPulseIngestionToken } from "@pulsekit/next";
191
+ import { connection } from "next/server";
192
+
193
+ export default async function PulseTrackerWrapper() {
194
+ await connection();
195
+ const token = process.env.PULSE_SECRET
196
+ ? await createPulseIngestionToken(process.env.PULSE_SECRET)
197
+ : undefined;
198
+
199
+ return (
200
+ <PulseTracker
201
+ excludePaths={["/admin/analytics"]}
202
+ token={token}
203
+ />
182
204
  );
183
205
  }
184
206
  `;
@@ -208,6 +230,15 @@ export { Spinner }
208
230
  import_node_fs2.default.writeFileSync(spinnerPath, spinnerContent, "utf8");
209
231
  console.log(" Created: components/ui/spinner.tsx");
210
232
  }
233
+ const componentsDir = appDir.includes(import_node_path2.default.join("src", "app")) ? import_node_path2.default.join(cwd, "src", "components") : import_node_path2.default.join(cwd, "components");
234
+ const wrapperPath = import_node_path2.default.join(componentsDir, "pulse-tracker-wrapper.tsx");
235
+ import_node_fs2.default.mkdirSync(componentsDir, { recursive: true });
236
+ if (import_node_fs2.default.existsSync(wrapperPath)) {
237
+ console.log(" Skipped (already exists): components/pulse-tracker-wrapper.tsx");
238
+ } else {
239
+ import_node_fs2.default.writeFileSync(wrapperPath, trackerWrapper, "utf8");
240
+ console.log(" Created: components/pulse-tracker-wrapper.tsx");
241
+ }
211
242
  const files = [
212
243
  { rel: "api/pulse/route.ts", content: pulseRoute },
213
244
  { rel: "api/pulse/auth/route.ts", content: authRoute },
@@ -251,21 +282,28 @@ async function injectPulseTracker() {
251
282
  return;
252
283
  }
253
284
  let content = import_node_fs3.default.readFileSync(foundPath, "utf8");
254
- if (content.includes("PulseTracker")) {
285
+ if (content.includes("PulseTrackerWrapper") || content.includes("PulseTracker")) {
255
286
  console.log(" PulseTracker already present in layout. Skipping.\n");
256
287
  return;
257
288
  }
258
- const importStatement = 'import { PulseTracker } from "@pulsekit/next/client";';
289
+ const importStatements = [
290
+ 'import { Suspense } from "react";',
291
+ 'import PulseTrackerWrapper from "@/components/pulse-tracker-wrapper";'
292
+ ];
259
293
  const importRegex = /^import\s.+$/gm;
260
294
  let lastImportEnd = -1;
261
295
  let match;
262
296
  while ((match = importRegex.exec(content)) !== null) {
263
297
  lastImportEnd = match.index + match[0].length;
264
298
  }
265
- if (lastImportEnd === -1) {
266
- content = importStatement + "\n" + content;
267
- } else {
268
- content = content.slice(0, lastImportEnd) + "\n" + importStatement + content.slice(lastImportEnd);
299
+ const newImports = importStatements.filter((stmt) => !content.includes(stmt));
300
+ const importBlock = newImports.join("\n");
301
+ if (importBlock) {
302
+ if (lastImportEnd === -1) {
303
+ content = importBlock + "\n" + content;
304
+ } else {
305
+ content = content.slice(0, lastImportEnd) + "\n" + importBlock + content.slice(lastImportEnd);
306
+ }
269
307
  }
270
308
  const bodyCloseIndex = content.lastIndexOf("</body>");
271
309
  if (bodyCloseIndex === -1) {
@@ -274,8 +312,11 @@ async function injectPulseTracker() {
274
312
  }
275
313
  const lineStart = content.lastIndexOf("\n", bodyCloseIndex) + 1;
276
314
  const indent = content.slice(lineStart, bodyCloseIndex).match(/^\s*/)?.[0] ?? " ";
277
- const trackerJsx = `${indent} <PulseTracker excludePaths={["/admin/analytics"]} />
278
- `;
315
+ const trackerJsx = [
316
+ `${indent} <Suspense>`,
317
+ `${indent} <PulseTrackerWrapper />`,
318
+ `${indent} </Suspense>`
319
+ ].join("\n") + "\n";
279
320
  content = content.slice(0, lineStart) + trackerJsx + content.slice(lineStart);
280
321
  import_node_fs3.default.writeFileSync(foundPath, content, "utf8");
281
322
  console.log(
@@ -287,12 +328,13 @@ function printManualInstructions() {
287
328
  console.log(
288
329
  " Could not auto-inject PulseTracker. Add it manually to your layout:\n"
289
330
  );
290
- console.log(' import { PulseTracker } from "@pulsekit/next/client";');
331
+ console.log(' import { Suspense } from "react";');
332
+ console.log(' import PulseTrackerWrapper from "@/components/pulse-tracker-wrapper";');
291
333
  console.log("");
292
334
  console.log(" // Add inside your <body> tag:");
293
- console.log(
294
- ' <PulseTracker excludePaths={["/admin/analytics"]} />\n'
295
- );
335
+ console.log(" <Suspense>");
336
+ console.log(" <PulseTrackerWrapper />");
337
+ console.log(" </Suspense>\n");
296
338
  }
297
339
 
298
340
  // src/inject-instrumentation.ts
@@ -396,6 +438,20 @@ ${SQL_MAP[file]}`).join("\n\n");
396
438
  }
397
439
 
398
440
  // src/index.ts
441
+ function appendEnvExample() {
442
+ const envExamplePath = import_node_path6.default.join(process.cwd(), ".env.example");
443
+ if (!import_node_fs6.default.existsSync(envExamplePath)) return;
444
+ const content = import_node_fs6.default.readFileSync(envExamplePath, "utf8");
445
+ const entries = [
446
+ { key: "PULSE_SECRET", value: "" },
447
+ { key: "SUPABASE_SERVICE_ROLE_KEY", value: "" }
448
+ ];
449
+ const missing = entries.filter((e) => !content.includes(e.key));
450
+ if (missing.length === 0) return;
451
+ const block = "\n# PulseKit\n" + missing.map((e) => `${e.key}=${e.value}`).join("\n") + "\n";
452
+ import_node_fs6.default.appendFileSync(envExamplePath, block, "utf8");
453
+ console.log(" Updated .env.example with PulseKit variables.\n");
454
+ }
399
455
  async function main() {
400
456
  console.log("\n create-pulsekit\n");
401
457
  console.log(" Setting up PulseKit analytics in your Next.js project.\n");
@@ -408,15 +464,22 @@ async function main() {
408
464
  await injectPulseTracker();
409
465
  await injectInstrumentation();
410
466
  writeMigration();
467
+ appendEnvExample();
411
468
  console.log("\n Done! PulseKit has been added to your project.\n");
412
469
  console.log(" To finish setup:");
413
- console.log(" 1. Add your Supabase credentials to .env.local:");
470
+ console.log(" 1. Add these variables to .env.local:");
414
471
  console.log(" NEXT_PUBLIC_SUPABASE_URL=<your-supabase-url>");
415
472
  console.log(" NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=<your-anon-key>");
473
+ console.log(" SUPABASE_SERVICE_ROLE_KEY=<your-service-role-key>");
474
+ console.log(" PULSE_SECRET=<a-random-string-at-least-16-chars>");
416
475
  console.log(" 2. Run the database migration:");
417
476
  console.log(" npx supabase link");
418
477
  console.log(" npx supabase db push");
419
- console.log(" 3. Start your dev server and visit /admin/analytics");
478
+ console.log(" 3. If your middleware protects routes (e.g. Supabase auth),");
479
+ console.log(" allow the PulseKit paths through:");
480
+ console.log(' !request.nextUrl.pathname.startsWith("/api/pulse")');
481
+ console.log(' !request.nextUrl.pathname.startsWith("/admin/analytics")');
482
+ console.log(" 4. Start your dev server and visit /admin/analytics\n");
420
483
  }
421
484
  main().catch((err) => {
422
485
  console.error("\n Error:", err.message || err);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/detect.ts","../src/install.ts","../src/scaffold.ts","../src/inject.ts","../src/inject-instrumentation.ts","../src/migration.ts","../src/index.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nexport function detectPackageManager(): PackageManager {\n const cwd = process.cwd();\n\n if (\n fs.existsSync(path.join(cwd, \"bun.lock\")) ||\n fs.existsSync(path.join(cwd, \"bun.lockb\"))\n ) {\n return \"bun\";\n }\n if (fs.existsSync(path.join(cwd, \"pnpm-lock.yaml\"))) {\n return \"pnpm\";\n }\n if (fs.existsSync(path.join(cwd, \"yarn.lock\"))) {\n return \"yarn\";\n }\n return \"npm\";\n}\n\nexport function validateNextJsProject(): void {\n const cwd = process.cwd();\n\n const pkgPath = path.join(cwd, \"package.json\");\n if (!fs.existsSync(pkgPath)) {\n throw new Error(\n \"No package.json found. Run this command from the root of a Next.js project.\"\n );\n }\n\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"));\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (!allDeps[\"next\"]) {\n throw new Error(\n \"next is not listed in package.json. This command requires a Next.js project.\"\n );\n }\n\n if (!fs.existsSync(getAppDir())) {\n throw new Error(\n \"No app/ directory found. PulseKit requires the Next.js App Router.\"\n );\n }\n}\n\nexport function getAppDir(): string {\n const cwd = process.cwd();\n const srcAppDir = path.join(cwd, \"src\", \"app\");\n if (fs.existsSync(srcAppDir)) {\n return srcAppDir;\n }\n return path.join(cwd, \"app\");\n}\n","import { execSync } from \"node:child_process\";\nimport type { PackageManager } from \"./detect\";\n\nconst PACKAGES = [\n \"@pulsekit/core\",\n \"@pulsekit/next\",\n \"@pulsekit/react\",\n \"@supabase/supabase-js@latest\",\n];\n\nexport async function installPackages(pm: PackageManager): Promise<void> {\n console.log(\" Installing packages...\\n\");\n\n const commands: Record<PackageManager, string> = {\n npm: `npm install ${PACKAGES.join(\" \")}`,\n pnpm: `pnpm add ${PACKAGES.join(\" \")}`,\n yarn: `yarn add ${PACKAGES.join(\" \")}`,\n bun: `bun add ${PACKAGES.join(\" \")}`,\n };\n\n const cmd = commands[pm];\n console.log(` > ${cmd}\\n`);\n\n try {\n execSync(cmd, { cwd: process.cwd(), stdio: \"inherit\" });\n } catch {\n throw new Error(\n `Package installation failed. Try running manually:\\n ${cmd}`\n );\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getAppDir } from \"./detect\";\n\nexport function scaffoldFiles(): void {\n console.log(\" Scaffolding files...\\n\");\n\n const appDir = getAppDir();\n\n const pulseRoute = `import { createPulseHandler } from \"@pulsekit/next\";\nimport { createClient } from \"@supabase/supabase-js\";\n\nconst supabase = createClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!\n);\n\nexport const POST = createPulseHandler({\n supabase,\n config: {\n siteId: \"default\",\n secret: process.env.PULSE_SECRET,\n },\n});\n`;\n\n const refreshRoute = `import { createRefreshHandler, withPulseAuth } from \"@pulsekit/next\";\nimport { createClient } from \"@supabase/supabase-js\";\n\nconst supabase = createClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!\n);\n\nexport const POST = withPulseAuth(createRefreshHandler({ supabase }));\n`;\n\n const consolidateRoute = `import { createConsolidateHandler, withPulseAuth } from \"@pulsekit/next\";\nimport { createClient } from \"@supabase/supabase-js\";\n\nconst supabase = createClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!\n);\n\nexport const POST = withPulseAuth(createConsolidateHandler({ supabase }));\n`;\n\n const authRoute = `import { createPulseAuthHandler } from \"@pulsekit/next\";\n\nconst handler = createPulseAuthHandler({ secret: process.env.PULSE_SECRET! });\n\nexport const POST = handler;\nexport const DELETE = handler;\n`;\n\n const dashboardPage = `import { Suspense } from \"react\";\nimport { createClient } from \"@supabase/supabase-js\";\nimport { PulseDashboard, PulseAuthGate } from \"@pulsekit/react\";\nimport { getPulseTimezone } from \"@pulsekit/next\";\nimport { Spinner } from \"@/components/ui/spinner\";\nimport \"@pulsekit/react/pulse.css\";\n\nconst supabase = createClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!\n);\n\nasync function Dashboard() {\n const timezone = await getPulseTimezone();\n\n return (\n <PulseDashboard\n supabase={supabase}\n siteId=\"default\"\n timeframe=\"7d\"\n timezone={timezone}\n />\n );\n}\n\nexport default function AnalyticsPage() {\n return (\n <PulseAuthGate secret={process.env.PULSE_SECRET}>\n <Suspense fallback={<div className=\"flex items-center justify-center min-h-screen p-6\"><Spinner className=\"size-6\" /></div>}>\n <Dashboard />\n </Suspense>\n </PulseAuthGate>\n );\n}\n`;\n\n // Scaffold the spinner component if not already present\n const spinnerContent = `import { LoaderIcon } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <LoaderIcon\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n`;\n\n const cwd = process.cwd();\n const componentsBase = appDir.includes(path.join(\"src\", \"app\"))\n ? path.join(cwd, \"src\", \"components\", \"ui\")\n : path.join(cwd, \"components\", \"ui\");\n\n const spinnerPath = path.join(componentsBase, \"spinner.tsx\");\n fs.mkdirSync(componentsBase, { recursive: true });\n if (fs.existsSync(spinnerPath)) {\n console.log(\" Skipped (already exists): components/ui/spinner.tsx\");\n } else {\n fs.writeFileSync(spinnerPath, spinnerContent, \"utf8\");\n console.log(\" Created: components/ui/spinner.tsx\");\n }\n\n const files = [\n { rel: \"api/pulse/route.ts\", content: pulseRoute },\n { rel: \"api/pulse/auth/route.ts\", content: authRoute },\n { rel: \"api/pulse/refresh-aggregates/route.ts\", content: refreshRoute },\n { rel: \"api/pulse/consolidate/route.ts\", content: consolidateRoute },\n { rel: \"admin/analytics/page.tsx\", content: dashboardPage },\n ];\n\n for (const { rel, content } of files) {\n const fullPath = path.join(appDir, rel);\n fs.mkdirSync(path.dirname(fullPath), { recursive: true });\n\n if (fs.existsSync(fullPath)) {\n console.log(` Skipped (already exists): ${rel}`);\n continue;\n }\n\n fs.writeFileSync(fullPath, content, \"utf8\");\n console.log(` Created: ${rel}`);\n }\n\n console.log(\"\");\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getAppDir } from \"./detect\";\n\nexport async function injectPulseTracker(): Promise<void> {\n console.log(\" Injecting PulseTracker into layout...\\n\");\n\n const appDir = getAppDir();\n\n const candidates = [\n path.join(appDir, \"layout.tsx\"),\n path.join(appDir, \"layout.jsx\"),\n path.join(appDir, \"layout.js\"),\n ];\n\n let foundPath: string | null = null;\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n foundPath = candidate;\n break;\n }\n }\n\n if (!foundPath) {\n printManualInstructions();\n return;\n }\n\n let content = fs.readFileSync(foundPath, \"utf8\");\n\n if (content.includes(\"PulseTracker\")) {\n console.log(\" PulseTracker already present in layout. Skipping.\\n\");\n return;\n }\n\n // Add import after the last existing import\n const importStatement =\n 'import { PulseTracker } from \"@pulsekit/next/client\";';\n\n const importRegex = /^import\\s.+$/gm;\n let lastImportEnd = -1;\n let match: RegExpExecArray | null;\n while ((match = importRegex.exec(content)) !== null) {\n lastImportEnd = match.index + match[0].length;\n }\n\n if (lastImportEnd === -1) {\n content = importStatement + \"\\n\" + content;\n } else {\n content =\n content.slice(0, lastImportEnd) +\n \"\\n\" +\n importStatement +\n content.slice(lastImportEnd);\n }\n\n // Inject <PulseTracker /> before </body>\n const bodyCloseIndex = content.lastIndexOf(\"</body>\");\n if (bodyCloseIndex === -1) {\n printManualInstructions();\n return;\n }\n\n // Detect indentation from the </body> line\n const lineStart = content.lastIndexOf(\"\\n\", bodyCloseIndex) + 1;\n const indent = content.slice(lineStart, bodyCloseIndex).match(/^\\s*/)?.[0] ?? \" \";\n const trackerJsx = `${indent} <PulseTracker excludePaths={[\"/admin/analytics\"]} />\\n`;\n\n content =\n content.slice(0, lineStart) + trackerJsx + content.slice(lineStart);\n\n fs.writeFileSync(foundPath, content, \"utf8\");\n console.log(\n ` Modified: ${path.relative(process.cwd(), foundPath)}\\n`\n );\n}\n\nfunction printManualInstructions(): void {\n console.log(\n \" Could not auto-inject PulseTracker. Add it manually to your layout:\\n\"\n );\n console.log(' import { PulseTracker } from \"@pulsekit/next/client\";');\n console.log(\"\");\n console.log(\" // Add inside your <body> tag:\");\n console.log(\n ' <PulseTracker excludePaths={[\"/admin/analytics\"]} />\\n'\n );\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getAppDir } from \"./detect\";\n\nconst FULL_CONTENT = `import { createClient } from \"@supabase/supabase-js\";\nimport { createPulseErrorReporter } from \"@pulsekit/next\";\n\nconst supabase = createClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!\n);\n\nexport const onRequestError = createPulseErrorReporter({\n supabase,\n siteId: \"default\",\n});\n`;\n\nconst IMPORT_LINE = 'import { createPulseErrorReporter } from \"@pulsekit/next\";';\n\nconst EXPORT_BLOCK = `\nexport const onRequestError = createPulseErrorReporter({\n supabase,\n siteId: \"default\",\n});\n`;\n\nexport async function injectInstrumentation(): Promise<void> {\n console.log(\" Setting up error reporting instrumentation...\\n\");\n\n const appDir = getAppDir();\n // src/app -> src/instrumentation.ts; app/ -> instrumentation.ts\n const useSrc = appDir.includes(path.join(\"src\", \"app\"));\n const baseDir = useSrc ? path.join(process.cwd(), \"src\") : process.cwd();\n\n const candidates = [\n path.join(baseDir, \"instrumentation.ts\"),\n path.join(baseDir, \"instrumentation.js\"),\n ];\n\n let foundPath: string | null = null;\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n foundPath = candidate;\n break;\n }\n }\n\n // Case 1: No file exists — create it\n if (!foundPath) {\n const targetPath = path.join(baseDir, \"instrumentation.ts\");\n fs.writeFileSync(targetPath, FULL_CONTENT, \"utf8\");\n console.log(` Created: ${path.relative(process.cwd(), targetPath)}\\n`);\n return;\n }\n\n const content = fs.readFileSync(foundPath, \"utf8\");\n\n // Case 3: Already has onRequestError — skip\n if (content.includes(\"onRequestError\")) {\n console.log(\" onRequestError already present in instrumentation. Skipping.\\n\");\n console.log(\" To add PulseKit error reporting manually, add:\\n\");\n console.log(` ${IMPORT_LINE}`);\n console.log(\"\");\n console.log(\" export const onRequestError = createPulseErrorReporter({\");\n console.log(\" supabase,\");\n console.log(' siteId: \"default\",');\n console.log(\" });\\n\");\n return;\n }\n\n // Case 2: File exists without onRequestError — append\n const importRegex = /^import\\s.+$/gm;\n let lastImportEnd = -1;\n let match: RegExpExecArray | null;\n while ((match = importRegex.exec(content)) !== null) {\n lastImportEnd = match.index + match[0].length;\n }\n\n let updated: string;\n if (lastImportEnd === -1) {\n updated = IMPORT_LINE + \"\\n\" + content + EXPORT_BLOCK;\n } else {\n updated =\n content.slice(0, lastImportEnd) +\n \"\\n\" +\n IMPORT_LINE +\n content.slice(lastImportEnd) +\n EXPORT_BLOCK;\n }\n\n fs.writeFileSync(foundPath, updated, \"utf8\");\n console.log(` Modified: ${path.relative(process.cwd(), foundPath)}\\n`);\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nconst SQL_MAP: Record<string, string> = JSON.parse(\n process.env.__EMBEDDED_SQL__!\n);\n\nexport function writeMigration(): void {\n console.log(\" Writing database migration...\\n\");\n\n const supabaseDir = path.join(process.cwd(), \"supabase\", \"migrations\");\n fs.mkdirSync(supabaseDir, { recursive: true });\n\n // Combine all SQL files into a single migration\n const files = Object.keys(SQL_MAP).sort();\n const combined = files\n .map((file) => `-- ${file}\\n${SQL_MAP[file]}`)\n .join(\"\\n\\n\");\n\n // Use a fixed timestamp so re-running doesn't create duplicates\n const filename = \"20250101000000_pulse_analytics.sql\";\n const fullPath = path.join(supabaseDir, filename);\n\n if (fs.existsSync(fullPath)) {\n console.log(` Skipped (already exists): supabase/migrations/${filename}\\n`);\n return;\n }\n\n fs.writeFileSync(fullPath, combined, \"utf8\");\n console.log(` Created: supabase/migrations/${filename}\\n`);\n}\n","import { detectPackageManager, validateNextJsProject } from \"./detect\";\nimport { installPackages } from \"./install\";\nimport { scaffoldFiles } from \"./scaffold\";\nimport { injectPulseTracker } from \"./inject\";\nimport { injectInstrumentation } from \"./inject-instrumentation\";\nimport { writeMigration } from \"./migration\";\n\nasync function main() {\n console.log(\"\\n create-pulsekit\\n\");\n console.log(\" Setting up PulseKit analytics in your Next.js project.\\n\");\n\n const pm = detectPackageManager();\n console.log(` Detected package manager: ${pm}\\n`);\n\n validateNextJsProject();\n\n await installPackages(pm);\n\n scaffoldFiles();\n\n await injectPulseTracker();\n\n await injectInstrumentation();\n\n writeMigration();\n\n console.log(\"\\n Done! PulseKit has been added to your project.\\n\");\n console.log(\" To finish setup:\");\n console.log(\" 1. Add your Supabase credentials to .env.local:\");\n console.log(\" NEXT_PUBLIC_SUPABASE_URL=<your-supabase-url>\");\n console.log(\" NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=<your-anon-key>\");\n console.log(\" 2. Run the database migration:\");\n console.log(\" npx supabase link\");\n console.log(\" npx supabase db push\");\n console.log(\" 3. Start your dev server and visit /admin/analytics\");\n}\n\nmain().catch((err) => {\n console.error(\"\\n Error:\", err.message || err);\n process.exit(1);\n});\n"],"mappings":"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","names":["fs","path","import_node_fs","import_node_path","path","fs","import_node_fs","import_node_path","path","fs","import_node_fs","import_node_path","path","fs","import_node_fs","import_node_path","path","fs"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/detect.ts","../src/install.ts","../src/scaffold.ts","../src/inject.ts","../src/inject-instrumentation.ts","../src/migration.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { detectPackageManager, validateNextJsProject } from \"./detect\";\nimport { installPackages } from \"./install\";\nimport { scaffoldFiles } from \"./scaffold\";\nimport { injectPulseTracker } from \"./inject\";\nimport { injectInstrumentation } from \"./inject-instrumentation\";\nimport { writeMigration } from \"./migration\";\n\nfunction appendEnvExample(): void {\n const envExamplePath = path.join(process.cwd(), \".env.example\");\n if (!fs.existsSync(envExamplePath)) return;\n\n const content = fs.readFileSync(envExamplePath, \"utf8\");\n const entries: { key: string; value: string }[] = [\n { key: \"PULSE_SECRET\", value: \"\" },\n { key: \"SUPABASE_SERVICE_ROLE_KEY\", value: \"\" },\n ];\n\n const missing = entries.filter((e) => !content.includes(e.key));\n if (missing.length === 0) return;\n\n const block =\n \"\\n# PulseKit\\n\" +\n missing.map((e) => `${e.key}=${e.value}`).join(\"\\n\") +\n \"\\n\";\n fs.appendFileSync(envExamplePath, block, \"utf8\");\n console.log(\" Updated .env.example with PulseKit variables.\\n\");\n}\n\nasync function main() {\n console.log(\"\\n create-pulsekit\\n\");\n console.log(\" Setting up PulseKit analytics in your Next.js project.\\n\");\n\n const pm = detectPackageManager();\n console.log(` Detected package manager: ${pm}\\n`);\n\n validateNextJsProject();\n\n await installPackages(pm);\n\n scaffoldFiles();\n\n await injectPulseTracker();\n\n await injectInstrumentation();\n\n writeMigration();\n\n appendEnvExample();\n\n console.log(\"\\n Done! PulseKit has been added to your project.\\n\");\n console.log(\" To finish setup:\");\n console.log(\" 1. Add these variables to .env.local:\");\n console.log(\" NEXT_PUBLIC_SUPABASE_URL=<your-supabase-url>\");\n console.log(\" NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=<your-anon-key>\");\n console.log(\" SUPABASE_SERVICE_ROLE_KEY=<your-service-role-key>\");\n console.log(\" PULSE_SECRET=<a-random-string-at-least-16-chars>\");\n console.log(\" 2. Run the database migration:\");\n console.log(\" npx supabase link\");\n console.log(\" npx supabase db push\");\n console.log(\" 3. If your middleware protects routes (e.g. Supabase auth),\");\n console.log(\" allow the PulseKit paths through:\");\n console.log(' !request.nextUrl.pathname.startsWith(\"/api/pulse\")');\n console.log(' !request.nextUrl.pathname.startsWith(\"/admin/analytics\")');\n console.log(\" 4. Start your dev server and visit /admin/analytics\\n\");\n}\n\nmain().catch((err) => {\n console.error(\"\\n Error:\", err.message || err);\n process.exit(1);\n});\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nexport function detectPackageManager(): PackageManager {\n const cwd = process.cwd();\n\n if (\n fs.existsSync(path.join(cwd, \"bun.lock\")) ||\n fs.existsSync(path.join(cwd, \"bun.lockb\"))\n ) {\n return \"bun\";\n }\n if (fs.existsSync(path.join(cwd, \"pnpm-lock.yaml\"))) {\n return \"pnpm\";\n }\n if (fs.existsSync(path.join(cwd, \"yarn.lock\"))) {\n return \"yarn\";\n }\n return \"npm\";\n}\n\nexport function validateNextJsProject(): void {\n const cwd = process.cwd();\n\n const pkgPath = path.join(cwd, \"package.json\");\n if (!fs.existsSync(pkgPath)) {\n throw new Error(\n \"No package.json found. Run this command from the root of a Next.js project.\"\n );\n }\n\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"));\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (!allDeps[\"next\"]) {\n throw new Error(\n \"next is not listed in package.json. This command requires a Next.js project.\"\n );\n }\n\n if (!fs.existsSync(getAppDir())) {\n throw new Error(\n \"No app/ directory found. PulseKit requires the Next.js App Router.\"\n );\n }\n}\n\nexport function getAppDir(): string {\n const cwd = process.cwd();\n const srcAppDir = path.join(cwd, \"src\", \"app\");\n if (fs.existsSync(srcAppDir)) {\n return srcAppDir;\n }\n return path.join(cwd, \"app\");\n}\n","import { execSync } from \"node:child_process\";\nimport type { PackageManager } from \"./detect\";\n\nconst PACKAGES = [\n \"@pulsekit/core\",\n \"@pulsekit/next\",\n \"@pulsekit/react\",\n \"@supabase/supabase-js@latest\",\n];\n\nexport async function installPackages(pm: PackageManager): Promise<void> {\n console.log(\" Installing packages...\\n\");\n\n const commands: Record<PackageManager, string> = {\n npm: `npm install ${PACKAGES.join(\" \")}`,\n pnpm: `pnpm add ${PACKAGES.join(\" \")}`,\n yarn: `yarn add ${PACKAGES.join(\" \")}`,\n bun: `bun add ${PACKAGES.join(\" \")}`,\n };\n\n const cmd = commands[pm];\n console.log(` > ${cmd}\\n`);\n\n try {\n execSync(cmd, { cwd: process.cwd(), stdio: \"inherit\" });\n } catch {\n throw new Error(\n `Package installation failed. Try running manually:\\n ${cmd}`\n );\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getAppDir } from \"./detect\";\n\nexport function scaffoldFiles(): void {\n console.log(\" Scaffolding files...\\n\");\n\n const appDir = getAppDir();\n\n const pulseRoute = `import { createPulseHandler } from \"@pulsekit/next\";\nimport { createClient } from \"@supabase/supabase-js\";\n\nconst supabase = createClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!\n);\n\nexport const POST = createPulseHandler({\n supabase,\n config: {\n siteId: \"default\",\n secret: process.env.PULSE_SECRET,\n },\n});\n`;\n\n const refreshRoute = `import { createRefreshHandler, withPulseAuth } from \"@pulsekit/next\";\nimport { createClient } from \"@supabase/supabase-js\";\n\nconst supabase = createClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!\n);\n\nexport const POST = withPulseAuth(createRefreshHandler({ supabase }));\n`;\n\n const consolidateRoute = `import { createConsolidateHandler, withPulseAuth } from \"@pulsekit/next\";\nimport { createClient } from \"@supabase/supabase-js\";\n\nconst supabase = createClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!\n);\n\nexport const POST = withPulseAuth(createConsolidateHandler({ supabase }));\n`;\n\n const authRoute = `import { createPulseAuthHandler } from \"@pulsekit/next\";\n\nconst handler = createPulseAuthHandler({ secret: process.env.PULSE_SECRET! });\n\nexport const POST = handler;\nexport const DELETE = handler;\n`;\n\n const dashboardPage = `import { Suspense } from \"react\";\nimport { createClient } from \"@supabase/supabase-js\";\nimport { PulseDashboard, PulseAuthGate } from \"@pulsekit/react\";\nimport { getPulseTimezone } from \"@pulsekit/next\";\nimport { Spinner } from \"@/components/ui/spinner\";\nimport \"@pulsekit/react/pulse.css\";\n\nconst supabase = createClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!\n);\n\nasync function Dashboard() {\n const timezone = await getPulseTimezone();\n\n return (\n <PulseDashboard\n supabase={supabase}\n siteId=\"default\"\n timeframe=\"7d\"\n timezone={timezone}\n />\n );\n}\n\nexport default function AnalyticsPage() {\n return (\n <Suspense fallback={<div className=\"flex items-center justify-center min-h-screen p-6\"><Spinner className=\"size-6\" /></div>}>\n <PulseAuthGate secret={process.env.PULSE_SECRET}>\n <Dashboard />\n </PulseAuthGate>\n </Suspense>\n );\n}\n`;\n\n const trackerWrapper = `import { PulseTracker } from \"@pulsekit/next/client\";\nimport { createPulseIngestionToken } from \"@pulsekit/next\";\nimport { connection } from \"next/server\";\n\nexport default async function PulseTrackerWrapper() {\n await connection();\n const token = process.env.PULSE_SECRET\n ? await createPulseIngestionToken(process.env.PULSE_SECRET)\n : undefined;\n\n return (\n <PulseTracker\n excludePaths={[\"/admin/analytics\"]}\n token={token}\n />\n );\n}\n`;\n\n // Scaffold the spinner component if not already present\n const spinnerContent = `import { LoaderIcon } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <LoaderIcon\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n`;\n\n const cwd = process.cwd();\n const componentsBase = appDir.includes(path.join(\"src\", \"app\"))\n ? path.join(cwd, \"src\", \"components\", \"ui\")\n : path.join(cwd, \"components\", \"ui\");\n\n const spinnerPath = path.join(componentsBase, \"spinner.tsx\");\n fs.mkdirSync(componentsBase, { recursive: true });\n if (fs.existsSync(spinnerPath)) {\n console.log(\" Skipped (already exists): components/ui/spinner.tsx\");\n } else {\n fs.writeFileSync(spinnerPath, spinnerContent, \"utf8\");\n console.log(\" Created: components/ui/spinner.tsx\");\n }\n\n // Scaffold the tracker wrapper component\n const componentsDir = appDir.includes(path.join(\"src\", \"app\"))\n ? path.join(cwd, \"src\", \"components\")\n : path.join(cwd, \"components\");\n const wrapperPath = path.join(componentsDir, \"pulse-tracker-wrapper.tsx\");\n fs.mkdirSync(componentsDir, { recursive: true });\n if (fs.existsSync(wrapperPath)) {\n console.log(\" Skipped (already exists): components/pulse-tracker-wrapper.tsx\");\n } else {\n fs.writeFileSync(wrapperPath, trackerWrapper, \"utf8\");\n console.log(\" Created: components/pulse-tracker-wrapper.tsx\");\n }\n\n const files = [\n { rel: \"api/pulse/route.ts\", content: pulseRoute },\n { rel: \"api/pulse/auth/route.ts\", content: authRoute },\n { rel: \"api/pulse/refresh-aggregates/route.ts\", content: refreshRoute },\n { rel: \"api/pulse/consolidate/route.ts\", content: consolidateRoute },\n { rel: \"admin/analytics/page.tsx\", content: dashboardPage },\n ];\n\n for (const { rel, content } of files) {\n const fullPath = path.join(appDir, rel);\n fs.mkdirSync(path.dirname(fullPath), { recursive: true });\n\n if (fs.existsSync(fullPath)) {\n console.log(` Skipped (already exists): ${rel}`);\n continue;\n }\n\n fs.writeFileSync(fullPath, content, \"utf8\");\n console.log(` Created: ${rel}`);\n }\n\n console.log(\"\");\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getAppDir } from \"./detect\";\n\nexport async function injectPulseTracker(): Promise<void> {\n console.log(\" Injecting PulseTracker into layout...\\n\");\n\n const appDir = getAppDir();\n\n const candidates = [\n path.join(appDir, \"layout.tsx\"),\n path.join(appDir, \"layout.jsx\"),\n path.join(appDir, \"layout.js\"),\n ];\n\n let foundPath: string | null = null;\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n foundPath = candidate;\n break;\n }\n }\n\n if (!foundPath) {\n printManualInstructions();\n return;\n }\n\n let content = fs.readFileSync(foundPath, \"utf8\");\n\n if (content.includes(\"PulseTrackerWrapper\") || content.includes(\"PulseTracker\")) {\n console.log(\" PulseTracker already present in layout. Skipping.\\n\");\n return;\n }\n\n // Add imports after the last existing import\n const importStatements = [\n 'import { Suspense } from \"react\";',\n 'import PulseTrackerWrapper from \"@/components/pulse-tracker-wrapper\";',\n ];\n\n const importRegex = /^import\\s.+$/gm;\n let lastImportEnd = -1;\n let match: RegExpExecArray | null;\n while ((match = importRegex.exec(content)) !== null) {\n lastImportEnd = match.index + match[0].length;\n }\n\n // Only add imports that aren't already present\n const newImports = importStatements.filter((stmt) => !content.includes(stmt));\n const importBlock = newImports.join(\"\\n\");\n\n if (importBlock) {\n if (lastImportEnd === -1) {\n content = importBlock + \"\\n\" + content;\n } else {\n content =\n content.slice(0, lastImportEnd) +\n \"\\n\" +\n importBlock +\n content.slice(lastImportEnd);\n }\n }\n\n // Inject <Suspense><PulseTrackerWrapper /></Suspense> before </body>\n const bodyCloseIndex = content.lastIndexOf(\"</body>\");\n if (bodyCloseIndex === -1) {\n printManualInstructions();\n return;\n }\n\n // Detect indentation from the </body> line\n const lineStart = content.lastIndexOf(\"\\n\", bodyCloseIndex) + 1;\n const indent = content.slice(lineStart, bodyCloseIndex).match(/^\\s*/)?.[0] ?? \" \";\n const trackerJsx = [\n `${indent} <Suspense>`,\n `${indent} <PulseTrackerWrapper />`,\n `${indent} </Suspense>`,\n ].join(\"\\n\") + \"\\n\";\n\n content =\n content.slice(0, lineStart) + trackerJsx + content.slice(lineStart);\n\n fs.writeFileSync(foundPath, content, \"utf8\");\n console.log(\n ` Modified: ${path.relative(process.cwd(), foundPath)}\\n`\n );\n}\n\nfunction printManualInstructions(): void {\n console.log(\n \" Could not auto-inject PulseTracker. Add it manually to your layout:\\n\"\n );\n console.log(' import { Suspense } from \"react\";');\n console.log(' import PulseTrackerWrapper from \"@/components/pulse-tracker-wrapper\";');\n console.log(\"\");\n console.log(\" // Add inside your <body> tag:\");\n console.log(\" <Suspense>\");\n console.log(\" <PulseTrackerWrapper />\");\n console.log(\" </Suspense>\\n\");\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getAppDir } from \"./detect\";\n\nconst FULL_CONTENT = `import { createClient } from \"@supabase/supabase-js\";\nimport { createPulseErrorReporter } from \"@pulsekit/next\";\n\nconst supabase = createClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!\n);\n\nexport const onRequestError = createPulseErrorReporter({\n supabase,\n siteId: \"default\",\n});\n`;\n\nconst IMPORT_LINE = 'import { createPulseErrorReporter } from \"@pulsekit/next\";';\n\nconst EXPORT_BLOCK = `\nexport const onRequestError = createPulseErrorReporter({\n supabase,\n siteId: \"default\",\n});\n`;\n\nexport async function injectInstrumentation(): Promise<void> {\n console.log(\" Setting up error reporting instrumentation...\\n\");\n\n const appDir = getAppDir();\n // src/app -> src/instrumentation.ts; app/ -> instrumentation.ts\n const useSrc = appDir.includes(path.join(\"src\", \"app\"));\n const baseDir = useSrc ? path.join(process.cwd(), \"src\") : process.cwd();\n\n const candidates = [\n path.join(baseDir, \"instrumentation.ts\"),\n path.join(baseDir, \"instrumentation.js\"),\n ];\n\n let foundPath: string | null = null;\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n foundPath = candidate;\n break;\n }\n }\n\n // Case 1: No file exists — create it\n if (!foundPath) {\n const targetPath = path.join(baseDir, \"instrumentation.ts\");\n fs.writeFileSync(targetPath, FULL_CONTENT, \"utf8\");\n console.log(` Created: ${path.relative(process.cwd(), targetPath)}\\n`);\n return;\n }\n\n const content = fs.readFileSync(foundPath, \"utf8\");\n\n // Case 3: Already has onRequestError — skip\n if (content.includes(\"onRequestError\")) {\n console.log(\" onRequestError already present in instrumentation. Skipping.\\n\");\n console.log(\" To add PulseKit error reporting manually, add:\\n\");\n console.log(` ${IMPORT_LINE}`);\n console.log(\"\");\n console.log(\" export const onRequestError = createPulseErrorReporter({\");\n console.log(\" supabase,\");\n console.log(' siteId: \"default\",');\n console.log(\" });\\n\");\n return;\n }\n\n // Case 2: File exists without onRequestError — append\n const importRegex = /^import\\s.+$/gm;\n let lastImportEnd = -1;\n let match: RegExpExecArray | null;\n while ((match = importRegex.exec(content)) !== null) {\n lastImportEnd = match.index + match[0].length;\n }\n\n let updated: string;\n if (lastImportEnd === -1) {\n updated = IMPORT_LINE + \"\\n\" + content + EXPORT_BLOCK;\n } else {\n updated =\n content.slice(0, lastImportEnd) +\n \"\\n\" +\n IMPORT_LINE +\n content.slice(lastImportEnd) +\n EXPORT_BLOCK;\n }\n\n fs.writeFileSync(foundPath, updated, \"utf8\");\n console.log(` Modified: ${path.relative(process.cwd(), foundPath)}\\n`);\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nconst SQL_MAP: Record<string, string> = JSON.parse(\n process.env.__EMBEDDED_SQL__!\n);\n\nexport function writeMigration(): void {\n console.log(\" Writing database migration...\\n\");\n\n const supabaseDir = path.join(process.cwd(), \"supabase\", \"migrations\");\n fs.mkdirSync(supabaseDir, { recursive: true });\n\n // Combine all SQL files into a single migration\n const files = Object.keys(SQL_MAP).sort();\n const combined = files\n .map((file) => `-- ${file}\\n${SQL_MAP[file]}`)\n .join(\"\\n\\n\");\n\n // Use a fixed timestamp so re-running doesn't create duplicates\n const filename = \"20250101000000_pulse_analytics.sql\";\n const fullPath = path.join(supabaseDir, filename);\n\n if (fs.existsSync(fullPath)) {\n console.log(` Skipped (already exists): supabase/migrations/${filename}\\n`);\n return;\n }\n\n fs.writeFileSync(fullPath, combined, \"utf8\");\n console.log(` Created: supabase/migrations/${filename}\\n`);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,kBAAe;AACf,IAAAC,oBAAiB;;;ACDjB,qBAAe;AACf,uBAAiB;AAIV,SAAS,uBAAuC;AACrD,QAAM,MAAM,QAAQ,IAAI;AAExB,MACE,eAAAC,QAAG,WAAW,iBAAAC,QAAK,KAAK,KAAK,UAAU,CAAC,KACxC,eAAAD,QAAG,WAAW,iBAAAC,QAAK,KAAK,KAAK,WAAW,CAAC,GACzC;AACA,WAAO;AAAA,EACT;AACA,MAAI,eAAAD,QAAG,WAAW,iBAAAC,QAAK,KAAK,KAAK,gBAAgB,CAAC,GAAG;AACnD,WAAO;AAAA,EACT;AACA,MAAI,eAAAD,QAAG,WAAW,iBAAAC,QAAK,KAAK,KAAK,WAAW,CAAC,GAAG;AAC9C,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,wBAA8B;AAC5C,QAAM,MAAM,QAAQ,IAAI;AAExB,QAAM,UAAU,iBAAAA,QAAK,KAAK,KAAK,cAAc;AAC7C,MAAI,CAAC,eAAAD,QAAG,WAAW,OAAO,GAAG;AAC3B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAAM,KAAK,MAAM,eAAAA,QAAG,aAAa,SAAS,MAAM,CAAC;AACvD,QAAM,UAAU,EAAE,GAAG,IAAI,cAAc,GAAG,IAAI,gBAAgB;AAC9D,MAAI,CAAC,QAAQ,MAAM,GAAG;AACpB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,eAAAA,QAAG,WAAW,UAAU,CAAC,GAAG;AAC/B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,YAAoB;AAClC,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,YAAY,iBAAAC,QAAK,KAAK,KAAK,OAAO,KAAK;AAC7C,MAAI,eAAAD,QAAG,WAAW,SAAS,GAAG;AAC5B,WAAO;AAAA,EACT;AACA,SAAO,iBAAAC,QAAK,KAAK,KAAK,KAAK;AAC7B;;;ACvDA,gCAAyB;AAGzB,IAAM,WAAW;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,eAAsB,gBAAgB,IAAmC;AACvE,UAAQ,IAAI,4BAA4B;AAExC,QAAM,WAA2C;AAAA,IAC/C,KAAK,eAAe,SAAS,KAAK,GAAG,CAAC;AAAA,IACtC,MAAM,YAAY,SAAS,KAAK,GAAG,CAAC;AAAA,IACpC,MAAM,YAAY,SAAS,KAAK,GAAG,CAAC;AAAA,IACpC,KAAK,WAAW,SAAS,KAAK,GAAG,CAAC;AAAA,EACpC;AAEA,QAAM,MAAM,SAAS,EAAE;AACvB,UAAQ,IAAI,OAAO,GAAG;AAAA,CAAI;AAE1B,MAAI;AACF,4CAAS,KAAK,EAAE,KAAK,QAAQ,IAAI,GAAG,OAAO,UAAU,CAAC;AAAA,EACxD,QAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IAAyD,GAAG;AAAA,IAC9D;AAAA,EACF;AACF;;;AC9BA,IAAAC,kBAAe;AACf,IAAAC,oBAAiB;AAGV,SAAS,gBAAsB;AACpC,UAAQ,IAAI,0BAA0B;AAEtC,QAAM,SAAS,UAAU;AAEzB,QAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBnB,QAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWrB,QAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWzB,QAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQlB,QAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoCtB,QAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBvB,QAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBvB,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,iBAAiB,OAAO,SAAS,kBAAAC,QAAK,KAAK,OAAO,KAAK,CAAC,IAC1D,kBAAAA,QAAK,KAAK,KAAK,OAAO,cAAc,IAAI,IACxC,kBAAAA,QAAK,KAAK,KAAK,cAAc,IAAI;AAErC,QAAM,cAAc,kBAAAA,QAAK,KAAK,gBAAgB,aAAa;AAC3D,kBAAAC,QAAG,UAAU,gBAAgB,EAAE,WAAW,KAAK,CAAC;AAChD,MAAI,gBAAAA,QAAG,WAAW,WAAW,GAAG;AAC9B,YAAQ,IAAI,yDAAyD;AAAA,EACvE,OAAO;AACL,oBAAAA,QAAG,cAAc,aAAa,gBAAgB,MAAM;AACpD,YAAQ,IAAI,wCAAwC;AAAA,EACtD;AAGA,QAAM,gBAAgB,OAAO,SAAS,kBAAAD,QAAK,KAAK,OAAO,KAAK,CAAC,IACzD,kBAAAA,QAAK,KAAK,KAAK,OAAO,YAAY,IAClC,kBAAAA,QAAK,KAAK,KAAK,YAAY;AAC/B,QAAM,cAAc,kBAAAA,QAAK,KAAK,eAAe,2BAA2B;AACxE,kBAAAC,QAAG,UAAU,eAAe,EAAE,WAAW,KAAK,CAAC;AAC/C,MAAI,gBAAAA,QAAG,WAAW,WAAW,GAAG;AAC9B,YAAQ,IAAI,oEAAoE;AAAA,EAClF,OAAO;AACL,oBAAAA,QAAG,cAAc,aAAa,gBAAgB,MAAM;AACpD,YAAQ,IAAI,mDAAmD;AAAA,EACjE;AAEA,QAAM,QAAQ;AAAA,IACZ,EAAE,KAAK,sBAAsB,SAAS,WAAW;AAAA,IACjD,EAAE,KAAK,2BAA2B,SAAS,UAAU;AAAA,IACrD,EAAE,KAAK,yCAAyC,SAAS,aAAa;AAAA,IACtE,EAAE,KAAK,kCAAkC,SAAS,iBAAiB;AAAA,IACnE,EAAE,KAAK,4BAA4B,SAAS,cAAc;AAAA,EAC5D;AAEA,aAAW,EAAE,KAAK,QAAQ,KAAK,OAAO;AACpC,UAAM,WAAW,kBAAAD,QAAK,KAAK,QAAQ,GAAG;AACtC,oBAAAC,QAAG,UAAU,kBAAAD,QAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAExD,QAAI,gBAAAC,QAAG,WAAW,QAAQ,GAAG;AAC3B,cAAQ,IAAI,iCAAiC,GAAG,EAAE;AAClD;AAAA,IACF;AAEA,oBAAAA,QAAG,cAAc,UAAU,SAAS,MAAM;AAC1C,YAAQ,IAAI,gBAAgB,GAAG,EAAE;AAAA,EACnC;AAEA,UAAQ,IAAI,EAAE;AAChB;;;AClLA,IAAAC,kBAAe;AACf,IAAAC,oBAAiB;AAGjB,eAAsB,qBAAoC;AACxD,UAAQ,IAAI,2CAA2C;AAEvD,QAAM,SAAS,UAAU;AAEzB,QAAM,aAAa;AAAA,IACjB,kBAAAC,QAAK,KAAK,QAAQ,YAAY;AAAA,IAC9B,kBAAAA,QAAK,KAAK,QAAQ,YAAY;AAAA,IAC9B,kBAAAA,QAAK,KAAK,QAAQ,WAAW;AAAA,EAC/B;AAEA,MAAI,YAA2B;AAC/B,aAAW,aAAa,YAAY;AAClC,QAAI,gBAAAC,QAAG,WAAW,SAAS,GAAG;AAC5B,kBAAY;AACZ;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,WAAW;AACd,4BAAwB;AACxB;AAAA,EACF;AAEA,MAAI,UAAU,gBAAAA,QAAG,aAAa,WAAW,MAAM;AAE/C,MAAI,QAAQ,SAAS,qBAAqB,KAAK,QAAQ,SAAS,cAAc,GAAG;AAC/E,YAAQ,IAAI,yDAAyD;AACrE;AAAA,EACF;AAGA,QAAM,mBAAmB;AAAA,IACvB;AAAA,IACA;AAAA,EACF;AAEA,QAAM,cAAc;AACpB,MAAI,gBAAgB;AACpB,MAAI;AACJ,UAAQ,QAAQ,YAAY,KAAK,OAAO,OAAO,MAAM;AACnD,oBAAgB,MAAM,QAAQ,MAAM,CAAC,EAAE;AAAA,EACzC;AAGA,QAAM,aAAa,iBAAiB,OAAO,CAAC,SAAS,CAAC,QAAQ,SAAS,IAAI,CAAC;AAC5E,QAAM,cAAc,WAAW,KAAK,IAAI;AAExC,MAAI,aAAa;AACf,QAAI,kBAAkB,IAAI;AACxB,gBAAU,cAAc,OAAO;AAAA,IACjC,OAAO;AACL,gBACE,QAAQ,MAAM,GAAG,aAAa,IAC9B,OACA,cACA,QAAQ,MAAM,aAAa;AAAA,IAC/B;AAAA,EACF;AAGA,QAAM,iBAAiB,QAAQ,YAAY,SAAS;AACpD,MAAI,mBAAmB,IAAI;AACzB,4BAAwB;AACxB;AAAA,EACF;AAGA,QAAM,YAAY,QAAQ,YAAY,MAAM,cAAc,IAAI;AAC9D,QAAM,SAAS,QAAQ,MAAM,WAAW,cAAc,EAAE,MAAM,MAAM,IAAI,CAAC,KAAK;AAC9E,QAAM,aAAa;AAAA,IACjB,GAAG,MAAM;AAAA,IACT,GAAG,MAAM;AAAA,IACT,GAAG,MAAM;AAAA,EACX,EAAE,KAAK,IAAI,IAAI;AAEf,YACE,QAAQ,MAAM,GAAG,SAAS,IAAI,aAAa,QAAQ,MAAM,SAAS;AAEpE,kBAAAA,QAAG,cAAc,WAAW,SAAS,MAAM;AAC3C,UAAQ;AAAA,IACN,iBAAiB,kBAAAD,QAAK,SAAS,QAAQ,IAAI,GAAG,SAAS,CAAC;AAAA;AAAA,EAC1D;AACF;AAEA,SAAS,0BAAgC;AACvC,UAAQ;AAAA,IACN;AAAA,EACF;AACA,UAAQ,IAAI,uCAAuC;AACnD,UAAQ,IAAI,2EAA2E;AACvF,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,oCAAoC;AAChD,UAAQ,IAAI,gBAAgB;AAC5B,UAAQ,IAAI,+BAA+B;AAC3C,UAAQ,IAAI,mBAAmB;AACjC;;;ACpGA,IAAAE,kBAAe;AACf,IAAAC,oBAAiB;AAGjB,IAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcrB,IAAM,cAAc;AAEpB,IAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAOrB,eAAsB,wBAAuC;AAC3D,UAAQ,IAAI,mDAAmD;AAE/D,QAAM,SAAS,UAAU;AAEzB,QAAM,SAAS,OAAO,SAAS,kBAAAC,QAAK,KAAK,OAAO,KAAK,CAAC;AACtD,QAAM,UAAU,SAAS,kBAAAA,QAAK,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,QAAQ,IAAI;AAEvE,QAAM,aAAa;AAAA,IACjB,kBAAAA,QAAK,KAAK,SAAS,oBAAoB;AAAA,IACvC,kBAAAA,QAAK,KAAK,SAAS,oBAAoB;AAAA,EACzC;AAEA,MAAI,YAA2B;AAC/B,aAAW,aAAa,YAAY;AAClC,QAAI,gBAAAC,QAAG,WAAW,SAAS,GAAG;AAC5B,kBAAY;AACZ;AAAA,IACF;AAAA,EACF;AAGA,MAAI,CAAC,WAAW;AACd,UAAM,aAAa,kBAAAD,QAAK,KAAK,SAAS,oBAAoB;AAC1D,oBAAAC,QAAG,cAAc,YAAY,cAAc,MAAM;AACjD,YAAQ,IAAI,gBAAgB,kBAAAD,QAAK,SAAS,QAAQ,IAAI,GAAG,UAAU,CAAC;AAAA,CAAI;AACxE;AAAA,EACF;AAEA,QAAM,UAAU,gBAAAC,QAAG,aAAa,WAAW,MAAM;AAGjD,MAAI,QAAQ,SAAS,gBAAgB,GAAG;AACtC,YAAQ,IAAI,oEAAoE;AAChF,YAAQ,IAAI,sDAAsD;AAClE,YAAQ,IAAI,OAAO,WAAW,EAAE;AAChC,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,8DAA8D;AAC1E,YAAQ,IAAI,iBAAiB;AAC7B,YAAQ,IAAI,0BAA0B;AACtC,YAAQ,IAAI,WAAW;AACvB;AAAA,EACF;AAGA,QAAM,cAAc;AACpB,MAAI,gBAAgB;AACpB,MAAI;AACJ,UAAQ,QAAQ,YAAY,KAAK,OAAO,OAAO,MAAM;AACnD,oBAAgB,MAAM,QAAQ,MAAM,CAAC,EAAE;AAAA,EACzC;AAEA,MAAI;AACJ,MAAI,kBAAkB,IAAI;AACxB,cAAU,cAAc,OAAO,UAAU;AAAA,EAC3C,OAAO;AACL,cACE,QAAQ,MAAM,GAAG,aAAa,IAC9B,OACA,cACA,QAAQ,MAAM,aAAa,IAC3B;AAAA,EACJ;AAEA,kBAAAA,QAAG,cAAc,WAAW,SAAS,MAAM;AAC3C,UAAQ,IAAI,iBAAiB,kBAAAD,QAAK,SAAS,QAAQ,IAAI,GAAG,SAAS,CAAC;AAAA,CAAI;AAC1E;;;AC7FA,IAAAE,kBAAe;AACf,IAAAC,oBAAiB;AAEjB,IAAM,UAAkC,KAAK;AAAA,EAC3C;AACF;AAEO,SAAS,iBAAuB;AACrC,UAAQ,IAAI,mCAAmC;AAE/C,QAAM,cAAc,kBAAAC,QAAK,KAAK,QAAQ,IAAI,GAAG,YAAY,YAAY;AACrE,kBAAAC,QAAG,UAAU,aAAa,EAAE,WAAW,KAAK,CAAC;AAG7C,QAAM,QAAQ,OAAO,KAAK,OAAO,EAAE,KAAK;AACxC,QAAM,WAAW,MACd,IAAI,CAAC,SAAS,MAAM,IAAI;AAAA,EAAK,QAAQ,IAAI,CAAC,EAAE,EAC5C,KAAK,MAAM;AAGd,QAAM,WAAW;AACjB,QAAM,WAAW,kBAAAD,QAAK,KAAK,aAAa,QAAQ;AAEhD,MAAI,gBAAAC,QAAG,WAAW,QAAQ,GAAG;AAC3B,YAAQ,IAAI,qDAAqD,QAAQ;AAAA,CAAI;AAC7E;AAAA,EACF;AAEA,kBAAAA,QAAG,cAAc,UAAU,UAAU,MAAM;AAC3C,UAAQ,IAAI,oCAAoC,QAAQ;AAAA,CAAI;AAC9D;;;ANrBA,SAAS,mBAAyB;AAChC,QAAM,iBAAiB,kBAAAC,QAAK,KAAK,QAAQ,IAAI,GAAG,cAAc;AAC9D,MAAI,CAAC,gBAAAC,QAAG,WAAW,cAAc,EAAG;AAEpC,QAAM,UAAU,gBAAAA,QAAG,aAAa,gBAAgB,MAAM;AACtD,QAAM,UAA4C;AAAA,IAChD,EAAE,KAAK,gBAAgB,OAAO,GAAG;AAAA,IACjC,EAAE,KAAK,6BAA6B,OAAO,GAAG;AAAA,EAChD;AAEA,QAAM,UAAU,QAAQ,OAAO,CAAC,MAAM,CAAC,QAAQ,SAAS,EAAE,GAAG,CAAC;AAC9D,MAAI,QAAQ,WAAW,EAAG;AAE1B,QAAM,QACJ,mBACA,QAAQ,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,IAAI,IACnD;AACF,kBAAAA,QAAG,eAAe,gBAAgB,OAAO,MAAM;AAC/C,UAAQ,IAAI,mDAAmD;AACjE;AAEA,eAAe,OAAO;AACpB,UAAQ,IAAI,uBAAuB;AACnC,UAAQ,IAAI,4DAA4D;AAExE,QAAM,KAAK,qBAAqB;AAChC,UAAQ,IAAI,+BAA+B,EAAE;AAAA,CAAI;AAEjD,wBAAsB;AAEtB,QAAM,gBAAgB,EAAE;AAExB,gBAAc;AAEd,QAAM,mBAAmB;AAEzB,QAAM,sBAAsB;AAE5B,iBAAe;AAEf,mBAAiB;AAEjB,UAAQ,IAAI,sDAAsD;AAClE,UAAQ,IAAI,oBAAoB;AAChC,UAAQ,IAAI,2CAA2C;AACvD,UAAQ,IAAI,qDAAqD;AACjE,UAAQ,IAAI,6DAA6D;AACzE,UAAQ,IAAI,0DAA0D;AACtE,UAAQ,IAAI,yDAAyD;AACrE,UAAQ,IAAI,oCAAoC;AAChD,UAAQ,IAAI,0BAA0B;AACtC,UAAQ,IAAI,6BAA6B;AACzC,UAAQ,IAAI,iEAAiE;AAC7E,UAAQ,IAAI,0CAA0C;AACtD,UAAQ,IAAI,2DAA2D;AACvE,UAAQ,IAAI,iEAAiE;AAC7E,UAAQ,IAAI,2DAA2D;AACzE;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,cAAc,IAAI,WAAW,GAAG;AAC9C,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["import_node_fs","import_node_path","fs","path","import_node_fs","import_node_path","path","fs","import_node_fs","import_node_path","path","fs","import_node_fs","import_node_path","path","fs","import_node_fs","import_node_path","path","fs","path","fs"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-pulsekit",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Set up PulseKit analytics in your Next.js project",
5
5
  "keywords": [
6
6
  "analytics",