├── packages ├── gatsby-plugin-ts │ ├── index.js │ ├── .npmignore │ ├── .gitignore │ ├── src │ │ ├── require-resolve.ts │ │ ├── gatsby-node.ts │ │ └── gatsby-node.test.js │ ├── package.json │ ├── tsconfig.json │ └── readme.md ├── gatsby-plugin-graphql-codegen │ ├── index.js │ ├── .npmignore │ ├── .gitignore │ ├── package.json │ ├── src │ │ ├── graphql-codegen.config.ts │ │ ├── gatsby-node.ts │ │ ├── graphql-codegen.config.test.js │ │ └── gatsby-node.test.js │ ├── tsconfig.json │ └── readme.md ├── gatsby-starter-blog-ts │ ├── static │ │ ├── robots.txt │ │ └── favicon.ico │ ├── src │ │ ├── global.d.ts │ │ ├── utils │ │ │ └── typography.ts │ │ ├── pages │ │ │ ├── 404.tsx │ │ │ └── index.tsx │ │ ├── components │ │ │ ├── bio.tsx │ │ │ ├── layout.tsx │ │ │ └── seo.tsx │ │ └── templates │ │ │ └── blog-post.tsx │ ├── types │ │ └── typography-theme-wordpress-2016 │ │ │ └── index.d.ts │ ├── .prettierrc │ ├── content │ │ ├── assets │ │ │ ├── gatsby-icon.png │ │ │ └── profile-pic.jpg │ │ └── blog │ │ │ ├── hello-world │ │ │ ├── salty_egg.jpg │ │ │ └── index.md │ │ │ ├── my-second-post │ │ │ └── index.md │ │ │ └── hi-folks │ │ │ └── index.md │ ├── LICENSE │ ├── .gitignore │ ├── gatsby-node.js │ ├── package.json │ ├── gatsby-config.js │ ├── tsconfig.json │ └── README.md └── gatsby-starter-ts │ ├── .prettierignore │ ├── .prettierrc │ ├── src │ ├── images │ │ ├── gatsby-icon.png │ │ └── gatsby-astronaut.png │ ├── pages │ │ ├── 404.tsx │ │ ├── page-2.tsx │ │ └── index.tsx │ ├── helpers │ │ ├── ensure-keys.ts │ │ └── assert-all.ts │ └── components │ │ ├── header.tsx │ │ ├── layout.tsx │ │ ├── image.tsx │ │ ├── seo.tsx │ │ └── layout.css │ ├── gatsby-node.js │ ├── gatsby-browser.tsx │ ├── gatsby-ssr.tsx │ ├── LICENSE │ ├── .gitignore │ ├── package.json │ ├── gatsby-config.js │ ├── tsconfig.json │ └── README.md ├── .gitignore ├── types └── gatsby-graphql.d.ts ├── prettier.config.js ├── babel.config.js ├── lerna.json ├── .eslintignore ├── .github ├── workflows │ ├── npm7.yml │ └── pull-request.yml └── ISSUE_TEMPLATE │ └── bug_report.md ├── renovate.json ├── scripts └── confirm.js ├── jest.config.js ├── LICENSE ├── package.json ├── .eslintrc.js ├── changelog.md └── readme.md /packages/gatsby-plugin-ts/index.js: -------------------------------------------------------------------------------- 1 | // noop -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-codegen/index.js: -------------------------------------------------------------------------------- 1 | // noop -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/static/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/src/global.d.ts: -------------------------------------------------------------------------------- 1 | declare const __PATH_PREFIX__: string 2 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/.prettierignore: -------------------------------------------------------------------------------- 1 | .cache 2 | package.json 3 | package-lock.json 4 | public 5 | -------------------------------------------------------------------------------- /types/gatsby-graphql.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'gatsby/graphql' { 2 | export * from 'graphql' 3 | } 4 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-ts/.npmignore: -------------------------------------------------------------------------------- 1 | # Publish built files 2 | ** 3 | !gatsby-node.js 4 | !require-resolve.js -------------------------------------------------------------------------------- /packages/gatsby-plugin-ts/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore built files 2 | gatsby-node.js 3 | gatsby-node.d.ts 4 | require-resolve.js -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-codegen/.npmignore: -------------------------------------------------------------------------------- 1 | # Publish built files 2 | ** 3 | !gatsby-node.js 4 | !graphql-codegen.config.js -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/types/typography-theme-wordpress-2016/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'typography-theme-wordpress-2016' 2 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | trailingComma: "es5", 3 | tabWidth: 2, 4 | semi: false, 5 | singleQuote: true, 6 | } -------------------------------------------------------------------------------- /packages/gatsby-plugin-ts/src/require-resolve.ts: -------------------------------------------------------------------------------- 1 | // this file is needed for testing so we can mock its result 2 | export default require.resolve 3 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d4rekanguok/gatsby-typescript/HEAD/packages/gatsby-starter-blog-ts/static/favicon.ico -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": false, 4 | "singleQuote": true, 5 | "tabWidth": 2, 6 | "trailingComma": "es5" 7 | } -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-codegen/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore built files 2 | gatsby-node.js 3 | gatsby-node.d.ts 4 | graphql-codegen.config.js 5 | graphql-codegen.config.d.ts -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "trailingComma": "es5", 4 | "singleQuote": true, 5 | "semi": false, 6 | "endOfLine": "lf" 7 | } -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/src/images/gatsby-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d4rekanguok/gatsby-typescript/HEAD/packages/gatsby-starter-ts/src/images/gatsby-icon.png -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/src/images/gatsby-astronaut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d4rekanguok/gatsby-typescript/HEAD/packages/gatsby-starter-ts/src/images/gatsby-astronaut.png -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/content/assets/gatsby-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d4rekanguok/gatsby-typescript/HEAD/packages/gatsby-starter-blog-ts/content/assets/gatsby-icon.png -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/content/assets/profile-pic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d4rekanguok/gatsby-typescript/HEAD/packages/gatsby-starter-blog-ts/content/assets/profile-pic.jpg -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/content/blog/hello-world/salty_egg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d4rekanguok/gatsby-typescript/HEAD/packages/gatsby-starter-blog-ts/content/blog/hello-world/salty_egg.jpg -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/gatsby-node.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's Node APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/node-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it 8 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/gatsby-browser.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's Browser APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/browser-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it 8 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/gatsby-ssr.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's SSR (Server Side Rendering) APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/ssr-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it 8 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | // babel is used purely for jest 2 | module.exports = { 3 | presets: [ 4 | [ 5 | '@babel/preset-env', 6 | { 7 | targets: { node: true }, 8 | }, 9 | ], 10 | ['@babel/preset-typescript'], 11 | ], 12 | } 13 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/*" 4 | ], 5 | "publish": { 6 | "ignoreChanges": [ 7 | "*.md" 8 | ], 9 | "message": "chore(release): publish" 10 | }, 11 | "npmClient": "yarn", 12 | "useWorkspaces": true, 13 | "version": "3.1.1" 14 | } 15 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .cache 3 | public 4 | 5 | packages/gatsby-plugin-graphql-codegen/gatsby-node.js 6 | packages/gatsby-plugin-graphql-codegen/index.js 7 | 8 | packages/gatsby-plugin-ts/gatsby-node.js 9 | packages/gatsby-plugin-ts/require-resolve.js 10 | packages/gatsby-plugin-ts/index.js 11 | 12 | ## babel, jest, prettier 13 | *.config.js -------------------------------------------------------------------------------- /.github/workflows/npm7.yml: -------------------------------------------------------------------------------- 1 | name: NPM7 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | node: [14, 16] 11 | steps: 12 | - uses: actions/checkout@v2 13 | - name: use node ${{ matrix.node }} 14 | uses: actions/setup-node@v2 15 | with: 16 | node-version: ${{ matrix.node }} 17 | - run: npm install 18 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/src/pages/404.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | import Layout from '../components/layout' 4 | import SEO from '../components/seo' 5 | 6 | const NotFoundPage: React.FC = () => ( 7 | 8 | 9 |

NOT FOUND

10 |

You just hit a route that doesn't exist... the sadness.

