db

package
v0.70.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 11, 2026 License: MIT Imports: 5 Imported by: 0

README

vibes/capability/db

Host-side database capability adapter for Vibescript. Exposes the db.find, db.query, db.update, db.sum, and db.each builtins to scripts and dispatches them to a host-provided implementation.

Embedders implement the interfaces in this package directly. The top-level vibes.NewDBCapability helper wraps a db.Database implementation in a script-visible capability adapter.

Interface segregation

The capability splits the host contract into composable pieces so read-only embedders can satisfy a narrower surface:

type DatabaseReader interface {
    Find(ctx context.Context, req DBFindRequest) (value.Value, error)
    Query(ctx context.Context, req DBQueryRequest) (value.Value, error)
    Sum(ctx context.Context, req DBSumRequest) (value.Value, error)
    Each(ctx context.Context, req DBEachRequest) ([]value.Value, error)
}

type DatabaseWriter interface {
    Update(ctx context.Context, req DBUpdateRequest) (value.Value, error)
}

type Database interface {
    DatabaseReader
    DatabaseWriter
}

Database is the full read/write surface scripts ultimately call. Any type that implements both sub-interfaces satisfies it, so existing implementations compile unchanged.

Read-only hosts

Analytics jobs and sandboxed previews can implement only DatabaseReader and compose it with a writer that rejects mutations:

type readOnly struct{ db.DatabaseReader }

func (readOnly) Update(context.Context, db.DBUpdateRequest) (value.Value, error) {
    return value.NewNil(), errors.New("read-only host: db.update is disabled")
}

cap, err := vibes.NewDBCapability("db", readOnly{reader})

vibes.NewDBCapability accepts any db.Database, so the composed value plugs in without further wiring.

Request shapes

Every method receives a request struct with already-cloned arguments and options; the host may keep the values without worrying about script aliasing.

Method Request fields
Find Collection, ID, Options
Query Collection, Options
Update Collection, ID, Attributes, Options
Sum Collection, Field, Options
Each Collection, Options (script-supplied block invoked per row)

Options carries the kwargs passed at the call site (for example include: on db.find or where: on db.query). Attributes on Update is the script-provided update hash. Return values from the host are validated as data-only and deep-copied before being handed back to the script.

Documentation

Overview

Package db provides the host-side database capability adapter for Vibescript. It exposes a thin Database interface plus the request structs that scripts can call via the db.* methods bound on a script invocation. The top-level vibes package wraps the capability behind a CapabilityAdapter implementation for installation on script calls.

Example

Example shows how to wire a db.Capability into a script invocation via the vibes facade and observe the find dispatch.

package main

import (
	"context"
	"fmt"

	"github.com/mgomes/vibescript/vibes"
	"github.com/mgomes/vibescript/vibes/capability/db"
	"github.com/mgomes/vibescript/vibes/value"
)

// stubDB returns canned responses for the godoc Examples. Real embedders
// would query an actual database, ORM, or external API.
type stubDB struct{}

func (stubDB) Find(_ context.Context, req db.DBFindRequest) (value.Value, error) {
	return value.NewHash(map[string]value.Value{
		"id":   req.ID,
		"name": value.NewString("Ada"),
	}), nil
}

func (stubDB) Query(_ context.Context, _ db.DBQueryRequest) (value.Value, error) {
	return value.NewArray(nil), nil
}

func (stubDB) Update(_ context.Context, _ db.DBUpdateRequest) (value.Value, error) {
	return value.NewBool(true), nil
}

func (stubDB) Sum(_ context.Context, _ db.DBSumRequest) (value.Value, error) {
	return value.NewInt(0), nil
}

func (stubDB) Each(_ context.Context, _ db.DBEachRequest) ([]value.Value, error) {
	return nil, nil
}

