writekit/studio/src/stores/plugins.ts

103 lines
3.3 KiB
TypeScript
Raw Normal View History

2026-01-09 00:16:46 +02:00
import { atom, map } from 'nanostores'
import { createFetcherStore, createMutatorStore } from './fetcher'
export interface Plugin {
id: string
name: string
language: 'typescript' | 'go'
source: string
hooks: string[]
enabled: boolean
wasm?: string
wasm_size?: number
created_at: string
updated_at: string
}
export interface CompileResult {
success: boolean
wasm?: string
size?: number
errors?: string[]
time_ms?: number
}
export const $plugins = createFetcherStore<Plugin[]>(['/api/studio/plugins'])
export const $currentPlugin = map<Partial<Plugin>>({
name: '',
language: 'typescript',
source: '',
hooks: [],
enabled: true,
})
export const $compileResult = atom<CompileResult | null>(null)
export const $isCompiling = atom(false)
export const $savePlugin = createMutatorStore(async ({ data, invalidate }: { data: Plugin; invalidate: (key: string) => void }) => {
const res = await fetch('/api/studio/plugins', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
if (!res.ok) throw new Error('Failed to save plugin')
invalidate('/api/studio/plugins')
return res.json()
})
export const $deletePlugin = createMutatorStore(async ({ data: id, invalidate }: { data: string; invalidate: (key: string) => void }) => {
const res = await fetch(`/api/studio/plugins/${id}`, { method: 'DELETE' })
if (!res.ok) throw new Error('Failed to delete plugin')
invalidate('/api/studio/plugins')
})
export const $togglePlugin = createMutatorStore(async ({ data, invalidate }: { data: { id: string; enabled: boolean }; invalidate: (key: string) => void }) => {
const res = await fetch(`/api/studio/plugins/${data.id}/toggle`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ enabled: data.enabled }),
})
if (!res.ok) throw new Error('Failed to toggle plugin')
invalidate('/api/studio/plugins')
})
export async function compilePlugin(language: string, source: string): Promise<CompileResult> {
$isCompiling.set(true)
$compileResult.set(null)
try {
const res = await fetch('/api/studio/plugins/compile', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ language, source }),
})
const result = await res.json()
$compileResult.set(result)
return result
} finally {
$isCompiling.set(false)
}
}
export async function testPlugin(pluginId: string, hook: string, testData: object): Promise<any> {
const res = await fetch(`/api/studio/plugins/${pluginId}/test`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ hook, data: testData }),
})
return res.json()
}
export const AVAILABLE_HOOKS = [
{ value: 'post.published', label: 'Post Published', description: 'Triggered when a post is published' },
{ value: 'post.updated', label: 'Post Updated', description: 'Triggered when a published post is updated' },
{ value: 'comment.created', label: 'Comment Created', description: 'Triggered when a new comment is posted' },
{ value: 'subscriber.created', label: 'Subscriber Created', description: 'Triggered when someone subscribes' },
]
export const LANGUAGES = [
{ value: 'typescript', label: 'TypeScript', extension: '.ts' },
{ value: 'go', label: 'Go', extension: '.go' },
]