@blotoutio/providers-dataflywheel-sdk 1.75.1 → 1.76.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs.js +145 -345
- package/index.js +145 -345
- package/index.mjs +145 -345
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -1,383 +1,183 @@
|
|
|
1
|
-
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
// back apart, as Facebook does with facebook::_fbp.
|
|
11
|
-
const kvKey = (key) => `${packageName}::${key}`;
|
|
12
|
-
const sessionStateKeyPrefix = 'dfw_sdk_state';
|
|
13
|
-
const sessionBootstrapPath = 'v1/session';
|
|
1
|
+
// A network ID is 128 random bits, spelled like Qinto's IDs: `n_` and a hyphenated UUID. Earlier IDs, still in some
|
|
2
|
+
// cookies and copies, are `n_<32 hex>`; they are read, and spelled the new way from then on. PlanetScale stores the UUID.
|
|
3
|
+
// Same rules as qinto-apps/data-flywheel/src/nid.ts; keep the two in step.
|
|
4
|
+
const NID_RE = /^n_([0-9a-f]{8})-?([0-9a-f]{4})-?([0-9a-f]{4})-?([0-9a-f]{4})-?([0-9a-f]{12})$/;
|
|
5
|
+
// The ID in its current spelling, or null when the value is not a network ID.
|
|
6
|
+
const toNid = (value) => {
|
|
7
|
+
const parts = typeof value === 'string' ? NID_RE.exec(value) : null;
|
|
8
|
+
return parts === null ? null : `n_${parts.slice(1).join('-')}`;
|
|
9
|
+
};
|
|
14
10
|
|
|
15
|
-
const
|
|
11
|
+
const packageName = 'dataFlywheel';
|
|
12
|
+
// The provider's own endpoints on the merchant's EdgeTag Worker (cdn/src/lib/api.ts), named like the network Worker's:
|
|
13
|
+
// /nid for approach 1, /nid1 for approach 2.
|
|
14
|
+
const nidPath = '/providers/dataFlywheel/nid';
|
|
15
|
+
const nidLookupPath = '/providers/dataFlywheel/nid1';
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
17
|
+
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
18
|
+
// The network ID, shared by every Data Flywheel merchant in one browser (on Qinto and EdgeTag), lives in a cookie on the
|
|
19
|
+
// network domain, which the network Worker reads and keeps. The same two approaches as the Qinto app
|
|
20
|
+
// (qinto-apps/data-flywheel/src/network.ts), each with its own cookie, so they can be compared:
|
|
21
|
+
// - approach 1, the primary (`dfw_nid`): the Worker mints an ID on the spot, with no lookup anywhere;
|
|
22
|
+
// - approach 2, the lookup (`dfw_nid_1`): the provider's endpoint on the merchant's EdgeTag Worker mints it, handing a
|
|
23
|
+
// visitor back the ID it had before, so a cleared cookie comes back the same.
|
|
24
|
+
// Each merchant keeps its own copy in localStorage, with when it last checked it (`<key>_at`). A page whose copy was
|
|
25
|
+
// checked in the last 7 days does nothing more: it calls neither the Worker nor the endpoint. Any other page (a first
|
|
26
|
+
// visit, cleared storage, a copy from before the timestamp, or 7 days on) runs the approach, which also sets the cookie
|
|
27
|
+
// again so its lifetime starts over, and checks the copy afresh. The endpoint only hears about an ID this merchant has
|
|
28
|
+
// not kept before.
|
|
29
|
+
const WAIT_MS = 5000;
|
|
30
|
+
const RECHECK_MS = 7 * 24 * 60 * 60 * 1000;
|
|
31
|
+
// Storage can be missing or refuse writes (private windows, blocked site data), which makes every page due.
|
|
32
|
+
const localCache = (key, userId) => {
|
|
33
|
+
const get = () => {
|
|
34
|
+
try {
|
|
35
|
+
return toNid(localStorage.getItem(key));
|
|
30
36
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (canLog()) {
|
|
34
|
-
console.error(prefix, ...args);
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
35
39
|
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
};
|
|
41
|
+
const owned = () => {
|
|
42
|
+
try {
|
|
43
|
+
return localStorage.getItem(`${key}_uid`) === userId;
|
|
40
44
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (canLog()) {
|
|
44
|
-
console.trace(prefix, ...args);
|
|
45
|
+
catch {
|
|
46
|
+
return false;
|
|
45
47
|
}
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
const initKey = `${keyPrefix}StoreMultiple`;
|
|
50
|
-
const saveKV = (destination, data) => {
|
|
51
|
-
const currentSession = getData(destination, 'session');
|
|
52
|
-
if (!currentSession['kv']) {
|
|
53
|
-
currentSession['kv'] = {};
|
|
54
|
-
}
|
|
55
|
-
currentSession['kv'] = {
|
|
56
|
-
...currentSession['kv'],
|
|
57
|
-
...data,
|
|
58
48
|
};
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
49
|
+
return {
|
|
50
|
+
get,
|
|
51
|
+
owned,
|
|
52
|
+
set: (nId) => {
|
|
53
|
+
try {
|
|
54
|
+
localStorage.setItem(key, nId);
|
|
55
|
+
localStorage.setItem(`${key}_at`, String(Date.now()));
|
|
56
|
+
localStorage.setItem(`${key}_uid`, userId);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// nothing to keep
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
due: () => {
|
|
63
|
+
try {
|
|
64
|
+
const age = Date.now() - Number(localStorage.getItem(`${key}_at`));
|
|
65
|
+
return !owned() || get() === null || !(age >= 0 && age < RECHECK_MS);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
};
|
|
81
72
|
};
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
73
|
+
const withTimeout = (work) => new Promise((resolve, reject) => {
|
|
74
|
+
const timer = setTimeout(() => reject(new Error('timeout')), WAIT_MS);
|
|
75
|
+
work.then(resolve, reject).finally(() => clearTimeout(timer));
|
|
76
|
+
});
|
|
77
|
+
// One JSON call, answering its `nId` when it is a well-formed ID.
|
|
78
|
+
const nIdOf = async (response) => {
|
|
79
|
+
const body = (await withTimeout((await withTimeout(response)).json()));
|
|
80
|
+
return toNid(body.nId);
|
|
81
|
+
};
|
|
82
|
+
const endpointFor = (destination, userId) => (path, init = {}) => {
|
|
83
|
+
const headers = new Headers(init.headers);
|
|
84
|
+
if (userId) {
|
|
85
|
+
headers.set('EdgeTagUserId', userId);
|
|
86
|
+
}
|
|
87
|
+
return fetch(new URL(path, destination).toString(), {
|
|
88
|
+
...init,
|
|
89
|
+
headers,
|
|
90
|
+
credentials: 'include',
|
|
91
|
+
});
|
|
92
92
|
};
|
|
93
|
-
const
|
|
93
|
+
const recorder = (endpoint, path) => async (nId) => {
|
|
94
|
+
const response = await withTimeout(endpoint(path, {
|
|
95
|
+
method: 'POST',
|
|
96
|
+
headers: { 'content-type': 'application/json' },
|
|
97
|
+
body: JSON.stringify({ nId, pageUrl: location.href }),
|
|
98
|
+
}));
|
|
99
|
+
return ((await withTimeout(response.json())).linked ===
|
|
100
|
+
true);
|
|
101
|
+
};
|
|
102
|
+
const workerNetwork = (origin) => (existing) => nIdOf(fetch(`${origin}/nid${existing === null ? '' : `?existing=${existing}`}`, { credentials: 'include' }));
|
|
103
|
+
const runNetworkCheck = async (network, record, cache) => {
|
|
94
104
|
try {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return {};
|
|
105
|
+
const copy = cache.get();
|
|
106
|
+
const nId = await network(copy);
|
|
107
|
+
if (nId !== null &&
|
|
108
|
+
((nId === copy && cache.owned()) || (await record(nId)))) {
|
|
109
|
+
cache.set(nId);
|
|
101
110
|
}
|
|
102
|
-
return JSON.parse(data) || {};
|
|
103
111
|
}
|
|
104
112
|
catch {
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
const
|
|
113
|
+
// fails open
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const workerLookup = (origin) => ({
|
|
117
|
+
read: (existing) => nIdOf(fetch(`${origin}/nid1${existing === null ? '' : `?existing=${existing}`}`, {
|
|
118
|
+
credentials: 'include',
|
|
119
|
+
})),
|
|
120
|
+
set: (nId) => nIdOf(fetch(`${origin}/nid1`, {
|
|
121
|
+
method: 'POST',
|
|
122
|
+
credentials: 'include',
|
|
123
|
+
body: JSON.stringify({ set: nId }),
|
|
124
|
+
})),
|
|
125
|
+
});
|
|
126
|
+
const lookupServer = (endpoint) => ({
|
|
127
|
+
lookup: () => nIdOf(endpoint(nidLookupPath)),
|
|
128
|
+
confirm: recorder(endpoint, nidLookupPath),
|
|
129
|
+
});
|
|
130
|
+
const runLookupCheck = async (network, server, cache) => {
|
|
109
131
|
try {
|
|
110
|
-
|
|
132
|
+
const copy = cache.get();
|
|
133
|
+
const held = await network.read(copy);
|
|
134
|
+
if (held !== null) {
|
|
135
|
+
if ((held === copy && cache.owned()) || (await server.confirm(held))) {
|
|
136
|
+
cache.set(held);
|
|
137
|
+
}
|
|
111
138
|
return;
|
|
112
139
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
logger.log('Session storage not supported.');
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
const getSession = (key) => {
|
|
120
|
-
try {
|
|
121
|
-
if (!sessionStorage) {
|
|
122
|
-
return {};
|
|
123
|
-
}
|
|
124
|
-
const data = sessionStorage.getItem(key);
|
|
125
|
-
if (!data) {
|
|
126
|
-
return {};
|
|
140
|
+
const nId = await server.lookup();
|
|
141
|
+
if (nId !== null && (await network.set(nId)) === nId) {
|
|
142
|
+
cache.set(nId);
|
|
127
143
|
}
|
|
128
|
-
return JSON.parse(data) || {};
|
|
129
144
|
}
|
|
130
145
|
catch {
|
|
131
|
-
|
|
146
|
+
// fails open
|
|
132
147
|
}
|
|
133
148
|
};
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const inFlight = new Map();
|
|
139
|
-
const memoryStates = new Map();
|
|
140
|
-
const stringValue = (value) => typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
141
|
-
const numberValue = (value) => typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
142
|
-
const isEnabledFlag = (value, defaultValue = true) => {
|
|
143
|
-
if (value == null || value === '')
|
|
144
|
-
return defaultValue;
|
|
145
|
-
return value !== '0' && value.toLowerCase() !== 'false';
|
|
146
|
-
};
|
|
147
|
-
const shouldBootstrap = (now, expiresAt) => expiresAt == null || now >= expiresAt;
|
|
148
|
-
const browserOrigin = () => {
|
|
149
|
-
var _a, _b;
|
|
150
|
-
try {
|
|
151
|
-
if (typeof window === 'undefined')
|
|
152
|
-
return null;
|
|
153
|
-
return typeof window.origin === 'string'
|
|
154
|
-
? window.origin
|
|
155
|
-
: (_b = (_a = window.location) === null || _a === void 0 ? void 0 : _a.origin) !== null && _b !== void 0 ? _b : null;
|
|
156
|
-
}
|
|
157
|
-
catch {
|
|
158
|
-
// If a sandbox prevents origin inspection, fail closed before issuing a
|
|
159
|
-
// credentialed request that the DFW Worker cannot safely authorize.
|
|
160
|
-
return 'null';
|
|
149
|
+
const startNetworkId = (endpoint, network, userId) => {
|
|
150
|
+
const cache = localCache('dfw_nid', userId);
|
|
151
|
+
if (cache.due()) {
|
|
152
|
+
void runNetworkCheck(network, recorder(endpoint, nidPath), cache);
|
|
161
153
|
}
|
|
162
154
|
};
|
|
163
|
-
const
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if (typeof window === 'undefined')
|
|
168
|
-
return null;
|
|
169
|
-
return (_a = window.sessionStorage) !== null && _a !== void 0 ? _a : null;
|
|
170
|
-
}
|
|
171
|
-
catch {
|
|
172
|
-
return null;
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
const sessionStorageFor = (storage) => (storage === undefined ? browserStorage() : storage);
|
|
176
|
-
const readSessionState = (storage, merchantId) => {
|
|
177
|
-
var _a;
|
|
178
|
-
const key = stateKey(merchantId);
|
|
179
|
-
const fallback = () => { var _a; return (_a = memoryStates.get(key)) !== null && _a !== void 0 ? _a : null; };
|
|
180
|
-
if (!storage)
|
|
181
|
-
return fallback();
|
|
182
|
-
try {
|
|
183
|
-
const raw = storage.getItem(key);
|
|
184
|
-
if (!raw)
|
|
185
|
-
return fallback();
|
|
186
|
-
const parsed = JSON.parse(raw);
|
|
187
|
-
const nId = stringValue(parsed.n_id);
|
|
188
|
-
const sessionId = stringValue(parsed.session_id);
|
|
189
|
-
const expiresAt = stringValue(parsed.expires_at);
|
|
190
|
-
if (!nId || !sessionId || !expiresAt)
|
|
191
|
-
return fallback();
|
|
192
|
-
return {
|
|
193
|
-
n_id: nId,
|
|
194
|
-
session_id: sessionId,
|
|
195
|
-
expires_at: expiresAt,
|
|
196
|
-
last_touch_at: (_a = numberValue(parsed.last_touch_at)) !== null && _a !== void 0 ? _a : 0,
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
catch {
|
|
200
|
-
return fallback();
|
|
155
|
+
const startLookupNetworkId = (endpoint, network, userId) => {
|
|
156
|
+
const cache = localCache('dfw_nid_1', userId);
|
|
157
|
+
if (cache.due()) {
|
|
158
|
+
void runLookupCheck(network, lookupServer(endpoint), cache);
|
|
201
159
|
}
|
|
202
160
|
};
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
try {
|
|
210
|
-
storage.setItem(key, JSON.stringify(state));
|
|
211
|
-
}
|
|
212
|
-
catch {
|
|
213
|
-
memoryStates.set(key, state);
|
|
214
|
-
// Storage can be disabled or full. The worker cookies remain authoritative.
|
|
215
|
-
}
|
|
216
|
-
};
|
|
217
|
-
function expiresAtMs(state) {
|
|
218
|
-
if (!state)
|
|
219
|
-
return null;
|
|
220
|
-
const expiresAt = Date.parse(state.expires_at);
|
|
221
|
-
return Number.isFinite(expiresAt) ? expiresAt : null;
|
|
222
|
-
}
|
|
223
|
-
// The dfw_nid cookie belongs to the DataFlywheel identity host, so the merchant's
|
|
224
|
-
// edge never receives it. Publishing into the SDK's kv store puts the same values
|
|
225
|
-
// on every request body instead -- identify included, which providerData is not.
|
|
226
|
-
const published = new Map();
|
|
227
|
-
function publishToKv(destination, state) {
|
|
228
|
-
if (!destination || !state)
|
|
229
|
-
return;
|
|
230
|
-
// saveKV rewrites the whole multi-destination blob synchronously, and the
|
|
231
|
-
// cached path runs on every event, so skip when nothing moved.
|
|
232
|
-
const last = published.get(destination);
|
|
233
|
-
if (last &&
|
|
234
|
-
last.n_id === state.n_id &&
|
|
235
|
-
last.session_id === state.session_id &&
|
|
236
|
-
last.expires_at === state.expires_at) {
|
|
161
|
+
|
|
162
|
+
// Every page load: each network ID approach runs unless the merchant already keeps its copy (network.ts).
|
|
163
|
+
const init = ({ manifest, destination, userId, }) => {
|
|
164
|
+
const variables = manifest.variables;
|
|
165
|
+
if (!(variables === null || variables === void 0 ? void 0 : variables.networkOrigin)) {
|
|
237
166
|
return;
|
|
238
167
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
expires_at: state.expires_at,
|
|
243
|
-
});
|
|
244
|
-
try {
|
|
245
|
-
saveKV(destination, {
|
|
246
|
-
[kvKey(storedNIdKey)]: state.n_id,
|
|
247
|
-
[kvKey(storedSessionIdKey)]: state.session_id,
|
|
248
|
-
[kvKey(storedSessionExpiryKey)]: state.expires_at,
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
catch {
|
|
252
|
-
// Storage can be unavailable; the providerData and provider-key routes remain.
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
function bootstrapUrl(input) {
|
|
256
|
-
const base = input.dataFlywheelUrl.endsWith('/')
|
|
257
|
-
? input.dataFlywheelUrl
|
|
258
|
-
: `${input.dataFlywheelUrl}/`;
|
|
259
|
-
const url = new URL(sessionBootstrapPath, base);
|
|
260
|
-
url.searchParams.set('merchant_id', input.merchantId);
|
|
261
|
-
const pageUrl = stringValue(input.pageUrl);
|
|
262
|
-
if (pageUrl) {
|
|
263
|
-
url.searchParams.set('page_url', pageUrl);
|
|
264
|
-
}
|
|
265
|
-
return url.toString();
|
|
266
|
-
}
|
|
267
|
-
function parseBootstrapResponse(body, now) {
|
|
268
|
-
var _a, _b;
|
|
269
|
-
const nId = stringValue(body.n_id);
|
|
270
|
-
const sessionId = stringValue((_a = body.session) === null || _a === void 0 ? void 0 : _a.session_id);
|
|
271
|
-
const expiresAt = stringValue((_b = body.session) === null || _b === void 0 ? void 0 : _b.expires_at);
|
|
272
|
-
if (!nId || !sessionId || !expiresAt)
|
|
273
|
-
return null;
|
|
274
|
-
return {
|
|
275
|
-
n_id: nId,
|
|
276
|
-
session_id: sessionId,
|
|
277
|
-
expires_at: expiresAt,
|
|
278
|
-
last_touch_at: now,
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
async function bootstrapSession(input) {
|
|
282
|
-
try {
|
|
283
|
-
const response = await input.fetcher(bootstrapUrl({
|
|
284
|
-
dataFlywheelUrl: input.dataFlywheelUrl,
|
|
285
|
-
merchantId: input.merchantId,
|
|
286
|
-
pageUrl: input.pageUrl,
|
|
287
|
-
}), { credentials: 'include' });
|
|
288
|
-
if (!response.ok)
|
|
289
|
-
return null;
|
|
290
|
-
const state = parseBootstrapResponse((await response.json()), input.now);
|
|
291
|
-
if (!state)
|
|
292
|
-
return null;
|
|
293
|
-
writeSessionState(input.storage, input.merchantId, state);
|
|
294
|
-
return state;
|
|
295
|
-
}
|
|
296
|
-
catch {
|
|
297
|
-
return null;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
function ensureSession(input) {
|
|
301
|
-
var _a, _b, _c, _d;
|
|
302
|
-
const variables = (_a = input.variables) !== null && _a !== void 0 ? _a : {};
|
|
303
|
-
const dataFlywheelUrl = stringValue(variables.dataFlywheelUrl);
|
|
304
|
-
const merchantId = stringValue(variables.merchantId);
|
|
305
|
-
if (!dataFlywheelUrl ||
|
|
306
|
-
!merchantId ||
|
|
307
|
-
!isEnabledFlag(variables.dataFlywheelSessionEnabled)) {
|
|
308
|
-
return Promise.resolve(null);
|
|
168
|
+
const endpoint = endpointFor(destination, userId);
|
|
169
|
+
if (variables.nidEnabled === '1') {
|
|
170
|
+
startNetworkId(endpoint, workerNetwork(variables.networkOrigin), userId);
|
|
309
171
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
const existing = readSessionState(storage, merchantId);
|
|
313
|
-
if (!shouldBootstrap(now, expiresAtMs(existing))) {
|
|
314
|
-
publishToKv(input.destination, existing);
|
|
315
|
-
return Promise.resolve(existing);
|
|
172
|
+
if (variables.nidLookupEnabled === '1') {
|
|
173
|
+
startLookupNetworkId(endpoint, workerLookup(variables.networkOrigin), userId);
|
|
316
174
|
}
|
|
317
|
-
// Opaque origins (sandboxed iframes like Shopify pixels) serialize to the
|
|
318
|
-
// string 'null' per the HTML spec — that is what window.origin returns and
|
|
319
|
-
// what the fail-closed browserOrigin() catch emits. JS null means no window
|
|
320
|
-
// at all (non-browser host), which is not an opaque-origin sandbox.
|
|
321
|
-
if ((input.origin === undefined ? browserOrigin() : input.origin) === 'null') {
|
|
322
|
-
return Promise.resolve(null);
|
|
323
|
-
}
|
|
324
|
-
const key = stateKey(merchantId);
|
|
325
|
-
const existingBootstrap = inFlight.get(key);
|
|
326
|
-
if (existingBootstrap)
|
|
327
|
-
return existingBootstrap;
|
|
328
|
-
const fetcher = (_d = input.fetcher) !== null && _d !== void 0 ? _d : (typeof fetch === 'function' ? fetch.bind(globalThis) : null);
|
|
329
|
-
if (!fetcher)
|
|
330
|
-
return Promise.resolve(null);
|
|
331
|
-
const bootstrap = bootstrapSession({
|
|
332
|
-
dataFlywheelUrl,
|
|
333
|
-
merchantId,
|
|
334
|
-
pageUrl: input.pageUrl,
|
|
335
|
-
storage,
|
|
336
|
-
fetcher,
|
|
337
|
-
now,
|
|
338
|
-
})
|
|
339
|
-
.then((state) => {
|
|
340
|
-
publishToKv(input.destination, state);
|
|
341
|
-
return state;
|
|
342
|
-
})
|
|
343
|
-
.finally(() => {
|
|
344
|
-
inFlight.delete(key);
|
|
345
|
-
});
|
|
346
|
-
inFlight.set(key, bootstrap);
|
|
347
|
-
return bootstrap;
|
|
348
|
-
}
|
|
349
|
-
function toProviderData(state) {
|
|
350
|
-
if (!state)
|
|
351
|
-
return {};
|
|
352
|
-
return {
|
|
353
|
-
n_id: state.n_id,
|
|
354
|
-
session_id: state.session_id,
|
|
355
|
-
expires_at: state.expires_at,
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
const init = (params) => {
|
|
360
|
-
void ensureSession({
|
|
361
|
-
variables: params.manifest.variables,
|
|
362
|
-
pageUrl: params.pageUrl,
|
|
363
|
-
destination: params.destination,
|
|
364
|
-
});
|
|
365
|
-
};
|
|
366
|
-
|
|
367
|
-
const tag = async ({ manifestVariables, pageUrl, destination, }) => {
|
|
368
|
-
const state = await ensureSession({
|
|
369
|
-
variables: manifestVariables,
|
|
370
|
-
pageUrl,
|
|
371
|
-
destination,
|
|
372
|
-
});
|
|
373
|
-
return toProviderData(state);
|
|
374
175
|
};
|
|
375
176
|
|
|
376
177
|
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
377
178
|
const data = {
|
|
378
179
|
name: packageName,
|
|
379
180
|
init,
|
|
380
|
-
tag,
|
|
381
181
|
};
|
|
382
182
|
try {
|
|
383
183
|
if (typeof window !== 'undefined') {
|