func main() {
	engine := vibes.MustNewEngine(vibes.Config{})
	script, err := engine.Compile(`def run()
  user = users.find("Player", "p-1")
  user[:name]
end`)
	if err != nil {
		fmt.Println("compile:", err)
		return
	}

	result, err := script.Call(context.Background(), "run", nil, vibes.CallOptions{
		Capabilities: []vibes.CapabilityAdapter{
			vibes.MustNewDBCapability("users", stubDB{}),
		},
	})
	if err != nil {
		fmt.Println("call:", err)
		return
	}
	fmt.Println(result.String())
}
Output:
Ada

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Capability

type Capability struct {
	// contains filtered or unexported fields
}

Capability is the concrete adapter returned by NewCapability. The per-method Call* functions accept an ExecutionContext so the package stays free of a vibes runtime dependency.

func MustNewCapability

func MustNewCapability(name string, db Database) *Capability

MustNewCapability constructs a database capability adapter or panics when name is empty or db is a nil implementation.

Example
package main

import (
	"context"
	"fmt"

	"github.com/mgomes/vibescript/vibes/capability/db"
	"github.com/mgomes/vibescript/vibes/value"
)

// stubDB returns canned responses for the godoc Examples. Real embedders
// would query an actual database, ORM, or external API.
type stubDB struct{}

func (stubDB) Find(_ context.Context, req db.DBFindRequest) (value.Value, error) {
	return value.NewHash(map[string]value.Value{
		"id":   req.ID,
		"name": value.NewString("Ada"),
	}), nil
}

func (stubDB) Query(_ context.Context, _ db.DBQueryRequest) (value.Value, error) {
	return value.NewArray(nil), nil
}

func (stubDB) Update(_ context.Context, _ db.DBUpdateRequest) (value.Value, error) {
	return value.NewBool(true), nil
}

func (stubDB) Sum(_ context.Context, _ db.DBSumRequest) (value.Value, error) {
	return value.NewInt(0), nil
}

func (stubDB) Each(_ context.Context, _ db.DBEachRequest) ([]value.Value, error) {
	return nil, nil
}

func main() {
	cap := db.MustNewCapability("users", stubDB{})
	fmt.Println(cap.Name())
}
Output:
users

func NewCapability

func NewCapability(name string, db Database) (*Capability, error)

NewCapability constructs a database capability adapter bound to the provided script-facing name. The returned *Capability holds the per-call dispatchers; package vibes wraps it in a CapabilityAdapter for installation on a script invocation.

Example
package main

import (
	"context"
	"fmt"

	"github.com/mgomes/vibescript/vibes/capability/db"
	"github.com/mgomes/vibescript/vibes/value"
)

// stubDB returns canned responses for the godoc Examples. Real embedders
// would query an actual database, ORM, or external API.
type stubDB struct{}

func (stubDB) Find(_ context.Context, req db.DBFindRequest) (value.Value, error) {
	return value.NewHash(map[string]value.Value{
		"id":   req.ID,
		"name": value.NewString("Ada"),
	}), nil
}

func (stubDB) Query(_ context.Context, _ db.DBQueryRequest) (value.Value, error) {
	return value.NewArray(nil), nil
}

func (stubDB) Update(_ context.Context, _ db.DBUpdateRequest) (value.Value, error) {
	return value.NewBool(true), nil
}

func (stubDB) Sum(_ context.Context, _ db.DBSumRequest) (value.Value, error) {
	return value.NewInt(0), nil
}

func (stubDB) Each(_ context.Context, _ db.DBEachRequest) ([]value.Value, error) {
	return nil, nil
}

func main() {
	cap, err := db.NewCapability("users", stubDB{})
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println(cap.Name())
}
Output:
users

func (*Capability) CallEach

func (c *Capability) CallEach(exec ExecutionContext, args []value.Value, kwargs map[string]value.Value, block value.Value) (value.Value, error)

CallEach implements the db.each boundary. The host returns the row set up front; the capability charges each row and its bounded data-only copy, then yields the independent snapshot to the script-supplied block.

func (*Capability) CallFind