11 |
12 | ) 13 | 14 | export default NotFoundPage 15 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ], 5 | "packageRules": [ 6 | { 7 | "packageNames": ["graphql"], 8 | "allowedVersions": "<=14" 9 | }, 10 | { 11 | "depTypeList": ["dependencies"], 12 | "rangeStrategy": "pin" 13 | }, 14 | { 15 | "updateTypes": ["minor", "patch", "pin", "digest"], 16 | "automerge": true, 17 | "automergeType": "pr" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/src/pages/page-2.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { Link } from 'gatsby' 3 | 4 | import Layout from '../components/layout' 5 | import SEO from '../components/seo' 6 | 7 | const SecondPage: React.FC = () => ( 8 | 9 | 10 |

Hi from the second page

11 |

Welcome to page 2

12 | Go back to the homepage 13 |
14 | ) 15 | 16 | export default SecondPage 17 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/content/blog/my-second-post/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: My Second Post! 3 | date: "2015-05-06T23:46:37.121Z" 4 | --- 5 | 6 | Wow! I love blogging so much already. 7 | 8 | Did you know that "despite its name, salted duck eggs can also be made from 9 | chicken eggs, though the taste and texture will be somewhat different, and the 10 | egg yolk will be less rich."? 11 | ([Wikipedia Link](http://en.wikipedia.org/wiki/Salted_duck_egg)) 12 | 13 | Yeah, I didn't either. 14 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { Link } from 'gatsby' 3 | 4 | import Layout from '../components/layout' 5 | import Image from '../components/image' 6 | import SEO from '../components/seo' 7 | 8 | const IndexPage: React.FC = () => ( 9 | 10 | 11 |

Hi people

12 |

Welcome to your new Gatsby site.

13 |

Now go build something great.

14 |
15 | 16 |
17 | Go to page 2 18 |
19 | ) 20 | 21 | export default IndexPage 22 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/src/utils/typography.ts: -------------------------------------------------------------------------------- 1 | import Typography from 'typography' 2 | import Wordpress2016 from 'typography-theme-wordpress-2016' 3 | 4 | Wordpress2016.overrideThemeStyles = () => { 5 | return { 6 | 'a.gatsby-resp-image-link': { 7 | boxShadow: `none`, 8 | }, 9 | } 10 | } 11 | 12 | delete Wordpress2016.googleFonts 13 | 14 | const typography = new Typography(Wordpress2016) 15 | 16 | // Hot reload typography in development. 17 | if (process.env.NODE_ENV !== `production`) { 18 | typography.injectStyles() 19 | } 20 | 21 | export default typography 22 | export const rhythm = typography.rhythm 23 | export const scale = typography.scale 24 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/src/helpers/ensure-keys.ts: -------------------------------------------------------------------------------- 1 | import assertAll from './assert-all' 2 | 3 | type ExcludeNullable> = NonNullable & 4 | { 5 | [k in K]-?: Exclude[k], null | undefined> 6 | } 7 | 8 | /** 9 | * Uses `assertAll` to assert the keys of an object are there and then returns 10 | * it. This is useful for asserting a codegen'ed graphQL type conforms to how 11 | * you're using it. 12 | */ 13 | function ensureKeys>( 14 | obj: T, 15 | keysToCheck: K[] 16 | ): ExcludeNullable { 17 | assertAll(obj, keysToCheck) 18 | return obj 19 | } 20 | 21 | export default ensureKeys 22 | -------------------------------------------------------------------------------- /scripts/confirm.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | 4 | function confirm() { 5 | const projectDir = path.join(process.cwd(), 'packages', 'gatsby-starter-ts') 6 | const generatedFile = path.join(projectDir, 'graphql-types.ts') 7 | const generatedAdditionalFile = path.join( 8 | projectDir, 9 | 'graphql-types-pokemon.ts' 10 | ) 11 | 12 | for (const file of [generatedFile, generatedAdditionalFile]) { 13 | fs.stat(file, (err) => { 14 | if (err) { 15 | console.error(`${file} doesn't exist.`) 16 | throw new Error(err) 17 | } 18 | 19 | console.log(`Generated: ${file}`) 20 | }) 21 | } 22 | } 23 | 24 | confirm() 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is & what you expected to happen instead 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior, or even better, a reproduction repository. This will allow us to address your issue a lot more quickly! 15 | 16 | **Environment (please complete the relevant info):** 17 | - OS (Mac, Linux, Window, etc.) 18 | - Gatsby version 19 | - Typescript version 20 | 21 | **Additional context** 22 | Add any other context about the problem here, `gatsby-config`, `tsconfig.json`, etc. 23 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | // For a detailed explanation regarding each configuration property, visit: 2 | // https://jestjs.io/docs/en/configuration.html 3 | 4 | const fs = require('fs') 5 | const path = require('path') 6 | const packages = fs.readdirSync(path.join(__dirname, './packages')) 7 | 8 | // https://jestjs.io/docs/en/configuration.html#modulenamemapper-objectstring-string 9 | const moduleNameMapperFromPackages = packages 10 | .map(package => [`^${package}/(.*)$`, `/packages/${package}/src/$1`]) 11 | .reduce((acc, [key, value]) => { 12 | acc[key] = value 13 | return acc 14 | }, {}) 15 | 16 | module.exports = { 17 | clearMocks: true, 18 | coverageDirectory: 'coverage', 19 | testEnvironment: 'node', 20 | moduleNameMapper: moduleNameMapperFromPackages, 21 | modulePathIgnorePatterns: ['.cache'], 22 | } 23 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/src/components/header.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from 'gatsby' 2 | import * as React from 'react' 3 | 4 | interface Props { 5 | siteTitle?: string 6 | } 7 | 8 | const Header: React.FC = ({ siteTitle = `` }) => ( 9 |
15 |
22 |

23 | 30 | {siteTitle} 31 | 32 |

33 |
34 |
35 | ) 36 | 37 | export default Header 38 | -------------------------------------------------------------------------------- /.github/workflows/pull-request.yml: -------------------------------------------------------------------------------- 1 | name: Lint, Build, Test 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - uses: actions/setup-node@v1 11 | with: 12 | node-version: 14.x 13 | 14 | - name: Get yarn cache 15 | id: yarn-cache 16 | run: echo "::set-output name=dir::$(yarn cache dir)" 17 | 18 | - uses: actions/cache@v2 19 | with: 20 | path: ${{ steps.yarn-cache.outputs.dir }} 21 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 22 | restore-keys: | 23 | ${{ runner.os }}-yarn- 24 | 25 | - run: yarn install --frozen-lockfile 26 | - run: yarn bootstrap 27 | - run: yarn lint 28 | - run: yarn build 29 | env: 30 | GATSBY_TELEMETRY_DISABLED: 1 31 | CI: true 32 | - run: yarn test 33 | - run: yarn confirm 34 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/src/pages/404.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { graphql } from 'gatsby' 3 | 4 | import Layout from '../components/layout' 5 | import SEO from '../components/seo' 6 | 7 | interface INotFoundPage { 8 | data: any 9 | location: Location 10 | } 11 | 12 | class NotFoundPage extends React.Component { 13 | render(): JSX.Element { 14 | const { data, location } = this.props 15 | const siteTitle = data.site.siteMetadata.title 16 | 17 | return ( 18 | 19 | 20 |

Not Found

21 |

You just hit a route that doesn't exist... the sadness.

22 |
23 | ) 24 | } 25 | } 26 | 27 | export default NotFoundPage 28 | 29 | export const pageQuery = graphql` 30 | query { 31 | site { 32 | siteMetadata { 33 | title 34 | } 35 | } 36 | } 37 | ` 38 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/content/blog/hello-world/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hello World 3 | date: "2015-05-01T22:12:03.284Z" 4 | --- 5 | 6 | This is my first post on my new fake blog! How exciting! 7 | 8 | I'm sure I'll write a lot more interesting things in the future. 9 | 10 | Oh, and here's a great quote from this Wikipedia on 11 | [salted duck eggs](http://en.wikipedia.org/wiki/Salted_duck_egg). 12 | 13 | > A salted duck egg is a Chinese preserved food product made by soaking duck 14 | > eggs in brine, or packing each egg in damp, salted charcoal. In Asian 15 | > supermarkets, these eggs are sometimes sold covered in a thick layer of salted 16 | > charcoal paste. The eggs may also be sold with the salted paste removed, 17 | > wrapped in plastic, and vacuum packed. From the salt curing process, the 18 | > salted duck eggs have a briny aroma, a gelatin-like egg white and a 19 | > firm-textured, round yolk that is bright orange-red in color. 20 | 21 | ![Chinese Salty Egg](./salty_egg.jpg) 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Derek Nguyen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Gatsbyjs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 gatsbyjs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/src/helpers/assert-all.ts: -------------------------------------------------------------------------------- 1 | type ExcludeNullable> = NonNullable & 2 | { 3 | [k in K]-?: Exclude[k], null | undefined> 4 | } 5 | 6 | /** 7 | * This function asserts all the properties of a given object are defined and 8 | * throws otherwise. This is useful when checking if a GraphQL response conforms 9 | * to a certain typescript type. 10 | */ 11 | function assertAll>( 12 | obj: T, 13 | keysToCheck: K[] 14 | ): asserts obj is ExcludeNullable { 15 | if (obj === null) { 16 | throw new Error(`Expected an object but found null`) 17 | } 18 | if (obj === undefined) { 19 | throw new Error(`Expected an object but found undefined`) 20 | } 21 | const nonNullableObj = obj as NonNullable 22 | 23 | for (const key of keysToCheck) { 24 | if (nonNullableObj[key] === null) { 25 | throw new Error(`Expected object to have key "${key}" but found null`) 26 | } 27 | if (nonNullableObj[key] === undefined) { 28 | throw new Error( 29 | `Expected object to have key "${key}" but found undefined` 30 | ) 31 | } 32 | } 33 | } 34 | 35 | export default assertAll 36 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/.gitignore: -------------------------------------------------------------------------------- 1 | !gatsby-node.js 2 | 3 | .yalc 4 | yalc.lock 5 | 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (http://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # Typescript v1 declaration files 45 | typings/ 46 | 47 | # Optional npm cache directory 48 | .npm 49 | 50 | # Optional eslint cache 51 | .eslintcache 52 | 53 | # Optional REPL history 54 | .node_repl_history 55 | 56 | # Output of 'npm pack' 57 | *.tgz 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # gatsby files 63 | .cache/ 64 | public 65 | 66 | # Mac files 67 | .DS_Store 68 | 69 | # Yarn 70 | yarn-error.log 71 | .pnp/ 72 | .pnp.js 73 | # Yarn Integrity file 74 | .yarn-integrity 75 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # dotenv environment variable files 55 | .env* 56 | 57 | # gatsby files 58 | .cache/ 59 | public 60 | 61 | # Mac files 62 | .DS_Store 63 | 64 | # Yarn 65 | yarn-error.log 66 | .pnp/ 67 | .pnp.js 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # Codegen 72 | graphql-types.ts 73 | graphql-types-pokemon.ts -------------------------------------------------------------------------------- /packages/gatsby-plugin-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-plugin-ts", 3 | "version": "3.1.1", 4 | "description": "Typescript support via ts-loader & fork-ts-checker-webpack-plugin + automate codegen", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "tsc -p ./", 8 | "prepublishOnly": "tsc -p ./" 9 | }, 10 | "keywords": [ 11 | "gatsby", 12 | "gatsby-plugin", 13 | "typescript" 14 | ], 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/d4rekanguok/gatsby-typescript.git" 18 | }, 19 | "author": "Derek Nguyen ", 20 | "license": "MIT", 21 | "dependencies": { 22 | "fork-ts-checker-webpack-plugin": "^6.2.10", 23 | "fs-extra": "^10.0.0", 24 | "gatsby-plugin-graphql-codegen": "^3.1.1", 25 | "ts-loader": "^9.2.2" 26 | }, 27 | "peerDependencies": { 28 | "gatsby": ">=3.0.0", 29 | "graphql": "^15.0.0", 30 | "typescript": "*" 31 | }, 32 | "peerDependenciesMeta": { 33 | "graphql": { 34 | "optional": true 35 | } 36 | }, 37 | "devDependencies": { 38 | "@types/fs-extra": "^9.0.0", 39 | "@types/node": "^14.0.0", 40 | "gatsby": "^4.0.0", 41 | "typescript": "^4.3.2" 42 | }, 43 | "bugs": { 44 | "url": "https://github.com/d4rekanguok/gatsby-typescript/issues" 45 | }, 46 | "homepage": "https://github.com/d4rekanguok/gatsby-typescript#readme" 47 | } 48 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/src/components/layout.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Layout component that queries for data 3 | * with Gatsby's useStaticQuery component 4 | * 5 | * See: https://www.gatsbyjs.org/docs/use-static-query/ 6 | */ 7 | 8 | import * as React from 'react' 9 | import { useStaticQuery, graphql } from 'gatsby' 10 | import ensureKeys from '../helpers/ensure-keys' 11 | import { SiteTitleQuery } from '../../graphql-types' 12 | 13 | import Header from './header' 14 | import './layout.css' 15 | 16 | interface Props { 17 | children: React.ReactNode 18 | } 19 | 20 | const Layout: React.FC = ({ children }) => { 21 | const data = useStaticQuery(graphql` 22 | query SiteTitle { 23 | site { 24 | siteMetadata { 25 | title 26 | } 27 | } 28 | } 29 | `) 30 | 31 | const { title } = ensureKeys(data.site?.siteMetadata, ['title']) 32 | 33 | return ( 34 | <> 35 |
36 |
43 |
{children}
44 |
45 | © {new Date().getFullYear()}, Built with 46 | {` `} 47 | Gatsby 48 |
49 |
50 | 51 | ) 52 | } 53 | 54 | export default Layout 55 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/src/components/image.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { useStaticQuery, graphql } from 'gatsby' 3 | import Img from 'gatsby-image' 4 | import ensureKeys from '../helpers/ensure-keys' 5 | import { ImageQuery } from '../../graphql-types' 6 | 7 | /* 8 | * This component is built using `gatsby-image` to automatically serve optimized 9 | * images with lazy loading and reduced file sizes. The image is loaded using a 10 | * `useStaticQuery`, which allows us to load the image from directly within this 11 | * component, rather than having to pass the image data down from pages. 12 | * 13 | * For more information, see the docs: 14 | * - `gatsby-image`: https://gatsby.dev/gatsby-image 15 | * - `useStaticQuery`: https://www.gatsbyjs.org/docs/use-static-query/ 16 | */ 17 | 18 | const Image: React.FC = () => { 19 | const data = useStaticQuery(graphql` 20 | query Image { 21 | placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) { 22 | childImageSharp { 23 | fluid(maxWidth: 300) { 24 | ...GatsbyImageSharpFluid 25 | } 26 | } 27 | } 28 | } 29 | `) 30 | 31 | const { fluid } = ensureKeys(data.placeholderImage?.childImageSharp, [ 32 | 'fluid', 33 | ]) 34 | 35 | return ( 36 | 37 | ) 38 | } 39 | 40 | export default Image 41 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-typescript", 3 | "version": "2.0.0", 4 | "description": "Alternative typescript support plugin for Gatsbyjs. Aims to make using typescript in Gatsby as painless as possible", 5 | "main": "index.js", 6 | "repository": "https://github.com/d4rekanguok/gatsby-plugin-ts.git", 7 | "author": "Derek Nguyen ", 8 | "license": "MIT", 9 | "scripts": { 10 | "bootstrap": "lerna bootstrap --use-workspaces", 11 | "build": "lerna run build", 12 | "test": "jest", 13 | "confirm": "node scripts/confirm", 14 | "lint": "eslint ." 15 | }, 16 | "private": true, 17 | "workspaces": { 18 | "packages": [ 19 | "packages/*" 20 | ], 21 | "nohoist": [ 22 | "**/gatsby-transformer-sharp", 23 | "**/gatsby-transformer-remark/**" 24 | ] 25 | }, 26 | "devDependencies": { 27 | "@babel/core": "^7.14.3", 28 | "@babel/preset-env": "^7.14.2", 29 | "@babel/preset-typescript": "^7.13.0", 30 | "@types/jest": "^26.0.23", 31 | "@typescript-eslint/eslint-plugin": "^4.25.0", 32 | "@typescript-eslint/parser": "^4.25.0", 33 | "eslint": "^7.27.0", 34 | "eslint-config-prettier": "^8.3.0", 35 | "eslint-plugin-jest": "^24.3.6", 36 | "eslint-plugin-prettier": "^3.4.0", 37 | "eslint-plugin-react": "^7.23.2", 38 | "graphql": "^15.0.0", 39 | "jest": "^27.0.1", 40 | "lerna": "^4.0.0", 41 | "prettier": "^2.3.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | extends: ['eslint:recommended', 'plugin:prettier/recommended'], 5 | overrides: [ 6 | // typescript 7 | { 8 | files: ['*.ts', '*.tsx'], 9 | excludedFiles: ['*.test.js', 'gatsby-node.js', 'gatsby-config.js'], 10 | plugins: ['@typescript-eslint'], 11 | extends: [ 12 | 'plugin:@typescript-eslint/eslint-recommended', 13 | 'plugin:@typescript-eslint/recommended', 14 | 'plugin:react/recommended', 15 | ], 16 | rules: { 17 | '@typescript-eslint/no-explicit-any': 0, 18 | '@typescript-eslint/member-delimiter-style': 0, 19 | '@typescript-eslint/interface-name-prefix': 0, 20 | '@typescript-eslint/no-use-before-define': 0, 21 | 'react/prop-types': 0, 22 | }, 23 | }, 24 | 25 | // gatsby and eslint config files 26 | { 27 | files: [ 28 | '.eslintrc.js', 29 | 'gatsby-node.js', 30 | 'gatsby-config.js', 31 | './scripts/**', 32 | ], 33 | env: { 34 | node: true, 35 | }, 36 | }, 37 | 38 | // test files 39 | { 40 | files: ['*.test.js'], 41 | plugins: ['jest'], 42 | env: { 43 | es6: true, 44 | node: true, 45 | 'jest/globals': true, 46 | }, 47 | extends: ['plugin:jest/recommended'], 48 | parserOptions: { 49 | ecmaVersion: 2019, 50 | sourceType: 'module', 51 | }, 52 | }, 53 | ], 54 | settings: { 55 | react: { 56 | version: 'detect', 57 | }, 58 | }, 59 | } 60 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-starter-ts", 3 | "private": true, 4 | "description": "A simple starter to get up and developing quickly with Gatsby", 5 | "version": "3.1.1", 6 | "author": "Kyle Mathews ", 7 | "dependencies": { 8 | "@types/react": "^17.0.8", 9 | "@types/react-dom": "^17.0.5", 10 | "@types/react-helmet": "^6.1.1", 11 | "gatsby": "^4.0.0", 12 | "gatsby-image": "^3.0.0", 13 | "graphql-tag": "^2.12.4", 14 | "react": "^17.0.2", 15 | "react-dom": "^17.0.2", 16 | "react-helmet": "^6.1.0" 17 | }, 18 | "devDependencies": { 19 | "gatsby-plugin-manifest": "^4.0.0", 20 | "gatsby-plugin-offline": "^5.0.0", 21 | "gatsby-plugin-react-helmet": "^5.0.0", 22 | "gatsby-plugin-sharp": "^4.0.0", 23 | "gatsby-plugin-ts": "^3.1.1", 24 | "gatsby-source-filesystem": "^4.0.0", 25 | "gatsby-transformer-sharp": "^4.0.0", 26 | "prettier": "^2.3.0", 27 | "typescript": "^4.3.2" 28 | }, 29 | "keywords": [ 30 | "gatsby" 31 | ], 32 | "license": "MIT", 33 | "scripts": { 34 | "build": "gatsby build", 35 | "develop": "gatsby develop", 36 | "format": "prettier --write \"**/*.{js,jsx,json,md}\"", 37 | "start": "npm run develop", 38 | "serve": "gatsby serve", 39 | "clean": "gatsby clean", 40 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1" 41 | }, 42 | "repository": { 43 | "type": "git", 44 | "url": "https://github.com/gatsbyjs/gatsby-starter-default" 45 | }, 46 | "bugs": { 47 | "url": "https://github.com/gatsbyjs/gatsby/issues" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/gatsby-node.js: -------------------------------------------------------------------------------- 1 | const path = require(`path`) 2 | const { createFilePath } = require(`gatsby-source-filesystem`) 3 | 4 | exports.createPages = ({ graphql, actions }) => { 5 | const { createPage } = actions 6 | 7 | const blogPost = path.resolve(`./src/templates/blog-post.tsx`) 8 | return graphql( 9 | ` 10 | { 11 | allMarkdownRemark( 12 | sort: { fields: [frontmatter___date], order: DESC } 13 | limit: 1000 14 | ) { 15 | edges { 16 | node { 17 | fields { 18 | slug 19 | } 20 | frontmatter { 21 | title 22 | } 23 | } 24 | } 25 | } 26 | } 27 | ` 28 | ).then((result) => { 29 | if (result.errors) { 30 | throw result.errors 31 | } 32 | 33 | // Create blog posts pages. 34 | const posts = result.data.allMarkdownRemark.edges 35 | 36 | posts.forEach((post, index) => { 37 | const previous = index === posts.length - 1 ? null : posts[index + 1].node 38 | const next = index === 0 ? null : posts[index - 1].node 39 | 40 | createPage({ 41 | path: post.node.fields.slug, 42 | component: blogPost, 43 | context: { 44 | slug: post.node.fields.slug, 45 | previous, 46 | next, 47 | }, 48 | }) 49 | }) 50 | 51 | return null 52 | }) 53 | } 54 | 55 | exports.onCreateNode = ({ node, actions, getNode }) => { 56 | const { createNodeField } = actions 57 | 58 | if (node.internal.type === `MarkdownRemark`) { 59 | const value = createFilePath({ node, getNode }) 60 | createNodeField({ 61 | name: `slug`, 62 | node, 63 | value, 64 | }) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-codegen/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-plugin-graphql-codegen", 3 | "version": "3.1.1", 4 | "description": "Automate codegen for Gatsby via graphql-codegen", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "tsc -p ./", 8 | "prepublishOnly": "tsc -p ./" 9 | }, 10 | "keywords": [ 11 | "gatsby", 12 | "gatsby-plugin", 13 | "typescript", 14 | "graphql", 15 | "graphql-codegen" 16 | ], 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/d4rekanguok/gatsby-typescript.git" 20 | }, 21 | "author": "Derek Nguyen ", 22 | "license": "MIT", 23 | "dependencies": { 24 | "@graphql-codegen/core": "^2.2.0", 25 | "@graphql-codegen/plugin-helpers": "^2.0.0", 26 | "@graphql-codegen/typescript": "^2.0.0", 27 | "@graphql-codegen/typescript-operations": "^2.0.0", 28 | "@graphql-tools/code-file-loader": "^7.0.0", 29 | "@graphql-tools/graphql-file-loader": "^7.0.0", 30 | "@graphql-tools/graphql-tag-pluck": "^7.0.0", 31 | "@graphql-tools/json-file-loader": "^7.0.0", 32 | "@graphql-tools/load": "^7.0.0", 33 | "@graphql-tools/url-loader": "7.0.0 - 7.4.2", 34 | "@graphql-tools/utils": "^8.0.0", 35 | "fs-extra": "^10.0.0", 36 | "lodash.debounce": "4.0.8" 37 | }, 38 | "peerDependencies": { 39 | "gatsby": ">=3.0.0", 40 | "graphql": "^15.0.0", 41 | "typescript": "*" 42 | }, 43 | "devDependencies": { 44 | "@types/fs-extra": "^9.0.0", 45 | "@types/lodash.debounce": "^4.0.0", 46 | "@types/node": "^15.0.0", 47 | "gatsby": "^4.0.0", 48 | "graphql": "^15.0.0", 49 | "typescript": "^4.3.2" 50 | }, 51 | "bugs": { 52 | "url": "https://github.com/d4rekanguok/gatsby-typescript/issues" 53 | }, 54 | "homepage": "https://github.com/d4rekanguok/gatsby-typescript#readme" 55 | } 56 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | siteMetadata: { 3 | title: `Gatsby TypeScript Starter`, 4 | description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`, 5 | author: `@gatsbyjs`, 6 | }, 7 | plugins: [ 8 | `gatsby-plugin-react-helmet`, 9 | { 10 | resolve: `gatsby-source-filesystem`, 11 | options: { 12 | name: `images`, 13 | path: `${__dirname}/src/images`, 14 | }, 15 | }, 16 | `gatsby-transformer-sharp`, 17 | `gatsby-plugin-sharp`, 18 | { 19 | resolve: `gatsby-plugin-manifest`, 20 | options: { 21 | name: `gatsby-starter-ts`, 22 | short_name: `starter`, 23 | start_url: `/`, 24 | background_color: `#294E80`, 25 | theme_color: `#294E80`, 26 | display: `minimal-ui`, 27 | icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site. 28 | }, 29 | }, 30 | { 31 | resolve: `gatsby-plugin-ts`, 32 | options: { 33 | additionalSchemas: [ 34 | { 35 | // demo api https://github.com/lucasbento/graphql-pokemon 36 | key: 'pokemon', 37 | schema: 'https://graphql-pokemon2.vercel.app', 38 | pluckConfig: { 39 | globalGqlIdentifierName: 'gql', 40 | modules: [ 41 | { 42 | name: 'graphql-tag', 43 | identifier: 'gql', 44 | }, 45 | ], 46 | }, 47 | }, 48 | ], 49 | }, 50 | }, 51 | // this (optional) plugin enables Progressive Web App + Offline functionality 52 | // To learn more, visit: https://gatsby.dev/offline 53 | // `gatsby-plugin-offline`, 54 | ], 55 | } 56 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/src/components/bio.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Bio component that queries for data 3 | * with Gatsby's StaticQuery component 4 | * 5 | * See: https://www.gatsbyjs.org/docs/static-query/ 6 | */ 7 | 8 | import * as React from 'react' 9 | import { StaticQuery, graphql } from 'gatsby' 10 | import Image from 'gatsby-image' 11 | 12 | import { rhythm } from '../utils/typography' 13 | 14 | const Bio: React.FC = () => ( 15 | { 18 | const { author, social } = data.site.siteMetadata 19 | return ( 20 |
26 | {author} 39 |

40 | Written by {author} who lives and works in San 41 | Francisco building useful things. 42 | {` `} 43 | 44 | You should follow him on Twitter 45 | 46 |

47 |
48 | ) 49 | }} 50 | /> 51 | ) 52 | 53 | const bioQuery = graphql` 54 | query BioQuery { 55 | avatar: file(absolutePath: { regex: "/profile-pic.jpg/" }) { 56 | childImageSharp { 57 | fixed(width: 50, height: 50) { 58 | ...GatsbyImageSharpFixed 59 | } 60 | } 61 | } 62 | site { 63 | siteMetadata { 64 | author 65 | social { 66 | twitter 67 | } 68 | } 69 | } 70 | } 71 | ` 72 | 73 | export default Bio 74 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/src/components/layout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Link } from 'gatsby' 3 | 4 | import { rhythm, scale } from '../utils/typography' 5 | 6 | interface ILayoutProps { 7 | location: Location 8 | title: string 9 | } 10 | 11 | class Layout extends React.Component { 12 | render(): JSX.Element { 13 | const { location, title, children } = this.props 14 | const rootPath = `${__PATH_PREFIX__}/` 15 | let header 16 | 17 | if (location.pathname === rootPath) { 18 | header = ( 19 |

26 | 34 | {title} 35 | 36 |

37 | ) 38 | } else { 39 | header = ( 40 |

46 | 54 | {title} 55 | 56 |

57 | ) 58 | } 59 | return ( 60 |
68 |
{header}
69 |
{children}
70 |
71 | © {new Date().getFullYear()}, Built with 72 | {` `} 73 | Gatsby 74 |
75 |
76 | ) 77 | } 78 | } 79 | 80 | export default Layout 81 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-starter-blog-ts", 3 | "private": true, 4 | "description": "A starter for a blog powered by Gatsby, Markdown & Typescript", 5 | "version": "3.1.1", 6 | "author": "Kyle Mathews ", 7 | "bugs": { 8 | "url": "https://github.com/d4rekanguok/gatsby-starter-blog-ts/issues" 9 | }, 10 | "dependencies": { 11 | "@types/node": "^15.6.1", 12 | "@types/react": "^17.0.8", 13 | "@types/react-dom": "^17.0.5", 14 | "@types/typography": "^0.16.3", 15 | "gatsby": "^4.0.0", 16 | "gatsby-image": "^3.0.0", 17 | "prismjs": "^1.23.0", 18 | "react": "^17.0.2", 19 | "react-dom": "^17.0.2", 20 | "react-helmet": "6.1.0", 21 | "react-typography": "^0.16.20", 22 | "typeface-merriweather": "^1.1.13", 23 | "typeface-montserrat": "^1.1.13", 24 | "typography": "^0.16.21", 25 | "typography-theme-wordpress-2016": "^0.16.19" 26 | }, 27 | "devDependencies": { 28 | "gatsby-plugin-feed": "^4.0.0", 29 | "gatsby-plugin-google-analytics": "^4.0.0", 30 | "gatsby-plugin-graphql-codegen": "^3.1.1", 31 | "gatsby-plugin-manifest": "^4.0.0", 32 | "gatsby-plugin-offline": "^5.0.0", 33 | "gatsby-plugin-react-helmet": "^5.0.0", 34 | "gatsby-plugin-sharp": "^4.0.0", 35 | "gatsby-plugin-ts": "^3.1.1", 36 | "gatsby-plugin-typescript": "^4.0.0", 37 | "gatsby-plugin-typography": "^4.0.0", 38 | "gatsby-remark-copy-linked-files": "^5.0.0", 39 | "gatsby-remark-images": "^6.0.0", 40 | "gatsby-remark-prismjs": "^6.0.0", 41 | "gatsby-remark-responsive-iframe": "^5.0.0", 42 | "gatsby-remark-smartypants": "^5.0.0", 43 | "gatsby-source-filesystem": "^4.0.0", 44 | "gatsby-transformer-remark": "^5.0.0", 45 | "gatsby-transformer-sharp": "^4.0.0", 46 | "prettier": "^2.3.0", 47 | "typescript": "^4.3.2" 48 | }, 49 | "homepage": "https://github.com/d4rekanguok/gatsby-starter-blog-ts#readme", 50 | "keywords": [ 51 | "gatsby" 52 | ], 53 | "license": "MIT", 54 | "main": "n/a", 55 | "repository": { 56 | "type": "git", 57 | "url": "git+https://github.com/d4rekanguok/gatsby-starter-blog-ts.git" 58 | }, 59 | "scripts": { 60 | "build-site": "gatsby build", 61 | "develop": "gatsby develop", 62 | "format": "prettier --write src/**/*.{js,jsx}", 63 | "start": "npm run develop", 64 | "serve": "gatsby serve", 65 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\"" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | siteMetadata: { 3 | title: `Gatsby Starter Blog`, 4 | author: `Kyle Mathews`, 5 | description: `A starter blog demonstrating what Gatsby can do.`, 6 | siteUrl: `https://gatsby-starter-blog-demo.netlify.com/`, 7 | social: { 8 | twitter: `kylemathews`, 9 | }, 10 | }, 11 | plugins: [ 12 | { 13 | resolve: `gatsby-source-filesystem`, 14 | options: { 15 | path: `${__dirname}/content/blog`, 16 | name: `blog`, 17 | }, 18 | }, 19 | { 20 | resolve: `gatsby-source-filesystem`, 21 | options: { 22 | path: `${__dirname}/content/assets`, 23 | name: `assets`, 24 | }, 25 | }, 26 | { 27 | resolve: `gatsby-transformer-remark`, 28 | options: { 29 | plugins: [ 30 | { 31 | resolve: `gatsby-remark-images`, 32 | options: { 33 | maxWidth: 590, 34 | }, 35 | }, 36 | { 37 | resolve: `gatsby-remark-responsive-iframe`, 38 | options: { 39 | wrapperStyle: `margin-bottom: 1.0725rem`, 40 | }, 41 | }, 42 | `gatsby-remark-prismjs`, 43 | `gatsby-remark-copy-linked-files`, 44 | `gatsby-remark-smartypants`, 45 | ], 46 | }, 47 | }, 48 | `gatsby-transformer-sharp`, 49 | `gatsby-plugin-sharp`, 50 | { 51 | resolve: `gatsby-plugin-ts`, 52 | options: { 53 | typeCheck: process.env.NODE_ENV !== 'production', 54 | fileName: `gen/graphql-types.ts`, 55 | }, 56 | }, 57 | // `gatsby-plugin-typescript`, 58 | // `gatsby-plugin-graphql-codegen`, 59 | { 60 | resolve: `gatsby-plugin-google-analytics`, 61 | options: { 62 | //trackingId: `ADD YOUR TRACKING ID HERE`, 63 | }, 64 | }, 65 | `gatsby-plugin-feed`, 66 | { 67 | resolve: `gatsby-plugin-manifest`, 68 | options: { 69 | name: `Gatsby Starter Blog`, 70 | short_name: `GatsbyJS`, 71 | start_url: `/`, 72 | background_color: `#ffffff`, 73 | theme_color: `#663399`, 74 | display: `minimal-ui`, 75 | icon: `content/assets/gatsby-icon.png`, 76 | }, 77 | }, 78 | `gatsby-plugin-offline`, 79 | `gatsby-plugin-react-helmet`, 80 | { 81 | resolve: `gatsby-plugin-typography`, 82 | options: { 83 | pathToConfigModule: `src/utils/typography`, 84 | }, 85 | }, 86 | ], 87 | } 88 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/src/components/seo.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * SEO component that queries for data with 3 | * Gatsby's useStaticQuery React hook 4 | * 5 | * See: https://www.gatsbyjs.org/docs/use-static-query/ 6 | */ 7 | 8 | import React from 'react' 9 | import PropTypes from 'prop-types' 10 | import { Helmet } from 'react-helmet' 11 | import { useStaticQuery, graphql } from 'gatsby' 12 | 13 | type MetaProps = JSX.IntrinsicElements['meta'] 14 | 15 | interface Props { 16 | title: string 17 | description?: string 18 | lang?: string 19 | meta?: MetaProps[] 20 | } 21 | 22 | const SEO: React.FC = ({ 23 | title, 24 | description = ``, 25 | lang = `en`, 26 | meta = [], 27 | }) => { 28 | const { site } = useStaticQuery( 29 | graphql` 30 | query { 31 | site { 32 | siteMetadata { 33 | title 34 | description 35 | author 36 | } 37 | } 38 | } 39 | ` 40 | ) 41 | 42 | const metaDescription = description || site.siteMetadata.description 43 | 44 | return ( 45 | 86 | ) 87 | } 88 | 89 | SEO.defaultProps = { 90 | lang: `en`, 91 | meta: [], 92 | description: ``, 93 | } 94 | 95 | SEO.propTypes = { 96 | description: PropTypes.string, 97 | lang: PropTypes.string, 98 | meta: PropTypes.arrayOf(PropTypes.object), 99 | title: PropTypes.string.isRequired, 100 | } 101 | 102 | export default SEO 103 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/src/templates/blog-post.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Link, graphql } from 'gatsby' 3 | 4 | import Bio from '../components/bio' 5 | import Layout from '../components/layout' 6 | import SEO from '../components/seo' 7 | import { rhythm, scale } from '../utils/typography' 8 | 9 | interface IPostTemplateProps { 10 | location: Location 11 | pageContext: any 12 | data: any 13 | } 14 | 15 | class BlogPostTemplate extends React.Component { 16 | render(): JSX.Element { 17 | const { location } = this.props 18 | const post = this.props.data.markdownRemark 19 | const siteTitle = this.props.data.site.siteMetadata.title 20 | const { previous, next } = this.props.pageContext 21 | 22 | return ( 23 | 24 | 28 |

{post.frontmatter.title}

29 |

37 | {post.frontmatter.date} 38 |

39 |
40 |
45 | 46 | 47 |
    56 |
  • 57 | {previous && ( 58 | 59 | ← {previous.frontmatter.title} 60 | 61 | )} 62 |
  • 63 |
  • 64 | {next && ( 65 | 66 | {next.frontmatter.title} → 67 | 68 | )} 69 |
  • 70 |
