@alstar/studio 0.0.0-beta.10 → 0.0.0-beta.12
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/api/api-key.ts +37 -49
- package/api/auth.ts +64 -0
- package/api/backup.ts +39 -28
- package/api/block.ts +80 -119
- package/api/index.ts +17 -10
- package/api/mcp.ts +39 -42
- package/components/AdminPanel.ts +29 -4
- package/components/BlockFieldRenderer.ts +20 -4
- package/components/Entries.ts +7 -3
- package/components/FieldRenderer.ts +1 -1
- package/components/Settings.ts +5 -93
- package/components/SiteLayout.ts +11 -9
- package/components/fields/Markdown.ts +1 -1
- package/components/fields/Slug.ts +122 -0
- package/components/fields/Text.ts +20 -4
- package/components/fields/index.ts +4 -1
- package/components/icons.ts +55 -0
- package/components/settings/ApiKeys.ts +122 -0
- package/components/settings/Backup.ts +82 -0
- package/components/settings/Users.ts +63 -0
- package/index.ts +51 -11
- package/package.json +6 -3
- package/pages/entry/[id].ts +1 -3
- package/pages/error.ts +14 -0
- package/pages/index.ts +1 -1
- package/pages/login.ts +21 -0
- package/pages/register.ts +33 -0
- package/pages/settings.ts +1 -3
- package/public/studio/css/settings.css +7 -15
- package/public/studio/js/markdown-editor.js +1 -1
- package/public/studio/js/sortable-list.js +1 -1
- package/public/studio/main.css +5 -1
- package/public/studio/main.js +13 -0
- package/queries/block-2.ts +339 -0
- package/queries/getBlockTrees-2.ts +71 -0
- package/queries/index.ts +1 -1
- package/readme.md +2 -2
- package/schema.sql +18 -0
- package/schemas.ts +11 -1
- package/types.ts +11 -0
- package/utils/auth.ts +54 -0
- package/utils/create-hash.ts +9 -0
- package/utils/define.ts +1 -3
- package/utils/renderSSE.ts +27 -0
- package/utils/slugify.ts +3 -1
- package/utils/startup-log.ts +15 -6
- package/components/Backup.ts +0 -10
- package/utils/build-structure-path.ts +0 -43
package/api/api-key.ts
CHANGED
|
@@ -4,70 +4,58 @@ import { Hono } from 'hono'
|
|
|
4
4
|
import { streamSSE } from 'hono/streaming'
|
|
5
5
|
import { db } from '@alstar/db'
|
|
6
6
|
import crypto from 'node:crypto'
|
|
7
|
-
|
|
8
|
-
import { stripNewlines } from '../utils/strip-newlines.ts'
|
|
9
7
|
import { sql } from '../utils/sql.ts'
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
export default () => {
|
|
13
|
-
const app = new Hono<{ Bindings: HttpBindings }>()
|
|
14
|
-
|
|
15
|
-
app.post('/api-key', async (c) => {
|
|
16
|
-
return streamSSE(c, async (stream) => {
|
|
17
|
-
const formData = await c.req.formData()
|
|
18
|
-
const data = Object.fromEntries(formData.entries())
|
|
8
|
+
import { createHash } from '../utils/create-hash.ts'
|
|
9
|
+
import { renderSSE } from '../utils/renderSSE.ts'
|
|
19
10
|
|
|
20
|
-
|
|
11
|
+
const app = new Hono<{ Bindings: HttpBindings }>()
|
|
21
12
|
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
app.post('/api-key', async (c) => {
|
|
14
|
+
return streamSSE(c, async (stream) => {
|
|
15
|
+
const formData = await c.req.formData()
|
|
16
|
+
const data = Object.fromEntries(formData.entries())
|
|
24
17
|
|
|
25
|
-
|
|
18
|
+
if (!data) return
|
|
26
19
|
|
|
27
|
-
|
|
20
|
+
const apiKey = crypto.randomUUID()
|
|
28
21
|
|
|
29
|
-
|
|
22
|
+
const hash = createHash(apiKey)
|
|
30
23
|
|
|
31
|
-
|
|
32
|
-
name: data.name?.toString(),
|
|
33
|
-
value: digest,
|
|
34
|
-
hint: `${apiKey.substring(0, 8)}-${xs(4)}-${xs(4)}-${xs(4)}-${xs(12)}`,
|
|
35
|
-
})
|
|
24
|
+
const xs = (length: number) => '*'.repeat(length)
|
|
36
25
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
})
|
|
26
|
+
db.insertInto('api_keys', {
|
|
27
|
+
name: data.name?.toString(),
|
|
28
|
+
value: hash,
|
|
29
|
+
hint: `${apiKey.substring(0, 8)}-${xs(4)}-${xs(4)}-${xs(4)}-${xs(12)}`,
|
|
30
|
+
})
|
|
41
31
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
})
|
|
32
|
+
await stream.writeSSE({
|
|
33
|
+
event: 'datastar-patch-signals',
|
|
34
|
+
data: `signals { apiKey: '${apiKey}', name: '' }`,
|
|
46
35
|
})
|
|
36
|
+
|
|
37
|
+
await renderSSE(stream, c)
|
|
47
38
|
})
|
|
39
|
+
})
|
|
48
40
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
41
|
+
app.delete('/api-key', async (c) => {
|
|
42
|
+
return streamSSE(c, async (stream) => {
|
|
43
|
+
const formData = await c.req.formData()
|
|
52
44
|
|
|
53
|
-
|
|
45
|
+
const value = formData.get('value')?.toString()
|
|
54
46
|
|
|
55
|
-
|
|
47
|
+
if (!value) return
|
|
56
48
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
49
|
+
db.database
|
|
50
|
+
.prepare(sql`
|
|
51
|
+
delete from api_keys
|
|
52
|
+
where
|
|
53
|
+
value = ?
|
|
54
|
+
`)
|
|
55
|
+
.run(value)
|
|
64
56
|
|
|
65
|
-
|
|
66
|
-
event: 'datastar-patch-elements',
|
|
67
|
-
data: `elements ${stripNewlines(Settings())}`,
|
|
68
|
-
})
|
|
69
|
-
})
|
|
57
|
+
await renderSSE(stream, c)
|
|
70
58
|
})
|
|
59
|
+
})
|
|
71
60
|
|
|
72
|
-
|
|
73
|
-
}
|
|
61
|
+
export const apiKeyRoutes = app
|
package/api/auth.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type HttpBindings } from '@hono/node-server'
|
|
2
|
+
import { Hono } from 'hono'
|
|
3
|
+
import { createHash } from '../utils/create-hash.ts'
|
|
4
|
+
import { db } from '@alstar/db'
|
|
5
|
+
import { streamSSE } from 'hono/streaming'
|
|
6
|
+
import { sql } from '../utils/sql.ts'
|
|
7
|
+
import { setCookie } from 'hono/cookie'
|
|
8
|
+
|
|
9
|
+
const app = new Hono<{ Bindings: HttpBindings }>()
|
|
10
|
+
|
|
11
|
+
app.post('/register', async (c) => {
|
|
12
|
+
return streamSSE(c, async (stream) => {
|
|
13
|
+
const formData = await c.req.formData()
|
|
14
|
+
const data = Object.fromEntries(formData.entries())
|
|
15
|
+
|
|
16
|
+
if (!data || !data.email || !data.password) return
|
|
17
|
+
|
|
18
|
+
const hash = createHash(data.password.toString())
|
|
19
|
+
|
|
20
|
+
db.insertInto('users', {
|
|
21
|
+
email: data.email?.toString(),
|
|
22
|
+
hash: hash,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
await stream.writeSSE({
|
|
26
|
+
event: 'datastar-patch-signals',
|
|
27
|
+
data: `signals { status: 200, message: 'User "${data.email}" created successfully' }`,
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
app.post('/login', async (c) => {
|
|
33
|
+
const formData = await c.req.formData()
|
|
34
|
+
const data = Object.fromEntries(formData.entries())
|
|
35
|
+
|
|
36
|
+
if (!data || !data.email || !data.password) return
|
|
37
|
+
|
|
38
|
+
const user = db.database
|
|
39
|
+
.prepare(sql`
|
|
40
|
+
select
|
|
41
|
+
*
|
|
42
|
+
from
|
|
43
|
+
users
|
|
44
|
+
where
|
|
45
|
+
email = ?
|
|
46
|
+
`)
|
|
47
|
+
.get(data.email.toString())
|
|
48
|
+
|
|
49
|
+
if (!user) {
|
|
50
|
+
return c.json({ status: 404, message: 'No user with that email' })
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const passwordHash = createHash(data.password.toString())
|
|
54
|
+
|
|
55
|
+
if (passwordHash !== user.hash) {
|
|
56
|
+
return c.json({ status: 401, message: 'Wrong password' })
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
setCookie(c, 'login', 'yes')
|
|
60
|
+
|
|
61
|
+
return c.redirect('/studio')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
export const authRoutes = app
|
package/api/backup.ts
CHANGED
|
@@ -1,38 +1,49 @@
|
|
|
1
|
-
import
|
|
1
|
+
import fsp from 'node:fs/promises'
|
|
2
|
+
import { backup } from 'node:sqlite'
|
|
3
|
+
|
|
2
4
|
import { Hono } from 'hono'
|
|
5
|
+
import { type HttpBindings } from '@hono/node-server'
|
|
3
6
|
import { streamSSE } from 'hono/streaming'
|
|
4
|
-
import { DatabaseSync } from 'node:sqlite'
|
|
5
|
-
|
|
6
|
-
import { stripNewlines } from '../utils/strip-newlines.ts'
|
|
7
7
|
import { db } from '@alstar/db'
|
|
8
|
+
import { stripNewlines } from '../utils/strip-newlines.ts'
|
|
9
|
+
import Settings from '../components/Settings.ts'
|
|
10
|
+
import path from 'node:path'
|
|
11
|
+
import { renderSSE } from '../utils/renderSSE.ts'
|
|
12
|
+
|
|
13
|
+
const app = new Hono<{ Bindings: HttpBindings }>()
|
|
14
|
+
|
|
15
|
+
app.post('/backup', async (c) => {
|
|
16
|
+
const date = new Date()
|
|
17
|
+
const name = `./backups/backup-${date.toISOString()}.db`
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
fsp.mkdir('./backups', { recursive: true })
|
|
8
21
|
|
|
9
|
-
|
|
10
|
-
const app = new Hono<{ Bindings: HttpBindings }>()
|
|
22
|
+
await backup(db.database, name)
|
|
11
23
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
// })
|
|
24
|
+
return streamSSE(c, async (stream) => await renderSSE(stream, c))
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.log(error)
|
|
27
|
+
return c.json({ status: 500, message: 'Something went wrong' })
|
|
28
|
+
}
|
|
29
|
+
})
|
|
19
30
|
|
|
20
|
-
|
|
31
|
+
app.delete('/backup', async (c) => {
|
|
32
|
+
const formData = await c.req.formData()
|
|
33
|
+
const data = Object.fromEntries(formData.entries())
|
|
21
34
|
|
|
22
|
-
|
|
35
|
+
if (!data.filename) {
|
|
36
|
+
return c.json({ status: 404, message: 'Need a filename to remove' })
|
|
37
|
+
}
|
|
23
38
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
// event: 'datastar-patch-signals',
|
|
27
|
-
// data: `signals {}`,
|
|
28
|
-
// })
|
|
39
|
+
try {
|
|
40
|
+
await fsp.rm(path.join('./backups', data.filename.toString()))
|
|
29
41
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
42
|
+
return streamSSE(c, async (stream) => await renderSSE(stream, c))
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.log(error)
|
|
45
|
+
return c.json({ status: 500, message: 'Something went wrong' })
|
|
46
|
+
}
|
|
47
|
+
})
|
|
36
48
|
|
|
37
|
-
|
|
38
|
-
}
|
|
49
|
+
export const backupRoutes = app
|
package/api/block.ts
CHANGED
|
@@ -2,103 +2,49 @@ import { type HttpBindings } from '@hono/node-server'
|
|
|
2
2
|
import { ServerSentEventGenerator } from '@starfederation/datastar-sdk'
|
|
3
3
|
import { Hono } from 'hono'
|
|
4
4
|
import { streamSSE } from 'hono/streaming'
|
|
5
|
-
import { stripNewlines } from '../utils/strip-newlines.ts'
|
|
6
5
|
import { sql } from '../utils/sql.ts'
|
|
7
|
-
import { type Structure } from '../types.ts'
|
|
8
6
|
import { db } from '@alstar/db'
|
|
9
|
-
import Entry from '../components/Entry.ts'
|
|
10
7
|
import {
|
|
11
8
|
blockWithChildren,
|
|
12
9
|
deleteBlockWithChildren,
|
|
13
10
|
} from '../queries/block-with-children.ts'
|
|
14
|
-
import AdminPanel from '../components/AdminPanel.ts'
|
|
15
11
|
import { query } from '../queries/index.ts'
|
|
12
|
+
import { renderSSE } from '../utils/renderSSE.ts'
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
const app = new Hono<{ Bindings: HttpBindings }>()
|
|
14
|
+
const app = new Hono<{ Bindings: HttpBindings }>()
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
app.post('/block', async (c) => {
|
|
17
|
+
return streamSSE(c, async (stream) => {
|
|
18
|
+
const formData = await c.req.formData()
|
|
19
|
+
const data = Object.fromEntries(formData.entries())
|
|
24
20
|
|
|
25
|
-
|
|
21
|
+
const definedData = JSON.parse(
|
|
22
|
+
JSON.stringify({
|
|
23
|
+
type: data.type?.toString(),
|
|
24
|
+
name: data.name?.toString(),
|
|
25
|
+
label: data.label?.toString(),
|
|
26
|
+
parent_id: data.parent_id?.toString(),
|
|
27
|
+
sort_order: data.sort_order?.toString(),
|
|
28
|
+
}),
|
|
29
|
+
)
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
db.insertInto('blocks', definedData)
|
|
28
32
|
|
|
29
|
-
|
|
30
|
-
name: data.name?.toString(),
|
|
31
|
-
label: row.label,
|
|
32
|
-
type: row.type,
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
await stream.writeSSE({
|
|
36
|
-
event: 'datastar-patch-elements',
|
|
37
|
-
data: `elements ${stripNewlines(AdminPanel())}`,
|
|
38
|
-
})
|
|
39
|
-
})
|
|
33
|
+
await renderSSE(stream, c)
|
|
40
34
|
})
|
|
35
|
+
})
|
|
41
36
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const data = Object.fromEntries(formData)
|
|
46
|
-
|
|
47
|
-
db.insertInto('blocks', {
|
|
48
|
-
type: data.type.toString(),
|
|
49
|
-
name: data.name.toString(),
|
|
50
|
-
label: data.label.toString(),
|
|
51
|
-
parent_id: data.parent_id.toString(),
|
|
52
|
-
sort_order: data.sort_order.toString(),
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
await stream.writeSSE({
|
|
56
|
-
event: 'datastar-patch-elements',
|
|
57
|
-
data: `elements ${stripNewlines(Entry({ entryId: parseInt(data.entry_id.toString()) }))}`,
|
|
58
|
-
})
|
|
59
|
-
})
|
|
60
|
-
})
|
|
37
|
+
app.patch('/block', async (c) => {
|
|
38
|
+
return streamSSE(c, async (stream) => {
|
|
39
|
+
const formData = await c.req.formData()
|
|
61
40
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const value = formData.get('value')?.toString()
|
|
68
|
-
const name = formData.get('name')?.toString()
|
|
69
|
-
const entryId = formData.get('entryId')?.toString()
|
|
70
|
-
const parentId = formData.get('parentId')?.toString()
|
|
71
|
-
// const sortOrder = formData.get('sort_order')?.toString()
|
|
72
|
-
|
|
73
|
-
if (!id || !value) return
|
|
74
|
-
|
|
75
|
-
const transaction = db.database.prepare(sql`
|
|
76
|
-
update blocks
|
|
77
|
-
set
|
|
78
|
-
value = ?
|
|
79
|
-
where
|
|
80
|
-
id = ?;
|
|
81
|
-
`)
|
|
82
|
-
|
|
83
|
-
transaction.run(value, id)
|
|
84
|
-
|
|
85
|
-
if (entryId === parentId && name?.toString() === 'title') {
|
|
86
|
-
const rootBlock = query.block({
|
|
87
|
-
id: parentId?.toString() || null,
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
if (rootBlock.type !== 'single') {
|
|
91
|
-
await stream.writeSSE({
|
|
92
|
-
event: 'datastar-patch-elements',
|
|
93
|
-
data: `elements <a href="/admin/entry/${entryId}" id="block_link_${entryId}">${value}</a>`,
|
|
94
|
-
})
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
})
|
|
98
|
-
})
|
|
41
|
+
const id = formData.get('id')?.toString()
|
|
42
|
+
const value = formData.get('value')?.toString()
|
|
43
|
+
// const name = formData.get('name')?.toString()
|
|
44
|
+
// const entryId = formData.get('entryId')?.toString()
|
|
45
|
+
// const parentId = formData.get('parentId')?.toString()
|
|
99
46
|
|
|
100
|
-
|
|
101
|
-
const body = await c.req.json()
|
|
47
|
+
if (!id || !value) return
|
|
102
48
|
|
|
103
49
|
const transaction = db.database.prepare(sql`
|
|
104
50
|
update blocks
|
|
@@ -108,56 +54,71 @@ export default (structure: Structure) => {
|
|
|
108
54
|
id = ?;
|
|
109
55
|
`)
|
|
110
56
|
|
|
111
|
-
transaction.run(
|
|
57
|
+
transaction.run(value, id)
|
|
112
58
|
|
|
113
|
-
|
|
59
|
+
await renderSSE(stream, c)
|
|
60
|
+
|
|
61
|
+
// if (entryId === parentId && name?.toString() === 'title') {
|
|
62
|
+
// const rootBlock = query.block({
|
|
63
|
+
// id: parentId?.toString() || null,
|
|
64
|
+
// })
|
|
65
|
+
|
|
66
|
+
// if (rootBlock.type !== 'single') {
|
|
67
|
+
// await stream.writeSSE({
|
|
68
|
+
// event: 'datastar-patch-elements',
|
|
69
|
+
// data: `elements <a href="/studio/entry/${entryId}" id="block_link_${entryId}">${value}</a>`,
|
|
70
|
+
// })
|
|
71
|
+
// }
|
|
72
|
+
// }
|
|
114
73
|
})
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
app.patch('/value', async (c) => {
|
|
77
|
+
const body = await c.req.json()
|
|
115
78
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
79
|
+
const transaction = db.database.prepare(sql`
|
|
80
|
+
update blocks
|
|
81
|
+
set
|
|
82
|
+
value = ?
|
|
83
|
+
where
|
|
84
|
+
id = ?;
|
|
85
|
+
`)
|
|
119
86
|
|
|
120
|
-
|
|
121
|
-
const entryId = formData.get('entry_id')?.toString()
|
|
87
|
+
transaction.run(body.value, body.id)
|
|
122
88
|
|
|
123
|
-
|
|
89
|
+
return c.json({ status: 200, message: 'success' })
|
|
90
|
+
})
|
|
124
91
|
|
|
125
|
-
|
|
92
|
+
app.delete('/block', async (c) => {
|
|
93
|
+
return streamSSE(c, async (stream) => {
|
|
94
|
+
const formData = await c.req.formData()
|
|
95
|
+
const id = formData.get('id')?.toString()
|
|
126
96
|
|
|
127
|
-
|
|
97
|
+
if (!id) return
|
|
128
98
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
data: `elements ${stripNewlines(Entry({ entryId: parseInt(entryId.toString()) }))}`,
|
|
133
|
-
})
|
|
134
|
-
} else {
|
|
135
|
-
await stream.writeSSE({
|
|
136
|
-
event: 'datastar-patch-elements',
|
|
137
|
-
data: `elements ${stripNewlines(AdminPanel())}`,
|
|
138
|
-
})
|
|
139
|
-
}
|
|
140
|
-
})
|
|
99
|
+
db.database.prepare(deleteBlockWithChildren).all(id)
|
|
100
|
+
|
|
101
|
+
await renderSSE(stream, c)
|
|
141
102
|
})
|
|
103
|
+
})
|
|
142
104
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
105
|
+
app.post('/sort-order', async (c) => {
|
|
106
|
+
const id = c.req.query('id')
|
|
107
|
+
const sortOrder = c.req.query('sort-order')
|
|
146
108
|
|
|
147
|
-
|
|
109
|
+
if (!id || !sortOrder) return
|
|
148
110
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
111
|
+
const transaction = db.database.prepare(sql`
|
|
112
|
+
update blocks
|
|
113
|
+
set
|
|
114
|
+
sort_order = ?
|
|
115
|
+
where
|
|
116
|
+
id = ?
|
|
117
|
+
`)
|
|
156
118
|
|
|
157
|
-
|
|
119
|
+
transaction.run(sortOrder, id)
|
|
158
120
|
|
|
159
|
-
|
|
160
|
-
|
|
121
|
+
return c.json({ status: 200, message: 'success' })
|
|
122
|
+
})
|
|
161
123
|
|
|
162
|
-
|
|
163
|
-
}
|
|
124
|
+
export const blockRoutes = app
|
package/api/index.ts
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
import apiKey from './api-key.ts'
|
|
3
|
-
import type { Structure } from '../types.ts'
|
|
4
|
-
import backup from './backup.ts'
|
|
1
|
+
import { Hono } from 'hono'
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
import { blockRoutes } from './block.ts'
|
|
4
|
+
import { apiKeyRoutes } from './api-key.ts'
|
|
5
|
+
import { backupRoutes } from './backup.ts'
|
|
6
|
+
import { authRoutes } from './auth.ts'
|
|
7
|
+
import { fieldRoutes } from '../components/fields/index.ts'
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
app.route('/', backup())
|
|
9
|
+
const routes = new Hono()
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
routes.route('/', blockRoutes)
|
|
12
|
+
routes.route('/', apiKeyRoutes)
|
|
13
|
+
routes.route('/', backupRoutes)
|
|
14
|
+
routes.route('/auth', authRoutes)
|
|
15
|
+
|
|
16
|
+
fieldRoutes.forEach((fieldRoute) => {
|
|
17
|
+
routes.route('/field', fieldRoute)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
export const apiRoutes = routes
|
package/api/mcp.ts
CHANGED
|
@@ -1,53 +1,50 @@
|
|
|
1
1
|
import { type HttpBindings } from '@hono/node-server'
|
|
2
|
-
import { ServerSentEventGenerator } from '@starfederation/datastar-sdk'
|
|
3
2
|
import { Hono } from 'hono'
|
|
4
3
|
import { sql } from '../utils/sql.ts'
|
|
5
4
|
import { db } from '@alstar/db'
|
|
6
5
|
import { bearerAuth } from 'hono/bearer-auth'
|
|
7
6
|
import crypto from 'node:crypto'
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
message: 'Response from MCP server!',
|
|
42
|
-
})
|
|
8
|
+
const app = new Hono<{ Bindings: HttpBindings }>()
|
|
9
|
+
|
|
10
|
+
app.use(
|
|
11
|
+
'/*',
|
|
12
|
+
bearerAuth({
|
|
13
|
+
verifyToken: async (token, c) => {
|
|
14
|
+
const hash = crypto.createHash('sha256')
|
|
15
|
+
|
|
16
|
+
hash.update(token)
|
|
17
|
+
|
|
18
|
+
const digest = hash.digest().toString('base64')
|
|
19
|
+
|
|
20
|
+
const exists = db.database
|
|
21
|
+
.prepare(sql`
|
|
22
|
+
select
|
|
23
|
+
value
|
|
24
|
+
from
|
|
25
|
+
api_keys
|
|
26
|
+
where
|
|
27
|
+
value = ?
|
|
28
|
+
`)
|
|
29
|
+
.get(digest)
|
|
30
|
+
|
|
31
|
+
return !!exists
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
app.get('/entry', async (c) => {
|
|
37
|
+
return c.json({
|
|
38
|
+
status: 'success',
|
|
39
|
+
message: 'Response from MCP server!',
|
|
43
40
|
})
|
|
41
|
+
})
|
|
44
42
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
})
|
|
43
|
+
app.post('/entry', async (c) => {
|
|
44
|
+
return c.json({
|
|
45
|
+
status: 'success',
|
|
46
|
+
message: 'New entry created!',
|
|
50
47
|
})
|
|
48
|
+
})
|
|
51
49
|
|
|
52
|
-
|
|
53
|
-
}
|
|
50
|
+
export const mcpRoutes = app
|