@kenkaiiii/gg-pixel 4.3.84 → 4.3.86
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 +59 -49
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +59 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +59 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -74,6 +74,12 @@ interface InstallOptions {
|
|
|
74
74
|
interface InstallResult {
|
|
75
75
|
projectId: string;
|
|
76
76
|
projectKey: string;
|
|
77
|
+
/**
|
|
78
|
+
* Per-project bearer secret returned by the server on creation. Stored in
|
|
79
|
+
* ~/.gg/projects.json and required for every /api/* call (read/list/patch/
|
|
80
|
+
* delete). Never leaves the user's machine — never inlined into source.
|
|
81
|
+
*/
|
|
82
|
+
projectSecret: string;
|
|
77
83
|
projectName: string;
|
|
78
84
|
projectKind: ProjectKind;
|
|
79
85
|
initFilePath: string;
|
package/dist/index.js
CHANGED
|
@@ -457,8 +457,8 @@ async function install(opts = {}) {
|
|
|
457
457
|
const existingKey = readEnvKey(envFilePath, "GG_PIXEL_KEY");
|
|
458
458
|
let created;
|
|
459
459
|
let reused = false;
|
|
460
|
-
if (existing && existingKey) {
|
|
461
|
-
created = { id: existing.id, key: existingKey };
|
|
460
|
+
if (existing && existing.secret && existingKey) {
|
|
461
|
+
created = { id: existing.id, key: existingKey, secret: existing.secret };
|
|
462
462
|
reused = true;
|
|
463
463
|
} else {
|
|
464
464
|
created = await createProject(fetchFn, ingestUrl, projectName);
|
|
@@ -475,10 +475,11 @@ async function install(opts = {}) {
|
|
|
475
475
|
if (kind !== "browser" && kind !== "tauri") {
|
|
476
476
|
writeEnvKey(envFilePath, "GG_PIXEL_KEY", created.key);
|
|
477
477
|
}
|
|
478
|
-
writeProjectsMapping(projectsJsonPath, created.id, projectName, nodeRoot);
|
|
478
|
+
writeProjectsMapping(projectsJsonPath, created.id, projectName, nodeRoot, created.secret);
|
|
479
479
|
return {
|
|
480
480
|
projectId: created.id,
|
|
481
481
|
projectKey: created.key,
|
|
482
|
+
projectSecret: created.secret,
|
|
482
483
|
projectName,
|
|
483
484
|
projectKind: kind,
|
|
484
485
|
initFilePath: wired.primaryInitPath,
|
|
@@ -535,8 +536,10 @@ async function createProject(fetchFn, ingestUrl, name) {
|
|
|
535
536
|
throw new Error(`POST /api/projects failed: ${res.status} ${await safeText(res)}`);
|
|
536
537
|
}
|
|
537
538
|
const body = await res.json();
|
|
538
|
-
if (!body.id || !body.key
|
|
539
|
-
|
|
539
|
+
if (!body.id || !body.key || !body.secret) {
|
|
540
|
+
throw new Error("response missing id/key/secret");
|
|
541
|
+
}
|
|
542
|
+
return { id: body.id, key: body.key, secret: body.secret };
|
|
540
543
|
}
|
|
541
544
|
async function safeText(r) {
|
|
542
545
|
try {
|
|
@@ -784,11 +787,11 @@ function wireNextjs({ projectRoot, projectKey, ingestUrl }) {
|
|
|
784
787
|
}
|
|
785
788
|
function writeNextInstrumentation(path, ingestUrl, projectKey) {
|
|
786
789
|
const existing = existsSync2(path) ? readFileSync2(path, "utf8") : "";
|
|
787
|
-
|
|
788
|
-
const
|
|
789
|
-
writeFileSync(path,
|
|
790
|
+
const block = nextInstrumentationBlock(ingestUrl, projectKey);
|
|
791
|
+
const next = upsertPixelBlock(existing, block);
|
|
792
|
+
if (next !== existing) writeFileSync(path, next, "utf8");
|
|
790
793
|
}
|
|
791
|
-
function
|
|
794
|
+
function nextInstrumentationBlock(ingestUrl, projectKey) {
|
|
792
795
|
const fallback = projectKey ? ` ?? ${JSON.stringify(projectKey)}` : "";
|
|
793
796
|
return `// Next.js auto-loads this file on server start. Pixel hooks the
|
|
794
797
|
// uncaughtExceptionMonitor + unhandledRejection events for API routes,
|
|
@@ -801,20 +804,7 @@ export async function register() {
|
|
|
801
804
|
sink: { kind: "http", ingestUrl: ${JSON.stringify(`${ingestUrl}/ingest`)} },
|
|
802
805
|
});
|
|
803
806
|
}
|
|
804
|
-
}
|
|
805
|
-
`;
|
|
806
|
-
}
|
|
807
|
-
function nextInstrumentationAppend(ingestUrl, projectKey) {
|
|
808
|
-
const fallback = projectKey ? ` ?? ${JSON.stringify(projectKey)}` : "";
|
|
809
|
-
return `// gg-pixel: server-side error tracking
|
|
810
|
-
import { initPixel } from "@kenkaiiii/gg-pixel";
|
|
811
|
-
if (typeof process !== "undefined" && process.env.NEXT_RUNTIME === "nodejs") {
|
|
812
|
-
initPixel({
|
|
813
|
-
projectKey: process.env.GG_PIXEL_KEY${fallback},
|
|
814
|
-
sink: { kind: "http", ingestUrl: ${JSON.stringify(`${ingestUrl}/ingest`)} },
|
|
815
|
-
});
|
|
816
|
-
}
|
|
817
|
-
`;
|
|
807
|
+
}`;
|
|
818
808
|
}
|
|
819
809
|
function findNextLayout(projectRoot) {
|
|
820
810
|
const candidates = [
|
|
@@ -947,25 +937,21 @@ function wireSveltekit({ projectRoot, projectKey, ingestUrl }) {
|
|
|
947
937
|
const serverPath = join2(projectRoot, "src/hooks.server.ts");
|
|
948
938
|
const clientPath = join2(projectRoot, "src/hooks.client.ts");
|
|
949
939
|
if (!existsSync2(dirname2(serverPath))) mkdirSync2(dirname2(serverPath), { recursive: true });
|
|
950
|
-
|
|
940
|
+
upsertPixelBlockInFile(
|
|
951
941
|
serverPath,
|
|
952
942
|
`import { initPixel } from "@kenkaiiii/gg-pixel";
|
|
953
943
|
initPixel({
|
|
954
944
|
projectKey: process.env.GG_PIXEL_KEY ?? ${JSON.stringify(projectKey)},
|
|
955
945
|
sink: { kind: "http", ingestUrl: ${JSON.stringify(`${ingestUrl}/ingest`)} },
|
|
956
|
-
})
|
|
957
|
-
`,
|
|
958
|
-
"@kenkaiiii/gg-pixel"
|
|
946
|
+
});`
|
|
959
947
|
);
|
|
960
|
-
|
|
948
|
+
upsertPixelBlockInFile(
|
|
961
949
|
clientPath,
|
|
962
950
|
`import { initPixel } from "@kenkaiiii/gg-pixel/browser";
|
|
963
951
|
initPixel({
|
|
964
952
|
projectKey: ${JSON.stringify(projectKey)},
|
|
965
953
|
ingestUrl: ${JSON.stringify(ingestUrl)},
|
|
966
|
-
})
|
|
967
|
-
`,
|
|
968
|
-
"@kenkaiiii/gg-pixel/browser"
|
|
954
|
+
});`
|
|
969
955
|
);
|
|
970
956
|
return {
|
|
971
957
|
primaryInitPath: clientPath,
|
|
@@ -1307,14 +1293,33 @@ function pickPath(root, candidates) {
|
|
|
1307
1293
|
}
|
|
1308
1294
|
return null;
|
|
1309
1295
|
}
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1296
|
+
var PIXEL_MARK_BEGIN = "// >>> gg-pixel auto-generated \u2014 do not edit between these markers <<<";
|
|
1297
|
+
var PIXEL_MARK_END = "// >>> /gg-pixel <<<";
|
|
1298
|
+
function wrapPixelBlock(content) {
|
|
1299
|
+
return `${PIXEL_MARK_BEGIN}
|
|
1300
|
+
${content.replace(/\s+$/, "")}
|
|
1301
|
+
${PIXEL_MARK_END}
|
|
1302
|
+
`;
|
|
1303
|
+
}
|
|
1304
|
+
function upsertPixelBlock(existing, block) {
|
|
1305
|
+
const wrapped = wrapPixelBlock(block);
|
|
1306
|
+
const beginIdx = existing.indexOf(PIXEL_MARK_BEGIN);
|
|
1307
|
+
if (beginIdx !== -1) {
|
|
1308
|
+
const endIdx = existing.indexOf(PIXEL_MARK_END, beginIdx);
|
|
1309
|
+
if (endIdx !== -1) {
|
|
1310
|
+
const after = endIdx + PIXEL_MARK_END.length;
|
|
1311
|
+
const trailNL = existing[after] === "\n" ? 1 : 0;
|
|
1312
|
+
return existing.slice(0, beginIdx) + wrapped + existing.slice(after + trailNL);
|
|
1313
|
+
}
|
|
1316
1314
|
}
|
|
1317
|
-
|
|
1315
|
+
if (existing.length === 0) return wrapped;
|
|
1316
|
+
const sep2 = existing.endsWith("\n") ? "" : "\n";
|
|
1317
|
+
return existing + sep2 + "\n" + wrapped;
|
|
1318
|
+
}
|
|
1319
|
+
function upsertPixelBlockInFile(filePath, block) {
|
|
1320
|
+
const existing = existsSync2(filePath) ? readFileSync2(filePath, "utf8") : "";
|
|
1321
|
+
const next = upsertPixelBlock(existing, block);
|
|
1322
|
+
if (next !== existing) writeFileSync(filePath, next, "utf8");
|
|
1318
1323
|
}
|
|
1319
1324
|
function injectImport(entryPath, initFilePath) {
|
|
1320
1325
|
let content;
|
|
@@ -1442,8 +1447,8 @@ async function installGo(ctx) {
|
|
|
1442
1447
|
const existingKey = readEnvKey(envFilePath, "GG_PIXEL_KEY");
|
|
1443
1448
|
let created;
|
|
1444
1449
|
let reused = false;
|
|
1445
|
-
if (existing && existingKey) {
|
|
1446
|
-
created = { id: existing.id, key: existingKey };
|
|
1450
|
+
if (existing && existing.secret && existingKey) {
|
|
1451
|
+
created = { id: existing.id, key: existingKey, secret: existing.secret };
|
|
1447
1452
|
reused = true;
|
|
1448
1453
|
} else {
|
|
1449
1454
|
created = await createProject(fetchFn, ingestUrl, projectName);
|
|
@@ -1471,10 +1476,11 @@ func init() {
|
|
|
1471
1476
|
"utf8"
|
|
1472
1477
|
);
|
|
1473
1478
|
writeEnvKey(envFilePath, "GG_PIXEL_KEY", created.key);
|
|
1474
|
-
writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot);
|
|
1479
|
+
writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot, created.secret);
|
|
1475
1480
|
return {
|
|
1476
1481
|
projectId: created.id,
|
|
1477
1482
|
projectKey: created.key,
|
|
1483
|
+
projectSecret: created.secret,
|
|
1478
1484
|
projectName,
|
|
1479
1485
|
projectKind: "go",
|
|
1480
1486
|
initFilePath,
|
|
@@ -1515,8 +1521,8 @@ async function installRuby(ctx) {
|
|
|
1515
1521
|
const existingKey = readEnvKey(envFilePath, "GG_PIXEL_KEY");
|
|
1516
1522
|
let created;
|
|
1517
1523
|
let reused = false;
|
|
1518
|
-
if (existing && existingKey) {
|
|
1519
|
-
created = { id: existing.id, key: existingKey };
|
|
1524
|
+
if (existing && existing.secret && existingKey) {
|
|
1525
|
+
created = { id: existing.id, key: existingKey, secret: existing.secret };
|
|
1520
1526
|
reused = true;
|
|
1521
1527
|
} else {
|
|
1522
1528
|
created = await createProject(fetchFn, ingestUrl, projectName);
|
|
@@ -1535,10 +1541,11 @@ GGPixel.init(
|
|
|
1535
1541
|
"utf8"
|
|
1536
1542
|
);
|
|
1537
1543
|
writeEnvKey(envFilePath, "GG_PIXEL_KEY", created.key);
|
|
1538
|
-
writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot);
|
|
1544
|
+
writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot, created.secret);
|
|
1539
1545
|
return {
|
|
1540
1546
|
projectId: created.id,
|
|
1541
1547
|
projectKey: created.key,
|
|
1548
|
+
projectSecret: created.secret,
|
|
1542
1549
|
projectName,
|
|
1543
1550
|
projectKind: "ruby",
|
|
1544
1551
|
initFilePath,
|
|
@@ -1591,8 +1598,8 @@ async function installPython(ctx) {
|
|
|
1591
1598
|
const existingKey = readEnvKey(envFilePath, "GG_PIXEL_KEY");
|
|
1592
1599
|
let created;
|
|
1593
1600
|
let reused = false;
|
|
1594
|
-
if (existing && existingKey) {
|
|
1595
|
-
created = { id: existing.id, key: existingKey };
|
|
1601
|
+
if (existing && existing.secret && existingKey) {
|
|
1602
|
+
created = { id: existing.id, key: existingKey, secret: existing.secret };
|
|
1596
1603
|
reused = true;
|
|
1597
1604
|
} else {
|
|
1598
1605
|
created = await createProject(fetchFn, ingestUrl, projectName);
|
|
@@ -1602,11 +1609,12 @@ async function installPython(ctx) {
|
|
|
1602
1609
|
const initFilePath = join2(projectRoot, "gg_pixel_init.py");
|
|
1603
1610
|
writeFileSync(initFilePath, renderPythonInitFile(ingestUrl, created.key), "utf8");
|
|
1604
1611
|
writeEnvKey(envFilePath, "GG_PIXEL_KEY", created.key);
|
|
1605
|
-
writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot);
|
|
1612
|
+
writeProjectsMapping(projectsJsonPath, created.id, projectName, projectRoot, created.secret);
|
|
1606
1613
|
const entryWiring = wirePythonEntry(projectRoot, initFilePath);
|
|
1607
1614
|
return {
|
|
1608
1615
|
projectId: created.id,
|
|
1609
1616
|
projectKey: created.key,
|
|
1617
|
+
projectSecret: created.secret,
|
|
1610
1618
|
projectName,
|
|
1611
1619
|
projectKind: "python",
|
|
1612
1620
|
initFilePath,
|
|
@@ -1724,7 +1732,7 @@ function findPythonEntryFile(projectRoot) {
|
|
|
1724
1732
|
}
|
|
1725
1733
|
return null;
|
|
1726
1734
|
}
|
|
1727
|
-
function writeProjectsMapping(projectsJsonPath, projectId, name, path) {
|
|
1735
|
+
function writeProjectsMapping(projectsJsonPath, projectId, name, path, secret) {
|
|
1728
1736
|
mkdirSync2(dirname2(projectsJsonPath), { recursive: true });
|
|
1729
1737
|
let map = {};
|
|
1730
1738
|
if (existsSync2(projectsJsonPath)) {
|
|
@@ -1733,7 +1741,9 @@ function writeProjectsMapping(projectsJsonPath, projectId, name, path) {
|
|
|
1733
1741
|
} catch {
|
|
1734
1742
|
}
|
|
1735
1743
|
}
|
|
1736
|
-
|
|
1744
|
+
const entry = { name, path };
|
|
1745
|
+
if (secret) entry.secret = secret;
|
|
1746
|
+
map[projectId] = entry;
|
|
1737
1747
|
writeFileSync(projectsJsonPath, `${JSON.stringify(map, null, 2)}
|
|
1738
1748
|
`, "utf8");
|
|
1739
1749
|
}
|