add plugins
All checks were successful
Build Multi-Platform Binaries / build (push) Successful in 11m9s

This commit is contained in:
Flik
2025-12-26 11:24:23 +08:00
parent d56fdafc1e
commit 4623a7f031
27 changed files with 2090 additions and 97 deletions

168
pkg/plugin/store/sqlite.go Normal file
View File

@@ -0,0 +1,168 @@
package store
import (
"database/sql"
"encoding/json"
"fmt"
"sync"
"time"
"github.com/gotunnel/pkg/plugin"
_ "modernc.org/sqlite"
)
// SQLiteStore SQLite 实现的 PluginStore
type SQLiteStore struct {
db *sql.DB
mu sync.RWMutex
}
// NewSQLiteStore 创建 SQLite plugin 存储
func NewSQLiteStore(dbPath string) (*SQLiteStore, error) {
db, err := sql.Open("sqlite", dbPath)
if err != nil {
return nil, err
}
store := &SQLiteStore{db: db}
if err := store.init(); err != nil {
db.Close()
return nil, err
}
return store, nil
}
// init 初始化数据库表
func (s *SQLiteStore) init() error {
query := `
CREATE TABLE IF NOT EXISTS plugins (
name TEXT PRIMARY KEY,
version TEXT NOT NULL,
type TEXT NOT NULL DEFAULT 'proxy',
source TEXT NOT NULL DEFAULT 'wasm',
description TEXT,
author TEXT,
checksum TEXT NOT NULL,
size INTEGER NOT NULL,
capabilities TEXT NOT NULL DEFAULT '[]',
config_schema TEXT NOT NULL DEFAULT '{}',
wasm_data BLOB NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)`
_, err := s.db.Exec(query)
return err
}
// GetAllPlugins 返回所有存储的 plugins
func (s *SQLiteStore) GetAllPlugins() ([]plugin.PluginMetadata, error) {
s.mu.RLock()
defer s.mu.RUnlock()
rows, err := s.db.Query(`
SELECT name, version, type, source, description, author,
checksum, size, capabilities, config_schema
FROM plugins`)
if err != nil {
return nil, err
}
defer rows.Close()
var plugins []plugin.PluginMetadata
for rows.Next() {
var m plugin.PluginMetadata
var capJSON, configJSON string
err := rows.Scan(&m.Name, &m.Version, &m.Type, &m.Source,
&m.Description, &m.Author, &m.Checksum, &m.Size,
&capJSON, &configJSON)
if err != nil {
return nil, err
}
json.Unmarshal([]byte(capJSON), &m.Capabilities)
json.Unmarshal([]byte(configJSON), &m.ConfigSchema)
plugins = append(plugins, m)
}
return plugins, rows.Err()
}
// GetPlugin 返回指定 plugin 的元数据
func (s *SQLiteStore) GetPlugin(name string) (*plugin.PluginMetadata, error) {
s.mu.RLock()
defer s.mu.RUnlock()
var m plugin.PluginMetadata
var capJSON, configJSON string
err := s.db.QueryRow(`
SELECT name, version, type, source, description, author,
checksum, size, capabilities, config_schema
FROM plugins WHERE name = ?`, name).Scan(
&m.Name, &m.Version, &m.Type, &m.Source,
&m.Description, &m.Author, &m.Checksum, &m.Size,
&capJSON, &configJSON)
if err == sql.ErrNoRows {
return nil, nil
}
if err != nil {
return nil, err
}
json.Unmarshal([]byte(capJSON), &m.Capabilities)
json.Unmarshal([]byte(configJSON), &m.ConfigSchema)
return &m, nil
}
// GetPluginData 返回 WASM 二进制
func (s *SQLiteStore) GetPluginData(name string) ([]byte, error) {
s.mu.RLock()
defer s.mu.RUnlock()
var data []byte
err := s.db.QueryRow(`SELECT wasm_data FROM plugins WHERE name = ?`, name).Scan(&data)
if err == sql.ErrNoRows {
return nil, fmt.Errorf("plugin %s not found", name)
}
return data, err
}
// SavePlugin 存储 plugin
func (s *SQLiteStore) SavePlugin(metadata plugin.PluginMetadata, wasmData []byte) error {
s.mu.Lock()
defer s.mu.Unlock()
capJSON, _ := json.Marshal(metadata.Capabilities)
configJSON, _ := json.Marshal(metadata.ConfigSchema)
_, err := s.db.Exec(`
INSERT OR REPLACE INTO plugins
(name, version, type, source, description, author, checksum, size,
capabilities, config_schema, wasm_data, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
metadata.Name, metadata.Version, metadata.Type, metadata.Source,
metadata.Description, metadata.Author, metadata.Checksum, metadata.Size,
string(capJSON), string(configJSON), wasmData, time.Now())
return err
}
// DeletePlugin 删除 plugin
func (s *SQLiteStore) DeletePlugin(name string) error {
s.mu.Lock()
defer s.mu.Unlock()
_, err := s.db.Exec(`DELETE FROM plugins WHERE name = ?`, name)
return err
}
// PluginExists 检查 plugin 是否存在
func (s *SQLiteStore) PluginExists(name string) (bool, error) {
s.mu.RLock()
defer s.mu.RUnlock()
var count int
err := s.db.QueryRow(`SELECT COUNT(*) FROM plugins WHERE name = ?`, name).Scan(&count)
return count > 0, err
}
// Close 关闭存储
func (s *SQLiteStore) Close() error {
return s.db.Close()
}