raindrop-ai 0.0.57 → 0.0.58

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 (3) hide show
  1. package/dist/index.js +117 -33
  2. package/dist/index.mjs +117 -33
  3. package/package.json +4 -2
package/dist/index.js CHANGED
@@ -108,7 +108,7 @@ var CategorizationRequestSchema = import_zod.z.object({
108
108
  // package.json
109
109
  var package_default = {
110
110
  name: "raindrop-ai",
111
- version: "0.0.57",
111
+ version: "0.0.58",
112
112
  main: "dist/index.js",
113
113
  module: "dist/index.mjs",
114
114
  types: "dist/index.d.ts",
@@ -140,12 +140,14 @@ var package_default = {
140
140
  dev: "tsup --watch",
141
141
  clean: "rm -rf .turbo && rm -rf dist",
142
142
  try: "tsx ./src/example/index.ts",
143
- prepublishOnly: "turbo build"
143
+ prepublishOnly: "turbo build",
144
+ smoke: "tsx ./scripts/smoke.ts"
144
145
  },
145
146
  devDependencies: {
146
147
  "@dawn/schemas": "*",
147
148
  "@types/node": "^20.11.17",
148
149
  tsup: "^8.4.0",
150
+ tsx: "^4.20.3",
149
151
  typescript: "^5.3.3"
150
152
  },
151
153
  dependencies: {
@@ -496,6 +498,61 @@ var AttachmentTypeSchema = import_zod2.z.enum(["code", "text", "image", "iframe"
496
498
  // src/index.ts
497
499
  process.env.TRACELOOP_TELEMETRY = "false";
498
500
  var MAX_INGEST_SIZE_BYTES = 1 * 1024 * 1024;
501
+ async function wait(ms) {
502
+ return new Promise((resolve) => setTimeout(resolve, ms));
503
+ }
504
+ function parseRetryAfter(headers) {
505
+ var _a;
506
+ const value = (_a = headers.get("Retry-After")) != null ? _a : headers.get("retry-after");
507
+ if (!value) return void 0;
508
+ const asNumber = Number(value);
509
+ if (!Number.isNaN(asNumber)) return asNumber * 1e3;
510
+ const asDate = new Date(value).getTime();
511
+ if (!Number.isNaN(asDate)) {
512
+ const delta = asDate - Date.now();
513
+ return delta > 0 ? delta : 0;
514
+ }
515
+ return void 0;
516
+ }
517
+ function getRetryDelayMs(attemptNumber, previousError) {
518
+ if (previousError && typeof previousError.retryAfterMs === "number") {
519
+ return Math.max(0, previousError.retryAfterMs);
520
+ }
521
+ if (attemptNumber <= 1) return 0;
522
+ const base = 500;
523
+ const factor = Math.pow(2, attemptNumber - 2);
524
+ return base * factor;
525
+ }
526
+ async function withRetry(operation, opName, maxAttempts, debugLogs = false) {
527
+ var _a;
528
+ let lastError = void 0;
529
+ for (let attemptNumber = 1; attemptNumber <= maxAttempts; attemptNumber++) {
530
+ if (attemptNumber > 1) {
531
+ const delay = getRetryDelayMs(attemptNumber, lastError);
532
+ if (debugLogs) {
533
+ console.warn(
534
+ `[raindrop] ${opName} retrying attempt ${attemptNumber}/${maxAttempts} in ${delay}ms...`
535
+ );
536
+ }
537
+ if (delay > 0) await wait(delay);
538
+ } else if (debugLogs) {
539
+ console.log(`[raindrop] ${opName} attempt ${attemptNumber}/${maxAttempts}`);
540
+ }
541
+ try {
542
+ return await operation();
543
+ } catch (err) {
544
+ lastError = err;
545
+ const isLast = attemptNumber === maxAttempts;
546
+ if (debugLogs) {
547
+ console.warn(
548
+ `[raindrop] ${opName} attempt ${attemptNumber} failed: ${(_a = err == null ? void 0 : err.message) != null ? _a : err}. ${isLast ? "No more retries." : "Will retry."}`
549
+ );
550
+ }
551
+ if (isLast) break;
552
+ }
553
+ }
554
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
555
+ }
499
556
  var Raindrop = class {
500
557
  constructor(config) {
501
558
  this.flushTimer = null;
@@ -763,27 +820,43 @@ var Raindrop = class {
763
820
  return Promise.all(flushPromises);
764
821
  }
765
822
  async sendBatchToApi(events, endpoint) {
823
+ var _a;
824
+ const opName = `POST ${endpoint}`;
766
825
  try {
767
- const response = await fetch(this.apiUrl + endpoint, {
768
- method: "post",
769
- headers: {
770
- "Content-Type": "application/json",
771
- Authorization: `Bearer ${this.writeKey}`
826
+ const response = await withRetry(
827
+ async () => {
828
+ const resp = await fetch(this.apiUrl + endpoint, {
829
+ method: "post",
830
+ headers: {
831
+ "Content-Type": "application/json",
832
+ Authorization: `Bearer ${this.writeKey}`
833
+ },
834
+ body: JSON.stringify(events.map(({ type, ...event }) => event))
835
+ });
836
+ if (!resp.ok) {
837
+ const text = await resp.text().catch(() => "");
838
+ const err = new Error(
839
+ `HTTP ${resp.status} ${resp.statusText}${text ? `: ${text}` : ""}`
840
+ );
841
+ const retryAfterMs = parseRetryAfter(resp.headers);
842
+ if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
843
+ throw err;
844
+ }
845
+ return resp;
772
846
  },
773
- body: JSON.stringify(events.map(({ type, ...event }) => event))
774
- });
775
- if (!response.ok) {
776
- throw new Error(response.statusText);
777
- }
847
+ opName,
848
+ 3,
849
+ this.debugLogs
850
+ );
778
851
  if (this.debugLogs) {
779
- console.log("[raindrop] Success: " + JSON.stringify(response.status));
852
+ console.log(`[raindrop] Success: ${response.status} (${opName})`);
780
853
  }
781
854
  return response;
782
855
  } catch (error) {
783
- if (error.response) {
784
- console.error("[raindrop] Error in response: " + error.response.data);
856
+ if (error == null ? void 0 : error.response) {
857
+ console.error(`[raindrop] Error in response (${opName}): ` + error.response.data);
785
858
  } else {
786
- console.error("[raindrop] Error: " + error.message);
859
+ console.error(`[raindrop] Error (${opName}): ` + ((_a = error == null ? void 0 : error.message) != null ? _a : String(error)));
787
860
  }
788
861
  }
789
862
  }
@@ -965,25 +1038,36 @@ var Raindrop = class {
965
1038
  * @param event - The event data conforming to ClientAiTrack schema.
966
1039
  */
967
1040
  async sendPartialEvent(event) {
1041
+ var _a;
968
1042
  const endpoint = "events/track_partial";
1043
+ const opName = `POST ${endpoint}`;
969
1044
  try {
970
- const response = await fetch(this.apiUrl + endpoint, {
971
- method: "POST",
972
- headers: {
973
- "Content-Type": "application/json",
974
- Authorization: `Bearer ${this.writeKey}`
1045
+ const response = await withRetry(
1046
+ async () => {
1047
+ const resp = await fetch(this.apiUrl + endpoint, {
1048
+ method: "POST",
1049
+ headers: {
1050
+ "Content-Type": "application/json",
1051
+ Authorization: `Bearer ${this.writeKey}`
1052
+ },
1053
+ body: JSON.stringify(event)
1054
+ // Send the single event object
1055
+ });
1056
+ if (!resp.ok) {
1057
+ const errorBody = await resp.text().catch(() => "");
1058
+ const err = new Error(
1059
+ `HTTP ${resp.status} ${resp.statusText}${errorBody ? `: ${errorBody}` : ""}`
1060
+ );
1061
+ const retryAfterMs = parseRetryAfter(resp.headers);
1062
+ if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
1063
+ throw err;
1064
+ }
1065
+ return resp;
975
1066
  },
976
- body: JSON.stringify(event)
977
- // Send the single event object
978
- });
979
- if (!response.ok) {
980
- const errorBody = await response.text();
981
- console.error(
982
- `[raindrop] Error sending partial event ${event.event_id} to ${endpoint}: ${response.status} ${response.statusText}`,
983
- errorBody
984
- );
985
- throw new Error(`HTTP ${response.status} ${response.statusText}`);
986
- }
1067
+ opName,
1068
+ 3,
1069
+ this.debugLogs
1070
+ );
987
1071
  if (this.debugLogs) {
988
1072
  console.log(
989
1073
  `[raindrop] Successfully sent partial event ${event.event_id} to ${endpoint}: ${response.status}`
@@ -992,7 +1076,7 @@ var Raindrop = class {
992
1076
  return response;
993
1077
  } catch (error) {
994
1078
  console.error(
995
- `[raindrop] Failed to send partial event ${event.event_id} to ${endpoint}: ${error.message}`
1079
+ `[raindrop] Failed to send partial event ${event.event_id} to ${endpoint}: ${(_a = error == null ? void 0 : error.message) != null ? _a : String(error)}`
996
1080
  );
997
1081
  throw error;
998
1082
  }
package/dist/index.mjs CHANGED
@@ -85,7 +85,7 @@ var CategorizationRequestSchema = z.object({
85
85
  // package.json
86
86
  var package_default = {
87
87
  name: "raindrop-ai",
88
- version: "0.0.57",
88
+ version: "0.0.58",
89
89
  main: "dist/index.js",
90
90
  module: "dist/index.mjs",
91
91
  types: "dist/index.d.ts",
@@ -117,12 +117,14 @@ var package_default = {
117
117
  dev: "tsup --watch",
118
118
  clean: "rm -rf .turbo && rm -rf dist",
119
119
  try: "tsx ./src/example/index.ts",
120
- prepublishOnly: "turbo build"
120
+ prepublishOnly: "turbo build",
121
+ smoke: "tsx ./scripts/smoke.ts"
121
122
  },
122
123
  devDependencies: {
123
124
  "@dawn/schemas": "*",
124
125
  "@types/node": "^20.11.17",
125
126
  tsup: "^8.4.0",
127
+ tsx: "^4.20.3",
126
128
  typescript: "^5.3.3"
127
129
  },
128
130
  dependencies: {
@@ -269,6 +271,61 @@ var AttachmentTypeSchema = z2.enum(["code", "text", "image", "iframe"]);
269
271
  // src/index.ts
270
272
  process.env.TRACELOOP_TELEMETRY = "false";
271
273
  var MAX_INGEST_SIZE_BYTES = 1 * 1024 * 1024;
274
+ async function wait(ms) {
275
+ return new Promise((resolve) => setTimeout(resolve, ms));
276
+ }
277
+ function parseRetryAfter(headers) {
278
+ var _a;
279
+ const value = (_a = headers.get("Retry-After")) != null ? _a : headers.get("retry-after");
280
+ if (!value) return void 0;
281
+ const asNumber = Number(value);
282
+ if (!Number.isNaN(asNumber)) return asNumber * 1e3;
283
+ const asDate = new Date(value).getTime();
284
+ if (!Number.isNaN(asDate)) {
285
+ const delta = asDate - Date.now();
286
+ return delta > 0 ? delta : 0;
287
+ }
288
+ return void 0;
289
+ }
290
+ function getRetryDelayMs(attemptNumber, previousError) {
291
+ if (previousError && typeof previousError.retryAfterMs === "number") {
292
+ return Math.max(0, previousError.retryAfterMs);
293
+ }
294
+ if (attemptNumber <= 1) return 0;
295
+ const base = 500;
296
+ const factor = Math.pow(2, attemptNumber - 2);
297
+ return base * factor;
298
+ }
299
+ async function withRetry(operation, opName, maxAttempts, debugLogs = false) {
300
+ var _a;
301
+ let lastError = void 0;
302
+ for (let attemptNumber = 1; attemptNumber <= maxAttempts; attemptNumber++) {
303
+ if (attemptNumber > 1) {
304
+ const delay = getRetryDelayMs(attemptNumber, lastError);
305
+ if (debugLogs) {
306
+ console.warn(
307
+ `[raindrop] ${opName} retrying attempt ${attemptNumber}/${maxAttempts} in ${delay}ms...`
308
+ );
309
+ }
310
+ if (delay > 0) await wait(delay);
311
+ } else if (debugLogs) {
312
+ console.log(`[raindrop] ${opName} attempt ${attemptNumber}/${maxAttempts}`);
313
+ }
314
+ try {
315
+ return await operation();
316
+ } catch (err) {
317
+ lastError = err;
318
+ const isLast = attemptNumber === maxAttempts;
319
+ if (debugLogs) {
320
+ console.warn(
321
+ `[raindrop] ${opName} attempt ${attemptNumber} failed: ${(_a = err == null ? void 0 : err.message) != null ? _a : err}. ${isLast ? "No more retries." : "Will retry."}`
322
+ );
323
+ }
324
+ if (isLast) break;
325
+ }
326
+ }
327
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
328
+ }
272
329
  var Raindrop = class {
273
330
  constructor(config) {
274
331
  this.flushTimer = null;
@@ -536,27 +593,43 @@ var Raindrop = class {
536
593
  return Promise.all(flushPromises);
537
594
  }
538
595
  async sendBatchToApi(events, endpoint) {
596
+ var _a;
597
+ const opName = `POST ${endpoint}`;
539
598
  try {
540
- const response = await fetch(this.apiUrl + endpoint, {
541
- method: "post",
542
- headers: {
543
- "Content-Type": "application/json",
544
- Authorization: `Bearer ${this.writeKey}`
599
+ const response = await withRetry(
600
+ async () => {
601
+ const resp = await fetch(this.apiUrl + endpoint, {
602
+ method: "post",
603
+ headers: {
604
+ "Content-Type": "application/json",
605
+ Authorization: `Bearer ${this.writeKey}`
606
+ },
607
+ body: JSON.stringify(events.map(({ type, ...event }) => event))
608
+ });
609
+ if (!resp.ok) {
610
+ const text = await resp.text().catch(() => "");
611
+ const err = new Error(
612
+ `HTTP ${resp.status} ${resp.statusText}${text ? `: ${text}` : ""}`
613
+ );
614
+ const retryAfterMs = parseRetryAfter(resp.headers);
615
+ if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
616
+ throw err;
617
+ }
618
+ return resp;
545
619
  },
546
- body: JSON.stringify(events.map(({ type, ...event }) => event))
547
- });
548
- if (!response.ok) {
549
- throw new Error(response.statusText);
550
- }
620
+ opName,
621
+ 3,
622
+ this.debugLogs
623
+ );
551
624
  if (this.debugLogs) {
552
- console.log("[raindrop] Success: " + JSON.stringify(response.status));
625
+ console.log(`[raindrop] Success: ${response.status} (${opName})`);
553
626
  }
554
627
  return response;
555
628
  } catch (error) {
556
- if (error.response) {
557
- console.error("[raindrop] Error in response: " + error.response.data);
629
+ if (error == null ? void 0 : error.response) {
630
+ console.error(`[raindrop] Error in response (${opName}): ` + error.response.data);
558
631
  } else {
559
- console.error("[raindrop] Error: " + error.message);
632
+ console.error(`[raindrop] Error (${opName}): ` + ((_a = error == null ? void 0 : error.message) != null ? _a : String(error)));
560
633
  }
561
634
  }
562
635
  }
@@ -738,25 +811,36 @@ var Raindrop = class {
738
811
  * @param event - The event data conforming to ClientAiTrack schema.
739
812
  */
740
813
  async sendPartialEvent(event) {
814
+ var _a;
741
815
  const endpoint = "events/track_partial";
816
+ const opName = `POST ${endpoint}`;
742
817
  try {
743
- const response = await fetch(this.apiUrl + endpoint, {
744
- method: "POST",
745
- headers: {
746
- "Content-Type": "application/json",
747
- Authorization: `Bearer ${this.writeKey}`
818
+ const response = await withRetry(
819
+ async () => {
820
+ const resp = await fetch(this.apiUrl + endpoint, {
821
+ method: "POST",
822
+ headers: {
823
+ "Content-Type": "application/json",
824
+ Authorization: `Bearer ${this.writeKey}`
825
+ },
826
+ body: JSON.stringify(event)
827
+ // Send the single event object
828
+ });
829
+ if (!resp.ok) {
830
+ const errorBody = await resp.text().catch(() => "");
831
+ const err = new Error(
832
+ `HTTP ${resp.status} ${resp.statusText}${errorBody ? `: ${errorBody}` : ""}`
833
+ );
834
+ const retryAfterMs = parseRetryAfter(resp.headers);
835
+ if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
836
+ throw err;
837
+ }
838
+ return resp;
748
839
  },
749
- body: JSON.stringify(event)
750
- // Send the single event object
751
- });
752
- if (!response.ok) {
753
- const errorBody = await response.text();
754
- console.error(
755
- `[raindrop] Error sending partial event ${event.event_id} to ${endpoint}: ${response.status} ${response.statusText}`,
756
- errorBody
757
- );
758
- throw new Error(`HTTP ${response.status} ${response.statusText}`);
759
- }
840
+ opName,
841
+ 3,
842
+ this.debugLogs
843
+ );
760
844
  if (this.debugLogs) {
761
845
  console.log(
762
846
  `[raindrop] Successfully sent partial event ${event.event_id} to ${endpoint}: ${response.status}`
@@ -765,7 +849,7 @@ var Raindrop = class {
765
849
  return response;
766
850
  } catch (error) {
767
851
  console.error(
768
- `[raindrop] Failed to send partial event ${event.event_id} to ${endpoint}: ${error.message}`
852
+ `[raindrop] Failed to send partial event ${event.event_id} to ${endpoint}: ${(_a = error == null ? void 0 : error.message) != null ? _a : String(error)}`
769
853
  );
770
854
  throw error;
771
855
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "raindrop-ai",
3
- "version": "0.0.57",
3
+ "version": "0.0.58",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -32,12 +32,14 @@
32
32
  "dev": "tsup --watch",
33
33
  "clean": "rm -rf .turbo && rm -rf dist",
34
34
  "try": "tsx ./src/example/index.ts",
35
- "prepublishOnly": "turbo build"
35
+ "prepublishOnly": "turbo build",
36
+ "smoke": "tsx ./scripts/smoke.ts"
36
37
  },
37
38
  "devDependencies": {
38
39
  "@dawn/schemas": "*",
39
40
  "@types/node": "^20.11.17",
40
41
  "tsup": "^8.4.0",
42
+ "tsx": "^4.20.3",
41
43
  "typescript": "^5.3.3"
42
44
  },
43
45
  "dependencies": {