@withone/cli 1.55.2 → 1.55.3

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.
Files changed (2) hide show
  1. package/dist/index.js +80 -16
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5810,7 +5810,7 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
5810
5810
  );
5811
5811
  let batchHitRateLimit = false;
5812
5812
  const now = (/* @__PURE__ */ new Date()).toISOString();
5813
- const pending = [];
5813
+ const pending2 = [];
5814
5814
  for (let j = 0; j < results.length; j++) {
5815
5815
  const result = results[j];
5816
5816
  const row = batch[j];
@@ -5829,7 +5829,7 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
5829
5829
  const fp = merged[config2.invalidateOn] ?? row[config2.invalidateOn];
5830
5830
  merged[ENRICH_FINGERPRINT_COLUMN] = fp == null ? null : String(fp);
5831
5831
  }
5832
- pending.push({ merged, id });
5832
+ pending2.push({ merged, id });
5833
5833
  } else if (result.status === "fulfilled" && result.value === null) {
5834
5834
  rateLimited++;
5835
5835
  skipped++;
@@ -5838,14 +5838,14 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
5838
5838
  skipped++;
5839
5839
  }
5840
5840
  }
5841
- let writes = pending;
5842
- if (ctx.transform && pending.length > 0) {
5843
- const transformed = await transformRecords(ctx.transform, pending.map((p10) => p10.merged));
5841
+ let writes = pending2;
5842
+ if (ctx.transform && pending2.length > 0) {
5843
+ const transformed = await transformRecords(ctx.transform, pending2.map((p10) => p10.merged));
5844
5844
  if (transformed) {
5845
5845
  const byId = /* @__PURE__ */ new Map();
5846
5846
  for (const r of transformed) byId.set(r[idField], r);
5847
5847
  writes = [];
5848
- for (const p10 of pending) {
5848
+ for (const p10 of pending2) {
5849
5849
  const t = byId.get(p10.id);
5850
5850
  if (!t) continue;
5851
5851
  if (!t[tsField]) t[tsField] = now;
@@ -11664,8 +11664,20 @@ import pc14 from "picocolors";
11664
11664
  var require3 = createRequire2(import.meta.url);
11665
11665
  var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com";
11666
11666
  var DEFAULT_POSTHOG_KEY = "phc_a9ok4w0uxiZcVoSWOISIlin85lHMXQD3vWPaYnuRlRV";
11667
+ var SEND_MAX_ATTEMPTS = 3;
11668
+ var QUEUE_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
11669
+ var EXIT_GRACE_MS = 300;
11667
11670
  var inFlight = /* @__PURE__ */ new Set();
11671
+ var pending = /* @__PURE__ */ new Set();
11672
+ var dispatched = /* @__PURE__ */ new Set();
11668
11673
  var delivered = /* @__PURE__ */ new Set();
11674
+ var UUID_SHAPE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
11675
+ function uuidFromInsertId(insertId) {
11676
+ if (UUID_SHAPE.test(insertId)) return insertId.toLowerCase();
11677
+ const h = createHash("sha1").update(`one-cli-event:${insertId}`).digest("hex");
11678
+ const variant = (parseInt(h[16], 16) & 3 | 8).toString(16);
11679
+ return `${h.slice(0, 8)}-${h.slice(8, 12)}-5${h.slice(13, 16)}-${variant}${h.slice(17, 20)}-${h.slice(20, 32)}`;
11680
+ }
11669
11681
  function posthogHost() {
11670
11682
  return process.env.ONE_POSTHOG_HOST || DEFAULT_POSTHOG_HOST;
11671
11683
  }
@@ -11721,9 +11733,10 @@ function personSet() {
11721
11733
  }
11722
11734
  function send(item) {
11723
11735
  const insertId = item.properties.$insert_id;
11736
+ if (insertId) dispatched.add(insertId);
11724
11737
  const controller = new AbortController();
11725
11738
  inFlight.add(controller);
11726
- void (async () => {
11739
+ const run = (async () => {
11727
11740
  try {
11728
11741
  const res = await fetch(`${posthogHost()}/i/v0/e/`, {
11729
11742
  method: "POST",
@@ -11732,6 +11745,8 @@ function send(item) {
11732
11745
  api_key: posthogKey(),
11733
11746
  event: item.event,
11734
11747
  distinct_id: item.distinct_id,
11748
+ // PostHog's dedupe key — a re-sent copy is dropped on ingest.
11749
+ uuid: item.uuid ?? (insertId ? uuidFromInsertId(insertId) : void 0),
11735
11750
  properties: item.properties,
11736
11751
  timestamp: item.timestamp
11737
11752
  }),
@@ -11745,6 +11760,8 @@ function send(item) {
11745
11760
  inFlight.delete(controller);
11746
11761
  }
11747
11762
  })();
11763
+ pending.add(run);
11764
+ void run.finally(() => pending.delete(run));
11748
11765
  }
11749
11766
  function capture(event, properties = {}, opts = {}) {
11750
11767
  if (isTelemetryDisabled()) {
@@ -11754,7 +11771,10 @@ function capture(event, properties = {}, opts = {}) {
11754
11771
  const did = opts.distinctId ?? distinctId();
11755
11772
  const props = { ...baseProperties(), ...properties };
11756
11773
  if (props.$insert_id === void 0) props.$insert_id = randomUUID();
11757
- if (did === distinctId()) {
11774
+ const insertId = props.$insert_id;
11775
+ if (opts.personProfile === false) {
11776
+ props.$process_person_profile = false;
11777
+ } else if (did === distinctId()) {
11758
11778
  const set = personSet();
11759
11779
  if (set) props.$set = set;
11760
11780
  }
@@ -11762,7 +11782,8 @@ function capture(event, properties = {}, opts = {}) {
11762
11782
  event,
11763
11783
  distinct_id: did,
11764
11784
  properties: props,
11765
- timestamp: opts.timestamp ?? (/* @__PURE__ */ new Date()).toISOString()
11785
+ timestamp: opts.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
11786
+ uuid: uuidFromInsertId(insertId)
11766
11787
  };
11767
11788
  appendAnalyticsQueue(JSON.stringify(item));
11768
11789
  }
@@ -11856,7 +11877,12 @@ function emitRollup(did, group) {
11856
11877
  window_end: new Date(group[group.length - 1].ts).toISOString(),
11857
11878
  $insert_id: insertId
11858
11879
  },
11859
- { distinctId: did, timestamp: new Date(group[group.length - 1].ts).toISOString() }
11880
+ {
11881
+ distinctId: did,
11882
+ timestamp: new Date(group[group.length - 1].ts).toISOString(),
11883
+ // Rollups bill at the anonymous rate; the person already exists.
11884
+ personProfile: false
11885
+ }
11860
11886
  );
11861
11887
  debugLog(`rollup \u2014 ${group.length} command(s) for ${did}`);
11862
11888
  }
@@ -11874,25 +11900,62 @@ function drainQueue() {
11874
11900
  writeAnalyticsQueue([]);
11875
11901
  return;
11876
11902
  }
11903
+ const now = Date.now();
11904
+ const kept = [];
11905
+ let changed = false;
11877
11906
  for (const line of readAnalyticsQueue()) {
11907
+ let item;
11878
11908
  try {
11879
- const item = JSON.parse(line);
11880
- if (item?.properties?.$insert_id) send(item);
11909
+ item = JSON.parse(line);
11881
11910
  } catch {
11911
+ changed = true;
11912
+ continue;
11913
+ }
11914
+ const insertId = item?.properties?.$insert_id;
11915
+ if (!insertId) {
11916
+ changed = true;
11917
+ continue;
11918
+ }
11919
+ const age = now - Date.parse(item.timestamp);
11920
+ const attempts = item.attempts ?? 0;
11921
+ if (!(age < QUEUE_MAX_AGE_MS) || attempts >= SEND_MAX_ATTEMPTS) {
11922
+ debugLog(`"${item.event}" dropped (${attempts} attempts, ${Math.round(age / 6e4)} min old)`);
11923
+ changed = true;
11924
+ continue;
11925
+ }
11926
+ if (dispatched.has(insertId)) {
11927
+ kept.push(line);
11928
+ continue;
11882
11929
  }
11930
+ item.attempts = attempts + 1;
11931
+ if (!item.uuid) item.uuid = uuidFromInsertId(insertId);
11932
+ kept.push(JSON.stringify(item));
11933
+ changed = true;
11934
+ send(item);
11883
11935
  }
11936
+ if (changed) writeAnalyticsQueue(kept);
11884
11937
  }
11885
- function flush() {
11938
+ async function flush() {
11939
+ if (pending.size > 0) {
11940
+ await Promise.race([
11941
+ Promise.allSettled([...pending]),
11942
+ new Promise((resolve) => setTimeout(resolve, EXIT_GRACE_MS))
11943
+ ]);
11944
+ }
11886
11945
  for (const controller of inFlight) controller.abort();
11887
11946
  const remaining = readAnalyticsQueue().filter((line) => {
11888
11947
  try {
11889
- const id = JSON.parse(line).properties?.$insert_id;
11890
- return id ? !delivered.has(id) : false;
11948
+ const item = JSON.parse(line);
11949
+ const id = item.properties?.$insert_id;
11950
+ if (!id || delivered.has(id)) return false;
11951
+ return (item.attempts ?? 0) < SEND_MAX_ATTEMPTS;
11891
11952
  } catch {
11892
11953
  return false;
11893
11954
  }
11894
11955
  });
11895
11956
  writeAnalyticsQueue(remaining);
11957
+ dispatched.clear();
11958
+ delivered.clear();
11896
11959
  }
11897
11960
  function maybeShowTelemetryNotice() {
11898
11961
  if (isTelemetryDisabled() || isAgentMode()) return;
@@ -12006,7 +12069,8 @@ program.hook("preAction", (thisCommand, actionCommand) => {
12006
12069
  program.hook("postAction", async () => {
12007
12070
  await closeBackendIfCached();
12008
12071
  flushUsageRollups();
12009
- flush();
12072
+ drainQueue();
12073
+ await flush();
12010
12074
  if (!updateCheckPromise) return;
12011
12075
  const info = await updateCheckPromise;
12012
12076
  if (!info) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withone/cli",
3
- "version": "1.55.2",
3
+ "version": "1.55.3",
4
4
  "description": "CLI for managing One",
5
5
  "type": "module",
6
6
  "files": [