Skip to content

Commit 7ad4426

Browse files
chore: wip
1 parent 103fabf commit 7ad4426

File tree

19 files changed

+1881
-0
lines changed

19 files changed

+1881
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Action } from '@stacksjs/actions'
2+
import { errors } from '@stacksjs/commerce'
3+
import { response } from '@stacksjs/router'
4+
5+
export default new Action({
6+
name: 'Error Destroy',
7+
description: 'Delete all errors in a group',
8+
method: 'DELETE',
9+
async handle(request: any) {
10+
const type = decodeURIComponent(request.query.type || '')
11+
const message = decodeURIComponent(request.query.message || '')
12+
13+
if (!type || !message) {
14+
return response.json({ error: 'Both type and message are required' }, 400)
15+
}
16+
17+
const success = await errors.destroyGroup(type, message)
18+
19+
if (!success) {
20+
return response.json({ error: 'Failed to delete errors' }, 500)
21+
}
22+
23+
return response.json({ data: { success: true, message: 'Errors deleted successfully' } })
24+
},
25+
})
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Action } from '@stacksjs/actions'
2+
import { errors } from '@stacksjs/commerce'
3+
import { response } from '@stacksjs/router'
4+
5+
export default new Action({
6+
name: 'Error Group',
7+
description: 'Fetch all errors in a specific group (by type and message)',
8+
method: 'GET',
9+
async handle(request: any) {
10+
const type = decodeURIComponent(request.query.type || '')
11+
const message = decodeURIComponent(request.query.message || '')
12+
13+
if (!type || !message) {
14+
return response.json({ error: 'Both type and message are required' }, 400)
15+
}
16+
17+
const results = await errors.fetchByGroup(type, message)
18+
19+
return response.json({ data: results })
20+
},
21+
})
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Action } from '@stacksjs/actions'
2+
import { errors } from '@stacksjs/commerce'
3+
import { response } from '@stacksjs/router'
4+
5+
export default new Action({
6+
name: 'Error Ignore',
7+
description: 'Ignore all errors in a group',
8+
method: 'PATCH',
9+
async handle(request: any) {
10+
const { type, message } = request.body || {}
11+
12+
if (!type || !message) {
13+
return response.json({ error: 'Both type and message are required' }, 400)
14+
}
15+
16+
const success = await errors.ignoreGroup(type, message)
17+
18+
if (!success) {
19+
return response.json({ error: 'Failed to ignore errors' }, 500)
20+
}
21+
22+
return response.json({ data: { success: true, message: 'Errors ignored successfully' } })
23+
},
24+
})
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Action } from '@stacksjs/actions'
2+
import { errors } from '@stacksjs/commerce'
3+
import { response } from '@stacksjs/router'
4+
5+
export default new Action({
6+
name: 'Error Index',
7+
description: 'Fetch all grouped errors (Sentry-like aggregation)',
8+
method: 'GET',
9+
async handle() {
10+
const results = await errors.fetchGrouped()
11+
12+
return response.json({ data: results })
13+
},
14+
})
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Action } from '@stacksjs/actions'
2+
import { errors } from '@stacksjs/commerce'
3+
import { response } from '@stacksjs/router'
4+
5+
export default new Action({
6+
name: 'Error Resolve',
7+
description: 'Resolve all errors in a group',
8+
method: 'PATCH',
9+
async handle(request: any) {
10+
const { type, message } = request.body || {}
11+
12+
if (!type || !message) {
13+
return response.json({ error: 'Both type and message are required' }, 400)
14+
}
15+
16+
const success = await errors.resolveGroup(type, message)
17+
18+
if (!success) {
19+
return response.json({ error: 'Failed to resolve errors' }, 500)
20+
}
21+
22+
return response.json({ data: { success: true, message: 'Errors resolved successfully' } })
23+
},
24+
})
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Action } from '@stacksjs/actions'
2+
import { errors } from '@stacksjs/commerce'
3+
import { response } from '@stacksjs/router'
4+
5+
export default new Action({
6+
name: 'Error Show',
7+
description: 'Fetch a single error by ID',
8+
method: 'GET',
9+
async handle(request: any) {
10+
const id = Number(request.params.id)
11+
const result = await errors.fetchById(id)
12+
13+
if (!result) {
14+
return response.json({ error: 'Error not found' }, 404)
15+
}
16+
17+
return response.json({ data: result })
18+
},
19+
})
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Action } from '@stacksjs/actions'
2+
import { errors } from '@stacksjs/commerce'
3+
import { response } from '@stacksjs/router'
4+
5+
export default new Action({
6+
name: 'Error Stats',
7+
description: 'Fetch error statistics',
8+
method: 'GET',
9+
async handle() {
10+
const stats = await errors.fetchStats()
11+
12+
return response.json({ data: stats })
13+
},
14+
})
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Action } from '@stacksjs/actions'
2+
import { errors } from '@stacksjs/commerce'
3+
import { response } from '@stacksjs/router'
4+
5+
export default new Action({
6+
name: 'Error Timeline',
7+
description: 'Fetch error timeline (hourly counts for last 24 hours)',
8+
method: 'GET',
9+
async handle() {
10+
const timeline = await errors.fetchTimeline()
11+
12+
return response.json({ data: timeline })
13+
},
14+
})
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Action } from '@stacksjs/actions'
2+
import { errors } from '@stacksjs/commerce'
3+
import { response } from '@stacksjs/router'
4+
5+
export default new Action({
6+
name: 'Error Unresolve',
7+
description: 'Unresolve (reopen) all errors in a group',
8+
method: 'PATCH',
9+
async handle(request: any) {
10+
const { type, message } = request.body || {}
11+
12+
if (!type || !message) {
13+
return response.json({ error: 'Both type and message are required' }, 400)
14+
}
15+
16+
const success = await errors.unresolveGroup(type, message)
17+
18+
if (!success) {
19+
return response.json({ error: 'Failed to unresolve errors' }, 500)
20+
}
21+
22+
return response.json({ data: { success: true, message: 'Errors unresolved successfully' } })
23+
},
24+
})

routes/api.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,3 +289,17 @@ route.group({ prefix: '/queries' }, async () => {
289289
})
290290

291291
route.get('/me', 'Actions/Auth/AuthUserAction').middleware('auth')
292+
293+
// Error Tracking / Monitoring routes
294+
route.group({ prefix: '/monitoring' }, async () => {
295+
// Errors
296+
route.get('/errors', 'Actions/Monitoring/ErrorIndexAction')
297+
route.get('/errors/stats', 'Actions/Monitoring/ErrorStatsAction')
298+
route.get('/errors/timeline', 'Actions/Monitoring/ErrorTimelineAction')
299+
route.get('/errors/group', 'Actions/Monitoring/ErrorGroupAction')
300+
route.get('/errors/{id}', 'Actions/Monitoring/ErrorShowAction')
301+
route.patch('/errors/resolve', 'Actions/Monitoring/ErrorResolveAction')
302+
route.patch('/errors/ignore', 'Actions/Monitoring/ErrorIgnoreAction')
303+
route.patch('/errors/unresolve', 'Actions/Monitoring/ErrorUnresolveAction')
304+
route.delete('/errors', 'Actions/Monitoring/ErrorDestroyAction')
305+
})

0 commit comments

Comments
 (0)