@reopt-ai/data-contract 0.6.3 → 0.7.0

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 (103) hide show
  1. package/dist/client.cjs +228 -321
  2. package/dist/client.cjs.map +1 -1
  3. package/dist/client.d.cts +57 -71
  4. package/dist/client.d.cts.map +1 -0
  5. package/dist/client.d.ts +57 -71
  6. package/dist/client.d.ts.map +1 -0
  7. package/dist/client.js +228 -322
  8. package/dist/client.js.map +1 -1
  9. package/dist/control.cjs +158 -54
  10. package/dist/control.cjs.map +1 -1
  11. package/dist/control.d.cts +121 -137
  12. package/dist/control.d.cts.map +1 -0
  13. package/dist/control.d.ts +121 -137
  14. package/dist/control.d.ts.map +1 -0
  15. package/dist/control.js +134 -54
  16. package/dist/control.js.map +1 -1
  17. package/dist/events-BUIeU60t.d.cts +142 -0
  18. package/dist/events-BUIeU60t.d.cts.map +1 -0
  19. package/dist/events-BUIeU60t.d.ts +142 -0
  20. package/dist/events-BUIeU60t.d.ts.map +1 -0
  21. package/dist/events.cjs +110 -15
  22. package/dist/events.cjs.map +1 -1
  23. package/dist/events.d.cts +2 -59
  24. package/dist/events.d.ts +2 -59
  25. package/dist/events.js +101 -15
  26. package/dist/events.js.map +1 -1
  27. package/dist/identity.cjs +150 -55
  28. package/dist/identity.cjs.map +1 -1
  29. package/dist/identity.d.cts +21 -20
  30. package/dist/identity.d.cts.map +1 -0
  31. package/dist/identity.d.ts +21 -20
  32. package/dist/identity.d.ts.map +1 -0
  33. package/dist/identity.js +126 -56
  34. package/dist/identity.js.map +1 -1
  35. package/dist/index.cjs +46 -25
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.d.cts +37 -54
  38. package/dist/index.d.cts.map +1 -0
  39. package/dist/index.d.ts +37 -54
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +36 -25
  42. package/dist/index.js.map +1 -1
  43. package/dist/ingest.cjs +152 -57
  44. package/dist/ingest.cjs.map +1 -1
  45. package/dist/ingest.d.cts +182 -193
  46. package/dist/ingest.d.cts.map +1 -0
  47. package/dist/ingest.d.ts +182 -193
  48. package/dist/ingest.d.ts.map +1 -0
  49. package/dist/ingest.js +126 -57
  50. package/dist/ingest.js.map +1 -1
  51. package/dist/query.cjs +284 -84
  52. package/dist/query.cjs.map +1 -1
  53. package/dist/query.d.cts +456 -469
  54. package/dist/query.d.cts.map +1 -0
  55. package/dist/query.d.ts +456 -469
  56. package/dist/query.d.ts.map +1 -0
  57. package/dist/query.js +245 -84
  58. package/dist/query.js.map +1 -1
  59. package/dist/report.cjs +104 -74
  60. package/dist/report.cjs.map +1 -1
  61. package/dist/report.d.cts +182 -136
  62. package/dist/report.d.cts.map +1 -0
  63. package/dist/report.d.ts +182 -136
  64. package/dist/report.d.ts.map +1 -0
  65. package/dist/report.js +93 -74
  66. package/dist/report.js.map +1 -1
  67. package/dist/version-B_0qb1_K.cjs +53 -0
  68. package/dist/version-B_0qb1_K.cjs.map +1 -0
  69. package/dist/version-C09Cyf4R.js +12 -0
  70. package/dist/version-C09Cyf4R.js.map +1 -0
  71. package/dist/{version-DJ2Grb_N.d.ts → version-CGujUGWd.d.cts} +5 -3
  72. package/dist/version-CGujUGWd.d.cts.map +1 -0
  73. package/dist/{version-DJ2Grb_N.d.cts → version-CGujUGWd.d.ts} +5 -3
  74. package/dist/version-CGujUGWd.d.ts.map +1 -0
  75. package/package.json +69 -28
  76. package/dist/chunk-3EEANNYN.cjs +0 -62
  77. package/dist/chunk-3EEANNYN.cjs.map +0 -1
  78. package/dist/chunk-7W33YGRO.js +0 -160
  79. package/dist/chunk-7W33YGRO.js.map +0 -1
  80. package/dist/chunk-F2RNXJGO.cjs +0 -19
  81. package/dist/chunk-F2RNXJGO.cjs.map +0 -1
  82. package/dist/chunk-FP2X3PRK.js +0 -62
  83. package/dist/chunk-FP2X3PRK.js.map +0 -1
  84. package/dist/chunk-JCEWUSUM.js +0 -53
  85. package/dist/chunk-JCEWUSUM.js.map +0 -1
  86. package/dist/chunk-L3JPDRVG.cjs +0 -160
  87. package/dist/chunk-L3JPDRVG.cjs.map +0 -1
  88. package/dist/chunk-L4KBQAOO.js +0 -204
  89. package/dist/chunk-L4KBQAOO.js.map +0 -1
  90. package/dist/chunk-NJ4JKNBX.js +0 -361
  91. package/dist/chunk-NJ4JKNBX.js.map +0 -1
  92. package/dist/chunk-ORNTN6AK.cjs +0 -53
  93. package/dist/chunk-ORNTN6AK.cjs.map +0 -1
  94. package/dist/chunk-PSUINLW7.js +0 -19
  95. package/dist/chunk-PSUINLW7.js.map +0 -1
  96. package/dist/chunk-RU26QFM2.js +0 -179
  97. package/dist/chunk-RU26QFM2.js.map +0 -1
  98. package/dist/chunk-XDH5QQYF.cjs +0 -361
  99. package/dist/chunk-XDH5QQYF.cjs.map +0 -1
  100. package/dist/chunk-YCTGHWTP.cjs +0 -204
  101. package/dist/chunk-YCTGHWTP.cjs.map +0 -1
  102. package/dist/chunk-ZI6A3WQP.cjs +0 -179
  103. package/dist/chunk-ZI6A3WQP.cjs.map +0 -1
package/dist/client.js CHANGED
@@ -1,336 +1,242 @@
1
- import {
2
- zIngestResponse
3
- } from "./chunk-RU26QFM2.js";
4
- import {
5
- CONTROL_API_PATHS,
6
- ORG_KEY_HEADER,
7
- PLATFORM_KEY_HEADER,
8
- zCreateOrganizationResponse,
9
- zCreateProjectResponse,
10
- zDeleteProjectResponse,
11
- zEventMetaResponse,
12
- zRotateClientSecretResponse,
13
- zRotateOrganizationKeyResponse,
14
- zUpdateOrganizationQuotaResponse
15
- } from "./chunk-L4KBQAOO.js";
16
- import {
17
- QUERY_API_PATHS,
18
- zEventsTimeseriesResponse,
19
- zFunnelResponse,
20
- zRetentionResponse,
21
- zTrafficOverviewResponse,
22
- zTrafficSourcesResponse
23
- } from "./chunk-NJ4JKNBX.js";
24
- import {
25
- DataApiError
26
- } from "./chunk-JCEWUSUM.js";
27
- import "./chunk-7W33YGRO.js";
28
- import {
29
- CLIENT_ID_HEADER,
30
- CLIENT_SECRET_HEADER,
31
- CONTRACT_VERSION,
32
- CONTRACT_VERSION_HEADER,
33
- REQUEST_ID_HEADER
34
- } from "./chunk-PSUINLW7.js";
35
- import "./chunk-FP2X3PRK.js";
36
-
37
- // src/client.ts
38
- var TRACK_PATH = "/api/track";
39
- var DEFAULTS = {
40
- timeoutMs: 1e4,
41
- maxRetries: 2,
42
- baseDelayMs: 500,
43
- maxDelayMs: 2e4
1
+ import { i as CONTRACT_VERSION_HEADER, n as CLIENT_SECRET_HEADER, r as CONTRACT_VERSION, t as CLIENT_ID_HEADER } from "./version-C09Cyf4R.js";
2
+ import { DataApiError } from "./index.js";
3
+ import { zIngestResponse } from "./ingest.js";
4
+ import { QUERY_API_PATHS, zEventsTimeseriesResponse, zFunnelResponse, zRetentionResponse, zTrafficOverviewResponse, zTrafficSourcesResponse } from "./query.js";
5
+ import { CONTROL_API_PATHS, ORG_KEY_HEADER, PLATFORM_KEY_HEADER, zCreateOrganizationResponse, zCreateProjectResponse, zDeleteProjectResponse, zEventMetaResponse, zRotateClientSecretResponse, zRotateOrganizationKeyResponse, zUpdateOrganizationQuotaResponse } from "./control.js";
6
+ //#region src/client.ts
7
+ const TRACK_PATH = "/api/track";
8
+ const DEFAULTS = {
9
+ timeoutMs: 1e4,
10
+ maxRetries: 2,
11
+ baseDelayMs: 500,
12
+ maxDelayMs: 2e4
44
13
  };
45
14
  function normalizeBaseUrl(baseUrl) {
46
- return baseUrl.replace(/\/+$/, "");
15
+ return baseUrl.replace(/\/+$/, "");
47
16
  }
48
17
  function parseRetryAfter(header) {
49
- if (!header) return void 0;
50
- const seconds = Number(header);
51
- if (Number.isFinite(seconds) && seconds >= 0) return Math.round(seconds * 1e3);
52
- const at = Date.parse(header);
53
- if (Number.isFinite(at)) return Math.max(0, at - Date.now());
54
- return void 0;
18
+ if (!header) return void 0;
19
+ const seconds = Number(header);
20
+ if (Number.isFinite(seconds) && seconds >= 0) return Math.round(seconds * 1e3);
21
+ const at = Date.parse(header);
22
+ if (Number.isFinite(at)) return Math.max(0, at - Date.now());
55
23
  }
56
24
  function sleep(ms, signal) {
57
- return new Promise((resolve, reject) => {
58
- if (signal?.aborted) {
59
- reject(signal.reason ?? new Error("Aborted"));
60
- return;
61
- }
62
- const timer = setTimeout(() => {
63
- signal?.removeEventListener("abort", onAbort);
64
- resolve();
65
- }, ms);
66
- const onAbort = () => {
67
- clearTimeout(timer);
68
- reject(signal?.reason ?? new Error("Aborted"));
69
- };
70
- signal?.addEventListener("abort", onAbort, { once: true });
71
- });
25
+ return new Promise((resolve, reject) => {
26
+ if (signal?.aborted) {
27
+ reject(signal.reason ?? new Error("Aborted"));
28
+ return;
29
+ }
30
+ const timer = setTimeout(() => {
31
+ signal?.removeEventListener("abort", onAbort);
32
+ resolve();
33
+ }, ms);
34
+ const onAbort = () => {
35
+ clearTimeout(timer);
36
+ reject(signal?.reason ?? new Error("Aborted"));
37
+ };
38
+ signal?.addEventListener("abort", onAbort, { once: true });
39
+ });
72
40
  }
73
41
  function backoffDelay(attempt, retry) {
74
- const exponential = retry.baseDelayMs * 2 ** attempt;
75
- const capped = Math.min(exponential, retry.maxDelayMs);
76
- return Math.round(capped * (0.5 + Math.random() * 0.5));
42
+ const exponential = retry.baseDelayMs * 2 ** attempt;
43
+ const capped = Math.min(exponential, retry.maxDelayMs);
44
+ return Math.round(capped * (.5 + Math.random() * .5));
77
45
  }
78
46
  function toApiError(status, rawBody, retryAfterMs, requestId) {
79
- let parsed;
80
- try {
81
- parsed = JSON.parse(rawBody);
82
- } catch {
83
- return new DataApiError({
84
- message: `reopt-data responded ${status} with a non-JSON body`,
85
- status,
86
- code: status >= 500 ? "internal_error" : "unknown_error",
87
- requestId,
88
- retryAfterMs,
89
- details: rawBody.slice(0, 2e3)
90
- });
91
- }
92
- const body = parsed ?? {};
93
- const code = typeof body.code === "string" ? body.code : status >= 500 ? "internal_error" : "unknown_error";
94
- const message = typeof body.message === "string" && body.message || typeof body.error === "string" && body.error || `reopt-data responded ${status}`;
95
- return new DataApiError({
96
- message,
97
- status,
98
- code,
99
- requestId: (typeof body.requestId === "string" ? body.requestId : void 0) ?? requestId,
100
- retryAfterMs,
101
- details: body.errors ?? void 0
102
- });
47
+ let parsed;
48
+ try {
49
+ parsed = JSON.parse(rawBody);
50
+ } catch {
51
+ return new DataApiError({
52
+ message: `reopt-data responded ${status} with a non-JSON body`,
53
+ status,
54
+ code: status >= 500 ? "internal_error" : "unknown_error",
55
+ requestId,
56
+ retryAfterMs,
57
+ details: rawBody.slice(0, 2e3)
58
+ });
59
+ }
60
+ const body = parsed ?? {};
61
+ const code = typeof body.code === "string" ? body.code : status >= 500 ? "internal_error" : "unknown_error";
62
+ const message = typeof body.message === "string" && body.message || typeof body.error === "string" && body.error || `reopt-data responded ${status}`;
63
+ return new DataApiError({
64
+ message,
65
+ status,
66
+ code,
67
+ requestId: (typeof body.requestId === "string" ? body.requestId : void 0) ?? requestId,
68
+ retryAfterMs,
69
+ details: body.errors ?? void 0
70
+ });
103
71
  }
104
72
  function createDataClient(options) {
105
- const baseUrl = normalizeBaseUrl(options.baseUrl);
106
- const doFetch = options.fetch ?? globalThis.fetch;
107
- if (typeof doFetch !== "function") {
108
- throw new TypeError("createDataClient: no fetch implementation available \u2014 pass options.fetch");
109
- }
110
- const timeoutMs = options.timeoutMs ?? DEFAULTS.timeoutMs;
111
- const retry = {
112
- maxRetries: options.retry?.maxRetries ?? DEFAULTS.maxRetries,
113
- baseDelayMs: options.retry?.baseDelayMs ?? DEFAULTS.baseDelayMs,
114
- maxDelayMs: options.retry?.maxDelayMs ?? DEFAULTS.maxDelayMs,
115
- respectRetryAfter: options.retry?.respectRetryAfter ?? true
116
- };
117
- const userAgent = options.userAgent ? `reopt-data-contract/${CONTRACT_VERSION} ${options.userAgent}` : `reopt-data-contract/${CONTRACT_VERSION}`;
118
- function requireClientCredentials() {
119
- if (!options.clientId || !options.clientSecret) {
120
- throw new DataApiError({
121
- message: "createDataClient was given no client credentials \u2014 pass clientId and clientSecret to use the ingest or query planes",
122
- status: 0,
123
- code: "credentials_missing"
124
- });
125
- }
126
- return { clientId: options.clientId, clientSecret: options.clientSecret };
127
- }
128
- async function requestOnce(method, path, body, extraHeaders, signal) {
129
- const controller = new AbortController();
130
- const timer = setTimeout(
131
- () => controller.abort(new Error(`reopt-data request timed out after ${timeoutMs}ms`)),
132
- timeoutMs
133
- );
134
- const onCallerAbort = () => controller.abort(signal?.reason ?? new Error("Aborted"));
135
- signal?.addEventListener("abort", onCallerAbort, { once: true });
136
- try {
137
- return await doFetch(`${baseUrl}${path}`, {
138
- method,
139
- headers: {
140
- "content-type": "application/json",
141
- "user-agent": userAgent,
142
- ...options.clientId && options.clientSecret ? { [CLIENT_ID_HEADER]: options.clientId, [CLIENT_SECRET_HEADER]: options.clientSecret } : {},
143
- ...extraHeaders
144
- },
145
- body: JSON.stringify(body),
146
- signal: controller.signal
147
- });
148
- } finally {
149
- clearTimeout(timer);
150
- signal?.removeEventListener("abort", onCallerAbort);
151
- }
152
- }
153
- async function send(method, path, body, parse, extraHeaders = {}, signal) {
154
- let lastError;
155
- for (let attempt = 0; attempt <= retry.maxRetries; attempt++) {
156
- let response;
157
- try {
158
- response = await requestOnce(method, path, body, extraHeaders, signal);
159
- } catch (cause) {
160
- if (signal?.aborted) throw cause;
161
- lastError = new DataApiError({
162
- message: cause instanceof Error ? cause.message : String(cause),
163
- status: 0,
164
- code: "network_error",
165
- details: cause
166
- });
167
- if (attempt < retry.maxRetries) {
168
- await sleep(backoffDelay(attempt, retry), signal);
169
- continue;
170
- }
171
- throw lastError;
172
- }
173
- const requestId = response.headers.get(REQUEST_ID_HEADER) ?? void 0;
174
- const serverContractVersion = response.headers.get(CONTRACT_VERSION_HEADER);
175
- const rawBody = await response.text();
176
- if (serverContractVersion !== CONTRACT_VERSION) {
177
- throw new DataApiError({
178
- message: serverContractVersion ? `reopt-data contract ${serverContractVersion} does not match client contract ${CONTRACT_VERSION}` : "reopt-data response did not declare its contract version",
179
- status: response.status,
180
- code: "contract_mismatch",
181
- requestId,
182
- details: { expected: CONTRACT_VERSION, received: serverContractVersion }
183
- });
184
- }
185
- if (response.ok) {
186
- let json;
187
- try {
188
- json = JSON.parse(rawBody);
189
- } catch (cause) {
190
- throw new DataApiError({
191
- message: "reopt-data returned a 2xx with an unparseable body",
192
- status: response.status,
193
- code: "contract_mismatch",
194
- requestId,
195
- details: cause
196
- });
197
- }
198
- try {
199
- return parse(json);
200
- } catch (cause) {
201
- throw new DataApiError({
202
- message: "reopt-data returned a 2xx that does not match the contract",
203
- status: response.status,
204
- code: "contract_mismatch",
205
- requestId,
206
- details: cause
207
- });
208
- }
209
- }
210
- const retryAfterMs = retry.respectRetryAfter ? parseRetryAfter(response.headers.get("retry-after")) : void 0;
211
- lastError = toApiError(response.status, rawBody, retryAfterMs, requestId);
212
- if (!lastError.retryable || attempt === retry.maxRetries) throw lastError;
213
- await sleep(retryAfterMs ?? backoffDelay(attempt, retry), signal);
214
- }
215
- throw lastError ?? new DataApiError({ message: "reopt-data request failed", status: 0, code: "network_error" });
216
- }
217
- async function post(path, body, parse, signal) {
218
- requireClientCredentials();
219
- return send("POST", path, body, parse, {}, signal);
220
- }
221
- return {
222
- ingest: {
223
- track(events, init) {
224
- return post(TRACK_PATH, events, (value) => zIngestResponse.parse(value), init?.signal);
225
- }
226
- },
227
- query: {
228
- eventsTimeseries(input, init) {
229
- return post(
230
- QUERY_API_PATHS.eventsTimeseries,
231
- input,
232
- (value) => zEventsTimeseriesResponse.parse(value),
233
- init?.signal
234
- );
235
- },
236
- funnel(input, init) {
237
- return post(QUERY_API_PATHS.funnel, input, (value) => zFunnelResponse.parse(value), init?.signal);
238
- },
239
- retention(input, init) {
240
- return post(QUERY_API_PATHS.retention, input, (value) => zRetentionResponse.parse(value), init?.signal);
241
- },
242
- trafficOverview(input, init) {
243
- return post(
244
- QUERY_API_PATHS.trafficOverview,
245
- input,
246
- (value) => zTrafficOverviewResponse.parse(value),
247
- init?.signal
248
- );
249
- },
250
- trafficSources(input, init) {
251
- return post(
252
- QUERY_API_PATHS.trafficSources,
253
- input,
254
- (value) => zTrafficSourcesResponse.parse(value),
255
- init?.signal
256
- );
257
- }
258
- },
259
- control: {
260
- createOrganization(input, auth, init) {
261
- return send(
262
- "POST",
263
- CONTROL_API_PATHS.organizations,
264
- input,
265
- (value) => zCreateOrganizationResponse.parse(value),
266
- { [PLATFORM_KEY_HEADER]: auth.platformKey },
267
- init?.signal
268
- );
269
- },
270
- rotateOrgKey(organizationId, auth, init) {
271
- return send(
272
- "POST",
273
- CONTROL_API_PATHS.organizationKeys(organizationId),
274
- {},
275
- (value) => zRotateOrganizationKeyResponse.parse(value),
276
- { [PLATFORM_KEY_HEADER]: auth.platformKey },
277
- init?.signal
278
- );
279
- },
280
- updateOrganizationQuota(organizationId, input, auth, init) {
281
- return send(
282
- "PATCH",
283
- CONTROL_API_PATHS.organization(organizationId),
284
- input,
285
- (value) => zUpdateOrganizationQuotaResponse.parse(value),
286
- { [PLATFORM_KEY_HEADER]: auth.platformKey },
287
- init?.signal
288
- );
289
- },
290
- createProject(input, auth, init) {
291
- return send(
292
- "POST",
293
- CONTROL_API_PATHS.projects,
294
- input,
295
- (value) => zCreateProjectResponse.parse(value),
296
- { [ORG_KEY_HEADER]: auth.orgKey },
297
- init?.signal
298
- );
299
- },
300
- rotateServerClientSecret(projectId, clientId, auth, init) {
301
- return send(
302
- "POST",
303
- CONTROL_API_PATHS.clientRotate(projectId, clientId),
304
- {},
305
- (value) => zRotateClientSecretResponse.parse(value),
306
- { [ORG_KEY_HEADER]: auth.orgKey },
307
- init?.signal
308
- );
309
- },
310
- deleteProject(projectId, input, auth, init) {
311
- return send(
312
- "DELETE",
313
- CONTROL_API_PATHS.project(projectId),
314
- input,
315
- (value) => zDeleteProjectResponse.parse(value),
316
- { [ORG_KEY_HEADER]: auth.orgKey },
317
- init?.signal
318
- );
319
- },
320
- upsertEventMeta(projectId, name, input, auth, init) {
321
- return send(
322
- "PUT",
323
- CONTROL_API_PATHS.projectEvent(projectId, name),
324
- input,
325
- (value) => zEventMetaResponse.parse(value),
326
- { [ORG_KEY_HEADER]: auth.orgKey },
327
- init?.signal
328
- );
329
- }
330
- }
331
- };
73
+ const baseUrl = normalizeBaseUrl(options.baseUrl);
74
+ const doFetch = options.fetch ?? globalThis.fetch;
75
+ if (typeof doFetch !== "function") throw new TypeError("createDataClient: no fetch implementation available — pass options.fetch");
76
+ const timeoutMs = options.timeoutMs ?? DEFAULTS.timeoutMs;
77
+ const retry = {
78
+ maxRetries: options.retry?.maxRetries ?? DEFAULTS.maxRetries,
79
+ baseDelayMs: options.retry?.baseDelayMs ?? DEFAULTS.baseDelayMs,
80
+ maxDelayMs: options.retry?.maxDelayMs ?? DEFAULTS.maxDelayMs,
81
+ respectRetryAfter: options.retry?.respectRetryAfter ?? true
82
+ };
83
+ const userAgent = options.userAgent ? `reopt-data-contract/${CONTRACT_VERSION} ${options.userAgent}` : `reopt-data-contract/${CONTRACT_VERSION}`;
84
+ function requireClientCredentials() {
85
+ if (!options.clientId || !options.clientSecret) throw new DataApiError({
86
+ message: "createDataClient was given no client credentials — pass clientId and clientSecret to use the ingest or query planes",
87
+ status: 0,
88
+ code: "credentials_missing"
89
+ });
90
+ return {
91
+ clientId: options.clientId,
92
+ clientSecret: options.clientSecret
93
+ };
94
+ }
95
+ async function requestOnce(method, path, body, extraHeaders, signal) {
96
+ const controller = new AbortController();
97
+ const timer = setTimeout(() => controller.abort(new Error(`reopt-data request timed out after ${timeoutMs}ms`)), timeoutMs);
98
+ const onCallerAbort = () => controller.abort(signal?.reason ?? new Error("Aborted"));
99
+ signal?.addEventListener("abort", onCallerAbort, { once: true });
100
+ try {
101
+ return await doFetch(`${baseUrl}${path}`, {
102
+ method,
103
+ headers: {
104
+ "content-type": "application/json",
105
+ "user-agent": userAgent,
106
+ ...options.clientId && options.clientSecret ? {
107
+ [CLIENT_ID_HEADER]: options.clientId,
108
+ [CLIENT_SECRET_HEADER]: options.clientSecret
109
+ } : {},
110
+ ...extraHeaders
111
+ },
112
+ body: JSON.stringify(body),
113
+ signal: controller.signal
114
+ });
115
+ } finally {
116
+ clearTimeout(timer);
117
+ signal?.removeEventListener("abort", onCallerAbort);
118
+ }
119
+ }
120
+ async function send(method, path, body, parse, extraHeaders = {}, signal) {
121
+ let lastError;
122
+ for (let attempt = 0; attempt <= retry.maxRetries; attempt++) {
123
+ let response;
124
+ try {
125
+ response = await requestOnce(method, path, body, extraHeaders, signal);
126
+ } catch (cause) {
127
+ if (signal?.aborted) throw cause;
128
+ lastError = new DataApiError({
129
+ message: cause instanceof Error ? cause.message : String(cause),
130
+ status: 0,
131
+ code: "network_error",
132
+ details: cause
133
+ });
134
+ if (attempt < retry.maxRetries) {
135
+ await sleep(backoffDelay(attempt, retry), signal);
136
+ continue;
137
+ }
138
+ throw lastError;
139
+ }
140
+ const requestId = response.headers.get("x-request-id") ?? void 0;
141
+ const serverContractVersion = response.headers.get(CONTRACT_VERSION_HEADER);
142
+ const rawBody = await response.text();
143
+ if (serverContractVersion !== "0.7.0") throw new DataApiError({
144
+ message: serverContractVersion ? `reopt-data contract ${serverContractVersion} does not match client contract ${CONTRACT_VERSION}` : "reopt-data response did not declare its contract version",
145
+ status: response.status,
146
+ code: "contract_mismatch",
147
+ requestId,
148
+ details: {
149
+ expected: CONTRACT_VERSION,
150
+ received: serverContractVersion
151
+ }
152
+ });
153
+ if (response.ok) {
154
+ let json;
155
+ try {
156
+ json = JSON.parse(rawBody);
157
+ } catch (cause) {
158
+ throw new DataApiError({
159
+ message: "reopt-data returned a 2xx with an unparseable body",
160
+ status: response.status,
161
+ code: "contract_mismatch",
162
+ requestId,
163
+ details: cause
164
+ });
165
+ }
166
+ try {
167
+ return parse(json);
168
+ } catch (cause) {
169
+ throw new DataApiError({
170
+ message: "reopt-data returned a 2xx that does not match the contract",
171
+ status: response.status,
172
+ code: "contract_mismatch",
173
+ requestId,
174
+ details: cause
175
+ });
176
+ }
177
+ }
178
+ const retryAfterMs = retry.respectRetryAfter ? parseRetryAfter(response.headers.get("retry-after")) : void 0;
179
+ lastError = toApiError(response.status, rawBody, retryAfterMs, requestId);
180
+ if (!lastError.retryable || attempt === retry.maxRetries) throw lastError;
181
+ await sleep(retryAfterMs ?? backoffDelay(attempt, retry), signal);
182
+ }
183
+ throw lastError ?? new DataApiError({
184
+ message: "reopt-data request failed",
185
+ status: 0,
186
+ code: "network_error"
187
+ });
188
+ }
189
+ async function post(path, body, parse, signal) {
190
+ requireClientCredentials();
191
+ return send("POST", path, body, parse, {}, signal);
192
+ }
193
+ return {
194
+ ingest: { track(events, init) {
195
+ return post(TRACK_PATH, events, (value) => zIngestResponse.parse(value), init?.signal);
196
+ } },
197
+ query: {
198
+ eventsTimeseries(input, init) {
199
+ return post(QUERY_API_PATHS.eventsTimeseries, input, (value) => zEventsTimeseriesResponse.parse(value), init?.signal);
200
+ },
201
+ funnel(input, init) {
202
+ return post(QUERY_API_PATHS.funnel, input, (value) => zFunnelResponse.parse(value), init?.signal);
203
+ },
204
+ retention(input, init) {
205
+ return post(QUERY_API_PATHS.retention, input, (value) => zRetentionResponse.parse(value), init?.signal);
206
+ },
207
+ trafficOverview(input, init) {
208
+ return post(QUERY_API_PATHS.trafficOverview, input, (value) => zTrafficOverviewResponse.parse(value), init?.signal);
209
+ },
210
+ trafficSources(input, init) {
211
+ return post(QUERY_API_PATHS.trafficSources, input, (value) => zTrafficSourcesResponse.parse(value), init?.signal);
212
+ }
213
+ },
214
+ control: {
215
+ createOrganization(input, auth, init) {
216
+ return send("POST", CONTROL_API_PATHS.organizations, input, (value) => zCreateOrganizationResponse.parse(value), { [PLATFORM_KEY_HEADER]: auth.platformKey }, init?.signal);
217
+ },
218
+ rotateOrgKey(organizationId, auth, init) {
219
+ return send("POST", CONTROL_API_PATHS.organizationKeys(organizationId), {}, (value) => zRotateOrganizationKeyResponse.parse(value), { [PLATFORM_KEY_HEADER]: auth.platformKey }, init?.signal);
220
+ },
221
+ updateOrganizationQuota(organizationId, input, auth, init) {
222
+ return send("PATCH", CONTROL_API_PATHS.organization(organizationId), input, (value) => zUpdateOrganizationQuotaResponse.parse(value), { [PLATFORM_KEY_HEADER]: auth.platformKey }, init?.signal);
223
+ },
224
+ createProject(input, auth, init) {
225
+ return send("POST", CONTROL_API_PATHS.projects, input, (value) => zCreateProjectResponse.parse(value), { [ORG_KEY_HEADER]: auth.orgKey }, init?.signal);
226
+ },
227
+ rotateServerClientSecret(projectId, clientId, auth, init) {
228
+ return send("POST", CONTROL_API_PATHS.clientRotate(projectId, clientId), {}, (value) => zRotateClientSecretResponse.parse(value), { [ORG_KEY_HEADER]: auth.orgKey }, init?.signal);
229
+ },
230
+ deleteProject(projectId, input, auth, init) {
231
+ return send("DELETE", CONTROL_API_PATHS.project(projectId), input, (value) => zDeleteProjectResponse.parse(value), { [ORG_KEY_HEADER]: auth.orgKey }, init?.signal);
232
+ },
233
+ upsertEventMeta(projectId, name, input, auth, init) {
234
+ return send("PUT", CONTROL_API_PATHS.projectEvent(projectId, name), input, (value) => zEventMetaResponse.parse(value), { [ORG_KEY_HEADER]: auth.orgKey }, init?.signal);
235
+ }
236
+ }
237
+ };
332
238
  }
333
- export {
334
- createDataClient
335
- };
239
+ //#endregion
240
+ export { createDataClient };
241
+
336
242
  //# sourceMappingURL=client.js.map