71 | 72 | ) 73 | } 74 | } 75 | 76 | export default BlogPostTemplate 77 | 78 | export const pageQuery = graphql` 79 | query BlogPostBySlug($slug: String!) { 80 | site { 81 | siteMetadata { 82 | title 83 | author 84 | } 85 | } 86 | markdownRemark(fields: { slug: { eq: $slug } }) { 87 | id 88 | excerpt(pruneLength: 160) 89 | html 90 | frontmatter { 91 | title 92 | date(formatString: "MMMM DD, YYYY") 93 | description 94 | } 95 | } 96 | } 97 | ` 98 | -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { Link, graphql } from 'gatsby' 3 | 4 | import Bio from '../components/bio' 5 | import Layout from '../components/layout' 6 | import SEO from '../components/seo' 7 | import { rhythm } from '../utils/typography' 8 | 9 | import { BlogIndexQuery } from '../../gen/graphql-types' 10 | 11 | interface IBlogIndexProps { 12 | // uncomment this when type is generated 13 | data: BlogIndexQuery 14 | // data: any; 15 | location: Location 16 | } 17 | 18 | class BlogIndex extends React.Component { 19 | render(): JSX.Element { 20 | const { data, location } = this.props 21 | if ( 22 | !data || 23 | !data.site || 24 | !data.site.siteMetadata || 25 | !data.site.siteMetadata.title || 26 | !data.allMarkdownRemark 27 | ) 28 | throw new Error('no data') 29 | const siteTitle = data.site.siteMetadata.title 30 | const posts = data.allMarkdownRemark.edges 31 | 32 | return ( 33 | 34 | 35 | 36 | {posts.map(({ node }) => { 37 | if ( 38 | !node.frontmatter || 39 | !node.excerpt || 40 | !node.fields || 41 | !node.fields.slug 42 | ) 43 | throw new Error('missing data') 44 | 45 | const title = node.frontmatter.title || node.fields.slug 46 | return ( 47 |
48 |

53 | 54 | {title} 55 | 56 |

57 | {node.frontmatter.date} 58 |

63 |

64 | ) 65 | })} 66 |
67 | ) 68 | } 69 | } 70 | 71 | export default BlogIndex 72 | 73 | export const pageQuery = graphql` 74 | query BlogIndex { 75 | site { 76 | siteMetadata { 77 | title 78 | } 79 | } 80 | allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) { 81 | edges { 82 | node { 83 | excerpt 84 | fields { 85 | slug 86 | } 87 | frontmatter { 88 | date(formatString: "MMMM DD, YYYY") 89 | title 90 | description 91 | } 92 | } 93 | } 94 | } 95 | } 96 | ` 97 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/src/components/seo.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * SEO component that queries for data with 3 | * Gatsby's useStaticQuery React hook 4 | * 5 | * See: https://www.gatsbyjs.org/docs/use-static-query/ 6 | */ 7 | 8 | import * as React from 'react' 9 | import { Helmet } from 'react-helmet' 10 | import { useStaticQuery, graphql } from 'gatsby' 11 | import ensureKeys from '../helpers/ensure-keys' 12 | import { SeoQuery } from '../../graphql-types' 13 | import gql from 'graphql-tag' 14 | 15 | type MetaProps = JSX.IntrinsicElements['meta'] 16 | 17 | interface Props { 18 | title: string 19 | description?: string 20 | lang?: string 21 | meta?: MetaProps[] 22 | } 23 | 24 | const SEO: React.FC = ({ 25 | title, 26 | description = ``, 27 | lang = `en`, 28 | meta = [], 29 | }) => { 30 | const { site } = useStaticQuery( 31 | graphql` 32 | query Seo { 33 | site { 34 | siteMetadata { 35 | title 36 | description 37 | author 38 | } 39 | } 40 | } 41 | ` 42 | ) 43 | 44 | const { author, description: siteDescription } = ensureKeys( 45 | site?.siteMetadata, 46 | [`author`, `description`] 47 | ) 48 | 49 | const metaDescription = description ?? siteDescription 50 | 51 | return ( 52 | 94 | ) 95 | } 96 | 97 | /** 98 | * `gatsby-plugin-ts`/`gatsby-plugin-graphql-codegen` supports codegen for 99 | * non-gatsby schemas. This is useful if you're using a client-side GraphQL client. 100 | * 101 | * Read more at: https://github.com/d4rekanguok/gatsby-typescript/blob/master/packages/gatsby-plugin-graphql-codegen/readme.md#additional-schema-options-for-optionsadditionalschemas 102 | */ 103 | export const someTestQuery = gql` 104 | query Pikachu { 105 | pokemon(name: "Pikachu") { 106 | id 107 | number 108 | name 109 | attacks { 110 | special { 111 | name 112 | type 113 | damage 114 | } 115 | } 116 | evolutions { 117 | id 118 | number 119 | name 120 | weight { 121 | minimum 122 | maximum 123 | } 124 | attacks { 125 | fast { 126 | name 127 | type 128 | damage 129 | } 130 | } 131 | } 132 | } 133 | } 134 | ` 135 | 136 | export default SEO 137 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). 6 | 7 | ## 2.7.0 8 | - codegen: User can now pass additional plugins & config for graphql-codegen via the new 2 options: `codegenConfig` and `codegenPlugins`. See readme for more info. 9 | 10 | ## 2.6.1 11 | - codegen: fix a bug where Gatsby reject codegen plugin's gatsby-node.js file 12 | 13 | ## 2.6.0 14 | - codegen: Multi schema supports: Now `codegen` accepts an additional schema. This means if you are using `graphql` on the client side, this plugin can now generate types for that as well. See readme for more information. 15 | 16 | ## 2.5.0 17 | - codegen: New config options: `failOnError`. If true, throw an error & stop the build when codegen failed. By default `codegen` will only throw an error during production. 18 | 19 | ## 2.4.0 20 | - codegen: Remove `.cache/fragments`, bump up Gatsby's peer dependencies. New Gatsby project will no longer see the warning message. 21 | - typecheck: Better default fork checker config, prevent crash. Thanks [gatsby-plugin-typescript-checker](https://github.com/DaleLJefferson/gatsby-plugin-typescript-checker)! 22 | 23 | ## 2.3.0 24 | - codegen: Only extracts graphql queries for Gatsby, allow users to pass in `pluckConfig` ([#62 by @kije](https://github.com/d4rekanguok/gatsby-typescript/pull/62)) 25 | 26 | ## 2.2.0 27 | - typecheck: Upgrade fork-ts-checker & ts-loader (#35) 28 | 29 | ## 2.1.4 30 | - codegen: Upgrade graphql-toolkit, fix a bug caused by version mismatched (#34) 31 | 32 | ## 2.1.2 33 | - codegen: Fix a graphql conflict error that happens in certain projects — use gatsby/graphql instead (#33) 34 | 35 | ## 2.1.0 36 | - Allow users to modify document paths (#26) 37 | - `gatsby-plugin-ts` now use `gatsby-plugin-graphql-codegen` under the hood instead of duplicating code 38 | 39 | ## 2.0.0 40 | - typecheck: allow user to pass in options for [`fork-ts-checker-webpack-plugin`](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin#options) 41 | - typecheck: #22: remove `alwaysCheck`, allow user to simply set `typeCheck` to enable / disable type checking completely. Previous behavior can be preserved by setting the following options in `gatsby-config.js`: 42 | 43 | ```js 44 | { 45 | resolve: 'gatsby-plugin-ts', 46 | options: { 47 | // Disable type checking in production 48 | typeCheck: process.env.NODE_ENV !== 'production', 49 | } 50 | } 51 | ``` 52 | 53 | ## 1.3.3 54 | - fix #15 where empty documents break build; display warning instead of throwing error 55 | - more greenkeeping 56 | - add `graphql-tag-pluck` as a dependency since it no longer comes with `graphql-toolkit` 57 | - use `graphql` directly instead of going thru `gatsby/graphql` 58 | 59 | ## 1.3.2 60 | - greenkeeping 61 | 62 | ## 1.3.1 63 | - fix: #13, check if directory exists before writing file 64 | 65 | ## 1.3.0 66 | - typecheck: Disable typecheck in production by default. Users can now pass in an `alwaysCheck` to enable typecheck during production (in `gatsby build`). 67 | 68 | ## 1.2.2 69 | - codegen: actually, we only need to search for fragments in root directory's `.cache` folder 70 | 71 | ## 1.2.1 72 | - codegen: restrict glob search for fragments in `node_modules` 73 | 74 | ## 1.1.1 75 | - fix missing extension in default name 76 | - fix document not being updated on file change 77 | 78 | ## 1.1.0 79 | - codegen for graphql queries now automatically re-run during develop -------------------------------------------------------------------------------- /packages/gatsby-plugin-ts/src/gatsby-node.ts: -------------------------------------------------------------------------------- 1 | import { GatsbyNode } from 'gatsby' 2 | import * as webpack from 'webpack' 3 | import * as tsloader from 'ts-loader' 4 | import FTCWebpackPlugin from 'fork-ts-checker-webpack-plugin' 5 | import { 6 | onPostBootstrap as onPostBootstrapCodegen, 7 | PluginOptions, 8 | } from 'gatsby-plugin-graphql-codegen/gatsby-node' 9 | import requireResolve from './require-resolve' 10 | import { ForkTsCheckerWebpackPluginOptions } from 'fork-ts-checker-webpack-plugin/lib/ForkTsCheckerWebpackPluginOptions' 11 | 12 | export interface TsOptions extends PluginOptions { 13 | tsLoader?: Partial 14 | typeCheck?: boolean 15 | alwaysCheck?: boolean 16 | forkTsCheckerPlugin?: Partial 17 | } 18 | 19 | const defaultOptions: TsOptions = { 20 | plugins: [], 21 | tsLoader: {}, 22 | typeCheck: true, 23 | alwaysCheck: false, 24 | forkTsCheckerPlugin: { 25 | async: false, 26 | formatter: 'codeframe', 27 | logger: { 28 | infrastructure: 'silent', 29 | issues: 'console', 30 | }, 31 | }, 32 | } 33 | 34 | // TODO: use something like lodash defaultDeep here when options get more complex 35 | type GetOptions = (options: TsOptions) => TsOptions 36 | const getOptions: GetOptions = (pluginOptions) => ({ 37 | ...defaultOptions, 38 | ...pluginOptions, 39 | forkTsCheckerPlugin: { 40 | ...defaultOptions.forkTsCheckerPlugin, 41 | ...pluginOptions.forkTsCheckerPlugin, 42 | }, 43 | }) 44 | 45 | type CreateRule = ( 46 | jsLoader: webpack.RuleSetUseItem, 47 | options: TsOptions 48 | ) => webpack.RuleSetRule 49 | const createRule: CreateRule = (jsLoader, { tsLoader }) => ({ 50 | test: /\.tsx?$/, 51 | exclude: /node_modules/, 52 | use: [ 53 | jsLoader, 54 | { 55 | loader: requireResolve('ts-loader'), 56 | options: { 57 | ...tsLoader, 58 | // use ForkTsCheckerWebpackPlugin for typecheck 59 | transpileOnly: true, 60 | }, 61 | }, 62 | ], 63 | }) 64 | 65 | export const resolvableExtensions: GatsbyNode['resolvableExtensions'] = () => [ 66 | '.ts', 67 | '.tsx', 68 | ] 69 | 70 | export const onCreateWebpackConfig: GatsbyNode['onCreateWebpackConfig'] = ( 71 | { loaders, actions }, 72 | pluginOptions: TsOptions = { plugins: [] } 73 | ) => { 74 | const options = getOptions(pluginOptions) 75 | const { typeCheck, forkTsCheckerPlugin } = options 76 | const jsLoader = loaders.js() 77 | if (!jsLoader) return 78 | const tsRule = createRule(jsLoader, options) 79 | 80 | const plugins: NonNullable = [] 81 | if (typeCheck) { 82 | plugins.push(new FTCWebpackPlugin(forkTsCheckerPlugin)) 83 | } 84 | 85 | const config: webpack.Configuration = { 86 | module: { 87 | rules: [tsRule], 88 | }, 89 | plugins, 90 | } 91 | 92 | actions.setWebpackConfig(config) 93 | } 94 | 95 | export const onPostBootstrap = onPostBootstrapCodegen 96 | 97 | export const onPreInit: GatsbyNode['onPreInit'] = ( 98 | { reporter }, 99 | options: TsOptions = { plugins: [] } 100 | ) => { 101 | const { alwaysCheck } = options 102 | const { typeCheck } = getOptions(options) 103 | if (typeof alwaysCheck !== 'undefined') { 104 | reporter.warn( 105 | `[gatsby-plugin-ts] \`alwaysCheck\` has been deprecated. Please set \`typeCheck\` instead.` 106 | ) 107 | } 108 | reporter.info( 109 | `[gatsby-plugin-ts] Typecheck is ${typeCheck ? 'enabled' : 'disabled'}.` 110 | ) 111 | } 112 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-ts/src/gatsby-node.test.js: -------------------------------------------------------------------------------- 1 | import { 2 | onPreInit, 3 | onCreateWebpackConfig, 4 | resolvableExtensions, 5 | } from './gatsby-node' 6 | 7 | jest.mock( 8 | 'fork-ts-checker-webpack-plugin', 9 | () => 10 | class MockFTCWebpackPlugin { 11 | constructor(options) { 12 | this.options = options 13 | } 14 | } 15 | ) 16 | 17 | jest.mock('./require-resolve', () => () => 'mock-resolved.ts') 18 | 19 | describe('resolvableExtensions', () => { 20 | it('is .ts and .tsx', () => { 21 | expect(resolvableExtensions()).toMatchInlineSnapshot(` 22 | Array [ 23 | ".ts", 24 | ".tsx", 25 | ] 26 | `) 27 | }) 28 | }) 29 | 30 | describe('onCreateWebpack', () => { 31 | it('early returns if there is no js loaders', () => { 32 | const mockGatsbyArgs = { 33 | loaders: { 34 | js: () => null, 35 | }, 36 | actions: { setWebpackConfig: jest.fn() }, 37 | } 38 | 39 | const pluginOptions = {} 40 | 41 | onCreateWebpackConfig(mockGatsbyArgs, pluginOptions) 42 | 43 | expect(mockGatsbyArgs.actions.setWebpackConfig).not.toHaveBeenCalled() 44 | }) 45 | 46 | it('creates a config', () => { 47 | const mockGatsbyArgs = { 48 | loaders: { 49 | js: () => 'mock-js-loader', 50 | }, 51 | actions: { setWebpackConfig: jest.fn() }, 52 | } 53 | 54 | const pluginOptions = { 55 | typeCheck: true, // this is a default option, but we're being explicit 56 | tsLoader: { mockOptions: {} }, 57 | } 58 | 59 | onCreateWebpackConfig(mockGatsbyArgs, pluginOptions) 60 | 61 | expect(mockGatsbyArgs.actions.setWebpackConfig).toHaveBeenCalledTimes(1) 62 | const config = mockGatsbyArgs.actions.setWebpackConfig.mock.calls[0][0] 63 | 64 | expect(config).toMatchInlineSnapshot(` 65 | Object { 66 | "module": Object { 67 | "rules": Array [ 68 | Object { 69 | "exclude": /node_modules/, 70 | "test": /\\\\\\.tsx\\?\\$/, 71 | "use": Array [ 72 | "mock-js-loader", 73 | Object { 74 | "loader": "mock-resolved.ts", 75 | "options": Object { 76 | "mockOptions": Object {}, 77 | "transpileOnly": true, 78 | }, 79 | }, 80 | ], 81 | }, 82 | ], 83 | }, 84 | "plugins": Array [ 85 | MockFTCWebpackPlugin { 86 | "options": Object { 87 | "async": false, 88 | "formatter": "codeframe", 89 | "logger": Object { 90 | "infrastructure": "silent", 91 | "issues": "console", 92 | }, 93 | }, 94 | }, 95 | ], 96 | } 97 | `) 98 | }) 99 | }) 100 | 101 | describe('onPreInit', () => { 102 | it('logs whether or not typecheck is enabled', () => { 103 | const mockReporter = { 104 | info: jest.fn(), 105 | warn: jest.fn(), 106 | } 107 | 108 | const pluginOptions = { 109 | plugins: [], 110 | typeCheck: true, 111 | } 112 | 113 | onPreInit({ reporter: mockReporter }, pluginOptions) 114 | 115 | expect(mockReporter.info).toMatchInlineSnapshot(` 116 | [MockFunction] { 117 | "calls": Array [ 118 | Array [ 119 | "[gatsby-plugin-ts] Typecheck is enabled.", 120 | ], 121 | ], 122 | "results": Array [ 123 | Object { 124 | "type": "return", 125 | "value": undefined, 126 | }, 127 | ], 128 | } 129 | `) 130 | expect(mockReporter.warn).not.toHaveBeenCalled() 131 | }) 132 | 133 | it('warns if deprecated alwaysCheck is enabled', () => { 134 | const mockReporter = { 135 | info: jest.fn(), 136 | warn: jest.fn(), 137 | } 138 | 139 | const pluginOptions = { 140 | plugins: [], 141 | typeCheck: false, 142 | alwaysCheck: true, 143 | } 144 | 145 | onPreInit({ reporter: mockReporter }, pluginOptions) 146 | 147 | expect(mockReporter.info).toMatchInlineSnapshot(` 148 | [MockFunction] { 149 | "calls": Array [ 150 | Array [ 151 | "[gatsby-plugin-ts] Typecheck is disabled.", 152 | ], 153 | ], 154 | "results": Array [ 155 | Object { 156 | "type": "return", 157 | "value": undefined, 158 | }, 159 | ], 160 | } 161 | `) 162 | expect(mockReporter.warn).toMatchInlineSnapshot(` 163 | [MockFunction] { 164 | "calls": Array [ 165 | Array [ 166 | "[gatsby-plugin-ts] \`alwaysCheck\` has been deprecated. Please set \`typeCheck\` instead.", 167 | ], 168 | ], 169 | "results": Array [ 170 | Object { 171 | "type": "return", 172 | "value": undefined, 173 | }, 174 | ], 175 | } 176 | `) 177 | }) 178 | }) 179 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-codegen/src/graphql-codegen.config.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs-extra' 2 | import * as path from 'path' 3 | import { Reporter } from 'gatsby' 4 | import { 5 | Types, 6 | CodegenPlugin, 7 | PluginFunction, 8 | } from '@graphql-codegen/plugin-helpers' 9 | import { Source } from '@graphql-tools/utils' 10 | import { loadDocuments } from '@graphql-tools/load' 11 | import { CodeFileLoader } from '@graphql-tools/code-file-loader' 12 | import { codegen } from '@graphql-codegen/core' 13 | import { printSchema, parse, GraphQLSchema } from 'gatsby/graphql' 14 | import { plugin as typescriptPlugin } from '@graphql-codegen/typescript' 15 | import { plugin as operationsPlugin } from '@graphql-codegen/typescript-operations' 16 | import { GraphQLTagPluckOptions } from '@graphql-tools/graphql-tag-pluck' 17 | 18 | function isSource(result: void | Source[]): result is Source[] { 19 | return typeof result !== 'undefined' 20 | } 21 | 22 | export type GatsbyCodegenPlugins = { 23 | resolve: 'typescript' | 'operations' | PluginFunction 24 | addToSchema: CodegenPlugin['addToSchema'] 25 | validate: CodegenPlugin['validate'] 26 | options: Record 27 | } 28 | 29 | type Plugins = { 30 | pluginMap: Record 31 | plugins: Record>[] 32 | } 33 | 34 | const defaultPlugins: Plugins = { 35 | plugins: [ 36 | { 37 | typescript: { 38 | skipTypename: true, 39 | enumsAsTypes: true, 40 | }, 41 | }, 42 | { 43 | operations: { 44 | skipTypename: true, 45 | exportFragmentSpreadSubTypes: true, 46 | }, 47 | }, 48 | ], 49 | pluginMap: { 50 | typescript: { 51 | plugin: typescriptPlugin, 52 | }, 53 | operations: { 54 | plugin: operationsPlugin, 55 | }, 56 | }, 57 | } 58 | export const mapCodegenPlugins = ({ 59 | codegenPlugins, 60 | defaultPlugins, 61 | }: { 62 | codegenPlugins: GatsbyCodegenPlugins[] 63 | defaultPlugins: Plugins 64 | }): Plugins => 65 | codegenPlugins.reduce((acc, plugin, i) => { 66 | const { resolve, options, ...otherOptions } = plugin 67 | // handle default plugins (typescript, operations) 68 | if (typeof resolve === 'string') { 69 | const added = acc.plugins.find( 70 | (addedPlugin) => Object.keys(addedPlugin)[0] === resolve 71 | ) 72 | 73 | if (!added) { 74 | throw new Error( 75 | `[gatsby-plugin-graphql-codegen] Invalid codegenPlugins: ${resolve}` 76 | ) 77 | } 78 | 79 | added[resolve] = { 80 | ...added[resolve], 81 | ...options, 82 | } 83 | // presumably new plugins 84 | } else { 85 | const identifier = `codegen-plugin-${i}` 86 | acc.plugins.push({ [identifier]: options }) 87 | acc.pluginMap[identifier] = { plugin: resolve, ...otherOptions } 88 | } 89 | return acc 90 | }, defaultPlugins) 91 | 92 | export interface CodegenOptions { 93 | documentPaths: string[] 94 | fileName: string 95 | pluckConfig: GraphQLTagPluckOptions 96 | codegenPlugins: GatsbyCodegenPlugins[] 97 | codegenConfig: Record 98 | } 99 | 100 | interface CreateConfigOptions extends CodegenOptions { 101 | directory: string 102 | reporter: Reporter 103 | } 104 | 105 | type CreateConfigFromSchema = ( 106 | schema: GraphQLSchema 107 | ) => Promise 108 | type CreateConfig = ( 109 | args: CreateConfigOptions 110 | ) => Promise 111 | const createConfig: CreateConfig = async ({ 112 | documentPaths, 113 | directory, 114 | fileName, 115 | reporter, 116 | pluckConfig, 117 | codegenPlugins, 118 | codegenConfig, 119 | }) => { 120 | // file name & location 121 | const pathToFile = path.join(directory, fileName) 122 | const { dir } = path.parse(pathToFile) 123 | await fs.ensureDir(dir) 124 | 125 | const { pluginMap, plugins } = mapCodegenPlugins({ 126 | codegenPlugins, 127 | defaultPlugins, 128 | }) 129 | 130 | return async (schema): Promise => { 131 | // documents 132 | const docPromises = documentPaths.map(async (docGlob) => { 133 | const _docGlob = path.join(directory, docGlob) 134 | return loadDocuments(_docGlob, { 135 | pluckConfig, 136 | loaders: [new CodeFileLoader()], 137 | }).catch((err) => { 138 | reporter.warn('[gatsby-plugin-graphql-codegen] ' + err.message) 139 | }) 140 | }) 141 | const results = await Promise.all(docPromises) 142 | const documents = results 143 | .filter(isSource) 144 | .reduce((acc, cur) => acc.concat(cur), []) 145 | 146 | return { 147 | filename: pathToFile, 148 | schema: parse(printSchema(schema)), 149 | config: codegenConfig, 150 | documents, 151 | plugins, 152 | pluginMap, 153 | } 154 | } 155 | } 156 | 157 | type GenerateFromSchema = (schema: GraphQLSchema) => Promise 158 | type GenerateWithConfig = ( 159 | initialOptions: CreateConfigOptions 160 | ) => Promise 161 | export const generateWithConfig: GenerateWithConfig = async ( 162 | initialOptions 163 | ) => { 164 | const createConfigFromSchema = await createConfig(initialOptions) 165 | return async (schema): Promise => { 166 | const config = await createConfigFromSchema(schema) 167 | const output = await codegen(config) 168 | return fs.writeFile(config.filename, output) 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-codegen/src/gatsby-node.ts: -------------------------------------------------------------------------------- 1 | import { GatsbyNode } from 'gatsby' 2 | import { 3 | generateWithConfig, 4 | GatsbyCodegenPlugins, 5 | CodegenOptions, 6 | } from './graphql-codegen.config' 7 | import debounce from 'lodash.debounce' 8 | import { GraphQLTagPluckOptions } from '@graphql-tools/graphql-tag-pluck' 9 | import { loadSchema, UnnormalizedTypeDefPointer } from '@graphql-tools/load' 10 | import { UrlLoader } from '@graphql-tools/url-loader' 11 | import { JsonFileLoader } from '@graphql-tools/json-file-loader' 12 | import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader' 13 | import { GraphQLSchema } from 'graphql' 14 | 15 | const DEFAULT_SCHEMA_KEY = 'default-gatsby-schema' 16 | 17 | export interface SchemaConfig { 18 | key: string 19 | fileName?: string 20 | schema: UnnormalizedTypeDefPointer 21 | documentPaths?: string[] 22 | pluckConfig: GraphQLTagPluckOptions 23 | codegenPlugins?: GatsbyCodegenPlugins[] 24 | codegenConfig?: Record 25 | } 26 | 27 | export interface PluginOptions extends Partial { 28 | plugins: unknown[] 29 | codegen?: boolean 30 | codegenDelay?: number 31 | failOnError?: boolean 32 | additionalSchemas?: SchemaConfig[] 33 | } 34 | 35 | const defaultOptions: Required = { 36 | plugins: [], 37 | documentPaths: ['./src/**/*.{ts,tsx}', './node_modules/gatsby-*/**/*.js'], 38 | fileName: 'graphql-types.ts', 39 | codegen: true, 40 | codegenDelay: 200, 41 | failOnError: process.env.NODE_ENV === 'production', 42 | pluckConfig: { 43 | globalGqlIdentifierName: 'graphql', 44 | modules: [ 45 | { 46 | name: 'gatsby', 47 | identifier: 'graphql', 48 | }, 49 | ], 50 | }, 51 | additionalSchemas: [], 52 | codegenPlugins: [], 53 | codegenConfig: {}, 54 | } 55 | 56 | type GetOptions = (options: PluginOptions) => Required 57 | const getOptions: GetOptions = (pluginOptions) => ({ 58 | ...defaultOptions, 59 | ...pluginOptions, 60 | }) 61 | 62 | type AsyncMap = ( 63 | collection: T[], 64 | callback: (item: T, index: number, collection: T[]) => Promise 65 | ) => Promise 66 | const asyncMap: AsyncMap = (collection, callback) => 67 | Promise.all(collection.map(callback)) 68 | 69 | export const onPostBootstrap: GatsbyNode['onPostBootstrap'] = async ( 70 | { store, reporter }, 71 | pluginOptions: PluginOptions = { plugins: [] } 72 | ) => { 73 | const options = getOptions(pluginOptions) 74 | if (!options.codegen) return 75 | 76 | const { 77 | documentPaths, 78 | fileName, 79 | codegenDelay, 80 | pluckConfig, 81 | additionalSchemas, 82 | failOnError, 83 | codegenPlugins, 84 | codegenConfig, 85 | } = options 86 | 87 | const { schema, program }: { schema: GraphQLSchema; program: any } = 88 | store.getState() 89 | const { directory } = program 90 | 91 | const defaultConfig = { 92 | key: DEFAULT_SCHEMA_KEY, 93 | fileName, 94 | documentPaths, 95 | pluckConfig, 96 | directory, 97 | schema, 98 | reporter, 99 | codegenPlugins, 100 | codegenConfig, 101 | } 102 | 103 | const configs = [ 104 | { 105 | ...defaultConfig, 106 | generateFromSchema: await generateWithConfig(defaultConfig), 107 | }, 108 | ...(await asyncMap(additionalSchemas, async ({ schema, ...config }) => { 109 | const codegenConfig = { 110 | fileName: `graphql-types-${config.key}.ts`, 111 | documentPaths, 112 | directory, 113 | schema: await loadSchema(schema, { 114 | loaders: [ 115 | new UrlLoader(), 116 | new JsonFileLoader(), 117 | new GraphQLFileLoader(), 118 | ], 119 | }), 120 | codegenPlugins: [], 121 | codegenConfig: {}, 122 | reporter, 123 | ...config, 124 | } 125 | return { 126 | ...codegenConfig, 127 | generateFromSchema: await generateWithConfig(codegenConfig), 128 | } 129 | })), 130 | ] 131 | 132 | const build = async (): Promise => { 133 | try { 134 | await asyncMap( 135 | configs, 136 | async ({ key, generateFromSchema, schema, fileName }) => { 137 | await generateFromSchema(schema) 138 | reporter.info( 139 | `[gatsby-plugin-graphql-codegen] definition for queries of schema ${key} has been updated at ${fileName}` 140 | ) 141 | } 142 | ) 143 | } catch (err) { 144 | // NOTE assume err is an ErrorMeta 145 | if (failOnError) { 146 | reporter.panic(err as any) 147 | } else { 148 | reporter.warn(err as any) 149 | } 150 | } 151 | } 152 | 153 | const buildDebounce = debounce(build, codegenDelay, { 154 | trailing: true, 155 | leading: false, 156 | }) 157 | 158 | const watchStore = async (): Promise => { 159 | const { lastAction: action } = store.getState() 160 | if (!['REPLACE_STATIC_QUERY', 'QUERY_EXTRACTED'].includes(action.type)) { 161 | return 162 | } 163 | const { schema } = store.getState() 164 | const defaultConfig = configs.find(({ key }) => key === DEFAULT_SCHEMA_KEY) 165 | if (defaultConfig) { 166 | defaultConfig.schema = schema 167 | } 168 | await buildDebounce() 169 | } 170 | 171 | // HACKY: might break when gatsby updates 172 | store.subscribe(watchStore) 173 | await build() 174 | } 175 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "ES2018" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */, 5 | "module": "ESNext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, 6 | "lib": [ 7 | "dom", 8 | "esnext" 9 | ] /* Specify library files to be included in the compilation. */, 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | "jsx": "preserve" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */, 13 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 16 | // "outFile": "./", /* Concatenate and emit output to single file. */ 17 | "outDir": "./dist" /* Redirect output structure to the directory. */, 18 | // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 19 | // "composite": true, /* Enable project compilation */ 20 | // "removeComments": true, /* Do not emit comments to output. */ 21 | // "noEmit": true, /* Do not emit outputs. */ 22 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 23 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 24 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 25 | 26 | /* Strict Type-Checking Options */ 27 | "strict": true /* Enable all strict type-checking options. */, 28 | "noImplicitAny": false /* Raise error on expressions and declarations with an implied 'any' type. */, 29 | // "strictNullChecks": true, /* Enable strict null checks. */ 30 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 34 | 35 | /* Additional Checks */ 36 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 40 | "skipLibCheck": true, /* Skip type checking of declaration files */ 41 | 42 | /* Module Resolution Options */ 43 | "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, 44 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 45 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 46 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 47 | "typeRoots": [ 48 | "./types", 49 | "./node_modules/@types" 50 | ] /* List of folders to include type definitions from. */, 51 | // "types": [], /* Type declaration files to be included in compilation. */ 52 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 53 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 54 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 55 | 56 | /* Source Map Options */ 57 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 58 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 59 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 60 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 61 | 62 | /* Experimental Options */ 63 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 64 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 65 | }, 66 | "exclude": ["node_modules", "./types"] 67 | } 68 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/README.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | Gatsby 5 | 6 |

7 |

8 | Gatsby's default starter 9 |

