@genn-inc/cluebase-frontend-sdk 0.0.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/README.md +222 -0
- package/dist/_generated/correlation-attribute-keys.d.ts +2 -0
- package/dist/_generated/correlation-attribute-keys.js +33 -0
- package/dist/_generated/identity-pii-policy.d.ts +38 -0
- package/dist/_generated/identity-pii-policy.js +103 -0
- package/dist/_generated/ingest-privacy-tables.d.ts +120 -0
- package/dist/_generated/ingest-privacy-tables.js +890 -0
- package/dist/_generated/otel-resource-keys.d.ts +21 -0
- package/dist/_generated/otel-resource-keys.js +72 -0
- package/dist/_generated/otel-span-conversion.d.ts +48 -0
- package/dist/_generated/otel-span-conversion.js +69 -0
- package/dist/_generated/parameter-snapshot-leaf.d.ts +11 -0
- package/dist/_generated/parameter-snapshot-leaf.js +37 -0
- package/dist/_generated/sdk-runtime-policy.d.ts +7 -0
- package/dist/_generated/sdk-runtime-policy.js +14 -0
- package/dist/_generated/usage-governor-tables.d.ts +15 -0
- package/dist/_generated/usage-governor-tables.js +44 -0
- package/dist/context/browser-storage.d.ts +15 -0
- package/dist/context/browser-storage.js +38 -0
- package/dist/context/environment.d.ts +37 -0
- package/dist/context/environment.js +229 -0
- package/dist/context/identity.d.ts +16 -0
- package/dist/context/identity.js +139 -0
- package/dist/context/organization.d.ts +16 -0
- package/dist/context/organization.js +60 -0
- package/dist/context/session.d.ts +28 -0
- package/dist/context/session.js +130 -0
- package/dist/context/tab.d.ts +22 -0
- package/dist/context/tab.js +117 -0
- package/dist/context/trace.d.ts +76 -0
- package/dist/context/trace.js +163 -0
- package/dist/exporter/batch.d.ts +94 -0
- package/dist/exporter/batch.js +485 -0
- package/dist/exporter/browser-outbox-records.d.ts +159 -0
- package/dist/exporter/browser-outbox-records.js +341 -0
- package/dist/exporter/browser-outbox.d.ts +112 -0
- package/dist/exporter/browser-outbox.js +876 -0
- package/dist/exporter/client.d.ts +92 -0
- package/dist/exporter/client.js +541 -0
- package/dist/exporter/delivery-response-contract.d.ts +103 -0
- package/dist/exporter/delivery-response-contract.js +147 -0
- package/dist/exporter/delivery-response.d.ts +37 -0
- package/dist/exporter/delivery-response.js +151 -0
- package/dist/exporter/diagnostics.d.ts +42 -0
- package/dist/exporter/diagnostics.js +148 -0
- package/dist/exporter/event-id.d.ts +10 -0
- package/dist/exporter/event-id.js +75 -0
- package/dist/exporter/frontend-resource.d.ts +20 -0
- package/dist/exporter/frontend-resource.js +52 -0
- package/dist/exporter/local-minimization.d.ts +29 -0
- package/dist/exporter/local-minimization.js +87 -0
- package/dist/exporter/observation-source-event-exporter.d.ts +69 -0
- package/dist/exporter/observation-source-event-exporter.js +154 -0
- package/dist/exporter/parameter-snapshot.d.ts +14 -0
- package/dist/exporter/parameter-snapshot.js +215 -0
- package/dist/exporter/path-template.d.ts +1 -0
- package/dist/exporter/path-template.js +67 -0
- package/dist/exporter/raw-event-to-source-signal.d.ts +12 -0
- package/dist/exporter/raw-event-to-source-signal.js +297 -0
- package/dist/exporter/retry.d.ts +8 -0
- package/dist/exporter/retry.js +8 -0
- package/dist/exporter/sanitize.d.ts +30 -0
- package/dist/exporter/sanitize.js +177 -0
- package/dist/exporter/schema-evidence.d.ts +20 -0
- package/dist/exporter/schema-evidence.js +232 -0
- package/dist/exporter/source-event.d.ts +99 -0
- package/dist/exporter/source-event.js +13 -0
- package/dist/exporter/span-to-source-signal.d.ts +8 -0
- package/dist/exporter/span-to-source-signal.js +174 -0
- package/dist/exporter/text-fingerprint.d.ts +9 -0
- package/dist/exporter/text-fingerprint.js +16 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +158 -0
- package/dist/instrumentation/action.d.ts +2 -0
- package/dist/instrumentation/action.js +171 -0
- package/dist/instrumentation/cluebase-authored-attributes.d.ts +4 -0
- package/dist/instrumentation/cluebase-authored-attributes.js +32 -0
- package/dist/instrumentation/common.d.ts +73 -0
- package/dist/instrumentation/common.js +90 -0
- package/dist/instrumentation/dom.d.ts +63 -0
- package/dist/instrumentation/dom.js +640 -0
- package/dist/instrumentation/drag.d.ts +2 -0
- package/dist/instrumentation/drag.js +82 -0
- package/dist/instrumentation/error.d.ts +2 -0
- package/dist/instrumentation/error.js +318 -0
- package/dist/instrumentation/form.d.ts +2 -0
- package/dist/instrumentation/form.js +132 -0
- package/dist/instrumentation/input.d.ts +2 -0
- package/dist/instrumentation/input.js +180 -0
- package/dist/instrumentation/location.d.ts +11 -0
- package/dist/instrumentation/location.js +69 -0
- package/dist/instrumentation/naming-evidence.d.ts +20 -0
- package/dist/instrumentation/naming-evidence.js +11 -0
- package/dist/instrumentation/navigation.d.ts +2 -0
- package/dist/instrumentation/navigation.js +144 -0
- package/dist/instrumentation/network-request.d.ts +103 -0
- package/dist/instrumentation/network-request.js +285 -0
- package/dist/instrumentation/network-span-attributes.d.ts +25 -0
- package/dist/instrumentation/network-span-attributes.js +153 -0
- package/dist/instrumentation/network.d.ts +16 -0
- package/dist/instrumentation/network.js +502 -0
- package/dist/instrumentation/page.d.ts +2 -0
- package/dist/instrumentation/page.js +56 -0
- package/dist/instrumentation/performance.d.ts +2 -0
- package/dist/instrumentation/performance.js +365 -0
- package/dist/integrations/next-router.d.ts +16 -0
- package/dist/integrations/next-router.js +18 -0
- package/dist/integrations/react-router.d.ts +7 -0
- package/dist/integrations/react-router.js +61 -0
- package/dist/internal/internal-log.d.ts +23 -0
- package/dist/internal/internal-log.js +47 -0
- package/dist/internal/metrics.d.ts +10 -0
- package/dist/internal/metrics.js +50 -0
- package/dist/provider/_version.d.ts +1 -0
- package/dist/provider/_version.js +3 -0
- package/dist/provider/config.d.ts +12 -0
- package/dist/provider/config.js +177 -0
- package/dist/provider/constants.d.ts +62 -0
- package/dist/provider/constants.js +118 -0
- package/dist/provider/contracts.d.ts +51 -0
- package/dist/provider/contracts.js +46 -0
- package/dist/provider/privacy-policy-store.d.ts +20 -0
- package/dist/provider/privacy-policy-store.js +56 -0
- package/dist/provider/sampling.d.ts +2 -0
- package/dist/provider/sampling.js +17 -0
- package/dist/provider/sdk-event-pipeline.d.ts +60 -0
- package/dist/provider/sdk-event-pipeline.js +478 -0
- package/dist/provider/sdk-input-normalization.d.ts +7 -0
- package/dist/provider/sdk-input-normalization.js +113 -0
- package/dist/provider/sdk-otel-pipeline.d.ts +14 -0
- package/dist/provider/sdk-otel-pipeline.js +148 -0
- package/dist/provider/sdk-runtime-surfaces.d.ts +49 -0
- package/dist/provider/sdk-runtime-surfaces.js +216 -0
- package/dist/provider/sdk.d.ts +2 -0
- package/dist/provider/sdk.js +614 -0
- package/dist/provider/types.d.ts +323 -0
- package/dist/provider/types.js +1 -0
- package/dist/provider/usage-governor.d.ts +7 -0
- package/dist/provider/usage-governor.js +116 -0
- package/package.json +59 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import type { InternalMetricsSnapshot } from "../internal/metrics.js";
|
|
2
|
+
import type { DiagnosticsSnapshot } from "../exporter/diagnostics.js";
|
|
3
|
+
import type { FrontendEventName, ParameterCaptureMode, SdkCollectionMode } from "./contracts.js";
|
|
4
|
+
export type { FrontendEventCategory, FrontendEventName, FrontendEventStatus, ParameterCaptureMode, SdkCollectionMode, } from "./contracts.js";
|
|
5
|
+
export type CluebaseConsentState = "granted" | "denied" | "unknown";
|
|
6
|
+
/**
|
|
7
|
+
* MVP group taxonomy. Public `cluebase.group(...)` accepts only the customer
|
|
8
|
+
* company concept. `account` / `workspace` are future concepts and are not
|
|
9
|
+
* exposed as MVP group inputs.
|
|
10
|
+
*/
|
|
11
|
+
export type CluebaseGroupType = "organization";
|
|
12
|
+
export type CanonicalJsonValue = string | number | boolean | null | CanonicalJsonValue[] | {
|
|
13
|
+
[key: string]: CanonicalJsonValue;
|
|
14
|
+
};
|
|
15
|
+
export type CluebaseTrackProperties = {
|
|
16
|
+
[propertyName: string]: CanonicalJsonValue;
|
|
17
|
+
};
|
|
18
|
+
export type CluebaseTrackMetrics = {
|
|
19
|
+
[metricName: string]: number;
|
|
20
|
+
};
|
|
21
|
+
export type CanonicalJsonInputValue = CanonicalJsonValue | undefined;
|
|
22
|
+
export type CluebaseGroupTraits = {
|
|
23
|
+
name?: string | null;
|
|
24
|
+
} & {
|
|
25
|
+
[traitName: string]: CanonicalJsonInputValue;
|
|
26
|
+
};
|
|
27
|
+
export type TransportProfile = "standard";
|
|
28
|
+
export type RequestLifecycleOutcome = "completed" | "failed" | "aborted" | "unknown";
|
|
29
|
+
export type DiagnosticCollectionConfig = {
|
|
30
|
+
enabledCollectors?: string[];
|
|
31
|
+
scope?: Record<string, string | number | boolean | null>;
|
|
32
|
+
ttlMs?: number;
|
|
33
|
+
expiresAt?: string;
|
|
34
|
+
budgetWindowMs?: number;
|
|
35
|
+
maxEventsPerWindow?: number;
|
|
36
|
+
sampleRate?: number;
|
|
37
|
+
reason?: string;
|
|
38
|
+
enabledBy?: string;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Public bootstrap options accepted by `cluebase.init`.
|
|
42
|
+
*
|
|
43
|
+
* The SDK derives dev/prod from the `projectKey` prefix. Browser ingest obtains
|
|
44
|
+
* short-lived tokens from `POST <endpoint>/api/v1/ingest/browser-tokens`.
|
|
45
|
+
*/
|
|
46
|
+
export type CluebaseInitOptions = {
|
|
47
|
+
endpoint: string;
|
|
48
|
+
projectKey: string;
|
|
49
|
+
autocapture?: boolean;
|
|
50
|
+
captureNetwork?: boolean;
|
|
51
|
+
captureErrors?: boolean;
|
|
52
|
+
capturePerformance?: boolean;
|
|
53
|
+
network?: {
|
|
54
|
+
tracePropagationOrigins?: string[];
|
|
55
|
+
};
|
|
56
|
+
batch?: {
|
|
57
|
+
enabled?: boolean;
|
|
58
|
+
maxSize?: number;
|
|
59
|
+
flushIntervalMs?: number;
|
|
60
|
+
maxEventBytes?: number;
|
|
61
|
+
maxPayloadBytes?: number;
|
|
62
|
+
};
|
|
63
|
+
privacy?: {
|
|
64
|
+
deniedKeys?: string[];
|
|
65
|
+
};
|
|
66
|
+
sampling?: {
|
|
67
|
+
sessionSampleRate?: number;
|
|
68
|
+
};
|
|
69
|
+
release?: {
|
|
70
|
+
frontendRelease?: string;
|
|
71
|
+
};
|
|
72
|
+
contextTraitsProvider?: () => CluebaseTrackProperties;
|
|
73
|
+
/**
|
|
74
|
+
* Controls how the SDK's internal ``WebTracerProvider`` interacts with
|
|
75
|
+
* the page's global OTel context.
|
|
76
|
+
*
|
|
77
|
+
* - ``"register"`` (default for SDKs initialised on pages without
|
|
78
|
+
* pre-existing OTel): call ``WebTracerProvider#register()`` so any
|
|
79
|
+
* ``trace.getTracer(...)`` call in the page routes through Cluebase's
|
|
80
|
+
* exporter, including Cluebase's own runtime span emissions.
|
|
81
|
+
* - ``"standalone"``: do not register globally. Cluebase's pipeline is
|
|
82
|
+
* private; only spans created via the SDK's own internal tracer
|
|
83
|
+
* reach the exporter. Use this when the host app already manages an
|
|
84
|
+
* OTel TracerProvider (Sentry, Datadog, Honeycomb, etc.) and Cluebase
|
|
85
|
+
* must not hijack it.
|
|
86
|
+
* - ``"detect"`` (recommended): inspect ``trace.getTracerProvider()``;
|
|
87
|
+
* if a non-proxy provider is already installed, behave as
|
|
88
|
+
* ``standalone``; otherwise behave as ``register``.
|
|
89
|
+
*/
|
|
90
|
+
otelProviderMode?: "register" | "standalone" | "detect";
|
|
91
|
+
};
|
|
92
|
+
export type ResolvedCluebaseConfig = {
|
|
93
|
+
endpoint: string;
|
|
94
|
+
originalEndpoint: string;
|
|
95
|
+
localSetupCheckEndpoint: string | null;
|
|
96
|
+
projectKey: string;
|
|
97
|
+
producerId: string;
|
|
98
|
+
transportProfile: TransportProfile;
|
|
99
|
+
autocapture: boolean;
|
|
100
|
+
captureNetwork: boolean;
|
|
101
|
+
captureErrors: boolean;
|
|
102
|
+
capturePerformance: boolean;
|
|
103
|
+
network: {
|
|
104
|
+
tracePropagationOrigins: string[];
|
|
105
|
+
};
|
|
106
|
+
batch: {
|
|
107
|
+
enabled: boolean;
|
|
108
|
+
maxSize: number;
|
|
109
|
+
flushIntervalMs: number;
|
|
110
|
+
maxEventBytes: number;
|
|
111
|
+
maxPayloadBytes: number;
|
|
112
|
+
};
|
|
113
|
+
privacy: {
|
|
114
|
+
deniedKeys: string[];
|
|
115
|
+
};
|
|
116
|
+
sampling: {
|
|
117
|
+
sessionSampleRate: number;
|
|
118
|
+
};
|
|
119
|
+
collection: {
|
|
120
|
+
mode: SdkCollectionMode;
|
|
121
|
+
diagnostic: {
|
|
122
|
+
enabledCollectors: string[];
|
|
123
|
+
scope: Record<string, string | number | boolean | null>;
|
|
124
|
+
ttlMs: number;
|
|
125
|
+
expiresAt: string | null;
|
|
126
|
+
budgetWindowMs: number;
|
|
127
|
+
maxEventsPerWindow: number;
|
|
128
|
+
sampleRate: number;
|
|
129
|
+
reason: string | null;
|
|
130
|
+
enabledBy: string | null;
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
release: {
|
|
134
|
+
frontendRelease: string | null;
|
|
135
|
+
};
|
|
136
|
+
contextTraitsProvider?: () => CluebaseTrackProperties;
|
|
137
|
+
otelProviderMode: "register" | "standalone" | "detect";
|
|
138
|
+
};
|
|
139
|
+
export type CluebaseBrowserSdk = {
|
|
140
|
+
init(options: CluebaseInitOptions): void;
|
|
141
|
+
identify(userId: string, traits?: CluebaseSubjectTraits): void;
|
|
142
|
+
setOrganization(organizationId: string, traits?: CluebaseGroupTraits): void;
|
|
143
|
+
logout(): void;
|
|
144
|
+
reset(): void;
|
|
145
|
+
track(eventName: string, properties?: CluebaseTrackProperties, metrics?: CluebaseTrackMetrics): void;
|
|
146
|
+
setConsent(consent: CluebaseConsentState): void;
|
|
147
|
+
getInternalMetrics(): InternalMetricsSnapshot;
|
|
148
|
+
flush(): Promise<void>;
|
|
149
|
+
close(): Promise<void>;
|
|
150
|
+
getDiagnostics(): DiagnosticsSnapshot;
|
|
151
|
+
};
|
|
152
|
+
export type { CostCapability } from "../_generated/usage-governor-tables.js";
|
|
153
|
+
import type { CostCapability } from "../_generated/usage-governor-tables.js";
|
|
154
|
+
export type LimitKind = "monthly_overage_amount_limit" | "internal_cost_limit" | "internal_limit" | "operator_global_monthly_cost_limit";
|
|
155
|
+
export type ThresholdStage = "info" | "warning" | "urgent" | "reached";
|
|
156
|
+
export type LimitReason = {
|
|
157
|
+
limitKind: LimitKind;
|
|
158
|
+
meterKey: string;
|
|
159
|
+
thresholdStage: ThresholdStage;
|
|
160
|
+
currentValue: number;
|
|
161
|
+
limitValue: number;
|
|
162
|
+
retryAfterAt: string | null;
|
|
163
|
+
};
|
|
164
|
+
export type IngestUsageGovernorFeedback = {
|
|
165
|
+
disabledCapabilities: CostCapability[];
|
|
166
|
+
limitReasons: LimitReason[];
|
|
167
|
+
retryAfterAt: string | null;
|
|
168
|
+
};
|
|
169
|
+
export type ParameterSnapshotLeafType = "string" | "number" | "boolean" | "null" | "object" | "array";
|
|
170
|
+
export type ParameterSnapshotLeaf = {
|
|
171
|
+
type: ParameterSnapshotLeafType;
|
|
172
|
+
value: unknown;
|
|
173
|
+
capture_mode: ParameterCaptureMode;
|
|
174
|
+
truncated_reason?: "max_event_bytes";
|
|
175
|
+
original_size_bytes?: number;
|
|
176
|
+
};
|
|
177
|
+
export type ParameterSnapshotValue = ParameterSnapshotLeaf | ParameterSnapshotValue[] | {
|
|
178
|
+
[key: string]: ParameterSnapshotValue;
|
|
179
|
+
};
|
|
180
|
+
export type SdkIdentityLinkType = "anonymous_to_user" | "user_to_organization" | "logout";
|
|
181
|
+
export type SdkIdentityLinkHint = {
|
|
182
|
+
link_type: SdkIdentityLinkType;
|
|
183
|
+
anonymous_id?: string | null;
|
|
184
|
+
user_id?: string | null;
|
|
185
|
+
organization_id?: string | null;
|
|
186
|
+
};
|
|
187
|
+
export type CluebaseContext = {
|
|
188
|
+
producer_id: string | null;
|
|
189
|
+
anonymous_id: string | null;
|
|
190
|
+
user_id: string | null;
|
|
191
|
+
organization_id?: string | null;
|
|
192
|
+
user_profile: CluebaseSubjectProfile | null;
|
|
193
|
+
session_id: string | null;
|
|
194
|
+
tab_id: string;
|
|
195
|
+
trace_id: string;
|
|
196
|
+
request_id: string;
|
|
197
|
+
request_span_id: string;
|
|
198
|
+
interaction_id: string;
|
|
199
|
+
correlation_id: string | null;
|
|
200
|
+
sdk_collection_mode: SdkCollectionMode;
|
|
201
|
+
frontend_release: string | null;
|
|
202
|
+
locale: string | null;
|
|
203
|
+
country: string | null;
|
|
204
|
+
device_type: string | null;
|
|
205
|
+
browser: string | null;
|
|
206
|
+
os: string | null;
|
|
207
|
+
referrer: string | null;
|
|
208
|
+
browser_family?: string | null;
|
|
209
|
+
browser_major_version?: string | null;
|
|
210
|
+
browser_engine?: string | null;
|
|
211
|
+
os_family?: string | null;
|
|
212
|
+
os_major_version?: string | null;
|
|
213
|
+
timezone?: string | null;
|
|
214
|
+
pointer_type_candidate?: string | null;
|
|
215
|
+
touch_capable?: boolean | null;
|
|
216
|
+
cookies_enabled?: boolean | null;
|
|
217
|
+
local_storage_available?: boolean | null;
|
|
218
|
+
session_storage_available?: boolean | null;
|
|
219
|
+
service_worker_supported?: boolean | null;
|
|
220
|
+
webgl_supported?: boolean | null;
|
|
221
|
+
reduced_motion?: string | null;
|
|
222
|
+
color_scheme?: string | null;
|
|
223
|
+
subject_traits: CluebaseSanitizedTraits;
|
|
224
|
+
organization_traits: CluebaseSanitizedTraits;
|
|
225
|
+
context_traits: CluebaseSanitizedTraits;
|
|
226
|
+
privacy_summary: CluebasePrivacySummary;
|
|
227
|
+
};
|
|
228
|
+
export type SessionContext = {
|
|
229
|
+
sessionId: string | null;
|
|
230
|
+
startedAtMs: number | null;
|
|
231
|
+
lastActivityAtMs: number | null;
|
|
232
|
+
};
|
|
233
|
+
export type CluebaseSanitizedTraits = {
|
|
234
|
+
[traitName: string]: CanonicalJsonValue;
|
|
235
|
+
};
|
|
236
|
+
export type CluebasePrivacySummary = {
|
|
237
|
+
level: "masked";
|
|
238
|
+
masked_value_count: number;
|
|
239
|
+
dropped_field_count: number;
|
|
240
|
+
masked_fields: string[];
|
|
241
|
+
rule_set_version: string | null;
|
|
242
|
+
};
|
|
243
|
+
export type IdentityContext = {
|
|
244
|
+
anonymousId: string | null;
|
|
245
|
+
userId: string | null;
|
|
246
|
+
traits: CluebaseSanitizedTraits;
|
|
247
|
+
};
|
|
248
|
+
export type OrganizationContext = {
|
|
249
|
+
organizationId: string | null;
|
|
250
|
+
traits: CluebaseSanitizedTraits;
|
|
251
|
+
};
|
|
252
|
+
export type CluebaseSubjectProfile = {
|
|
253
|
+
display_name: string | null;
|
|
254
|
+
avatar_url: string | null;
|
|
255
|
+
contact_identity_hash: string | null;
|
|
256
|
+
contact_domain: string | null;
|
|
257
|
+
};
|
|
258
|
+
/**
|
|
259
|
+
* Customer-facing trait dict accepted by `cluebase.identify` /
|
|
260
|
+
* `cluebase.setOrganization`.
|
|
261
|
+
*
|
|
262
|
+
* Customers use the camelCase form on every SDK. The ingest core normalizes
|
|
263
|
+
* these values after receiving the SDK source signal.
|
|
264
|
+
*
|
|
265
|
+
* `displayName`, `email`, and `emailAddress` are accepted alternate keys.
|
|
266
|
+
* Email traits are transported only as privacy-safe contact-derived fields.
|
|
267
|
+
*/
|
|
268
|
+
export type CluebaseSubjectTraits = {
|
|
269
|
+
name?: string | null;
|
|
270
|
+
email?: string | null;
|
|
271
|
+
emailAddress?: string | null;
|
|
272
|
+
displayName?: string | null;
|
|
273
|
+
avatarUrl?: string | null;
|
|
274
|
+
} & {
|
|
275
|
+
[traitName: string]: CanonicalJsonInputValue;
|
|
276
|
+
};
|
|
277
|
+
export type CluebaseLoggerDetails = {
|
|
278
|
+
[detailName: string]: CanonicalJsonValue;
|
|
279
|
+
};
|
|
280
|
+
export type CluebaseInternalLogger = {
|
|
281
|
+
debug: (message: string, details?: CluebaseLoggerDetails) => void;
|
|
282
|
+
warn: (message: string, details?: CluebaseLoggerDetails) => void;
|
|
283
|
+
error: (message: string, details?: CluebaseLoggerDetails) => void;
|
|
284
|
+
};
|
|
285
|
+
export type RawEventName = FrontendEventName;
|
|
286
|
+
export type RawCapturedPayload = {
|
|
287
|
+
[payloadKey: string]: CanonicalJsonValue | undefined;
|
|
288
|
+
};
|
|
289
|
+
export type RawCapturedEvent = {
|
|
290
|
+
type: RawEventName;
|
|
291
|
+
occurredAtMs?: number;
|
|
292
|
+
payload: RawCapturedPayload;
|
|
293
|
+
};
|
|
294
|
+
export type CaptureEventHandler = (event: RawCapturedEvent) => void;
|
|
295
|
+
export type CaptureModuleContext = {
|
|
296
|
+
onEvent: CaptureEventHandler;
|
|
297
|
+
onInternalError: (source: string, error: unknown) => void;
|
|
298
|
+
getViewId: () => string | null;
|
|
299
|
+
getConsent: () => CluebaseConsentState;
|
|
300
|
+
getObservationContext?: () => {
|
|
301
|
+
anonymousId: string | null;
|
|
302
|
+
userId: string | null;
|
|
303
|
+
organizationId?: string | null;
|
|
304
|
+
sessionId: string | null;
|
|
305
|
+
tabId: string | null;
|
|
306
|
+
};
|
|
307
|
+
shouldIgnoreElement?: (element: Element) => boolean;
|
|
308
|
+
startInteraction?: (input: {
|
|
309
|
+
interactionId?: string | null;
|
|
310
|
+
interactionInitiator?: string | null;
|
|
311
|
+
interactionStartEventKind?: string | null;
|
|
312
|
+
targetStableKey?: string | null;
|
|
313
|
+
formKey?: string | null;
|
|
314
|
+
interactionScopeKind?: string | null;
|
|
315
|
+
interactionScopeKey?: string | null;
|
|
316
|
+
nowMs?: number;
|
|
317
|
+
}) => string | null;
|
|
318
|
+
requestFlush?: () => void;
|
|
319
|
+
};
|
|
320
|
+
export type CaptureStopHandle = {
|
|
321
|
+
stop: () => void;
|
|
322
|
+
flush?: (reason: string) => void | Promise<void>;
|
|
323
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CostCapability, IngestUsageGovernorFeedback } from "./types.js";
|
|
2
|
+
export declare const DEFAULT_INGEST_USAGE_GOVERNOR_FEEDBACK: IngestUsageGovernorFeedback;
|
|
3
|
+
export declare const normalizeIngestUsageGovernorFeedback: (feedback?: Partial<IngestUsageGovernorFeedback> | null) => IngestUsageGovernorFeedback;
|
|
4
|
+
export declare const mergeIngestUsageGovernorFeedback: (current: IngestUsageGovernorFeedback | null, incoming: IngestUsageGovernorFeedback | null) => IngestUsageGovernorFeedback | null;
|
|
5
|
+
export declare const parseGovernorFeedbackEnvelope: (value: unknown) => IngestUsageGovernorFeedback | null;
|
|
6
|
+
export declare const isCostCapabilityDisabled: (feedback: Pick<IngestUsageGovernorFeedback, "disabledCapabilities">, capability: CostCapability) => boolean;
|
|
7
|
+
export declare const hasUsageGovernorFeedbackChanged: (current: IngestUsageGovernorFeedback, next: IngestUsageGovernorFeedback) => boolean;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { COST_CAPABILITIES as GENERATED_COST_CAPABILITIES, LIMIT_KINDS as GENERATED_LIMIT_KINDS, THRESHOLD_STAGES as GENERATED_THRESHOLD_STAGES, } from "../_generated/usage-governor-tables.js";
|
|
2
|
+
export const DEFAULT_INGEST_USAGE_GOVERNOR_FEEDBACK = {
|
|
3
|
+
disabledCapabilities: [],
|
|
4
|
+
limitReasons: [],
|
|
5
|
+
retryAfterAt: null,
|
|
6
|
+
};
|
|
7
|
+
// 正本から生成した一覧をそのまま使います。ここへ書き写していたため
|
|
8
|
+
// `replay_storage` が抜け、受付側が「止めよ」と言っても画面側が捨てていました。
|
|
9
|
+
const COST_CAPABILITIES = new Set(GENERATED_COST_CAPABILITIES);
|
|
10
|
+
const LIMIT_KINDS = new Set(GENERATED_LIMIT_KINDS);
|
|
11
|
+
const THRESHOLD_STAGES = new Set(GENERATED_THRESHOLD_STAGES);
|
|
12
|
+
const asObject = (value) => {
|
|
13
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
return null;
|
|
17
|
+
};
|
|
18
|
+
const asCostCapability = (value) => {
|
|
19
|
+
return typeof value === "string" &&
|
|
20
|
+
COST_CAPABILITIES.has(value)
|
|
21
|
+
? value
|
|
22
|
+
: null;
|
|
23
|
+
};
|
|
24
|
+
const asLimitKind = (value) => {
|
|
25
|
+
return typeof value === "string" && LIMIT_KINDS.has(value)
|
|
26
|
+
? value
|
|
27
|
+
: null;
|
|
28
|
+
};
|
|
29
|
+
const asThresholdStage = (value) => {
|
|
30
|
+
return typeof value === "string" &&
|
|
31
|
+
THRESHOLD_STAGES.has(value)
|
|
32
|
+
? value
|
|
33
|
+
: null;
|
|
34
|
+
};
|
|
35
|
+
const asNonNegativeNumber = (value) => {
|
|
36
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0
|
|
37
|
+
? value
|
|
38
|
+
: null;
|
|
39
|
+
};
|
|
40
|
+
const asNullableString = (value) => {
|
|
41
|
+
return typeof value === "string" ? value : null;
|
|
42
|
+
};
|
|
43
|
+
const parseLimitReason = (value) => {
|
|
44
|
+
const record = asObject(value);
|
|
45
|
+
if (!record) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const limitKind = asLimitKind(record.limitKind);
|
|
49
|
+
const thresholdStage = asThresholdStage(record.thresholdStage);
|
|
50
|
+
const currentValue = asNonNegativeNumber(record.currentValue);
|
|
51
|
+
const limitValue = asNonNegativeNumber(record.limitValue);
|
|
52
|
+
const retryAfterAt = record.retryAfterAt === null ? null : asNullableString(record.retryAfterAt);
|
|
53
|
+
if (!limitKind ||
|
|
54
|
+
typeof record.meterKey !== "string" ||
|
|
55
|
+
!thresholdStage ||
|
|
56
|
+
currentValue === null ||
|
|
57
|
+
limitValue === null ||
|
|
58
|
+
retryAfterAt === undefined) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
limitKind,
|
|
63
|
+
meterKey: record.meterKey,
|
|
64
|
+
thresholdStage,
|
|
65
|
+
currentValue,
|
|
66
|
+
limitValue,
|
|
67
|
+
retryAfterAt,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
const uniqueCapabilities = (capabilities) => [...new Set(capabilities)];
|
|
71
|
+
export const normalizeIngestUsageGovernorFeedback = (feedback) => {
|
|
72
|
+
const disabledCapabilities = Array.isArray(feedback?.disabledCapabilities)
|
|
73
|
+
? feedback.disabledCapabilities
|
|
74
|
+
.map(asCostCapability)
|
|
75
|
+
.filter((capability) => capability !== null)
|
|
76
|
+
: [];
|
|
77
|
+
const limitReasons = Array.isArray(feedback?.limitReasons)
|
|
78
|
+
? feedback.limitReasons
|
|
79
|
+
.map(parseLimitReason)
|
|
80
|
+
.filter((reason) => reason !== null)
|
|
81
|
+
: [];
|
|
82
|
+
return {
|
|
83
|
+
disabledCapabilities: uniqueCapabilities(disabledCapabilities),
|
|
84
|
+
limitReasons,
|
|
85
|
+
retryAfterAt: typeof feedback?.retryAfterAt === "string" ? feedback.retryAfterAt : null,
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
export const mergeIngestUsageGovernorFeedback = (current, incoming) => {
|
|
89
|
+
if (!current) {
|
|
90
|
+
return incoming;
|
|
91
|
+
}
|
|
92
|
+
if (!incoming) {
|
|
93
|
+
return current;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
disabledCapabilities: uniqueCapabilities([
|
|
97
|
+
...current.disabledCapabilities,
|
|
98
|
+
...incoming.disabledCapabilities,
|
|
99
|
+
]),
|
|
100
|
+
limitReasons: [...current.limitReasons, ...incoming.limitReasons],
|
|
101
|
+
retryAfterAt: current.retryAfterAt ?? incoming.retryAfterAt,
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
export const parseGovernorFeedbackEnvelope = (value) => {
|
|
105
|
+
const payload = asObject(value);
|
|
106
|
+
const governor = asObject(payload?.governor);
|
|
107
|
+
if (!governor) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
return normalizeIngestUsageGovernorFeedback(governor);
|
|
111
|
+
};
|
|
112
|
+
export const isCostCapabilityDisabled = (feedback, capability) => feedback.disabledCapabilities.includes(capability);
|
|
113
|
+
export const hasUsageGovernorFeedbackChanged = (current, next) => current.retryAfterAt !== next.retryAfterAt ||
|
|
114
|
+
current.disabledCapabilities.join("|") !==
|
|
115
|
+
next.disabledCapabilities.join("|") ||
|
|
116
|
+
JSON.stringify(current.limitReasons) !== JSON.stringify(next.limitReasons);
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@genn-inc/cluebase-frontend-sdk",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/genn-inc/cluebase.git"
|
|
7
|
+
},
|
|
8
|
+
"description": "Cluebase Frontend SDK — OTel-based observation-source event capture for frontend apps",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "dist/index.js",
|
|
11
|
+
"types": "dist/index.d.ts",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist/",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"browser": "./dist/index.js",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "node ./scripts/clean-dist.mjs && node ../../../scripts/generate-shared-contract-tables.mjs && node ./scripts/generate-version-module.mjs && tsc -p tsconfig.build.json && node ./scripts/fix-esm-relative-imports.mjs",
|
|
25
|
+
"prepack": "pnpm build",
|
|
26
|
+
"prepublishOnly": "pnpm lint && pnpm test:cov && pnpm typecheck && pnpm test:package-import",
|
|
27
|
+
"lint": "pnpm exec biome lint src",
|
|
28
|
+
"test:package-import": "pnpm build && node ../../../tests/distribution/frontend-sdk/check-package-import.mjs",
|
|
29
|
+
"typecheck": "tsc -p tsconfig.typecheck.json",
|
|
30
|
+
"_comment_test": "実環境が要る試験 (`*-live.test.ts`) を既定の実行から外します (`tests/README.md` §12.2)。**綴りで拾います** — file 名を並べると、新しい live を足した人がここへ足し忘れて黙ります。**設定側 (`vitest.config.ts`) の `exclude` には置けません**: 実測 (2026-08-21) では、そこへ置くと live を名指しした実行まで `No test files found` で落ちます。script に置けば、手元と CI で対象が同じまま、実環境のあるジョブだけが名指しで拾えます。",
|
|
31
|
+
"test": "vitest run --config ../../../tests/config/vitest/frontend-sdk.config.ts --exclude \"../../../tests/integration/frontend-sdk/**/*-live.test.ts\"",
|
|
32
|
+
"test:cov": "vitest run --config ../../../tests/config/vitest/frontend-sdk.config.ts --coverage --exclude \"../../../tests/integration/frontend-sdk/**/*-live.test.ts\"",
|
|
33
|
+
"_comment_test_live": "実環境がある段だけがここを呼びます。**vitest の位置引数は glob ではなく道筋への部分一致です** — 実測 (2026-08-21): `vitest run \"src/**/*-live.test.ts\"` は `No test files found` で 0 件、`vitest run live.test.ts` は 1 件。綴りを CI ではなくここに置くので、CI 側は script 名を呼ぶだけになります。",
|
|
34
|
+
"test:live": "vitest run --config ../../../tests/config/vitest/frontend-sdk.config.ts ../../../tests/integration/frontend-sdk"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@cluebase/schema": "workspace:*",
|
|
38
|
+
"@cluebase/shared": "workspace:*",
|
|
39
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
40
|
+
"jsdom": "^26.1.0",
|
|
41
|
+
"typescript": "^5.9.3",
|
|
42
|
+
"vitest": "^3.2.7"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@noble/hashes": "1.8.0",
|
|
46
|
+
"@opentelemetry/api": ">=1.9.1 <1.10.0",
|
|
47
|
+
"@opentelemetry/api-logs": ">=0.218.0 <1.0.0",
|
|
48
|
+
"@opentelemetry/browser-instrumentation": ">=0.5.2 <1.0.0",
|
|
49
|
+
"@opentelemetry/core": ">=2.7.1 <3.0.0",
|
|
50
|
+
"@opentelemetry/instrumentation-document-load": ">=0.63.0 <1.0.0",
|
|
51
|
+
"@opentelemetry/instrumentation-fetch": ">=0.218.0 <1.0.0",
|
|
52
|
+
"@opentelemetry/instrumentation-xml-http-request": ">=0.218.0 <1.0.0",
|
|
53
|
+
"@opentelemetry/resources": ">=2.7.1 <3.0.0",
|
|
54
|
+
"@opentelemetry/sdk-trace-base": ">=2.7.1 <3.0.0",
|
|
55
|
+
"@opentelemetry/sdk-trace-web": ">=2.7.1 <3.0.0",
|
|
56
|
+
"json-canonicalize": "2.0.0",
|
|
57
|
+
"zod": "^4.4.3"
|
|
58
|
+
}
|
|
59
|
+
}
|