yowrap

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Apr 27, 2024 License: MIT Imports: 4 Imported by: 0

README

🌮 yowrap 🌮

GoDoc Test Status codecov Go Report Card

Lightweight Go package designed to effortlessly wrap the Yo package for enhanced functionality.

Context

Yo is a command-line tool that generates Go code from SQL DDL files. The generated code is used to interact with Google Cloud Spanner databases, representing the table and a set of methods to interact with the table.

Yo is a great tool to generate the boilerplate code needed to interact with a Google Cloud Spanner database. However, the generated code is not intended to be modified by the user, as it is overwritten every time the yo tool is executed. This pkg is designed to extend the generated code functionality creating a more capable model.

This package is designed to be used in conjunction with the yo tool, not as a replacement.

See Yo for more information about the yo tool.

Features

  • Commit transaction: This feature allows the client to commit a model transaction directly from the model instance without using the spanner.Mutation outside the model. Now, the model has the responsibility of writing the changes to the database.
  • Custom model hooks: This feature allows the client to define custom hooks that will be executed before or after a specific method is called. This is useful for adding custom logic to the model methods.
  • Inheric model methods: All the method signatures from the generated code are inherited by the model. This allows the client to call the generated methods directly from the model instance.

Usage

Use yowrap as a wrapper for the generated model but committing the transaction outside the model. This mantains the ability to use the generated methods-

package main

import (
    "context"
    "fmt"
    "log"

    "cloud.google.com/go/spanner"
    "github.com/jferrl/yowrap"
)


func main() {
    spannerClient, err := spanner.NewClient(ctx, "projects/my-project/instances/my-instance/databases/my-database")
    if err != nil {
        log.Fatalf("Failed to create a Spanner client: %v", err)
    }
    defer spannerClient.Close()

    // Go struct generated by the yo tool
    user := &User{
        ID:    1,
        Name:  "John Doe",
        Email: " [email protected]",
    }

    // Create a new user model
    user := yowrap.NewModel(user)

    mut := user.Insert(ctx)

    _, err = spannerClient.Apply(ctx, []*spanner.Mutation{mut})
    if err != nil {
        log.Fatalf("Failed to apply the mutation: %v", err)
    }
}

Use yowrap as a wrapper for the generated model and commit the transaction directly from the model.


package main

import (
    "context"
    "fmt"
    "log"

    "cloud.google.com/go/spanner"
    "github.com/jferrl/yowrap"
)

func main() {
    spannerClient, err := spanner.NewClient(ctx, "projects/my-project/instances/my-instance/databases/my-database")
    if err != nil {
        log.Fatalf("Failed to create a Spanner client: %v", err)
    }
    defer spannerClient.Close()

    // Go struct generated by the yo tool
    user := &User{
        ID:    1,
        Name:  "John Doe",
        Email: " [email protected]",
    }

    // Create a new user model
    user := yowrap.NewModel(user, yowrap.WithSpannerClientOption(spannerClient))

    // Commit the transaction
    _, err = user.Apply(ctx, yowrap.Insert)
    if err != nil {
        log.Fatalf("Failed to insert and commit the user: %v", err)
    }
}

Use yowrap with a custom hook.


package main

import (
    "context"
    "fmt"
    "log"

    "cloud.google.com/go/spanner"
    "github.com/jferrl/yowrap"
)

func main() {
    spannerClient, err := spanner.NewClient(ctx, "projects/my-project/instances/my-instance/databases/my-database")
    if err != nil {
        log.Fatalf("Failed to create a Spanner client: %v", err)
    }
    defer spannerClient.Close()

    // Go struct generated by the yo tool
    user := &User{
        ID:    1,
        Name:  "John Doe",
        Email: " [email protected]",
    }

    // Create a new user model
    user := yowrap.NewModel(user, yowrap.WithSpannerClientOption(spannerClient))

    // Add a custom hook
    user.On(yowrap.BeforeInsert, func(_ context.Context, m *yowrap.Model[*user.User], _ *spanner.ReadWriteTransaction) error {
        log.Println("Before insert")
        return nil
    })

    // Commit the transaction
    _, err = user.Apply(ctx, yowrap.Insert)
    if err != nil {
        log.Fatalf("Failed to insert and commit the user: %v", err)
    }
}

