@reopt-ai/data-contract 0.1.0 → 0.2.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.
@@ -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 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\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}\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 postOnce(path: string, body: unknown, signal?: AbortSignal): 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: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"user-agent\": userAgent,\n [CLIENT_ID_HEADER]: options.clientId,\n [CLIENT_SECRET_HEADER]: options.clientSecret,\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 post<T>(path: string, body: unknown, parse: (value: unknown) => T, signal?: AbortSignal): 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 postOnce(path, body, 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 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 };\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 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":[]}
@@ -0,0 +1,45 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+ var _chunkLBSBZO7Ocjs = require('./chunk-LBSBZO7O.cjs');
22
+ require('./chunk-GCLUMVPA.cjs');
23
+ require('./chunk-CSTC3ADG.cjs');
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+ exports.CONTROL_API_PATHS = _chunkLBSBZO7Ocjs.CONTROL_API_PATHS; exports.CONTROL_ERROR_CODES = _chunkLBSBZO7Ocjs.CONTROL_ERROR_CODES; exports.ORG_KEY_HEADER = _chunkLBSBZO7Ocjs.ORG_KEY_HEADER; exports.PLATFORM_KEY_HEADER = _chunkLBSBZO7Ocjs.PLATFORM_KEY_HEADER; exports.zControlError = _chunkLBSBZO7Ocjs.zControlError; exports.zControlErrorCode = _chunkLBSBZO7Ocjs.zControlErrorCode; exports.zCreateOrganizationInput = _chunkLBSBZO7Ocjs.zCreateOrganizationInput; exports.zCreateOrganizationResponse = _chunkLBSBZO7Ocjs.zCreateOrganizationResponse; exports.zCreateProjectInput = _chunkLBSBZO7Ocjs.zCreateProjectInput; exports.zCreateProjectResponse = _chunkLBSBZO7Ocjs.zCreateProjectResponse; exports.zDeleteProjectInput = _chunkLBSBZO7Ocjs.zDeleteProjectInput; exports.zDeleteProjectResponse = _chunkLBSBZO7Ocjs.zDeleteProjectResponse; exports.zExternalId = _chunkLBSBZO7Ocjs.zExternalId; exports.zOrganization = _chunkLBSBZO7Ocjs.zOrganization; exports.zProject = _chunkLBSBZO7Ocjs.zProject; exports.zRotateClientSecretResponse = _chunkLBSBZO7Ocjs.zRotateClientSecretResponse; exports.zRotateOrganizationKeyResponse = _chunkLBSBZO7Ocjs.zRotateOrganizationKeyResponse; exports.zUpdateOrganizationQuotaInput = _chunkLBSBZO7Ocjs.zUpdateOrganizationQuotaInput; exports.zUpdateOrganizationQuotaResponse = _chunkLBSBZO7Ocjs.zUpdateOrganizationQuotaResponse;
45
+ //# sourceMappingURL=control.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/eric/reopt-ai/reopt-data/packages/data-contract/dist/control.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,w0CAAC","file":"/Users/eric/reopt-ai/reopt-data/packages/data-contract/dist/control.cjs"}
@@ -0,0 +1,181 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * `POST /api/v1/organizations` · `/api/v1/projects` and friends — the
5
+ * provisioning contract.
6
+ *
7
+ * A project-scoped client credential cannot authenticate the creation of the
8
+ * project it is scoped to, and an organization key cannot authenticate the
9
+ * creation of its own organization. So provisioning runs on two credentials
10
+ * above the client one: a platform key that creates organizations and writes
11
+ * quotas, and an organization key that creates and deletes projects inside one
12
+ * organization.
13
+ *
14
+ * Quota writes sit with the platform key on purpose. Organization keys are held
15
+ * one-per-workspace by the caller and so have a wide exposure surface; a leaked
16
+ * one that could raise its own limits would turn a credential leak into an
17
+ * unbounded bill.
18
+ */
19
+
20
+ declare const PLATFORM_KEY_HEADER = "reopt-platform-key";
21
+ declare const ORG_KEY_HEADER = "reopt-org-key";
22
+ /**
23
+ * The caller's own id for the thing being provisioned.
24
+ *
25
+ * Preferred over an `Idempotency-Key` header because this domain has a real
26
+ * natural key — the caller already has a stable id for the workspace or brand —
27
+ * and a header would make the caller store a second one just to retry safely.
28
+ */
29
+ declare const zExternalId: z.ZodString;
30
+ declare const zCreateOrganizationInput: z.ZodObject<{
31
+ externalId: z.ZodString;
32
+ name: z.ZodString;
33
+ slug: z.ZodOptional<z.ZodString>;
34
+ monthlyEventQuota: z.ZodOptional<z.ZodNumber>;
35
+ monthlyCreditQuota: z.ZodOptional<z.ZodNumber>;
36
+ }, z.core.$strip>;
37
+ type CreateOrganizationInput = z.input<typeof zCreateOrganizationInput>;
38
+ declare const zOrganization: z.ZodObject<{
39
+ id: z.ZodString;
40
+ externalId: z.ZodString;
41
+ name: z.ZodString;
42
+ slug: z.ZodString;
43
+ monthlyEventQuota: z.ZodNumber;
44
+ monthlyCreditQuota: z.ZodNumber;
45
+ }, z.core.$strip>;
46
+ declare const zCreateOrganizationResponse: z.ZodObject<{
47
+ created: z.ZodBoolean;
48
+ organization: z.ZodObject<{
49
+ id: z.ZodString;
50
+ externalId: z.ZodString;
51
+ name: z.ZodString;
52
+ slug: z.ZodString;
53
+ monthlyEventQuota: z.ZodNumber;
54
+ monthlyCreditQuota: z.ZodNumber;
55
+ }, z.core.$strip>;
56
+ orgKey: z.ZodOptional<z.ZodString>;
57
+ }, z.core.$strip>;
58
+ type CreateOrganizationResponse = z.infer<typeof zCreateOrganizationResponse>;
59
+ declare const zRotateOrganizationKeyResponse: z.ZodObject<{
60
+ organizationId: z.ZodString;
61
+ keyPrefix: z.ZodString;
62
+ orgKey: z.ZodString;
63
+ }, z.core.$strip>;
64
+ type RotateOrganizationKeyResponse = z.infer<typeof zRotateOrganizationKeyResponse>;
65
+ declare const zUpdateOrganizationQuotaInput: z.ZodObject<{
66
+ monthlyEventQuota: z.ZodOptional<z.ZodNumber>;
67
+ monthlyCreditQuota: z.ZodOptional<z.ZodNumber>;
68
+ }, z.core.$strip>;
69
+ type UpdateOrganizationQuotaInput = z.input<typeof zUpdateOrganizationQuotaInput>;
70
+ declare const zUpdateOrganizationQuotaResponse: z.ZodObject<{
71
+ organization: z.ZodObject<{
72
+ id: z.ZodString;
73
+ externalId: z.ZodString;
74
+ name: z.ZodString;
75
+ slug: z.ZodString;
76
+ monthlyEventQuota: z.ZodNumber;
77
+ monthlyCreditQuota: z.ZodNumber;
78
+ }, z.core.$strip>;
79
+ }, z.core.$strip>;
80
+ type UpdateOrganizationQuotaResponse = z.infer<typeof zUpdateOrganizationQuotaResponse>;
81
+ declare const zCreateProjectInput: z.ZodObject<{
82
+ externalId: z.ZodString;
83
+ name: z.ZodString;
84
+ domain: z.ZodOptional<z.ZodString>;
85
+ timezone: z.ZodOptional<z.ZodString>;
86
+ retentionDays: z.ZodOptional<z.ZodNumber>;
87
+ }, z.core.$strip>;
88
+ type CreateProjectInput = z.input<typeof zCreateProjectInput>;
89
+ declare const zProject: z.ZodObject<{
90
+ id: z.ZodString;
91
+ externalId: z.ZodString;
92
+ organizationId: z.ZodString;
93
+ name: z.ZodString;
94
+ timezone: z.ZodString;
95
+ retentionDays: z.ZodNullable<z.ZodNumber>;
96
+ }, z.core.$strip>;
97
+ declare const zCreateProjectResponse: z.ZodObject<{
98
+ created: z.ZodBoolean;
99
+ project: z.ZodObject<{
100
+ id: z.ZodString;
101
+ externalId: z.ZodString;
102
+ organizationId: z.ZodString;
103
+ name: z.ZodString;
104
+ timezone: z.ZodString;
105
+ retentionDays: z.ZodNullable<z.ZodNumber>;
106
+ }, z.core.$strip>;
107
+ clients: z.ZodObject<{
108
+ browser: z.ZodObject<{
109
+ id: z.ZodString;
110
+ writeKey: z.ZodString;
111
+ scopes: z.ZodArray<z.ZodString>;
112
+ }, z.core.$strip>;
113
+ server: z.ZodObject<{
114
+ id: z.ZodString;
115
+ clientSecret: z.ZodOptional<z.ZodString>;
116
+ scopes: z.ZodArray<z.ZodString>;
117
+ }, z.core.$strip>;
118
+ }, z.core.$strip>;
119
+ }, z.core.$strip>;
120
+ type CreateProjectResponse = z.infer<typeof zCreateProjectResponse>;
121
+ declare const zRotateClientSecretResponse: z.ZodObject<{
122
+ projectId: z.ZodString;
123
+ clientId: z.ZodString;
124
+ clientSecret: z.ZodString;
125
+ }, z.core.$strip>;
126
+ type RotateClientSecretResponse = z.infer<typeof zRotateClientSecretResponse>;
127
+ declare const zDeleteProjectInput: z.ZodObject<{
128
+ purge: z.ZodLiteral<true>;
129
+ externalId: z.ZodString;
130
+ }, z.core.$strip>;
131
+ type DeleteProjectInput = z.input<typeof zDeleteProjectInput>;
132
+ declare const zDeleteProjectResponse: z.ZodObject<{
133
+ projectId: z.ZodString;
134
+ purge: z.ZodEnum<{
135
+ queued: "queued";
136
+ "already-absent": "already-absent";
137
+ }>;
138
+ purgingAt: z.ZodOptional<z.ZodString>;
139
+ }, z.core.$strip>;
140
+ type DeleteProjectResponse = z.infer<typeof zDeleteProjectResponse>;
141
+ declare const CONTROL_ERROR_CODES: readonly ["unauthorized", "organization_scope_mismatch", "external_id_conflict", "project_external_id_mismatch", "not_found", "validation_failed", "rate_limited", "internal_error"];
142
+ declare const zControlErrorCode: z.ZodEnum<{
143
+ validation_failed: "validation_failed";
144
+ unauthorized: "unauthorized";
145
+ rate_limited: "rate_limited";
146
+ internal_error: "internal_error";
147
+ organization_scope_mismatch: "organization_scope_mismatch";
148
+ external_id_conflict: "external_id_conflict";
149
+ project_external_id_mismatch: "project_external_id_mismatch";
150
+ not_found: "not_found";
151
+ }>;
152
+ type ControlErrorCode = z.infer<typeof zControlErrorCode>;
153
+ declare const zControlError: z.ZodObject<{
154
+ status: z.ZodNumber;
155
+ code: z.ZodEnum<{
156
+ validation_failed: "validation_failed";
157
+ unauthorized: "unauthorized";
158
+ rate_limited: "rate_limited";
159
+ internal_error: "internal_error";
160
+ organization_scope_mismatch: "organization_scope_mismatch";
161
+ external_id_conflict: "external_id_conflict";
162
+ project_external_id_mismatch: "project_external_id_mismatch";
163
+ not_found: "not_found";
164
+ }>;
165
+ error: z.ZodString;
166
+ message: z.ZodOptional<z.ZodString>;
167
+ errors: z.ZodOptional<z.ZodUnknown>;
168
+ requestId: z.ZodOptional<z.ZodString>;
169
+ }, z.core.$strip>;
170
+ type ControlError = z.infer<typeof zControlError>;
171
+ /** Paths, so the client and the route handlers cannot drift apart. */
172
+ declare const CONTROL_API_PATHS: {
173
+ readonly organizations: "/api/v1/organizations";
174
+ readonly organization: (id: string) => string;
175
+ readonly organizationKeys: (id: string) => string;
176
+ readonly projects: "/api/v1/projects";
177
+ readonly project: (id: string) => string;
178
+ readonly clientRotate: (projectId: string, clientId: string) => string;
179
+ };
180
+
181
+ export { CONTROL_API_PATHS, CONTROL_ERROR_CODES, type ControlError, type ControlErrorCode, type CreateOrganizationInput, type CreateOrganizationResponse, type CreateProjectInput, type CreateProjectResponse, type DeleteProjectInput, type DeleteProjectResponse, ORG_KEY_HEADER, PLATFORM_KEY_HEADER, type RotateClientSecretResponse, type RotateOrganizationKeyResponse, type UpdateOrganizationQuotaInput, type UpdateOrganizationQuotaResponse, zControlError, zControlErrorCode, zCreateOrganizationInput, zCreateOrganizationResponse, zCreateProjectInput, zCreateProjectResponse, zDeleteProjectInput, zDeleteProjectResponse, zExternalId, zOrganization, zProject, zRotateClientSecretResponse, zRotateOrganizationKeyResponse, zUpdateOrganizationQuotaInput, zUpdateOrganizationQuotaResponse };
@@ -0,0 +1,181 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * `POST /api/v1/organizations` · `/api/v1/projects` and friends — the
5
+ * provisioning contract.
6
+ *
7
+ * A project-scoped client credential cannot authenticate the creation of the
8
+ * project it is scoped to, and an organization key cannot authenticate the
9
+ * creation of its own organization. So provisioning runs on two credentials
10
+ * above the client one: a platform key that creates organizations and writes
11
+ * quotas, and an organization key that creates and deletes projects inside one
12
+ * organization.
13
+ *
14
+ * Quota writes sit with the platform key on purpose. Organization keys are held
15
+ * one-per-workspace by the caller and so have a wide exposure surface; a leaked
16
+ * one that could raise its own limits would turn a credential leak into an
17
+ * unbounded bill.
18
+ */
19
+
20
+ declare const PLATFORM_KEY_HEADER = "reopt-platform-key";
21
+ declare const ORG_KEY_HEADER = "reopt-org-key";
22
+ /**
23
+ * The caller's own id for the thing being provisioned.
24
+ *
25
+ * Preferred over an `Idempotency-Key` header because this domain has a real
26
+ * natural key — the caller already has a stable id for the workspace or brand —
27
+ * and a header would make the caller store a second one just to retry safely.
28
+ */
29
+ declare const zExternalId: z.ZodString;
30
+ declare const zCreateOrganizationInput: z.ZodObject<{
31
+ externalId: z.ZodString;
32
+ name: z.ZodString;
33
+ slug: z.ZodOptional<z.ZodString>;
34
+ monthlyEventQuota: z.ZodOptional<z.ZodNumber>;
35
+ monthlyCreditQuota: z.ZodOptional<z.ZodNumber>;
36
+ }, z.core.$strip>;
37
+ type CreateOrganizationInput = z.input<typeof zCreateOrganizationInput>;
38
+ declare const zOrganization: z.ZodObject<{
39
+ id: z.ZodString;
40
+ externalId: z.ZodString;
41
+ name: z.ZodString;
42
+ slug: z.ZodString;
43
+ monthlyEventQuota: z.ZodNumber;
44
+ monthlyCreditQuota: z.ZodNumber;
45
+ }, z.core.$strip>;
46
+ declare const zCreateOrganizationResponse: z.ZodObject<{
47
+ created: z.ZodBoolean;
48
+ organization: z.ZodObject<{
49
+ id: z.ZodString;
50
+ externalId: z.ZodString;
51
+ name: z.ZodString;
52
+ slug: z.ZodString;
53
+ monthlyEventQuota: z.ZodNumber;
54
+ monthlyCreditQuota: z.ZodNumber;
55
+ }, z.core.$strip>;
56
+ orgKey: z.ZodOptional<z.ZodString>;
57
+ }, z.core.$strip>;
58
+ type CreateOrganizationResponse = z.infer<typeof zCreateOrganizationResponse>;
59
+ declare const zRotateOrganizationKeyResponse: z.ZodObject<{
60
+ organizationId: z.ZodString;
61
+ keyPrefix: z.ZodString;
62
+ orgKey: z.ZodString;
63
+ }, z.core.$strip>;
64
+ type RotateOrganizationKeyResponse = z.infer<typeof zRotateOrganizationKeyResponse>;
65
+ declare const zUpdateOrganizationQuotaInput: z.ZodObject<{
66
+ monthlyEventQuota: z.ZodOptional<z.ZodNumber>;
67
+ monthlyCreditQuota: z.ZodOptional<z.ZodNumber>;
68
+ }, z.core.$strip>;
69
+ type UpdateOrganizationQuotaInput = z.input<typeof zUpdateOrganizationQuotaInput>;
70
+ declare const zUpdateOrganizationQuotaResponse: z.ZodObject<{
71
+ organization: z.ZodObject<{
72
+ id: z.ZodString;
73
+ externalId: z.ZodString;
74
+ name: z.ZodString;
75
+ slug: z.ZodString;
76
+ monthlyEventQuota: z.ZodNumber;
77
+ monthlyCreditQuota: z.ZodNumber;
78
+ }, z.core.$strip>;
79
+ }, z.core.$strip>;
80
+ type UpdateOrganizationQuotaResponse = z.infer<typeof zUpdateOrganizationQuotaResponse>;
81
+ declare const zCreateProjectInput: z.ZodObject<{
82
+ externalId: z.ZodString;
83
+ name: z.ZodString;
84
+ domain: z.ZodOptional<z.ZodString>;
85
+ timezone: z.ZodOptional<z.ZodString>;
86
+ retentionDays: z.ZodOptional<z.ZodNumber>;
87
+ }, z.core.$strip>;
88
+ type CreateProjectInput = z.input<typeof zCreateProjectInput>;
89
+ declare const zProject: z.ZodObject<{
90
+ id: z.ZodString;
91
+ externalId: z.ZodString;
92
+ organizationId: z.ZodString;
93
+ name: z.ZodString;
94
+ timezone: z.ZodString;
95
+ retentionDays: z.ZodNullable<z.ZodNumber>;
96
+ }, z.core.$strip>;
97
+ declare const zCreateProjectResponse: z.ZodObject<{
98
+ created: z.ZodBoolean;
99
+ project: z.ZodObject<{
100
+ id: z.ZodString;
101
+ externalId: z.ZodString;
102
+ organizationId: z.ZodString;
103
+ name: z.ZodString;
104
+ timezone: z.ZodString;
105
+ retentionDays: z.ZodNullable<z.ZodNumber>;
106
+ }, z.core.$strip>;
107
+ clients: z.ZodObject<{
108
+ browser: z.ZodObject<{
109
+ id: z.ZodString;
110
+ writeKey: z.ZodString;
111
+ scopes: z.ZodArray<z.ZodString>;
112
+ }, z.core.$strip>;
113
+ server: z.ZodObject<{
114
+ id: z.ZodString;
115
+ clientSecret: z.ZodOptional<z.ZodString>;
116
+ scopes: z.ZodArray<z.ZodString>;
117
+ }, z.core.$strip>;
118
+ }, z.core.$strip>;
119
+ }, z.core.$strip>;
120
+ type CreateProjectResponse = z.infer<typeof zCreateProjectResponse>;
121
+ declare const zRotateClientSecretResponse: z.ZodObject<{
122
+ projectId: z.ZodString;
123
+ clientId: z.ZodString;
124
+ clientSecret: z.ZodString;
125
+ }, z.core.$strip>;
126
+ type RotateClientSecretResponse = z.infer<typeof zRotateClientSecretResponse>;
127
+ declare const zDeleteProjectInput: z.ZodObject<{
128
+ purge: z.ZodLiteral<true>;
129
+ externalId: z.ZodString;
130
+ }, z.core.$strip>;
131
+ type DeleteProjectInput = z.input<typeof zDeleteProjectInput>;
132
+ declare const zDeleteProjectResponse: z.ZodObject<{
133
+ projectId: z.ZodString;
134
+ purge: z.ZodEnum<{
135
+ queued: "queued";
136
+ "already-absent": "already-absent";
137
+ }>;
138
+ purgingAt: z.ZodOptional<z.ZodString>;
139
+ }, z.core.$strip>;
140
+ type DeleteProjectResponse = z.infer<typeof zDeleteProjectResponse>;
141
+ declare const CONTROL_ERROR_CODES: readonly ["unauthorized", "organization_scope_mismatch", "external_id_conflict", "project_external_id_mismatch", "not_found", "validation_failed", "rate_limited", "internal_error"];
142
+ declare const zControlErrorCode: z.ZodEnum<{
143
+ validation_failed: "validation_failed";
144
+ unauthorized: "unauthorized";
145
+ rate_limited: "rate_limited";
146
+ internal_error: "internal_error";
147
+ organization_scope_mismatch: "organization_scope_mismatch";
148
+ external_id_conflict: "external_id_conflict";
149
+ project_external_id_mismatch: "project_external_id_mismatch";
150
+ not_found: "not_found";
151
+ }>;
152
+ type ControlErrorCode = z.infer<typeof zControlErrorCode>;
153
+ declare const zControlError: z.ZodObject<{
154
+ status: z.ZodNumber;
155
+ code: z.ZodEnum<{
156
+ validation_failed: "validation_failed";
157
+ unauthorized: "unauthorized";
158
+ rate_limited: "rate_limited";
159
+ internal_error: "internal_error";
160
+ organization_scope_mismatch: "organization_scope_mismatch";
161
+ external_id_conflict: "external_id_conflict";
162
+ project_external_id_mismatch: "project_external_id_mismatch";
163
+ not_found: "not_found";
164
+ }>;
165
+ error: z.ZodString;
166
+ message: z.ZodOptional<z.ZodString>;
167
+ errors: z.ZodOptional<z.ZodUnknown>;
168
+ requestId: z.ZodOptional<z.ZodString>;
169
+ }, z.core.$strip>;
170
+ type ControlError = z.infer<typeof zControlError>;
171
+ /** Paths, so the client and the route handlers cannot drift apart. */
172
+ declare const CONTROL_API_PATHS: {
173
+ readonly organizations: "/api/v1/organizations";
174
+ readonly organization: (id: string) => string;
175
+ readonly organizationKeys: (id: string) => string;
176
+ readonly projects: "/api/v1/projects";
177
+ readonly project: (id: string) => string;
178
+ readonly clientRotate: (projectId: string, clientId: string) => string;
179
+ };
180
+
181
+ export { CONTROL_API_PATHS, CONTROL_ERROR_CODES, type ControlError, type ControlErrorCode, type CreateOrganizationInput, type CreateOrganizationResponse, type CreateProjectInput, type CreateProjectResponse, type DeleteProjectInput, type DeleteProjectResponse, ORG_KEY_HEADER, PLATFORM_KEY_HEADER, type RotateClientSecretResponse, type RotateOrganizationKeyResponse, type UpdateOrganizationQuotaInput, type UpdateOrganizationQuotaResponse, zControlError, zControlErrorCode, zCreateOrganizationInput, zCreateOrganizationResponse, zCreateProjectInput, zCreateProjectResponse, zDeleteProjectInput, zDeleteProjectResponse, zExternalId, zOrganization, zProject, zRotateClientSecretResponse, zRotateOrganizationKeyResponse, zUpdateOrganizationQuotaInput, zUpdateOrganizationQuotaResponse };
@@ -0,0 +1,45 @@
1
+ import {
2
+ CONTROL_API_PATHS,
3
+ CONTROL_ERROR_CODES,
4
+ ORG_KEY_HEADER,
5
+ PLATFORM_KEY_HEADER,
6
+ zControlError,
7
+ zControlErrorCode,
8
+ zCreateOrganizationInput,
9
+ zCreateOrganizationResponse,
10
+ zCreateProjectInput,
11
+ zCreateProjectResponse,
12
+ zDeleteProjectInput,
13
+ zDeleteProjectResponse,
14
+ zExternalId,
15
+ zOrganization,
16
+ zProject,
17
+ zRotateClientSecretResponse,
18
+ zRotateOrganizationKeyResponse,
19
+ zUpdateOrganizationQuotaInput,
20
+ zUpdateOrganizationQuotaResponse
21
+ } from "./chunk-2SJPZP2D.js";
22
+ import "./chunk-SC7TFGTO.js";
23
+ import "./chunk-IKOEYZVT.js";
24
+ export {
25
+ CONTROL_API_PATHS,
26
+ CONTROL_ERROR_CODES,
27
+ ORG_KEY_HEADER,
28
+ PLATFORM_KEY_HEADER,
29
+ zControlError,
30
+ zControlErrorCode,
31
+ zCreateOrganizationInput,
32
+ zCreateOrganizationResponse,
33
+ zCreateProjectInput,
34
+ zCreateProjectResponse,
35
+ zDeleteProjectInput,
36
+ zDeleteProjectResponse,
37
+ zExternalId,
38
+ zOrganization,
39
+ zProject,
40
+ zRotateClientSecretResponse,
41
+ zRotateOrganizationKeyResponse,
42
+ zUpdateOrganizationQuotaInput,
43
+ zUpdateOrganizationQuotaResponse
44
+ };
45
+ //# sourceMappingURL=control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/dist/index.cjs CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
 
11
11
 
12
- var _chunkZQVRSCTWcjs = require('./chunk-ZQVRSCTW.cjs');
12
+ var _chunkCSTC3ADGcjs = require('./chunk-CSTC3ADG.cjs');
13
13
 
14
14
 
15
15
 
@@ -21,5 +21,5 @@ var _chunkZQVRSCTWcjs = require('./chunk-ZQVRSCTW.cjs');
21
21
 
22
22
 
23
23
 
24
- exports.CLIENT_ID_HEADER = _chunkZQVRSCTWcjs.CLIENT_ID_HEADER; exports.CLIENT_SECRET_HEADER = _chunkZQVRSCTWcjs.CLIENT_SECRET_HEADER; exports.CONTRACT_VERSION = _chunkZQVRSCTWcjs.CONTRACT_VERSION; exports.CONTRACT_VERSION_HEADER = _chunkZQVRSCTWcjs.CONTRACT_VERSION_HEADER; exports.DEVICE_ID_HEADER = _chunkZQVRSCTWcjs.DEVICE_ID_HEADER; exports.DataApiError = _chunkZQVRSCTWcjs.DataApiError; exports.REQUEST_ID_HEADER = _chunkZQVRSCTWcjs.REQUEST_ID_HEADER; exports.WRITE_KEY_HEADER = _chunkZQVRSCTWcjs.WRITE_KEY_HEADER; exports.zDate = _chunkZQVRSCTWcjs.zDate; exports.zInstant = _chunkZQVRSCTWcjs.zInstant;
24
+ exports.CLIENT_ID_HEADER = _chunkCSTC3ADGcjs.CLIENT_ID_HEADER; exports.CLIENT_SECRET_HEADER = _chunkCSTC3ADGcjs.CLIENT_SECRET_HEADER; exports.CONTRACT_VERSION = _chunkCSTC3ADGcjs.CONTRACT_VERSION; exports.CONTRACT_VERSION_HEADER = _chunkCSTC3ADGcjs.CONTRACT_VERSION_HEADER; exports.DEVICE_ID_HEADER = _chunkCSTC3ADGcjs.DEVICE_ID_HEADER; exports.DataApiError = _chunkCSTC3ADGcjs.DataApiError; exports.REQUEST_ID_HEADER = _chunkCSTC3ADGcjs.REQUEST_ID_HEADER; exports.WRITE_KEY_HEADER = _chunkCSTC3ADGcjs.WRITE_KEY_HEADER; exports.zDate = _chunkCSTC3ADGcjs.zDate; exports.zInstant = _chunkCSTC3ADGcjs.zInstant;
25
25
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.cts CHANGED
@@ -8,7 +8,8 @@ import { z } from 'zod';
8
8
  * `@reopt-ai/data-contract` this module — version, shared primitives, errors
