11import { defineVuepalFeature } from '../defineFeature'
2+ import { pascalCase , camelCase } from 'change-case'
23
3- export default defineVuepalFeature ( {
4+ type DrupalRouteDefinition = {
5+ fragments : string [ ]
6+ }
7+
8+ export default defineVuepalFeature < {
9+ routeQueries ?: Record < string , DrupalRouteDefinition >
10+ } > ( {
411 name : 'drupalRoute' ,
512 description : 'Adds routing related GraphQL queries and composables.' ,
6- setup ( helper ) {
13+ setup ( helper , options ) {
714 helper
815 . assertGraphqlObjectField ( { extension : 'routing' } , 'Query' , 'route' )
916 . assertGraphqlObjectField (
@@ -18,10 +25,15 @@ export default defineVuepalFeature({
1825
1926 helper . addComposable ( 'useDrupalRoute' )
2027 helper . addComposable ( 'buildDrupalMetatags' )
28+
29+ helper . addGraphqlFile ( 'fragment.metatag.graphql' )
30+
31+ // Conditionally add the breadcrumb on the route fragment.
2132 const breadcrumbSpread = helper . hasFeatureEnabled ( 'breadcrumb' )
2233 ? 'breadcrumb { ...breadcrumb }'
2334 : ''
2435
36+ // Conditionally add the languageSwitchLinks on the route fragment.
2537 const languageSwitchLinksSpread = helper . hasFeatureEnabled (
2638 'languageSwitchLinks' ,
2739 )
@@ -72,16 +84,101 @@ fragment useDrupalRoute on Query {
7284 }
7385 }
7486}
87+ ` ,
88+ )
89+
90+ const routeQueries = Object . entries ( options ?. routeQueries || { } )
91+
92+ if ( helper . isModuleBuild ) {
93+ routeQueries . push ( [
94+ 'nodeCanonical' ,
95+ {
96+ fragments : [ 'nodePage' ] ,
97+ } ,
98+ ] )
99+ }
100+
101+ if ( ! routeQueries . length ) {
102+ return
103+ }
104+
105+ helper . addComposable ( 'useDrupalRouteQuery' )
75106
76- fragment metatag on Metatag {
77- id
78- tag
79- attributes {
80- key
81- value
107+ helper . addTemplate (
108+ 'route-queries' ,
109+ ( ) => {
110+ const mapping = routeQueries . reduce < Record < string , string > > (
111+ ( acc , [ name ] ) => {
112+ acc [ name ] = camelCase ( 'route_' + name )
113+ return acc
114+ } ,
115+ { } ,
116+ )
117+ return `
118+ export const mapping = ${ JSON . stringify ( mapping , null , 2 ) }
119+ `
120+ } ,
121+ ( ) => {
122+ const imports = [
123+ ...new Set ( routeQueries . flatMap ( ( v ) => v [ 1 ] . fragments ) ) . values ( ) ,
124+ ]
125+ . map ( ( fragmentName ) => {
126+ return pascalCase ( fragmentName + 'Fragment' )
127+ } )
128+ . join ( ',\n ' )
129+ const importStatement = `import type {\n ${ imports } \n} from '#graphql-operations'`
130+ const queries = routeQueries
131+ . map ( ( [ name , definition ] ) => {
132+ const fragments = definition . fragments
133+ . map ( ( v ) => pascalCase ( v + 'Fragment' ) )
134+ . join ( ' | ' )
135+ return `"${ name } ": ${ fragments } `
136+ } )
137+ . join ( ',\n ' )
138+
139+ const possibleQueryNames = routeQueries
140+ . map ( ( [ name ] ) => {
141+ return `'${ camelCase ( 'route_' + name ) } '`
142+ } )
143+ . join ( ' | ' )
144+
145+ return `
146+ ${ importStatement }
147+ import type { Query } from '#nuxt-graphql-middleware/operation-types'
148+
149+ declare module '#vuepal-build/route-queries' {
150+ export type DrupalRouteQueries = {
151+ ${ queries }
82152 }
153+ type PossibleQueryNames = ${ possibleQueryNames }
154+ export const mapping: Record<keyof DrupalRouteQueries, keyof Pick<Query, PossibleQueryNames>>;
83155}
84- ` ,
156+ `
157+ } ,
85158 )
159+
160+ // Generate GraphQL queries.
161+ routeQueries . forEach ( ( [ name , definition ] ) => {
162+ const queryName = camelCase ( 'route_' + name )
163+
164+ const spreads = definition . fragments
165+ . map ( ( v ) => '...' + v )
166+ . join ( '\n ' )
167+ helper . graphql . addDocument (
168+ 'vuepal-route-query:' + name ,
169+ `
170+ query ${ queryName } ($path: String!) {
171+ ...useDrupalRoute
172+ route(path: $path) {
173+ ... on EntityUrl {
174+ entity {
175+ __typename
176+ ${ spreads }
177+ }
178+ }
179+ }
180+ }` ,
181+ )
182+ } )
86183 } ,
87184} )
0 commit comments