@pendo/openfeature-web-provider 0.1.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 +175 -0
- package/dist/PendoProvider.d.ts +102 -0
- package/dist/PendoProvider.js +205 -0
- package/dist/PendoTelemetryHook.d.ts +47 -0
- package/dist/PendoTelemetryHook.js +70 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +8 -0
- package/package.json +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# @pendo/openfeature-web-provider
|
|
2
|
+
|
|
3
|
+
OpenFeature provider for [Pendo](https://www.pendo.io/) feature flags in web browsers.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @pendo/openfeature-web-provider @openfeature/web-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
The Pendo agent must be installed on your page. The provider reads flags from `window.pendo.segmentFlags` which is populated by the agent.
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<script>
|
|
17
|
+
(function(apiKey){
|
|
18
|
+
// Pendo agent snippet
|
|
19
|
+
// ...
|
|
20
|
+
})('YOUR_PENDO_API_KEY');
|
|
21
|
+
</script>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
### Basic Setup
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { OpenFeature } from '@openfeature/web-sdk';
|
|
30
|
+
import { PendoProvider } from '@pendo/openfeature-web-provider';
|
|
31
|
+
|
|
32
|
+
// Initialize the provider (waits for Pendo agent to be ready)
|
|
33
|
+
await OpenFeature.setProviderAndWait(new PendoProvider());
|
|
34
|
+
|
|
35
|
+
// Get a client
|
|
36
|
+
const client = OpenFeature.getClient();
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Evaluating Flags
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
// Boolean flag
|
|
43
|
+
const showNewFeature = await client.getBooleanValue('new-checkout-flow', false);
|
|
44
|
+
|
|
45
|
+
// String flag (returns "on" or "off")
|
|
46
|
+
const variant = await client.getStringValue('checkout-variant', 'control');
|
|
47
|
+
|
|
48
|
+
// Number flag (returns 1 or 0)
|
|
49
|
+
const flagValue = await client.getNumberValue('feature-score', 0);
|
|
50
|
+
|
|
51
|
+
// Object flag (returns { enabled: true/false })
|
|
52
|
+
const config = await client.getObjectValue('feature-config', { enabled: false });
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Event Tracking
|
|
56
|
+
|
|
57
|
+
Track custom events to Pendo:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
const provider = new PendoProvider();
|
|
61
|
+
await OpenFeature.setProviderAndWait(provider);
|
|
62
|
+
|
|
63
|
+
// Track an event
|
|
64
|
+
provider.track('checkout_started', undefined, { cartValue: '99.99' });
|
|
65
|
+
|
|
66
|
+
// The context parameter is ignored in the web provider
|
|
67
|
+
// since the Pendo agent already knows the current visitor
|
|
68
|
+
provider.track('feature_used');
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Telemetry Hook
|
|
72
|
+
|
|
73
|
+
Automatically track all flag evaluations to Pendo using the telemetry hook:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { OpenFeature } from '@openfeature/web-sdk';
|
|
77
|
+
import { PendoProvider, PendoTelemetryHook } from '@pendo/openfeature-web-provider';
|
|
78
|
+
|
|
79
|
+
const provider = new PendoProvider();
|
|
80
|
+
const telemetryHook = new PendoTelemetryHook();
|
|
81
|
+
|
|
82
|
+
await OpenFeature.setProviderAndWait(provider);
|
|
83
|
+
OpenFeature.addHooks(telemetryHook);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
#### Telemetry Hook Options
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const telemetryHook = new PendoTelemetryHook({
|
|
90
|
+
// Optional: Custom event name (default: "flag_evaluated")
|
|
91
|
+
eventName: 'feature_flag_evaluated',
|
|
92
|
+
|
|
93
|
+
// Optional: Filter which flags to track
|
|
94
|
+
flagFilter: (flagKey) => flagKey.startsWith('feature_'),
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### Event Payload
|
|
99
|
+
|
|
100
|
+
Each flag evaluation sends a track event with these properties:
|
|
101
|
+
|
|
102
|
+
| Property | Description |
|
|
103
|
+
|----------|-------------|
|
|
104
|
+
| `flag_key` | The flag that was evaluated |
|
|
105
|
+
| `flag_variant` | "on", "off", or variant name |
|
|
106
|
+
| `flag_reason` | "TARGETING_MATCH", "DEFAULT", or "ERROR" |
|
|
107
|
+
| `flag_value` | Stringified value |
|
|
108
|
+
| `provider_name` | "pendo-provider" |
|
|
109
|
+
|
|
110
|
+
### Configuration Options
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
const provider = new PendoProvider({
|
|
114
|
+
// API key for Pendo initialization (optional if already initialized)
|
|
115
|
+
apiKey: 'YOUR_API_KEY',
|
|
116
|
+
|
|
117
|
+
// Timeout waiting for Pendo agent to be ready (default: 5000ms)
|
|
118
|
+
readyTimeout: 10000,
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## How It Works
|
|
123
|
+
|
|
124
|
+
1. The provider waits for the Pendo agent to initialize
|
|
125
|
+
2. Flag evaluation checks if the flag key exists in `window.pendo.segmentFlags`
|
|
126
|
+
3. If the flag key is present, the flag is enabled; otherwise, it returns the default value
|
|
127
|
+
|
|
128
|
+
## Context
|
|
129
|
+
|
|
130
|
+
The web provider does not require explicit context for flag evaluation since the Pendo agent maintains visitor/account identity automatically. However, you can pass context for consistency with the OpenFeature API:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
const enabled = await client.getBooleanValue('my-flag', false, {
|
|
134
|
+
targetingKey: 'user-123', // Ignored by web provider
|
|
135
|
+
accountId: 'account-456', // Ignored by web provider
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Resolution Details
|
|
140
|
+
|
|
141
|
+
| Scenario | Reason | Variant |
|
|
142
|
+
|----------|--------|---------|
|
|
143
|
+
| Flag key in segmentFlags | `TARGETING_MATCH` | `on` |
|
|
144
|
+
| Flag key not in segmentFlags | `DEFAULT` | `off` |
|
|
145
|
+
| Pendo not ready | `DEFAULT` | `default` |
|
|
146
|
+
|
|
147
|
+
## Troubleshooting
|
|
148
|
+
|
|
149
|
+
### Flags always return default values
|
|
150
|
+
|
|
151
|
+
1. Check that the Pendo agent is properly installed and initialized
|
|
152
|
+
2. Verify the visitor is in a segment that has the flag enabled
|
|
153
|
+
3. Check browser console for `[PendoProvider]` warnings
|
|
154
|
+
|
|
155
|
+
### Provider times out
|
|
156
|
+
|
|
157
|
+
Increase the `readyTimeout` option:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
new PendoProvider({ readyTimeout: 15000 });
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Track events not appearing
|
|
164
|
+
|
|
165
|
+
Ensure the Pendo agent's `track` function is available:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
if (window.pendo?.track) {
|
|
169
|
+
provider.track('my-event');
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## License
|
|
174
|
+
|
|
175
|
+
MIT
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { Provider, ProviderMetadata, ResolutionDetails, EvaluationContext, JsonValue, Hook, TrackingEventDetails } from "@openfeature/web-sdk";
|
|
2
|
+
import { ClientProviderStatus } from "@openfeature/web-sdk";
|
|
3
|
+
declare global {
|
|
4
|
+
interface Window {
|
|
5
|
+
pendo?: {
|
|
6
|
+
segmentFlags?: string[];
|
|
7
|
+
isReady?: () => boolean;
|
|
8
|
+
initialize?: (options: unknown) => void;
|
|
9
|
+
track?: (event: string, properties?: Record<string, string>) => void;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export interface PendoProviderOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Optional: Pendo API key for initialization.
|
|
16
|
+
* If not provided, assumes Pendo is already initialized on the page.
|
|
17
|
+
*/
|
|
18
|
+
apiKey?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Optional: Timeout in milliseconds to wait for Pendo to be ready.
|
|
21
|
+
* Default: 5000ms
|
|
22
|
+
*/
|
|
23
|
+
readyTimeout?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* OpenFeature provider for Pendo feature flags.
|
|
27
|
+
*
|
|
28
|
+
* This provider evaluates feature flags by checking the `pendo.segmentFlags` array
|
|
29
|
+
* which is populated by the Pendo agent based on segment membership.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* import { OpenFeature } from '@openfeature/web-sdk';
|
|
34
|
+
* import { PendoProvider } from '@pendo/openfeature-web-provider';
|
|
35
|
+
*
|
|
36
|
+
* await OpenFeature.setProviderAndWait(new PendoProvider());
|
|
37
|
+
*
|
|
38
|
+
* const client = OpenFeature.getClient();
|
|
39
|
+
* const enabled = await client.getBooleanValue('myFeature', false);
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare class PendoProvider implements Provider {
|
|
43
|
+
readonly metadata: ProviderMetadata;
|
|
44
|
+
readonly rulesChanged?: () => void;
|
|
45
|
+
status: ClientProviderStatus;
|
|
46
|
+
hooks?: Hook[];
|
|
47
|
+
private options;
|
|
48
|
+
private readyPromise;
|
|
49
|
+
constructor(options?: PendoProviderOptions);
|
|
50
|
+
/**
|
|
51
|
+
* Initialize the provider.
|
|
52
|
+
* Waits for Pendo to be ready before resolving.
|
|
53
|
+
*/
|
|
54
|
+
initialize(): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Wait for Pendo to be ready with timeout.
|
|
57
|
+
*/
|
|
58
|
+
private waitForPendo;
|
|
59
|
+
/**
|
|
60
|
+
* Shutdown the provider.
|
|
61
|
+
*/
|
|
62
|
+
onClose(): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Resolve a boolean flag value.
|
|
65
|
+
*
|
|
66
|
+
* Checks if the flagKey exists in pendo.segmentFlags array.
|
|
67
|
+
*/
|
|
68
|
+
resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, _context: EvaluationContext): ResolutionDetails<boolean>;
|
|
69
|
+
/**
|
|
70
|
+
* Resolve a string flag value.
|
|
71
|
+
*
|
|
72
|
+
* For Pendo flags, this returns "on" if the flag is enabled, "off" otherwise.
|
|
73
|
+
*/
|
|
74
|
+
resolveStringEvaluation(flagKey: string, defaultValue: string, context: EvaluationContext): ResolutionDetails<string>;
|
|
75
|
+
/**
|
|
76
|
+
* Resolve a number flag value.
|
|
77
|
+
*
|
|
78
|
+
* For Pendo flags, this returns 1 if enabled, 0 if disabled.
|
|
79
|
+
*/
|
|
80
|
+
resolveNumberEvaluation(flagKey: string, defaultValue: number, context: EvaluationContext): ResolutionDetails<number>;
|
|
81
|
+
/**
|
|
82
|
+
* Resolve an object flag value.
|
|
83
|
+
*
|
|
84
|
+
* For Pendo flags, this returns { enabled: true/false }.
|
|
85
|
+
*/
|
|
86
|
+
resolveObjectEvaluation<T extends JsonValue>(flagKey: string, defaultValue: T, context: EvaluationContext): ResolutionDetails<T>;
|
|
87
|
+
/**
|
|
88
|
+
* Get the segment flags array from Pendo.
|
|
89
|
+
*/
|
|
90
|
+
private getSegmentFlags;
|
|
91
|
+
/**
|
|
92
|
+
* Track a custom event in Pendo.
|
|
93
|
+
*
|
|
94
|
+
* This method delegates to the Pendo agent's track function.
|
|
95
|
+
* The Pendo agent must be initialized on the page for this to work.
|
|
96
|
+
*
|
|
97
|
+
* @param trackingEventName - The name of the event to track
|
|
98
|
+
* @param _context - Evaluation context (unused in web provider, Pendo agent handles visitor context)
|
|
99
|
+
* @param trackingEventDetails - Optional additional event properties
|
|
100
|
+
*/
|
|
101
|
+
track(trackingEventName: string, _context: EvaluationContext, trackingEventDetails: TrackingEventDetails): void;
|
|
102
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PendoProvider = void 0;
|
|
4
|
+
const web_sdk_1 = require("@openfeature/web-sdk");
|
|
5
|
+
/**
|
|
6
|
+
* OpenFeature provider for Pendo feature flags.
|
|
7
|
+
*
|
|
8
|
+
* This provider evaluates feature flags by checking the `pendo.segmentFlags` array
|
|
9
|
+
* which is populated by the Pendo agent based on segment membership.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* import { OpenFeature } from '@openfeature/web-sdk';
|
|
14
|
+
* import { PendoProvider } from '@pendo/openfeature-web-provider';
|
|
15
|
+
*
|
|
16
|
+
* await OpenFeature.setProviderAndWait(new PendoProvider());
|
|
17
|
+
*
|
|
18
|
+
* const client = OpenFeature.getClient();
|
|
19
|
+
* const enabled = await client.getBooleanValue('myFeature', false);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
class PendoProvider {
|
|
23
|
+
constructor(options = {}) {
|
|
24
|
+
this.metadata = {
|
|
25
|
+
name: "pendo-provider",
|
|
26
|
+
};
|
|
27
|
+
this.status = web_sdk_1.ClientProviderStatus.NOT_READY;
|
|
28
|
+
this.readyPromise = null;
|
|
29
|
+
this.options = {
|
|
30
|
+
readyTimeout: 5000,
|
|
31
|
+
...options,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Initialize the provider.
|
|
36
|
+
* Waits for Pendo to be ready before resolving.
|
|
37
|
+
*/
|
|
38
|
+
async initialize() {
|
|
39
|
+
if (this.readyPromise) {
|
|
40
|
+
return this.readyPromise;
|
|
41
|
+
}
|
|
42
|
+
this.readyPromise = this.waitForPendo();
|
|
43
|
+
await this.readyPromise;
|
|
44
|
+
this.status = web_sdk_1.ClientProviderStatus.READY;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Wait for Pendo to be ready with timeout.
|
|
48
|
+
*/
|
|
49
|
+
async waitForPendo() {
|
|
50
|
+
const timeout = this.options.readyTimeout ?? 5000;
|
|
51
|
+
const startTime = Date.now();
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const check = () => {
|
|
54
|
+
// Check if pendo is available and ready
|
|
55
|
+
if (typeof window !== "undefined" && window.pendo) {
|
|
56
|
+
if (window.pendo.isReady?.() || window.pendo.segmentFlags !== undefined) {
|
|
57
|
+
resolve();
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Check timeout
|
|
62
|
+
if (Date.now() - startTime > timeout) {
|
|
63
|
+
// Don't reject - just resolve and work without Pendo
|
|
64
|
+
// Flags will default to false
|
|
65
|
+
console.warn("[PendoProvider] Pendo not ready within timeout. Flags will use default values.");
|
|
66
|
+
resolve();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Try again
|
|
70
|
+
setTimeout(check, 100);
|
|
71
|
+
};
|
|
72
|
+
// Also listen for pendo:ready event
|
|
73
|
+
if (typeof document !== "undefined") {
|
|
74
|
+
document.addEventListener("pendo:ready", () => {
|
|
75
|
+
resolve();
|
|
76
|
+
}, { once: true });
|
|
77
|
+
}
|
|
78
|
+
check();
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Shutdown the provider.
|
|
83
|
+
*/
|
|
84
|
+
async onClose() {
|
|
85
|
+
this.status = web_sdk_1.ClientProviderStatus.NOT_READY;
|
|
86
|
+
this.readyPromise = null;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Resolve a boolean flag value.
|
|
90
|
+
*
|
|
91
|
+
* Checks if the flagKey exists in pendo.segmentFlags array.
|
|
92
|
+
*/
|
|
93
|
+
resolveBooleanEvaluation(flagKey, defaultValue, _context) {
|
|
94
|
+
const flags = this.getSegmentFlags();
|
|
95
|
+
if (!flags) {
|
|
96
|
+
return {
|
|
97
|
+
value: defaultValue,
|
|
98
|
+
reason: "DEFAULT",
|
|
99
|
+
variant: "default",
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
const enabled = flags.includes(flagKey);
|
|
103
|
+
return {
|
|
104
|
+
value: enabled,
|
|
105
|
+
reason: enabled ? "TARGETING_MATCH" : "DEFAULT",
|
|
106
|
+
variant: enabled ? "on" : "off",
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Resolve a string flag value.
|
|
111
|
+
*
|
|
112
|
+
* For Pendo flags, this returns "on" if the flag is enabled, "off" otherwise.
|
|
113
|
+
*/
|
|
114
|
+
resolveStringEvaluation(flagKey, defaultValue, context) {
|
|
115
|
+
const boolResult = this.resolveBooleanEvaluation(flagKey, false, context);
|
|
116
|
+
if (boolResult.reason === "DEFAULT" && !boolResult.value) {
|
|
117
|
+
return {
|
|
118
|
+
value: defaultValue,
|
|
119
|
+
reason: "DEFAULT",
|
|
120
|
+
variant: "default",
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
value: boolResult.value ? "on" : "off",
|
|
125
|
+
reason: boolResult.reason,
|
|
126
|
+
variant: boolResult.variant,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Resolve a number flag value.
|
|
131
|
+
*
|
|
132
|
+
* For Pendo flags, this returns 1 if enabled, 0 if disabled.
|
|
133
|
+
*/
|
|
134
|
+
resolveNumberEvaluation(flagKey, defaultValue, context) {
|
|
135
|
+
const boolResult = this.resolveBooleanEvaluation(flagKey, false, context);
|
|
136
|
+
if (boolResult.reason === "DEFAULT" && !boolResult.value) {
|
|
137
|
+
return {
|
|
138
|
+
value: defaultValue,
|
|
139
|
+
reason: "DEFAULT",
|
|
140
|
+
variant: "default",
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
value: boolResult.value ? 1 : 0,
|
|
145
|
+
reason: boolResult.reason,
|
|
146
|
+
variant: boolResult.variant,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Resolve an object flag value.
|
|
151
|
+
*
|
|
152
|
+
* For Pendo flags, this returns { enabled: true/false }.
|
|
153
|
+
*/
|
|
154
|
+
resolveObjectEvaluation(flagKey, defaultValue, context) {
|
|
155
|
+
const boolResult = this.resolveBooleanEvaluation(flagKey, false, context);
|
|
156
|
+
if (boolResult.reason === "DEFAULT" && !boolResult.value) {
|
|
157
|
+
return {
|
|
158
|
+
value: defaultValue,
|
|
159
|
+
reason: "DEFAULT",
|
|
160
|
+
variant: "default",
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
value: { enabled: boolResult.value },
|
|
165
|
+
reason: boolResult.reason,
|
|
166
|
+
variant: boolResult.variant,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Get the segment flags array from Pendo.
|
|
171
|
+
*/
|
|
172
|
+
getSegmentFlags() {
|
|
173
|
+
if (typeof window === "undefined") {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
return window.pendo?.segmentFlags;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Track a custom event in Pendo.
|
|
180
|
+
*
|
|
181
|
+
* This method delegates to the Pendo agent's track function.
|
|
182
|
+
* The Pendo agent must be initialized on the page for this to work.
|
|
183
|
+
*
|
|
184
|
+
* @param trackingEventName - The name of the event to track
|
|
185
|
+
* @param _context - Evaluation context (unused in web provider, Pendo agent handles visitor context)
|
|
186
|
+
* @param trackingEventDetails - Optional additional event properties
|
|
187
|
+
*/
|
|
188
|
+
track(trackingEventName, _context, trackingEventDetails) {
|
|
189
|
+
if (typeof window === "undefined" || !window.pendo?.track) {
|
|
190
|
+
console.warn("[PendoProvider] Pendo agent not available for tracking");
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
// Convert TrackingEventDetails to Record<string, string> for Pendo agent
|
|
194
|
+
const properties = {};
|
|
195
|
+
for (const [key, value] of Object.entries(trackingEventDetails)) {
|
|
196
|
+
if (value !== undefined && value !== null) {
|
|
197
|
+
properties[key] = String(value);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// Fire-and-forget: delegate to Pendo agent
|
|
201
|
+
window.pendo.track(trackingEventName, properties);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
exports.PendoProvider = PendoProvider;
|
|
205
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGVuZG9Qcm92aWRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9QZW5kb1Byb3ZpZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQVNBLGtEQUE0RDtBQTJCNUQ7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCxNQUFhLGFBQWE7SUFZeEIsWUFBWSxVQUFnQyxFQUFFO1FBWHJDLGFBQVEsR0FBcUI7WUFDcEMsSUFBSSxFQUFFLGdCQUFnQjtTQUN2QixDQUFDO1FBR0YsV0FBTSxHQUF5Qiw4QkFBb0IsQ0FBQyxTQUFTLENBQUM7UUFJdEQsaUJBQVksR0FBeUIsSUFBSSxDQUFDO1FBR2hELElBQUksQ0FBQyxPQUFPLEdBQUc7WUFDYixZQUFZLEVBQUUsSUFBSTtZQUNsQixHQUFHLE9BQU87U0FDWCxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxVQUFVO1FBQ2QsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDdEIsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO1FBQzNCLENBQUM7UUFFRCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUN4QyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUM7UUFDeEIsSUFBSSxDQUFDLE1BQU0sR0FBRyw4QkFBb0IsQ0FBQyxLQUFLLENBQUM7SUFDM0MsQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLFlBQVk7UUFDeEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDO1FBQ2xELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUU3QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3JDLE1BQU0sS0FBSyxHQUFHLEdBQUcsRUFBRTtnQkFDakIsd0NBQXdDO2dCQUN4QyxJQUFJLE9BQU8s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QU0sS0FBSyxXQUFXLEVBQUUsQ0FBQztZQUNsQyxPQUFPLFNBQVMsQ0FBQztRQUNuQixDQUFDO1FBRUQsT0FBTyxNQUFNLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQztJQUNwQyxDQUFDO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0gsS0FBSyxDQUNILGlCQUF5QixFQUN6QixRQUEyQixFQUMzQixvQkFBMEM7UUFFMUMsSUFBSSxPQUFPLE1BQU0sS0FBSyxXQUFXLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDO1lBQzFELE9BQU8sQ0FBQyxJQUFJLENBQUMsd0RBQXdELENBQUMsQ0FBQztZQUN2RSxPQUFPO1FBQ1QsQ0FBQztRQUVELHlFQUF5RTtRQUN6RSxNQUFNLFVBQVUsR0FBMkIsRUFBRSxDQUFDO1FBQzlDLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLG9CQUFvQixDQUFDLEVBQUUsQ0FBQztZQUNoRSxJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUMxQyxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2xDLENBQUM7UUFDSCxDQUFDO1FBRUQsMkNBQTJDO1FBQzNDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLGlCQUFpQixFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3BELENBQUM7Q0FDRjtBQWhQRCxzQ0FnUEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7XG4gIFByb3ZpZGVyLFxuICBQcm92aWRlck1ldGFkYXRhLFxuICBSZXNvbHV0aW9uRGV0YWlscyxcbiAgRXZhbHVhdGlvbkNvbnRleHQsXG4gIEpzb25WYWx1ZSxcbiAgSG9vayxcbiAgVHJhY2tpbmdFdmVudERldGFpbHMsXG59IGZyb20gXCJAb3BlbmZlYXR1cmUvd2ViLXNka1wiO1xuaW1wb3J0IHsgQ2xpZW50UHJvdmlkZXJTdGF0dXMgfSBmcm9tIFwiQG9wZW5mZWF0dXJlL3dlYi1zZGtcIjtcblxuZGVjbGFyZSBnbG9iYWwge1xuICBpbnRlcmZhY2UgV2luZG93IHtcbiAgICBwZW5kbz86IHtcbiAgICAgIHNlZ21lbnRGbGFncz86IHN0cmluZ1tdO1xuICAgICAgaXNSZWFkeT86ICgpID0+IGJvb2xlYW47XG4gICAgICBpbml0aWFsaXplPzogKG9wdGlvbnM6IHVua25vd24pID0+IHZvaWQ7XG4gICAgICB0cmFjaz86IChldmVudDogc3RyaW5nLCBwcm9wZXJ0aWVzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPikgPT4gdm9pZDtcbiAgICB9O1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGVuZG9Qcm92aWRlck9wdGlvbnMge1xuICAvKipcbiAgICogT3B0aW9uYWw6IFBlbmRvIEFQSSBrZXkgZm9yIGluaXRpYWxpemF0aW9uLlxuICAgKiBJZiBub3QgcHJvdmlkZWQsIGFzc3VtZXMgUGVuZG8gaXMgYWxyZWFkeSBpbml0aWFsaXplZCBvbiB0aGUgcGFnZS5cbiAgICovXG4gIGFwaUtleT86IHN0cmluZztcblxuICAvKipcbiAgICogT3B0aW9uYWw6IFRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzIHRvIHdhaXQgZm9yIFBlbmRvIHRvIGJlIHJlYWR5LlxuICAgKiBEZWZhdWx0OiA1MDAwbXNcbiAgICovXG4gIHJlYWR5VGltZW91dD86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBPcGVuRmVhdHVyZSBwcm92aWRlciBmb3IgUGVuZG8gZmVhdHVyZSBmbGFncy5cbiAqXG4gKiBUaGlzIHByb3ZpZGVyIGV2YWx1YXRlcyBmZWF0dXJlIGZsYWdzIGJ5IGNoZWNraW5nIHRoZSBgcGVuZG8uc2VnbWVudEZsYWdzYCBhcnJheVxuICogd2hpY2ggaXMgcG9wdWxhdGVkIGJ5IHRoZSBQZW5kbyBhZ2VudCBiYXNlZCBvbiBzZWdtZW50IG1lbWJlcnNoaXAuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IE9wZW5GZWF0dXJlIH0gZnJvbSAnQG9wZW5mZWF0dXJlL3dlYi1zZGsnO1xuICogaW1wb3J0IHsgUGVuZG9Qcm92aWRlciB9IGZyb20gJ0BwZW5kby9vcGVuZmVhdHVyZS13ZWItcHJvdmlkZXInO1xuICpcbiAqIGF3YWl0IE9wZW5GZWF0dXJlLnNldFByb3ZpZGVyQW5kV2FpdChuZXcgUGVuZG9Qcm92aWRlcigpKTtcbiAqXG4gKiBjb25zdCBjbGllbnQgPSBPcGVuRmVhdHVyZS5nZXRDbGllbnQoKTtcbiAqIGNvbnN0IGVuYWJsZWQgPSBhd2FpdCBjbGllbnQuZ2V0Qm9vbGVhblZhbHVlKCdteUZlYXR1cmUnLCBmYWxzZSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIFBlbmRvUHJvdmlkZXIgaW1wbGVtZW50cyBQcm92aWRlciB7XG4gIHJlYWRvbmx5IG1ldGFkYXRhOiBQcm92aWRlck1ldGFkYXRhID0ge1xuICAgIG5hbWU6IFwicGVuZG8tcHJvdmlkZXJcIixcbiAgfTtcblxuICByZWFkb25seSBydWxlc0NoYW5nZWQ/OiAoKSA9PiB2b2lkO1xuICBzdGF0dXM6IENsaWVudFByb3ZpZGVyU3RhdHVzID0gQ2xpZW50UHJvdmlkZXJTdGF0dXMuTk9UX1JFQURZO1xuICBob29rcz86IEhvb2tbXTtcblxuICBwcml2YXRlIG9wdGlvbnM6IFBlbmRvUHJvdmlkZXJPcHRpb25zO1xuICBwcml2YXRlIHJlYWR5UHJvbWlzZTogUHJvbWlzZTx2b2lkPiB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IFBlbmRvUHJvdmlkZXJPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICByZWFkeVRpbWVvdXQ6IDUwMDAsXG4gICAgICAuLi5vcHRpb25zLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSB0aGUgcHJvdmlkZXIuXG4gICAqIFdhaXRzIGZvciBQZW5kbyB0byBiZSByZWFkeSBiZWZvcmUgcmVzb2x2aW5nLlxuICAgKi9cbiAgYXN5bmMgaW5pdGlhbGl6ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5yZWFkeVByb21pc2UpIHtcbiAgICAgIHJldHVybiB0aGlzLnJlYWR5UHJvbWlzZTtcbiAgICB9XG5cbiAgICB0aGlzLnJlYWR5UHJvbWlzZSA9IHRoaXMud2FpdEZvclBlbmRvKCk7XG4gICAgYXdhaXQgdGhpcy5yZWFkeVByb21pc2U7XG4gICAgdGhpcy5zdGF0dXMgPSBDbGllbnRQcm92aWRlclN0YXR1cy5SRUFEWTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXYWl0IGZvciBQZW5kbyB0byBiZSByZWFkeSB3aXRoIHRpbWVvdXQuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHdhaXRGb3JQZW5kbygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB0aW1lb3V0ID0gdGhpcy5vcHRpb25zLnJlYWR5VGltZW91dCA/PyA1MDAwO1xuICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgY2hlY2sgPSAoKSA9PiB7XG4gICAgICAgIC8vIENoZWNrIGlmIHBlbmRvIGlzIGF2YWlsYWJsZSBhbmQgcmVhZHlcbiAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgJiYgd2luZG93LnBlbmRvKSB7XG4gICAgICAgICAgaWYgKHdpbmRvdy5wZW5kby5pc1JlYWR5Py4oKSB8fCB3aW5kb3cucGVuZG8uc2VnbWVudEZsYWdzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayB0aW1lb3V0XG4gICAgICAgIGlmIChEYXRlLm5vdygpIC0gc3RhcnRUaW1lID4gdGltZW91dCkge1xuICAgICAgICAgIC8vIERvbid0IHJlamVjdCAtIGp1c3QgcmVzb2x2ZSBhbmQgd29yayB3aXRob3V0IFBlbmRvXG4gICAgICAgICAgLy8gRmxhZ3Mgd2lsbCBkZWZhdWx0IHRvIGZhbHNlXG4gICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgXCJbUGVuZG9Qcm92aWRlcl0gUGVuZG8gbm90IHJlYWR5IHdpdGhpbiB0aW1lb3V0LiBGbGFncyB3aWxsIHVzZSBkZWZhdWx0IHZhbHVlcy5cIlxuICAgICAgICAgICk7XG4gICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRyeSBhZ2FpblxuICAgICAgICBzZXRUaW1lb3V0KGNoZWNrLCAxMDApO1xuICAgICAgfTtcblxuICAgICAgLy8gQWxzbyBsaXN0ZW4gZm9yIHBlbmRvOnJlYWR5IGV2ZW50XG4gICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgXCJwZW5kbzpyZWFkeVwiLFxuICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgb25jZTogdHJ1ZSB9XG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGNoZWNrKCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU2h1dGRvd24gdGhlIHByb3ZpZGVyLlxuICAgKi9cbiAgYXN5bmMgb25DbG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLnN0YXR1cyA9IENsaWVudFByb3ZpZGVyU3RhdHVzLk5PVF9SRUFEWTtcbiAgICB0aGlzLnJlYWR5UHJvbWlzZSA9IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZSBhIGJvb2xlYW4gZmxhZyB2YWx1ZS5cbiAgICpcbiAgICogQ2hlY2tzIGlmIHRoZSBmbGFnS2V5IGV4aXN0cyBpbiBwZW5kby5zZWdtZW50RmxhZ3MgYXJyYXkuXG4gICAqL1xuICByZXNvbHZlQm9vbGVhbkV2YWx1YXRpb24oXG4gICAgZmxhZ0tleTogc3RyaW5nLFxuICAgIGRlZmF1bHRWYWx1ZTogYm9vbGVhbixcbiAgICBfY29udGV4dDogRXZhbHVhdGlvbkNvbnRleHRcbiAgKTogUmVzb2x1dGlvbkRldGFpbHM8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGZsYWdzID0gdGhpcy5nZXRTZWdtZW50RmxhZ3MoKTtcblxuICAgIGlmICghZmxhZ3MpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHZhbHVlOiBkZWZhdWx0VmFsdWUsXG4gICAgICAgIHJlYXNvbjogXCJERUZBVUxUXCIsXG4gICAgICAgIHZhcmlhbnQ6IFwiZGVmYXVsdFwiLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCBlbmFibGVkID0gZmxhZ3MuaW5jbHVkZXMoZmxhZ0tleSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdmFsdWU6IGVuYWJsZWQsXG4gICAgICByZWFzb246IGVuYWJsZWQgPyBcIlRBUkdFVElOR19NQVRDSFwiIDogXCJERUZBVUxUXCIsXG4gICAgICB2YXJpYW50OiBlbmFibGVkID8gXCJvblwiIDogXCJvZmZcIixcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgYSBzdHJpbmcgZmxhZyB2YWx1ZS5cbiAgICpcbiAgICogRm9yIFBlbmRvIGZsYWdzLCB0aGlzIHJldHVybnMgXCJvblwiIGlmIHRoZSBmbGFnIGlzIGVuYWJsZWQsIFwib2ZmXCIgb3RoZXJ3aXNlLlxuICAgKi9cbiAgcmVzb2x2ZVN0cmluZ0V2YWx1YXRpb24oXG4gICAgZmxhZ0tleTogc3RyaW5nLFxuICAgIGRlZmF1bHRWYWx1ZTogc3RyaW5nLFxuICAgIGNvbnRleHQ6IEV2YWx1YXRpb25Db250ZXh0XG4gICk6IFJlc29sdXRpb25EZXRhaWxzPHN0cmluZz4ge1xuICAgIGNvbnN0IGJvb2xSZXN1bHQgPSB0aGlzLnJlc29sdmVCb29sZWFuRXZhbHVhdGlvbihmbGFnS2V5LCBmYWxzZSwgY29udGV4dCk7XG5cbiAgICBpZiAoYm9vbFJlc3VsdC5yZWFzb24gPT09IFwiREVGQVVMVFwiICYmICFib29sUmVzdWx0LnZhbHVlKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB2YWx1ZTogZGVmYXVsdFZhbHVlLFxuICAgICAgICByZWFzb246IFwiREVGQVVMVFwiLFxuICAgICAgICB2YXJpYW50OiBcImRlZmF1bHRcIixcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHZhbHVlOiBib29sUmVzdWx0LnZhbHVlID8gXCJvblwiIDogXCJvZmZcIixcbiAgICAgIHJlYXNvbjogYm9vbFJlc3VsdC5yZWFzb24sXG4gICAgICB2YXJpYW50OiBib29sUmVzdWx0LnZhcmlhbnQsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlIGEgbnVtYmVyIGZsYWcgdmFsdWUuXG4gICAqXG4gICAqIEZvciBQZW5kbyBmbGFncywgdGhpcyByZXR1cm5zIDEgaWYgZW5hYmxlZCwgMCBpZiBkaXNhYmxlZC5cbiAgICovXG4gIHJlc29sdmVOdW1iZXJFdmFsdWF0aW9uKFxuICAgIGZsYWdLZXk6IHN0cmluZyxcbiAgICBkZWZhdWx0VmFsdWU6IG51bWJlcixcbiAgICBjb250ZXh0OiBFdmFsdWF0aW9uQ29udGV4dFxuICApOiBSZXNvbHV0aW9uRGV0YWlsczxudW1iZXI+IHtcbiAgICBjb25zdCBib29sUmVzdWx0ID0gdGhpcy5yZXNvbHZlQm9vbGVhbkV2YWx1YXRpb24oZmxhZ0tleSwgZmFsc2UsIGNvbnRleHQpO1xuXG4gICAgaWYgKGJvb2xSZXN1bHQucmVhc29uID09PSBcIkRFRkFVTFRcIiAmJiAhYm9vbFJlc3VsdC52YWx1ZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmFsdWU6IGRlZmF1bHRWYWx1ZSxcbiAgICAgICAgcmVhc29uOiBcIkRFRkFVTFRcIixcbiAgICAgICAgdmFyaWFudDogXCJkZWZhdWx0XCIsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICB2YWx1ZTogYm9vbFJlc3VsdC52YWx1ZSA/IDEgOiAwLFxuICAgICAgcmVhc29uOiBib29sUmVzdWx0LnJlYXNvbixcbiAgICAgIHZhcmlhbnQ6IGJvb2xSZXN1bHQudmFyaWFudCxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgYW4gb2JqZWN0IGZsYWcgdmFsdWUuXG4gICAqXG4gICAqIEZvciBQZW5kbyBmbGFncywgdGhpcyByZXR1cm5zIHsgZW5hYmxlZDogdHJ1ZS9mYWxzZSB9LlxuICAgKi9cbiAgcmVzb2x2ZU9iamVjdEV2YWx1YXRpb248VCBleHRlbmRzIEpzb25WYWx1ZT4oXG4gICAgZmxhZ0tleTogc3RyaW5nLFxuICAgIGRlZmF1bHRWYWx1ZTogVCxcbiAgICBjb250ZXh0OiBFdmFsdWF0aW9uQ29udGV4dFxuICApOiBSZXNvbHV0aW9uRGV0YWlsczxUPiB7XG4gICAgY29uc3QgYm9vbFJlc3VsdCA9IHRoaXMucmVzb2x2ZUJvb2xlYW5FdmFsdWF0aW9uKGZsYWdLZXksIGZhbHNlLCBjb250ZXh0KTtcblxuICAgIGlmIChib29sUmVzdWx0LnJlYXNvbiA9PT0gXCJERUZBVUxUXCIgJiYgIWJvb2xSZXN1bHQudmFsdWUpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHZhbHVlOiBkZWZhdWx0VmFsdWUsXG4gICAgICAgIHJlYXNvbjogXCJERUZBVUxUXCIsXG4gICAgICAgIHZhcmlhbnQ6IFwiZGVmYXVsdFwiLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdmFsdWU6IHsgZW5hYmxlZDogYm9vbFJlc3VsdC52YWx1ZSB9IGFzIHVua25vd24gYXMgVCxcbiAgICAgIHJlYXNvbjogYm9vbFJlc3VsdC5yZWFzb24sXG4gICAgICB2YXJpYW50OiBib29sUmVzdWx0LnZhcmlhbnQsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIHNlZ21lbnQgZmxhZ3MgYXJyYXkgZnJvbSBQZW5kby5cbiAgICovXG4gIHByaXZhdGUgZ2V0U2VnbWVudEZsYWdzKCk6IHN0cmluZ1tdIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICByZXR1cm4gd2luZG93LnBlbmRvPy5zZWdtZW50RmxhZ3M7XG4gIH1cblxuICAvKipcbiAgICogVHJhY2sgYSBjdXN0b20gZXZlbnQgaW4gUGVuZG8uXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIGRlbGVnYXRlcyB0byB0aGUgUGVuZG8gYWdlbnQncyB0cmFjayBmdW5jdGlvbi5cbiAgICogVGhlIFBlbmRvIGFnZW50IG11c3QgYmUgaW5pdGlhbGl6ZWQgb24gdGhlIHBhZ2UgZm9yIHRoaXMgdG8gd29yay5cbiAgICpcbiAgICogQHBhcmFtIHRyYWNraW5nRXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHRyYWNrXG4gICAqIEBwYXJhbSBfY29udGV4dCAtIEV2YWx1YXRpb24gY29udGV4dCAodW51c2VkIGluIHdlYiBwcm92aWRlciwgUGVuZG8gYWdlbnQgaGFuZGxlcyB2aXNpdG9yIGNvbnRleHQpXG4gICAqIEBwYXJhbSB0cmFja2luZ0V2ZW50RGV0YWlscyAtIE9wdGlvbmFsIGFkZGl0aW9uYWwgZXZlbnQgcHJvcGVydGllc1xuICAgKi9cbiAgdHJhY2soXG4gICAgdHJhY2tpbmdFdmVudE5hbWU6IHN0cmluZyxcbiAgICBfY29udGV4dDogRXZhbHVhdGlvbkNvbnRleHQsXG4gICAgdHJhY2tpbmdFdmVudERldGFpbHM6IFRyYWNraW5nRXZlbnREZXRhaWxzXG4gICk6IHZvaWQge1xuICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSBcInVuZGVmaW5lZFwiIHx8ICF3aW5kb3cucGVuZG8/LnRyYWNrKSB7XG4gICAgICBjb25zb2xlLndhcm4oXCJbUGVuZG9Qcm92aWRlcl0gUGVuZG8gYWdlbnQgbm90IGF2YWlsYWJsZSBmb3IgdHJhY2tpbmdcIik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gQ29udmVydCBUcmFja2luZ0V2ZW50RGV0YWlscyB0byBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IGZvciBQZW5kbyBhZ2VudFxuICAgIGNvbnN0IHByb3BlcnRpZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyh0cmFja2luZ0V2ZW50RGV0YWlscykpIHtcbiAgICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsKSB7XG4gICAgICAgIHByb3BlcnRpZXNba2V5XSA9IFN0cmluZyh2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRmlyZS1hbmQtZm9yZ2V0OiBkZWxlZ2F0ZSB0byBQZW5kbyBhZ2VudFxuICAgIHdpbmRvdy5wZW5kby50cmFjayh0cmFja2luZ0V2ZW50TmFtZSwgcHJvcGVydGllcyk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Hook, HookContext, EvaluationDetails, FlagValue } from "@openfeature/web-sdk";
|
|
2
|
+
export interface PendoTelemetryHookOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Event name for flag evaluation tracking.
|
|
5
|
+
* Default: "flag_evaluated"
|
|
6
|
+
*/
|
|
7
|
+
eventName?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Optional filter function to selectively track flags.
|
|
10
|
+
* Return true to track the flag, false to skip.
|
|
11
|
+
*/
|
|
12
|
+
flagFilter?: (flagKey: string) => boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* OpenFeature hook that automatically tracks flag evaluations to Pendo.
|
|
16
|
+
*
|
|
17
|
+
* This hook sends an event to Pendo after each flag evaluation, allowing you
|
|
18
|
+
* to analyze feature flag usage alongside your other Pendo analytics.
|
|
19
|
+
*
|
|
20
|
+
* The hook uses the Pendo agent's track function, so the Pendo agent must be
|
|
21
|
+
* initialized on the page for tracking to work.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* import { OpenFeature } from '@openfeature/web-sdk';
|
|
26
|
+
* import { PendoProvider, PendoTelemetryHook } from '@pendo/openfeature-web-provider';
|
|
27
|
+
*
|
|
28
|
+
* const provider = new PendoProvider();
|
|
29
|
+
* const telemetryHook = new PendoTelemetryHook();
|
|
30
|
+
*
|
|
31
|
+
* await OpenFeature.setProviderAndWait(provider);
|
|
32
|
+
* OpenFeature.addHooks(telemetryHook);
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare class PendoTelemetryHook implements Hook {
|
|
36
|
+
private options;
|
|
37
|
+
constructor(options?: PendoTelemetryHookOptions);
|
|
38
|
+
/**
|
|
39
|
+
* Called after a flag is successfully evaluated.
|
|
40
|
+
* Sends the evaluation result to Pendo as a track event.
|
|
41
|
+
*/
|
|
42
|
+
after(hookContext: Readonly<HookContext<FlagValue>>, evaluationDetails: EvaluationDetails<FlagValue>): void;
|
|
43
|
+
/**
|
|
44
|
+
* Convert a flag value to a string for tracking.
|
|
45
|
+
*/
|
|
46
|
+
private stringifyValue;
|
|
47
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PendoTelemetryHook = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* OpenFeature hook that automatically tracks flag evaluations to Pendo.
|
|
6
|
+
*
|
|
7
|
+
* This hook sends an event to Pendo after each flag evaluation, allowing you
|
|
8
|
+
* to analyze feature flag usage alongside your other Pendo analytics.
|
|
9
|
+
*
|
|
10
|
+
* The hook uses the Pendo agent's track function, so the Pendo agent must be
|
|
11
|
+
* initialized on the page for tracking to work.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { OpenFeature } from '@openfeature/web-sdk';
|
|
16
|
+
* import { PendoProvider, PendoTelemetryHook } from '@pendo/openfeature-web-provider';
|
|
17
|
+
*
|
|
18
|
+
* const provider = new PendoProvider();
|
|
19
|
+
* const telemetryHook = new PendoTelemetryHook();
|
|
20
|
+
*
|
|
21
|
+
* await OpenFeature.setProviderAndWait(provider);
|
|
22
|
+
* OpenFeature.addHooks(telemetryHook);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
class PendoTelemetryHook {
|
|
26
|
+
constructor(options = {}) {
|
|
27
|
+
this.options = {
|
|
28
|
+
eventName: "flag_evaluated",
|
|
29
|
+
...options,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Called after a flag is successfully evaluated.
|
|
34
|
+
* Sends the evaluation result to Pendo as a track event.
|
|
35
|
+
*/
|
|
36
|
+
after(hookContext, evaluationDetails) {
|
|
37
|
+
const { flagKey } = hookContext;
|
|
38
|
+
// Check if this flag should be tracked
|
|
39
|
+
if (this.options.flagFilter && !this.options.flagFilter(flagKey)) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// Check if Pendo agent is available
|
|
43
|
+
if (typeof window === "undefined" || !window.pendo?.track) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const properties = {
|
|
47
|
+
flag_key: flagKey,
|
|
48
|
+
flag_variant: evaluationDetails.variant || "unknown",
|
|
49
|
+
flag_reason: evaluationDetails.reason || "UNKNOWN",
|
|
50
|
+
flag_value: this.stringifyValue(evaluationDetails.value),
|
|
51
|
+
provider_name: hookContext.providerMetadata.name,
|
|
52
|
+
};
|
|
53
|
+
// Fire-and-forget: delegate to Pendo agent
|
|
54
|
+
window.pendo.track(this.options.eventName, properties);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Convert a flag value to a string for tracking.
|
|
58
|
+
*/
|
|
59
|
+
stringifyValue(value) {
|
|
60
|
+
if (value === null) {
|
|
61
|
+
return "null";
|
|
62
|
+
}
|
|
63
|
+
if (typeof value === "object") {
|
|
64
|
+
return JSON.stringify(value);
|
|
65
|
+
}
|
|
66
|
+
return String(value);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.PendoTelemetryHook = PendoTelemetryHook;
|
|
70
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGVuZG9UZWxlbWV0cnlIb29rLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1BlbmRvVGVsZW1ldHJ5SG9vay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFxQkE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gsTUFBYSxrQkFBa0I7SUFLN0IsWUFBWSxVQUFxQyxFQUFFO1FBQ2pELElBQUksQ0FBQyxPQUFPLEdBQUc7WUFDYixTQUFTLEVBQUUsZ0JBQWdCO1lBQzNCLEdBQUcsT0FBTztTQUNYLENBQUM7SUFDSixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUNILFdBQTZDLEVBQzdDLGlCQUErQztRQUUvQyxNQUFNLEVBQUUsT0FBTyxFQUFFLEdBQUcsV0FBVyxDQUFDO1FBRWhDLHVDQUF1QztRQUN2QyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNqRSxPQUFPO1FBQ1QsQ0FBQztRQUVELG9DQUFvQztRQUNwQyxJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUM7WUFDMUQsT0FBTztRQUNULENBQUM7UUFFRCxNQUFNLFVBQVUsR0FBMkI7WUFDekMsUUFBUSxFQUFFLE9BQU87WUFDakIsWUFBWSxFQUFFLGlCQUFpQixDQUFDLE9BQU8sSUFBSSxTQUFTO1lBQ3BELFdBQVcsRUFBRSxpQkFBaUIsQ0FBQyxNQUFNLElBQUksU0FBUztZQUNsRCxVQUFVLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUM7WUFDeEQsYUFBYSxFQUFFLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJO1NBQ2pELENBQUM7UUFFRiwyQ0FBMkM7UUFDM0MsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVEOztPQUVHO0lBQ0ssY0FBYyxDQUFDLEtBQWdCO1FBQ3JDLElBQUksS0FBSyxLQUFLLElBQUksRUFBRSxDQUFDO1lBQ25CLE9BQU8sTUFBTSxDQUFDO1FBQ2hCLENBQUM7UUFDRCxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzlCLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMvQixDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDdkIsQ0FBQztDQUNGO0FBeERELGdEQXdEQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHtcbiAgSG9vayxcbiAgSG9va0NvbnRleHQsXG4gIEV2YWx1YXRpb25EZXRhaWxzLFxuICBGbGFnVmFsdWUsXG59IGZyb20gXCJAb3BlbmZlYXR1cmUvd2ViLXNka1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIFBlbmRvVGVsZW1ldHJ5SG9va09wdGlvbnMge1xuICAvKipcbiAgICogRXZlbnQgbmFtZSBmb3IgZmxhZyBldmFsdWF0aW9uIHRyYWNraW5nLlxuICAgKiBEZWZhdWx0OiBcImZsYWdfZXZhbHVhdGVkXCJcbiAgICovXG4gIGV2ZW50TmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogT3B0aW9uYWwgZmlsdGVyIGZ1bmN0aW9uIHRvIHNlbGVjdGl2ZWx5IHRyYWNrIGZsYWdzLlxuICAgKiBSZXR1cm4gdHJ1ZSB0byB0cmFjayB0aGUgZmxhZywgZmFsc2UgdG8gc2tpcC5cbiAgICovXG4gIGZsYWdGaWx0ZXI/OiAoZmxhZ0tleTogc3RyaW5nKSA9PiBib29sZWFuO1xufVxuXG4vKipcbiAqIE9wZW5GZWF0dXJlIGhvb2sgdGhhdCBhdXRvbWF0aWNhbGx5IHRyYWNrcyBmbGFnIGV2YWx1YXRpb25zIHRvIFBlbmRvLlxuICpcbiAqIFRoaXMgaG9vayBzZW5kcyBhbiBldmVudCB0byBQZW5kbyBhZnRlciBlYWNoIGZsYWcgZXZhbHVhdGlvbiwgYWxsb3dpbmcgeW91XG4gKiB0byBhbmFseXplIGZlYXR1cmUgZmxhZyB1c2FnZSBhbG9uZ3NpZGUgeW91ciBvdGhlciBQZW5kbyBhbmFseXRpY3MuXG4gKlxuICogVGhlIGhvb2sgdXNlcyB0aGUgUGVuZG8gYWdlbnQncyB0cmFjayBmdW5jdGlvbiwgc28gdGhlIFBlbmRvIGFnZW50IG11c3QgYmVcbiAqIGluaXRpYWxpemVkIG9uIHRoZSBwYWdlIGZvciB0cmFja2luZyB0byB3b3JrLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBPcGVuRmVhdHVyZSB9IGZyb20gJ0BvcGVuZmVhdHVyZS93ZWItc2RrJztcbiAqIGltcG9ydCB7IFBlbmRvUHJvdmlkZXIsIFBlbmRvVGVsZW1ldHJ5SG9vayB9IGZyb20gJ0BwZW5kby9vcGVuZmVhdHVyZS13ZWItcHJvdmlkZXInO1xuICpcbiAqIGNvbnN0IHByb3ZpZGVyID0gbmV3IFBlbmRvUHJvdmlkZXIoKTtcbiAqIGNvbnN0IHRlbGVtZXRyeUhvb2sgPSBuZXcgUGVuZG9UZWxlbWV0cnlIb29rKCk7XG4gKlxuICogYXdhaXQgT3BlbkZlYXR1cmUuc2V0UHJvdmlkZXJBbmRXYWl0KHByb3ZpZGVyKTtcbiAqIE9wZW5GZWF0dXJlLmFkZEhvb2tzKHRlbGVtZXRyeUhvb2spO1xuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBQZW5kb1RlbGVtZXRyeUhvb2sgaW1wbGVtZW50cyBIb29rIHtcbiAgcHJpdmF0ZSBvcHRpb25zOiBSZXF1aXJlZDxPbWl0PFBlbmRvVGVsZW1ldHJ5SG9va09wdGlvbnMsIFwiZmxhZ0ZpbHRlclwiPj4gJiB7XG4gICAgZmxhZ0ZpbHRlcj86IChmbGFnS2V5OiBzdHJpbmcpID0+IGJvb2xlYW47XG4gIH07XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogUGVuZG9UZWxlbWV0cnlIb29rT3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5vcHRpb25zID0ge1xuICAgICAgZXZlbnROYW1lOiBcImZsYWdfZXZhbHVhdGVkXCIsXG4gICAgICAuLi5vcHRpb25zLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ2FsbGVkIGFmdGVyIGEgZmxhZyBpcyBzdWNjZXNzZnVsbHkgZXZhbHVhdGVkLlxuICAgKiBTZW5kcyB0aGUgZXZhbHVhdGlvbiByZXN1bHQgdG8gUGVuZG8gYXMgYSB0cmFjayBldmVudC5cbiAgICovXG4gIGFmdGVyKFxuICAgIGhvb2tDb250ZXh0OiBSZWFkb25seTxIb29rQ29udGV4dDxGbGFnVmFsdWU+PixcbiAgICBldmFsdWF0aW9uRGV0YWlsczogRXZhbHVhdGlvbkRldGFpbHM8RmxhZ1ZhbHVlPlxuICApOiB2b2lkIHtcbiAgICBjb25zdCB7IGZsYWdLZXkgfSA9IGhvb2tDb250ZXh0O1xuXG4gICAgLy8gQ2hlY2sgaWYgdGhpcyBmbGFnIHNob3VsZCBiZSB0cmFja2VkXG4gICAgaWYgKHRoaXMub3B0aW9ucy5mbGFnRmlsdGVyICYmICF0aGlzLm9wdGlvbnMuZmxhZ0ZpbHRlcihmbGFnS2V5KSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGlmIFBlbmRvIGFnZW50IGlzIGF2YWlsYWJsZVxuICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSBcInVuZGVmaW5lZFwiIHx8ICF3aW5kb3cucGVuZG8/LnRyYWNrKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgcHJvcGVydGllczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgIGZsYWdfa2V5OiBmbGFnS2V5LFxuICAgICAgZmxhZ192YXJpYW50OiBldmFsdWF0aW9uRGV0YWlscy52YXJpYW50IHx8IFwidW5rbm93blwiLFxuICAgICAgZmxhZ19yZWFzb246IGV2YWx1YXRpb25EZXRhaWxzLnJlYXNvbiB8fCBcIlVOS05PV05cIixcbiAgICAgIGZsYWdfdmFsdWU6IHRoaXMuc3RyaW5naWZ5VmFsdWUoZXZhbHVhdGlvbkRldGFpbHMudmFsdWUpLFxuICAgICAgcHJvdmlkZXJfbmFtZTogaG9va0NvbnRleHQucHJvdmlkZXJNZXRhZGF0YS5uYW1lLFxuICAgIH07XG5cbiAgICAvLyBGaXJlLWFuZC1mb3JnZXQ6IGRlbGVnYXRlIHRvIFBlbmRvIGFnZW50XG4gICAgd2luZG93LnBlbmRvLnRyYWNrKHRoaXMub3B0aW9ucy5ldmVudE5hbWUsIHByb3BlcnRpZXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnQgYSBmbGFnIHZhbHVlIHRvIGEgc3RyaW5nIGZvciB0cmFja2luZy5cbiAgICovXG4gIHByaXZhdGUgc3RyaW5naWZ5VmFsdWUodmFsdWU6IEZsYWdWYWx1ZSk6IHN0cmluZyB7XG4gICAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgICByZXR1cm4gXCJudWxsXCI7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG4gICAgfVxuICAgIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICB9XG59XG4iXX0=
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PendoTelemetryHook = exports.PendoProvider = void 0;
|
|
4
|
+
var PendoProvider_1 = require("./PendoProvider");
|
|
5
|
+
Object.defineProperty(exports, "PendoProvider", { enumerable: true, get: function () { return PendoProvider_1.PendoProvider; } });
|
|
6
|
+
var PendoTelemetryHook_1 = require("./PendoTelemetryHook");
|
|
7
|
+
Object.defineProperty(exports, "PendoTelemetryHook", { enumerable: true, get: function () { return PendoTelemetryHook_1.PendoTelemetryHook; } });
|
|
8
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsaURBQWdEO0FBQXZDLDhHQUFBLGFBQWEsT0FBQTtBQUV0QiwyREFBMEQ7QUFBakQsd0hBQUEsa0JBQWtCLE9BQUEiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgeyBQZW5kb1Byb3ZpZGVyIH0gZnJvbSBcIi4vUGVuZG9Qcm92aWRlclwiO1xuZXhwb3J0IHR5cGUgeyBQZW5kb1Byb3ZpZGVyT3B0aW9ucyB9IGZyb20gXCIuL1BlbmRvUHJvdmlkZXJcIjtcbmV4cG9ydCB7IFBlbmRvVGVsZW1ldHJ5SG9vayB9IGZyb20gXCIuL1BlbmRvVGVsZW1ldHJ5SG9va1wiO1xuZXhwb3J0IHR5cGUgeyBQZW5kb1RlbGVtZXRyeUhvb2tPcHRpb25zIH0gZnJvbSBcIi4vUGVuZG9UZWxlbWV0cnlIb29rXCI7XG4iXX0=
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pendo/openfeature-web-provider",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "OpenFeature provider for Pendo feature flags (web/browser)",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"test": "jest",
|
|
14
|
+
"lint": "eslint src"
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"@openfeature/web-sdk": "^1.0.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@openfeature/web-sdk": "^1.0.0",
|
|
21
|
+
"@types/node": "^20.0.0",
|
|
22
|
+
"typescript": "^5.3.0"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"openfeature",
|
|
26
|
+
"feature-flags",
|
|
27
|
+
"pendo",
|
|
28
|
+
"provider"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/pendo-io/pendo-flags.git",
|
|
34
|
+
"directory": "packages/web-provider"
|
|
35
|
+
}
|
|
36
|
+
}
|