Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
1# Development
2
3Thanks for contributing! We want to ensure that `urql` evolves and fulfills
4its idea of extensibility and flexibility by seeing continuous improvements
5and enhancements, no matter how small or big they might be.
6
7If you're about to add a new exchange, please consider publishing it as
8a separate package.
9
10## How to contribute?
11
12We follow fairly standard but lenient rules around pull requests and issues.
13Please pick a title that describes your change briefly, optionally in the imperative
14mood if possible.
15
16If you have an idea for a feature or want to fix a bug, consider opening an issue
17first. We're also happy to discuss and help you open a PR and get your changes
18in!
19
20- If you have a question, try [creating a GitHub Discussions thread.](https://github.com/urql-graphql/urql/discussions/new)
21- If you think you've found a bug, [open a new issue.](https://github.com/urql-graphql/urql/issues/new/choose)
22- or, if you found a bug you'd like to fix, [open a PR.](https://github.com/urql-graphql/urql/compare)
23- If you'd like to propose a change [open an RFC issue.](https://github.com/urql-graphql/urql/issues/new?labels=future+%F0%9F%94%AE&template=RFC.md&title=RFC%3A+Your+Proposal) You can read more about the RFC process [below](#how-do-i-propose-changes).
24
25### What are the issue conventions?
26
27There are **no strict conventions**, but we do have two templates in place that will fit most
28issues, since questions and other discussion start on GitHub Discussions. The bug template is fairly
29standard and the rule of thumb is to try to explain **what you expected** and **what you got
30instead.** Following this makes it very clear whether it's a known behavior, an unexpected issue,
31or an undocumented quirk.
32
33We do ask that issues _aren’t_ created for questions, or where a bug is likely to be either caused
34by misusage or misconfiguration. In short, if you can’t provide a reproduction of the issue, then
35it may be the case that you’ve got a question instead.
36
37If you need a template for creating a reproduction, all of our examples can be opened in isolated
38sandboxes or modified as you see fit: https://github.com/urql-graphql/urql/tree/main/examples
39
40### How do I propose changes?
41
42We follow an **RFC proposal process**. This allows anyone to propose a new feature or a change, and
43allows us to communicate our current planned features or changes, so any technical discussion,
44progress, or upcoming changes are always **documented transparently.** You can [find the RFC
45template](https://github.com/urql-graphql/urql/issues/new/choose) in our issue creator.
46
47All RFCs are added to the [RFC Lifecycle board.](https://github.com/urql-graphql/urql/projects/3)
48This board tracks where an RFC stands and who's working on it until it's completed. Bugs and PRs may
49end up on there too if no corresponding RFC exists or was necessary. RFCs are typically first added
50to "In Discussion" until we believe they're ready to be worked on. This step may either be short,
51skipped, or rather long, if no plan is in place for a change yet. So if you see a way to help,
52please leave some suggestions.
53
54### What are the PR conventions?
55
56This also comes with **no strict conventions**. We only ask you to follow the PR template we have
57in place more strictly here than the templates for issues, since it asks you to list a summary
58(maybe even with a short explanation) and a list of technical changes.
59
60If you're **resolving** an issue please don't forget to add `Resolve #123` to the description so that
61it's automatically linked, so that there's no ambiguity and which issue is being addressed (if any)
62
63You'll find that a comment by the "Changeset" bot may pop up. If you don't know what a **changeset**
64is and why it's asking you to document your changes, read on at ["How do I document a change for the
65changelog"](#how-do-i-document-a-change-for-the-changelog)
66
67We also typically **name** our PRs with a slightly descriptive title, e.g. `(shortcode) - Title`,
68where shortcode is either the name of a package, e.g. `(core)` and the title is an imperative mood
69description, e.g. "Update X" or "Refactor Y."
70
71## How do I set up the project?
72
73Luckily it's not hard to get started. You can install dependencies
74[using `pnpm`](https://pnpm.io/installation#using-corepack).
75Please don't use `npm` or `yarn` to respect the lockfile.
76
77```sh
78pnpm install
79```
80
81There are multiple commands you can run in the root folder to test your changes:
82
83```sh
84# TypeScript checks:
85pnpm run check
86
87# Linting (prettier & eslint):
88pnpm run lint
89
90# Unit Tests (for all packages):
91pnpm run test
92
93# Builds (for all packages):
94pnpm run build
95```
96
97You can find the main packages in `packages/*` and the addon exchanges in `exchanges/*`.
98Each package also has its own scripts that are common and shared between all packages.
99
100```sh
101# Unit Tests for the current package:
102pnpm run test
103
104# Linting (prettier & eslint):
105pnpm run lint
106
107# Build the current package:
108pnpm run build
109
110# TypeScript checks for the current package:
111pnpm run check
112```
113
114While you can run `build` globally in the interest of time it's advisable to only run it
115on the packages you're working on. Note that TypeScript checks don't require any packages
116to be built.
117
118## How do I test my changes?
119
120It's always good practice to run the tests when making changes. If you're unsure which packages
121may be affected by your new tests or changes you may run `pnpm test` in the root of
122the repository.
123
124If your editor is not set up with type checks you may also want to run `pnpm run check` on your
125changes.
126
127Additionally you can head to any example in the `examples/` folder
128and run them. There you'll also need to install their dependencies as they're isolated projects,
129without a lockfile and without linking to packages in the monorepos.
130All examples are started using the `package.json`'s `start` script.
131
132## How do I lint my code?
133
134We ensure consistency in `urql`'s codebase using `eslint` and `prettier`.
135They are run on a `precommit` hook, so if something's off they'll try
136to automatically fix up your code, or display an error.
137
138If you have them set up in your editor, even better!
139
140## How do I document a change for the changelog?
141
142This project uses [changesets](https://github.com/atlassian/changesets). This means that for
143every PR there must be documentation for what has been changed and which package is affected.
144
145You can document a change by running `changeset`, which will ask you which packages
146have changed and whether the change is major/minor/patch. It will then ask you to write
147a change entry as markdown.
148
149```sh
150# In the root of the urql repository call:
151pnpm changeset
152```
153
154This will create a new "changeset file" in the `.changeset` folder, which you should commit and
155push, so that it's added to your PR.
156This will eventually end up in the package's `CHANGELOG.md` file when we do a release.
157
158You won't need to add a changeset if you're simply making "non-visible" changes to the docs or other
159files that aren't published to the npm registry.
160
161[Read more about adding a `changeset` here.](https://github.com/atlassian/changesets/blob/master/docs/adding-a-changeset.md#i-am-in-a-multi-package-repository-a-mono-repo)
162
163## How do I release new versions of our packages?
164
165Hold up, that's **automated**! Since we use `changeset` to document our changes, which determines what
166goes into the changelog and what kind of version bump a change should make, you can also use the
167tool to check what's currently posed to change after a release batch using: `pnpm changeset status`.
168
169We have a [GitHub Actions workflow](./.github/workflow/release.yml) which is triggered whenever new
170changes are merged. It will always open a **"Version Packages" PR** which is kept up-to-date. This PR
171documents all changes that are made and will show in its description what all new changelogs are
172going to contain for their new entries.
173
174Once a "Version Packages" PR is approved by a contributor and merged, the action will automatically
175take care of creating the release, publishing all updated packages to the npm registry, and creating
176appropriate tags on GitHub too.
177
178This process is automated, but the changelog should be checked for errors.
179
180As to **when** to merge the automated PR and publish? Maybe not after every change. Typically there
181are two release batches: hotfixes and release batches. We expect that a hotfix for a single package
182should go out as quickly as possible if it negatively affects users. For **release batches**
183however, it's common to assume that if one change is made to a package that more will follow in the
184same week. So waiting for **a day or two** when other changes are expected will make sense to keep the
185fatigue as low as possible for downstream maintainers.
186
187## How do I upgrade all dependencies?
188
189It may be a good idea to keep all dependencies on the `urql` repository **up-to-date** every now and
190then. Typically we do this by running `pnpm update --interactive --latest` and checking one-by-one
191which dependencies will need to be bumped. In case of any security issues it may make sense to
192just run `pnpm update [package]`.
193
194While this is rare with `pnpm`, upgrading some transitive dependencies may accidentally duplicate
195them if two packages depend on different compatible version ranges. This can be fixed by running:
196
197```sh
198npx pnpm-deduplicate
199pnpm install
200```
201
202It's common to then **create a PR** (with a changeset documenting the packages that need to reflect
203new changes if any `dependencies` have changed) with the name of
204"(chore) - Upgrade direct and transitive dependencies" or something similar.
205
206## How do I add a new package?
207
208First of all we need to know **where** to put the package.
209
210- Exchanges should be added to `exchanges/` and the folder should be the plain
211 name of the exchange. Since the `package.json:name` is following the convention
212 of `@urql/exchange-*` the folder should just be without this conventional prefix.
213- All other packages should be added to `packages/`. Typically all packages should
214 be named `@urql/*` and their folders should be named exactly this without the
215 prefix or `*-urql`. Optionally if the package will be named `*-urql` then the folder
216 can take on the same name.
217
218When adding a new package, start by **copying** a `package.json` file from another project.
219You may want to alter the following fields first:
220
221- `name`
222- `version` (either start at `0.1.0` or `1.0.0`)
223- `description`
224- `repository.directory`
225- `keywords`
226
227Make sure to also alter the `devDependencies`, `peerDependencies`, and `dependencies` to match
228the new package's needs.
229
230**The `main` and `module` fields follow a convention:**
231All output bundles will always be output in the `./dist` folder by `rollup`, which is set up in
232the `build` script. Their filenames are a "kebab case" (dash-cased) version of the `name` field with
233an appropriate extension (`.esm.js` for `module` and `.cjs.js` for `main`).
234
235If your entrypoint won't be at `src/index.ts` you may alter it. But the `types` field has to match
236the same file relative to the `dist/types` folder, where `rollup` will output the TypeScript
237declaration files.
238
239When setting up your package make sure to create a `src/index.ts` file
240(or any other file which you've pointed `package.json:source` to). Also don't forget to
241copy over the `tsconfig.json` from another package (You won't need to change it).
242
243The `scripts.prepare` task is set up to check your new `package.json` file for correctness. So in
244case you get anything wrong, you'll get a short error when running `pnpm` after setting your new
245project up. Just in case! 😄
246
247Afterwards you can check whether everything is working correctly by running:
248
249```sh
250pnpm install
251pnpm run check
252```
253
254At this point, **don't publish** the package or a prerelease yourself if you can avoid it. If you can't
255or have already, we'll need to get the **rights** fixed by adding the package to the `@urql` scope.
256Typically what we do is:
257
258```sh
259npm access grant read-write urql:developers [package]
260```