Refactor DSL management by introducing IO interfaces for database and file system operations

- Removed the db.go and fs.go files, consolidating database and file system interactions into a unified IO interface.
- Updated DSL struct to include db and fs fields for improved separation of concerns.
- Refactored existing methods across various DSL managers (API, Connector, MCP, Model) to utilize the new IO interfaces for operations like Inspect, Create, Update, Delete, and List.
- Enhanced error handling and validation in Create, Update, and Delete methods to ensure robust functionality.
- Updated types to include new options for Load, Unload, and Reload operations, improving flexibility and usability.
This commit is contained in:
Max 2025-07-15 12:25:56 +08:00
parent 06f5134083
commit 62e20a90ea
10 changed files with 315 additions and 174 deletions

View file

@ -9,11 +9,13 @@ import (
// YaoAPI is the MCP client DSL manager
type YaoAPI struct {
root string // The relative path of the MCP client DSL
fs types.IO // The file system IO interface
db types.IO // The database IO interface
}
// New returns a new connector DSL manager
func New(root string) types.Manager {
return &YaoAPI{root: root}
func New(root string, fs types.IO, db types.IO) types.Manager {
return &YaoAPI{root: root, fs: fs, db: db}
}
// Loaded return all loaded DSLs
@ -22,17 +24,17 @@ func (api *YaoAPI) Loaded(ctx context.Context) (map[string]*types.Info, error) {
}
// Load will unload the DSL first, then load the DSL from DB or file system
func (api *YaoAPI) Load(ctx context.Context, id string, options interface{}) error {
func (api *YaoAPI) Load(ctx context.Context, options *types.LoadOptions) error {
return nil
}
// Reload will unload the DSL first, then reload the DSL from DB or file system
func (api *YaoAPI) Reload(ctx context.Context, id string, options interface{}) error {
func (api *YaoAPI) Reload(ctx context.Context, options *types.ReloadOptions) error {
return nil
}
// Unload will unload the DSL from memory
func (api *YaoAPI) Unload(ctx context.Context, id string, options interface{}) error {
func (api *YaoAPI) Unload(ctx context.Context, options *types.UnloadOptions) error {
return nil
}
@ -42,6 +44,6 @@ func (api *YaoAPI) Validate(ctx context.Context, source string) (bool, []types.L
}
// Execute will execute the DSL
func (api *YaoAPI) Execute(ctx context.Context, method string, args ...any) (any, error) {
func (api *YaoAPI) Execute(ctx context.Context, id string, method string, args ...any) (any, error) {
return nil, nil
}

View file

@ -9,11 +9,13 @@ import (
// YaoConnector is the connector DSL manager
type YaoConnector struct {
root string // The relative path of the connector DSL
fs types.IO // The file system IO interface
db types.IO // The database IO interface
}
// New returns a new connector DSL manager
func New(root string) types.Manager {
return &YaoConnector{root: root}
func New(root string, fs types.IO, db types.IO) types.Manager {
return &YaoConnector{root: root, fs: fs, db: db}
}
// Loaded return all loaded DSLs
@ -22,17 +24,17 @@ func (c *YaoConnector) Loaded(ctx context.Context) (map[string]*types.Info, erro
}
// Load will unload the DSL first, then load the DSL from DB or file system
func (c *YaoConnector) Load(ctx context.Context, id string, options interface{}) error {
func (c *YaoConnector) Load(ctx context.Context, options *types.LoadOptions) error {
return nil
}
// Unload will unload the DSL from memory
func (c *YaoConnector) Unload(ctx context.Context, id string, options interface{}) error {
func (c *YaoConnector) Unload(ctx context.Context, options *types.UnloadOptions) error {
return nil
}
// Reload will unload the DSL first, then reload the DSL from DB or file system
func (c *YaoConnector) Reload(ctx context.Context, id string, options interface{}) error {
func (c *YaoConnector) Reload(ctx context.Context, options *types.ReloadOptions) error {
return nil
}
@ -42,6 +44,6 @@ func (c *YaoConnector) Validate(ctx context.Context, source string) (bool, []typ
}
// Execute will execute the DSL
func (c *YaoConnector) Execute(ctx context.Context, method string, args ...any) (any, error) {
func (c *YaoConnector) Execute(ctx context.Context, id string, method string, args ...any) (any, error) {
return nil, nil
}

View file

@ -6,6 +6,7 @@ import (
"github.com/yaoapp/yao/dsl/api"
"github.com/yaoapp/yao/dsl/connector"
"github.com/yaoapp/yao/dsl/io"
"github.com/yaoapp/yao/dsl/mcp"
"github.com/yaoapp/yao/dsl/model"
"github.com/yaoapp/yao/dsl/types"
@ -17,11 +18,15 @@ type DSL struct {
exts []string
root string
manager types.Manager
db types.IO
fs types.IO
}
// New returns a new DSL manager
func New(typ types.Type) (types.DSL, error) {
var manager types.Manager
var db types.IO = io.NewDB(typ)
var fs types.IO = io.NewFS(typ)
// Get the root path and the extensions of the type
root, exts := types.TypeRootAndExts(typ)
@ -30,15 +35,15 @@ func New(typ types.Type) (types.DSL, error) {
switch typ {
case types.TypeConnector:
exts = []string{".conn.yao", ".conn.jsonc", ".conn.json"}
manager = connector.New(root)
manager = connector.New(root, fs, db)
case types.TypeModel:
exts = []string{".mod.yao", ".mod.jsonc", ".mod.json"}
manager = model.New(root)
manager = model.New(root, fs, db)
case types.TypeMCPClient:
exts = []string{".mcp.yao", ".mcp.jsonc", ".mcp.json"}
manager = mcp.NewClient(root)
manager = mcp.NewClient(root, fs, db)
// case types.TypeMCPServer:
// exts = []string{".mcp.yao", ".mcp.jsonc", ".mcp.json"}
@ -46,27 +51,27 @@ func New(typ types.Type) (types.DSL, error) {
case types.TypeAPI:
exts = []string{".http.yao", ".http.jsonc", ".http.json"}
manager = api.New(root)
manager = api.New(root, fs, db)
default:
return nil, fmt.Errorf("dsl manager is not initialized, %s not supported", typ)
}
return &DSL{Type: typ, manager: manager, root: root, exts: exts}, nil
return &DSL{Type: typ, manager: manager, root: root, exts: exts, db: db, fs: fs}, nil
}
// Inspect DSL
func (dsl *DSL) Inspect(ctx context.Context, id string) (*types.Info, error) {
// Get the info from the db
info, exists, err := dsl.dbInspect(id)
info, exists, err := dsl.db.Inspect(id)
if err != nil {
return nil, err
}
if !exists {
// Get the info from the file
info, exists, err = dsl.fsInspect(types.ToPath(dsl.Type, id))
info, exists, err = dsl.fs.Inspect(id)
if err != nil {
return nil, err
}
@ -99,14 +104,14 @@ func (dsl *DSL) Path(ctx context.Context, id string) (string, error) {
func (dsl *DSL) Source(ctx context.Context, id string) (string, error) {
// Get the source from the db
source, exists, err := dsl.dbSource(id)
source, exists, err := dsl.db.Source(id)
if err != nil {
return "", err
}
if !exists {
// Get the source from the file
source, exists, err = dsl.fsSource(types.ToPath(dsl.Type, id))
source, exists, err = dsl.fs.Source(id)
if err != nil {
return "", err
}
@ -122,13 +127,13 @@ func (dsl *DSL) Source(ctx context.Context, id string) (string, error) {
// List DSLs
func (dsl *DSL) List(ctx context.Context, opts *types.ListOptions) ([]*types.Info, error) {
// Get the list from the db
dbList, err := dsl.dbList(opts)
dbList, err := dsl.db.List(opts)
if err != nil {
return nil, err
}
// Get the list from the file
fileList, err := dsl.fsList(opts)
fileList, err := dsl.fs.List(opts)
if err != nil {
return nil, err
}
@ -167,22 +172,35 @@ func (dsl *DSL) List(ctx context.Context, opts *types.ListOptions) ([]*types.Inf
// Create DSL
func (dsl *DSL) Create(ctx context.Context, options *types.CreateOptions) error {
if options == nil {
return fmt.Errorf("create options is required")
}
if options.Store == types.StoreTypeDB {
err := dsl.dbCreate(options)
err := dsl.db.Create(options)
if err != nil {
return err
}
}
if options.Store == types.StoreTypeFile {
err := dsl.fsCreate(options)
err := dsl.fs.Create(options)
if err != nil {
return err
}
}
var loadOptions *types.LoadOptions = &types.LoadOptions{
ID: options.ID,
Path: types.ToPath(dsl.Type, options.ID),
Source: options.Source,
Store: options.Store,
Options: options.Load,
}
// Load the DSL
err := dsl.Load(ctx, options.ID, options.LoadOptions)
err := dsl.Load(ctx, loadOptions)
if err != nil {
return err
}
@ -193,7 +211,7 @@ func (dsl *DSL) Create(ctx context.Context, options *types.CreateOptions) error
// Exists Check if the DSL exists
func (dsl *DSL) Exists(ctx context.Context, id string) (bool, error) {
// Check if the DSL exists in the db
exists, err := dsl.dbExists(id)
exists, err := dsl.db.Exists(id)
if err != nil {
return false, err
}
@ -203,20 +221,24 @@ func (dsl *DSL) Exists(ctx context.Context, id string) (bool, error) {
}
// Check if the DSL exists in the file
return dsl.fsExists(id)
return dsl.fs.Exists(id)
}
// Update DSL
func (dsl *DSL) Update(ctx context.Context, options *types.UpdateOptions) error {
if options == nil {
return fmt.Errorf("update options is required")
}
// Exists
info, exists, err := dsl.dbInspect(options.ID)
info, exists, err := dsl.db.Inspect(options.ID)
if err != nil {
return err
}
if !exists {
info, exists, err = dsl.fsInspect(types.ToPath(dsl.Type, options.ID))
info, exists, err = dsl.fs.Inspect(options.ID)
if err != nil {
return err
}
@ -225,92 +247,113 @@ func (dsl *DSL) Update(ctx context.Context, options *types.UpdateOptions) error
}
}
// Create the reload options
var reloadOptions *types.ReloadOptions = &types.ReloadOptions{
ID: options.ID,
Path: info.Path,
Source: options.Source,
Store: info.Store,
Options: options.Reload,
}
// Update the DSL in the db
if info.Store == types.StoreTypeDB {
err := dsl.dbUpdate(options)
err := dsl.db.Update(options)
if err != nil {
return err
}
// Reload the DSL
return dsl.manager.Reload(ctx, options.ID, options.ReloadOptions)
return dsl.manager.Reload(ctx, reloadOptions)
}
// Update the DSL in the file
err = dsl.fsUpdate(options)
err = dsl.fs.Update(options)
if err != nil {
return err
}
// Reload the DSL
return dsl.manager.Reload(ctx, options.ID, options.ReloadOptions)
return dsl.manager.Reload(ctx, reloadOptions)
}
// Delete DSL
func (dsl *DSL) Delete(ctx context.Context, id string, options ...interface{}) error {
func (dsl *DSL) Delete(ctx context.Context, options *types.DeleteOptions) error {
if options == nil {
return fmt.Errorf("delete options is required")
}
if options.ID == "" {
return fmt.Errorf("delete options id is required")
}
// Exists
info, exists, err := dsl.dbInspect(id)
info, exists, err := dsl.db.Inspect(options.ID)
if err != nil {
return err
}
if !exists {
info, exists, err = dsl.fsInspect(types.ToPath(dsl.Type, id))
info, exists, err = dsl.fs.Inspect(options.ID)
if err != nil {
return err
}
if !exists {
return fmt.Errorf("%s DSL not found, %s", dsl.Type, id)
return fmt.Errorf("%s DSL not found, %s", dsl.Type, options.ID)
}
}
var unloadOptions interface{}
if len(options) > 0 {
unloadOptions = options[0]
var opts map[string]interface{}
if options.Options != nil {
opts = options.Options
}
var unloadOptions *types.UnloadOptions = &types.UnloadOptions{
ID: options.ID,
Path: info.Path,
Store: info.Store,
Options: opts,
}
if info.Store == types.StoreTypeDB {
err = dsl.dbDelete(id)
err = dsl.db.Delete(options.ID)
if err != nil {
return err
}
// Unload the DSL
return dsl.manager.Unload(ctx, id, unloadOptions)
return dsl.manager.Unload(ctx, unloadOptions)
}
err = dsl.fsDelete(id)
err = dsl.fs.Delete(options.ID)
if err != nil {
return err
}
// Unload the DSL
return dsl.manager.Unload(ctx, id, unloadOptions)
return dsl.manager.Unload(ctx, unloadOptions)
}
// Load DSL
func (dsl *DSL) Load(ctx context.Context, id string, options interface{}) error {
return dsl.manager.Load(ctx, id, options)
func (dsl *DSL) Load(ctx context.Context, options *types.LoadOptions) error {
return dsl.manager.Load(ctx, options)
}
// Unload DSL
func (dsl *DSL) Unload(ctx context.Context, id string, options ...interface{}) error {
var unloadOptions interface{}
if len(options) > 0 {
unloadOptions = options[0]
}
return dsl.manager.Unload(ctx, id, unloadOptions)
func (dsl *DSL) Unload(ctx context.Context, options *types.UnloadOptions) error {
return dsl.manager.Unload(ctx, options)
}
// Reload DSL
func (dsl *DSL) Reload(ctx context.Context, id string, options interface{}) error {
return dsl.manager.Reload(ctx, id, options)
func (dsl *DSL) Reload(ctx context.Context, options *types.ReloadOptions) error {
return dsl.manager.Reload(ctx, options)
}
// Execute DSL (Some DSLs can be executed)
func (dsl *DSL) Execute(ctx context.Context, method string, args ...any) (any, error) {
return dsl.manager.Execute(ctx, method, args...)
func (dsl *DSL) Execute(ctx context.Context, id string, method string, args ...any) (any, error) {
return dsl.manager.Execute(ctx, id, method, args...)
}
// Validate DSL

View file

@ -1,4 +1,4 @@
package dsl
package io
import (
"fmt"
@ -10,8 +10,18 @@ import (
"github.com/yaoapp/yao/dsl/types"
)
// getInfoFromDB get the info from the db
func (dsl *DSL) dbInspect(id string) (*types.Info, bool, error) {
// DB is the db io
type DB struct {
Type types.Type
}
// NewDB create a new db io
func NewDB(typ types.Type) types.IO {
return &DB{Type: typ}
}
// Inspect get the info from the db
func (db *DB) Inspect(id string) (*types.Info, bool, error) {
// Get from database
m := model.Select("__yao.dsl")
@ -57,8 +67,8 @@ func (dsl *DSL) dbInspect(id string) (*types.Info, bool, error) {
return &info, true, nil
}
// getSourceFromDB get the source from the db
func (dsl *DSL) dbSource(id string) (string, bool, error) {
// Source get the source from the db
func (db *DB) Source(id string) (string, bool, error) {
// Get from database
m := model.Select("__yao.dsl")
@ -79,14 +89,14 @@ func (dsl *DSL) dbSource(id string) (string, bool, error) {
source, ok := rows[0]["source"].(string)
if !ok {
return "", true, fmt.Errorf("%s %s source is not a string", dsl.Type, id)
return "", true, fmt.Errorf("%s %s source is not a string", db.Type, id)
}
return source, true, nil
}
// getListFromDB get the list from the db
func (dsl *DSL) dbList(options *types.ListOptions) ([]*types.Info, error) {
// List get the list from the db
func (db *DB) List(options *types.ListOptions) ([]*types.Info, error) {
// Get from database
m := model.Select("__yao.dsl")
@ -96,7 +106,7 @@ func (dsl *DSL) dbList(options *types.ListOptions) ([]*types.Info, error) {
orders = []model.QueryOrder{{Column: "sort", Option: "asc"}}
}
var wheres []model.QueryWhere = []model.QueryWhere{{Column: "type", Value: dsl.Type}}
var wheres []model.QueryWhere = []model.QueryWhere{{Column: "type", Value: db.Type}}
// Filter by tags
if len(options.Tags) > 0 {
@ -110,7 +120,7 @@ func (dsl *DSL) dbList(options *types.ListOptions) ([]*types.Info, error) {
// Get the list
rows, err := m.Get(model.QueryParam{
Wheres: []model.QueryWhere{{Column: "type", Value: dsl.Type}},
Wheres: []model.QueryWhere{{Column: "type", Value: db.Type}},
Select: []interface{}{"dsl_id", "label", "path", "sort", "tags", "description", "status", "store", "mtime", "ctime"},
Orders: orders,
})
@ -136,10 +146,11 @@ func (dsl *DSL) dbList(options *types.ListOptions) ([]*types.Info, error) {
return infos, nil
}
func (dsl *DSL) dbCreate(options *types.CreateOptions) error {
// Create create the dsl
func (db *DB) Create(options *types.CreateOptions) error {
if options.Source == "" {
return fmt.Errorf("%s %s source is required", dsl.Type, options.ID)
return fmt.Errorf("%s %s source is required", db.Type, options.ID)
}
// Get info from source
@ -154,7 +165,7 @@ func (dsl *DSL) dbCreate(options *types.CreateOptions) error {
data := map[string]interface{}{
"source": options.Source,
"dsl_id": options.ID,
"type": dsl.Type,
"type": db.Type,
"label": info.Label,
"path": info.Path,
"sort": info.Sort,
@ -174,9 +185,10 @@ func (dsl *DSL) dbCreate(options *types.CreateOptions) error {
return nil
}
func (dsl *DSL) dbUpdate(options *types.UpdateOptions) error {
// Update update the dsl
func (db *DB) Update(options *types.UpdateOptions) error {
if options.Source == "" && options.Info == nil {
return fmt.Errorf("%s %s one of source or info is required", dsl.Type, options.ID)
return fmt.Errorf("%s %s one of source or info is required", db.Type, options.ID)
}
m := model.Select("__yao.dsl")
@ -192,7 +204,7 @@ func (dsl *DSL) dbUpdate(options *types.UpdateOptions) error {
}
if len(rows) == 0 {
return fmt.Errorf("%s %s not found", dsl.Type, options.ID)
return fmt.Errorf("%s %s not found", db.Type, options.ID)
}
row := rows[0]
@ -234,7 +246,8 @@ func (dsl *DSL) dbUpdate(options *types.UpdateOptions) error {
return nil
}
func (dsl *DSL) dbDelete(id string) error {
// Delete delete the dsl
func (db *DB) Delete(id string) error {
// Get from database
m := model.Select("__yao.dsl")
@ -250,7 +263,7 @@ func (dsl *DSL) dbDelete(id string) error {
}
if len(rows) == 0 {
return fmt.Errorf("%s %s not found", dsl.Type, id)
return fmt.Errorf("%s %s not found", db.Type, id)
}
// Delete the dsl
@ -258,7 +271,8 @@ func (dsl *DSL) dbDelete(id string) error {
return m.Delete(row["id"])
}
func (dsl *DSL) dbExists(id string) (bool, error) {
// Exists check if the dsl exists
func (db *DB) Exists(id string) (bool, error) {
// Get from database
m := model.Select("__yao.dsl")

View file

@ -1,4 +1,4 @@
package dsl
package io
import (
"fmt"
@ -8,15 +8,19 @@ import (
"github.com/yaoapp/yao/dsl/types"
)
// getInfoFromFile get the info from the file
func (dsl *DSL) fsInspect(id string, path ...string) (*types.Info, bool, error) {
file := ""
if len(path) > 0 {
file = path[0]
} else {
file = types.ToPath(dsl.Type, id)
}
// FS is the fs io
type FS struct {
Type types.Type
}
// NewFS create a new fs io
func NewFS(typ types.Type) types.IO {
return &FS{Type: typ}
}
// Inspect get the info from the file
func (fs *FS) Inspect(id string) (*types.Info, bool, error) {
file := types.ToPath(fs.Type, id)
var info types.Info = types.Info{ID: id, Path: file}
exists, err := application.App.Exists(file)
if err != nil {
@ -49,9 +53,9 @@ func (dsl *DSL) fsInspect(id string, path ...string) (*types.Info, bool, error)
return &info, true, nil
}
// getSourceFromFile get the source from the file
func (dsl *DSL) fsSource(id string) (string, bool, error) {
path := types.ToPath(dsl.Type, id)
// Source get the source from the file
func (fs *FS) Source(id string) (string, bool, error) {
path := types.ToPath(fs.Type, id)
exists, err := application.App.Exists(path)
if err != nil {
return "", false, err
@ -68,9 +72,9 @@ func (dsl *DSL) fsSource(id string) (string, bool, error) {
return string(data), true, nil
}
// getListFromPath get the list from the path
func (dsl *DSL) fsList(options *types.ListOptions) ([]*types.Info, error) {
root, exts := types.TypeRootAndExts(dsl.Type)
// List get the list from the path
func (fs *FS) List(options *types.ListOptions) ([]*types.Info, error) {
root, exts := types.TypeRootAndExts(fs.Type)
var infos []*types.Info = []*types.Info{}
patterns := []string{}
for _, ext := range exts {
@ -81,8 +85,8 @@ func (dsl *DSL) fsList(options *types.ListOptions) ([]*types.Info, error) {
if isdir {
return nil
}
id := types.WithTypeToID(dsl.Type, file)
info, _, err := dsl.fsInspect(id, file)
id := types.WithTypeToID(fs.Type, file)
info, _, err := fs.Inspect(id)
if err != nil {
errs = append(errs, err)
return nil
@ -112,9 +116,10 @@ func (dsl *DSL) fsList(options *types.ListOptions) ([]*types.Info, error) {
return infos, err
}
func (dsl *DSL) fsCreate(options *types.CreateOptions) error {
// Create create the file
func (fs *FS) Create(options *types.CreateOptions) error {
path := types.ToPath(dsl.Type, options.ID)
path := types.ToPath(fs.Type, options.ID)
// Check if the file is a directory
exists, err := application.App.Exists(path)
@ -123,21 +128,22 @@ func (dsl *DSL) fsCreate(options *types.CreateOptions) error {
}
if exists {
return fmt.Errorf("%v %s already exists", dsl.Type, options.ID)
return fmt.Errorf("%v %s already exists", fs.Type, options.ID)
}
// Create the file
return application.App.Write(path, []byte(options.Source))
}
func (dsl *DSL) fsUpdate(options *types.UpdateOptions) error {
// Update update the file
func (fs *FS) Update(options *types.UpdateOptions) error {
// Validate the options
if options.Source == "" && options.Info == nil {
return fmt.Errorf("%v %s one of source or info is required", dsl.Type, options.ID)
return fmt.Errorf("%v %s one of source or info is required", fs.Type, options.ID)
}
path := types.ToPath(dsl.Type, options.ID)
path := types.ToPath(fs.Type, options.ID)
// Check if the file exists
exists, err := application.App.Exists(path)
@ -146,7 +152,7 @@ func (dsl *DSL) fsUpdate(options *types.UpdateOptions) error {
}
if !exists {
return fmt.Errorf("%v %s not found", dsl.Type, options.ID)
return fmt.Errorf("%v %s not found", fs.Type, options.ID)
}
// Update source
@ -179,9 +185,10 @@ func (dsl *DSL) fsUpdate(options *types.UpdateOptions) error {
return application.App.Write(path, []byte(new))
}
func (dsl *DSL) fsDelete(id string) error {
// Delete delete the file
func (fs *FS) Delete(id string) error {
path := types.ToPath(dsl.Type, id)
path := types.ToPath(fs.Type, id)
// Check if the file is a directory
exists, err := application.App.Exists(path)
@ -190,14 +197,15 @@ func (dsl *DSL) fsDelete(id string) error {
}
if !exists {
return fmt.Errorf("%v %s not found", dsl.Type, id)
return fmt.Errorf("%v %s not found", fs.Type, id)
}
// Delete the file
return application.App.Remove(path)
}
func (dsl *DSL) fsExists(id string) (bool, error) {
path := types.ToPath(dsl.Type, id)
// Exists check if the file exists
func (fs *FS) Exists(id string) (bool, error) {
path := types.ToPath(fs.Type, id)
return application.App.Exists(path)
}

View file

@ -9,16 +9,13 @@ import (
// YaoMCPClient is the MCP client DSL manager
type YaoMCPClient struct {
root string // The relative path of the MCP client DSL
fs types.IO // The file system IO interface
db types.IO // The database IO interface
}
// NewClient returns a new MCP client DSL manager
func NewClient(root string) types.Manager {
return New(root)
}
// New returns a new connector DSL manager
func New(root string) types.Manager {
return &YaoMCPClient{root: root}
func NewClient(root string, fs types.IO, db types.IO) types.Manager {
return &YaoMCPClient{root: root, fs: fs, db: db}
}
// Loaded return all loaded DSLs
@ -27,17 +24,17 @@ func (client *YaoMCPClient) Loaded(ctx context.Context) (map[string]*types.Info,
}
// Load will unload the DSL first, then load the DSL from DB or file system
func (client *YaoMCPClient) Load(ctx context.Context, id string, options interface{}) error {
func (client *YaoMCPClient) Load(ctx context.Context, options *types.LoadOptions) error {
return nil
}
// Unload will unload the DSL from memory
func (client *YaoMCPClient) Unload(ctx context.Context, id string, options interface{}) error {
func (client *YaoMCPClient) Unload(ctx context.Context, options *types.UnloadOptions) error {
return nil
}
// Reload will unload the DSL first, then reload the DSL from DB or file system
func (client *YaoMCPClient) Reload(ctx context.Context, id string, options interface{}) error {
func (client *YaoMCPClient) Reload(ctx context.Context, options *types.ReloadOptions) error {
return nil
}
@ -47,6 +44,6 @@ func (client *YaoMCPClient) Validate(ctx context.Context, source string) (bool,
}
// Execute will execute the DSL
func (client *YaoMCPClient) Execute(ctx context.Context, method string, args ...any) (any, error) {
func (client *YaoMCPClient) Execute(ctx context.Context, id string, method string, args ...any) (any, error) {
return nil, nil
}

View file

@ -22,17 +22,17 @@ func (server *YaoMCPServer) Loaded(ctx context.Context) (map[string]*types.Info,
}
// Load will unload the DSL first, then load the DSL from DB or file system
func (server *YaoMCPServer) Load(ctx context.Context, id string, options interface{}) error {
func (server *YaoMCPServer) Load(ctx context.Context, options *types.LoadOptions) error {
return nil
}
// Unload will unload the DSL from memory
func (server *YaoMCPServer) Unload(ctx context.Context, id string, options interface{}) error {
func (server *YaoMCPServer) Unload(ctx context.Context, options *types.UnloadOptions) error {
return nil
}
// Reload will unload the DSL first, then reload the DSL from DB or file system
func (server *YaoMCPServer) Reload(ctx context.Context, id string, options interface{}) error {
func (server *YaoMCPServer) Reload(ctx context.Context, options *types.ReloadOptions) error {
return nil
}
@ -42,6 +42,6 @@ func (server *YaoMCPServer) Validate(ctx context.Context, source string) (bool,
}
// Execute will execute the DSL
func (server *YaoMCPServer) Execute(ctx context.Context, method string, args ...any) (any, error) {
func (server *YaoMCPServer) Execute(ctx context.Context, id string, method string, args ...any) (any, error) {
return nil, nil
}

View file

@ -10,17 +10,14 @@ import (
// YaoModel is the MCP client DSL manager
type YaoModel struct {
root string // The relative path of the MCP client DSL
}
// NewClient returns a new MCP client DSL manager
func NewClient(root string) types.Manager {
return New(root)
root string // The relative path of the model DSL
fs types.IO // The file system IO interface
db types.IO // The database IO interface
}
// New returns a new connector DSL manager
func New(root string) types.Manager {
return &YaoModel{root: root}
func New(root string, fs types.IO, db types.IO) types.Manager {
return &YaoModel{root: root, fs: fs, db: db}
}
// Loaded return all loaded DSLs
@ -43,10 +40,19 @@ func (m *YaoModel) Loaded(ctx context.Context) (map[string]*types.Info, error) {
}
// Load will unload the DSL first, then load the DSL from DB or file system
func (m *YaoModel) Load(ctx context.Context, id string, options interface{}) error {
func (m *YaoModel) Load(ctx context.Context, options *types.LoadOptions) error {
if options == nil {
return fmt.Errorf("load options is required")
}
if options.ID == "" {
return fmt.Errorf("load options id is required")
}
var opts map[string]interface{}
if v, ok := options.(map[string]interface{}); ok {
opts = v
if options.Options != nil {
opts = options.Options
}
var migration bool = false
@ -59,8 +65,8 @@ func (m *YaoModel) Load(ctx context.Context, id string, options interface{}) err
reset = v.(bool)
}
path := types.ToPath(types.TypeModel, id)
mod, err := model.LoadSync(path, id)
path := types.ToPath(types.TypeModel, options.ID)
mod, err := model.LoadSync(path, options.ID)
if err != nil {
return err
}
@ -73,11 +79,19 @@ func (m *YaoModel) Load(ctx context.Context, id string, options interface{}) err
}
// Unload will unload the DSL from memory
func (m *YaoModel) Unload(ctx context.Context, id string, options interface{}) error {
func (m *YaoModel) Unload(ctx context.Context, options *types.UnloadOptions) error {
if options == nil {
return fmt.Errorf("unload options is required")
}
if options.ID == "" {
return fmt.Errorf("unload options id is required")
}
var opts map[string]interface{}
if v, ok := options.(map[string]interface{}); ok {
opts = v
if options.Options != nil {
opts = options.Options
}
var dropTable bool = false
@ -85,9 +99,9 @@ func (m *YaoModel) Unload(ctx context.Context, id string, options interface{}) e
dropTable = v.(bool)
}
mod := model.Select(id)
mod := model.Select(options.ID)
if mod == nil {
return fmt.Errorf("model %s not found", id)
return fmt.Errorf("model %s not found", options.ID)
}
if dropTable {
@ -98,11 +112,19 @@ func (m *YaoModel) Unload(ctx context.Context, id string, options interface{}) e
}
// Reload will unload the DSL first, then reload the DSL from DB or file system
func (m *YaoModel) Reload(ctx context.Context, id string, options interface{}) error {
func (m *YaoModel) Reload(ctx context.Context, options *types.ReloadOptions) error {
if options == nil {
return fmt.Errorf("reload options is required")
}
if options.ID == "" {
return fmt.Errorf("reload options id is required")
}
var opts map[string]interface{}
if v, ok := options.(map[string]interface{}); ok {
opts = v
if options.Options != nil {
opts = options.Options
}
var migration bool = false
@ -116,8 +138,8 @@ func (m *YaoModel) Reload(ctx context.Context, id string, options interface{}) e
}
// Reload the model
path := types.ToPath(types.TypeModel, id)
mod, err := model.LoadSync(path, id)
path := types.ToPath(types.TypeModel, options.ID)
mod, err := model.LoadSync(path, options.ID)
if err != nil {
return err
}
@ -134,6 +156,6 @@ func (m *YaoModel) Validate(ctx context.Context, source string) (bool, []types.L
}
// Execute will execute the DSL
func (m *YaoModel) Execute(ctx context.Context, method string, args ...any) (any, error) {
func (m *YaoModel) Execute(ctx context.Context, id string, method string, args ...any) (any, error) {
return nil, fmt.Errorf("Not implemented")
}

View file

@ -1,6 +1,8 @@
package types
import "context"
import (
"context"
)
// DSL interface
type DSL interface {
@ -13,15 +15,15 @@ type DSL interface {
// DSL Operations
Create(ctx context.Context, options *CreateOptions) error // Create DSL, Create will unload the DSL first, then create the DSL to DB
Update(ctx context.Context, options *UpdateOptions) error // Update DSL, Update will unload the DSL first, then update the DSL, if update info only, will not unload the DSL
Delete(ctx context.Context, id string, unloadOptions ...interface{}) error // Delete DSL, Delete will unload the DSL first, then delete the DSL file
Delete(ctx context.Context, options *DeleteOptions) error // Delete DSL, Delete will unload the DSL first, then delete the DSL file
// Load manager
Load(ctx context.Context, id string, options interface{}) error // Load DSL, Load will unload the DSL first, then load the DSL from DB or file system
Reload(ctx context.Context, id string, options interface{}) error // Reload DSL, Reload will unload the DSL first, then reload the DSL from DB or file system
Unload(ctx context.Context, id string, options ...interface{}) error // Unload DSL, Unload will unload the DSL from memory
Load(ctx context.Context, options *LoadOptions) error // Load DSL, Load will unload the DSL first, then load the DSL from DB or file system
Reload(ctx context.Context, options *ReloadOptions) error // Reload DSL, Reload will unload the DSL first, then reload the DSL from DB or file system
Unload(ctx context.Context, options *UnloadOptions) error // Unload DSL, Unload will unload the DSL from memory
// Execute
Execute(ctx context.Context, method string, args ...any) (any, error) // Execute DSL (Some DSLs can be executed)
Execute(ctx context.Context, id string, method string, args ...any) (any, error) // Execute DSL (Some DSLs can be executed)
// Validate
Validate(ctx context.Context, source string) (bool, []LintMessage) // Validate DSL, Validate will validate the DSL from source
@ -33,17 +35,28 @@ type Manager interface {
Loaded(ctx context.Context) (map[string]*Info, error) // Get all loaded DSLs
// Load DSL, Load will unload the DSL first, then load the DSL from DB or file system
Load(ctx context.Context, id string, options interface{}) error
Load(ctx context.Context, options *LoadOptions) error
// Unload DSL, Unload will unload the DSL from memory
Unload(ctx context.Context, id string, options interface{}) error
Unload(ctx context.Context, options *UnloadOptions) error
// Reload DSL, Reload will unload the DSL first, then reload the DSL from DB or file system
Reload(ctx context.Context, id string, options interface{}) error
Reload(ctx context.Context, options *ReloadOptions) error
// Validate DSL, Validate will validate the DSL from source
Validate(ctx context.Context, source string) (bool, []LintMessage)
// Execute DSL (Some DSLs can be executed)
Execute(ctx context.Context, method string, args ...any) (any, error)
Execute(ctx context.Context, id string, method string, args ...any) (any, error)
}
// IO interface
type IO interface {
Inspect(id string) (*Info, bool, error)
Source(id string) (string, bool, error)
List(options *ListOptions) ([]*Info, error)
Create(options *CreateOptions) error
Update(options *UpdateOptions) error
Delete(id string) error
Exists(id string) (bool, error)
}

View file

@ -79,14 +79,20 @@ const (
// Info for DSL
type Info struct {
ID string
Type Type
Sort int
Path string
Label string
Description string
Tags []string
Status Status
Sort int
Path string
Store StoreType
Readable bool
Builtin bool
Status Status
Mtime time.Time
Ctime time.Time
}
@ -103,7 +109,7 @@ type CreateOptions struct {
ID string // ID is the id of the DSL, if not provided, a new id will be generated, required
Source string // Source is the source of the DSL, if not provided, the DSL will be loaded from the file system
Store StoreType // Store is the store type of the DSL, if not provided, the DSL will be loaded from the file system
LoadOptions interface{} // LoadOptions is the options for the DSL, if not provided, the DSL will be loaded from the file system
Load map[string]interface{} // LoadOptions is the options for the DSL, if not provided, the DSL will be loaded from the file system
}
// UpdateOptions for DSL upsert
@ -111,7 +117,41 @@ type UpdateOptions struct {
ID string // ID is the id of the DSL, if not provided, a new id will be generated, required
Info *Info // Info is the info of the DSL, if not provided, the DSL will be loaded from the file system, one of info or source must be provided
Source string // Source is the source of the DSL, if not provided, the DSL will be loaded from the file system, one of info or source must be provided
ReloadOptions interface{} // ReloadOptions is the options for the DSL, if not provided, the DSL will be loaded from the file system
Reload map[string]interface{} // ReloadOptions is the options for the DSL, if not provided, the DSL will be loaded from the file system
}
// DeleteOptions for DSL delete options
type DeleteOptions struct {
ID string // ID is the id of the DSL, if not provided, a new id will be generated, required
Path string // Path is the path of the DSL, if not provided, the DSL will be loaded from the file system
Options map[string]interface{} // Options is the options for the DSL, if not provided, the DSL will be loaded from the file system
}
// LoadOptions for DSL load options
type LoadOptions struct {
ID string
Path string
Source string
Store StoreType
Options map[string]interface{}
}
// UnloadOptions for DSL unload options
type UnloadOptions struct {
ID string
Path string
Source string
Store StoreType
Options map[string]interface{}
}
// ReloadOptions for DSL reload options
type ReloadOptions struct {
ID string
Path string
Source string
Store StoreType
Options map[string]interface{}
}
// LintMessage for DSL linter