9
9
  * `@reopt-ai/data-contract/ingest` POST /api/track request + response schemas
10
10
  * `@reopt-ai/data-contract/query` POST /api/v1/query/* request + response schemas
11
- * `@reopt-ai/data-contract/client` createDataClient() typed fetch over both
11
+ * `@reopt-ai/data-contract/control` provisioning request + response schemas
12
+ * `@reopt-ai/data-contract/client` createDataClient() — typed fetch over all
12
13
  *
13
14
  * Only `/client` touches `fetch`; everything else is pure zod. The single
14
15
  * runtime dependency is zod, deliberately — consumers bundle this.
@@ -19,7 +20,7 @@ import { z } from 'zod';
19
20
  * The server echoes the version it was built against in `x-reopt-contract-version`;
20
21
  * `createDataClient` surfaces a mismatch rather than guessing.
21
22
  */
22
- declare const CONTRACT_VERSION = "0.1.0";
23
+ declare const CONTRACT_VERSION = "0.2.0";
23
24
  /** Response header carrying the server's contract version. */
24
25
  declare const CONTRACT_VERSION_HEADER = "x-reopt-contract-version";
25
26
  /** Request header names shared by the ingest and query planes. */
package/dist/index.d.ts CHANGED
@@ -8,7 +8,8 @@ import { z } from 'zod';
8
8
  * `@reopt-ai/data-contract` this module — version, shared primitives, errors
