@linkforty/core 1.0.0 → 1.2.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/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/database.d.ts.map +1 -1
- package/dist/lib/database.js +154 -0
- package/dist/lib/database.js.map +1 -1
- package/dist/lib/event-emitter.d.ts +46 -0
- package/dist/lib/event-emitter.d.ts.map +1 -0
- package/dist/lib/event-emitter.js +29 -0
- package/dist/lib/event-emitter.js.map +1 -0
- package/dist/lib/fingerprint.d.ts +64 -0
- package/dist/lib/fingerprint.d.ts.map +1 -0
- package/dist/lib/fingerprint.js +387 -0
- package/dist/lib/fingerprint.js.map +1 -0
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +1 -0
- package/dist/lib/utils.js.map +1 -1
- package/dist/lib/webhook.d.ts +18 -0
- package/dist/lib/webhook.d.ts.map +1 -0
- package/dist/lib/webhook.js +150 -0
- package/dist/lib/webhook.js.map +1 -0
- package/dist/routes/debug.d.ts +7 -0
- package/dist/routes/debug.d.ts.map +1 -0
- package/dist/routes/debug.js +321 -0
- package/dist/routes/debug.js.map +1 -0
- package/dist/routes/index.d.ts +5 -0
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +11 -1
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/links.d.ts.map +1 -1
- package/dist/routes/links.js +21 -3
- package/dist/routes/links.js.map +1 -1
- package/dist/routes/preview.d.ts +3 -0
- package/dist/routes/preview.d.ts.map +1 -0
- package/dist/routes/preview.js +225 -0
- package/dist/routes/preview.js.map +1 -0
- package/dist/routes/qr.d.ts +6 -0
- package/dist/routes/qr.d.ts.map +1 -0
- package/dist/routes/qr.js +136 -0
- package/dist/routes/qr.js.map +1 -0
- package/dist/routes/redirect.d.ts.map +1 -1
- package/dist/routes/redirect.js +167 -11
- package/dist/routes/redirect.js.map +1 -1
- package/dist/routes/sdk.d.ts +7 -0
- package/dist/routes/sdk.d.ts.map +1 -0
- package/dist/routes/sdk.js +265 -0
- package/dist/routes/sdk.js.map +1 -0
- package/dist/routes/webhooks.d.ts +3 -0
- package/dist/routes/webhooks.d.ts.map +1 -0
- package/dist/routes/webhooks.js +212 -0
- package/dist/routes/webhooks.js.map +1 -0
- package/dist/types/index.d.ts +81 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +11 -7
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.CONFIDENCE_THRESHOLD = exports.DEFAULT_ATTRIBUTION_WINDOW_HOURS = void 0;
|
|
40
|
+
exports.generateFingerprintHash = generateFingerprintHash;
|
|
41
|
+
exports.calculateConfidenceScore = calculateConfidenceScore;
|
|
42
|
+
exports.matchInstallToClick = matchInstallToClick;
|
|
43
|
+
exports.storeFingerprintForClick = storeFingerprintForClick;
|
|
44
|
+
exports.recordInstallEvent = recordInstallEvent;
|
|
45
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
46
|
+
const database_js_1 = require("./database.js");
|
|
47
|
+
/**
|
|
48
|
+
* Scoring weights for probabilistic matching
|
|
49
|
+
* Total should equal 100 for percentage-based confidence
|
|
50
|
+
*/
|
|
51
|
+
const FINGERPRINT_WEIGHTS = {
|
|
52
|
+
IP_ADDRESS: 40,
|
|
53
|
+
USER_AGENT: 30,
|
|
54
|
+
TIMEZONE: 10,
|
|
55
|
+
LANGUAGE: 10,
|
|
56
|
+
SCREEN_RESOLUTION: 10,
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Default attribution window in hours (7 days)
|
|
60
|
+
*/
|
|
61
|
+
exports.DEFAULT_ATTRIBUTION_WINDOW_HOURS = 168;
|
|
62
|
+
/**
|
|
63
|
+
* Minimum confidence threshold for attribution (70%)
|
|
64
|
+
*/
|
|
65
|
+
exports.CONFIDENCE_THRESHOLD = 70;
|
|
66
|
+
/**
|
|
67
|
+
* Generate a fingerprint hash from device data
|
|
68
|
+
* Uses SHA-256 hash of concatenated device attributes
|
|
69
|
+
*/
|
|
70
|
+
function generateFingerprintHash(data) {
|
|
71
|
+
const components = [
|
|
72
|
+
data.ipAddress || '',
|
|
73
|
+
data.userAgent || '',
|
|
74
|
+
data.timezone || '',
|
|
75
|
+
data.language || '',
|
|
76
|
+
data.screenWidth?.toString() || '',
|
|
77
|
+
data.screenHeight?.toString() || '',
|
|
78
|
+
data.platform || '',
|
|
79
|
+
data.platformVersion || '',
|
|
80
|
+
];
|
|
81
|
+
const concatenated = components.join('|');
|
|
82
|
+
return crypto_1.default.createHash('sha256').update(concatenated).digest('hex');
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Normalize IP address for comparison
|
|
86
|
+
* Handles IPv4 and IPv6, removes subnet variations
|
|
87
|
+
*/
|
|
88
|
+
function normalizeIP(ip) {
|
|
89
|
+
if (!ip)
|
|
90
|
+
return '';
|
|
91
|
+
// For IPv4, use first 3 octets (e.g., 192.168.1.x)
|
|
92
|
+
if (ip.includes('.')) {
|
|
93
|
+
const parts = ip.split('.');
|
|
94
|
+
return parts.slice(0, 3).join('.');
|
|
95
|
+
}
|
|
96
|
+
// For IPv6, use first 4 groups (e.g., 2001:0db8:85a3:0000:xxxx)
|
|
97
|
+
if (ip.includes(':')) {
|
|
98
|
+
const parts = ip.split(':');
|
|
99
|
+
return parts.slice(0, 4).join(':');
|
|
100
|
+
}
|
|
101
|
+
return ip;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Normalize user agent for comparison
|
|
105
|
+
* Extracts key identifiers and removes version numbers
|
|
106
|
+
*/
|
|
107
|
+
function normalizeUserAgent(ua) {
|
|
108
|
+
if (!ua)
|
|
109
|
+
return '';
|
|
110
|
+
// Extract platform (iOS, Android, Windows, Mac, Linux)
|
|
111
|
+
const platformMatch = ua.match(/(iPhone|iPad|Android|Windows|Macintosh|Linux)/i);
|
|
112
|
+
const platform = platformMatch ? platformMatch[1] : '';
|
|
113
|
+
// Extract browser (Chrome, Safari, Firefox, Edge)
|
|
114
|
+
const browserMatch = ua.match(/(Chrome|Safari|Firefox|Edge|Opera)/i);
|
|
115
|
+
const browser = browserMatch ? browserMatch[1] : '';
|
|
116
|
+
return `${platform}|${browser}`.toLowerCase();
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Calculate confidence score by comparing two fingerprints
|
|
120
|
+
* Returns a score from 0-100 based on matched components
|
|
121
|
+
*/
|
|
122
|
+
function calculateConfidenceScore(fingerprint1, fingerprint2) {
|
|
123
|
+
let score = 0;
|
|
124
|
+
const matchedFactors = [];
|
|
125
|
+
// Compare IP addresses (normalized to /24 subnet for IPv4)
|
|
126
|
+
if (fingerprint1.ipAddress && fingerprint2.ipAddress) {
|
|
127
|
+
const ip1 = normalizeIP(fingerprint1.ipAddress);
|
|
128
|
+
const ip2 = normalizeIP(fingerprint2.ipAddress);
|
|
129
|
+
if (ip1 === ip2) {
|
|
130
|
+
score += FINGERPRINT_WEIGHTS.IP_ADDRESS;
|
|
131
|
+
matchedFactors.push('ip');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Compare user agents (normalized to platform + browser)
|
|
135
|
+
if (fingerprint1.userAgent && fingerprint2.userAgent) {
|
|
136
|
+
const ua1 = normalizeUserAgent(fingerprint1.userAgent);
|
|
137
|
+
const ua2 = normalizeUserAgent(fingerprint2.userAgent);
|
|
138
|
+
if (ua1 === ua2) {
|
|
139
|
+
score += FINGERPRINT_WEIGHTS.USER_AGENT;
|
|
140
|
+
matchedFactors.push('user_agent');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Compare timezone
|
|
144
|
+
if (fingerprint1.timezone && fingerprint2.timezone) {
|
|
145
|
+
if (fingerprint1.timezone === fingerprint2.timezone) {
|
|
146
|
+
score += FINGERPRINT_WEIGHTS.TIMEZONE;
|
|
147
|
+
matchedFactors.push('timezone');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Compare language
|
|
151
|
+
if (fingerprint1.language && fingerprint2.language) {
|
|
152
|
+
// Match first 2 characters (e.g., "en-US" matches "en-GB")
|
|
153
|
+
const lang1 = fingerprint1.language.substring(0, 2).toLowerCase();
|
|
154
|
+
const lang2 = fingerprint2.language.substring(0, 2).toLowerCase();
|
|
155
|
+
if (lang1 === lang2) {
|
|
156
|
+
score += FINGERPRINT_WEIGHTS.LANGUAGE;
|
|
157
|
+
matchedFactors.push('language');
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Compare screen resolution
|
|
161
|
+
if (fingerprint1.screenWidth &&
|
|
162
|
+
fingerprint1.screenHeight &&
|
|
163
|
+
fingerprint2.screenWidth &&
|
|
164
|
+
fingerprint2.screenHeight) {
|
|
165
|
+
if (fingerprint1.screenWidth === fingerprint2.screenWidth &&
|
|
166
|
+
fingerprint1.screenHeight === fingerprint2.screenHeight) {
|
|
167
|
+
score += FINGERPRINT_WEIGHTS.SCREEN_RESOLUTION;
|
|
168
|
+
matchedFactors.push('screen');
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return { score, matchedFactors };
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Match an install event to potential click events via probabilistic fingerprinting
|
|
175
|
+
* Returns the best match above confidence threshold within attribution window
|
|
176
|
+
*
|
|
177
|
+
* Note: Uses link-specific attribution windows - each link can have its own window
|
|
178
|
+
*/
|
|
179
|
+
async function matchInstallToClick(installFingerprint, attributionWindowHours = exports.DEFAULT_ATTRIBUTION_WINDOW_HOURS) {
|
|
180
|
+
// Query recent click events within maximum possible attribution window (90 days)
|
|
181
|
+
// We'll validate against each link's specific window during matching
|
|
182
|
+
const maxWindowHours = 2160; // 90 days
|
|
183
|
+
const cutoffTime = new Date(Date.now() - maxWindowHours * 60 * 60 * 1000);
|
|
184
|
+
const clicksResult = await database_js_1.db.query(`SELECT
|
|
185
|
+
ce.id as click_id,
|
|
186
|
+
ce.link_id,
|
|
187
|
+
ce.clicked_at,
|
|
188
|
+
l.attribution_window_hours,
|
|
189
|
+
df.ip_address,
|
|
190
|
+
df.user_agent,
|
|
191
|
+
df.timezone,
|
|
192
|
+
df.language,
|
|
193
|
+
df.screen_width,
|
|
194
|
+
df.screen_height,
|
|
195
|
+
df.platform,
|
|
196
|
+
df.platform_version
|
|
197
|
+
FROM click_events ce
|
|
198
|
+
INNER JOIN device_fingerprints df ON df.click_id = ce.id
|
|
199
|
+
INNER JOIN links l ON ce.link_id = l.id
|
|
200
|
+
WHERE ce.clicked_at >= $1
|
|
201
|
+
ORDER BY ce.clicked_at DESC
|
|
202
|
+
LIMIT 1000`, [cutoffTime]);
|
|
203
|
+
if (clicksResult.rows.length === 0) {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
const installTime = new Date();
|
|
207
|
+
// Calculate confidence score for each potential match
|
|
208
|
+
let bestMatch = null;
|
|
209
|
+
let highestScore = 0;
|
|
210
|
+
for (const row of clicksResult.rows) {
|
|
211
|
+
// Check if click is within the link's specific attribution window
|
|
212
|
+
const linkWindowHours = row.attribution_window_hours || exports.DEFAULT_ATTRIBUTION_WINDOW_HOURS;
|
|
213
|
+
const clickTime = new Date(row.clicked_at);
|
|
214
|
+
const timeDiffHours = (installTime.getTime() - clickTime.getTime()) / (1000 * 60 * 60);
|
|
215
|
+
if (timeDiffHours > linkWindowHours) {
|
|
216
|
+
// Click is too old for this link's attribution window, skip it
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
const clickFingerprint = {
|
|
220
|
+
ipAddress: row.ip_address,
|
|
221
|
+
userAgent: row.user_agent,
|
|
222
|
+
timezone: row.timezone,
|
|
223
|
+
language: row.language,
|
|
224
|
+
screenWidth: row.screen_width,
|
|
225
|
+
screenHeight: row.screen_height,
|
|
226
|
+
platform: row.platform,
|
|
227
|
+
platformVersion: row.platform_version,
|
|
228
|
+
};
|
|
229
|
+
const { score, matchedFactors } = calculateConfidenceScore(installFingerprint, clickFingerprint);
|
|
230
|
+
// Track the best match
|
|
231
|
+
if (score > highestScore && score >= exports.CONFIDENCE_THRESHOLD) {
|
|
232
|
+
highestScore = score;
|
|
233
|
+
bestMatch = {
|
|
234
|
+
clickId: row.click_id,
|
|
235
|
+
linkId: row.link_id,
|
|
236
|
+
confidenceScore: score,
|
|
237
|
+
matchedFactors,
|
|
238
|
+
clickedAt: new Date(row.clicked_at),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return bestMatch;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Store device fingerprint for a click event
|
|
246
|
+
*/
|
|
247
|
+
async function storeFingerprintForClick(clickId, fingerprintData) {
|
|
248
|
+
const fingerprintHash = generateFingerprintHash(fingerprintData);
|
|
249
|
+
await database_js_1.db.query(`INSERT INTO device_fingerprints (
|
|
250
|
+
click_id,
|
|
251
|
+
fingerprint_hash,
|
|
252
|
+
ip_address,
|
|
253
|
+
user_agent,
|
|
254
|
+
timezone,
|
|
255
|
+
language,
|
|
256
|
+
screen_width,
|
|
257
|
+
screen_height,
|
|
258
|
+
platform,
|
|
259
|
+
platform_version
|
|
260
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, [
|
|
261
|
+
clickId,
|
|
262
|
+
fingerprintHash,
|
|
263
|
+
fingerprintData.ipAddress,
|
|
264
|
+
fingerprintData.userAgent,
|
|
265
|
+
fingerprintData.timezone || null,
|
|
266
|
+
fingerprintData.language || null,
|
|
267
|
+
fingerprintData.screenWidth || null,
|
|
268
|
+
fingerprintData.screenHeight || null,
|
|
269
|
+
fingerprintData.platform || null,
|
|
270
|
+
fingerprintData.platformVersion || null,
|
|
271
|
+
]);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Record an install event and attempt to match it to a click
|
|
275
|
+
*/
|
|
276
|
+
async function recordInstallEvent(fingerprintData, deviceId, attributionWindowHours = exports.DEFAULT_ATTRIBUTION_WINDOW_HOURS) {
|
|
277
|
+
const fingerprintHash = generateFingerprintHash(fingerprintData);
|
|
278
|
+
// Attempt to match install to a click
|
|
279
|
+
const match = await matchInstallToClick(fingerprintData, attributionWindowHours);
|
|
280
|
+
// Insert install event
|
|
281
|
+
const installResult = await database_js_1.db.query(`INSERT INTO install_events (
|
|
282
|
+
link_id,
|
|
283
|
+
click_id,
|
|
284
|
+
fingerprint_hash,
|
|
285
|
+
confidence_score,
|
|
286
|
+
installed_at,
|
|
287
|
+
first_open_at,
|
|
288
|
+
attribution_window_hours,
|
|
289
|
+
ip_address,
|
|
290
|
+
user_agent,
|
|
291
|
+
timezone,
|
|
292
|
+
language,
|
|
293
|
+
screen_width,
|
|
294
|
+
screen_height,
|
|
295
|
+
platform,
|
|
296
|
+
platform_version,
|
|
297
|
+
device_id,
|
|
298
|
+
deep_link_data
|
|
299
|
+
) VALUES ($1, $2, $3, $4, NOW(), NOW(), $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
|
|
300
|
+
RETURNING id, deep_link_data`, [
|
|
301
|
+
match?.linkId || null,
|
|
302
|
+
match?.clickId || null,
|
|
303
|
+
fingerprintHash,
|
|
304
|
+
match?.confidenceScore || null,
|
|
305
|
+
attributionWindowHours,
|
|
306
|
+
fingerprintData.ipAddress,
|
|
307
|
+
fingerprintData.userAgent,
|
|
308
|
+
fingerprintData.timezone || null,
|
|
309
|
+
fingerprintData.language || null,
|
|
310
|
+
fingerprintData.screenWidth || null,
|
|
311
|
+
fingerprintData.screenHeight || null,
|
|
312
|
+
fingerprintData.platform || null,
|
|
313
|
+
fingerprintData.platformVersion || null,
|
|
314
|
+
deviceId || null,
|
|
315
|
+
match ? JSON.stringify({}) : JSON.stringify({}), // Will be populated from link data
|
|
316
|
+
]);
|
|
317
|
+
const installId = installResult.rows[0].id;
|
|
318
|
+
let deepLinkData = {};
|
|
319
|
+
// If we have a match, retrieve the deep link data from the original link
|
|
320
|
+
if (match) {
|
|
321
|
+
const linkResult = await database_js_1.db.query(`SELECT
|
|
322
|
+
short_code,
|
|
323
|
+
original_url,
|
|
324
|
+
ios_url,
|
|
325
|
+
android_url,
|
|
326
|
+
web_fallback_url,
|
|
327
|
+
utm_parameters,
|
|
328
|
+
targeting_rules
|
|
329
|
+
FROM links
|
|
330
|
+
WHERE id = $1`, [match.linkId]);
|
|
331
|
+
if (linkResult.rows.length > 0) {
|
|
332
|
+
const link = linkResult.rows[0];
|
|
333
|
+
deepLinkData = {
|
|
334
|
+
shortCode: link.short_code,
|
|
335
|
+
originalUrl: link.original_url,
|
|
336
|
+
iosUrl: link.ios_url,
|
|
337
|
+
androidUrl: link.android_url,
|
|
338
|
+
webFallbackUrl: link.web_fallback_url,
|
|
339
|
+
utmParameters: link.utm_parameters,
|
|
340
|
+
targetingRules: link.targeting_rules,
|
|
341
|
+
clickedAt: match.clickedAt,
|
|
342
|
+
confidenceScore: match.confidenceScore,
|
|
343
|
+
matchedFactors: match.matchedFactors,
|
|
344
|
+
};
|
|
345
|
+
// Update the install event with deep link data
|
|
346
|
+
await database_js_1.db.query(`UPDATE install_events
|
|
347
|
+
SET deep_link_data = $1,
|
|
348
|
+
deep_link_retrieved = true
|
|
349
|
+
WHERE id = $2`, [JSON.stringify(deepLinkData), installId]);
|
|
350
|
+
// Trigger webhooks for install_event (only if attributed)
|
|
351
|
+
try {
|
|
352
|
+
// Get the link's user_id for webhook lookup
|
|
353
|
+
const linkUserResult = await database_js_1.db.query('SELECT user_id FROM links WHERE id = $1', [match.linkId]);
|
|
354
|
+
if (linkUserResult.rows.length > 0) {
|
|
355
|
+
const userId = linkUserResult.rows[0].user_id;
|
|
356
|
+
const webhooksResult = await database_js_1.db.query('SELECT * FROM webhooks WHERE user_id = $1 AND is_active = true', [userId]);
|
|
357
|
+
if (webhooksResult.rows.length > 0) {
|
|
358
|
+
const { triggerWebhooks } = await Promise.resolve().then(() => __importStar(require('./webhook.js')));
|
|
359
|
+
const installEventData = {
|
|
360
|
+
id: installId,
|
|
361
|
+
linkId: match.linkId,
|
|
362
|
+
fingerprintHash,
|
|
363
|
+
confidenceScore: match.confidenceScore,
|
|
364
|
+
installedAt: new Date().toISOString(),
|
|
365
|
+
deepLinkData,
|
|
366
|
+
ipAddress: fingerprintData.ipAddress,
|
|
367
|
+
userAgent: fingerprintData.userAgent,
|
|
368
|
+
platform: fingerprintData.platform,
|
|
369
|
+
};
|
|
370
|
+
// Trigger webhooks without delivery logging (basic version)
|
|
371
|
+
// For delivery logging, use @linkforty/cloud premium features
|
|
372
|
+
await triggerWebhooks(webhooksResult.rows, 'install_event', installId, installEventData);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
catch (webhookError) {
|
|
377
|
+
console.error(`Error triggering install webhooks: ${webhookError}`);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return {
|
|
382
|
+
installId,
|
|
383
|
+
match,
|
|
384
|
+
deepLinkData,
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
//# sourceMappingURL=fingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/lib/fingerprint.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/utils.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export declare function generateShortCode(length?: number): string;
|
|
|
2
2
|
export declare function parseUserAgent(userAgent: string): {
|
|
3
3
|
deviceType: string;
|
|
4
4
|
platform: string;
|
|
5
|
+
platformVersion: string | undefined;
|
|
5
6
|
browser: string;
|
|
6
7
|
};
|
|
7
8
|
export declare function getLocationFromIP(ip: string): {
|
package/dist/lib/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAIA,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,MAAU,GAAG,MAAM,CAE5D;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAIA,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,MAAU,GAAG,MAAM,CAE5D;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM;;;;;EAU/C;AAoDD,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;;;EAwB3C;AAED,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACrC,MAAM,CAYR;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,KAAK,CAYzE"}
|
package/dist/lib/utils.js
CHANGED
package/dist/lib/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":";;;;;AAIA,8CAEC;AAED,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":";;;;;AAIA,8CAEC;AAED,wCAUC;AAoDD,8CAwBC;AAED,4CAeC;AAED,oCAYC;AA7HD,mCAAgC;AAChC,4DAA+B;AAC/B,gEAAoC;AAEpC,SAAgB,iBAAiB,CAAC,SAAiB,CAAC;IAClD,OAAO,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC;AACxB,CAAC;AAED,SAAgB,cAAc,CAAC,SAAiB;IAC9C,MAAM,MAAM,GAAG,IAAI,sBAAQ,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;IAElC,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,SAAS;QAC3C,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,SAAS;QACrC,eAAe,EAAE,MAAM,CAAC,EAAE,CAAC,OAAO,IAAI,SAAS;QAC/C,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,SAAS;KAC1C,CAAC;AACJ,CAAC;AAED,kDAAkD;AAClD,MAAM,aAAa,GAA2B;IAC5C,EAAE,EAAE,eAAe;IACnB,EAAE,EAAE,gBAAgB;IACpB,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,OAAO;IACX,EAAE,EAAE,OAAO;IACX,EAAE,EAAE,aAAa;IACjB,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,OAAO;IACX,EAAE,EAAE,OAAO;IACX,EAAE,EAAE,OAAO;IACX,EAAE,EAAE,aAAa;IACjB,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,aAAa;IACjB,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,cAAc;IAClB,EAAE,EAAE,OAAO;IACX,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,OAAO;IACX,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,sBAAsB;IAC1B,EAAE,EAAE,cAAc;IAClB,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,aAAa;IACjB,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,aAAa;IACjB,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,gBAAgB;IACpB,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,SAAS;CACd,CAAC;AAEF,SAAgB,iBAAiB,CAAC,EAAU;IAC1C,MAAM,GAAG,GAAG,oBAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAE7B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO;YACL,WAAW,EAAE,IAAI;YACjB,WAAW,EAAE,IAAI;YACjB,MAAM,EAAE,IAAI;YACZ,IAAI,EAAE,IAAI;YACV,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;YACf,QAAQ,EAAE,IAAI;SACf,CAAC;IACJ,CAAC;IAED,OAAO;QACL,WAAW,EAAE,GAAG,CAAC,OAAO;QACxB,WAAW,EAAE,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,OAAO;QACtD,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,QAAQ,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI;QAC7B,SAAS,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI;QAC9B,QAAQ,EAAE,GAAG,CAAC,QAAQ;KACvB,CAAC;AACJ,CAAC;AAED,SAAgB,gBAAgB,CAC9B,WAAmB,EACnB,aAAsC;IAEtC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;IAEjC,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YACrD,IAAI,KAAK,EAAE,CAAC;gBACV,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED,SAAgB,YAAY,CAAC,SAAiB;IAC5C,MAAM,EAAE,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;IAEnC,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACxE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Webhook, WebhookPayload, WebhookDeliveryResult, WebhookEvent } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generate HMAC SHA-256 signature for webhook payload
|
|
4
|
+
*/
|
|
5
|
+
export declare function generateWebhookSignature(payload: string, secret: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Generate a secure random secret for webhook signing
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateWebhookSecret(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Deliver webhook with retry logic and exponential backoff
|
|
12
|
+
*/
|
|
13
|
+
export declare function deliverWebhook(webhook: Webhook, payload: WebhookPayload, logDelivery?: (result: WebhookDeliveryResult) => Promise<void>): Promise<WebhookDeliveryResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Trigger webhooks for a specific event (fire and forget)
|
|
16
|
+
*/
|
|
17
|
+
export declare function triggerWebhooks(webhooks: Webhook[], event: WebhookEvent, eventId: string, data: any, logDelivery?: (webhookId: string, result: WebhookDeliveryResult) => Promise<void>): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=webhook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/lib/webhook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtG;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AA4ED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,cAAc,EACvB,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,GAC7D,OAAO,CAAC,qBAAqB,CAAC,CAmChC;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,GAAG,EACT,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,GAChF,OAAO,CAAC,IAAI,CAAC,CAuCf"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateWebhookSignature = generateWebhookSignature;
|
|
7
|
+
exports.generateWebhookSecret = generateWebhookSecret;
|
|
8
|
+
exports.deliverWebhook = deliverWebhook;
|
|
9
|
+
exports.triggerWebhooks = triggerWebhooks;
|
|
10
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
11
|
+
/**
|
|
12
|
+
* Generate HMAC SHA-256 signature for webhook payload
|
|
13
|
+
*/
|
|
14
|
+
function generateWebhookSignature(payload, secret) {
|
|
15
|
+
return crypto_1.default.createHmac('sha256', secret).update(payload).digest('hex');
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Generate a secure random secret for webhook signing
|
|
19
|
+
*/
|
|
20
|
+
function generateWebhookSecret() {
|
|
21
|
+
return crypto_1.default.randomBytes(32).toString('hex');
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Sleep utility for retry delays
|
|
25
|
+
*/
|
|
26
|
+
function sleep(ms) {
|
|
27
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Attempt a single webhook delivery
|
|
31
|
+
*/
|
|
32
|
+
async function attemptWebhookDelivery(webhook, payload, attemptNumber) {
|
|
33
|
+
const payloadString = JSON.stringify(payload);
|
|
34
|
+
const signature = generateWebhookSignature(payloadString, webhook.secret);
|
|
35
|
+
const headers = {
|
|
36
|
+
'Content-Type': 'application/json',
|
|
37
|
+
'X-LinkForty-Signature': `sha256=${signature}`,
|
|
38
|
+
'X-LinkForty-Event': payload.event,
|
|
39
|
+
'X-LinkForty-Event-ID': payload.event_id,
|
|
40
|
+
'User-Agent': 'LinkForty-Webhook/1.0',
|
|
41
|
+
...webhook.headers,
|
|
42
|
+
};
|
|
43
|
+
const controller = new AbortController();
|
|
44
|
+
const timeoutId = setTimeout(() => controller.abort(), webhook.timeout_ms);
|
|
45
|
+
try {
|
|
46
|
+
const response = await fetch(webhook.url, {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers,
|
|
49
|
+
body: payloadString,
|
|
50
|
+
signal: controller.signal,
|
|
51
|
+
});
|
|
52
|
+
clearTimeout(timeoutId);
|
|
53
|
+
const responseBody = await response.text().catch(() => '');
|
|
54
|
+
const result = {
|
|
55
|
+
success: response.ok,
|
|
56
|
+
webhookId: webhook.id,
|
|
57
|
+
eventType: payload.event,
|
|
58
|
+
eventId: payload.event_id,
|
|
59
|
+
responseStatus: response.status,
|
|
60
|
+
responseBody: responseBody.substring(0, 1000), // Limit response body size
|
|
61
|
+
attemptNumber,
|
|
62
|
+
deliveredAt: response.ok ? new Date().toISOString() : undefined,
|
|
63
|
+
};
|
|
64
|
+
if (!response.ok) {
|
|
65
|
+
result.errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
clearTimeout(timeoutId);
|
|
71
|
+
return {
|
|
72
|
+
success: false,
|
|
73
|
+
webhookId: webhook.id,
|
|
74
|
+
eventType: payload.event,
|
|
75
|
+
eventId: payload.event_id,
|
|
76
|
+
errorMessage: error.name === 'AbortError'
|
|
77
|
+
? `Timeout after ${webhook.timeout_ms}ms`
|
|
78
|
+
: error.message || 'Unknown error',
|
|
79
|
+
attemptNumber,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Deliver webhook with retry logic and exponential backoff
|
|
85
|
+
*/
|
|
86
|
+
async function deliverWebhook(webhook, payload, logDelivery) {
|
|
87
|
+
const maxRetries = webhook.retry_count || 3;
|
|
88
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
89
|
+
const result = await attemptWebhookDelivery(webhook, payload, attempt);
|
|
90
|
+
// Log delivery attempt if logging function provided
|
|
91
|
+
if (logDelivery) {
|
|
92
|
+
await logDelivery(result).catch(err => {
|
|
93
|
+
console.error('Failed to log webhook delivery:', err);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
// If successful, return immediately
|
|
97
|
+
if (result.success) {
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
// If not the last attempt, wait before retrying with exponential backoff
|
|
101
|
+
if (attempt < maxRetries) {
|
|
102
|
+
// Exponential backoff: 1s, 2s, 4s, 8s, 16s, 30s (capped at 30s)
|
|
103
|
+
const delayMs = Math.min(1000 * Math.pow(2, attempt - 1), 30000);
|
|
104
|
+
await sleep(delayMs);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Return the last failed result
|
|
108
|
+
return {
|
|
109
|
+
success: false,
|
|
110
|
+
webhookId: webhook.id,
|
|
111
|
+
eventType: payload.event,
|
|
112
|
+
eventId: payload.event_id,
|
|
113
|
+
errorMessage: `Failed after ${maxRetries} attempts`,
|
|
114
|
+
attemptNumber: maxRetries,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Trigger webhooks for a specific event (fire and forget)
|
|
119
|
+
*/
|
|
120
|
+
async function triggerWebhooks(webhooks, event, eventId, data, logDelivery) {
|
|
121
|
+
// Create webhook payload
|
|
122
|
+
const payload = {
|
|
123
|
+
event,
|
|
124
|
+
event_id: eventId,
|
|
125
|
+
timestamp: new Date().toISOString(),
|
|
126
|
+
data,
|
|
127
|
+
};
|
|
128
|
+
// Filter webhooks that should receive this event
|
|
129
|
+
const relevantWebhooks = webhooks.filter(webhook => webhook.is_active && webhook.events.includes(event));
|
|
130
|
+
if (relevantWebhooks.length === 0) {
|
|
131
|
+
return; // No webhooks to trigger
|
|
132
|
+
}
|
|
133
|
+
// Fire and forget - don't await these deliveries
|
|
134
|
+
const deliveryPromises = relevantWebhooks.map(async (webhook) => {
|
|
135
|
+
try {
|
|
136
|
+
const result = await deliverWebhook(webhook, payload, logDelivery ? (result) => logDelivery(webhook.id, result) : undefined);
|
|
137
|
+
if (!result.success) {
|
|
138
|
+
console.error(`Webhook ${webhook.id} delivery failed:`, result.errorMessage);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
console.error(`Webhook ${webhook.id} delivery error:`, error);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
// Fire and forget - log errors but don't block
|
|
146
|
+
Promise.all(deliveryPromises).catch(err => {
|
|
147
|
+
console.error('Webhook delivery batch error:', err);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=webhook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/lib/webhook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/routes/debug.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAkB,MAAM,SAAS,CAAC;AAqB1D;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,eAAe,iBAoVzD"}
|