@reopt-ai/data-contract 0.5.0 → 0.6.1
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-2LZBZXBF.js → chunk-33BCA2LH.js} +1 -15
- package/dist/chunk-33BCA2LH.js.map +1 -0
- package/dist/chunk-3EEANNYN.cjs +62 -0
- package/dist/chunk-3EEANNYN.cjs.map +1 -0
- package/dist/{chunk-MFZEIH5Z.js → chunk-EZ2TA4S6.js} +31 -6
- package/dist/chunk-EZ2TA4S6.js.map +1 -0
- package/dist/chunk-FP2X3PRK.js +62 -0
- package/dist/chunk-FP2X3PRK.js.map +1 -0
- package/dist/{chunk-VQ2CD5MG.cjs → chunk-FUGY5ANJ.cjs} +13 -13
- package/dist/{chunk-VQ2CD5MG.cjs.map → chunk-FUGY5ANJ.cjs.map} +1 -1
- package/dist/chunk-GCQZNME3.js +153 -0
- package/dist/chunk-GCQZNME3.js.map +1 -0
- package/dist/chunk-HLQAZ6JW.js +19 -0
- package/dist/chunk-HLQAZ6JW.js.map +1 -0
- package/dist/{chunk-AHXPQQKO.js → chunk-IY4MXH35.js} +3 -3
- package/dist/chunk-JB4MJQX7.cjs +19 -0
- package/dist/chunk-JB4MJQX7.cjs.map +1 -0
- package/dist/{chunk-BCGR27G2.js → chunk-L3WJGIKD.js} +2 -2
- package/dist/{chunk-4B4AY44F.cjs → chunk-LA5F5KR6.cjs} +6 -6
- package/dist/{chunk-4B4AY44F.cjs.map → chunk-LA5F5KR6.cjs.map} +1 -1
- package/dist/chunk-PHPTCLRU.cjs +153 -0
- package/dist/chunk-PHPTCLRU.cjs.map +1 -0
- package/dist/{chunk-XI3VP5DN.cjs → chunk-VGB2VJO4.cjs} +34 -9
- package/dist/chunk-VGB2VJO4.cjs.map +1 -0
- package/dist/{chunk-OLSMH4RY.cjs → chunk-YSAEOYPD.cjs} +2 -16
- package/dist/chunk-YSAEOYPD.cjs.map +1 -0
- package/dist/client.cjs +53 -49
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +2 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +9 -5
- package/dist/client.js.map +1 -1
- package/dist/control.cjs +5 -4
- package/dist/control.cjs.map +1 -1
- package/dist/control.d.cts +6 -6
- package/dist/control.d.ts +6 -6
- package/dist/control.js +4 -3
- package/dist/events.cjs +17 -0
- package/dist/events.cjs.map +1 -0
- package/dist/events.d.cts +59 -0
- package/dist/events.d.ts +59 -0
- package/dist/events.js +17 -0
- package/dist/events.js.map +1 -0
- package/dist/identity.cjs +57 -0
- package/dist/identity.cjs.map +1 -0
- package/dist/identity.d.cts +119 -0
- package/dist/identity.d.ts +119 -0
- package/dist/identity.js +57 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.cjs +4 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -15
- package/dist/index.d.ts +5 -15
- package/dist/index.js +7 -5
- package/dist/ingest.cjs +18 -2
- package/dist/ingest.cjs.map +1 -1
- package/dist/ingest.d.cts +39 -9
- package/dist/ingest.d.ts +39 -9
- package/dist/ingest.js +18 -2
- package/dist/query.cjs +4 -3
- package/dist/query.cjs.map +1 -1
- package/dist/query.d.cts +17 -16
- package/dist/query.d.ts +17 -16
- package/dist/query.js +3 -2
- package/dist/version-BzeRTpta.d.cts +26 -0
- package/dist/version-BzeRTpta.d.ts +26 -0
- package/package.json +13 -2
- package/dist/chunk-2LZBZXBF.js.map +0 -1
- package/dist/chunk-MFZEIH5Z.js.map +0 -1
- package/dist/chunk-OLSMH4RY.cjs.map +0 -1
- package/dist/chunk-XI3VP5DN.cjs.map +0 -1
- /package/dist/{chunk-AHXPQQKO.js.map → chunk-IY4MXH35.js.map} +0 -0
- /package/dist/{chunk-BCGR27G2.js.map → chunk-L3WJGIKD.js.map} +0 -0
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 CONTRACT_VERSION_HEADER,\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 zEventMetaResponse,\n type CreateOrganizationInput,\n type EventMetaResponse,\n type UpsertEventMetaInput,\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 zTrafficOverviewResponse,\n zTrafficSourcesResponse,\n type EventsTimeseriesInput,\n type EventsTimeseriesResponse,\n type FunnelInput,\n type FunnelResponse,\n type RetentionInput,\n type RetentionResponse,\n type TrafficOverviewInput,\n type TrafficOverviewResponse,\n type TrafficSourcesInput,\n type TrafficSourcesResponse,\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 trafficOverview(input: TrafficOverviewInput, init?: DataRequestInit): Promise<TrafficOverviewResponse>;\n trafficSources(input: TrafficSourcesInput, init?: DataRequestInit): Promise<TrafficSourcesResponse>;\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 /** Idempotent: a repeat with the same body changes nothing and answers 200. */\n upsertEventMeta(\n projectId: string,\n name: string,\n input: UpsertEventMetaInput,\n auth: OrganizationAuth,\n init?: DataRequestInit\n ): Promise<EventMetaResponse>;\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\" | \"PUT\" | \"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\" | \"PUT\" | \"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 serverContractVersion = response.headers.get(CONTRACT_VERSION_HEADER);\n const rawBody = await response.text();\n\n if (serverContractVersion !== CONTRACT_VERSION) {\n throw new DataApiError({\n message: serverContractVersion\n ? `reopt-data contract ${serverContractVersion} does not match client contract ${CONTRACT_VERSION}`\n : \"reopt-data response did not declare its contract version\",\n status: response.status,\n code: \"contract_mismatch\",\n requestId,\n details: { expected: CONTRACT_VERSION, received: serverContractVersion },\n });\n }\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 trafficOverview(input, init) {\n return post(\n QUERY_API_PATHS.trafficOverview,\n input,\n (value) => zTrafficOverviewResponse.parse(value),\n init?.signal\n );\n },\n trafficSources(input, init) {\n return post(\n QUERY_API_PATHS.trafficSources,\n input,\n (value) => zTrafficSourcesResponse.parse(value),\n init?.signal\n );\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 upsertEventMeta(projectId, name, input, auth, init) {\n return send(\n \"PUT\",\n CONTROL_API_PATHS.projectEvent(projectId, name),\n input,\n (value) => zEventMetaResponse.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 CONTRACT_VERSION_HEADER,\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 zEventMetaResponse,\n type CreateOrganizationInput,\n type EventMetaResponse,\n type UpsertEventMetaInput,\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 zTrafficOverviewResponse,\n zTrafficSourcesResponse,\n type EventsTimeseriesInput,\n type EventsTimeseriesResponse,\n type FunnelInput,\n type FunnelResponse,\n type RetentionInput,\n type RetentionResponse,\n type TrafficOverviewInput,\n type TrafficOverviewResponse,\n type TrafficSourcesInput,\n type TrafficSourcesResponse,\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 trafficOverview(input: TrafficOverviewInput, init?: DataRequestInit): Promise<TrafficOverviewResponse>;\n trafficSources(input: TrafficSourcesInput, init?: DataRequestInit): Promise<TrafficSourcesResponse>;\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 /** Idempotent: a repeat with the same body changes nothing and answers 200. */\n upsertEventMeta(\n projectId: string,\n name: string,\n input: UpsertEventMetaInput,\n auth: OrganizationAuth,\n init?: DataRequestInit\n ): Promise<EventMetaResponse>;\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\" | \"PUT\" | \"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\" | \"PUT\" | \"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 serverContractVersion = response.headers.get(CONTRACT_VERSION_HEADER);\n const rawBody = await response.text();\n\n if (serverContractVersion !== CONTRACT_VERSION) {\n throw new DataApiError({\n message: serverContractVersion\n ? `reopt-data contract ${serverContractVersion} does not match client contract ${CONTRACT_VERSION}`\n : \"reopt-data response did not declare its contract version\",\n status: response.status,\n code: \"contract_mismatch\",\n requestId,\n details: { expected: CONTRACT_VERSION, received: serverContractVersion },\n });\n }\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 trafficOverview(input, init) {\n return post(\n QUERY_API_PATHS.trafficOverview,\n input,\n (value) => zTrafficOverviewResponse.parse(value),\n init?.signal\n );\n },\n trafficSources(input, init) {\n return post(\n QUERY_API_PATHS.trafficSources,\n input,\n (value) => zTrafficSourcesResponse.parse(value),\n init?.signal\n );\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 upsertEventMeta(projectId, name, input, auth, init) {\n return send(\n \"PUT\",\n CONTROL_API_PATHS.projectEvent(projectId, name),\n input,\n (value) => zEventMetaResponse.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
|
@@ -23,9 +23,10 @@
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
var
|
|
27
|
-
require('./chunk-
|
|
28
|
-
require('./chunk-
|
|
26
|
+
var _chunkLA5F5KR6cjs = require('./chunk-LA5F5KR6.cjs');
|
|
27
|
+
require('./chunk-FUGY5ANJ.cjs');
|
|
28
|
+
require('./chunk-YSAEOYPD.cjs');
|
|
29
|
+
require('./chunk-JB4MJQX7.cjs');
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
|
|
@@ -51,5 +52,5 @@ require('./chunk-OLSMH4RY.cjs');
|
|
|
51
52
|
|
|
52
53
|
|
|
53
54
|
|
|
54
|
-
exports.CONTROL_API_PATHS =
|
|
55
|
+
exports.CONTROL_API_PATHS = _chunkLA5F5KR6cjs.CONTROL_API_PATHS; exports.CONTROL_ERROR_CODES = _chunkLA5F5KR6cjs.CONTROL_ERROR_CODES; exports.EVENT_META_STATUSES = _chunkLA5F5KR6cjs.EVENT_META_STATUSES; exports.ORG_KEY_HEADER = _chunkLA5F5KR6cjs.ORG_KEY_HEADER; exports.PLATFORM_KEY_HEADER = _chunkLA5F5KR6cjs.PLATFORM_KEY_HEADER; exports.zControlError = _chunkLA5F5KR6cjs.zControlError; exports.zControlErrorCode = _chunkLA5F5KR6cjs.zControlErrorCode; exports.zCreateOrganizationInput = _chunkLA5F5KR6cjs.zCreateOrganizationInput; exports.zCreateOrganizationResponse = _chunkLA5F5KR6cjs.zCreateOrganizationResponse; exports.zCreateProjectInput = _chunkLA5F5KR6cjs.zCreateProjectInput; exports.zCreateProjectResponse = _chunkLA5F5KR6cjs.zCreateProjectResponse; exports.zDeleteProjectInput = _chunkLA5F5KR6cjs.zDeleteProjectInput; exports.zDeleteProjectResponse = _chunkLA5F5KR6cjs.zDeleteProjectResponse; exports.zEventMetaResponse = _chunkLA5F5KR6cjs.zEventMetaResponse; exports.zEventMetaStatus = _chunkLA5F5KR6cjs.zEventMetaStatus; exports.zEventName = _chunkLA5F5KR6cjs.zEventName; exports.zExternalId = _chunkLA5F5KR6cjs.zExternalId; exports.zOrganization = _chunkLA5F5KR6cjs.zOrganization; exports.zProject = _chunkLA5F5KR6cjs.zProject; exports.zRotateClientSecretResponse = _chunkLA5F5KR6cjs.zRotateClientSecretResponse; exports.zRotateOrganizationKeyResponse = _chunkLA5F5KR6cjs.zRotateOrganizationKeyResponse; exports.zUpdateOrganizationQuotaInput = _chunkLA5F5KR6cjs.zUpdateOrganizationQuotaInput; exports.zUpdateOrganizationQuotaResponse = _chunkLA5F5KR6cjs.zUpdateOrganizationQuotaResponse; exports.zUpsertEventMetaInput = _chunkLA5F5KR6cjs.zUpsertEventMetaInput;
|
|
55
56
|
//# sourceMappingURL=control.cjs.map
|
package/dist/control.cjs.map
CHANGED
|
@@ -1 +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;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;AACA;AACA;AACA;AACA;AACA;AACF,2oDAAC","file":"/Users/eric/reopt-ai/reopt-data/packages/data-contract/dist/control.cjs"}
|
|
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;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,2oDAAC","file":"/Users/eric/reopt-ai/reopt-data/packages/data-contract/dist/control.cjs"}
|
package/dist/control.d.cts
CHANGED
|
@@ -181,27 +181,27 @@ declare const zEventMetaResponse: z.ZodObject<{
|
|
|
181
181
|
type EventMetaResponse = z.infer<typeof zEventMetaResponse>;
|
|
182
182
|
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"];
|
|
183
183
|
declare const zControlErrorCode: z.ZodEnum<{
|
|
184
|
+
validation_failed: "validation_failed";
|
|
184
185
|
unauthorized: "unauthorized";
|
|
186
|
+
rate_limited: "rate_limited";
|
|
187
|
+
internal_error: "internal_error";
|
|
185
188
|
organization_scope_mismatch: "organization_scope_mismatch";
|
|
186
189
|
external_id_conflict: "external_id_conflict";
|
|
187
190
|
project_external_id_mismatch: "project_external_id_mismatch";
|
|
188
191
|
not_found: "not_found";
|
|
189
|
-
validation_failed: "validation_failed";
|
|
190
|
-
rate_limited: "rate_limited";
|
|
191
|
-
internal_error: "internal_error";
|
|
192
192
|
}>;
|
|
193
193
|
type ControlErrorCode = z.infer<typeof zControlErrorCode>;
|
|
194
194
|
declare const zControlError: z.ZodObject<{
|
|
195
195
|
status: z.ZodNumber;
|
|
196
196
|
code: z.ZodEnum<{
|
|
197
|
+
validation_failed: "validation_failed";
|
|
197
198
|
unauthorized: "unauthorized";
|
|
199
|
+
rate_limited: "rate_limited";
|
|
200
|
+
internal_error: "internal_error";
|
|
198
201
|
organization_scope_mismatch: "organization_scope_mismatch";
|
|
199
202
|
external_id_conflict: "external_id_conflict";
|
|
200
203
|
project_external_id_mismatch: "project_external_id_mismatch";
|
|
201
204
|
not_found: "not_found";
|
|
202
|
-
validation_failed: "validation_failed";
|
|
203
|
-
rate_limited: "rate_limited";
|
|
204
|
-
internal_error: "internal_error";
|
|
205
205
|
}>;
|
|
206
206
|
error: z.ZodString;
|
|
207
207
|
message: z.ZodOptional<z.ZodString>;
|
package/dist/control.d.ts
CHANGED
|
@@ -181,27 +181,27 @@ declare const zEventMetaResponse: z.ZodObject<{
|
|
|
181
181
|
type EventMetaResponse = z.infer<typeof zEventMetaResponse>;
|
|
182
182
|
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"];
|
|
183
183
|
declare const zControlErrorCode: z.ZodEnum<{
|
|
184
|
+
validation_failed: "validation_failed";
|
|
184
185
|
unauthorized: "unauthorized";
|
|
186
|
+
rate_limited: "rate_limited";
|
|
187
|
+
internal_error: "internal_error";
|
|
185
188
|
organization_scope_mismatch: "organization_scope_mismatch";
|
|
186
189
|
external_id_conflict: "external_id_conflict";
|
|
187
190
|
project_external_id_mismatch: "project_external_id_mismatch";
|
|
188
191
|
not_found: "not_found";
|
|
189
|
-
validation_failed: "validation_failed";
|
|
190
|
-
rate_limited: "rate_limited";
|
|
191
|
-
internal_error: "internal_error";
|
|
192
192
|
}>;
|
|
193
193
|
type ControlErrorCode = z.infer<typeof zControlErrorCode>;
|
|
194
194
|
declare const zControlError: z.ZodObject<{
|
|
195
195
|
status: z.ZodNumber;
|
|
196
196
|
code: z.ZodEnum<{
|
|
197
|
+
validation_failed: "validation_failed";
|
|
197
198
|
unauthorized: "unauthorized";
|
|
199
|
+
rate_limited: "rate_limited";
|
|
200
|
+
internal_error: "internal_error";
|
|
198
201
|
organization_scope_mismatch: "organization_scope_mismatch";
|
|
199
202
|
external_id_conflict: "external_id_conflict";
|
|
200
203
|
project_external_id_mismatch: "project_external_id_mismatch";
|
|
201
204
|
not_found: "not_found";
|
|
202
|
-
validation_failed: "validation_failed";
|
|
203
|
-
rate_limited: "rate_limited";
|
|
204
|
-
internal_error: "internal_error";
|
|
205
205
|
}>;
|
|
206
206
|
error: z.ZodString;
|
|
207
207
|
message: z.ZodOptional<z.ZodString>;
|
package/dist/control.js
CHANGED
|
@@ -23,9 +23,10 @@ import {
|
|
|
23
23
|
zUpdateOrganizationQuotaInput,
|
|
24
24
|
zUpdateOrganizationQuotaResponse,
|
|
25
25
|
zUpsertEventMetaInput
|
|
26
|
-
} from "./chunk-
|
|
27
|
-
import "./chunk-
|
|
28
|
-
import "./chunk-
|
|
26
|
+
} from "./chunk-IY4MXH35.js";
|
|
27
|
+
import "./chunk-L3WJGIKD.js";
|
|
28
|
+
import "./chunk-33BCA2LH.js";
|
|
29
|
+
import "./chunk-HLQAZ6JW.js";
|
|
29
30
|
export {
|
|
30
31
|
CONTROL_API_PATHS,
|
|
31
32
|
CONTROL_ERROR_CODES,
|
package/dist/events.cjs
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
var _chunk3EEANNYNcjs = require('./chunk-3EEANNYN.cjs');
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
exports.AUTO_EVENT_NAMES = _chunk3EEANNYNcjs.AUTO_EVENT_NAMES; exports.AUTO_EVENT_PROPERTIES = _chunk3EEANNYNcjs.AUTO_EVENT_PROPERTIES; exports.AUTO_EVENT_ROLLUP_KEYS = _chunk3EEANNYNcjs.AUTO_EVENT_ROLLUP_KEYS; exports.RESERVED_EVENT_NAMES = _chunk3EEANNYNcjs.RESERVED_EVENT_NAMES; exports.SCROLL_DEPTH_BUCKETS = _chunk3EEANNYNcjs.SCROLL_DEPTH_BUCKETS; exports.scrollDepthBucket = _chunk3EEANNYNcjs.scrollDepthBucket;
|
|
17
|
+
//# sourceMappingURL=events.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/eric/reopt-ai/reopt-data/packages/data-contract/dist/events.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACF,iaAAC","file":"/Users/eric/reopt-ai/reopt-data/packages/data-contract/dist/events.cjs"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@reopt-ai/data-contract/events` — event names and property keys, with no
|
|
3
|
+
* zod. Browser SDKs import this so their production bundles stay free of
|
|
4
|
+
* schema code; `./ingest` re-exports everything here.
|
|
5
|
+
*/
|
|
6
|
+
/** Event names the pipeline reserves for its own session bookkeeping. */
|
|
7
|
+
declare const RESERVED_EVENT_NAMES: readonly ["session_start", "session_end", "screen_view"];
|
|
8
|
+
/**
|
|
9
|
+
* Events the SDKs emit on their own. One declaration, so a consumer that
|
|
10
|
+
* registers them in its event catalogue (to make them roll up) cannot drift
|
|
11
|
+
* from what the SDK actually sends — a drifted name silently falls back to
|
|
12
|
+
* raw queries, which is slower but not visibly wrong.
|
|
13
|
+
*/
|
|
14
|
+
declare const AUTO_EVENT_NAMES: {
|
|
15
|
+
readonly pageview: "$pageview";
|
|
16
|
+
readonly screenView: "$screen_view";
|
|
17
|
+
readonly pageleave: "$pageleave";
|
|
18
|
+
readonly webVitals: "$web_vitals";
|
|
19
|
+
readonly exception: "$exception";
|
|
20
|
+
};
|
|
21
|
+
type AutoEventName = (typeof AUTO_EVENT_NAMES)[keyof typeof AUTO_EVENT_NAMES];
|
|
22
|
+
/**
|
|
23
|
+
* Property keys each automatic event carries. Consumers derive their
|
|
24
|
+
* breakdown / rollup property lists from here rather than retyping them.
|
|
25
|
+
* `path`, `origin`, `referrer` and `utm_*` are the keys the ingest pipeline
|
|
26
|
+
* reads into session and event columns.
|
|
27
|
+
*/
|
|
28
|
+
declare const AUTO_EVENT_PROPERTIES: {
|
|
29
|
+
readonly $pageview: readonly ["path", "origin", "title", "referrer", "search", "utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"];
|
|
30
|
+
readonly $screen_view: readonly ["screen_name"];
|
|
31
|
+
readonly $pageleave: readonly ["path", "origin", "duration", "scroll_depth", "scroll_depth_bucket"];
|
|
32
|
+
readonly $web_vitals: readonly ["metric_name", "metric_id", "value", "delta", "rating", "navigation_type", "path"];
|
|
33
|
+
readonly $exception: readonly ["$exception_type", "$exception_message", "$exception_stack", "$exception_source", "$exception_handled", "path"];
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* The subset of {@link AUTO_EVENT_PROPERTIES} that is a sensible rollup
|
|
37
|
+
* dimension: low cardinality, categorical. Per-measurement ids and
|
|
38
|
+
* continuous values (`metric_id`, `value`, `delta`, `duration`,
|
|
39
|
+
* `scroll_depth`) are deliberately absent — as dimensions they would make
|
|
40
|
+
* the rollup larger than the raw table it summarises. Derive
|
|
41
|
+
* `rollupProperties` from here, not from the full property list.
|
|
42
|
+
*/
|
|
43
|
+
declare const AUTO_EVENT_ROLLUP_KEYS: {
|
|
44
|
+
readonly $pageview: readonly ["path", "origin", "referrer", "utm_source", "utm_medium", "utm_campaign"];
|
|
45
|
+
readonly $screen_view: readonly ["screen_name"];
|
|
46
|
+
readonly $pageleave: readonly ["path", "origin", "scroll_depth_bucket"];
|
|
47
|
+
readonly $web_vitals: readonly ["metric_name", "rating", "navigation_type", "path"];
|
|
48
|
+
readonly $exception: readonly ["$exception_type", "$exception_source", "$exception_handled", "path"];
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* `$pageleave.scroll_depth` is the exact 0–100 percentage; `scroll_depth_bucket`
|
|
52
|
+
* is the deepest of these thresholds reached, as a string — the value to
|
|
53
|
+
* break down by. `"0"` means the visitor never reached the first threshold.
|
|
54
|
+
*/
|
|
55
|
+
declare const SCROLL_DEPTH_BUCKETS: readonly [25, 50, 75, 100];
|
|
56
|
+
type ScrollDepthBucket = "0" | `${(typeof SCROLL_DEPTH_BUCKETS)[number]}`;
|
|
57
|
+
declare function scrollDepthBucket(depth: number): ScrollDepthBucket;
|
|
58
|
+
|
|
59
|
+
export { AUTO_EVENT_NAMES, AUTO_EVENT_PROPERTIES, AUTO_EVENT_ROLLUP_KEYS, type AutoEventName, RESERVED_EVENT_NAMES, SCROLL_DEPTH_BUCKETS, type ScrollDepthBucket, scrollDepthBucket };
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@reopt-ai/data-contract/events` — event names and property keys, with no
|
|
3
|
+
* zod. Browser SDKs import this so their production bundles stay free of
|
|
4
|
+
* schema code; `./ingest` re-exports everything here.
|
|
5
|
+
*/
|
|
6
|
+
/** Event names the pipeline reserves for its own session bookkeeping. */
|
|
7
|
+
declare const RESERVED_EVENT_NAMES: readonly ["session_start", "session_end", "screen_view"];
|
|
8
|
+
/**
|
|
9
|
+
* Events the SDKs emit on their own. One declaration, so a consumer that
|
|
10
|
+
* registers them in its event catalogue (to make them roll up) cannot drift
|
|
11
|
+
* from what the SDK actually sends — a drifted name silently falls back to
|
|
12
|
+
* raw queries, which is slower but not visibly wrong.
|
|
13
|
+
*/
|
|
14
|
+
declare const AUTO_EVENT_NAMES: {
|
|
15
|
+
readonly pageview: "$pageview";
|
|
16
|
+
readonly screenView: "$screen_view";
|
|
17
|
+
readonly pageleave: "$pageleave";
|
|
18
|
+
readonly webVitals: "$web_vitals";
|
|
19
|
+
readonly exception: "$exception";
|
|
20
|
+
};
|
|
21
|
+
type AutoEventName = (typeof AUTO_EVENT_NAMES)[keyof typeof AUTO_EVENT_NAMES];
|
|
22
|
+
/**
|
|
23
|
+
* Property keys each automatic event carries. Consumers derive their
|
|
24
|
+
* breakdown / rollup property lists from here rather than retyping them.
|
|
25
|
+
* `path`, `origin`, `referrer` and `utm_*` are the keys the ingest pipeline
|
|
26
|
+
* reads into session and event columns.
|
|
27
|
+
*/
|
|
28
|
+
declare const AUTO_EVENT_PROPERTIES: {
|
|
29
|
+
readonly $pageview: readonly ["path", "origin", "title", "referrer", "search", "utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"];
|
|
30
|
+
readonly $screen_view: readonly ["screen_name"];
|
|
31
|
+
readonly $pageleave: readonly ["path", "origin", "duration", "scroll_depth", "scroll_depth_bucket"];
|
|
32
|
+
readonly $web_vitals: readonly ["metric_name", "metric_id", "value", "delta", "rating", "navigation_type", "path"];
|
|
33
|
+
readonly $exception: readonly ["$exception_type", "$exception_message", "$exception_stack", "$exception_source", "$exception_handled", "path"];
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* The subset of {@link AUTO_EVENT_PROPERTIES} that is a sensible rollup
|
|
37
|
+
* dimension: low cardinality, categorical. Per-measurement ids and
|
|
38
|
+
* continuous values (`metric_id`, `value`, `delta`, `duration`,
|
|
39
|
+
* `scroll_depth`) are deliberately absent — as dimensions they would make
|
|
40
|
+
* the rollup larger than the raw table it summarises. Derive
|
|
41
|
+
* `rollupProperties` from here, not from the full property list.
|
|
42
|
+
*/
|
|
43
|
+
declare const AUTO_EVENT_ROLLUP_KEYS: {
|
|
44
|
+
readonly $pageview: readonly ["path", "origin", "referrer", "utm_source", "utm_medium", "utm_campaign"];
|
|
45
|
+
readonly $screen_view: readonly ["screen_name"];
|
|
46
|
+
readonly $pageleave: readonly ["path", "origin", "scroll_depth_bucket"];
|
|
47
|
+
readonly $web_vitals: readonly ["metric_name", "rating", "navigation_type", "path"];
|
|
48
|
+
readonly $exception: readonly ["$exception_type", "$exception_source", "$exception_handled", "path"];
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* `$pageleave.scroll_depth` is the exact 0–100 percentage; `scroll_depth_bucket`
|
|
52
|
+
* is the deepest of these thresholds reached, as a string — the value to
|
|
53
|
+
* break down by. `"0"` means the visitor never reached the first threshold.
|
|
54
|
+
*/
|
|
55
|
+
declare const SCROLL_DEPTH_BUCKETS: readonly [25, 50, 75, 100];
|
|
56
|
+
type ScrollDepthBucket = "0" | `${(typeof SCROLL_DEPTH_BUCKETS)[number]}`;
|
|
57
|
+
declare function scrollDepthBucket(depth: number): ScrollDepthBucket;
|
|
58
|
+
|
|
59
|
+
export { AUTO_EVENT_NAMES, AUTO_EVENT_PROPERTIES, AUTO_EVENT_ROLLUP_KEYS, type AutoEventName, RESERVED_EVENT_NAMES, SCROLL_DEPTH_BUCKETS, type ScrollDepthBucket, scrollDepthBucket };
|
package/dist/events.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AUTO_EVENT_NAMES,
|
|
3
|
+
AUTO_EVENT_PROPERTIES,
|
|
4
|
+
AUTO_EVENT_ROLLUP_KEYS,
|
|
5
|
+
RESERVED_EVENT_NAMES,
|
|
6
|
+
SCROLL_DEPTH_BUCKETS,
|
|
7
|
+
scrollDepthBucket
|
|
8
|
+
} from "./chunk-FP2X3PRK.js";
|
|
9
|
+
export {
|
|
10
|
+
AUTO_EVENT_NAMES,
|
|
11
|
+
AUTO_EVENT_PROPERTIES,
|
|
12
|
+
AUTO_EVENT_ROLLUP_KEYS,
|
|
13
|
+
RESERVED_EVENT_NAMES,
|
|
14
|
+
SCROLL_DEPTH_BUCKETS,
|
|
15
|
+
scrollDepthBucket
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
var _chunkPHPTCLRUcjs = require('./chunk-PHPTCLRU.cjs');
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
var _chunkJB4MJQX7cjs = require('./chunk-JB4MJQX7.cjs');
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
exports.CLIENT_ID_HEADER = _chunkJB4MJQX7cjs.CLIENT_ID_HEADER; exports.CLIENT_SECRET_HEADER = _chunkJB4MJQX7cjs.CLIENT_SECRET_HEADER; exports.CONTRACT_VERSION = _chunkJB4MJQX7cjs.CONTRACT_VERSION; exports.CONTRACT_VERSION_HEADER = _chunkJB4MJQX7cjs.CONTRACT_VERSION_HEADER; exports.COOKIE_MAX_AGE_SECONDS = _chunkPHPTCLRUcjs.COOKIE_MAX_AGE_SECONDS; exports.DEVICE_ID_HEADER = _chunkJB4MJQX7cjs.DEVICE_ID_HEADER; exports.IDENTITY_ID_PATTERN = _chunkPHPTCLRUcjs.IDENTITY_ID_PATTERN; exports.IDENTITY_REQUEST_HEADERS = _chunkPHPTCLRUcjs.IDENTITY_REQUEST_HEADERS; exports.OPT_OUT_CONSENT_CATEGORY = _chunkPHPTCLRUcjs.OPT_OUT_CONSENT_CATEGORY; exports.REQUEST_ID_HEADER = _chunkJB4MJQX7cjs.REQUEST_ID_HEADER; exports.SESSION_HEADER_SEPARATOR = _chunkPHPTCLRUcjs.SESSION_HEADER_SEPARATOR; exports.SESSION_ID_HEADER = _chunkPHPTCLRUcjs.SESSION_ID_HEADER; exports.WRITE_KEY_HEADER = _chunkJB4MJQX7cjs.WRITE_KEY_HEADER; exports.consentCookieName = _chunkPHPTCLRUcjs.consentCookieName; exports.deviceCookieName = _chunkPHPTCLRUcjs.deviceCookieName; exports.formatSessionHeader = _chunkPHPTCLRUcjs.formatSessionHeader; exports.isOptedOut = _chunkPHPTCLRUcjs.isOptedOut; exports.isValidIdentityId = _chunkPHPTCLRUcjs.isValidIdentityId; exports.parseConsentCookie = _chunkPHPTCLRUcjs.parseConsentCookie; exports.parseDeviceCookie = _chunkPHPTCLRUcjs.parseDeviceCookie; exports.parseSessionHeader = _chunkPHPTCLRUcjs.parseSessionHeader; exports.serializeConsentCookie = _chunkPHPTCLRUcjs.serializeConsentCookie; exports.serializeDeviceCookie = _chunkPHPTCLRUcjs.serializeDeviceCookie; exports.signSessionToken = _chunkPHPTCLRUcjs.signSessionToken; exports.verifySessionToken = _chunkPHPTCLRUcjs.verifySessionToken;
|
|
57
|
+
//# sourceMappingURL=identity.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/eric/reopt-ai/reopt-data/packages/data-contract/dist/identity.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,oqDAAC","file":"/Users/eric/reopt-ai/reopt-data/packages/data-contract/dist/identity.cjs"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
export { C as CLIENT_ID_HEADER, a as CLIENT_SECRET_HEADER, b as CONTRACT_VERSION, c as CONTRACT_VERSION_HEADER, D as DEVICE_ID_HEADER, R as REQUEST_ID_HEADER, W as WRITE_KEY_HEADER } from './version-BzeRTpta.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Request header carrying the browser's current session id. The browser SDK
|
|
5
|
+
* adds it to same-origin requests so a server-side `track()` can land in the
|
|
6
|
+
* session the user is actually in; the server SDK forwards it to ingest.
|
|
7
|
+
*
|
|
8
|
+
* Ingest treats it as a *hint*, never as authority — a browser can put any
|
|
9
|
+
* value here.
|
|
10
|
+
*/
|
|
11
|
+
declare const SESSION_ID_HEADER = "reopt-session-id";
|
|
12
|
+
/** Every request header the identity protocol may carry, for CORS allow-lists. */
|
|
13
|
+
declare const IDENTITY_REQUEST_HEADERS: readonly ["reopt-device-id", "reopt-session-id"];
|
|
14
|
+
/**
|
|
15
|
+
* 400 days — the longest lifetime Chrome will honour. Anything longer is
|
|
16
|
+
* silently clamped to this, so asking for more only hides the real expiry.
|
|
17
|
+
*/
|
|
18
|
+
declare const COOKIE_MAX_AGE_SECONDS: number;
|
|
19
|
+
/** Consent category whose refusal means "send nothing at all". */
|
|
20
|
+
declare const OPT_OUT_CONSENT_CATEGORY = "analytics";
|
|
21
|
+
/** `reopt_<writeKey>_device` — device id plus session/profile hints. */
|
|
22
|
+
declare function deviceCookieName(writeKey: string): string;
|
|
23
|
+
/** `reopt_<writeKey>_consent` — per-category consent decisions. */
|
|
24
|
+
declare function consentCookieName(writeKey: string): string;
|
|
25
|
+
/** Everything the device cookie may carry. Only `deviceId` is required. */
|
|
26
|
+
interface DeviceCookieState {
|
|
27
|
+
deviceId: string;
|
|
28
|
+
/** Current session, if the browser has one. */
|
|
29
|
+
sessionId?: string;
|
|
30
|
+
/** Last identified profile. A hint for the server SDK, never trusted by ingest. */
|
|
31
|
+
profileId?: string;
|
|
32
|
+
}
|
|
33
|
+
/** Per-category consent. `false` withdraws, `true` grants, absent = undecided. */
|
|
34
|
+
type ConsentCookieState = Record<string, boolean>;
|
|
35
|
+
/**
|
|
36
|
+
* What the server hands the browser SDK so the first render already agrees
|
|
37
|
+
* with the server about who the visitor is. Plain JSON — it crosses the
|
|
38
|
+
* RSC → client component boundary as a prop.
|
|
39
|
+
*/
|
|
40
|
+
interface ReoptBootstrap {
|
|
41
|
+
/** From the device cookie (seeded by the proxy on first visit). */
|
|
42
|
+
deviceId: string;
|
|
43
|
+
/** Session hint, or `null` when the browser has not started one. */
|
|
44
|
+
sessionId: string | null;
|
|
45
|
+
/** Result of the server's `getProfileId` resolver, or `null`. */
|
|
46
|
+
profileId: string | null;
|
|
47
|
+
consent: ConsentCookieState;
|
|
48
|
+
/** Server clock at render time, so a skewed device clock can be corrected. */
|
|
49
|
+
serverTimeMs: number;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Ids are opaque, but a cookie is attacker-controlled input (a sibling
|
|
53
|
+
* subdomain can set one). The value ends up in an HTTP header, and
|
|
54
|
+
* `Headers.set` throws on anything outside ISO-8859-1 — so a single odd
|
|
55
|
+
* cookie would break every `fetch` the tracing patch touches. Only the URL
|
|
56
|
+
* "unreserved" set is accepted; every id this SDK mints is a UUID.
|
|
57
|
+
*/
|
|
58
|
+
declare const IDENTITY_ID_PATTERN: RegExp;
|
|
59
|
+
declare function isValidIdentityId(value: unknown): value is string;
|
|
60
|
+
/**
|
|
61
|
+
* Reads a device cookie value. Accepts the JSON envelope written by
|
|
62
|
+
* `serializeDeviceCookie` and, for cookies seeded before the envelope existed,
|
|
63
|
+
* a bare device id. Returns `null` for anything else — a malformed cookie is
|
|
64
|
+
* treated as absent, never as an error, so a corrupted value cannot take the
|
|
65
|
+
* page down.
|
|
66
|
+
*/
|
|
67
|
+
declare function parseDeviceCookie(raw: string | null | undefined): DeviceCookieState | null;
|
|
68
|
+
/**
|
|
69
|
+
* Cookie values may not contain `;`, `,` or whitespace, and JSON contains
|
|
70
|
+
* quotes and commas. The envelope is therefore URI-encoded; `parseDeviceCookie`
|
|
71
|
+
* reverses it. Optional fields are omitted rather than written as `null` so
|
|
72
|
+
* the cookie stays as small as the state it carries.
|
|
73
|
+
*/
|
|
74
|
+
declare function serializeDeviceCookie(state: DeviceCookieState): string;
|
|
75
|
+
/**
|
|
76
|
+
* Reads a consent cookie. Only boolean entries survive; anything else in the
|
|
77
|
+
* object is dropped rather than failing the whole cookie, because one odd key
|
|
78
|
+
* must not erase a user's recorded opt-out.
|
|
79
|
+
*/
|
|
80
|
+
declare function parseConsentCookie(raw: string | null | undefined): ConsentCookieState | null;
|
|
81
|
+
declare function serializeConsentCookie(state: ConsentCookieState): string;
|
|
82
|
+
/**
|
|
83
|
+
* "Opted out" means the visitor refused the `analytics` category. An absent
|
|
84
|
+
* cookie or an undecided category is *not* an opt-out — it is the default
|
|
85
|
+
* state of every first visit, and treating it as refusal would make consent
|
|
86
|
+
* banners mandatory for every integration.
|
|
87
|
+
*/
|
|
88
|
+
declare function isOptedOut(consent: ConsentCookieState | null | undefined): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Sessions are assigned by ingest, not by the browser. To let a later request
|
|
91
|
+
* — from the same browser, or from a server acting for it — join that session
|
|
92
|
+
* with authority, ingest hands the browser its session id together with an
|
|
93
|
+
* HMAC over it, and the browser sends both back as `reopt-session-id`. An
|
|
94
|
+
* unsigned or wrongly signed value is a hint at most: ingest falls back to
|
|
95
|
+
* deciding the session from the device, exactly as if the header were absent.
|
|
96
|
+
*
|
|
97
|
+
* The token is `base64url(HMAC-SHA256(secret, sessionId))`. The secret is
|
|
98
|
+
* per project and never leaves the server. WebCrypto only, so this runs in
|
|
99
|
+
* browsers, edge runtimes and Node alike.
|
|
100
|
+
*/
|
|
101
|
+
declare const SESSION_HEADER_SEPARATOR = ".";
|
|
102
|
+
interface SessionCredential {
|
|
103
|
+
id: string;
|
|
104
|
+
token: string;
|
|
105
|
+
}
|
|
106
|
+
/** `<id>.<token>` — what travels in `reopt-session-id`. */
|
|
107
|
+
declare function formatSessionHeader(credential: SessionCredential): string;
|
|
108
|
+
/** Splits a `reopt-session-id` value. `null` unless both parts are well-formed. */
|
|
109
|
+
declare function parseSessionHeader(value: string | null | undefined): SessionCredential | null;
|
|
110
|
+
/** Issues the token for `sessionId`. Server-side only — needs the project secret. */
|
|
111
|
+
declare function signSessionToken(secret: string, sessionId: string): Promise<string>;
|
|
112
|
+
/**
|
|
113
|
+
* Constant-time check of a presented token. Recomputes and compares the
|
|
114
|
+
* digests byte by byte rather than using `subtle.verify` with a decoded
|
|
115
|
+
* token, so a malformed token can never throw its way past the check.
|
|
116
|
+
*/
|
|
117
|
+
declare function verifySessionToken(secret: string, credential: SessionCredential): Promise<boolean>;
|
|
118
|
+
|
|
119
|
+
export { COOKIE_MAX_AGE_SECONDS, type ConsentCookieState, type DeviceCookieState, IDENTITY_ID_PATTERN, IDENTITY_REQUEST_HEADERS, OPT_OUT_CONSENT_CATEGORY, type ReoptBootstrap, SESSION_HEADER_SEPARATOR, SESSION_ID_HEADER, type SessionCredential, consentCookieName, deviceCookieName, formatSessionHeader, isOptedOut, isValidIdentityId, parseConsentCookie, parseDeviceCookie, parseSessionHeader, serializeConsentCookie, serializeDeviceCookie, signSessionToken, verifySessionToken };
|