9
9
  * `@reopt-ai/data-contract/ingest` POST /api/track request + response schemas
10
10
  * `@reopt-ai/data-contract/query` POST /api/v1/query/* request + response schemas
11
- * `@reopt-ai/data-contract/client` createDataClient() typed fetch over both
11
+ * `@reopt-ai/data-contract/control` provisioning request + response schemas
12
+ * `@reopt-ai/data-contract/client` createDataClient() — typed fetch over all
12
13
  *
13
14
  * Only `/client` touches `fetch`; everything else is pure zod. The single
14
15
  * runtime dependency is zod, deliberately — consumers bundle this.
@@ -19,7 +20,7 @@ import { z } from 'zod';
19
20
  * The server echoes the version it was built against in `x-reopt-contract-version`;
20
21
  * `createDataClient` surfaces a mismatch rather than guessing.
21
22
  */
22
- declare const CONTRACT_VERSION = "0.1.0";
23
+ declare const CONTRACT_VERSION = "0.2.0";
23
24
  /** Response header carrying the server's contract version. */
24
25
  declare const CONTRACT_VERSION_HEADER = "x-reopt-contract-version";
25
26
  /** Request header names shared by the ingest and query planes. */
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  WRITE_KEY_HEADER,
10
10
  zDate,
11
11
  zInstant
