#Imaginary extension DX
1 messages · Page 1 of 1 (latest)
package todoapp
//go:generate dagger client --type gofile -o ./generated.go
import (
"context"
"dagger.io/dagger"
)
func init() {
dagger.Register(TodoApp))
}
func TodoApp(ctx context.Context, source dagger.DirectoryID) *App {
return &App{
Source: source,
}
}
type App {
Source dagger.DirectoryID
}
func (app *App) Build(ctx context.Context) (*Build, error) {
q := ctx.Graph().Yarn().Run("build", app.source)
resp, err := q.Execute(ctx, dagger.IncludeFields("Contents", "Logs"))
if err != nil {
return nil, err
}
return &Build{
Contents: resp.Contents,
Logs: resp.Logs,
}, nil
}
type Build {
Contents dagger.DirectoryID
Logs string
}
func (b *Build) Deployment(ctx context.Context, siteName string, token dagger.SecretID) (*Deployment, error) {
q := ctx.Graph().Netlify(token).Site(siteName)).Deployment(b.contents)
res, err := q.Execute(ctx, dagger.IncludeField("URL", "Logs"))
if err != nil {
return nil, err
}
return &Deployment{
URL: res.URL,
Logs: res.Logs,
}, nil
}
type Deployment {
URL string
Logs string
}
package todoapp
//go:generate dagger client --type gofile -o ./generated.go
import (
"context"
"dagger.io/dagger"
)
func init() {
dagger.Register(TodoApp))
}
func TodoApp(ctx context.Context, source dagger.DirectoryID) *App {
return &App{
Source: source,
}
}
type App {
Source dagger.DirectoryID
}
func (app *App) Build(ctx context.Context) (*Build, error) {
q := ctx.Graph().Yarn().Run("build", app.source)
resp, err := q.Execute(ctx, dagger.IncludeFields("Contents", "Logs"))
if err != nil {
return nil, err
}
return &Build{
Contents: resp.Contents,
Logs: resp.Logs,
}, nil
}
type Build {
Contents dagger.DirectoryID
Logs string
}
func (b *Build) Deployment(ctx context.Context, siteName string, token dagger.SecretID) (*Deployment, error) {
q := ctx.Graph().Netlify(token).Site(siteName)).Deployment(b.contents)
res, err := q.Execute(ctx, dagger.IncludeField("URL", "Logs"))
if err != nil {
return nil, err
}
return &Deployment{
URL: res.URL,
Logs: res.Logs,
}, nil
}
type Deployment {
URL string
Logs string
}
I'm kind of punting on using generated types (leaning heavily on positional args...) because I'm not sure what they would be and how I would use them
Adding a hook to integrate the generated code:
package todoapp
//go:generate dagger client gofile -o ./generated.go
import (
"context"
"dagger.io/dagger"
)
// NOTES:
//
// 1. Dagger generates a custom query builder called `Graph`
// 2. Presumably it would also generate input types for all fields in the graph, into a flat namespace.
// This may not be practical, for now we are avoiding the use of input types
// 3. To keep things simple we assume that struct resolvers are "all or nothing": clients cannot differentiate
// between an error resolving a struct, and an error resolving one of its fields.
// Let's see how far we can go with this constraint.
// 4. Scalar fields can be included / excluded to avoid unnecessary network I/O
// 5. The API only supports a subset of queries, where scalars are only queried from one struct;
// that struct is returned to the caller (intermediary fields are removed). We call this "flattening"
func init() {
// - Graph is the (generated) client for the base graph we want to extend
// - TodoApp is our graph extensions
dagger.Extend(Graph, TodoApp))
}
func TodoApp(ctx context.Context, g Graph, source dagger.DirectoryID) *App {
return &App{
Source: source,
}
}
type App {
Source dagger.DirectoryID
}
func (app *App) Build(ctx context.Context, g Graph) (*Build, error) {
q := g.Yarn().Run("build", app.source)
resp, err := q.Execute(ctx, dagger.IncludeFields("Contents", "Logs"))
if err != nil {
return nil, err
}
return &Build{
Contents: resp.Contents,
Logs: resp.Logs,
}, nil
}
type Build {
Contents dagger.DirectoryID
Logs string
}
func (b *Build) Deployment(ctx context.Context, g Graph, siteName string, token dagger.SecretID) (*Deployment, error) {
q := g.Netlify(token).Site(siteName)).Deployment(b.contents)
res, err := q.Execute(ctx, dagger.IncludeField("URL", "Logs"))
if err != nil {
return nil, err
}
return &Deployment{
URL: res.URL,
Logs: res.Logs,
}, nil
}
type Deployment {
URL string
Logs string
}
I think we may be able to copy the "opts" style of llb's API
might be smoother in Go compared to 1 function = 1 input type struct
On a high level I think we are on the same page in terms of the direction here. I was starting to write out an iteration based on yours but have to run to dinner now. I'll take a look again on Monday. Either way, very exciting, this is definitely going to be another order of magnitude improvement!
pushed my latest iteration on this branch: https://github.com/shykes/todoapp/tree/cloak-demov3
With dagger.Extend(Graph, TodoApp)), shouldn't it be instances of those types?
Also, why do we pass the graph in each operation? Wouldn't it be the same graph for the whole App?
- TodoApp is not a type.
- Graph: honestly not 100% sure what this should look like.
- pass the graph in each operation: not sure either
I’m painting this with a very broad brush atm 🙂
Got it!