@gurulu/cli 1.6.5 → 1.6.7
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/bin.js +186 -85
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +186 -85
- package/dist/lib/detect.d.ts +6 -0
- package/dist/lib/detect.d.ts.map +1 -1
- package/dist/lib/detect.js +54 -5
- package/dist/wizard/run.d.ts.map +1 -1
- package/dist/wizard/verify.d.ts +4 -0
- package/dist/wizard/verify.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -39672,6 +39672,84 @@ var validateCmd = defineCommand({
|
|
|
39672
39672
|
}
|
|
39673
39673
|
});
|
|
39674
39674
|
|
|
39675
|
+
// src/wizard/verify.ts
|
|
39676
|
+
import { randomUUID } from "node:crypto";
|
|
39677
|
+
function deriveIngestEndpoint(apiEndpoint) {
|
|
39678
|
+
try {
|
|
39679
|
+
const u3 = new URL(apiEndpoint);
|
|
39680
|
+
if (u3.hostname.startsWith("api.")) {
|
|
39681
|
+
u3.hostname = `ingest.${u3.hostname.slice(4)}`;
|
|
39682
|
+
return u3.origin;
|
|
39683
|
+
}
|
|
39684
|
+
if (u3.hostname === "localhost" || u3.hostname === "127.0.0.1")
|
|
39685
|
+
return apiEndpoint;
|
|
39686
|
+
return u3.origin;
|
|
39687
|
+
} catch {
|
|
39688
|
+
return "https://ingest.gurulu.io";
|
|
39689
|
+
}
|
|
39690
|
+
}
|
|
39691
|
+
async function selfVerify(opts) {
|
|
39692
|
+
const fetchImpl2 = opts.fetchImpl ?? fetch;
|
|
39693
|
+
const nowMs = (opts.now ?? Date.now)();
|
|
39694
|
+
const anonymousId = `gurulu_verify_${nowMs.toString(36)}${Math.floor(nowMs % 1000)}`;
|
|
39695
|
+
const sessionId = randomUUID();
|
|
39696
|
+
const eventType = opts.eventType ?? "interaction";
|
|
39697
|
+
const payload = {
|
|
39698
|
+
event_key: opts.eventKey,
|
|
39699
|
+
event_type: eventType,
|
|
39700
|
+
occurred_at: new Date(nowMs).toISOString(),
|
|
39701
|
+
anonymous_id: anonymousId,
|
|
39702
|
+
session_id: sessionId,
|
|
39703
|
+
producer: opts.producer ?? "sdk_web",
|
|
39704
|
+
properties: { ...opts.properties ?? {}, gurulu_install_verify: true },
|
|
39705
|
+
test_mode: true
|
|
39706
|
+
};
|
|
39707
|
+
let resp;
|
|
39708
|
+
try {
|
|
39709
|
+
const r3 = await fetchImpl2(`${opts.ingestEndpoint}/v1/ingest/event`, {
|
|
39710
|
+
method: "POST",
|
|
39711
|
+
headers: {
|
|
39712
|
+
"Content-Type": "application/json",
|
|
39713
|
+
Authorization: `Bearer ${opts.writeKey}`
|
|
39714
|
+
},
|
|
39715
|
+
body: JSON.stringify(payload)
|
|
39716
|
+
});
|
|
39717
|
+
if (r3.status === 401 || r3.status === 403) {
|
|
39718
|
+
return mk("error", false, [`ingest auth reddetti (${r3.status}) — write key geçersiz`], opts, anonymousId);
|
|
39719
|
+
}
|
|
39720
|
+
if (r3.status >= 500) {
|
|
39721
|
+
return mk("error", false, [`ingest ${r3.status} — sunucu hatası`], opts, anonymousId);
|
|
39722
|
+
}
|
|
39723
|
+
resp = await r3.json().catch(() => ({}));
|
|
39724
|
+
} catch (e2) {
|
|
39725
|
+
const msg = e2 instanceof Error ? e2.message : String(e2);
|
|
39726
|
+
return mk("error", false, [`ingest erişilemedi: ${msg}`], opts, anonymousId);
|
|
39727
|
+
}
|
|
39728
|
+
const decision = resp.decision ?? "error";
|
|
39729
|
+
const ok = decision === "accept" || decision === "warn";
|
|
39730
|
+
const reasons = (resp.reasons ?? []).map((x2) => String(x2));
|
|
39731
|
+
const result = mk(decision, ok, reasons, opts, anonymousId);
|
|
39732
|
+
if (ok && opts.client) {
|
|
39733
|
+
result.landedInClickhouse = await pollRecent(opts.client, opts.eventKey, anonymousId);
|
|
39734
|
+
}
|
|
39735
|
+
return result;
|
|
39736
|
+
}
|
|
39737
|
+
function mk(decision, ok, reasons, opts, anonymousId) {
|
|
39738
|
+
return { ok, decision, reasons, eventKey: opts.eventKey, anonymousId };
|
|
39739
|
+
}
|
|
39740
|
+
async function pollRecent(client, eventKey, anonymousId, attempts = 8, delayMs = 3000) {
|
|
39741
|
+
for (let i2 = 0;i2 < attempts; i2++) {
|
|
39742
|
+
try {
|
|
39743
|
+
const res = await client.recentEvents({ event_key: eventKey, limit: 50 });
|
|
39744
|
+
if (res.events.some((e2) => e2.anonymous_id === anonymousId))
|
|
39745
|
+
return true;
|
|
39746
|
+
} catch {}
|
|
39747
|
+
if (i2 < attempts - 1)
|
|
39748
|
+
await new Promise((r3) => setTimeout(r3, delayMs));
|
|
39749
|
+
}
|
|
39750
|
+
return false;
|
|
39751
|
+
}
|
|
39752
|
+
|
|
39675
39753
|
// src/commands/doctor.ts
|
|
39676
39754
|
async function runDoctor(opts = {}) {
|
|
39677
39755
|
const cwd = opts.cwd ?? process.cwd();
|
|
@@ -39780,6 +39858,39 @@ async function runDoctor(opts = {}) {
|
|
|
39780
39858
|
message: `health overview unavailable: ${err instanceof Error ? err.message : String(err)}`
|
|
39781
39859
|
});
|
|
39782
39860
|
}
|
|
39861
|
+
if (manifest && manifest.events.length > 0) {
|
|
39862
|
+
const candidate = manifest.events.find((e2) => e2.lifecycle === "active" && e2.type === "interaction" && e2.producerAllowed.includes("sdk_web"));
|
|
39863
|
+
if (candidate) {
|
|
39864
|
+
const props = {};
|
|
39865
|
+
for (const pr of candidate.properties) {
|
|
39866
|
+
if (!pr.required)
|
|
39867
|
+
continue;
|
|
39868
|
+
props[pr.name] = pr.type === "number" ? 1 : pr.type === "boolean" ? true : pr.type === "array" ? [] : pr.type === "json" ? {} : "e2e";
|
|
39869
|
+
}
|
|
39870
|
+
const vr = await selfVerify({
|
|
39871
|
+
ingestEndpoint: deriveIngestEndpoint(project.endpoint ?? cred.endpoint),
|
|
39872
|
+
writeKey: cred.apiKey,
|
|
39873
|
+
eventKey: candidate.key,
|
|
39874
|
+
eventType: candidate.type,
|
|
39875
|
+
producer: "sdk_web",
|
|
39876
|
+
properties: props,
|
|
39877
|
+
client
|
|
39878
|
+
});
|
|
39879
|
+
const landed = vr.landedInClickhouse;
|
|
39880
|
+
checks.push({
|
|
39881
|
+
name: "end_to_end",
|
|
39882
|
+
status: landed === true ? "pass" : vr.ok ? "warn" : "fail",
|
|
39883
|
+
message: landed === true ? "test event ingest→pipeline→dashboard ulaştı (uçtan uca çalışıyor)" : vr.ok ? "ingest kabul etti ama event ~24sn'de dashboard'a ULAŞMADI — pipeline gecikmesi/sorunu" : `test event '${candidate.key}' ${vr.decision}: ${vr.reasons[0] ?? "doğrulanamadı"}`,
|
|
39884
|
+
detail: { decision: vr.decision, landed_in_clickhouse: landed ?? null }
|
|
39885
|
+
});
|
|
39886
|
+
} else {
|
|
39887
|
+
checks.push({
|
|
39888
|
+
name: "end_to_end",
|
|
39889
|
+
status: "skip",
|
|
39890
|
+
message: "uygun test event yok (aktif interaction + sdk_web producer) — E2E atlandı"
|
|
39891
|
+
});
|
|
39892
|
+
}
|
|
39893
|
+
}
|
|
39783
39894
|
try {
|
|
39784
39895
|
const scan = runValidate({ cwd });
|
|
39785
39896
|
const total = scan.deprecated_calls.length + scan.unknown_calls.length;
|
|
@@ -40223,7 +40334,7 @@ var pullCmd = defineCommand({
|
|
|
40223
40334
|
});
|
|
40224
40335
|
|
|
40225
40336
|
// src/lib/detect.ts
|
|
40226
|
-
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
40337
|
+
import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync4 } from "node:fs";
|
|
40227
40338
|
import { dirname as dirname2, join as join5, parse } from "node:path";
|
|
40228
40339
|
var COMPETITOR_DEP_MAP = {
|
|
40229
40340
|
"posthog-js": "posthog",
|
|
@@ -40389,11 +40500,51 @@ function detectLlmFrameworks(pkg) {
|
|
|
40389
40500
|
}
|
|
40390
40501
|
return [...found];
|
|
40391
40502
|
}
|
|
40503
|
+
function expandWorkspaceGlobs(rootDir, patterns) {
|
|
40504
|
+
const out = [];
|
|
40505
|
+
for (const pat of patterns) {
|
|
40506
|
+
if (pat.endsWith("/*")) {
|
|
40507
|
+
const base = join5(rootDir, pat.slice(0, -2));
|
|
40508
|
+
if (!existsSync4(base))
|
|
40509
|
+
continue;
|
|
40510
|
+
try {
|
|
40511
|
+
for (const name of readdirSync2(base)) {
|
|
40512
|
+
const d2 = join5(base, name);
|
|
40513
|
+
if (existsSync4(join5(d2, "package.json")))
|
|
40514
|
+
out.push(d2);
|
|
40515
|
+
}
|
|
40516
|
+
} catch {}
|
|
40517
|
+
} else {
|
|
40518
|
+
const d2 = join5(rootDir, pat);
|
|
40519
|
+
if (existsSync4(join5(d2, "package.json")))
|
|
40520
|
+
out.push(d2);
|
|
40521
|
+
}
|
|
40522
|
+
}
|
|
40523
|
+
return out;
|
|
40524
|
+
}
|
|
40525
|
+
function findWorkspaceFrameworkPackage(rootDir, pkg) {
|
|
40526
|
+
const patterns = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces?.packages ?? [];
|
|
40527
|
+
if (patterns.length === 0)
|
|
40528
|
+
return null;
|
|
40529
|
+
let fallback = null;
|
|
40530
|
+
for (const d2 of expandWorkspaceGlobs(rootDir, patterns)) {
|
|
40531
|
+
const p = readPackageJson(d2);
|
|
40532
|
+
if (!p)
|
|
40533
|
+
continue;
|
|
40534
|
+
const fw = detectFramework(p, d2);
|
|
40535
|
+
if (frameworkRuntime(fw) === "browser")
|
|
40536
|
+
return { dir: d2, framework: fw, pkg: p };
|
|
40537
|
+
if (fw !== "unknown" && !fallback)
|
|
40538
|
+
fallback = { dir: d2, framework: fw, pkg: p };
|
|
40539
|
+
}
|
|
40540
|
+
return fallback;
|
|
40541
|
+
}
|
|
40392
40542
|
function detectProject(dir) {
|
|
40393
40543
|
const pkg = readPackageJson(dir);
|
|
40394
40544
|
let framework = detectFramework(pkg, dir);
|
|
40395
40545
|
const { root, isMonorepo } = findWorkspaceRoot(dir);
|
|
40396
40546
|
let effectivePkg = pkg;
|
|
40547
|
+
let appDir = dir;
|
|
40397
40548
|
if (framework === "unknown" && isMonorepo && root !== dir) {
|
|
40398
40549
|
const rootPkg = readPackageJson(root);
|
|
40399
40550
|
const rootFw = detectFramework(rootPkg, root);
|
|
@@ -40402,19 +40553,28 @@ function detectProject(dir) {
|
|
|
40402
40553
|
effectivePkg = pkg ?? rootPkg;
|
|
40403
40554
|
}
|
|
40404
40555
|
}
|
|
40556
|
+
if (framework === "unknown" && pkg?.workspaces) {
|
|
40557
|
+
const found = findWorkspaceFrameworkPackage(dir, pkg);
|
|
40558
|
+
if (found) {
|
|
40559
|
+
framework = found.framework;
|
|
40560
|
+
appDir = found.dir;
|
|
40561
|
+
effectivePkg = found.pkg;
|
|
40562
|
+
}
|
|
40563
|
+
}
|
|
40405
40564
|
return {
|
|
40406
40565
|
dir,
|
|
40407
40566
|
hasPackageJson: pkg !== null,
|
|
40408
40567
|
framework,
|
|
40409
40568
|
runtime: frameworkRuntime(framework),
|
|
40410
40569
|
packageManager: detectPackageManager(dir),
|
|
40411
|
-
packageJson:
|
|
40412
|
-
llmFrameworks: detectLlmFrameworks(
|
|
40570
|
+
packageJson: effectivePkg,
|
|
40571
|
+
llmFrameworks: detectLlmFrameworks(effectivePkg),
|
|
40413
40572
|
moduleType: detectModuleType(effectivePkg),
|
|
40414
40573
|
rootDir: root,
|
|
40574
|
+
appDir,
|
|
40415
40575
|
isMonorepo,
|
|
40416
|
-
competitors: detectCompetitors(
|
|
40417
|
-
language: detectLanguage(
|
|
40576
|
+
competitors: detectCompetitors(effectivePkg),
|
|
40577
|
+
language: detectLanguage(appDir)
|
|
40418
40578
|
};
|
|
40419
40579
|
}
|
|
40420
40580
|
|
|
@@ -41626,7 +41786,7 @@ function createCheckpoint(cwd, snapshots = new Map) {
|
|
|
41626
41786
|
}
|
|
41627
41787
|
|
|
41628
41788
|
// src/wizard/context.ts
|
|
41629
|
-
import { readdirSync as
|
|
41789
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync9 } from "node:fs";
|
|
41630
41790
|
import { extname as extname2, join as join10, relative as relative2 } from "node:path";
|
|
41631
41791
|
var INCLUDE_EXT = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".vue", ".svelte", ".astro"]);
|
|
41632
41792
|
var SECRET_PATTERNS = [
|
|
@@ -41709,7 +41869,7 @@ function collectCandidates(dir, base, depth, maxDepth, out) {
|
|
|
41709
41869
|
return;
|
|
41710
41870
|
let entries;
|
|
41711
41871
|
try {
|
|
41712
|
-
entries =
|
|
41872
|
+
entries = readdirSync3(dir, { withFileTypes: true });
|
|
41713
41873
|
} catch {
|
|
41714
41874
|
return;
|
|
41715
41875
|
}
|
|
@@ -41931,81 +42091,6 @@ async function renderPlan(plan) {
|
|
|
41931
42091
|
return plan.events;
|
|
41932
42092
|
}
|
|
41933
42093
|
|
|
41934
|
-
// src/wizard/verify.ts
|
|
41935
|
-
function deriveIngestEndpoint(apiEndpoint) {
|
|
41936
|
-
try {
|
|
41937
|
-
const u3 = new URL(apiEndpoint);
|
|
41938
|
-
if (u3.hostname.startsWith("api.")) {
|
|
41939
|
-
u3.hostname = `ingest.${u3.hostname.slice(4)}`;
|
|
41940
|
-
return u3.origin;
|
|
41941
|
-
}
|
|
41942
|
-
if (u3.hostname === "localhost" || u3.hostname === "127.0.0.1")
|
|
41943
|
-
return apiEndpoint;
|
|
41944
|
-
return u3.origin;
|
|
41945
|
-
} catch {
|
|
41946
|
-
return "https://ingest.gurulu.io";
|
|
41947
|
-
}
|
|
41948
|
-
}
|
|
41949
|
-
async function selfVerify(opts) {
|
|
41950
|
-
const fetchImpl2 = opts.fetchImpl ?? fetch;
|
|
41951
|
-
const nowMs = (opts.now ?? Date.now)();
|
|
41952
|
-
const anonymousId = `gurulu_verify_${nowMs.toString(36)}${Math.floor(nowMs % 1000)}`;
|
|
41953
|
-
const eventType = opts.eventType ?? "interaction";
|
|
41954
|
-
const payload = {
|
|
41955
|
-
event_key: opts.eventKey,
|
|
41956
|
-
event_type: eventType,
|
|
41957
|
-
occurred_at: new Date(nowMs).toISOString(),
|
|
41958
|
-
anonymous_id: anonymousId,
|
|
41959
|
-
producer: "sdk",
|
|
41960
|
-
properties: { gurulu_install_verify: true },
|
|
41961
|
-
test_mode: true
|
|
41962
|
-
};
|
|
41963
|
-
let resp;
|
|
41964
|
-
try {
|
|
41965
|
-
const r3 = await fetchImpl2(`${opts.ingestEndpoint}/v1/ingest/event`, {
|
|
41966
|
-
method: "POST",
|
|
41967
|
-
headers: {
|
|
41968
|
-
"Content-Type": "application/json",
|
|
41969
|
-
Authorization: `Bearer ${opts.writeKey}`
|
|
41970
|
-
},
|
|
41971
|
-
body: JSON.stringify(payload)
|
|
41972
|
-
});
|
|
41973
|
-
if (r3.status === 401 || r3.status === 403) {
|
|
41974
|
-
return mk("error", false, [`ingest auth reddetti (${r3.status}) — write key geçersiz`], opts, anonymousId);
|
|
41975
|
-
}
|
|
41976
|
-
if (r3.status >= 500) {
|
|
41977
|
-
return mk("error", false, [`ingest ${r3.status} — sunucu hatası`], opts, anonymousId);
|
|
41978
|
-
}
|
|
41979
|
-
resp = await r3.json().catch(() => ({}));
|
|
41980
|
-
} catch (e2) {
|
|
41981
|
-
const msg = e2 instanceof Error ? e2.message : String(e2);
|
|
41982
|
-
return mk("error", false, [`ingest erişilemedi: ${msg}`], opts, anonymousId);
|
|
41983
|
-
}
|
|
41984
|
-
const decision = resp.decision ?? "error";
|
|
41985
|
-
const ok = decision === "accept" || decision === "warn";
|
|
41986
|
-
const reasons = (resp.reasons ?? []).map((x2) => String(x2));
|
|
41987
|
-
const result = mk(decision, ok, reasons, opts, anonymousId);
|
|
41988
|
-
if (ok && opts.client) {
|
|
41989
|
-
result.landedInClickhouse = await pollRecent(opts.client, opts.eventKey, anonymousId);
|
|
41990
|
-
}
|
|
41991
|
-
return result;
|
|
41992
|
-
}
|
|
41993
|
-
function mk(decision, ok, reasons, opts, anonymousId) {
|
|
41994
|
-
return { ok, decision, reasons, eventKey: opts.eventKey, anonymousId };
|
|
41995
|
-
}
|
|
41996
|
-
async function pollRecent(client, eventKey, anonymousId, attempts = 4, delayMs = 1500) {
|
|
41997
|
-
for (let i2 = 0;i2 < attempts; i2++) {
|
|
41998
|
-
try {
|
|
41999
|
-
const res = await client.recentEvents({ event_key: eventKey, limit: 50 });
|
|
42000
|
-
if (res.events.some((e2) => e2.anonymous_id === anonymousId))
|
|
42001
|
-
return true;
|
|
42002
|
-
} catch {}
|
|
42003
|
-
if (i2 < attempts - 1)
|
|
42004
|
-
await new Promise((r3) => setTimeout(r3, delayMs));
|
|
42005
|
-
}
|
|
42006
|
-
return false;
|
|
42007
|
-
}
|
|
42008
|
-
|
|
42009
42094
|
// src/wizard/wire.ts
|
|
42010
42095
|
import { existsSync as existsSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync10 } from "node:fs";
|
|
42011
42096
|
|
|
@@ -42381,6 +42466,10 @@ async function runWizard(opts) {
|
|
|
42381
42466
|
const { workspaceId, writeKey } = await resolveWorkspace(client, auth.workspaceId, opts);
|
|
42382
42467
|
phase(3, "Projeni tanıyoruz", "Kodun okunuyor; hangi kullanıcı olaylarını (ör. kayıt, satın alma) izleyeceğimiz planlanıyor.");
|
|
42383
42468
|
const detected = detectProject(opts.cwd);
|
|
42469
|
+
if (detected.appDir !== opts.cwd) {
|
|
42470
|
+
p4.log.info(c3.dim(`Monorepo: kurulum ${detected.framework} app'ine → ${detected.appDir}`));
|
|
42471
|
+
opts.cwd = detected.appDir;
|
|
42472
|
+
}
|
|
42384
42473
|
let framework = detected.framework;
|
|
42385
42474
|
if (opts.framework && FRAMEWORKS.includes(opts.framework)) {
|
|
42386
42475
|
framework = opts.framework;
|
|
@@ -42684,7 +42773,13 @@ ${captureGuide(approvedEvents, identifyHint, isNode)}`);
|
|
|
42684
42773
|
if (inj.strategy === "manual")
|
|
42685
42774
|
p4.log.message(plan.initSnippet);
|
|
42686
42775
|
}
|
|
42687
|
-
|
|
42776
|
+
const e2eOk = verifyResult?.landedInClickhouse === true;
|
|
42777
|
+
const e2eFailed = verifyResult != null && (verifyResult.landedInClickhouse === false || !verifyResult.ok);
|
|
42778
|
+
if (e2eFailed) {
|
|
42779
|
+
p4.outro(`${c3.bold("⚠ Kurulum yapıldı ama UÇTAN UCA DOĞRULANAMADI")} — kod + kayıt tamam, ama test event dashboard'a ulaşmadı (ingest kabul etti/pipeline'da kayboldu). ${c3.dim("Tekrar:")} ${c3.bold("gurulu doctor")}`);
|
|
42780
|
+
} else {
|
|
42781
|
+
p4.outro(`${c3.neon("\uD83E\uDD89 Hazır!")}${e2eOk ? c3.dim(" · uçtan uca doğrulandı") : ""} ${c3.dim("Doğrula:")} ${c3.bold("gurulu doctor")} ${c3.dim("·")} ${c3.dim("Dashboard:")} ${c3.cyan("https://dashboard.gurulu.io/app?onboard=done")}`);
|
|
42782
|
+
}
|
|
42688
42783
|
}
|
|
42689
42784
|
async function resolveWorkspace(client, authWorkspaceId, opts) {
|
|
42690
42785
|
if (opts.writeKey) {
|
|
@@ -42722,7 +42817,13 @@ function verifyLabel(v2) {
|
|
|
42722
42817
|
switch (v2.decision) {
|
|
42723
42818
|
case "accept":
|
|
42724
42819
|
case "warn":
|
|
42725
|
-
|
|
42820
|
+
if (v2.landedInClickhouse === false) {
|
|
42821
|
+
return "⚠ ingest kabul etti ama event dashboard'a ULAŞMADI (~24sn) — pipeline gecikmesi/sorunu; `gurulu doctor` ile tekrar dene";
|
|
42822
|
+
}
|
|
42823
|
+
if (v2.landedInClickhouse === true) {
|
|
42824
|
+
return "✓ uçtan uca doğrulandı — test event dashboard'a ulaştı";
|
|
42825
|
+
}
|
|
42826
|
+
return `✓ test event kabul edildi (${v2.decision})`;
|
|
42726
42827
|
case "quarantine":
|
|
42727
42828
|
return `⚠ event kayıtlı ama eksik prop (quarantine) — Gurulu'ya bağlısın`;
|
|
42728
42829
|
case "reject":
|
|
@@ -43133,7 +43234,7 @@ var uninstallCmd = defineCommand({
|
|
|
43133
43234
|
});
|
|
43134
43235
|
|
|
43135
43236
|
// src/index.ts
|
|
43136
|
-
var VERSION = "1.6.
|
|
43237
|
+
var VERSION = "1.6.7";
|
|
43137
43238
|
var mainCmd = defineCommand({
|
|
43138
43239
|
meta: {
|
|
43139
43240
|
name: "gurulu",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACrE;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,SAAS,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAuN/E;AA2BD,eAAO,MAAM,SAAS,qDAkBpB,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -39249,6 +39249,84 @@ var validateCmd = defineCommand({
|
|
|
39249
39249
|
}
|
|
39250
39250
|
});
|
|
39251
39251
|
|
|
39252
|
+
// src/wizard/verify.ts
|
|
39253
|
+
import { randomUUID } from "node:crypto";
|
|
39254
|
+
function deriveIngestEndpoint(apiEndpoint) {
|
|
39255
|
+
try {
|
|
39256
|
+
const u3 = new URL(apiEndpoint);
|
|
39257
|
+
if (u3.hostname.startsWith("api.")) {
|
|
39258
|
+
u3.hostname = `ingest.${u3.hostname.slice(4)}`;
|
|
39259
|
+
return u3.origin;
|
|
39260
|
+
}
|
|
39261
|
+
if (u3.hostname === "localhost" || u3.hostname === "127.0.0.1")
|
|
39262
|
+
return apiEndpoint;
|
|
39263
|
+
return u3.origin;
|
|
39264
|
+
} catch {
|
|
39265
|
+
return "https://ingest.gurulu.io";
|
|
39266
|
+
}
|
|
39267
|
+
}
|
|
39268
|
+
async function selfVerify(opts) {
|
|
39269
|
+
const fetchImpl2 = opts.fetchImpl ?? fetch;
|
|
39270
|
+
const nowMs = (opts.now ?? Date.now)();
|
|
39271
|
+
const anonymousId = `gurulu_verify_${nowMs.toString(36)}${Math.floor(nowMs % 1000)}`;
|
|
39272
|
+
const sessionId = randomUUID();
|
|
39273
|
+
const eventType = opts.eventType ?? "interaction";
|
|
39274
|
+
const payload = {
|
|
39275
|
+
event_key: opts.eventKey,
|
|
39276
|
+
event_type: eventType,
|
|
39277
|
+
occurred_at: new Date(nowMs).toISOString(),
|
|
39278
|
+
anonymous_id: anonymousId,
|
|
39279
|
+
session_id: sessionId,
|
|
39280
|
+
producer: opts.producer ?? "sdk_web",
|
|
39281
|
+
properties: { ...opts.properties ?? {}, gurulu_install_verify: true },
|
|
39282
|
+
test_mode: true
|
|
39283
|
+
};
|
|
39284
|
+
let resp;
|
|
39285
|
+
try {
|
|
39286
|
+
const r3 = await fetchImpl2(`${opts.ingestEndpoint}/v1/ingest/event`, {
|
|
39287
|
+
method: "POST",
|
|
39288
|
+
headers: {
|
|
39289
|
+
"Content-Type": "application/json",
|
|
39290
|
+
Authorization: `Bearer ${opts.writeKey}`
|
|
39291
|
+
},
|
|
39292
|
+
body: JSON.stringify(payload)
|
|
39293
|
+
});
|
|
39294
|
+
if (r3.status === 401 || r3.status === 403) {
|
|
39295
|
+
return mk("error", false, [`ingest auth reddetti (${r3.status}) — write key geçersiz`], opts, anonymousId);
|
|
39296
|
+
}
|
|
39297
|
+
if (r3.status >= 500) {
|
|
39298
|
+
return mk("error", false, [`ingest ${r3.status} — sunucu hatası`], opts, anonymousId);
|
|
39299
|
+
}
|
|
39300
|
+
resp = await r3.json().catch(() => ({}));
|
|
39301
|
+
} catch (e2) {
|
|
39302
|
+
const msg = e2 instanceof Error ? e2.message : String(e2);
|
|
39303
|
+
return mk("error", false, [`ingest erişilemedi: ${msg}`], opts, anonymousId);
|
|
39304
|
+
}
|
|
39305
|
+
const decision = resp.decision ?? "error";
|
|
39306
|
+
const ok = decision === "accept" || decision === "warn";
|
|
39307
|
+
const reasons = (resp.reasons ?? []).map((x2) => String(x2));
|
|
39308
|
+
const result = mk(decision, ok, reasons, opts, anonymousId);
|
|
39309
|
+
if (ok && opts.client) {
|
|
39310
|
+
result.landedInClickhouse = await pollRecent(opts.client, opts.eventKey, anonymousId);
|
|
39311
|
+
}
|
|
39312
|
+
return result;
|
|
39313
|
+
}
|
|
39314
|
+
function mk(decision, ok, reasons, opts, anonymousId) {
|
|
39315
|
+
return { ok, decision, reasons, eventKey: opts.eventKey, anonymousId };
|
|
39316
|
+
}
|
|
39317
|
+
async function pollRecent(client, eventKey, anonymousId, attempts = 8, delayMs = 3000) {
|
|
39318
|
+
for (let i2 = 0;i2 < attempts; i2++) {
|
|
39319
|
+
try {
|
|
39320
|
+
const res = await client.recentEvents({ event_key: eventKey, limit: 50 });
|
|
39321
|
+
if (res.events.some((e2) => e2.anonymous_id === anonymousId))
|
|
39322
|
+
return true;
|
|
39323
|
+
} catch {}
|
|
39324
|
+
if (i2 < attempts - 1)
|
|
39325
|
+
await new Promise((r3) => setTimeout(r3, delayMs));
|
|
39326
|
+
}
|
|
39327
|
+
return false;
|
|
39328
|
+
}
|
|
39329
|
+
|
|
39252
39330
|
// src/commands/doctor.ts
|
|
39253
39331
|
async function runDoctor(opts = {}) {
|
|
39254
39332
|
const cwd = opts.cwd ?? process.cwd();
|
|
@@ -39357,6 +39435,39 @@ async function runDoctor(opts = {}) {
|
|
|
39357
39435
|
message: `health overview unavailable: ${err instanceof Error ? err.message : String(err)}`
|
|
39358
39436
|
});
|
|
39359
39437
|
}
|
|
39438
|
+
if (manifest && manifest.events.length > 0) {
|
|
39439
|
+
const candidate = manifest.events.find((e2) => e2.lifecycle === "active" && e2.type === "interaction" && e2.producerAllowed.includes("sdk_web"));
|
|
39440
|
+
if (candidate) {
|
|
39441
|
+
const props = {};
|
|
39442
|
+
for (const pr of candidate.properties) {
|
|
39443
|
+
if (!pr.required)
|
|
39444
|
+
continue;
|
|
39445
|
+
props[pr.name] = pr.type === "number" ? 1 : pr.type === "boolean" ? true : pr.type === "array" ? [] : pr.type === "json" ? {} : "e2e";
|
|
39446
|
+
}
|
|
39447
|
+
const vr = await selfVerify({
|
|
39448
|
+
ingestEndpoint: deriveIngestEndpoint(project.endpoint ?? cred.endpoint),
|
|
39449
|
+
writeKey: cred.apiKey,
|
|
39450
|
+
eventKey: candidate.key,
|
|
39451
|
+
eventType: candidate.type,
|
|
39452
|
+
producer: "sdk_web",
|
|
39453
|
+
properties: props,
|
|
39454
|
+
client
|
|
39455
|
+
});
|
|
39456
|
+
const landed = vr.landedInClickhouse;
|
|
39457
|
+
checks.push({
|
|
39458
|
+
name: "end_to_end",
|
|
39459
|
+
status: landed === true ? "pass" : vr.ok ? "warn" : "fail",
|
|
39460
|
+
message: landed === true ? "test event ingest→pipeline→dashboard ulaştı (uçtan uca çalışıyor)" : vr.ok ? "ingest kabul etti ama event ~24sn'de dashboard'a ULAŞMADI — pipeline gecikmesi/sorunu" : `test event '${candidate.key}' ${vr.decision}: ${vr.reasons[0] ?? "doğrulanamadı"}`,
|
|
39461
|
+
detail: { decision: vr.decision, landed_in_clickhouse: landed ?? null }
|
|
39462
|
+
});
|
|
39463
|
+
} else {
|
|
39464
|
+
checks.push({
|
|
39465
|
+
name: "end_to_end",
|
|
39466
|
+
status: "skip",
|
|
39467
|
+
message: "uygun test event yok (aktif interaction + sdk_web producer) — E2E atlandı"
|
|
39468
|
+
});
|
|
39469
|
+
}
|
|
39470
|
+
}
|
|
39360
39471
|
try {
|
|
39361
39472
|
const scan = runValidate({ cwd });
|
|
39362
39473
|
const total = scan.deprecated_calls.length + scan.unknown_calls.length;
|
|
@@ -39800,7 +39911,7 @@ var pullCmd = defineCommand({
|
|
|
39800
39911
|
});
|
|
39801
39912
|
|
|
39802
39913
|
// src/lib/detect.ts
|
|
39803
|
-
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
39914
|
+
import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync4 } from "node:fs";
|
|
39804
39915
|
import { dirname as dirname2, join as join5, parse } from "node:path";
|
|
39805
39916
|
var COMPETITOR_DEP_MAP = {
|
|
39806
39917
|
"posthog-js": "posthog",
|
|
@@ -39966,11 +40077,51 @@ function detectLlmFrameworks(pkg) {
|
|
|
39966
40077
|
}
|
|
39967
40078
|
return [...found];
|
|
39968
40079
|
}
|
|
40080
|
+
function expandWorkspaceGlobs(rootDir, patterns) {
|
|
40081
|
+
const out = [];
|
|
40082
|
+
for (const pat of patterns) {
|
|
40083
|
+
if (pat.endsWith("/*")) {
|
|
40084
|
+
const base = join5(rootDir, pat.slice(0, -2));
|
|
40085
|
+
if (!existsSync4(base))
|
|
40086
|
+
continue;
|
|
40087
|
+
try {
|
|
40088
|
+
for (const name of readdirSync2(base)) {
|
|
40089
|
+
const d2 = join5(base, name);
|
|
40090
|
+
if (existsSync4(join5(d2, "package.json")))
|
|
40091
|
+
out.push(d2);
|
|
40092
|
+
}
|
|
40093
|
+
} catch {}
|
|
40094
|
+
} else {
|
|
40095
|
+
const d2 = join5(rootDir, pat);
|
|
40096
|
+
if (existsSync4(join5(d2, "package.json")))
|
|
40097
|
+
out.push(d2);
|
|
40098
|
+
}
|
|
40099
|
+
}
|
|
40100
|
+
return out;
|
|
40101
|
+
}
|
|
40102
|
+
function findWorkspaceFrameworkPackage(rootDir, pkg) {
|
|
40103
|
+
const patterns = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces?.packages ?? [];
|
|
40104
|
+
if (patterns.length === 0)
|
|
40105
|
+
return null;
|
|
40106
|
+
let fallback = null;
|
|
40107
|
+
for (const d2 of expandWorkspaceGlobs(rootDir, patterns)) {
|
|
40108
|
+
const p = readPackageJson(d2);
|
|
40109
|
+
if (!p)
|
|
40110
|
+
continue;
|
|
40111
|
+
const fw = detectFramework(p, d2);
|
|
40112
|
+
if (frameworkRuntime(fw) === "browser")
|
|
40113
|
+
return { dir: d2, framework: fw, pkg: p };
|
|
40114
|
+
if (fw !== "unknown" && !fallback)
|
|
40115
|
+
fallback = { dir: d2, framework: fw, pkg: p };
|
|
40116
|
+
}
|
|
40117
|
+
return fallback;
|
|
40118
|
+
}
|
|
39969
40119
|
function detectProject(dir) {
|
|
39970
40120
|
const pkg = readPackageJson(dir);
|
|
39971
40121
|
let framework = detectFramework(pkg, dir);
|
|
39972
40122
|
const { root, isMonorepo } = findWorkspaceRoot(dir);
|
|
39973
40123
|
let effectivePkg = pkg;
|
|
40124
|
+
let appDir = dir;
|
|
39974
40125
|
if (framework === "unknown" && isMonorepo && root !== dir) {
|
|
39975
40126
|
const rootPkg = readPackageJson(root);
|
|
39976
40127
|
const rootFw = detectFramework(rootPkg, root);
|
|
@@ -39979,19 +40130,28 @@ function detectProject(dir) {
|
|
|
39979
40130
|
effectivePkg = pkg ?? rootPkg;
|
|
39980
40131
|
}
|
|
39981
40132
|
}
|
|
40133
|
+
if (framework === "unknown" && pkg?.workspaces) {
|
|
40134
|
+
const found = findWorkspaceFrameworkPackage(dir, pkg);
|
|
40135
|
+
if (found) {
|
|
40136
|
+
framework = found.framework;
|
|
40137
|
+
appDir = found.dir;
|
|
40138
|
+
effectivePkg = found.pkg;
|
|
40139
|
+
}
|
|
40140
|
+
}
|
|
39982
40141
|
return {
|
|
39983
40142
|
dir,
|
|
39984
40143
|
hasPackageJson: pkg !== null,
|
|
39985
40144
|
framework,
|
|
39986
40145
|
runtime: frameworkRuntime(framework),
|
|
39987
40146
|
packageManager: detectPackageManager(dir),
|
|
39988
|
-
packageJson:
|
|
39989
|
-
llmFrameworks: detectLlmFrameworks(
|
|
40147
|
+
packageJson: effectivePkg,
|
|
40148
|
+
llmFrameworks: detectLlmFrameworks(effectivePkg),
|
|
39990
40149
|
moduleType: detectModuleType(effectivePkg),
|
|
39991
40150
|
rootDir: root,
|
|
40151
|
+
appDir,
|
|
39992
40152
|
isMonorepo,
|
|
39993
|
-
competitors: detectCompetitors(
|
|
39994
|
-
language: detectLanguage(
|
|
40153
|
+
competitors: detectCompetitors(effectivePkg),
|
|
40154
|
+
language: detectLanguage(appDir)
|
|
39995
40155
|
};
|
|
39996
40156
|
}
|
|
39997
40157
|
|
|
@@ -41203,7 +41363,7 @@ function createCheckpoint(cwd, snapshots = new Map) {
|
|
|
41203
41363
|
}
|
|
41204
41364
|
|
|
41205
41365
|
// src/wizard/context.ts
|
|
41206
|
-
import { readdirSync as
|
|
41366
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync9 } from "node:fs";
|
|
41207
41367
|
import { extname as extname2, join as join10, relative as relative2 } from "node:path";
|
|
41208
41368
|
var INCLUDE_EXT = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".vue", ".svelte", ".astro"]);
|
|
41209
41369
|
var SECRET_PATTERNS = [
|
|
@@ -41286,7 +41446,7 @@ function collectCandidates(dir, base, depth, maxDepth, out) {
|
|
|
41286
41446
|
return;
|
|
41287
41447
|
let entries;
|
|
41288
41448
|
try {
|
|
41289
|
-
entries =
|
|
41449
|
+
entries = readdirSync3(dir, { withFileTypes: true });
|
|
41290
41450
|
} catch {
|
|
41291
41451
|
return;
|
|
41292
41452
|
}
|
|
@@ -41508,81 +41668,6 @@ async function renderPlan(plan) {
|
|
|
41508
41668
|
return plan.events;
|
|
41509
41669
|
}
|
|
41510
41670
|
|
|
41511
|
-
// src/wizard/verify.ts
|
|
41512
|
-
function deriveIngestEndpoint(apiEndpoint) {
|
|
41513
|
-
try {
|
|
41514
|
-
const u3 = new URL(apiEndpoint);
|
|
41515
|
-
if (u3.hostname.startsWith("api.")) {
|
|
41516
|
-
u3.hostname = `ingest.${u3.hostname.slice(4)}`;
|
|
41517
|
-
return u3.origin;
|
|
41518
|
-
}
|
|
41519
|
-
if (u3.hostname === "localhost" || u3.hostname === "127.0.0.1")
|
|
41520
|
-
return apiEndpoint;
|
|
41521
|
-
return u3.origin;
|
|
41522
|
-
} catch {
|
|
41523
|
-
return "https://ingest.gurulu.io";
|
|
41524
|
-
}
|
|
41525
|
-
}
|
|
41526
|
-
async function selfVerify(opts) {
|
|
41527
|
-
const fetchImpl2 = opts.fetchImpl ?? fetch;
|
|
41528
|
-
const nowMs = (opts.now ?? Date.now)();
|
|
41529
|
-
const anonymousId = `gurulu_verify_${nowMs.toString(36)}${Math.floor(nowMs % 1000)}`;
|
|
41530
|
-
const eventType = opts.eventType ?? "interaction";
|
|
41531
|
-
const payload = {
|
|
41532
|
-
event_key: opts.eventKey,
|
|
41533
|
-
event_type: eventType,
|
|
41534
|
-
occurred_at: new Date(nowMs).toISOString(),
|
|
41535
|
-
anonymous_id: anonymousId,
|
|
41536
|
-
producer: "sdk",
|
|
41537
|
-
properties: { gurulu_install_verify: true },
|
|
41538
|
-
test_mode: true
|
|
41539
|
-
};
|
|
41540
|
-
let resp;
|
|
41541
|
-
try {
|
|
41542
|
-
const r3 = await fetchImpl2(`${opts.ingestEndpoint}/v1/ingest/event`, {
|
|
41543
|
-
method: "POST",
|
|
41544
|
-
headers: {
|
|
41545
|
-
"Content-Type": "application/json",
|
|
41546
|
-
Authorization: `Bearer ${opts.writeKey}`
|
|
41547
|
-
},
|
|
41548
|
-
body: JSON.stringify(payload)
|
|
41549
|
-
});
|
|
41550
|
-
if (r3.status === 401 || r3.status === 403) {
|
|
41551
|
-
return mk("error", false, [`ingest auth reddetti (${r3.status}) — write key geçersiz`], opts, anonymousId);
|
|
41552
|
-
}
|
|
41553
|
-
if (r3.status >= 500) {
|
|
41554
|
-
return mk("error", false, [`ingest ${r3.status} — sunucu hatası`], opts, anonymousId);
|
|
41555
|
-
}
|
|
41556
|
-
resp = await r3.json().catch(() => ({}));
|
|
41557
|
-
} catch (e2) {
|
|
41558
|
-
const msg = e2 instanceof Error ? e2.message : String(e2);
|
|
41559
|
-
return mk("error", false, [`ingest erişilemedi: ${msg}`], opts, anonymousId);
|
|
41560
|
-
}
|
|
41561
|
-
const decision = resp.decision ?? "error";
|
|
41562
|
-
const ok = decision === "accept" || decision === "warn";
|
|
41563
|
-
const reasons = (resp.reasons ?? []).map((x2) => String(x2));
|
|
41564
|
-
const result = mk(decision, ok, reasons, opts, anonymousId);
|
|
41565
|
-
if (ok && opts.client) {
|
|
41566
|
-
result.landedInClickhouse = await pollRecent(opts.client, opts.eventKey, anonymousId);
|
|
41567
|
-
}
|
|
41568
|
-
return result;
|
|
41569
|
-
}
|
|
41570
|
-
function mk(decision, ok, reasons, opts, anonymousId) {
|
|
41571
|
-
return { ok, decision, reasons, eventKey: opts.eventKey, anonymousId };
|
|
41572
|
-
}
|
|
41573
|
-
async function pollRecent(client, eventKey, anonymousId, attempts = 4, delayMs = 1500) {
|
|
41574
|
-
for (let i2 = 0;i2 < attempts; i2++) {
|
|
41575
|
-
try {
|
|
41576
|
-
const res = await client.recentEvents({ event_key: eventKey, limit: 50 });
|
|
41577
|
-
if (res.events.some((e2) => e2.anonymous_id === anonymousId))
|
|
41578
|
-
return true;
|
|
41579
|
-
} catch {}
|
|
41580
|
-
if (i2 < attempts - 1)
|
|
41581
|
-
await new Promise((r3) => setTimeout(r3, delayMs));
|
|
41582
|
-
}
|
|
41583
|
-
return false;
|
|
41584
|
-
}
|
|
41585
|
-
|
|
41586
41671
|
// src/wizard/wire.ts
|
|
41587
41672
|
import { existsSync as existsSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync10 } from "node:fs";
|
|
41588
41673
|
|
|
@@ -41958,6 +42043,10 @@ async function runWizard(opts) {
|
|
|
41958
42043
|
const { workspaceId, writeKey } = await resolveWorkspace(client, auth.workspaceId, opts);
|
|
41959
42044
|
phase(3, "Projeni tanıyoruz", "Kodun okunuyor; hangi kullanıcı olaylarını (ör. kayıt, satın alma) izleyeceğimiz planlanıyor.");
|
|
41960
42045
|
const detected = detectProject(opts.cwd);
|
|
42046
|
+
if (detected.appDir !== opts.cwd) {
|
|
42047
|
+
p4.log.info(c3.dim(`Monorepo: kurulum ${detected.framework} app'ine → ${detected.appDir}`));
|
|
42048
|
+
opts.cwd = detected.appDir;
|
|
42049
|
+
}
|
|
41961
42050
|
let framework = detected.framework;
|
|
41962
42051
|
if (opts.framework && FRAMEWORKS.includes(opts.framework)) {
|
|
41963
42052
|
framework = opts.framework;
|
|
@@ -42261,7 +42350,13 @@ ${captureGuide(approvedEvents, identifyHint, isNode)}`);
|
|
|
42261
42350
|
if (inj.strategy === "manual")
|
|
42262
42351
|
p4.log.message(plan.initSnippet);
|
|
42263
42352
|
}
|
|
42264
|
-
|
|
42353
|
+
const e2eOk = verifyResult?.landedInClickhouse === true;
|
|
42354
|
+
const e2eFailed = verifyResult != null && (verifyResult.landedInClickhouse === false || !verifyResult.ok);
|
|
42355
|
+
if (e2eFailed) {
|
|
42356
|
+
p4.outro(`${c3.bold("⚠ Kurulum yapıldı ama UÇTAN UCA DOĞRULANAMADI")} — kod + kayıt tamam, ama test event dashboard'a ulaşmadı (ingest kabul etti/pipeline'da kayboldu). ${c3.dim("Tekrar:")} ${c3.bold("gurulu doctor")}`);
|
|
42357
|
+
} else {
|
|
42358
|
+
p4.outro(`${c3.neon("\uD83E\uDD89 Hazır!")}${e2eOk ? c3.dim(" · uçtan uca doğrulandı") : ""} ${c3.dim("Doğrula:")} ${c3.bold("gurulu doctor")} ${c3.dim("·")} ${c3.dim("Dashboard:")} ${c3.cyan("https://dashboard.gurulu.io/app?onboard=done")}`);
|
|
42359
|
+
}
|
|
42265
42360
|
}
|
|
42266
42361
|
async function resolveWorkspace(client, authWorkspaceId, opts) {
|
|
42267
42362
|
if (opts.writeKey) {
|
|
@@ -42299,7 +42394,13 @@ function verifyLabel(v2) {
|
|
|
42299
42394
|
switch (v2.decision) {
|
|
42300
42395
|
case "accept":
|
|
42301
42396
|
case "warn":
|
|
42302
|
-
|
|
42397
|
+
if (v2.landedInClickhouse === false) {
|
|
42398
|
+
return "⚠ ingest kabul etti ama event dashboard'a ULAŞMADI (~24sn) — pipeline gecikmesi/sorunu; `gurulu doctor` ile tekrar dene";
|
|
42399
|
+
}
|
|
42400
|
+
if (v2.landedInClickhouse === true) {
|
|
42401
|
+
return "✓ uçtan uca doğrulandı — test event dashboard'a ulaştı";
|
|
42402
|
+
}
|
|
42403
|
+
return `✓ test event kabul edildi (${v2.decision})`;
|
|
42303
42404
|
case "quarantine":
|
|
42304
42405
|
return `⚠ event kayıtlı ama eksik prop (quarantine) — Gurulu'ya bağlısın`;
|
|
42305
42406
|
case "reject":
|
|
@@ -42710,7 +42811,7 @@ var uninstallCmd = defineCommand({
|
|
|
42710
42811
|
});
|
|
42711
42812
|
|
|
42712
42813
|
// src/index.ts
|
|
42713
|
-
var VERSION = "1.6.
|
|
42814
|
+
var VERSION = "1.6.7";
|
|
42714
42815
|
var mainCmd = defineCommand({
|
|
42715
42816
|
meta: {
|
|
42716
42817
|
name: "gurulu",
|
package/dist/lib/detect.d.ts
CHANGED
|
@@ -22,6 +22,12 @@ export interface DetectedProject {
|
|
|
22
22
|
moduleType: ModuleType;
|
|
23
23
|
/** Workspace root (lockfile dizini); cwd ile aynıysa monorepo değil. */
|
|
24
24
|
rootDir: string;
|
|
25
|
+
/**
|
|
26
|
+
* Framework app'inin gerçek dizini. Genelde = dir; ama monorepo ROOT'unda
|
|
27
|
+
* çalışıp framework bir alt-pakette (ör. apps/dashboard) ise o alt-paket dizini.
|
|
28
|
+
* `.env` + kod-wire + SDK install BURAYA hedeflenir (root'a değil).
|
|
29
|
+
*/
|
|
30
|
+
appDir: string;
|
|
25
31
|
/** cwd bir monorepo paketi mi (root farklı + workspaces sinyali). */
|
|
26
32
|
isMonorepo: boolean;
|
|
27
33
|
/** Tespit edilen rakip analytics SDK'ları (augmentation/twin için, boş = yok). */
|
package/dist/lib/detect.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/lib/detect.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,OAAO,GACP,KAAK,GACL,MAAM,GACN,QAAQ,GACR,OAAO,GACP,MAAM,GACN,SAAS,GACT,SAAS,GACT,MAAM,GACN,KAAK,GACL,aAAa,GACb,SAAS,CAAC;AAEd,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAGrD,MAAM,MAAM,YAAY,GACpB,QAAQ,GACR,WAAW,GACX,WAAW,GACX,cAAc,GACd,WAAW,GACX,QAAQ,GACR,SAAS,GACT,QAAQ,CAAC;AAIb,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,CAAC;AAkB3F,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,GAAG,UAAU,EAAE,CAM5E;AAeD,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE7D,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,KAAK,CAAC;AAIvC,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,GAAG,SAAS,CAAC;AAE1D,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAYpD;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACrC,mEAAmE;IACnE,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,6EAA6E;IAC7E,UAAU,EAAE,UAAU,CAAC;IACvB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,UAAU,EAAE,OAAO,CAAC;IACpB,kFAAkF;IAClF,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,+EAA+E;IAC/E,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,UAAU,gBAAgB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,gFAAgF;IAChF,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACjD;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,GAAG,UAAU,CAEzE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CA0BpF;AAiBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAchE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAmBpF;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAmBvD;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,GAAG,YAAY,EAAE,CAMhF;
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/lib/detect.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/detect.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/lib/detect.ts
|
|
2
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
3
3
|
import { dirname, join, parse } from "node:path";
|
|
4
4
|
var COMPETITOR_DEP_MAP = {
|
|
5
5
|
"posthog-js": "posthog",
|
|
@@ -165,11 +165,51 @@ function detectLlmFrameworks(pkg) {
|
|
|
165
165
|
}
|
|
166
166
|
return [...found];
|
|
167
167
|
}
|
|
168
|
+
function expandWorkspaceGlobs(rootDir, patterns) {
|
|
169
|
+
const out = [];
|
|
170
|
+
for (const pat of patterns) {
|
|
171
|
+
if (pat.endsWith("/*")) {
|
|
172
|
+
const base = join(rootDir, pat.slice(0, -2));
|
|
173
|
+
if (!existsSync(base))
|
|
174
|
+
continue;
|
|
175
|
+
try {
|
|
176
|
+
for (const name of readdirSync(base)) {
|
|
177
|
+
const d = join(base, name);
|
|
178
|
+
if (existsSync(join(d, "package.json")))
|
|
179
|
+
out.push(d);
|
|
180
|
+
}
|
|
181
|
+
} catch {}
|
|
182
|
+
} else {
|
|
183
|
+
const d = join(rootDir, pat);
|
|
184
|
+
if (existsSync(join(d, "package.json")))
|
|
185
|
+
out.push(d);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return out;
|
|
189
|
+
}
|
|
190
|
+
function findWorkspaceFrameworkPackage(rootDir, pkg) {
|
|
191
|
+
const patterns = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces?.packages ?? [];
|
|
192
|
+
if (patterns.length === 0)
|
|
193
|
+
return null;
|
|
194
|
+
let fallback = null;
|
|
195
|
+
for (const d of expandWorkspaceGlobs(rootDir, patterns)) {
|
|
196
|
+
const p = readPackageJson(d);
|
|
197
|
+
if (!p)
|
|
198
|
+
continue;
|
|
199
|
+
const fw = detectFramework(p, d);
|
|
200
|
+
if (frameworkRuntime(fw) === "browser")
|
|
201
|
+
return { dir: d, framework: fw, pkg: p };
|
|
202
|
+
if (fw !== "unknown" && !fallback)
|
|
203
|
+
fallback = { dir: d, framework: fw, pkg: p };
|
|
204
|
+
}
|
|
205
|
+
return fallback;
|
|
206
|
+
}
|
|
168
207
|
function detectProject(dir) {
|
|
169
208
|
const pkg = readPackageJson(dir);
|
|
170
209
|
let framework = detectFramework(pkg, dir);
|
|
171
210
|
const { root, isMonorepo } = findWorkspaceRoot(dir);
|
|
172
211
|
let effectivePkg = pkg;
|
|
212
|
+
let appDir = dir;
|
|
173
213
|
if (framework === "unknown" && isMonorepo && root !== dir) {
|
|
174
214
|
const rootPkg = readPackageJson(root);
|
|
175
215
|
const rootFw = detectFramework(rootPkg, root);
|
|
@@ -178,19 +218,28 @@ function detectProject(dir) {
|
|
|
178
218
|
effectivePkg = pkg ?? rootPkg;
|
|
179
219
|
}
|
|
180
220
|
}
|
|
221
|
+
if (framework === "unknown" && pkg?.workspaces) {
|
|
222
|
+
const found = findWorkspaceFrameworkPackage(dir, pkg);
|
|
223
|
+
if (found) {
|
|
224
|
+
framework = found.framework;
|
|
225
|
+
appDir = found.dir;
|
|
226
|
+
effectivePkg = found.pkg;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
181
229
|
return {
|
|
182
230
|
dir,
|
|
183
231
|
hasPackageJson: pkg !== null,
|
|
184
232
|
framework,
|
|
185
233
|
runtime: frameworkRuntime(framework),
|
|
186
234
|
packageManager: detectPackageManager(dir),
|
|
187
|
-
packageJson:
|
|
188
|
-
llmFrameworks: detectLlmFrameworks(
|
|
235
|
+
packageJson: effectivePkg,
|
|
236
|
+
llmFrameworks: detectLlmFrameworks(effectivePkg),
|
|
189
237
|
moduleType: detectModuleType(effectivePkg),
|
|
190
238
|
rootDir: root,
|
|
239
|
+
appDir,
|
|
191
240
|
isMonorepo,
|
|
192
|
-
competitors: detectCompetitors(
|
|
193
|
-
language: detectLanguage(
|
|
241
|
+
competitors: detectCompetitors(effectivePkg),
|
|
242
|
+
language: detectLanguage(appDir)
|
|
194
243
|
};
|
|
195
244
|
}
|
|
196
245
|
export {
|
package/dist/wizard/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/wizard/run.ts"],"names":[],"mappings":"AAuCA,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,4CAA4C;IAC5C,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,sFAAsF;IACtF,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA0DD,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/wizard/run.ts"],"names":[],"mappings":"AAuCA,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,4CAA4C;IAC5C,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,sFAAsF;IACtF,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA0DD,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAmelE"}
|
package/dist/wizard/verify.d.ts
CHANGED
|
@@ -17,6 +17,10 @@ export interface SelfVerifyOptions {
|
|
|
17
17
|
writeKey: string;
|
|
18
18
|
eventKey: string;
|
|
19
19
|
eventType?: 'interaction' | 'intent' | 'outcome';
|
|
20
|
+
/** Event'in izin verdiği producer (default 'sdk_web'). Yanlış producer → reject. */
|
|
21
|
+
producer?: string;
|
|
22
|
+
/** Zorunlu prop'ları doldur → quarantine yerine accept (E2E poll CH'ye ulaşsın). */
|
|
23
|
+
properties?: Record<string, unknown>;
|
|
20
24
|
/** CH'de de doğrula (recentEvents poll). Default false — senkron decision yeter. */
|
|
21
25
|
client?: ApiClient;
|
|
22
26
|
/** Test-injection (fetch mock). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/wizard/verify.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/wizard/verify.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,MAAM,GAAG,YAAY,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAC;AAEjG,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,cAAc,CAAC;IACzB,+DAA+D;IAC/D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,+DAA+D;IAC/D,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AASD,mFAAmF;AACnF,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAahE;AAED,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;IACjD,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,oFAAoF;IACpF,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,mCAAmC;IACnC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CA4D/E"}
|