@tradejs/app 3.1.29-beta.269 → 3.1.29-beta.271
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/app",
|
|
3
|
-
"version": "3.1.29-beta.
|
|
3
|
+
"version": "3.1.29-beta.271",
|
|
4
4
|
"description": "Installable Next.js UI for the TradeJS TypeScript framework: dashboards, backtests, charts, and runtime data.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tradejs",
|
|
@@ -59,11 +59,11 @@
|
|
|
59
59
|
"@emotion/react": "^11.14.0",
|
|
60
60
|
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
61
61
|
"@node-oauth/oauth2-server": "^5.3.0",
|
|
62
|
-
"@tradejs/core": "^3.1.29-beta.
|
|
63
|
-
"@tradejs/indicators": "^3.1.29-beta.
|
|
64
|
-
"@tradejs/infra": "^3.1.29-beta.
|
|
65
|
-
"@tradejs/node": "^3.1.29-beta.
|
|
66
|
-
"@tradejs/types": "^3.1.29-beta.
|
|
62
|
+
"@tradejs/core": "^3.1.29-beta.271",
|
|
63
|
+
"@tradejs/indicators": "^3.1.29-beta.271",
|
|
64
|
+
"@tradejs/infra": "^3.1.29-beta.271",
|
|
65
|
+
"@tradejs/node": "^3.1.29-beta.271",
|
|
66
|
+
"@tradejs/types": "^3.1.29-beta.271",
|
|
67
67
|
"@types/bcryptjs": "2.4.6",
|
|
68
68
|
"@types/lodash": "4.17.24",
|
|
69
69
|
"@types/node": "24.13.3",
|
|
@@ -19,6 +19,14 @@ import { getCurrentUserName } from '#app/lib/currentUser';
|
|
|
19
19
|
export const dynamic = 'force-dynamic';
|
|
20
20
|
|
|
21
21
|
type UpdateBody =
|
|
22
|
+
| {
|
|
23
|
+
section: 'notifications';
|
|
24
|
+
data?: {
|
|
25
|
+
signals?: boolean;
|
|
26
|
+
aiAnalysis?: boolean;
|
|
27
|
+
runtimeDebug?: boolean;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
22
30
|
| {
|
|
23
31
|
section: 'jev';
|
|
24
32
|
data?: { apiKey?: string; apiEndpoint?: string; model?: string };
|
|
@@ -65,6 +73,7 @@ const UPDATE_SECTIONS = new Set([
|
|
|
65
73
|
'ai',
|
|
66
74
|
'jev',
|
|
67
75
|
'telegram',
|
|
76
|
+
'notifications',
|
|
68
77
|
'password',
|
|
69
78
|
]);
|
|
70
79
|
|
|
@@ -123,6 +132,11 @@ const toResponse = (rawSettings: UserSettings) => {
|
|
|
123
132
|
model: settings.AI_MODEL,
|
|
124
133
|
responseLanguage: settings.AI_RESPONSE_LANGUAGE,
|
|
125
134
|
},
|
|
135
|
+
notifications: {
|
|
136
|
+
signals: settings.NOTIFY_SIGNALS !== false,
|
|
137
|
+
aiAnalysis: settings.NOTIFY_AI_ANALYSIS !== false,
|
|
138
|
+
runtimeDebug: settings.NOTIFY_RUNTIME_DEBUG !== false,
|
|
139
|
+
},
|
|
126
140
|
telegram: {
|
|
127
141
|
botToken: maskSecret(settings.TG_BOT_TOKEN),
|
|
128
142
|
chatId: settings.TG_CHAT_ID,
|
|
@@ -279,6 +293,37 @@ export const PATCH = async (request: Request) => {
|
|
|
279
293
|
}
|
|
280
294
|
}
|
|
281
295
|
|
|
296
|
+
if (body.section === 'notifications') {
|
|
297
|
+
const patch: Partial<UserRecord> = {};
|
|
298
|
+
const fields = {
|
|
299
|
+
signals: 'NOTIFY_SIGNALS',
|
|
300
|
+
aiAnalysis: 'NOTIFY_AI_ANALYSIS',
|
|
301
|
+
runtimeDebug: 'NOTIFY_RUNTIME_DEBUG',
|
|
302
|
+
} as const;
|
|
303
|
+
if (
|
|
304
|
+
!body.data ||
|
|
305
|
+
typeof body.data !== 'object' ||
|
|
306
|
+
Array.isArray(body.data)
|
|
307
|
+
) {
|
|
308
|
+
return NextResponse.json(
|
|
309
|
+
{ error: 'Invalid notification settings' },
|
|
310
|
+
{ status: 400 },
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
for (const [field, key] of Object.entries(fields)) {
|
|
314
|
+
if (!(field in body.data)) continue;
|
|
315
|
+
const value = body.data[field as keyof typeof fields];
|
|
316
|
+
if (typeof value !== 'boolean') {
|
|
317
|
+
return NextResponse.json(
|
|
318
|
+
{ error: 'Notification settings must be boolean' },
|
|
319
|
+
{ status: 400 },
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
patch[key] = value;
|
|
323
|
+
}
|
|
324
|
+
if (hasKeys(patch)) await updateUserRecord(userName, patch);
|
|
325
|
+
}
|
|
326
|
+
|
|
282
327
|
if (body.section === 'telegram') {
|
|
283
328
|
const patch: Partial<UserRecord> = {};
|
|
284
329
|
const botToken = cleanOptionalText(body.data?.botToken);
|