func (c *Capability) CallFind(exec ExecutionContext, args []value.Value, kwargs map[string]value.Value, block value.Value) (value.Value, error)

CallFind implements the db.find boundary: arg validation, host invocation, and cloning of the host-returned Value so script-side state cannot alias the host's data.

func (*Capability) CallQuery

func (c *Capability) CallQuery(exec ExecutionContext, args []value.Value, kwargs map[string]value.Value, block value.Value) (value.Value, error)

CallQuery implements the db.query boundary.

func (*Capability) CallSum

func (c *Capability) CallSum(exec ExecutionContext, args []value.Value, kwargs map[string]value.Value, block value.Value) (value.Value, error)

CallSum implements the db.sum boundary.

func (*Capability) CallUpdate

func (c *Capability) CallUpdate(exec ExecutionContext, args []value.Value, kwargs map[string]value.Value, block value.Value) (value.Value, error)

CallUpdate implements the db.update boundary.

func (*Capability) Contracts

func (c *Capability) Contracts() map[string]Contract

Contracts returns the boundary validators the runtime should enforce around each db.* builtin. The map keys must match the builtin names bound in the vibes-side adapter so the contract scanner can resolve them.

func (*Capability) Name

func (c *Capability) Name() string

Name returns the script-facing name the capability was bound under.

type Contract

type Contract struct {
	ValidateArgs   func(args []value.Value, kwargs map[string]value.Value, block value.Value) error
	ValidateReturn func(result value.Value) error
	// CallValidated runs the method after ValidateArgs has already succeeded.
	CallValidated func(exec ExecutionContext, args []value.Value, kwargs map[string]value.Value, block value.Value) (value.Value, error)
}

Contract pairs the boundary validators registered for a single capability method. The runtime adapter converts this into vibes.CapabilityMethodContract when installing the capability.

type DBEachRequest

type DBEachRequest struct {
	Collection string
	Options    map[string]value.Value
}

DBEachRequest captures db.each calls.

type DBFindRequest

type DBFindRequest struct {
	Collection string
	ID         value.Value
	Options    map[string]value.Value
}

DBFindRequest captures db.find calls.

type DBQueryRequest

type DBQueryRequest struct {
	Collection string
	Options    map[string]value.Value
}

DBQueryRequest captures db.query calls.

type DBSumRequest

type DBSumRequest struct {
	Collection string
	Field      string
	Options    map[string]value.Value
}

DBSumRequest captures db.sum calls.

type DBUpdateRequest

type DBUpdateRequest struct {
	Collection string
	ID         value.Value
	Attributes map[string]value.Value
	Options    map[string]value.Value
}

DBUpdateRequest captures db.update calls.

type Database

type Database interface {
	DatabaseReader
	DatabaseWriter
}

Database is the full read/write surface scripts can call. It is satisfied by any type that implements both DatabaseReader and DatabaseWriter, so existing implementations keep compiling unchanged.

type DatabaseReader

type DatabaseReader interface {
	Find(ctx context.Context, req DBFindRequest) (value.Value, error)
	Query(ctx context.Context, req DBQueryRequest) (value.Value, error)
	Sum(ctx context.Context, req DBSumRequest) (value.Value, error)
	Each(ctx context.Context, req DBEachRequest) ([]value.Value, error)
}

DatabaseReader exposes the read-only subset of the database capability. Host implementations that should not allow scripts to mutate data can satisfy only this interface and wrap with a writer that returns an error on Update calls.

type DatabaseWriter

type DatabaseWriter interface {
	Update(ctx context.Context, req DBUpdateRequest) (value.Value, error)
}

DatabaseWriter exposes the write subset of the database capability.

type ExecutionContext

type ExecutionContext interface {
	Context() context.Context
	Step() error
	CallBlock(block value.Value, args []value.Value) (value.Value, error)
}

ExecutionContext describes the slice of the vibes runtime the db capability calls into. *vibes.Execution satisfies it structurally. Defining the interface here keeps the db package free of an import of vibes and so prevents an import cycle.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL