@reopt-ai/data-contract 0.2.0 → 0.3.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.
- package/dist/{chunk-IKOEYZVT.js → chunk-2LJ7JLDX.js} +2 -2
- package/dist/chunk-2LJ7JLDX.js.map +1 -0
- package/dist/{chunk-FRJK7OCQ.js → chunk-3A7WZ7L6.js} +3 -1
- package/dist/chunk-3A7WZ7L6.js.map +1 -0
- package/dist/{chunk-SC7TFGTO.js → chunk-55IWO4S3.js} +9 -5
- package/dist/chunk-55IWO4S3.js.map +1 -0
- package/dist/{chunk-LBSBZO7O.cjs → chunk-ATPS4UV6.cjs} +5 -5
- package/dist/{chunk-LBSBZO7O.cjs.map → chunk-ATPS4UV6.cjs.map} +1 -1
- package/dist/{chunk-GCLUMVPA.cjs → chunk-I2T4HRBM.cjs} +17 -13
- package/dist/chunk-I2T4HRBM.cjs.map +1 -0
- package/dist/{chunk-2SJPZP2D.js → chunk-J4VD3TLV.js} +3 -3
- package/dist/{chunk-CSTC3ADG.cjs → chunk-KXEQGD3E.cjs} +2 -2
- package/dist/{chunk-CSTC3ADG.cjs.map → chunk-KXEQGD3E.cjs.map} +1 -1
- package/dist/{chunk-HRKELGGH.cjs → chunk-RDPPPFGO.cjs} +3 -1
- package/dist/{chunk-FRJK7OCQ.js.map → chunk-RDPPPFGO.cjs.map} +1 -1
- package/dist/client.cjs +48 -38
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +2 -2
- package/dist/client.d.ts +2 -2
- package/dist/client.js +17 -7
- package/dist/client.js.map +1 -1
- package/dist/control.cjs +4 -4
- package/dist/control.js +3 -3
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +1 -1
- package/dist/ingest.cjs +2 -2
- package/dist/ingest.d.cts +3 -1
- package/dist/ingest.d.ts +3 -1
- package/dist/ingest.js +1 -1
- package/dist/query.cjs +5 -3
- package/dist/query.cjs.map +1 -1
- package/dist/query.d.cts +18 -2
- package/dist/query.d.ts +18 -2
- package/dist/query.js +4 -2
- package/package.json +1 -1
- package/dist/chunk-GCLUMVPA.cjs.map +0 -1
- package/dist/chunk-HRKELGGH.cjs.map +0 -1
- package/dist/chunk-IKOEYZVT.js.map +0 -1
- package/dist/chunk-SC7TFGTO.js.map +0 -1
- /package/dist/{chunk-2SJPZP2D.js.map → chunk-J4VD3TLV.js.map} +0 -0
package/dist/client.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkRDPPPFGOcjs = require('./chunk-RDPPPFGO.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
@@ -11,20 +11,20 @@ var _chunkHRKELGGHcjs = require('./chunk-HRKELGGH.cjs');
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
var
|
|
14
|
+
var _chunkATPS4UV6cjs = require('./chunk-ATPS4UV6.cjs');
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
var
|
|
20
|
+
var _chunkI2T4HRBMcjs = require('./chunk-I2T4HRBM.cjs');
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
var
|
|
27
|
+
var _chunkKXEQGD3Ecjs = require('./chunk-KXEQGD3E.cjs');
|
|
28
28
|
|
|
29
29
|
// src/client.ts
|
|
30
30
|
var TRACK_PATH = "/api/track";
|
|
@@ -72,7 +72,7 @@ function toApiError(status, rawBody, retryAfterMs, requestId) {
|
|
|
72
72
|
try {
|
|
73
73
|
parsed = JSON.parse(rawBody);
|
|
74
74
|
} catch (e) {
|
|
75
|
-
return new (0,
|
|
75
|
+
return new (0, _chunkKXEQGD3Ecjs.DataApiError)({
|
|
76
76
|
message: `reopt-data responded ${status} with a non-JSON body`,
|
|
77
77
|
status,
|
|
78
78
|
code: status >= 500 ? "internal_error" : "unknown_error",
|
|
@@ -84,7 +84,7 @@ function toApiError(status, rawBody, retryAfterMs, requestId) {
|
|
|
84
84
|
const body = _nullishCoalesce(parsed, () => ( {}));
|
|
85
85
|
const code = typeof body.code === "string" ? body.code : status >= 500 ? "internal_error" : "unknown_error";
|
|
86
86
|
const message = typeof body.message === "string" && body.message || typeof body.error === "string" && body.error || `reopt-data responded ${status}`;
|
|
87
|
-
return new (0,
|
|
87
|
+
return new (0, _chunkKXEQGD3Ecjs.DataApiError)({
|
|
88
88
|
message,
|
|
89
89
|
status,
|
|
90
90
|
code,
|
|
@@ -106,7 +106,17 @@ function createDataClient(options) {
|
|
|
106
106
|
maxDelayMs: _nullishCoalesce(_optionalChain([options, 'access', _11 => _11.retry, 'optionalAccess', _12 => _12.maxDelayMs]), () => ( DEFAULTS.maxDelayMs)),
|
|
107
107
|
respectRetryAfter: _nullishCoalesce(_optionalChain([options, 'access', _13 => _13.retry, 'optionalAccess', _14 => _14.respectRetryAfter]), () => ( true))
|
|
108
108
|
};
|
|
109
|
-
const userAgent = options.userAgent ? `reopt-data-contract/${
|
|
109
|
+
const userAgent = options.userAgent ? `reopt-data-contract/${_chunkKXEQGD3Ecjs.CONTRACT_VERSION} ${options.userAgent}` : `reopt-data-contract/${_chunkKXEQGD3Ecjs.CONTRACT_VERSION}`;
|
|
110
|
+
function requireClientCredentials() {
|
|
111
|
+
if (!options.clientId || !options.clientSecret) {
|
|
112
|
+
throw new (0, _chunkKXEQGD3Ecjs.DataApiError)({
|
|
113
|
+
message: "createDataClient was given no client credentials \u2014 pass clientId and clientSecret to use the ingest or query planes",
|
|
114
|
+
status: 0,
|
|
115
|
+
code: "credentials_missing"
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return { clientId: options.clientId, clientSecret: options.clientSecret };
|
|
119
|
+
}
|
|
110
120
|
async function requestOnce(method, path, body, extraHeaders, signal) {
|
|
111
121
|
const controller = new AbortController();
|
|
112
122
|
const timer = setTimeout(
|
|
@@ -121,8 +131,7 @@ function createDataClient(options) {
|
|
|
121
131
|
headers: {
|
|
122
132
|
"content-type": "application/json",
|
|
123
133
|
"user-agent": userAgent,
|
|
124
|
-
[
|
|
125
|
-
[_chunkCSTC3ADGcjs.CLIENT_SECRET_HEADER]: options.clientSecret,
|
|
134
|
+
...options.clientId && options.clientSecret ? { [_chunkKXEQGD3Ecjs.CLIENT_ID_HEADER]: options.clientId, [_chunkKXEQGD3Ecjs.CLIENT_SECRET_HEADER]: options.clientSecret } : {},
|
|
126
135
|
...extraHeaders
|
|
127
136
|
},
|
|
128
137
|
body: JSON.stringify(body),
|
|
@@ -141,7 +150,7 @@ function createDataClient(options) {
|
|
|
141
150
|
response = await requestOnce(method, path, body, extraHeaders, signal);
|
|
142
151
|
} catch (cause) {
|
|
143
152
|
if (_optionalChain([signal, 'optionalAccess', _20 => _20.aborted])) throw cause;
|
|
144
|
-
lastError = new (0,
|
|
153
|
+
lastError = new (0, _chunkKXEQGD3Ecjs.DataApiError)({
|
|
145
154
|
message: cause instanceof Error ? cause.message : String(cause),
|
|
146
155
|
status: 0,
|
|
147
156
|
code: "network_error",
|
|
@@ -153,14 +162,14 @@ function createDataClient(options) {
|
|
|
153
162
|
}
|
|
154
163
|
throw lastError;
|
|
155
164
|
}
|
|
156
|
-
const requestId = _nullishCoalesce(response.headers.get(
|
|
165
|
+
const requestId = _nullishCoalesce(response.headers.get(_chunkKXEQGD3Ecjs.REQUEST_ID_HEADER), () => ( void 0));
|
|
157
166
|
const rawBody = await response.text();
|
|
158
167
|
if (response.ok) {
|
|
159
168
|
let json;
|
|
160
169
|
try {
|
|
161
170
|
json = JSON.parse(rawBody);
|
|
162
171
|
} catch (cause) {
|
|
163
|
-
throw new (0,
|
|
172
|
+
throw new (0, _chunkKXEQGD3Ecjs.DataApiError)({
|
|
164
173
|
message: "reopt-data returned a 2xx with an unparseable body",
|
|
165
174
|
status: response.status,
|
|
166
175
|
code: "contract_mismatch",
|
|
@@ -171,7 +180,7 @@ function createDataClient(options) {
|
|
|
171
180
|
try {
|
|
172
181
|
return parse(json);
|
|
173
182
|
} catch (cause) {
|
|
174
|
-
throw new (0,
|
|
183
|
+
throw new (0, _chunkKXEQGD3Ecjs.DataApiError)({
|
|
175
184
|
message: "reopt-data returned a 2xx that does not match the contract",
|
|
176
185
|
status: response.status,
|
|
177
186
|
code: "contract_mismatch",
|
|
@@ -185,91 +194,92 @@ function createDataClient(options) {
|
|
|
185
194
|
if (!lastError.retryable || attempt === retry.maxRetries) throw lastError;
|
|
186
195
|
await sleep(_nullishCoalesce(retryAfterMs, () => ( backoffDelay(attempt, retry))), signal);
|
|
187
196
|
}
|
|
188
|
-
throw _nullishCoalesce(lastError, () => ( new (0,
|
|
197
|
+
throw _nullishCoalesce(lastError, () => ( new (0, _chunkKXEQGD3Ecjs.DataApiError)({ message: "reopt-data request failed", status: 0, code: "network_error" })));
|
|
189
198
|
}
|
|
190
|
-
function post(path, body, parse, signal) {
|
|
199
|
+
async function post(path, body, parse, signal) {
|
|
200
|
+
requireClientCredentials();
|
|
191
201
|
return send("POST", path, body, parse, {}, signal);
|
|
192
202
|
}
|
|
193
203
|
return {
|
|
194
204
|
ingest: {
|
|
195
205
|
track(events, init) {
|
|
196
|
-
return post(TRACK_PATH, events, (value) =>
|
|
206
|
+
return post(TRACK_PATH, events, (value) => _chunkRDPPPFGOcjs.zIngestResponse.parse(value), _optionalChain([init, 'optionalAccess', _21 => _21.signal]));
|
|
197
207
|
}
|
|
198
208
|
},
|
|
199
209
|
query: {
|
|
200
210
|
eventsTimeseries(input, init) {
|
|
201
211
|
return post(
|
|
202
|
-
|
|
212
|
+
_chunkI2T4HRBMcjs.QUERY_API_PATHS.eventsTimeseries,
|
|
203
213
|
input,
|
|
204
|
-
(value) =>
|
|
214
|
+
(value) => _chunkI2T4HRBMcjs.zEventsTimeseriesResponse.parse(value),
|
|
205
215
|
_optionalChain([init, 'optionalAccess', _22 => _22.signal])
|
|
206
216
|
);
|
|
207
217
|
},
|
|
208
218
|
funnel(input, init) {
|
|
209
|
-
return post(
|
|
219
|
+
return post(_chunkI2T4HRBMcjs.QUERY_API_PATHS.funnel, input, (value) => _chunkI2T4HRBMcjs.zFunnelResponse.parse(value), _optionalChain([init, 'optionalAccess', _23 => _23.signal]));
|
|
210
220
|
},
|
|
211
221
|
retention(input, init) {
|
|
212
|
-
return post(
|
|
222
|
+
return post(_chunkI2T4HRBMcjs.QUERY_API_PATHS.retention, input, (value) => _chunkI2T4HRBMcjs.zRetentionResponse.parse(value), _optionalChain([init, 'optionalAccess', _24 => _24.signal]));
|
|
213
223
|
}
|
|
214
224
|
},
|
|
215
225
|
control: {
|
|
216
226
|
createOrganization(input, auth, init) {
|
|
217
227
|
return send(
|
|
218
228
|
"POST",
|
|
219
|
-
|
|
229
|
+
_chunkATPS4UV6cjs.CONTROL_API_PATHS.organizations,
|
|
220
230
|
input,
|
|
221
|
-
(value) =>
|
|
222
|
-
{ [
|
|
231
|
+
(value) => _chunkATPS4UV6cjs.zCreateOrganizationResponse.parse(value),
|
|
232
|
+
{ [_chunkATPS4UV6cjs.PLATFORM_KEY_HEADER]: auth.platformKey },
|
|
223
233
|
_optionalChain([init, 'optionalAccess', _25 => _25.signal])
|
|
224
234
|
);
|
|
225
235
|
},
|
|
226
236
|
rotateOrgKey(organizationId, auth, init) {
|
|
227
237
|
return send(
|
|
228
238
|
"POST",
|
|
229
|
-
|
|
239
|
+
_chunkATPS4UV6cjs.CONTROL_API_PATHS.organizationKeys(organizationId),
|
|
230
240
|
{},
|
|
231
|
-
(value) =>
|
|
232
|
-
{ [
|
|
241
|
+
(value) => _chunkATPS4UV6cjs.zRotateOrganizationKeyResponse.parse(value),
|
|
242
|
+
{ [_chunkATPS4UV6cjs.PLATFORM_KEY_HEADER]: auth.platformKey },
|
|
233
243
|
_optionalChain([init, 'optionalAccess', _26 => _26.signal])
|
|
234
244
|
);
|
|
235
245
|
},
|
|
236
246
|
updateOrganizationQuota(organizationId, input, auth, init) {
|
|
237
247
|
return send(
|
|
238
248
|
"PATCH",
|
|
239
|
-
|
|
249
|
+
_chunkATPS4UV6cjs.CONTROL_API_PATHS.organization(organizationId),
|
|
240
250
|
input,
|
|
241
|
-
(value) =>
|
|
242
|
-
{ [
|
|
251
|
+
(value) => _chunkATPS4UV6cjs.zUpdateOrganizationQuotaResponse.parse(value),
|
|
252
|
+
{ [_chunkATPS4UV6cjs.PLATFORM_KEY_HEADER]: auth.platformKey },
|
|
243
253
|
_optionalChain([init, 'optionalAccess', _27 => _27.signal])
|
|
244
254
|
);
|
|
245
255
|
},
|
|
246
256
|
createProject(input, auth, init) {
|
|
247
257
|
return send(
|
|
248
258
|
"POST",
|
|
249
|
-
|
|
259
|
+
_chunkATPS4UV6cjs.CONTROL_API_PATHS.projects,
|
|
250
260
|
input,
|
|
251
|
-
(value) =>
|
|
252
|
-
{ [
|
|
261
|
+
(value) => _chunkATPS4UV6cjs.zCreateProjectResponse.parse(value),
|
|
262
|
+
{ [_chunkATPS4UV6cjs.ORG_KEY_HEADER]: auth.orgKey },
|
|
253
263
|
_optionalChain([init, 'optionalAccess', _28 => _28.signal])
|
|
254
264
|
);
|
|
255
265
|
},
|
|
256
266
|
rotateServerClientSecret(projectId, clientId, auth, init) {
|
|
257
267
|
return send(
|
|
258
268
|
"POST",
|
|
259
|
-
|
|
269
|
+
_chunkATPS4UV6cjs.CONTROL_API_PATHS.clientRotate(projectId, clientId),
|
|
260
270
|
{},
|
|
261
|
-
(value) =>
|
|
262
|
-
{ [
|
|
271
|
+
(value) => _chunkATPS4UV6cjs.zRotateClientSecretResponse.parse(value),
|
|
272
|
+
{ [_chunkATPS4UV6cjs.ORG_KEY_HEADER]: auth.orgKey },
|
|
263
273
|
_optionalChain([init, 'optionalAccess', _29 => _29.signal])
|
|
264
274
|
);
|
|
265
275
|
},
|
|
266
276
|
deleteProject(projectId, input, auth, init) {
|
|
267
277
|
return send(
|
|
268
278
|
"DELETE",
|
|
269
|
-
|
|
279
|
+
_chunkATPS4UV6cjs.CONTROL_API_PATHS.project(projectId),
|
|
270
280
|
input,
|
|
271
|
-
(value) =>
|
|
272
|
-
{ [
|
|
281
|
+
(value) => _chunkATPS4UV6cjs.zDeleteProjectResponse.parse(value),
|
|
282
|
+
{ [_chunkATPS4UV6cjs.ORG_KEY_HEADER]: auth.orgKey },
|
|
273
283
|
_optionalChain([init, 'optionalAccess', _30 => _30.signal])
|
|
274
284
|
);
|
|
275
285
|
}
|
package/dist/client.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/eric/reopt-ai/reopt-data/packages/data-contract/dist/client.cjs","../src/client.ts"],"names":[],"mappings":"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","file":"/Users/eric/reopt-ai/reopt-data/packages/data-contract/dist/client.cjs","sourcesContent":[null,"/**\n * `createDataClient` — typed fetch over the ingest and query planes.\n *\n * Deliberately stateless: no queue, no buffer, no background flush. Batch\n * assembly and cursor management belong to the caller (a forwarder already has\n * a cursor and byte-batching; duplicating that here would give it two).\n *\n * Every response is parsed with the contract schema, so a server that drifts\n * from the contract surfaces as `contract_mismatch` instead of quietly\n * returning something the caller then mis-reads.\n */\nimport {\n CLIENT_ID_HEADER,\n CLIENT_SECRET_HEADER,\n CONTRACT_VERSION,\n DataApiError,\n REQUEST_ID_HEADER,\n type ClientCredentials,\n} from \"./index.js\";\nimport { zIngestResponse, type IngestResponse, type ITrackHandlerPayload } from \"./ingest.js\";\nimport {\n CONTROL_API_PATHS,\n ORG_KEY_HEADER,\n PLATFORM_KEY_HEADER,\n zCreateOrganizationResponse,\n zCreateProjectResponse,\n zDeleteProjectResponse,\n zRotateClientSecretResponse,\n zRotateOrganizationKeyResponse,\n zUpdateOrganizationQuotaResponse,\n type CreateOrganizationInput,\n type CreateOrganizationResponse,\n type CreateProjectInput,\n type CreateProjectResponse,\n type DeleteProjectInput,\n type DeleteProjectResponse,\n type RotateClientSecretResponse,\n type RotateOrganizationKeyResponse,\n type UpdateOrganizationQuotaInput,\n type UpdateOrganizationQuotaResponse,\n} from \"./control.js\";\nimport {\n QUERY_API_PATHS,\n zEventsTimeseriesResponse,\n zFunnelResponse,\n zRetentionResponse,\n type EventsTimeseriesInput,\n type EventsTimeseriesResponse,\n type FunnelInput,\n type FunnelResponse,\n type RetentionInput,\n type RetentionResponse,\n} from \"./query.js\";\n\nconst TRACK_PATH = \"/api/track\";\n\nexport interface DataClientRetryOptions {\n /** Attempts after the first. Only 429 and 5xx are retried. Default 2. */\n maxRetries?: number;\n /** First backoff step; doubles each attempt, with jitter. Default 500ms. */\n baseDelayMs?: number;\n /** Cap on a single backoff step. Default 20s. */\n maxDelayMs?: number;\n /** Prefer the server's `Retry-After` over the computed backoff. Default true. */\n respectRetryAfter?: boolean;\n}\n\nexport interface DataClientOptions extends ClientCredentials {\n /** Origin of the reopt-data deployment, e.g. `https://data.reopt.app`. Trailing slash ignored. */\n baseUrl: string;\n /** Injected so callers can pass a framework-instrumented fetch. Defaults to `globalThis.fetch`. */\n fetch?: typeof globalThis.fetch;\n /** Per-attempt timeout. Default 10s. */\n timeoutMs?: number;\n retry?: DataClientRetryOptions;\n /** Appended to the default `reopt-data-contract/<version>`. */\n userAgent?: string;\n}\n\nexport interface DataRequestInit {\n signal?: AbortSignal;\n}\n\n/**\n * Provisioning credentials are passed per call rather than held on the client,\n * because they are a different authority from the client credential the rest of\n * the surface uses — and because a long-lived object holding the platform key\n * is a wider blast radius than a value the caller reads at the moment it needs\n * it.\n */\nexport interface PlatformAuth {\n platformKey: string;\n}\n\nexport interface OrganizationAuth {\n orgKey: string;\n}\n\nexport interface DataClient {\n ingest: {\n /**\n * `POST /api/track`. Send events as one batch; splitting to stay under\n * the 512KB body cap is the caller's job, since only the caller knows how\n * to resume a partially-sent range.\n */\n track(events: ITrackHandlerPayload[], init?: DataRequestInit): Promise<IngestResponse>;\n };\n query: {\n eventsTimeseries(input: EventsTimeseriesInput, init?: DataRequestInit): Promise<EventsTimeseriesResponse>;\n funnel(input: FunnelInput, init?: DataRequestInit): Promise<FunnelResponse>;\n retention(input: RetentionInput, init?: DataRequestInit): Promise<RetentionResponse>;\n };\n control: {\n /** Idempotent on `externalId`. `orgKey` comes back only on first creation. */\n createOrganization(\n input: CreateOrganizationInput,\n auth: PlatformAuth,\n init?: DataRequestInit\n ): Promise<CreateOrganizationResponse>;\n /** Issues a new key and revokes every previous one. The recovery path for a lost key. */\n rotateOrgKey(\n organizationId: string,\n auth: PlatformAuth,\n init?: DataRequestInit\n ): Promise<RotateOrganizationKeyResponse>;\n updateOrganizationQuota(\n organizationId: string,\n input: UpdateOrganizationQuotaInput,\n auth: PlatformAuth,\n init?: DataRequestInit\n ): Promise<UpdateOrganizationQuotaResponse>;\n /** Idempotent on `externalId`. `clientSecret` comes back only on first creation. */\n createProject(\n input: CreateProjectInput,\n auth: OrganizationAuth,\n init?: DataRequestInit\n ): Promise<CreateProjectResponse>;\n rotateServerClientSecret(\n projectId: string,\n clientId: string,\n auth: OrganizationAuth,\n init?: DataRequestInit\n ): Promise<RotateClientSecretResponse>;\n /** Irreversible. Idempotent: a project that is already gone still answers 202. */\n deleteProject(\n projectId: string,\n input: DeleteProjectInput,\n auth: OrganizationAuth,\n init?: DataRequestInit\n ): Promise<DeleteProjectResponse>;\n };\n}\n\nconst DEFAULTS = {\n timeoutMs: 10_000,\n maxRetries: 2,\n baseDelayMs: 500,\n maxDelayMs: 20_000,\n} as const;\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.replace(/\\/+$/, \"\");\n}\n\n/** `Retry-After` is either delta-seconds or an HTTP date; both are legal. */\nfunction parseRetryAfter(header: string | null): number | undefined {\n if (!header) return undefined;\n\n const seconds = Number(header);\n if (Number.isFinite(seconds) && seconds >= 0) return Math.round(seconds * 1000);\n\n const at = Date.parse(header);\n if (Number.isFinite(at)) return Math.max(0, at - Date.now());\n\n return undefined;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason ?? new Error(\"Aborted\"));\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal?.reason ?? new Error(\"Aborted\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction backoffDelay(attempt: number, retry: Required<DataClientRetryOptions>): number {\n const exponential = retry.baseDelayMs * 2 ** attempt;\n const capped = Math.min(exponential, retry.maxDelayMs);\n // Full jitter — a fleet of forwarders that all got 429 should not all come\n // back at the same instant.\n return Math.round(capped * (0.5 + Math.random() * 0.5));\n}\n\n/**\n * Body of a non-2xx response. Both planes share `{ status, code, error, ... }`,\n * so one reader covers them; anything else is reported as `internal_error`\n * with the raw text kept in `details`.\n */\nfunction toApiError(\n status: number,\n rawBody: string,\n retryAfterMs: number | undefined,\n requestId?: string\n): DataApiError {\n let parsed: unknown;\n try {\n parsed = JSON.parse(rawBody);\n } catch {\n return new DataApiError({\n message: `reopt-data responded ${status} with a non-JSON body`,\n status,\n code: status >= 500 ? \"internal_error\" : \"unknown_error\",\n requestId,\n retryAfterMs,\n details: rawBody.slice(0, 2000),\n });\n }\n\n const body = (parsed ?? {}) as Record<string, unknown>;\n const code = typeof body.code === \"string\" ? body.code : status >= 500 ? \"internal_error\" : \"unknown_error\";\n const message =\n (typeof body.message === \"string\" && body.message) ||\n (typeof body.error === \"string\" && body.error) ||\n `reopt-data responded ${status}`;\n\n return new DataApiError({\n message,\n status,\n code,\n requestId: (typeof body.requestId === \"string\" ? body.requestId : undefined) ?? requestId,\n retryAfterMs,\n details: body.errors ?? undefined,\n });\n}\n\nexport function createDataClient(options: DataClientOptions): DataClient {\n const baseUrl = normalizeBaseUrl(options.baseUrl);\n const doFetch = options.fetch ?? globalThis.fetch;\n if (typeof doFetch !== \"function\") {\n throw new TypeError(\"createDataClient: no fetch implementation available — pass options.fetch\");\n }\n\n const timeoutMs = options.timeoutMs ?? DEFAULTS.timeoutMs;\n const retry: Required<DataClientRetryOptions> = {\n maxRetries: options.retry?.maxRetries ?? DEFAULTS.maxRetries,\n baseDelayMs: options.retry?.baseDelayMs ?? DEFAULTS.baseDelayMs,\n maxDelayMs: options.retry?.maxDelayMs ?? DEFAULTS.maxDelayMs,\n respectRetryAfter: options.retry?.respectRetryAfter ?? true,\n };\n\n const userAgent = options.userAgent\n ? `reopt-data-contract/${CONTRACT_VERSION} ${options.userAgent}`\n : `reopt-data-contract/${CONTRACT_VERSION}`;\n\n async function requestOnce(\n method: \"POST\" | \"PATCH\" | \"DELETE\",\n path: string,\n body: unknown,\n extraHeaders: Record<string, string>,\n signal?: AbortSignal\n ): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(\n () => controller.abort(new Error(`reopt-data request timed out after ${timeoutMs}ms`)),\n timeoutMs\n );\n const onCallerAbort = () => controller.abort(signal?.reason ?? new Error(\"Aborted\"));\n signal?.addEventListener(\"abort\", onCallerAbort, { once: true });\n\n try {\n return await doFetch(`${baseUrl}${path}`, {\n method,\n headers: {\n \"content-type\": \"application/json\",\n \"user-agent\": userAgent,\n [CLIENT_ID_HEADER]: options.clientId,\n [CLIENT_SECRET_HEADER]: options.clientSecret,\n ...extraHeaders,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", onCallerAbort);\n }\n }\n\n async function send<T>(\n method: \"POST\" | \"PATCH\" | \"DELETE\",\n path: string,\n body: unknown,\n parse: (value: unknown) => T,\n extraHeaders: Record<string, string> = {},\n signal?: AbortSignal\n ): Promise<T> {\n let lastError: DataApiError | undefined;\n\n for (let attempt = 0; attempt <= retry.maxRetries; attempt++) {\n let response: Response;\n try {\n response = await requestOnce(method, path, body, extraHeaders, signal);\n } catch (cause) {\n // A caller-initiated abort is not a transport failure — propagate it.\n if (signal?.aborted) throw cause;\n lastError = new DataApiError({\n message: cause instanceof Error ? cause.message : String(cause),\n status: 0,\n code: \"network_error\",\n details: cause,\n });\n if (attempt < retry.maxRetries) {\n await sleep(backoffDelay(attempt, retry), signal);\n continue;\n }\n throw lastError;\n }\n\n const requestId = response.headers.get(REQUEST_ID_HEADER) ?? undefined;\n const rawBody = await response.text();\n\n if (response.ok) {\n let json: unknown;\n try {\n json = JSON.parse(rawBody);\n } catch (cause) {\n throw new DataApiError({\n message: \"reopt-data returned a 2xx with an unparseable body\",\n status: response.status,\n code: \"contract_mismatch\",\n requestId,\n details: cause,\n });\n }\n\n try {\n return parse(json);\n } catch (cause) {\n throw new DataApiError({\n message: \"reopt-data returned a 2xx that does not match the contract\",\n status: response.status,\n code: \"contract_mismatch\",\n requestId,\n details: cause,\n });\n }\n }\n\n const retryAfterMs = retry.respectRetryAfter ? parseRetryAfter(response.headers.get(\"retry-after\")) : undefined;\n lastError = toApiError(response.status, rawBody, retryAfterMs, requestId);\n\n if (!lastError.retryable || attempt === retry.maxRetries) throw lastError;\n await sleep(retryAfterMs ?? backoffDelay(attempt, retry), signal);\n }\n\n /* c8 ignore next -- the loop either returns or throws */\n throw lastError ?? new DataApiError({ message: \"reopt-data request failed\", status: 0, code: \"network_error\" });\n }\n\n function post<T>(path: string, body: unknown, parse: (value: unknown) => T, signal?: AbortSignal): Promise<T> {\n return send(\"POST\", path, body, parse, {}, signal);\n }\n\n return {\n ingest: {\n track(events, init) {\n return post(TRACK_PATH, events, (value) => zIngestResponse.parse(value), init?.signal);\n },\n },\n query: {\n eventsTimeseries(input, init) {\n return post(\n QUERY_API_PATHS.eventsTimeseries,\n input,\n (value) => zEventsTimeseriesResponse.parse(value),\n init?.signal\n );\n },\n funnel(input, init) {\n return post(QUERY_API_PATHS.funnel, input, (value) => zFunnelResponse.parse(value), init?.signal);\n },\n retention(input, init) {\n return post(QUERY_API_PATHS.retention, input, (value) => zRetentionResponse.parse(value), init?.signal);\n },\n },\n control: {\n createOrganization(input, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.organizations,\n input,\n (value) => zCreateOrganizationResponse.parse(value),\n { [PLATFORM_KEY_HEADER]: auth.platformKey },\n init?.signal\n );\n },\n rotateOrgKey(organizationId, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.organizationKeys(organizationId),\n {},\n (value) => zRotateOrganizationKeyResponse.parse(value),\n { [PLATFORM_KEY_HEADER]: auth.platformKey },\n init?.signal\n );\n },\n updateOrganizationQuota(organizationId, input, auth, init) {\n return send(\n \"PATCH\",\n CONTROL_API_PATHS.organization(organizationId),\n input,\n (value) => zUpdateOrganizationQuotaResponse.parse(value),\n { [PLATFORM_KEY_HEADER]: auth.platformKey },\n init?.signal\n );\n },\n createProject(input, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.projects,\n input,\n (value) => zCreateProjectResponse.parse(value),\n { [ORG_KEY_HEADER]: auth.orgKey },\n init?.signal\n );\n },\n rotateServerClientSecret(projectId, clientId, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.clientRotate(projectId, clientId),\n {},\n (value) => zRotateClientSecretResponse.parse(value),\n { [ORG_KEY_HEADER]: auth.orgKey },\n init?.signal\n );\n },\n deleteProject(projectId, input, auth, init) {\n return send(\n \"DELETE\",\n CONTROL_API_PATHS.project(projectId),\n input,\n (value) => zDeleteProjectResponse.parse(value),\n { [ORG_KEY_HEADER]: auth.orgKey },\n init?.signal\n );\n },\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/Users/eric/reopt-ai/reopt-data/packages/data-contract/dist/client.cjs","../src/client.ts"],"names":[],"mappings":"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","file":"/Users/eric/reopt-ai/reopt-data/packages/data-contract/dist/client.cjs","sourcesContent":[null,"/**\n * `createDataClient` — typed fetch over the ingest and query planes.\n *\n * Deliberately stateless: no queue, no buffer, no background flush. Batch\n * assembly and cursor management belong to the caller (a forwarder already has\n * a cursor and byte-batching; duplicating that here would give it two).\n *\n * Every response is parsed with the contract schema, so a server that drifts\n * from the contract surfaces as `contract_mismatch` instead of quietly\n * returning something the caller then mis-reads.\n */\nimport {\n CLIENT_ID_HEADER,\n CLIENT_SECRET_HEADER,\n CONTRACT_VERSION,\n DataApiError,\n REQUEST_ID_HEADER,\n type OptionalClientCredentials,\n} from \"./index.js\";\nimport { zIngestResponse, type IngestResponse, type ITrackHandlerPayload } from \"./ingest.js\";\nimport {\n CONTROL_API_PATHS,\n ORG_KEY_HEADER,\n PLATFORM_KEY_HEADER,\n zCreateOrganizationResponse,\n zCreateProjectResponse,\n zDeleteProjectResponse,\n zRotateClientSecretResponse,\n zRotateOrganizationKeyResponse,\n zUpdateOrganizationQuotaResponse,\n type CreateOrganizationInput,\n type CreateOrganizationResponse,\n type CreateProjectInput,\n type CreateProjectResponse,\n type DeleteProjectInput,\n type DeleteProjectResponse,\n type RotateClientSecretResponse,\n type RotateOrganizationKeyResponse,\n type UpdateOrganizationQuotaInput,\n type UpdateOrganizationQuotaResponse,\n} from \"./control.js\";\nimport {\n QUERY_API_PATHS,\n zEventsTimeseriesResponse,\n zFunnelResponse,\n zRetentionResponse,\n type EventsTimeseriesInput,\n type EventsTimeseriesResponse,\n type FunnelInput,\n type FunnelResponse,\n type RetentionInput,\n type RetentionResponse,\n} from \"./query.js\";\n\nconst TRACK_PATH = \"/api/track\";\n\nexport interface DataClientRetryOptions {\n /** Attempts after the first. Only 429 and 5xx are retried. Default 2. */\n maxRetries?: number;\n /** First backoff step; doubles each attempt, with jitter. Default 500ms. */\n baseDelayMs?: number;\n /** Cap on a single backoff step. Default 20s. */\n maxDelayMs?: number;\n /** Prefer the server's `Retry-After` over the computed backoff. Default true. */\n respectRetryAfter?: boolean;\n}\n\nexport interface DataClientOptions extends OptionalClientCredentials {\n /** Origin of the reopt-data deployment, e.g. `https://data.reopt.app`. Trailing slash ignored. */\n baseUrl: string;\n /** Injected so callers can pass a framework-instrumented fetch. Defaults to `globalThis.fetch`. */\n fetch?: typeof globalThis.fetch;\n /** Per-attempt timeout. Default 10s. */\n timeoutMs?: number;\n retry?: DataClientRetryOptions;\n /** Appended to the default `reopt-data-contract/<version>`. */\n userAgent?: string;\n}\n\nexport interface DataRequestInit {\n signal?: AbortSignal;\n}\n\n/**\n * Provisioning credentials are passed per call rather than held on the client,\n * because they are a different authority from the client credential the rest of\n * the surface uses — and because a long-lived object holding the platform key\n * is a wider blast radius than a value the caller reads at the moment it needs\n * it.\n */\nexport interface PlatformAuth {\n platformKey: string;\n}\n\nexport interface OrganizationAuth {\n orgKey: string;\n}\n\nexport interface DataClient {\n ingest: {\n /**\n * `POST /api/track`. Send events as one batch; splitting to stay under\n * the 512KB body cap is the caller's job, since only the caller knows how\n * to resume a partially-sent range.\n */\n track(events: ITrackHandlerPayload[], init?: DataRequestInit): Promise<IngestResponse>;\n };\n query: {\n eventsTimeseries(input: EventsTimeseriesInput, init?: DataRequestInit): Promise<EventsTimeseriesResponse>;\n funnel(input: FunnelInput, init?: DataRequestInit): Promise<FunnelResponse>;\n retention(input: RetentionInput, init?: DataRequestInit): Promise<RetentionResponse>;\n };\n control: {\n /** Idempotent on `externalId`. `orgKey` comes back only on first creation. */\n createOrganization(\n input: CreateOrganizationInput,\n auth: PlatformAuth,\n init?: DataRequestInit\n ): Promise<CreateOrganizationResponse>;\n /** Issues a new key and revokes every previous one. The recovery path for a lost key. */\n rotateOrgKey(\n organizationId: string,\n auth: PlatformAuth,\n init?: DataRequestInit\n ): Promise<RotateOrganizationKeyResponse>;\n updateOrganizationQuota(\n organizationId: string,\n input: UpdateOrganizationQuotaInput,\n auth: PlatformAuth,\n init?: DataRequestInit\n ): Promise<UpdateOrganizationQuotaResponse>;\n /** Idempotent on `externalId`. `clientSecret` comes back only on first creation. */\n createProject(\n input: CreateProjectInput,\n auth: OrganizationAuth,\n init?: DataRequestInit\n ): Promise<CreateProjectResponse>;\n rotateServerClientSecret(\n projectId: string,\n clientId: string,\n auth: OrganizationAuth,\n init?: DataRequestInit\n ): Promise<RotateClientSecretResponse>;\n /** Irreversible. Idempotent: a project that is already gone still answers 202. */\n deleteProject(\n projectId: string,\n input: DeleteProjectInput,\n auth: OrganizationAuth,\n init?: DataRequestInit\n ): Promise<DeleteProjectResponse>;\n };\n}\n\nconst DEFAULTS = {\n timeoutMs: 10_000,\n maxRetries: 2,\n baseDelayMs: 500,\n maxDelayMs: 20_000,\n} as const;\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.replace(/\\/+$/, \"\");\n}\n\n/** `Retry-After` is either delta-seconds or an HTTP date; both are legal. */\nfunction parseRetryAfter(header: string | null): number | undefined {\n if (!header) return undefined;\n\n const seconds = Number(header);\n if (Number.isFinite(seconds) && seconds >= 0) return Math.round(seconds * 1000);\n\n const at = Date.parse(header);\n if (Number.isFinite(at)) return Math.max(0, at - Date.now());\n\n return undefined;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason ?? new Error(\"Aborted\"));\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal?.reason ?? new Error(\"Aborted\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction backoffDelay(attempt: number, retry: Required<DataClientRetryOptions>): number {\n const exponential = retry.baseDelayMs * 2 ** attempt;\n const capped = Math.min(exponential, retry.maxDelayMs);\n // Full jitter — a fleet of forwarders that all got 429 should not all come\n // back at the same instant.\n return Math.round(capped * (0.5 + Math.random() * 0.5));\n}\n\n/**\n * Body of a non-2xx response. Both planes share `{ status, code, error, ... }`,\n * so one reader covers them; anything else is reported as `internal_error`\n * with the raw text kept in `details`.\n */\nfunction toApiError(\n status: number,\n rawBody: string,\n retryAfterMs: number | undefined,\n requestId?: string\n): DataApiError {\n let parsed: unknown;\n try {\n parsed = JSON.parse(rawBody);\n } catch {\n return new DataApiError({\n message: `reopt-data responded ${status} with a non-JSON body`,\n status,\n code: status >= 500 ? \"internal_error\" : \"unknown_error\",\n requestId,\n retryAfterMs,\n details: rawBody.slice(0, 2000),\n });\n }\n\n const body = (parsed ?? {}) as Record<string, unknown>;\n const code = typeof body.code === \"string\" ? body.code : status >= 500 ? \"internal_error\" : \"unknown_error\";\n const message =\n (typeof body.message === \"string\" && body.message) ||\n (typeof body.error === \"string\" && body.error) ||\n `reopt-data responded ${status}`;\n\n return new DataApiError({\n message,\n status,\n code,\n requestId: (typeof body.requestId === \"string\" ? body.requestId : undefined) ?? requestId,\n retryAfterMs,\n details: body.errors ?? undefined,\n });\n}\n\nexport function createDataClient(options: DataClientOptions): DataClient {\n const baseUrl = normalizeBaseUrl(options.baseUrl);\n const doFetch = options.fetch ?? globalThis.fetch;\n if (typeof doFetch !== \"function\") {\n throw new TypeError(\"createDataClient: no fetch implementation available — pass options.fetch\");\n }\n\n const timeoutMs = options.timeoutMs ?? DEFAULTS.timeoutMs;\n const retry: Required<DataClientRetryOptions> = {\n maxRetries: options.retry?.maxRetries ?? DEFAULTS.maxRetries,\n baseDelayMs: options.retry?.baseDelayMs ?? DEFAULTS.baseDelayMs,\n maxDelayMs: options.retry?.maxDelayMs ?? DEFAULTS.maxDelayMs,\n respectRetryAfter: options.retry?.respectRetryAfter ?? true,\n };\n\n const userAgent = options.userAgent\n ? `reopt-data-contract/${CONTRACT_VERSION} ${options.userAgent}`\n : `reopt-data-contract/${CONTRACT_VERSION}`;\n\n /**\n * Client credentials, or a clear failure. The ingest and query planes cannot\n * run without them; the provisioning plane never uses them.\n */\n function requireClientCredentials(): { clientId: string; clientSecret: string } {\n if (!options.clientId || !options.clientSecret) {\n throw new DataApiError({\n message:\n \"createDataClient was given no client credentials — pass clientId and clientSecret to use the ingest or query planes\",\n status: 0,\n code: \"credentials_missing\",\n });\n }\n return { clientId: options.clientId, clientSecret: options.clientSecret };\n }\n\n async function requestOnce(\n method: \"POST\" | \"PATCH\" | \"DELETE\",\n path: string,\n body: unknown,\n extraHeaders: Record<string, string>,\n signal?: AbortSignal\n ): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(\n () => controller.abort(new Error(`reopt-data request timed out after ${timeoutMs}ms`)),\n timeoutMs\n );\n const onCallerAbort = () => controller.abort(signal?.reason ?? new Error(\"Aborted\"));\n signal?.addEventListener(\"abort\", onCallerAbort, { once: true });\n\n try {\n return await doFetch(`${baseUrl}${path}`, {\n method,\n headers: {\n \"content-type\": \"application/json\",\n \"user-agent\": userAgent,\n ...(options.clientId && options.clientSecret\n ? { [CLIENT_ID_HEADER]: options.clientId, [CLIENT_SECRET_HEADER]: options.clientSecret }\n : {}),\n ...extraHeaders,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", onCallerAbort);\n }\n }\n\n async function send<T>(\n method: \"POST\" | \"PATCH\" | \"DELETE\",\n path: string,\n body: unknown,\n parse: (value: unknown) => T,\n extraHeaders: Record<string, string> = {},\n signal?: AbortSignal\n ): Promise<T> {\n let lastError: DataApiError | undefined;\n\n for (let attempt = 0; attempt <= retry.maxRetries; attempt++) {\n let response: Response;\n try {\n response = await requestOnce(method, path, body, extraHeaders, signal);\n } catch (cause) {\n // A caller-initiated abort is not a transport failure — propagate it.\n if (signal?.aborted) throw cause;\n lastError = new DataApiError({\n message: cause instanceof Error ? cause.message : String(cause),\n status: 0,\n code: \"network_error\",\n details: cause,\n });\n if (attempt < retry.maxRetries) {\n await sleep(backoffDelay(attempt, retry), signal);\n continue;\n }\n throw lastError;\n }\n\n const requestId = response.headers.get(REQUEST_ID_HEADER) ?? undefined;\n const rawBody = await response.text();\n\n if (response.ok) {\n let json: unknown;\n try {\n json = JSON.parse(rawBody);\n } catch (cause) {\n throw new DataApiError({\n message: \"reopt-data returned a 2xx with an unparseable body\",\n status: response.status,\n code: \"contract_mismatch\",\n requestId,\n details: cause,\n });\n }\n\n try {\n return parse(json);\n } catch (cause) {\n throw new DataApiError({\n message: \"reopt-data returned a 2xx that does not match the contract\",\n status: response.status,\n code: \"contract_mismatch\",\n requestId,\n details: cause,\n });\n }\n }\n\n const retryAfterMs = retry.respectRetryAfter ? parseRetryAfter(response.headers.get(\"retry-after\")) : undefined;\n lastError = toApiError(response.status, rawBody, retryAfterMs, requestId);\n\n if (!lastError.retryable || attempt === retry.maxRetries) throw lastError;\n await sleep(retryAfterMs ?? backoffDelay(attempt, retry), signal);\n }\n\n /* c8 ignore next -- the loop either returns or throws */\n throw lastError ?? new DataApiError({ message: \"reopt-data request failed\", status: 0, code: \"network_error\" });\n }\n\n /**\n * The ingest and query planes; both require client credentials.\n *\n * `async` so a missing credential rejects rather than throwing\n * synchronously — an async method that sometimes throws before returning a\n * promise slips past every `.catch()` a caller writes.\n */\n async function post<T>(path: string, body: unknown, parse: (value: unknown) => T, signal?: AbortSignal): Promise<T> {\n requireClientCredentials();\n return send(\"POST\", path, body, parse, {}, signal);\n }\n\n return {\n ingest: {\n track(events, init) {\n return post(TRACK_PATH, events, (value) => zIngestResponse.parse(value), init?.signal);\n },\n },\n query: {\n eventsTimeseries(input, init) {\n return post(\n QUERY_API_PATHS.eventsTimeseries,\n input,\n (value) => zEventsTimeseriesResponse.parse(value),\n init?.signal\n );\n },\n funnel(input, init) {\n return post(QUERY_API_PATHS.funnel, input, (value) => zFunnelResponse.parse(value), init?.signal);\n },\n retention(input, init) {\n return post(QUERY_API_PATHS.retention, input, (value) => zRetentionResponse.parse(value), init?.signal);\n },\n },\n control: {\n createOrganization(input, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.organizations,\n input,\n (value) => zCreateOrganizationResponse.parse(value),\n { [PLATFORM_KEY_HEADER]: auth.platformKey },\n init?.signal\n );\n },\n rotateOrgKey(organizationId, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.organizationKeys(organizationId),\n {},\n (value) => zRotateOrganizationKeyResponse.parse(value),\n { [PLATFORM_KEY_HEADER]: auth.platformKey },\n init?.signal\n );\n },\n updateOrganizationQuota(organizationId, input, auth, init) {\n return send(\n \"PATCH\",\n CONTROL_API_PATHS.organization(organizationId),\n input,\n (value) => zUpdateOrganizationQuotaResponse.parse(value),\n { [PLATFORM_KEY_HEADER]: auth.platformKey },\n init?.signal\n );\n },\n createProject(input, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.projects,\n input,\n (value) => zCreateProjectResponse.parse(value),\n { [ORG_KEY_HEADER]: auth.orgKey },\n init?.signal\n );\n },\n rotateServerClientSecret(projectId, clientId, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.clientRotate(projectId, clientId),\n {},\n (value) => zRotateClientSecretResponse.parse(value),\n { [ORG_KEY_HEADER]: auth.orgKey },\n init?.signal\n );\n },\n deleteProject(projectId, input, auth, init) {\n return send(\n \"DELETE\",\n CONTROL_API_PATHS.project(projectId),\n input,\n (value) => zDeleteProjectResponse.parse(value),\n { [ORG_KEY_HEADER]: auth.orgKey },\n init?.signal\n );\n },\n },\n };\n}\n"]}
|
package/dist/client.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OptionalClientCredentials } from './index.cjs';
|
|
2
2
|
import { ITrackHandlerPayload, IngestResponse } from './ingest.cjs';
|
|
3
3
|
import { CreateOrganizationInput, CreateOrganizationResponse, RotateOrganizationKeyResponse, UpdateOrganizationQuotaInput, UpdateOrganizationQuotaResponse, CreateProjectInput, CreateProjectResponse, RotateClientSecretResponse, DeleteProjectInput, DeleteProjectResponse } from './control.cjs';
|
|
4
4
|
import { EventsTimeseriesInput, EventsTimeseriesResponse, FunnelInput, FunnelResponse, RetentionInput, RetentionResponse } from './query.cjs';
|
|
@@ -26,7 +26,7 @@ interface DataClientRetryOptions {
|
|
|
26
26
|
/** Prefer the server's `Retry-After` over the computed backoff. Default true. */
|
|
27
27
|
respectRetryAfter?: boolean;
|
|
28
28
|
}
|
|
29
|
-
interface DataClientOptions extends
|
|
29
|
+
interface DataClientOptions extends OptionalClientCredentials {
|
|
30
30
|
/** Origin of the reopt-data deployment, e.g. `https://data.reopt.app`. Trailing slash ignored. */
|
|
31
31
|
baseUrl: string;
|
|
32
32
|
/** Injected so callers can pass a framework-instrumented fetch. Defaults to `globalThis.fetch`. */
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OptionalClientCredentials } from './index.js';
|
|
2
2
|
import { ITrackHandlerPayload, IngestResponse } from './ingest.js';
|
|
3
3
|
import { CreateOrganizationInput, CreateOrganizationResponse, RotateOrganizationKeyResponse, UpdateOrganizationQuotaInput, UpdateOrganizationQuotaResponse, CreateProjectInput, CreateProjectResponse, RotateClientSecretResponse, DeleteProjectInput, DeleteProjectResponse } from './control.js';
|
|
4
4
|
import { EventsTimeseriesInput, EventsTimeseriesResponse, FunnelInput, FunnelResponse, RetentionInput, RetentionResponse } from './query.js';
|
|
@@ -26,7 +26,7 @@ interface DataClientRetryOptions {
|
|
|
26
26
|
/** Prefer the server's `Retry-After` over the computed backoff. Default true. */
|
|
27
27
|
respectRetryAfter?: boolean;
|
|
28
28
|
}
|
|
29
|
-
interface DataClientOptions extends
|
|
29
|
+
interface DataClientOptions extends OptionalClientCredentials {
|
|
30
30
|
/** Origin of the reopt-data deployment, e.g. `https://data.reopt.app`. Trailing slash ignored. */
|
|
31
31
|
baseUrl: string;
|
|
32
32
|
/** Injected so callers can pass a framework-instrumented fetch. Defaults to `globalThis.fetch`. */
|
package/dist/client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
zIngestResponse
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3A7WZ7L6.js";
|
|
4
4
|
import {
|
|
5
5
|
CONTROL_API_PATHS,
|
|
6
6
|
ORG_KEY_HEADER,
|
|
@@ -11,20 +11,20 @@ import {
|
|
|
11
11
|
zRotateClientSecretResponse,
|
|
12
12
|
zRotateOrganizationKeyResponse,
|
|
13
13
|
zUpdateOrganizationQuotaResponse
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-J4VD3TLV.js";
|
|
15
15
|
import {
|
|
16
16
|
QUERY_API_PATHS,
|
|
17
17
|
zEventsTimeseriesResponse,
|
|
18
18
|
zFunnelResponse,
|
|
19
19
|
zRetentionResponse
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-55IWO4S3.js";
|
|
21
21
|
import {
|
|
22
22
|
CLIENT_ID_HEADER,
|
|
23
23
|
CLIENT_SECRET_HEADER,
|
|
24
24
|
CONTRACT_VERSION,
|
|
25
25
|
DataApiError,
|
|
26
26
|
REQUEST_ID_HEADER
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-2LJ7JLDX.js";
|
|
28
28
|
|
|
29
29
|
// src/client.ts
|
|
30
30
|
var TRACK_PATH = "/api/track";
|
|
@@ -107,6 +107,16 @@ function createDataClient(options) {
|
|
|
107
107
|
respectRetryAfter: options.retry?.respectRetryAfter ?? true
|
|
108
108
|
};
|
|
109
109
|
const userAgent = options.userAgent ? `reopt-data-contract/${CONTRACT_VERSION} ${options.userAgent}` : `reopt-data-contract/${CONTRACT_VERSION}`;
|
|
110
|
+
function requireClientCredentials() {
|
|
111
|
+
if (!options.clientId || !options.clientSecret) {
|
|
112
|
+
throw new DataApiError({
|
|
113
|
+
message: "createDataClient was given no client credentials \u2014 pass clientId and clientSecret to use the ingest or query planes",
|
|
114
|
+
status: 0,
|
|
115
|
+
code: "credentials_missing"
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return { clientId: options.clientId, clientSecret: options.clientSecret };
|
|
119
|
+
}
|
|
110
120
|
async function requestOnce(method, path, body, extraHeaders, signal) {
|
|
111
121
|
const controller = new AbortController();
|
|
112
122
|
const timer = setTimeout(
|
|
@@ -121,8 +131,7 @@ function createDataClient(options) {
|
|
|
121
131
|
headers: {
|
|
122
132
|
"content-type": "application/json",
|
|
123
133
|
"user-agent": userAgent,
|
|
124
|
-
[CLIENT_ID_HEADER]: options.clientId,
|
|
125
|
-
[CLIENT_SECRET_HEADER]: options.clientSecret,
|
|
134
|
+
...options.clientId && options.clientSecret ? { [CLIENT_ID_HEADER]: options.clientId, [CLIENT_SECRET_HEADER]: options.clientSecret } : {},
|
|
126
135
|
...extraHeaders
|
|
127
136
|
},
|
|
128
137
|
body: JSON.stringify(body),
|
|
@@ -187,7 +196,8 @@ function createDataClient(options) {
|
|
|
187
196
|
}
|
|
188
197
|
throw lastError ?? new DataApiError({ message: "reopt-data request failed", status: 0, code: "network_error" });
|
|
189
198
|
}
|
|
190
|
-
function post(path, body, parse, signal) {
|
|
199
|
+
async function post(path, body, parse, signal) {
|
|
200
|
+
requireClientCredentials();
|
|
191
201
|
return send("POST", path, body, parse, {}, signal);
|
|
192
202
|
}
|
|
193
203
|
return {
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts"],"sourcesContent":["/**\n * `createDataClient` — typed fetch over the ingest and query planes.\n *\n * Deliberately stateless: no queue, no buffer, no background flush. Batch\n * assembly and cursor management belong to the caller (a forwarder already has\n * a cursor and byte-batching; duplicating that here would give it two).\n *\n * Every response is parsed with the contract schema, so a server that drifts\n * from the contract surfaces as `contract_mismatch` instead of quietly\n * returning something the caller then mis-reads.\n */\nimport {\n CLIENT_ID_HEADER,\n CLIENT_SECRET_HEADER,\n CONTRACT_VERSION,\n DataApiError,\n REQUEST_ID_HEADER,\n type ClientCredentials,\n} from \"./index.js\";\nimport { zIngestResponse, type IngestResponse, type ITrackHandlerPayload } from \"./ingest.js\";\nimport {\n CONTROL_API_PATHS,\n ORG_KEY_HEADER,\n PLATFORM_KEY_HEADER,\n zCreateOrganizationResponse,\n zCreateProjectResponse,\n zDeleteProjectResponse,\n zRotateClientSecretResponse,\n zRotateOrganizationKeyResponse,\n zUpdateOrganizationQuotaResponse,\n type CreateOrganizationInput,\n type CreateOrganizationResponse,\n type CreateProjectInput,\n type CreateProjectResponse,\n type DeleteProjectInput,\n type DeleteProjectResponse,\n type RotateClientSecretResponse,\n type RotateOrganizationKeyResponse,\n type UpdateOrganizationQuotaInput,\n type UpdateOrganizationQuotaResponse,\n} from \"./control.js\";\nimport {\n QUERY_API_PATHS,\n zEventsTimeseriesResponse,\n zFunnelResponse,\n zRetentionResponse,\n type EventsTimeseriesInput,\n type EventsTimeseriesResponse,\n type FunnelInput,\n type FunnelResponse,\n type RetentionInput,\n type RetentionResponse,\n} from \"./query.js\";\n\nconst TRACK_PATH = \"/api/track\";\n\nexport interface DataClientRetryOptions {\n /** Attempts after the first. Only 429 and 5xx are retried. Default 2. */\n maxRetries?: number;\n /** First backoff step; doubles each attempt, with jitter. Default 500ms. */\n baseDelayMs?: number;\n /** Cap on a single backoff step. Default 20s. */\n maxDelayMs?: number;\n /** Prefer the server's `Retry-After` over the computed backoff. Default true. */\n respectRetryAfter?: boolean;\n}\n\nexport interface DataClientOptions extends ClientCredentials {\n /** Origin of the reopt-data deployment, e.g. `https://data.reopt.app`. Trailing slash ignored. */\n baseUrl: string;\n /** Injected so callers can pass a framework-instrumented fetch. Defaults to `globalThis.fetch`. */\n fetch?: typeof globalThis.fetch;\n /** Per-attempt timeout. Default 10s. */\n timeoutMs?: number;\n retry?: DataClientRetryOptions;\n /** Appended to the default `reopt-data-contract/<version>`. */\n userAgent?: string;\n}\n\nexport interface DataRequestInit {\n signal?: AbortSignal;\n}\n\n/**\n * Provisioning credentials are passed per call rather than held on the client,\n * because they are a different authority from the client credential the rest of\n * the surface uses — and because a long-lived object holding the platform key\n * is a wider blast radius than a value the caller reads at the moment it needs\n * it.\n */\nexport interface PlatformAuth {\n platformKey: string;\n}\n\nexport interface OrganizationAuth {\n orgKey: string;\n}\n\nexport interface DataClient {\n ingest: {\n /**\n * `POST /api/track`. Send events as one batch; splitting to stay under\n * the 512KB body cap is the caller's job, since only the caller knows how\n * to resume a partially-sent range.\n */\n track(events: ITrackHandlerPayload[], init?: DataRequestInit): Promise<IngestResponse>;\n };\n query: {\n eventsTimeseries(input: EventsTimeseriesInput, init?: DataRequestInit): Promise<EventsTimeseriesResponse>;\n funnel(input: FunnelInput, init?: DataRequestInit): Promise<FunnelResponse>;\n retention(input: RetentionInput, init?: DataRequestInit): Promise<RetentionResponse>;\n };\n control: {\n /** Idempotent on `externalId`. `orgKey` comes back only on first creation. */\n createOrganization(\n input: CreateOrganizationInput,\n auth: PlatformAuth,\n init?: DataRequestInit\n ): Promise<CreateOrganizationResponse>;\n /** Issues a new key and revokes every previous one. The recovery path for a lost key. */\n rotateOrgKey(\n organizationId: string,\n auth: PlatformAuth,\n init?: DataRequestInit\n ): Promise<RotateOrganizationKeyResponse>;\n updateOrganizationQuota(\n organizationId: string,\n input: UpdateOrganizationQuotaInput,\n auth: PlatformAuth,\n init?: DataRequestInit\n ): Promise<UpdateOrganizationQuotaResponse>;\n /** Idempotent on `externalId`. `clientSecret` comes back only on first creation. */\n createProject(\n input: CreateProjectInput,\n auth: OrganizationAuth,\n init?: DataRequestInit\n ): Promise<CreateProjectResponse>;\n rotateServerClientSecret(\n projectId: string,\n clientId: string,\n auth: OrganizationAuth,\n init?: DataRequestInit\n ): Promise<RotateClientSecretResponse>;\n /** Irreversible. Idempotent: a project that is already gone still answers 202. */\n deleteProject(\n projectId: string,\n input: DeleteProjectInput,\n auth: OrganizationAuth,\n init?: DataRequestInit\n ): Promise<DeleteProjectResponse>;\n };\n}\n\nconst DEFAULTS = {\n timeoutMs: 10_000,\n maxRetries: 2,\n baseDelayMs: 500,\n maxDelayMs: 20_000,\n} as const;\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.replace(/\\/+$/, \"\");\n}\n\n/** `Retry-After` is either delta-seconds or an HTTP date; both are legal. */\nfunction parseRetryAfter(header: string | null): number | undefined {\n if (!header) return undefined;\n\n const seconds = Number(header);\n if (Number.isFinite(seconds) && seconds >= 0) return Math.round(seconds * 1000);\n\n const at = Date.parse(header);\n if (Number.isFinite(at)) return Math.max(0, at - Date.now());\n\n return undefined;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason ?? new Error(\"Aborted\"));\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal?.reason ?? new Error(\"Aborted\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction backoffDelay(attempt: number, retry: Required<DataClientRetryOptions>): number {\n const exponential = retry.baseDelayMs * 2 ** attempt;\n const capped = Math.min(exponential, retry.maxDelayMs);\n // Full jitter — a fleet of forwarders that all got 429 should not all come\n // back at the same instant.\n return Math.round(capped * (0.5 + Math.random() * 0.5));\n}\n\n/**\n * Body of a non-2xx response. Both planes share `{ status, code, error, ... }`,\n * so one reader covers them; anything else is reported as `internal_error`\n * with the raw text kept in `details`.\n */\nfunction toApiError(\n status: number,\n rawBody: string,\n retryAfterMs: number | undefined,\n requestId?: string\n): DataApiError {\n let parsed: unknown;\n try {\n parsed = JSON.parse(rawBody);\n } catch {\n return new DataApiError({\n message: `reopt-data responded ${status} with a non-JSON body`,\n status,\n code: status >= 500 ? \"internal_error\" : \"unknown_error\",\n requestId,\n retryAfterMs,\n details: rawBody.slice(0, 2000),\n });\n }\n\n const body = (parsed ?? {}) as Record<string, unknown>;\n const code = typeof body.code === \"string\" ? body.code : status >= 500 ? \"internal_error\" : \"unknown_error\";\n const message =\n (typeof body.message === \"string\" && body.message) ||\n (typeof body.error === \"string\" && body.error) ||\n `reopt-data responded ${status}`;\n\n return new DataApiError({\n message,\n status,\n code,\n requestId: (typeof body.requestId === \"string\" ? body.requestId : undefined) ?? requestId,\n retryAfterMs,\n details: body.errors ?? undefined,\n });\n}\n\nexport function createDataClient(options: DataClientOptions): DataClient {\n const baseUrl = normalizeBaseUrl(options.baseUrl);\n const doFetch = options.fetch ?? globalThis.fetch;\n if (typeof doFetch !== \"function\") {\n throw new TypeError(\"createDataClient: no fetch implementation available — pass options.fetch\");\n }\n\n const timeoutMs = options.timeoutMs ?? DEFAULTS.timeoutMs;\n const retry: Required<DataClientRetryOptions> = {\n maxRetries: options.retry?.maxRetries ?? DEFAULTS.maxRetries,\n baseDelayMs: options.retry?.baseDelayMs ?? DEFAULTS.baseDelayMs,\n maxDelayMs: options.retry?.maxDelayMs ?? DEFAULTS.maxDelayMs,\n respectRetryAfter: options.retry?.respectRetryAfter ?? true,\n };\n\n const userAgent = options.userAgent\n ? `reopt-data-contract/${CONTRACT_VERSION} ${options.userAgent}`\n : `reopt-data-contract/${CONTRACT_VERSION}`;\n\n async function requestOnce(\n method: \"POST\" | \"PATCH\" | \"DELETE\",\n path: string,\n body: unknown,\n extraHeaders: Record<string, string>,\n signal?: AbortSignal\n ): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(\n () => controller.abort(new Error(`reopt-data request timed out after ${timeoutMs}ms`)),\n timeoutMs\n );\n const onCallerAbort = () => controller.abort(signal?.reason ?? new Error(\"Aborted\"));\n signal?.addEventListener(\"abort\", onCallerAbort, { once: true });\n\n try {\n return await doFetch(`${baseUrl}${path}`, {\n method,\n headers: {\n \"content-type\": \"application/json\",\n \"user-agent\": userAgent,\n [CLIENT_ID_HEADER]: options.clientId,\n [CLIENT_SECRET_HEADER]: options.clientSecret,\n ...extraHeaders,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", onCallerAbort);\n }\n }\n\n async function send<T>(\n method: \"POST\" | \"PATCH\" | \"DELETE\",\n path: string,\n body: unknown,\n parse: (value: unknown) => T,\n extraHeaders: Record<string, string> = {},\n signal?: AbortSignal\n ): Promise<T> {\n let lastError: DataApiError | undefined;\n\n for (let attempt = 0; attempt <= retry.maxRetries; attempt++) {\n let response: Response;\n try {\n response = await requestOnce(method, path, body, extraHeaders, signal);\n } catch (cause) {\n // A caller-initiated abort is not a transport failure — propagate it.\n if (signal?.aborted) throw cause;\n lastError = new DataApiError({\n message: cause instanceof Error ? cause.message : String(cause),\n status: 0,\n code: \"network_error\",\n details: cause,\n });\n if (attempt < retry.maxRetries) {\n await sleep(backoffDelay(attempt, retry), signal);\n continue;\n }\n throw lastError;\n }\n\n const requestId = response.headers.get(REQUEST_ID_HEADER) ?? undefined;\n const rawBody = await response.text();\n\n if (response.ok) {\n let json: unknown;\n try {\n json = JSON.parse(rawBody);\n } catch (cause) {\n throw new DataApiError({\n message: \"reopt-data returned a 2xx with an unparseable body\",\n status: response.status,\n code: \"contract_mismatch\",\n requestId,\n details: cause,\n });\n }\n\n try {\n return parse(json);\n } catch (cause) {\n throw new DataApiError({\n message: \"reopt-data returned a 2xx that does not match the contract\",\n status: response.status,\n code: \"contract_mismatch\",\n requestId,\n details: cause,\n });\n }\n }\n\n const retryAfterMs = retry.respectRetryAfter ? parseRetryAfter(response.headers.get(\"retry-after\")) : undefined;\n lastError = toApiError(response.status, rawBody, retryAfterMs, requestId);\n\n if (!lastError.retryable || attempt === retry.maxRetries) throw lastError;\n await sleep(retryAfterMs ?? backoffDelay(attempt, retry), signal);\n }\n\n /* c8 ignore next -- the loop either returns or throws */\n throw lastError ?? new DataApiError({ message: \"reopt-data request failed\", status: 0, code: \"network_error\" });\n }\n\n function post<T>(path: string, body: unknown, parse: (value: unknown) => T, signal?: AbortSignal): Promise<T> {\n return send(\"POST\", path, body, parse, {}, signal);\n }\n\n return {\n ingest: {\n track(events, init) {\n return post(TRACK_PATH, events, (value) => zIngestResponse.parse(value), init?.signal);\n },\n },\n query: {\n eventsTimeseries(input, init) {\n return post(\n QUERY_API_PATHS.eventsTimeseries,\n input,\n (value) => zEventsTimeseriesResponse.parse(value),\n init?.signal\n );\n },\n funnel(input, init) {\n return post(QUERY_API_PATHS.funnel, input, (value) => zFunnelResponse.parse(value), init?.signal);\n },\n retention(input, init) {\n return post(QUERY_API_PATHS.retention, input, (value) => zRetentionResponse.parse(value), init?.signal);\n },\n },\n control: {\n createOrganization(input, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.organizations,\n input,\n (value) => zCreateOrganizationResponse.parse(value),\n { [PLATFORM_KEY_HEADER]: auth.platformKey },\n init?.signal\n );\n },\n rotateOrgKey(organizationId, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.organizationKeys(organizationId),\n {},\n (value) => zRotateOrganizationKeyResponse.parse(value),\n { [PLATFORM_KEY_HEADER]: auth.platformKey },\n init?.signal\n );\n },\n updateOrganizationQuota(organizationId, input, auth, init) {\n return send(\n \"PATCH\",\n CONTROL_API_PATHS.organization(organizationId),\n input,\n (value) => zUpdateOrganizationQuotaResponse.parse(value),\n { [PLATFORM_KEY_HEADER]: auth.platformKey },\n init?.signal\n );\n },\n createProject(input, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.projects,\n input,\n (value) => zCreateProjectResponse.parse(value),\n { [ORG_KEY_HEADER]: auth.orgKey },\n init?.signal\n );\n },\n rotateServerClientSecret(projectId, clientId, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.clientRotate(projectId, clientId),\n {},\n (value) => zRotateClientSecretResponse.parse(value),\n { [ORG_KEY_HEADER]: auth.orgKey },\n init?.signal\n );\n },\n deleteProject(projectId, input, auth, init) {\n return send(\n \"DELETE\",\n CONTROL_API_PATHS.project(projectId),\n input,\n (value) => zDeleteProjectResponse.parse(value),\n { [ORG_KEY_HEADER]: auth.orgKey },\n init?.signal\n );\n },\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/client.ts"],"sourcesContent":["/**\n * `createDataClient` — typed fetch over the ingest and query planes.\n *\n * Deliberately stateless: no queue, no buffer, no background flush. Batch\n * assembly and cursor management belong to the caller (a forwarder already has\n * a cursor and byte-batching; duplicating that here would give it two).\n *\n * Every response is parsed with the contract schema, so a server that drifts\n * from the contract surfaces as `contract_mismatch` instead of quietly\n * returning something the caller then mis-reads.\n */\nimport {\n CLIENT_ID_HEADER,\n CLIENT_SECRET_HEADER,\n CONTRACT_VERSION,\n DataApiError,\n REQUEST_ID_HEADER,\n type OptionalClientCredentials,\n} from \"./index.js\";\nimport { zIngestResponse, type IngestResponse, type ITrackHandlerPayload } from \"./ingest.js\";\nimport {\n CONTROL_API_PATHS,\n ORG_KEY_HEADER,\n PLATFORM_KEY_HEADER,\n zCreateOrganizationResponse,\n zCreateProjectResponse,\n zDeleteProjectResponse,\n zRotateClientSecretResponse,\n zRotateOrganizationKeyResponse,\n zUpdateOrganizationQuotaResponse,\n type CreateOrganizationInput,\n type CreateOrganizationResponse,\n type CreateProjectInput,\n type CreateProjectResponse,\n type DeleteProjectInput,\n type DeleteProjectResponse,\n type RotateClientSecretResponse,\n type RotateOrganizationKeyResponse,\n type UpdateOrganizationQuotaInput,\n type UpdateOrganizationQuotaResponse,\n} from \"./control.js\";\nimport {\n QUERY_API_PATHS,\n zEventsTimeseriesResponse,\n zFunnelResponse,\n zRetentionResponse,\n type EventsTimeseriesInput,\n type EventsTimeseriesResponse,\n type FunnelInput,\n type FunnelResponse,\n type RetentionInput,\n type RetentionResponse,\n} from \"./query.js\";\n\nconst TRACK_PATH = \"/api/track\";\n\nexport interface DataClientRetryOptions {\n /** Attempts after the first. Only 429 and 5xx are retried. Default 2. */\n maxRetries?: number;\n /** First backoff step; doubles each attempt, with jitter. Default 500ms. */\n baseDelayMs?: number;\n /** Cap on a single backoff step. Default 20s. */\n maxDelayMs?: number;\n /** Prefer the server's `Retry-After` over the computed backoff. Default true. */\n respectRetryAfter?: boolean;\n}\n\nexport interface DataClientOptions extends OptionalClientCredentials {\n /** Origin of the reopt-data deployment, e.g. `https://data.reopt.app`. Trailing slash ignored. */\n baseUrl: string;\n /** Injected so callers can pass a framework-instrumented fetch. Defaults to `globalThis.fetch`. */\n fetch?: typeof globalThis.fetch;\n /** Per-attempt timeout. Default 10s. */\n timeoutMs?: number;\n retry?: DataClientRetryOptions;\n /** Appended to the default `reopt-data-contract/<version>`. */\n userAgent?: string;\n}\n\nexport interface DataRequestInit {\n signal?: AbortSignal;\n}\n\n/**\n * Provisioning credentials are passed per call rather than held on the client,\n * because they are a different authority from the client credential the rest of\n * the surface uses — and because a long-lived object holding the platform key\n * is a wider blast radius than a value the caller reads at the moment it needs\n * it.\n */\nexport interface PlatformAuth {\n platformKey: string;\n}\n\nexport interface OrganizationAuth {\n orgKey: string;\n}\n\nexport interface DataClient {\n ingest: {\n /**\n * `POST /api/track`. Send events as one batch; splitting to stay under\n * the 512KB body cap is the caller's job, since only the caller knows how\n * to resume a partially-sent range.\n */\n track(events: ITrackHandlerPayload[], init?: DataRequestInit): Promise<IngestResponse>;\n };\n query: {\n eventsTimeseries(input: EventsTimeseriesInput, init?: DataRequestInit): Promise<EventsTimeseriesResponse>;\n funnel(input: FunnelInput, init?: DataRequestInit): Promise<FunnelResponse>;\n retention(input: RetentionInput, init?: DataRequestInit): Promise<RetentionResponse>;\n };\n control: {\n /** Idempotent on `externalId`. `orgKey` comes back only on first creation. */\n createOrganization(\n input: CreateOrganizationInput,\n auth: PlatformAuth,\n init?: DataRequestInit\n ): Promise<CreateOrganizationResponse>;\n /** Issues a new key and revokes every previous one. The recovery path for a lost key. */\n rotateOrgKey(\n organizationId: string,\n auth: PlatformAuth,\n init?: DataRequestInit\n ): Promise<RotateOrganizationKeyResponse>;\n updateOrganizationQuota(\n organizationId: string,\n input: UpdateOrganizationQuotaInput,\n auth: PlatformAuth,\n init?: DataRequestInit\n ): Promise<UpdateOrganizationQuotaResponse>;\n /** Idempotent on `externalId`. `clientSecret` comes back only on first creation. */\n createProject(\n input: CreateProjectInput,\n auth: OrganizationAuth,\n init?: DataRequestInit\n ): Promise<CreateProjectResponse>;\n rotateServerClientSecret(\n projectId: string,\n clientId: string,\n auth: OrganizationAuth,\n init?: DataRequestInit\n ): Promise<RotateClientSecretResponse>;\n /** Irreversible. Idempotent: a project that is already gone still answers 202. */\n deleteProject(\n projectId: string,\n input: DeleteProjectInput,\n auth: OrganizationAuth,\n init?: DataRequestInit\n ): Promise<DeleteProjectResponse>;\n };\n}\n\nconst DEFAULTS = {\n timeoutMs: 10_000,\n maxRetries: 2,\n baseDelayMs: 500,\n maxDelayMs: 20_000,\n} as const;\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.replace(/\\/+$/, \"\");\n}\n\n/** `Retry-After` is either delta-seconds or an HTTP date; both are legal. */\nfunction parseRetryAfter(header: string | null): number | undefined {\n if (!header) return undefined;\n\n const seconds = Number(header);\n if (Number.isFinite(seconds) && seconds >= 0) return Math.round(seconds * 1000);\n\n const at = Date.parse(header);\n if (Number.isFinite(at)) return Math.max(0, at - Date.now());\n\n return undefined;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason ?? new Error(\"Aborted\"));\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal?.reason ?? new Error(\"Aborted\"));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction backoffDelay(attempt: number, retry: Required<DataClientRetryOptions>): number {\n const exponential = retry.baseDelayMs * 2 ** attempt;\n const capped = Math.min(exponential, retry.maxDelayMs);\n // Full jitter — a fleet of forwarders that all got 429 should not all come\n // back at the same instant.\n return Math.round(capped * (0.5 + Math.random() * 0.5));\n}\n\n/**\n * Body of a non-2xx response. Both planes share `{ status, code, error, ... }`,\n * so one reader covers them; anything else is reported as `internal_error`\n * with the raw text kept in `details`.\n */\nfunction toApiError(\n status: number,\n rawBody: string,\n retryAfterMs: number | undefined,\n requestId?: string\n): DataApiError {\n let parsed: unknown;\n try {\n parsed = JSON.parse(rawBody);\n } catch {\n return new DataApiError({\n message: `reopt-data responded ${status} with a non-JSON body`,\n status,\n code: status >= 500 ? \"internal_error\" : \"unknown_error\",\n requestId,\n retryAfterMs,\n details: rawBody.slice(0, 2000),\n });\n }\n\n const body = (parsed ?? {}) as Record<string, unknown>;\n const code = typeof body.code === \"string\" ? body.code : status >= 500 ? \"internal_error\" : \"unknown_error\";\n const message =\n (typeof body.message === \"string\" && body.message) ||\n (typeof body.error === \"string\" && body.error) ||\n `reopt-data responded ${status}`;\n\n return new DataApiError({\n message,\n status,\n code,\n requestId: (typeof body.requestId === \"string\" ? body.requestId : undefined) ?? requestId,\n retryAfterMs,\n details: body.errors ?? undefined,\n });\n}\n\nexport function createDataClient(options: DataClientOptions): DataClient {\n const baseUrl = normalizeBaseUrl(options.baseUrl);\n const doFetch = options.fetch ?? globalThis.fetch;\n if (typeof doFetch !== \"function\") {\n throw new TypeError(\"createDataClient: no fetch implementation available — pass options.fetch\");\n }\n\n const timeoutMs = options.timeoutMs ?? DEFAULTS.timeoutMs;\n const retry: Required<DataClientRetryOptions> = {\n maxRetries: options.retry?.maxRetries ?? DEFAULTS.maxRetries,\n baseDelayMs: options.retry?.baseDelayMs ?? DEFAULTS.baseDelayMs,\n maxDelayMs: options.retry?.maxDelayMs ?? DEFAULTS.maxDelayMs,\n respectRetryAfter: options.retry?.respectRetryAfter ?? true,\n };\n\n const userAgent = options.userAgent\n ? `reopt-data-contract/${CONTRACT_VERSION} ${options.userAgent}`\n : `reopt-data-contract/${CONTRACT_VERSION}`;\n\n /**\n * Client credentials, or a clear failure. The ingest and query planes cannot\n * run without them; the provisioning plane never uses them.\n */\n function requireClientCredentials(): { clientId: string; clientSecret: string } {\n if (!options.clientId || !options.clientSecret) {\n throw new DataApiError({\n message:\n \"createDataClient was given no client credentials — pass clientId and clientSecret to use the ingest or query planes\",\n status: 0,\n code: \"credentials_missing\",\n });\n }\n return { clientId: options.clientId, clientSecret: options.clientSecret };\n }\n\n async function requestOnce(\n method: \"POST\" | \"PATCH\" | \"DELETE\",\n path: string,\n body: unknown,\n extraHeaders: Record<string, string>,\n signal?: AbortSignal\n ): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(\n () => controller.abort(new Error(`reopt-data request timed out after ${timeoutMs}ms`)),\n timeoutMs\n );\n const onCallerAbort = () => controller.abort(signal?.reason ?? new Error(\"Aborted\"));\n signal?.addEventListener(\"abort\", onCallerAbort, { once: true });\n\n try {\n return await doFetch(`${baseUrl}${path}`, {\n method,\n headers: {\n \"content-type\": \"application/json\",\n \"user-agent\": userAgent,\n ...(options.clientId && options.clientSecret\n ? { [CLIENT_ID_HEADER]: options.clientId, [CLIENT_SECRET_HEADER]: options.clientSecret }\n : {}),\n ...extraHeaders,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", onCallerAbort);\n }\n }\n\n async function send<T>(\n method: \"POST\" | \"PATCH\" | \"DELETE\",\n path: string,\n body: unknown,\n parse: (value: unknown) => T,\n extraHeaders: Record<string, string> = {},\n signal?: AbortSignal\n ): Promise<T> {\n let lastError: DataApiError | undefined;\n\n for (let attempt = 0; attempt <= retry.maxRetries; attempt++) {\n let response: Response;\n try {\n response = await requestOnce(method, path, body, extraHeaders, signal);\n } catch (cause) {\n // A caller-initiated abort is not a transport failure — propagate it.\n if (signal?.aborted) throw cause;\n lastError = new DataApiError({\n message: cause instanceof Error ? cause.message : String(cause),\n status: 0,\n code: \"network_error\",\n details: cause,\n });\n if (attempt < retry.maxRetries) {\n await sleep(backoffDelay(attempt, retry), signal);\n continue;\n }\n throw lastError;\n }\n\n const requestId = response.headers.get(REQUEST_ID_HEADER) ?? undefined;\n const rawBody = await response.text();\n\n if (response.ok) {\n let json: unknown;\n try {\n json = JSON.parse(rawBody);\n } catch (cause) {\n throw new DataApiError({\n message: \"reopt-data returned a 2xx with an unparseable body\",\n status: response.status,\n code: \"contract_mismatch\",\n requestId,\n details: cause,\n });\n }\n\n try {\n return parse(json);\n } catch (cause) {\n throw new DataApiError({\n message: \"reopt-data returned a 2xx that does not match the contract\",\n status: response.status,\n code: \"contract_mismatch\",\n requestId,\n details: cause,\n });\n }\n }\n\n const retryAfterMs = retry.respectRetryAfter ? parseRetryAfter(response.headers.get(\"retry-after\")) : undefined;\n lastError = toApiError(response.status, rawBody, retryAfterMs, requestId);\n\n if (!lastError.retryable || attempt === retry.maxRetries) throw lastError;\n await sleep(retryAfterMs ?? backoffDelay(attempt, retry), signal);\n }\n\n /* c8 ignore next -- the loop either returns or throws */\n throw lastError ?? new DataApiError({ message: \"reopt-data request failed\", status: 0, code: \"network_error\" });\n }\n\n /**\n * The ingest and query planes; both require client credentials.\n *\n * `async` so a missing credential rejects rather than throwing\n * synchronously — an async method that sometimes throws before returning a\n * promise slips past every `.catch()` a caller writes.\n */\n async function post<T>(path: string, body: unknown, parse: (value: unknown) => T, signal?: AbortSignal): Promise<T> {\n requireClientCredentials();\n return send(\"POST\", path, body, parse, {}, signal);\n }\n\n return {\n ingest: {\n track(events, init) {\n return post(TRACK_PATH, events, (value) => zIngestResponse.parse(value), init?.signal);\n },\n },\n query: {\n eventsTimeseries(input, init) {\n return post(\n QUERY_API_PATHS.eventsTimeseries,\n input,\n (value) => zEventsTimeseriesResponse.parse(value),\n init?.signal\n );\n },\n funnel(input, init) {\n return post(QUERY_API_PATHS.funnel, input, (value) => zFunnelResponse.parse(value), init?.signal);\n },\n retention(input, init) {\n return post(QUERY_API_PATHS.retention, input, (value) => zRetentionResponse.parse(value), init?.signal);\n },\n },\n control: {\n createOrganization(input, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.organizations,\n input,\n (value) => zCreateOrganizationResponse.parse(value),\n { [PLATFORM_KEY_HEADER]: auth.platformKey },\n init?.signal\n );\n },\n rotateOrgKey(organizationId, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.organizationKeys(organizationId),\n {},\n (value) => zRotateOrganizationKeyResponse.parse(value),\n { [PLATFORM_KEY_HEADER]: auth.platformKey },\n init?.signal\n );\n },\n updateOrganizationQuota(organizationId, input, auth, init) {\n return send(\n \"PATCH\",\n CONTROL_API_PATHS.organization(organizationId),\n input,\n (value) => zUpdateOrganizationQuotaResponse.parse(value),\n { [PLATFORM_KEY_HEADER]: auth.platformKey },\n init?.signal\n );\n },\n createProject(input, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.projects,\n input,\n (value) => zCreateProjectResponse.parse(value),\n { [ORG_KEY_HEADER]: auth.orgKey },\n init?.signal\n );\n },\n rotateServerClientSecret(projectId, clientId, auth, init) {\n return send(\n \"POST\",\n CONTROL_API_PATHS.clientRotate(projectId, clientId),\n {},\n (value) => zRotateClientSecretResponse.parse(value),\n { [ORG_KEY_HEADER]: auth.orgKey },\n init?.signal\n );\n },\n deleteProject(projectId, input, auth, init) {\n return send(\n \"DELETE\",\n CONTROL_API_PATHS.project(projectId),\n input,\n (value) => zDeleteProjectResponse.parse(value),\n { [ORG_KEY_HEADER]: auth.orgKey },\n init?.signal\n );\n },\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/control.cjs
CHANGED
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
var
|
|
22
|
-
require('./chunk-
|
|
23
|
-
require('./chunk-
|
|
21
|
+
var _chunkATPS4UV6cjs = require('./chunk-ATPS4UV6.cjs');
|
|
22
|
+
require('./chunk-I2T4HRBM.cjs');
|
|
23
|
+
require('./chunk-KXEQGD3E.cjs');
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
|
|
@@ -41,5 +41,5 @@ require('./chunk-CSTC3ADG.cjs');
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
exports.CONTROL_API_PATHS =
|
|
44
|
+
exports.CONTROL_API_PATHS = _chunkATPS4UV6cjs.CONTROL_API_PATHS; exports.CONTROL_ERROR_CODES = _chunkATPS4UV6cjs.CONTROL_ERROR_CODES; exports.ORG_KEY_HEADER = _chunkATPS4UV6cjs.ORG_KEY_HEADER; exports.PLATFORM_KEY_HEADER = _chunkATPS4UV6cjs.PLATFORM_KEY_HEADER; exports.zControlError = _chunkATPS4UV6cjs.zControlError; exports.zControlErrorCode = _chunkATPS4UV6cjs.zControlErrorCode; exports.zCreateOrganizationInput = _chunkATPS4UV6cjs.zCreateOrganizationInput; exports.zCreateOrganizationResponse = _chunkATPS4UV6cjs.zCreateOrganizationResponse; exports.zCreateProjectInput = _chunkATPS4UV6cjs.zCreateProjectInput; exports.zCreateProjectResponse = _chunkATPS4UV6cjs.zCreateProjectResponse; exports.zDeleteProjectInput = _chunkATPS4UV6cjs.zDeleteProjectInput; exports.zDeleteProjectResponse = _chunkATPS4UV6cjs.zDeleteProjectResponse; exports.zExternalId = _chunkATPS4UV6cjs.zExternalId; exports.zOrganization = _chunkATPS4UV6cjs.zOrganization; exports.zProject = _chunkATPS4UV6cjs.zProject; exports.zRotateClientSecretResponse = _chunkATPS4UV6cjs.zRotateClientSecretResponse; exports.zRotateOrganizationKeyResponse = _chunkATPS4UV6cjs.zRotateOrganizationKeyResponse; exports.zUpdateOrganizationQuotaInput = _chunkATPS4UV6cjs.zUpdateOrganizationQuotaInput; exports.zUpdateOrganizationQuotaResponse = _chunkATPS4UV6cjs.zUpdateOrganizationQuotaResponse;
|
|
45
45
|
//# sourceMappingURL=control.cjs.map
|
package/dist/control.js
CHANGED
|
@@ -18,9 +18,9 @@ import {
|
|
|
18
18
|
zRotateOrganizationKeyResponse,
|
|
19
19
|
zUpdateOrganizationQuotaInput,
|
|
20
20
|
zUpdateOrganizationQuotaResponse
|
|
21
|
-
} from "./chunk-
|
|
22
|
-
import "./chunk-
|
|
23
|
-
import "./chunk-
|
|
21
|
+
} from "./chunk-J4VD3TLV.js";
|
|
22
|
+
import "./chunk-55IWO4S3.js";
|
|
23
|
+
import "./chunk-2LJ7JLDX.js";
|
|
24
24
|
export {
|
|
25
25
|
CONTROL_API_PATHS,
|
|
26
26
|
CONTROL_ERROR_CODES,
|
package/dist/index.cjs
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
var
|
|
12
|
+
var _chunkKXEQGD3Ecjs = require('./chunk-KXEQGD3E.cjs');
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
@@ -21,5 +21,5 @@ var _chunkCSTC3ADGcjs = require('./chunk-CSTC3ADG.cjs');
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
exports.CLIENT_ID_HEADER =
|
|
24
|
+
exports.CLIENT_ID_HEADER = _chunkKXEQGD3Ecjs.CLIENT_ID_HEADER; exports.CLIENT_SECRET_HEADER = _chunkKXEQGD3Ecjs.CLIENT_SECRET_HEADER; exports.CONTRACT_VERSION = _chunkKXEQGD3Ecjs.CONTRACT_VERSION; exports.CONTRACT_VERSION_HEADER = _chunkKXEQGD3Ecjs.CONTRACT_VERSION_HEADER; exports.DEVICE_ID_HEADER = _chunkKXEQGD3Ecjs.DEVICE_ID_HEADER; exports.DataApiError = _chunkKXEQGD3Ecjs.DataApiError; exports.REQUEST_ID_HEADER = _chunkKXEQGD3Ecjs.REQUEST_ID_HEADER; exports.WRITE_KEY_HEADER = _chunkKXEQGD3Ecjs.WRITE_KEY_HEADER; exports.zDate = _chunkKXEQGD3Ecjs.zDate; exports.zInstant = _chunkKXEQGD3Ecjs.zInstant;
|
|
25
25
|
//# sourceMappingURL=index.cjs.map
|