@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.269",
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.269",
63
- "@tradejs/indicators": "^3.1.29-beta.269",
64
- "@tradejs/infra": "^3.1.29-beta.269",
65
- "@tradejs/node": "^3.1.29-beta.269",
66
- "@tradejs/types": "^3.1.29-beta.269",
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);