@kenkaiiii/gg-pixel 4.3.89 → 4.3.91
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 +10 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +213 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +56 -1
- package/dist/index.d.ts +56 -1
- package/dist/index.js +210 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -25,7 +25,9 @@ __export(index_exports, {
|
|
|
25
25
|
flushPixel: () => flushPixel,
|
|
26
26
|
initPixel: () => initPixel,
|
|
27
27
|
install: () => install,
|
|
28
|
-
|
|
28
|
+
isInstallProbeFingerprint: () => isInstallProbeFingerprint,
|
|
29
|
+
reportPixel: () => reportPixel,
|
|
30
|
+
verifyInstall: () => verifyInstall
|
|
29
31
|
});
|
|
30
32
|
module.exports = __toCommonJS(index_exports);
|
|
31
33
|
|
|
@@ -520,6 +522,7 @@ async function install(opts = {}) {
|
|
|
520
522
|
projectSecret: created.secret,
|
|
521
523
|
projectName,
|
|
522
524
|
projectKind: kind,
|
|
525
|
+
projectRoot: nodeRoot,
|
|
523
526
|
initFilePath: wired.primaryInitPath,
|
|
524
527
|
envFilePath,
|
|
525
528
|
projectsJsonPath,
|
|
@@ -1122,6 +1125,11 @@ function wireElectron({ projectRoot, pkg, projectKey, ingestUrl }) {
|
|
|
1122
1125
|
"renderer.ts",
|
|
1123
1126
|
"renderer.tsx",
|
|
1124
1127
|
"renderer.js",
|
|
1128
|
+
// `src/renderer.{ts,tsx,js}` is the convention used by multi-window
|
|
1129
|
+
// Electron apps that keep all renderer entries in src/.
|
|
1130
|
+
"src/renderer.ts",
|
|
1131
|
+
"src/renderer.tsx",
|
|
1132
|
+
"src/renderer.js",
|
|
1125
1133
|
"src/index.tsx",
|
|
1126
1134
|
"src/index.jsx",
|
|
1127
1135
|
"src/main.tsx",
|
|
@@ -1177,7 +1185,7 @@ function resolveMainEntryFromPkg(projectRoot, pkg) {
|
|
|
1177
1185
|
"electron/main.ts"
|
|
1178
1186
|
]);
|
|
1179
1187
|
}
|
|
1180
|
-
var RENDERER_HTML_DIRS = ["ui", "renderer", "src/renderer", "public", "static"];
|
|
1188
|
+
var RENDERER_HTML_DIRS = ["ui", "renderer", "src/renderer", "src", "public", "static"];
|
|
1181
1189
|
function findRendererHtmlFiles(projectRoot) {
|
|
1182
1190
|
for (const dir of RENDERER_HTML_DIRS) {
|
|
1183
1191
|
const root = (0, import_node_path2.join)(projectRoot, dir);
|
|
@@ -1594,6 +1602,7 @@ func init() {
|
|
|
1594
1602
|
projectSecret: created.secret,
|
|
1595
1603
|
projectName,
|
|
1596
1604
|
projectKind: "go",
|
|
1605
|
+
projectRoot,
|
|
1597
1606
|
initFilePath,
|
|
1598
1607
|
envFilePath,
|
|
1599
1608
|
projectsJsonPath,
|
|
@@ -1659,6 +1668,7 @@ GGPixel.init(
|
|
|
1659
1668
|
projectSecret: created.secret,
|
|
1660
1669
|
projectName,
|
|
1661
1670
|
projectKind: "ruby",
|
|
1671
|
+
projectRoot,
|
|
1662
1672
|
initFilePath,
|
|
1663
1673
|
envFilePath,
|
|
1664
1674
|
projectsJsonPath,
|
|
@@ -1728,6 +1738,7 @@ async function installPython(ctx) {
|
|
|
1728
1738
|
projectSecret: created.secret,
|
|
1729
1739
|
projectName,
|
|
1730
1740
|
projectKind: "python",
|
|
1741
|
+
projectRoot,
|
|
1731
1742
|
initFilePath,
|
|
1732
1743
|
envFilePath,
|
|
1733
1744
|
projectsJsonPath,
|
|
@@ -1859,6 +1870,203 @@ function writeProjectsMapping(projectsJsonPath, projectId, name, path, secret) {
|
|
|
1859
1870
|
`, "utf8");
|
|
1860
1871
|
}
|
|
1861
1872
|
|
|
1873
|
+
// src/verify.ts
|
|
1874
|
+
var import_node_child_process3 = require("child_process");
|
|
1875
|
+
var import_node_fs4 = require("fs");
|
|
1876
|
+
var import_node_path3 = require("path");
|
|
1877
|
+
var import_node_crypto3 = require("crypto");
|
|
1878
|
+
var PROBE_FINGERPRINT_PREFIX = "__pixel_install_probe__";
|
|
1879
|
+
function isInstallProbeFingerprint(fingerprint2) {
|
|
1880
|
+
return typeof fingerprint2 === "string" && fingerprint2.startsWith(PROBE_FINGERPRINT_PREFIX);
|
|
1881
|
+
}
|
|
1882
|
+
async function verifyInstall(opts) {
|
|
1883
|
+
const fetchFn = opts.fetchFn ?? fetch;
|
|
1884
|
+
const spawnFn = opts.spawnFn ?? import_node_child_process3.spawn;
|
|
1885
|
+
const timeoutMs = opts.timeoutMs ?? 5e3;
|
|
1886
|
+
const ingest = opts.ingestUrl.replace(/\/+$/, "");
|
|
1887
|
+
const fingerprint2 = `${PROBE_FINGERPRINT_PREFIX}${(0, import_node_crypto3.randomBytes)(6).toString("hex")}`;
|
|
1888
|
+
const start = Date.now();
|
|
1889
|
+
let method;
|
|
1890
|
+
let probeError = null;
|
|
1891
|
+
if (opts.skipChildProbe) {
|
|
1892
|
+
try {
|
|
1893
|
+
await postDirectIngest({
|
|
1894
|
+
ingestUrl: ingest,
|
|
1895
|
+
projectKey: opts.projectKey,
|
|
1896
|
+
fingerprint: fingerprint2,
|
|
1897
|
+
fetchFn
|
|
1898
|
+
});
|
|
1899
|
+
method = "direct_ingest";
|
|
1900
|
+
} catch (err) {
|
|
1901
|
+
return {
|
|
1902
|
+
kind: "failed",
|
|
1903
|
+
reason: "Direct ingest failed",
|
|
1904
|
+
hint: err.message
|
|
1905
|
+
};
|
|
1906
|
+
}
|
|
1907
|
+
} else {
|
|
1908
|
+
try {
|
|
1909
|
+
await runChildProbe({
|
|
1910
|
+
projectRoot: opts.projectRoot,
|
|
1911
|
+
ingestUrl: ingest,
|
|
1912
|
+
projectKey: opts.projectKey,
|
|
1913
|
+
fingerprint: fingerprint2,
|
|
1914
|
+
spawnFn
|
|
1915
|
+
});
|
|
1916
|
+
method = "child_process";
|
|
1917
|
+
} catch (err) {
|
|
1918
|
+
probeError = err.message;
|
|
1919
|
+
try {
|
|
1920
|
+
await postDirectIngest({
|
|
1921
|
+
ingestUrl: ingest,
|
|
1922
|
+
projectKey: opts.projectKey,
|
|
1923
|
+
fingerprint: fingerprint2,
|
|
1924
|
+
fetchFn
|
|
1925
|
+
});
|
|
1926
|
+
method = "direct_ingest";
|
|
1927
|
+
} catch (err2) {
|
|
1928
|
+
return {
|
|
1929
|
+
kind: "failed",
|
|
1930
|
+
reason: "Could not deliver probe event",
|
|
1931
|
+
hint: `child-process: ${probeError}; direct ingest: ${err2.message}`
|
|
1932
|
+
};
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
const probeRow = await pollForFingerprint({
|
|
1937
|
+
ingestUrl: ingest,
|
|
1938
|
+
projectId: opts.projectId,
|
|
1939
|
+
projectSecret: opts.projectSecret,
|
|
1940
|
+
fingerprint: fingerprint2,
|
|
1941
|
+
timeoutMs,
|
|
1942
|
+
fetchFn
|
|
1943
|
+
});
|
|
1944
|
+
if (!probeRow) {
|
|
1945
|
+
return {
|
|
1946
|
+
kind: "failed",
|
|
1947
|
+
reason: `Probe sent (${method}) but didn't appear in /api/projects/${opts.projectId}/errors within ${timeoutMs}ms`,
|
|
1948
|
+
hint: probeError ?? void 0
|
|
1949
|
+
};
|
|
1950
|
+
}
|
|
1951
|
+
try {
|
|
1952
|
+
await fetchFn(`${ingest}/api/errors/${probeRow.id}`, {
|
|
1953
|
+
method: "DELETE",
|
|
1954
|
+
headers: { authorization: `Bearer ${opts.projectSecret}` }
|
|
1955
|
+
});
|
|
1956
|
+
} catch {
|
|
1957
|
+
}
|
|
1958
|
+
return {
|
|
1959
|
+
kind: "ok",
|
|
1960
|
+
method,
|
|
1961
|
+
latencyMs: Date.now() - start
|
|
1962
|
+
};
|
|
1963
|
+
}
|
|
1964
|
+
async function runChildProbe(args) {
|
|
1965
|
+
const ggDir = (0, import_node_path3.join)(args.projectRoot, ".gg");
|
|
1966
|
+
if (!(0, import_node_fs4.existsSync)(ggDir)) (0, import_node_fs4.mkdirSync)(ggDir, { recursive: true });
|
|
1967
|
+
const probePath = (0, import_node_path3.join)(ggDir, `pixel-probe-${(0, import_node_crypto3.randomBytes)(4).toString("hex")}.mjs`);
|
|
1968
|
+
const script = `import "@kenkaiiii/gg-pixel";
|
|
1969
|
+
const body = ${JSON.stringify({
|
|
1970
|
+
project_key: args.projectKey,
|
|
1971
|
+
fingerprint: args.fingerprint,
|
|
1972
|
+
type: "InstallProbe",
|
|
1973
|
+
message: "Install verification probe \u2014 auto-generated, safe to delete",
|
|
1974
|
+
stack: [],
|
|
1975
|
+
code_context: null,
|
|
1976
|
+
runtime: "",
|
|
1977
|
+
manual_report: true,
|
|
1978
|
+
level: "error"
|
|
1979
|
+
})};
|
|
1980
|
+
body.event_id = "evt_probe_" + crypto.randomUUID();
|
|
1981
|
+
body.runtime = "installer-node-" + process.versions.node;
|
|
1982
|
+
body.occurred_at = new Date().toISOString();
|
|
1983
|
+
const res = await fetch(${JSON.stringify(args.ingestUrl + "/ingest")}, {
|
|
1984
|
+
method: "POST",
|
|
1985
|
+
headers: { "content-type": "application/json" },
|
|
1986
|
+
body: JSON.stringify(body),
|
|
1987
|
+
});
|
|
1988
|
+
if (!res.ok) {
|
|
1989
|
+
const txt = await res.text().catch(() => "");
|
|
1990
|
+
console.error("probe ingest failed: status=" + res.status + " body=" + txt.slice(0, 200));
|
|
1991
|
+
process.exit(1);
|
|
1992
|
+
}
|
|
1993
|
+
`;
|
|
1994
|
+
(0, import_node_fs4.writeFileSync)(probePath, script, "utf8");
|
|
1995
|
+
try {
|
|
1996
|
+
await new Promise((resolve2, reject) => {
|
|
1997
|
+
const opts = { cwd: args.projectRoot, stdio: "pipe" };
|
|
1998
|
+
const child = args.spawnFn("node", [probePath], opts);
|
|
1999
|
+
let stderr = "";
|
|
2000
|
+
child.stderr?.on("data", (b) => {
|
|
2001
|
+
stderr += b.toString();
|
|
2002
|
+
});
|
|
2003
|
+
const timer = setTimeout(() => {
|
|
2004
|
+
child.kill("SIGKILL");
|
|
2005
|
+
reject(new Error("Probe child timed out after 10s"));
|
|
2006
|
+
}, 1e4);
|
|
2007
|
+
child.on("error", (err) => {
|
|
2008
|
+
clearTimeout(timer);
|
|
2009
|
+
reject(err);
|
|
2010
|
+
});
|
|
2011
|
+
child.on("exit", (code) => {
|
|
2012
|
+
clearTimeout(timer);
|
|
2013
|
+
if (code === 0) resolve2();
|
|
2014
|
+
else reject(new Error(`Probe exited code=${code}; stderr: ${stderr.trim().slice(0, 400)}`));
|
|
2015
|
+
});
|
|
2016
|
+
});
|
|
2017
|
+
} finally {
|
|
2018
|
+
try {
|
|
2019
|
+
(0, import_node_fs4.unlinkSync)(probePath);
|
|
2020
|
+
} catch {
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
async function postDirectIngest(args) {
|
|
2025
|
+
const res = await args.fetchFn(`${args.ingestUrl}/ingest`, {
|
|
2026
|
+
method: "POST",
|
|
2027
|
+
headers: { "content-type": "application/json" },
|
|
2028
|
+
body: JSON.stringify({
|
|
2029
|
+
event_id: `evt_probe_${(0, import_node_crypto3.randomBytes)(8).toString("hex")}`,
|
|
2030
|
+
project_key: args.projectKey,
|
|
2031
|
+
fingerprint: args.fingerprint,
|
|
2032
|
+
type: "InstallProbe",
|
|
2033
|
+
message: "Install verification probe",
|
|
2034
|
+
stack: [],
|
|
2035
|
+
code_context: null,
|
|
2036
|
+
runtime: `installer-node-${process.versions.node}`,
|
|
2037
|
+
manual_report: true,
|
|
2038
|
+
level: "error",
|
|
2039
|
+
occurred_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
2040
|
+
})
|
|
2041
|
+
});
|
|
2042
|
+
if (!res.ok) {
|
|
2043
|
+
let body = "";
|
|
2044
|
+
try {
|
|
2045
|
+
body = await res.text();
|
|
2046
|
+
} catch {
|
|
2047
|
+
}
|
|
2048
|
+
throw new Error(`POST /ingest \u2192 ${res.status} ${body.slice(0, 200)}`);
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
async function pollForFingerprint(args) {
|
|
2052
|
+
const deadline = Date.now() + args.timeoutMs;
|
|
2053
|
+
while (Date.now() < deadline) {
|
|
2054
|
+
try {
|
|
2055
|
+
const res = await args.fetchFn(`${args.ingestUrl}/api/projects/${args.projectId}/errors`, {
|
|
2056
|
+
headers: { authorization: `Bearer ${args.projectSecret}` }
|
|
2057
|
+
});
|
|
2058
|
+
if (res.ok) {
|
|
2059
|
+
const body = await res.json();
|
|
2060
|
+
const match = body.errors.find((e) => e.fingerprint === args.fingerprint);
|
|
2061
|
+
if (match) return { id: match.id };
|
|
2062
|
+
}
|
|
2063
|
+
} catch {
|
|
2064
|
+
}
|
|
2065
|
+
await new Promise((r) => setTimeout(r, 250));
|
|
2066
|
+
}
|
|
2067
|
+
return null;
|
|
2068
|
+
}
|
|
2069
|
+
|
|
1862
2070
|
// src/index.ts
|
|
1863
2071
|
var active = null;
|
|
1864
2072
|
function initPixel(options) {
|
|
@@ -1911,6 +2119,8 @@ function defaultRuntime() {
|
|
|
1911
2119
|
flushPixel,
|
|
1912
2120
|
initPixel,
|
|
1913
2121
|
install,
|
|
1914
|
-
|
|
2122
|
+
isInstallProbeFingerprint,
|
|
2123
|
+
reportPixel,
|
|
2124
|
+
verifyInstall
|
|
1915
2125
|
});
|
|
1916
2126
|
//# sourceMappingURL=index.cjs.map
|