@layers/client 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +362 -111
- package/dist/{index-BCpCaNor.d.ts → index-DGDLULwp.d.ts} +2 -1
- package/dist/index-DGDLULwp.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{src-CDTj2A6Q.js → src-DQ_-NO-4.js} +3 -2
- package/dist/{src-CDTj2A6Q.js.map → src-DQ_-NO-4.js.map} +1 -1
- package/package.json +2 -2
- package/dist/index-BCpCaNor.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,64 +1,289 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Layers Web SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@layers/client` is the Layers analytics SDK for web browsers. It provides event tracking, screen tracking, user identification, automatic attribution capture (UTM parameters, click IDs, referrer), consent management, and lifecycle-aware event flushing with `sendBeacon` support.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Modern browser with ES module support
|
|
8
|
+
- React 18+ (for React hooks, optional)
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
6
11
|
|
|
7
12
|
```bash
|
|
8
13
|
npm install @layers/client
|
|
9
14
|
# or
|
|
15
|
+
yarn add @layers/client
|
|
16
|
+
# or
|
|
10
17
|
pnpm add @layers/client
|
|
11
18
|
```
|
|
12
19
|
|
|
13
20
|
## Quick Start
|
|
14
21
|
|
|
15
|
-
```
|
|
22
|
+
```typescript
|
|
16
23
|
import { LayersClient } from '@layers/client';
|
|
17
24
|
|
|
18
25
|
const layers = new LayersClient({
|
|
19
|
-
apiKey: 'your-api-key',
|
|
20
26
|
appId: 'your-app-id',
|
|
21
27
|
environment: 'production'
|
|
22
28
|
});
|
|
23
|
-
|
|
24
29
|
await layers.init();
|
|
25
30
|
|
|
26
31
|
// Track events
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// Track screen views
|
|
30
|
-
await layers.screen('home_page');
|
|
32
|
+
layers.track('button_click', { button_name: 'signup' });
|
|
31
33
|
|
|
32
|
-
//
|
|
33
|
-
layers.
|
|
34
|
+
// Track page views
|
|
35
|
+
layers.screen('Home');
|
|
34
36
|
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
+
// Identify users
|
|
38
|
+
layers.setAppUserId('user_123');
|
|
37
39
|
```
|
|
38
40
|
|
|
39
41
|
## Configuration
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
### LayersConfig
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
interface LayersConfig {
|
|
47
|
+
appId: string;
|
|
48
|
+
environment: 'development' | 'staging' | 'production';
|
|
49
|
+
appUserId?: string;
|
|
50
|
+
enableDebug?: boolean;
|
|
51
|
+
baseUrl?: string;
|
|
52
|
+
flushIntervalMs?: number;
|
|
53
|
+
flushThreshold?: number;
|
|
54
|
+
maxQueueSize?: number;
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
| Option | Type | Default | Description |
|
|
59
|
+
| ----------------- | ------------- | ------------------------- | ------------------------------------------------ |
|
|
60
|
+
| `appId` | `string` | _required_ | Your Layers application identifier. |
|
|
61
|
+
| `environment` | `Environment` | _required_ | `'development'`, `'staging'`, or `'production'`. |
|
|
62
|
+
| `appUserId` | `string` | `undefined` | Optional user ID to set at construction time. |
|
|
63
|
+
| `enableDebug` | `boolean` | `false` | Enable verbose console logging. |
|
|
64
|
+
| `baseUrl` | `string` | `"https://in.layers.com"` | Custom ingest API endpoint. |
|
|
65
|
+
| `flushIntervalMs` | `number` | `30000` | Automatic flush interval in milliseconds. |
|
|
66
|
+
| `flushThreshold` | `number` | `10` | Queue size that triggers an automatic flush. |
|
|
67
|
+
| `maxQueueSize` | `number` | `1000` | Maximum events in the queue before dropping. |
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
const layers = new LayersClient({
|
|
71
|
+
appId: 'your-app-id',
|
|
72
|
+
environment: 'development',
|
|
73
|
+
enableDebug: true,
|
|
74
|
+
flushIntervalMs: 15000,
|
|
75
|
+
flushThreshold: 5,
|
|
76
|
+
maxQueueSize: 5000
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Core API
|
|
42
81
|
|
|
43
|
-
|
|
44
|
-
| ----------------- | -------------------------------------------- | ----------------------- | ------------------------------------------ |
|
|
45
|
-
| `apiKey` | `string` | _required_ | API key from the Layers dashboard |
|
|
46
|
-
| `appId` | `string` | _required_ | Application identifier |
|
|
47
|
-
| `environment` | `'development' \| 'staging' \| 'production'` | _required_ | Deployment environment |
|
|
48
|
-
| `appUserId` | `string` | `undefined` | Pre-set user ID at init time |
|
|
49
|
-
| `enableDebug` | `boolean` | `false` | Verbose console logging for all SDK calls |
|
|
50
|
-
| `baseUrl` | `string` | `https://in.layers.com` | Override the ingest endpoint |
|
|
51
|
-
| `flushIntervalMs` | `number` | `30000` | Periodic flush interval (ms) |
|
|
52
|
-
| `flushThreshold` | `number` | `10` | Queue depth that triggers auto-flush |
|
|
53
|
-
| `maxQueueSize` | `number` | `1000` | Max events in queue before dropping oldest |
|
|
82
|
+
### Constructor & Initialization
|
|
54
83
|
|
|
55
|
-
|
|
84
|
+
```typescript
|
|
85
|
+
const layers = new LayersClient(config: LayersConfig);
|
|
86
|
+
await layers.init();
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The constructor creates the SDK instance with localStorage-backed persistence. Calling `init()` detects device info, attaches lifecycle listeners (online/offline, visibility change, beforeunload), captures attribution signals, and fetches remote config.
|
|
90
|
+
|
|
91
|
+
You can call `track()` and `screen()` before `init()` completes -- events are queued.
|
|
56
92
|
|
|
57
|
-
|
|
93
|
+
### Event Tracking
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
track(eventName: string, properties?: EventProperties): void
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Events are batched and flushed automatically. Attribution properties (UTM, click IDs, referrer) from the current session are automatically merged into every event.
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
layers.track('purchase_completed', {
|
|
103
|
+
product_id: 'sku_123',
|
|
104
|
+
price: 9.99,
|
|
105
|
+
currency: 'USD'
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Screen/Page Tracking
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
screen(screenName: string, properties?: EventProperties): void
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Attribution properties are automatically merged.
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
layers.screen('ProductDetail', { product_id: 'sku_123' });
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### User Identity
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// Set or clear the app user ID
|
|
125
|
+
setAppUserId(appUserId: string | undefined): void
|
|
126
|
+
|
|
127
|
+
// Get the current user ID
|
|
128
|
+
getAppUserId(): string | undefined
|
|
129
|
+
|
|
130
|
+
// Deprecated aliases
|
|
131
|
+
setUserId(userId: string): void
|
|
132
|
+
getUserId(): string | undefined
|
|
133
|
+
```
|
|
58
134
|
|
|
59
|
-
|
|
135
|
+
```typescript
|
|
136
|
+
// After login
|
|
137
|
+
layers.setAppUserId('user_123');
|
|
60
138
|
|
|
61
|
-
|
|
139
|
+
// On logout
|
|
140
|
+
layers.setAppUserId(undefined);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### User Properties
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
setUserProperties(properties: UserProperties): void
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
layers.setUserProperties({
|
|
151
|
+
email: 'user@example.com',
|
|
152
|
+
plan: 'premium',
|
|
153
|
+
signup_date: '2024-01-15'
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Consent Management
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
setConsent(consent: ConsentState): void
|
|
161
|
+
getConsentState(): ConsentState
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
interface ConsentState {
|
|
166
|
+
analytics?: boolean;
|
|
167
|
+
advertising?: boolean;
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
// User accepts analytics only
|
|
173
|
+
layers.setConsent({ analytics: true, advertising: false });
|
|
174
|
+
|
|
175
|
+
// Read current state
|
|
176
|
+
const consent = layers.getConsentState();
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Session Management
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
// Get the current session ID
|
|
183
|
+
getSessionId(): string
|
|
184
|
+
|
|
185
|
+
// End the current session and start a new one
|
|
186
|
+
startNewSession(): void
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Device Info
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
setDeviceInfo(deviceInfo: DeviceContext): void
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Override auto-detected device context fields.
|
|
196
|
+
|
|
197
|
+
### Flush & Shutdown
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
// Flush all queued events to the server
|
|
201
|
+
async flush(): Promise<void>
|
|
202
|
+
|
|
203
|
+
// Shut down immediately (no flush, events persisted to localStorage)
|
|
204
|
+
shutdown(): void
|
|
205
|
+
|
|
206
|
+
// Shut down with a final flush (with timeout)
|
|
207
|
+
async shutdownAsync(timeoutMs?: number): Promise<void> // default: 3000ms
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Error Handling
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
on(event: 'error', listener: (error: Error) => void): this
|
|
214
|
+
off(event: 'error', listener: (error: Error) => void): this
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
layers.on('error', (error) => {
|
|
219
|
+
console.error('Layers error:', error.message);
|
|
220
|
+
});
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Attribution
|
|
224
|
+
|
|
225
|
+
The SDK automatically captures and persists attribution signals from the current page URL and referrer.
|
|
226
|
+
|
|
227
|
+
### Captured Signals
|
|
228
|
+
|
|
229
|
+
**Click IDs** (highest priority -- overwrites existing attribution):
|
|
230
|
+
|
|
231
|
+
- `fbclid` (Meta/Facebook)
|
|
232
|
+
- `gclid`, `gbraid`, `wbraid` (Google)
|
|
233
|
+
- `ttclid` (TikTok)
|
|
234
|
+
- `msclkid` (Microsoft/Bing)
|
|
235
|
+
- `rclid` (Reddit)
|
|
236
|
+
|
|
237
|
+
**UTM Parameters**:
|
|
238
|
+
|
|
239
|
+
- `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, `utm_term`
|
|
240
|
+
|
|
241
|
+
**Referrer**:
|
|
242
|
+
|
|
243
|
+
- `document.referrer`
|
|
244
|
+
|
|
245
|
+
### How It Works
|
|
246
|
+
|
|
247
|
+
1. On `init()`, the SDK reads the current URL's query parameters and `document.referrer`.
|
|
248
|
+
2. Attribution data is persisted in `localStorage` with a 30-day TTL.
|
|
249
|
+
3. Click IDs take priority -- a new click ID overwrites the entire stored record.
|
|
250
|
+
4. UTM parameters overwrite on fresh campaign visits, but preserve existing click IDs.
|
|
251
|
+
5. Attribution properties are automatically prefixed with `$attribution_` and merged into every `track()` and `screen()` call.
|
|
252
|
+
|
|
253
|
+
### Manually Reading Attribution
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
import { getAttribution, getAttributionProperties } from '@layers/client';
|
|
257
|
+
|
|
258
|
+
// Get the full stored attribution data (or null if expired/missing)
|
|
259
|
+
const attribution = getAttribution();
|
|
260
|
+
|
|
261
|
+
// Get a flat property bag for merging into events
|
|
262
|
+
const props = getAttributionProperties();
|
|
263
|
+
// { '$attribution_utm_source': 'google', '$attribution_click_id_param': 'gclid', ... }
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### AttributionData Type
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
interface AttributionData {
|
|
270
|
+
click_id_param?: string;
|
|
271
|
+
click_id_value?: string;
|
|
272
|
+
utm_source?: string;
|
|
273
|
+
utm_medium?: string;
|
|
274
|
+
utm_campaign?: string;
|
|
275
|
+
utm_content?: string;
|
|
276
|
+
utm_term?: string;
|
|
277
|
+
referrer_url?: string;
|
|
278
|
+
captured_at: number;
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## React Integration
|
|
283
|
+
|
|
284
|
+
The SDK includes React hooks for idiomatic usage. Import from `@layers/client/react`.
|
|
285
|
+
|
|
286
|
+
### LayersProvider
|
|
62
287
|
|
|
63
288
|
```tsx
|
|
64
289
|
import { LayersProvider } from '@layers/client/react';
|
|
@@ -67,7 +292,6 @@ function App() {
|
|
|
67
292
|
return (
|
|
68
293
|
<LayersProvider
|
|
69
294
|
config={{
|
|
70
|
-
apiKey: 'your-api-key',
|
|
71
295
|
appId: 'your-app-id',
|
|
72
296
|
environment: 'production'
|
|
73
297
|
}}
|
|
@@ -78,73 +302,87 @@ function App() {
|
|
|
78
302
|
}
|
|
79
303
|
```
|
|
80
304
|
|
|
81
|
-
|
|
305
|
+
Initializes the client on mount and shuts it down on unmount.
|
|
82
306
|
|
|
83
|
-
###
|
|
307
|
+
### useLayers
|
|
84
308
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
309
|
+
```typescript
|
|
310
|
+
function useLayers(): LayersClient;
|
|
311
|
+
```
|
|
88
312
|
|
|
89
|
-
Returns
|
|
313
|
+
Returns the `LayersClient` instance. Throws if used outside a `<LayersProvider>`.
|
|
90
314
|
|
|
91
315
|
```tsx
|
|
92
|
-
|
|
316
|
+
function MyComponent() {
|
|
317
|
+
const layers = useLayers();
|
|
318
|
+
layers.track('component_viewed');
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### useTrack
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
function useTrack(): (eventName: string, properties?: EventProperties) => void;
|
|
326
|
+
```
|
|
93
327
|
|
|
328
|
+
Returns a stable, memoized track function.
|
|
329
|
+
|
|
330
|
+
```tsx
|
|
94
331
|
function SignupButton() {
|
|
95
332
|
const track = useTrack();
|
|
96
333
|
|
|
97
|
-
return <button onClick={() => track('signup_click', { source: 'hero' })}>Sign
|
|
334
|
+
return <button onClick={() => track('signup_click', { source: 'hero' })}>Sign Up</button>;
|
|
98
335
|
}
|
|
99
336
|
```
|
|
100
337
|
|
|
101
|
-
|
|
338
|
+
### useScreen
|
|
102
339
|
|
|
103
|
-
|
|
340
|
+
```typescript
|
|
341
|
+
function useScreen(): (screenName: string, properties?: EventProperties) => void;
|
|
342
|
+
```
|
|
104
343
|
|
|
105
|
-
|
|
106
|
-
import { useScreen } from '@layers/client/react';
|
|
107
|
-
import { useEffect } from 'react';
|
|
344
|
+
Returns a stable, memoized screen tracking function.
|
|
108
345
|
|
|
346
|
+
```tsx
|
|
109
347
|
function Dashboard() {
|
|
110
348
|
const screen = useScreen();
|
|
111
349
|
useEffect(() => {
|
|
112
|
-
screen('
|
|
350
|
+
screen('Dashboard');
|
|
113
351
|
}, [screen]);
|
|
114
352
|
|
|
115
|
-
return <div
|
|
353
|
+
return <div>Dashboard</div>;
|
|
116
354
|
}
|
|
117
355
|
```
|
|
118
356
|
|
|
119
|
-
|
|
357
|
+
### useIdentify
|
|
120
358
|
|
|
121
|
-
|
|
359
|
+
```typescript
|
|
360
|
+
function useIdentify(): (userId: string | undefined) => void;
|
|
361
|
+
```
|
|
122
362
|
|
|
123
|
-
|
|
124
|
-
import { useIdentify } from '@layers/client/react';
|
|
363
|
+
Returns a stable, memoized identify function. Pass `undefined` to clear.
|
|
125
364
|
|
|
365
|
+
```tsx
|
|
126
366
|
function LoginForm() {
|
|
127
367
|
const identify = useIdentify();
|
|
128
368
|
|
|
129
|
-
const onLogin = (userId: string) =>
|
|
130
|
-
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
const onLogout = () => {
|
|
134
|
-
identify(undefined);
|
|
135
|
-
};
|
|
369
|
+
const onLogin = (userId: string) => identify(userId);
|
|
370
|
+
const onLogout = () => identify(undefined);
|
|
136
371
|
}
|
|
137
372
|
```
|
|
138
373
|
|
|
139
|
-
|
|
374
|
+
### useConsent
|
|
140
375
|
|
|
141
|
-
|
|
376
|
+
```typescript
|
|
377
|
+
function useConsent(): {
|
|
378
|
+
setConsent: (consent: ConsentState) => void;
|
|
379
|
+
getConsentState: () => ConsentState;
|
|
380
|
+
};
|
|
381
|
+
```
|
|
142
382
|
|
|
143
383
|
```tsx
|
|
144
|
-
import { useConsent } from '@layers/client/react';
|
|
145
|
-
|
|
146
384
|
function ConsentBanner() {
|
|
147
|
-
const { setConsent
|
|
385
|
+
const { setConsent } = useConsent();
|
|
148
386
|
|
|
149
387
|
return (
|
|
150
388
|
<button onClick={() => setConsent({ analytics: true, advertising: false })}>
|
|
@@ -154,71 +392,84 @@ function ConsentBanner() {
|
|
|
154
392
|
}
|
|
155
393
|
```
|
|
156
394
|
|
|
157
|
-
|
|
395
|
+
## Automatic Behaviors
|
|
158
396
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
397
|
+
- **Attribution capture**: UTM parameters, click IDs, and referrer are captured and persisted on init.
|
|
398
|
+
- **Attribution enrichment**: Stored attribution is merged into every `track()` and `screen()` call.
|
|
399
|
+
- **Online/offline detection**: Events are flushed when the browser reconnects.
|
|
400
|
+
- **Visibility change flush**: Events are flushed via `navigator.sendBeacon` when the page is hidden (tab switch, minimize).
|
|
401
|
+
- **Before unload flush**: Events are persisted to `localStorage` on page close.
|
|
402
|
+
- **Periodic flush**: Events are flushed on a timer (configurable).
|
|
403
|
+
- **Remote config**: Server configuration is fetched during init.
|
|
404
|
+
- **Device context**: OS, browser, locale, screen size, and timezone are detected automatically.
|
|
405
|
+
- **Event persistence**: Events are persisted in `localStorage` and rehydrated on page load.
|
|
163
406
|
|
|
164
|
-
|
|
165
|
-
const layers = useLayers();
|
|
166
|
-
// layers.setUserProperties({ plan: 'pro' });
|
|
167
|
-
}
|
|
168
|
-
```
|
|
407
|
+
## SPA (Single Page App) Usage
|
|
169
408
|
|
|
170
|
-
|
|
409
|
+
For single-page apps with client-side routing, call `screen()` on route changes:
|
|
171
410
|
|
|
172
|
-
|
|
411
|
+
```typescript
|
|
412
|
+
// React Router
|
|
413
|
+
import { useLocation } from 'react-router-dom';
|
|
173
414
|
|
|
174
|
-
|
|
175
|
-
const
|
|
415
|
+
function RouteTracker() {
|
|
416
|
+
const location = useLocation();
|
|
417
|
+
const screen = useScreen();
|
|
176
418
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
});
|
|
419
|
+
useEffect(() => {
|
|
420
|
+
screen(location.pathname, { search: location.search });
|
|
421
|
+
}, [location, screen]);
|
|
181
422
|
|
|
182
|
-
|
|
183
|
-
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
184
425
|
```
|
|
185
426
|
|
|
186
|
-
|
|
427
|
+
```typescript
|
|
428
|
+
'use client';
|
|
187
429
|
|
|
188
|
-
|
|
430
|
+
import { usePathname } from 'next/navigation';
|
|
189
431
|
|
|
190
|
-
|
|
432
|
+
function PageTracker() {
|
|
433
|
+
const pathname = usePathname();
|
|
434
|
+
const screen = useScreen();
|
|
191
435
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
436
|
+
useEffect(() => {
|
|
437
|
+
screen(pathname);
|
|
438
|
+
}, [pathname, screen]);
|
|
195
439
|
|
|
196
|
-
|
|
197
|
-
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
198
442
|
```
|
|
199
443
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
444
|
+
## TypeScript Types
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
import type {
|
|
448
|
+
AttributionData,
|
|
449
|
+
BaseEvent,
|
|
450
|
+
ConsentState,
|
|
451
|
+
DeviceContext,
|
|
452
|
+
Environment,
|
|
453
|
+
ErrorListener,
|
|
454
|
+
EventProperties,
|
|
455
|
+
EventsBatchPayload,
|
|
456
|
+
LayersConfig,
|
|
457
|
+
RemoteConfigResponse,
|
|
458
|
+
UserProperties
|
|
459
|
+
} from '@layers/client';
|
|
216
460
|
```
|
|
217
461
|
|
|
218
|
-
##
|
|
462
|
+
## Wire Protocol Types
|
|
219
463
|
|
|
220
|
-
The
|
|
464
|
+
The package also exports TypeScript interfaces for the Layers wire protocol, useful for building custom integrations:
|
|
221
465
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
466
|
+
```typescript
|
|
467
|
+
import type {
|
|
468
|
+
BaseEvent,
|
|
469
|
+
ConsentPayload,
|
|
470
|
+
EventsBatchPayload,
|
|
471
|
+
RemoteConfigResponse,
|
|
472
|
+
SKANPostbackPayload,
|
|
473
|
+
UserPropertiesPayload
|
|
474
|
+
} from '@layers/client';
|
|
475
|
+
```
|
|
@@ -13,6 +13,7 @@ interface DeviceContext {
|
|
|
13
13
|
idfa?: string;
|
|
14
14
|
idfv?: string;
|
|
15
15
|
attStatus?: string;
|
|
16
|
+
timezone?: string;
|
|
16
17
|
}
|
|
17
18
|
interface ConsentState {
|
|
18
19
|
analytics?: boolean | null;
|
|
@@ -301,4 +302,4 @@ declare class LayersClient {
|
|
|
301
302
|
}
|
|
302
303
|
//#endregion
|
|
303
304
|
export { LayersError as _, getAttribution as a, ConsentPayload as c, SKANPostbackPayload as d, UserPropertiesPayload as f, EventProperties as g, Environment as h, AttributionData as i, EventsBatchPayload as l, DeviceContext as m, LayersClient as n, getAttributionProperties as o, ConsentState as p, LayersConfig as r, BaseEvent as s, ErrorListener as t, RemoteConfigResponse as u, UserProperties as v };
|
|
304
|
-
//# sourceMappingURL=index-
|
|
305
|
+
//# sourceMappingURL=index-DGDLULwp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-DGDLULwp.d.ts","names":[],"sources":["../../wasm/src/types.ts","../src/api-types.ts","../src/attribution.ts","../src/index.ts"],"sourcesContent":[],"mappings":";KAGY,WAAA;AAAA,KAEA,QAAA,GAFW,KAAA,GAAA,SAAA,GAAA,cAAA,GAAA,KAAA,GAAA,MAAA,GAAA,SAAA,GAAA,OAAA;UAgBN,aAAA;aACJ;;ECjBI,UAAA,CAAA,EAAS,MAAA;EAqCT,WAAA,CAAA,EAAA,MAAA;EAMA,MAAA,CAAA,EAAA,MAAA;EAQA,WAAA,CAAA,EAAA,MAAc;EAYd,UAAA,CAAA,EAAA,MAAA;EAQH,SAAA,CAAA,EAAA,MAAA;EAMG,IAAA,CAAA,EAAA,MAAA;EAKG,IAAA,CAAA,EAAA,MAAA;EAGH,SAAA,CAAA,EAAA,MAAA;EAAM,QAAA,CAAA,EAAA,MAAA;AAkBvB;UDxEiB,YAAA;;;AErBjB;AAkGA;AAsBA;;;;ACjGA;AAmBA;AAEA;;;;;;;AA2IqB,UH/IJ,eAAA,CG+II;EAKO,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAA;;;;;;;;;;;;;;;;UHlIX,cAAA;;;KAsBL,eAAA;cAkBC,WAAA,SAAoB,KAAA;iBAChB;;oBAGG;;;;UChHH,SAAA;EDAL,KAAA,EAAA,MAAA;EAEA,SAAA,EAAQ,MAAA;EAcH,QAAA,CAAA,EAAA,MAAa;EAeb,MAAA,EAAA,MAAA;EAmBA,WAAA,CAAA,EAAA,MAAe;EAkBf,OAAA,CAAA,EAAA,MAAA;EAsBL,YAAA,CAAA,EAAA,MAAe;EAkBd,UAAA,CAAA,EAAA,MAAY;EACR,WAAA,EAAA,aAAA,GAAA,SAAA,GAAA,YAAA;EAGG,QAAA,EAAA,KAAA,GAAA,SAAA,GAAA,cAAA,GAAA,KAAA,GAAA,MAAA,GAAA,SAAA,GAAA,OAAA;EAJa,UAAA,EAAA,MAAA;EAAK,WAAA,EAAA,MAAA;;;;EC5GrB,MAAA,EAAA,MAAS;EAqCT,UAAA,CAAA,EAAA,MAAA;EAMA,cAAA,CAAA,EAAA,MAAA;EAQA,aAAA,CAAA,EAAA,MAAc;EAYd,QAAA,CAAA,EAAA,MAAA;EAQH,eAAA,CAAA,EAAA,MAAA;EAMG,UAAA,CAAA,EAAA,MAAA;EAKG,UAAA,CAAA,EAAA,MAAA;EAGH,YAAA,CAAA,EAAA,MAAA;EAAM,WAAA,CAAA,EAAA,MAAA;EAkBN,QAAA,CAAA,EAAA,MAAA;;;;EC7FA,UAAA,CAAA,EAAA,YAAe,GAAA,QAAA,GAAA,YAAA,GAAA,gBAAA;EAkGhB,YAAA,CAAA,EAAA,MAAc;EAsBd,iBAAA,CAAA,EAAA,MAAA;eDjGD;;;AEAE,UFIA,kBAAA,CEAF;EAeH,MAAA,EFdF,SEce,EAAA;EAEZ,QAAA,CAAA,EAAA,MAAY;EAgBH,OAAA,EAAA,MAAA;;AA6CkB,UFxEvB,qBAAA,CEwEuB;EAoBE,WAAA,CAAA,EAAA,MAAA;EAeV,OAAA,CAAA,EAAA,MAAA;EAKV,MAAA,EAAA,MAAA;EAsCD,UAAA,EFlJP,MEkJO,CAAA,MAAA,EAAA,OAAA,CAAA;EAKO,SAAA,EAAA,MAAA;;AAwBa,UF3KxB,cAAA,CE2KwB;EA2CV,WAAA,CAAA,EAAA,MAAA;EAQC,OAAA,CAAA,EAAA,MAAA;EAAa,MAAA,EAAA,MAAA;;;;;;;;UFlN5B,oBAAA;;;;;;;;;;;cAQH;;;;;;iBAMG;;;;;oBAKG;;;;;;iBAGH;;;;;;;;;;;;;;;;;;;UAkBA,mBAAA;;;;;;;;;;;;;;;UC7FA,eAAA;EFVL,cAAW,CAAA,EAAA,MAAA;EAEX,cAAQ,CAAA,EAAA,MAAA;EAcH,UAAA,CAAA,EAAA,MAAa;EAeb,UAAA,CAAA,EAAA,MAAY;EAmBZ,YAAA,CAAA,EAAA,MAAe;EAkBf,WAAA,CAAA,EAAA,MAAc;EAsBnB,QAAA,CAAA,EAAA,MAAA;EAkBC,YAAA,CAAA,EAAY,MAAA;EACR,WAAA,EAAA,MAAA;;ACxEjB;AAMA;AAQA;AAYiB,iBC6CD,cAAA,CAAA,CD7CqB,EC6CH,eD7CG,GAAA,IAAA;;;;;AAsBd,iBC6CP,wBAAA,CAAA,CD7CO,EC6CqB,MD7CrB,CAAA,MAAA,EAAA,MAAA,CAAA;;;ADjBN,UGnCA,YAAA,CHmCc;EAsBnB;EAkBC,KAAA,EAAA,MAAA;EACI;EAGG,WAAA,EG3EL,WH2EK;EAJa;EAAK,SAAA,CAAA,EAAA,MAAA;;;;EC5GrB,OAAA,CAAA,EAAA,MAAS;EAqCT;EAMA,eAAA,CAAA,EAAA,MAAqB;EAQrB;EAYA,cAAA,CAAA,EAAA,MAAoB;EAQvB;EAMG,YAAA,CAAA,EAAA,MAAA;;AAQA,KEjCL,aAAA,GFiCK,CAAA,KAAA,EEjCmB,KFiCnB,EAAA,GAAA,IAAA;AAAM,cE/BV,YAAA,CF+BU;EAkBN,QAAA,IAAA;;;;EC7FA,iBAAA,OAAe;EAkGhB,QAAA,cAAc;EAsBd,QAAA,eAAA;;;;ECjGC,WAAA,CAAA,MAAY,EAqCP,YAjCP;EAeH;EAEC,IAAA,CAAA,CAAA,EA6CG,OA7CS,CAAA,IAAA,CAAA;EAgBH;;;;;;EA2HD,KAAA,CAAA,SAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EA9EmB,eA8EnB,CAAA,EAAA,IAAA;EAKO;;;;;;0CA/Dc;;gCAeV;;sBAKV;;;;;;;;;;;;qBAsCD;;4BAKO;;WAKX;;;;;;;qCAmBwB;;;;;;;;+BA2CV;;;;gCAQC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as LayersError, a as getAttribution, c as ConsentPayload, d as SKANPostbackPayload, f as UserPropertiesPayload, g as EventProperties, h as Environment, i as AttributionData, l as EventsBatchPayload, m as DeviceContext, n as LayersClient, o as getAttributionProperties, p as ConsentState, r as LayersConfig, s as BaseEvent, t as ErrorListener, u as RemoteConfigResponse, v as UserProperties } from "./index-
|
|
1
|
+
import { _ as LayersError, a as getAttribution, c as ConsentPayload, d as SKANPostbackPayload, f as UserPropertiesPayload, g as EventProperties, h as Environment, i as AttributionData, l as EventsBatchPayload, m as DeviceContext, n as LayersClient, o as getAttributionProperties, p as ConsentState, r as LayersConfig, s as BaseEvent, t as ErrorListener, u as RemoteConfigResponse, v as UserProperties } from "./index-DGDLULwp.js";
|
|
2
2
|
export { AttributionData, BaseEvent, ConsentPayload, ConsentState, DeviceContext, Environment, ErrorListener, EventProperties, EventsBatchPayload, LayersClient, LayersConfig, LayersError, RemoteConfigResponse, SKANPostbackPayload, UserProperties, UserPropertiesPayload, getAttribution, getAttributionProperties };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { i as getAttributionProperties, n as LayersError, r as getAttribution, t as LayersClient } from "./src-
|
|
1
|
+
import { i as getAttributionProperties, n as LayersError, r as getAttribution, t as LayersClient } from "./src-DQ_-NO-4.js";
|
|
2
2
|
|
|
3
3
|
export { LayersClient, LayersError, getAttribution, getAttributionProperties };
|
package/dist/react.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as EventProperties, n as LayersClient, p as ConsentState, r as LayersConfig } from "./index-
|
|
1
|
+
import { g as EventProperties, n as LayersClient, p as ConsentState, r as LayersConfig } from "./index-DGDLULwp.js";
|
|
2
2
|
import { ReactNode } from "react";
|
|
3
3
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
4
|
|
package/dist/react.js
CHANGED
|
@@ -317,7 +317,8 @@ var LayersClient = class {
|
|
|
317
317
|
appVersion: SDK_VERSION,
|
|
318
318
|
deviceModel: this.detectDeviceModel(),
|
|
319
319
|
locale: this.detectLocale(),
|
|
320
|
-
screenSize: this.detectScreenSize()
|
|
320
|
+
screenSize: this.detectScreenSize(),
|
|
321
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
321
322
|
};
|
|
322
323
|
this.core.setDeviceContext(context);
|
|
323
324
|
}
|
|
@@ -395,4 +396,4 @@ const SDK_VERSION = typeof __LAYERS_CLIENT_VERSION__ !== "undefined" ? __LAYERS_
|
|
|
395
396
|
|
|
396
397
|
//#endregion
|
|
397
398
|
export { getAttributionProperties as i, LayersError$1 as n, getAttribution as r, LayersClient as t };
|
|
398
|
-
//# sourceMappingURL=src-
|
|
399
|
+
//# sourceMappingURL=src-DQ_-NO-4.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src-CDTj2A6Q.js","names":["params: URLSearchParams","clickIdParam: string | undefined","clickIdValue: string | undefined","utms: Partial<Pick<AttributionData, (typeof UTM_PARAMS)[number]>>","data: AttributionData","props: Record<string, string>","context: DeviceContext","SDK_VERSION: string"],"sources":["../src/attribution.ts","../src/index.ts"],"sourcesContent":["const CLICK_ID_PARAMS = [\n 'fbclid',\n 'gclid',\n 'gbraid',\n 'wbraid',\n 'ttclid',\n 'msclkid',\n 'rclid'\n] as const;\nconst UTM_PARAMS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'] as const;\nconst STORAGE_KEY = 'layers_attribution';\nconst TTL_MS = 30 * 24 * 60 * 60 * 1000; // 30 days\n\nexport interface AttributionData {\n click_id_param?: string;\n click_id_value?: string;\n utm_source?: string;\n utm_medium?: string;\n utm_campaign?: string;\n utm_content?: string;\n utm_term?: string;\n referrer_url?: string;\n captured_at: number;\n}\n\n/**\n * Capture attribution signals from the current page URL and referrer.\n * Persists to localStorage with a 30-day TTL. Click IDs take priority:\n * if a new click ID is present, the entire record is overwritten.\n */\nexport function captureAttribution(): void {\n if (typeof window === 'undefined' || typeof localStorage === 'undefined') return;\n\n let params: URLSearchParams;\n try {\n params = new URLSearchParams(window.location.search);\n } catch {\n return;\n }\n\n // Check for click IDs first — any click ID overwrites the stored record\n let clickIdParam: string | undefined;\n let clickIdValue: string | undefined;\n for (const param of CLICK_ID_PARAMS) {\n const value = params.get(param);\n if (value) {\n clickIdParam = param;\n clickIdValue = value;\n break; // first match wins\n }\n }\n\n // Collect UTM params\n const utms: Partial<Pick<AttributionData, (typeof UTM_PARAMS)[number]>> = {};\n let hasUtm = false;\n for (const param of UTM_PARAMS) {\n const value = params.get(param);\n if (value) {\n utms[param] = value;\n hasUtm = true;\n }\n }\n\n const referrer =\n typeof document !== 'undefined' && document.referrer ? document.referrer : undefined;\n\n // Nothing to capture\n if (!clickIdParam && !hasUtm && !referrer) return;\n\n const existing = getAttribution();\n\n // If a new click ID is present, overwrite entirely\n if (clickIdParam) {\n const data: AttributionData = {\n click_id_param: clickIdParam,\n ...(clickIdValue != null && { click_id_value: clickIdValue }),\n ...utms,\n ...(referrer != null && { referrer_url: referrer }),\n captured_at: Date.now()\n };\n writeAttribution(data);\n return;\n }\n\n // If UTMs are present, overwrite (fresh campaign visit)\n if (hasUtm) {\n const data: AttributionData = {\n // Preserve existing click ID if no new one\n ...(existing?.click_id_param != null && { click_id_param: existing.click_id_param }),\n ...(existing?.click_id_value != null && { click_id_value: existing.click_id_value }),\n ...utms,\n ...(referrer != null && { referrer_url: referrer }),\n captured_at: Date.now()\n };\n writeAttribution(data);\n return;\n }\n\n // Only referrer and no existing attribution — store it\n if (!existing) {\n const data: AttributionData = {\n ...(referrer != null && { referrer_url: referrer }),\n captured_at: Date.now()\n };\n writeAttribution(data);\n }\n}\n\n/**\n * Read stored attribution data, returning null if missing or expired.\n */\nexport function getAttribution(): AttributionData | null {\n if (typeof localStorage === 'undefined') return null;\n\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n\n const data: AttributionData = JSON.parse(raw);\n if (Date.now() - data.captured_at > TTL_MS) {\n localStorage.removeItem(STORAGE_KEY);\n return null;\n }\n return data;\n } catch {\n return null;\n }\n}\n\n/**\n * Return a flat property bag suitable for merging into event properties.\n * Keys are prefixed with `$attribution_` to avoid collisions.\n */\nexport function getAttributionProperties(): Record<string, string> {\n const data = getAttribution();\n if (!data) return {};\n\n const props: Record<string, string> = {};\n\n if (data.click_id_param) props['$attribution_click_id_param'] = data.click_id_param;\n if (data.click_id_value) props['$attribution_click_id_value'] = data.click_id_value;\n if (data.utm_source) props['$attribution_utm_source'] = data.utm_source;\n if (data.utm_medium) props['$attribution_utm_medium'] = data.utm_medium;\n if (data.utm_campaign) props['$attribution_utm_campaign'] = data.utm_campaign;\n if (data.utm_content) props['$attribution_utm_content'] = data.utm_content;\n if (data.utm_term) props['$attribution_utm_term'] = data.utm_term;\n if (data.referrer_url) props['$attribution_referrer_url'] = data.referrer_url;\n\n return props;\n}\n\nfunction writeAttribution(data: AttributionData): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(data));\n } catch {\n // localStorage full or unavailable — silently ignore\n }\n}\n","// @layers/client — Web browser SDK.\n// Thin wrapper over @layers/core-wasm. Owns only:\n// - localStorage persistence\n// - window online/offline detection\n// - navigator device info\n// - visibilitychange / beforeunload flush\nimport {\n FetchHttpClient,\n LayersCore,\n LayersError,\n createDefaultPersistence\n} from '@layers/core-wasm';\nimport type {\n ConsentState,\n DeviceContext,\n Environment,\n EventProperties,\n UserProperties\n} from '@layers/core-wasm';\n\nimport { captureAttribution, getAttributionProperties } from './attribution.js';\n\nexport type {\n ConsentState,\n DeviceContext,\n Environment,\n EventProperties,\n UserProperties\n} from '@layers/core-wasm';\n\nexport { LayersError } from '@layers/core-wasm';\n\nexport * from './api-types.js';\nexport type { AttributionData } from './attribution.js';\nexport { getAttribution, getAttributionProperties } from './attribution.js';\n\nexport interface LayersConfig {\n /** Unique application identifier issued by the Layers dashboard. */\n appId: string;\n /** Deployment environment label. @default \"production\" */\n environment: Environment;\n /** Optional user identifier to associate events with from the start. */\n appUserId?: string;\n /** Enable verbose debug logging to the console. @default false */\n enableDebug?: boolean;\n /** Base URL for the Layers ingest API. @default \"https://in.layers.com\" */\n baseUrl?: string;\n /** How often the event queue is flushed, in milliseconds. @default 30000 */\n flushIntervalMs?: number;\n /** Number of queued events that triggers an automatic flush. @default 10 */\n flushThreshold?: number;\n /** Maximum number of events to hold in the queue before dropping. @default 1000 */\n maxQueueSize?: number;\n}\n\nexport type ErrorListener = (error: Error) => void;\n\nexport class LayersClient {\n private core: LayersCore;\n private appUserId: string | undefined;\n private isOnline = true;\n private readonly enableDebug: boolean;\n private readonly baseUrl: string;\n\n // Stored listener references for cleanup on shutdown\n private onlineListener: (() => void) | null = null;\n private offlineListener: (() => void) | null = null;\n private visibilityListener: (() => void) | null = null;\n private beforeUnloadListener: (() => void) | null = null;\n\n // Error listeners\n private readonly errorListeners: Set<ErrorListener> = new Set();\n\n constructor(config: LayersConfig) {\n this.enableDebug = config.enableDebug ?? false;\n this.baseUrl = (config.baseUrl ?? 'https://in.layers.com').replace(/\\/$/, '');\n this.appUserId = config.appUserId;\n\n const persistence = createDefaultPersistence(config.appId);\n const httpClient = new FetchHttpClient();\n\n this.core = LayersCore.init({\n config: {\n appId: config.appId,\n environment: config.environment,\n ...(config.baseUrl != null && { baseUrl: config.baseUrl }),\n ...(config.enableDebug != null && { enableDebug: config.enableDebug }),\n ...(config.flushIntervalMs != null && { flushIntervalMs: config.flushIntervalMs }),\n ...(config.flushThreshold != null && { flushThreshold: config.flushThreshold }),\n ...(config.maxQueueSize != null && { maxQueueSize: config.maxQueueSize }),\n sdkVersion: `client/${SDK_VERSION}`\n },\n httpClient,\n persistence\n });\n\n if (this.appUserId) {\n this.core.identify(this.appUserId);\n }\n }\n\n /** Initialize the client: detects device info, attaches lifecycle listeners, and fetches remote config. */\n async init(): Promise<void> {\n this.initializeDeviceInfo();\n this.setupNetworkListener();\n this.setupLifecycleListeners();\n captureAttribution();\n await this.core.fetchRemoteConfig().catch(() => {\n // Remote config fetch is best-effort\n });\n }\n\n /**\n * Record a custom analytics event with an optional property bag.\n *\n * Events are batched and flushed automatically when the queue reaches\n * `flushThreshold` or the periodic flush timer fires.\n */\n track(eventName: string, properties?: EventProperties): void {\n if (this.enableDebug) {\n console.log(\n `[Layers] track(\"${eventName}\", ${Object.keys(properties ?? {}).length} properties)`\n );\n }\n try {\n const merged = { ...getAttributionProperties(), ...properties };\n this.core.track(eventName, merged, this.appUserId);\n } catch (e) {\n this.emitError(e);\n }\n }\n\n /**\n * Record a screen view event with an optional property bag.\n *\n * Events are batched and flushed automatically when the queue reaches\n * `flushThreshold` or the periodic flush timer fires.\n */\n screen(screenName: string, properties?: EventProperties): void {\n if (this.enableDebug) {\n console.log(\n `[Layers] screen(\"${screenName}\", ${Object.keys(properties ?? {}).length} properties)`\n );\n }\n try {\n const merged = { ...getAttributionProperties(), ...properties };\n this.core.screen(screenName, merged, this.appUserId);\n } catch (e) {\n this.emitError(e);\n }\n }\n\n /** Set or update user-level properties that persist across sessions. */\n setUserProperties(properties: UserProperties): void {\n this.core.setUserProperties(properties);\n }\n\n /** Update the user's consent state for analytics and advertising data collection. */\n setConsent(consent: ConsentState): void {\n this.core.setConsent(consent);\n }\n\n /** Associate all subsequent events with the given user ID, or clear it with `undefined`. */\n setAppUserId(appUserId: string | undefined): void {\n if (this.enableDebug) {\n console.log(`[Layers] setAppUserId(${appUserId ? `\"${appUserId}\"` : 'undefined'})`);\n }\n this.appUserId = appUserId;\n if (appUserId) {\n this.core.identify(appUserId);\n } else {\n this.core.identify('');\n }\n }\n\n /** @deprecated Use setAppUserId instead */\n setUserId(userId: string): void {\n this.setAppUserId(userId);\n }\n\n /** Return the current app user ID, or `undefined` if not set. */\n getAppUserId(): string | undefined {\n return this.appUserId;\n }\n\n /** @deprecated Use getAppUserId instead */\n getUserId(): string | undefined {\n return this.appUserId;\n }\n\n /** Return the current anonymous session ID. */\n getSessionId(): string {\n return this.core.getSessionId();\n }\n\n /** Return the current consent state for analytics and advertising. */\n getConsentState(): ConsentState {\n return this.core.getConsentState();\n }\n\n /** Override device-level context fields (platform, OS, locale, etc.). */\n setDeviceInfo(deviceInfo: DeviceContext): void {\n this.core.setDeviceContext(deviceInfo);\n }\n\n /** Flush all queued events to the server. Falls back to synchronous persistence on failure. */\n async flush(): Promise<void> {\n try {\n await this.core.flushAsync();\n } catch (e) {\n this.emitError(e);\n this.core.flush();\n }\n }\n\n /** Immediately shut down the client, removing all event listeners. Queued events are persisted but not flushed. */\n shutdown(): void {\n this.cleanupListeners();\n this.core.shutdown();\n }\n\n /**\n * Async shutdown: flushes remaining events before shutting down.\n * @param timeoutMs Maximum time to wait for flush (default 3000ms).\n */\n async shutdownAsync(timeoutMs = 3000): Promise<void> {\n this.cleanupListeners();\n try {\n await Promise.race([\n this.core.flushAsync(),\n new Promise<void>((resolve) => setTimeout(resolve, timeoutMs))\n ]);\n } catch {\n // Best effort — proceed with shutdown\n }\n this.core.shutdown();\n }\n\n private cleanupListeners(): void {\n if (typeof window !== 'undefined') {\n if (this.onlineListener) {\n window.removeEventListener('online', this.onlineListener);\n this.onlineListener = null;\n }\n if (this.offlineListener) {\n window.removeEventListener('offline', this.offlineListener);\n this.offlineListener = null;\n }\n if (this.beforeUnloadListener) {\n window.removeEventListener('beforeunload', this.beforeUnloadListener);\n this.beforeUnloadListener = null;\n }\n }\n if (typeof document !== 'undefined' && this.visibilityListener) {\n document.removeEventListener('visibilitychange', this.visibilityListener);\n this.visibilityListener = null;\n }\n }\n\n /** End the current session and start a new one with a fresh session ID. */\n startNewSession(): void {\n this.core.startNewSession();\n }\n\n /**\n * Register an error listener. Errors from track/screen/flush\n * that would otherwise be silently dropped are forwarded here.\n */\n on(event: 'error', listener: ErrorListener): this {\n if (event === 'error') this.errorListeners.add(listener);\n return this;\n }\n\n /**\n * Remove a previously registered error listener.\n */\n off(event: 'error', listener: ErrorListener): this {\n if (event === 'error') this.errorListeners.delete(listener);\n return this;\n }\n\n private emitError(error: unknown): void {\n const err = error instanceof Error ? error : new Error(String(error));\n for (const listener of this.errorListeners) {\n try {\n listener(err);\n } catch {}\n }\n if (this.enableDebug && this.errorListeners.size === 0) {\n console.warn('[Layers]', err.message);\n }\n }\n\n // --- Platform-specific: browser device info ---\n\n private initializeDeviceInfo(): void {\n const context: DeviceContext = {\n platform: 'web',\n osVersion: this.detectOS(),\n appVersion: SDK_VERSION,\n deviceModel: this.detectDeviceModel(),\n locale: this.detectLocale(),\n screenSize: this.detectScreenSize()\n };\n this.core.setDeviceContext(context);\n }\n\n private detectOS(): string {\n if (typeof navigator === 'undefined') return 'unknown';\n const ua = navigator.userAgent;\n if (ua.includes('Windows')) return 'Windows';\n if (ua.includes('Mac OS')) return 'macOS';\n if (ua.includes('Linux')) return 'Linux';\n if (ua.includes('Android')) return 'Android';\n if (ua.includes('iPhone') || ua.includes('iPad')) return 'iOS';\n return 'unknown';\n }\n\n private detectDeviceModel(): string {\n if (typeof navigator === 'undefined') return 'unknown';\n if ('userAgentData' in navigator) {\n const uaData = (navigator as { userAgentData?: { platform?: string } }).userAgentData;\n if (uaData?.platform) return uaData.platform;\n }\n return navigator.platform ?? 'unknown';\n }\n\n private detectLocale(): string {\n if (typeof navigator === 'undefined') return 'en-US';\n return navigator.language ?? 'en-US';\n }\n\n private detectScreenSize(): string {\n if (typeof window === 'undefined' || typeof screen === 'undefined') return 'unknown';\n return `${screen.width}x${screen.height}`;\n }\n\n // --- Platform-specific: network listener ---\n\n private setupNetworkListener(): void {\n if (typeof window === 'undefined') return;\n\n this.isOnline = navigator?.onLine ?? true;\n\n this.onlineListener = () => {\n this.isOnline = true;\n void this.core.flushAsync().catch(() => {});\n };\n this.offlineListener = () => {\n this.isOnline = false;\n };\n\n window.addEventListener('online', this.onlineListener);\n window.addEventListener('offline', this.offlineListener);\n }\n\n // --- Platform-specific: lifecycle listeners ---\n\n private getBeaconUrl(): string {\n return `${this.baseUrl}/events`;\n }\n\n private setupLifecycleListeners(): void {\n if (typeof window === 'undefined' || typeof document === 'undefined') return;\n\n // Flush on page hide / visibility change.\n // Use sendBeacon for best-effort network delivery before the page is hidden.\n // Falls back to synchronous localStorage persistence if sendBeacon fails.\n this.visibilityListener = () => {\n if (document.visibilityState === 'hidden') {\n if (\n typeof navigator !== 'undefined' &&\n navigator.sendBeacon &&\n this.core.queueDepth() > 0\n ) {\n try {\n const batch = this.core.createBeaconPayload();\n if (batch) {\n const sent = navigator.sendBeacon(this.getBeaconUrl(), batch);\n if (sent) {\n this.core.clearBeaconEvents();\n return;\n }\n // sendBeacon failed — requeue events before falling back to persistence\n this.core.requeueBeaconEvents();\n this.core.flush();\n return;\n }\n } catch {\n // sendBeacon threw — requeue any drained events before sync flush\n this.core.requeueBeaconEvents();\n }\n }\n this.core.flush();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityListener);\n\n // Flush on beforeunload — synchronous persistence as last resort\n this.beforeUnloadListener = () => {\n this.core.flush();\n };\n window.addEventListener('beforeunload', this.beforeUnloadListener);\n }\n}\n\n// SDK version injected at build time by tsdown define\ndeclare const __LAYERS_CLIENT_VERSION__: string;\nconst SDK_VERSION: string =\n typeof __LAYERS_CLIENT_VERSION__ !== 'undefined' ? __LAYERS_CLIENT_VERSION__ : '0.1.1-alpha.1';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"src-DQ_-NO-4.js","names":["params: URLSearchParams","clickIdParam: string | undefined","clickIdValue: string | undefined","utms: Partial<Pick<AttributionData, (typeof UTM_PARAMS)[number]>>","data: AttributionData","props: Record<string, string>","context: DeviceContext","SDK_VERSION: string"],"sources":["../src/attribution.ts","../src/index.ts"],"sourcesContent":["const CLICK_ID_PARAMS = [\n 'fbclid',\n 'gclid',\n 'gbraid',\n 'wbraid',\n 'ttclid',\n 'msclkid',\n 'rclid'\n] as const;\nconst UTM_PARAMS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'] as const;\nconst STORAGE_KEY = 'layers_attribution';\nconst TTL_MS = 30 * 24 * 60 * 60 * 1000; // 30 days\n\nexport interface AttributionData {\n click_id_param?: string;\n click_id_value?: string;\n utm_source?: string;\n utm_medium?: string;\n utm_campaign?: string;\n utm_content?: string;\n utm_term?: string;\n referrer_url?: string;\n captured_at: number;\n}\n\n/**\n * Capture attribution signals from the current page URL and referrer.\n * Persists to localStorage with a 30-day TTL. Click IDs take priority:\n * if a new click ID is present, the entire record is overwritten.\n */\nexport function captureAttribution(): void {\n if (typeof window === 'undefined' || typeof localStorage === 'undefined') return;\n\n let params: URLSearchParams;\n try {\n params = new URLSearchParams(window.location.search);\n } catch {\n return;\n }\n\n // Check for click IDs first — any click ID overwrites the stored record\n let clickIdParam: string | undefined;\n let clickIdValue: string | undefined;\n for (const param of CLICK_ID_PARAMS) {\n const value = params.get(param);\n if (value) {\n clickIdParam = param;\n clickIdValue = value;\n break; // first match wins\n }\n }\n\n // Collect UTM params\n const utms: Partial<Pick<AttributionData, (typeof UTM_PARAMS)[number]>> = {};\n let hasUtm = false;\n for (const param of UTM_PARAMS) {\n const value = params.get(param);\n if (value) {\n utms[param] = value;\n hasUtm = true;\n }\n }\n\n const referrer =\n typeof document !== 'undefined' && document.referrer ? document.referrer : undefined;\n\n // Nothing to capture\n if (!clickIdParam && !hasUtm && !referrer) return;\n\n const existing = getAttribution();\n\n // If a new click ID is present, overwrite entirely\n if (clickIdParam) {\n const data: AttributionData = {\n click_id_param: clickIdParam,\n ...(clickIdValue != null && { click_id_value: clickIdValue }),\n ...utms,\n ...(referrer != null && { referrer_url: referrer }),\n captured_at: Date.now()\n };\n writeAttribution(data);\n return;\n }\n\n // If UTMs are present, overwrite (fresh campaign visit)\n if (hasUtm) {\n const data: AttributionData = {\n // Preserve existing click ID if no new one\n ...(existing?.click_id_param != null && { click_id_param: existing.click_id_param }),\n ...(existing?.click_id_value != null && { click_id_value: existing.click_id_value }),\n ...utms,\n ...(referrer != null && { referrer_url: referrer }),\n captured_at: Date.now()\n };\n writeAttribution(data);\n return;\n }\n\n // Only referrer and no existing attribution — store it\n if (!existing) {\n const data: AttributionData = {\n ...(referrer != null && { referrer_url: referrer }),\n captured_at: Date.now()\n };\n writeAttribution(data);\n }\n}\n\n/**\n * Read stored attribution data, returning null if missing or expired.\n */\nexport function getAttribution(): AttributionData | null {\n if (typeof localStorage === 'undefined') return null;\n\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n\n const data: AttributionData = JSON.parse(raw);\n if (Date.now() - data.captured_at > TTL_MS) {\n localStorage.removeItem(STORAGE_KEY);\n return null;\n }\n return data;\n } catch {\n return null;\n }\n}\n\n/**\n * Return a flat property bag suitable for merging into event properties.\n * Keys are prefixed with `$attribution_` to avoid collisions.\n */\nexport function getAttributionProperties(): Record<string, string> {\n const data = getAttribution();\n if (!data) return {};\n\n const props: Record<string, string> = {};\n\n if (data.click_id_param) props['$attribution_click_id_param'] = data.click_id_param;\n if (data.click_id_value) props['$attribution_click_id_value'] = data.click_id_value;\n if (data.utm_source) props['$attribution_utm_source'] = data.utm_source;\n if (data.utm_medium) props['$attribution_utm_medium'] = data.utm_medium;\n if (data.utm_campaign) props['$attribution_utm_campaign'] = data.utm_campaign;\n if (data.utm_content) props['$attribution_utm_content'] = data.utm_content;\n if (data.utm_term) props['$attribution_utm_term'] = data.utm_term;\n if (data.referrer_url) props['$attribution_referrer_url'] = data.referrer_url;\n\n return props;\n}\n\nfunction writeAttribution(data: AttributionData): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(data));\n } catch {\n // localStorage full or unavailable — silently ignore\n }\n}\n","// @layers/client — Web browser SDK.\n// Thin wrapper over @layers/core-wasm. Owns only:\n// - localStorage persistence\n// - window online/offline detection\n// - navigator device info\n// - visibilitychange / beforeunload flush\nimport {\n FetchHttpClient,\n LayersCore,\n LayersError,\n createDefaultPersistence\n} from '@layers/core-wasm';\nimport type {\n ConsentState,\n DeviceContext,\n Environment,\n EventProperties,\n UserProperties\n} from '@layers/core-wasm';\n\nimport { captureAttribution, getAttributionProperties } from './attribution.js';\n\nexport type {\n ConsentState,\n DeviceContext,\n Environment,\n EventProperties,\n UserProperties\n} from '@layers/core-wasm';\n\nexport { LayersError } from '@layers/core-wasm';\n\nexport * from './api-types.js';\nexport type { AttributionData } from './attribution.js';\nexport { getAttribution, getAttributionProperties } from './attribution.js';\n\nexport interface LayersConfig {\n /** Unique application identifier issued by the Layers dashboard. */\n appId: string;\n /** Deployment environment label. @default \"production\" */\n environment: Environment;\n /** Optional user identifier to associate events with from the start. */\n appUserId?: string;\n /** Enable verbose debug logging to the console. @default false */\n enableDebug?: boolean;\n /** Base URL for the Layers ingest API. @default \"https://in.layers.com\" */\n baseUrl?: string;\n /** How often the event queue is flushed, in milliseconds. @default 30000 */\n flushIntervalMs?: number;\n /** Number of queued events that triggers an automatic flush. @default 10 */\n flushThreshold?: number;\n /** Maximum number of events to hold in the queue before dropping. @default 1000 */\n maxQueueSize?: number;\n}\n\nexport type ErrorListener = (error: Error) => void;\n\nexport class LayersClient {\n private core: LayersCore;\n private appUserId: string | undefined;\n private isOnline = true;\n private readonly enableDebug: boolean;\n private readonly baseUrl: string;\n\n // Stored listener references for cleanup on shutdown\n private onlineListener: (() => void) | null = null;\n private offlineListener: (() => void) | null = null;\n private visibilityListener: (() => void) | null = null;\n private beforeUnloadListener: (() => void) | null = null;\n\n // Error listeners\n private readonly errorListeners: Set<ErrorListener> = new Set();\n\n constructor(config: LayersConfig) {\n this.enableDebug = config.enableDebug ?? false;\n this.baseUrl = (config.baseUrl ?? 'https://in.layers.com').replace(/\\/$/, '');\n this.appUserId = config.appUserId;\n\n const persistence = createDefaultPersistence(config.appId);\n const httpClient = new FetchHttpClient();\n\n this.core = LayersCore.init({\n config: {\n appId: config.appId,\n environment: config.environment,\n ...(config.baseUrl != null && { baseUrl: config.baseUrl }),\n ...(config.enableDebug != null && { enableDebug: config.enableDebug }),\n ...(config.flushIntervalMs != null && { flushIntervalMs: config.flushIntervalMs }),\n ...(config.flushThreshold != null && { flushThreshold: config.flushThreshold }),\n ...(config.maxQueueSize != null && { maxQueueSize: config.maxQueueSize }),\n sdkVersion: `client/${SDK_VERSION}`\n },\n httpClient,\n persistence\n });\n\n if (this.appUserId) {\n this.core.identify(this.appUserId);\n }\n }\n\n /** Initialize the client: detects device info, attaches lifecycle listeners, and fetches remote config. */\n async init(): Promise<void> {\n this.initializeDeviceInfo();\n this.setupNetworkListener();\n this.setupLifecycleListeners();\n captureAttribution();\n await this.core.fetchRemoteConfig().catch(() => {\n // Remote config fetch is best-effort\n });\n }\n\n /**\n * Record a custom analytics event with an optional property bag.\n *\n * Events are batched and flushed automatically when the queue reaches\n * `flushThreshold` or the periodic flush timer fires.\n */\n track(eventName: string, properties?: EventProperties): void {\n if (this.enableDebug) {\n console.log(\n `[Layers] track(\"${eventName}\", ${Object.keys(properties ?? {}).length} properties)`\n );\n }\n try {\n const merged = { ...getAttributionProperties(), ...properties };\n this.core.track(eventName, merged, this.appUserId);\n } catch (e) {\n this.emitError(e);\n }\n }\n\n /**\n * Record a screen view event with an optional property bag.\n *\n * Events are batched and flushed automatically when the queue reaches\n * `flushThreshold` or the periodic flush timer fires.\n */\n screen(screenName: string, properties?: EventProperties): void {\n if (this.enableDebug) {\n console.log(\n `[Layers] screen(\"${screenName}\", ${Object.keys(properties ?? {}).length} properties)`\n );\n }\n try {\n const merged = { ...getAttributionProperties(), ...properties };\n this.core.screen(screenName, merged, this.appUserId);\n } catch (e) {\n this.emitError(e);\n }\n }\n\n /** Set or update user-level properties that persist across sessions. */\n setUserProperties(properties: UserProperties): void {\n this.core.setUserProperties(properties);\n }\n\n /** Update the user's consent state for analytics and advertising data collection. */\n setConsent(consent: ConsentState): void {\n this.core.setConsent(consent);\n }\n\n /** Associate all subsequent events with the given user ID, or clear it with `undefined`. */\n setAppUserId(appUserId: string | undefined): void {\n if (this.enableDebug) {\n console.log(`[Layers] setAppUserId(${appUserId ? `\"${appUserId}\"` : 'undefined'})`);\n }\n this.appUserId = appUserId;\n if (appUserId) {\n this.core.identify(appUserId);\n } else {\n this.core.identify('');\n }\n }\n\n /** @deprecated Use setAppUserId instead */\n setUserId(userId: string): void {\n this.setAppUserId(userId);\n }\n\n /** Return the current app user ID, or `undefined` if not set. */\n getAppUserId(): string | undefined {\n return this.appUserId;\n }\n\n /** @deprecated Use getAppUserId instead */\n getUserId(): string | undefined {\n return this.appUserId;\n }\n\n /** Return the current anonymous session ID. */\n getSessionId(): string {\n return this.core.getSessionId();\n }\n\n /** Return the current consent state for analytics and advertising. */\n getConsentState(): ConsentState {\n return this.core.getConsentState();\n }\n\n /** Override device-level context fields (platform, OS, locale, etc.). */\n setDeviceInfo(deviceInfo: DeviceContext): void {\n this.core.setDeviceContext(deviceInfo);\n }\n\n /** Flush all queued events to the server. Falls back to synchronous persistence on failure. */\n async flush(): Promise<void> {\n try {\n await this.core.flushAsync();\n } catch (e) {\n this.emitError(e);\n this.core.flush();\n }\n }\n\n /** Immediately shut down the client, removing all event listeners. Queued events are persisted but not flushed. */\n shutdown(): void {\n this.cleanupListeners();\n this.core.shutdown();\n }\n\n /**\n * Async shutdown: flushes remaining events before shutting down.\n * @param timeoutMs Maximum time to wait for flush (default 3000ms).\n */\n async shutdownAsync(timeoutMs = 3000): Promise<void> {\n this.cleanupListeners();\n try {\n await Promise.race([\n this.core.flushAsync(),\n new Promise<void>((resolve) => setTimeout(resolve, timeoutMs))\n ]);\n } catch {\n // Best effort — proceed with shutdown\n }\n this.core.shutdown();\n }\n\n private cleanupListeners(): void {\n if (typeof window !== 'undefined') {\n if (this.onlineListener) {\n window.removeEventListener('online', this.onlineListener);\n this.onlineListener = null;\n }\n if (this.offlineListener) {\n window.removeEventListener('offline', this.offlineListener);\n this.offlineListener = null;\n }\n if (this.beforeUnloadListener) {\n window.removeEventListener('beforeunload', this.beforeUnloadListener);\n this.beforeUnloadListener = null;\n }\n }\n if (typeof document !== 'undefined' && this.visibilityListener) {\n document.removeEventListener('visibilitychange', this.visibilityListener);\n this.visibilityListener = null;\n }\n }\n\n /** End the current session and start a new one with a fresh session ID. */\n startNewSession(): void {\n this.core.startNewSession();\n }\n\n /**\n * Register an error listener. Errors from track/screen/flush\n * that would otherwise be silently dropped are forwarded here.\n */\n on(event: 'error', listener: ErrorListener): this {\n if (event === 'error') this.errorListeners.add(listener);\n return this;\n }\n\n /**\n * Remove a previously registered error listener.\n */\n off(event: 'error', listener: ErrorListener): this {\n if (event === 'error') this.errorListeners.delete(listener);\n return this;\n }\n\n private emitError(error: unknown): void {\n const err = error instanceof Error ? error : new Error(String(error));\n for (const listener of this.errorListeners) {\n try {\n listener(err);\n } catch {}\n }\n if (this.enableDebug && this.errorListeners.size === 0) {\n console.warn('[Layers]', err.message);\n }\n }\n\n // --- Platform-specific: browser device info ---\n\n private initializeDeviceInfo(): void {\n const context: DeviceContext = {\n platform: 'web',\n osVersion: this.detectOS(),\n appVersion: SDK_VERSION,\n deviceModel: this.detectDeviceModel(),\n locale: this.detectLocale(),\n screenSize: this.detectScreenSize(),\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone\n };\n this.core.setDeviceContext(context);\n }\n\n private detectOS(): string {\n if (typeof navigator === 'undefined') return 'unknown';\n const ua = navigator.userAgent;\n if (ua.includes('Windows')) return 'Windows';\n if (ua.includes('Mac OS')) return 'macOS';\n if (ua.includes('Linux')) return 'Linux';\n if (ua.includes('Android')) return 'Android';\n if (ua.includes('iPhone') || ua.includes('iPad')) return 'iOS';\n return 'unknown';\n }\n\n private detectDeviceModel(): string {\n if (typeof navigator === 'undefined') return 'unknown';\n if ('userAgentData' in navigator) {\n const uaData = (navigator as { userAgentData?: { platform?: string } }).userAgentData;\n if (uaData?.platform) return uaData.platform;\n }\n return navigator.platform ?? 'unknown';\n }\n\n private detectLocale(): string {\n if (typeof navigator === 'undefined') return 'en-US';\n return navigator.language ?? 'en-US';\n }\n\n private detectScreenSize(): string {\n if (typeof window === 'undefined' || typeof screen === 'undefined') return 'unknown';\n return `${screen.width}x${screen.height}`;\n }\n\n // --- Platform-specific: network listener ---\n\n private setupNetworkListener(): void {\n if (typeof window === 'undefined') return;\n\n this.isOnline = navigator?.onLine ?? true;\n\n this.onlineListener = () => {\n this.isOnline = true;\n void this.core.flushAsync().catch(() => {});\n };\n this.offlineListener = () => {\n this.isOnline = false;\n };\n\n window.addEventListener('online', this.onlineListener);\n window.addEventListener('offline', this.offlineListener);\n }\n\n // --- Platform-specific: lifecycle listeners ---\n\n private getBeaconUrl(): string {\n return `${this.baseUrl}/events`;\n }\n\n private setupLifecycleListeners(): void {\n if (typeof window === 'undefined' || typeof document === 'undefined') return;\n\n // Flush on page hide / visibility change.\n // Use sendBeacon for best-effort network delivery before the page is hidden.\n // Falls back to synchronous localStorage persistence if sendBeacon fails.\n this.visibilityListener = () => {\n if (document.visibilityState === 'hidden') {\n if (\n typeof navigator !== 'undefined' &&\n navigator.sendBeacon &&\n this.core.queueDepth() > 0\n ) {\n try {\n const batch = this.core.createBeaconPayload();\n if (batch) {\n const sent = navigator.sendBeacon(this.getBeaconUrl(), batch);\n if (sent) {\n this.core.clearBeaconEvents();\n return;\n }\n // sendBeacon failed — requeue events before falling back to persistence\n this.core.requeueBeaconEvents();\n this.core.flush();\n return;\n }\n } catch {\n // sendBeacon threw — requeue any drained events before sync flush\n this.core.requeueBeaconEvents();\n }\n }\n this.core.flush();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityListener);\n\n // Flush on beforeunload — synchronous persistence as last resort\n this.beforeUnloadListener = () => {\n this.core.flush();\n };\n window.addEventListener('beforeunload', this.beforeUnloadListener);\n }\n}\n\n// SDK version injected at build time by tsdown define\ndeclare const __LAYERS_CLIENT_VERSION__: string;\nconst SDK_VERSION: string =\n typeof __LAYERS_CLIENT_VERSION__ !== 'undefined' ? __LAYERS_CLIENT_VERSION__ : '0.1.1-alpha.1';\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@layers/client",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"dist"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@layers/core-wasm": "1.0
|
|
36
|
+
"@layers/core-wasm": "1.2.0"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"react": ">=18"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BCpCaNor.d.ts","names":[],"sources":["../../wasm/src/types.ts","../src/api-types.ts","../src/attribution.ts","../src/index.ts"],"sourcesContent":[],"mappings":"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"}
|