License

Copyright 2024, jferrl

yowrap is released under the MIT license.

Documentation

Overview

Package yowrap provides a wrapper around the generated Yo model.

Index

Constants

This section is empty.

Variables

View Source
var ErrNoClient = errors.New("no spanner client")

ErrNoClient is returned when the spanner client is not set.

Functions

This section is empty.

Types

type Hook

type Hook int

Hook defines an action that can be executed during a mutation.

const (
	// AfterInsert is executed when the Insert txn is called.
	AfterInsert Hook = iota + 1
	// AfterUpdate is executed when the Update txn is called.
	AfterUpdate
	// AfterInsertOrUpdate is executed when the InsertOrUpdate txn is called.
	AfterInsertOrUpdate
	// AfterDelete is executed when the Delete txn is called.
	AfterDelete
	// BeforeInsert is executed before the Insert txn is called.
	BeforeInsert
	// BeforeUpdate is executed before the Update txn is called.
	BeforeUpdate
	// BeforeInsertOrUpdate is executed before the InsertOrUpdate txn is called.
	BeforeInsertOrUpdate
	// BeforeDelete is executed before the Delete txn is called.
	BeforeDelete
)

type HookFunc

type HookFunc[T Yoable[T]] func(context.Context, *Model[T], *spanner.ReadWriteTransaction) error

HookFunc defines a function that could be executed during a transaction. The function should return an error if the transaction should be aborted. This funcions are used for create hooks that are executed before or after. This hooks are able to modify the model before the transaction is executed or create some new stuff during the ongoin transaction.

type Model

type Model[T Yoable[T]] struct {
	Yoable[T]
	spanner.Client
	// contains filtered or unexported fields
}

Model is a struct that embeds the generated model and implements the Yo interface.

func NewModel

func NewModel[T Yoable[T]](m T, opts ...Opt[T]) *Model[T]

NewModel returns a new wrapped yo model.

func (*Model[T]) Apply

func (m *Model[T]) Apply(ctx context.Context, mtype Mutation) (time.Time, error)

Apply executes a kind of mutation against the database. It executes the before hook, the mutation and the after hook.

func (*Model[T]) Model

func (m *Model[T]) Model() Yoable[T]

Model returns the embedded model.

func (*Model[T]) On

func (m *Model[T]) On(h Hook, f HookFunc[T])

On registers a hook function to be executed during a transaction.

type Mutation

type Mutation int

Mutation defines a mutation that can be executed within spanner.

const (
	// Insert is a mutation that inserts a row into a table.
	Insert Mutation = iota + 1
	// Update is a mutation that updates a row in a table.
	Update
	// InsertOrUpdate is a mutation that inserts a row into a table. If the row
	// already exists, it updates it instead. Any column values not explicitly
	// written are preserved.
	InsertOrUpdate
	// Delete is a mutation that deletes a row from a table.
	Delete
)

func (Mutation) Hooks

func (m Mutation) Hooks() (before, after Hook)

Hooks defines an action that can be executed during a mutation.

type Opt

type Opt[T Yoable[T]] func(*Model[T])

Opt is a function that modifies a Model.

func WithSpannerClientOption

func WithSpannerClientOption[T Yoable[T]](c *spanner.Client) Opt[T]

WithSpannerClientOption returns an Opt that sets the spanner client.

type Yoable

type Yoable[Y any] interface {
	Insert(ctx context.Context) *spanner.Mutation
	Update(ctx context.Context) *spanner.Mutation
	InsertOrUpdate(ctx context.Context) *spanner.Mutation
	Delete(ctx context.Context) *spanner.Mutation
}

Yoable is the common interface for the generated model.

Directories

Path Synopsis
internal
user
Code generated by yo.
Code generated by yo.

Jump to

Keyboard shortcuts

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