@windrun-huaiin/backend-core 30.0.0 → 31.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -0
- package/dist/app/api/user/anonymous/init/fingerprint-only-route.d.ts +8 -0
- package/dist/app/api/user/anonymous/init/fingerprint-only-route.d.ts.map +1 -0
- package/dist/app/api/user/anonymous/init/fingerprint-only-route.js +20 -0
- package/dist/app/api/user/anonymous/init/fingerprint-only-route.mjs +18 -0
- package/dist/app/api/user/anonymous/init/route-shared.d.ts +10 -0
- package/dist/app/api/user/anonymous/init/route-shared.d.ts.map +1 -0
- package/dist/app/api/user/anonymous/init/route-shared.js +557 -0
- package/dist/app/api/user/anonymous/init/route-shared.mjs +555 -0
- package/dist/app/api/user/anonymous/init/route.d.ts +3 -3
- package/dist/app/api/user/anonymous/init/route.d.ts.map +1 -1
- package/dist/app/api/user/anonymous/init/route.js +6 -554
- package/dist/app/api/user/anonymous/init/route.mjs +7 -555
- package/dist/app/api/webhook/clerk/user/route.js +16 -16
- package/dist/app/api/webhook/clerk/user/route.mjs +16 -16
- package/dist/auth/auth-utils.d.ts +8 -23
- package/dist/auth/auth-utils.d.ts.map +1 -1
- package/dist/auth/auth-utils.js +8 -20
- package/dist/auth/auth-utils.mjs +8 -20
- package/dist/lib/money-price-config.d.ts +28 -28
- package/dist/lib/money-price-config.js +31 -31
- package/dist/lib/money-price-config.mjs +31 -31
- package/dist/lib/stripe-config.js +3 -3
- package/dist/lib/stripe-config.mjs +3 -3
- package/dist/prisma/prisma-transaction-util.js +1 -1
- package/dist/prisma/prisma-transaction-util.mjs +1 -1
- package/dist/prisma/prisma.d.ts.map +1 -1
- package/dist/prisma/prisma.js +18 -19
- package/dist/prisma/prisma.mjs +18 -19
- package/dist/services/aggregate/billing.aggregate.service.js +6 -6
- package/dist/services/aggregate/billing.aggregate.service.mjs +6 -6
- package/dist/services/aggregate/user.aggregate.service.d.ts +9 -9
- package/dist/services/aggregate/user.aggregate.service.js +16 -16
- package/dist/services/aggregate/user.aggregate.service.mjs +16 -16
- package/dist/services/database/constants.js +34 -34
- package/dist/services/database/constants.mjs +34 -34
- package/dist/services/database/credit.service.js +2 -2
- package/dist/services/database/credit.service.mjs +2 -2
- package/dist/services/database/transaction.service.js +1 -1
- package/dist/services/database/transaction.service.mjs +1 -1
- package/dist/services/database/user.service.js +2 -2
- package/dist/services/database/user.service.mjs +2 -2
- package/dist/services/stripe/webhook-handler.js +5 -5
- package/dist/services/stripe/webhook-handler.mjs +5 -5
- package/package.json +18 -6
- package/src/app/api/user/anonymous/init/fingerprint-only-route.ts +14 -0
- package/src/app/api/user/anonymous/init/route-shared.ts +710 -0
- package/src/app/api/user/anonymous/init/route.ts +7 -712
- package/src/app/api/webhook/clerk/user/route.ts +17 -17
- package/src/auth/auth-utils.ts +8 -23
- package/src/lib/money-price-config.ts +31 -32
- package/src/lib/stripe-config.ts +3 -3
- package/src/prisma/prisma-transaction-util.ts +1 -1
- package/src/prisma/prisma.ts +18 -19
- package/src/services/aggregate/billing.aggregate.service.ts +7 -7
- package/src/services/aggregate/user.aggregate.service.ts +16 -16
- package/src/services/database/constants.ts +34 -34
- package/src/services/database/credit.service.ts +2 -2
- package/src/services/database/transaction.service.ts +1 -1
- package/src/services/database/user.service.ts +2 -2
- package/src/services/stripe/webhook-handler.ts +5 -5
|
@@ -60,7 +60,7 @@ const createCheckoutSession = (params, subscriptionData) => tslib.__awaiter(void
|
|
|
60
60
|
}
|
|
61
61
|
// One-time payment specific configuration
|
|
62
62
|
if (isSubscriptionMode) {
|
|
63
|
-
//
|
|
63
|
+
// Attach order metadata for later event matching. Stripe only allows this in subscription mode.
|
|
64
64
|
sessionParams.subscription_data = subscriptionData;
|
|
65
65
|
}
|
|
66
66
|
else {
|
|
@@ -89,7 +89,7 @@ const createCheckoutSession = (params, subscriptionData) => tslib.__awaiter(void
|
|
|
89
89
|
throw error;
|
|
90
90
|
}
|
|
91
91
|
});
|
|
92
|
-
//
|
|
92
|
+
// Resolve the payment ID from an invoice ID.
|
|
93
93
|
const fetchPaymentId = (invoiceId) => tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
94
94
|
var _a, _b;
|
|
95
95
|
const fullInvoice = yield getStripe().invoices.retrieve(invoiceId, {
|
|
@@ -147,7 +147,7 @@ const createOrGetCustomer = (params) => tslib.__awaiter(void 0, void 0, void 0,
|
|
|
147
147
|
return stripeCustomer.id;
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
|
-
//
|
|
150
|
+
// Create a new customer.
|
|
151
151
|
const customerParams = {
|
|
152
152
|
metadata: {
|
|
153
153
|
user_id: userId,
|
|
@@ -58,7 +58,7 @@ const createCheckoutSession = (params, subscriptionData) => __awaiter(void 0, vo
|
|
|
58
58
|
}
|
|
59
59
|
// One-time payment specific configuration
|
|
60
60
|
if (isSubscriptionMode) {
|
|
61
|
-
//
|
|
61
|
+
// Attach order metadata for later event matching. Stripe only allows this in subscription mode.
|
|
62
62
|
sessionParams.subscription_data = subscriptionData;
|
|
63
63
|
}
|
|
64
64
|
else {
|
|
@@ -87,7 +87,7 @@ const createCheckoutSession = (params, subscriptionData) => __awaiter(void 0, vo
|
|
|
87
87
|
throw error;
|
|
88
88
|
}
|
|
89
89
|
});
|
|
90
|
-
//
|
|
90
|
+
// Resolve the payment ID from an invoice ID.
|
|
91
91
|
const fetchPaymentId = (invoiceId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
92
92
|
var _a, _b;
|
|
93
93
|
const fullInvoice = yield getStripe().invoices.retrieve(invoiceId, {
|
|
@@ -145,7 +145,7 @@ const createOrGetCustomer = (params) => __awaiter(void 0, void 0, void 0, functi
|
|
|
145
145
|
return stripeCustomer.id;
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
|
-
//
|
|
148
|
+
// Create a new customer.
|
|
149
149
|
const customerParams = {
|
|
150
150
|
metadata: {
|
|
151
151
|
user_id: userId,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var tslib = require('tslib');
|
|
4
4
|
var prisma = require('./prisma.js');
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// Transaction helper that logs rollback details on failure.
|
|
7
7
|
function runInTransaction(fn, operationName) {
|
|
8
8
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
9
9
|
const start = Date.now();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __awaiter } from 'tslib';
|
|
2
2
|
import { getBackendCorePrisma } from './prisma.mjs';
|
|
3
3
|
|
|
4
|
-
//
|
|
4
|
+
// Transaction helper that logs rollback details on failure.
|
|
5
5
|
function runInTransaction(fn, operationName) {
|
|
6
6
|
return __awaiter(this, void 0, void 0, function* () {
|
|
7
7
|
const start = Date.now();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma.d.ts","sourceRoot":"","sources":["../../src/prisma/prisma.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAEzD,MAAM,MAAM,uBAAuB,GAAG,2BAA2B,CAAC;AAClE,MAAM,MAAM,2BAA2B,GAAG;IAKxC,YAAY,EAAE,GAAG,CAAC;IAElB,GAAG,CAAC,EAAE,GAAG,CAAC;IAEV,WAAW,EAAE,GAAG,CAAC;IAEjB,iBAAiB,CAAC,EAAE,GAAG,CAAC;IAExB,SAAS,EAAE,GAAG,CAAC;IAEf,eAAe,CAAC,EAAE,GAAG,CAAC;IAEtB,IAAI,EAAE,GAAG,CAAC;IAEV,YAAY,EAAE,GAAG,CAAC;IAElB,MAAM,EAAE,GAAG,CAAC;IAEZ,WAAW,EAAE,GAAG,CAAC;IAEjB,cAAc,EAAE,GAAG,CAAC;IAEpB,UAAU,EAAE,GAAG,CAAC;IAEhB,MAAM,EAAE,GAAG,CAAC;CACb,CAAC;AA2CF,wBAAgB,kBAAkB,IAAI,KAAK,CAI1C;AAED,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,2BAA2B,EACzC,UAAU,SAAmE,GAC5E,2BAA2B,CAK7B;AAED,wBAAgB,oBAAoB,IAAI,uBAAuB,CAQ9D;AAID,eAAO,MAAM,MAAM,6BAIjB,CAAC;
|
|
1
|
+
{"version":3,"file":"prisma.d.ts","sourceRoot":"","sources":["../../src/prisma/prisma.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAEzD,MAAM,MAAM,uBAAuB,GAAG,2BAA2B,CAAC;AAClE,MAAM,MAAM,2BAA2B,GAAG;IAKxC,YAAY,EAAE,GAAG,CAAC;IAElB,GAAG,CAAC,EAAE,GAAG,CAAC;IAEV,WAAW,EAAE,GAAG,CAAC;IAEjB,iBAAiB,CAAC,EAAE,GAAG,CAAC;IAExB,SAAS,EAAE,GAAG,CAAC;IAEf,eAAe,CAAC,EAAE,GAAG,CAAC;IAEtB,IAAI,EAAE,GAAG,CAAC;IAEV,YAAY,EAAE,GAAG,CAAC;IAElB,MAAM,EAAE,GAAG,CAAC;IAEZ,WAAW,EAAE,GAAG,CAAC;IAEjB,cAAc,EAAE,GAAG,CAAC;IAEpB,UAAU,EAAE,GAAG,CAAC;IAEhB,MAAM,EAAE,GAAG,CAAC;CACb,CAAC;AA2CF,wBAAgB,kBAAkB,IAAI,KAAK,CAI1C;AAED,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,2BAA2B,EACzC,UAAU,SAAmE,GAC5E,2BAA2B,CAK7B;AAED,wBAAgB,oBAAoB,IAAI,uBAAuB,CAQ9D;AAID,eAAO,MAAM,MAAM,6BAIjB,CAAC;AAsFH,wBAAgB,+BAA+B,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,GAAG,uBAAuB,CAEjI"}
|
package/dist/prisma/prisma.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const globalForPrisma = globalThis;
|
|
4
|
-
// ====================
|
|
4
|
+
// ==================== Logging Configuration ====================
|
|
5
5
|
const getLogConfig = () => {
|
|
6
6
|
if (process.env.PRISMA_DEBUG === 'true') {
|
|
7
7
|
return [
|
|
@@ -67,41 +67,40 @@ function registerDevelopmentQueryLogger(prismaClient, instanceId) {
|
|
|
67
67
|
const listenerId = `listener_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;
|
|
68
68
|
globalForPrisma[ID_KEY] = listenerId;
|
|
69
69
|
console.log(`Prisma Query Logger Registered | Listener ID: ${listenerId} | Instance ID: ${instanceId}`);
|
|
70
|
-
// ---
|
|
70
|
+
// --- Custom SQL interpolation ---
|
|
71
71
|
const interpolate = (query, params) => {
|
|
72
|
-
// 1.
|
|
72
|
+
// 1. Validate and parse parameters safely.
|
|
73
73
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
74
74
|
let parameters = [];
|
|
75
75
|
try {
|
|
76
|
-
//
|
|
77
|
-
// 如果 params 是空字符串 "",或者不是有效的 JSON,这里会捕获错误
|
|
76
|
+
// Parse the params string. Empty strings or invalid JSON are handled by the catch block.
|
|
78
77
|
parameters = params && params.length > 0 ? JSON.parse(params) : [];
|
|
79
78
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
80
79
|
}
|
|
81
80
|
catch (e) {
|
|
82
|
-
//
|
|
81
|
+
// If parsing fails, return the original query without interpolation.
|
|
83
82
|
return query;
|
|
84
83
|
}
|
|
85
|
-
//
|
|
84
|
+
// Ensure parameters is an array.
|
|
86
85
|
if (!Array.isArray(parameters)) {
|
|
87
|
-
console.warn('Prisma params
|
|
86
|
+
console.warn('Prisma params did not parse to an array; skipping parameter interpolation. Result:', parameters);
|
|
88
87
|
return query;
|
|
89
88
|
}
|
|
90
|
-
//
|
|
89
|
+
// If there are no parameters, return the query as-is.
|
|
91
90
|
if (parameters.length === 0) {
|
|
92
91
|
return query;
|
|
93
92
|
}
|
|
94
|
-
// 2.
|
|
93
|
+
// 2. Safely stringify parameter values.
|
|
95
94
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
96
95
|
const safeValues = parameters.map((p) => {
|
|
97
96
|
if (p === null)
|
|
98
97
|
return 'NULL';
|
|
99
|
-
//
|
|
98
|
+
// Quote and escape string values for readable SQL logging.
|
|
100
99
|
if (typeof p === 'string')
|
|
101
100
|
return `'${p.replace(/'/g, "''")}'`;
|
|
102
|
-
return p; //
|
|
101
|
+
return p; // Numbers, booleans, and similar values can be returned directly.
|
|
103
102
|
});
|
|
104
|
-
// 3.
|
|
103
|
+
// 3. Replace $1, $2, ... placeholders.
|
|
105
104
|
let sql = query;
|
|
106
105
|
for (let i = 0; i < safeValues.length; i++) {
|
|
107
106
|
const placeholder = new RegExp('\\$' + (i + 1) + '(?!\\d)', 'g');
|
|
@@ -114,20 +113,20 @@ function registerDevelopmentQueryLogger(prismaClient, instanceId) {
|
|
|
114
113
|
const slow = ms >= 200 ? '🐌 SLOW SQL ' : '🚀 SQL';
|
|
115
114
|
const interpolatedSql = interpolate(event.query, event.params);
|
|
116
115
|
const clean = interpolatedSql
|
|
117
|
-
.replace(/"[^"]+"\./g, '') //
|
|
118
|
-
.replace(/= '([^']+)'/g, `= '$1'`) //
|
|
119
|
-
.replace(/"/g, ''); //
|
|
116
|
+
.replace(/"[^"]+"\./g, '') // Remove "table". prefixes.
|
|
117
|
+
.replace(/= '([^']+)'/g, `= '$1'`) // Keep normalized quoted values.
|
|
118
|
+
.replace(/"/g, ''); // Remove remaining double quotes.
|
|
120
119
|
console.log('─'.repeat(60));
|
|
121
120
|
console.log(`Prisma Instance ID: ${instanceId} | Listener ID: ${listenerId}`);
|
|
122
121
|
console.log(`${clean};`);
|
|
123
|
-
console.log(
|
|
122
|
+
console.log(`Duration: ${ms}ms, ${slow}`);
|
|
124
123
|
};
|
|
125
|
-
//
|
|
124
|
+
// Register the wrapped handler.
|
|
126
125
|
(_a = prismaClient.$on) === null || _a === void 0 ? void 0 : _a.call(prismaClient, 'query', wrappedHandler);
|
|
127
126
|
globalForPrisma[REGISTERED_KEY] = true;
|
|
128
127
|
}
|
|
129
128
|
}
|
|
130
|
-
// ====================
|
|
129
|
+
// ==================== Client Helper: fall back to the global non-transaction client when no transaction client is provided ====================
|
|
131
130
|
function checkAndFallbackWithNonTCClient(tx) {
|
|
132
131
|
return tx !== null && tx !== void 0 ? tx : getBackendCorePrisma();
|
|
133
132
|
}
|
package/dist/prisma/prisma.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const globalForPrisma = globalThis;
|
|
2
|
-
// ====================
|
|
2
|
+
// ==================== Logging Configuration ====================
|
|
3
3
|
const getLogConfig = () => {
|
|
4
4
|
if (process.env.PRISMA_DEBUG === 'true') {
|
|
5
5
|
return [
|
|
@@ -65,41 +65,40 @@ function registerDevelopmentQueryLogger(prismaClient, instanceId) {
|
|
|
65
65
|
const listenerId = `listener_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;
|
|
66
66
|
globalForPrisma[ID_KEY] = listenerId;
|
|
67
67
|
console.log(`Prisma Query Logger Registered | Listener ID: ${listenerId} | Instance ID: ${instanceId}`);
|
|
68
|
-
// ---
|
|
68
|
+
// --- Custom SQL interpolation ---
|
|
69
69
|
const interpolate = (query, params) => {
|
|
70
|
-
// 1.
|
|
70
|
+
// 1. Validate and parse parameters safely.
|
|
71
71
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
72
72
|
let parameters = [];
|
|
73
73
|
try {
|
|
74
|
-
//
|
|
75
|
-
// 如果 params 是空字符串 "",或者不是有效的 JSON,这里会捕获错误
|
|
74
|
+
// Parse the params string. Empty strings or invalid JSON are handled by the catch block.
|
|
76
75
|
parameters = params && params.length > 0 ? JSON.parse(params) : [];
|
|
77
76
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
78
77
|
}
|
|
79
78
|
catch (e) {
|
|
80
|
-
//
|
|
79
|
+
// If parsing fails, return the original query without interpolation.
|
|
81
80
|
return query;
|
|
82
81
|
}
|
|
83
|
-
//
|
|
82
|
+
// Ensure parameters is an array.
|
|
84
83
|
if (!Array.isArray(parameters)) {
|
|
85
|
-
console.warn('Prisma params
|
|
84
|
+
console.warn('Prisma params did not parse to an array; skipping parameter interpolation. Result:', parameters);
|
|
86
85
|
return query;
|
|
87
86
|
}
|
|
88
|
-
//
|
|
87
|
+
// If there are no parameters, return the query as-is.
|
|
89
88
|
if (parameters.length === 0) {
|
|
90
89
|
return query;
|
|
91
90
|
}
|
|
92
|
-
// 2.
|
|
91
|
+
// 2. Safely stringify parameter values.
|
|
93
92
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
94
93
|
const safeValues = parameters.map((p) => {
|
|
95
94
|
if (p === null)
|
|
96
95
|
return 'NULL';
|
|
97
|
-
//
|
|
96
|
+
// Quote and escape string values for readable SQL logging.
|
|
98
97
|
if (typeof p === 'string')
|
|
99
98
|
return `'${p.replace(/'/g, "''")}'`;
|
|
100
|
-
return p; //
|
|
99
|
+
return p; // Numbers, booleans, and similar values can be returned directly.
|
|
101
100
|
});
|
|
102
|
-
// 3.
|
|
101
|
+
// 3. Replace $1, $2, ... placeholders.
|
|
103
102
|
let sql = query;
|
|
104
103
|
for (let i = 0; i < safeValues.length; i++) {
|
|
105
104
|
const placeholder = new RegExp('\\$' + (i + 1) + '(?!\\d)', 'g');
|
|
@@ -112,20 +111,20 @@ function registerDevelopmentQueryLogger(prismaClient, instanceId) {
|
|
|
112
111
|
const slow = ms >= 200 ? '🐌 SLOW SQL ' : '🚀 SQL';
|
|
113
112
|
const interpolatedSql = interpolate(event.query, event.params);
|
|
114
113
|
const clean = interpolatedSql
|
|
115
|
-
.replace(/"[^"]+"\./g, '') //
|
|
116
|
-
.replace(/= '([^']+)'/g, `= '$1'`) //
|
|
117
|
-
.replace(/"/g, ''); //
|
|
114
|
+
.replace(/"[^"]+"\./g, '') // Remove "table". prefixes.
|
|
115
|
+
.replace(/= '([^']+)'/g, `= '$1'`) // Keep normalized quoted values.
|
|
116
|
+
.replace(/"/g, ''); // Remove remaining double quotes.
|
|
118
117
|
console.log('─'.repeat(60));
|
|
119
118
|
console.log(`Prisma Instance ID: ${instanceId} | Listener ID: ${listenerId}`);
|
|
120
119
|
console.log(`${clean};`);
|
|
121
|
-
console.log(
|
|
120
|
+
console.log(`Duration: ${ms}ms, ${slow}`);
|
|
122
121
|
};
|
|
123
|
-
//
|
|
122
|
+
// Register the wrapped handler.
|
|
124
123
|
(_a = prismaClient.$on) === null || _a === void 0 ? void 0 : _a.call(prismaClient, 'query', wrappedHandler);
|
|
125
124
|
globalForPrisma[REGISTERED_KEY] = true;
|
|
126
125
|
}
|
|
127
126
|
}
|
|
128
|
-
// ====================
|
|
127
|
+
// ==================== Client Helper: fall back to the global non-transaction client when no transaction client is provided ====================
|
|
129
128
|
function checkAndFallbackWithNonTCClient(tx) {
|
|
130
129
|
return tx !== null && tx !== void 0 ? tx : getBackendCorePrisma();
|
|
131
130
|
}
|
|
@@ -14,7 +14,7 @@ class BillingAggregateService {
|
|
|
14
14
|
yield prismaTransactionUtil.runInTransaction((tx) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
15
15
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
16
16
|
const now = new Date();
|
|
17
|
-
//
|
|
17
|
+
// Set subscription expiry to the last second of the expiration date
|
|
18
18
|
const originSubPeriodEnd = context.periodEnd;
|
|
19
19
|
const specialEnd = originSubPeriodEnd ? new Date(originSubPeriodEnd.setHours(23, 59, 59, 999)) : originSubPeriodEnd;
|
|
20
20
|
const updatedSubscription = yield subscription_service.subscriptionService.updateSubscription(context.subIdKey, {
|
|
@@ -132,7 +132,7 @@ class BillingAggregateService {
|
|
|
132
132
|
paidEmail: context.paidEmail,
|
|
133
133
|
payUpdatedAt: new Date(),
|
|
134
134
|
}, tx);
|
|
135
|
-
//
|
|
135
|
+
// Set subscription expiry to the last second of the expiration date
|
|
136
136
|
const originSubPeriodEnd = context.periodEnd;
|
|
137
137
|
const specialEnd = originSubPeriodEnd ? new Date(originSubPeriodEnd.setHours(23, 59, 59, 999)) : originSubPeriodEnd;
|
|
138
138
|
yield subscription_service.subscriptionService.updateSubscription(context.subIdKey, {
|
|
@@ -218,7 +218,7 @@ class BillingAggregateService {
|
|
|
218
218
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
219
219
|
yield prismaTransactionUtil.runInTransaction((tx) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
220
220
|
if (params.isUserCancel) {
|
|
221
|
-
//
|
|
221
|
+
// Record the time when the user unsubscribes
|
|
222
222
|
yield transaction_service.transactionService.update(params.orderId, {
|
|
223
223
|
subLastTryCancelAt: new Date(),
|
|
224
224
|
}, tx);
|
|
@@ -236,14 +236,14 @@ class BillingAggregateService {
|
|
|
236
236
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
237
237
|
yield prismaTransactionUtil.runInTransaction((tx) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
238
238
|
var _a;
|
|
239
|
-
//
|
|
239
|
+
// Update the order and log cancellation details
|
|
240
240
|
yield transaction_service.transactionService.update(context.orderId, {
|
|
241
241
|
subPeriodCanceledAt: context.canceledAt,
|
|
242
242
|
subCancellationDetail: (_a = context.cancellationDetail) !== null && _a !== void 0 ? _a : undefined
|
|
243
243
|
}, tx);
|
|
244
|
-
//
|
|
244
|
+
// Update subscription information
|
|
245
245
|
yield subscription_service.subscriptionService.updateStatus(context.subIdKey, constants.SubscriptionStatus.CANCELED, tx);
|
|
246
|
-
//
|
|
246
|
+
// Clear credits and keep audit trail
|
|
247
247
|
yield credit_service.creditService.purgePaidCredit(context.userId, 'cancel_subscription_purge', context.orderId, tx);
|
|
248
248
|
}));
|
|
249
249
|
});
|
|
@@ -12,7 +12,7 @@ class BillingAggregateService {
|
|
|
12
12
|
yield runInTransaction((tx) => __awaiter(this, void 0, void 0, function* () {
|
|
13
13
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
14
14
|
const now = new Date();
|
|
15
|
-
//
|
|
15
|
+
// Set subscription expiry to the last second of the expiration date
|
|
16
16
|
const originSubPeriodEnd = context.periodEnd;
|
|
17
17
|
const specialEnd = originSubPeriodEnd ? new Date(originSubPeriodEnd.setHours(23, 59, 59, 999)) : originSubPeriodEnd;
|
|
18
18
|
const updatedSubscription = yield subscriptionService.updateSubscription(context.subIdKey, {
|
|
@@ -130,7 +130,7 @@ class BillingAggregateService {
|
|
|
130
130
|
paidEmail: context.paidEmail,
|
|
131
131
|
payUpdatedAt: new Date(),
|
|
132
132
|
}, tx);
|
|
133
|
-
//
|
|
133
|
+
// Set subscription expiry to the last second of the expiration date
|
|
134
134
|
const originSubPeriodEnd = context.periodEnd;
|
|
135
135
|
const specialEnd = originSubPeriodEnd ? new Date(originSubPeriodEnd.setHours(23, 59, 59, 999)) : originSubPeriodEnd;
|
|
136
136
|
yield subscriptionService.updateSubscription(context.subIdKey, {
|
|
@@ -216,7 +216,7 @@ class BillingAggregateService {
|
|
|
216
216
|
return __awaiter(this, void 0, void 0, function* () {
|
|
217
217
|
yield runInTransaction((tx) => __awaiter(this, void 0, void 0, function* () {
|
|
218
218
|
if (params.isUserCancel) {
|
|
219
|
-
//
|
|
219
|
+
// Record the time when the user unsubscribes
|
|
220
220
|
yield transactionService.update(params.orderId, {
|
|
221
221
|
subLastTryCancelAt: new Date(),
|
|
222
222
|
}, tx);
|
|
@@ -234,14 +234,14 @@ class BillingAggregateService {
|
|
|
234
234
|
return __awaiter(this, void 0, void 0, function* () {
|
|
235
235
|
yield runInTransaction((tx) => __awaiter(this, void 0, void 0, function* () {
|
|
236
236
|
var _a;
|
|
237
|
-
//
|
|
237
|
+
// Update the order and log cancellation details
|
|
238
238
|
yield transactionService.update(context.orderId, {
|
|
239
239
|
subPeriodCanceledAt: context.canceledAt,
|
|
240
240
|
subCancellationDetail: (_a = context.cancellationDetail) !== null && _a !== void 0 ? _a : undefined
|
|
241
241
|
}, tx);
|
|
242
|
-
//
|
|
242
|
+
// Update subscription information
|
|
243
243
|
yield subscriptionService.updateStatus(context.subIdKey, SubscriptionStatus.CANCELED, tx);
|
|
244
|
-
//
|
|
244
|
+
// Clear credits and keep audit trail
|
|
245
245
|
yield creditService.purgePaidCredit(context.userId, 'cancel_subscription_purge', context.orderId, tx);
|
|
246
246
|
}));
|
|
247
247
|
});
|
|
@@ -7,17 +7,17 @@ export declare class UserAggregateService {
|
|
|
7
7
|
credit: Credit;
|
|
8
8
|
}>;
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Create a new registered user
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
* 1.
|
|
14
|
-
* 2.
|
|
15
|
-
* 3.
|
|
16
|
-
* 4.
|
|
12
|
+
* Initialization steps (parallel to credit):
|
|
13
|
+
* 1. Create User record
|
|
14
|
+
* 2. Initialize Credit record (free credits)
|
|
15
|
+
* 3. Initialize Subscription record (placeholder, status=INCOMPLETE)
|
|
16
|
+
* 4. Record CreditUsage (audit)
|
|
17
17
|
*
|
|
18
|
-
*
|
|
19
|
-
* - session.completed
|
|
20
|
-
* -
|
|
18
|
+
* When the user subscribes via Stripe later:
|
|
19
|
+
* - session.completed or invoice.paid will UPDATE the subscription record
|
|
20
|
+
* - No CREATE needed, only UPDATE to ensure logical consistency
|
|
21
21
|
*/
|
|
22
22
|
createNewRegisteredUser(clerkUserId: string, email?: string, fingerprintId?: string, userName?: string, sourceRef?: CoreJsonValue): Promise<{
|
|
23
23
|
newUser: User;
|
|
@@ -32,17 +32,17 @@ class UserAggregateService {
|
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
|
-
*
|
|
35
|
+
* Create a new registered user
|
|
36
36
|
*
|
|
37
|
-
*
|
|
38
|
-
* 1.
|
|
39
|
-
* 2.
|
|
40
|
-
* 3.
|
|
41
|
-
* 4.
|
|
37
|
+
* Initialization steps (parallel to credit):
|
|
38
|
+
* 1. Create User record
|
|
39
|
+
* 2. Initialize Credit record (free credits)
|
|
40
|
+
* 3. Initialize Subscription record (placeholder, status=INCOMPLETE)
|
|
41
|
+
* 4. Record CreditUsage (audit)
|
|
42
42
|
*
|
|
43
|
-
*
|
|
44
|
-
* - session.completed
|
|
45
|
-
* -
|
|
43
|
+
* When the user subscribes via Stripe later:
|
|
44
|
+
* - session.completed or invoice.paid will UPDATE the subscription record
|
|
45
|
+
* - No CREATE needed, only UPDATE to ensure logical consistency
|
|
46
46
|
*/
|
|
47
47
|
createNewRegisteredUser(clerkUserId, email, fingerprintId, userName, sourceRef) {
|
|
48
48
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -68,7 +68,7 @@ class UserAggregateService {
|
|
|
68
68
|
}));
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
|
-
//
|
|
71
|
+
// Note: Handle credit review logs
|
|
72
72
|
upgradeToRegistered(userId, email, clerkUserId, userName) {
|
|
73
73
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
74
74
|
return prismaTransactionUtil.runInTransaction((tx) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -77,9 +77,9 @@ class UserAggregateService {
|
|
|
77
77
|
clerkUserId,
|
|
78
78
|
userName
|
|
79
79
|
}, tx);
|
|
80
|
-
//
|
|
80
|
+
// Clear anonymous credits first and audit for traceability
|
|
81
81
|
yield credit_service.creditService.purgeFreeCredit(userId, 'user_registered_purge', userId, tx);
|
|
82
|
-
//
|
|
82
|
+
// Then initialize free credits upon successful registration
|
|
83
83
|
const credit = yield credit_service.creditService.initializeCreditWithFree({
|
|
84
84
|
userId: updateUser.userId,
|
|
85
85
|
feature: 'user_registration_init',
|
|
@@ -95,20 +95,20 @@ class UserAggregateService {
|
|
|
95
95
|
handleUserUnregister(clerkUserId) {
|
|
96
96
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
97
97
|
return prismaTransactionUtil.runInTransaction((tx) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
98
|
-
//
|
|
98
|
+
// query DB user
|
|
99
99
|
const user = yield user_service.userService.findByClerkUserId(clerkUserId, tx);
|
|
100
100
|
if (!user) {
|
|
101
101
|
console.log(`User with clerkUserId ${clerkUserId} not found`);
|
|
102
102
|
return null;
|
|
103
103
|
}
|
|
104
104
|
const userId = user.userId;
|
|
105
|
-
//
|
|
105
|
+
// Update user status and retain user info (especially FingerprintId) to prevent repeated registration abuse
|
|
106
106
|
yield user_service.userService.unregister(user.userId, tx);
|
|
107
|
-
//
|
|
107
|
+
// Clear credits
|
|
108
108
|
yield credit_service.creditService.purgeCredit(userId, 'soft_delete_user', userId, tx);
|
|
109
109
|
const subscription = yield subscription_service.subscriptionService.getActiveSubscription(userId, tx);
|
|
110
110
|
if (subscription) {
|
|
111
|
-
//
|
|
111
|
+
// Update subscription info if it exists
|
|
112
112
|
yield subscription_service.subscriptionService.cancelSubscription(subscription.id, true, tx);
|
|
113
113
|
}
|
|
114
114
|
return user.userId;
|
|
@@ -30,17 +30,17 @@ class UserAggregateService {
|
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
33
|
+
* Create a new registered user
|
|
34
34
|
*
|
|
35
|
-
*
|
|
36
|
-
* 1.
|
|
37
|
-
* 2.
|
|
38
|
-
* 3.
|
|
39
|
-
* 4.
|
|
35
|
+
* Initialization steps (parallel to credit):
|
|
36
|
+
* 1. Create User record
|
|
37
|
+
* 2. Initialize Credit record (free credits)
|
|
38
|
+
* 3. Initialize Subscription record (placeholder, status=INCOMPLETE)
|
|
39
|
+
* 4. Record CreditUsage (audit)
|
|
40
40
|
*
|
|
41
|
-
*
|
|
42
|
-
* - session.completed
|
|
43
|
-
* -
|
|
41
|
+
* When the user subscribes via Stripe later:
|
|
42
|
+
* - session.completed or invoice.paid will UPDATE the subscription record
|
|
43
|
+
* - No CREATE needed, only UPDATE to ensure logical consistency
|
|
44
44
|
*/
|
|
45
45
|
createNewRegisteredUser(clerkUserId, email, fingerprintId, userName, sourceRef) {
|
|
46
46
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -66,7 +66,7 @@ class UserAggregateService {
|
|
|
66
66
|
}));
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
|
-
//
|
|
69
|
+
// Note: Handle credit review logs
|
|
70
70
|
upgradeToRegistered(userId, email, clerkUserId, userName) {
|
|
71
71
|
return __awaiter(this, void 0, void 0, function* () {
|
|
72
72
|
return runInTransaction((tx) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -75,9 +75,9 @@ class UserAggregateService {
|
|
|
75
75
|
clerkUserId,
|
|
76
76
|
userName
|
|
77
77
|
}, tx);
|
|
78
|
-
//
|
|
78
|
+
// Clear anonymous credits first and audit for traceability
|
|
79
79
|
yield creditService.purgeFreeCredit(userId, 'user_registered_purge', userId, tx);
|
|
80
|
-
//
|
|
80
|
+
// Then initialize free credits upon successful registration
|
|
81
81
|
const credit = yield creditService.initializeCreditWithFree({
|
|
82
82
|
userId: updateUser.userId,
|
|
83
83
|
feature: 'user_registration_init',
|
|
@@ -93,20 +93,20 @@ class UserAggregateService {
|
|
|
93
93
|
handleUserUnregister(clerkUserId) {
|
|
94
94
|
return __awaiter(this, void 0, void 0, function* () {
|
|
95
95
|
return runInTransaction((tx) => __awaiter(this, void 0, void 0, function* () {
|
|
96
|
-
//
|
|
96
|
+
// query DB user
|
|
97
97
|
const user = yield userService.findByClerkUserId(clerkUserId, tx);
|
|
98
98
|
if (!user) {
|
|
99
99
|
console.log(`User with clerkUserId ${clerkUserId} not found`);
|
|
100
100
|
return null;
|
|
101
101
|
}
|
|
102
102
|
const userId = user.userId;
|
|
103
|
-
//
|
|
103
|
+
// Update user status and retain user info (especially FingerprintId) to prevent repeated registration abuse
|
|
104
104
|
yield userService.unregister(user.userId, tx);
|
|
105
|
-
//
|
|
105
|
+
// Clear credits
|
|
106
106
|
yield creditService.purgeCredit(userId, 'soft_delete_user', userId, tx);
|
|
107
107
|
const subscription = yield subscriptionService.getActiveSubscription(userId, tx);
|
|
108
108
|
if (subscription) {
|
|
109
|
-
//
|
|
109
|
+
// Update subscription info if it exists
|
|
110
110
|
yield subscriptionService.cancelSubscription(subscription.id, true, tx);
|
|
111
111
|
}
|
|
112
112
|
return user.userId;
|