diff --git a/entc/gen/internal/bindata.go b/entc/gen/internal/bindata.go index 48aebc2a1..659bf8547 100644 --- a/entc/gen/internal/bindata.go +++ b/entc/gen/internal/bindata.go @@ -884,7 +884,7 @@ func templateHeaderTmpl() (*asset, error) { return a, nil } -var _templateHookTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xdc\x54\x5d\x8f\xa4\x44\x14\x7d\x86\x5f\x71\x24\x4c\x02\x9b\xb6\x58\xf7\x4d\x13\x1f\x36\xe3\x6c\x9c\x64\x9d\x36\x3a\xfa\x62\x7c\xa8\x85\x4b\x53\x02\x55\xa4\xaa\x98\xed\x09\xf2\xdf\xcd\x2d\xa0\x07\xb7\xcd\x26\x26\x3e\xf9\xd2\x9d\xdc\x7b\xee\x47\x9d\x73\x2e\xd3\x54\xbc\x8a\x6f\xcd\xf0\x6c\xd5\xa9\xf1\x78\xf3\xfa\xab\xaf\xbf\x1c\x2c\x39\xd2\x1e\xef\x64\x49\x1f\x8c\x69\x71\xaf\x4b\x81\xb7\x5d\x87\x00\x72\xe0\xbc\x7d\xa2\x4a\xc4\x8f\x8d\x72\x70\x66\xb4\x25\xa1\x34\x15\x41\x39\x74\xaa\x24\xed\xa8\xc2\xa8\x2b\xb2\xf0\x0d\xe1\xed\x20\xcb\x86\xf0\x46\xbc\xde\xb2\xa8\xcd\xa8\xab\x58\xe9\x90\x7f\x7f\x7f\x7b\xf7\xf0\xf3\x1d\x6a\xd5\x11\xd6\x98\x35\xc6\xa3\x52\x96\x4a\x6f\xec\x33\x4c\x0d\xbf\x1b\xe6\x2d\x91\x88\x5f\x15\xf3\x1c\xc7\xd3\x84\x8a\x6a\xa5\x09\x49\x63\x4c\x9b\x60\x0d\x7e\x54\xbe\x01\x9d\x3d\xe9\x0a\x29\x92\x1f\x65\xd9\xca\x13\x25\x3b\x54\x34\x4d\xf0\xd4\x0f\x9d\xf4\x5c\x4c\xb2\x22\x9b\x40\x70\x6a\x9a\xc0\x75\xdc\x4a\xf5\x83\xb1\x1e\xc9\x34\x21\x15\xb7\x46\xd7\xea\x24\xd6\x66\x98\xe7\x24\xcc\x4a\x87\xf6\x84\x6f\xbe\xc5\x07\xe9\xe8\x9f\x50\x01\x64\xa5\x3e\x11\x52\xcd\xc0\x54\x3c\x98\x8a\xdc\xb6\x45\xaa\x65\x4f\x1c\x1f\xac\xd2\x1e\xa9\x16\x0f\x1c\x48\xde\x8d\xba\xbc\xac\x9a\xfa\xe7\xe1\x05\x54\x23\x79\x75\xe3\xc4\x8d\x4b\x96\xe9\xa9\x16\x3f\x8c\x5e\x7a\x65\x74\xa8\xe5\xa1\x51\x51\xe0\xb1\x21\x5c\x26\xcc\x33\x42\x13\xe5\x20\x35\x64\x25\x07\xcf\x1a\x19\xc8\xae\x33\x1f\x03\xf1\xa3\x23\x66\xdb\xd8\x4a\x69\x69\x9f\x43\x8f\x7a\xd4\x25\x37\x86\x74\x4b\x2f\xb1\x8e\x40\xcf\x23\x8d\x15\x71\x14\xfa\xee\x07\x71\x51\x56\x1a\xed\xe9\xec\x99\x11\xfe\x3f\xe0\xf2\x8e\x79\xce\x91\x6d\xd4\xcd\xb3\xf8\x55\x76\x23\x1d\x40\xd6\x1a\x9b\x2f\xab\x87\xf7\x10\x4a\xd9\x75\x0e\x75\x56\xfa\xf3\x01\x7d\x2e\xe2\x88\x5b\x23\xab\xf7\xe3\xf2\x15\xcd\x28\x5c\x4d\xed\xb1\x9b\xb4\xd1\xf4\x99\xf9\x98\xe2\x28\xea\x9f\x0e\x30\x2d\x13\xde\x8b\x6c\xbf\x77\x1c\x45\xaa\xc6\x17\xa6\x0d\xb0\xc8\x92\x1f\xad\x86\x56\xdd\x01\x75\xef\xc5\x1d\xb7\xa8\xb3\x64\xd4\x74\x1e\xa8\xf4\x54\x2d\x34\x31\x81\xa1\xc5\xcd\xa3\xc0\x92\xda\xd3\x91\xf0\xe3\xe2\x28\x9a\xe3\x4b\xcb\xed\xcd\x4f\x79\x1c\xfd\xcd\x93\x45\x81\xa3\x06\x9d\xa9\x1c\x3d\xb9\xa0\xdb\x49\x3d\x91\x06\x7b\x1b\x46\x77\xeb\xc5\x6c\x61\x33\x90\x0d\x0b\x88\xb8\x28\xe2\xa2\x88\x18\x27\x8e\x3a\x7b\x6f\x4e\x87\x3d\x37\xdf\x51\x47\x9e\xfe\xdc\x45\x6e\x2d\x49\x4f\x39\xd7\x05\xda\x8f\x3a\x6b\xda\x7d\xc9\xf7\xc6\xb4\x07\x98\x61\x1f\x3b\x0e\xf9\xa7\x10\xe6\x6a\x7b\x16\x3b\x43\xd3\xd9\x5f\xa9\x12\xa8\xbf\x8a\x05\x9a\xd7\xda\x4f\xb3\xc4\x27\x92\x2d\x5e\xfb\xcf\x94\x67\x79\x7b\x71\x1c\xb2\x5c\xdc\xbb\xcc\x0c\x6b\x74\xdb\xa1\x69\xc3\xf6\xb9\x78\xb1\xdc\xaa\x5d\x10\xef\x62\x08\x5e\xe4\x0a\x32\x07\x2d\x17\x0d\x7f\xa2\x3f\xd8\x04\x0b\xde\x41\x2e\xf2\xf9\x46\x72\x8c\x53\x8e\x0f\xf3\x45\x3d\xb7\xe4\x7a\xe9\xcb\x06\x66\xd8\xc4\x5c\xce\xe1\x31\x07\xf3\xec\xb2\x1c\xbf\xfd\x7e\x4d\x7e\x51\x5c\x16\xbb\x4a\x2f\xd9\x68\x59\x27\xfb\xac\x1d\x7e\x19\x2a\xb6\xc3\x21\x54\xcc\xfc\x3b\x5f\xac\xb1\xd6\x5f\x5b\x81\xb4\xff\xbf\x79\xe0\xea\xda\x6f\xdc\x8b\x4e\xfc\x7d\xd5\xc6\x2f\x5f\x55\xaa\xf8\xb2\x43\xa7\x7f\x69\x91\xcb\xc1\xff\x15\x00\x00\xff\xff\x28\xef\xa0\xa2\xa7\x07\x00\x00") +var _templateHookTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xe4\x56\x41\x6f\xdc\x36\x13\x3d\x4b\xbf\x62\x3e\x61\x0d\x48\xf9\x64\xca\xc9\xad\x0d\x5c\x20\x70\x1d\x34\x40\x6a\x17\xad\xdb\x4b\x90\x03\x23\x8d\x56\xec\x52\xa4\x40\x52\xde\x5d\xa8\xfa\xef\xc5\x90\xd2\x5a\xb6\x0a\xc3\x08\x82\x5e\x7a\x49\xbc\x33\xc3\x99\xe1\x7b\x6f\x86\x1a\x86\xe2\x55\x7c\xa5\xbb\xa3\x11\xdb\xc6\xc1\x9b\x8b\xd7\xdf\x9d\x77\x06\x2d\x2a\x07\xef\x79\x89\x5f\xb4\xde\xc1\x07\x55\x32\x78\x27\x25\xf8\x20\x0b\xe4\x37\xf7\x58\xb1\xf8\xae\x11\x16\xac\xee\x4d\x89\x50\xea\x0a\x41\x58\x90\xa2\x44\x65\xb1\x82\x5e\x55\x68\xc0\x35\x08\xef\x3a\x5e\x36\x08\x6f\xd8\xc5\xec\x85\x5a\xf7\xaa\x8a\x85\xf2\xfe\x8f\x1f\xae\xae\x6f\x7e\xbb\x86\x5a\x48\x84\xc9\x66\xb4\x76\x50\x09\x83\xa5\xd3\xe6\x08\xba\x06\xb7\x28\xe6\x0c\x22\x8b\x5f\x15\xe3\x18\xc7\xc3\x00\x15\xd6\x42\x21\x24\x8d\xd6\xbb\x04\x26\xe3\x5e\xb8\x06\xf0\xe0\x50\x55\xb0\x81\xe4\x17\x5e\xee\xf8\x16\x93\x45\x54\x34\x0c\xe0\xb0\xed\x24\x77\x74\x18\x79\x85\x26\x01\x46\xae\x61\x00\x3a\x47\xa9\x44\xdb\x69\xe3\x20\x19\x06\xd8\xb0\x2b\xad\x6a\xb1\x65\x53\x32\x18\xc7\xc4\xd7\xda\x74\xbb\x2d\x7c\x7f\x09\x5f\xb8\xc5\x7f\x8a\xf2\x41\x86\xab\x2d\xc2\x46\x51\xe0\x86\xdd\xe8\x0a\xed\xdc\xc5\x46\xf1\x16\xc9\xde\x19\xa1\x1c\x6c\x14\xbb\x21\x43\xf2\xbe\x57\xe5\xa9\xd5\x8d\x3b\x76\x0f\x41\x35\x24\xaf\xce\x2c\x3b\xb3\x49\xa8\xbe\x51\xec\xe7\xde\x71\x27\xb4\xf2\x67\xa9\x68\x54\x14\x70\xd7\x20\x9c\x2a\x8c\x23\xf8\x24\xc2\x02\x57\xc0\x2b\xde\x39\xe2\x48\x03\x97\x52\xef\x3d\xf0\xbd\x45\x42\x5b\x9b\x4a\x28\x6e\x8e\x3e\x47\xdd\xab\x92\x12\x03\xb7\x21\x17\x9b\x4a\x40\x4b\x25\xb5\x61\x71\xe4\xf3\x2e\x0b\xd1\xa1\xb4\xd4\xca\xe1\xc1\x11\x22\xf4\x7f\x0e\xa7\x7b\x8c\x63\x06\xe9\x0c\xdd\x38\xb2\x3f\xb8\xec\x31\x07\x34\x46\x9b\x2c\xb4\xee\xef\x83\x50\x72\x29\x2d\xd4\x69\xe9\x0e\x39\xb4\x19\x8b\x23\x4a\x0d\x69\xbd\x2c\x97\x4d\xd1\x14\x05\xab\xaa\x2d\x2c\x2a\xcd\x30\x3d\x53\x1f\x86\x38\x8a\xda\xfb\x1c\xf4\x8e\x00\x6f\x59\xba\xec\x3b\x8e\x22\x51\xc3\xff\xf4\xce\x87\x45\x06\x5d\x6f\x14\x28\x21\x73\xa8\x5b\xc7\xae\x29\x45\x9d\x26\xbd\xc2\x43\x87\xa5\xc3\x2a\xc0\x44\x00\xfa\x14\x67\x77\x0c\x82\x6b\x09\x47\x42\x97\x8b\xa3\x68\x8c\x4f\x29\xe7\x3b\xdf\x67\x71\xf4\x48\x93\x45\x01\xb7\x0a\xf0\x80\x65\xef\xd0\x7a\xde\xb6\xe2\x1e\x15\x90\xb6\x41\x2b\x39\x4d\xcc\x6c\xd6\x1d\x1a\xdf\x00\x8b\x8b\x22\x2e\x8a\x88\xe2\xd8\xad\x4a\x3f\xea\x6d\xbe\xc4\xe6\x47\x94\xe8\xf0\xaf\x85\xe5\xca\x20\x77\x98\xd1\x39\x0f\xfb\xad\x4a\x9b\xdd\xf2\xc8\x4f\x5a\xef\x72\xd0\xdd\xd2\x76\xdb\x65\x4f\x43\x08\xab\xf9\x5a\xa4\x0c\x85\x07\xb7\x62\xc5\x43\xbf\xb2\x79\x98\xa7\xb3\x4f\xbd\x48\x23\x92\x06\xad\x7d\x33\xe6\x89\xde\x96\xdd\x76\x69\xc6\x3e\xd8\x54\x77\x93\x75\xee\xa1\xd9\xf9\xee\x33\xf6\x20\xb9\x89\x3b\x4f\xde\x49\x10\xd4\xc8\x2a\x64\xf4\x5c\x06\x0e\x7f\xc5\x3f\x49\x04\x21\xde\x02\x0f\xf4\xb9\x86\x93\x8d\x5c\x96\x06\xf3\x81\x3d\x1b\x7c\x2d\x77\x65\x03\xba\x9b\xc9\x0c\xe3\x70\x97\x01\xe1\x6c\xd3\x0c\x3e\x7d\x5e\x83\x5f\x14\xa7\xc6\x56\xee\xe0\x8d\x42\x3b\xe9\xb3\x72\xf8\xbd\xab\x48\x0e\xb9\x3f\x31\xd2\xbf\xe3\x49\x1a\xd3\xf9\xff\x92\x14\x56\x43\x7f\x66\x1f\xe8\xa2\x35\xab\xb4\x0b\xcb\x15\x2b\x1a\x70\x9f\xe9\x2b\x94\x72\xd5\x70\xa1\x80\x7b\x45\x90\x50\xa4\xb0\x8e\x46\x9c\x04\x43\xbb\xbc\xa2\x5a\x58\xd7\x58\x3a\x71\x8f\xf2\x08\xa2\xa5\x9d\xf3\x45\x22\x0b\xcb\x82\x5e\x68\x3f\xc9\x55\x0e\xc2\xc1\x5e\x48\x09\x5c\xee\xf9\xd1\x42\xa3\x65\xe5\x77\x85\xa5\x55\x6a\x71\x91\x78\x7a\x8c\xbd\x43\x9b\x0a\x0d\x8b\xfd\xb6\x0a\xed\x58\x67\x7a\xda\x61\x71\x14\xa2\x57\xba\x9a\x9a\xbf\xc1\x7d\x38\x10\x3a\xa0\xfe\x15\xee\xa1\xf4\xb6\xb9\x16\x0b\x1a\x9a\x63\xd3\x90\x92\x31\xf6\x24\x67\x36\x15\x7f\xd0\x90\xff\x3d\xf0\xae\x43\x55\xa5\xab\x1e\x52\x25\x64\x96\x4f\x35\x18\xcb\x66\x44\xbd\x10\x7d\x0b\x61\x7f\xae\x11\x9d\xc7\x92\xbc\xb5\x50\x5c\x7a\xdf\xd4\x67\x5a\x86\xba\x61\xe8\xd2\x6f\xae\xf1\x5a\x1b\x10\xf4\xf6\x48\x54\x69\xc9\x7c\x57\x19\x9c\xc3\xeb\xb7\x20\xe0\x87\x4b\xb8\x78\x0b\xe2\xfc\x3c\x88\xd1\xe7\xbe\x84\x29\xea\x93\xf8\x1c\xd6\xd3\xe3\xb7\xe4\xdf\x99\x96\x17\x0b\xfa\x9d\xa7\x6b\xfa\x3e\x23\x45\x78\x2a\x72\xe0\x55\x25\xd4\x36\xa8\xae\xc3\x52\xd4\x02\x2b\x8f\x3b\x1d\xe2\x13\x55\x9c\xa8\x52\x78\xd2\xe7\xe9\x79\xad\xa5\xde\xaf\x08\x0a\xa5\x5e\x22\x28\x85\x7b\xbf\x42\xfd\x9b\xcf\x77\xb8\x56\x53\x0e\x17\xf9\x23\x4a\xfe\x4f\x3f\xc2\x9f\xd9\x22\xc1\x25\x4c\x7a\x9c\x2d\xf9\x4c\x0f\x69\xf0\xf9\xc0\x45\xd8\x23\x85\xcf\x11\x33\x84\xd7\xe1\xdb\xf6\x65\x10\x7a\xdf\xd7\x63\x18\x6a\xa5\x61\x64\x27\xdb\xd3\x39\x2c\xd9\x84\xb4\x8f\x5a\xdc\x36\x7c\xfe\x4e\xdf\x2e\x7f\x07\x00\x00\xff\xff\xe5\x75\x44\xe4\x73\x0c\x00\x00") func templateHookTmplBytes() ([]byte, error) { return bindataRead( @@ -899,7 +899,7 @@ func templateHookTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "template/hook.tmpl", size: 1959, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + info := bindataFileInfo{name: "template/hook.tmpl", size: 3187, mode: os.FileMode(420), modTime: time.Unix(1, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/entc/gen/template/hook.tmpl b/entc/gen/template/hook.tmpl index e2570c6db..5692d6a95 100644 --- a/entc/gen/template/hook.tmpl +++ b/entc/gen/template/hook.tmpl @@ -55,7 +55,7 @@ func On(hk {{ $pkg }}.Hook, op {{ $pkg }}.Op) {{ $pkg }}.Hook { // } // } // -func Reject(op {{ $pkg }}.Op) ent.Hook { +func Reject(op {{ $pkg }}.Op) {{ $pkg }}.Hook { return func(next {{ $pkg }}.Mutator) {{ $pkg }}.Mutator { return {{ $pkg }}.MutateFunc(func(ctx context.Context, m {{ $pkg }}.Mutation) ({{ $pkg }}.Value, error) { if m.Op().Is(op) { @@ -65,4 +65,43 @@ func Reject(op {{ $pkg }}.Op) ent.Hook { }) } } -{{ end }} \ No newline at end of file + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []{{ $pkg }}.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...{{ $pkg }}.Hook) Chain { + return Chain{append([]{{ $pkg }}.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() {{ $pkg }}.Hook { + return func(next {{ $pkg }}.Mutator) {{ $pkg }}.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return {{ $pkg }}.MutateFunc(func(ctx context.Context, m {{ $pkg }}.Mutation) ({{ $pkg }}.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...{{ $pkg }}.Hook) Chain { + newHooks := make([]{{ $pkg }}.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} + +{{ end }} diff --git a/entc/integration/config/ent/hook/hook.go b/entc/integration/config/ent/hook/hook.go index 595de2382..ee0914c2c 100644 --- a/entc/integration/config/ent/hook/hook.go +++ b/entc/integration/config/ent/hook/hook.go @@ -59,3 +59,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/entc/integration/customid/ent/hook/hook.go b/entc/integration/customid/ent/hook/hook.go index aad4d8d07..0fe4acb9f 100644 --- a/entc/integration/customid/ent/hook/hook.go +++ b/entc/integration/customid/ent/hook/hook.go @@ -111,3 +111,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/entc/integration/ent/hook/hook.go b/entc/integration/ent/hook/hook.go index 495881c29..cd38f0788 100644 --- a/entc/integration/ent/hook/hook.go +++ b/entc/integration/ent/hook/hook.go @@ -202,3 +202,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/entc/integration/gremlin/ent/hook/hook.go b/entc/integration/gremlin/ent/hook/hook.go index d56cde064..c343b59d2 100644 --- a/entc/integration/gremlin/ent/hook/hook.go +++ b/entc/integration/gremlin/ent/hook/hook.go @@ -202,3 +202,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/entc/integration/hooks/ent/hook/hook.go b/entc/integration/hooks/ent/hook/hook.go index abcd7461e..a8585c6ae 100644 --- a/entc/integration/hooks/ent/hook/hook.go +++ b/entc/integration/hooks/ent/hook/hook.go @@ -72,3 +72,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/entc/integration/hooks/hooks_test.go b/entc/integration/hooks/hooks_test.go index 490afb233..b8d1bd6d8 100644 --- a/entc/integration/hooks/hooks_test.go +++ b/entc/integration/hooks/hooks_test.go @@ -3,6 +3,7 @@ package hooks import ( "context" "fmt" + "sort" "testing" "github.com/facebookincubator/ent/entc/integration/hooks/ent" @@ -58,6 +59,30 @@ func TestRuntimeHooks(t *testing.T) { require.Equal(t, 4, calls) } +func TestRuntimeChain(t *testing.T) { + ctx := context.Background() + client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1", ent.Log(t.Log)) + require.NoError(t, err) + defer client.Close() + require.NoError(t, client.Schema.Create(ctx)) + var ( + chain hook.Chain + values []int + ) + for value := 0; value < 5; value++ { + chain = chain.Append(func(next ent.Mutator) ent.Mutator { + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + values = append(values, value) + return next.Mutate(ctx, m) + }) + }) + } + client.User.Use(chain.Hook()) + client.User.Create().SetName("alexsn").SaveX(ctx) + require.Len(t, values, 5) + require.True(t, sort.IntsAreSorted(values)) +} + func TestMutationClient(t *testing.T) { ctx := context.Background() client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") diff --git a/entc/integration/idtype/ent/hook/hook.go b/entc/integration/idtype/ent/hook/hook.go index 3f79984cd..a87213084 100644 --- a/entc/integration/idtype/ent/hook/hook.go +++ b/entc/integration/idtype/ent/hook/hook.go @@ -59,3 +59,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/entc/integration/json/ent/hook/hook.go b/entc/integration/json/ent/hook/hook.go index 5f115b234..080067021 100644 --- a/entc/integration/json/ent/hook/hook.go +++ b/entc/integration/json/ent/hook/hook.go @@ -59,3 +59,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/entc/integration/migrate/entv1/hook/hook.go b/entc/integration/migrate/entv1/hook/hook.go index 315a444f0..5e322ccc6 100644 --- a/entc/integration/migrate/entv1/hook/hook.go +++ b/entc/integration/migrate/entv1/hook/hook.go @@ -10,7 +10,6 @@ import ( "context" "fmt" - "github.com/facebookincubator/ent/entc/integration/ent" "github.com/facebookincubator/ent/entc/integration/migrate/entv1" ) @@ -63,7 +62,7 @@ func On(hk entv1.Hook, op entv1.Op) entv1.Hook { // } // } // -func Reject(op entv1.Op) ent.Hook { +func Reject(op entv1.Op) entv1.Hook { return func(next entv1.Mutator) entv1.Mutator { return entv1.MutateFunc(func(ctx context.Context, m entv1.Mutation) (entv1.Value, error) { if m.Op().Is(op) { @@ -73,3 +72,41 @@ func Reject(op entv1.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []entv1.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...entv1.Hook) Chain { + return Chain{append([]entv1.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() entv1.Hook { + return func(next entv1.Mutator) entv1.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return entv1.MutateFunc(func(ctx context.Context, m entv1.Mutation) (entv1.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...entv1.Hook) Chain { + newHooks := make([]entv1.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/entc/integration/migrate/entv2/hook/hook.go b/entc/integration/migrate/entv2/hook/hook.go index aaa7ab9a8..97f994209 100644 --- a/entc/integration/migrate/entv2/hook/hook.go +++ b/entc/integration/migrate/entv2/hook/hook.go @@ -10,7 +10,6 @@ import ( "context" "fmt" - "github.com/facebookincubator/ent/entc/integration/ent" "github.com/facebookincubator/ent/entc/integration/migrate/entv2" ) @@ -89,7 +88,7 @@ func On(hk entv2.Hook, op entv2.Op) entv2.Hook { // } // } // -func Reject(op entv2.Op) ent.Hook { +func Reject(op entv2.Op) entv2.Hook { return func(next entv2.Mutator) entv2.Mutator { return entv2.MutateFunc(func(ctx context.Context, m entv2.Mutation) (entv2.Value, error) { if m.Op().Is(op) { @@ -99,3 +98,41 @@ func Reject(op entv2.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []entv2.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...entv2.Hook) Chain { + return Chain{append([]entv2.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() entv2.Hook { + return func(next entv2.Mutator) entv2.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return entv2.MutateFunc(func(ctx context.Context, m entv2.Mutation) (entv2.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...entv2.Hook) Chain { + newHooks := make([]entv2.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/entc/integration/privacy/ent/hook/hook.go b/entc/integration/privacy/ent/hook/hook.go index f43075a2e..3d3e7ec25 100644 --- a/entc/integration/privacy/ent/hook/hook.go +++ b/entc/integration/privacy/ent/hook/hook.go @@ -72,3 +72,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/entc/integration/template/ent/hook/hook.go b/entc/integration/template/ent/hook/hook.go index a74426b47..eef5b5240 100644 --- a/entc/integration/template/ent/hook/hook.go +++ b/entc/integration/template/ent/hook/hook.go @@ -85,3 +85,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/examples/edgeindex/ent/hook/hook.go b/examples/edgeindex/ent/hook/hook.go index 129e3f4f9..8747dca91 100644 --- a/examples/edgeindex/ent/hook/hook.go +++ b/examples/edgeindex/ent/hook/hook.go @@ -72,3 +72,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/examples/entcpkg/ent/hook/hook.go b/examples/entcpkg/ent/hook/hook.go index 9667f60c9..5515bcd7b 100644 --- a/examples/entcpkg/ent/hook/hook.go +++ b/examples/entcpkg/ent/hook/hook.go @@ -59,3 +59,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/examples/m2m2types/ent/hook/hook.go b/examples/m2m2types/ent/hook/hook.go index d3edc9dcc..37f764f86 100644 --- a/examples/m2m2types/ent/hook/hook.go +++ b/examples/m2m2types/ent/hook/hook.go @@ -72,3 +72,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/examples/m2mbidi/ent/hook/hook.go b/examples/m2mbidi/ent/hook/hook.go index ba9b9f768..c641f0a43 100644 --- a/examples/m2mbidi/ent/hook/hook.go +++ b/examples/m2mbidi/ent/hook/hook.go @@ -59,3 +59,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/examples/m2mrecur/ent/hook/hook.go b/examples/m2mrecur/ent/hook/hook.go index c8ed3cc49..5b3e0182e 100644 --- a/examples/m2mrecur/ent/hook/hook.go +++ b/examples/m2mrecur/ent/hook/hook.go @@ -59,3 +59,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/examples/o2m2types/ent/hook/hook.go b/examples/o2m2types/ent/hook/hook.go index 2af05b279..51dfd7830 100644 --- a/examples/o2m2types/ent/hook/hook.go +++ b/examples/o2m2types/ent/hook/hook.go @@ -72,3 +72,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/examples/o2mrecur/ent/hook/hook.go b/examples/o2mrecur/ent/hook/hook.go index 905e8611f..6554d7635 100644 --- a/examples/o2mrecur/ent/hook/hook.go +++ b/examples/o2mrecur/ent/hook/hook.go @@ -59,3 +59,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/examples/o2o2types/ent/hook/hook.go b/examples/o2o2types/ent/hook/hook.go index fece1274b..ad15b5706 100644 --- a/examples/o2o2types/ent/hook/hook.go +++ b/examples/o2o2types/ent/hook/hook.go @@ -72,3 +72,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/examples/o2obidi/ent/hook/hook.go b/examples/o2obidi/ent/hook/hook.go index a78411b87..d11d5c5e2 100644 --- a/examples/o2obidi/ent/hook/hook.go +++ b/examples/o2obidi/ent/hook/hook.go @@ -59,3 +59,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/examples/o2orecur/ent/hook/hook.go b/examples/o2orecur/ent/hook/hook.go index d50fa5f68..47b157322 100644 --- a/examples/o2orecur/ent/hook/hook.go +++ b/examples/o2orecur/ent/hook/hook.go @@ -59,3 +59,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/examples/start/ent/hook/hook.go b/examples/start/ent/hook/hook.go index 9b81514cf..8a4f54999 100644 --- a/examples/start/ent/hook/hook.go +++ b/examples/start/ent/hook/hook.go @@ -85,3 +85,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/examples/traversal/ent/hook/hook.go b/examples/traversal/ent/hook/hook.go index 528637fc0..36e91e96d 100644 --- a/examples/traversal/ent/hook/hook.go +++ b/examples/traversal/ent/hook/hook.go @@ -85,3 +85,41 @@ func Reject(op ent.Op) ent.Hook { }) } } + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(next ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + next = c.hooks[i](next) + } + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + return next.Mutate(ctx, m) + }) + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +}