-
Notifications
You must be signed in to change notification settings - Fork 3
Added how to implement TS doc #209
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
Merged
Merged
Changes from 3 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
f602315
Bump fast-xml-parser from 4.2.5 to 4.4.1 (#141)
dependabot[bot] 12fd1be
Update CODEOWNERS
josephfusco d0dcaf6
Merge pull request #143 from wpengine/josephfusco-patch-1
josephfusco 59d0309
Bump dset from 3.1.3 to 3.1.4 (#145)
dependabot[bot] bcbf291
Bump micromatch from 4.0.5 to 4.0.8 (#144)
dependabot[bot] 557f492
Bump path-to-regexp from 6.2.1 to 6.3.0 (#147)
dependabot[bot] a1a94a9
Bump next from 14.1.1 to 14.2.12 (#148)
dependabot[bot] bce6800
Bump cross-spawn from 7.0.3 to 7.0.6
dependabot[bot] fc66cca
Merge pull request #191 from wpengine/dependabot/npm_and_yarn/cross-s…
josephfusco ec0b72c
added how to implement TS doc
Fran-A-Dev 7896406
added fs naming and code block highlights
Fran-A-Dev e741c18
Merge branch 'toolkit' into doc/implement-TypeScript
moonmeister bdbec88
missed things
moonmeister 6710317
merged toolkit updates
Fran-A-Dev 5ef9e16
Resolved merge conflict in nav.json
Fran-A-Dev 62ef152
Merge branch 'toolkit' into doc/implement-TypeScript
Fran-A-Dev 07a5eea
removed graphql codegen and replaced it with updated auto generate co…
Fran-A-Dev b829c14
added steps on headers
Fran-A-Dev af5a8c4
added how to implement TS doc
Fran-A-Dev 481e4e9
added fs naming and code block highlights
Fran-A-Dev 38eeff2
missed things
moonmeister 671ad7d
removed graphql codegen and replaced it with updated auto generate co…
Fran-A-Dev fb710ba
added steps on headers
Fran-A-Dev be9dc0b
misc cleanup
moonmeister 31e7fb2
added changes to TS doc to make it more clear and purposeful
Fran-A-Dev c425d77
Merge remote-tracking branch 'origin/toolkit' into doc/implement-Type…
Fran-A-Dev 3dba5de
Test commit using pnpm setup
Fran-A-Dev 0ee5a79
merged conflicts and took care of conflict
Fran-A-Dev 1811675
Update docs for clarity
kellenmace 5173d95
Rename doc to 'generate-types-with-graphql-codegen' and remove the ol…
kellenmace File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+168 KB
src/pages/docs/how-to/implement-typescript/images/typescript-fausthooks-type.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,183 @@ | ||
| export const metadata = { | ||
| title: "Implement TypeScript", | ||
| }; | ||
|
|
||
| ## Implementing TypeScript | ||
|
|
||
| Faust.js provides support for TypeScript, including built-in types for Templates, Blocks, and more. | ||
|
|
||
| [View the Faust.js TypeScript scaffold application](https://github.com/wpengine/faust-scaffold-ts) | ||
|
|
||
| ### Using graphql-codegen | ||
|
|
||
| First things first, you should consider using @graphql-codegen to generate types for the GraphQL queries. | ||
|
|
||
| Below is a sample config for generating the relevant typings: | ||
|
|
||
| ```ts title="codegen.ts" | ||
| import { CodegenConfig } from "@graphql-codegen/cli"; | ||
|
|
||
| const config: CodegenConfig = { | ||
| schema: "https://faustexample.wpengine.com/graphql", | ||
| documents: ["src/**/*.{tsx,ts}"], | ||
| generates: { | ||
| "./src/__generated__/": { | ||
| preset: "client", | ||
| plugins: [], | ||
| presetConfig: { | ||
| gqlTagName: "gql", | ||
| }, | ||
| }, | ||
| }, | ||
| ignoreNoDocuments: true, | ||
| }; | ||
|
|
||
| export default config; | ||
| ``` | ||
|
|
||
| Add the following npm script that works by scanning the `src` folder for GraphQL queries and generating a bunch of files inside `/src/**generated**/` for the TypeScript types: | ||
|
|
||
| ```json title="package.json" | ||
| { | ||
| "scripts": { | ||
| ... | ||
| "generate": "graphql-codegen", | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| > **_Note:_** Be sure to enable WPGraphQL introspection before running the `npm run generate` command since it is disabled by default. | ||
|
|
||
| The most important file is the `graphql.ts` which contains all the schema types from the WPGraphQL endpoint plus the types of the queries: | ||
|
|
||
| ```ts title="/src/__generated__/graphql.ts" | ||
| ... | ||
| export type GetPostQueryVariables = Exact<{ | ||
| databaseId: Scalars['ID']; | ||
| asPreview?: InputMaybe<Scalars['Boolean']>; | ||
| }>; | ||
|
|
||
| export type GetPostQuery = { __typename?: 'RootQuery', post?: { __typename?: 'Post', title?: string | null, content?: string | null, date?: string | null, author?: { __typename?: 'NodeWithAuthorToUserConnectionEdge', node: { __typename?: 'User', name?: string | null } } | null } | null, generalSettings?: { __typename?: 'GeneralSettings', title?: string | null, description?: string | null } | null, primaryMenuItems?: { __typename?: 'RootQueryToMenuItemConnection', nodes: Array<{ __typename?: 'MenuItem', id: string, uri?: string | null, path?: string | null, label?: string | null, parentId?: string | null, cssClasses?: Array<string | null> | null, menu?: { __typename?: 'MenuItemToMenuConnectionEdge', node: { __typename?: 'Menu', name?: string | null } } | null }> } | null }; | ||
| ``` | ||
|
|
||
| You can use these types with the `FaustTemplate` helper which we will explain next. | ||
|
|
||
| ### How to apply types for WP Template Pages | ||
|
|
||
| When creating a new WP Template page, you can use the `FaustTemplate` to declare the type of the function component passing the type of the GraphQL query that was generated for that page: | ||
|
|
||
| ```ts title="src/wp-templates/single.tsx" | ||
| import { gql } from "../__generated__"; | ||
|
|
||
| import { GetPostQuery } from "../__generated__/graphql"; | ||
| import { FaustTemplate } from "@faustwp/core"; | ||
|
|
||
| const Component: FaustTemplate<GetPostQuery> = (props) => { | ||
| ... | ||
| } | ||
| ``` | ||
|
|
||
| Then you can inspect all the types in the `props` parameters as you type: | ||
|
|
||
|  | ||
|
|
||
| All the data from the query results will be properly typed based on the introspected schema: | ||
|
|
||
|  | ||
|
|
||
| ## How to apply types for block components | ||
|
|
||
| Similarly, when creating Block components using `@faustwp/blocks` packages, you can use the `WordPressBlock` type that will include all the relevant properties of that block: | ||
|
|
||
| ```ts title="src/wp-blocks/CoreParagraph.tsx" | ||
| import { gql } from "../__generated__"; | ||
| import { WordPressBlock } from "@faustwp/blocks"; | ||
| import { CoreParagraphFragmentFragment } from "../__generated__/graphql"; | ||
|
|
||
| const CoreParagraph: WordPressBlock<CoreParagraphFragmentFragment> = ( | ||
| props | ||
| ) => { | ||
| return <p>{props.attributes?.content}</p>; | ||
| }; | ||
|
|
||
| export const fragments = { | ||
| entry: gql(` | ||
| fragment CoreParagraphFragment on CoreParagraph { | ||
| attributes { | ||
| content | ||
| } | ||
| } | ||
| `), | ||
| key: `CoreParagraphFragment`, | ||
| }; | ||
| ``` | ||
|
|
||
| Here we pass the `CoreParagraphFragmentFragment` type that corresponds to the `CoreParagraphFragment` fragment mapping all fields to TypeScript types. Then TypeScript will only allow the declared types to be used in the props parameter. | ||
|
|
||
| ## How to apply types for the plugin system | ||
|
|
||
| Faust providers a `FaustHooks` type that you can use for applying the corresponding type of the `hooks` parameter: | ||
|
|
||
| ```ts title="src/plugins/ProjectTemplatePlugin.ts" | ||
| import { FaustHooks, FaustPlugin } from "@faustwp/core"; | ||
|
|
||
| export class ProjectTemplatePlugin implements FaustPlugin { | ||
| constructor() {} | ||
|
|
||
| apply(hooks: FaustHooks) { | ||
| hooks.addFilter("possibleTemplatesList", "faust", (templates, data) => { | ||
| if (data?.seedNode?.__typename === "Project") { | ||
| return Array.from(new Set(["project", ...templates])); | ||
| } | ||
| return templates; | ||
| }); | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Here the `hooks` parameter will autocomplete all correct types from each filter that is provided by the framework: | ||
|
|
||
|  | ||
|
|
||
| ## How to migrate existing pages to TypeScript | ||
|
|
||
| In general terms, most of the strategies for migrating existing pages to TypeScript should follow the relevant guide described in the [TypeScript Docs](https://www.typescriptlang.org/docs/). | ||
|
|
||
| To summarize, you should use the following types available: | ||
|
|
||
| - `FaustTemplate`: For WP Template pages. | ||
| - `WordPressBlock`: For Block components. | ||
| - `GetStaticProps`, `GetServerSideProps`, and `GetStaticPaths`: For the result type of the Next.js `getStaticProps`, `getServerSideProps`, and `getStaticPaths` functions. | ||
| - `FaustHooks`: For the Plugin system hooks. | ||
|
|
||
| Let’s see an example of how to type the `[...wordpressNode].tsx` page: | ||
|
|
||
| ```ts title=" src/pages/[...wordpressNode].tsx" | ||
|
|
||
|
|
||
| import { getWordPressProps, WordPressTemplate } from "@faustwp/core"; | ||
| import { GetStaticPaths, GetStaticProps } from "next"; | ||
|
|
||
| export type WordPressTemplateProps = Parameters<typeof WordPressTemplate>[0]; | ||
|
|
||
| export default function Page(props: WordPressTemplateProps) { | ||
| return <WordPressTemplate {...props} />; | ||
| } | ||
|
|
||
| export const getStaticProps: GetStaticProps = (ctx) => { | ||
| return getWordPressProps({ ctx }); | ||
| }; | ||
|
|
||
| export const getStaticPaths: GetStaticPaths = () => { | ||
| return { | ||
| paths: [], | ||
| fallback: "blocking", | ||
| }; | ||
| }; | ||
| ``` | ||
|
|
||
| Here, since we are not exposing the type parameters of the `WordPressTemplate` function, you will need to extract them using the [Parameters](https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype) utility type: | ||
|
|
||
| ```ts title="[...wordpressNode].tsx" | ||
| export type WordPressTemplateProps = Parameters<typeof WordPressTemplate>[0]; | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Why are we showing graphql codegen here? Don't we have our own generate command for this?
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.
It's because it showed in the original docs here and it tells the user to consider it:
https://faustjs.org/guide/how-to-implement-typescript
Should I just do away with codegen @moonmeister ?
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.
Yeah, my best guess is this doc was written before our built in generate command had shipped and it was never updated. Let's get that fixed.
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.
Sounds good will fix it