From ac33f2f04c8549deaa1f11ba8bb72467fec191f9 Mon Sep 17 00:00:00 2001 From: George Suntres Date: Wed, 22 Apr 2026 10:30:27 -0400 Subject: [PATCH] Add UpdateSet --- go.mod | 6 ++--- go.sum | 49 +++++++---------------------------- persist.go | 11 ++++++++ persist_test.go | 7 ++--- persist_update_set.go | 59 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 46 deletions(-) create mode 100644 persist_update_set.go diff --git a/go.mod b/go.mod index 7fe0e61..60baa37 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,14 @@ module git.gsuntres.com/general/persist go 1.25.0 require ( - git.gsuntres.com/general/commons v0.0.0-20260418234051-1298398922cc - git.gsuntres.com/general/mongo v0.0.0-20260419001855-29144f54bd36 + git.gsuntres.com/general/commons v0.0.0-20260422140002-55de9c34e8c1 + git.gsuntres.com/general/mongo v0.0.0-20260422142328-49a1d24660aa git.gsuntres.com/general/structful v0.0.0-20260415004657-80b95298f342 github.com/go-viper/mapstructure/v2 v2.5.0 github.com/testcontainers/testcontainers-go v0.41.0 github.com/testcontainers/testcontainers-go/modules/mongodb v0.41.0 go.mongodb.org/mongo-driver/v2 v2.5.1 golang.org/x/crypto v0.50.0 - golang.org/x/text v0.36.0 ) require ( @@ -75,6 +74,7 @@ require ( go.opentelemetry.io/otel/trace v1.41.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.43.0 // indirect + golang.org/x/text v0.36.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260330182312-d5a96adf58d8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index f53aa72..3a16c78 100644 --- a/go.sum +++ b/go.sum @@ -1,33 +1,11 @@ dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -git.gsuntres.com/general/commons v0.0.0-20260329171253-65eec3c3b1e3 h1:BMs+fuAzLvvuZFFUYruUZxdPhFOxzLRwRXPwkkkTNrw= -git.gsuntres.com/general/commons v0.0.0-20260329171253-65eec3c3b1e3/go.mod h1:j+Iy310zO6jFrqXgMLIlAJeMIc332AHnoRUhsIroN/4= -git.gsuntres.com/general/commons v0.0.0-20260402010100-7e8cf14bb0a5 h1:iDZS0uQComRTiYxinclK73RoyI3Fsk3xNuAIWqN9590= -git.gsuntres.com/general/commons v0.0.0-20260402010100-7e8cf14bb0a5/go.mod h1:ZawSPCI/Irjx7P83qJRcknKGuLLJ9c7hhP4OXgILnCY= -git.gsuntres.com/general/commons v0.0.0-20260414224953-706ed2e6b0be h1:dqRYGcUv3zcQPFS8KTUakkNbXaA1rC8P0Ll2ruNQceM= -git.gsuntres.com/general/commons v0.0.0-20260414224953-706ed2e6b0be/go.mod h1:ZawSPCI/Irjx7P83qJRcknKGuLLJ9c7hhP4OXgILnCY= -git.gsuntres.com/general/commons v0.0.0-20260418004121-f52793a7641f h1:lSjhzGQBpON/Cc+wXZXcMrpgm0RQ+waipLoC/abmX7I= -git.gsuntres.com/general/commons v0.0.0-20260418004121-f52793a7641f/go.mod h1:ZawSPCI/Irjx7P83qJRcknKGuLLJ9c7hhP4OXgILnCY= -git.gsuntres.com/general/commons v0.0.0-20260418234051-1298398922cc h1:jv+WAlpviuWQcsdZSmw1I/3yEnf8q3JNfRabxRTCk8k= -git.gsuntres.com/general/commons v0.0.0-20260418234051-1298398922cc/go.mod h1:S93xcBczrgN+gZU0JWkPRnTcAMvQuTp1ChyKkOd/I50= -git.gsuntres.com/general/mongo v0.0.0-20260329164619-eff6c4ecee15 h1:MD2fRF3oIQ7g/ToW+toCZH3/LL8bBsSz9PhEQyjOpk0= -git.gsuntres.com/general/mongo v0.0.0-20260329164619-eff6c4ecee15/go.mod h1:AUb/BDG+dVPHpKmO5GsoZqIbDO8uqbxBabEqtqAB4tw= -git.gsuntres.com/general/mongo v0.0.0-20260411181748-96254895839d h1:eDbxpvgu0d751/SBIHlH1Km2er49Luau35/8ztCeBfk= -git.gsuntres.com/general/mongo v0.0.0-20260411181748-96254895839d/go.mod h1:AUb/BDG+dVPHpKmO5GsoZqIbDO8uqbxBabEqtqAB4tw= -git.gsuntres.com/general/mongo v0.0.0-20260418004600-7599b8b85689 h1:S9ryADnMXyTKWtUsjm1+Ah9of8R+4MmUrJgXEyrfAgg= -git.gsuntres.com/general/mongo v0.0.0-20260418004600-7599b8b85689/go.mod h1:C3f5b9tKohacdYd2Ugnyu9rMdvQZ5a+XrrKb+O/WA/M= -git.gsuntres.com/general/mongo v0.0.0-20260418161100-6e91f8475035 h1:8XxWEbdwRAQUAnHcKhWtqGYjCEWT2/NGU6XlwEZkhpU= -git.gsuntres.com/general/mongo v0.0.0-20260418161100-6e91f8475035/go.mod h1:C3f5b9tKohacdYd2Ugnyu9rMdvQZ5a+XrrKb+O/WA/M= -git.gsuntres.com/general/mongo v0.0.0-20260419001855-29144f54bd36 h1:1ut5g7fWjNEaeXzMDJizioMBJ3LJJCBfJkjSvw+m42Q= -git.gsuntres.com/general/mongo v0.0.0-20260419001855-29144f54bd36/go.mod h1:C3f5b9tKohacdYd2Ugnyu9rMdvQZ5a+XrrKb+O/WA/M= -git.gsuntres.com/general/structful v0.0.0-20260330181942-47f7fdf9c083 h1:Z4zgJfWbcfnUiE1NjqMukUMYYlpN/10DUFpu4u789eQ= -git.gsuntres.com/general/structful v0.0.0-20260330181942-47f7fdf9c083/go.mod h1:yAdT20C09rz2VHA6ALurxc2KUaF03cSqvmRvDwv+KZk= -git.gsuntres.com/general/structful v0.0.0-20260402004702-c83e44b04a9f h1:bJpj6N9a2fBlcwMFoG+egkDsAmNbjfzdz3arzbdgzHs= -git.gsuntres.com/general/structful v0.0.0-20260402004702-c83e44b04a9f/go.mod h1:fB5HAdx2wWMUkTitRz729EhpASpiHrgTYdIKQugVMjs= +git.gsuntres.com/general/commons v0.0.0-20260422140002-55de9c34e8c1 h1:g96tzABUPqaAaftDBLbDkf/za21kBAUiex8LU//NsFE= +git.gsuntres.com/general/commons v0.0.0-20260422140002-55de9c34e8c1/go.mod h1:s774W5vN/53DLYKeY4iwFnwPOIHfSg8/V6Ft7sEdl9M= +git.gsuntres.com/general/mongo v0.0.0-20260422142328-49a1d24660aa h1:Um0LsIApTZlVtXif+DYqyd28pjfzK4ObGScksqJFeZk= +git.gsuntres.com/general/mongo v0.0.0-20260422142328-49a1d24660aa/go.mod h1:N1OVqb4osp/dlH+nvtTqe5rZK367Dqx6oprJT9xLpac= git.gsuntres.com/general/structful v0.0.0-20260415004657-80b95298f342 h1:atJ49utlrKue+mu+lbw18bvhG30TnTXQYokTKrH80+4= git.gsuntres.com/general/structful v0.0.0-20260415004657-80b95298f342/go.mod h1:QILJDJKzi75Q4av6LvI+/OwXAeqoLtx6p5UZXqlxfKc= -git.gsuntres.com/general/sys v0.0.0-20260329160429-49966ca31027 h1:4pmcjxEDM4rzv+iimQ7wTgCAQ1VnAoeGiHLuf6wC6Fw= -git.gsuntres.com/general/sys v0.0.0-20260329160429-49966ca31027/go.mod h1:OVs7w4/tJO1GT7cLIeEsb90LuZqH2xYIVQODI5P1GJs= git.gsuntres.com/general/sys v0.0.1 h1:JpGG6HCkJrTaCICR09kURhMTIc+/s8yb0lHQjo/TDVI= git.gsuntres.com/general/sys v0.0.1/go.mod h1:OVs7w4/tJO1GT7cLIeEsb90LuZqH2xYIVQODI5P1GJs= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= @@ -69,6 +47,8 @@ github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -87,8 +67,6 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/ianlancetaylor/jsonschema v0.0.0-20251021232724-46ecbf32a0a5 h1:x2QxKV4w/sBEwwUUmBH/8cFjeOBZqwaB5dz5rcuFspU= github.com/ianlancetaylor/jsonschema v0.0.0-20251021232724-46ecbf32a0a5/go.mod h1:KtN3dTgXsLnC5GJBRNmOPd/HUInNcQ84lUCrKJPrvDc= -github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= -github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -168,8 +146,6 @@ github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfS github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE= -go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= go.mongodb.org/mongo-driver/v2 v2.5.1 h1:j2U/Qp+wvueSpqitLCSZPT/+ZpVc1xzuwdHWwl7d8ro= go.mongodb.org/mongo-driver/v2 v2.5.1/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= @@ -192,16 +168,14 @@ go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lI go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= -golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= -golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= @@ -215,21 +189,16 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= -golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU= -golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= +golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= -golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= diff --git a/persist.go b/persist.go index 5ccf503..dcd2d97 100644 --- a/persist.go +++ b/persist.go @@ -104,6 +104,7 @@ func Init(props *InitProps) { BuildGetOne(col, report) BuildDeleteOne(col, report) BuildReplaceOne(col, report) + BuildUpdateSet(col, report) client.AddDefinition(col) } @@ -315,3 +316,13 @@ func (p *Persist) GetAccountByCode(ctx context.Context, code string) (*Account, return &acc, nil } + +func SetRelaxed() { + client := mongo.GetMongoClient() + client.SetRelaxed() +} + +func SetStrict() { + client := mongo.GetMongoClient() + client.SetStrict() +} \ No newline at end of file diff --git a/persist_test.go b/persist_test.go index a428984..6f0138d 100644 --- a/persist_test.go +++ b/persist_test.go @@ -66,8 +66,9 @@ func TestSaveUser_Valid(t *testing.T) { Password: "mypass", Email: "too@long.test", } - + SetRelaxed() user, err := p.SaveUser(context.TODO(), data) + SetStrict() if err != nil { t.Fatalf("Should have saved user %#v", err) @@ -152,8 +153,8 @@ func TestSaveUser_UsesSysDb(t *testing.T) { delete(found, "_id") delete(found, "password") - delete(found, "created_at") - delete(found, "updated_at") + delete(found, "createdAt") + delete(found, "updatedAt") d, _ := mongo.ToMap(data) diff --git a/persist_update_set.go b/persist_update_set.go new file mode 100644 index 0000000..0bd12ed --- /dev/null +++ b/persist_update_set.go @@ -0,0 +1,59 @@ +package persist + +import ( + "fmt" + "context" + "reflect" + + "git.gsuntres.com/general/commons" + "git.gsuntres.com/general/mongo" +) + +func BuildUpdateSet(col map[string]any, report *InitReport) { + name := col["_name"].(string) + singular := col["singular"].(string) + + // prepare input arguments and return results + in := []reflect.Type{ + reflect.TypeOf((*context.Context)(nil)).Elem(), + reflect.TypeOf((*map[string]any)(nil)).Elem(), + reflect.TypeOf((*map[string]any)(nil)).Elem(), + } + out := []reflect.Type{ + reflect.TypeOf((*bool)(nil)).Elem(), + reflect.TypeOf((*error)(nil)).Elem(), + } + + // create function signature + variadic := false + funcType := reflect.FuncOf(in, out, variadic) + fname := fmt.Sprintf("%s%s%s", "Update", commons.StringTitle(singular), "Set") + fields = append(fields, reflect.StructField{ + Name: fname, + Type: funcType, + }) + + isSystem := false + if v, ok := col["system"]; ok { + isSystem = v.(bool) + } + + report.AddField(fname) + + mc := mongo.GetMongoClient() + + // we defer function's implementation until we create the actual struct + deferedFuncs[fname] = func(ctx context.Context, filter map[string]any, data map[string]any) (bool, error) { + db := "__undefined__" + if isSystem { + db = sysDb + } else { + account := ctx.Value("account").(string) + if account != "" { + db = mc.GetName(account) + } + } + + return mc.UpdateSet(ctx, db, name, filter, data) + } +}