tersejson 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/LICENSE +21 -0
- package/README.md +476 -0
- package/dist/analytics.d.mts +186 -0
- package/dist/analytics.d.ts +186 -0
- package/dist/analytics.js +226 -0
- package/dist/analytics.js.map +1 -0
- package/dist/analytics.mjs +217 -0
- package/dist/analytics.mjs.map +1 -0
- package/dist/client-BQAZg7I8.d.mts +138 -0
- package/dist/client-DOOGwp_p.d.ts +138 -0
- package/dist/client.d.mts +2 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +200 -0
- package/dist/client.js.map +1 -0
- package/dist/client.mjs +188 -0
- package/dist/client.mjs.map +1 -0
- package/dist/express-BoL__Ao6.d.mts +67 -0
- package/dist/express-LSVylWpN.d.ts +67 -0
- package/dist/express.d.mts +4 -0
- package/dist/express.d.ts +4 -0
- package/dist/express.js +522 -0
- package/dist/express.js.map +1 -0
- package/dist/express.mjs +512 -0
- package/dist/express.mjs.map +1 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1001 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +985 -0
- package/dist/index.mjs.map +1 -0
- package/dist/integrations-7WeFO1Lk.d.mts +264 -0
- package/dist/integrations-7WeFO1Lk.d.ts +264 -0
- package/dist/integrations.d.mts +1 -0
- package/dist/integrations.d.ts +1 -0
- package/dist/integrations.js +381 -0
- package/dist/integrations.js.map +1 -0
- package/dist/integrations.mjs +367 -0
- package/dist/integrations.mjs.map +1 -0
- package/dist/types-CzaGQaV7.d.mts +134 -0
- package/dist/types-CzaGQaV7.d.ts +134 -0
- package/package.json +87 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1001 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __export = (target, all) => {
|
|
5
|
+
for (var name in all)
|
|
6
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
// src/types.ts
|
|
10
|
+
function isTersePayload(value) {
|
|
11
|
+
return typeof value === "object" && value !== null && "__terse__" in value && value.__terse__ === true && "v" in value && "k" in value && "d" in value;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// src/core.ts
|
|
15
|
+
function alphaGenerator(index) {
|
|
16
|
+
let key = "";
|
|
17
|
+
let remaining = index;
|
|
18
|
+
do {
|
|
19
|
+
key = String.fromCharCode(97 + remaining % 26) + key;
|
|
20
|
+
remaining = Math.floor(remaining / 26) - 1;
|
|
21
|
+
} while (remaining >= 0);
|
|
22
|
+
return key;
|
|
23
|
+
}
|
|
24
|
+
function numericGenerator(index) {
|
|
25
|
+
return String(index);
|
|
26
|
+
}
|
|
27
|
+
function alphanumericGenerator(index) {
|
|
28
|
+
const letterIndex = Math.floor(index / 9);
|
|
29
|
+
const numIndex = index % 9 + 1;
|
|
30
|
+
return alphaGenerator(letterIndex) + numIndex;
|
|
31
|
+
}
|
|
32
|
+
function shortGenerator(index) {
|
|
33
|
+
if (index === 0) return "_";
|
|
34
|
+
return alphaGenerator(index - 1);
|
|
35
|
+
}
|
|
36
|
+
function prefixedGenerator(prefix, style = "numeric") {
|
|
37
|
+
return (index) => {
|
|
38
|
+
if (style === "alpha") {
|
|
39
|
+
return prefix + alphaGenerator(index);
|
|
40
|
+
}
|
|
41
|
+
return prefix + index;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function createKeyGenerator(pattern) {
|
|
45
|
+
if (typeof pattern === "function") {
|
|
46
|
+
return { generator: pattern, name: "custom" };
|
|
47
|
+
}
|
|
48
|
+
if (typeof pattern === "string") {
|
|
49
|
+
switch (pattern) {
|
|
50
|
+
case "alpha":
|
|
51
|
+
return { generator: alphaGenerator, name: "alpha" };
|
|
52
|
+
case "numeric":
|
|
53
|
+
return { generator: numericGenerator, name: "numeric" };
|
|
54
|
+
case "alphanumeric":
|
|
55
|
+
return { generator: alphanumericGenerator, name: "alphanumeric" };
|
|
56
|
+
case "short":
|
|
57
|
+
return { generator: shortGenerator, name: "short" };
|
|
58
|
+
case "prefixed":
|
|
59
|
+
return { generator: prefixedGenerator("k"), name: "prefixed:k" };
|
|
60
|
+
default:
|
|
61
|
+
return { generator: alphaGenerator, name: "alpha" };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (typeof pattern === "object" && "prefix" in pattern) {
|
|
65
|
+
return {
|
|
66
|
+
generator: prefixedGenerator(pattern.prefix, pattern.style || "numeric"),
|
|
67
|
+
name: `prefixed:${pattern.prefix}`
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return { generator: alphaGenerator, name: "alpha" };
|
|
71
|
+
}
|
|
72
|
+
function resolveNestedDepth(handling, maxDepth) {
|
|
73
|
+
if (handling === void 0 || handling === "deep") {
|
|
74
|
+
return maxDepth;
|
|
75
|
+
}
|
|
76
|
+
if (handling === "shallow") {
|
|
77
|
+
return 1;
|
|
78
|
+
}
|
|
79
|
+
if (handling === "arrays") {
|
|
80
|
+
return maxDepth;
|
|
81
|
+
}
|
|
82
|
+
if (typeof handling === "number") {
|
|
83
|
+
return handling;
|
|
84
|
+
}
|
|
85
|
+
return maxDepth;
|
|
86
|
+
}
|
|
87
|
+
function collectKeys(data, options, currentDepth = 0) {
|
|
88
|
+
const keys = /* @__PURE__ */ new Set();
|
|
89
|
+
const { minKeyLength, maxDepth, nestedHandling, excludeKeys, includeKeys } = options;
|
|
90
|
+
if (currentDepth >= maxDepth) return keys;
|
|
91
|
+
const keyCounts = /* @__PURE__ */ new Map();
|
|
92
|
+
for (const item of data) {
|
|
93
|
+
if (typeof item !== "object" || item === null) continue;
|
|
94
|
+
for (const key of Object.keys(item)) {
|
|
95
|
+
if (excludeKeys?.includes(key)) continue;
|
|
96
|
+
const shouldInclude = includeKeys?.includes(key) || key.length >= minKeyLength;
|
|
97
|
+
if (shouldInclude) {
|
|
98
|
+
keys.add(key);
|
|
99
|
+
keyCounts.set(key, (keyCounts.get(key) || 0) + 1);
|
|
100
|
+
}
|
|
101
|
+
const value = item[key];
|
|
102
|
+
if (nestedHandling === "shallow") {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (Array.isArray(value) && value.length > 0 && isCompressibleArray(value)) {
|
|
106
|
+
const nestedKeys = collectKeys(
|
|
107
|
+
value,
|
|
108
|
+
options,
|
|
109
|
+
currentDepth + 1
|
|
110
|
+
);
|
|
111
|
+
nestedKeys.forEach((k) => keys.add(k));
|
|
112
|
+
} else if (nestedHandling !== "arrays" && typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
113
|
+
const nestedKeys = collectKeys(
|
|
114
|
+
[value],
|
|
115
|
+
options,
|
|
116
|
+
currentDepth + 1
|
|
117
|
+
);
|
|
118
|
+
nestedKeys.forEach((k) => keys.add(k));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (options.homogeneousOnly && data.length > 0) {
|
|
123
|
+
for (const [key, count] of keyCounts) {
|
|
124
|
+
if (count < data.length) {
|
|
125
|
+
keys.delete(key);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return keys;
|
|
130
|
+
}
|
|
131
|
+
function isCompressibleArray(data) {
|
|
132
|
+
if (!Array.isArray(data) || data.length === 0) return false;
|
|
133
|
+
return data.every(
|
|
134
|
+
(item) => typeof item === "object" && item !== null && !Array.isArray(item)
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
function compressObject(obj, keyToShort, maxDepth, currentDepth = 0) {
|
|
138
|
+
if (currentDepth >= maxDepth) return obj;
|
|
139
|
+
const compressed = {};
|
|
140
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
141
|
+
const shortKey = keyToShort.get(key) ?? key;
|
|
142
|
+
if (Array.isArray(value) && isCompressibleArray(value)) {
|
|
143
|
+
compressed[shortKey] = value.map(
|
|
144
|
+
(item) => compressObject(
|
|
145
|
+
item,
|
|
146
|
+
keyToShort,
|
|
147
|
+
maxDepth,
|
|
148
|
+
currentDepth + 1
|
|
149
|
+
)
|
|
150
|
+
);
|
|
151
|
+
} else if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
152
|
+
compressed[shortKey] = compressObject(
|
|
153
|
+
value,
|
|
154
|
+
keyToShort,
|
|
155
|
+
maxDepth,
|
|
156
|
+
currentDepth + 1
|
|
157
|
+
);
|
|
158
|
+
} else {
|
|
159
|
+
compressed[shortKey] = value;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return compressed;
|
|
163
|
+
}
|
|
164
|
+
function expandObject(obj, shortToKey, maxDepth, currentDepth = 0) {
|
|
165
|
+
if (currentDepth >= maxDepth) return obj;
|
|
166
|
+
const expanded = {};
|
|
167
|
+
for (const [shortKey, value] of Object.entries(obj)) {
|
|
168
|
+
const originalKey = shortToKey.get(shortKey) ?? shortKey;
|
|
169
|
+
if (Array.isArray(value)) {
|
|
170
|
+
expanded[originalKey] = value.map((item) => {
|
|
171
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
172
|
+
return expandObject(
|
|
173
|
+
item,
|
|
174
|
+
shortToKey,
|
|
175
|
+
maxDepth,
|
|
176
|
+
currentDepth + 1
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
return item;
|
|
180
|
+
});
|
|
181
|
+
} else if (typeof value === "object" && value !== null) {
|
|
182
|
+
expanded[originalKey] = expandObject(
|
|
183
|
+
value,
|
|
184
|
+
shortToKey,
|
|
185
|
+
maxDepth,
|
|
186
|
+
currentDepth + 1
|
|
187
|
+
);
|
|
188
|
+
} else {
|
|
189
|
+
expanded[originalKey] = value;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return expanded;
|
|
193
|
+
}
|
|
194
|
+
function compress(data, options = {}) {
|
|
195
|
+
const {
|
|
196
|
+
minKeyLength = 3,
|
|
197
|
+
maxDepth = 10,
|
|
198
|
+
keyPattern = "alpha",
|
|
199
|
+
nestedHandling = "deep",
|
|
200
|
+
homogeneousOnly = false,
|
|
201
|
+
excludeKeys,
|
|
202
|
+
includeKeys
|
|
203
|
+
} = options;
|
|
204
|
+
const { generator, name: patternName } = createKeyGenerator(keyPattern);
|
|
205
|
+
const effectiveDepth = resolveNestedDepth(nestedHandling, maxDepth);
|
|
206
|
+
const allKeys = collectKeys(data, {
|
|
207
|
+
minKeyLength,
|
|
208
|
+
maxDepth: effectiveDepth,
|
|
209
|
+
nestedHandling,
|
|
210
|
+
excludeKeys,
|
|
211
|
+
includeKeys,
|
|
212
|
+
homogeneousOnly
|
|
213
|
+
});
|
|
214
|
+
const sortedKeys = Array.from(allKeys).sort();
|
|
215
|
+
const keyToShort = /* @__PURE__ */ new Map();
|
|
216
|
+
const keyMap = {};
|
|
217
|
+
sortedKeys.forEach((key, index) => {
|
|
218
|
+
const shortKey = generator(index);
|
|
219
|
+
if (shortKey.length < key.length) {
|
|
220
|
+
keyToShort.set(key, shortKey);
|
|
221
|
+
keyMap[shortKey] = key;
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
const compressed = data.map(
|
|
225
|
+
(item) => compressObject(item, keyToShort, effectiveDepth)
|
|
226
|
+
);
|
|
227
|
+
return {
|
|
228
|
+
__terse__: true,
|
|
229
|
+
v: 1,
|
|
230
|
+
k: keyMap,
|
|
231
|
+
d: compressed,
|
|
232
|
+
p: patternName
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function expand(payload) {
|
|
236
|
+
const shortToKey = new Map(
|
|
237
|
+
Object.entries(payload.k).map(([short, original]) => [short, original])
|
|
238
|
+
);
|
|
239
|
+
if (Array.isArray(payload.d)) {
|
|
240
|
+
return payload.d.map((item) => {
|
|
241
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
242
|
+
return expandObject(item, shortToKey, 10);
|
|
243
|
+
}
|
|
244
|
+
return item;
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
if (typeof payload.d === "object" && payload.d !== null) {
|
|
248
|
+
return expandObject(payload.d, shortToKey, 10);
|
|
249
|
+
}
|
|
250
|
+
return payload.d;
|
|
251
|
+
}
|
|
252
|
+
function createTerseProxy(compressed, keyMap) {
|
|
253
|
+
const originalToShort = new Map(
|
|
254
|
+
Object.entries(keyMap).map(([short, original]) => [original, short])
|
|
255
|
+
);
|
|
256
|
+
const handler = {
|
|
257
|
+
get(target, prop) {
|
|
258
|
+
if (typeof prop === "symbol") {
|
|
259
|
+
return Reflect.get(target, prop);
|
|
260
|
+
}
|
|
261
|
+
const shortKey = originalToShort.get(prop);
|
|
262
|
+
const actualKey = shortKey ?? prop;
|
|
263
|
+
const value = target[actualKey];
|
|
264
|
+
if (Array.isArray(value)) {
|
|
265
|
+
return value.map((item) => {
|
|
266
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
267
|
+
return createTerseProxy(item, keyMap);
|
|
268
|
+
}
|
|
269
|
+
return item;
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
if (typeof value === "object" && value !== null) {
|
|
273
|
+
return createTerseProxy(value, keyMap);
|
|
274
|
+
}
|
|
275
|
+
return value;
|
|
276
|
+
},
|
|
277
|
+
has(target, prop) {
|
|
278
|
+
if (typeof prop === "symbol") {
|
|
279
|
+
return Reflect.has(target, prop);
|
|
280
|
+
}
|
|
281
|
+
const shortKey = originalToShort.get(prop);
|
|
282
|
+
return (shortKey ?? prop) in target;
|
|
283
|
+
},
|
|
284
|
+
ownKeys(target) {
|
|
285
|
+
return Object.keys(target).map((shortKey) => keyMap[shortKey] ?? shortKey);
|
|
286
|
+
},
|
|
287
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
288
|
+
if (typeof prop === "symbol") {
|
|
289
|
+
return Reflect.getOwnPropertyDescriptor(target, prop);
|
|
290
|
+
}
|
|
291
|
+
const shortKey = originalToShort.get(prop);
|
|
292
|
+
const actualKey = shortKey ?? prop;
|
|
293
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, actualKey);
|
|
294
|
+
if (descriptor) {
|
|
295
|
+
return { ...descriptor, enumerable: true, configurable: true };
|
|
296
|
+
}
|
|
297
|
+
return void 0;
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
return new Proxy(compressed, handler);
|
|
301
|
+
}
|
|
302
|
+
function wrapWithProxy(payload) {
|
|
303
|
+
if (Array.isArray(payload.d)) {
|
|
304
|
+
return payload.d.map((item) => {
|
|
305
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
306
|
+
return createTerseProxy(item, payload.k);
|
|
307
|
+
}
|
|
308
|
+
return item;
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
if (typeof payload.d === "object" && payload.d !== null) {
|
|
312
|
+
return createTerseProxy(payload.d, payload.k);
|
|
313
|
+
}
|
|
314
|
+
return payload.d;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// src/express.ts
|
|
318
|
+
var express_exports = {};
|
|
319
|
+
__export(express_exports, {
|
|
320
|
+
TerseAnalytics: () => TerseAnalytics,
|
|
321
|
+
analytics: () => analytics,
|
|
322
|
+
default: () => express_default,
|
|
323
|
+
getAnalytics: () => getAnalytics,
|
|
324
|
+
initAnalytics: () => initAnalytics,
|
|
325
|
+
terse: () => terse,
|
|
326
|
+
terseQueryParam: () => terseQueryParam
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// src/analytics.ts
|
|
330
|
+
var DEFAULT_CONFIG = {
|
|
331
|
+
enabled: false,
|
|
332
|
+
reportToCloud: false,
|
|
333
|
+
reportInterval: 6e4,
|
|
334
|
+
trackEndpoints: false,
|
|
335
|
+
endpoint: "https://api.tersejson.com/v1/analytics",
|
|
336
|
+
debug: false
|
|
337
|
+
};
|
|
338
|
+
var TerseAnalytics = class {
|
|
339
|
+
constructor(config = {}) {
|
|
340
|
+
this.events = [];
|
|
341
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
342
|
+
this.isNode = typeof window === "undefined";
|
|
343
|
+
this.stats = this.createEmptyStats();
|
|
344
|
+
if (this.config.enabled && this.config.reportToCloud) {
|
|
345
|
+
this.startReporting();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Create empty stats object
|
|
350
|
+
*/
|
|
351
|
+
createEmptyStats() {
|
|
352
|
+
return {
|
|
353
|
+
totalEvents: 0,
|
|
354
|
+
totalOriginalBytes: 0,
|
|
355
|
+
totalCompressedBytes: 0,
|
|
356
|
+
totalBytesSaved: 0,
|
|
357
|
+
averageRatio: 0,
|
|
358
|
+
totalObjects: 0,
|
|
359
|
+
sessionStart: Date.now(),
|
|
360
|
+
lastEvent: Date.now()
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Record a compression event
|
|
365
|
+
*/
|
|
366
|
+
record(event) {
|
|
367
|
+
if (!this.config.enabled) return;
|
|
368
|
+
const fullEvent = {
|
|
369
|
+
...event,
|
|
370
|
+
timestamp: Date.now(),
|
|
371
|
+
// Hash endpoint for privacy if tracking is enabled
|
|
372
|
+
endpoint: this.config.trackEndpoints && event.endpoint ? this.hashEndpoint(event.endpoint) : void 0
|
|
373
|
+
};
|
|
374
|
+
this.stats.totalEvents++;
|
|
375
|
+
this.stats.totalOriginalBytes += event.originalSize;
|
|
376
|
+
this.stats.totalCompressedBytes += event.compressedSize;
|
|
377
|
+
this.stats.totalBytesSaved += event.originalSize - event.compressedSize;
|
|
378
|
+
this.stats.totalObjects += event.objectCount;
|
|
379
|
+
this.stats.lastEvent = fullEvent.timestamp;
|
|
380
|
+
this.stats.averageRatio = this.stats.totalCompressedBytes / this.stats.totalOriginalBytes;
|
|
381
|
+
this.events.push(fullEvent);
|
|
382
|
+
if (this.config.onEvent) {
|
|
383
|
+
this.config.onEvent(fullEvent);
|
|
384
|
+
}
|
|
385
|
+
if (this.config.debug) {
|
|
386
|
+
const savings = ((1 - event.compressedSize / event.originalSize) * 100).toFixed(1);
|
|
387
|
+
console.log(`[tersejson:analytics] ${event.originalSize} \u2192 ${event.compressedSize} bytes (${savings}% saved)`);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Get current stats
|
|
392
|
+
*/
|
|
393
|
+
getStats() {
|
|
394
|
+
return { ...this.stats };
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Get formatted stats summary
|
|
398
|
+
*/
|
|
399
|
+
getSummary() {
|
|
400
|
+
const stats = this.stats;
|
|
401
|
+
const savedKB = (stats.totalBytesSaved / 1024).toFixed(2);
|
|
402
|
+
const savedPercent = stats.totalOriginalBytes > 0 ? ((1 - stats.averageRatio) * 100).toFixed(1) : "0";
|
|
403
|
+
return `TerseJSON Stats: ${stats.totalEvents} compressions, ${savedKB}KB saved (${savedPercent}% avg)`;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Reset stats
|
|
407
|
+
*/
|
|
408
|
+
reset() {
|
|
409
|
+
this.events = [];
|
|
410
|
+
this.stats = this.createEmptyStats();
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Start periodic reporting to cloud
|
|
414
|
+
*/
|
|
415
|
+
startReporting() {
|
|
416
|
+
if (this.reportTimer) return;
|
|
417
|
+
this.reportTimer = setInterval(() => {
|
|
418
|
+
this.reportToCloud();
|
|
419
|
+
}, this.config.reportInterval);
|
|
420
|
+
if (this.isNode && typeof process !== "undefined") {
|
|
421
|
+
process.on("beforeExit", () => this.reportToCloud());
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Stop reporting
|
|
426
|
+
*/
|
|
427
|
+
stop() {
|
|
428
|
+
if (this.reportTimer) {
|
|
429
|
+
clearInterval(this.reportTimer);
|
|
430
|
+
this.reportTimer = void 0;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Report stats to tersejson.com
|
|
435
|
+
*/
|
|
436
|
+
async reportToCloud() {
|
|
437
|
+
if (!this.config.reportToCloud || this.events.length === 0) return;
|
|
438
|
+
const payload = {
|
|
439
|
+
apiKey: this.config.apiKey,
|
|
440
|
+
projectId: this.config.projectId,
|
|
441
|
+
stats: this.stats,
|
|
442
|
+
events: this.events.slice(-100),
|
|
443
|
+
// Last 100 events only
|
|
444
|
+
meta: {
|
|
445
|
+
version: "0.1.0",
|
|
446
|
+
runtime: this.isNode ? "node" : "browser"
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
try {
|
|
450
|
+
const fetchFn = this.isNode ? (await import('https')).request : globalThis.fetch;
|
|
451
|
+
if (this.isNode) {
|
|
452
|
+
const url = new URL(this.config.endpoint);
|
|
453
|
+
const req = fetchFn({
|
|
454
|
+
hostname: url.hostname,
|
|
455
|
+
port: url.port || 443,
|
|
456
|
+
path: url.pathname,
|
|
457
|
+
method: "POST",
|
|
458
|
+
headers: {
|
|
459
|
+
"Content-Type": "application/json"
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
req.write(JSON.stringify(payload));
|
|
463
|
+
req.end();
|
|
464
|
+
} else {
|
|
465
|
+
fetchFn(this.config.endpoint, {
|
|
466
|
+
method: "POST",
|
|
467
|
+
headers: { "Content-Type": "application/json" },
|
|
468
|
+
body: JSON.stringify(payload),
|
|
469
|
+
keepalive: true
|
|
470
|
+
// Allow sending on page unload
|
|
471
|
+
}).catch(() => {
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
this.events = [];
|
|
475
|
+
if (this.config.onStats) {
|
|
476
|
+
this.config.onStats(this.stats);
|
|
477
|
+
}
|
|
478
|
+
if (this.config.debug) {
|
|
479
|
+
console.log("[tersejson:analytics] Reported stats to cloud");
|
|
480
|
+
}
|
|
481
|
+
} catch {
|
|
482
|
+
if (this.config.debug) {
|
|
483
|
+
console.log("[tersejson:analytics] Failed to report stats");
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Hash endpoint for privacy
|
|
489
|
+
*/
|
|
490
|
+
hashEndpoint(endpoint) {
|
|
491
|
+
return endpoint.replace(/\/\d+/g, "/:id").replace(/\/[a-f0-9-]{36}/gi, "/:uuid").replace(/\?.*$/, "");
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
var globalAnalytics = null;
|
|
495
|
+
function initAnalytics(config) {
|
|
496
|
+
globalAnalytics = new TerseAnalytics(config);
|
|
497
|
+
return globalAnalytics;
|
|
498
|
+
}
|
|
499
|
+
function getAnalytics() {
|
|
500
|
+
return globalAnalytics;
|
|
501
|
+
}
|
|
502
|
+
function recordEvent(event) {
|
|
503
|
+
globalAnalytics?.record(event);
|
|
504
|
+
}
|
|
505
|
+
var analytics = {
|
|
506
|
+
/**
|
|
507
|
+
* Enable local-only analytics (no cloud reporting)
|
|
508
|
+
*/
|
|
509
|
+
local(options = {}) {
|
|
510
|
+
return initAnalytics({
|
|
511
|
+
enabled: true,
|
|
512
|
+
reportToCloud: false,
|
|
513
|
+
debug: options.debug,
|
|
514
|
+
onEvent: options.onEvent
|
|
515
|
+
});
|
|
516
|
+
},
|
|
517
|
+
/**
|
|
518
|
+
* Enable cloud analytics with API key
|
|
519
|
+
*/
|
|
520
|
+
cloud(apiKey, options = {}) {
|
|
521
|
+
return initAnalytics({
|
|
522
|
+
...options,
|
|
523
|
+
enabled: true,
|
|
524
|
+
reportToCloud: true,
|
|
525
|
+
apiKey
|
|
526
|
+
});
|
|
527
|
+
},
|
|
528
|
+
/**
|
|
529
|
+
* Get current stats
|
|
530
|
+
*/
|
|
531
|
+
getStats() {
|
|
532
|
+
return globalAnalytics?.getStats() ?? null;
|
|
533
|
+
},
|
|
534
|
+
/**
|
|
535
|
+
* Get formatted summary
|
|
536
|
+
*/
|
|
537
|
+
getSummary() {
|
|
538
|
+
return globalAnalytics?.getSummary() ?? "Analytics not initialized";
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
// src/express.ts
|
|
543
|
+
var DEFAULT_OPTIONS = {
|
|
544
|
+
// Middleware-specific options
|
|
545
|
+
minArrayLength: 2,
|
|
546
|
+
shouldCompress: () => true,
|
|
547
|
+
headerName: "x-terse-json",
|
|
548
|
+
debug: false,
|
|
549
|
+
// CompressOptions
|
|
550
|
+
minKeyLength: 3,
|
|
551
|
+
maxDepth: 10,
|
|
552
|
+
keyPattern: "alpha",
|
|
553
|
+
nestedHandling: "deep",
|
|
554
|
+
homogeneousOnly: false,
|
|
555
|
+
excludeKeys: [],
|
|
556
|
+
includeKeys: []
|
|
557
|
+
};
|
|
558
|
+
function terse(options = {}) {
|
|
559
|
+
const { analytics: analyticsOption, ...restOptions } = options;
|
|
560
|
+
const config = { ...DEFAULT_OPTIONS, ...restOptions };
|
|
561
|
+
let analyticsInstance = null;
|
|
562
|
+
if (analyticsOption) {
|
|
563
|
+
if (analyticsOption instanceof TerseAnalytics) {
|
|
564
|
+
analyticsInstance = analyticsOption;
|
|
565
|
+
} else if (analyticsOption === true) {
|
|
566
|
+
analyticsInstance = new TerseAnalytics({ enabled: true, debug: config.debug });
|
|
567
|
+
} else if (typeof analyticsOption === "object") {
|
|
568
|
+
analyticsInstance = new TerseAnalytics({ enabled: true, ...analyticsOption });
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return function terseMiddleware(req, res, next) {
|
|
572
|
+
const acceptsTerse = req.headers["accept-terse"] === "true" || req.headers["x-accept-terse"] === "true";
|
|
573
|
+
const originalJson = res.json.bind(res);
|
|
574
|
+
res.json = function terseJson(data) {
|
|
575
|
+
if (!acceptsTerse) {
|
|
576
|
+
return originalJson(data);
|
|
577
|
+
}
|
|
578
|
+
if (!isCompressibleArray(data)) {
|
|
579
|
+
return originalJson(data);
|
|
580
|
+
}
|
|
581
|
+
if (data.length < config.minArrayLength) {
|
|
582
|
+
return originalJson(data);
|
|
583
|
+
}
|
|
584
|
+
if (!config.shouldCompress(data, req)) {
|
|
585
|
+
return originalJson(data);
|
|
586
|
+
}
|
|
587
|
+
try {
|
|
588
|
+
const dataArray = data;
|
|
589
|
+
const compressed = compress(dataArray, {
|
|
590
|
+
minKeyLength: config.minKeyLength,
|
|
591
|
+
maxDepth: config.maxDepth,
|
|
592
|
+
keyPattern: config.keyPattern,
|
|
593
|
+
nestedHandling: config.nestedHandling,
|
|
594
|
+
homogeneousOnly: config.homogeneousOnly,
|
|
595
|
+
excludeKeys: config.excludeKeys,
|
|
596
|
+
includeKeys: config.includeKeys
|
|
597
|
+
});
|
|
598
|
+
const originalSize = JSON.stringify(data).length;
|
|
599
|
+
const compressedSize = JSON.stringify(compressed).length;
|
|
600
|
+
if (analyticsInstance) {
|
|
601
|
+
analyticsInstance.record({
|
|
602
|
+
originalSize,
|
|
603
|
+
compressedSize,
|
|
604
|
+
objectCount: dataArray.length,
|
|
605
|
+
keysCompressed: Object.keys(compressed.k).length,
|
|
606
|
+
endpoint: req.path,
|
|
607
|
+
keyPattern: compressed.p || "alpha"
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
recordEvent({
|
|
611
|
+
originalSize,
|
|
612
|
+
compressedSize,
|
|
613
|
+
objectCount: dataArray.length,
|
|
614
|
+
keysCompressed: Object.keys(compressed.k).length,
|
|
615
|
+
endpoint: req.path,
|
|
616
|
+
keyPattern: compressed.p || "alpha"
|
|
617
|
+
});
|
|
618
|
+
if (config.debug) {
|
|
619
|
+
const savings = ((1 - compressedSize / originalSize) * 100).toFixed(1);
|
|
620
|
+
console.log(
|
|
621
|
+
`[tersejson] Compressed ${originalSize} -> ${compressedSize} bytes (${savings}% savings)`
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
res.setHeader(config.headerName, "true");
|
|
625
|
+
return originalJson(compressed);
|
|
626
|
+
} catch (error) {
|
|
627
|
+
if (config.debug) {
|
|
628
|
+
console.error("[tersejson] Compression failed:", error);
|
|
629
|
+
}
|
|
630
|
+
return originalJson(data);
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
next();
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
function terseQueryParam(paramName = "terse") {
|
|
637
|
+
return function terseQueryMiddleware(req, _res, next) {
|
|
638
|
+
if (req.query[paramName] === "true") {
|
|
639
|
+
req.headers["accept-terse"] = "true";
|
|
640
|
+
}
|
|
641
|
+
next();
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
var express_default = terse;
|
|
645
|
+
|
|
646
|
+
// src/client.ts
|
|
647
|
+
var client_exports = {};
|
|
648
|
+
__export(client_exports, {
|
|
649
|
+
axiosInterceptor: () => axiosInterceptor,
|
|
650
|
+
createFetch: () => createFetch,
|
|
651
|
+
default: () => client_default,
|
|
652
|
+
expand: () => expand,
|
|
653
|
+
fetch: () => fetch,
|
|
654
|
+
isTersePayload: () => isTersePayload,
|
|
655
|
+
process: () => process2,
|
|
656
|
+
proxy: () => wrapWithProxy,
|
|
657
|
+
useTerseFetch: () => useTerseFetch
|
|
658
|
+
});
|
|
659
|
+
var DEFAULT_OPTIONS2 = {
|
|
660
|
+
headerName: "x-terse-json",
|
|
661
|
+
debug: false,
|
|
662
|
+
autoExpand: true
|
|
663
|
+
};
|
|
664
|
+
function process2(data, options = {}) {
|
|
665
|
+
const { useProxy = true } = options;
|
|
666
|
+
if (isTersePayload(data)) {
|
|
667
|
+
return useProxy ? wrapWithProxy(data) : expand(data);
|
|
668
|
+
}
|
|
669
|
+
return data;
|
|
670
|
+
}
|
|
671
|
+
function createFetch(options = {}) {
|
|
672
|
+
const config = { ...DEFAULT_OPTIONS2, ...options };
|
|
673
|
+
return async function terseFetch(input, init = {}) {
|
|
674
|
+
const headers = new Headers(init.headers);
|
|
675
|
+
headers.set("accept-terse", "true");
|
|
676
|
+
const response = await globalThis.fetch(input, {
|
|
677
|
+
...init,
|
|
678
|
+
headers
|
|
679
|
+
});
|
|
680
|
+
const isTerse = response.headers.get(config.headerName) === "true";
|
|
681
|
+
if (!isTerse || !config.autoExpand) {
|
|
682
|
+
return response;
|
|
683
|
+
}
|
|
684
|
+
const clonedResponse = response.clone();
|
|
685
|
+
return new Proxy(response, {
|
|
686
|
+
get(target, prop) {
|
|
687
|
+
if (prop === "json") {
|
|
688
|
+
return async function() {
|
|
689
|
+
const data = await clonedResponse.json();
|
|
690
|
+
if (isTersePayload(data)) {
|
|
691
|
+
if (config.debug) {
|
|
692
|
+
console.log("[tersejson] Expanding terse response");
|
|
693
|
+
}
|
|
694
|
+
return wrapWithProxy(data);
|
|
695
|
+
}
|
|
696
|
+
return data;
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
const value = Reflect.get(target, prop);
|
|
700
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
701
|
+
}
|
|
702
|
+
});
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
var fetch = createFetch();
|
|
706
|
+
function useTerseFetch(options = {}) {
|
|
707
|
+
return createFetch(options);
|
|
708
|
+
}
|
|
709
|
+
var axiosInterceptor = {
|
|
710
|
+
request: (config) => {
|
|
711
|
+
config.headers = config.headers || {};
|
|
712
|
+
config.headers["accept-terse"] = "true";
|
|
713
|
+
return config;
|
|
714
|
+
},
|
|
715
|
+
response: (response) => {
|
|
716
|
+
const isTerse = response.headers?.["x-terse-json"] === "true";
|
|
717
|
+
if (isTerse && isTersePayload(response.data)) {
|
|
718
|
+
response.data = wrapWithProxy(response.data);
|
|
719
|
+
}
|
|
720
|
+
return response;
|
|
721
|
+
}
|
|
722
|
+
};
|
|
723
|
+
var client_default = { fetch, createFetch, expand, proxy: wrapWithProxy, process: process2 };
|
|
724
|
+
|
|
725
|
+
// src/integrations.ts
|
|
726
|
+
var integrations_exports = {};
|
|
727
|
+
__export(integrations_exports, {
|
|
728
|
+
angularInterceptorSnippet: () => angularInterceptorSnippet,
|
|
729
|
+
angularJSInterceptorSnippet: () => angularJSInterceptorSnippet,
|
|
730
|
+
axiosInterceptors: () => axiosInterceptors,
|
|
731
|
+
createAngularInterceptor: () => createAngularInterceptor,
|
|
732
|
+
createAngularJSInterceptor: () => createAngularJSInterceptor,
|
|
733
|
+
createAxiosInterceptors: () => createAxiosInterceptors,
|
|
734
|
+
createQueryFn: () => createQueryFn,
|
|
735
|
+
createSWRFetcher: () => createSWRFetcher,
|
|
736
|
+
default: () => integrations_default,
|
|
737
|
+
jQuerySetupSnippet: () => jQuerySetupSnippet,
|
|
738
|
+
setupJQueryAjax: () => setupJQueryAjax
|
|
739
|
+
});
|
|
740
|
+
function createAxiosInterceptors(options = {}) {
|
|
741
|
+
const { useProxy = true, debug = false } = options;
|
|
742
|
+
return {
|
|
743
|
+
request: (config) => {
|
|
744
|
+
if (config.headers) {
|
|
745
|
+
if (typeof config.headers.set === "function") {
|
|
746
|
+
config.headers.set("accept-terse", "true");
|
|
747
|
+
} else {
|
|
748
|
+
config.headers["accept-terse"] = "true";
|
|
749
|
+
}
|
|
750
|
+
} else {
|
|
751
|
+
config.headers = { "accept-terse": "true" };
|
|
752
|
+
}
|
|
753
|
+
return config;
|
|
754
|
+
},
|
|
755
|
+
response: (response) => {
|
|
756
|
+
let isTerse = false;
|
|
757
|
+
if (response.headers) {
|
|
758
|
+
if (typeof response.headers.get === "function") {
|
|
759
|
+
isTerse = response.headers.get("x-terse-json") === "true";
|
|
760
|
+
} else {
|
|
761
|
+
isTerse = response.headers["x-terse-json"] === "true";
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
if (isTerse && isTersePayload(response.data)) {
|
|
765
|
+
if (debug) {
|
|
766
|
+
console.log("[tersejson] Expanding Axios response");
|
|
767
|
+
}
|
|
768
|
+
response.data = useProxy ? wrapWithProxy(response.data) : expand(response.data);
|
|
769
|
+
}
|
|
770
|
+
return response;
|
|
771
|
+
}
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
var axiosInterceptors = createAxiosInterceptors();
|
|
775
|
+
function createAngularInterceptor(options = {}) {
|
|
776
|
+
const { useProxy = true, debug = false } = options;
|
|
777
|
+
return {
|
|
778
|
+
/**
|
|
779
|
+
* Modifies the request to include the accept-terse header
|
|
780
|
+
*/
|
|
781
|
+
modifyRequest: (req) => {
|
|
782
|
+
return req.clone({
|
|
783
|
+
setHeaders: {
|
|
784
|
+
"accept-terse": "true"
|
|
785
|
+
}
|
|
786
|
+
});
|
|
787
|
+
},
|
|
788
|
+
/**
|
|
789
|
+
* Processes the response to expand TerseJSON payloads
|
|
790
|
+
*/
|
|
791
|
+
processResponse: (event) => {
|
|
792
|
+
if (event.type === 4 && event.body !== void 0) {
|
|
793
|
+
const isTerse = event.headers?.get("x-terse-json") === "true";
|
|
794
|
+
if (isTerse && isTersePayload(event.body)) {
|
|
795
|
+
if (debug) {
|
|
796
|
+
console.log("[tersejson] Expanding Angular response");
|
|
797
|
+
}
|
|
798
|
+
return {
|
|
799
|
+
...event,
|
|
800
|
+
body: useProxy ? wrapWithProxy(event.body) : expand(event.body)
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
return event;
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
var angularInterceptorSnippet = `
|
|
809
|
+
// terse.interceptor.ts
|
|
810
|
+
import { Injectable } from '@angular/core';
|
|
811
|
+
import {
|
|
812
|
+
HttpInterceptor,
|
|
813
|
+
HttpRequest,
|
|
814
|
+
HttpHandler,
|
|
815
|
+
HttpEvent,
|
|
816
|
+
HttpResponse
|
|
817
|
+
} from '@angular/common/http';
|
|
818
|
+
import { Observable } from 'rxjs';
|
|
819
|
+
import { map } from 'rxjs/operators';
|
|
820
|
+
import { isTersePayload, wrapWithProxy } from 'tersejson';
|
|
821
|
+
|
|
822
|
+
@Injectable()
|
|
823
|
+
export class TerseInterceptor implements HttpInterceptor {
|
|
824
|
+
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
|
825
|
+
// Add accept-terse header
|
|
826
|
+
const terseReq = req.clone({
|
|
827
|
+
setHeaders: { 'accept-terse': 'true' }
|
|
828
|
+
});
|
|
829
|
+
|
|
830
|
+
return next.handle(terseReq).pipe(
|
|
831
|
+
map(event => {
|
|
832
|
+
if (event instanceof HttpResponse && event.body) {
|
|
833
|
+
const isTerse = event.headers.get('x-terse-json') === 'true';
|
|
834
|
+
if (isTerse && isTersePayload(event.body)) {
|
|
835
|
+
return event.clone({ body: wrapWithProxy(event.body) });
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
return event;
|
|
839
|
+
})
|
|
840
|
+
);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// app.module.ts - Add to providers:
|
|
845
|
+
// { provide: HTTP_INTERCEPTORS, useClass: TerseInterceptor, multi: true }
|
|
846
|
+
`;
|
|
847
|
+
function createAngularJSInterceptor(options = {}) {
|
|
848
|
+
const { useProxy = true, debug = false } = options;
|
|
849
|
+
return {
|
|
850
|
+
/**
|
|
851
|
+
* Request interceptor - adds accept-terse header
|
|
852
|
+
*/
|
|
853
|
+
request: (config) => {
|
|
854
|
+
config.headers = config.headers || {};
|
|
855
|
+
config.headers["accept-terse"] = "true";
|
|
856
|
+
return config;
|
|
857
|
+
},
|
|
858
|
+
/**
|
|
859
|
+
* Response interceptor - expands TerseJSON payloads
|
|
860
|
+
*/
|
|
861
|
+
response: (response) => {
|
|
862
|
+
const isTerse = response.headers("x-terse-json") === "true";
|
|
863
|
+
if (isTerse && isTersePayload(response.data)) {
|
|
864
|
+
if (debug) {
|
|
865
|
+
console.log("[tersejson] Expanding AngularJS response");
|
|
866
|
+
}
|
|
867
|
+
response.data = useProxy ? wrapWithProxy(response.data) : expand(response.data);
|
|
868
|
+
}
|
|
869
|
+
return response;
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
var angularJSInterceptorSnippet = `
|
|
874
|
+
// Setup TerseJSON with AngularJS
|
|
875
|
+
angular.module('myApp', [])
|
|
876
|
+
.factory('terseInterceptor', ['$q', function($q) {
|
|
877
|
+
return {
|
|
878
|
+
request: function(config) {
|
|
879
|
+
config.headers = config.headers || {};
|
|
880
|
+
config.headers['accept-terse'] = 'true';
|
|
881
|
+
return config;
|
|
882
|
+
},
|
|
883
|
+
response: function(response) {
|
|
884
|
+
var isTerse = response.headers('x-terse-json') === 'true';
|
|
885
|
+
if (isTerse && response.data && response.data.__terse__) {
|
|
886
|
+
// Use tersejson.process() or tersejson.wrapWithProxy()
|
|
887
|
+
response.data = tersejson.process(response.data);
|
|
888
|
+
}
|
|
889
|
+
return response;
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
}])
|
|
893
|
+
.config(['$httpProvider', function($httpProvider) {
|
|
894
|
+
$httpProvider.interceptors.push('terseInterceptor');
|
|
895
|
+
}]);
|
|
896
|
+
`;
|
|
897
|
+
function setupJQueryAjax($, options = {}) {
|
|
898
|
+
const { useProxy = true, debug = false } = options;
|
|
899
|
+
$.ajaxSetup({
|
|
900
|
+
headers: {
|
|
901
|
+
"accept-terse": "true"
|
|
902
|
+
}
|
|
903
|
+
});
|
|
904
|
+
$.ajaxPrefilter((ajaxOptions) => {
|
|
905
|
+
const originalDataFilter = ajaxOptions.dataFilter;
|
|
906
|
+
ajaxOptions.dataFilter = function(data, type) {
|
|
907
|
+
let processed = data;
|
|
908
|
+
if (originalDataFilter) {
|
|
909
|
+
processed = originalDataFilter(data, type);
|
|
910
|
+
}
|
|
911
|
+
if (type === "json" || type === void 0) {
|
|
912
|
+
try {
|
|
913
|
+
const parsed = typeof processed === "string" ? JSON.parse(processed) : processed;
|
|
914
|
+
if (isTersePayload(parsed)) {
|
|
915
|
+
if (debug) {
|
|
916
|
+
console.log("[tersejson] Expanding jQuery response");
|
|
917
|
+
}
|
|
918
|
+
return useProxy ? wrapWithProxy(parsed) : expand(parsed);
|
|
919
|
+
}
|
|
920
|
+
return parsed;
|
|
921
|
+
} catch {
|
|
922
|
+
return processed;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
return processed;
|
|
926
|
+
};
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
var jQuerySetupSnippet = `
|
|
930
|
+
// Setup TerseJSON with jQuery
|
|
931
|
+
$.ajaxSetup({
|
|
932
|
+
headers: { 'accept-terse': 'true' },
|
|
933
|
+
dataFilter: function(data, type) {
|
|
934
|
+
if (type === 'json') {
|
|
935
|
+
var parsed = JSON.parse(data);
|
|
936
|
+
if (parsed && parsed.__terse__) {
|
|
937
|
+
return tersejson.process(parsed);
|
|
938
|
+
}
|
|
939
|
+
return parsed;
|
|
940
|
+
}
|
|
941
|
+
return data;
|
|
942
|
+
}
|
|
943
|
+
});
|
|
944
|
+
`;
|
|
945
|
+
function createSWRFetcher(options = {}) {
|
|
946
|
+
const { useProxy = true, debug = false } = options;
|
|
947
|
+
return async (url) => {
|
|
948
|
+
const response = await globalThis.fetch(url, {
|
|
949
|
+
headers: {
|
|
950
|
+
"accept-terse": "true"
|
|
951
|
+
}
|
|
952
|
+
});
|
|
953
|
+
if (!response.ok) {
|
|
954
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
955
|
+
}
|
|
956
|
+
const data = await response.json();
|
|
957
|
+
if (isTersePayload(data)) {
|
|
958
|
+
if (debug) {
|
|
959
|
+
console.log("[tersejson] Expanding SWR response");
|
|
960
|
+
}
|
|
961
|
+
return useProxy ? wrapWithProxy(data) : expand(data);
|
|
962
|
+
}
|
|
963
|
+
return data;
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
var createQueryFn = createSWRFetcher;
|
|
967
|
+
var integrations_default = {
|
|
968
|
+
// Axios
|
|
969
|
+
createAxiosInterceptors,
|
|
970
|
+
axiosInterceptors,
|
|
971
|
+
// Angular
|
|
972
|
+
createAngularInterceptor,
|
|
973
|
+
angularInterceptorSnippet,
|
|
974
|
+
// AngularJS
|
|
975
|
+
createAngularJSInterceptor,
|
|
976
|
+
angularJSInterceptorSnippet,
|
|
977
|
+
// jQuery
|
|
978
|
+
setupJQueryAjax,
|
|
979
|
+
jQuerySetupSnippet,
|
|
980
|
+
// SWR / React Query
|
|
981
|
+
createSWRFetcher,
|
|
982
|
+
createQueryFn
|
|
983
|
+
};
|
|
984
|
+
|
|
985
|
+
exports.TerseAnalytics = TerseAnalytics;
|
|
986
|
+
exports.analytics = analytics;
|
|
987
|
+
exports.client = client_exports;
|
|
988
|
+
exports.compress = compress;
|
|
989
|
+
exports.createKeyGenerator = createKeyGenerator;
|
|
990
|
+
exports.createTerseProxy = createTerseProxy;
|
|
991
|
+
exports.expand = expand;
|
|
992
|
+
exports.express = express_exports;
|
|
993
|
+
exports.getAnalytics = getAnalytics;
|
|
994
|
+
exports.initAnalytics = initAnalytics;
|
|
995
|
+
exports.integrations = integrations_exports;
|
|
996
|
+
exports.isCompressibleArray = isCompressibleArray;
|
|
997
|
+
exports.isTersePayload = isTersePayload;
|
|
998
|
+
exports.recordEvent = recordEvent;
|
|
999
|
+
exports.wrapWithProxy = wrapWithProxy;
|
|
1000
|
+
//# sourceMappingURL=index.js.map
|
|
1001
|
+
//# sourceMappingURL=index.js.map
|