10 | 11 | Kick off your project with this default boilerplate. This starter ships with the main Gatsby configuration files you might need to get up and running blazing fast with the blazing fast app generator for React. 12 | 13 | _Have another more specific idea? You may want to check out our vibrant collection of [official and community-created starters](https://www.gatsbyjs.org/docs/gatsby-starters/)._ 14 | 15 | ## 🚀 Quick start 16 | 17 | 1. **Create a Gatsby site.** 18 | 19 | Use the Gatsby CLI to create a new site, specifying the default starter. 20 | 21 | ```shell 22 | # create a new Gatsby site using the default starter 23 | gatsby new my-default-starter https://github.com/gatsbyjs/gatsby-starter-default 24 | ``` 25 | 26 | 1. **Start developing.** 27 | 28 | Navigate into your new site’s directory and start it up. 29 | 30 | ```shell 31 | cd my-default-starter/ 32 | gatsby develop 33 | ``` 34 | 35 | 1. **Open the source code and start editing!** 36 | 37 | Your site is now running at `http://localhost:8000`! 38 | 39 | _Note: You'll also see a second link: _`http://localhost:8000/___graphql`_. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the [Gatsby tutorial](https://www.gatsbyjs.org/tutorial/part-five/#introducing-graphiql)._ 40 | 41 | Open the `my-default-starter` directory in your code editor of choice and edit `src/pages/index.js`. Save your changes and the browser will update in real time! 42 | 43 | ## 🧐 What's inside? 44 | 45 | A quick look at the top-level files and directories you'll see in a Gatsby project. 46 | 47 | . 48 | ├── node_modules 49 | ├── src 50 | ├── .gitignore 51 | ├── .prettierrc 52 | ├── gatsby-browser.js 53 | ├── gatsby-config.js 54 | ├── gatsby-node.js 55 | ├── gatsby-ssr.js 56 | ├── LICENSE 57 | ├── package-lock.json 58 | ├── package.json 59 | └── README.md 60 | 61 | 1. **`/node_modules`**: This directory contains all of the modules of code that your project depends on (npm packages) are automatically installed. 62 | 63 | 2. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for “source code”. 64 | 65 | 3. **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for. 66 | 67 | 4. **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent. 68 | 69 | 5. **`gatsby-browser.js`**: This file is where Gatsby expects to find any usage of the [Gatsby browser APIs](https://www.gatsbyjs.org/docs/browser-apis/) (if any). These allow customization/extension of default Gatsby settings affecting the browser. 70 | 71 | 6. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins you’d like to include, etc. (Check out the [config docs](https://www.gatsbyjs.org/docs/gatsby-config/) for more detail). 72 | 73 | 7. **`gatsby-node.js`**: This file is where Gatsby expects to find any usage of the [Gatsby Node APIs](https://www.gatsbyjs.org/docs/node-apis/) (if any). These allow customization/extension of default Gatsby settings affecting pieces of the site build process. 74 | 75 | 8. **`gatsby-ssr.js`**: This file is where Gatsby expects to find any usage of the [Gatsby server-side rendering APIs](https://www.gatsbyjs.org/docs/ssr-apis/) (if any). These allow customization of default Gatsby settings affecting server-side rendering. 76 | 77 | 9. **`LICENSE`**: Gatsby is licensed under the MIT license. 78 | 79 | 10. **`package-lock.json`** (See `package.json` below, first). This is an automatically generated file based on the exact versions of your npm dependencies that were installed for your project. **(You won’t change this file directly).** 80 | 81 | 11. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the project’s name, author, etc). This manifest is how npm knows which packages to install for your project. 82 | 83 | 12. **`README.md`**: A text file containing useful reference information about your project. 84 | 85 | ## 🎓 Learning Gatsby 86 | 87 | Looking for more guidance? Full documentation for Gatsby lives [on the website](https://www.gatsbyjs.org/). Here are some places to start: 88 | 89 | - **For most developers, we recommend starting with our [in-depth tutorial for creating a site with Gatsby](https://www.gatsbyjs.org/tutorial/).** It starts with zero assumptions about your level of ability and walks through every step of the process. 90 | 91 | - **To dive straight into code samples, head [to our documentation](https://www.gatsbyjs.org/docs/).** In particular, check out the _Guides_, _API Reference_, and _Advanced Tutorials_ sections in the sidebar. 92 | 93 | ## 💫 Deploy 94 | 95 | [![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-default) 96 | 97 | 98 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | "lib": ["dom", "es2017"], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | "outDir": "./", /* Redirect output structure to the directory. */ 15 | "rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "composite": true, /* Enable project compilation */ 17 | // "removeComments": true, /* Do not emit comments to output. */ 18 | // "noEmit": true, /* Do not emit outputs. */ 19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true, /* Enable all strict type-checking options. */ 25 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 26 | // "strictNullChecks": true, /* Enable strict null checks. */ 27 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 28 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 29 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 30 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 31 | 32 | /* Additional Checks */ 33 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 34 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 35 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 36 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 37 | "skipLibCheck": true, /* Skip type checking of declaration files */ 38 | 39 | /* Module Resolution Options */ 40 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 41 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 42 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 43 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 44 | // "typeRoots": [], /* List of folders to include type definitions from. */ 45 | // "types": [], /* Type declaration files to be included in compilation. */ 46 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 47 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 48 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 49 | 50 | /* Source Map Options */ 51 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 52 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 53 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 54 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 55 | 56 | /* Experimental Options */ 57 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 58 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 59 | }, 60 | "include": ["src", "../../types"], 61 | "exclude": ["node_modules"] 62 | } -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "ESNext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | "lib": ["dom", "esnext"], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | "outDir": "./dist", /* Redirect output structure to the directory. */ 15 | // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "composite": true, /* Enable project compilation */ 17 | // "removeComments": true, /* Do not emit comments to output. */ 18 | // "noEmit": true, /* Do not emit outputs. */ 19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true, /* Enable all strict type-checking options. */ 25 | "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */ 26 | // "strictNullChecks": true, /* Enable strict null checks. */ 27 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 28 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 29 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 30 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 31 | 32 | /* Additional Checks */ 33 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 34 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 35 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 36 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 37 | "skipLibCheck": true, /* Skip type checking of declaration files */ 38 | 39 | /* Module Resolution Options */ 40 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 41 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 42 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 43 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 44 | "typeRoots": [ "./types", "../../node_modules/@types"], /* List of folders to include type definitions from. */ 45 | // "types": [], /* Type declaration files to be included in compilation. */ 46 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 47 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 48 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 49 | 50 | /* Source Map Options */ 51 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 52 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 53 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 54 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 55 | 56 | /* Experimental Options */ 57 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 58 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 59 | }, 60 | "exclude": ["node_modules", "./types"] 61 | } -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/README.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | Gatsby 5 | 6 |

7 |

8 | Typescript blog starter 9 |

10 | 11 | Gatsby's blog starter, typescript-ifed with [`gatsby-plugin-ts`](https://github.com/d4rekanguok/gatsby-plugin-ts). 12 | 13 | --- 14 | 15 | Kick off your project with this blog boilerplate. This starter ships with the main Gatsby configuration files you might need to get up and running blazing fast with the blazing fast app generator for React. 16 | 17 | _Have another more specific idea? You may want to check out our vibrant collection of [official and community-created starters](https://www.gatsbyjs.org/docs/gatsby-starters/)._ 18 | 19 | ## 🚀 Quick start 20 | 21 | 1. **Create a Gatsby site.** 22 | 23 | Use the Gatsby CLI to create a new site, specifying the blog starter. 24 | 25 | ```sh 26 | # create a new Gatsby site using the blog starter 27 | gatsby new my-blog-starter https://github.com/gatsbyjs/gatsby-starter-blog 28 | ``` 29 | 30 | 1. **Start developing.** 31 | 32 | Navigate into your new site’s directory and start it up. 33 | 34 | ```sh 35 | cd my-blog-starter/ 36 | gatsby develop 37 | ``` 38 | 39 | 1. **Open the source code and start editing!** 40 | 41 | Your site is now running at `http://localhost:8000`! 42 | 43 | _Note: You'll also see a second link: _`http://localhost:8000/___graphql`_. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the [Gatsby tutorial](https://www.gatsbyjs.org/tutorial/part-five/#introducing-graphiql)._ 44 | 45 | Open the `my-blog-starter` directory in your code editor of choice and edit `src/pages/index.js`. Save your changes and the browser will update in real time! 46 | 47 | ## 🧐 What's inside? 48 | 49 | A quick look at the top-level files and directories you'll see in a Gatsby project. 50 | 51 | . 52 | ├── node_modules 53 | ├── src 54 | ├── .gitignore 55 | ├── .prettierrc 56 | ├── gatsby-browser.js 57 | ├── gatsby-config.js 58 | ├── gatsby-node.js 59 | ├── gatsby-ssr.js 60 | ├── LICENSE 61 | ├── package-lock.json 62 | ├── package.json 63 | └── README.md 64 | 65 | 1. **`/node_modules`**: This directory contains all of the modules of code that your project depends on (npm packages) are automatically installed. 66 | 67 | 2. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for “source code”. 68 | 69 | 3. **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for. 70 | 71 | 4. **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent. 72 | 73 | 5. **`gatsby-browser.js`**: This file is where Gatsby expects to find any usage of the [Gatsby browser APIs](https://www.gatsbyjs.org/docs/browser-apis/) (if any). These allow customization/extension of default Gatsby settings affecting the browser. 74 | 75 | 6. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins you’d like to include, etc. (Check out the [config docs](https://www.gatsbyjs.org/docs/gatsby-config/) for more detail). 76 | 77 | 7. **`gatsby-node.js`**: This file is where Gatsby expects to find any usage of the [Gatsby Node APIs](https://www.gatsbyjs.org/docs/node-apis/) (if any). These allow customization/extension of default Gatsby settings affecting pieces of the site build process. 78 | 79 | 8. **`gatsby-ssr.js`**: This file is where Gatsby expects to find any usage of the [Gatsby server-side rendering APIs](https://www.gatsbyjs.org/docs/ssr-apis/) (if any). These allow customization of default Gatsby settings affecting server-side rendering. 80 | 81 | 9. **`LICENSE`**: Gatsby is licensed under the MIT license. 82 | 83 | 10. **`package-lock.json`** (See `package.json` below, first). This is an automatically generated file based on the exact versions of your npm dependencies that were installed for your project. **(You won’t change this file directly).** 84 | 85 | 11. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the project’s name, author, etc). This manifest is how npm knows which packages to install for your project. 86 | 87 | 12. **`README.md`**: A text file containing useful reference information about your project. 88 | 89 | ## 🎓 Learning Gatsby 90 | 91 | Looking for more guidance? Full documentation for Gatsby lives [on the website](https://www.gatsbyjs.org/). Here are some places to start: 92 | 93 | - **For most developers, we recommend starting with our [in-depth tutorial for creating a site with Gatsby](https://www.gatsbyjs.org/tutorial/).** It starts with zero assumptions about your level of ability and walks through every step of the process. 94 | 95 | - **To dive straight into code samples, head [to our documentation](https://www.gatsbyjs.org/docs/).** In particular, check out the _Guides_, _API Reference_, and _Advanced Tutorials_ sections in the sidebar. 96 | 97 | ## 💫 Deploy 98 | 99 | [![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-blog) 100 | 101 | 102 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-codegen/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | "lib": ["dom", "esnext"], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | "outDir": "./", /* Redirect output structure to the directory. */ 15 | "rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "composite": true, /* Enable project compilation */ 17 | // "removeComments": true, /* Do not emit comments to output. */ 18 | // "noEmit": true, /* Do not emit outputs. */ 19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true, /* Enable all strict type-checking options. */ 25 | // remove this flag when graphql-codegen fix @graphql-codegen/visitor-plugin-common/client-side-base-visitor.d.ts:111:17 26 | "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */ 27 | // "strictNullChecks": true, /* Enable strict null checks. */ 28 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 29 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 30 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 31 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 32 | 33 | /* Additional Checks */ 34 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 35 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 36 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 37 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 38 | "skipLibCheck": true, /* Skip type checking of declaration files */ 39 | 40 | /* Module Resolution Options */ 41 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 42 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 43 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 44 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 45 | // "typeRoots": [], /* List of folders to include type definitions from. */ 46 | // "types": [], /* Type declaration files to be included in compilation. */ 47 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 48 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 49 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 50 | 51 | /* Source Map Options */ 52 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 53 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 54 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 55 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 56 | 57 | /* Experimental Options */ 58 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 59 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 60 | }, 61 | "include": ["src", "../../types"], 62 | "exclude": ["node_modules"] 63 | } -------------------------------------------------------------------------------- /packages/gatsby-starter-blog-ts/content/blog/hi-folks/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: New Beginnings 3 | date: "2015-05-28T22:40:32.169Z" 4 | description: This is a custom description for SEO and Open Graph purposes, rather than the default generated excerpt. Simply add a description field to the frontmatter. 5 | --- 6 | 7 | Far far away, behind the word mountains, far from the countries Vokalia and 8 | Consonantia, there live the blind texts. Separated they live in Bookmarksgrove 9 | right at the coast of the Semantics, a large language ocean. A small river named 10 | Duden flows by their place and supplies it with the necessary regelialia. 11 | 12 | ## On deer horse aboard tritely yikes and much 13 | 14 | The Big Oxmox advised her not to do so, because there were thousands of bad 15 | Commas, wild Question Marks and devious Semikoli, but the Little Blind Text 16 | didn’t listen. She packed her seven versalia, put her initial into the belt and 17 | made herself on the way. 18 | 19 | - This however showed weasel 20 | - Well uncritical so misled 21 | - this is very interesting 22 | - Goodness much until that fluid owl 23 | 24 | When she reached the first hills of the **Italic Mountains**, she had a last 25 | view back on the skyline of her hometown _Bookmarksgrove_, the headline of 26 | [Alphabet Village](http://google.com) and the subline of her own road, the Line 27 | Lane. Pityful a rethoric question ran over her cheek, then she continued her 28 | way. On her way she met a copy. 29 | 30 | ### Overlaid the jeepers uselessly much excluding 31 | 32 | But nothing the copy said could convince her and so it didn’t take long until a 33 | few insidious Copy Writers ambushed her, made her drunk with 34 | [Longe and Parole](http://google.com) and dragged her into their agency, where 35 | they abused her for their projects again and again. And if she hasn’t been 36 | rewritten, then they are still using her. 37 | 38 | > Far far away, behind the word mountains, far from the countries Vokalia and 39 | > Consonantia, there live the blind texts. Separated they live in Bookmarksgrove 40 | > right at the coast of the Semantics, a large language ocean. 41 | 42 | It is a paradisematic country, in which roasted parts of sentences fly into your 43 | mouth. Even the all-powerful Pointing has no control about the blind texts it is 44 | an almost unorthographic life One day however a small line of blind text by the 45 | name of Lorem Ipsum decided to leave for the far World of Grammar. 46 | 47 | ### According a funnily until pre-set or arrogant well cheerful 48 | 49 | The Big Oxmox advised her not to do so, because there were thousands of bad 50 | Commas, wild Question Marks and devious Semikoli, but the Little Blind Text 51 | didn’t listen. She packed her seven versalia, put her initial into the belt and 52 | made herself on the way. 53 | 54 | 1. So baboon this 55 | 2. Mounted militant weasel gregariously admonishingly straightly hey 56 | 3. Dear foresaw hungry and much some overhung 57 | 4. Rash opossum less because less some amid besides yikes jeepers frenetic 58 | impassive fruitlessly shut 59 | 60 | When she reached the first hills of the Italic Mountains, she had a last view 61 | back on the skyline of her hometown Bookmarksgrove, the headline of Alphabet 62 | Village and the subline of her own road, the Line Lane. Pityful a rethoric 63 | question ran over her cheek, then she continued her way. On her way she met a 64 | copy. 65 | 66 | > The copy warned the Little Blind Text, that where it came from it would have 67 | > been rewritten a thousand times and everything that was left from its origin 68 | > would be the word "and" and the Little Blind Text should turn around and 69 | > return to its own, safe country. 70 | 71 | But nothing the copy said could convince her and so it didn’t take long until a 72 | few insidious Copy Writers ambushed her, made her drunk with Longe and Parole 73 | and dragged her into their agency, where they abused her for their projects 74 | again and again. And if she hasn’t been rewritten, then they are still using 75 | her. Far far away, behind the word mountains, far from the countries Vokalia and 76 | Consonantia, there live the blind texts. 77 | 78 | #### Silent delightfully including because before one up barring chameleon 79 | 80 | Separated they live in Bookmarksgrove right at the coast of the Semantics, a 81 | large language ocean. A small river named Duden flows by their place and 82 | supplies it with the necessary regelialia. It is a paradisematic country, in 83 | which roasted parts of sentences fly into your mouth. 84 | 85 | Even the all-powerful Pointing has no control about the blind texts it is an 86 | almost unorthographic life One day however a small line of blind text by the 87 | name of Lorem Ipsum decided to leave for the far World of Grammar. The Big Oxmox 88 | advised her not to do so, because there were thousands of bad Commas, wild 89 | Question Marks and devious Semikoli, but the Little Blind Text didn’t listen. 90 | 91 | ##### Wherever far wow thus a squirrel raccoon jeez jaguar this from along 92 | 93 | She packed her seven versalia, put her initial into the belt and made herself on 94 | the way. When she reached the first hills of the Italic Mountains, she had a 95 | last view back on the skyline of her hometown Bookmarksgrove, the headline of 96 | Alphabet Village and the subline of her own road, the Line Lane. Pityful a 97 | rethoric question ran over her cheek, then she continued her way. On her way she 98 | met a copy. 99 | 100 | ###### Slapped cozy a that lightheartedly and far 101 | 102 | The copy warned the Little Blind Text, that where it came from it would have 103 | been rewritten a thousand times and everything that was left from its origin 104 | would be the word "and" and the Little Blind Text should turn around and return 105 | to its own, safe country. But nothing the copy said could convince her and so it 106 | didn’t take long until a few insidious Copy Writers ambushed her, made her drunk 107 | with Longe and Parole and dragged her into their agency, where they abused her 108 | for their projects again and again. 109 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-codegen/src/graphql-codegen.config.test.js: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs-extra' 2 | import * as path from 'path' 3 | import { buildSchema } from 'graphql' 4 | import { loadDocuments } from '@graphql-tools/load' 5 | import { generateWithConfig, mapCodegenPlugins } from './graphql-codegen.config' 6 | 7 | jest.mock('fs-extra', () => ({ 8 | ensureDir: jest.fn(), 9 | writeFile: jest.fn(), 10 | })) 11 | 12 | jest.mock('@graphql-tools/load', () => ({ 13 | loadDocuments: jest.fn(), 14 | })) 15 | 16 | it('takes in options and returns a function that runs codegen for the schema', async () => { 17 | loadDocuments.mockReturnValueOnce(Promise.resolve([])) 18 | 19 | const mockReporter = { 20 | warn: jest.fn(), 21 | } 22 | 23 | const generateFromSchema = await generateWithConfig({ 24 | directory: './example-directory', 25 | documentPaths: ['./src/**/*.{ts,tsx}'], 26 | fileName: 'example-types.ts', 27 | reporter: mockReporter, 28 | codegenPlugins: [], 29 | codegenConfig: {}, 30 | }) 31 | 32 | const mockSchema = buildSchema(` 33 | type Query { 34 | example: String 35 | } 36 | `) 37 | 38 | expect(mockSchema).toMatchInlineSnapshot(` 39 | GraphQLSchema { 40 | "__validationErrors": undefined, 41 | "_directives": Array [ 42 | "@include", 43 | "@skip", 44 | "@deprecated", 45 | "@specifiedBy", 46 | ], 47 | "_implementationsMap": Object {}, 48 | "_mutationType": undefined, 49 | "_queryType": "Query", 50 | "_subTypeMap": Object {}, 51 | "_subscriptionType": undefined, 52 | "_typeMap": Object { 53 | "Boolean": "Boolean", 54 | "Query": "Query", 55 | "String": "String", 56 | "__Directive": "__Directive", 57 | "__DirectiveLocation": "__DirectiveLocation", 58 | "__EnumValue": "__EnumValue", 59 | "__Field": "__Field", 60 | "__InputValue": "__InputValue", 61 | "__Schema": "__Schema", 62 | "__Type": "__Type", 63 | "__TypeKind": "__TypeKind", 64 | }, 65 | "astNode": undefined, 66 | "description": undefined, 67 | "extensionASTNodes": Array [], 68 | "extensions": undefined, 69 | } 70 | `) 71 | 72 | await generateFromSchema(mockSchema) 73 | 74 | expect(fs.ensureDir).toMatchInlineSnapshot(` 75 | [MockFunction] { 76 | "calls": Array [ 77 | Array [ 78 | "example-directory", 79 | ], 80 | ], 81 | "results": Array [ 82 | Object { 83 | "type": "return", 84 | "value": undefined, 85 | }, 86 | ], 87 | } 88 | `) 89 | 90 | expect(fs.writeFile.mock.calls[0]).toBeDefined() 91 | expect(fs.writeFile.mock.calls[0][0]).toBe( 92 | path.join('example-directory', 'example-types.ts') 93 | ) 94 | expect(fs.writeFile.mock.calls[0][1]).toMatchInlineSnapshot(` 95 | "export type Maybe = T | null; 96 | export type Exact = { [K in keyof T]: T[K] }; 97 | export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; 98 | export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; 99 | /** All built-in and custom scalars, mapped to their actual values */ 100 | export type Scalars = { 101 | ID: string; 102 | String: string; 103 | Boolean: boolean; 104 | Int: number; 105 | Float: number; 106 | }; 107 | 108 | export type Query = { 109 | example?: Maybe; 110 | }; 111 | " 112 | `) 113 | 114 | expect(mockReporter.warn).not.toHaveBeenCalled() 115 | }) 116 | 117 | it('calls `reporter.warn` when `loadDocuments` rejects', async () => { 118 | loadDocuments.mockReturnValueOnce(Promise.reject(new Error('test error'))) 119 | 120 | const mockReporter = { 121 | warn: jest.fn(), 122 | } 123 | 124 | const generateFromSchema = await generateWithConfig({ 125 | directory: './example-directory', 126 | documentPaths: ['./src/**/*.{ts,tsx}'], 127 | fileName: 'example-types.ts', 128 | reporter: mockReporter, 129 | codegenPlugins: [], 130 | codegenConfig: {}, 131 | }) 132 | 133 | const mockSchema = buildSchema(` 134 | type Query { 135 | example: String 136 | } 137 | `) 138 | 139 | await generateFromSchema(mockSchema) 140 | 141 | expect(mockReporter.warn).toMatchInlineSnapshot(` 142 | [MockFunction] { 143 | "calls": Array [ 144 | Array [ 145 | "[gatsby-plugin-graphql-codegen] test error", 146 | ], 147 | ], 148 | "results": Array [ 149 | Object { 150 | "type": "return", 151 | "value": undefined, 152 | }, 153 | ], 154 | } 155 | `) 156 | }) 157 | 158 | describe('mapCodegenPlugins', () => { 159 | const fakePlugin = () => {} 160 | 161 | it('add new plugin', () => { 162 | const { pluginMap, plugins } = mapCodegenPlugins({ 163 | codegenPlugins: [ 164 | { 165 | resolve: fakePlugin, 166 | options: { 167 | hey: false, 168 | }, 169 | }, 170 | ], 171 | defaultPlugins: { 172 | pluginMap: {}, 173 | plugins: [], 174 | }, 175 | }) 176 | 177 | const identifier = 'codegen-plugin-0' 178 | 179 | expect(plugins).toHaveLength(1) 180 | expect(plugins).toContainEqual({ [identifier]: { hey: false } }) 181 | expect(pluginMap).toHaveProperty(identifier) 182 | expect(pluginMap[identifier].plugin).toBe(fakePlugin) 183 | }) 184 | 185 | it('update default plugins', () => { 186 | const { pluginMap, plugins } = mapCodegenPlugins({ 187 | codegenPlugins: [ 188 | { 189 | resolve: 'typescript', 190 | options: { 191 | hey: false, 192 | }, 193 | }, 194 | ], 195 | defaultPlugins: { 196 | pluginMap: { 197 | typescript: { 198 | plugin: fakePlugin, 199 | }, 200 | }, 201 | plugins: [{ typescript: { hey: true } }], 202 | }, 203 | }) 204 | 205 | const identifier = 'typescript' 206 | 207 | expect(plugins).toHaveLength(1) 208 | expect(plugins).toContainEqual({ [identifier]: { hey: false } }) 209 | expect(pluginMap).toHaveProperty(identifier) 210 | expect(pluginMap[identifier].plugin).toBe(fakePlugin) 211 | }) 212 | 213 | it('add new plugin and update default plugin', () => { 214 | const { pluginMap, plugins } = mapCodegenPlugins({ 215 | codegenPlugins: [ 216 | { 217 | resolve: 'typescript', 218 | options: { 219 | hey: false, 220 | }, 221 | }, 222 | { 223 | resolve: fakePlugin, 224 | options: { 225 | how: 1, 226 | }, 227 | }, 228 | ], 229 | defaultPlugins: { 230 | pluginMap: { 231 | typescript: { 232 | plugin: fakePlugin, 233 | }, 234 | }, 235 | plugins: [{ typescript: { hey: true } }], 236 | }, 237 | }) 238 | 239 | expect(plugins).toHaveLength(2) 240 | expect(plugins).toContainEqual({ typescript: { hey: false } }) 241 | expect(plugins).toContainEqual({ 'codegen-plugin-1': { how: 1 } }) 242 | expect(pluginMap).toHaveProperty('typescript') 243 | expect(pluginMap).toHaveProperty('codegen-plugin-1') 244 | }) 245 | }) 246 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-codegen/readme.md: -------------------------------------------------------------------------------- 1 | # Gatsby Typescript Graphql Codegen 2 | 3 | Automatic type generation for your graphql queries via [`graphql-code-generator`](https://github.com/dotansimha/graphql-code-generator) 4 | 5 | 6 | ## Installation 7 | 8 | ``` 9 | yarn add typescript gatsby-plugin-graphql-codegen 10 | ``` 11 | 12 | Add this to your gatsby config like any other plugins: 13 | ```js 14 | // gatsby-config.js 15 | module.exports = { 16 | plugins: [ 17 | `gatsby-plugin-graphql-codegen`, 18 | ] 19 | } 20 | ``` 21 | 22 | ### Options 23 | 24 | |key | default | value | 25 | |---|---|---| 26 | |options.codegen| `true` | enable / disable generating definitions for graphql queries| 27 | |options.documentPaths|
['./src/**/*.{ts,tsx}',
'./.cache/fragments/*.js',
'./node_modules/gatsby-*/**/*.js']
| The paths to files containing graphql queries.
⚠️ The default paths will be overwritten by the `documentPaths` you pass in, so please make sure to include *all* necessary paths ⚠️ 28 | |options.fileName| `graphql-type.ts` | path to the generated file. By default, it's placed at the project root directory & it should not be placed into `src`, since this will create an infinite loop| 29 | |options.codegenDelay| `200` | amount of delay from file change to codegen| 30 | |options.pluckConfig|
{ globalGqlIdentifierName: "graphql", modules: [ { name: 'gatsby', identifier: 'graphql' } ] }
| options passed to [graphql-tag-pluck](https://github.com/ardatan/graphql-toolkit/tree/master/packages/graphql-tag-pluck) when extracting queries and fragments from documents | 31 | |options.failOnError (^2.5.0)| `process.env.NODE_ENV === 'production'` | Throw error if the codegen fails. By default only apply to production builds. 32 | |options.codegenConfig (^2.7.0)| `{}` | Add config directly to `graphql-codegen`. These key-value config will be applied to every `graphql-codegen` plugins. See [graphql-codegen docs on the config field](https://graphql-code-generator.com/docs/getting-started/config-field) | 33 | |options.codegenPlugins (^2.7.0)| `[]` | Add additional plugins to `graphql-codegen`. We use the same format as Gatsby's. See example usage below. 34 | |options.additionalSchemas (^2.6.0)|
[]
| array of additional schemas (other than the schema used by gatsby queries) for which types should be generated for. This is useful when you use client-side queries (e.g. with apollo-client) where you are querying another schema/endpoint | 35 | 36 | #### Additional Schema Options (for `options.additionalSchemas`) 37 | |key | default | value | 38 | |---|---|---| 39 | |key| - | an unique key used internally by this plugin to identify different schemas| 40 | |fileName| graphql-types-${key}.ts | path to the generated file for this schema. By default, it's placed at the project root directory & it should not be placed into `src`, since this will create an infinite loop | 41 | |documentPaths| value of `options.documentPaths` | The paths to files containing graphql queries. See also `options.documentPaths` | 42 | |pluckConfig| - | options passed to [graphql-tag-pluck](https://github.com/ardatan/graphql-toolkit/tree/master/packages/graphql-tag-pluck) when extracting queries and fragments from documents | 43 | |schema| - | additional schema to process. Can either be an url, a path to a local schema definition (both `.json` and `.graphql` are supported) or an inline definition. See also https://github.com/ardatan/graphql-toolkit#-schema-loading | 44 | |codegenConfig (^2.7.0)| `{}` | See `codegenConfig` above 45 | |codegenPlugin (^2.7.0)| `{}` | See `codegenPlugin` above 46 | 47 | ## Example Setups 48 | 49 | ### Normal Usecase 50 | Set it & forget it 51 | 52 | ```js 53 | exports.default = { 54 | plugins: [ 55 | `gatsby-plugin-graphql-codegen`, 56 | ] 57 | } 58 | ``` 59 | 60 | ### Custom Filename & Location 61 | 62 | ```js 63 | exports.default = { 64 | plugins: [{ 65 | resolve: `gatsby-plugin-graphql-codegen`, 66 | options: { 67 | fileName: `./gatsby-graphql.ts`, 68 | } 69 | }] 70 | } 71 | ``` 72 | 73 | ### Gatsby-node.ts 74 | You have queries in your gatsby-node? We can take care of that. The experience is not 100% right now, but that'll change soon! 75 | 76 | ```js 77 | exports.default = { 78 | plugins: [{ 79 | resolve: `gatsby-plugin-graphql-codegen`, 80 | options: { 81 | fileName: `./gatsby-graphql.ts`, 82 | documentPaths: [ 83 | './src/**/*.{ts,tsx}', 84 | './node_modules/gatsby-*/**/*.js', 85 | './gatsby-node.ts', 86 | ], 87 | } 88 | }] 89 | } 90 | ``` 91 | 92 | ### Customize Graphql Codegen 93 | You want to pass additional config to `graphql-codegen`: 94 | 95 | ```js 96 | // additional plugins 97 | import { plugin as resolverPlugin } from '@graphql-codegen/typescript-resolvers' 98 | 99 | exports.default = { 100 | plugins: [{ 101 | resolve: `gatsby-plugin-graphql-codegen`, 102 | options: { 103 | codegenConfig: { 104 | // key-value configs that will be applied to every plugins. 105 | // Note: The example below is completely unnecessary, just a demonstration. 106 | typesPrefix: 'Hi' // -> import { HiImageQuery } from '../../graphql-types' 107 | }, 108 | codegenPlugins: [{ 109 | // built-in plugin. 110 | // Use `typescript` for `@graphql-codegen/typescript` 111 | // and `operations` for `@graphql-codegen/typescript-operations` 112 | resolve: 'typescript', 113 | options: { 114 | namingConvention: `lower-case#lowerCase`, 115 | } 116 | },{ 117 | // additional plugin 118 | resolve: resolverPlugin, 119 | options: { 120 | typesPrefix: 'I' 121 | } 122 | }] 123 | } 124 | }] 125 | } 126 | ``` 127 | 128 | ### Dual-Schema Setup 129 | If you use `graphql` on the client side, this is for you. 130 | 131 | ```js 132 | exports.default = { 133 | plugins: [{ 134 | resolve: `gatsby-plugin-graphql-codegen`, 135 | options: { 136 | additionalSchemas: [{ 137 | key: 'pokemon', 138 | fileName: './graphql-pokemon.ts', 139 | schema: 'https://graphql-pokemon.now.sh/', 140 | pluckConfig: { 141 | // config to ensure only queries using the `gql` tag are used for this schema 142 | globalGqlIdentifierName: 'gql', 143 | modules: [ 144 | { 145 | name: 'graphql-tag', 146 | identifier: 'gql', 147 | }, 148 | ], 149 | }, 150 | }], 151 | } 152 | }] 153 | } 154 | ``` 155 | 156 | ## Code generation 157 | 158 | By default, this plugin will build typing for your queries automatically to `graphql-types.d.ts` on every edit. Please note that the definition file **should not** be placed inside `src` since this triggers a never ending loop during development. 159 | 160 | In order to take advantage of the generated code, user needs to name their query: 161 | 162 | ```js 163 | // src/pages/index.tsx 164 | 165 | export const pageQuery = graphql` 166 | - query { 167 | + query BlogIndex { 168 | site { 169 | siteMetadata { 170 | title 171 | } 172 | } 173 | ... 174 | ``` 175 | 176 | ...and import it from the generated type file: 177 | 178 | ```js 179 | // src/pages/index.tsx 180 | 181 | import { PageProps } from "gatsby"; 182 | import { BlogIndexQuery } from '../graphqlTypes' 183 | 184 | const BlogIndex: React.FC> = ({ data, location }) => { 185 | ... 186 | } 187 | ``` 188 | -------------------------------------------------------------------------------- /packages/gatsby-plugin-ts/readme.md: -------------------------------------------------------------------------------- 1 | # Gatsby Typescript Plugin 2 | 3 | An alternative to the official typescript plugin, with [`ts-loader`](https://github.com/TypeStrong/ts-loader) & automatic type generation for your graphql queries (using [`graphql-code-generator`](https://github.com/dotansimha/graphql-code-generator)) 4 | 5 | --- 6 | ## Installation 7 | 8 | ``` 9 | yarn add typescript gatsby-plugin-ts 10 | ``` 11 | 12 | Add this to your gatsby config like any other plugins: 13 | ```js 14 | // gatsby-config.js 15 | module.exports = { 16 | plugins: [ 17 | `gatsby-plugin-ts`, 18 | ] 19 | } 20 | ``` 21 | 22 | --- 23 | 24 | Unlike the official plugin, you'd have to bring your own `tsconfig.json`. 25 | 26 | ```bash 27 | # generate a tsconfig if you have none 28 | tsc --init 29 | ``` 30 | 31 | In order for this plugin to work right, you'd need to set your compile options like the following: 32 | 33 | ```js 34 | "compilerOptions": { 35 | "target": "ES2018", /* or at least ES2015 */ 36 | "module": "ESNext", /* or at least ES2015 */ 37 | "lib": ["dom"], /* <-- required! */ 38 | "jsx": "preserve", /* <-- required! */ 39 | "moduleResolution": "node", /* <-- required! */ 40 | 41 | /* for mixed ts/js codebase */ 42 | "allowJs": true, 43 | "outDir": "./build" /* this won't be used by ts-loader */ 44 | /* other options... */ 45 | } 46 | 47 | ``` 48 | 49 | ### Options 50 | 51 | |key | default | value | 52 | |---|---|---| 53 | |**typecheck options**||| 54 | |options.tsLoader| `{}` | option to be passed into `ts-loader`. `transpileOnly` is always `true`, since typechecking is handled by `fork-ts-checker-webpack-plugin`. [See ts-loader docs](https://github.com/TypeStrong/ts-loader#options) for more | 55 | |options.alwaysCheck | `false` | ⚠️deprecated
By default type checking is disabled in production mode (during `gatsby build`). Set this to `true` to enable type checking in production as well | 56 | |options.typeCheck | `true` | Enable / disable type checking with `fork-ts-checker-webpack-plugin`. | 57 | |options.forkTsCheckerPlugin | `{}` | Options that'll be passed to `fork-ts-checker-webpack-plugin`. For all options, please see [their docs](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin#options) 58 | |**codegen options**||| 59 | |options.codegen| `true` | enable / disable generating definitions for graphql queries| 60 | |options.documentPaths|
['./src/**/*.{ts,tsx}',
'./.cache/fragments/*.js',
'./node_modules/gatsby-*/**/*.js']
| The paths to files containing graphql queries.
⚠️ The default paths will be overwritten by the `documentPaths` you pass in, so please make sure to include *all* necessary paths ⚠️ 61 | |options.fileName| `graphql-type.ts` | path to the generated file. By default, it's placed at the project root directory & it should not be placed into `src`, since this will create an infinite loop| 62 | |options.codegenDelay| `200` | amount of delay from file change to codegen| 63 | |options.pluckConfig|
{ globalGqlIdentifierName: "graphql", modules: [ { name: 'gatsby', identifier: 'graphql' } ] }
| options passed to [graphql-tag-pluck](https://github.com/ardatan/graphql-toolkit/tree/master/packages/graphql-tag-pluck) when extracting queries and fragments from documents | 64 | |options.failOnError (2.5.0)| `process.env.NODE_ENV === 'production'` | Throw error if the codegen fails. By default only apply to production builds. 65 | |options.codegenConfig (^2.7.0)| `{}` | Add config directly to `graphql-codegen`. These key-value config will be applied to every `graphql-codegen` plugins. See [graphql-codegen docs on the config field](https://graphql-code-generator.com/docs/getting-started/config-field) | 66 | |options.codegenPlugins (^2.7.0)| `[]` | Add additional plugins to `graphql-codegen`. We use the same format as Gatsby's. See example usage below. 67 | |options.additionalSchemas (^2.6.0)|
[]
| array of additional schemas (other than the schema used by gatsby queries) for which types should be generated for. This is useful when you use client-side queries (e.g. with apollo-client) where you are querying another schema/endpoint | 68 | 69 | ## Example Setup 70 | 71 | ### Basic 72 | 73 | ```js 74 | module.exports = { 75 | plugins: [ 76 | `gatsby-plugin-ts`, 77 | ] 78 | } 79 | ``` 80 | 81 | ### Custom Output Path 82 | 83 | ```js 84 | module.exports = { 85 | plugins: [ 86 | { 87 | resolve: `gatsby-plugin-ts`, 88 | options: { 89 | fileName: `gen/graphql-types.ts`, 90 | } 91 | } 92 | ] 93 | } 94 | ``` 95 | 96 | ### I need to change everything 97 | 98 | ```js 99 | // gatsby-config.js 100 | { 101 | resolve: `gatsby-plugin-ts`, 102 | options: { 103 | tsLoader: { 104 | logLevel: 'warn', 105 | }, 106 | forkTsCheckerPlugin: { 107 | eslint: true, 108 | }, 109 | fileName: `types/graphql-types.ts`, 110 | codegen: true, 111 | codegenDelay: 250, 112 | typeCheck: false, 113 | pluckConfig: { 114 | // this is the default config 115 | globalGqlIdentifierName: 'graphql', 116 | modules: [ 117 | { name: 'gatsby', identifier: 'graphql' }, 118 | ], 119 | }, 120 | additionalSchemas: [ 121 | { 122 | key: 'example', 123 | fileName: 'graphql-types-example.ts', 124 | schema: 'https://example.com/graphql', 125 | pluckConfig: { 126 | // config to ensure only queries using the `gql` tag are used for this schema 127 | globalGqlIdentifierName: 'gql', 128 | modules: [ 129 | { 130 | name: 'graphql-tag', 131 | identifier: 'gql', 132 | }, 133 | ], 134 | }, 135 | } 136 | ], 137 | }, 138 | } 139 | ``` 140 | 141 | ### Gatsby files 142 | 143 | - `gatsby-config` has to be a `.js` file 144 | - `gatsby-node` is run directly by `node`, so it has to be a .js file as well. It is a shame, because in a complicated Gatsby app it is where a lot of logic live & will benefit from ts. As a work around, it can be built with `tsc` independently, in a script in `package.json` or somehow in gatsby's pre-init hook. 145 | - Gatsby's global variable like `__PATH_PREFIX__` can be handled by declaring this code somewhere: 146 | 147 | ```ts 148 | // src/global.d.ts 149 | declare const __PATH_PREFIX__: string 150 | ``` 151 | 152 | ## Code generation 153 | 154 | By default, this plugin will build typing for your queries automatically to `graphql-types.d.ts` on every edit. Please note that the definition file **should not** be placed inside `src` since this triggers a never ending loop during development. 155 | 156 | In order to take advantage of the generated code, user needs to name their query: 157 | 158 | ```js 159 | // src/pages/index.tsx 160 | 161 | export const pageQuery = graphql` 162 | - query { 163 | + query BlogIndex { 164 | site { 165 | siteMetadata { 166 | title 167 | } 168 | } 169 | ... 170 | ``` 171 | 172 | ...and import it from the generated type file: 173 | 174 | ```js 175 | // src/pages/index.tsx 176 | 177 | import { BlogIndexQuery } from '../graphqlTypes' 178 | 179 | interface IBlogIndexProps { 180 | data: BlogIndexQuery; 181 | location: Location; 182 | } 183 | 184 | const BlogIndex: React.FC = ({ data, location }) => { 185 | ... 186 | } 187 | ``` 188 | 189 | ## Disable type checking in production 190 | 191 | Previously this plugin disable type checking in production by default, which can be changed by setting `alwaysCheck` to `true`. Since 2.0.0 it no longer does this. If you want to preseve the previous behavior, please set the `typeCheck` option like below: 192 | 193 | ```js 194 | { 195 | resolve: 'gatsby-plugin-ts', 196 | options: { 197 | // Disable type checking in production 198 | typeCheck: process.env.NODE_ENV !== 'production', 199 | } 200 | } 201 | ``` -------------------------------------------------------------------------------- /packages/gatsby-plugin-graphql-codegen/src/gatsby-node.test.js: -------------------------------------------------------------------------------- 1 | import { onPostBootstrap } from './gatsby-node' 2 | import { generateWithConfig } from './graphql-codegen.config' 3 | 4 | jest.mock('./graphql-codegen.config', () => ({ generateWithConfig: jest.fn() })) 5 | 6 | const delay = (milliseconds) => 7 | new Promise((resolve) => setTimeout(resolve, milliseconds)) 8 | 9 | it('early returns if the codegen option is false', async () => { 10 | const mockGetState = jest.fn() 11 | const mockGatsbyArgs = { 12 | store: { 13 | getState: mockGetState, 14 | }, 15 | } 16 | 17 | const pluginOptions = { 18 | plugins: [], 19 | codegen: false, 20 | } 21 | 22 | await onPostBootstrap(mockGatsbyArgs, pluginOptions) 23 | 24 | expect(mockGetState).not.toHaveBeenCalled() 25 | }) 26 | 27 | it('calls `generateWithConfig` from `graphql-codegen.config.ts`', async () => { 28 | const mockGatsbyArgs = { 29 | store: { 30 | getState: () => ({ 31 | schema: 'mock-schema', 32 | program: { directory: 'mock-directory' }, 33 | }), 34 | subscribe: jest.fn(), 35 | }, 36 | reporter: { 37 | info: jest.fn(), 38 | panic: jest.fn(), 39 | }, 40 | } 41 | 42 | const pluginOptions = { 43 | documentPaths: ['./example-document-paths'], 44 | fileName: './example-filename.ts', 45 | plugins: [], 46 | } 47 | 48 | const mockGenerateFromSchema = jest.fn() 49 | generateWithConfig.mockReturnValueOnce(mockGenerateFromSchema) 50 | 51 | await onPostBootstrap(mockGatsbyArgs, pluginOptions) 52 | 53 | expect(generateWithConfig).toHaveBeenCalledTimes(1) 54 | expect(generateWithConfig.mock.calls[0][0]).toMatchInlineSnapshot(` 55 | Object { 56 | "codegenConfig": Object {}, 57 | "codegenPlugins": Array [], 58 | "directory": "mock-directory", 59 | "documentPaths": Array [ 60 | "./example-document-paths", 61 | ], 62 | "fileName": "./example-filename.ts", 63 | "key": "default-gatsby-schema", 64 | "pluckConfig": Object { 65 | "globalGqlIdentifierName": "graphql", 66 | "modules": Array [ 67 | Object { 68 | "identifier": "graphql", 69 | "name": "gatsby", 70 | }, 71 | ], 72 | }, 73 | "reporter": Object { 74 | "info": [MockFunction] { 75 | "calls": Array [ 76 | Array [ 77 | "[gatsby-plugin-graphql-codegen] definition for queries of schema default-gatsby-schema has been updated at ./example-filename.ts", 78 | ], 79 | ], 80 | "results": Array [ 81 | Object { 82 | "type": "return", 83 | "value": undefined, 84 | }, 85 | ], 86 | }, 87 | "panic": [MockFunction], 88 | }, 89 | "schema": "mock-schema", 90 | } 91 | `) 92 | 93 | expect(mockGenerateFromSchema).toMatchInlineSnapshot(` 94 | [MockFunction] { 95 | "calls": Array [ 96 | Array [ 97 | "mock-schema", 98 | ], 99 | ], 100 | "results": Array [ 101 | Object { 102 | "type": "return", 103 | "value": undefined, 104 | }, 105 | ], 106 | } 107 | `) 108 | }) 109 | 110 | it('calls `reporter.warn` if `generateWithConfig` throws', async () => { 111 | const mockGatsbyArgs = { 112 | store: { 113 | getState: () => ({ 114 | schema: 'mock-schema', 115 | program: { directory: 'mock-directory' }, 116 | }), 117 | subscribe: jest.fn(), 118 | }, 119 | reporter: { 120 | info: jest.fn(), 121 | warn: jest.fn(), 122 | }, 123 | } 124 | 125 | const pluginOptions = { 126 | documentPaths: ['./example-document-paths'], 127 | fileName: './example-filename.ts', 128 | plugins: [], 129 | } 130 | 131 | const mockGenerateFromSchema = () => { 132 | throw new Error('mock error') 133 | } 134 | generateWithConfig.mockReturnValueOnce(mockGenerateFromSchema) 135 | 136 | await onPostBootstrap(mockGatsbyArgs, pluginOptions) 137 | 138 | expect(mockGatsbyArgs.reporter.warn).toMatchInlineSnapshot(` 139 | [MockFunction] { 140 | "calls": Array [ 141 | Array [ 142 | [Error: mock error], 143 | ], 144 | ], 145 | "results": Array [ 146 | Object { 147 | "type": "return", 148 | "value": undefined, 149 | }, 150 | ], 151 | } 152 | `) 153 | }) 154 | 155 | it('subscribes to the store and debounces the `build` function', async () => { 156 | // this variable is assigned when the `.subscribe` function is called. 157 | // it allows us to invoke the listener and mock "notify" its state 158 | let notify 159 | 160 | const codegenDelay = 50 161 | 162 | const mockState = { 163 | schema: 'mock-schema', 164 | program: { directory: 'mock-directory' }, 165 | // this type has to be either `QUERY_EXTRACTED` or `REPLACE_STATIC_QUERY` 166 | lastAction: { type: 'QUERY_EXTRACTED' }, 167 | } 168 | 169 | const mockGatsbyArgs = { 170 | store: { 171 | getState: () => mockState, 172 | subscribe: (listener) => { 173 | notify = listener 174 | }, 175 | }, 176 | reporter: { 177 | info: jest.fn(), 178 | warn: jest.fn(), 179 | }, 180 | } 181 | 182 | const pluginOptions = { 183 | documentPaths: ['./example-document-paths'], 184 | fileName: './example-filename.ts', 185 | codegenDelay, 186 | plugins: [], 187 | } 188 | 189 | const mockGenerateFromSchema = jest.fn() 190 | generateWithConfig.mockReturnValue(mockGenerateFromSchema) 191 | 192 | await onPostBootstrap(mockGatsbyArgs, pluginOptions) 193 | expect(mockGenerateFromSchema).toHaveBeenCalledTimes(1) 194 | 195 | // notify the subscriber 5 times 196 | for (let i = 0; i < 5; i += 1) { 197 | notify() 198 | } 199 | 200 | // wait 2x the amount of the codegen delay to ensure everything has flushed 201 | await delay(codegenDelay * 2) 202 | // because of the debounce, we should expect it to have only been called 203 | // twice instead of 6 times 204 | expect(mockGenerateFromSchema).toHaveBeenCalledTimes(2) 205 | 206 | expect(mockGatsbyArgs.reporter.info).toHaveBeenCalled() 207 | expect(mockGatsbyArgs.reporter.warn).not.toHaveBeenCalled() 208 | }) 209 | 210 | it("doesn't call build if the `lastAction.type` isn't 'REPLACE_STATIC_QUERY' or 'QUERY_EXTRACTED'", async () => { 211 | // this variable is assigned when the `.subscribe` function is called. 212 | // it allows us to invoke the listener and mock "notify" its state 213 | let notify 214 | 215 | const codegenDelay = 50 216 | 217 | const mockState = { 218 | schema: 'mock-schema', 219 | program: { directory: 'mock-directory' }, 220 | lastAction: { type: 'NOT_THE_CORRECT_ACTION' }, 221 | } 222 | 223 | const mockGatsbyArgs = { 224 | store: { 225 | getState: () => mockState, 226 | subscribe: (listener) => { 227 | notify = listener 228 | }, 229 | }, 230 | reporter: { 231 | info: jest.fn(), 232 | panic: jest.fn(), 233 | }, 234 | } 235 | 236 | const pluginOptions = { 237 | documentPaths: ['./example-document-paths'], 238 | fileName: './example-filename.ts', 239 | codegenDelay, 240 | plugins: [], 241 | } 242 | 243 | const mockGenerateFromSchema = jest.fn() 244 | generateWithConfig.mockReturnValue(mockGenerateFromSchema) 245 | 246 | await onPostBootstrap(mockGatsbyArgs, pluginOptions) 247 | expect(mockGenerateFromSchema).toHaveBeenCalledTimes(1) 248 | 249 | // notify the subscriber 5 times 250 | for (let i = 0; i < 5; i += 1) { 251 | notify() 252 | } 253 | 254 | // wait 2x the amount of the codegen delay to ensure everything has flushed 255 | await delay(codegenDelay * 2) 256 | // because the lastAction.type above isn't the 'REPLACE_STATIC_QUERY' or 257 | // 'QUERY_EXTRACTED', this will only be called once 258 | expect(mockGenerateFromSchema).toHaveBeenCalledTimes(1) 259 | }) 260 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Gatsby Typescript 2 | 3 | An alternative to the official typescript plugin, with [`ts-loader`](https://github.com/TypeStrong/ts-loader) & automatic type generation for your graphql queries (using [`graphql-code-generator`](https://github.com/dotansimha/graphql-code-generator)) 4 | 5 | --- 6 | 7 | > Hi there 👋 8 | > Are you just looking for a way to generate graphql types for your graphql queries? 9 | > 10 | > `gatsby-plugin-graphql-codegen` is what you want. However, other maintainers and I haven't been able to keep this repo up to shape. Please have a look at @cometkim's [graphql-plugin-typegen](https://github.com/cometkim/gatsby-plugin-typegen) which does almost the same thing & better maintained. 11 | > Still, ideas & PRs are all welcomed. If you'd like to help maintain this project, please feel free to reach out. Thank you, have a great day! 12 | 13 | --- 14 | 15 | 16 | This monorepo houses 2 packages: 17 | 18 | | npm package | Description | Docs | 19 | |---|---|---| 20 | | gatsby-plugin-ts | alternative typescript support with `ts-loader` & automated graphql codegen via `graphql-code-generator` | [`docs`](./packages/gatsby-plugin-ts/readme.md) 21 | | gatsby-plugin-graphql-codegen | automated graphql codegen via `graphql-code-generator` | [`docs`](./packages/gatsby-plugin-graphql-codegen/readme.md) 22 | 23 | --- 24 | 25 | Quick links: [Acknowledgement](https://github.com/d4rekanguok/gatsby-typescript#acknowledgment) • [General Q&A](https://github.com/d4rekanguok/gatsby-typescript#general-qa) • [Contribute](https://github.com/d4rekanguok/gatsby-typescript#contribute-to-this-repo) 26 | 27 | --- 28 | 29 | ## Acknowledgment 30 | 31 | Special thanks to the contributors, who have improved this project with code, bug reports & suggestions: 32 | 33 | ### Code 34 | 35 | [@ricokahler (maintainer)](https://github.com/ricokahler), 36 | 37 | [@kije](https://github.com/kije), 38 | 39 | [@Js-Brecht](https://github.com/Js-Brecht), 40 | 41 | [@Kerumen](https://github.com/Kerumen), 42 | 43 | [@olee](https://github.com/olee), 44 | 45 | [@Tielem](https://github.com/Tielem) 46 | 47 | ### Bugs & Suggestions 48 | 49 | [@frantic1048](https://github.com/frantic1048), 50 | 51 | [@cometkim](https://github.com/cometkim), 52 | 53 | [@FrobtheBuilder](https://github.com/FrobtheBuilder), 54 | 55 | [@aswinckr](https://github.com/aswinckr), 56 | 57 | [@mshick](https://github.com/mshick), 58 | 59 | [@joewood](https://github.com/joewood), 60 | 61 | [@Jdruwe](https://github.com/Jdruwe) 62 | 63 | 64 | 65 | Do you want to send a PR? [see this section](https://github.com/d4rekanguok/gatsby-typescript#contribute-to-this-repo) 66 | 67 | 68 | 69 | ### Powered By 70 | 71 | This project is built upon these awesome projects: 72 | 73 | - TypeStrong projects: 74 | - [TS Loader](https://github.com/TypeStrong/ts-loader) 75 | - [Fork TS Checker Webpack Plugin](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin) 76 | 77 | - [The Guild](https://the-guild.dev/)'s projects: 78 | - [Graphql Code Generator](https://github.com/dotansimha/graphql-code-generator) 79 | - [Graphql Toolkit](https://github.com/ardatan/graphql-toolkit) 80 | 81 | And of course, [Gatsbyjs](https://github.com/gatsbyjs/gatsby) and [Typescript](https://github.com/microsoft/typescript) 82 | 83 | --- 84 | 85 | ## General Q&A 86 | 87 | Here's a list of common questions I've seen since releasing this project. If you have a question that's not here, please don't hesitate to open an issue! 88 | 89 |
90 | 91 | Why use gatsby-plugin-ts? 92 | 93 | 94 | Gatsby use `babel-preset-typescript` which strips type information out of your code without doing typecheck. `gatsby-plugin-ts` use `ts-loader`, so you don't have to (1) worry about the [caveats](https://babeljs.io/docs/en/babel-plugin-transform-typescript#caveats) of `babel-preset-typescript` or (2) use an IDE / code editor that can typecheck for you. 95 | 96 | It also generate typings for your graphql queries, make it easier to strengthen your code. 97 | 98 | If you're already using something like VSCode and/or don't want to do typecheck in production, you can toggle off the typecheck option. 99 |
100 | 101 |
102 | 103 | What's the difference between gatsby-plugin-ts and gatsby-plugin-graphql-codegen? 104 | 105 | 106 | Originally belong to the same plugin, the codegen portion was extracted to `gatsby-plugin-graphql-codegen` so it can be used with the official typescript plugin. If you are already using `gatsby-plugin-ts`, you don't need `gatsby-plugin-graphql-codegen`. 107 |
108 | 109 |
110 | 111 | Should I check the generated type definition into git? 112 | 113 | 114 | It's up to your preference. 115 |
116 | 117 |
118 | 119 | What is up with all the Maybe<T>? 120 | 121 | 122 | It's due to Gatsby internal. There's an effort to [make typing more strict here](https://github.com/gatsbyjs/gatsby/issues/20069). 123 | 124 | You also may find the new optional chaining & nullish coalescing operator in typescript 3.7 helpful to deal with this. 125 |
126 | 127 |
128 | 129 | Can I turn off type checking and/or type generating? 130 | 131 | 132 | Yes! You can also use node env to determine whether to enable these features. 133 | 134 | ```js 135 | // gatsby-config.js 136 | { 137 | resolve: `gatsby-plugin-ts`, 138 | options: { 139 | codegen: false, 140 | typeCheck: process.env.NODE_ENV === 'development', 141 | } 142 | }, 143 | ``` 144 | 145 | 146 | 147 |
148 | 149 |
150 | 151 | My graphql queries returns null 152 | 153 | 154 | Gatsby extract graphql queries statically and it only understand queries inside template literal. It's possible that tsc is transpiling your template literal to string concat quivalent. Check your `tsconfig.json` & make sure you have a setting similar to this: 155 | 156 | ```js 157 | "compilerOptions": { 158 | "target": "ES2018", /* or at least ES2015 */ 159 | "module": "ESNext", /* or at least ES2015 */ 160 | "lib": ["dom"], /* <-- required! */ 161 | "jsx": "preserve", /* <-- required! */ 162 | "moduleResolution": "node", /* <-- required! */ 163 | /* other options... */ 164 | } 165 | ``` 166 | 167 |
168 | 169 |
170 | 171 | What if I have a mixed ts/js codebase? 172 | 173 | 174 | You'd have to update your `tsconfig` with the below options: 175 | 176 | ```json 177 | "allowJs": true, 178 | "outDir": "./build" 179 | ``` 180 | 181 | The `outDir` option won't be used by ts-loader, but you may need it to satisfy vscode. 182 | 183 |
184 | 185 |
186 | 187 | Babel doesn't understand the new optional chaining & nullish coalescing syntax even though my IDE shows no errors 188 | 189 | 190 | If you are using `gatsby-plugin-ts`, before you go off and install a bunch of babel plugins like a lot of tutorials suggest, check if your compilation `target` in `tsconfig.json` is too high (`ESNext` or `ES2019`). 191 | 192 | With these targets, tsc will leave the new syntax as-is, which babel might not understand. Downgrade them to `ES2018` should fix the issue; also make sure _your_ IDE's typescript version is the same as the one listed in your `package.json` dependency. 193 | 194 |
195 | 196 |
197 | 198 | Can I write `gatsby-node` in typescript & have its queries typing generated as well? 199 | 200 | 201 | Yes, but it's not easy at the moment. We're working on it; stay tuned! 202 | 203 |
204 | 205 |
206 | 207 | Typechecking causes `gatsby develop` to crash. 208 | 209 | 210 | We're trying to pin down why this happens, please share your experience in [#36](https://github.com/d4rekanguok/gatsby-typescript/issues/36) 211 | 212 |
213 | 214 | ### Common warning & errors 215 | Gatsby recently moved plugins' fragments from `.cache` to `node_modules`. We currently support both paths, but sometimes it may cause conflict warnings & errors: 216 | 217 |
218 | 219 | `warning: Unable to find any GraphQL type definitions for the following pointers ...` 220 | 221 | 222 | If you are annoyed by this warning, set the `documentPaths` options as below: 223 | 224 | ```js 225 | // gatsby-config.js 226 | { 227 | resolve: 'gatsby-plugin-graphql-codegen', 228 | options: { 229 | documentPaths: [ 230 | './src/**/*.{ts,tsx}', 231 | './node_modules/gatsby-*/**/*.js', 232 | ], 233 | } 234 | }, 235 | ``` 236 | 237 | ~~We will remove the `.cache/fragments` path and bump gatsby peer dependency version in a later release.~~ 238 | 239 | **Update**: Since 2.4.0, we've removed `.cache/fragments` & bump up gatsby peer dep. 240 | 241 |
242 | 243 |
244 | 245 | Duplicate identifier error: Duplicate identifier 'GatsbyImageSharpFixedFragment' 246 | 247 | 248 | If you see this error please run a `gatsby clean` to remove fragments in `.cache`, or set the `documentPaths` options as below: 249 | 250 | ```js 251 | // gatsby-config.js 252 | { 253 | resolve: 'gatsby-plugin-graphql-codegen', 254 | options: { 255 | documentPaths: [ 256 | './src/**/*.{ts,tsx}', 257 | './node_modules/gatsby-*/**/*.js', 258 | ], 259 | } 260 | }, 261 | ``` 262 |
263 | 264 |
265 | 266 | Missing definition Unknown identifier 'GatsbyImageSharpFixedFragment' in a yarn/lerna monorepo 267 | 268 | 269 | Are you using a monorepo? It's possible that the missing fragment's plugin is 'hoisted' (moved to workspace root's `node_modules`). A simple fix is use a `nohoist` config, supported by both lerna & yarn. Here's an example with yarn workspace, where `gatsby-transformer-sharp` is always installed in its project's `node_modules`. 270 | 271 | in your root's `package.json` 272 | ```json 273 | "workspaces": { 274 | "packages": ["packages/*"], 275 | "nohoist": [ 276 | "**/gatsby-transformer-sharp" 277 | ] 278 | } 279 | ``` 280 | 281 |
282 | 283 | ## Contribute to this repo 284 | 285 | All PRs / issues are welcomed. 286 | 287 | Steps to run in development: 288 | 289 | ```bash 290 | # 0 291 | git clone https://github.com/d4rekanguok/gatsby-typescript.git && cd gatsby-typescript 292 | 293 | # 1 Install deps 294 | yarn 295 | 296 | # 2 Hook up dependencies 297 | yarn bootstrap 298 | 299 | # 3 Build binaries 300 | lerna run build 301 | 302 | # 4 Run test 303 | yarn test 304 | ``` 305 | 306 | You can test your code against the starters inside the repo. Don't forget to checkout the changes in those repo before sending a PR. Alternatively, use [yalc](https://github.com/whitecolor/yalc) to test the plugins in your own Gatsby project: 307 | 308 | ```bash 309 | # 1 Install yalc 310 | npm i yalc -G 311 | 312 | # 2 cd into, say, gatsby-plugin-ts 313 | cd packages/gatsby-plugin-ts 314 | 315 | # 3 Publish to yalc 316 | yalc publish 317 | 318 | # 4 cd into your gatsby project 319 | cd ../../my-gatsby-project 320 | 321 | # 5 Install yalc & re-install deps 322 | npm uninstall gatsby-plugin-ts && yalc add gatsby-plugin-ts 323 | 324 | npm install 325 | 326 | # 6 Subsequent update 327 | yalc update 328 | 329 | # 7 Done? remove yalc deps 330 | yalc remove --all 331 | ``` 332 | -------------------------------------------------------------------------------- /packages/gatsby-starter-ts/src/components/layout.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-family: sans-serif; 3 | -ms-text-size-adjust: 100%; 4 | -webkit-text-size-adjust: 100%; 5 | } 6 | body { 7 | margin: 0; 8 | -webkit-font-smoothing: antialiased; 9 | -moz-osx-font-smoothing: grayscale; 10 | } 11 | article, 12 | aside, 13 | details, 14 | figcaption, 15 | figure, 16 | footer, 17 | header, 18 | main, 19 | menu, 20 | nav, 21 | section, 22 | summary { 23 | display: block; 24 | } 25 | audio, 26 | canvas, 27 | progress, 28 | video { 29 | display: inline-block; 30 | } 31 | audio:not([controls]) { 32 | display: none; 33 | height: 0; 34 | } 35 | progress { 36 | vertical-align: baseline; 37 | } 38 | [hidden], 39 | template { 40 | display: none; 41 | } 42 | a { 43 | background-color: transparent; 44 | -webkit-text-decoration-skip: objects; 45 | } 46 | a:active, 47 | a:hover { 48 | outline-width: 0; 49 | } 50 | abbr[title] { 51 | border-bottom: none; 52 | text-decoration: underline; 53 | text-decoration: underline dotted; 54 | } 55 | b, 56 | strong { 57 | font-weight: inherit; 58 | font-weight: bolder; 59 | } 60 | dfn { 61 | font-style: italic; 62 | } 63 | h1 { 64 | font-size: 2em; 65 | margin: 0.67em 0; 66 | } 67 | mark { 68 | background-color: #ff0; 69 | color: #000; 70 | } 71 | small { 72 | font-size: 80%; 73 | } 74 | sub, 75 | sup { 76 | font-size: 75%; 77 | line-height: 0; 78 | position: relative; 79 | vertical-align: baseline; 80 | } 81 | sub { 82 | bottom: -0.25em; 83 | } 84 | sup { 85 | top: -0.5em; 86 | } 87 | img { 88 | border-style: none; 89 | } 90 | svg:not(:root) { 91 | overflow: hidden; 92 | } 93 | code, 94 | kbd, 95 | pre, 96 | samp { 97 | font-family: monospace, monospace; 98 | font-size: 1em; 99 | } 100 | figure { 101 | margin: 1em 40px; 102 | } 103 | hr { 104 | box-sizing: content-box; 105 | height: 0; 106 | overflow: visible; 107 | } 108 | button, 109 | input, 110 | optgroup, 111 | select, 112 | textarea { 113 | font: inherit; 114 | margin: 0; 115 | } 116 | optgroup { 117 | font-weight: 700; 118 | } 119 | button, 120 | input { 121 | overflow: visible; 122 | } 123 | button, 124 | select { 125 | text-transform: none; 126 | } 127 | [type="reset"], 128 | [type="submit"], 129 | button, 130 | html [type="button"] { 131 | -webkit-appearance: button; 132 | } 133 | [type="button"]::-moz-focus-inner, 134 | [type="reset"]::-moz-focus-inner, 135 | [type="submit"]::-moz-focus-inner, 136 | button::-moz-focus-inner { 137 | border-style: none; 138 | padding: 0; 139 | } 140 | [type="button"]:-moz-focusring, 141 | [type="reset"]:-moz-focusring, 142 | [type="submit"]:-moz-focusring, 143 | button:-moz-focusring { 144 | outline: 1px dotted ButtonText; 145 | } 146 | fieldset { 147 | border: 1px solid silver; 148 | margin: 0 2px; 149 | padding: 0.35em 0.625em 0.75em; 150 | } 151 | legend { 152 | box-sizing: border-box; 153 | color: inherit; 154 | display: table; 155 | max-width: 100%; 156 | padding: 0; 157 | white-space: normal; 158 | } 159 | textarea { 160 | overflow: auto; 161 | } 162 | [type="checkbox"], 163 | [type="radio"] { 164 | box-sizing: border-box; 165 | padding: 0; 166 | } 167 | [type="number"]::-webkit-inner-spin-button, 168 | [type="number"]::-webkit-outer-spin-button { 169 | height: auto; 170 | } 171 | [type="search"] { 172 | -webkit-appearance: textfield; 173 | outline-offset: -2px; 174 | } 175 | [type="search"]::-webkit-search-cancel-button, 176 | [type="search"]::-webkit-search-decoration { 177 | -webkit-appearance: none; 178 | } 179 | ::-webkit-input-placeholder { 180 | color: inherit; 181 | opacity: 0.54; 182 | } 183 | ::-webkit-file-upload-button { 184 | -webkit-appearance: button; 185 | font: inherit; 186 | } 187 | html { 188 | font: 112.5%/1.45em georgia, serif; 189 | box-sizing: border-box; 190 | overflow-y: scroll; 191 | } 192 | * { 193 | box-sizing: inherit; 194 | } 195 | *:before { 196 | box-sizing: inherit; 197 | } 198 | *:after { 199 | box-sizing: inherit; 200 | } 201 | body { 202 | color: hsla(0, 0%, 0%, 0.8); 203 | font-family: georgia, serif; 204 | font-weight: normal; 205 | word-wrap: break-word; 206 | font-kerning: normal; 207 | -moz-font-feature-settings: "kern", "liga", "clig", "calt"; 208 | -ms-font-feature-settings: "kern", "liga", "clig", "calt"; 209 | -webkit-font-feature-settings: "kern", "liga", "clig", "calt"; 210 | font-feature-settings: "kern", "liga", "clig", "calt"; 211 | } 212 | img { 213 | max-width: 100%; 214 | margin-left: 0; 215 | margin-right: 0; 216 | margin-top: 0; 217 | padding-bottom: 0; 218 | padding-left: 0; 219 | padding-right: 0; 220 | padding-top: 0; 221 | margin-bottom: 1.45rem; 222 | } 223 | h1 { 224 | margin-left: 0; 225 | margin-right: 0; 226 | margin-top: 0; 227 | padding-bottom: 0; 228 | padding-left: 0; 229 | padding-right: 0; 230 | padding-top: 0; 231 | margin-bottom: 1.45rem; 232 | color: inherit; 233 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 234 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 235 | font-weight: bold; 236 | text-rendering: optimizeLegibility; 237 | font-size: 2.25rem; 238 | line-height: 1.1; 239 | } 240 | h2 { 241 | margin-left: 0; 242 | margin-right: 0; 243 | margin-top: 0; 244 | padding-bottom: 0; 245 | padding-left: 0; 246 | padding-right: 0; 247 | padding-top: 0; 248 | margin-bottom: 1.45rem; 249 | color: inherit; 250 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 251 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 252 | font-weight: bold; 253 | text-rendering: optimizeLegibility; 254 | font-size: 1.62671rem; 255 | line-height: 1.1; 256 | } 257 | h3 { 258 | margin-left: 0; 259 | margin-right: 0; 260 | margin-top: 0; 261 | padding-bottom: 0; 262 | padding-left: 0; 263 | padding-right: 0; 264 | padding-top: 0; 265 | margin-bottom: 1.45rem; 266 | color: inherit; 267 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 268 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 269 | font-weight: bold; 270 | text-rendering: optimizeLegibility; 271 | font-size: 1.38316rem; 272 | line-height: 1.1; 273 | } 274 | h4 { 275 | margin-left: 0; 276 | margin-right: 0; 277 | margin-top: 0; 278 | padding-bottom: 0; 279 | padding-left: 0; 280 | padding-right: 0; 281 | padding-top: 0; 282 | margin-bottom: 1.45rem; 283 | color: inherit; 284 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 285 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 286 | font-weight: bold; 287 | text-rendering: optimizeLegibility; 288 | font-size: 1rem; 289 | line-height: 1.1; 290 | } 291 | h5 { 292 | margin-left: 0; 293 | margin-right: 0; 294 | margin-top: 0; 295 | padding-bottom: 0; 296 | padding-left: 0; 297 | padding-right: 0; 298 | padding-top: 0; 299 | margin-bottom: 1.45rem; 300 | color: inherit; 301 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 302 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 303 | font-weight: bold; 304 | text-rendering: optimizeLegibility; 305 | font-size: 0.85028rem; 306 | line-height: 1.1; 307 | } 308 | h6 { 309 | margin-left: 0; 310 | margin-right: 0; 311 | margin-top: 0; 312 | padding-bottom: 0; 313 | padding-left: 0; 314 | padding-right: 0; 315 | padding-top: 0; 316 | margin-bottom: 1.45rem; 317 | color: inherit; 318 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 319 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 320 | font-weight: bold; 321 | text-rendering: optimizeLegibility; 322 | font-size: 0.78405rem; 323 | line-height: 1.1; 324 | } 325 | hgroup { 326 | margin-left: 0; 327 | margin-right: 0; 328 | margin-top: 0; 329 | padding-bottom: 0; 330 | padding-left: 0; 331 | padding-right: 0; 332 | padding-top: 0; 333 | margin-bottom: 1.45rem; 334 | } 335 | ul { 336 | margin-left: 1.45rem; 337 | margin-right: 0; 338 | margin-top: 0; 339 | padding-bottom: 0; 340 | padding-left: 0; 341 | padding-right: 0; 342 | padding-top: 0; 343 | margin-bottom: 1.45rem; 344 | list-style-position: outside; 345 | list-style-image: none; 346 | } 347 | ol { 348 | margin-left: 1.45rem; 349 | margin-right: 0; 350 | margin-top: 0; 351 | padding-bottom: 0; 352 | padding-left: 0; 353 | padding-right: 0; 354 | padding-top: 0; 355 | margin-bottom: 1.45rem; 356 | list-style-position: outside; 357 | list-style-image: none; 358 | } 359 | dl { 360 | margin-left: 0; 361 | margin-right: 0; 362 | margin-top: 0; 363 | padding-bottom: 0; 364 | padding-left: 0; 365 | padding-right: 0; 366 | padding-top: 0; 367 | margin-bottom: 1.45rem; 368 | } 369 | dd { 370 | margin-left: 0; 371 | margin-right: 0; 372 | margin-top: 0; 373 | padding-bottom: 0; 374 | padding-left: 0; 375 | padding-right: 0; 376 | padding-top: 0; 377 | margin-bottom: 1.45rem; 378 | } 379 | p { 380 | margin-left: 0; 381 | margin-right: 0; 382 | margin-top: 0; 383 | padding-bottom: 0; 384 | padding-left: 0; 385 | padding-right: 0; 386 | padding-top: 0; 387 | margin-bottom: 1.45rem; 388 | } 389 | figure { 390 | margin-left: 0; 391 | margin-right: 0; 392 | margin-top: 0; 393 | padding-bottom: 0; 394 | padding-left: 0; 395 | padding-right: 0; 396 | padding-top: 0; 397 | margin-bottom: 1.45rem; 398 | } 399 | pre { 400 | margin-left: 0; 401 | margin-right: 0; 402 | margin-top: 0; 403 | margin-bottom: 1.45rem; 404 | font-size: 0.85rem; 405 | line-height: 1.42; 406 | background: hsla(0, 0%, 0%, 0.04); 407 | border-radius: 3px; 408 | overflow: auto; 409 | word-wrap: normal; 410 | padding: 1.45rem; 411 | } 412 | table { 413 | margin-left: 0; 414 | margin-right: 0; 415 | margin-top: 0; 416 | padding-bottom: 0; 417 | padding-left: 0; 418 | padding-right: 0; 419 | padding-top: 0; 420 | margin-bottom: 1.45rem; 421 | font-size: 1rem; 422 | line-height: 1.45rem; 423 | border-collapse: collapse; 424 | width: 100%; 425 | } 426 | fieldset { 427 | margin-left: 0; 428 | margin-right: 0; 429 | margin-top: 0; 430 | padding-bottom: 0; 431 | padding-left: 0; 432 | padding-right: 0; 433 | padding-top: 0; 434 | margin-bottom: 1.45rem; 435 | } 436 | blockquote { 437 | margin-left: 1.45rem; 438 | margin-right: 1.45rem; 439 | margin-top: 0; 440 | padding-bottom: 0; 441 | padding-left: 0; 442 | padding-right: 0; 443 | padding-top: 0; 444 | margin-bottom: 1.45rem; 445 | } 446 | form { 447 | margin-left: 0; 448 | margin-right: 0; 449 | margin-top: 0; 450 | padding-bottom: 0; 451 | padding-left: 0; 452 | padding-right: 0; 453 | padding-top: 0; 454 | margin-bottom: 1.45rem; 455 | } 456 | noscript { 457 | margin-left: 0; 458 | margin-right: 0; 459 | margin-top: 0; 460 | padding-bottom: 0; 461 | padding-left: 0; 462 | padding-right: 0; 463 | padding-top: 0; 464 | margin-bottom: 1.45rem; 465 | } 466 | iframe { 467 | margin-left: 0; 468 | margin-right: 0; 469 | margin-top: 0; 470 | padding-bottom: 0; 471 | padding-left: 0; 472 | padding-right: 0; 473 | padding-top: 0; 474 | margin-bottom: 1.45rem; 475 | } 476 | hr { 477 | margin-left: 0; 478 | margin-right: 0; 479 | margin-top: 0; 480 | padding-bottom: 0; 481 | padding-left: 0; 482 | padding-right: 0; 483 | padding-top: 0; 484 | margin-bottom: calc(1.45rem - 1px); 485 | background: hsla(0, 0%, 0%, 0.2); 486 | border: none; 487 | height: 1px; 488 | } 489 | address { 490 | margin-left: 0; 491 | margin-right: 0; 492 | margin-top: 0; 493 | padding-bottom: 0; 494 | padding-left: 0; 495 | padding-right: 0; 496 | padding-top: 0; 497 | margin-bottom: 1.45rem; 498 | } 499 | b { 500 | font-weight: bold; 501 | } 502 | strong { 503 | font-weight: bold; 504 | } 505 | dt { 506 | font-weight: bold; 507 | } 508 | th { 509 | font-weight: bold; 510 | } 511 | li { 512 | margin-bottom: calc(1.45rem / 2); 513 | } 514 | ol li { 515 | padding-left: 0; 516 | } 517 | ul li { 518 | padding-left: 0; 519 | } 520 | li > ol { 521 | margin-left: 1.45rem; 522 | margin-bottom: calc(1.45rem / 2); 523 | margin-top: calc(1.45rem / 2); 524 | } 525 | li > ul { 526 | margin-left: 1.45rem; 527 | margin-bottom: calc(1.45rem / 2); 528 | margin-top: calc(1.45rem / 2); 529 | } 530 | blockquote *:last-child { 531 | margin-bottom: 0; 532 | } 533 | li *:last-child { 534 | margin-bottom: 0; 535 | } 536 | p *:last-child { 537 | margin-bottom: 0; 538 | } 539 | li > p { 540 | margin-bottom: calc(1.45rem / 2); 541 | } 542 | code { 543 | font-size: 0.85rem; 544 | line-height: 1.45rem; 545 | } 546 | kbd { 547 | font-size: 0.85rem; 548 | line-height: 1.45rem; 549 | } 550 | samp { 551 | font-size: 0.85rem; 552 | line-height: 1.45rem; 553 | } 554 | abbr { 555 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 556 | cursor: help; 557 | } 558 | acronym { 559 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 560 | cursor: help; 561 | } 562 | abbr[title] { 563 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 564 | cursor: help; 565 | text-decoration: none; 566 | } 567 | thead { 568 | text-align: left; 569 | } 570 | td, 571 | th { 572 | text-align: left; 573 | border-bottom: 1px solid hsla(0, 0%, 0%, 0.12); 574 | font-feature-settings: "tnum"; 575 | -moz-font-feature-settings: "tnum"; 576 | -ms-font-feature-settings: "tnum"; 577 | -webkit-font-feature-settings: "tnum"; 578 | padding-left: 0.96667rem; 579 | padding-right: 0.96667rem; 580 | padding-top: 0.725rem; 581 | padding-bottom: calc(0.725rem - 1px); 582 | } 583 | th:first-child, 584 | td:first-child { 585 | padding-left: 0; 586 | } 587 | th:last-child, 588 | td:last-child { 589 | padding-right: 0; 590 | } 591 | tt, 592 | code { 593 | background-color: hsla(0, 0%, 0%, 0.04); 594 | border-radius: 3px; 595 | font-family: "SFMono-Regular", Consolas, "Roboto Mono", "Droid Sans Mono", 596 | "Liberation Mono", Menlo, Courier, monospace; 597 | padding: 0; 598 | padding-top: 0.2em; 599 | padding-bottom: 0.2em; 600 | } 601 | pre code { 602 | background: none; 603 | line-height: 1.42; 604 | } 605 | code:before, 606 | code:after, 607 | tt:before, 608 | tt:after { 609 | letter-spacing: -0.2em; 610 | content: " "; 611 | } 612 | pre code:before, 613 | pre code:after, 614 | pre tt:before, 615 | pre tt:after { 616 | content: ""; 617 | } 618 | @media only screen and (max-width: 480px) { 619 | html { 620 | font-size: 100%; 621 | } 622 | } 623 | --------------------------------------------------------------------------------