@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.
- package/dist/app/api/user/anonymous/init/route.d.ts.map +1 -1
- package/dist/app/api/user/anonymous/init/route.js +374 -16
- package/dist/app/api/user/anonymous/init/route.mjs +374 -16
- package/dist/index.js +2 -0
- package/dist/index.mjs +1 -0
- package/dist/services/aggregate/anonymous.aggregate.service.d.ts +21 -0
- package/dist/services/aggregate/anonymous.aggregate.service.d.ts.map +1 -0
- package/dist/services/aggregate/anonymous.aggregate.service.js +87 -0
- package/dist/services/aggregate/anonymous.aggregate.service.mjs +85 -0
- package/dist/services/aggregate/index.d.ts +1 -0
- package/dist/services/aggregate/index.d.ts.map +1 -1
- package/dist/services/aggregate/index.js +2 -0
- package/dist/services/aggregate/index.mjs +1 -0
- package/package.json +2 -2
- package/src/app/api/user/anonymous/init/route.ts +451 -18
- package/src/services/aggregate/anonymous.aggregate.service.ts +113 -0
- package/src/services/aggregate/index.ts +1 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { creditService, subscriptionService, userService } from '@/db';
|
|
2
|
+
import { UserStatus } from '@/db/constants';
|
|
3
|
+
import type { Credit, Subscription, User } from '@/db/prisma-model-type';
|
|
4
|
+
import { freeAmount } from '@/lib/credit-init';
|
|
5
|
+
import { runInTransaction } from '@/prisma/prisma-transaction-util';
|
|
6
|
+
import { CreditType, OperationType } from '@/db/constants';
|
|
7
|
+
import { Prisma } from '@/db/prisma-model-type';
|
|
8
|
+
|
|
9
|
+
const ANONYMOUS_INIT_LOCK_NAMESPACE = 92831;
|
|
10
|
+
|
|
11
|
+
type AnonymousInitContext = {
|
|
12
|
+
user: User;
|
|
13
|
+
credit: Credit | null;
|
|
14
|
+
subscription: Subscription | null;
|
|
15
|
+
isNewUser: boolean;
|
|
16
|
+
totalUsersOnDevice: number;
|
|
17
|
+
hasAnonymousUser: boolean;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
class AnonymousAggregateService {
|
|
21
|
+
private async lockFingerprintInit(
|
|
22
|
+
tx: Prisma.TransactionClient,
|
|
23
|
+
fingerprintId: string,
|
|
24
|
+
): Promise<void> {
|
|
25
|
+
await tx.$executeRaw`
|
|
26
|
+
SELECT pg_advisory_xact_lock(
|
|
27
|
+
${Prisma.raw(String(ANONYMOUS_INIT_LOCK_NAMESPACE))},
|
|
28
|
+
hashtext(${fingerprintId})
|
|
29
|
+
)
|
|
30
|
+
`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private async findLatestUserContextByFingerprintId(
|
|
34
|
+
fingerprintId: string,
|
|
35
|
+
tx: Prisma.TransactionClient,
|
|
36
|
+
): Promise<AnonymousInitContext | null> {
|
|
37
|
+
const existingUsers = await userService.findListByFingerprintId(fingerprintId, tx);
|
|
38
|
+
if (existingUsers.length === 0) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const latestUser = existingUsers[0];
|
|
43
|
+
const [credit, subscription] = await Promise.all([
|
|
44
|
+
creditService.getCredit(latestUser.userId, tx),
|
|
45
|
+
subscriptionService.getActiveSubscription(latestUser.userId, tx),
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
user: latestUser,
|
|
50
|
+
credit,
|
|
51
|
+
subscription,
|
|
52
|
+
isNewUser: false,
|
|
53
|
+
totalUsersOnDevice: existingUsers.length,
|
|
54
|
+
hasAnonymousUser: true,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private async createAnonymousUser(
|
|
59
|
+
fingerprintId: string,
|
|
60
|
+
tx: Prisma.TransactionClient,
|
|
61
|
+
options?: { sourceRef?: Prisma.InputJsonValue; },
|
|
62
|
+
): Promise<AnonymousInitContext> {
|
|
63
|
+
const newUser = await userService.createUser(
|
|
64
|
+
{
|
|
65
|
+
fingerprintId,
|
|
66
|
+
sourceRef: options?.sourceRef,
|
|
67
|
+
status: UserStatus.ANONYMOUS,
|
|
68
|
+
},
|
|
69
|
+
tx,
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const credit = await creditService.initializeCreditWithFree(
|
|
73
|
+
{
|
|
74
|
+
userId: newUser.userId,
|
|
75
|
+
feature: 'anonymous_user_init',
|
|
76
|
+
creditType: CreditType.FREE,
|
|
77
|
+
operationType: OperationType.SYS_GIFT,
|
|
78
|
+
operationReferId: newUser.userId,
|
|
79
|
+
creditsChange: freeAmount,
|
|
80
|
+
},
|
|
81
|
+
tx,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
await subscriptionService.initializeSubscription(newUser.userId, tx);
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
user: newUser,
|
|
88
|
+
credit,
|
|
89
|
+
subscription: null,
|
|
90
|
+
isNewUser: true,
|
|
91
|
+
totalUsersOnDevice: 1,
|
|
92
|
+
hasAnonymousUser: true,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async getOrCreateByFingerprintId(
|
|
97
|
+
fingerprintId: string,
|
|
98
|
+
options?: { sourceRef?: Prisma.InputJsonValue; },
|
|
99
|
+
): Promise<AnonymousInitContext> {
|
|
100
|
+
return runInTransaction(async (tx) => {
|
|
101
|
+
await this.lockFingerprintInit(tx, fingerprintId);
|
|
102
|
+
|
|
103
|
+
const existingContext = await this.findLatestUserContextByFingerprintId(fingerprintId, tx);
|
|
104
|
+
if (existingContext) {
|
|
105
|
+
return existingContext;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return this.createAnonymousUser(fingerprintId, tx, options);
|
|
109
|
+
}, 'anonymous_get_or_create_by_fingerprint_id');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export const anonymousAggregateService = new AnonymousAggregateService();
|