{"id":13630571,"url":"https://github.com/smooth-code/fraql","last_synced_at":"2025-04-04T12:10:12.867Z","repository":{"id":57126874,"uuid":"134836974","full_name":"smooth-code/fraql","owner":"smooth-code","description":"GraphQL fragments made simple ⚡️","archived":false,"fork":false,"pushed_at":"2020-03-14T12:42:10.000Z","size":783,"stargazers_count":447,"open_issues_count":1,"forks_count":23,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-04-14T13:50:44.062Z","etag":null,"topics":["apollo","apollographql","fragment","graphql","mocking","react","relay"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smooth-code.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-05-25T09:46:45.000Z","updated_at":"2024-03-29T04:04:01.000Z","dependencies_parsed_at":"2022-08-31T13:51:46.425Z","dependency_job_id":null,"html_url":"https://github.com/smooth-code/fraql","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smooth-code%2Ffraql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smooth-code%2Ffraql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smooth-code%2Ffraql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smooth-code%2Ffraql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smooth-code","download_url":"https://codeload.github.com/smooth-code/fraql/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247174456,"owners_count":20896078,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apollo","apollographql","fragment","graphql","mocking","react","relay"],"created_at":"2024-08-01T22:01:47.639Z","updated_at":"2025-04-04T12:10:12.849Z","avatar_url":"https://github.com/smooth-code.png","language":"JavaScript","readme":"\u003ch1 align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/smooth-code/fraql/master/resources/fraql-logo.png\" alt=\"FraQL\" title=\"FraQL\" width=\"300\"\u003e\n\u003c/h1\u003e\n\u003cp align=\"center\" style=\"font-size: 1.2rem;\"\u003eGraphQL fragments made simple ⚡️\u003c/p\u003e\n\n[![Build Status][build-badge]][build]\n[![Code Coverage][coverage-badge]][coverage]\n[![version][version-badge]][package] [![MIT License][license-badge]][license]\n\n[![PRs Welcome][prs-badge]][prs]\n\n[![Watch on GitHub][github-watch-badge]][github-watch]\n[![Star on GitHub][github-star-badge]][github-star]\n[![Tweet][twitter-badge]][twitter]\n\n```sh\nnpm install fraql graphql graphql-tools graphql-tag\n```\n\nFraQL solves several things:\n\n* ☀️ Isolation: fragments don't rely on name anymore\n* ✨ Mocking: generate data \u0026 props from fragments\n* 🤯 Collocation: put GraphQL in your components\n\n## Example\n\n```js\nimport gql from 'fraql'\n\n// Create fragment without naming it.\nconst fragment = gql`\n  fragment _ on Article {\n    title\n    description\n  }\n`\n\n// Just use it in your queries!\nconst query = gql`\n  query Articles {\n    articles {\n      id\n      ${fragment}\n    }\n  }\n`\n```\n\n**⚡️ [See live example on CodeSandbox](https://codesandbox.io/s/l42jqm319l)**\n\n## Motivation\n\nPutting data next to your component is a good practice. It is built-in [Relay](https://facebook.github.io/relay/) and Lee Byron explains the advantages into [his talk about the IDEA architecture](https://www.youtube.com/watch?v=oTcDmnAXZ4E).\n\nI tried to do it by myself, but relying on fragment names is not an easy task. FraQL solves this issue by bringing isolation, fragments do not rely on their names.\n\nThe second problem solved by FraQL is the mocking. Generating a set of data for complex components is a pain. FraQL solves it by generating data right from your fragments!\n\n## Usage with React\n\n### Reference fragments into components\n\nFraQL exports a default tag function that is a drop-in replacement for `graphql-tag`. By using it you can create reusable fragments easily.\n\nFraQL is not a framework, but it comes with good practices. It is recommended to create a static property `fragments` on your components that contains a map of component properties. For each one, you specify the associated fragment.\n\nYou may have noticed that the name of the fragment is \"\\_\". FraQL transforms your fragment into an inline fragment. You can pick any name you want, because it will be dropped the transformation anyway.\n\n```js\nimport React from 'react'\nimport gql from 'fraql'\n\nconst ArticleCard = ({ article }) =\u003e (\n  \u003cdiv\u003e\n    \u003ch1\u003e{article.title}\u003c/h1\u003e\n    \u003cp\u003e{article.description}\u003c/p\u003e\n  \u003c/div\u003e\n)\n\n// Create a map of fragments and reference them on a static property \"fragments\".\nArticleCard.fragments = {\n  article: gql`\n    fragment _ on Article {\n      title\n      description\n    }\n  `,\n}\n\nexport default ArticleCard\n```\n\n### Use fragments into your queries\n\nWith FraQL, using a fragment into a query is obvious, just put the fragment where you want to use it.\n\nImporting `gql` from `fraql` is not required for queries. In this case this is just a pass-through to `graphql-tag`. The magic behind FraQL only happens when you use it on a fragment.\n\n```js\nimport React from 'react'\nimport gql from 'fraql'\nimport { Query } from 'apollo-client'\nimport ArticleCard from './ArticleCard'\n\n// Build your query by using your fragment.\nconst ARTICLES = gql`\n  query Articles {\n    articles {\n      id\n      ${ArticleCard.fragments.article}\n    }\n  }\n`\n\nconst ArticleList = ({ articles }) =\u003e (\n  \u003cdiv\u003e\n    \u003cQuery query={ARTICLES}\u003e\n      {({ data }) =\u003e\n        data.articles \u0026\u0026\n        data.articles.map(article =\u003e (\n          \u003cArticleCard key={article.id} article={article} /\u003e\n        ))\n      }\n    \u003c/Query\u003e\n  \u003c/div\u003e\n)\n\nexport default ArticleList\n```\n\n**⚡️ [See live example on CodeSandbox](https://codesandbox.io/s/l42jqm319l)**\n\n**⚡️ [See React example in this repository](https://github.com/smooth-code/fraql/tree/master/examples/react)**\n\n## Mocking\n\nTools like [StoryBook](https://github.com/storybooks/storybook) allows you to develop your components into an isolated environment. But you still have to write a set of data for displaying your components. Each time you modify your component, you have to modify this set of data, it is a real pain to maintain!\n\nIf all your components have fragments, you get mocking for free!\n\n#### 1. Generate introspection\n\nMocking data from a fragment requires knowing all schema types. That's why you have to generate a introspection result from your schema in order to use mocking.\n\nFraQL exposes a method `introspectSchema` to simplify this operation. The only thing you have to do is create a script that dumps your introspection result into a JSON file.\n\n```js\n// Example of script that generates an introspection result into \"schema.json\".\nconst { writeFileSync } = require('fs')\nconst { introspectSchema } = require('fraql/server')\nconst schema = require('./myGraphQLSchema') // Your schema defined server-side\n\nconst data = introspectSchema(schema)\nfs.writeFileSync('schema.json', JSON.stringify(data))\n```\n\n#### 2. Create a mocker\n\nFraQL exposes a method `createMockerFromIntrospection` that creates a mocker from your `schema.json`.\n\nIt is recommended to create one mocker and to use it wherever you need to generate data.\n\n```js\n// mocker.js\nimport { createMockerFromIntrospection } from 'fraql/mock'\nimport introspectionData from './schema.json'\n\nexport default createMockerFromIntrospection(introspectionData)\n```\n\n#### 3. Mock your fragments\n\nYou can now mock fragments using `mockFragment` or `mockFragments` methods.\n\n**Single fragment**\n\n```js\nimport gql from 'fraql'\nimport mocker from './mocker'\n\nconst fragment = gql`\n  fragment _ on Article {\n    id\n    title\n    author {\n      name\n    }\n  }\n`\n\nconst data = mocker.mockFragment(fragment)\n// {\n//   id: '4b165f7d-2ee1-4f09-8fd7-fc90d38a238a',\n//   title: 'Hello World',\n//   author: {\n//     name: 'Hello World',\n//   },\n// }\n```\n\n**Multiple fragments (components)**\n\n```js\nimport React from 'react'\nimport gql from 'fraql'\nimport mocker from './mocker'\nimport ArticleCard from './ArticleCard'\n\n// Generate all props directly from fragments.\nconst props = mocker.mockFragments(ArticleCard.fragments)\n\n// Create an element using generated props.\nconst articleCard = \u003cArticleCard {...props} /\u003e\n```\n\n**⚡️ [See StoryBook example in this repository](https://github.com/smooth-code/fraql/tree/master/examples/react)**\n\n## Recipes\n\n### Compose fragments\n\nOne of the principles of React is component composition. It is recommended to do the same with your GraphQL fragments.\n\n```js\n// ArticleTitle.js\nimport React from 'react'\nimport gql from 'fraql'\n\nconst ArticleTitle = ({ article }) =\u003e \u003ch2\u003e{article.title}\u003c/h2\u003e\n\nArticleTitle.fragments = {\n  article: gql`\n    fragment _ on Article {\n      title\n    }\n  `,\n}\n\nexport default ArticleTitle\n```\n\n```js\n// ArticleCard.js\nimport React from 'react'\nimport gql from 'fraql'\nimport ArticleTitle from './ArticleTitle'\n\nconst ArticleCard = ({ article }) =\u003e (\n  \u003cdiv\u003e\n    \u003cArticleTitle article={article} /\u003e\n    \u003cdiv\u003e{article.text}\u003c/div\u003e\n  \u003c/div\u003e\n)\n\nArticleCard.fragments = {\n  article: gql`\n    fragment _ on Article {\n      ${ArticleTitle.fragments.article}\n      text\n    }\n  `,\n}\n\nexport default ArticleCard\n```\n\n### Use without `gql`\n\nFraQL offers a drop-in replacement for `graphql-tag` but sometimes you don't use `gql` to define your fragments. As mentioned in [graphql-tag documentation](https://github.com/apollographql/graphql-tag) there are lots of other ways to do it (using Babel, Webpack, etc..).\n\nFraQL exposes a function `toInlineFragment` that transforms a GraphQL fragment into an inline fragment.\n\n```js\nimport { toInlineFragment } from 'fraql'\nimport gql from 'graphql-tag'\nimport fragment from './myFragment.gql'\n\nconst inlineFragment = toInlineFragment(fragment)\n\nconst query = gql`\n  query {\n    articles {\n      ${inlineFragment}\n    }\n  }\n`\n```\n\n### Mix named and inline fragments\n\nSometimes you may want to have the best of the two worlds, use a named fragment in one query and an inline fragment in another.\n\nFor this specific use-case FraQL exposes the original document:\n\n```js\nimport gql from 'fraql'\n\nconst fragment = gql`\n  fragment BaseArticleInfos on Article {\n    title\n    text\n  }\n`\n\nconst query = gql`\n  query Articles {\n    articles {\n      ...BaseArticleInfos\n    }\n  }\n\n  ${fragment.originalDocument}\n`\n```\n\n### Use custom mocks\n\nMocking feature of FraQL is build on top of [graphql-tools](https://www.apollographql.com/docs/graphql-tools/), it means you can [customize all your mocks](https://www.apollographql.com/docs/graphql-tools/mocking.html#Customizing-mocks).\n\nYou can define global mocks when you create the mocker:\n\n```js\nimport introspectionData from './schema.json'\n\nconst mocker = createMockerFromIntrospection(introspectionData, {\n  mocks: {\n    Article: () =\u003e ({\n      title: 'My article title',\n    }),\n  },\n})\n```\n\nAnd you can override them into `mockFragment` and `mockFragments`:\n\n```js\nimport ArticleCard from './ArticleCard'\n\nconst props = mocker.mockFragments(ArticleCard.fragments, {\n  mocks: {\n    Article: () =\u003e ({\n      title: 'Another title',\n    }),\n  },\n})\n```\n\n## API\n\n### `fraql` / `gql`\n\nThe default export of `fraql` is a drop-in replacement for `graphql-tag` that automatically converts fragments into inline fragments.\n\n```js\nimport gql from 'fraql'\n\nconst inlineFragment = gql`\n  fragment _ on Article {\n    title\n  }\n`\n\nconst query = gql`\n  {\n    articles {\n      id\n      ${inlineFragment}\n    }\n  }\n`\n```\n\n### `toInlineFragment(fragmentDocument)`\n\nConverts a fragment into an inline fragment usable in requests.\n\n```js\nimport gql from 'graphql-tag'\nimport { toInlineFragment } from 'fraql'\n\nconst fragment = gql`\n  fragment ArticleTitle on Article {\n    title\n  }\n`\n\nconst inlineFragment = toInlineFragment(fragment)\n\nconst query = gql`\n  {\n    articles {\n      id\n      ${inlineFragment}\n    }\n  }\n`\n```\n\n### `introspectSchema(schema)`\n\nGenerates introspection data from a schema.\n\n```js\nimport { introspectSchema } from 'fraql/server'\nimport schema from './graphqlSchema'\n\nconst introspectionData = introspectSchema(schema)\n```\n\n### `createMockerFromIntrospection(introspectionData, { mocks } = {})`\n\nGenerates a mocker from an introspection result generated using `introspectSchema`.\n\nYou can specify mocks, using [the same format as `graphql-tools`](https://www.apollographql.com/docs/graphql-tools/mocking.html#Customizing-mocks).\n\n```js\nimport { createMockerFromIntrospection } from 'fraql/mock'\nimport introspectionData from './schema.json'\n\nconst mocker = createMockerFromIntrospection(introspectionData)\n```\n\n### `mocker.mockFragment(fragment, { mocks } = {})`\n\nGenerates mock data from one fragment.\n\nYou can specify mocks, using [the same format as `graphql-tools`](https://www.apollographql.com/docs/graphql-tools/mocking.html#Customizing-mocks).\n\n```js\nconst fragment = gql`\n  fragment _ on Article {\n    title\n  }\n`\n\nconst data = fraqlMocker.mockFragment(fragment)\n// { title: 'Hello World' }\n```\n\n### `mocker.mockFragments(fragments, { mocks } = {})`\n\nGenerates mock data from a map of fragments.\n\nYou can specify mocks, using [the same format as `graphql-tools`](https://www.apollographql.com/docs/graphql-tools/mocking.html#Customizing-mocks).\n\n```js\nconst fragments = {\n  article: gql`\n    fragment _ on Article {\n      title\n      author {\n        name\n      }\n    }\n  `,\n  book: gql`\n    fragment _ on Book {\n      title\n    }\n  `,\n}\n\nconst data = fraqlMocker.mockFragment(fragments)\n// {\n//   article: {\n//     title: 'Hello World',\n//     author: {\n//       name: 'Hello World',\n//     },\n//   },\n//   book: {\n//     title: 'Hello World',\n//   }\n// }\n```\n\n## Inspiration \u0026 Thanks\n\n* Thanks to [Relay](https://facebook.github.io/relay/) for bringing the collocation idea\n* Thanks to Lee Byron for [his awesome talk about IDEA Architecture](https://www.youtube.com/watch?v=oTcDmnAXZ4E)\n* Thanks to [Apollo](https://www.apollographql.com) for the awesome tools they provide to the GraphQL community\n\n# License\n\nMIT\n\n[build-badge]: https://img.shields.io/travis/smooth-code/fraql.svg?style=flat-square\n[build]: https://travis-ci.org/smooth-code/fraql\n[coverage-badge]: https://img.shields.io/codecov/c/github/smooth-code/fraql.svg?style=flat-square\n[coverage]: https://codecov.io/github/smooth-code/fraql\n[version-badge]: https://img.shields.io/npm/v/fraql.svg?style=flat-square\n[package]: https://www.npmjs.com/package/fraql\n[license-badge]: https://img.shields.io/npm/l/fraql.svg?style=flat-square\n[license]: https://github.com/smooth-code/fraql/blob/master/LICENSE\n[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square\n[prs]: http://makeapullrequest.com\n[github-watch-badge]: https://img.shields.io/github/watchers/smooth-code/fraql.svg?style=social\n[github-watch]: https://github.com/smooth-code/fraql/watchers\n[github-star-badge]: https://img.shields.io/github/stars/smooth-code/fraql.svg?style=social\n[github-star]: https://github.com/smooth-code/fraql/stargazers\n[twitter]: https://twitter.com/intent/tweet?text=Check%20out%20fraql!%20https://github.com/smooth-code/fraql%20%F0%9F%91%8D\n[twitter-badge]: https://img.shields.io/twitter/url/https/github.com/smooth-code/fraql.svg?style=social\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmooth-code%2Ffraql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmooth-code%2Ffraql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmooth-code%2Ffraql/lists"}