-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: use getStaticPaths with PageRouteFragment #253
base: main
Are you sure you want to change the base?
Conversation
7640530
to
d429258
Compare
Deploying head-start with
|
Latest commit: |
cf7bdbb
|
Status: | ✅ Deploy successful! |
Preview URL: | https://2a65d321.head-start.pages.dev |
Branch Preview URL: | https://refactor-static-paths.head-start.pages.dev |
@@ -34,7 +34,6 @@ module.exports = { | |||
* @see https://github.com/Tonel/typescript-type-generation-graphql-example/blob/2d43584b1d75c9086c4ddd594a6b2401a29b0055/graphql.config.yml#L11-L23 | |||
*/ | |||
config: { | |||
dedupeFragments: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was all that was necessary to be able to import full fragments into the datocmsCollection
from @lib/datocms/types.ts
. After npm run prep
, that file will have all fragments used in the project as template strings, with all their nested fragments injected, ie:
export const PageRoute = gql`
fragment PageRoute on PageRecord {
...PageRouteFields
...PageRouteParent
}
${PageRouteFields}
${PageRouteParent}`;
(note that I cleaned up the indentation)
declare module '*.fragment.graphql' { | ||
import { DocumentNode } from 'graphql'; | ||
const value: DocumentNode; | ||
export default value; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This allows for importing the fragments into code. Note the difference in export statement between *.query.graphql
and *.fragment.graphql
.
query: parse(/* graphql */` | ||
query ${collection}Meta { | ||
records: all${collection}(first: 1) { __typename } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to get the right __typename
, fetch one record from the collection.
d429258
to
cf7bdbb
Compare
: fragment; | ||
const { definitions } = fragmentDocument; | ||
const fragmentDefinition = definitions | ||
.find((definition): definition is FragmentDefinitionNode => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For explanation of is
, see https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
const recordsPerPage = 100; // DatoCMS GraphQL API has a limit of 100 records per request | ||
const totalPages = Math.ceil(meta.count / recordsPerPage); | ||
const records: CollectionType[] = []; | ||
const fragmentDocument = typeof fragment === 'string' | ||
? parse(`fragment InlineFragment on ${type} { ${fragment} }`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Create new fragment to maintain support for passing a string
to argument fragment
|
||
for (let page = 0; page < totalPages; page++) { | ||
const data = await datocmsRequest({ | ||
query: parse(/* graphql */` | ||
${print(fragmentDocument)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Insert fragment definition from fragmentDocument
, which is either the fragment
passed from an import from @lib/datocms/types.ts
or the one created from a string
;
query All${collection} { | ||
${collection}: all${collection} ( | ||
first: ${recordsPerPage}, | ||
skip: ${page * recordsPerPage} | ||
) { | ||
${fragment} | ||
...${fragmentDefinition?.name?.value} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use said fragment
@@ -29,36 +30,60 @@ afterEach(() => { | |||
afterAll(() => server.close()); | |||
|
|||
describe('datocmsCollection:', () => { | |||
test('should successfully fetch a non-paginated collection', async () => { | |||
const fragment = parse(/* graphql */` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test all functions with passing a parsed fragment by default
} | ||
`); | ||
|
||
test('supports passing fragment as a string', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test if passing a string keeps working
data: { | ||
meta: { count: totalRecords }, | ||
records: [{ __typename: 'MyMockRecord' }], | ||
} satisfies CollectionInfo, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure the payload for the mocked service is the same type as the expected return value
const pageSlugs = { | ||
en: 'example-page', | ||
nl: 'voorbeeld-pagina' | ||
} as Record<string, string> as Record<SiteLocale, string>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure that this test scenario works, even when the SiteLocale definition generated from a DatoCMS instance might have completely different locales
type LocalizedSlugs = { | ||
_allSlugLocales?: | ||
| { | ||
locale?: SiteLocale | null; | ||
value?: string; | ||
}[] | ||
| null; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot of null
and undefined
in here, but it is important that these definitions have an exact overlap with types from DatoCMS.
} | ||
} | ||
`, | ||
fragment, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Congratulations to getting to the end. This is the actual feature!
Changes
datocmsCollection
for better typed getStaticPathsHow to test
Checklist
I have made updated relevant documentation files (in project README, docs/, etc)I have added a decision log entry if the change affects the architecture or changes a significant technology