diff --git a/README.md b/README.md index 781054a..be3efd1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# yowrap +# 🌮 yowrap 🌮 [![GoDoc](https://img.shields.io/static/v1?label=godoc&message=reference&color=blue)](https://pkg.go.dev/github.com/jferrl/yowrap) [![Test Status](https://github.com/jferrl/yowrap/workflows/tests/badge.svg)](https://github.com/jferrl/yowrap/actions?query=workflow%3Atests) @@ -7,5 +7,157 @@ Lightweight Go package designed to effortlessly wrap the [Yo](https://github.com/cloudspannerecosystem/yo) package for enhanced functionality. +## Context +[Yo](https://github.com/cloudspannerecosystem/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 package provides a way to extend a model with custom methods, without modifying the generated code. + +The main idea of this pkg is extending the `yo` generated code functionality in order to create a more capable model. + +This package is designed to be used in conjunction with the `yo` tool, not as a replacement. + +See [Yo](https://github.com/cloudspannerecosystem/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- + +```go +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. + +```go + +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. + +```go + +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.