@miso.ai/client-sdk-core 1.13.0-beta.1 → 1.13.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/plugin/analytics.js +161 -0
- package/dist/cjs/plugin/index.js +7 -0
- package/dist/cjs/version.js +1 -1
- package/package.json +2 -2
- package/src/plugin/CLAUDE.md +106 -0
- package/src/plugin/analytics.js +185 -0
- package/src/plugin/index.js +1 -0
- package/src/version.js +1 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _commons = require("@miso.ai/commons");
|
|
8
|
+
function _objectDestructuringEmpty(t) { if (null == t) throw new TypeError("Cannot destructure " + t); }
|
|
9
|
+
const PLUGIN_ID = 'std:analytics';
|
|
10
|
+
class AnalyticsPlugin extends _commons.Component {
|
|
11
|
+
static get id() {
|
|
12
|
+
return PLUGIN_ID;
|
|
13
|
+
}
|
|
14
|
+
constructor() {
|
|
15
|
+
super('analytics');
|
|
16
|
+
this._members = [];
|
|
17
|
+
this._engagement = undefined;
|
|
18
|
+
}
|
|
19
|
+
config(options = {}) {
|
|
20
|
+
this._options = options;
|
|
21
|
+
for (const member of this._members) {
|
|
22
|
+
// notify update
|
|
23
|
+
// TODO: merge with global options
|
|
24
|
+
//member.config(options);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
install(MisoClient, context) {
|
|
28
|
+
context.addSubtree(this);
|
|
29
|
+
this._engagement = new _commons.UserEngagementObserver(this._handleEngagement.bind(this));
|
|
30
|
+
// TODO: should we provide a way to stop the observer?
|
|
31
|
+
MisoClient.on('create', this._injectClient.bind(this));
|
|
32
|
+
}
|
|
33
|
+
_injectClient(client) {
|
|
34
|
+
client.on('workflow', this._injectWorkflow.bind(this));
|
|
35
|
+
}
|
|
36
|
+
_injectWorkflow(workflow) {
|
|
37
|
+
workflow.analytics = new Analytics(this, workflow);
|
|
38
|
+
}
|
|
39
|
+
_handleEngagement() {
|
|
40
|
+
for (const member of this._members) {
|
|
41
|
+
member._syncEngagementState();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.default = AnalyticsPlugin;
|
|
46
|
+
function normalizeOptions(_ref = {}) {
|
|
47
|
+
let options = Object.assign({}, (_objectDestructuringEmpty(_ref), _ref));
|
|
48
|
+
return Object.assign({}, options);
|
|
49
|
+
}
|
|
50
|
+
function mergeTwoOptions(base, overrides) {
|
|
51
|
+
return Object.assign({}, base, overrides);
|
|
52
|
+
}
|
|
53
|
+
class Analytics {
|
|
54
|
+
constructor(plugin, workflow) {
|
|
55
|
+
this._plugin = plugin;
|
|
56
|
+
plugin._members.push(this);
|
|
57
|
+
this._workflow = workflow;
|
|
58
|
+
this._timer = new _commons.Stopwatch();
|
|
59
|
+
this._options = normalizeOptions();
|
|
60
|
+
this._injectWorkflow(workflow);
|
|
61
|
+
this._session = undefined;
|
|
62
|
+
this._startAt = undefined;
|
|
63
|
+
this._loadingAt = undefined;
|
|
64
|
+
this._readyAt = undefined;
|
|
65
|
+
this.config();
|
|
66
|
+
}
|
|
67
|
+
_injectWorkflow(workflow) {
|
|
68
|
+
this._listenToLiftcycleEvents(workflow);
|
|
69
|
+
this._injectProcessInteraction(workflow);
|
|
70
|
+
}
|
|
71
|
+
_listenToLiftcycleEvents(workflow) {
|
|
72
|
+
workflow.on('session', this._handleSession.bind(this));
|
|
73
|
+
workflow.on('loading', this._handleLoading.bind(this));
|
|
74
|
+
workflow.on('ready', this._handleReady.bind(this));
|
|
75
|
+
}
|
|
76
|
+
_injectProcessInteraction(workflow) {
|
|
77
|
+
// TODO: ad-hoc, find a way to provide plugin API in plugin root
|
|
78
|
+
workflow._pluginContext.processInteractionPasses.push(this._writeStateToInteraction.bind(this));
|
|
79
|
+
}
|
|
80
|
+
_handleSession(session) {
|
|
81
|
+
if (this._session && session.index === this._session.index) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (this._session) {
|
|
85
|
+
// send a last heartbeat event for the old session
|
|
86
|
+
this._sendHeartbeat();
|
|
87
|
+
}
|
|
88
|
+
this._session = session;
|
|
89
|
+
this._timer.reset();
|
|
90
|
+
this._startAt = Date.now();
|
|
91
|
+
this._loadingAt = undefined;
|
|
92
|
+
this._readyAt = undefined;
|
|
93
|
+
}
|
|
94
|
+
_handleLoading({
|
|
95
|
+
session
|
|
96
|
+
} = {}) {
|
|
97
|
+
this._loadingAt = Date.now();
|
|
98
|
+
}
|
|
99
|
+
_handleReady({
|
|
100
|
+
session
|
|
101
|
+
} = {}) {
|
|
102
|
+
this._readyAt = Date.now();
|
|
103
|
+
// start timer if user is engaged
|
|
104
|
+
this._syncEngagementState();
|
|
105
|
+
}
|
|
106
|
+
_sendHeartbeat() {
|
|
107
|
+
const tracker = this._workflow.trackers.container;
|
|
108
|
+
tracker && tracker.heartbeat();
|
|
109
|
+
}
|
|
110
|
+
_writeStateToInteraction(payload) {
|
|
111
|
+
const {
|
|
112
|
+
state
|
|
113
|
+
} = this;
|
|
114
|
+
return (0, _commons.mergeInteractions)(payload, {
|
|
115
|
+
context: {
|
|
116
|
+
custom_context: {
|
|
117
|
+
analytics_timestamp: state.timestamp,
|
|
118
|
+
user_engagement_time: state.userEngagementTime,
|
|
119
|
+
user_idle_time: state.userIdleTime,
|
|
120
|
+
user_waiting_time: state.userWaitingTime
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
config(options = {}) {
|
|
126
|
+
this._options = mergeTwoOptions(this._options, normalizeOptions(options));
|
|
127
|
+
}
|
|
128
|
+
get options() {
|
|
129
|
+
return Object.assign({}, this._options);
|
|
130
|
+
}
|
|
131
|
+
get state() {
|
|
132
|
+
const currentTime = Date.now();
|
|
133
|
+
const loadingAt = this._loadingAt;
|
|
134
|
+
const readyAt = this._readyAt;
|
|
135
|
+
let userEngagementTime = 0,
|
|
136
|
+
userIdleTime = 0,
|
|
137
|
+
userWaitingTime = 0;
|
|
138
|
+
if (loadingAt !== undefined) {
|
|
139
|
+
userWaitingTime = currentTime - loadingAt;
|
|
140
|
+
}
|
|
141
|
+
if (readyAt !== undefined) {
|
|
142
|
+
userWaitingTime = readyAt - loadingAt;
|
|
143
|
+
userEngagementTime = this._timer.getDuration(currentTime);
|
|
144
|
+
userIdleTime = currentTime - readyAt - userEngagementTime;
|
|
145
|
+
}
|
|
146
|
+
return (0, _commons.trimObj)({
|
|
147
|
+
timestamp: currentTime,
|
|
148
|
+
userWaitingTime,
|
|
149
|
+
userEngagementTime,
|
|
150
|
+
userIdleTime
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
_syncEngagementState() {
|
|
154
|
+
const shallStart = this._plugin._engagement.engaged;
|
|
155
|
+
if (shallStart) {
|
|
156
|
+
this._timer.start();
|
|
157
|
+
} else {
|
|
158
|
+
this._timer.stop();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
package/dist/cjs/plugin/index.js
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
Object.defineProperty(exports, "AnalyticsPlugin", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _analytics.default;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
6
12
|
Object.defineProperty(exports, "ApiPatchPlugin", {
|
|
7
13
|
enumerable: true,
|
|
8
14
|
get: function () {
|
|
@@ -52,4 +58,5 @@ var _interactions = _interopRequireDefault(require("./interactions.js"));
|
|
|
52
58
|
var _nativeFetch = _interopRequireDefault(require("./native-fetch.js"));
|
|
53
59
|
var _apiPatch = _interopRequireDefault(require("./api-patch.js"));
|
|
54
60
|
var _headerApiKey = _interopRequireDefault(require("./header-api-key.js"));
|
|
61
|
+
var _analytics = _interopRequireDefault(require("./analytics.js"));
|
|
55
62
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
package/dist/cjs/version.js
CHANGED
package/package.json
CHANGED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Plugin System
|
|
2
|
+
|
|
3
|
+
This directory contains the core plugin infrastructure and standard plugins for the Miso Client SDK.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
### PluginRoot (`plugin-root.js`)
|
|
8
|
+
|
|
9
|
+
The central registry that manages plugin lifecycle:
|
|
10
|
+
|
|
11
|
+
- **Registration**: `register(PluginClass)` - Makes a plugin available by its ID
|
|
12
|
+
- **Activation**: `use(id, options)` - Instantiates and installs a registered plugin
|
|
13
|
+
- **Installation**: `install(id, options)` - Combines register + use, supports remote loading for `std:*` plugins
|
|
14
|
+
|
|
15
|
+
### PluginContext
|
|
16
|
+
|
|
17
|
+
Exposed to plugins during `install()`, provides hooks into the SDK:
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
context.addPayloadPass(fn) // Modify API request payloads
|
|
21
|
+
context.addHeadersPass(fn) // Modify request headers
|
|
22
|
+
context.addUrlPass(fn) // Modify request URLs
|
|
23
|
+
context.setCustomFetch(fn) // Override fetch implementation
|
|
24
|
+
context.setCustomSendBeacon(fn) // Override sendBeacon
|
|
25
|
+
context.addSubtree(component) // Register as component subtree for event propagation
|
|
26
|
+
context.onHubUpdate(fn) // Listen to hub state updates
|
|
27
|
+
context.onHubEmit(fn) // Listen to hub emissions
|
|
28
|
+
context.whenInstalled(id) // Wait for another plugin
|
|
29
|
+
context.classes // Access to SDK classes
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Creating a Plugin
|
|
33
|
+
|
|
34
|
+
### Basic Structure
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
const PLUGIN_ID = 'std:my-plugin';
|
|
38
|
+
|
|
39
|
+
export default class MyPlugin {
|
|
40
|
+
static get id() {
|
|
41
|
+
return PLUGIN_ID;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Optional: extend Component for event support
|
|
45
|
+
// constructor() { super('my-plugin'); }
|
|
46
|
+
|
|
47
|
+
install(MisoClient, context) {
|
|
48
|
+
// Setup logic here
|
|
49
|
+
MisoClient.on('create', this._injectClient.bind(this));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Optional: allow runtime configuration
|
|
53
|
+
config(options) {
|
|
54
|
+
this._options = options;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
_injectClient(client) {
|
|
58
|
+
// Extend client instances
|
|
59
|
+
client.myFeature = new MyFeature(this, client);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Plugin Patterns
|
|
65
|
+
|
|
66
|
+
1. **Payload Modifier** (e.g., `context.js`, `interactions.js`): Intercept and modify API payloads
|
|
67
|
+
2. **Client Injector**: Add properties/methods to each MisoClient instance
|
|
68
|
+
3. **Component-based** (extend `Component`): For plugins needing event emission and subtree registration
|
|
69
|
+
|
|
70
|
+
## Standard Plugins
|
|
71
|
+
|
|
72
|
+
| Plugin | ID | Purpose |
|
|
73
|
+
|--------|-----|---------|
|
|
74
|
+
| `ContextPlugin` | `std:context` | User identity (anonymous_id, user_id, site) |
|
|
75
|
+
| `PageInfoPlugin` | `std:page-info` | Adds page metadata to requests |
|
|
76
|
+
| `AutoEventsPlugin` | `std:auto-events` | Automatic interaction tracking |
|
|
77
|
+
| `InteractionsPlugin` | `std:interactions` | Enriches interaction records with SDK version/UUID |
|
|
78
|
+
| `NativeFetchPlugin` | `std:native-fetch` | Uses native fetch, bypassing custom implementations |
|
|
79
|
+
| `ApiPatchPlugin` | `std:api-patch` | Applies patches to API responses |
|
|
80
|
+
| `HeaderApiKeyPlugin` | `std:header-api-key` | Sends API key in header instead of query |
|
|
81
|
+
| `AnalyticsPlugin` | `std:analytics` | User engagement timing and analytics |
|
|
82
|
+
|
|
83
|
+
## Pass Functions
|
|
84
|
+
|
|
85
|
+
Pass functions receive a context object and return modified values:
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
// Payload pass signature
|
|
89
|
+
function modifyPayload({ client, apiGroup, apiName, payload }) {
|
|
90
|
+
// apiGroup: 'search', 'ask', 'interactions', etc.
|
|
91
|
+
// apiName: 'search', 'upload', 'questions', etc.
|
|
92
|
+
return modifiedPayload;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Headers pass signature
|
|
96
|
+
function modifyHeaders({ client, headers }) {
|
|
97
|
+
return { ...headers, 'X-Custom': 'value' };
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Lifecycle
|
|
102
|
+
|
|
103
|
+
1. `register()` - Plugin class stored by ID
|
|
104
|
+
2. `use()` - Plugin instantiated, `config()` called if options provided
|
|
105
|
+
3. `install()` - Plugin's `install(MisoClient, context)` called
|
|
106
|
+
4. `MisoClient.on('create')` - Hook to extend new client instances
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { Component, UserEngagementObserver, Stopwatch, trimObj, mergeInteractions } from '@miso.ai/commons';
|
|
2
|
+
|
|
3
|
+
const PLUGIN_ID = 'std:analytics';
|
|
4
|
+
|
|
5
|
+
export default class AnalyticsPlugin extends Component {
|
|
6
|
+
|
|
7
|
+
static get id() {
|
|
8
|
+
return PLUGIN_ID;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
constructor() {
|
|
12
|
+
super('analytics');
|
|
13
|
+
this._members = [];
|
|
14
|
+
this._engagement = undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
config(options = {}) {
|
|
18
|
+
this._options = options;
|
|
19
|
+
for (const member of this._members) {
|
|
20
|
+
// notify update
|
|
21
|
+
// TODO: merge with global options
|
|
22
|
+
//member.config(options);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
install(MisoClient, context) {
|
|
27
|
+
context.addSubtree(this);
|
|
28
|
+
this._engagement = new UserEngagementObserver(this._handleEngagement.bind(this));
|
|
29
|
+
// TODO: should we provide a way to stop the observer?
|
|
30
|
+
MisoClient.on('create', this._injectClient.bind(this));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
_injectClient(client) {
|
|
34
|
+
client.on('workflow', this._injectWorkflow.bind(this));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
_injectWorkflow(workflow) {
|
|
38
|
+
workflow.analytics = new Analytics(this, workflow);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
_handleEngagement() {
|
|
42
|
+
for (const member of this._members) {
|
|
43
|
+
member._syncEngagementState();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function normalizeOptions({ ...options } = {}) {
|
|
50
|
+
return {
|
|
51
|
+
...options,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function mergeTwoOptions(base, overrides) {
|
|
56
|
+
return {
|
|
57
|
+
...base,
|
|
58
|
+
...overrides,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
class Analytics {
|
|
63
|
+
|
|
64
|
+
constructor(plugin, workflow) {
|
|
65
|
+
this._plugin = plugin;
|
|
66
|
+
plugin._members.push(this);
|
|
67
|
+
this._workflow = workflow;
|
|
68
|
+
this._timer = new Stopwatch();
|
|
69
|
+
this._options = normalizeOptions();
|
|
70
|
+
|
|
71
|
+
this._injectWorkflow(workflow);
|
|
72
|
+
|
|
73
|
+
this._session = undefined;
|
|
74
|
+
this._startAt = undefined;
|
|
75
|
+
this._loadingAt = undefined;
|
|
76
|
+
this._readyAt = undefined;
|
|
77
|
+
|
|
78
|
+
this.config();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
_injectWorkflow(workflow) {
|
|
82
|
+
this._listenToLiftcycleEvents(workflow);
|
|
83
|
+
this._injectProcessInteraction(workflow);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
_listenToLiftcycleEvents(workflow) {
|
|
87
|
+
workflow.on('session', this._handleSession.bind(this));
|
|
88
|
+
workflow.on('loading', this._handleLoading.bind(this));
|
|
89
|
+
workflow.on('ready', this._handleReady.bind(this));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
_injectProcessInteraction(workflow) {
|
|
93
|
+
// TODO: ad-hoc, find a way to provide plugin API in plugin root
|
|
94
|
+
workflow._pluginContext.processInteractionPasses.push(this._writeStateToInteraction.bind(this));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
_handleSession(session) {
|
|
98
|
+
if (this._session && session.index === this._session.index) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (this._session) {
|
|
103
|
+
// send a last heartbeat event for the old session
|
|
104
|
+
this._sendHeartbeat();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
this._session = session;
|
|
108
|
+
this._timer.reset();
|
|
109
|
+
this._startAt = Date.now();
|
|
110
|
+
this._loadingAt = undefined;
|
|
111
|
+
this._readyAt = undefined;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
_handleLoading({ session } = {}) {
|
|
115
|
+
this._loadingAt = Date.now();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
_handleReady({ session } = {}) {
|
|
119
|
+
this._readyAt = Date.now();
|
|
120
|
+
// start timer if user is engaged
|
|
121
|
+
this._syncEngagementState();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
_sendHeartbeat() {
|
|
125
|
+
const tracker = this._workflow.trackers.container;
|
|
126
|
+
tracker && tracker.heartbeat();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
_writeStateToInteraction(payload) {
|
|
130
|
+
const { state } = this;
|
|
131
|
+
return mergeInteractions(payload, {
|
|
132
|
+
context: {
|
|
133
|
+
custom_context: {
|
|
134
|
+
analytics_timestamp: state.timestamp,
|
|
135
|
+
user_engagement_time: state.userEngagementTime,
|
|
136
|
+
user_idle_time: state.userIdleTime,
|
|
137
|
+
user_waiting_time: state.userWaitingTime,
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
config(options = {}) {
|
|
144
|
+
this._options = mergeTwoOptions(this._options, normalizeOptions(options));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
get options() {
|
|
148
|
+
return {
|
|
149
|
+
...this._options,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
get state() {
|
|
154
|
+
const currentTime = Date.now();
|
|
155
|
+
const loadingAt = this._loadingAt;
|
|
156
|
+
const readyAt = this._readyAt;
|
|
157
|
+
let userEngagementTime = 0, userIdleTime = 0, userWaitingTime = 0;
|
|
158
|
+
|
|
159
|
+
if (loadingAt !== undefined) {
|
|
160
|
+
userWaitingTime = currentTime - loadingAt;
|
|
161
|
+
}
|
|
162
|
+
if (readyAt !== undefined) {
|
|
163
|
+
userWaitingTime = readyAt - loadingAt;
|
|
164
|
+
userEngagementTime = this._timer.getDuration(currentTime);
|
|
165
|
+
userIdleTime = currentTime - readyAt - userEngagementTime;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return trimObj({
|
|
169
|
+
timestamp: currentTime,
|
|
170
|
+
userWaitingTime,
|
|
171
|
+
userEngagementTime,
|
|
172
|
+
userIdleTime,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
_syncEngagementState() {
|
|
177
|
+
const shallStart = this._plugin._engagement.engaged;
|
|
178
|
+
if (shallStart) {
|
|
179
|
+
this._timer.start();
|
|
180
|
+
} else {
|
|
181
|
+
this._timer.stop();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
}
|
package/src/plugin/index.js
CHANGED
|
@@ -5,3 +5,4 @@ export { default as InteractionsPlugin } from './interactions.js';
|
|
|
5
5
|
export { default as NativeFetchPlugin } from './native-fetch.js';
|
|
6
6
|
export { default as ApiPatchPlugin } from './api-patch.js';
|
|
7
7
|
export { default as HeaderApiKeyPlugin } from './header-api-key.js';
|
|
8
|
+
export { default as AnalyticsPlugin } from './analytics.js';
|
package/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '1.13.0-beta.
|
|
1
|
+
export default '1.13.0-beta.2';
|