@insforge/cli 0.1.79 → 0.1.80
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 +119 -498
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { readFileSync as
|
|
5
|
-
import { join as
|
|
4
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
5
|
+
import { join as join15, dirname as dirname2 } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
import * as clack18 from "@clack/prompts";
|
|
@@ -6961,7 +6961,7 @@ function registerDiagnoseCommands(diagnoseCmd2) {
|
|
|
6961
6961
|
const s = !json ? clack15.spinner() : null;
|
|
6962
6962
|
s?.start("Collecting diagnostic data...");
|
|
6963
6963
|
const data2 = await collectDiagnosticData(projectId, ossMode, apiUrl);
|
|
6964
|
-
const cliVersion = "0.1.
|
|
6964
|
+
const cliVersion = "0.1.80";
|
|
6965
6965
|
s?.stop("Data collected");
|
|
6966
6966
|
if (!json) {
|
|
6967
6967
|
console.log(`
|
|
@@ -8325,8 +8325,7 @@ function registerPaymentsCommands(paymentsCmd2) {
|
|
|
8325
8325
|
}
|
|
8326
8326
|
|
|
8327
8327
|
// src/commands/posthog/setup.ts
|
|
8328
|
-
import {
|
|
8329
|
-
import { join as join16, dirname as dirname2 } from "path";
|
|
8328
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
8330
8329
|
import * as clack16 from "@clack/prompts";
|
|
8331
8330
|
import pc3 from "picocolors";
|
|
8332
8331
|
|
|
@@ -8492,200 +8491,19 @@ function sleep(ms, signal) {
|
|
|
8492
8491
|
});
|
|
8493
8492
|
}
|
|
8494
8493
|
|
|
8495
|
-
// src/lib/framework-detect.ts
|
|
8496
|
-
import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
|
|
8497
|
-
import { join as join14 } from "path";
|
|
8498
|
-
function contextFromCwd(cwd) {
|
|
8499
|
-
let pkg2 = null;
|
|
8500
|
-
const pkgPath = join14(cwd, "package.json");
|
|
8501
|
-
if (existsSync10(pkgPath)) {
|
|
8502
|
-
try {
|
|
8503
|
-
pkg2 = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
8504
|
-
} catch {
|
|
8505
|
-
pkg2 = null;
|
|
8506
|
-
}
|
|
8507
|
-
}
|
|
8508
|
-
return {
|
|
8509
|
-
hasDir: (rel) => existsSync10(join14(cwd, rel)),
|
|
8510
|
-
pkg: pkg2
|
|
8511
|
-
};
|
|
8512
|
-
}
|
|
8513
|
-
function hasDep(pkg2, name) {
|
|
8514
|
-
if (!pkg2) return false;
|
|
8515
|
-
return Boolean(pkg2.dependencies?.[name] ?? pkg2.devDependencies?.[name]);
|
|
8516
|
-
}
|
|
8517
|
-
function detectFramework(ctx) {
|
|
8518
|
-
if (hasDep(ctx.pkg, "next")) {
|
|
8519
|
-
const hasApp = ctx.hasDir("app") || ctx.hasDir("src/app");
|
|
8520
|
-
const hasPages = ctx.hasDir("pages") || ctx.hasDir("src/pages");
|
|
8521
|
-
if (hasApp && !hasPages) return "next-app";
|
|
8522
|
-
if (hasPages && !hasApp) return "next-pages";
|
|
8523
|
-
if (hasApp && hasPages) return "next-app";
|
|
8524
|
-
return "next-app";
|
|
8525
|
-
}
|
|
8526
|
-
if (hasDep(ctx.pkg, "vite") && hasDep(ctx.pkg, "react")) {
|
|
8527
|
-
return "vite-react";
|
|
8528
|
-
}
|
|
8529
|
-
if (hasDep(ctx.pkg, "@sveltejs/kit")) {
|
|
8530
|
-
return "sveltekit";
|
|
8531
|
-
}
|
|
8532
|
-
if (hasDep(ctx.pkg, "astro")) {
|
|
8533
|
-
return "astro";
|
|
8534
|
-
}
|
|
8535
|
-
return null;
|
|
8536
|
-
}
|
|
8537
|
-
|
|
8538
|
-
// src/lib/package-manager.ts
|
|
8539
|
-
import { existsSync as existsSync11 } from "fs";
|
|
8540
|
-
import { join as join15 } from "path";
|
|
8541
|
-
import { exec as exec4 } from "child_process";
|
|
8542
|
-
import { promisify as promisify5 } from "util";
|
|
8543
|
-
var execAsync4 = promisify5(exec4);
|
|
8544
|
-
function detectPackageManager(cwd) {
|
|
8545
|
-
if (existsSync11(join15(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
8546
|
-
if (existsSync11(join15(cwd, "yarn.lock"))) return "yarn";
|
|
8547
|
-
if (existsSync11(join15(cwd, "bun.lockb")) || existsSync11(join15(cwd, "bun.lock"))) {
|
|
8548
|
-
return "bun";
|
|
8549
|
-
}
|
|
8550
|
-
return "npm";
|
|
8551
|
-
}
|
|
8552
|
-
function installCommand(pm, pkg2) {
|
|
8553
|
-
switch (pm) {
|
|
8554
|
-
case "pnpm":
|
|
8555
|
-
return `pnpm add ${pkg2}`;
|
|
8556
|
-
case "yarn":
|
|
8557
|
-
return `yarn add ${pkg2}`;
|
|
8558
|
-
case "bun":
|
|
8559
|
-
return `bun add ${pkg2}`;
|
|
8560
|
-
case "npm":
|
|
8561
|
-
default:
|
|
8562
|
-
return `npm install ${pkg2}`;
|
|
8563
|
-
}
|
|
8564
|
-
}
|
|
8565
|
-
function hasPackage(pkg2, name) {
|
|
8566
|
-
if (!pkg2) return false;
|
|
8567
|
-
return Boolean(pkg2.dependencies?.[name] ?? pkg2.devDependencies?.[name]);
|
|
8568
|
-
}
|
|
8569
|
-
async function runInstall(pm, pkgName, cwd) {
|
|
8570
|
-
const cmd = installCommand(pm, pkgName);
|
|
8571
|
-
await execAsync4(cmd, { cwd, maxBuffer: 16 * 1024 * 1024 });
|
|
8572
|
-
}
|
|
8573
|
-
|
|
8574
|
-
// src/lib/env-writer.ts
|
|
8575
|
-
import { existsSync as existsSync12, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
8576
|
-
var KEY_LINE_RE = (key) => (
|
|
8577
|
-
// Match `KEY=...` at the start of a line (allowing leading whitespace).
|
|
8578
|
-
// Captures the value side; we only need the value portion to compare.
|
|
8579
|
-
new RegExp(`^\\s*${key.replace(/[$.*+?^()[\\]{}|]/g, "\\$&")}\\s*=\\s*(.*)$`, "m")
|
|
8580
|
-
);
|
|
8581
|
-
function stripQuotes(v) {
|
|
8582
|
-
const t = v.trim();
|
|
8583
|
-
if (t.startsWith('"') && t.endsWith('"') && t.length >= 2 || t.startsWith("'") && t.endsWith("'") && t.length >= 2) {
|
|
8584
|
-
return t.slice(1, -1);
|
|
8585
|
-
}
|
|
8586
|
-
const hash = t.indexOf(" #");
|
|
8587
|
-
return hash >= 0 ? t.slice(0, hash).trimEnd() : t;
|
|
8588
|
-
}
|
|
8589
|
-
function upsertEnvFile(path6, entries) {
|
|
8590
|
-
const exists = existsSync12(path6);
|
|
8591
|
-
let content = exists ? readFileSync9(path6, "utf-8") : "";
|
|
8592
|
-
const result = { added: [], skipped: [], mismatched: [] };
|
|
8593
|
-
const additions = [];
|
|
8594
|
-
for (const [key, value] of Object.entries(entries)) {
|
|
8595
|
-
const re = KEY_LINE_RE(key);
|
|
8596
|
-
const match = content.match(re);
|
|
8597
|
-
if (match) {
|
|
8598
|
-
const existingValue = stripQuotes(match[1] ?? "");
|
|
8599
|
-
if (existingValue === value) {
|
|
8600
|
-
result.skipped.push(key);
|
|
8601
|
-
} else {
|
|
8602
|
-
result.mismatched.push({ key, existingValue, newValue: value });
|
|
8603
|
-
}
|
|
8604
|
-
continue;
|
|
8605
|
-
}
|
|
8606
|
-
additions.push(`${key}=${value}`);
|
|
8607
|
-
result.added.push(key);
|
|
8608
|
-
}
|
|
8609
|
-
if (additions.length > 0) {
|
|
8610
|
-
if (content.length > 0 && !content.endsWith("\n")) {
|
|
8611
|
-
content += "\n";
|
|
8612
|
-
}
|
|
8613
|
-
content += additions.join("\n") + "\n";
|
|
8614
|
-
writeFileSync7(path6, content);
|
|
8615
|
-
} else if (!exists) {
|
|
8616
|
-
}
|
|
8617
|
-
return result;
|
|
8618
|
-
}
|
|
8619
|
-
|
|
8620
|
-
// src/templates/posthog/next-app/posthog-provider.tsx.txt
|
|
8621
|
-
var posthog_provider_tsx_default = "'use client';\n\nimport { useEffect } from 'react';\nimport posthog from 'posthog-js';\n\n// PostHog client-side provider for the Next.js App Router.\n// Initialises posthog-js exactly once on the client; SSR is skipped because\n// `useEffect` only runs in the browser.\nexport function PostHogProvider({ children }: { children: React.ReactNode }) {\n useEffect(() => {\n if (typeof window === 'undefined') return;\n if (posthog.__loaded) return;\n\n const key = process.env.NEXT_PUBLIC_POSTHOG_KEY;\n if (!key) {\n // Fail closed in production: missing env var \u2192 no init, no events.\n // Avoids accidentally firing events without a key in CI/preview builds.\n return;\n }\n\n posthog.init(key, {\n api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST || '{{HOST}}',\n capture_pageview: true,\n capture_pageleave: true,\n });\n }, []);\n\n return <>{children}</>;\n}\n";
|
|
8622
|
-
|
|
8623
|
-
// src/templates/posthog/next-app/layout-snippet.tsx.txt
|
|
8624
|
-
var layout_snippet_tsx_default = `// Wrap your <body> children with <PostHogProvider> in app/layout.tsx:
|
|
8625
|
-
//
|
|
8626
|
-
// import { PostHogProvider } from './posthog-provider';
|
|
8627
|
-
//
|
|
8628
|
-
// export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
8629
|
-
// return (
|
|
8630
|
-
// <html lang="en">
|
|
8631
|
-
// <body>
|
|
8632
|
-
// <PostHogProvider>{children}</PostHogProvider>
|
|
8633
|
-
// </body>
|
|
8634
|
-
// </html>
|
|
8635
|
-
// );
|
|
8636
|
-
// }
|
|
8637
|
-
`;
|
|
8638
|
-
|
|
8639
|
-
// src/templates/posthog/next-pages/_app.tsx.txt
|
|
8640
|
-
var app_tsx_default = "import type { AppProps } from 'next/app';\nimport { useEffect } from 'react';\nimport posthog from 'posthog-js';\n\nif (typeof window !== 'undefined') {\n const key = process.env.NEXT_PUBLIC_POSTHOG_KEY;\n if (key && !posthog.__loaded) {\n posthog.init(key, {\n api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST || '{{HOST}}',\n capture_pageview: true,\n capture_pageleave: true,\n });\n }\n}\n\nexport default function App({ Component, pageProps }: AppProps) {\n useEffect(() => {\n // Capture pageviews on client-side route changes.\n const handleRouteChange = () => posthog.capture('$pageview');\n if (typeof window !== 'undefined') {\n window.addEventListener('popstate', handleRouteChange);\n return () => window.removeEventListener('popstate', handleRouteChange);\n }\n }, []);\n\n return <Component {...pageProps} />;\n}\n";
|
|
8641
|
-
|
|
8642
|
-
// src/templates/posthog/vite-react/main-snippet.tsx.txt
|
|
8643
|
-
var main_snippet_tsx_default = "// Add this near the top of src/main.tsx, before ReactDOM.createRoot:\nimport posthog from 'posthog-js';\n\nconst posthogKey = import.meta.env.VITE_PUBLIC_POSTHOG_KEY;\nif (posthogKey) {\n posthog.init(posthogKey, {\n api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST || '{{HOST}}',\n capture_pageview: true,\n capture_pageleave: true,\n });\n}\n";
|
|
8644
|
-
|
|
8645
|
-
// src/templates/posthog/sveltekit/hooks.client.ts.txt
|
|
8646
|
-
var hooks_client_ts_default = "import posthog from 'posthog-js';\nimport { browser } from '$app/environment';\nimport { PUBLIC_POSTHOG_KEY, PUBLIC_POSTHOG_HOST } from '$env/static/public';\n\n// `hooks.client.ts` only runs in the browser, so we don't need an explicit\n// `typeof window` guard. The `browser` import is included so future edits\n// (e.g. moving init to a non-client hook) don't accidentally fire on the server.\nif (browser && PUBLIC_POSTHOG_KEY) {\n posthog.init(PUBLIC_POSTHOG_KEY, {\n api_host: PUBLIC_POSTHOG_HOST || '{{HOST}}',\n capture_pageview: true,\n capture_pageleave: true,\n });\n}\n\nexport const handleError = ({ error }: { error: unknown }) => {\n posthog.capture('$exception', { error: String(error) });\n};\n";
|
|
8647
|
-
|
|
8648
|
-
// src/templates/posthog/astro/posthog-init.ts.txt
|
|
8649
|
-
var posthog_init_ts_default = "import posthog from 'posthog-js';\n\n// PostHog client init for Astro. This module runs only in the browser bundle\n// (Astro inlines `client:load` / `<script>` imports into client JS). We still\n// guard with `typeof window` because the same file may be transitively\n// imported during SSR \u2014 the guard prevents init from accidentally running on\n// the server during static generation.\nif (typeof window !== 'undefined') {\n const key = import.meta.env.PUBLIC_POSTHOG_KEY;\n if (key) {\n posthog.init(key, {\n api_host: import.meta.env.PUBLIC_POSTHOG_HOST || '{{HOST}}',\n capture_pageview: 'history_change',\n capture_pageleave: true,\n });\n }\n}\n";
|
|
8650
|
-
|
|
8651
|
-
// src/templates/posthog/index.ts
|
|
8652
|
-
var templates = {
|
|
8653
|
-
"next-app": {
|
|
8654
|
-
provider: posthog_provider_tsx_default,
|
|
8655
|
-
layoutSnippet: layout_snippet_tsx_default
|
|
8656
|
-
},
|
|
8657
|
-
"next-pages": {
|
|
8658
|
-
app: app_tsx_default
|
|
8659
|
-
},
|
|
8660
|
-
"vite-react": {
|
|
8661
|
-
mainSnippet: main_snippet_tsx_default
|
|
8662
|
-
},
|
|
8663
|
-
sveltekit: {
|
|
8664
|
-
hooks: hooks_client_ts_default
|
|
8665
|
-
},
|
|
8666
|
-
astro: {
|
|
8667
|
-
init: posthog_init_ts_default
|
|
8668
|
-
}
|
|
8669
|
-
};
|
|
8670
|
-
function renderTemplate(raw, vars) {
|
|
8671
|
-
return raw.replace(/\{\{([A-Z0-9_]+)\}\}/g, (match, key) => {
|
|
8672
|
-
return Object.prototype.hasOwnProperty.call(vars, key) ? vars[key] : match;
|
|
8673
|
-
});
|
|
8674
|
-
}
|
|
8675
|
-
|
|
8676
8494
|
// src/commands/posthog/setup.ts
|
|
8677
8495
|
var POLL_INTERVAL_MS4 = 2e3;
|
|
8678
8496
|
var POLL_TIMEOUT_MS4 = 15 * 60 * 1e3;
|
|
8679
8497
|
var MAX_TRANSIENT_RETRIES = 5;
|
|
8498
|
+
var NPX_COMMAND = process.platform === "win32" ? "npx.cmd" : "npx";
|
|
8499
|
+
var WIZARD_COMMAND = `${NPX_COMMAND} -y @posthog/wizard@latest`;
|
|
8680
8500
|
function registerPosthogSetupCommand(program2) {
|
|
8681
|
-
program2.command("setup").description("
|
|
8501
|
+
program2.command("setup").description("Connect PostHog to your InsForge dashboard, then run the official PostHog wizard to wire it into your app").option("--skip-browser", "Do not auto-open the browser for OAuth; only print the URL").action(async (opts, cmd) => {
|
|
8682
8502
|
const { json, apiUrl } = getRootOpts(cmd);
|
|
8683
8503
|
try {
|
|
8684
8504
|
const result = await runSetup({
|
|
8685
8505
|
json,
|
|
8686
8506
|
apiUrl,
|
|
8687
|
-
forceFramework: opts.framework,
|
|
8688
|
-
skipInstall: Boolean(opts.skipInstall),
|
|
8689
8507
|
skipBrowser: Boolean(opts.skipBrowser)
|
|
8690
8508
|
});
|
|
8691
8509
|
if (json) {
|
|
@@ -8709,62 +8527,60 @@ async function runSetup(opts) {
|
|
|
8709
8527
|
clack16.intro("PostHog setup");
|
|
8710
8528
|
outputSuccess(`Linked to InsForge project: ${proj.project_name} (${proj.project_id})`);
|
|
8711
8529
|
}
|
|
8712
|
-
const
|
|
8713
|
-
|
|
8530
|
+
const dashboardConnection = await ensureDashboardConnection(proj.project_id, token, opts);
|
|
8531
|
+
if (opts.json) {
|
|
8532
|
+
return {
|
|
8533
|
+
dashboardConnection,
|
|
8534
|
+
wizardSkipped: true,
|
|
8535
|
+
wizardCommand: WIZARD_COMMAND
|
|
8536
|
+
};
|
|
8537
|
+
}
|
|
8538
|
+
outputInfo("Running the official PostHog setup wizard to wire PostHog into your app...");
|
|
8539
|
+
outputInfo(
|
|
8540
|
+
pc3.dim("(it will open a browser for OAuth and let you pick a PostHog project)")
|
|
8541
|
+
);
|
|
8542
|
+
const wizardResult = spawnSync2(NPX_COMMAND, ["-y", "@posthog/wizard@latest"], {
|
|
8543
|
+
stdio: "inherit",
|
|
8544
|
+
env: process.env
|
|
8545
|
+
});
|
|
8546
|
+
if (wizardResult.error) {
|
|
8547
|
+
throw new CLIError(`Failed to launch PostHog wizard: ${wizardResult.error.message}`);
|
|
8548
|
+
}
|
|
8549
|
+
const exitCode = wizardResult.status ?? 1;
|
|
8550
|
+
if (wizardResult.signal === "SIGINT" || exitCode === 130) {
|
|
8551
|
+
clack16.outro("Setup cancelled.");
|
|
8552
|
+
return {
|
|
8553
|
+
dashboardConnection,
|
|
8554
|
+
wizardSkipped: false,
|
|
8555
|
+
wizardExitCode: exitCode
|
|
8556
|
+
};
|
|
8557
|
+
}
|
|
8558
|
+
if (exitCode !== 0) {
|
|
8559
|
+
throw new CLIError(`PostHog wizard exited with code ${exitCode}.`);
|
|
8560
|
+
}
|
|
8561
|
+
clack16.outro("Done. Open the Analytics page in your InsForge dashboard to view data.");
|
|
8562
|
+
return {
|
|
8563
|
+
dashboardConnection,
|
|
8564
|
+
wizardSkipped: false,
|
|
8565
|
+
wizardExitCode: exitCode
|
|
8566
|
+
};
|
|
8567
|
+
}
|
|
8568
|
+
async function ensureDashboardConnection(projectId, token, opts) {
|
|
8569
|
+
const startResult = await startPosthogCliFlow(projectId, token, opts.apiUrl);
|
|
8714
8570
|
if (startResult.type === "connected") {
|
|
8715
8571
|
if (!opts.json) {
|
|
8716
|
-
outputSuccess("PostHog already connected
|
|
8572
|
+
outputSuccess("PostHog is already connected to your InsForge dashboard.");
|
|
8717
8573
|
}
|
|
8718
|
-
const fetchResult = await fetchPosthogConnection(
|
|
8574
|
+
const fetchResult = await fetchPosthogConnection(projectId, token, opts.apiUrl);
|
|
8719
8575
|
if (fetchResult.kind !== "connected") {
|
|
8720
8576
|
throw new CLIError(
|
|
8721
8577
|
"cli-start reported connected, but /connection returned not-connected. Try again, or check the dashboard."
|
|
8722
8578
|
);
|
|
8723
8579
|
}
|
|
8724
|
-
|
|
8725
|
-
} else {
|
|
8726
|
-
conn = await runConnectFlow(proj.project_id, token, startResult.authorizeUrl, opts);
|
|
8580
|
+
return "already-connected";
|
|
8727
8581
|
}
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
"Connection succeeded but cloud-backend returned no apiKey. Try again or check the dashboard."
|
|
8731
|
-
);
|
|
8732
|
-
}
|
|
8733
|
-
const framework = resolveFramework(opts);
|
|
8734
|
-
if (framework === null) {
|
|
8735
|
-
return reportNoFramework(conn, opts);
|
|
8736
|
-
}
|
|
8737
|
-
if (!opts.json) outputSuccess(`Detected framework: ${frameworkLabel(framework)}`);
|
|
8738
|
-
const cwd = process.cwd();
|
|
8739
|
-
const ctx = contextFromCwd(cwd);
|
|
8740
|
-
const pm = detectPackageManager(cwd);
|
|
8741
|
-
const alreadyInstalled = hasPackage(ctx.pkg, "posthog-js");
|
|
8742
|
-
let installedSdk = false;
|
|
8743
|
-
if (alreadyInstalled) {
|
|
8744
|
-
if (!opts.json) outputInfo(pc3.dim("posthog-js is already installed \u2014 skipping install."));
|
|
8745
|
-
} else if (opts.skipInstall) {
|
|
8746
|
-
if (!opts.json) {
|
|
8747
|
-
outputInfo(pc3.yellow(`Skipping install. Run manually: ${installCommand(pm, "posthog-js")}`));
|
|
8748
|
-
}
|
|
8749
|
-
} else {
|
|
8750
|
-
installedSdk = await installSdk(pm, cwd, opts);
|
|
8751
|
-
}
|
|
8752
|
-
const filesWritten = [];
|
|
8753
|
-
const notes = [];
|
|
8754
|
-
const envResult = writeForFramework(framework, conn, cwd, filesWritten, notes, opts);
|
|
8755
|
-
if (!opts.json) {
|
|
8756
|
-
if (notes.length > 0) {
|
|
8757
|
-
for (const n of notes) clack16.log.info(n);
|
|
8758
|
-
}
|
|
8759
|
-
clack16.outro("Done. Run your dev server to start sending events.");
|
|
8760
|
-
}
|
|
8761
|
-
return {
|
|
8762
|
-
framework,
|
|
8763
|
-
installedSdk,
|
|
8764
|
-
filesWritten,
|
|
8765
|
-
envWritten: envResult,
|
|
8766
|
-
notes
|
|
8767
|
-
};
|
|
8582
|
+
await runConnectFlow(projectId, token, startResult.authorizeUrl, opts);
|
|
8583
|
+
return "newly-connected";
|
|
8768
8584
|
}
|
|
8769
8585
|
async function runConnectFlow(projectId, token, authorizeUrl, opts) {
|
|
8770
8586
|
if (opts.json) {
|
|
@@ -8772,7 +8588,7 @@ async function runConnectFlow(projectId, token, authorizeUrl, opts) {
|
|
|
8772
8588
|
`);
|
|
8773
8589
|
process.stderr.write("Your browser should open automatically. If not, copy the URL above.\n");
|
|
8774
8590
|
} else {
|
|
8775
|
-
clack16.log.info("PostHog is not connected to
|
|
8591
|
+
clack16.log.info("PostHog is not yet connected to your InsForge dashboard.");
|
|
8776
8592
|
outputInfo("");
|
|
8777
8593
|
outputInfo(`Open this URL to authorize PostHog:
|
|
8778
8594
|
${pc3.cyan(pc3.underline(authorizeUrl))}`);
|
|
@@ -8786,9 +8602,9 @@ async function runConnectFlow(projectId, token, authorizeUrl, opts) {
|
|
|
8786
8602
|
}
|
|
8787
8603
|
}
|
|
8788
8604
|
const spinner11 = !opts.json && isInteractive ? clack16.spinner() : null;
|
|
8789
|
-
spinner11?.start("Waiting for connection... (timeout: 15 minutes)");
|
|
8605
|
+
spinner11?.start("Waiting for InsForge dashboard connection... (timeout: 15 minutes)");
|
|
8790
8606
|
try {
|
|
8791
|
-
|
|
8607
|
+
await pollPosthogConnection(
|
|
8792
8608
|
projectId,
|
|
8793
8609
|
token,
|
|
8794
8610
|
{
|
|
@@ -8800,262 +8616,21 @@ async function runConnectFlow(projectId, token, authorizeUrl, opts) {
|
|
|
8800
8616
|
const secs = Math.floor(elapsed / 1e3);
|
|
8801
8617
|
const mins = Math.floor(secs / 60);
|
|
8802
8618
|
const remaining = `${mins}m ${secs % 60}s elapsed`;
|
|
8803
|
-
spinner11.message(`Waiting for connection... (${remaining})`);
|
|
8619
|
+
spinner11.message(`Waiting for InsForge dashboard connection... (${remaining})`);
|
|
8804
8620
|
}
|
|
8805
8621
|
}
|
|
8806
8622
|
},
|
|
8807
8623
|
opts.apiUrl
|
|
8808
8624
|
);
|
|
8809
|
-
spinner11?.stop("
|
|
8810
|
-
return conn;
|
|
8625
|
+
spinner11?.stop("InsForge dashboard connection received.");
|
|
8811
8626
|
} catch (err) {
|
|
8812
|
-
spinner11?.stop("
|
|
8627
|
+
spinner11?.stop("InsForge dashboard connection wait failed.");
|
|
8813
8628
|
throw err;
|
|
8814
8629
|
}
|
|
8815
8630
|
}
|
|
8816
|
-
function resolveFramework(opts) {
|
|
8817
|
-
if (opts.forceFramework) {
|
|
8818
|
-
const valid = ["next-app", "next-pages", "vite-react", "sveltekit", "astro"];
|
|
8819
|
-
if (!valid.includes(opts.forceFramework)) {
|
|
8820
|
-
throw new CLIError(
|
|
8821
|
-
`Invalid --framework "${opts.forceFramework}". Valid: ${valid.join(", ")}`
|
|
8822
|
-
);
|
|
8823
|
-
}
|
|
8824
|
-
return opts.forceFramework;
|
|
8825
|
-
}
|
|
8826
|
-
return detectFramework(contextFromCwd(process.cwd()));
|
|
8827
|
-
}
|
|
8828
|
-
async function installSdk(pm, cwd, opts) {
|
|
8829
|
-
const cmd = installCommand(pm, "posthog-js");
|
|
8830
|
-
const spinner11 = !opts.json && isInteractive ? clack16.spinner() : null;
|
|
8831
|
-
spinner11?.start(`Installing posthog-js (${cmd})...`);
|
|
8832
|
-
try {
|
|
8833
|
-
await runInstall(pm, "posthog-js", cwd);
|
|
8834
|
-
spinner11?.stop("Installed posthog-js.");
|
|
8835
|
-
return true;
|
|
8836
|
-
} catch (err) {
|
|
8837
|
-
spinner11?.stop("Install failed.");
|
|
8838
|
-
if (!opts.json) {
|
|
8839
|
-
clack16.log.warn(
|
|
8840
|
-
`Could not run \`${cmd}\` automatically: ${err.message}
|
|
8841
|
-
Run it manually, then re-run \`insforge posthog setup\`.`
|
|
8842
|
-
);
|
|
8843
|
-
}
|
|
8844
|
-
return false;
|
|
8845
|
-
}
|
|
8846
|
-
}
|
|
8847
|
-
function writeForFramework(framework, conn, cwd, filesWritten, notes, opts) {
|
|
8848
|
-
const host = conn.host || "https://us.posthog.com";
|
|
8849
|
-
const phc = conn.apiKey ?? "";
|
|
8850
|
-
switch (framework) {
|
|
8851
|
-
case "next-app":
|
|
8852
|
-
return writeNextApp(cwd, phc, host, filesWritten, notes, opts);
|
|
8853
|
-
case "next-pages":
|
|
8854
|
-
return writeNextPages(cwd, phc, host, filesWritten, notes, opts);
|
|
8855
|
-
case "vite-react":
|
|
8856
|
-
return writeViteReact(cwd, phc, host, filesWritten, notes, opts);
|
|
8857
|
-
case "sveltekit":
|
|
8858
|
-
return writeSveltekit(cwd, phc, host, filesWritten, notes, opts);
|
|
8859
|
-
case "astro":
|
|
8860
|
-
return writeAstro(cwd, phc, host, filesWritten, notes, opts);
|
|
8861
|
-
}
|
|
8862
|
-
}
|
|
8863
|
-
function writeNextApp(cwd, phc, host, filesWritten, notes, opts) {
|
|
8864
|
-
const appDir = existsSync13(join16(cwd, "src/app")) ? "src/app" : "app";
|
|
8865
|
-
const providerPath = join16(cwd, appDir, "posthog-provider.tsx");
|
|
8866
|
-
writeIfMissing(
|
|
8867
|
-
providerPath,
|
|
8868
|
-
renderTemplate(templates["next-app"].provider, { HOST: host }),
|
|
8869
|
-
filesWritten,
|
|
8870
|
-
notes,
|
|
8871
|
-
opts
|
|
8872
|
-
);
|
|
8873
|
-
notes.push(
|
|
8874
|
-
`Add the provider to your ${appDir}/layout.tsx:
|
|
8875
|
-
${templates["next-app"].layoutSnippet}`
|
|
8876
|
-
);
|
|
8877
|
-
const envFile = ".env.local";
|
|
8878
|
-
return writeEnv(
|
|
8879
|
-
cwd,
|
|
8880
|
-
envFile,
|
|
8881
|
-
{
|
|
8882
|
-
NEXT_PUBLIC_POSTHOG_KEY: phc,
|
|
8883
|
-
NEXT_PUBLIC_POSTHOG_HOST: host
|
|
8884
|
-
},
|
|
8885
|
-
opts
|
|
8886
|
-
);
|
|
8887
|
-
}
|
|
8888
|
-
function writeNextPages(cwd, phc, host, filesWritten, notes, opts) {
|
|
8889
|
-
const pagesDir = existsSync13(join16(cwd, "src/pages")) ? "src/pages" : "pages";
|
|
8890
|
-
const appPath = join16(cwd, pagesDir, "_app.tsx");
|
|
8891
|
-
writeIfMissing(
|
|
8892
|
-
appPath,
|
|
8893
|
-
renderTemplate(templates["next-pages"].app, { HOST: host }),
|
|
8894
|
-
filesWritten,
|
|
8895
|
-
notes,
|
|
8896
|
-
opts,
|
|
8897
|
-
"pages/_app.tsx already exists. Open it and add `posthog.init(...)` near the top \u2014 see PostHog Next.js docs."
|
|
8898
|
-
);
|
|
8899
|
-
const envFile = ".env.local";
|
|
8900
|
-
return writeEnv(
|
|
8901
|
-
cwd,
|
|
8902
|
-
envFile,
|
|
8903
|
-
{
|
|
8904
|
-
NEXT_PUBLIC_POSTHOG_KEY: phc,
|
|
8905
|
-
NEXT_PUBLIC_POSTHOG_HOST: host
|
|
8906
|
-
},
|
|
8907
|
-
opts
|
|
8908
|
-
);
|
|
8909
|
-
}
|
|
8910
|
-
function writeViteReact(cwd, phc, host, _filesWritten, notes, opts) {
|
|
8911
|
-
notes.push(
|
|
8912
|
-
`Add this snippet near the top of src/main.tsx:
|
|
8913
|
-
${renderTemplate(templates["vite-react"].mainSnippet, { HOST: host })}`
|
|
8914
|
-
);
|
|
8915
|
-
const envFile = ".env";
|
|
8916
|
-
return writeEnv(
|
|
8917
|
-
cwd,
|
|
8918
|
-
envFile,
|
|
8919
|
-
{
|
|
8920
|
-
VITE_PUBLIC_POSTHOG_KEY: phc,
|
|
8921
|
-
VITE_PUBLIC_POSTHOG_HOST: host
|
|
8922
|
-
},
|
|
8923
|
-
opts
|
|
8924
|
-
);
|
|
8925
|
-
}
|
|
8926
|
-
function writeSveltekit(cwd, phc, host, filesWritten, notes, opts) {
|
|
8927
|
-
const hooksPath = join16(cwd, "src/hooks.client.ts");
|
|
8928
|
-
writeIfMissing(
|
|
8929
|
-
hooksPath,
|
|
8930
|
-
renderTemplate(templates.sveltekit.hooks, { HOST: host }),
|
|
8931
|
-
filesWritten,
|
|
8932
|
-
notes,
|
|
8933
|
-
opts,
|
|
8934
|
-
"src/hooks.client.ts already exists. Add `posthog.init(...)` to it \u2014 see PostHog SvelteKit docs."
|
|
8935
|
-
);
|
|
8936
|
-
const envFile = ".env";
|
|
8937
|
-
return writeEnv(
|
|
8938
|
-
cwd,
|
|
8939
|
-
envFile,
|
|
8940
|
-
{
|
|
8941
|
-
PUBLIC_POSTHOG_KEY: phc,
|
|
8942
|
-
PUBLIC_POSTHOG_HOST: host
|
|
8943
|
-
},
|
|
8944
|
-
opts
|
|
8945
|
-
);
|
|
8946
|
-
}
|
|
8947
|
-
function writeAstro(cwd, phc, host, filesWritten, notes, opts) {
|
|
8948
|
-
const initPath = join16(cwd, "src/lib/posthog.ts");
|
|
8949
|
-
writeIfMissing(
|
|
8950
|
-
initPath,
|
|
8951
|
-
renderTemplate(templates.astro.init, { HOST: host }),
|
|
8952
|
-
filesWritten,
|
|
8953
|
-
notes,
|
|
8954
|
-
opts,
|
|
8955
|
-
"src/lib/posthog.ts already exists. Add `posthog.init(...)` per PostHog Astro docs."
|
|
8956
|
-
);
|
|
8957
|
-
notes.push(
|
|
8958
|
-
`Import the init module from your layout to load it on the client:
|
|
8959
|
-
// src/layouts/Layout.astro (inside <head> or <body>)
|
|
8960
|
-
<script>import '../lib/posthog';</script>`
|
|
8961
|
-
);
|
|
8962
|
-
const envFile = ".env";
|
|
8963
|
-
return writeEnv(
|
|
8964
|
-
cwd,
|
|
8965
|
-
envFile,
|
|
8966
|
-
{
|
|
8967
|
-
PUBLIC_POSTHOG_KEY: phc,
|
|
8968
|
-
PUBLIC_POSTHOG_HOST: host
|
|
8969
|
-
},
|
|
8970
|
-
opts
|
|
8971
|
-
);
|
|
8972
|
-
}
|
|
8973
|
-
function writeIfMissing(filePath, contents, filesWritten, notes, opts, conflictNote) {
|
|
8974
|
-
if (existsSync13(filePath)) {
|
|
8975
|
-
const existing = readFileSync10(filePath, "utf-8");
|
|
8976
|
-
if (existing.includes("posthog.init")) {
|
|
8977
|
-
if (!opts.json) {
|
|
8978
|
-
outputInfo(pc3.dim(`${relative3(filePath)} already calls posthog.init \u2014 leaving it alone.`));
|
|
8979
|
-
}
|
|
8980
|
-
return;
|
|
8981
|
-
}
|
|
8982
|
-
if (conflictNote) notes.push(conflictNote);
|
|
8983
|
-
if (!opts.json) {
|
|
8984
|
-
outputInfo(
|
|
8985
|
-
pc3.yellow(
|
|
8986
|
-
`${relative3(filePath)} exists. Skipped writing \u2014 see notes below for manual changes.`
|
|
8987
|
-
)
|
|
8988
|
-
);
|
|
8989
|
-
}
|
|
8990
|
-
return;
|
|
8991
|
-
}
|
|
8992
|
-
mkdirSync3(dirname2(filePath), { recursive: true });
|
|
8993
|
-
writeFileSync8(filePath, contents);
|
|
8994
|
-
filesWritten.push(filePath);
|
|
8995
|
-
if (!opts.json) outputSuccess(`Wrote ${relative3(filePath)}`);
|
|
8996
|
-
}
|
|
8997
|
-
function writeEnv(cwd, envFile, entries, opts) {
|
|
8998
|
-
const path6 = join16(cwd, envFile);
|
|
8999
|
-
const r = upsertEnvFile(path6, entries);
|
|
9000
|
-
if (!opts.json) {
|
|
9001
|
-
if (r.added.length > 0) {
|
|
9002
|
-
outputSuccess(`Wrote ${envFile}: ${r.added.join(", ")}`);
|
|
9003
|
-
}
|
|
9004
|
-
if (r.skipped.length > 0) {
|
|
9005
|
-
outputInfo(
|
|
9006
|
-
pc3.dim(`${envFile}: ${r.skipped.join(", ")} already set (matching) \u2014 left as-is.`)
|
|
9007
|
-
);
|
|
9008
|
-
}
|
|
9009
|
-
for (const m of r.mismatched) {
|
|
9010
|
-
clack16.log.warn(
|
|
9011
|
-
`${envFile} has ${m.key}=${pc3.dim(m.existingValue)}, expected ${m.newValue}. Left existing value untouched.`
|
|
9012
|
-
);
|
|
9013
|
-
}
|
|
9014
|
-
}
|
|
9015
|
-
return {
|
|
9016
|
-
file: envFile,
|
|
9017
|
-
added: r.added,
|
|
9018
|
-
mismatched: r.mismatched.map((m) => m.key)
|
|
9019
|
-
};
|
|
9020
|
-
}
|
|
9021
|
-
function reportNoFramework(conn, opts) {
|
|
9022
|
-
if (!opts.json) {
|
|
9023
|
-
clack16.log.warn("No supported framework detected in this directory.");
|
|
9024
|
-
outputInfo("");
|
|
9025
|
-
outputInfo(`Your PostHog public key: ${pc3.cyan(conn.apiKey ?? "(missing)")}`);
|
|
9026
|
-
outputInfo(`Your PostHog host: ${conn.host ?? "https://us.posthog.com"}`);
|
|
9027
|
-
outputInfo("");
|
|
9028
|
-
outputInfo("See https://posthog.com/docs/libraries to install the SDK manually.");
|
|
9029
|
-
clack16.outro("Done.");
|
|
9030
|
-
}
|
|
9031
|
-
return {
|
|
9032
|
-
framework: null,
|
|
9033
|
-
installedSdk: false,
|
|
9034
|
-
filesWritten: [],
|
|
9035
|
-
envWritten: { file: "", added: [], mismatched: [] },
|
|
9036
|
-
notes: ["No supported framework detected."]
|
|
9037
|
-
};
|
|
9038
|
-
}
|
|
9039
|
-
function frameworkLabel(framework) {
|
|
9040
|
-
switch (framework) {
|
|
9041
|
-
case "next-app":
|
|
9042
|
-
return "Next.js (App Router)";
|
|
9043
|
-
case "next-pages":
|
|
9044
|
-
return "Next.js (Pages Router)";
|
|
9045
|
-
case "vite-react":
|
|
9046
|
-
return "Vite + React";
|
|
9047
|
-
case "sveltekit":
|
|
9048
|
-
return "SvelteKit";
|
|
9049
|
-
case "astro":
|
|
9050
|
-
return "Astro";
|
|
9051
|
-
}
|
|
9052
|
-
}
|
|
9053
|
-
function relative3(p3) {
|
|
9054
|
-
return p3.replace(process.cwd() + "/", "");
|
|
9055
|
-
}
|
|
9056
8631
|
|
|
9057
8632
|
// src/commands/config/export.ts
|
|
9058
|
-
import { writeFileSync as
|
|
8633
|
+
import { writeFileSync as writeFileSync7, existsSync as existsSync10 } from "fs";
|
|
9059
8634
|
import { resolve as resolve5 } from "path";
|
|
9060
8635
|
import * as p from "@clack/prompts";
|
|
9061
8636
|
import pc4 from "picocolors";
|
|
@@ -9539,7 +9114,7 @@ function registerConfigExportCommand(cfg) {
|
|
|
9539
9114
|
try {
|
|
9540
9115
|
await requireAuth();
|
|
9541
9116
|
const target = resolve5(process.cwd(), opts.out);
|
|
9542
|
-
if (
|
|
9117
|
+
if (existsSync10(target) && !opts.force) {
|
|
9543
9118
|
if (json) {
|
|
9544
9119
|
throw new CLIError(
|
|
9545
9120
|
`${opts.out} exists. Re-run with --force to overwrite.`,
|
|
@@ -9560,7 +9135,7 @@ function registerConfigExportCommand(cfg) {
|
|
|
9560
9135
|
const raw = await res.json();
|
|
9561
9136
|
const { config, skipped } = configFromMetadata(raw);
|
|
9562
9137
|
const toml = stringifyConfigToml(config);
|
|
9563
|
-
|
|
9138
|
+
writeFileSync7(target, toml, "utf8");
|
|
9564
9139
|
if (json) {
|
|
9565
9140
|
console.log(JSON.stringify({ written: target, config, skipped }, null, 2));
|
|
9566
9141
|
} else {
|
|
@@ -9582,7 +9157,7 @@ function registerConfigExportCommand(cfg) {
|
|
|
9582
9157
|
}
|
|
9583
9158
|
|
|
9584
9159
|
// src/commands/config/plan.ts
|
|
9585
|
-
import { readFileSync as
|
|
9160
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
9586
9161
|
import { resolve as resolve6 } from "path";
|
|
9587
9162
|
import pc5 from "picocolors";
|
|
9588
9163
|
|
|
@@ -9888,7 +9463,7 @@ function registerConfigPlanCommand(cfg) {
|
|
|
9888
9463
|
try {
|
|
9889
9464
|
await requireAuth();
|
|
9890
9465
|
const tomlPath = resolve6(process.cwd(), opts.file);
|
|
9891
|
-
const tomlSource =
|
|
9466
|
+
const tomlSource = readFileSync8(tomlPath, "utf8");
|
|
9892
9467
|
const file = parseConfigToml(tomlSource);
|
|
9893
9468
|
const res = await ossFetch("/api/metadata");
|
|
9894
9469
|
const raw = await res.json();
|
|
@@ -9916,7 +9491,7 @@ function registerConfigPlanCommand(cfg) {
|
|
|
9916
9491
|
}
|
|
9917
9492
|
|
|
9918
9493
|
// src/commands/config/apply.ts
|
|
9919
|
-
import { readFileSync as
|
|
9494
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
9920
9495
|
import { resolve as resolve7 } from "path";
|
|
9921
9496
|
import * as p2 from "@clack/prompts";
|
|
9922
9497
|
import pc6 from "picocolors";
|
|
@@ -9926,7 +9501,7 @@ function registerConfigApplyCommand(cfg) {
|
|
|
9926
9501
|
try {
|
|
9927
9502
|
await requireAuth();
|
|
9928
9503
|
const tomlPath = resolve7(process.cwd(), opts.file);
|
|
9929
|
-
const tomlSource =
|
|
9504
|
+
const tomlSource = readFileSync9(tomlPath, "utf8");
|
|
9930
9505
|
const file = parseConfigToml(tomlSource);
|
|
9931
9506
|
const res = await ossFetch("/api/metadata");
|
|
9932
9507
|
const raw = await res.json();
|
|
@@ -10083,8 +9658,8 @@ function registerConfigCommand(program2) {
|
|
|
10083
9658
|
}
|
|
10084
9659
|
|
|
10085
9660
|
// src/commands/ai/setup.ts
|
|
10086
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
10087
|
-
import { isAbsolute, join as
|
|
9661
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
|
|
9662
|
+
import { isAbsolute, join as join14, relative as relative3, resolve as resolve8 } from "path";
|
|
10088
9663
|
import * as clack17 from "@clack/prompts";
|
|
10089
9664
|
import pc7 from "picocolors";
|
|
10090
9665
|
|
|
@@ -10105,6 +9680,52 @@ async function getOpenRouterApiKey() {
|
|
|
10105
9680
|
};
|
|
10106
9681
|
}
|
|
10107
9682
|
|
|
9683
|
+
// src/lib/env-writer.ts
|
|
9684
|
+
import { existsSync as existsSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
|
|
9685
|
+
var KEY_LINE_RE = (key) => (
|
|
9686
|
+
// Match `KEY=...` at the start of a line (allowing leading whitespace).
|
|
9687
|
+
// Captures the value side; we only need the value portion to compare.
|
|
9688
|
+
new RegExp(`^\\s*${key.replace(/[$.*+?^()[\\]{}|]/g, "\\$&")}\\s*=\\s*(.*)$`, "m")
|
|
9689
|
+
);
|
|
9690
|
+
function stripQuotes(v) {
|
|
9691
|
+
const t = v.trim();
|
|
9692
|
+
if (t.startsWith('"') && t.endsWith('"') && t.length >= 2 || t.startsWith("'") && t.endsWith("'") && t.length >= 2) {
|
|
9693
|
+
return t.slice(1, -1);
|
|
9694
|
+
}
|
|
9695
|
+
const hash = t.indexOf(" #");
|
|
9696
|
+
return hash >= 0 ? t.slice(0, hash).trimEnd() : t;
|
|
9697
|
+
}
|
|
9698
|
+
function upsertEnvFile(path6, entries) {
|
|
9699
|
+
const exists = existsSync11(path6);
|
|
9700
|
+
let content = exists ? readFileSync10(path6, "utf-8") : "";
|
|
9701
|
+
const result = { added: [], skipped: [], mismatched: [] };
|
|
9702
|
+
const additions = [];
|
|
9703
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
9704
|
+
const re = KEY_LINE_RE(key);
|
|
9705
|
+
const match = content.match(re);
|
|
9706
|
+
if (match) {
|
|
9707
|
+
const existingValue = stripQuotes(match[1] ?? "");
|
|
9708
|
+
if (existingValue === value) {
|
|
9709
|
+
result.skipped.push(key);
|
|
9710
|
+
} else {
|
|
9711
|
+
result.mismatched.push({ key, existingValue, newValue: value });
|
|
9712
|
+
}
|
|
9713
|
+
continue;
|
|
9714
|
+
}
|
|
9715
|
+
additions.push(`${key}=${value}`);
|
|
9716
|
+
result.added.push(key);
|
|
9717
|
+
}
|
|
9718
|
+
if (additions.length > 0) {
|
|
9719
|
+
if (content.length > 0 && !content.endsWith("\n")) {
|
|
9720
|
+
content += "\n";
|
|
9721
|
+
}
|
|
9722
|
+
content += additions.join("\n") + "\n";
|
|
9723
|
+
writeFileSync8(path6, content);
|
|
9724
|
+
} else if (!exists) {
|
|
9725
|
+
}
|
|
9726
|
+
return result;
|
|
9727
|
+
}
|
|
9728
|
+
|
|
10108
9729
|
// src/commands/ai/setup.ts
|
|
10109
9730
|
var DEFAULT_ENV_FILE = ".env.local";
|
|
10110
9731
|
var OPENROUTER_ENV_KEY = "OPENROUTER_API_KEY";
|
|
@@ -10196,7 +9817,7 @@ async function runAiSetup(opts) {
|
|
|
10196
9817
|
};
|
|
10197
9818
|
}
|
|
10198
9819
|
function displayPath(path6) {
|
|
10199
|
-
const rel =
|
|
9820
|
+
const rel = relative3(process.cwd(), path6);
|
|
10200
9821
|
if (!rel || rel.startsWith("..") || isAbsolute(rel)) {
|
|
10201
9822
|
return path6;
|
|
10202
9823
|
}
|
|
@@ -10210,12 +9831,12 @@ function isLocalEnvFile(envFile) {
|
|
|
10210
9831
|
function ensureLocalEnvIgnored(cwd, envFile) {
|
|
10211
9832
|
if (!isLocalEnvFile(envFile)) return false;
|
|
10212
9833
|
const envPath = resolve8(cwd, envFile);
|
|
10213
|
-
const relEnvPath =
|
|
9834
|
+
const relEnvPath = relative3(cwd, envPath);
|
|
10214
9835
|
if (!relEnvPath || relEnvPath.startsWith("..") || isAbsolute(relEnvPath)) {
|
|
10215
9836
|
return false;
|
|
10216
9837
|
}
|
|
10217
|
-
const gitignorePath =
|
|
10218
|
-
const existing =
|
|
9838
|
+
const gitignorePath = join14(cwd, ".gitignore");
|
|
9839
|
+
const existing = existsSync12(gitignorePath) ? readFileSync11(gitignorePath, "utf-8") : "";
|
|
10219
9840
|
const lines = new Set(existing.split(/\r?\n/).map((line) => line.trim()));
|
|
10220
9841
|
const envBasename = envFile.replace(/\\/g, "/").split("/").pop() ?? envFile;
|
|
10221
9842
|
if (lines.has(".env*") || lines.has(".env.*") || lines.has(".env*.local") || lines.has(".env.local") && envBasename === ".env.local") {
|
|
@@ -10235,8 +9856,8 @@ function registerAiCommands(aiCmd2) {
|
|
|
10235
9856
|
}
|
|
10236
9857
|
|
|
10237
9858
|
// src/index.ts
|
|
10238
|
-
var __dirname =
|
|
10239
|
-
var pkg = JSON.parse(
|
|
9859
|
+
var __dirname = dirname2(fileURLToPath(import.meta.url));
|
|
9860
|
+
var pkg = JSON.parse(readFileSync12(join15(__dirname, "../package.json"), "utf-8"));
|
|
10240
9861
|
var INSFORGE_LOGO = `
|
|
10241
9862
|
\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
10242
9863
|
\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D
|