snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s

This commit is contained in:
upstream-mirror
2026-09-18 01:22:23 +05:00
commit 7e385fc126
8391 changed files with 1766236 additions and 0 deletions

View File

@@ -0,0 +1,318 @@
package {{ .Package }}
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
// {{ .Source }}
import (
"context"
"fmt"
"github.com/cortezaproject/corteza/server/pkg/actionlog"
"github.com/cortezaproject/corteza/server/pkg/errors"
"github.com/cortezaproject/corteza/server/pkg/locale"
{{- range .Import }}
{{ normalizeImport . }}
{{- end }}
"strings"
"time"
)
type (
{{ $.Service }}ActionProps struct {
{{- range $prop := $.Props }}
{{ $prop.Name }} {{ $prop.Type }}
{{- end }}
}
{{ if $.Actions }}
{{ $.Service }}Action struct {
timestamp time.Time
resource string
action string
log string
severity actionlog.Severity
// prefix for error when action fails
errorMessage string
props *{{ $.Service }}ActionProps
}
{{ end }}
{{ $.Service }}LogMetaKey struct {}
{{ $.Service }}PropsMetaKey struct {}
)
var (
// just a placeholder to cover template cases w/o fmt package use
_ = fmt.Println
)
// *********************************************************************************************************************
// *********************************************************************************************************************
// Props methods
{{- range $prop := $.Props }}
// {{ camelCase "set" $prop.Name }} updates {{ $.Service }}ActionProps's {{ $prop.Name }}
//
// This function is auto-generated.
//
func (p *{{ $.Service }}ActionProps) {{ camelCase "set" $prop.Name }}({{ $prop.Name }} {{ $prop.Type }}) *{{ $.Service }}ActionProps {
p.{{ $prop.Name }} = {{ $prop.Name }}
return p
}
{{ end }}
// Serialize converts {{ $.Service }}ActionProps to actionlog.Meta
//
// This function is auto-generated.
//
func (p {{ $.Service }}ActionProps) Serialize() actionlog.Meta {
var (
m = make(actionlog.Meta)
)
{{ range $prop := $.Props }}
{{- if $prop.Builtin }}
m.Set("{{ $prop.Name }}", p.{{ $prop.Name }}, true)
{{- else }}
if p.{{ $prop.Name }} != nil {
{{- range $f := $prop.Fields }}
m.Set("{{ $prop.Name }}.{{ $f }}", p.{{ $prop.Name }}.{{ camelCase " " $f }}, true)
{{- end }}
}
{{- end }}
{{- end }}
return m
}
// tr translates string and replaces meta value placeholder with values
//
// This function is auto-generated.
//
func (p {{ $.Service }}ActionProps) Format(in string, err error) string {
var (
pairs = []string{"{{"{{"}}err}}"}
{{- if $.Props }}
// first non-empty string
fns = func(ii ... interface{}) string {
for _, i:= range ii {
if s :=fmt.Sprintf("%v", i); len(s) > 0 {
return s
}
}
return ""
}
{{- end }}
)
if err != nil {
pairs = append(pairs, err.Error())
} else {
pairs = append(pairs, "nil")
}
{{- range $prop := $.Props }}
{{- if $prop.Builtin }}
pairs = append(pairs, "{{"{{"}}{{ $prop.Name }}}}", fns(p.{{ $prop.Name }}))
{{- else }}
if p.{{ $prop.Name }} != nil {
// replacement for "{{"{{"}}{{ $prop.Name }}}}" (in order how fields are defined)
pairs = append(
pairs,
"{{"{{"}}{{ $prop.Name }}}}",
fns(
{{- range $f := $prop.Fields }}
p.{{ $prop.Name }}.{{ camelCase " " $f }},
{{- end }}
),
)
{{- range $f := $prop.Fields }}
pairs = append(pairs, "{{"{{"}}{{ $prop.Name }}.{{ $f }}}}", fns(p.{{ $prop.Name }}.{{ camelCase " " $f }}))
{{- end }}
}
{{- end }}
{{- end }}
return strings.NewReplacer(pairs...).Replace(in)
}
{{ if $.Actions }}
// *********************************************************************************************************************
// *********************************************************************************************************************
// Action methods
// String returns loggable description as string
//
// This function is auto-generated.
//
func (a *{{ $.Service }}Action) String() string {
var props = &{{ $.Service }}ActionProps{}
if a.props != nil {
props = a.props
}
return props.Format(a.log, nil)
}
func (e *{{ $.Service }}Action) ToAction() *actionlog.Action {
return &actionlog.Action{
Resource: e.resource,
Action: e.action,
Severity: e.severity,
Description: e.String(),
Meta: e.props.Serialize(),
}
}
{{ end }}
{{ if $.Actions }}
// *********************************************************************************************************************
// *********************************************************************************************************************
// Action constructors
{{ range $a := $.Actions }}
// {{ camelCase "" $.Service "Action" $a.Action }} returns "{{ $.Resource }}.{{ $a.Action }}" action
//
// This function is auto-generated.
//
func {{ camelCase "" $.Service "Action" $a.Action }}(props ... *{{ $.Service }}ActionProps) *{{ $.Service }}Action {
a := &{{ $.Service }}Action{
timestamp: time.Now(),
resource: "{{ $.Resource }}",
action: "{{ $a.Action }}",
log: "{{ $a.Log }}",
severity: {{ $a.SeverityConstName }},
}
if len(props) > 0 {
a.props = props[0]
}
return a
}
{{ end }}
{{ end }}
{{ if $.Errors }}
// *********************************************************************************************************************
// *********************************************************************************************************************
// Error constructors
{{ range $e := $.Errors }}
// {{ camelCase "" $.Service "Err" $e.Error }} returns "{{ $.Resource }}.{{ $e.Error }}" as *errors.Error
//
{{- if $e.MaskedWith }}
// Note: This error will be wrapped with safe ({{ $.Resource }}.{{ $e.MaskedWith }}) error!
{{- end }}
//
// This function is auto-generated.
//
func {{ camelCase "" $.Service "Err" $e.Error }}(mm ... *{{ $.Service }}ActionProps) *errors.Error {
var p = &{{ $.Service }}ActionProps{}
if len(mm) > 0 {
p = mm[0]
}
var e = errors.New(
errors.KindInternal,
{{ if $e.Message }}p.Format({{ printf "%q" $e.Message }}, nil){{ else }}{{ printf "%q" $e.Error }}{{ end }},
errors.Meta("type", {{ printf "%q" $e.Error }}),
errors.Meta("resource", {{ printf "%q" $.Resource }}),
{{ if $e.Documentation }}
// link to documentation; formatting applies in case we need some special link formatting
errors.Meta("documentation", p.Format({{ printf "%q" $e.Documentation }}, nil)),
{{ end -}}
{{ if $e.Details }}
// details, used in detailed eror reporting
errors.Meta("details", p.Format({{ printf "%q" $e.Details }}, nil)),
{{ end -}}
{{- if $e.Log }}
// action log entry; no formatting, it will be applied inside recordAction fn.
errors.Meta({{ $.Service }}LogMetaKey{}, {{ printf "%q" $e.Log }}),
{{ end -}}
errors.Meta({{ $.Service }}PropsMetaKey{}, p),
// translation namespace & key
errors.Meta(locale.ErrorMetaNamespace{}, {{ printf "%q" $.Component }}),
errors.Meta(locale.ErrorMetaKey{}, "{{ kebabCase $.Service }}.errors.{{ $e.Error }}"),
errors.StackSkip(1),
)
if len(mm) > 0 {
}
{{ if $e.MaskedWith }}
// Wrap with safe error
e = {{ camelCase "" $.Service "Err" $e.MaskedWith }}().Wrap(e)
{{ end }}
return e
}
{{ end }}
{{ end }}
// *********************************************************************************************************************
// *********************************************************************************************************************
// recordAction is a service helper function wraps function that can return error
//
// It will wrap unrecognized/internal errors with generic errors.
//
// This function is auto-generated.
//
func (svc {{ $.Service }}) recordAction(ctx context.Context, props *{{ $.Service }}ActionProps, actionFn func(... *{{ $.Service }}ActionProps) *{{ $.Service }}Action, err error) error {
if svc.actionlog == nil || actionFn == nil {
// action log disabled or no action fn passed, return error as-is
return err
} else if err == nil {
// action completed w/o error, record it
svc.actionlog.Record(ctx, actionFn(props).ToAction())
return nil
}
a := actionFn(props).ToAction()
// Extracting error information and recording it as action
a.Error = err.Error()
switch c := err.(type) {
case *errors.Error:
m := c.Meta()
a.Error = err.Error()
a.Severity = actionlog.Severity(m.AsInt("severity"))
a.Description = props.Format(m.AsString({{ $.Service }}LogMetaKey{}), err)
if p, has := m[{{ $.Service }}PropsMetaKey{}]; has {
a.Meta = p.(*{{ $.Service }}ActionProps).Serialize()
}
svc.actionlog.Record(ctx, a)
default:
svc.actionlog.Record(ctx, a)
}
// Original error is passed on
return err
}

View File

@@ -0,0 +1,63 @@
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
{{- range .Definitions }}
// - {{ .Source }}
{{- end }}
{{ range $d := .Definitions }}
= `{{ $d.Name }}`
[cols="2m,4a,3a"]
|===
| Name | Description | I/O
{{- range $f := .Functions }}
{{- if eq $f.Kind "function" }}
| [#fnc-{{ toLower $d.Name }}-{{ toLower $f.Name }}]#<<fnc-{{ toLower $d.Name }}-{{ toLower $f.Name }},{{ if $f.Meta.Short }}{{ $f.Meta.Short }}{{ else }}{{ $f.Name }}{{ end }}>>#
| {{ if $f.Meta.Description }}{{ $f.Meta.Description }}{{ end }}
|
{{- if gt (len $f.Params) 0}}
.Parameters:
{{- range $p := $f.Params}}
* {{ if $p.Required }}#*# {{ end }}`{{ if $p.Meta }}
{{- if $p.Meta.Label }}
{{- $p.Meta.Label }}
{{- else }}
{{- $p.Name }}
{{- end }}
{{- else }}
{{- $p.Name }}
{{- end }}`
({{- range $pti, $pt := $p.Types }}
`{{- $pt.WorkflowType }}`,
{{- end }})
{{- end }}
{{- end }}
{{- if gt (len $f.Results) 0}}
.Results:
{{- range $r := $f.Results}}
* {{ if $r.Meta }}
{{- if $r.Meta.Label }}
{{- $r.Meta.Label }}
{{- else }}
{{- $r.Name }}
{{- end }}
{{- else }}
{{- $r.Name }}
{{- end }} (`{{ $r.WorkflowType }}`)
{{- end }}
{{- end }}
{{- end }}
{{- end }}
|===
{{- end }}

View File

@@ -0,0 +1,269 @@
package {{ .Package }}
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
// {{ .Source }}
import (
atypes "github.com/cortezaproject/corteza/server/automation/types"
"context"
"github.com/cortezaproject/corteza/server/pkg/expr"
"github.com/cortezaproject/corteza/server/pkg/wfexec"
{{- range .Imports }}
{{ normalizeImport . }}
{{- end }}
)
var _ wfexec.ExecResponse
type (
{{ $.Name }}HandlerRegistry interface {
AddFunctions(ff ...*atypes.Function)
Type(ref string) expr.Type
}
)
func (h {{ $.Name }}Handler) register() {
h.reg.AddFunctions(
{{- range .Functions }}
h.{{ export .Name }}(),
{{- end }}
)
}
{{ range .Functions }}
{{ $REF := unexport $.Prefix $.Name .Name }}
{{ $ARGS := unexport $.Name .Name "Args" }}
{{ $RESULTS := unexport $.Name .Name "Results" }}
type (
{{ $ARGS }} struct {
{{ range .Params }}
{{ $name := .Name }}
{{ $isArray := .IsArray }}
has{{ export .Name }} bool
{{- if gt (len .Types) 1 }}
{{ export .Name }} interface{}
{{- range .Types }}
{{ $name }}{{ export .Suffix }} {{ if $isArray }}[]{{ end }}{{ .GoType }}
{{- end }}
{{- else -}}
{{ range .Types }}
{{ export $name }}{{ export .Suffix }} {{ if $isArray }}[]{{ end }}{{ .GoType }}
{{- end }}
{{- end -}}
{{- end }}
}
{{ if .Results }}
{{ unexport $.Name .Name }}Results struct {
{{ range .Results }}
{{ export .Name }} {{ if .IsArray }}[]{{ end }}{{ .GoType }}
{{- end }}
}
{{- end }}
)
{{ range .Params }}
{{- if gt (len .Types) 1 }}
{{ $name := .Name }}
{{ $isArray := .IsArray }}
func (a {{ $ARGS }}) {{ export "get" $name }}() (bool, {{ range .Types }}{{ if $isArray }}[]{{ end }}{{ .GoType }},{{ end }}) {
return a.has{{ export $name }}{{ range .Types }}, a.{{ $name }}{{ export .Suffix }}{{ end }}
}
{{- end }}
{{- end }}
// {{ export .Name }} function {{ .Meta.Short }}
//
// expects implementation of {{ .Name }} function:
// func (h {{ $.Name }}Handler) {{ .Name }}(ctx context.Context, args *{{ $ARGS }}) ({{ if .Results }}results *{{ $RESULTS }}, {{ end }}err error) {
// return
// }
func (h {{ $.Name }}Handler) {{ export .Name }}() *atypes.Function {
return &atypes.Function{
Ref: {{ printf "%q" ( $REF ) }},
Kind: {{ printf "%q" .Kind }},
Labels: {{ printf "%#v" .Labels }},
{{- if .Meta }}
Meta: &atypes.FunctionMeta{
{{- if .Meta.Short }}
Short: {{ printf "%q" .Meta.Short }},
{{- end }}
{{- if .Meta.Description }}
Description: {{ printf "%q" .Meta.Description }},
{{- end }}
{{- if .Meta.Visual }}
Visual: {{ printf "%#v" .Meta.Visual }},
{{- end }}
},
{{- end }}
Parameters: []*atypes.Param{
{{- range .Params }}
{
Name: {{ printf "%q" .Name }},
Types: []string{ {{ range .Types }}{{ printf "%q" .WorkflowType }},{{ end }} },
{{- if .Required }}Required: true,{{ end }}
{{- if .IsArray }}IsArray: true,{{ end }}
{{- if .Meta }}
Meta: &atypes.ParamMeta{
{{- if .Meta.Label }}
Label: {{ printf "%#v" .Meta.Label }},
{{- end }}
{{- if .Meta.Description }}
Description: {{ printf "%#v" .Meta.Description }},
{{- end }}
{{- if .Meta.Visual }}
Visual: {{ printf "%#v" .Meta.Visual }},
{{- end }}
},
{{ end }}
},
{{- end }}
},
{{ if .Results }}
Results: []*atypes.Param{
{{ range .Results }}
{
Name: {{ printf "%q" .Name }},
Types: []string{ {{ printf "%q" .WorkflowType }} },
{{ if .IsArray }}IsArray: true,{{ end -}}
{{ if .Meta -}}
Meta: &atypes.ParamMeta{
{{- if .Meta.Label }}
Label: {{ printf "%#v" .Meta.Label }},
{{- end }}
{{- if .Meta.Description }}
Description: {{ printf "%#v" .Meta.Description }},
{{- end }}
{{- if .Meta.Visual }}
Visual: {{ printf "%#v" .Meta.Visual }},
{{- end }}
},
{{ end }}
},
{{ end }}
},
{{ end }}
{{ if eq .Kind "iterator" }}
Iterator: func(ctx context.Context, in *expr.Vars) (out wfexec.IteratorHandler, err error) {
var (
args = &{{ $ARGS }}{
{{- range .Params }}
has{{ export .Name }}: in.Has({{ printf "%q" .Name }}),
{{- end }}
}
)
{{ template "params" .Params }}
return h.{{ .Name }}(ctx, args)
},
{{ else }}
Handler: func(ctx context.Context, in *expr.Vars) (out *expr.Vars, err error) {
var (
args = &{{ $ARGS }}{
{{- range .Params }}
has{{ export .Name }}: in.Has({{ printf "%q" .Name }}),
{{- end }}
}
)
{{ template "params" .Params }}
{{ if .Results }}
var results *{{ $RESULTS }}
if results, err = h.{{ .Name }}(ctx, args); err != nil {
return
}
out = &expr.Vars{}
{{- range .Results }}
{{ if .IsArray }}
{
// converting results.{{ export .Name }} ({{ .GoType }}) to Array (of {{ .WorkflowType }})
var (
tval expr.TypedValue
tarr = make([]expr.TypedValue, len(results.{{ export .Name }}))
)
for i := range results.{{ export .Name }} {
if tarr[i], err = h.reg.Type({{ printf "%q" .WorkflowType }}).Cast(results.{{ export .Name }}[i]); err != nil {
return
}
}
if tval, err = expr.NewArray(tarr); err != nil {
return
} else if err = expr.Assign(out, {{ printf "%q" .Name }}, tval); err != nil {
return
}
}
{{ else }}
{
// converting results.{{ export .Name }} ({{ .GoType }}) to {{ .WorkflowType }}
var (
tval expr.TypedValue
)
if tval, err = h.reg.Type({{ printf "%q" .WorkflowType }}).Cast(results.{{ export .Name }}); err != nil {
return
} else if err = expr.Assign(out, {{ printf "%q" .Name }}, tval); err != nil {
return
}
}
{{ end }}
{{ end }}
return
{{- else }}
return out, h.{{ .Name }}(ctx, args)
{{- end }}
},
{{ end }}
}
}
{{ end }}
{{ define "params" }}
if err = in.Decode(args); err != nil {
return
}
{{ range . }}
{{ $name := .Name }}
{{ $isArray := .IsArray }}
{{ if gt (len .Types) 1 }}
// Converting {{ export .Name }} argument
if args.has{{ export .Name }} {
aux := expr.Must(expr.Select(in, {{ printf "%q" .Name }}))
switch aux.Type() {
{{- range .Types }}
case h.reg.Type({{ printf "%q" .WorkflowType }}).Type():
args.{{ $name }}{{ export .Suffix }} = aux.Get().({{ if $isArray }}[]{{ end }}{{ .GoType }})
{{- end -}}
}
}
{{- end }}
{{ end }}
{{ end }}

View File

@@ -0,0 +1,55 @@
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
{{- range .Definitions }}
// - {{ .Source }}
{{- end }}
= Resources and events
{{- range .Definitions }}
{{- range .Resources }}
== {{ .ResourceString }}
=== Events
{{- if .BeforeAfter }}
.Before/after events:
{{- range $ba := .BeforeAfter }}
* `before('{{ $ba }}')`
{{- end }}
{{- range $ba := .BeforeAfter }}
* `after('{{ $ba }}')`
{{- end }}
{{- end }}
{{ if .On -}}
.On events:
{{- range $on := .On }}
* `on('{{ $on }}')`
{{- end }}
{{- end }}
=== Exec arguments
.Argument properties:
[%header, cols=3*]
|===
|Name|Type|Mutable
{{- range $p := .Properties }}
| `{{ $p.Name }}`
| `{{ $p.Type }}`
{{- if $p.Immutable }}
| no
{{ else }}
| yes
{{ end -}}
{{ end -}}
|===
{{- end }}
{{- end }}

View File

@@ -0,0 +1,240 @@
package {{ .Package }}
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
// {{ .Source }}
import (
"encoding/json"
{{- range .Imports }}
{{ normalizeImport . }}
{{- end }}
"github.com/cortezaproject/corteza/server/pkg/expr"
)
// dummy placing to simplify import generation logic
var _ = json.NewEncoder
type (
{{ range $r := $.Resources }}
// {{ camelCase $r.ResourceIdent "base" }}
//
// This type is auto-generated.
{{ camelCase $r.ResourceIdent "base" }} struct {
immutable bool
{{- range $r.Properties }}
{{ .Name }} {{ .Type }}
{{- end }}
}
{{ range $event := $r.Events }}
// {{ camelCase $r.ResourceIdent $event }}
//
// This type is auto-generated.
{{ camelCase $r.ResourceIdent $event }} struct {
*{{ camelCase $r.ResourceIdent "base" }}
}
{{ end }}
{{ end }}
)
{{ range $r := $.Resources }}
// ResourceType returns "{{ $r.ResourceString }}"
//
// This function is auto-generated.
func ({{ camelCase .ResourceIdent "base" }}) ResourceType() string {
return "{{ .ResourceString }}"
}
{{ range $event := $r.Events }}
// EventType on {{ camelCase $r.ResourceIdent $event }} returns "{{ $event }}"
//
// This function is auto-generated.
func ({{ camelCase $r.ResourceIdent $event }}) EventType() string {
return "{{ $event }}"
}
{{ end }}
{{ range $event := $r.Events }}
// {{ camelCase "" $r.ResourceIdent $event }} creates {{ $event }} for {{ $r.ResourceString }} resource
//
// This function is auto-generated.
func {{ camelCase "" $r.ResourceIdent $event }}(
{{- range $r.Properties }}
{{- if not .Internal }}
{{ camelCase "arg" .Name }} {{ .Type }},
{{- end -}}
{{- end}}
) *{{ camelCase $r.ResourceIdent $event }} {
return &{{ camelCase $r.ResourceIdent $event }}{
{{ camelCase $r.ResourceIdent "base" }}: &{{ camelCase $r.ResourceIdent "base" }}{
immutable: false,
{{- range $r.Properties }}
{{- if not .Internal }}
{{ .Name }}: {{ camelCase "arg" .Name }},
{{- end -}}
{{- end}}
},
}
}
// {{ camelCase "" $r.ResourceIdent $event "Immutable" }} creates {{ $event }} for {{ $r.ResourceString }} resource
//
// None of the arguments will be mutable!
//
// This function is auto-generated.
func {{ camelCase "" $r.ResourceIdent $event "Immutable" }}(
{{- range $r.Properties }}
{{- if not .Internal }}
{{ camelCase "arg" .Name }} {{ .Type }},
{{- end -}}
{{- end}}
) *{{ camelCase $r.ResourceIdent $event }} {
return &{{ camelCase $r.ResourceIdent $event }}{
{{ camelCase $r.ResourceIdent "base" }}: &{{ camelCase $r.ResourceIdent "base" }}{
immutable: true,
{{- range $r.Properties }}
{{- if not .Internal }}
{{ .Name }}: {{ camelCase "arg" .Name }},
{{- end -}}
{{- end}}
},
}
}
{{ end }}
{{ range $r.Properties }}
{{ if not .Immutable }}
// {{ camelCase "Set" .Name }} sets new {{ .Name }} value
//
// This function is auto-generated.
func (res *{{ camelCase $r.ResourceIdent "base" }}) {{ camelCase "Set" .Name }}({{ camelCase "arg" .Name }} {{ .Type }}) {
res.{{ .Name }} = {{ camelCase "arg" .Name }}
}
{{ end }}
// {{ camelCase "" .Name }} returns {{ .Name }}
//
// This function is auto-generated.
func (res {{ camelCase $r.ResourceIdent "base" }}) {{ camelCase "" .Name }}() {{ .Type }} {
return res.{{ .Name }}
}
{{ end }}
// Encode internal data to be passed as event params & arguments to triggered Corredor script
func (res {{ camelCase .ResourceIdent "base" }}) Encode() (args map[string][]byte, err error) {
{{- if $r.Properties }}
args = make(map[string][]byte)
{{ range $prop := $r.Properties }}
if args["{{ $prop.Name }}"], err = json.Marshal(res.{{ $prop.Name }}); err != nil {
return nil, err
}
{{ end }}
{{ else }}
// Handle argument encoding
{{ end -}}
return
}
// Encode internal data to be passed as event params & arguments to workflow
func (res {{ camelCase .ResourceIdent "base" }}) EncodeVars() (out *expr.Vars, err error) {
{{- if $r.Properties }}
out = &expr.Vars{}
var v expr.TypedValue
{{ range $r.Properties }}
{{- if .ExprType }}
if v, err = automation.{{ export "new" .ExprType }}(res.{{ .Name }}); err == nil {
err = out.Set({{ printf "%q" .Name }},v)
}
if err != nil {
return
}
{{- else }}
// Could not found expression-type counterpart for {{ .Type }}
{{- end }}
{{ end }}
{{ end -}}
_ = v
return
}
// Decode return values from Corredor script into struct props
func (res *{{ camelCase .ResourceIdent "base" }}) Decode(results map[string][]byte)( err error) {
if res.immutable {
// Respect immutability
return
}
{{- if $r.Result }}
if res.{{ $r.Result }} != nil {
if r, ok := results["result"]; ok && len(results) == 1 {
if err = json.Unmarshal(r, res.{{ $r.Result }}); err != nil {
return
}
}
}
{{ end -}}
{{- range $prop := $r.Properties }}
{{- if not $prop.Immutable }}
if res.{{ $prop.Name }} != nil {
if r, ok := results["{{ $prop.Name }}"]; ok {
if err = json.Unmarshal(r, res.{{ $prop.Name }}); err != nil {
return
}
}
}
{{ else }}
// Do not decode {{ $prop.Name }}; marked as immutable
{{ end -}}
{{ end -}}
return
}
func (res *{{ camelCase .ResourceIdent "base" }}) DecodeVars(vars *expr.Vars) (err error) {
if res.immutable {
// Respect immutability
return
}
{{- range $r.Properties }}
{{- if .Immutable }}
// {{ .Name }} marked as immutable
{{- else }}
{{- if .ExprType }}
if res.{{ .Name }} != nil && vars.Has({{ printf "%q" .Name }}) {
var aux *automation.{{ export .ExprType }}
aux, err = automation.{{ export "new" .ExprType }}(expr.Must(vars.Select({{ printf "%q" .Name }})))
if err != nil {
return
}
res.{{ .Name }} = aux.GetValue()
}
{{- else }}
// Could not find expression-type counterpart for {{ .Type }}
{{- end }}
{{- end }}
{{- end }}
return
}
{{ end }}

View File

@@ -0,0 +1,19 @@
package {{ .Package }}
import (
"github.com/cortezaproject/corteza/server/pkg/eventbus"
)
var _=eventbus.ConstraintMaker
// Match returns false if given conditions do not match event & resource internals
func (res {{ camelCase .ResourceIdent "base" }}) Match(c eventbus.ConstraintMatcher) bool {
// By default we match no mather what kind of constraints we receive
//
// Function will be called multiple times - once for every trigger constraint
// All should match (return true):
// constraint#1 AND constraint#2 AND constraint#3 ...
//
// When there are multiple values, Match() can decide how to treat them (OR, AND...)
return true
}

View File

@@ -0,0 +1,45 @@
package rest
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
func getEventTypeDefinitions() []eventTypeDef {
return []eventTypeDef{
{{ range .Definitions }}
{{ range $r := .Resources }}
{{ template "eventTypeDefinitions" dict "res" $r "type" "on" "types" .On }}
{{ template "eventTypeDefinitions" dict "res" $r "type" "before" "types" .BeforeAfter }}
{{ template "eventTypeDefinitions" dict "res" $r "type" "after" "types" .BeforeAfter }}
{{ end }}
{{ end }}
}
}
{{ define "eventTypeDefinitions" }}
{{ range $ev := $.types }}
{
ResourceType: {{ printf "%q" $.res.ResourceString }},
EventType: {{ printf "%q" (camelCase $.type $ev) }},
Properties: []eventTypePropertyDef{
{{ range $.res.Properties }}
{{ if not .Internal }}
{
Name: {{ printf "%q" .Name }},
Type: {{ printf "%q" .ExprType }},
Immutable: {{ printf "%v" .Immutable }},
},
{{ end }}
{{ end }}
},
Constraints: []eventTypeConstraintDef{
{{ range $.res.Constraints }}
{
Name: {{ printf "%q" .Name }},
},
{{ end }}
},
},
{{ end }}
{{ end }}

View File

@@ -0,0 +1,32 @@
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
{{- range .Definitions }}
// - {{ .Source }}
{{- end }}
[cols="2m,3a"]
|===
| Type | Structure
{{- range .Definitions }}
{{- range $tName, $tDef := .Types }}
{{- if gt (len $tDef.Struct) 0}}
| [#objref-{{ toLower $tName }}]#<<objref-{{ toLower $tName }},{{ $tName }}>>#
|
{{- if $tDef.Struct }}
[source]
----
{
{{- range $s := .Struct }}
{{ $s.Name }} ({{ $s.ExprType }})
{{- end }}
}
----
{{ end }}
{{- end }}
{{- end }}
{{ end }}
|===

View File

@@ -0,0 +1,220 @@
package {{ .Package }}
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
// {{ .Source }}
import (
"context"
"fmt"
"sync"
{{- range .Imports }}
{{ normalizeImport . }}
{{- end }}
{{- if ne .Package "expr" }}
. "github.com/cortezaproject/corteza/server/pkg/expr"
{{- end }}
)
var _ = context.Background
var _ = fmt.Errorf
{{ range $exprType, $def := .Types }}
{{ if not $def.CustomType }}
// {{ $exprType }} is an expression type, wrapper for {{ $def.As }} type
type {{ $exprType }} struct{
value {{ $def.As }}
mux sync.RWMutex
}
// New{{ $exprType }} creates new instance of {{ $exprType }} expression type
func New{{ $exprType }}(val interface{}) (*{{ $exprType }}, error) {
if c, err := {{ export "CastTo" $exprType }}(val); err != nil {
return nil, fmt.Errorf("unable to create {{ $exprType }}: %w", err)
} else {
return &{{ $exprType }}{value: c}, nil
}
}
// Get return underlying value on {{ $exprType }}
func (t *{{ $exprType }}) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// GetValue returns underlying value on {{ $exprType }}
func (t *{{ $exprType }}) GetValue() {{ $def.As }} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Type return type name
func ({{ $exprType }}) Type() string { return "{{ $exprType }}" }
// Cast converts value to {{ $def.As }}
func ({{ $exprType }}) Cast(val interface{}) (TypedValue, error) {
return New{{ $exprType }}(val)
}
// Assign new value to {{ $exprType }}
//
// value is first passed through {{ export "CastTo" $exprType }}
func (t *{{ $exprType }}) Assign(val interface{}) (error) {
if c, err := {{ export "CastTo" $exprType }}(val); err != nil {
return err
} else {
t.value = c
return nil
}
}
{{ if $def.Comparable }}
{{ if not $def.CustomComparator }}
// Compare the two {{ $exprType }} values
func (t {{ $exprType }}) Compare(to TypedValue) (int, error) {
c, err := New{{ $exprType }}(to)
if err != nil {
return 0, fmt.Errorf("cannot compare %s and %s: %s", t.Type(), c.Type(), err.Error())
}
switch {
case t.value == c.value:
return 0, nil
case t.value < c.value:
return -1, nil
case t.value > c.value:
return 1, nil
default:
return 0, fmt.Errorf("cannot compare %s and %s: unknown state", t.Type(), c.Type())
}
}
{{ else }}
// Compare the two {{ $exprType }} values
func (t {{ $exprType }}) Compare(to TypedValue) (int, error) {
return compareTo{{ $exprType }}(t, to)
}
{{ end }}
{{ end }}
{{ if $def.Struct }}
{{ if not $def.CustomFieldAssigner }}
func (t *{{ $exprType }}) AssignFieldValue(key string, val TypedValue) error {
t.mux.Lock()
defer t.mux.Unlock()
return {{ $def.AssignerFn }}({{ if not (hasPtr $def.As) }}&{{ end }}t.value, key, val)
}
{{ end }}
{{ if not $def.CustomGValSelector }}
// SelectGVal implements gval.Selector requirements
//
// It allows gval lib to access {{ $exprType }}'s underlying value ({{ $def.As }})
// and it's fields
//
func (t *{{ $exprType }}) SelectGVal(ctx context.Context, k string) (interface{}, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return {{ unexport $exprType "GValSelector" }}(t.value, k)
}
{{ end }}
{{ if not $def.CustomSelector }}
// Select is field accessor for {{ $def.As }}
//
// Similar to SelectGVal but returns typed values
func (t *{{ $exprType }}) Select(k string) (TypedValue, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return {{ unexport $exprType "TypedValueSelector" }}(t.value, k)
}
{{ end }}
func (t *{{ $exprType }}) Has(k string) bool {
t.mux.RLock()
defer t.mux.RUnlock()
switch k {
{{- range $def.Struct }}
{{- if .ExprType }}
case {{ printf "%q" .Name }}{{ if .Alias }}, {{ printf "%q" .Alias }}{{ end }}:
return true
{{- end }}
{{- end }}
}
return false
}
// {{ unexport $exprType "GValSelector" }} is field accessor for {{ $def.As }}
func {{ unexport $exprType "GValSelector" }}(res {{ $def.As }}, k string) (interface{}, error) {
{{- if hasPtr $def.As }}
if res == nil {
return nil, nil
}
{{- end }}
switch k {
{{- range $def.Struct }}
{{- if .ExprType }}
case {{ printf "%q" .Name }}{{ if .Alias }}, {{ printf "%q" .Alias }}{{ end }}:
return res.{{ export .Name }}, nil
{{- end }}
{{- end }}
}
return nil, fmt.Errorf("unknown field '%s'", k)}
// {{ unexport $exprType "TypedValueSelector" }} is field accessor for {{ $def.As }}
func {{ unexport $exprType "TypedValueSelector" }}(res {{ $def.As }}, k string) (TypedValue, error) {
{{- if hasPtr $def.As }}
if res == nil {
return nil, nil
}
{{- end }}
switch k {
{{- range $def.Struct }}
{{- if .ExprType }}
case {{ printf "%q" .Name }}{{ if .Alias }}, {{ printf "%q" .Alias }}{{ end }}:
return {{ export "New" .ExprType }}(res.{{ export .Name }})
{{- end }}
{{- end }}
}
return nil, fmt.Errorf("unknown field '%s'", k)
}
{{ if $def.BuiltInAssignerFn }}
// {{ $def.AssignerFn }} is field value setter for {{ $def.As }}
//
// Value types are passed by pointer, otherwise assigned values are lost
func {{ $def.AssignerFn }}(res {{ if not (hasPtr $def.As) }}*{{ end }}{{ $def.As }}, k string, val interface{}) (error) {
switch k {
{{- range $def.Struct }}
case {{ printf "%q" .Name }}{{ if .Alias }}, {{ printf "%q" .Alias }}{{ end }}:
{{- if .Readonly }}
return fmt.Errorf("field '%s' is read-only", k)
{{- else }}
aux, err := {{ export "CastTo" .ExprType }}(val)
if err != nil {
return err
}
res.{{ export .Name }} = aux
return nil
{{- end }}
{{- end }}
}
return fmt.Errorf("unknown field '%s'", k)
}
{{ end }}
{{ end }} {{/* if $def.Struct */}}
{{ end }} {{/* if not $def.CustomType */}}
{{ end }} {{/* types loop */}}

View File

@@ -0,0 +1,66 @@
package handlers
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
// {{ .Source }}
import (
"context"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/cortezaproject/corteza/server/{{ .App }}/rest/request"
"github.com/cortezaproject/corteza/server/pkg/api"
)
type (
// Internal API interface
{{ export $.Endpoint.Entrypoint }}API interface {
{{- range $a := $.Endpoint.Apis }}
{{ export $a.Name }}(context.Context, *request.{{ export $.Endpoint.Entrypoint $a.Name }}) (interface{}, error)
{{- end }}
}
// HTTP API interface
{{ export .Endpoint.Entrypoint }} struct {
{{- range $a := .Endpoint.Apis }}
{{ export $a.Name }} func(http.ResponseWriter, *http.Request)
{{- end }}
}
)
func {{ export "New" $.Endpoint.Entrypoint }}(h {{ export $.Endpoint.Entrypoint }}API) *{{ export $.Endpoint.Entrypoint }} {
return &{{ export $.Endpoint.Entrypoint }}{
{{- range $a := .Endpoint.Apis }}
{{ export $a.Name }}: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.New{{ export $.Endpoint.Entrypoint $a.Name }}()
if err := params.Fill(r); err != nil {
api.Send(w, r, err)
return
}
value, err := h.{{ export $a.Name }}(r.Context(), params)
if err != nil {
api.Send(w, r, err)
return
}
api.Send(w, r, value)
},
{{- end }}
}
}
func (h {{ export $.Endpoint.Entrypoint }}) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) {
r.Group(func(r chi.Router) {
r.Use(middlewares...)
{{- range $a := .Endpoint.Apis }}
r.{{ export ( toLower $a.Method ) }}("{{ $.Endpoint.Path }}{{ $a.Path }}", h.{{ export $a.Name }})
{{- end }}
})
}

View File

@@ -0,0 +1,222 @@
package request
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
// {{ .Source }}
import (
"encoding/json"
"github.com/cortezaproject/corteza/server/pkg/payload"
"github.com/go-chi/chi/v5"
"io"
"fmt"
"mime/multipart"
"net/http"
"strings"
{{- range .Imports }}
{{ normalizeImport . }}
{{- end }}
)
// dummy vars to prevent
// unused imports complain
var (
_ = chi.URLParam
_ = multipart.ErrMessageTooLarge
_ = payload.ParseUint64s
_ = strings.ToLower
_ = io.EOF
_ = fmt.Errorf
_ = json.NewEncoder
)
type (
// Internal API interface
{{- range $a := $.Endpoint.Apis }}
{{ export $.Endpoint.Entrypoint $a.Name }} struct {
{{- range $p := $a.Params.All }}
// {{ export $p.Name }} {{ $p.Origin }} parameter
//
// {{ $p.Title }}
{{ export $p.Name }} {{ $p.Type }} {{ $p.FieldTag }}
{{ end }}
}
{{ end }}
)
{{- range $a := $.Endpoint.Apis }}
// {{ export "New" $.Endpoint.Entrypoint $a.Name }} request
func {{ export "New" $.Endpoint.Entrypoint $a.Name }}() *{{ export $.Endpoint.Entrypoint $a.Name }} {
return &{{ export $.Endpoint.Entrypoint $a.Name }}{}
}
// Auditable returns all auditable/loggable parameters
func (r {{ export $.Endpoint.Entrypoint $a.Name }}) Auditable() map[string]interface{} {
return map[string]interface{}{
{{- range $p := $a.Params.All }}
{{- if not $p.Sensitive }}
"{{ $p.Name }}": r.{{ export $p.Name }},
{{- end }}
{{- end }}
}
}
{{- range $p := $a.Params.All }}
// Auditable returns all auditable/loggable parameters
func (r {{ export $.Endpoint.Entrypoint $a.Name }}) Get{{ export $p.Name }}() {{ $p.Type }} {
return r.{{ export $p.Name }}
}
{{- end }}
// Fill processes request and fills internal variables
func (r *{{ export $.Endpoint.Entrypoint $a.Name }}) Fill(req *http.Request) (err error) {
{{ if $a.Params.Post }}
if strings.HasPrefix(strings.ToLower(req.Header.Get("content-type")), "application/json") {
err = json.NewDecoder(req.Body).Decode(r)
switch {
case err == io.EOF:
err = nil
case err != nil:
return fmt.Errorf("error parsing http request body: %w", err)
}
}
{{- end }}
{{ if $a.Params.Get }}
{
// GET params
tmp := req.URL.Query()
{{ range $p := $a.Params.Get }}
{{- if or $p.IsSlice $p.HasExplicitParser }}
if val, ok := tmp["{{ $p.Name }}[]"]; ok {
r.{{ export $p.Name }}, err = {{ $p.Parser "val" }}
if err != nil {
return err
}
} else if val, ok := tmp["{{ $p.Name }}"]; ok {
r.{{ export $p.Name }}, err = {{ $p.Parser "val" }}
if err != nil {
return err
}
}
{{- else }}
if val, ok := tmp["{{ $p.Name }}"]; ok && len(val) > 0 {
r.{{ export $p.Name }}, err = {{ $p.Parser "val[0]" }}
if err != nil {
return err
}
}
{{- end }}
{{- end }}
}
{{- end }}
{{ if $a.Params.Post }}
{
// Caching 32MB to memory, the rest to disk
if err = req.ParseMultipartForm(32 << 20); err != nil && err != http.ErrNotMultipart {
return err
} else if err == nil {
// Multipart params
{{ range $p := $a.Params.Post }}
{{ if $p.IsUpload }}
// Ignoring {{ $p.Name }} as its handled in the POST params section
{{- else }}
{{- if or $p.HasExplicitParser }}
if val, ok := req.MultipartForm.Value["{{ $p.Name }}[]"]; ok {
r.{{ export $p.Name }}, err = {{ $p.Parser "val" }}
if err != nil {
return err
}
} else if val, ok := req.MultipartForm.Value["{{ $p.Name }}"]; ok {
r.{{ export $p.Name }}, err = {{ $p.Parser "val" }}
if err != nil {
return err
}
}
{{- else if not $p.IsSlice }}
if val, ok := req.MultipartForm.Value["{{ $p.Name }}"]; ok && len(val) > 0 {
r.{{ export $p.Name }}, err = {{ $p.Parser "val[0]" }}
if err != nil {
return err
}
}
{{- end }}
{{- end }}
{{- end }}
}
}
{
if err = req.ParseForm(); err != nil {
return err
}
// POST params
{{ range $p := $a.Params.Post }}
{{ if $p.IsUpload }}
if _, r.{{ export $p.Name }}, err = req.FormFile("{{ $p.Name }}"); err != nil {
return fmt.Errorf("error processing uploaded file: %w", err)
}
{{ else }}
{{- if or $p.HasExplicitParser }}
if val, ok := req.Form["{{ $p.Name }}[]"]; ok {
r.{{ export $p.Name }}, err = {{ $p.Parser "val" }}
if err != nil {
return err
}
} else if val, ok := req.Form["{{ $p.Name }}"]; ok {
r.{{ export $p.Name }}, err = {{ $p.Parser "val" }}
if err != nil {
return err
}
}
{{- else if or $p.IsSlice }}
//if val, ok := req.Form["{{ $p.Name }}[]"]; ok && len(val) > 0 {
// r.{{ export $p.Name }}, err = {{ $p.Parser "val" }}
// if err != nil {
// return err
// }
//}
{{- else }}
if val, ok := req.Form["{{ $p.Name }}"]; ok && len(val) > 0 {
r.{{ export $p.Name }}, err = {{ $p.Parser "val[0]" }}
if err != nil {
return err
}
}
{{- end }}
{{- end }}
{{- end }}
}
{{ end }}
{{ if $a.Params.Path }}
{
var val string
// path params
{{ range $p := $a.Params.Path }}
val = chi.URLParam(req, "{{ $p.Name }}")
r.{{ export $p.Name }}, err = {{ $p.Parser "val" }}
if err != nil {
return err
}
{{ end }}
}
{{ end }}
return err
}
{{- end }}

View File

@@ -0,0 +1,41 @@
package {{ .Package }}
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
// {{ .Source }}
import (
labelTypes "github.com/cortezaproject/corteza/server/pkg/label/types"
)
{{ range $name, $set := .Types }}
{{ if $set.LabelResourceType }}
// SetLabel adds new label to label map
func (m *{{ $name }}) SetLabel(key string, value labelTypes.LabelValue) {
if m.Labels == nil {
m.Labels = make(map[string]labelTypes.LabelValue)
}
m.Labels[key] = value
}
// GetLabels adds new label to label map
func (m {{ $name }}) GetLabels() map[string]labelTypes.LabelValue {
return m.Labels
}
// GetLabels adds new label to label map
func ({{ $name }}) LabelResourceKind() string {
return {{ printf "%q" $set.LabelResourceType }}
}
// GetLabels adds new label to label map
func (m {{ $name }}) LabelResourceID() uint64 {
return m.ID
}
{{ end }}
{{ end }}

View File

@@ -0,0 +1,89 @@
package {{ .Package }}
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
// {{ .Source }}
{{ if .Imports }}
import (
{{ range $i, $import := .Imports }}
"{{ $import }}"
{{ end }}
)
{{ end }}
type (
{{ range $name, $set := .Types }}
// {{ $name }}Set slice of {{ $name }}
//
// This type is auto-generated.
{{ $name }}Set []*{{ $name }}
{{ end }}
)
{{ range $name, $set := .Types }}
// Walk iterates through every slice item and calls w({{ $name }}) err
//
// This function is auto-generated.
func (set {{ $name }}Set) Walk(w func(*{{ $name }}) error) (err error) {
for i := range set {
if err = w(set[i]); err != nil {
return
}
}
return
}
// Filter iterates through every slice item, calls f({{ $name }}) (bool, err) and return filtered slice
//
// This function is auto-generated.
func (set {{ $name }}Set) Filter(f func(*{{ $name }}) (bool, error)) (out {{ $name }}Set, err error) {
var ok bool
out = {{ $name }}Set{}
for i := range set {
if ok, err = f(set[i]); err != nil {
return
} else if ok {
out = append(out, set[i])
}
}
return
}
{{ if not $set.NoIdField }}
// FindByID finds items from slice by its ID property
//
// This function is auto-generated.
func (set {{ $name }}Set) FindByID(ID uint64) *{{ $name }} {
for i := range set {
if set[i].ID == ID {
return set[i]
}
}
return nil
}
// IDs returns a slice of uint64s from all items in the set
//
// This function is auto-generated.
func (set {{ $name }}Set) IDs() (IDs []uint64) {
IDs = make([]uint64, len(set))
for i := range set {
IDs[i] = set[i].ID
}
return
}
{{ end }}
{{ end }}

View File

@@ -0,0 +1,116 @@
package {{ .Package }}
// This file is auto-generated.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// Definitions file that controls how this file is generated:
// {{ .Source }}
import (
"fmt"
"github.com/stretchr/testify/require"
"testing"
{{ range $i, $import := .Imports }}
"{{ $import }}"
{{ end }}
)
{{ range $name, $set := .Types }}
func Test{{ $name }}SetWalk(t *testing.T) {
var (
value = make({{ $name }}Set, 3)
req = require.New(t)
)
// check walk with no errors
{
err := value.Walk(func(*{{ $name }}) error {
return nil
})
req.NoError(err)
}
// check walk with error
req.Error(value.Walk(func(*{{ $name }}) error { return fmt.Errorf("walk error") }))
}
func Test{{ $name }}SetFilter(t *testing.T) {
var (
value = make({{ $name }}Set, 3)
req = require.New(t)
)
// filter nothing
{
set, err := value.Filter(func(*{{ $name }}) (bool, error) {
return true, nil
})
req.NoError(err)
req.Equal(len(set), len(value))
}
// filter one item
{
found := false
set, err := value.Filter(func(*{{ $name }}) (bool, error) {
if !found {
found = true
return found, nil
}
return false, nil
})
req.NoError(err)
req.Len(set, 1)
}
// filter error
{
_, err := value.Filter(func(*{{ $name }}) (bool, error) {
return false, fmt.Errorf("filter error")
})
req.Error(err)
}
}
{{ if not $set.NoIdField }}
func Test{{ $name }}SetIDs(t *testing.T) {
var (
value = make({{ $name }}Set, 3)
req = require.New(t)
)
// construct objects
value[0] = new({{ $name }})
value[1] = new({{ $name }})
value[2] = new({{ $name }})
// set ids
value[0].ID = 1
value[1].ID = 2
value[2].ID = 3
// Find existing
{
val := value.FindByID(2)
req.Equal(uint64(2), val.ID)
}
// Find non-existing
{
val := value.FindByID(4)
req.Nil(val)
}
// List IDs from set
{
val := value.IDs()
req.Equal(len(val), len(value))
}
}
{{ end }}
{{ end }}