@windrun-huaiin/backend-core 14.1.0 → 14.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.
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/app/api/user/anonymous/init/route.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA0QxD;;;GAGG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,kCAE9C"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/app/api/user/anonymous/init/route.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA2rBxD;;;GAGG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,kCAE9C"}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var tslib_es6 = require('../../../../../node_modules/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.46.2_tslib@2.8.1_typescript@5.9.3/node_modules/tslib/tslib.es6.js');
4
- var user_aggregate_service = require('../../../../../services/aggregate/user.aggregate.service.js');
4
+ var anonymous_aggregate_service = require('../../../../../services/aggregate/anonymous.aggregate.service.js');
5
5
  var server = require('@windrun-huaiin/third-ui/fingerprint/server');
6
6
  var server$1 = require('@clerk/nextjs/server');
7
7
  var server$2 = require('next/server');
@@ -25,6 +25,9 @@ function createErrorResponse(message, status = 400) {
25
25
  }
26
26
  const SOURCE_REF_MAX_LENGTH = 2048;
27
27
  const QUERY_PARAM_MAX_LENGTH = 512;
28
+ const USER_AGENT_MAX_LENGTH = 1024;
29
+ const FIRST_TOUCH_HEADER_MAX_LENGTH = 4096;
30
+ const FIRST_TOUCH_HEADER_NAME = 'x-first-touch';
28
31
  function normalizeSourceRef(ref) {
29
32
  if (!ref) {
30
33
  return null;
@@ -49,6 +52,28 @@ function normalizeQueryParam(value) {
49
52
  ? trimmed.slice(0, QUERY_PARAM_MAX_LENGTH)
50
53
  : trimmed;
51
54
  }
55
+ function decodeHeaderValue(value) {
56
+ try {
57
+ return decodeURIComponent(value);
58
+ }
59
+ catch (_a) {
60
+ return null;
61
+ }
62
+ }
63
+ function mergeSourceRef(target, source) {
64
+ if (!source) {
65
+ return;
66
+ }
67
+ const entries = Object.entries(source);
68
+ for (const [key, value] of entries) {
69
+ if (value === undefined || value === null) {
70
+ continue;
71
+ }
72
+ if (target[key] === undefined) {
73
+ target[key] = value;
74
+ }
75
+ }
76
+ }
52
77
  function applySearchParams(sourceRef, params) {
53
78
  const setIfEmpty = (key, value) => {
54
79
  if (sourceRef[key] !== undefined) {
@@ -64,26 +89,350 @@ function applySearchParams(sourceRef, params) {
64
89
  setIfEmpty('utmCampaign', params.get('utm_campaign'));
65
90
  setIfEmpty('utmTerm', params.get('utm_term'));
66
91
  setIfEmpty('utmContent', params.get('utm_content'));
92
+ setIfEmpty('utmId', params.get('utm_id'));
67
93
  setIfEmpty('ref', params.get('ref'));
94
+ setIfEmpty('gclid', params.get('gclid'));
95
+ setIfEmpty('fbclid', params.get('fbclid'));
96
+ setIfEmpty('msclkid', params.get('msclkid'));
97
+ setIfEmpty('ttclid', params.get('ttclid'));
98
+ setIfEmpty('twclid', params.get('twclid'));
99
+ setIfEmpty('liFatId', params.get('li_fat_id'));
100
+ }
101
+ function normalizeHost(host) {
102
+ if (!host) {
103
+ return null;
104
+ }
105
+ return host.trim().toLowerCase() || null;
106
+ }
107
+ function getRootDomain(host) {
108
+ const normalizedHost = normalizeHost(host);
109
+ if (!normalizedHost) {
110
+ return null;
111
+ }
112
+ const hostname = normalizedHost.split(':')[0];
113
+ if (hostname === 'localhost' || /^\d{1,3}(\.\d{1,3}){3}$/.test(hostname)) {
114
+ return hostname;
115
+ }
116
+ const parts = hostname.split('.').filter(Boolean);
117
+ if (parts.length <= 2) {
118
+ return hostname;
119
+ }
120
+ return parts.slice(-2).join('.');
121
+ }
122
+ function isInternalReferer(landingHost, refererHost) {
123
+ const normalizedLandingHost = normalizeHost(landingHost);
124
+ const normalizedRefererHost = normalizeHost(refererHost);
125
+ if (!normalizedLandingHost || !normalizedRefererHost) {
126
+ return false;
127
+ }
128
+ if (normalizedLandingHost === normalizedRefererHost) {
129
+ return true;
130
+ }
131
+ return normalizedLandingHost.endsWith(`.${normalizedRefererHost}`)
132
+ || normalizedRefererHost.endsWith(`.${normalizedLandingHost}`);
133
+ }
134
+ function detectPlatform(value) {
135
+ const normalized = value === null || value === void 0 ? void 0 : value.trim().toLowerCase();
136
+ if (!normalized) {
137
+ return null;
138
+ }
139
+ const matcherList = [
140
+ { pattern: /chatgpt|chat-openai|openai/, platform: 'openai', channel: 'ai' },
141
+ { pattern: /claude|anthropic/, platform: 'anthropic', channel: 'ai' },
142
+ { pattern: /perplexity/, platform: 'perplexity', channel: 'ai' },
143
+ { pattern: /gemini/, platform: 'gemini', channel: 'ai' },
144
+ { pattern: /copilot/, platform: 'copilot', channel: 'ai' },
145
+ { pattern: /google/, platform: 'google', channel: 'search' },
146
+ { pattern: /bing/, platform: 'bing', channel: 'search' },
147
+ { pattern: /baidu/, platform: 'baidu', channel: 'search' },
148
+ { pattern: /yahoo/, platform: 'yahoo', channel: 'search' },
149
+ { pattern: /duckduckgo/, platform: 'duckduckgo', channel: 'search' },
150
+ { pattern: /facebook/, platform: 'facebook', channel: 'social' },
151
+ { pattern: /instagram/, platform: 'instagram', channel: 'social' },
152
+ { pattern: /x\.com|twitter/, platform: 'x', channel: 'social' },
153
+ { pattern: /linkedin/, platform: 'linkedin', channel: 'social' },
154
+ { pattern: /reddit/, platform: 'reddit', channel: 'social' },
155
+ { pattern: /youtube/, platform: 'youtube', channel: 'social' },
156
+ ];
157
+ const matched = matcherList.find(({ pattern }) => pattern.test(normalized));
158
+ if (!matched) {
159
+ return null;
160
+ }
161
+ return matched.platform;
162
+ }
163
+ function detectChannelFromPlatform(platform) {
164
+ switch (platform) {
165
+ case 'openai':
166
+ case 'anthropic':
167
+ case 'perplexity':
168
+ case 'gemini':
169
+ case 'copilot':
170
+ return 'ai';
171
+ case 'google':
172
+ case 'bing':
173
+ case 'baidu':
174
+ case 'yahoo':
175
+ case 'duckduckgo':
176
+ return 'search';
177
+ case 'facebook':
178
+ case 'instagram':
179
+ case 'x':
180
+ case 'linkedin':
181
+ case 'reddit':
182
+ case 'youtube':
183
+ return 'social';
184
+ default:
185
+ return null;
186
+ }
187
+ }
188
+ function detectChannelFromUtmMedium(value) {
189
+ const normalized = value === null || value === void 0 ? void 0 : value.trim().toLowerCase();
190
+ if (!normalized) {
191
+ return null;
192
+ }
193
+ if (/^(cpc|ppc|paid|paid_search|display|banner|affiliate|email|newsletter|push|sms)$/.test(normalized)) {
194
+ return 'campaign';
195
+ }
196
+ if (/^(social|social_paid|social-organic|social_organic)$/.test(normalized)) {
197
+ return 'social';
198
+ }
199
+ if (/^(organic|seo|search)$/.test(normalized)) {
200
+ return 'search';
201
+ }
202
+ if (/^(referral|partner)$/.test(normalized)) {
203
+ return 'referral';
204
+ }
205
+ if (/^(ai|llm)$/.test(normalized)) {
206
+ return 'ai';
207
+ }
208
+ return 'campaign';
209
+ }
210
+ function parseUserAgent(request) {
211
+ var _a, _b, _c, _d, _e;
212
+ const userAgentHeader = request.headers.get('user-agent');
213
+ const secChUaMobile = (_a = normalizeQueryParam(request.headers.get('sec-ch-ua-mobile'))) !== null && _a !== void 0 ? _a : undefined;
214
+ const secChUaPlatform = (_b = normalizeQueryParam(request.headers.get('sec-ch-ua-platform'))) !== null && _b !== void 0 ? _b : undefined;
215
+ const userAgent = (_d = (_c = normalizeSourceRef(userAgentHeader)) === null || _c === void 0 ? void 0 : _c.slice(0, USER_AGENT_MAX_LENGTH)) !== null && _d !== void 0 ? _d : undefined;
216
+ const ua = (_e = userAgent === null || userAgent === void 0 ? void 0 : userAgent.toLowerCase()) !== null && _e !== void 0 ? _e : '';
217
+ let deviceType = 'desktop';
218
+ if (!ua) {
219
+ deviceType = 'unknown';
220
+ }
221
+ else if (/bot|spider|crawler|curl|wget|headless/.test(ua)) {
222
+ deviceType = 'bot';
223
+ }
224
+ else if (/ipad|tablet/.test(ua)) {
225
+ deviceType = 'tablet';
226
+ }
227
+ else if (/mobi|iphone|android/.test(ua) || secChUaMobile === '?1') {
228
+ deviceType = 'mobile';
229
+ }
230
+ let os = 'Unknown';
231
+ if (/iphone|ipad|ipod/.test(ua)) {
232
+ os = 'iOS';
233
+ }
234
+ else if (/android/.test(ua)) {
235
+ os = 'Android';
236
+ }
237
+ else if (/windows nt/.test(ua)) {
238
+ os = 'Windows';
239
+ }
240
+ else if (/mac os x|macintosh/.test(ua)) {
241
+ os = 'macOS';
242
+ }
243
+ else if (/cros/.test(ua)) {
244
+ os = 'Chrome OS';
245
+ }
246
+ else if (/linux/.test(ua)) {
247
+ os = 'Linux';
248
+ }
249
+ if (secChUaPlatform) {
250
+ const normalizedPlatform = secChUaPlatform.replaceAll('"', '');
251
+ if (normalizedPlatform && normalizedPlatform !== 'Unknown') {
252
+ os = normalizedPlatform;
253
+ }
254
+ }
255
+ let browser = 'Unknown';
256
+ if (/edg\//.test(ua)) {
257
+ browser = 'Edge';
258
+ }
259
+ else if (/opr\//.test(ua) || /opera/.test(ua)) {
260
+ browser = 'Opera';
261
+ }
262
+ else if (/samsungbrowser\//.test(ua)) {
263
+ browser = 'Samsung Internet';
264
+ }
265
+ else if (/crios\//.test(ua) || /chrome\//.test(ua)) {
266
+ browser = 'Chrome';
267
+ }
268
+ else if (/firefox\//.test(ua)) {
269
+ browser = 'Firefox';
270
+ }
271
+ else if (/safari\//.test(ua) && !/chrome\//.test(ua) && !/crios\//.test(ua)) {
272
+ browser = 'Safari';
273
+ }
274
+ return {
275
+ userAgent,
276
+ deviceType,
277
+ os,
278
+ browser,
279
+ secChUaMobile,
280
+ secChUaPlatform,
281
+ };
282
+ }
283
+ function parseFirstTouchHeader(request) {
284
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
285
+ const rawHeader = request.headers.get(FIRST_TOUCH_HEADER_NAME);
286
+ const normalizedHeader = (_a = normalizeSourceRef(rawHeader)) === null || _a === void 0 ? void 0 : _a.slice(0, FIRST_TOUCH_HEADER_MAX_LENGTH);
287
+ if (!normalizedHeader) {
288
+ return null;
289
+ }
290
+ const decodedHeader = decodeHeaderValue(normalizedHeader);
291
+ if (!decodedHeader) {
292
+ return null;
293
+ }
294
+ try {
295
+ const parsed = JSON.parse(decodedHeader);
296
+ const sourceRef = {};
297
+ sourceRef.capturedAt = (_b = normalizeQueryParam(typeof parsed.capturedAt === 'string' ? parsed.capturedAt : null)) !== null && _b !== void 0 ? _b : undefined;
298
+ sourceRef.landingUrl = (_c = normalizeSourceRef(typeof parsed.landingUrl === 'string' ? parsed.landingUrl : null)) !== null && _c !== void 0 ? _c : undefined;
299
+ sourceRef.landingPath = (_d = normalizeSourceRef(typeof parsed.landingPath === 'string' ? parsed.landingPath : null)) !== null && _d !== void 0 ? _d : undefined;
300
+ sourceRef.landingHost = (_e = normalizeHost(typeof parsed.landingHost === 'string' ? parsed.landingHost : null)) !== null && _e !== void 0 ? _e : undefined;
301
+ sourceRef.ref = (_f = normalizeQueryParam(typeof parsed.ref === 'string' ? parsed.ref : null)) !== null && _f !== void 0 ? _f : undefined;
302
+ sourceRef.utmSource = (_g = normalizeQueryParam(typeof parsed.utmSource === 'string' ? parsed.utmSource : null)) !== null && _g !== void 0 ? _g : undefined;
303
+ sourceRef.utmMedium = (_h = normalizeQueryParam(typeof parsed.utmMedium === 'string' ? parsed.utmMedium : null)) !== null && _h !== void 0 ? _h : undefined;
304
+ sourceRef.utmCampaign = (_j = normalizeQueryParam(typeof parsed.utmCampaign === 'string' ? parsed.utmCampaign : null)) !== null && _j !== void 0 ? _j : undefined;
305
+ sourceRef.utmTerm = (_k = normalizeQueryParam(typeof parsed.utmTerm === 'string' ? parsed.utmTerm : null)) !== null && _k !== void 0 ? _k : undefined;
306
+ sourceRef.utmContent = (_l = normalizeQueryParam(typeof parsed.utmContent === 'string' ? parsed.utmContent : null)) !== null && _l !== void 0 ? _l : undefined;
307
+ sourceRef.utmId = (_m = normalizeQueryParam(typeof parsed.utmId === 'string' ? parsed.utmId : null)) !== null && _m !== void 0 ? _m : undefined;
308
+ sourceRef.gclid = (_o = normalizeQueryParam(typeof parsed.gclid === 'string' ? parsed.gclid : null)) !== null && _o !== void 0 ? _o : undefined;
309
+ sourceRef.fbclid = (_p = normalizeQueryParam(typeof parsed.fbclid === 'string' ? parsed.fbclid : null)) !== null && _p !== void 0 ? _p : undefined;
310
+ sourceRef.msclkid = (_q = normalizeQueryParam(typeof parsed.msclkid === 'string' ? parsed.msclkid : null)) !== null && _q !== void 0 ? _q : undefined;
311
+ sourceRef.ttclid = (_r = normalizeQueryParam(typeof parsed.ttclid === 'string' ? parsed.ttclid : null)) !== null && _r !== void 0 ? _r : undefined;
312
+ sourceRef.twclid = (_s = normalizeQueryParam(typeof parsed.twclid === 'string' ? parsed.twclid : null)) !== null && _s !== void 0 ? _s : undefined;
313
+ sourceRef.liFatId = (_t = normalizeQueryParam(typeof parsed.liFatId === 'string' ? parsed.liFatId : null)) !== null && _t !== void 0 ? _t : undefined;
314
+ const externalReferrer = normalizeSourceRef(typeof parsed.externalReferrer === 'string' ? parsed.externalReferrer : null);
315
+ if (externalReferrer) {
316
+ sourceRef.httpRefer = externalReferrer;
317
+ try {
318
+ const refererUrl = new URL(externalReferrer);
319
+ sourceRef.refererHost = (_u = normalizeHost(refererUrl.host)) !== null && _u !== void 0 ? _u : undefined;
320
+ sourceRef.refererPath = (_v = normalizeSourceRef(refererUrl.pathname)) !== null && _v !== void 0 ? _v : undefined;
321
+ sourceRef.refererDomain = (_w = getRootDomain(refererUrl.host)) !== null && _w !== void 0 ? _w : undefined;
322
+ applySearchParams(sourceRef, refererUrl.searchParams);
323
+ }
324
+ catch (error) {
325
+ console.warn('Failed to parse first-touch referrer url:', error);
326
+ }
327
+ }
328
+ return Object.keys(sourceRef).length > 0 ? sourceRef : null;
329
+ }
330
+ catch (error) {
331
+ console.warn('Failed to parse first-touch header:', error);
332
+ return null;
333
+ }
334
+ }
335
+ function finalizeAttribution(sourceRef) {
336
+ var _a, _b, _c, _d, _e;
337
+ const landingHost = normalizeHost(sourceRef.landingHost);
338
+ const refererHost = normalizeHost(sourceRef.refererHost);
339
+ const internal = isInternalReferer(landingHost, refererHost);
340
+ const hasCampaignMarker = Boolean(sourceRef.utmSource
341
+ || sourceRef.utmMedium
342
+ || sourceRef.utmCampaign
343
+ || sourceRef.utmTerm
344
+ || sourceRef.utmContent
345
+ || sourceRef.utmId
346
+ || sourceRef.ref
347
+ || sourceRef.gclid
348
+ || sourceRef.fbclid
349
+ || sourceRef.msclkid
350
+ || sourceRef.ttclid
351
+ || sourceRef.twclid
352
+ || sourceRef.liFatId);
353
+ if (internal) {
354
+ sourceRef.isInternalReferer = true;
355
+ }
356
+ const utmPlatform = detectPlatform(sourceRef.utmSource) || detectPlatform(sourceRef.ref);
357
+ if (utmPlatform) {
358
+ sourceRef.sourcePlatform = utmPlatform;
359
+ sourceRef.sourceChannel = (_c = (_b = (_a = detectChannelFromPlatform(utmPlatform)) !== null && _a !== void 0 ? _a : detectChannelFromUtmMedium(sourceRef.utmMedium)) !== null && _b !== void 0 ? _b : sourceRef.sourceChannel) !== null && _c !== void 0 ? _c : 'campaign';
360
+ sourceRef.sourceType = 'campaign';
361
+ return;
362
+ }
363
+ if (sourceRef.gclid) {
364
+ sourceRef.sourcePlatform = 'google';
365
+ sourceRef.sourceChannel = 'search';
366
+ sourceRef.sourceType = 'campaign';
367
+ return;
368
+ }
369
+ if (sourceRef.msclkid) {
370
+ sourceRef.sourcePlatform = 'bing';
371
+ sourceRef.sourceChannel = 'search';
372
+ sourceRef.sourceType = 'campaign';
373
+ return;
374
+ }
375
+ if (sourceRef.fbclid) {
376
+ sourceRef.sourcePlatform = 'facebook';
377
+ sourceRef.sourceChannel = 'social';
378
+ sourceRef.sourceType = 'campaign';
379
+ return;
380
+ }
381
+ if (sourceRef.ttclid) {
382
+ sourceRef.sourcePlatform = 'tiktok';
383
+ sourceRef.sourceChannel = 'social';
384
+ sourceRef.sourceType = 'campaign';
385
+ return;
386
+ }
387
+ if (sourceRef.twclid) {
388
+ sourceRef.sourcePlatform = 'x';
389
+ sourceRef.sourceChannel = 'social';
390
+ sourceRef.sourceType = 'campaign';
391
+ return;
392
+ }
393
+ if (sourceRef.liFatId) {
394
+ sourceRef.sourcePlatform = 'linkedin';
395
+ sourceRef.sourceChannel = 'social';
396
+ sourceRef.sourceType = 'campaign';
397
+ return;
398
+ }
399
+ if (hasCampaignMarker) {
400
+ sourceRef.sourcePlatform = 'other';
401
+ sourceRef.sourceChannel = (_d = detectChannelFromUtmMedium(sourceRef.utmMedium)) !== null && _d !== void 0 ? _d : 'campaign';
402
+ sourceRef.sourceType = 'campaign';
403
+ return;
404
+ }
405
+ if (!internal && refererHost) {
406
+ const refererPlatform = detectPlatform(refererHost) || detectPlatform(sourceRef.httpRefer);
407
+ sourceRef.sourcePlatform = refererPlatform !== null && refererPlatform !== void 0 ? refererPlatform : 'other';
408
+ sourceRef.sourceChannel = (_e = detectChannelFromPlatform(refererPlatform)) !== null && _e !== void 0 ? _e : 'referral';
409
+ sourceRef.sourceType = 'referer';
410
+ return;
411
+ }
412
+ sourceRef.sourcePlatform = 'direct';
413
+ sourceRef.sourceChannel = 'direct';
414
+ sourceRef.sourceType = 'direct';
68
415
  }
69
416
  // 提取用户首次访问来源
70
417
  function extractSourceRef(request) {
418
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
71
419
  const headerRef = request.headers.get('referer') || request.headers.get('referrer');
72
420
  const customRef = request.headers.get('x-source-ref');
73
421
  const queryRef = request.nextUrl.searchParams.get('ref');
74
- console.log({
75
- headerRef,
76
- customRef,
77
- queryRef
78
- });
79
- const sourceRef = {};
422
+ const firstTouchRef = parseFirstTouchHeader(request);
423
+ const sourceRef = Object.assign({}, parseUserAgent(request));
424
+ mergeSourceRef(sourceRef, firstTouchRef);
425
+ sourceRef.landingUrl = (_b = (_a = sourceRef.landingUrl) !== null && _a !== void 0 ? _a : normalizeSourceRef(request.nextUrl.toString())) !== null && _b !== void 0 ? _b : undefined;
426
+ sourceRef.landingPath = (_d = (_c = sourceRef.landingPath) !== null && _c !== void 0 ? _c : normalizeSourceRef(request.nextUrl.pathname)) !== null && _d !== void 0 ? _d : undefined;
427
+ sourceRef.landingHost = (_f = (_e = sourceRef.landingHost) !== null && _e !== void 0 ? _e : normalizeHost(request.nextUrl.host)) !== null && _f !== void 0 ? _f : undefined;
428
+ sourceRef.ref = (_h = (_g = sourceRef.ref) !== null && _g !== void 0 ? _g : normalizeQueryParam(queryRef)) !== null && _h !== void 0 ? _h : undefined;
80
429
  let normalizedHttpRef = null;
81
- const candidates = [headerRef, customRef, queryRef];
430
+ const candidates = [customRef, headerRef];
82
431
  for (const candidate of candidates) {
83
432
  const normalized = normalizeSourceRef(candidate);
84
433
  if (normalized) {
85
434
  normalizedHttpRef = normalized;
86
- sourceRef.httpRefer = normalized;
435
+ sourceRef.httpRefer = (_j = sourceRef.httpRefer) !== null && _j !== void 0 ? _j : normalized;
87
436
  break;
88
437
  }
89
438
  }
@@ -92,12 +441,16 @@ function extractSourceRef(request) {
92
441
  if (normalizedHttpRef) {
93
442
  try {
94
443
  const refererUrl = new URL(normalizedHttpRef);
444
+ sourceRef.refererHost = (_l = (_k = sourceRef.refererHost) !== null && _k !== void 0 ? _k : normalizeHost(refererUrl.host)) !== null && _l !== void 0 ? _l : undefined;
445
+ sourceRef.refererPath = (_o = (_m = sourceRef.refererPath) !== null && _m !== void 0 ? _m : normalizeSourceRef(refererUrl.pathname)) !== null && _o !== void 0 ? _o : undefined;
446
+ sourceRef.refererDomain = (_q = (_p = sourceRef.refererDomain) !== null && _p !== void 0 ? _p : getRootDomain(refererUrl.host)) !== null && _q !== void 0 ? _q : undefined;
95
447
  applySearchParams(sourceRef, refererUrl.searchParams);
96
448
  }
97
449
  catch (error) {
98
450
  console.warn('Failed to parse referer url for utm/ref:', error);
99
451
  }
100
452
  }
453
+ finalizeAttribution(sourceRef);
101
454
  return Object.keys(sourceRef).length > 0 ? sourceRef : null;
102
455
  }
103
456
  /**
@@ -174,17 +527,22 @@ function handleFingerprintRequest(request_1) {
174
527
  return createErrorResponse('User not found', 404);
175
528
  }
176
529
  const sourceRef = extractSourceRef(request);
177
- // 创建新的匿名用户
178
- const { newUser, credit } = yield user_aggregate_service.userAggregateService.initAnonymousUser(fingerprintId, { sourceRef: sourceRef !== null && sourceRef !== void 0 ? sourceRef : undefined });
179
- console.log(`Created new anonymous user ${newUser.userId} with fingerprint ${fingerprintId}`);
530
+ const anonymousInitResult = yield anonymous_aggregate_service.anonymousAggregateService.getOrCreateByFingerprintId(fingerprintId, { sourceRef: sourceRef !== null && sourceRef !== void 0 ? sourceRef : undefined });
531
+ if (anonymousInitResult.isNewUser) {
532
+ console.log(`Created new anonymous user ${anonymousInitResult.user.userId} with fingerprint ${fingerprintId}`);
533
+ }
180
534
  // 返回创建结果
181
535
  const response = createSuccessResponse({
182
536
  entities: {
183
- user: newUser,
184
- credit,
185
- subscription: null,
537
+ user: anonymousInitResult.user,
538
+ credit: anonymousInitResult.credit,
539
+ subscription: anonymousInitResult.subscription,
540
+ },
541
+ isNewUser: anonymousInitResult.isNewUser,
542
+ options: {
543
+ totalUsersOnDevice: anonymousInitResult.totalUsersOnDevice,
544
+ hasAnonymousUser: anonymousInitResult.hasAnonymousUser,
186
545
  },
187
- isNewUser: true,
188
546
  });
189
547
  return server$2.NextResponse.json(response);
190
548
  }