@gurulu/cli 1.6.6 → 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 +126 -78
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +126 -78
- 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;
|
|
@@ -41980,81 +42091,6 @@ async function renderPlan(plan) {
|
|
|
41980
42091
|
return plan.events;
|
|
41981
42092
|
}
|
|
41982
42093
|
|
|
41983
|
-
// src/wizard/verify.ts
|
|
41984
|
-
function deriveIngestEndpoint(apiEndpoint) {
|
|
41985
|
-
try {
|
|
41986
|
-
const u3 = new URL(apiEndpoint);
|
|
41987
|
-
if (u3.hostname.startsWith("api.")) {
|
|
41988
|
-
u3.hostname = `ingest.${u3.hostname.slice(4)}`;
|
|
41989
|
-
return u3.origin;
|
|
41990
|
-
}
|
|
41991
|
-
if (u3.hostname === "localhost" || u3.hostname === "127.0.0.1")
|
|
41992
|
-
return apiEndpoint;
|
|
41993
|
-
return u3.origin;
|
|
41994
|
-
} catch {
|
|
41995
|
-
return "https://ingest.gurulu.io";
|
|
41996
|
-
}
|
|
41997
|
-
}
|
|
41998
|
-
async function selfVerify(opts) {
|
|
41999
|
-
const fetchImpl2 = opts.fetchImpl ?? fetch;
|
|
42000
|
-
const nowMs = (opts.now ?? Date.now)();
|
|
42001
|
-
const anonymousId = `gurulu_verify_${nowMs.toString(36)}${Math.floor(nowMs % 1000)}`;
|
|
42002
|
-
const eventType = opts.eventType ?? "interaction";
|
|
42003
|
-
const payload = {
|
|
42004
|
-
event_key: opts.eventKey,
|
|
42005
|
-
event_type: eventType,
|
|
42006
|
-
occurred_at: new Date(nowMs).toISOString(),
|
|
42007
|
-
anonymous_id: anonymousId,
|
|
42008
|
-
producer: "sdk",
|
|
42009
|
-
properties: { gurulu_install_verify: true },
|
|
42010
|
-
test_mode: true
|
|
42011
|
-
};
|
|
42012
|
-
let resp;
|
|
42013
|
-
try {
|
|
42014
|
-
const r3 = await fetchImpl2(`${opts.ingestEndpoint}/v1/ingest/event`, {
|
|
42015
|
-
method: "POST",
|
|
42016
|
-
headers: {
|
|
42017
|
-
"Content-Type": "application/json",
|
|
42018
|
-
Authorization: `Bearer ${opts.writeKey}`
|
|
42019
|
-
},
|
|
42020
|
-
body: JSON.stringify(payload)
|
|
42021
|
-
});
|
|
42022
|
-
if (r3.status === 401 || r3.status === 403) {
|
|
42023
|
-
return mk("error", false, [`ingest auth reddetti (${r3.status}) — write key geçersiz`], opts, anonymousId);
|
|
42024
|
-
}
|
|
42025
|
-
if (r3.status >= 500) {
|
|
42026
|
-
return mk("error", false, [`ingest ${r3.status} — sunucu hatası`], opts, anonymousId);
|
|
42027
|
-
}
|
|
42028
|
-
resp = await r3.json().catch(() => ({}));
|
|
42029
|
-
} catch (e2) {
|
|
42030
|
-
const msg = e2 instanceof Error ? e2.message : String(e2);
|
|
42031
|
-
return mk("error", false, [`ingest erişilemedi: ${msg}`], opts, anonymousId);
|
|
42032
|
-
}
|
|
42033
|
-
const decision = resp.decision ?? "error";
|
|
42034
|
-
const ok = decision === "accept" || decision === "warn";
|
|
42035
|
-
const reasons = (resp.reasons ?? []).map((x2) => String(x2));
|
|
42036
|
-
const result = mk(decision, ok, reasons, opts, anonymousId);
|
|
42037
|
-
if (ok && opts.client) {
|
|
42038
|
-
result.landedInClickhouse = await pollRecent(opts.client, opts.eventKey, anonymousId);
|
|
42039
|
-
}
|
|
42040
|
-
return result;
|
|
42041
|
-
}
|
|
42042
|
-
function mk(decision, ok, reasons, opts, anonymousId) {
|
|
42043
|
-
return { ok, decision, reasons, eventKey: opts.eventKey, anonymousId };
|
|
42044
|
-
}
|
|
42045
|
-
async function pollRecent(client, eventKey, anonymousId, attempts = 4, delayMs = 1500) {
|
|
42046
|
-
for (let i2 = 0;i2 < attempts; i2++) {
|
|
42047
|
-
try {
|
|
42048
|
-
const res = await client.recentEvents({ event_key: eventKey, limit: 50 });
|
|
42049
|
-
if (res.events.some((e2) => e2.anonymous_id === anonymousId))
|
|
42050
|
-
return true;
|
|
42051
|
-
} catch {}
|
|
42052
|
-
if (i2 < attempts - 1)
|
|
42053
|
-
await new Promise((r3) => setTimeout(r3, delayMs));
|
|
42054
|
-
}
|
|
42055
|
-
return false;
|
|
42056
|
-
}
|
|
42057
|
-
|
|
42058
42094
|
// src/wizard/wire.ts
|
|
42059
42095
|
import { existsSync as existsSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync10 } from "node:fs";
|
|
42060
42096
|
|
|
@@ -42737,7 +42773,13 @@ ${captureGuide(approvedEvents, identifyHint, isNode)}`);
|
|
|
42737
42773
|
if (inj.strategy === "manual")
|
|
42738
42774
|
p4.log.message(plan.initSnippet);
|
|
42739
42775
|
}
|
|
42740
|
-
|
|
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
|
+
}
|
|
42741
42783
|
}
|
|
42742
42784
|
async function resolveWorkspace(client, authWorkspaceId, opts) {
|
|
42743
42785
|
if (opts.writeKey) {
|
|
@@ -42775,7 +42817,13 @@ function verifyLabel(v2) {
|
|
|
42775
42817
|
switch (v2.decision) {
|
|
42776
42818
|
case "accept":
|
|
42777
42819
|
case "warn":
|
|
42778
|
-
|
|
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})`;
|
|
42779
42827
|
case "quarantine":
|
|
42780
42828
|
return `⚠ event kayıtlı ama eksik prop (quarantine) — Gurulu'ya bağlısın`;
|
|
42781
42829
|
case "reject":
|
|
@@ -43186,7 +43234,7 @@ var uninstallCmd = defineCommand({
|
|
|
43186
43234
|
});
|
|
43187
43235
|
|
|
43188
43236
|
// src/index.ts
|
|
43189
|
-
var VERSION = "1.6.
|
|
43237
|
+
var VERSION = "1.6.7";
|
|
43190
43238
|
var mainCmd = defineCommand({
|
|
43191
43239
|
meta: {
|
|
43192
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;
|
|
@@ -41557,81 +41668,6 @@ async function renderPlan(plan) {
|
|
|
41557
41668
|
return plan.events;
|
|
41558
41669
|
}
|
|
41559
41670
|
|
|
41560
|
-
// src/wizard/verify.ts
|
|
41561
|
-
function deriveIngestEndpoint(apiEndpoint) {
|
|
41562
|
-
try {
|
|
41563
|
-
const u3 = new URL(apiEndpoint);
|
|
41564
|
-
if (u3.hostname.startsWith("api.")) {
|
|
41565
|
-
u3.hostname = `ingest.${u3.hostname.slice(4)}`;
|
|
41566
|
-
return u3.origin;
|
|
41567
|
-
}
|
|
41568
|
-
if (u3.hostname === "localhost" || u3.hostname === "127.0.0.1")
|
|
41569
|
-
return apiEndpoint;
|
|
41570
|
-
return u3.origin;
|
|
41571
|
-
} catch {
|
|
41572
|
-
return "https://ingest.gurulu.io";
|
|
41573
|
-
}
|
|
41574
|
-
}
|
|
41575
|
-
async function selfVerify(opts) {
|
|
41576
|
-
const fetchImpl2 = opts.fetchImpl ?? fetch;
|
|
41577
|
-
const nowMs = (opts.now ?? Date.now)();
|
|
41578
|
-
const anonymousId = `gurulu_verify_${nowMs.toString(36)}${Math.floor(nowMs % 1000)}`;
|
|
41579
|
-
const eventType = opts.eventType ?? "interaction";
|
|
41580
|
-
const payload = {
|
|
41581
|
-
event_key: opts.eventKey,
|
|
41582
|
-
event_type: eventType,
|
|
41583
|
-
occurred_at: new Date(nowMs).toISOString(),
|
|
41584
|
-
anonymous_id: anonymousId,
|
|
41585
|
-
producer: "sdk",
|
|
41586
|
-
properties: { gurulu_install_verify: true },
|
|
41587
|
-
test_mode: true
|
|
41588
|
-
};
|
|
41589
|
-
let resp;
|
|
41590
|
-
try {
|
|
41591
|
-
const r3 = await fetchImpl2(`${opts.ingestEndpoint}/v1/ingest/event`, {
|
|
41592
|
-
method: "POST",
|
|
41593
|
-
headers: {
|
|
41594
|
-
"Content-Type": "application/json",
|
|
41595
|
-
Authorization: `Bearer ${opts.writeKey}`
|
|
41596
|
-
},
|
|
41597
|
-
body: JSON.stringify(payload)
|
|
41598
|
-
});
|
|
41599
|
-
if (r3.status === 401 || r3.status === 403) {
|
|
41600
|
-
return mk("error", false, [`ingest auth reddetti (${r3.status}) — write key geçersiz`], opts, anonymousId);
|
|
41601
|
-
}
|
|
41602
|
-
if (r3.status >= 500) {
|
|
41603
|
-
return mk("error", false, [`ingest ${r3.status} — sunucu hatası`], opts, anonymousId);
|
|
41604
|
-
}
|
|
41605
|
-
resp = await r3.json().catch(() => ({}));
|
|
41606
|
-
} catch (e2) {
|
|
41607
|
-
const msg = e2 instanceof Error ? e2.message : String(e2);
|
|
41608
|
-
return mk("error", false, [`ingest erişilemedi: ${msg}`], opts, anonymousId);
|
|
41609
|
-
}
|
|
41610
|
-
const decision = resp.decision ?? "error";
|
|
41611
|
-
const ok = decision === "accept" || decision === "warn";
|
|
41612
|
-
const reasons = (resp.reasons ?? []).map((x2) => String(x2));
|
|
41613
|
-
const result = mk(decision, ok, reasons, opts, anonymousId);
|
|
41614
|
-
if (ok && opts.client) {
|
|
41615
|
-
result.landedInClickhouse = await pollRecent(opts.client, opts.eventKey, anonymousId);
|
|
41616
|
-
}
|
|
41617
|
-
return result;
|
|
41618
|
-
}
|
|
41619
|
-
function mk(decision, ok, reasons, opts, anonymousId) {
|
|
41620
|
-
return { ok, decision, reasons, eventKey: opts.eventKey, anonymousId };
|
|
41621
|
-
}
|
|
41622
|
-
async function pollRecent(client, eventKey, anonymousId, attempts = 4, delayMs = 1500) {
|
|
41623
|
-
for (let i2 = 0;i2 < attempts; i2++) {
|
|
41624
|
-
try {
|
|
41625
|
-
const res = await client.recentEvents({ event_key: eventKey, limit: 50 });
|
|
41626
|
-
if (res.events.some((e2) => e2.anonymous_id === anonymousId))
|
|
41627
|
-
return true;
|
|
41628
|
-
} catch {}
|
|
41629
|
-
if (i2 < attempts - 1)
|
|
41630
|
-
await new Promise((r3) => setTimeout(r3, delayMs));
|
|
41631
|
-
}
|
|
41632
|
-
return false;
|
|
41633
|
-
}
|
|
41634
|
-
|
|
41635
41671
|
// src/wizard/wire.ts
|
|
41636
41672
|
import { existsSync as existsSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync10 } from "node:fs";
|
|
41637
41673
|
|
|
@@ -42314,7 +42350,13 @@ ${captureGuide(approvedEvents, identifyHint, isNode)}`);
|
|
|
42314
42350
|
if (inj.strategy === "manual")
|
|
42315
42351
|
p4.log.message(plan.initSnippet);
|
|
42316
42352
|
}
|
|
42317
|
-
|
|
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
|
+
}
|
|
42318
42360
|
}
|
|
42319
42361
|
async function resolveWorkspace(client, authWorkspaceId, opts) {
|
|
42320
42362
|
if (opts.writeKey) {
|
|
@@ -42352,7 +42394,13 @@ function verifyLabel(v2) {
|
|
|
42352
42394
|
switch (v2.decision) {
|
|
42353
42395
|
case "accept":
|
|
42354
42396
|
case "warn":
|
|
42355
|
-
|
|
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})`;
|
|
42356
42404
|
case "quarantine":
|
|
42357
42405
|
return `⚠ event kayıtlı ama eksik prop (quarantine) — Gurulu'ya bağlısın`;
|
|
42358
42406
|
case "reject":
|
|
@@ -42763,7 +42811,7 @@ var uninstallCmd = defineCommand({
|
|
|
42763
42811
|
});
|
|
42764
42812
|
|
|
42765
42813
|
// src/index.ts
|
|
42766
|
-
var VERSION = "1.6.
|
|
42814
|
+
var VERSION = "1.6.7";
|
|
42767
42815
|
var mainCmd = defineCommand({
|
|
42768
42816
|
meta: {
|
|
42769
42817
|
name: "gurulu",
|
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"}
|