upfynai-code 2.5.0 → 2.6.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/README.md +131 -0
- package/client/dist/assets/{AppContent-CRld2UWX.js → AppContent-C0CyP3g5.js} +3 -3
- package/client/dist/assets/{CanvasPanel-CB4sweQq.js → CanvasPanel-0u9QR7U-.js} +5 -5
- package/client/dist/assets/DashboardPanel-Dgqw1yZk.js +1 -0
- package/client/dist/assets/{LoginModal-BwkvjfPR.js → LoginModal-CZDEzqjK.js} +1 -1
- package/client/dist/assets/Onboarding-DR6NZ4Vz.js +1 -0
- package/client/dist/assets/{SetupForm-CH5EA5W0.js → SetupForm-D49gtWY4.js} +1 -1
- package/client/dist/assets/{WorkflowsPanel-CO5g5yGG.js → WorkflowsPanel-CqlbEJA_.js} +1 -1
- package/client/dist/assets/{ar-SA-G6X2FPQ2-DoJuo98H.js → ar-SA-G6X2FPQ2-BWqa1yBH.js} +1 -1
- package/client/dist/assets/{arc-B0wBaTeh.js → arc-BegSKqEW.js} +1 -1
- package/client/dist/assets/{az-AZ-76LH7QW2-xdrt1Z13.js → az-AZ-76LH7QW2-DrVlbZDP.js} +1 -1
- package/client/dist/assets/{bg-BG-XCXSNQG7-D8NAiF6Y.js → bg-BG-XCXSNQG7-DdunjBgT.js} +1 -1
- package/client/dist/assets/{blockDiagram-38ab4fdb-DSnyKzK4.js → blockDiagram-38ab4fdb-BKMbwGHu.js} +1 -1
- package/client/dist/assets/{bn-BD-2XOGV67Q-B0qWv8_J.js → bn-BD-2XOGV67Q-_7DtmvwO.js} +1 -1
- package/client/dist/assets/{c4Diagram-3d4e48cf-DoZJ13XA.js → c4Diagram-3d4e48cf-hJuiHhSn.js} +1 -1
- package/client/dist/assets/{ca-ES-6MX7JW3Y-RgLhfbZZ.js → ca-ES-6MX7JW3Y-BFIrmojG.js} +1 -1
- package/client/dist/assets/channel-Bur-rRTp.js +1 -0
- package/client/dist/assets/{classDiagram-70f12bd4-GNyDrRCk.js → classDiagram-70f12bd4-BjiAf9cM.js} +1 -1
- package/client/dist/assets/{classDiagram-v2-f2320105-CxdGhHm2.js → classDiagram-v2-f2320105-pwBewejc.js} +1 -1
- package/client/dist/assets/clone-BtqXeoBJ.js +1 -0
- package/client/dist/assets/{createText-2e5e7dd3-DiPywQOa.js → createText-2e5e7dd3-Dq_acOWe.js} +1 -1
- package/client/dist/assets/{cs-CZ-2BRQDIVT-BAjmnuoC.js → cs-CZ-2BRQDIVT-B-x4F6TJ.js} +1 -1
- package/client/dist/assets/{da-DK-5WZEPLOC-JxKVGt8o.js → da-DK-5WZEPLOC-Btlc8Dgn.js} +1 -1
- package/client/dist/assets/{de-DE-XR44H4JA-CrnRlt4z.js → de-DE-XR44H4JA-BVu3ZIoD.js} +1 -1
- package/client/dist/assets/{edges-e0da2a9e-DDsXzXLJ.js → edges-e0da2a9e-DH0wVTXR.js} +1 -1
- package/client/dist/assets/{el-GR-BZB4AONW-DQd8iogq.js → el-GR-BZB4AONW-h2ll8_ZC.js} +1 -1
- package/client/dist/assets/{erDiagram-9861fffd-CBiCC4rl.js → erDiagram-9861fffd-BYezLIR7.js} +1 -1
- package/client/dist/assets/{es-ES-U4NZUMDT-vvUblc5i.js → es-ES-U4NZUMDT-Cveiulwt.js} +1 -1
- package/client/dist/assets/{eu-ES-A7QVB2H4-De4NNCc1.js → eu-ES-A7QVB2H4-DQluL2PY.js} +1 -1
- package/client/dist/assets/{fa-IR-HGAKTJCU-DFBXqIqq.js → fa-IR-HGAKTJCU-BJtcMBSv.js} +1 -1
- package/client/dist/assets/{fi-FI-Z5N7JZ37-DV9zESPg.js → fi-FI-Z5N7JZ37-D8NfbVXV.js} +1 -1
- package/client/dist/assets/{flowDb-956e92f1-BhdSHbdO.js → flowDb-956e92f1-scnUykhM.js} +1 -1
- package/client/dist/assets/{flowDiagram-66a62f08-M-fp1_Ie.js → flowDiagram-66a62f08-jVyWsfyU.js} +1 -1
- package/client/dist/assets/flowDiagram-v2-96b9c2cf-N6xgi25h.js +1 -0
- package/client/dist/assets/{flowchart-elk-definition-4a651766-Bp0SonQx.js → flowchart-elk-definition-4a651766-gKGX3HqR.js} +1 -1
- package/client/dist/assets/{fr-FR-RHASNOE6-CKTMXuGk.js → fr-FR-RHASNOE6-vdj42kC6.js} +1 -1
- package/client/dist/assets/{ganttDiagram-c361ad54-iA737GUS.js → ganttDiagram-c361ad54-C2CiWFUP.js} +1 -1
- package/client/dist/assets/{gitGraphDiagram-72cf32ee-BX-wj-PV.js → gitGraphDiagram-72cf32ee-C59Yz2LK.js} +1 -1
- package/client/dist/assets/{gl-ES-HMX3MZ6V-Cdiqq4jY.js → gl-ES-HMX3MZ6V-DQo0TzoP.js} +1 -1
- package/client/dist/assets/{graph-Rxkx3sEa.js → graph-Dx_H43Kv.js} +1 -1
- package/client/dist/assets/{he-IL-6SHJWFNN-gYmR5_KT.js → he-IL-6SHJWFNN-DKXK5e33.js} +1 -1
- package/client/dist/assets/{hi-IN-IWLTKZ5I-pyqK94AR.js → hi-IN-IWLTKZ5I-C2Qgqc0R.js} +1 -1
- package/client/dist/assets/{hu-HU-A5ZG7DT2-DpacJgJy.js → hu-HU-A5ZG7DT2-Ss-6vX0m.js} +1 -1
- package/client/dist/assets/{id-ID-SAP4L64H-CAvIX-mj.js → id-ID-SAP4L64H-D7Wsg1S2.js} +1 -1
- package/client/dist/assets/{index-3862675e-BX3Fpn6V.js → index-3862675e-u8Nv7hHC.js} +1 -1
- package/client/dist/assets/{index-BBlwbHq_.js → index-BVowJdZF.js} +4 -4
- package/client/dist/assets/{index-ClfzLIqY.js → index-ce18TYkg.js} +4 -4
- package/client/dist/assets/index-kQoJx-bc.css +1 -0
- package/client/dist/assets/{infoDiagram-f8f76790-Ckv8imiv.js → infoDiagram-f8f76790-LmoJYsxo.js} +1 -1
- package/client/dist/assets/{it-IT-JPQ66NNP-BtpNRSce.js → it-IT-JPQ66NNP-CAPTVl7M.js} +1 -1
- package/client/dist/assets/{ja-JP-DBVTYXUO-CwJRyY6M.js → ja-JP-DBVTYXUO-eNVPawR2.js} +1 -1
- package/client/dist/assets/{journeyDiagram-49397b02-DWWZssji.js → journeyDiagram-49397b02-BaJqehpR.js} +1 -1
- package/client/dist/assets/{kaa-6HZHGXH3-DIWQEb4A.js → kaa-6HZHGXH3-tpuNkKhS.js} +1 -1
- package/client/dist/assets/{kab-KAB-ZGHBKWFO-DjGbqhUg.js → kab-KAB-ZGHBKWFO-Dp83kx4x.js} +1 -1
- package/client/dist/assets/{kk-KZ-P5N5QNE5-B_VzJdWf.js → kk-KZ-P5N5QNE5-B9IlC6YN.js} +1 -1
- package/client/dist/assets/{km-KH-HSX4SM5Z-DUD5mi0o.js → km-KH-HSX4SM5Z-B_KMYaMj.js} +1 -1
- package/client/dist/assets/{ko-KR-MTYHY66A--sDB10db.js → ko-KR-MTYHY66A-yebnUNdb.js} +1 -1
- package/client/dist/assets/{ku-TR-6OUDTVRD-CKvKrkcX.js → ku-TR-6OUDTVRD-BR6fh6-5.js} +1 -1
- package/client/dist/assets/{layout-CkB7sSeq.js → layout-DLl5Jwcl.js} +1 -1
- package/client/dist/assets/{line-DC7MA9qY.js → line-FpB7omSK.js} +1 -1
- package/client/dist/assets/{linear-C1lBBthf.js → linear-CkXqUFJ8.js} +1 -1
- package/client/dist/assets/{lt-LT-XHIRWOB4-MSZf7xYG.js → lt-LT-XHIRWOB4-SutZSWtR.js} +1 -1
- package/client/dist/assets/{lv-LV-5QDEKY6T-C-gvvmBB.js → lv-LV-5QDEKY6T-DuAxdcZL.js} +1 -1
- package/client/dist/assets/{mindmap-definition-fc14e90a-B3O7hztq.js → mindmap-definition-fc14e90a-DyxXOExh.js} +1 -1
- package/client/dist/assets/{mr-IN-CRQNXWMA-XHtBUWQH.js → mr-IN-CRQNXWMA-DqDUWM_8.js} +1 -1
- package/client/dist/assets/{my-MM-5M5IBNSE-D9eD2edL.js → my-MM-5M5IBNSE-C40kMFMR.js} +1 -1
- package/client/dist/assets/{nb-NO-T6EIAALU-BlImC6gp.js → nb-NO-T6EIAALU-DVij32Ju.js} +1 -1
- package/client/dist/assets/{nl-NL-IS3SIHDZ-CPFhnaSP.js → nl-NL-IS3SIHDZ-rT84mDYq.js} +1 -1
- package/client/dist/assets/{nn-NO-6E72VCQL-BMvoJSKQ.js → nn-NO-6E72VCQL-BBZXBW8V.js} +1 -1
- package/client/dist/assets/{oc-FR-POXYY2M6-Buye63LS.js → oc-FR-POXYY2M6-DzjOugOf.js} +1 -1
- package/client/dist/assets/{pa-IN-N4M65BXN-D9uQ3niy.js → pa-IN-N4M65BXN-DD1iU8_F.js} +1 -1
- package/client/dist/assets/{percentages-BXMCSKIN-BzXIakGM.js → percentages-BXMCSKIN-WVlHS4wx.js} +6 -6
- package/client/dist/assets/{pieDiagram-8a3498a8-BU38mzx-.js → pieDiagram-8a3498a8-Dd_85qBH.js} +1 -1
- package/client/dist/assets/{pl-PL-T2D74RX3-BqM4xdcg.js → pl-PL-T2D74RX3-ukVXa48G.js} +1 -1
- package/client/dist/assets/{pt-BR-5N22H2LF-rAjrxGyI.js → pt-BR-5N22H2LF-BibawarT.js} +1 -1
- package/client/dist/assets/{pt-PT-UZXXM6DQ-DXsqcwLt.js → pt-PT-UZXXM6DQ-So3i9l9w.js} +1 -1
- package/client/dist/assets/{quadrantDiagram-120e2f19-HhK4H1WU.js → quadrantDiagram-120e2f19-C4dFVDEx.js} +1 -1
- package/client/dist/assets/{requirementDiagram-deff3bca-aDrcyj-A.js → requirementDiagram-deff3bca-DrTO7yFl.js} +1 -1
- package/client/dist/assets/{ro-RO-JPDTUUEW-D_F9UKer.js → ro-RO-JPDTUUEW-DY0Xq_Hd.js} +1 -1
- package/client/dist/assets/{ru-RU-B4JR7IUQ-MirqN29p.js → ru-RU-B4JR7IUQ-B7u_Zvkd.js} +1 -1
- package/client/dist/assets/{sankeyDiagram-04a897e0-C6ij7qbQ.js → sankeyDiagram-04a897e0-D24gfzuS.js} +1 -1
- package/client/dist/assets/{sequenceDiagram-704730f1-C0EKO3th.js → sequenceDiagram-704730f1-Dgji2XLQ.js} +1 -1
- package/client/dist/assets/{si-LK-N5RQ5JYF-DyZC3mkC.js → si-LK-N5RQ5JYF-OejsLzQ_.js} +1 -1
- package/client/dist/assets/{sk-SK-C5VTKIMK-D-ksz-WY.js → sk-SK-C5VTKIMK-_vy2Bt-M.js} +1 -1
- package/client/dist/assets/{sl-SI-NN7IZMDC-CknuYoQ1.js → sl-SI-NN7IZMDC-DKOl_u2M.js} +1 -1
- package/client/dist/assets/{stateDiagram-587899a1-CYoq2VjL.js → stateDiagram-587899a1-CJ8eBaiU.js} +1 -1
- package/client/dist/assets/{stateDiagram-v2-d93cdb3a-C5lbp5px.js → stateDiagram-v2-d93cdb3a-C5K3l-Nt.js} +1 -1
- package/client/dist/assets/{styles-6aaf32cf-Dkfsk8gt.js → styles-6aaf32cf-DAKE0jbx.js} +1 -1
- package/client/dist/assets/{styles-9a916d00-CMYqtcEN.js → styles-9a916d00-LFAJCgEy.js} +1 -1
- package/client/dist/assets/{styles-c10674c1-Bp-5OlRU.js → styles-c10674c1-CllKO8NG.js} +1 -1
- package/client/dist/assets/{subset-shared.chunk-kfIB1Zam.js → subset-shared.chunk-Uy-J87FQ.js} +1 -1
- package/client/dist/assets/{subset-worker.chunk-DwQBgc4z.js → subset-worker.chunk-dvgDvqt9.js} +1 -1
- package/client/dist/assets/{sv-SE-XGPEYMSR-DwN13se1.js → sv-SE-XGPEYMSR-CDCB2ZV5.js} +1 -1
- package/client/dist/assets/{svgDrawCommon-08f97a94-CEgCMqs4.js → svgDrawCommon-08f97a94-CObOzbFQ.js} +1 -1
- package/client/dist/assets/{ta-IN-2NMHFXQM-ejDfFhwa.js → ta-IN-2NMHFXQM-DHUNdO69.js} +1 -1
- package/client/dist/assets/{th-TH-HPSO5L25-Bqc90ZNn.js → th-TH-HPSO5L25-zI2hnBq3.js} +1 -1
- package/client/dist/assets/{timeline-definition-85554ec2-BmGdKqG0.js → timeline-definition-85554ec2-C2XHRmxK.js} +1 -1
- package/client/dist/assets/{tr-TR-DEFEU3FU-CJvlPbcW.js → tr-TR-DEFEU3FU-l-6Hu4-D.js} +1 -1
- package/client/dist/assets/{uk-UA-QMV73CPH-D26-cbWL.js → uk-UA-QMV73CPH-CqSOwrl7.js} +1 -1
- package/client/dist/assets/{vendor-icons-aNdOvTr_.js → vendor-icons-Lb69KSFJ.js} +136 -126
- package/client/dist/assets/{vi-VN-M7AON7JQ-MbqIIwYM.js → vi-VN-M7AON7JQ-CUL8-mBZ.js} +1 -1
- package/client/dist/assets/{xychartDiagram-e933f94c-gfcTauxU.js → xychartDiagram-e933f94c-1fmf6slj.js} +1 -1
- package/client/dist/assets/{zh-CN-LNUGB5OW-BZSmhUdL.js → zh-CN-LNUGB5OW-CB5y5VVU.js} +1 -1
- package/client/dist/assets/{zh-HK-E62DVLB3-BJqejpiX.js → zh-HK-E62DVLB3-BHcrrEeJ.js} +1 -1
- package/client/dist/assets/{zh-TW-RAJ6MFWO-BBXtV-Uz.js → zh-TW-RAJ6MFWO-DoDUdkaJ.js} +1 -1
- package/client/dist/index.html +3 -3
- package/package.json +17 -14
- package/server/cli.js +44 -0
- package/server/database/db.js +16 -2
- package/server/index.js +2738 -2621
- package/server/middleware/auth.js +10 -2
- package/server/relay-client.js +73 -20
- package/server/routes/agent.js +1226 -1266
- package/server/routes/auth.js +32 -29
- package/server/routes/commands.js +598 -601
- package/server/routes/cursor.js +806 -807
- package/server/routes/dashboard.js +154 -1
- package/server/routes/git.js +1151 -1165
- package/server/routes/mcp.js +534 -551
- package/server/routes/settings.js +261 -269
- package/server/routes/taskmaster.js +1927 -1963
- package/server/routes/vapi-chat.js +94 -0
- package/server/routes/voice.js +0 -4
- package/server/sandbox.js +120 -0
- package/client/dist/assets/DashboardPanel-BXaA-b9z.js +0 -1
- package/client/dist/assets/Onboarding-2A_5fPxy.js +0 -1
- package/client/dist/assets/channel-BmO6nY0W.js +0 -1
- package/client/dist/assets/clone-xuHMqFoD.js +0 -1
- package/client/dist/assets/flowDiagram-v2-96b9c2cf-C5eiN8Pg.js +0 -1
- package/client/dist/assets/index-Td4UdtLF.css +0 -1
|
@@ -1,10 +1,163 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import { getProjects, getSessions } from '../projects.js';
|
|
3
|
+
import { userDb, subscriptionDb, paymentDb, apiKeysDb, credentialsDb, relayTokensDb, webhookDb, workflowDb } from '../database/db.js';
|
|
3
4
|
|
|
4
5
|
const router = Router();
|
|
5
6
|
|
|
7
|
+
// AI provider credential types
|
|
8
|
+
const AI_PROVIDER_TYPES = ['anthropic_key', 'openai_key', 'openrouter_key', 'google_key'];
|
|
9
|
+
const PROVIDER_LABELS = {
|
|
10
|
+
anthropic_key: 'Anthropic',
|
|
11
|
+
openai_key: 'OpenAI',
|
|
12
|
+
openrouter_key: 'OpenRouter',
|
|
13
|
+
google_key: 'Google',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* GET /api/dashboard/user-stats — Per-user dashboard data from Turso
|
|
18
|
+
* Aggregates: account, subscription, payments, API keys, AI providers, relay tokens, webhooks, workflows
|
|
19
|
+
*/
|
|
20
|
+
router.get('/user-stats', async (req, res) => {
|
|
21
|
+
try {
|
|
22
|
+
const userId = req.user.id;
|
|
23
|
+
|
|
24
|
+
// Run all DB queries in parallel
|
|
25
|
+
const [
|
|
26
|
+
fullUser,
|
|
27
|
+
activeSub,
|
|
28
|
+
allSubs,
|
|
29
|
+
payments,
|
|
30
|
+
apiKeys,
|
|
31
|
+
credentials,
|
|
32
|
+
relayTokens,
|
|
33
|
+
webhooks,
|
|
34
|
+
workflows,
|
|
35
|
+
] = await Promise.all([
|
|
36
|
+
userDb.getUserById(userId),
|
|
37
|
+
subscriptionDb.getActiveSub(userId).catch(() => null),
|
|
38
|
+
subscriptionDb.getAllSubs(userId).catch(() => []),
|
|
39
|
+
paymentDb.getUserPayments(userId).catch(() => []),
|
|
40
|
+
apiKeysDb.getApiKeys(userId).catch(() => []),
|
|
41
|
+
credentialsDb.getCredentials(userId).catch(() => []),
|
|
42
|
+
relayTokensDb.getTokens(userId).catch(() => []),
|
|
43
|
+
webhookDb.getAll(userId).catch(() => []),
|
|
44
|
+
workflowDb.getAll(userId).catch(() => []),
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
// Expire overdue subs
|
|
48
|
+
try { await subscriptionDb.expireOverdue(); } catch { /* non-critical */ }
|
|
49
|
+
|
|
50
|
+
// Account
|
|
51
|
+
const account = fullUser ? {
|
|
52
|
+
username: fullUser.username,
|
|
53
|
+
email: fullUser.email,
|
|
54
|
+
phone: fullUser.phone,
|
|
55
|
+
firstName: fullUser.first_name,
|
|
56
|
+
lastName: fullUser.last_name,
|
|
57
|
+
userCode: fullUser.user_code,
|
|
58
|
+
createdAt: fullUser.created_at,
|
|
59
|
+
lastLogin: fullUser.last_login,
|
|
60
|
+
accessOverride: fullUser.access_override,
|
|
61
|
+
} : null;
|
|
62
|
+
|
|
63
|
+
// Subscription
|
|
64
|
+
const subscription = {
|
|
65
|
+
active: activeSub ? {
|
|
66
|
+
id: activeSub.id,
|
|
67
|
+
planId: activeSub.plan_id,
|
|
68
|
+
status: activeSub.status,
|
|
69
|
+
startsAt: activeSub.starts_at,
|
|
70
|
+
expiresAt: activeSub.expires_at,
|
|
71
|
+
amount: activeSub.amount,
|
|
72
|
+
currency: activeSub.currency || 'INR',
|
|
73
|
+
} : null,
|
|
74
|
+
history: allSubs.map(s => ({
|
|
75
|
+
id: s.id,
|
|
76
|
+
planId: s.plan_id,
|
|
77
|
+
status: s.status,
|
|
78
|
+
startsAt: s.starts_at,
|
|
79
|
+
expiresAt: s.expires_at,
|
|
80
|
+
amount: s.amount,
|
|
81
|
+
currency: s.currency || 'INR',
|
|
82
|
+
createdAt: s.created_at,
|
|
83
|
+
})),
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Payments
|
|
87
|
+
const paidPayments = payments.filter(p => p.status === 'paid');
|
|
88
|
+
const totalAmountPaise = paidPayments.reduce((sum, p) => sum + (Number(p.amount) || 0), 0);
|
|
89
|
+
const paymentData = {
|
|
90
|
+
total: payments.length,
|
|
91
|
+
paid: paidPayments.length,
|
|
92
|
+
totalAmountPaise,
|
|
93
|
+
recent: payments.slice(0, 10).map(p => ({
|
|
94
|
+
id: p.id,
|
|
95
|
+
planId: p.plan_id,
|
|
96
|
+
amount: p.amount,
|
|
97
|
+
currency: p.currency || 'INR',
|
|
98
|
+
status: p.status,
|
|
99
|
+
createdAt: p.created_at,
|
|
100
|
+
})),
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// API Keys
|
|
104
|
+
const activeKeys = apiKeys.filter(k => k.is_active);
|
|
105
|
+
const apiKeyData = {
|
|
106
|
+
total: apiKeys.length,
|
|
107
|
+
active: activeKeys.length,
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// AI Providers (filter credentials by AI provider types)
|
|
111
|
+
const aiCreds = credentials.filter(c => AI_PROVIDER_TYPES.includes(c.credential_type));
|
|
112
|
+
const activeAiCreds = aiCreds.filter(c => c.is_active);
|
|
113
|
+
const aiProviderData = {
|
|
114
|
+
total: aiCreds.length,
|
|
115
|
+
active: activeAiCreds.length,
|
|
116
|
+
providers: activeAiCreds.map(c => PROVIDER_LABELS[c.credential_type] || c.credential_type),
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Relay Tokens
|
|
120
|
+
const activeTokens = relayTokens.filter(t => t.is_active);
|
|
121
|
+
const lastConnected = relayTokens
|
|
122
|
+
.filter(t => t.last_connected)
|
|
123
|
+
.sort((a, b) => new Date(b.last_connected) - new Date(a.last_connected))[0]?.last_connected || null;
|
|
124
|
+
const relayData = {
|
|
125
|
+
total: relayTokens.length,
|
|
126
|
+
active: activeTokens.length,
|
|
127
|
+
lastConnected,
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// Webhooks
|
|
131
|
+
const activeWebhooks = webhooks.filter(w => w.is_active);
|
|
132
|
+
const webhookData = {
|
|
133
|
+
total: webhooks.length,
|
|
134
|
+
active: activeWebhooks.length,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// Workflows
|
|
138
|
+
const activeWorkflows = workflows.filter(w => w.is_active);
|
|
139
|
+
const workflowData = {
|
|
140
|
+
total: workflows.length,
|
|
141
|
+
active: activeWorkflows.length,
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
res.json({
|
|
145
|
+
account,
|
|
146
|
+
subscription,
|
|
147
|
+
payments: paymentData,
|
|
148
|
+
apiKeys: apiKeyData,
|
|
149
|
+
aiProviders: aiProviderData,
|
|
150
|
+
relayTokens: relayData,
|
|
151
|
+
webhooks: webhookData,
|
|
152
|
+
workflows: workflowData,
|
|
153
|
+
});
|
|
154
|
+
} catch (error) {
|
|
155
|
+
res.status(500).json({ error: 'Failed to fetch user stats' });
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
6
159
|
/**
|
|
7
|
-
* GET /api/dashboard/stats — Dashboard usage analytics
|
|
160
|
+
* GET /api/dashboard/stats — Dashboard usage analytics (local projects)
|
|
8
161
|
* Returns session counts, provider breakdown, and today's activity.
|
|
9
162
|
*/
|
|
10
163
|
router.get('/stats', async (req, res) => {
|