12
- } from "./chunk-IAOPUBJU.js";
12
+ } from "./chunk-IKOEYZVT.js";
13
13
  export {
14
14
  CLIENT_ID_HEADER,
15
15
  CLIENT_SECRET_HEADER,
package/dist/ingest.d.cts CHANGED
@@ -234,31 +234,31 @@ declare function reconcileIngestResponse(response: IngestResponse, sentCount: nu
234
234
  */
235
235
  declare const INGEST_ERROR_CODES: readonly ["unauthorized", "invalid_json", "payload_too_large", "empty_batch", "alias_unsupported", "project_without_organization", "validation_failed", "rate_limited", "quota_exceeded", "internal_error"];
236
236
  declare const zIngestErrorCode: z.ZodEnum<{
237
- unauthorized: "unauthorized";
238
237
  validation_failed: "validation_failed";
239
- rate_limited: "rate_limited";
240
- internal_error: "internal_error";
238
+ unauthorized: "unauthorized";
241
239
  invalid_json: "invalid_json";
242
240
  payload_too_large: "payload_too_large";
243
241
  empty_batch: "empty_batch";
244
242
  alias_unsupported: "alias_unsupported";
245
243
  project_without_organization: "project_without_organization";
244
+ rate_limited: "rate_limited";
246
245
  quota_exceeded: "quota_exceeded";
246
+ internal_error: "internal_error";
247
247
  }>;
248
248
  type IngestErrorCode = z.infer<typeof zIngestErrorCode>;
249
249
  declare const zIngestError: z.ZodObject<{
250
250
  status: z.ZodNumber;
251
251
  code: z.ZodEnum<{
252
- unauthorized: "unauthorized";
253
252
  validation_failed: "validation_failed";
254
- rate_limited: "rate_limited";
255
- internal_error: "internal_error";
253
+ unauthorized: "unauthorized";
256
254
  invalid_json: "invalid_json";
257
255
  payload_too_large: "payload_too_large";
258
256
  empty_batch: "empty_batch";
259
257
  alias_unsupported: "alias_unsupported";
260
258
  project_without_organization: "project_without_organization";
259
+ rate_limited: "rate_limited";
261
260
  quota_exceeded: "quota_exceeded";
261
+ internal_error: "internal_error";
262
262
  }>;
263
263
  error: z.ZodString;
264
264
  message: z.ZodOptional<z.ZodString>;