@kenkaiiii/gg-pixel 4.3.62 → 4.3.63

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/cli.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // src/install.ts
4
4
  import { existsSync, readFileSync, writeFileSync, appendFileSync, mkdirSync } from "fs";
5
5
  import { homedir } from "os";
6
- import { dirname, join, resolve } from "path";
6
+ import { dirname, join, relative, resolve, sep } from "path";
7
7
  import { spawnSync } from "child_process";
8
8
  var DEFAULT_INGEST_URL = "https://gg-pixel-server.buzzbeamaustralia.workers.dev";
9
9
  async function install(opts = {}) {
@@ -27,6 +27,7 @@ async function install(opts = {}) {
27
27
  const home = opts.homeDir ?? homedir();
28
28
  const projectsJsonPath = join(home, ".gg", "projects.json");
29
29
  writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot);
30
+ const entryWiring = wireEntryFile(projectRoot, initFilePath, pkg);
30
31
  return {
31
32
  projectId: created.id,
32
33
  projectKey: created.key,
@@ -35,7 +36,8 @@ async function install(opts = {}) {
35
36
  envFilePath,
36
37
  projectsJsonPath,
37
38
  packageManager: pm,
38
- packageInstalled
39
+ packageInstalled,
40
+ entryWiring
39
41
  };
40
42
  }
41
43
  function findProjectRoot(start) {
@@ -76,7 +78,7 @@ function detectPackageManager(projectRoot) {
76
78
  }
77
79
  function runInstall(projectRoot, pm, pkg) {
78
80
  const cmd = pm;
79
- const args = pm === "npm" ? ["install", pkg] : ["add", pkg];
81
+ const args = pm === "npm" ? ["install", pkg, "--no-audit", "--no-fund"] : ["add", pkg];
80
82
  const result = spawnSync(cmd, args, { cwd: projectRoot, stdio: "inherit" });
81
83
  return result.status === 0;
82
84
  }
@@ -100,14 +102,108 @@ function writeEnvKey(envPath, key, value) {
100
102
  writeFileSync(envPath, current.replace(lineRegex, `${key}=${value}`), "utf8");
101
103
  return;
102
104
  }
103
- const sep = current.endsWith("\n") || current.length === 0 ? "" : "\n";
104
- appendFileSync(envPath, `${sep}${key}=${value}
105
+ const sep2 = current.endsWith("\n") || current.length === 0 ? "" : "\n";
106
+ appendFileSync(envPath, `${sep2}${key}=${value}
105
107
  `, "utf8");
106
108
  return;
107
109
  }
108
110
  writeFileSync(envPath, `${key}=${value}
109
111
  `, "utf8");
110
112
  }
113
+ function wireEntryFile(projectRoot, initFilePath, pkg) {
114
+ const entryPath = findEntryFile(projectRoot, pkg);
115
+ if (!entryPath) return { kind: "no_entry_found" };
116
+ let content;
117
+ try {
118
+ content = readFileSync(entryPath, "utf8");
119
+ } catch (err) {
120
+ return { kind: "skipped", reason: `unreadable: ${err.message}` };
121
+ }
122
+ if (content.includes("gg-pixel.init")) {
123
+ return { kind: "already_present", entryPath };
124
+ }
125
+ const fromDir = dirname(entryPath);
126
+ let spec = relative(fromDir, initFilePath).split(sep).join("/");
127
+ if (!spec.startsWith(".")) spec = "./" + spec;
128
+ const isCjs = isCommonJsEntry(entryPath, pkg);
129
+ const importLine = isCjs ? `require(${JSON.stringify(spec)});` : `import ${JSON.stringify(spec)};`;
130
+ const lines = content.split("\n");
131
+ let insertAt = 0;
132
+ if (lines[0]?.startsWith("#!")) insertAt = 1;
133
+ while (insertAt < lines.length && /^\s*(?:["']use strict["']|\/\/|\/\*)/.test(lines[insertAt] ?? "")) {
134
+ insertAt++;
135
+ }
136
+ const updated = [...lines.slice(0, insertAt), importLine, ...lines.slice(insertAt)].join("\n");
137
+ writeFileSync(entryPath, updated, "utf8");
138
+ return { kind: "injected", entryPath };
139
+ }
140
+ function findEntryFile(projectRoot, pkg) {
141
+ const tryPath = (rel) => {
142
+ const p = join(projectRoot, rel);
143
+ if (existsSync(p)) return p;
144
+ if (rel.endsWith(".js")) {
145
+ const ts = join(projectRoot, rel.replace(/\.js$/, ".ts"));
146
+ if (existsSync(ts)) return ts;
147
+ }
148
+ return null;
149
+ };
150
+ if (typeof pkg.bin === "string") {
151
+ const found = tryPath(pkg.bin);
152
+ if (found) return found;
153
+ }
154
+ if (pkg.bin && typeof pkg.bin === "object") {
155
+ for (const value of Object.values(pkg.bin)) {
156
+ if (typeof value === "string") {
157
+ const found = tryPath(value);
158
+ if (found) return found;
159
+ }
160
+ }
161
+ }
162
+ if (pkg.main) {
163
+ const found = tryPath(pkg.main);
164
+ if (found) return found;
165
+ }
166
+ if (pkg.module) {
167
+ const found = tryPath(pkg.module);
168
+ if (found) return found;
169
+ }
170
+ const candidates = [
171
+ "src/index.ts",
172
+ "src/index.tsx",
173
+ "src/index.js",
174
+ "src/index.mjs",
175
+ "src/main.ts",
176
+ "src/main.tsx",
177
+ "src/main.js",
178
+ "src/server.ts",
179
+ "src/server.js",
180
+ "src/app.ts",
181
+ "src/app.js",
182
+ "src/cli.ts",
183
+ "src/cli.js",
184
+ "index.ts",
185
+ "index.tsx",
186
+ "index.js",
187
+ "index.mjs",
188
+ "main.ts",
189
+ "main.js",
190
+ "server.ts",
191
+ "server.js",
192
+ "app.ts",
193
+ "app.js"
194
+ ];
195
+ for (const c of candidates) {
196
+ const found = tryPath(c);
197
+ if (found) return found;
198
+ }
199
+ return null;
200
+ }
201
+ function isCommonJsEntry(entryPath, pkg) {
202
+ if (entryPath.endsWith(".cjs")) return true;
203
+ if (entryPath.endsWith(".mjs")) return false;
204
+ if (entryPath.endsWith(".ts") || entryPath.endsWith(".tsx")) return false;
205
+ return pkg.type !== "module";
206
+ }
111
207
  function writeProjectsMapping(projectsJsonPath, projectId, name, path) {
112
208
  mkdirSync(dirname(projectsJsonPath), { recursive: true });
113
209
  let map = {};
@@ -169,14 +265,26 @@ async function main(argv) {
169
265
  console.log(` Wrote: ${result.initFilePath}`);
170
266
  console.log(` Wrote env: ${result.envFilePath}`);
171
267
  console.log(` Mapping saved: ${result.projectsJsonPath}`);
268
+ switch (result.entryWiring.kind) {
269
+ case "injected":
270
+ console.log(` Wired entry: ${result.entryWiring.entryPath}`);
271
+ break;
272
+ case "already_present":
273
+ console.log(` Entry: ${result.entryWiring.entryPath} (already wired)`);
274
+ break;
275
+ case "no_entry_found":
276
+ console.log(` \u26A0 Could not auto-detect your entry file.`);
277
+ console.log(` Add this line to the TOP of your entry file manually:`);
278
+ console.log(` import "./gg-pixel.init.mjs";`);
279
+ break;
280
+ case "skipped":
281
+ console.log(` \u26A0 Entry wiring skipped: ${result.entryWiring.reason}`);
282
+ break;
283
+ }
172
284
  if (!result.packageInstalled && !args.skipPackageInstall) {
173
285
  console.log(` \u26A0 Package install failed via ${result.packageManager}. Run it manually.`);
174
286
  }
175
287
  console.log("");
176
- console.log("Last step: add this line to the TOP of your entry file:");
177
- console.log("");
178
- console.log(` import "./gg-pixel.init.mjs";`);
179
- console.log("");
180
288
  }
181
289
  main(process.argv.slice(2)).catch((err) => {
182
290
  console.error(err instanceof Error ? err.message : String(err));
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/install.ts","../src/cli.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync, appendFileSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\n\nexport const DEFAULT_INGEST_URL = \"https://gg-pixel-server.buzzbeamaustralia.workers.dev\";\n\nexport interface InstallOptions {\n cwd?: string;\n ingestUrl?: string;\n projectName?: string;\n fetchFn?: typeof fetch;\n skipPackageInstall?: boolean;\n homeDir?: string;\n}\n\nexport interface InstallResult {\n projectId: string;\n projectKey: string;\n projectName: string;\n initFilePath: string;\n envFilePath: string;\n projectsJsonPath: string;\n packageManager: PackageManager;\n packageInstalled: boolean;\n}\n\nexport type PackageManager = \"pnpm\" | \"yarn\" | \"bun\" | \"npm\";\n\nexport async function install(opts: InstallOptions = {}): Promise<InstallResult> {\n const cwd = resolve(opts.cwd ?? process.cwd());\n const ingestUrl = (opts.ingestUrl ?? DEFAULT_INGEST_URL).replace(/\\/+$/, \"\");\n const fetchFn = opts.fetchFn ?? fetch;\n\n const projectRoot = findProjectRoot(cwd);\n if (!projectRoot) {\n throw new Error(`No package.json found in ${cwd} or any parent directory.`);\n }\n\n const pkgPath = join(projectRoot, \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as { name?: string };\n const projectName = opts.projectName ?? pkg.name ?? projectRoot.split(\"/\").pop() ?? \"unnamed\";\n\n const created = await createProject(fetchFn, ingestUrl, projectName);\n\n const pm = detectPackageManager(projectRoot);\n const packageInstalled = opts.skipPackageInstall\n ? false\n : runInstall(projectRoot, pm, \"@kenkaiiii/gg-pixel\");\n\n const initFilePath = join(projectRoot, \"gg-pixel.init.mjs\");\n writeFileSync(initFilePath, renderInitFile(ingestUrl), \"utf8\");\n\n const envFilePath = join(projectRoot, \".env\");\n writeEnvKey(envFilePath, \"GG_PIXEL_KEY\", created.key);\n\n const home = opts.homeDir ?? homedir();\n const projectsJsonPath = join(home, \".gg\", \"projects.json\");\n writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot);\n\n return {\n projectId: created.id,\n projectKey: created.key,\n projectName,\n initFilePath,\n envFilePath,\n projectsJsonPath,\n packageManager: pm,\n packageInstalled,\n };\n}\n\nfunction findProjectRoot(start: string): string | null {\n let dir = start;\n for (let i = 0; i < 20; i++) {\n if (existsSync(join(dir, \"package.json\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n return null;\n}\n\nasync function createProject(\n fetchFn: typeof fetch,\n ingestUrl: string,\n name: string,\n): Promise<{ id: string; key: string }> {\n const res = await fetchFn(`${ingestUrl}/api/projects`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ name }),\n });\n if (!res.ok) {\n throw new Error(`POST /api/projects failed: ${res.status} ${await safeText(res)}`);\n }\n const body = (await res.json()) as { id: string; key: string };\n if (!body.id || !body.key) throw new Error(\"response missing id/key\");\n return { id: body.id, key: body.key };\n}\n\nasync function safeText(r: Response): Promise<string> {\n try {\n return await r.text();\n } catch {\n return \"\";\n }\n}\n\nexport function detectPackageManager(projectRoot: string): PackageManager {\n if (existsSync(join(projectRoot, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(join(projectRoot, \"bun.lockb\"))) return \"bun\";\n if (existsSync(join(projectRoot, \"yarn.lock\"))) return \"yarn\";\n return \"npm\";\n}\n\nfunction runInstall(projectRoot: string, pm: PackageManager, pkg: string): boolean {\n const cmd = pm;\n const args = pm === \"npm\" ? [\"install\", pkg] : [\"add\", pkg];\n const result = spawnSync(cmd, args, { cwd: projectRoot, stdio: \"inherit\" });\n return result.status === 0;\n}\n\nexport function renderInitFile(ingestUrl: string): string {\n return `import { initPixel } from \"@kenkaiiii/gg-pixel\";\n\nconst key = process.env.GG_PIXEL_KEY;\nif (key) {\n initPixel({\n projectKey: key,\n sink: { kind: \"http\", ingestUrl: ${JSON.stringify(`${ingestUrl}/ingest`)} },\n });\n}\n`;\n}\n\nexport function writeEnvKey(envPath: string, key: string, value: string): void {\n if (existsSync(envPath)) {\n const current = readFileSync(envPath, \"utf8\");\n const lineRegex = new RegExp(`^${key}=.*$`, \"m\");\n if (lineRegex.test(current)) {\n writeFileSync(envPath, current.replace(lineRegex, `${key}=${value}`), \"utf8\");\n return;\n }\n const sep = current.endsWith(\"\\n\") || current.length === 0 ? \"\" : \"\\n\";\n appendFileSync(envPath, `${sep}${key}=${value}\\n`, \"utf8\");\n return;\n }\n writeFileSync(envPath, `${key}=${value}\\n`, \"utf8\");\n}\n\nexport function writeProjectsMapping(\n projectsJsonPath: string,\n projectId: string,\n name: string,\n path: string,\n): void {\n mkdirSync(dirname(projectsJsonPath), { recursive: true });\n let map: Record<string, { name: string; path: string }> = {};\n if (existsSync(projectsJsonPath)) {\n try {\n map = JSON.parse(readFileSync(projectsJsonPath, \"utf8\")) as typeof map;\n } catch {\n // start fresh on corrupt file\n }\n }\n map[projectId] = { name, path };\n writeFileSync(projectsJsonPath, `${JSON.stringify(map, null, 2)}\\n`, \"utf8\");\n}\n","import { install, DEFAULT_INGEST_URL } from \"./install.js\";\n\ninterface ParsedArgs {\n command: string;\n ingestUrl?: string;\n name?: string;\n skipPackageInstall: boolean;\n help: boolean;\n}\n\nfunction parse(argv: string[]): ParsedArgs {\n const out: ParsedArgs = { command: argv[0] ?? \"\", skipPackageInstall: false, help: false };\n for (let i = 1; i < argv.length; i++) {\n const a = argv[i];\n if (a === \"--ingest-url\") out.ingestUrl = argv[++i];\n else if (a === \"--name\") out.name = argv[++i];\n else if (a === \"--skip-install\") out.skipPackageInstall = true;\n else if (a === \"--help\" || a === \"-h\") out.help = true;\n }\n return out;\n}\n\nfunction printUsage(): void {\n console.log(`gg-pixel install — drop the pixel into the current project\n\nUsage:\n gg-pixel install [--name <project-name>] [--ingest-url <url>] [--skip-install]\n\nOptions:\n --name Project name to register (defaults to package.json name)\n --ingest-url Backend URL (defaults to ${DEFAULT_INGEST_URL})\n --skip-install Skip the package-manager install step (useful for testing)\n`);\n}\n\nasync function main(argv: string[]): Promise<void> {\n const args = parse(argv);\n if (args.help || !args.command) {\n printUsage();\n return;\n }\n if (args.command !== \"install\") {\n console.error(`Unknown command: ${args.command}`);\n printUsage();\n process.exitCode = 1;\n return;\n }\n\n const result = await install({\n ingestUrl: args.ingestUrl,\n projectName: args.name,\n skipPackageInstall: args.skipPackageInstall,\n });\n\n console.log(\"\");\n console.log(\"Pixel installed.\");\n console.log(` Project: ${result.projectName} (${result.projectId})`);\n console.log(` Wrote: ${result.initFilePath}`);\n console.log(` Wrote env: ${result.envFilePath}`);\n console.log(` Mapping saved: ${result.projectsJsonPath}`);\n if (!result.packageInstalled && !args.skipPackageInstall) {\n console.log(` ⚠ Package install failed via ${result.packageManager}. Run it manually.`);\n }\n console.log(\"\");\n console.log(\"Last step: add this line to the TOP of your entry file:\");\n console.log(\"\");\n console.log(` import \"./gg-pixel.init.mjs\";`);\n console.log(\"\");\n}\n\nmain(process.argv.slice(2)).catch((err: unknown) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/install.ts","../src/cli.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync, appendFileSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\n\nexport const DEFAULT_INGEST_URL = \"https://gg-pixel-server.buzzbeamaustralia.workers.dev\";\n\nexport interface InstallOptions {\n cwd?: string;\n ingestUrl?: string;\n projectName?: string;\n fetchFn?: typeof fetch;\n skipPackageInstall?: boolean;\n homeDir?: string;\n}\n\nexport interface InstallResult {\n projectId: string;\n projectKey: string;\n projectName: string;\n initFilePath: string;\n envFilePath: string;\n projectsJsonPath: string;\n packageManager: PackageManager;\n packageInstalled: boolean;\n entryWiring: EntryWiringResult;\n}\n\nexport type EntryWiringResult =\n | { kind: \"injected\"; entryPath: string }\n | { kind: \"already_present\"; entryPath: string }\n | { kind: \"no_entry_found\" }\n | { kind: \"skipped\"; reason: string };\n\ninterface PackageJson {\n name?: string;\n type?: string;\n main?: string;\n module?: string;\n bin?: string | Record<string, string>;\n}\n\nexport type PackageManager = \"pnpm\" | \"yarn\" | \"bun\" | \"npm\";\n\nexport async function install(opts: InstallOptions = {}): Promise<InstallResult> {\n const cwd = resolve(opts.cwd ?? process.cwd());\n const ingestUrl = (opts.ingestUrl ?? DEFAULT_INGEST_URL).replace(/\\/+$/, \"\");\n const fetchFn = opts.fetchFn ?? fetch;\n\n const projectRoot = findProjectRoot(cwd);\n if (!projectRoot) {\n throw new Error(`No package.json found in ${cwd} or any parent directory.`);\n }\n\n const pkgPath = join(projectRoot, \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as PackageJson;\n const projectName = opts.projectName ?? pkg.name ?? projectRoot.split(\"/\").pop() ?? \"unnamed\";\n\n const created = await createProject(fetchFn, ingestUrl, projectName);\n\n const pm = detectPackageManager(projectRoot);\n const packageInstalled = opts.skipPackageInstall\n ? false\n : runInstall(projectRoot, pm, \"@kenkaiiii/gg-pixel\");\n\n const initFilePath = join(projectRoot, \"gg-pixel.init.mjs\");\n writeFileSync(initFilePath, renderInitFile(ingestUrl), \"utf8\");\n\n const envFilePath = join(projectRoot, \".env\");\n writeEnvKey(envFilePath, \"GG_PIXEL_KEY\", created.key);\n\n const home = opts.homeDir ?? homedir();\n const projectsJsonPath = join(home, \".gg\", \"projects.json\");\n writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot);\n\n const entryWiring = wireEntryFile(projectRoot, initFilePath, pkg);\n\n return {\n projectId: created.id,\n projectKey: created.key,\n projectName,\n initFilePath,\n envFilePath,\n projectsJsonPath,\n packageManager: pm,\n packageInstalled,\n entryWiring,\n };\n}\n\nfunction findProjectRoot(start: string): string | null {\n let dir = start;\n for (let i = 0; i < 20; i++) {\n if (existsSync(join(dir, \"package.json\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n return null;\n}\n\nasync function createProject(\n fetchFn: typeof fetch,\n ingestUrl: string,\n name: string,\n): Promise<{ id: string; key: string }> {\n const res = await fetchFn(`${ingestUrl}/api/projects`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ name }),\n });\n if (!res.ok) {\n throw new Error(`POST /api/projects failed: ${res.status} ${await safeText(res)}`);\n }\n const body = (await res.json()) as { id: string; key: string };\n if (!body.id || !body.key) throw new Error(\"response missing id/key\");\n return { id: body.id, key: body.key };\n}\n\nasync function safeText(r: Response): Promise<string> {\n try {\n return await r.text();\n } catch {\n return \"\";\n }\n}\n\nexport function detectPackageManager(projectRoot: string): PackageManager {\n if (existsSync(join(projectRoot, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(join(projectRoot, \"bun.lockb\"))) return \"bun\";\n if (existsSync(join(projectRoot, \"yarn.lock\"))) return \"yarn\";\n return \"npm\";\n}\n\nfunction runInstall(projectRoot: string, pm: PackageManager, pkg: string): boolean {\n const cmd = pm;\n // npm prints `npm audit` warnings + `npm fund` solicitations on every install.\n // That output is about the user's *existing* project — irrelevant to pixel.\n // The other package managers don't show this noise by default.\n const args = pm === \"npm\" ? [\"install\", pkg, \"--no-audit\", \"--no-fund\"] : [\"add\", pkg];\n const result = spawnSync(cmd, args, { cwd: projectRoot, stdio: \"inherit\" });\n return result.status === 0;\n}\n\nexport function renderInitFile(ingestUrl: string): string {\n return `import { initPixel } from \"@kenkaiiii/gg-pixel\";\n\nconst key = process.env.GG_PIXEL_KEY;\nif (key) {\n initPixel({\n projectKey: key,\n sink: { kind: \"http\", ingestUrl: ${JSON.stringify(`${ingestUrl}/ingest`)} },\n });\n}\n`;\n}\n\nexport function writeEnvKey(envPath: string, key: string, value: string): void {\n if (existsSync(envPath)) {\n const current = readFileSync(envPath, \"utf8\");\n const lineRegex = new RegExp(`^${key}=.*$`, \"m\");\n if (lineRegex.test(current)) {\n writeFileSync(envPath, current.replace(lineRegex, `${key}=${value}`), \"utf8\");\n return;\n }\n const sep = current.endsWith(\"\\n\") || current.length === 0 ? \"\" : \"\\n\";\n appendFileSync(envPath, `${sep}${key}=${value}\\n`, \"utf8\");\n return;\n }\n writeFileSync(envPath, `${key}=${value}\\n`, \"utf8\");\n}\n\nexport function wireEntryFile(\n projectRoot: string,\n initFilePath: string,\n pkg: PackageJson,\n): EntryWiringResult {\n const entryPath = findEntryFile(projectRoot, pkg);\n if (!entryPath) return { kind: \"no_entry_found\" };\n\n let content: string;\n try {\n content = readFileSync(entryPath, \"utf8\");\n } catch (err) {\n return { kind: \"skipped\", reason: `unreadable: ${(err as Error).message}` };\n }\n\n if (content.includes(\"gg-pixel.init\")) {\n return { kind: \"already_present\", entryPath };\n }\n\n // Compute import specifier relative to the entry file.\n const fromDir = dirname(entryPath);\n let spec = relative(fromDir, initFilePath).split(sep).join(\"/\");\n if (!spec.startsWith(\".\")) spec = \"./\" + spec;\n\n const isCjs = isCommonJsEntry(entryPath, pkg);\n const importLine = isCjs\n ? `require(${JSON.stringify(spec)});`\n : `import ${JSON.stringify(spec)};`;\n\n // Inject at the top — after a shebang line and any leading \"use strict\",\n // but before all other code, so pixel hooks run before anything else.\n const lines = content.split(\"\\n\");\n let insertAt = 0;\n if (lines[0]?.startsWith(\"#!\")) insertAt = 1;\n while (\n insertAt < lines.length &&\n /^\\s*(?:[\"']use strict[\"']|\\/\\/|\\/\\*)/.test(lines[insertAt] ?? \"\")\n ) {\n insertAt++;\n }\n\n const updated = [...lines.slice(0, insertAt), importLine, ...lines.slice(insertAt)].join(\"\\n\");\n writeFileSync(entryPath, updated, \"utf8\");\n return { kind: \"injected\", entryPath };\n}\n\nfunction findEntryFile(projectRoot: string, pkg: PackageJson): string | null {\n const tryPath = (rel: string): string | null => {\n const p = join(projectRoot, rel);\n if (existsSync(p)) return p;\n // If user pointed `main` at .js but only the .ts source exists (common in TS projects).\n if (rel.endsWith(\".js\")) {\n const ts = join(projectRoot, rel.replace(/\\.js$/, \".ts\"));\n if (existsSync(ts)) return ts;\n }\n return null;\n };\n\n if (typeof pkg.bin === \"string\") {\n const found = tryPath(pkg.bin);\n if (found) return found;\n }\n if (pkg.bin && typeof pkg.bin === \"object\") {\n for (const value of Object.values(pkg.bin)) {\n if (typeof value === \"string\") {\n const found = tryPath(value);\n if (found) return found;\n }\n }\n }\n if (pkg.main) {\n const found = tryPath(pkg.main);\n if (found) return found;\n }\n if (pkg.module) {\n const found = tryPath(pkg.module);\n if (found) return found;\n }\n\n // Fall back to common conventions.\n const candidates = [\n \"src/index.ts\",\n \"src/index.tsx\",\n \"src/index.js\",\n \"src/index.mjs\",\n \"src/main.ts\",\n \"src/main.tsx\",\n \"src/main.js\",\n \"src/server.ts\",\n \"src/server.js\",\n \"src/app.ts\",\n \"src/app.js\",\n \"src/cli.ts\",\n \"src/cli.js\",\n \"index.ts\",\n \"index.tsx\",\n \"index.js\",\n \"index.mjs\",\n \"main.ts\",\n \"main.js\",\n \"server.ts\",\n \"server.js\",\n \"app.ts\",\n \"app.js\",\n ];\n for (const c of candidates) {\n const found = tryPath(c);\n if (found) return found;\n }\n return null;\n}\n\nfunction isCommonJsEntry(entryPath: string, pkg: PackageJson): boolean {\n if (entryPath.endsWith(\".cjs\")) return true;\n if (entryPath.endsWith(\".mjs\")) return false;\n if (entryPath.endsWith(\".ts\") || entryPath.endsWith(\".tsx\")) return false;\n // .js → governed by package.json type (default is \"commonjs\")\n return pkg.type !== \"module\";\n}\n\nexport function writeProjectsMapping(\n projectsJsonPath: string,\n projectId: string,\n name: string,\n path: string,\n): void {\n mkdirSync(dirname(projectsJsonPath), { recursive: true });\n let map: Record<string, { name: string; path: string }> = {};\n if (existsSync(projectsJsonPath)) {\n try {\n map = JSON.parse(readFileSync(projectsJsonPath, \"utf8\")) as typeof map;\n } catch {\n // start fresh on corrupt file\n }\n }\n map[projectId] = { name, path };\n writeFileSync(projectsJsonPath, `${JSON.stringify(map, null, 2)}\\n`, \"utf8\");\n}\n","import { install, DEFAULT_INGEST_URL } from \"./install.js\";\n\ninterface ParsedArgs {\n command: string;\n ingestUrl?: string;\n name?: string;\n skipPackageInstall: boolean;\n help: boolean;\n}\n\nfunction parse(argv: string[]): ParsedArgs {\n const out: ParsedArgs = { command: argv[0] ?? \"\", skipPackageInstall: false, help: false };\n for (let i = 1; i < argv.length; i++) {\n const a = argv[i];\n if (a === \"--ingest-url\") out.ingestUrl = argv[++i];\n else if (a === \"--name\") out.name = argv[++i];\n else if (a === \"--skip-install\") out.skipPackageInstall = true;\n else if (a === \"--help\" || a === \"-h\") out.help = true;\n }\n return out;\n}\n\nfunction printUsage(): void {\n console.log(`gg-pixel install — drop the pixel into the current project\n\nUsage:\n gg-pixel install [--name <project-name>] [--ingest-url <url>] [--skip-install]\n\nOptions:\n --name Project name to register (defaults to package.json name)\n --ingest-url Backend URL (defaults to ${DEFAULT_INGEST_URL})\n --skip-install Skip the package-manager install step (useful for testing)\n`);\n}\n\nasync function main(argv: string[]): Promise<void> {\n const args = parse(argv);\n if (args.help || !args.command) {\n printUsage();\n return;\n }\n if (args.command !== \"install\") {\n console.error(`Unknown command: ${args.command}`);\n printUsage();\n process.exitCode = 1;\n return;\n }\n\n const result = await install({\n ingestUrl: args.ingestUrl,\n projectName: args.name,\n skipPackageInstall: args.skipPackageInstall,\n });\n\n console.log(\"\");\n console.log(\"Pixel installed.\");\n console.log(` Project: ${result.projectName} (${result.projectId})`);\n console.log(` Wrote: ${result.initFilePath}`);\n console.log(` Wrote env: ${result.envFilePath}`);\n console.log(` Mapping saved: ${result.projectsJsonPath}`);\n switch (result.entryWiring.kind) {\n case \"injected\":\n console.log(` Wired entry: ${result.entryWiring.entryPath}`);\n break;\n case \"already_present\":\n console.log(` Entry: ${result.entryWiring.entryPath} (already wired)`);\n break;\n case \"no_entry_found\":\n console.log(` ⚠ Could not auto-detect your entry file.`);\n console.log(` Add this line to the TOP of your entry file manually:`);\n console.log(` import \"./gg-pixel.init.mjs\";`);\n break;\n case \"skipped\":\n console.log(` ⚠ Entry wiring skipped: ${result.entryWiring.reason}`);\n break;\n }\n if (!result.packageInstalled && !args.skipPackageInstall) {\n console.log(` ⚠ Package install failed via ${result.packageManager}. Run it manually.`);\n }\n console.log(\"\");\n}\n\nmain(process.argv.slice(2)).catch((err: unknown) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n});\n"],"mappings":"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","names":["sep"]}
package/dist/index.cjs CHANGED
@@ -430,6 +430,7 @@ async function install(opts = {}) {
430
430
  const home = opts.homeDir ?? (0, import_node_os2.homedir)();
431
431
  const projectsJsonPath = (0, import_node_path2.join)(home, ".gg", "projects.json");
432
432
  writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot);
433
+ const entryWiring = wireEntryFile(projectRoot, initFilePath, pkg);
433
434
  return {
434
435
  projectId: created.id,
435
436
  projectKey: created.key,
@@ -438,7 +439,8 @@ async function install(opts = {}) {
438
439
  envFilePath,
439
440
  projectsJsonPath,
440
441
  packageManager: pm,
441
- packageInstalled
442
+ packageInstalled,
443
+ entryWiring
442
444
  };
443
445
  }
444
446
  function findProjectRoot(start) {
@@ -479,7 +481,7 @@ function detectPackageManager(projectRoot) {
479
481
  }
480
482
  function runInstall(projectRoot, pm, pkg) {
481
483
  const cmd = pm;
482
- const args = pm === "npm" ? ["install", pkg] : ["add", pkg];
484
+ const args = pm === "npm" ? ["install", pkg, "--no-audit", "--no-fund"] : ["add", pkg];
483
485
  const result = (0, import_node_child_process.spawnSync)(cmd, args, { cwd: projectRoot, stdio: "inherit" });
484
486
  return result.status === 0;
485
487
  }
@@ -503,14 +505,108 @@ function writeEnvKey(envPath, key, value) {
503
505
  (0, import_node_fs3.writeFileSync)(envPath, current.replace(lineRegex, `${key}=${value}`), "utf8");
504
506
  return;
505
507
  }
506
- const sep = current.endsWith("\n") || current.length === 0 ? "" : "\n";
507
- (0, import_node_fs3.appendFileSync)(envPath, `${sep}${key}=${value}
508
+ const sep2 = current.endsWith("\n") || current.length === 0 ? "" : "\n";
509
+ (0, import_node_fs3.appendFileSync)(envPath, `${sep2}${key}=${value}
508
510
  `, "utf8");
509
511
  return;
510
512
  }
511
513
  (0, import_node_fs3.writeFileSync)(envPath, `${key}=${value}
512
514
  `, "utf8");
513
515
  }
516
+ function wireEntryFile(projectRoot, initFilePath, pkg) {
517
+ const entryPath = findEntryFile(projectRoot, pkg);
518
+ if (!entryPath) return { kind: "no_entry_found" };
519
+ let content;
520
+ try {
521
+ content = (0, import_node_fs3.readFileSync)(entryPath, "utf8");
522
+ } catch (err) {
523
+ return { kind: "skipped", reason: `unreadable: ${err.message}` };
524
+ }
525
+ if (content.includes("gg-pixel.init")) {
526
+ return { kind: "already_present", entryPath };
527
+ }
528
+ const fromDir = (0, import_node_path2.dirname)(entryPath);
529
+ let spec = (0, import_node_path2.relative)(fromDir, initFilePath).split(import_node_path2.sep).join("/");
530
+ if (!spec.startsWith(".")) spec = "./" + spec;
531
+ const isCjs = isCommonJsEntry(entryPath, pkg);
532
+ const importLine = isCjs ? `require(${JSON.stringify(spec)});` : `import ${JSON.stringify(spec)};`;
533
+ const lines = content.split("\n");
534
+ let insertAt = 0;
535
+ if (lines[0]?.startsWith("#!")) insertAt = 1;
536
+ while (insertAt < lines.length && /^\s*(?:["']use strict["']|\/\/|\/\*)/.test(lines[insertAt] ?? "")) {
537
+ insertAt++;
538
+ }
539
+ const updated = [...lines.slice(0, insertAt), importLine, ...lines.slice(insertAt)].join("\n");
540
+ (0, import_node_fs3.writeFileSync)(entryPath, updated, "utf8");
541
+ return { kind: "injected", entryPath };
542
+ }
543
+ function findEntryFile(projectRoot, pkg) {
544
+ const tryPath = (rel) => {
545
+ const p = (0, import_node_path2.join)(projectRoot, rel);
546
+ if ((0, import_node_fs3.existsSync)(p)) return p;
547
+ if (rel.endsWith(".js")) {
548
+ const ts = (0, import_node_path2.join)(projectRoot, rel.replace(/\.js$/, ".ts"));
549
+ if ((0, import_node_fs3.existsSync)(ts)) return ts;
550
+ }
551
+ return null;
552
+ };
553
+ if (typeof pkg.bin === "string") {
554
+ const found = tryPath(pkg.bin);
555
+ if (found) return found;
556
+ }
557
+ if (pkg.bin && typeof pkg.bin === "object") {
558
+ for (const value of Object.values(pkg.bin)) {
559
+ if (typeof value === "string") {
560
+ const found = tryPath(value);
561
+ if (found) return found;
562
+ }
563
+ }
564
+ }
565
+ if (pkg.main) {
566
+ const found = tryPath(pkg.main);
567
+ if (found) return found;
568
+ }
569
+ if (pkg.module) {
570
+ const found = tryPath(pkg.module);
571
+ if (found) return found;
572
+ }
573
+ const candidates = [
574
+ "src/index.ts",
575
+ "src/index.tsx",
576
+ "src/index.js",
577
+ "src/index.mjs",
578
+ "src/main.ts",
579
+ "src/main.tsx",
580
+ "src/main.js",
581
+ "src/server.ts",
582
+ "src/server.js",
583
+ "src/app.ts",
584
+ "src/app.js",
585
+ "src/cli.ts",
586
+ "src/cli.js",
587
+ "index.ts",
588
+ "index.tsx",
589
+ "index.js",
590
+ "index.mjs",
591
+ "main.ts",
592
+ "main.js",
593
+ "server.ts",
594
+ "server.js",
595
+ "app.ts",
596
+ "app.js"
597
+ ];
598
+ for (const c of candidates) {
599
+ const found = tryPath(c);
600
+ if (found) return found;
601
+ }
602
+ return null;
603
+ }
604
+ function isCommonJsEntry(entryPath, pkg) {
605
+ if (entryPath.endsWith(".cjs")) return true;
606
+ if (entryPath.endsWith(".mjs")) return false;
607
+ if (entryPath.endsWith(".ts") || entryPath.endsWith(".tsx")) return false;
608
+ return pkg.type !== "module";
609
+ }
514
610
  function writeProjectsMapping(projectsJsonPath, projectId, name, path) {
515
611
  (0, import_node_fs3.mkdirSync)((0, import_node_path2.dirname)(projectsJsonPath), { recursive: true });
516
612
  let map = {};
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/adapters/node.ts","../src/core/stack.ts","../src/core/fingerprint.ts","../src/code-context.ts","../src/core/queue.ts","../src/core/sinks/http.ts","../src/core/sinks/local-sqlite.ts","../src/install.ts"],"sourcesContent":["import { installNodeAdapter, type NodeAdapter } from \"./adapters/node.js\";\nimport { HttpSink } from \"./core/sinks/http.js\";\nimport { LocalSqliteSink } from \"./core/sinks/local-sqlite.js\";\nimport type { PixelOptions, ReportInput, Sink, SinkConfig } from \"./core/types.js\";\n\nlet active: NodeAdapter | null = null;\n\nexport function initPixel(options: PixelOptions): NodeAdapter {\n if (active) {\n throw new Error(\"gg-pixel is already initialized; call closePixel() first\");\n }\n const sink = buildSink(options.sink);\n active = installNodeAdapter({\n projectKey: options.projectKey,\n runtime: options.runtime ?? defaultRuntime(),\n sink,\n captureConsoleErrors: options.captureConsoleErrors ?? true,\n captureConsoleWarnings: options.captureConsoleWarnings ?? false,\n captureUnhandledRejections: options.captureUnhandledRejections ?? true,\n captureUncaughtExceptions: options.captureUncaughtExceptions ?? true,\n });\n return active;\n}\n\nexport function reportPixel(input: ReportInput): void {\n if (!active) return;\n active.report(input);\n}\n\nexport async function flushPixel(): Promise<void> {\n if (!active) return;\n await active.flush();\n}\n\nexport async function closePixel(): Promise<void> {\n if (!active) return;\n await active.close();\n active = null;\n}\n\nfunction buildSink(config: SinkConfig): Sink {\n switch (config.kind) {\n case \"http\":\n return new HttpSink(config.ingestUrl, config.fetchFn);\n case \"local\":\n return new LocalSqliteSink(config.path);\n case \"custom\":\n return config.sink;\n }\n}\n\nfunction defaultRuntime(): string {\n const v = process.versions.node;\n return `node-${v}`;\n}\n\nexport type {\n Level,\n PixelOptions,\n ReportInput,\n Sink,\n SinkConfig,\n StackFrame,\n CodeContext,\n WireEvent,\n} from \"./core/types.js\";\n\nexport { install, DEFAULT_INGEST_URL } from \"./install.js\";\nexport type { InstallOptions, InstallResult, PackageManager } from \"./install.js\";\n","import { randomUUID } from \"node:crypto\";\nimport { parseStack } from \"../core/stack.js\";\nimport { fingerprint } from \"../core/fingerprint.js\";\nimport { captureCodeContext } from \"../code-context.js\";\nimport { EventQueue } from \"../core/queue.js\";\nimport type { Level, ReportInput, Sink, WireEvent } from \"../core/types.js\";\n\nexport interface NodeAdapterOptions {\n projectKey: string;\n runtime: string;\n sink: Sink;\n captureConsoleErrors: boolean;\n captureConsoleWarnings: boolean;\n captureUnhandledRejections: boolean;\n captureUncaughtExceptions: boolean;\n}\n\nexport interface NodeAdapter {\n report(input: ReportInput): void;\n flush(): Promise<void>;\n close(): Promise<void>;\n}\n\nexport function installNodeAdapter(opts: NodeAdapterOptions): NodeAdapter {\n const queue = new EventQueue(opts.sink);\n const detach: Array<() => void> = [];\n\n const enqueueError = (err: unknown, level: Level, manual: boolean) => {\n try {\n const event = buildEvent(err, level, manual, opts.projectKey, opts.runtime);\n queue.enqueue(event);\n } catch {\n // never let pixel break the host program\n }\n };\n\n const enqueueErrorSync = (err: unknown, level: Level, manual: boolean) => {\n try {\n const event = buildEvent(err, level, manual, opts.projectKey, opts.runtime);\n queue.enqueueSync(event);\n } catch {\n // never let pixel break the host program\n }\n };\n\n if (opts.captureUncaughtExceptions) {\n const handler = (err: Error) => enqueueErrorSync(err, \"fatal\", false);\n process.on(\"uncaughtExceptionMonitor\", handler);\n detach.push(() => process.off(\"uncaughtExceptionMonitor\", handler));\n }\n\n if (opts.captureUnhandledRejections) {\n const handler = (reason: unknown) => enqueueErrorSync(reason, \"error\", false);\n process.on(\"unhandledRejection\", handler);\n detach.push(() => process.off(\"unhandledRejection\", handler));\n }\n\n if (opts.captureConsoleErrors) {\n detach.push(patchConsole(\"error\", (args) => enqueueError(consoleError(args), \"error\", false)));\n }\n\n if (opts.captureConsoleWarnings) {\n detach.push(patchConsole(\"warn\", (args) => enqueueError(consoleError(args), \"warning\", false)));\n }\n\n const onBeforeExit = () => {\n void queue.flush();\n };\n process.on(\"beforeExit\", onBeforeExit);\n detach.push(() => process.off(\"beforeExit\", onBeforeExit));\n\n return {\n report(input: ReportInput) {\n const level = input.level ?? \"error\";\n if (input.error !== undefined) {\n try {\n const event = buildEvent(input.error, level, true, opts.projectKey, opts.runtime);\n if (input.message) event.message = input.message;\n queue.enqueue(event);\n } catch {\n // never let pixel break the host program\n }\n return;\n }\n const err = new Error(input.message);\n err.name = \"ManualReport\";\n enqueueError(err, level, true);\n },\n flush: () => queue.flush(),\n close: async () => {\n for (const fn of detach) fn();\n await queue.close();\n },\n };\n}\n\nfunction buildEvent(\n err: unknown,\n level: Level,\n manual: boolean,\n projectKey: string,\n runtime: string,\n): WireEvent {\n const { type, message, stackString } = normalize(err);\n const stack = parseStack(stackString);\n return {\n event_id: randomUUID(),\n project_key: projectKey,\n fingerprint: fingerprint(type, stack),\n type,\n message,\n stack,\n code_context: captureCodeContext(stack),\n runtime,\n manual_report: manual,\n level,\n occurred_at: new Date().toISOString(),\n };\n}\n\nfunction normalize(err: unknown): { type: string; message: string; stackString?: string } {\n if (err instanceof Error) {\n return { type: err.name || \"Error\", message: err.message, stackString: err.stack };\n }\n if (typeof err === \"string\") {\n return { type: \"StringError\", message: err };\n }\n try {\n return { type: \"UnknownError\", message: JSON.stringify(err) };\n } catch {\n return { type: \"UnknownError\", message: String(err) };\n }\n}\n\nfunction consoleError(args: unknown[]): unknown {\n for (const a of args) if (a instanceof Error) return a;\n return new Error(args.map(stringify).join(\" \"));\n}\n\nfunction stringify(x: unknown): string {\n if (typeof x === \"string\") return x;\n try {\n return JSON.stringify(x);\n } catch {\n return String(x);\n }\n}\n\ntype ConsoleMethod = \"error\" | \"warn\";\n\nfunction patchConsole(method: ConsoleMethod, onCall: (args: unknown[]) => void): () => void {\n const original = console[method];\n console[method] = (...args: unknown[]) => {\n try {\n onCall(args);\n } catch {\n // never let pixel break the host program\n }\n original.apply(console, args);\n };\n return () => {\n console[method] = original;\n };\n}\n","import type { StackFrame } from \"./types.js\";\n\nconst FRAME_WITH_FN = /^\\s*at\\s+(.+?)\\s+\\((.+?):(\\d+):(\\d+)\\)\\s*$/;\nconst FRAME_NO_FN = /^\\s*at\\s+(.+?):(\\d+):(\\d+)\\s*$/;\n\nexport function parseStack(stack: string | undefined): StackFrame[] {\n if (!stack) return [];\n const frames: StackFrame[] = [];\n for (const line of stack.split(\"\\n\")) {\n const withFn = FRAME_WITH_FN.exec(line);\n if (withFn) {\n const file = withFn[2];\n frames.push({\n fn: withFn[1],\n file,\n line: Number(withFn[3]),\n col: Number(withFn[4]),\n in_app: isInApp(file),\n });\n continue;\n }\n const noFn = FRAME_NO_FN.exec(line);\n if (noFn) {\n const file = noFn[1];\n frames.push({\n fn: \"<anon>\",\n file,\n line: Number(noFn[2]),\n col: Number(noFn[3]),\n in_app: isInApp(file),\n });\n }\n }\n return frames;\n}\n\nfunction isInApp(file: string): boolean {\n if (!file) return false;\n if (file.startsWith(\"node:\")) return false;\n if (file.startsWith(\"internal/\")) return false;\n if (file.includes(\"/node_modules/\")) return false;\n return true;\n}\n","import { createHash } from \"node:crypto\";\nimport type { StackFrame } from \"./types.js\";\n\nexport function fingerprint(type: string, stack: StackFrame[]): string {\n const top = stack[0];\n const normalized = top\n ? `${type}|${normalizeFile(top.file)}|${top.fn || \"<anon>\"}|${top.line}`\n : `${type}|<no-stack>`;\n return createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n}\n\nfunction normalizeFile(file: string): string {\n return file\n .replace(/^file:\\/\\//, \"\")\n .replace(/^.*\\/node_modules\\//, \"node_modules/\")\n .replace(/\\?.*$/, \"\");\n}\n","import { readFileSync, existsSync } from \"node:fs\";\nimport type { CodeContext, StackFrame } from \"./core/types.js\";\n\nconst WINDOW = 2;\nconst cache = new Map<string, string[] | null>();\n\nexport function captureCodeContext(stack: StackFrame[]): CodeContext | null {\n const top = stack.find((f) => isReadable(f.file));\n if (!top) return null;\n const lines = loadLines(top.file);\n if (!lines) return null;\n const start = Math.max(0, top.line - 1 - WINDOW);\n const end = Math.min(lines.length, top.line + WINDOW);\n return {\n file: top.file,\n error_line: top.line,\n lines: lines.slice(start, end),\n };\n}\n\nfunction isReadable(file: string): boolean {\n if (!file || file.startsWith(\"node:\")) return false;\n if (file.includes(\"/node_modules/\")) return false;\n return file.startsWith(\"/\") || file.startsWith(\"file://\");\n}\n\nfunction loadLines(file: string): string[] | null {\n const path = file.replace(/^file:\\/\\//, \"\");\n if (cache.has(path)) return cache.get(path) ?? null;\n if (!existsSync(path)) {\n cache.set(path, null);\n return null;\n }\n try {\n const lines = readFileSync(path, \"utf8\").split(\"\\n\");\n cache.set(path, lines);\n return lines;\n } catch {\n cache.set(path, null);\n return null;\n }\n}\n","import type { Sink, WireEvent } from \"./types.js\";\n\nconst MAX_BUFFER = 100;\nconst BASE_DELAY_MS = 200;\nconst MAX_DELAY_MS = 5_000;\n\nexport class EventQueue {\n private readonly buffer: WireEvent[] = [];\n private draining = false;\n private closed = false;\n\n constructor(private readonly sink: Sink) {}\n\n enqueue(event: WireEvent): void {\n if (this.closed) return;\n if (this.buffer.length >= MAX_BUFFER) {\n this.buffer.shift();\n }\n this.buffer.push(event);\n void this.drain();\n }\n\n enqueueSync(event: WireEvent): void {\n if (this.closed) return;\n if (this.sink.emitSync) {\n try {\n this.sink.emitSync(event);\n return;\n } catch {\n // fall through to async path\n }\n }\n this.enqueue(event);\n }\n\n async flush(): Promise<void> {\n while (this.buffer.length > 0 || this.draining) {\n await new Promise((r) => setTimeout(r, 10));\n }\n }\n\n async close(): Promise<void> {\n await this.flush();\n this.closed = true;\n if (this.sink.close) await this.sink.close();\n }\n\n private async drain(): Promise<void> {\n if (this.draining) return;\n this.draining = true;\n let attempt = 0;\n while (this.buffer.length > 0) {\n const event = this.buffer[0];\n try {\n await this.sink.emit(event);\n this.buffer.shift();\n attempt = 0;\n } catch {\n attempt++;\n if (attempt >= 5) {\n this.buffer.shift();\n attempt = 0;\n continue;\n }\n const delay = Math.min(BASE_DELAY_MS * 2 ** (attempt - 1), MAX_DELAY_MS);\n await new Promise((r) => setTimeout(r, delay));\n }\n }\n this.draining = false;\n }\n}\n","import type { Sink, WireEvent } from \"../types.js\";\n\nexport class HttpSink implements Sink {\n constructor(\n private readonly ingestUrl: string,\n private readonly fetchFn: typeof fetch = fetch,\n ) {}\n\n async emit(event: WireEvent): Promise<void> {\n const res = await this.fetchFn(this.ingestUrl, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-pixel-key\": event.project_key,\n },\n body: JSON.stringify(event),\n });\n if (!res.ok) {\n throw new Error(`pixel ingest failed: ${res.status}`);\n }\n }\n}\n","import { homedir } from \"node:os\";\nimport { mkdirSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport Database from \"better-sqlite3\";\nimport type { Sink, WireEvent } from \"../types.js\";\n\nconst SCHEMA = `\n CREATE TABLE IF NOT EXISTS events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n event_id TEXT NOT NULL UNIQUE,\n project_key TEXT NOT NULL,\n fingerprint TEXT NOT NULL,\n type TEXT NOT NULL,\n message TEXT NOT NULL,\n stack TEXT NOT NULL,\n code_context TEXT,\n runtime TEXT NOT NULL,\n manual_report INTEGER NOT NULL DEFAULT 0,\n level TEXT NOT NULL,\n occurred_at TEXT NOT NULL,\n ingested_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n CREATE INDEX IF NOT EXISTS events_fingerprint ON events(project_key, fingerprint);\n CREATE INDEX IF NOT EXISTS events_occurred ON events(occurred_at);\n`;\n\nexport class LocalSqliteSink implements Sink {\n private readonly db: Database.Database;\n private readonly insert: Database.Statement;\n\n constructor(path?: string) {\n const resolved = path ?? join(homedir(), \".gg\", \"errors.db\");\n mkdirSync(dirname(resolved), { recursive: true });\n this.db = new Database(resolved);\n this.db.pragma(\"journal_mode = WAL\");\n this.db.exec(SCHEMA);\n this.insert = this.db.prepare(`\n INSERT INTO events (\n event_id, project_key, fingerprint, type, message, stack, code_context,\n runtime, manual_report, level, occurred_at\n ) VALUES (\n @event_id, @project_key, @fingerprint, @type, @message, @stack, @code_context,\n @runtime, @manual_report, @level, @occurred_at\n )\n `);\n }\n\n emitSync(event: WireEvent): void {\n this.insert.run({\n event_id: event.event_id,\n project_key: event.project_key,\n fingerprint: event.fingerprint,\n type: event.type,\n message: event.message,\n stack: JSON.stringify(event.stack),\n code_context: event.code_context ? JSON.stringify(event.code_context) : null,\n runtime: event.runtime,\n manual_report: event.manual_report ? 1 : 0,\n level: event.level,\n occurred_at: event.occurred_at,\n });\n }\n\n async emit(event: WireEvent): Promise<void> {\n this.emitSync(event);\n }\n\n async close(): Promise<void> {\n this.db.close();\n }\n}\n","import { existsSync, readFileSync, writeFileSync, appendFileSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\n\nexport const DEFAULT_INGEST_URL = \"https://gg-pixel-server.buzzbeamaustralia.workers.dev\";\n\nexport interface InstallOptions {\n cwd?: string;\n ingestUrl?: string;\n projectName?: string;\n fetchFn?: typeof fetch;\n skipPackageInstall?: boolean;\n homeDir?: string;\n}\n\nexport interface InstallResult {\n projectId: string;\n projectKey: string;\n projectName: string;\n initFilePath: string;\n envFilePath: string;\n projectsJsonPath: string;\n packageManager: PackageManager;\n packageInstalled: boolean;\n}\n\nexport type PackageManager = \"pnpm\" | \"yarn\" | \"bun\" | \"npm\";\n\nexport async function install(opts: InstallOptions = {}): Promise<InstallResult> {\n const cwd = resolve(opts.cwd ?? process.cwd());\n const ingestUrl = (opts.ingestUrl ?? DEFAULT_INGEST_URL).replace(/\\/+$/, \"\");\n const fetchFn = opts.fetchFn ?? fetch;\n\n const projectRoot = findProjectRoot(cwd);\n if (!projectRoot) {\n throw new Error(`No package.json found in ${cwd} or any parent directory.`);\n }\n\n const pkgPath = join(projectRoot, \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as { name?: string };\n const projectName = opts.projectName ?? pkg.name ?? projectRoot.split(\"/\").pop() ?? \"unnamed\";\n\n const created = await createProject(fetchFn, ingestUrl, projectName);\n\n const pm = detectPackageManager(projectRoot);\n const packageInstalled = opts.skipPackageInstall\n ? false\n : runInstall(projectRoot, pm, \"@kenkaiiii/gg-pixel\");\n\n const initFilePath = join(projectRoot, \"gg-pixel.init.mjs\");\n writeFileSync(initFilePath, renderInitFile(ingestUrl), \"utf8\");\n\n const envFilePath = join(projectRoot, \".env\");\n writeEnvKey(envFilePath, \"GG_PIXEL_KEY\", created.key);\n\n const home = opts.homeDir ?? homedir();\n const projectsJsonPath = join(home, \".gg\", \"projects.json\");\n writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot);\n\n return {\n projectId: created.id,\n projectKey: created.key,\n projectName,\n initFilePath,\n envFilePath,\n projectsJsonPath,\n packageManager: pm,\n packageInstalled,\n };\n}\n\nfunction findProjectRoot(start: string): string | null {\n let dir = start;\n for (let i = 0; i < 20; i++) {\n if (existsSync(join(dir, \"package.json\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n return null;\n}\n\nasync function createProject(\n fetchFn: typeof fetch,\n ingestUrl: string,\n name: string,\n): Promise<{ id: string; key: string }> {\n const res = await fetchFn(`${ingestUrl}/api/projects`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ name }),\n });\n if (!res.ok) {\n throw new Error(`POST /api/projects failed: ${res.status} ${await safeText(res)}`);\n }\n const body = (await res.json()) as { id: string; key: string };\n if (!body.id || !body.key) throw new Error(\"response missing id/key\");\n return { id: body.id, key: body.key };\n}\n\nasync function safeText(r: Response): Promise<string> {\n try {\n return await r.text();\n } catch {\n return \"\";\n }\n}\n\nexport function detectPackageManager(projectRoot: string): PackageManager {\n if (existsSync(join(projectRoot, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(join(projectRoot, \"bun.lockb\"))) return \"bun\";\n if (existsSync(join(projectRoot, \"yarn.lock\"))) return \"yarn\";\n return \"npm\";\n}\n\nfunction runInstall(projectRoot: string, pm: PackageManager, pkg: string): boolean {\n const cmd = pm;\n const args = pm === \"npm\" ? [\"install\", pkg] : [\"add\", pkg];\n const result = spawnSync(cmd, args, { cwd: projectRoot, stdio: \"inherit\" });\n return result.status === 0;\n}\n\nexport function renderInitFile(ingestUrl: string): string {\n return `import { initPixel } from \"@kenkaiiii/gg-pixel\";\n\nconst key = process.env.GG_PIXEL_KEY;\nif (key) {\n initPixel({\n projectKey: key,\n sink: { kind: \"http\", ingestUrl: ${JSON.stringify(`${ingestUrl}/ingest`)} },\n });\n}\n`;\n}\n\nexport function writeEnvKey(envPath: string, key: string, value: string): void {\n if (existsSync(envPath)) {\n const current = readFileSync(envPath, \"utf8\");\n const lineRegex = new RegExp(`^${key}=.*$`, \"m\");\n if (lineRegex.test(current)) {\n writeFileSync(envPath, current.replace(lineRegex, `${key}=${value}`), \"utf8\");\n return;\n }\n const sep = current.endsWith(\"\\n\") || current.length === 0 ? \"\" : \"\\n\";\n appendFileSync(envPath, `${sep}${key}=${value}\\n`, \"utf8\");\n return;\n }\n writeFileSync(envPath, `${key}=${value}\\n`, \"utf8\");\n}\n\nexport function writeProjectsMapping(\n projectsJsonPath: string,\n projectId: string,\n name: string,\n path: string,\n): void {\n mkdirSync(dirname(projectsJsonPath), { recursive: true });\n let map: Record<string, { name: string; path: string }> = {};\n if (existsSync(projectsJsonPath)) {\n try {\n map = JSON.parse(readFileSync(projectsJsonPath, \"utf8\")) as typeof map;\n } catch {\n // start fresh on corrupt file\n }\n }\n map[projectId] = { name, path };\n writeFileSync(projectsJsonPath, `${JSON.stringify(map, null, 2)}\\n`, \"utf8\");\n}\n"],"mappings":"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","names":["import_node_crypto","import_node_fs","Database","import_node_fs","import_node_os","import_node_path"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/adapters/node.ts","../src/core/stack.ts","../src/core/fingerprint.ts","../src/code-context.ts","../src/core/queue.ts","../src/core/sinks/http.ts","../src/core/sinks/local-sqlite.ts","../src/install.ts"],"sourcesContent":["import { installNodeAdapter, type NodeAdapter } from \"./adapters/node.js\";\nimport { HttpSink } from \"./core/sinks/http.js\";\nimport { LocalSqliteSink } from \"./core/sinks/local-sqlite.js\";\nimport type { PixelOptions, ReportInput, Sink, SinkConfig } from \"./core/types.js\";\n\nlet active: NodeAdapter | null = null;\n\nexport function initPixel(options: PixelOptions): NodeAdapter {\n if (active) {\n throw new Error(\"gg-pixel is already initialized; call closePixel() first\");\n }\n const sink = buildSink(options.sink);\n active = installNodeAdapter({\n projectKey: options.projectKey,\n runtime: options.runtime ?? defaultRuntime(),\n sink,\n captureConsoleErrors: options.captureConsoleErrors ?? true,\n captureConsoleWarnings: options.captureConsoleWarnings ?? false,\n captureUnhandledRejections: options.captureUnhandledRejections ?? true,\n captureUncaughtExceptions: options.captureUncaughtExceptions ?? true,\n });\n return active;\n}\n\nexport function reportPixel(input: ReportInput): void {\n if (!active) return;\n active.report(input);\n}\n\nexport async function flushPixel(): Promise<void> {\n if (!active) return;\n await active.flush();\n}\n\nexport async function closePixel(): Promise<void> {\n if (!active) return;\n await active.close();\n active = null;\n}\n\nfunction buildSink(config: SinkConfig): Sink {\n switch (config.kind) {\n case \"http\":\n return new HttpSink(config.ingestUrl, config.fetchFn);\n case \"local\":\n return new LocalSqliteSink(config.path);\n case \"custom\":\n return config.sink;\n }\n}\n\nfunction defaultRuntime(): string {\n const v = process.versions.node;\n return `node-${v}`;\n}\n\nexport type {\n Level,\n PixelOptions,\n ReportInput,\n Sink,\n SinkConfig,\n StackFrame,\n CodeContext,\n WireEvent,\n} from \"./core/types.js\";\n\nexport { install, DEFAULT_INGEST_URL } from \"./install.js\";\nexport type { InstallOptions, InstallResult, PackageManager } from \"./install.js\";\n","import { randomUUID } from \"node:crypto\";\nimport { parseStack } from \"../core/stack.js\";\nimport { fingerprint } from \"../core/fingerprint.js\";\nimport { captureCodeContext } from \"../code-context.js\";\nimport { EventQueue } from \"../core/queue.js\";\nimport type { Level, ReportInput, Sink, WireEvent } from \"../core/types.js\";\n\nexport interface NodeAdapterOptions {\n projectKey: string;\n runtime: string;\n sink: Sink;\n captureConsoleErrors: boolean;\n captureConsoleWarnings: boolean;\n captureUnhandledRejections: boolean;\n captureUncaughtExceptions: boolean;\n}\n\nexport interface NodeAdapter {\n report(input: ReportInput): void;\n flush(): Promise<void>;\n close(): Promise<void>;\n}\n\nexport function installNodeAdapter(opts: NodeAdapterOptions): NodeAdapter {\n const queue = new EventQueue(opts.sink);\n const detach: Array<() => void> = [];\n\n const enqueueError = (err: unknown, level: Level, manual: boolean) => {\n try {\n const event = buildEvent(err, level, manual, opts.projectKey, opts.runtime);\n queue.enqueue(event);\n } catch {\n // never let pixel break the host program\n }\n };\n\n const enqueueErrorSync = (err: unknown, level: Level, manual: boolean) => {\n try {\n const event = buildEvent(err, level, manual, opts.projectKey, opts.runtime);\n queue.enqueueSync(event);\n } catch {\n // never let pixel break the host program\n }\n };\n\n if (opts.captureUncaughtExceptions) {\n const handler = (err: Error) => enqueueErrorSync(err, \"fatal\", false);\n process.on(\"uncaughtExceptionMonitor\", handler);\n detach.push(() => process.off(\"uncaughtExceptionMonitor\", handler));\n }\n\n if (opts.captureUnhandledRejections) {\n const handler = (reason: unknown) => enqueueErrorSync(reason, \"error\", false);\n process.on(\"unhandledRejection\", handler);\n detach.push(() => process.off(\"unhandledRejection\", handler));\n }\n\n if (opts.captureConsoleErrors) {\n detach.push(patchConsole(\"error\", (args) => enqueueError(consoleError(args), \"error\", false)));\n }\n\n if (opts.captureConsoleWarnings) {\n detach.push(patchConsole(\"warn\", (args) => enqueueError(consoleError(args), \"warning\", false)));\n }\n\n const onBeforeExit = () => {\n void queue.flush();\n };\n process.on(\"beforeExit\", onBeforeExit);\n detach.push(() => process.off(\"beforeExit\", onBeforeExit));\n\n return {\n report(input: ReportInput) {\n const level = input.level ?? \"error\";\n if (input.error !== undefined) {\n try {\n const event = buildEvent(input.error, level, true, opts.projectKey, opts.runtime);\n if (input.message) event.message = input.message;\n queue.enqueue(event);\n } catch {\n // never let pixel break the host program\n }\n return;\n }\n const err = new Error(input.message);\n err.name = \"ManualReport\";\n enqueueError(err, level, true);\n },\n flush: () => queue.flush(),\n close: async () => {\n for (const fn of detach) fn();\n await queue.close();\n },\n };\n}\n\nfunction buildEvent(\n err: unknown,\n level: Level,\n manual: boolean,\n projectKey: string,\n runtime: string,\n): WireEvent {\n const { type, message, stackString } = normalize(err);\n const stack = parseStack(stackString);\n return {\n event_id: randomUUID(),\n project_key: projectKey,\n fingerprint: fingerprint(type, stack),\n type,\n message,\n stack,\n code_context: captureCodeContext(stack),\n runtime,\n manual_report: manual,\n level,\n occurred_at: new Date().toISOString(),\n };\n}\n\nfunction normalize(err: unknown): { type: string; message: string; stackString?: string } {\n if (err instanceof Error) {\n return { type: err.name || \"Error\", message: err.message, stackString: err.stack };\n }\n if (typeof err === \"string\") {\n return { type: \"StringError\", message: err };\n }\n try {\n return { type: \"UnknownError\", message: JSON.stringify(err) };\n } catch {\n return { type: \"UnknownError\", message: String(err) };\n }\n}\n\nfunction consoleError(args: unknown[]): unknown {\n for (const a of args) if (a instanceof Error) return a;\n return new Error(args.map(stringify).join(\" \"));\n}\n\nfunction stringify(x: unknown): string {\n if (typeof x === \"string\") return x;\n try {\n return JSON.stringify(x);\n } catch {\n return String(x);\n }\n}\n\ntype ConsoleMethod = \"error\" | \"warn\";\n\nfunction patchConsole(method: ConsoleMethod, onCall: (args: unknown[]) => void): () => void {\n const original = console[method];\n console[method] = (...args: unknown[]) => {\n try {\n onCall(args);\n } catch {\n // never let pixel break the host program\n }\n original.apply(console, args);\n };\n return () => {\n console[method] = original;\n };\n}\n","import type { StackFrame } from \"./types.js\";\n\nconst FRAME_WITH_FN = /^\\s*at\\s+(.+?)\\s+\\((.+?):(\\d+):(\\d+)\\)\\s*$/;\nconst FRAME_NO_FN = /^\\s*at\\s+(.+?):(\\d+):(\\d+)\\s*$/;\n\nexport function parseStack(stack: string | undefined): StackFrame[] {\n if (!stack) return [];\n const frames: StackFrame[] = [];\n for (const line of stack.split(\"\\n\")) {\n const withFn = FRAME_WITH_FN.exec(line);\n if (withFn) {\n const file = withFn[2];\n frames.push({\n fn: withFn[1],\n file,\n line: Number(withFn[3]),\n col: Number(withFn[4]),\n in_app: isInApp(file),\n });\n continue;\n }\n const noFn = FRAME_NO_FN.exec(line);\n if (noFn) {\n const file = noFn[1];\n frames.push({\n fn: \"<anon>\",\n file,\n line: Number(noFn[2]),\n col: Number(noFn[3]),\n in_app: isInApp(file),\n });\n }\n }\n return frames;\n}\n\nfunction isInApp(file: string): boolean {\n if (!file) return false;\n if (file.startsWith(\"node:\")) return false;\n if (file.startsWith(\"internal/\")) return false;\n if (file.includes(\"/node_modules/\")) return false;\n return true;\n}\n","import { createHash } from \"node:crypto\";\nimport type { StackFrame } from \"./types.js\";\n\nexport function fingerprint(type: string, stack: StackFrame[]): string {\n const top = stack[0];\n const normalized = top\n ? `${type}|${normalizeFile(top.file)}|${top.fn || \"<anon>\"}|${top.line}`\n : `${type}|<no-stack>`;\n return createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n}\n\nfunction normalizeFile(file: string): string {\n return file\n .replace(/^file:\\/\\//, \"\")\n .replace(/^.*\\/node_modules\\//, \"node_modules/\")\n .replace(/\\?.*$/, \"\");\n}\n","import { readFileSync, existsSync } from \"node:fs\";\nimport type { CodeContext, StackFrame } from \"./core/types.js\";\n\nconst WINDOW = 2;\nconst cache = new Map<string, string[] | null>();\n\nexport function captureCodeContext(stack: StackFrame[]): CodeContext | null {\n const top = stack.find((f) => isReadable(f.file));\n if (!top) return null;\n const lines = loadLines(top.file);\n if (!lines) return null;\n const start = Math.max(0, top.line - 1 - WINDOW);\n const end = Math.min(lines.length, top.line + WINDOW);\n return {\n file: top.file,\n error_line: top.line,\n lines: lines.slice(start, end),\n };\n}\n\nfunction isReadable(file: string): boolean {\n if (!file || file.startsWith(\"node:\")) return false;\n if (file.includes(\"/node_modules/\")) return false;\n return file.startsWith(\"/\") || file.startsWith(\"file://\");\n}\n\nfunction loadLines(file: string): string[] | null {\n const path = file.replace(/^file:\\/\\//, \"\");\n if (cache.has(path)) return cache.get(path) ?? null;\n if (!existsSync(path)) {\n cache.set(path, null);\n return null;\n }\n try {\n const lines = readFileSync(path, \"utf8\").split(\"\\n\");\n cache.set(path, lines);\n return lines;\n } catch {\n cache.set(path, null);\n return null;\n }\n}\n","import type { Sink, WireEvent } from \"./types.js\";\n\nconst MAX_BUFFER = 100;\nconst BASE_DELAY_MS = 200;\nconst MAX_DELAY_MS = 5_000;\n\nexport class EventQueue {\n private readonly buffer: WireEvent[] = [];\n private draining = false;\n private closed = false;\n\n constructor(private readonly sink: Sink) {}\n\n enqueue(event: WireEvent): void {\n if (this.closed) return;\n if (this.buffer.length >= MAX_BUFFER) {\n this.buffer.shift();\n }\n this.buffer.push(event);\n void this.drain();\n }\n\n enqueueSync(event: WireEvent): void {\n if (this.closed) return;\n if (this.sink.emitSync) {\n try {\n this.sink.emitSync(event);\n return;\n } catch {\n // fall through to async path\n }\n }\n this.enqueue(event);\n }\n\n async flush(): Promise<void> {\n while (this.buffer.length > 0 || this.draining) {\n await new Promise((r) => setTimeout(r, 10));\n }\n }\n\n async close(): Promise<void> {\n await this.flush();\n this.closed = true;\n if (this.sink.close) await this.sink.close();\n }\n\n private async drain(): Promise<void> {\n if (this.draining) return;\n this.draining = true;\n let attempt = 0;\n while (this.buffer.length > 0) {\n const event = this.buffer[0];\n try {\n await this.sink.emit(event);\n this.buffer.shift();\n attempt = 0;\n } catch {\n attempt++;\n if (attempt >= 5) {\n this.buffer.shift();\n attempt = 0;\n continue;\n }\n const delay = Math.min(BASE_DELAY_MS * 2 ** (attempt - 1), MAX_DELAY_MS);\n await new Promise((r) => setTimeout(r, delay));\n }\n }\n this.draining = false;\n }\n}\n","import type { Sink, WireEvent } from \"../types.js\";\n\nexport class HttpSink implements Sink {\n constructor(\n private readonly ingestUrl: string,\n private readonly fetchFn: typeof fetch = fetch,\n ) {}\n\n async emit(event: WireEvent): Promise<void> {\n const res = await this.fetchFn(this.ingestUrl, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-pixel-key\": event.project_key,\n },\n body: JSON.stringify(event),\n });\n if (!res.ok) {\n throw new Error(`pixel ingest failed: ${res.status}`);\n }\n }\n}\n","import { homedir } from \"node:os\";\nimport { mkdirSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport Database from \"better-sqlite3\";\nimport type { Sink, WireEvent } from \"../types.js\";\n\nconst SCHEMA = `\n CREATE TABLE IF NOT EXISTS events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n event_id TEXT NOT NULL UNIQUE,\n project_key TEXT NOT NULL,\n fingerprint TEXT NOT NULL,\n type TEXT NOT NULL,\n message TEXT NOT NULL,\n stack TEXT NOT NULL,\n code_context TEXT,\n runtime TEXT NOT NULL,\n manual_report INTEGER NOT NULL DEFAULT 0,\n level TEXT NOT NULL,\n occurred_at TEXT NOT NULL,\n ingested_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n CREATE INDEX IF NOT EXISTS events_fingerprint ON events(project_key, fingerprint);\n CREATE INDEX IF NOT EXISTS events_occurred ON events(occurred_at);\n`;\n\nexport class LocalSqliteSink implements Sink {\n private readonly db: Database.Database;\n private readonly insert: Database.Statement;\n\n constructor(path?: string) {\n const resolved = path ?? join(homedir(), \".gg\", \"errors.db\");\n mkdirSync(dirname(resolved), { recursive: true });\n this.db = new Database(resolved);\n this.db.pragma(\"journal_mode = WAL\");\n this.db.exec(SCHEMA);\n this.insert = this.db.prepare(`\n INSERT INTO events (\n event_id, project_key, fingerprint, type, message, stack, code_context,\n runtime, manual_report, level, occurred_at\n ) VALUES (\n @event_id, @project_key, @fingerprint, @type, @message, @stack, @code_context,\n @runtime, @manual_report, @level, @occurred_at\n )\n `);\n }\n\n emitSync(event: WireEvent): void {\n this.insert.run({\n event_id: event.event_id,\n project_key: event.project_key,\n fingerprint: event.fingerprint,\n type: event.type,\n message: event.message,\n stack: JSON.stringify(event.stack),\n code_context: event.code_context ? JSON.stringify(event.code_context) : null,\n runtime: event.runtime,\n manual_report: event.manual_report ? 1 : 0,\n level: event.level,\n occurred_at: event.occurred_at,\n });\n }\n\n async emit(event: WireEvent): Promise<void> {\n this.emitSync(event);\n }\n\n async close(): Promise<void> {\n this.db.close();\n }\n}\n","import { existsSync, readFileSync, writeFileSync, appendFileSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\n\nexport const DEFAULT_INGEST_URL = \"https://gg-pixel-server.buzzbeamaustralia.workers.dev\";\n\nexport interface InstallOptions {\n cwd?: string;\n ingestUrl?: string;\n projectName?: string;\n fetchFn?: typeof fetch;\n skipPackageInstall?: boolean;\n homeDir?: string;\n}\n\nexport interface InstallResult {\n projectId: string;\n projectKey: string;\n projectName: string;\n initFilePath: string;\n envFilePath: string;\n projectsJsonPath: string;\n packageManager: PackageManager;\n packageInstalled: boolean;\n entryWiring: EntryWiringResult;\n}\n\nexport type EntryWiringResult =\n | { kind: \"injected\"; entryPath: string }\n | { kind: \"already_present\"; entryPath: string }\n | { kind: \"no_entry_found\" }\n | { kind: \"skipped\"; reason: string };\n\ninterface PackageJson {\n name?: string;\n type?: string;\n main?: string;\n module?: string;\n bin?: string | Record<string, string>;\n}\n\nexport type PackageManager = \"pnpm\" | \"yarn\" | \"bun\" | \"npm\";\n\nexport async function install(opts: InstallOptions = {}): Promise<InstallResult> {\n const cwd = resolve(opts.cwd ?? process.cwd());\n const ingestUrl = (opts.ingestUrl ?? DEFAULT_INGEST_URL).replace(/\\/+$/, \"\");\n const fetchFn = opts.fetchFn ?? fetch;\n\n const projectRoot = findProjectRoot(cwd);\n if (!projectRoot) {\n throw new Error(`No package.json found in ${cwd} or any parent directory.`);\n }\n\n const pkgPath = join(projectRoot, \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as PackageJson;\n const projectName = opts.projectName ?? pkg.name ?? projectRoot.split(\"/\").pop() ?? \"unnamed\";\n\n const created = await createProject(fetchFn, ingestUrl, projectName);\n\n const pm = detectPackageManager(projectRoot);\n const packageInstalled = opts.skipPackageInstall\n ? false\n : runInstall(projectRoot, pm, \"@kenkaiiii/gg-pixel\");\n\n const initFilePath = join(projectRoot, \"gg-pixel.init.mjs\");\n writeFileSync(initFilePath, renderInitFile(ingestUrl), \"utf8\");\n\n const envFilePath = join(projectRoot, \".env\");\n writeEnvKey(envFilePath, \"GG_PIXEL_KEY\", created.key);\n\n const home = opts.homeDir ?? homedir();\n const projectsJsonPath = join(home, \".gg\", \"projects.json\");\n writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot);\n\n const entryWiring = wireEntryFile(projectRoot, initFilePath, pkg);\n\n return {\n projectId: created.id,\n projectKey: created.key,\n projectName,\n initFilePath,\n envFilePath,\n projectsJsonPath,\n packageManager: pm,\n packageInstalled,\n entryWiring,\n };\n}\n\nfunction findProjectRoot(start: string): string | null {\n let dir = start;\n for (let i = 0; i < 20; i++) {\n if (existsSync(join(dir, \"package.json\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n return null;\n}\n\nasync function createProject(\n fetchFn: typeof fetch,\n ingestUrl: string,\n name: string,\n): Promise<{ id: string; key: string }> {\n const res = await fetchFn(`${ingestUrl}/api/projects`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ name }),\n });\n if (!res.ok) {\n throw new Error(`POST /api/projects failed: ${res.status} ${await safeText(res)}`);\n }\n const body = (await res.json()) as { id: string; key: string };\n if (!body.id || !body.key) throw new Error(\"response missing id/key\");\n return { id: body.id, key: body.key };\n}\n\nasync function safeText(r: Response): Promise<string> {\n try {\n return await r.text();\n } catch {\n return \"\";\n }\n}\n\nexport function detectPackageManager(projectRoot: string): PackageManager {\n if (existsSync(join(projectRoot, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(join(projectRoot, \"bun.lockb\"))) return \"bun\";\n if (existsSync(join(projectRoot, \"yarn.lock\"))) return \"yarn\";\n return \"npm\";\n}\n\nfunction runInstall(projectRoot: string, pm: PackageManager, pkg: string): boolean {\n const cmd = pm;\n // npm prints `npm audit` warnings + `npm fund` solicitations on every install.\n // That output is about the user's *existing* project — irrelevant to pixel.\n // The other package managers don't show this noise by default.\n const args = pm === \"npm\" ? [\"install\", pkg, \"--no-audit\", \"--no-fund\"] : [\"add\", pkg];\n const result = spawnSync(cmd, args, { cwd: projectRoot, stdio: \"inherit\" });\n return result.status === 0;\n}\n\nexport function renderInitFile(ingestUrl: string): string {\n return `import { initPixel } from \"@kenkaiiii/gg-pixel\";\n\nconst key = process.env.GG_PIXEL_KEY;\nif (key) {\n initPixel({\n projectKey: key,\n sink: { kind: \"http\", ingestUrl: ${JSON.stringify(`${ingestUrl}/ingest`)} },\n });\n}\n`;\n}\n\nexport function writeEnvKey(envPath: string, key: string, value: string): void {\n if (existsSync(envPath)) {\n const current = readFileSync(envPath, \"utf8\");\n const lineRegex = new RegExp(`^${key}=.*$`, \"m\");\n if (lineRegex.test(current)) {\n writeFileSync(envPath, current.replace(lineRegex, `${key}=${value}`), \"utf8\");\n return;\n }\n const sep = current.endsWith(\"\\n\") || current.length === 0 ? \"\" : \"\\n\";\n appendFileSync(envPath, `${sep}${key}=${value}\\n`, \"utf8\");\n return;\n }\n writeFileSync(envPath, `${key}=${value}\\n`, \"utf8\");\n}\n\nexport function wireEntryFile(\n projectRoot: string,\n initFilePath: string,\n pkg: PackageJson,\n): EntryWiringResult {\n const entryPath = findEntryFile(projectRoot, pkg);\n if (!entryPath) return { kind: \"no_entry_found\" };\n\n let content: string;\n try {\n content = readFileSync(entryPath, \"utf8\");\n } catch (err) {\n return { kind: \"skipped\", reason: `unreadable: ${(err as Error).message}` };\n }\n\n if (content.includes(\"gg-pixel.init\")) {\n return { kind: \"already_present\", entryPath };\n }\n\n // Compute import specifier relative to the entry file.\n const fromDir = dirname(entryPath);\n let spec = relative(fromDir, initFilePath).split(sep).join(\"/\");\n if (!spec.startsWith(\".\")) spec = \"./\" + spec;\n\n const isCjs = isCommonJsEntry(entryPath, pkg);\n const importLine = isCjs\n ? `require(${JSON.stringify(spec)});`\n : `import ${JSON.stringify(spec)};`;\n\n // Inject at the top — after a shebang line and any leading \"use strict\",\n // but before all other code, so pixel hooks run before anything else.\n const lines = content.split(\"\\n\");\n let insertAt = 0;\n if (lines[0]?.startsWith(\"#!\")) insertAt = 1;\n while (\n insertAt < lines.length &&\n /^\\s*(?:[\"']use strict[\"']|\\/\\/|\\/\\*)/.test(lines[insertAt] ?? \"\")\n ) {\n insertAt++;\n }\n\n const updated = [...lines.slice(0, insertAt), importLine, ...lines.slice(insertAt)].join(\"\\n\");\n writeFileSync(entryPath, updated, \"utf8\");\n return { kind: \"injected\", entryPath };\n}\n\nfunction findEntryFile(projectRoot: string, pkg: PackageJson): string | null {\n const tryPath = (rel: string): string | null => {\n const p = join(projectRoot, rel);\n if (existsSync(p)) return p;\n // If user pointed `main` at .js but only the .ts source exists (common in TS projects).\n if (rel.endsWith(\".js\")) {\n const ts = join(projectRoot, rel.replace(/\\.js$/, \".ts\"));\n if (existsSync(ts)) return ts;\n }\n return null;\n };\n\n if (typeof pkg.bin === \"string\") {\n const found = tryPath(pkg.bin);\n if (found) return found;\n }\n if (pkg.bin && typeof pkg.bin === \"object\") {\n for (const value of Object.values(pkg.bin)) {\n if (typeof value === \"string\") {\n const found = tryPath(value);\n if (found) return found;\n }\n }\n }\n if (pkg.main) {\n const found = tryPath(pkg.main);\n if (found) return found;\n }\n if (pkg.module) {\n const found = tryPath(pkg.module);\n if (found) return found;\n }\n\n // Fall back to common conventions.\n const candidates = [\n \"src/index.ts\",\n \"src/index.tsx\",\n \"src/index.js\",\n \"src/index.mjs\",\n \"src/main.ts\",\n \"src/main.tsx\",\n \"src/main.js\",\n \"src/server.ts\",\n \"src/server.js\",\n \"src/app.ts\",\n \"src/app.js\",\n \"src/cli.ts\",\n \"src/cli.js\",\n \"index.ts\",\n \"index.tsx\",\n \"index.js\",\n \"index.mjs\",\n \"main.ts\",\n \"main.js\",\n \"server.ts\",\n \"server.js\",\n \"app.ts\",\n \"app.js\",\n ];\n for (const c of candidates) {\n const found = tryPath(c);\n if (found) return found;\n }\n return null;\n}\n\nfunction isCommonJsEntry(entryPath: string, pkg: PackageJson): boolean {\n if (entryPath.endsWith(\".cjs\")) return true;\n if (entryPath.endsWith(\".mjs\")) return false;\n if (entryPath.endsWith(\".ts\") || entryPath.endsWith(\".tsx\")) return false;\n // .js → governed by package.json type (default is \"commonjs\")\n return pkg.type !== \"module\";\n}\n\nexport function writeProjectsMapping(\n projectsJsonPath: string,\n projectId: string,\n name: string,\n path: string,\n): void {\n mkdirSync(dirname(projectsJsonPath), { recursive: true });\n let map: Record<string, { name: string; path: string }> = {};\n if (existsSync(projectsJsonPath)) {\n try {\n map = JSON.parse(readFileSync(projectsJsonPath, \"utf8\")) as typeof map;\n } catch {\n // start fresh on corrupt file\n }\n }\n map[projectId] = { name, path };\n writeFileSync(projectsJsonPath, `${JSON.stringify(map, null, 2)}\\n`, \"utf8\");\n}\n"],"mappings":"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","names":["import_node_crypto","import_node_fs","Database","import_node_fs","import_node_os","import_node_path","sep"]}
package/dist/index.d.cts CHANGED
@@ -80,7 +80,20 @@ interface InstallResult {
80
80
  projectsJsonPath: string;
81
81
  packageManager: PackageManager;
82
82
  packageInstalled: boolean;
83
+ entryWiring: EntryWiringResult;
83
84
  }
85
+ type EntryWiringResult = {
86
+ kind: "injected";
87
+ entryPath: string;
88
+ } | {
89
+ kind: "already_present";
90
+ entryPath: string;
91
+ } | {
92
+ kind: "no_entry_found";
93
+ } | {
94
+ kind: "skipped";
95
+ reason: string;
96
+ };
84
97
  type PackageManager = "pnpm" | "yarn" | "bun" | "npm";
85
98
  declare function install(opts?: InstallOptions): Promise<InstallResult>;
86
99
 
package/dist/index.d.ts CHANGED
@@ -80,7 +80,20 @@ interface InstallResult {
80
80
  projectsJsonPath: string;
81
81
  packageManager: PackageManager;
82
82
  packageInstalled: boolean;
83
+ entryWiring: EntryWiringResult;
83
84
  }
85
+ type EntryWiringResult = {
86
+ kind: "injected";
87
+ entryPath: string;
88
+ } | {
89
+ kind: "already_present";
90
+ entryPath: string;
91
+ } | {
92
+ kind: "no_entry_found";
93
+ } | {
94
+ kind: "skipped";
95
+ reason: string;
96
+ };
84
97
  type PackageManager = "pnpm" | "yarn" | "bun" | "npm";
85
98
  declare function install(opts?: InstallOptions): Promise<InstallResult>;
86
99
 
package/dist/index.js CHANGED
@@ -365,7 +365,7 @@ var LocalSqliteSink = class {
365
365
  // src/install.ts
366
366
  import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync, appendFileSync, mkdirSync as mkdirSync2 } from "fs";
367
367
  import { homedir as homedir2 } from "os";
368
- import { dirname as dirname2, join as join2, resolve } from "path";
368
+ import { dirname as dirname2, join as join2, relative, resolve, sep } from "path";
369
369
  import { spawnSync } from "child_process";
370
370
  var DEFAULT_INGEST_URL = "https://gg-pixel-server.buzzbeamaustralia.workers.dev";
371
371
  async function install(opts = {}) {
@@ -389,6 +389,7 @@ async function install(opts = {}) {
389
389
  const home = opts.homeDir ?? homedir2();
390
390
  const projectsJsonPath = join2(home, ".gg", "projects.json");
391
391
  writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot);
392
+ const entryWiring = wireEntryFile(projectRoot, initFilePath, pkg);
392
393
  return {
393
394
  projectId: created.id,
394
395
  projectKey: created.key,
@@ -397,7 +398,8 @@ async function install(opts = {}) {
397
398
  envFilePath,
398
399
  projectsJsonPath,
399
400
  packageManager: pm,
400
- packageInstalled
401
+ packageInstalled,
402
+ entryWiring
401
403
  };
402
404
  }
403
405
  function findProjectRoot(start) {
@@ -438,7 +440,7 @@ function detectPackageManager(projectRoot) {
438
440
  }
439
441
  function runInstall(projectRoot, pm, pkg) {
440
442
  const cmd = pm;
441
- const args = pm === "npm" ? ["install", pkg] : ["add", pkg];
443
+ const args = pm === "npm" ? ["install", pkg, "--no-audit", "--no-fund"] : ["add", pkg];
442
444
  const result = spawnSync(cmd, args, { cwd: projectRoot, stdio: "inherit" });
443
445
  return result.status === 0;
444
446
  }
@@ -462,14 +464,108 @@ function writeEnvKey(envPath, key, value) {
462
464
  writeFileSync(envPath, current.replace(lineRegex, `${key}=${value}`), "utf8");
463
465
  return;
464
466
  }
465
- const sep = current.endsWith("\n") || current.length === 0 ? "" : "\n";
466
- appendFileSync(envPath, `${sep}${key}=${value}
467
+ const sep2 = current.endsWith("\n") || current.length === 0 ? "" : "\n";
468
+ appendFileSync(envPath, `${sep2}${key}=${value}
467
469
  `, "utf8");
468
470
  return;
469
471
  }
470
472
  writeFileSync(envPath, `${key}=${value}
471
473
  `, "utf8");
472
474
  }
475
+ function wireEntryFile(projectRoot, initFilePath, pkg) {
476
+ const entryPath = findEntryFile(projectRoot, pkg);
477
+ if (!entryPath) return { kind: "no_entry_found" };
478
+ let content;
479
+ try {
480
+ content = readFileSync2(entryPath, "utf8");
481
+ } catch (err) {
482
+ return { kind: "skipped", reason: `unreadable: ${err.message}` };
483
+ }
484
+ if (content.includes("gg-pixel.init")) {
485
+ return { kind: "already_present", entryPath };
486
+ }
487
+ const fromDir = dirname2(entryPath);
488
+ let spec = relative(fromDir, initFilePath).split(sep).join("/");
489
+ if (!spec.startsWith(".")) spec = "./" + spec;
490
+ const isCjs = isCommonJsEntry(entryPath, pkg);
491
+ const importLine = isCjs ? `require(${JSON.stringify(spec)});` : `import ${JSON.stringify(spec)};`;
492
+ const lines = content.split("\n");
493
+ let insertAt = 0;
494
+ if (lines[0]?.startsWith("#!")) insertAt = 1;
495
+ while (insertAt < lines.length && /^\s*(?:["']use strict["']|\/\/|\/\*)/.test(lines[insertAt] ?? "")) {
496
+ insertAt++;
497
+ }
498
+ const updated = [...lines.slice(0, insertAt), importLine, ...lines.slice(insertAt)].join("\n");
499
+ writeFileSync(entryPath, updated, "utf8");
500
+ return { kind: "injected", entryPath };
501
+ }
502
+ function findEntryFile(projectRoot, pkg) {
503
+ const tryPath = (rel) => {
504
+ const p = join2(projectRoot, rel);
505
+ if (existsSync2(p)) return p;
506
+ if (rel.endsWith(".js")) {
507
+ const ts = join2(projectRoot, rel.replace(/\.js$/, ".ts"));
508
+ if (existsSync2(ts)) return ts;
509
+ }
510
+ return null;
511
+ };
512
+ if (typeof pkg.bin === "string") {
513
+ const found = tryPath(pkg.bin);
514
+ if (found) return found;
515
+ }
516
+ if (pkg.bin && typeof pkg.bin === "object") {
517
+ for (const value of Object.values(pkg.bin)) {
518
+ if (typeof value === "string") {
519
+ const found = tryPath(value);
520
+ if (found) return found;
521
+ }
522
+ }
523
+ }
524
+ if (pkg.main) {
525
+ const found = tryPath(pkg.main);
526
+ if (found) return found;
527
+ }
528
+ if (pkg.module) {
529
+ const found = tryPath(pkg.module);
530
+ if (found) return found;
531
+ }
532
+ const candidates = [
533
+ "src/index.ts",
534
+ "src/index.tsx",
535
+ "src/index.js",
536
+ "src/index.mjs",
537
+ "src/main.ts",
538
+ "src/main.tsx",
539
+ "src/main.js",
540
+ "src/server.ts",
541
+ "src/server.js",
542
+ "src/app.ts",
543
+ "src/app.js",
544
+ "src/cli.ts",
545
+ "src/cli.js",
546
+ "index.ts",
547
+ "index.tsx",
548
+ "index.js",
549
+ "index.mjs",
550
+ "main.ts",
551
+ "main.js",
552
+ "server.ts",
553
+ "server.js",
554
+ "app.ts",
555
+ "app.js"
556
+ ];
557
+ for (const c of candidates) {
558
+ const found = tryPath(c);
559
+ if (found) return found;
560
+ }
561
+ return null;
562
+ }
563
+ function isCommonJsEntry(entryPath, pkg) {
564
+ if (entryPath.endsWith(".cjs")) return true;
565
+ if (entryPath.endsWith(".mjs")) return false;
566
+ if (entryPath.endsWith(".ts") || entryPath.endsWith(".tsx")) return false;
567
+ return pkg.type !== "module";
568
+ }
473
569
  function writeProjectsMapping(projectsJsonPath, projectId, name, path) {
474
570
  mkdirSync2(dirname2(projectsJsonPath), { recursive: true });
475
571
  let map = {};
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapters/node.ts","../src/core/stack.ts","../src/core/fingerprint.ts","../src/code-context.ts","../src/core/queue.ts","../src/core/sinks/http.ts","../src/core/sinks/local-sqlite.ts","../src/install.ts","../src/index.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { parseStack } from \"../core/stack.js\";\nimport { fingerprint } from \"../core/fingerprint.js\";\nimport { captureCodeContext } from \"../code-context.js\";\nimport { EventQueue } from \"../core/queue.js\";\nimport type { Level, ReportInput, Sink, WireEvent } from \"../core/types.js\";\n\nexport interface NodeAdapterOptions {\n projectKey: string;\n runtime: string;\n sink: Sink;\n captureConsoleErrors: boolean;\n captureConsoleWarnings: boolean;\n captureUnhandledRejections: boolean;\n captureUncaughtExceptions: boolean;\n}\n\nexport interface NodeAdapter {\n report(input: ReportInput): void;\n flush(): Promise<void>;\n close(): Promise<void>;\n}\n\nexport function installNodeAdapter(opts: NodeAdapterOptions): NodeAdapter {\n const queue = new EventQueue(opts.sink);\n const detach: Array<() => void> = [];\n\n const enqueueError = (err: unknown, level: Level, manual: boolean) => {\n try {\n const event = buildEvent(err, level, manual, opts.projectKey, opts.runtime);\n queue.enqueue(event);\n } catch {\n // never let pixel break the host program\n }\n };\n\n const enqueueErrorSync = (err: unknown, level: Level, manual: boolean) => {\n try {\n const event = buildEvent(err, level, manual, opts.projectKey, opts.runtime);\n queue.enqueueSync(event);\n } catch {\n // never let pixel break the host program\n }\n };\n\n if (opts.captureUncaughtExceptions) {\n const handler = (err: Error) => enqueueErrorSync(err, \"fatal\", false);\n process.on(\"uncaughtExceptionMonitor\", handler);\n detach.push(() => process.off(\"uncaughtExceptionMonitor\", handler));\n }\n\n if (opts.captureUnhandledRejections) {\n const handler = (reason: unknown) => enqueueErrorSync(reason, \"error\", false);\n process.on(\"unhandledRejection\", handler);\n detach.push(() => process.off(\"unhandledRejection\", handler));\n }\n\n if (opts.captureConsoleErrors) {\n detach.push(patchConsole(\"error\", (args) => enqueueError(consoleError(args), \"error\", false)));\n }\n\n if (opts.captureConsoleWarnings) {\n detach.push(patchConsole(\"warn\", (args) => enqueueError(consoleError(args), \"warning\", false)));\n }\n\n const onBeforeExit = () => {\n void queue.flush();\n };\n process.on(\"beforeExit\", onBeforeExit);\n detach.push(() => process.off(\"beforeExit\", onBeforeExit));\n\n return {\n report(input: ReportInput) {\n const level = input.level ?? \"error\";\n if (input.error !== undefined) {\n try {\n const event = buildEvent(input.error, level, true, opts.projectKey, opts.runtime);\n if (input.message) event.message = input.message;\n queue.enqueue(event);\n } catch {\n // never let pixel break the host program\n }\n return;\n }\n const err = new Error(input.message);\n err.name = \"ManualReport\";\n enqueueError(err, level, true);\n },\n flush: () => queue.flush(),\n close: async () => {\n for (const fn of detach) fn();\n await queue.close();\n },\n };\n}\n\nfunction buildEvent(\n err: unknown,\n level: Level,\n manual: boolean,\n projectKey: string,\n runtime: string,\n): WireEvent {\n const { type, message, stackString } = normalize(err);\n const stack = parseStack(stackString);\n return {\n event_id: randomUUID(),\n project_key: projectKey,\n fingerprint: fingerprint(type, stack),\n type,\n message,\n stack,\n code_context: captureCodeContext(stack),\n runtime,\n manual_report: manual,\n level,\n occurred_at: new Date().toISOString(),\n };\n}\n\nfunction normalize(err: unknown): { type: string; message: string; stackString?: string } {\n if (err instanceof Error) {\n return { type: err.name || \"Error\", message: err.message, stackString: err.stack };\n }\n if (typeof err === \"string\") {\n return { type: \"StringError\", message: err };\n }\n try {\n return { type: \"UnknownError\", message: JSON.stringify(err) };\n } catch {\n return { type: \"UnknownError\", message: String(err) };\n }\n}\n\nfunction consoleError(args: unknown[]): unknown {\n for (const a of args) if (a instanceof Error) return a;\n return new Error(args.map(stringify).join(\" \"));\n}\n\nfunction stringify(x: unknown): string {\n if (typeof x === \"string\") return x;\n try {\n return JSON.stringify(x);\n } catch {\n return String(x);\n }\n}\n\ntype ConsoleMethod = \"error\" | \"warn\";\n\nfunction patchConsole(method: ConsoleMethod, onCall: (args: unknown[]) => void): () => void {\n const original = console[method];\n console[method] = (...args: unknown[]) => {\n try {\n onCall(args);\n } catch {\n // never let pixel break the host program\n }\n original.apply(console, args);\n };\n return () => {\n console[method] = original;\n };\n}\n","import type { StackFrame } from \"./types.js\";\n\nconst FRAME_WITH_FN = /^\\s*at\\s+(.+?)\\s+\\((.+?):(\\d+):(\\d+)\\)\\s*$/;\nconst FRAME_NO_FN = /^\\s*at\\s+(.+?):(\\d+):(\\d+)\\s*$/;\n\nexport function parseStack(stack: string | undefined): StackFrame[] {\n if (!stack) return [];\n const frames: StackFrame[] = [];\n for (const line of stack.split(\"\\n\")) {\n const withFn = FRAME_WITH_FN.exec(line);\n if (withFn) {\n const file = withFn[2];\n frames.push({\n fn: withFn[1],\n file,\n line: Number(withFn[3]),\n col: Number(withFn[4]),\n in_app: isInApp(file),\n });\n continue;\n }\n const noFn = FRAME_NO_FN.exec(line);\n if (noFn) {\n const file = noFn[1];\n frames.push({\n fn: \"<anon>\",\n file,\n line: Number(noFn[2]),\n col: Number(noFn[3]),\n in_app: isInApp(file),\n });\n }\n }\n return frames;\n}\n\nfunction isInApp(file: string): boolean {\n if (!file) return false;\n if (file.startsWith(\"node:\")) return false;\n if (file.startsWith(\"internal/\")) return false;\n if (file.includes(\"/node_modules/\")) return false;\n return true;\n}\n","import { createHash } from \"node:crypto\";\nimport type { StackFrame } from \"./types.js\";\n\nexport function fingerprint(type: string, stack: StackFrame[]): string {\n const top = stack[0];\n const normalized = top\n ? `${type}|${normalizeFile(top.file)}|${top.fn || \"<anon>\"}|${top.line}`\n : `${type}|<no-stack>`;\n return createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n}\n\nfunction normalizeFile(file: string): string {\n return file\n .replace(/^file:\\/\\//, \"\")\n .replace(/^.*\\/node_modules\\//, \"node_modules/\")\n .replace(/\\?.*$/, \"\");\n}\n","import { readFileSync, existsSync } from \"node:fs\";\nimport type { CodeContext, StackFrame } from \"./core/types.js\";\n\nconst WINDOW = 2;\nconst cache = new Map<string, string[] | null>();\n\nexport function captureCodeContext(stack: StackFrame[]): CodeContext | null {\n const top = stack.find((f) => isReadable(f.file));\n if (!top) return null;\n const lines = loadLines(top.file);\n if (!lines) return null;\n const start = Math.max(0, top.line - 1 - WINDOW);\n const end = Math.min(lines.length, top.line + WINDOW);\n return {\n file: top.file,\n error_line: top.line,\n lines: lines.slice(start, end),\n };\n}\n\nfunction isReadable(file: string): boolean {\n if (!file || file.startsWith(\"node:\")) return false;\n if (file.includes(\"/node_modules/\")) return false;\n return file.startsWith(\"/\") || file.startsWith(\"file://\");\n}\n\nfunction loadLines(file: string): string[] | null {\n const path = file.replace(/^file:\\/\\//, \"\");\n if (cache.has(path)) return cache.get(path) ?? null;\n if (!existsSync(path)) {\n cache.set(path, null);\n return null;\n }\n try {\n const lines = readFileSync(path, \"utf8\").split(\"\\n\");\n cache.set(path, lines);\n return lines;\n } catch {\n cache.set(path, null);\n return null;\n }\n}\n","import type { Sink, WireEvent } from \"./types.js\";\n\nconst MAX_BUFFER = 100;\nconst BASE_DELAY_MS = 200;\nconst MAX_DELAY_MS = 5_000;\n\nexport class EventQueue {\n private readonly buffer: WireEvent[] = [];\n private draining = false;\n private closed = false;\n\n constructor(private readonly sink: Sink) {}\n\n enqueue(event: WireEvent): void {\n if (this.closed) return;\n if (this.buffer.length >= MAX_BUFFER) {\n this.buffer.shift();\n }\n this.buffer.push(event);\n void this.drain();\n }\n\n enqueueSync(event: WireEvent): void {\n if (this.closed) return;\n if (this.sink.emitSync) {\n try {\n this.sink.emitSync(event);\n return;\n } catch {\n // fall through to async path\n }\n }\n this.enqueue(event);\n }\n\n async flush(): Promise<void> {\n while (this.buffer.length > 0 || this.draining) {\n await new Promise((r) => setTimeout(r, 10));\n }\n }\n\n async close(): Promise<void> {\n await this.flush();\n this.closed = true;\n if (this.sink.close) await this.sink.close();\n }\n\n private async drain(): Promise<void> {\n if (this.draining) return;\n this.draining = true;\n let attempt = 0;\n while (this.buffer.length > 0) {\n const event = this.buffer[0];\n try {\n await this.sink.emit(event);\n this.buffer.shift();\n attempt = 0;\n } catch {\n attempt++;\n if (attempt >= 5) {\n this.buffer.shift();\n attempt = 0;\n continue;\n }\n const delay = Math.min(BASE_DELAY_MS * 2 ** (attempt - 1), MAX_DELAY_MS);\n await new Promise((r) => setTimeout(r, delay));\n }\n }\n this.draining = false;\n }\n}\n","import type { Sink, WireEvent } from \"../types.js\";\n\nexport class HttpSink implements Sink {\n constructor(\n private readonly ingestUrl: string,\n private readonly fetchFn: typeof fetch = fetch,\n ) {}\n\n async emit(event: WireEvent): Promise<void> {\n const res = await this.fetchFn(this.ingestUrl, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-pixel-key\": event.project_key,\n },\n body: JSON.stringify(event),\n });\n if (!res.ok) {\n throw new Error(`pixel ingest failed: ${res.status}`);\n }\n }\n}\n","import { homedir } from \"node:os\";\nimport { mkdirSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport Database from \"better-sqlite3\";\nimport type { Sink, WireEvent } from \"../types.js\";\n\nconst SCHEMA = `\n CREATE TABLE IF NOT EXISTS events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n event_id TEXT NOT NULL UNIQUE,\n project_key TEXT NOT NULL,\n fingerprint TEXT NOT NULL,\n type TEXT NOT NULL,\n message TEXT NOT NULL,\n stack TEXT NOT NULL,\n code_context TEXT,\n runtime TEXT NOT NULL,\n manual_report INTEGER NOT NULL DEFAULT 0,\n level TEXT NOT NULL,\n occurred_at TEXT NOT NULL,\n ingested_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n CREATE INDEX IF NOT EXISTS events_fingerprint ON events(project_key, fingerprint);\n CREATE INDEX IF NOT EXISTS events_occurred ON events(occurred_at);\n`;\n\nexport class LocalSqliteSink implements Sink {\n private readonly db: Database.Database;\n private readonly insert: Database.Statement;\n\n constructor(path?: string) {\n const resolved = path ?? join(homedir(), \".gg\", \"errors.db\");\n mkdirSync(dirname(resolved), { recursive: true });\n this.db = new Database(resolved);\n this.db.pragma(\"journal_mode = WAL\");\n this.db.exec(SCHEMA);\n this.insert = this.db.prepare(`\n INSERT INTO events (\n event_id, project_key, fingerprint, type, message, stack, code_context,\n runtime, manual_report, level, occurred_at\n ) VALUES (\n @event_id, @project_key, @fingerprint, @type, @message, @stack, @code_context,\n @runtime, @manual_report, @level, @occurred_at\n )\n `);\n }\n\n emitSync(event: WireEvent): void {\n this.insert.run({\n event_id: event.event_id,\n project_key: event.project_key,\n fingerprint: event.fingerprint,\n type: event.type,\n message: event.message,\n stack: JSON.stringify(event.stack),\n code_context: event.code_context ? JSON.stringify(event.code_context) : null,\n runtime: event.runtime,\n manual_report: event.manual_report ? 1 : 0,\n level: event.level,\n occurred_at: event.occurred_at,\n });\n }\n\n async emit(event: WireEvent): Promise<void> {\n this.emitSync(event);\n }\n\n async close(): Promise<void> {\n this.db.close();\n }\n}\n","import { existsSync, readFileSync, writeFileSync, appendFileSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\n\nexport const DEFAULT_INGEST_URL = \"https://gg-pixel-server.buzzbeamaustralia.workers.dev\";\n\nexport interface InstallOptions {\n cwd?: string;\n ingestUrl?: string;\n projectName?: string;\n fetchFn?: typeof fetch;\n skipPackageInstall?: boolean;\n homeDir?: string;\n}\n\nexport interface InstallResult {\n projectId: string;\n projectKey: string;\n projectName: string;\n initFilePath: string;\n envFilePath: string;\n projectsJsonPath: string;\n packageManager: PackageManager;\n packageInstalled: boolean;\n}\n\nexport type PackageManager = \"pnpm\" | \"yarn\" | \"bun\" | \"npm\";\n\nexport async function install(opts: InstallOptions = {}): Promise<InstallResult> {\n const cwd = resolve(opts.cwd ?? process.cwd());\n const ingestUrl = (opts.ingestUrl ?? DEFAULT_INGEST_URL).replace(/\\/+$/, \"\");\n const fetchFn = opts.fetchFn ?? fetch;\n\n const projectRoot = findProjectRoot(cwd);\n if (!projectRoot) {\n throw new Error(`No package.json found in ${cwd} or any parent directory.`);\n }\n\n const pkgPath = join(projectRoot, \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as { name?: string };\n const projectName = opts.projectName ?? pkg.name ?? projectRoot.split(\"/\").pop() ?? \"unnamed\";\n\n const created = await createProject(fetchFn, ingestUrl, projectName);\n\n const pm = detectPackageManager(projectRoot);\n const packageInstalled = opts.skipPackageInstall\n ? false\n : runInstall(projectRoot, pm, \"@kenkaiiii/gg-pixel\");\n\n const initFilePath = join(projectRoot, \"gg-pixel.init.mjs\");\n writeFileSync(initFilePath, renderInitFile(ingestUrl), \"utf8\");\n\n const envFilePath = join(projectRoot, \".env\");\n writeEnvKey(envFilePath, \"GG_PIXEL_KEY\", created.key);\n\n const home = opts.homeDir ?? homedir();\n const projectsJsonPath = join(home, \".gg\", \"projects.json\");\n writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot);\n\n return {\n projectId: created.id,\n projectKey: created.key,\n projectName,\n initFilePath,\n envFilePath,\n projectsJsonPath,\n packageManager: pm,\n packageInstalled,\n };\n}\n\nfunction findProjectRoot(start: string): string | null {\n let dir = start;\n for (let i = 0; i < 20; i++) {\n if (existsSync(join(dir, \"package.json\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n return null;\n}\n\nasync function createProject(\n fetchFn: typeof fetch,\n ingestUrl: string,\n name: string,\n): Promise<{ id: string; key: string }> {\n const res = await fetchFn(`${ingestUrl}/api/projects`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ name }),\n });\n if (!res.ok) {\n throw new Error(`POST /api/projects failed: ${res.status} ${await safeText(res)}`);\n }\n const body = (await res.json()) as { id: string; key: string };\n if (!body.id || !body.key) throw new Error(\"response missing id/key\");\n return { id: body.id, key: body.key };\n}\n\nasync function safeText(r: Response): Promise<string> {\n try {\n return await r.text();\n } catch {\n return \"\";\n }\n}\n\nexport function detectPackageManager(projectRoot: string): PackageManager {\n if (existsSync(join(projectRoot, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(join(projectRoot, \"bun.lockb\"))) return \"bun\";\n if (existsSync(join(projectRoot, \"yarn.lock\"))) return \"yarn\";\n return \"npm\";\n}\n\nfunction runInstall(projectRoot: string, pm: PackageManager, pkg: string): boolean {\n const cmd = pm;\n const args = pm === \"npm\" ? [\"install\", pkg] : [\"add\", pkg];\n const result = spawnSync(cmd, args, { cwd: projectRoot, stdio: \"inherit\" });\n return result.status === 0;\n}\n\nexport function renderInitFile(ingestUrl: string): string {\n return `import { initPixel } from \"@kenkaiiii/gg-pixel\";\n\nconst key = process.env.GG_PIXEL_KEY;\nif (key) {\n initPixel({\n projectKey: key,\n sink: { kind: \"http\", ingestUrl: ${JSON.stringify(`${ingestUrl}/ingest`)} },\n });\n}\n`;\n}\n\nexport function writeEnvKey(envPath: string, key: string, value: string): void {\n if (existsSync(envPath)) {\n const current = readFileSync(envPath, \"utf8\");\n const lineRegex = new RegExp(`^${key}=.*$`, \"m\");\n if (lineRegex.test(current)) {\n writeFileSync(envPath, current.replace(lineRegex, `${key}=${value}`), \"utf8\");\n return;\n }\n const sep = current.endsWith(\"\\n\") || current.length === 0 ? \"\" : \"\\n\";\n appendFileSync(envPath, `${sep}${key}=${value}\\n`, \"utf8\");\n return;\n }\n writeFileSync(envPath, `${key}=${value}\\n`, \"utf8\");\n}\n\nexport function writeProjectsMapping(\n projectsJsonPath: string,\n projectId: string,\n name: string,\n path: string,\n): void {\n mkdirSync(dirname(projectsJsonPath), { recursive: true });\n let map: Record<string, { name: string; path: string }> = {};\n if (existsSync(projectsJsonPath)) {\n try {\n map = JSON.parse(readFileSync(projectsJsonPath, \"utf8\")) as typeof map;\n } catch {\n // start fresh on corrupt file\n }\n }\n map[projectId] = { name, path };\n writeFileSync(projectsJsonPath, `${JSON.stringify(map, null, 2)}\\n`, \"utf8\");\n}\n","import { installNodeAdapter, type NodeAdapter } from \"./adapters/node.js\";\nimport { HttpSink } from \"./core/sinks/http.js\";\nimport { LocalSqliteSink } from \"./core/sinks/local-sqlite.js\";\nimport type { PixelOptions, ReportInput, Sink, SinkConfig } from \"./core/types.js\";\n\nlet active: NodeAdapter | null = null;\n\nexport function initPixel(options: PixelOptions): NodeAdapter {\n if (active) {\n throw new Error(\"gg-pixel is already initialized; call closePixel() first\");\n }\n const sink = buildSink(options.sink);\n active = installNodeAdapter({\n projectKey: options.projectKey,\n runtime: options.runtime ?? defaultRuntime(),\n sink,\n captureConsoleErrors: options.captureConsoleErrors ?? true,\n captureConsoleWarnings: options.captureConsoleWarnings ?? false,\n captureUnhandledRejections: options.captureUnhandledRejections ?? true,\n captureUncaughtExceptions: options.captureUncaughtExceptions ?? true,\n });\n return active;\n}\n\nexport function reportPixel(input: ReportInput): void {\n if (!active) return;\n active.report(input);\n}\n\nexport async function flushPixel(): Promise<void> {\n if (!active) return;\n await active.flush();\n}\n\nexport async function closePixel(): Promise<void> {\n if (!active) return;\n await active.close();\n active = null;\n}\n\nfunction buildSink(config: SinkConfig): Sink {\n switch (config.kind) {\n case \"http\":\n return new HttpSink(config.ingestUrl, config.fetchFn);\n case \"local\":\n return new LocalSqliteSink(config.path);\n case \"custom\":\n return config.sink;\n }\n}\n\nfunction defaultRuntime(): string {\n const v = process.versions.node;\n return `node-${v}`;\n}\n\nexport type {\n Level,\n PixelOptions,\n ReportInput,\n Sink,\n SinkConfig,\n StackFrame,\n CodeContext,\n WireEvent,\n} from \"./core/types.js\";\n\nexport { install, DEFAULT_INGEST_URL } from \"./install.js\";\nexport type { InstallOptions, InstallResult, PackageManager } from \"./install.js\";\n"],"mappings":";AAAA,SAAS,kBAAkB;;;ACE3B,IAAM,gBAAgB;AACtB,IAAM,cAAc;AAEb,SAAS,WAAW,OAAyC;AAClE,MAAI,CAAC,MAAO,QAAO,CAAC;AACpB,QAAM,SAAuB,CAAC;AAC9B,aAAW,QAAQ,MAAM,MAAM,IAAI,GAAG;AACpC,UAAM,SAAS,cAAc,KAAK,IAAI;AACtC,QAAI,QAAQ;AACV,YAAM,OAAO,OAAO,CAAC;AACrB,aAAO,KAAK;AAAA,QACV,IAAI,OAAO,CAAC;AAAA,QACZ;AAAA,QACA,MAAM,OAAO,OAAO,CAAC,CAAC;AAAA,QACtB,KAAK,OAAO,OAAO,CAAC,CAAC;AAAA,QACrB,QAAQ,QAAQ,IAAI;AAAA,MACtB,CAAC;AACD;AAAA,IACF;AACA,UAAM,OAAO,YAAY,KAAK,IAAI;AAClC,QAAI,MAAM;AACR,YAAM,OAAO,KAAK,CAAC;AACnB,aAAO,KAAK;AAAA,QACV,IAAI;AAAA,QACJ;AAAA,QACA,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,QACpB,KAAK,OAAO,KAAK,CAAC,CAAC;AAAA,QACnB,QAAQ,QAAQ,IAAI;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,MAAuB;AACtC,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,WAAW,OAAO,EAAG,QAAO;AACrC,MAAI,KAAK,WAAW,WAAW,EAAG,QAAO;AACzC,MAAI,KAAK,SAAS,gBAAgB,EAAG,QAAO;AAC5C,SAAO;AACT;;;AC1CA,SAAS,kBAAkB;AAGpB,SAAS,YAAY,MAAc,OAA6B;AACrE,QAAM,MAAM,MAAM,CAAC;AACnB,QAAM,aAAa,MACf,GAAG,IAAI,IAAI,cAAc,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,QAAQ,IAAI,IAAI,IAAI,KACpE,GAAG,IAAI;AACX,SAAO,WAAW,QAAQ,EAAE,OAAO,UAAU,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AAC1E;AAEA,SAAS,cAAc,MAAsB;AAC3C,SAAO,KACJ,QAAQ,cAAc,EAAE,EACxB,QAAQ,uBAAuB,eAAe,EAC9C,QAAQ,SAAS,EAAE;AACxB;;;AChBA,SAAS,cAAc,kBAAkB;AAGzC,IAAM,SAAS;AACf,IAAM,QAAQ,oBAAI,IAA6B;AAExC,SAAS,mBAAmB,OAAyC;AAC1E,QAAM,MAAM,MAAM,KAAK,CAAC,MAAM,WAAW,EAAE,IAAI,CAAC;AAChD,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,QAAQ,UAAU,IAAI,IAAI;AAChC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,QAAQ,KAAK,IAAI,GAAG,IAAI,OAAO,IAAI,MAAM;AAC/C,QAAM,MAAM,KAAK,IAAI,MAAM,QAAQ,IAAI,OAAO,MAAM;AACpD,SAAO;AAAA,IACL,MAAM,IAAI;AAAA,IACV,YAAY,IAAI;AAAA,IAChB,OAAO,MAAM,MAAM,OAAO,GAAG;AAAA,EAC/B;AACF;AAEA,SAAS,WAAW,MAAuB;AACzC,MAAI,CAAC,QAAQ,KAAK,WAAW,OAAO,EAAG,QAAO;AAC9C,MAAI,KAAK,SAAS,gBAAgB,EAAG,QAAO;AAC5C,SAAO,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,SAAS;AAC1D;AAEA,SAAS,UAAU,MAA+B;AAChD,QAAM,OAAO,KAAK,QAAQ,cAAc,EAAE;AAC1C,MAAI,MAAM,IAAI,IAAI,EAAG,QAAO,MAAM,IAAI,IAAI,KAAK;AAC/C,MAAI,CAAC,WAAW,IAAI,GAAG;AACrB,UAAM,IAAI,MAAM,IAAI;AACpB,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,QAAQ,aAAa,MAAM,MAAM,EAAE,MAAM,IAAI;AACnD,UAAM,IAAI,MAAM,KAAK;AACrB,WAAO;AAAA,EACT,QAAQ;AACN,UAAM,IAAI,MAAM,IAAI;AACpB,WAAO;AAAA,EACT;AACF;;;ACvCA,IAAM,aAAa;AACnB,IAAM,gBAAgB;AACtB,IAAM,eAAe;AAEd,IAAM,aAAN,MAAiB;AAAA,EAKtB,YAA6B,MAAY;AAAZ;AAAA,EAAa;AAAA,EAJzB,SAAsB,CAAC;AAAA,EAChC,WAAW;AAAA,EACX,SAAS;AAAA,EAIjB,QAAQ,OAAwB;AAC9B,QAAI,KAAK,OAAQ;AACjB,QAAI,KAAK,OAAO,UAAU,YAAY;AACpC,WAAK,OAAO,MAAM;AAAA,IACpB;AACA,SAAK,OAAO,KAAK,KAAK;AACtB,SAAK,KAAK,MAAM;AAAA,EAClB;AAAA,EAEA,YAAY,OAAwB;AAClC,QAAI,KAAK,OAAQ;AACjB,QAAI,KAAK,KAAK,UAAU;AACtB,UAAI;AACF,aAAK,KAAK,SAAS,KAAK;AACxB;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AACA,SAAK,QAAQ,KAAK;AAAA,EACpB;AAAA,EAEA,MAAM,QAAuB;AAC3B,WAAO,KAAK,OAAO,SAAS,KAAK,KAAK,UAAU;AAC9C,YAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,KAAK,MAAM;AACjB,SAAK,SAAS;AACd,QAAI,KAAK,KAAK,MAAO,OAAM,KAAK,KAAK,MAAM;AAAA,EAC7C;AAAA,EAEA,MAAc,QAAuB;AACnC,QAAI,KAAK,SAAU;AACnB,SAAK,WAAW;AAChB,QAAI,UAAU;AACd,WAAO,KAAK,OAAO,SAAS,GAAG;AAC7B,YAAM,QAAQ,KAAK,OAAO,CAAC;AAC3B,UAAI;AACF,cAAM,KAAK,KAAK,KAAK,KAAK;AAC1B,aAAK,OAAO,MAAM;AAClB,kBAAU;AAAA,MACZ,QAAQ;AACN;AACA,YAAI,WAAW,GAAG;AAChB,eAAK,OAAO,MAAM;AAClB,oBAAU;AACV;AAAA,QACF;AACA,cAAM,QAAQ,KAAK,IAAI,gBAAgB,MAAM,UAAU,IAAI,YAAY;AACvE,cAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC;AAAA,MAC/C;AAAA,IACF;AACA,SAAK,WAAW;AAAA,EAClB;AACF;;;AJ/CO,SAAS,mBAAmB,MAAuC;AACxE,QAAM,QAAQ,IAAI,WAAW,KAAK,IAAI;AACtC,QAAM,SAA4B,CAAC;AAEnC,QAAM,eAAe,CAAC,KAAc,OAAc,WAAoB;AACpE,QAAI;AACF,YAAM,QAAQ,WAAW,KAAK,OAAO,QAAQ,KAAK,YAAY,KAAK,OAAO;AAC1E,YAAM,QAAQ,KAAK;AAAA,IACrB,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,mBAAmB,CAAC,KAAc,OAAc,WAAoB;AACxE,QAAI;AACF,YAAM,QAAQ,WAAW,KAAK,OAAO,QAAQ,KAAK,YAAY,KAAK,OAAO;AAC1E,YAAM,YAAY,KAAK;AAAA,IACzB,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,MAAI,KAAK,2BAA2B;AAClC,UAAM,UAAU,CAAC,QAAe,iBAAiB,KAAK,SAAS,KAAK;AACpE,YAAQ,GAAG,4BAA4B,OAAO;AAC9C,WAAO,KAAK,MAAM,QAAQ,IAAI,4BAA4B,OAAO,CAAC;AAAA,EACpE;AAEA,MAAI,KAAK,4BAA4B;AACnC,UAAM,UAAU,CAAC,WAAoB,iBAAiB,QAAQ,SAAS,KAAK;AAC5E,YAAQ,GAAG,sBAAsB,OAAO;AACxC,WAAO,KAAK,MAAM,QAAQ,IAAI,sBAAsB,OAAO,CAAC;AAAA,EAC9D;AAEA,MAAI,KAAK,sBAAsB;AAC7B,WAAO,KAAK,aAAa,SAAS,CAAC,SAAS,aAAa,aAAa,IAAI,GAAG,SAAS,KAAK,CAAC,CAAC;AAAA,EAC/F;AAEA,MAAI,KAAK,wBAAwB;AAC/B,WAAO,KAAK,aAAa,QAAQ,CAAC,SAAS,aAAa,aAAa,IAAI,GAAG,WAAW,KAAK,CAAC,CAAC;AAAA,EAChG;AAEA,QAAM,eAAe,MAAM;AACzB,SAAK,MAAM,MAAM;AAAA,EACnB;AACA,UAAQ,GAAG,cAAc,YAAY;AACrC,SAAO,KAAK,MAAM,QAAQ,IAAI,cAAc,YAAY,CAAC;AAEzD,SAAO;AAAA,IACL,OAAO,OAAoB;AACzB,YAAM,QAAQ,MAAM,SAAS;AAC7B,UAAI,MAAM,UAAU,QAAW;AAC7B,YAAI;AACF,gBAAM,QAAQ,WAAW,MAAM,OAAO,OAAO,MAAM,KAAK,YAAY,KAAK,OAAO;AAChF,cAAI,MAAM,QAAS,OAAM,UAAU,MAAM;AACzC,gBAAM,QAAQ,KAAK;AAAA,QACrB,QAAQ;AAAA,QAER;AACA;AAAA,MACF;AACA,YAAM,MAAM,IAAI,MAAM,MAAM,OAAO;AACnC,UAAI,OAAO;AACX,mBAAa,KAAK,OAAO,IAAI;AAAA,IAC/B;AAAA,IACA,OAAO,MAAM,MAAM,MAAM;AAAA,IACzB,OAAO,YAAY;AACjB,iBAAW,MAAM,OAAQ,IAAG;AAC5B,YAAM,MAAM,MAAM;AAAA,IACpB;AAAA,EACF;AACF;AAEA,SAAS,WACP,KACA,OACA,QACA,YACA,SACW;AACX,QAAM,EAAE,MAAM,SAAS,YAAY,IAAI,UAAU,GAAG;AACpD,QAAM,QAAQ,WAAW,WAAW;AACpC,SAAO;AAAA,IACL,UAAU,WAAW;AAAA,IACrB,aAAa;AAAA,IACb,aAAa,YAAY,MAAM,KAAK;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,mBAAmB,KAAK;AAAA,IACtC;AAAA,IACA,eAAe;AAAA,IACf;AAAA,IACA,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,EACtC;AACF;AAEA,SAAS,UAAU,KAAuE;AACxF,MAAI,eAAe,OAAO;AACxB,WAAO,EAAE,MAAM,IAAI,QAAQ,SAAS,SAAS,IAAI,SAAS,aAAa,IAAI,MAAM;AAAA,EACnF;AACA,MAAI,OAAO,QAAQ,UAAU;AAC3B,WAAO,EAAE,MAAM,eAAe,SAAS,IAAI;AAAA,EAC7C;AACA,MAAI;AACF,WAAO,EAAE,MAAM,gBAAgB,SAAS,KAAK,UAAU,GAAG,EAAE;AAAA,EAC9D,QAAQ;AACN,WAAO,EAAE,MAAM,gBAAgB,SAAS,OAAO,GAAG,EAAE;AAAA,EACtD;AACF;AAEA,SAAS,aAAa,MAA0B;AAC9C,aAAW,KAAK,KAAM,KAAI,aAAa,MAAO,QAAO;AACrD,SAAO,IAAI,MAAM,KAAK,IAAI,SAAS,EAAE,KAAK,GAAG,CAAC;AAChD;AAEA,SAAS,UAAU,GAAoB;AACrC,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,MAAI;AACF,WAAO,KAAK,UAAU,CAAC;AAAA,EACzB,QAAQ;AACN,WAAO,OAAO,CAAC;AAAA,EACjB;AACF;AAIA,SAAS,aAAa,QAAuB,QAA+C;AAC1F,QAAM,WAAW,QAAQ,MAAM;AAC/B,UAAQ,MAAM,IAAI,IAAI,SAAoB;AACxC,QAAI;AACF,aAAO,IAAI;AAAA,IACb,QAAQ;AAAA,IAER;AACA,aAAS,MAAM,SAAS,IAAI;AAAA,EAC9B;AACA,SAAO,MAAM;AACX,YAAQ,MAAM,IAAI;AAAA,EACpB;AACF;;;AKjKO,IAAM,WAAN,MAA+B;AAAA,EACpC,YACmB,WACA,UAAwB,OACzC;AAFiB;AACA;AAAA,EAChB;AAAA,EAEH,MAAM,KAAK,OAAiC;AAC1C,UAAM,MAAM,MAAM,KAAK,QAAQ,KAAK,WAAW;AAAA,MAC7C,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe,MAAM;AAAA,MACvB;AAAA,MACA,MAAM,KAAK,UAAU,KAAK;AAAA,IAC5B,CAAC;AACD,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,wBAAwB,IAAI,MAAM,EAAE;AAAA,IACtD;AAAA,EACF;AACF;;;ACrBA,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAC1B,SAAS,SAAS,YAAY;AAC9B,OAAO,cAAc;AAGrB,IAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBR,IAAM,kBAAN,MAAsC;AAAA,EAC1B;AAAA,EACA;AAAA,EAEjB,YAAY,MAAe;AACzB,UAAM,WAAW,QAAQ,KAAK,QAAQ,GAAG,OAAO,WAAW;AAC3D,cAAU,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAChD,SAAK,KAAK,IAAI,SAAS,QAAQ;AAC/B,SAAK,GAAG,OAAO,oBAAoB;AACnC,SAAK,GAAG,KAAK,MAAM;AACnB,SAAK,SAAS,KAAK,GAAG,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAQ7B;AAAA,EACH;AAAA,EAEA,SAAS,OAAwB;AAC/B,SAAK,OAAO,IAAI;AAAA,MACd,UAAU,MAAM;AAAA,MAChB,aAAa,MAAM;AAAA,MACnB,aAAa,MAAM;AAAA,MACnB,MAAM,MAAM;AAAA,MACZ,SAAS,MAAM;AAAA,MACf,OAAO,KAAK,UAAU,MAAM,KAAK;AAAA,MACjC,cAAc,MAAM,eAAe,KAAK,UAAU,MAAM,YAAY,IAAI;AAAA,MACxE,SAAS,MAAM;AAAA,MACf,eAAe,MAAM,gBAAgB,IAAI;AAAA,MACzC,OAAO,MAAM;AAAA,MACb,aAAa,MAAM;AAAA,IACrB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,KAAK,OAAiC;AAC1C,SAAK,SAAS,KAAK;AAAA,EACrB;AAAA,EAEA,MAAM,QAAuB;AAC3B,SAAK,GAAG,MAAM;AAAA,EAChB;AACF;;;ACtEA,SAAS,cAAAA,aAAY,gBAAAC,eAAc,eAAe,gBAAgB,aAAAC,kBAAiB;AACnF,SAAS,WAAAC,gBAAe;AACxB,SAAS,WAAAC,UAAS,QAAAC,OAAM,eAAe;AACvC,SAAS,iBAAiB;AAEnB,IAAM,qBAAqB;AAwBlC,eAAsB,QAAQ,OAAuB,CAAC,GAA2B;AAC/E,QAAM,MAAM,QAAQ,KAAK,OAAO,QAAQ,IAAI,CAAC;AAC7C,QAAM,aAAa,KAAK,aAAa,oBAAoB,QAAQ,QAAQ,EAAE;AAC3E,QAAM,UAAU,KAAK,WAAW;AAEhC,QAAM,cAAc,gBAAgB,GAAG;AACvC,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,MAAM,4BAA4B,GAAG,2BAA2B;AAAA,EAC5E;AAEA,QAAM,UAAUA,MAAK,aAAa,cAAc;AAChD,QAAM,MAAM,KAAK,MAAMJ,cAAa,SAAS,MAAM,CAAC;AACpD,QAAM,cAAc,KAAK,eAAe,IAAI,QAAQ,YAAY,MAAM,GAAG,EAAE,IAAI,KAAK;AAEpF,QAAM,UAAU,MAAM,cAAc,SAAS,WAAW,WAAW;AAEnE,QAAM,KAAK,qBAAqB,WAAW;AAC3C,QAAM,mBAAmB,KAAK,qBAC1B,QACA,WAAW,aAAa,IAAI,qBAAqB;AAErD,QAAM,eAAeI,MAAK,aAAa,mBAAmB;AAC1D,gBAAc,cAAc,eAAe,SAAS,GAAG,MAAM;AAE7D,QAAM,cAAcA,MAAK,aAAa,MAAM;AAC5C,cAAY,aAAa,gBAAgB,QAAQ,GAAG;AAEpD,QAAM,OAAO,KAAK,WAAWF,SAAQ;AACrC,QAAM,mBAAmBE,MAAK,MAAM,OAAO,eAAe;AAC1D,uBAAqB,kBAAkB,QAAQ,IAAI,aAAa,WAAW;AAE3E,SAAO;AAAA,IACL,WAAW,QAAQ;AAAA,IACnB,YAAY,QAAQ;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,OAA8B;AACrD,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,QAAIL,YAAWK,MAAK,KAAK,cAAc,CAAC,EAAG,QAAO;AAClD,UAAM,SAASD,SAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK,QAAO;AAC3B,UAAM;AAAA,EACR;AACA,SAAO;AACT;AAEA,eAAe,cACb,SACA,WACA,MACsC;AACtC,QAAM,MAAM,MAAM,QAAQ,GAAG,SAAS,iBAAiB;AAAA,IACrD,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,EAAE,KAAK,CAAC;AAAA,EAC/B,CAAC;AACD,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAM,8BAA8B,IAAI,MAAM,IAAI,MAAM,SAAS,GAAG,CAAC,EAAE;AAAA,EACnF;AACA,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,MAAI,CAAC,KAAK,MAAM,CAAC,KAAK,IAAK,OAAM,IAAI,MAAM,yBAAyB;AACpE,SAAO,EAAE,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI;AACtC;AAEA,eAAe,SAAS,GAA8B;AACpD,MAAI;AACF,WAAO,MAAM,EAAE,KAAK;AAAA,EACtB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,qBAAqB,aAAqC;AACxE,MAAIJ,YAAWK,MAAK,aAAa,gBAAgB,CAAC,EAAG,QAAO;AAC5D,MAAIL,YAAWK,MAAK,aAAa,WAAW,CAAC,EAAG,QAAO;AACvD,MAAIL,YAAWK,MAAK,aAAa,WAAW,CAAC,EAAG,QAAO;AACvD,SAAO;AACT;AAEA,SAAS,WAAW,aAAqB,IAAoB,KAAsB;AACjF,QAAM,MAAM;AACZ,QAAM,OAAO,OAAO,QAAQ,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,GAAG;AAC1D,QAAM,SAAS,UAAU,KAAK,MAAM,EAAE,KAAK,aAAa,OAAO,UAAU,CAAC;AAC1E,SAAO,OAAO,WAAW;AAC3B;AAEO,SAAS,eAAe,WAA2B;AACxD,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uCAM8B,KAAK,UAAU,GAAG,SAAS,SAAS,CAAC;AAAA;AAAA;AAAA;AAI5E;AAEO,SAAS,YAAY,SAAiB,KAAa,OAAqB;AAC7E,MAAIL,YAAW,OAAO,GAAG;AACvB,UAAM,UAAUC,cAAa,SAAS,MAAM;AAC5C,UAAM,YAAY,IAAI,OAAO,IAAI,GAAG,QAAQ,GAAG;AAC/C,QAAI,UAAU,KAAK,OAAO,GAAG;AAC3B,oBAAc,SAAS,QAAQ,QAAQ,WAAW,GAAG,GAAG,IAAI,KAAK,EAAE,GAAG,MAAM;AAC5E;AAAA,IACF;AACA,UAAM,MAAM,QAAQ,SAAS,IAAI,KAAK,QAAQ,WAAW,IAAI,KAAK;AAClE,mBAAe,SAAS,GAAG,GAAG,GAAG,GAAG,IAAI,KAAK;AAAA,GAAM,MAAM;AACzD;AAAA,EACF;AACA,gBAAc,SAAS,GAAG,GAAG,IAAI,KAAK;AAAA,GAAM,MAAM;AACpD;AAEO,SAAS,qBACd,kBACA,WACA,MACA,MACM;AACN,EAAAC,WAAUE,SAAQ,gBAAgB,GAAG,EAAE,WAAW,KAAK,CAAC;AACxD,MAAI,MAAsD,CAAC;AAC3D,MAAIJ,YAAW,gBAAgB,GAAG;AAChC,QAAI;AACF,YAAM,KAAK,MAAMC,cAAa,kBAAkB,MAAM,CAAC;AAAA,IACzD,QAAQ;AAAA,IAER;AAAA,EACF;AACA,MAAI,SAAS,IAAI,EAAE,MAAM,KAAK;AAC9B,gBAAc,kBAAkB,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AAC7E;;;ACnKA,IAAI,SAA6B;AAE1B,SAAS,UAAU,SAAoC;AAC5D,MAAI,QAAQ;AACV,UAAM,IAAI,MAAM,0DAA0D;AAAA,EAC5E;AACA,QAAM,OAAO,UAAU,QAAQ,IAAI;AACnC,WAAS,mBAAmB;AAAA,IAC1B,YAAY,QAAQ;AAAA,IACpB,SAAS,QAAQ,WAAW,eAAe;AAAA,IAC3C;AAAA,IACA,sBAAsB,QAAQ,wBAAwB;AAAA,IACtD,wBAAwB,QAAQ,0BAA0B;AAAA,IAC1D,4BAA4B,QAAQ,8BAA8B;AAAA,IAClE,2BAA2B,QAAQ,6BAA6B;AAAA,EAClE,CAAC;AACD,SAAO;AACT;AAEO,SAAS,YAAY,OAA0B;AACpD,MAAI,CAAC,OAAQ;AACb,SAAO,OAAO,KAAK;AACrB;AAEA,eAAsB,aAA4B;AAChD,MAAI,CAAC,OAAQ;AACb,QAAM,OAAO,MAAM;AACrB;AAEA,eAAsB,aAA4B;AAChD,MAAI,CAAC,OAAQ;AACb,QAAM,OAAO,MAAM;AACnB,WAAS;AACX;AAEA,SAAS,UAAU,QAA0B;AAC3C,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,IAAI,SAAS,OAAO,WAAW,OAAO,OAAO;AAAA,IACtD,KAAK;AACH,aAAO,IAAI,gBAAgB,OAAO,IAAI;AAAA,IACxC,KAAK;AACH,aAAO,OAAO;AAAA,EAClB;AACF;AAEA,SAAS,iBAAyB;AAChC,QAAM,IAAI,QAAQ,SAAS;AAC3B,SAAO,QAAQ,CAAC;AAClB;","names":["existsSync","readFileSync","mkdirSync","homedir","dirname","join"]}
1
+ {"version":3,"sources":["../src/adapters/node.ts","../src/core/stack.ts","../src/core/fingerprint.ts","../src/code-context.ts","../src/core/queue.ts","../src/core/sinks/http.ts","../src/core/sinks/local-sqlite.ts","../src/install.ts","../src/index.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { parseStack } from \"../core/stack.js\";\nimport { fingerprint } from \"../core/fingerprint.js\";\nimport { captureCodeContext } from \"../code-context.js\";\nimport { EventQueue } from \"../core/queue.js\";\nimport type { Level, ReportInput, Sink, WireEvent } from \"../core/types.js\";\n\nexport interface NodeAdapterOptions {\n projectKey: string;\n runtime: string;\n sink: Sink;\n captureConsoleErrors: boolean;\n captureConsoleWarnings: boolean;\n captureUnhandledRejections: boolean;\n captureUncaughtExceptions: boolean;\n}\n\nexport interface NodeAdapter {\n report(input: ReportInput): void;\n flush(): Promise<void>;\n close(): Promise<void>;\n}\n\nexport function installNodeAdapter(opts: NodeAdapterOptions): NodeAdapter {\n const queue = new EventQueue(opts.sink);\n const detach: Array<() => void> = [];\n\n const enqueueError = (err: unknown, level: Level, manual: boolean) => {\n try {\n const event = buildEvent(err, level, manual, opts.projectKey, opts.runtime);\n queue.enqueue(event);\n } catch {\n // never let pixel break the host program\n }\n };\n\n const enqueueErrorSync = (err: unknown, level: Level, manual: boolean) => {\n try {\n const event = buildEvent(err, level, manual, opts.projectKey, opts.runtime);\n queue.enqueueSync(event);\n } catch {\n // never let pixel break the host program\n }\n };\n\n if (opts.captureUncaughtExceptions) {\n const handler = (err: Error) => enqueueErrorSync(err, \"fatal\", false);\n process.on(\"uncaughtExceptionMonitor\", handler);\n detach.push(() => process.off(\"uncaughtExceptionMonitor\", handler));\n }\n\n if (opts.captureUnhandledRejections) {\n const handler = (reason: unknown) => enqueueErrorSync(reason, \"error\", false);\n process.on(\"unhandledRejection\", handler);\n detach.push(() => process.off(\"unhandledRejection\", handler));\n }\n\n if (opts.captureConsoleErrors) {\n detach.push(patchConsole(\"error\", (args) => enqueueError(consoleError(args), \"error\", false)));\n }\n\n if (opts.captureConsoleWarnings) {\n detach.push(patchConsole(\"warn\", (args) => enqueueError(consoleError(args), \"warning\", false)));\n }\n\n const onBeforeExit = () => {\n void queue.flush();\n };\n process.on(\"beforeExit\", onBeforeExit);\n detach.push(() => process.off(\"beforeExit\", onBeforeExit));\n\n return {\n report(input: ReportInput) {\n const level = input.level ?? \"error\";\n if (input.error !== undefined) {\n try {\n const event = buildEvent(input.error, level, true, opts.projectKey, opts.runtime);\n if (input.message) event.message = input.message;\n queue.enqueue(event);\n } catch {\n // never let pixel break the host program\n }\n return;\n }\n const err = new Error(input.message);\n err.name = \"ManualReport\";\n enqueueError(err, level, true);\n },\n flush: () => queue.flush(),\n close: async () => {\n for (const fn of detach) fn();\n await queue.close();\n },\n };\n}\n\nfunction buildEvent(\n err: unknown,\n level: Level,\n manual: boolean,\n projectKey: string,\n runtime: string,\n): WireEvent {\n const { type, message, stackString } = normalize(err);\n const stack = parseStack(stackString);\n return {\n event_id: randomUUID(),\n project_key: projectKey,\n fingerprint: fingerprint(type, stack),\n type,\n message,\n stack,\n code_context: captureCodeContext(stack),\n runtime,\n manual_report: manual,\n level,\n occurred_at: new Date().toISOString(),\n };\n}\n\nfunction normalize(err: unknown): { type: string; message: string; stackString?: string } {\n if (err instanceof Error) {\n return { type: err.name || \"Error\", message: err.message, stackString: err.stack };\n }\n if (typeof err === \"string\") {\n return { type: \"StringError\", message: err };\n }\n try {\n return { type: \"UnknownError\", message: JSON.stringify(err) };\n } catch {\n return { type: \"UnknownError\", message: String(err) };\n }\n}\n\nfunction consoleError(args: unknown[]): unknown {\n for (const a of args) if (a instanceof Error) return a;\n return new Error(args.map(stringify).join(\" \"));\n}\n\nfunction stringify(x: unknown): string {\n if (typeof x === \"string\") return x;\n try {\n return JSON.stringify(x);\n } catch {\n return String(x);\n }\n}\n\ntype ConsoleMethod = \"error\" | \"warn\";\n\nfunction patchConsole(method: ConsoleMethod, onCall: (args: unknown[]) => void): () => void {\n const original = console[method];\n console[method] = (...args: unknown[]) => {\n try {\n onCall(args);\n } catch {\n // never let pixel break the host program\n }\n original.apply(console, args);\n };\n return () => {\n console[method] = original;\n };\n}\n","import type { StackFrame } from \"./types.js\";\n\nconst FRAME_WITH_FN = /^\\s*at\\s+(.+?)\\s+\\((.+?):(\\d+):(\\d+)\\)\\s*$/;\nconst FRAME_NO_FN = /^\\s*at\\s+(.+?):(\\d+):(\\d+)\\s*$/;\n\nexport function parseStack(stack: string | undefined): StackFrame[] {\n if (!stack) return [];\n const frames: StackFrame[] = [];\n for (const line of stack.split(\"\\n\")) {\n const withFn = FRAME_WITH_FN.exec(line);\n if (withFn) {\n const file = withFn[2];\n frames.push({\n fn: withFn[1],\n file,\n line: Number(withFn[3]),\n col: Number(withFn[4]),\n in_app: isInApp(file),\n });\n continue;\n }\n const noFn = FRAME_NO_FN.exec(line);\n if (noFn) {\n const file = noFn[1];\n frames.push({\n fn: \"<anon>\",\n file,\n line: Number(noFn[2]),\n col: Number(noFn[3]),\n in_app: isInApp(file),\n });\n }\n }\n return frames;\n}\n\nfunction isInApp(file: string): boolean {\n if (!file) return false;\n if (file.startsWith(\"node:\")) return false;\n if (file.startsWith(\"internal/\")) return false;\n if (file.includes(\"/node_modules/\")) return false;\n return true;\n}\n","import { createHash } from \"node:crypto\";\nimport type { StackFrame } from \"./types.js\";\n\nexport function fingerprint(type: string, stack: StackFrame[]): string {\n const top = stack[0];\n const normalized = top\n ? `${type}|${normalizeFile(top.file)}|${top.fn || \"<anon>\"}|${top.line}`\n : `${type}|<no-stack>`;\n return createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n}\n\nfunction normalizeFile(file: string): string {\n return file\n .replace(/^file:\\/\\//, \"\")\n .replace(/^.*\\/node_modules\\//, \"node_modules/\")\n .replace(/\\?.*$/, \"\");\n}\n","import { readFileSync, existsSync } from \"node:fs\";\nimport type { CodeContext, StackFrame } from \"./core/types.js\";\n\nconst WINDOW = 2;\nconst cache = new Map<string, string[] | null>();\n\nexport function captureCodeContext(stack: StackFrame[]): CodeContext | null {\n const top = stack.find((f) => isReadable(f.file));\n if (!top) return null;\n const lines = loadLines(top.file);\n if (!lines) return null;\n const start = Math.max(0, top.line - 1 - WINDOW);\n const end = Math.min(lines.length, top.line + WINDOW);\n return {\n file: top.file,\n error_line: top.line,\n lines: lines.slice(start, end),\n };\n}\n\nfunction isReadable(file: string): boolean {\n if (!file || file.startsWith(\"node:\")) return false;\n if (file.includes(\"/node_modules/\")) return false;\n return file.startsWith(\"/\") || file.startsWith(\"file://\");\n}\n\nfunction loadLines(file: string): string[] | null {\n const path = file.replace(/^file:\\/\\//, \"\");\n if (cache.has(path)) return cache.get(path) ?? null;\n if (!existsSync(path)) {\n cache.set(path, null);\n return null;\n }\n try {\n const lines = readFileSync(path, \"utf8\").split(\"\\n\");\n cache.set(path, lines);\n return lines;\n } catch {\n cache.set(path, null);\n return null;\n }\n}\n","import type { Sink, WireEvent } from \"./types.js\";\n\nconst MAX_BUFFER = 100;\nconst BASE_DELAY_MS = 200;\nconst MAX_DELAY_MS = 5_000;\n\nexport class EventQueue {\n private readonly buffer: WireEvent[] = [];\n private draining = false;\n private closed = false;\n\n constructor(private readonly sink: Sink) {}\n\n enqueue(event: WireEvent): void {\n if (this.closed) return;\n if (this.buffer.length >= MAX_BUFFER) {\n this.buffer.shift();\n }\n this.buffer.push(event);\n void this.drain();\n }\n\n enqueueSync(event: WireEvent): void {\n if (this.closed) return;\n if (this.sink.emitSync) {\n try {\n this.sink.emitSync(event);\n return;\n } catch {\n // fall through to async path\n }\n }\n this.enqueue(event);\n }\n\n async flush(): Promise<void> {\n while (this.buffer.length > 0 || this.draining) {\n await new Promise((r) => setTimeout(r, 10));\n }\n }\n\n async close(): Promise<void> {\n await this.flush();\n this.closed = true;\n if (this.sink.close) await this.sink.close();\n }\n\n private async drain(): Promise<void> {\n if (this.draining) return;\n this.draining = true;\n let attempt = 0;\n while (this.buffer.length > 0) {\n const event = this.buffer[0];\n try {\n await this.sink.emit(event);\n this.buffer.shift();\n attempt = 0;\n } catch {\n attempt++;\n if (attempt >= 5) {\n this.buffer.shift();\n attempt = 0;\n continue;\n }\n const delay = Math.min(BASE_DELAY_MS * 2 ** (attempt - 1), MAX_DELAY_MS);\n await new Promise((r) => setTimeout(r, delay));\n }\n }\n this.draining = false;\n }\n}\n","import type { Sink, WireEvent } from \"../types.js\";\n\nexport class HttpSink implements Sink {\n constructor(\n private readonly ingestUrl: string,\n private readonly fetchFn: typeof fetch = fetch,\n ) {}\n\n async emit(event: WireEvent): Promise<void> {\n const res = await this.fetchFn(this.ingestUrl, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-pixel-key\": event.project_key,\n },\n body: JSON.stringify(event),\n });\n if (!res.ok) {\n throw new Error(`pixel ingest failed: ${res.status}`);\n }\n }\n}\n","import { homedir } from \"node:os\";\nimport { mkdirSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport Database from \"better-sqlite3\";\nimport type { Sink, WireEvent } from \"../types.js\";\n\nconst SCHEMA = `\n CREATE TABLE IF NOT EXISTS events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n event_id TEXT NOT NULL UNIQUE,\n project_key TEXT NOT NULL,\n fingerprint TEXT NOT NULL,\n type TEXT NOT NULL,\n message TEXT NOT NULL,\n stack TEXT NOT NULL,\n code_context TEXT,\n runtime TEXT NOT NULL,\n manual_report INTEGER NOT NULL DEFAULT 0,\n level TEXT NOT NULL,\n occurred_at TEXT NOT NULL,\n ingested_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n CREATE INDEX IF NOT EXISTS events_fingerprint ON events(project_key, fingerprint);\n CREATE INDEX IF NOT EXISTS events_occurred ON events(occurred_at);\n`;\n\nexport class LocalSqliteSink implements Sink {\n private readonly db: Database.Database;\n private readonly insert: Database.Statement;\n\n constructor(path?: string) {\n const resolved = path ?? join(homedir(), \".gg\", \"errors.db\");\n mkdirSync(dirname(resolved), { recursive: true });\n this.db = new Database(resolved);\n this.db.pragma(\"journal_mode = WAL\");\n this.db.exec(SCHEMA);\n this.insert = this.db.prepare(`\n INSERT INTO events (\n event_id, project_key, fingerprint, type, message, stack, code_context,\n runtime, manual_report, level, occurred_at\n ) VALUES (\n @event_id, @project_key, @fingerprint, @type, @message, @stack, @code_context,\n @runtime, @manual_report, @level, @occurred_at\n )\n `);\n }\n\n emitSync(event: WireEvent): void {\n this.insert.run({\n event_id: event.event_id,\n project_key: event.project_key,\n fingerprint: event.fingerprint,\n type: event.type,\n message: event.message,\n stack: JSON.stringify(event.stack),\n code_context: event.code_context ? JSON.stringify(event.code_context) : null,\n runtime: event.runtime,\n manual_report: event.manual_report ? 1 : 0,\n level: event.level,\n occurred_at: event.occurred_at,\n });\n }\n\n async emit(event: WireEvent): Promise<void> {\n this.emitSync(event);\n }\n\n async close(): Promise<void> {\n this.db.close();\n }\n}\n","import { existsSync, readFileSync, writeFileSync, appendFileSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\n\nexport const DEFAULT_INGEST_URL = \"https://gg-pixel-server.buzzbeamaustralia.workers.dev\";\n\nexport interface InstallOptions {\n cwd?: string;\n ingestUrl?: string;\n projectName?: string;\n fetchFn?: typeof fetch;\n skipPackageInstall?: boolean;\n homeDir?: string;\n}\n\nexport interface InstallResult {\n projectId: string;\n projectKey: string;\n projectName: string;\n initFilePath: string;\n envFilePath: string;\n projectsJsonPath: string;\n packageManager: PackageManager;\n packageInstalled: boolean;\n entryWiring: EntryWiringResult;\n}\n\nexport type EntryWiringResult =\n | { kind: \"injected\"; entryPath: string }\n | { kind: \"already_present\"; entryPath: string }\n | { kind: \"no_entry_found\" }\n | { kind: \"skipped\"; reason: string };\n\ninterface PackageJson {\n name?: string;\n type?: string;\n main?: string;\n module?: string;\n bin?: string | Record<string, string>;\n}\n\nexport type PackageManager = \"pnpm\" | \"yarn\" | \"bun\" | \"npm\";\n\nexport async function install(opts: InstallOptions = {}): Promise<InstallResult> {\n const cwd = resolve(opts.cwd ?? process.cwd());\n const ingestUrl = (opts.ingestUrl ?? DEFAULT_INGEST_URL).replace(/\\/+$/, \"\");\n const fetchFn = opts.fetchFn ?? fetch;\n\n const projectRoot = findProjectRoot(cwd);\n if (!projectRoot) {\n throw new Error(`No package.json found in ${cwd} or any parent directory.`);\n }\n\n const pkgPath = join(projectRoot, \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as PackageJson;\n const projectName = opts.projectName ?? pkg.name ?? projectRoot.split(\"/\").pop() ?? \"unnamed\";\n\n const created = await createProject(fetchFn, ingestUrl, projectName);\n\n const pm = detectPackageManager(projectRoot);\n const packageInstalled = opts.skipPackageInstall\n ? false\n : runInstall(projectRoot, pm, \"@kenkaiiii/gg-pixel\");\n\n const initFilePath = join(projectRoot, \"gg-pixel.init.mjs\");\n writeFileSync(initFilePath, renderInitFile(ingestUrl), \"utf8\");\n\n const envFilePath = join(projectRoot, \".env\");\n writeEnvKey(envFilePath, \"GG_PIXEL_KEY\", created.key);\n\n const home = opts.homeDir ?? homedir();\n const projectsJsonPath = join(home, \".gg\", \"projects.json\");\n writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot);\n\n const entryWiring = wireEntryFile(projectRoot, initFilePath, pkg);\n\n return {\n projectId: created.id,\n projectKey: created.key,\n projectName,\n initFilePath,\n envFilePath,\n projectsJsonPath,\n packageManager: pm,\n packageInstalled,\n entryWiring,\n };\n}\n\nfunction findProjectRoot(start: string): string | null {\n let dir = start;\n for (let i = 0; i < 20; i++) {\n if (existsSync(join(dir, \"package.json\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n return null;\n}\n\nasync function createProject(\n fetchFn: typeof fetch,\n ingestUrl: string,\n name: string,\n): Promise<{ id: string; key: string }> {\n const res = await fetchFn(`${ingestUrl}/api/projects`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ name }),\n });\n if (!res.ok) {\n throw new Error(`POST /api/projects failed: ${res.status} ${await safeText(res)}`);\n }\n const body = (await res.json()) as { id: string; key: string };\n if (!body.id || !body.key) throw new Error(\"response missing id/key\");\n return { id: body.id, key: body.key };\n}\n\nasync function safeText(r: Response): Promise<string> {\n try {\n return await r.text();\n } catch {\n return \"\";\n }\n}\n\nexport function detectPackageManager(projectRoot: string): PackageManager {\n if (existsSync(join(projectRoot, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(join(projectRoot, \"bun.lockb\"))) return \"bun\";\n if (existsSync(join(projectRoot, \"yarn.lock\"))) return \"yarn\";\n return \"npm\";\n}\n\nfunction runInstall(projectRoot: string, pm: PackageManager, pkg: string): boolean {\n const cmd = pm;\n // npm prints `npm audit` warnings + `npm fund` solicitations on every install.\n // That output is about the user's *existing* project — irrelevant to pixel.\n // The other package managers don't show this noise by default.\n const args = pm === \"npm\" ? [\"install\", pkg, \"--no-audit\", \"--no-fund\"] : [\"add\", pkg];\n const result = spawnSync(cmd, args, { cwd: projectRoot, stdio: \"inherit\" });\n return result.status === 0;\n}\n\nexport function renderInitFile(ingestUrl: string): string {\n return `import { initPixel } from \"@kenkaiiii/gg-pixel\";\n\nconst key = process.env.GG_PIXEL_KEY;\nif (key) {\n initPixel({\n projectKey: key,\n sink: { kind: \"http\", ingestUrl: ${JSON.stringify(`${ingestUrl}/ingest`)} },\n });\n}\n`;\n}\n\nexport function writeEnvKey(envPath: string, key: string, value: string): void {\n if (existsSync(envPath)) {\n const current = readFileSync(envPath, \"utf8\");\n const lineRegex = new RegExp(`^${key}=.*$`, \"m\");\n if (lineRegex.test(current)) {\n writeFileSync(envPath, current.replace(lineRegex, `${key}=${value}`), \"utf8\");\n return;\n }\n const sep = current.endsWith(\"\\n\") || current.length === 0 ? \"\" : \"\\n\";\n appendFileSync(envPath, `${sep}${key}=${value}\\n`, \"utf8\");\n return;\n }\n writeFileSync(envPath, `${key}=${value}\\n`, \"utf8\");\n}\n\nexport function wireEntryFile(\n projectRoot: string,\n initFilePath: string,\n pkg: PackageJson,\n): EntryWiringResult {\n const entryPath = findEntryFile(projectRoot, pkg);\n if (!entryPath) return { kind: \"no_entry_found\" };\n\n let content: string;\n try {\n content = readFileSync(entryPath, \"utf8\");\n } catch (err) {\n return { kind: \"skipped\", reason: `unreadable: ${(err as Error).message}` };\n }\n\n if (content.includes(\"gg-pixel.init\")) {\n return { kind: \"already_present\", entryPath };\n }\n\n // Compute import specifier relative to the entry file.\n const fromDir = dirname(entryPath);\n let spec = relative(fromDir, initFilePath).split(sep).join(\"/\");\n if (!spec.startsWith(\".\")) spec = \"./\" + spec;\n\n const isCjs = isCommonJsEntry(entryPath, pkg);\n const importLine = isCjs\n ? `require(${JSON.stringify(spec)});`\n : `import ${JSON.stringify(spec)};`;\n\n // Inject at the top — after a shebang line and any leading \"use strict\",\n // but before all other code, so pixel hooks run before anything else.\n const lines = content.split(\"\\n\");\n let insertAt = 0;\n if (lines[0]?.startsWith(\"#!\")) insertAt = 1;\n while (\n insertAt < lines.length &&\n /^\\s*(?:[\"']use strict[\"']|\\/\\/|\\/\\*)/.test(lines[insertAt] ?? \"\")\n ) {\n insertAt++;\n }\n\n const updated = [...lines.slice(0, insertAt), importLine, ...lines.slice(insertAt)].join(\"\\n\");\n writeFileSync(entryPath, updated, \"utf8\");\n return { kind: \"injected\", entryPath };\n}\n\nfunction findEntryFile(projectRoot: string, pkg: PackageJson): string | null {\n const tryPath = (rel: string): string | null => {\n const p = join(projectRoot, rel);\n if (existsSync(p)) return p;\n // If user pointed `main` at .js but only the .ts source exists (common in TS projects).\n if (rel.endsWith(\".js\")) {\n const ts = join(projectRoot, rel.replace(/\\.js$/, \".ts\"));\n if (existsSync(ts)) return ts;\n }\n return null;\n };\n\n if (typeof pkg.bin === \"string\") {\n const found = tryPath(pkg.bin);\n if (found) return found;\n }\n if (pkg.bin && typeof pkg.bin === \"object\") {\n for (const value of Object.values(pkg.bin)) {\n if (typeof value === \"string\") {\n const found = tryPath(value);\n if (found) return found;\n }\n }\n }\n if (pkg.main) {\n const found = tryPath(pkg.main);\n if (found) return found;\n }\n if (pkg.module) {\n const found = tryPath(pkg.module);\n if (found) return found;\n }\n\n // Fall back to common conventions.\n const candidates = [\n \"src/index.ts\",\n \"src/index.tsx\",\n \"src/index.js\",\n \"src/index.mjs\",\n \"src/main.ts\",\n \"src/main.tsx\",\n \"src/main.js\",\n \"src/server.ts\",\n \"src/server.js\",\n \"src/app.ts\",\n \"src/app.js\",\n \"src/cli.ts\",\n \"src/cli.js\",\n \"index.ts\",\n \"index.tsx\",\n \"index.js\",\n \"index.mjs\",\n \"main.ts\",\n \"main.js\",\n \"server.ts\",\n \"server.js\",\n \"app.ts\",\n \"app.js\",\n ];\n for (const c of candidates) {\n const found = tryPath(c);\n if (found) return found;\n }\n return null;\n}\n\nfunction isCommonJsEntry(entryPath: string, pkg: PackageJson): boolean {\n if (entryPath.endsWith(\".cjs\")) return true;\n if (entryPath.endsWith(\".mjs\")) return false;\n if (entryPath.endsWith(\".ts\") || entryPath.endsWith(\".tsx\")) return false;\n // .js → governed by package.json type (default is \"commonjs\")\n return pkg.type !== \"module\";\n}\n\nexport function writeProjectsMapping(\n projectsJsonPath: string,\n projectId: string,\n name: string,\n path: string,\n): void {\n mkdirSync(dirname(projectsJsonPath), { recursive: true });\n let map: Record<string, { name: string; path: string }> = {};\n if (existsSync(projectsJsonPath)) {\n try {\n map = JSON.parse(readFileSync(projectsJsonPath, \"utf8\")) as typeof map;\n } catch {\n // start fresh on corrupt file\n }\n }\n map[projectId] = { name, path };\n writeFileSync(projectsJsonPath, `${JSON.stringify(map, null, 2)}\\n`, \"utf8\");\n}\n","import { installNodeAdapter, type NodeAdapter } from \"./adapters/node.js\";\nimport { HttpSink } from \"./core/sinks/http.js\";\nimport { LocalSqliteSink } from \"./core/sinks/local-sqlite.js\";\nimport type { PixelOptions, ReportInput, Sink, SinkConfig } from \"./core/types.js\";\n\nlet active: NodeAdapter | null = null;\n\nexport function initPixel(options: PixelOptions): NodeAdapter {\n if (active) {\n throw new Error(\"gg-pixel is already initialized; call closePixel() first\");\n }\n const sink = buildSink(options.sink);\n active = installNodeAdapter({\n projectKey: options.projectKey,\n runtime: options.runtime ?? defaultRuntime(),\n sink,\n captureConsoleErrors: options.captureConsoleErrors ?? true,\n captureConsoleWarnings: options.captureConsoleWarnings ?? false,\n captureUnhandledRejections: options.captureUnhandledRejections ?? true,\n captureUncaughtExceptions: options.captureUncaughtExceptions ?? true,\n });\n return active;\n}\n\nexport function reportPixel(input: ReportInput): void {\n if (!active) return;\n active.report(input);\n}\n\nexport async function flushPixel(): Promise<void> {\n if (!active) return;\n await active.flush();\n}\n\nexport async function closePixel(): Promise<void> {\n if (!active) return;\n await active.close();\n active = null;\n}\n\nfunction buildSink(config: SinkConfig): Sink {\n switch (config.kind) {\n case \"http\":\n return new HttpSink(config.ingestUrl, config.fetchFn);\n case \"local\":\n return new LocalSqliteSink(config.path);\n case \"custom\":\n return config.sink;\n }\n}\n\nfunction defaultRuntime(): string {\n const v = process.versions.node;\n return `node-${v}`;\n}\n\nexport type {\n Level,\n PixelOptions,\n ReportInput,\n Sink,\n SinkConfig,\n StackFrame,\n CodeContext,\n WireEvent,\n} from \"./core/types.js\";\n\nexport { install, DEFAULT_INGEST_URL } from \"./install.js\";\nexport type { InstallOptions, InstallResult, PackageManager } from \"./install.js\";\n"],"mappings":"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","names":["existsSync","readFileSync","mkdirSync","homedir","dirname","join","sep"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kenkaiiii/gg-pixel",
3
- "version": "4.3.62",
3
+ "version": "4.3.63",
4
4
  "type": "module",
5
5
  "description": "Universal error tracking pixel optimized for autonomous coding agents",
6
6
  "license": "MIT",