@blotoutio/providers-dataflywheel-sdk 1.63.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 +5 -0
- package/index.cjs.js +202 -0
- package/index.d.ts +1 -0
- package/index.js +205 -0
- package/index.mjs +200 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# DataFlywheel Browser SDK
|
|
2
|
+
|
|
3
|
+
Browser helper loaded by EdgeTag for DataFlywheel session bootstrap.
|
|
4
|
+
|
|
5
|
+
It calls the DataFlywheel global worker `/v1/session` directly with credentialed fetches. EdgeTag delivers this helper and forwards event payloads, but it does not mint or decide DataFlywheel sessions.
|
package/index.cjs.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const packageName = 'dataFlywheel';
|
|
4
|
+
const sessionStateKeyPrefix = 'dfw_sdk_state';
|
|
5
|
+
const sessionBootstrapPath = 'v1/session';
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
8
|
+
// Coalesces concurrent cold bootstraps per merchant: events firing in the same
|
|
9
|
+
// tick share one in-flight /v1/session call instead of racing N handshakes.
|
|
10
|
+
const inFlight = new Map();
|
|
11
|
+
const memoryStates = new Map();
|
|
12
|
+
const stringValue = (value) => typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
13
|
+
const numberValue = (value) => typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
14
|
+
const isEnabledFlag = (value, defaultValue = true) => {
|
|
15
|
+
if (value == null || value === '')
|
|
16
|
+
return defaultValue;
|
|
17
|
+
return value !== '0' && value.toLowerCase() !== 'false';
|
|
18
|
+
};
|
|
19
|
+
const shouldBootstrap = (now, expiresAt) => expiresAt == null || now >= expiresAt;
|
|
20
|
+
const stateKey = (merchantId) => `${sessionStateKeyPrefix}:${merchantId}`;
|
|
21
|
+
const browserStorage = () => {
|
|
22
|
+
var _a;
|
|
23
|
+
try {
|
|
24
|
+
if (typeof window === 'undefined')
|
|
25
|
+
return null;
|
|
26
|
+
return (_a = window.sessionStorage) !== null && _a !== void 0 ? _a : null;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const sessionStorageFor = (storage) => (storage === undefined ? browserStorage() : storage);
|
|
33
|
+
const readSessionState = (storage, merchantId) => {
|
|
34
|
+
var _a;
|
|
35
|
+
const key = stateKey(merchantId);
|
|
36
|
+
const fallback = () => { var _a; return (_a = memoryStates.get(key)) !== null && _a !== void 0 ? _a : null; };
|
|
37
|
+
if (!storage)
|
|
38
|
+
return fallback();
|
|
39
|
+
try {
|
|
40
|
+
const raw = storage.getItem(key);
|
|
41
|
+
if (!raw)
|
|
42
|
+
return fallback();
|
|
43
|
+
const parsed = JSON.parse(raw);
|
|
44
|
+
const nId = stringValue(parsed.n_id);
|
|
45
|
+
const sessionId = stringValue(parsed.session_id);
|
|
46
|
+
const expiresAt = stringValue(parsed.expires_at);
|
|
47
|
+
if (!nId || !sessionId || !expiresAt)
|
|
48
|
+
return fallback();
|
|
49
|
+
return {
|
|
50
|
+
n_id: nId,
|
|
51
|
+
session_id: sessionId,
|
|
52
|
+
expires_at: expiresAt,
|
|
53
|
+
last_touch_at: (_a = numberValue(parsed.last_touch_at)) !== null && _a !== void 0 ? _a : 0,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return fallback();
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const writeSessionState = (storage, merchantId, state) => {
|
|
61
|
+
const key = stateKey(merchantId);
|
|
62
|
+
if (!storage) {
|
|
63
|
+
memoryStates.set(key, state);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
storage.setItem(key, JSON.stringify(state));
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
memoryStates.set(key, state);
|
|
71
|
+
// Storage can be disabled or full. The worker cookies remain authoritative.
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
function expiresAtMs(state) {
|
|
75
|
+
if (!state)
|
|
76
|
+
return null;
|
|
77
|
+
const expiresAt = Date.parse(state.expires_at);
|
|
78
|
+
return Number.isFinite(expiresAt) ? expiresAt : null;
|
|
79
|
+
}
|
|
80
|
+
function bootstrapUrl(input) {
|
|
81
|
+
const base = input.dataFlywheelUrl.endsWith('/')
|
|
82
|
+
? input.dataFlywheelUrl
|
|
83
|
+
: `${input.dataFlywheelUrl}/`;
|
|
84
|
+
const url = new URL(sessionBootstrapPath, base);
|
|
85
|
+
url.searchParams.set('merchant_id', input.merchantId);
|
|
86
|
+
const pageUrl = stringValue(input.pageUrl);
|
|
87
|
+
if (pageUrl) {
|
|
88
|
+
url.searchParams.set('page_url', pageUrl);
|
|
89
|
+
}
|
|
90
|
+
return url.toString();
|
|
91
|
+
}
|
|
92
|
+
function parseBootstrapResponse(body, now) {
|
|
93
|
+
var _a, _b;
|
|
94
|
+
const nId = stringValue(body.n_id);
|
|
95
|
+
const sessionId = stringValue((_a = body.session) === null || _a === void 0 ? void 0 : _a.session_id);
|
|
96
|
+
const expiresAt = stringValue((_b = body.session) === null || _b === void 0 ? void 0 : _b.expires_at);
|
|
97
|
+
if (!nId || !sessionId || !expiresAt)
|
|
98
|
+
return null;
|
|
99
|
+
return {
|
|
100
|
+
n_id: nId,
|
|
101
|
+
session_id: sessionId,
|
|
102
|
+
expires_at: expiresAt,
|
|
103
|
+
last_touch_at: now,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async function bootstrapSession(input) {
|
|
107
|
+
try {
|
|
108
|
+
const response = await input.fetcher(bootstrapUrl({
|
|
109
|
+
dataFlywheelUrl: input.dataFlywheelUrl,
|
|
110
|
+
merchantId: input.merchantId,
|
|
111
|
+
pageUrl: input.pageUrl,
|
|
112
|
+
}), { credentials: 'include' });
|
|
113
|
+
if (!response.ok)
|
|
114
|
+
return null;
|
|
115
|
+
const state = parseBootstrapResponse((await response.json()), input.now);
|
|
116
|
+
if (!state)
|
|
117
|
+
return null;
|
|
118
|
+
writeSessionState(input.storage, input.merchantId, state);
|
|
119
|
+
return state;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function ensureSession(input) {
|
|
126
|
+
var _a, _b, _c, _d;
|
|
127
|
+
const variables = (_a = input.variables) !== null && _a !== void 0 ? _a : {};
|
|
128
|
+
const dataFlywheelUrl = stringValue(variables.dataFlywheelUrl);
|
|
129
|
+
const merchantId = stringValue(variables.merchantId);
|
|
130
|
+
if (!dataFlywheelUrl ||
|
|
131
|
+
!merchantId ||
|
|
132
|
+
!isEnabledFlag(variables.dataFlywheelSessionEnabled)) {
|
|
133
|
+
return Promise.resolve(null);
|
|
134
|
+
}
|
|
135
|
+
const storage = sessionStorageFor(input.storage);
|
|
136
|
+
const now = (_c = (_b = input.now) === null || _b === void 0 ? void 0 : _b.call(input)) !== null && _c !== void 0 ? _c : Date.now();
|
|
137
|
+
const existing = readSessionState(storage, merchantId);
|
|
138
|
+
if (!shouldBootstrap(now, expiresAtMs(existing))) {
|
|
139
|
+
return Promise.resolve(existing);
|
|
140
|
+
}
|
|
141
|
+
const key = stateKey(merchantId);
|
|
142
|
+
const existingBootstrap = inFlight.get(key);
|
|
143
|
+
if (existingBootstrap)
|
|
144
|
+
return existingBootstrap;
|
|
145
|
+
const fetcher = (_d = input.fetcher) !== null && _d !== void 0 ? _d : (typeof fetch === 'function' ? fetch.bind(globalThis) : null);
|
|
146
|
+
if (!fetcher)
|
|
147
|
+
return Promise.resolve(null);
|
|
148
|
+
const bootstrap = bootstrapSession({
|
|
149
|
+
dataFlywheelUrl,
|
|
150
|
+
merchantId,
|
|
151
|
+
pageUrl: input.pageUrl,
|
|
152
|
+
storage,
|
|
153
|
+
fetcher,
|
|
154
|
+
now,
|
|
155
|
+
}).finally(() => {
|
|
156
|
+
inFlight.delete(key);
|
|
157
|
+
});
|
|
158
|
+
inFlight.set(key, bootstrap);
|
|
159
|
+
return bootstrap;
|
|
160
|
+
}
|
|
161
|
+
function toProviderData(state) {
|
|
162
|
+
if (!state)
|
|
163
|
+
return {};
|
|
164
|
+
return {
|
|
165
|
+
n_id: state.n_id,
|
|
166
|
+
session_id: state.session_id,
|
|
167
|
+
expires_at: state.expires_at,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const init = (params) => {
|
|
172
|
+
void ensureSession({
|
|
173
|
+
variables: params.manifest.variables,
|
|
174
|
+
pageUrl: params.pageUrl,
|
|
175
|
+
});
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const tag = async ({ manifestVariables, pageUrl, }) => {
|
|
179
|
+
const state = await ensureSession({
|
|
180
|
+
variables: manifestVariables,
|
|
181
|
+
pageUrl,
|
|
182
|
+
});
|
|
183
|
+
return toProviderData(state);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
187
|
+
const data = {
|
|
188
|
+
name: packageName,
|
|
189
|
+
init,
|
|
190
|
+
tag,
|
|
191
|
+
};
|
|
192
|
+
try {
|
|
193
|
+
if (typeof window !== 'undefined') {
|
|
194
|
+
window.edgetagProviders = window.edgetagProviders || [];
|
|
195
|
+
window.edgetagProviders.push(data);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
// no window
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
module.exports = data;
|
package/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
package/index.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
var ProvidersDataflywheelSdk = (function () {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const packageName = 'dataFlywheel';
|
|
5
|
+
const sessionStateKeyPrefix = 'dfw_sdk_state';
|
|
6
|
+
const sessionBootstrapPath = 'v1/session';
|
|
7
|
+
|
|
8
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
9
|
+
// Coalesces concurrent cold bootstraps per merchant: events firing in the same
|
|
10
|
+
// tick share one in-flight /v1/session call instead of racing N handshakes.
|
|
11
|
+
const inFlight = new Map();
|
|
12
|
+
const memoryStates = new Map();
|
|
13
|
+
const stringValue = (value) => typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
14
|
+
const numberValue = (value) => typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
15
|
+
const isEnabledFlag = (value, defaultValue = true) => {
|
|
16
|
+
if (value == null || value === '')
|
|
17
|
+
return defaultValue;
|
|
18
|
+
return value !== '0' && value.toLowerCase() !== 'false';
|
|
19
|
+
};
|
|
20
|
+
const shouldBootstrap = (now, expiresAt) => expiresAt == null || now >= expiresAt;
|
|
21
|
+
const stateKey = (merchantId) => `${sessionStateKeyPrefix}:${merchantId}`;
|
|
22
|
+
const browserStorage = () => {
|
|
23
|
+
var _a;
|
|
24
|
+
try {
|
|
25
|
+
if (typeof window === 'undefined')
|
|
26
|
+
return null;
|
|
27
|
+
return (_a = window.sessionStorage) !== null && _a !== void 0 ? _a : null;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const sessionStorageFor = (storage) => (storage === undefined ? browserStorage() : storage);
|
|
34
|
+
const readSessionState = (storage, merchantId) => {
|
|
35
|
+
var _a;
|
|
36
|
+
const key = stateKey(merchantId);
|
|
37
|
+
const fallback = () => { var _a; return (_a = memoryStates.get(key)) !== null && _a !== void 0 ? _a : null; };
|
|
38
|
+
if (!storage)
|
|
39
|
+
return fallback();
|
|
40
|
+
try {
|
|
41
|
+
const raw = storage.getItem(key);
|
|
42
|
+
if (!raw)
|
|
43
|
+
return fallback();
|
|
44
|
+
const parsed = JSON.parse(raw);
|
|
45
|
+
const nId = stringValue(parsed.n_id);
|
|
46
|
+
const sessionId = stringValue(parsed.session_id);
|
|
47
|
+
const expiresAt = stringValue(parsed.expires_at);
|
|
48
|
+
if (!nId || !sessionId || !expiresAt)
|
|
49
|
+
return fallback();
|
|
50
|
+
return {
|
|
51
|
+
n_id: nId,
|
|
52
|
+
session_id: sessionId,
|
|
53
|
+
expires_at: expiresAt,
|
|
54
|
+
last_touch_at: (_a = numberValue(parsed.last_touch_at)) !== null && _a !== void 0 ? _a : 0,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return fallback();
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const writeSessionState = (storage, merchantId, state) => {
|
|
62
|
+
const key = stateKey(merchantId);
|
|
63
|
+
if (!storage) {
|
|
64
|
+
memoryStates.set(key, state);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
storage.setItem(key, JSON.stringify(state));
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
memoryStates.set(key, state);
|
|
72
|
+
// Storage can be disabled or full. The worker cookies remain authoritative.
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
function expiresAtMs(state) {
|
|
76
|
+
if (!state)
|
|
77
|
+
return null;
|
|
78
|
+
const expiresAt = Date.parse(state.expires_at);
|
|
79
|
+
return Number.isFinite(expiresAt) ? expiresAt : null;
|
|
80
|
+
}
|
|
81
|
+
function bootstrapUrl(input) {
|
|
82
|
+
const base = input.dataFlywheelUrl.endsWith('/')
|
|
83
|
+
? input.dataFlywheelUrl
|
|
84
|
+
: `${input.dataFlywheelUrl}/`;
|
|
85
|
+
const url = new URL(sessionBootstrapPath, base);
|
|
86
|
+
url.searchParams.set('merchant_id', input.merchantId);
|
|
87
|
+
const pageUrl = stringValue(input.pageUrl);
|
|
88
|
+
if (pageUrl) {
|
|
89
|
+
url.searchParams.set('page_url', pageUrl);
|
|
90
|
+
}
|
|
91
|
+
return url.toString();
|
|
92
|
+
}
|
|
93
|
+
function parseBootstrapResponse(body, now) {
|
|
94
|
+
var _a, _b;
|
|
95
|
+
const nId = stringValue(body.n_id);
|
|
96
|
+
const sessionId = stringValue((_a = body.session) === null || _a === void 0 ? void 0 : _a.session_id);
|
|
97
|
+
const expiresAt = stringValue((_b = body.session) === null || _b === void 0 ? void 0 : _b.expires_at);
|
|
98
|
+
if (!nId || !sessionId || !expiresAt)
|
|
99
|
+
return null;
|
|
100
|
+
return {
|
|
101
|
+
n_id: nId,
|
|
102
|
+
session_id: sessionId,
|
|
103
|
+
expires_at: expiresAt,
|
|
104
|
+
last_touch_at: now,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
async function bootstrapSession(input) {
|
|
108
|
+
try {
|
|
109
|
+
const response = await input.fetcher(bootstrapUrl({
|
|
110
|
+
dataFlywheelUrl: input.dataFlywheelUrl,
|
|
111
|
+
merchantId: input.merchantId,
|
|
112
|
+
pageUrl: input.pageUrl,
|
|
113
|
+
}), { credentials: 'include' });
|
|
114
|
+
if (!response.ok)
|
|
115
|
+
return null;
|
|
116
|
+
const state = parseBootstrapResponse((await response.json()), input.now);
|
|
117
|
+
if (!state)
|
|
118
|
+
return null;
|
|
119
|
+
writeSessionState(input.storage, input.merchantId, state);
|
|
120
|
+
return state;
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function ensureSession(input) {
|
|
127
|
+
var _a, _b, _c, _d;
|
|
128
|
+
const variables = (_a = input.variables) !== null && _a !== void 0 ? _a : {};
|
|
129
|
+
const dataFlywheelUrl = stringValue(variables.dataFlywheelUrl);
|
|
130
|
+
const merchantId = stringValue(variables.merchantId);
|
|
131
|
+
if (!dataFlywheelUrl ||
|
|
132
|
+
!merchantId ||
|
|
133
|
+
!isEnabledFlag(variables.dataFlywheelSessionEnabled)) {
|
|
134
|
+
return Promise.resolve(null);
|
|
135
|
+
}
|
|
136
|
+
const storage = sessionStorageFor(input.storage);
|
|
137
|
+
const now = (_c = (_b = input.now) === null || _b === void 0 ? void 0 : _b.call(input)) !== null && _c !== void 0 ? _c : Date.now();
|
|
138
|
+
const existing = readSessionState(storage, merchantId);
|
|
139
|
+
if (!shouldBootstrap(now, expiresAtMs(existing))) {
|
|
140
|
+
return Promise.resolve(existing);
|
|
141
|
+
}
|
|
142
|
+
const key = stateKey(merchantId);
|
|
143
|
+
const existingBootstrap = inFlight.get(key);
|
|
144
|
+
if (existingBootstrap)
|
|
145
|
+
return existingBootstrap;
|
|
146
|
+
const fetcher = (_d = input.fetcher) !== null && _d !== void 0 ? _d : (typeof fetch === 'function' ? fetch.bind(globalThis) : null);
|
|
147
|
+
if (!fetcher)
|
|
148
|
+
return Promise.resolve(null);
|
|
149
|
+
const bootstrap = bootstrapSession({
|
|
150
|
+
dataFlywheelUrl,
|
|
151
|
+
merchantId,
|
|
152
|
+
pageUrl: input.pageUrl,
|
|
153
|
+
storage,
|
|
154
|
+
fetcher,
|
|
155
|
+
now,
|
|
156
|
+
}).finally(() => {
|
|
157
|
+
inFlight.delete(key);
|
|
158
|
+
});
|
|
159
|
+
inFlight.set(key, bootstrap);
|
|
160
|
+
return bootstrap;
|
|
161
|
+
}
|
|
162
|
+
function toProviderData(state) {
|
|
163
|
+
if (!state)
|
|
164
|
+
return {};
|
|
165
|
+
return {
|
|
166
|
+
n_id: state.n_id,
|
|
167
|
+
session_id: state.session_id,
|
|
168
|
+
expires_at: state.expires_at,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const init = (params) => {
|
|
173
|
+
void ensureSession({
|
|
174
|
+
variables: params.manifest.variables,
|
|
175
|
+
pageUrl: params.pageUrl,
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const tag = async ({ manifestVariables, pageUrl, }) => {
|
|
180
|
+
const state = await ensureSession({
|
|
181
|
+
variables: manifestVariables,
|
|
182
|
+
pageUrl,
|
|
183
|
+
});
|
|
184
|
+
return toProviderData(state);
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
188
|
+
const data = {
|
|
189
|
+
name: packageName,
|
|
190
|
+
init,
|
|
191
|
+
tag,
|
|
192
|
+
};
|
|
193
|
+
try {
|
|
194
|
+
if (typeof window !== 'undefined') {
|
|
195
|
+
window.edgetagProviders = window.edgetagProviders || [];
|
|
196
|
+
window.edgetagProviders.push(data);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// no window
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return data;
|
|
204
|
+
|
|
205
|
+
})();
|
package/index.mjs
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
const packageName = 'dataFlywheel';
|
|
2
|
+
const sessionStateKeyPrefix = 'dfw_sdk_state';
|
|
3
|
+
const sessionBootstrapPath = 'v1/session';
|
|
4
|
+
|
|
5
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
6
|
+
// Coalesces concurrent cold bootstraps per merchant: events firing in the same
|
|
7
|
+
// tick share one in-flight /v1/session call instead of racing N handshakes.
|
|
8
|
+
const inFlight = new Map();
|
|
9
|
+
const memoryStates = new Map();
|
|
10
|
+
const stringValue = (value) => typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
11
|
+
const numberValue = (value) => typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
12
|
+
const isEnabledFlag = (value, defaultValue = true) => {
|
|
13
|
+
if (value == null || value === '')
|
|
14
|
+
return defaultValue;
|
|
15
|
+
return value !== '0' && value.toLowerCase() !== 'false';
|
|
16
|
+
};
|
|
17
|
+
const shouldBootstrap = (now, expiresAt) => expiresAt == null || now >= expiresAt;
|
|
18
|
+
const stateKey = (merchantId) => `${sessionStateKeyPrefix}:${merchantId}`;
|
|
19
|
+
const browserStorage = () => {
|
|
20
|
+
var _a;
|
|
21
|
+
try {
|
|
22
|
+
if (typeof window === 'undefined')
|
|
23
|
+
return null;
|
|
24
|
+
return (_a = window.sessionStorage) !== null && _a !== void 0 ? _a : null;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const sessionStorageFor = (storage) => (storage === undefined ? browserStorage() : storage);
|
|
31
|
+
const readSessionState = (storage, merchantId) => {
|
|
32
|
+
var _a;
|
|
33
|
+
const key = stateKey(merchantId);
|
|
34
|
+
const fallback = () => { var _a; return (_a = memoryStates.get(key)) !== null && _a !== void 0 ? _a : null; };
|
|
35
|
+
if (!storage)
|
|
36
|
+
return fallback();
|
|
37
|
+
try {
|
|
38
|
+
const raw = storage.getItem(key);
|
|
39
|
+
if (!raw)
|
|
40
|
+
return fallback();
|
|
41
|
+
const parsed = JSON.parse(raw);
|
|
42
|
+
const nId = stringValue(parsed.n_id);
|
|
43
|
+
const sessionId = stringValue(parsed.session_id);
|
|
44
|
+
const expiresAt = stringValue(parsed.expires_at);
|
|
45
|
+
if (!nId || !sessionId || !expiresAt)
|
|
46
|
+
return fallback();
|
|
47
|
+
return {
|
|
48
|
+
n_id: nId,
|
|
49
|
+
session_id: sessionId,
|
|
50
|
+
expires_at: expiresAt,
|
|
51
|
+
last_touch_at: (_a = numberValue(parsed.last_touch_at)) !== null && _a !== void 0 ? _a : 0,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return fallback();
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const writeSessionState = (storage, merchantId, state) => {
|
|
59
|
+
const key = stateKey(merchantId);
|
|
60
|
+
if (!storage) {
|
|
61
|
+
memoryStates.set(key, state);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
storage.setItem(key, JSON.stringify(state));
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
memoryStates.set(key, state);
|
|
69
|
+
// Storage can be disabled or full. The worker cookies remain authoritative.
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
function expiresAtMs(state) {
|
|
73
|
+
if (!state)
|
|
74
|
+
return null;
|
|
75
|
+
const expiresAt = Date.parse(state.expires_at);
|
|
76
|
+
return Number.isFinite(expiresAt) ? expiresAt : null;
|
|
77
|
+
}
|
|
78
|
+
function bootstrapUrl(input) {
|
|
79
|
+
const base = input.dataFlywheelUrl.endsWith('/')
|
|
80
|
+
? input.dataFlywheelUrl
|
|
81
|
+
: `${input.dataFlywheelUrl}/`;
|
|
82
|
+
const url = new URL(sessionBootstrapPath, base);
|
|
83
|
+
url.searchParams.set('merchant_id', input.merchantId);
|
|
84
|
+
const pageUrl = stringValue(input.pageUrl);
|
|
85
|
+
if (pageUrl) {
|
|
86
|
+
url.searchParams.set('page_url', pageUrl);
|
|
87
|
+
}
|
|
88
|
+
return url.toString();
|
|
89
|
+
}
|
|
90
|
+
function parseBootstrapResponse(body, now) {
|
|
91
|
+
var _a, _b;
|
|
92
|
+
const nId = stringValue(body.n_id);
|
|
93
|
+
const sessionId = stringValue((_a = body.session) === null || _a === void 0 ? void 0 : _a.session_id);
|
|
94
|
+
const expiresAt = stringValue((_b = body.session) === null || _b === void 0 ? void 0 : _b.expires_at);
|
|
95
|
+
if (!nId || !sessionId || !expiresAt)
|
|
96
|
+
return null;
|
|
97
|
+
return {
|
|
98
|
+
n_id: nId,
|
|
99
|
+
session_id: sessionId,
|
|
100
|
+
expires_at: expiresAt,
|
|
101
|
+
last_touch_at: now,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
async function bootstrapSession(input) {
|
|
105
|
+
try {
|
|
106
|
+
const response = await input.fetcher(bootstrapUrl({
|
|
107
|
+
dataFlywheelUrl: input.dataFlywheelUrl,
|
|
108
|
+
merchantId: input.merchantId,
|
|
109
|
+
pageUrl: input.pageUrl,
|
|
110
|
+
}), { credentials: 'include' });
|
|
111
|
+
if (!response.ok)
|
|
112
|
+
return null;
|
|
113
|
+
const state = parseBootstrapResponse((await response.json()), input.now);
|
|
114
|
+
if (!state)
|
|
115
|
+
return null;
|
|
116
|
+
writeSessionState(input.storage, input.merchantId, state);
|
|
117
|
+
return state;
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function ensureSession(input) {
|
|
124
|
+
var _a, _b, _c, _d;
|
|
125
|
+
const variables = (_a = input.variables) !== null && _a !== void 0 ? _a : {};
|
|
126
|
+
const dataFlywheelUrl = stringValue(variables.dataFlywheelUrl);
|
|
127
|
+
const merchantId = stringValue(variables.merchantId);
|
|
128
|
+
if (!dataFlywheelUrl ||
|
|
129
|
+
!merchantId ||
|
|
130
|
+
!isEnabledFlag(variables.dataFlywheelSessionEnabled)) {
|
|
131
|
+
return Promise.resolve(null);
|
|
132
|
+
}
|
|
133
|
+
const storage = sessionStorageFor(input.storage);
|
|
134
|
+
const now = (_c = (_b = input.now) === null || _b === void 0 ? void 0 : _b.call(input)) !== null && _c !== void 0 ? _c : Date.now();
|
|
135
|
+
const existing = readSessionState(storage, merchantId);
|
|
136
|
+
if (!shouldBootstrap(now, expiresAtMs(existing))) {
|
|
137
|
+
return Promise.resolve(existing);
|
|
138
|
+
}
|
|
139
|
+
const key = stateKey(merchantId);
|
|
140
|
+
const existingBootstrap = inFlight.get(key);
|
|
141
|
+
if (existingBootstrap)
|
|
142
|
+
return existingBootstrap;
|
|
143
|
+
const fetcher = (_d = input.fetcher) !== null && _d !== void 0 ? _d : (typeof fetch === 'function' ? fetch.bind(globalThis) : null);
|
|
144
|
+
if (!fetcher)
|
|
145
|
+
return Promise.resolve(null);
|
|
146
|
+
const bootstrap = bootstrapSession({
|
|
147
|
+
dataFlywheelUrl,
|
|
148
|
+
merchantId,
|
|
149
|
+
pageUrl: input.pageUrl,
|
|
150
|
+
storage,
|
|
151
|
+
fetcher,
|
|
152
|
+
now,
|
|
153
|
+
}).finally(() => {
|
|
154
|
+
inFlight.delete(key);
|
|
155
|
+
});
|
|
156
|
+
inFlight.set(key, bootstrap);
|
|
157
|
+
return bootstrap;
|
|
158
|
+
}
|
|
159
|
+
function toProviderData(state) {
|
|
160
|
+
if (!state)
|
|
161
|
+
return {};
|
|
162
|
+
return {
|
|
163
|
+
n_id: state.n_id,
|
|
164
|
+
session_id: state.session_id,
|
|
165
|
+
expires_at: state.expires_at,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const init = (params) => {
|
|
170
|
+
void ensureSession({
|
|
171
|
+
variables: params.manifest.variables,
|
|
172
|
+
pageUrl: params.pageUrl,
|
|
173
|
+
});
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const tag = async ({ manifestVariables, pageUrl, }) => {
|
|
177
|
+
const state = await ensureSession({
|
|
178
|
+
variables: manifestVariables,
|
|
179
|
+
pageUrl,
|
|
180
|
+
});
|
|
181
|
+
return toProviderData(state);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
185
|
+
const data = {
|
|
186
|
+
name: packageName,
|
|
187
|
+
init,
|
|
188
|
+
tag,
|
|
189
|
+
};
|
|
190
|
+
try {
|
|
191
|
+
if (typeof window !== 'undefined') {
|
|
192
|
+
window.edgetagProviders = window.edgetagProviders || [];
|
|
193
|
+
window.edgetagProviders.push(data);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
// no window
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export { data as default };
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@blotoutio/providers-dataflywheel-sdk",
|
|
3
|
+
"version": "1.63.0",
|
|
4
|
+
"description": "DataFlywheel browser SDK for EdgeTag",
|
|
5
|
+
"author": "Blotout",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://github.com/blotoutio/edgetag-sdk",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"main": "./index.cjs.js",
|
|
12
|
+
"module": "./index.mjs",
|
|
13
|
+
"types": "./index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./index.d.ts",
|
|
17
|
+
"require": "./index.cjs.js",
|
|
18
|
+
"import": "./index.mjs",
|
|
19
|
+
"default": "./index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/blotoutio/edgetag-sdk.git"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"package.json",
|
|
28
|
+
"README.md",
|
|
29
|
+
"index.js",
|
|
30
|
+
"index.cjs.js",
|
|
31
|
+
"index.mjs",
|
|
32
|
+
"index.d.ts"
|
|
33
|
+
]
|
|
34
|
+
}
|