Skip to content

Commit 84366c9

Browse files
paritosh-08hasura-bot
authored andcommitted
server: apply naming convention to prefixing/suffixing for graphql-default
PR-URL: hasura/graphql-engine-mono#5020 GitOrigin-RevId: 145ed4d5dcc352308486fefe9bb7f75f8ed1a84a
1 parent 107180d commit 84366c9

File tree

4 files changed

+88
-31
lines changed

4 files changed

+88
-31
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858

5959
### Bug fixes and improvements
6060

61+
- server: fix prefix/suffix behaviour for `graphql-default` naming convention (fixes #8544)
6162
- server: fix namespace visibility during introspection (fix #8434)
6263
- server: Create missing SQL triggers, if any, while reloading metadata and startup.
6364
- server: fix name transformation bug in `graphql-default` naming convention (fixes #8640 partially)

server/src-lib/Data/Text/Casing.hs

+16-4
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,18 @@ module Data.Text.Casing
3131
transformGQLSuffixWith,
3232

3333
-- * Helpers
34-
identifierToList,
3534
fromTuple,
3635
fromName,
36+
fromNonEmptyList,
37+
identifierToList,
38+
lowerFirstChar,
39+
transformPrefixAndSuffixAndConcat,
40+
upperFirstChar,
3741
)
3842
where
3943

4044
import Data.List (intersperse)
45+
import Data.List.NonEmpty qualified as NE
4146
import Data.Text qualified as T
4247
import Hasura.Prelude
4348
import Language.GraphQL.Draft.Syntax qualified as G
@@ -59,6 +64,9 @@ fromTuple (pref, suffs) = Identifier pref suffs
5964
fromName :: G.Name -> GQLNameIdentifier
6065
fromName n = Identifier n []
6166

67+
fromNonEmptyList :: NonEmpty G.Name -> GQLNameIdentifier
68+
fromNonEmptyList neList = Identifier (NE.head neList) (map G.convertNameToSuffix (NE.tail neList))
69+
6270
-- | transforms a graphql name with a transforming function
6371
--
6472
-- Note: This will return the graphql name without transformation if the
@@ -104,12 +112,16 @@ toSnakeG (Identifier pref suff) = G.addSuffixes pref (map (transformGQLSuffixWit
104112

105113
-- | To @PascalCase@ for @GQLNameIdentifier@
106114
toPascalG :: GQLNameIdentifier -> G.Name
107-
toPascalG (Identifier pref suff) = G.addSuffixes pref (map (transformGQLSuffixWith upperFirstChar) suff)
115+
toPascalG gqlIdentifier = transformPrefixAndSuffixAndConcat gqlIdentifier upperFirstChar upperFirstChar
108116

109117
-- | To @camelCase@ for @GQLNameIdentifier@
110118
toCamelG :: GQLNameIdentifier -> G.Name
111-
toCamelG (Identifier pref []) = pref
112-
toCamelG (Identifier x xs) = G.addSuffixes (transformNameWith lowerFirstChar x) (map (transformGQLSuffixWith upperFirstChar) xs)
119+
toCamelG gqlIdentifier = transformPrefixAndSuffixAndConcat gqlIdentifier lowerFirstChar upperFirstChar
120+
121+
-- | Transforms @GQLNameIdentifier@ and returns a @G.Name@
122+
transformPrefixAndSuffixAndConcat :: GQLNameIdentifier -> (T.Text -> T.Text) -> (T.Text -> T.Text) -> G.Name
123+
transformPrefixAndSuffixAndConcat (Identifier pref suff) prefixTransformer suffixTransformer =
124+
G.addSuffixes (transformNameWith prefixTransformer pref) (map (transformGQLSuffixWith suffixTransformer) suff)
113125

114126
-- @fromSnake@ is used in splitting the schema/table names separated by @_@
115127
-- For global naming conventions:

server/src-lib/Hasura/RQL/Types/SourceCustomization.hs

+25-15
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import Control.Lens
4747
import Data.Aeson qualified as J
4848
import Data.Aeson.Extended
4949
import Data.Has
50+
import Data.List.NonEmpty qualified as NE
5051
import Data.Monoid
5152
import Data.Text qualified as T
5253
import Data.Text.Casing (GQLNameIdentifier (..))
@@ -121,20 +122,20 @@ parseNamingConventionFromText "graphql-default" = Right GraphqlCase
121122
parseNamingConventionFromText _ = Left "naming_convention can either be \"hasura-default\" or \"graphql-default\""
122123

123124
mkCustomizedTypename :: Maybe SourceTypeCustomization -> NamingCase -> MkTypename
124-
mkCustomizedTypename stc tCase = MkTypename ((applyTypeNameCaseCust tCase) . (applyTypeCust stc))
125+
mkCustomizedTypename stc tCase = MkTypename ((applyTypeNameCaseCust tCase) . (applyTypeCust stc tCase))
125126

126-
mkCustomizedFieldName :: Maybe RootFieldsCustomization -> MkRootFieldName
127-
mkCustomizedFieldName rtc = MkRootFieldName (applyFieldCust rtc)
127+
mkCustomizedFieldName :: Maybe RootFieldsCustomization -> NamingCase -> MkRootFieldName
128+
mkCustomizedFieldName rtc tCase = MkRootFieldName (applyFieldCust rtc tCase)
128129

129130
-- | apply prefix and suffix to type name according to the source customization
130-
applyTypeCust :: Maybe SourceTypeCustomization -> (G.Name -> G.Name)
131-
applyTypeCust Nothing = id
132-
applyTypeCust (Just SourceTypeCustomization {..}) = applyPrefixSuffix _stcPrefix _stcSuffix
131+
applyTypeCust :: Maybe SourceTypeCustomization -> NamingCase -> (G.Name -> G.Name)
132+
applyTypeCust Nothing _ = id
133+
applyTypeCust (Just SourceTypeCustomization {..}) tCase = applyPrefixSuffix _stcPrefix _stcSuffix tCase True
133134

134135
-- | apply prefix and suffix to field name according to the source customization
135-
applyFieldCust :: Maybe RootFieldsCustomization -> (G.Name -> G.Name)
136-
applyFieldCust Nothing = id
137-
applyFieldCust (Just RootFieldsCustomization {..}) = applyPrefixSuffix _rootfcPrefix _rootfcSuffix
136+
applyFieldCust :: Maybe RootFieldsCustomization -> NamingCase -> (G.Name -> G.Name)
137+
applyFieldCust Nothing _ = id
138+
applyFieldCust (Just RootFieldsCustomization {..}) tCase = applyPrefixSuffix _rootfcPrefix _rootfcSuffix tCase False
138139

139140
-- | apply naming convention to type name
140141
applyTypeNameCaseCust :: NamingCase -> G.Name -> G.Name
@@ -188,11 +189,20 @@ applyEnumValueCase tCase v = case tCase of
188189
GraphqlCase -> C.transformNameWith (T.toUpper) v
189190

190191
-- | append/prepend the suffix/prefix in the graphql name
191-
applyPrefixSuffix :: Maybe G.Name -> Maybe G.Name -> G.Name -> G.Name
192-
applyPrefixSuffix Nothing Nothing name = name
193-
applyPrefixSuffix (Just prefix) Nothing name = prefix <> name
194-
applyPrefixSuffix Nothing (Just suffix) name = name <> suffix
195-
applyPrefixSuffix (Just prefix) (Just suffix) name = prefix <> name <> suffix
192+
applyPrefixSuffix :: Maybe G.Name -> Maybe G.Name -> NamingCase -> Bool -> G.Name -> G.Name
193+
applyPrefixSuffix Nothing Nothing tCase isTypeName name = concatPrefixSuffix tCase isTypeName $ NE.fromList [name]
194+
applyPrefixSuffix (Just prefix) Nothing tCase isTypeName name = concatPrefixSuffix tCase isTypeName $ NE.fromList [prefix, name]
195+
applyPrefixSuffix Nothing (Just suffix) tCase isTypeName name = concatPrefixSuffix tCase isTypeName $ NE.fromList [name, suffix]
196+
applyPrefixSuffix (Just prefix) (Just suffix) tCase isTypeName name = concatPrefixSuffix tCase isTypeName $ NE.fromList [prefix, name, suffix]
197+
198+
concatPrefixSuffix :: NamingCase -> Bool -> NonEmpty G.Name -> G.Name
199+
concatPrefixSuffix (HasuraCase) _ neList = sconcat neList
200+
concatPrefixSuffix (GraphqlCase) isTypeName neList =
201+
if isTypeName
202+
then C.toPascalG prefixSuffixGQLIdent
203+
else C.transformPrefixAndSuffixAndConcat prefixSuffixGQLIdent id C.upperFirstChar
204+
where
205+
prefixSuffixGQLIdent = C.fromNonEmptyList neList
196206

197207
data SourceCustomization = SourceCustomization
198208
{ _scRootFields :: !(Maybe RootFieldsCustomization),
@@ -262,7 +272,7 @@ withSourceCustomization sc@SourceCustomization {..} namingConventionSupport defa
262272
HasuraCase -> pure HasuraCase
263273

264274
withTypenameCustomization (mkCustomizedTypename _scTypeNames tCase)
265-
. withRootFieldNameCustomization (mkCustomizedFieldName _scRootFields)
275+
. withRootFieldNameCustomization (mkCustomizedFieldName _scRootFields tCase)
266276
. withNamingCaseCustomization tCase
267277
$ m
268278

server/tests-py/queries/naming_conventions/type_and_field_names_with_prefix_and_suffix.yaml

+46-12
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
customization:
2121
root_fields:
2222
prefix: test
23-
suffix: Query
23+
suffix: query
2424
naming_convention: graphql-default
2525

2626
- description: create table 1
@@ -57,7 +57,7 @@
5757
status: 200
5858
response:
5959
data:
60-
testauthorLocalQuery:
60+
testAuthorLocalQuery:
6161
- id: 1
6262
name: 'Author 1'
6363
__typename: AuthorLocal
@@ -67,7 +67,7 @@
6767
query:
6868
query: |
6969
query {
70-
testauthorLocalQuery {
70+
testAuthorLocalQuery {
7171
id
7272
name
7373
__typename
@@ -89,7 +89,7 @@
8989
query:
9090
query: |
9191
query {
92-
a: testauthorLocalQuery {
92+
a: testAuthorLocalQuery {
9393
b: id
9494
c: name
9595
d: __typename
@@ -101,14 +101,14 @@
101101
status: 200
102102
response:
103103
data:
104-
testauthorLocalByPkQuery:
104+
testAuthorLocalByPkQuery:
105105
id: 1
106106
name: 'Author 1'
107107
__typename: AuthorLocal
108108
query:
109109
query: |
110110
query {
111-
testauthorLocalByPkQuery(id: 1) {
111+
testAuthorLocalByPkQuery(id: 1) {
112112
id
113113
name
114114
__typename
@@ -120,15 +120,15 @@
120120
status: 200
121121
response:
122122
data:
123-
testauthorLocalAggregateQuery:
123+
testAuthorLocalAggregateQuery:
124124
__typename: AuthorLocalAggregate
125125
aggregate:
126126
__typename: AuthorLocalAggregateFields
127127
count: 1
128128
query:
129129
query: |
130130
query MyQuery {
131-
testauthorLocalAggregateQuery(where: {name: {_eq: "Author 2"}}) {
131+
testAuthorLocalAggregateQuery(where: {name: {_eq: "Author 2"}}) {
132132
__typename
133133
aggregate {
134134
__typename
@@ -142,7 +142,7 @@
142142
status: 200
143143
response:
144144
data:
145-
testinsertAuthorLocalQuery:
145+
testInsertAuthorLocalQuery:
146146
__typename: AuthorLocalMutationResponse
147147
returning:
148148
- __typename: AuthorLocal
@@ -151,7 +151,7 @@
151151
query:
152152
query: |
153153
mutation MyMutation {
154-
testinsertAuthorLocalQuery(objects: {name: "Author 3", id: 3}) {
154+
testInsertAuthorLocalQuery(objects: {name: "Author 3", id: 3}) {
155155
__typename
156156
returning {
157157
__typename
@@ -166,20 +166,54 @@
166166
status: 200
167167
response:
168168
data:
169-
testdeleteAuthorLocalByPkQuery:
169+
testDeleteAuthorLocalByPkQuery:
170170
__typename: AuthorLocal
171171
id: 3
172172
name: Author 3
173173
query:
174174
query: |
175175
mutation MyMutation {
176-
testdeleteAuthorLocalByPkQuery(id: 3) {
176+
testDeleteAuthorLocalByPkQuery(id: 3) {
177177
__typename
178178
id
179179
name
180180
}
181181
}
182182
183+
- description: PG update source
184+
url: /v1/metadata
185+
status: 200
186+
response:
187+
message: success
188+
query:
189+
type: pg_update_source
190+
args:
191+
name: pg1
192+
customization:
193+
root_fields:
194+
prefix: Test
195+
suffix: query
196+
naming_convention: graphql-default
197+
198+
- description: Lookup by pk
199+
url: /v1/graphql
200+
status: 200
201+
response:
202+
data:
203+
TestAuthorLocalByPkQuery:
204+
id: 1
205+
name: 'Author 1'
206+
__typename: AuthorLocal
207+
query:
208+
query: |
209+
query {
210+
TestAuthorLocalByPkQuery(id: 1) {
211+
id
212+
name
213+
__typename
214+
}
215+
}
216+
183217
- description: untrack table
184218
url: /v1/metadata
185219
status: 200

0 commit comments

Comments
 (0)