From cdbe6d78d36f246898d9985897c2b4ff4916da9e Mon Sep 17 00:00:00 2001 From: Gani Georgiev Date: Wed, 23 Aug 2023 20:50:36 +0300 Subject: [PATCH] added basic fields wildcard support --- CHANGELOG.md | 2 + tools/rest/json_serializer.go | 19 ++++++++ tools/rest/json_serializer_test.go | 70 ++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5285648af..321d34c98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,8 @@ - Skip API `fields` json transformations for non 20x responses ([#3176](https://github.com/pocketbase/pocketbase/issues/3176)). +- (@todo docs) Added `fields` wildcard (`*`) support. + - (@todo docs) Added new "Strip urls domain" `editor` field option to allow controlling the default TinyMCE imported urls behavior (_default to `false` for new content_). - Reduced the default JSVM prewarmed pool size to 25 to reduce the initial memory consumptions (_you can manually adjust the pool size with `--hooksPool=50` if you need to, but the default should suffice for most cases_). diff --git a/tools/rest/json_serializer.go b/tools/rest/json_serializer.go index b3ad35c9f..cda7b4224 100644 --- a/tools/rest/json_serializer.go +++ b/tools/rest/json_serializer.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/labstack/echo/v5" + "github.com/pocketbase/pocketbase/tools/list" "github.com/pocketbase/pocketbase/tools/search" ) @@ -94,6 +95,24 @@ func pickMapFields(data map[string]any, fields []string) { return // nothing to pick } + if list.ExistInSlice("*", fields) { + // append all missing root level data keys + for k := range data { + var exists bool + + for _, f := range fields { + if strings.HasPrefix(f+".", k+".") { + exists = true + break + } + } + + if !exists { + fields = append(fields, k) + } + } + } + DataLoop: for k := range data { matchingFields := make([]string, 0, len(fields)) diff --git a/tools/rest/json_serializer_test.go b/tools/rest/json_serializer_test.go index f46e66515..6c13f500e 100644 --- a/tools/rest/json_serializer_test.go +++ b/tools/rest/json_serializer_test.go @@ -204,6 +204,76 @@ func TestSerialize(t *testing.T) { "fields=a,c", `{"items":[{"a":11,"c":"test1"},{"a":22,"c":"test2"}],"page":1,"perPage":10,"totalItems":20,"totalPages":30}`, }, + { + "root wildcard", + rest.Serializer{}, + 200, + &search.Result{ + Page: 1, + PerPage: 10, + TotalItems: 20, + TotalPages: 30, + Items: []any{ + map[string]any{"a": 11, "b": 11, "c": "test1"}, + map[string]any{"a": 22, "b": 22, "c": "test2"}, + }, + }, + "fields=*", + `{"items":[{"a":11,"b":11,"c":"test1"},{"a":22,"b":22,"c":"test2"}],"page":1,"perPage":10,"totalItems":20,"totalPages":30}`, + }, + { + "root wildcard with nested exception", + rest.Serializer{}, + 200, + map[string]any{ + "id": "123", + "title": "lorem", + "rel": map[string]any{ + "id": "456", + "title": "rel_title", + }, + }, + "fields=*,rel.id", + `{"id":"123","rel":{"id":"456"},"title":"lorem"}`, + }, + { + "sub wildcard", + rest.Serializer{}, + 200, + map[string]any{ + "id": "123", + "title": "lorem", + "rel": map[string]any{ + "id": "456", + "title": "rel_title", + "sub": map[string]any{ + "id": "789", + "title": "sub_title", + }, + }, + }, + "fields=id,rel.*", + `{"id":"123","rel":{"id":"456","sub":{"id":"789","title":"sub_title"},"title":"rel_title"}}`, + }, + { + "sub wildcard with nested exception", + rest.Serializer{}, + 200, + map[string]any{ + "id": "123", + "title": "lorem", + "rel": map[string]any{ + "id": "456", + "title": "rel_title", + "sub": map[string]any{ + "id": "789", + "title": "sub_title", + }, + }, + }, + "fields=id,rel.*,rel.sub.id", + `{"id":"123","rel":{"id":"456","sub":{"id":"789"},"title":"rel_title"}}`, + }, } for _, s := range scenarios {