Rework CI and project toolchain (#1043)

- remove `cargo-make` integration
- rework CI pipeline more granular and precise
- rework releasing process
- tune up project layout
- fill up new CHANGELOGs

Additionally:
- fix latest nightly/stable Rust inconsistencies
This commit is contained in:
Kai Ren 2022-04-08 17:44:50 +03:00 committed by GitHub
parent d0b56f9222
commit 72ed45a77c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
442 changed files with 2385 additions and 3169 deletions

View file

@ -1,34 +1,11 @@
version: 2 version: 2
updates: updates:
- package-ecosystem: cargo - package-ecosystem: cargo
directory: "/" directory: /
schedule: schedule:
interval: daily interval: daily
open-pull-requests-limit: 10
ignore: - package-ecosystem: github-actions
- dependency-name: warp directory: /
versions: schedule:
- 0.3.0 interval: daily
- 0.3.1
- dependency-name: tokio
versions:
- 1.1.0
- 1.2.0
- 1.3.0
- 1.4.0
- dependency-name: actix
versions:
- 0.11.0
- dependency-name: actix-rt
versions:
- 2.0.0
- 2.1.0
- dependency-name: bytes
versions:
- 1.0.0
- dependency-name: hyper
versions:
- 0.14.1
- dependency-name: rand
versions:
- 0.8.0

View file

@ -1,57 +0,0 @@
name: Book
on:
pull_request:
paths:
- 'docs/book/**'
push:
paths:
- 'docs/book/**'
jobs:
tests:
name: Test code examples
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Test via skeptic
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path docs/book/tests/Cargo.toml
deploy:
name: Deploy book on gh-pages
needs: [tests]
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install mdBook
uses: peaceiris/actions-mdbook@v1
- name: Render book
run: |
mdbook build -d gh-pages/master docs/book
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
keepFiles: true
publish_dir: docs/book/gh-pages

View file

@ -1,151 +1,370 @@
name: CI name: CI
on: [pull_request, push] on:
push:
branches: ["master"]
tags: ["juniper*@*"]
pull_request:
branches: ["master"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
RUST_BACKTRACE: 1
jobs: jobs:
###################################################
# Formatting
###################################################
format: ##########################
name: Check formatting # Linting and formatting #
##########################
clippy:
if: ${{ github.ref == 'refs/heads/master'
|| startsWith(github.ref, 'refs/tags/juniper')
|| !contains(github.event.head_commit.message, '[skip ci]') }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - uses: actions/checkout@v3
uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1
- name: Install rust
uses: actions-rs/toolchain@v1
with: with:
toolchain: stable
components: rustfmt
profile: minimal profile: minimal
override: true toolchain: stable
components: clippy
- name: Run rustfmt - run: make cargo.lint
uses: actions-rs/cargo@v1
rustfmt:
if: ${{ github.ref == 'refs/heads/master'
|| startsWith(github.ref, 'refs/tags/juniper')
|| !contains(github.event.head_commit.message, '[skip ci]') }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with: with:
command: fmt profile: minimal
args: -- --check toolchain: nightly
components: rustfmt
################################################### - run: make cargo.fmt check=yes
# Main Builds
###################################################
build:
runs-on: ${{ matrix.os }}
###########
# Testing #
###########
example:
if: ${{ github.ref == 'refs/heads/master'
|| startsWith(github.ref, 'refs/tags/juniper')
|| !contains(github.event.head_commit.message, '[skip ci]') }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
rust: [stable, beta, nightly] example:
os: [ubuntu-latest, windows-latest, macOS-latest] - actix_subscriptions
- basic_subscriptions
- warp_async
- warp_subscriptions
os:
- ubuntu
- macOS
- windows
toolchain:
- stable
- beta
- nightly
runs-on: ${{ matrix.os }}-latest
steps: steps:
- name: Checkout - uses: actions/checkout@v3
uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1
- name: Install rust
uses: actions-rs/toolchain@v1
with: with:
toolchain: ${{ matrix.rust }}
profile: minimal profile: minimal
toolchain: ${{ matrix.toolchain }}
override: true override: true
- uses: davidB/rust-cargo-make@v1 - run: cargo check -p example_${{ matrix.example }}
feature:
if: ${{ github.ref == 'refs/heads/master'
|| startsWith(github.ref, 'refs/tags/juniper')
|| !contains(github.event.head_commit.message, '[skip ci]') }}
strategy:
fail-fast: false
matrix:
include:
- { feature: <none>, crate: juniper }
- { feature: bson, crate: juniper }
- { feature: chrono, crate: juniper }
- { feature: chrono-clock, crate: juniper }
- { feature: chrono-tz, crate: juniper }
- { feature: expose-test-schema, crate: juniper }
- { feature: graphql-parser, crate: juniper }
- { feature: schema-language, crate: juniper }
- { feature: serde_json, crate: juniper }
- { feature: time, crate: juniper }
- { feature: url, crate: juniper }
- { feature: uuid, crate: juniper }
- { feature: <none>, crate: juniper_actix }
- { feature: subscriptions, crate: juniper_actix }
- { feature: <none>, crate: juniper_warp }
- { feature: subscriptions, crate: juniper_warp }
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with: with:
version: '0.20.0' profile: minimal
toolchain: stable
override: true
- name: Build and run tests # TODO: Enable once MSRV is supported.
#- run: cargo +nightly update -Z minimal-versions
- run: cargo check -p ${{ matrix.crate }} --no-default-features
${{ matrix.feature != '<none>'
&& format('--features {0}', matrix.feature)
|| '' }}
env: env:
CARGO_MAKE_RUN_CODECOV: true RUSTFLAGS: -D warnings
run: |
cargo make workspace-ci-flow --no-workspace
################################################### package:
# WASM Builds if: ${{ startsWith(github.ref, 'refs/tags/juniper') }}
################################################### runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
- name: Parse crate name
id: crate
run: echo ::set-output
name=NAME::$(printf "$GITHUB_REF" | cut -d '/' -f3
| cut -d '@' -f1)
- run: cargo package -p ${{ steps.crate.outputs.NAME }}
test:
if: ${{ github.ref == 'refs/heads/master'
|| startsWith(github.ref, 'refs/tags/juniper')
|| !contains(github.event.head_commit.message, '[skip ci]') }}
strategy:
fail-fast: false
matrix:
crate:
- juniper_codegen
- juniper
- juniper_subscriptions
- juniper_graphql_ws
- juniper_integration_tests
- juniper_codegen_tests
- juniper_book_tests
- juniper_actix
- juniper_hyper
- juniper_iron
- juniper_rocket
- juniper_warp
os:
- ubuntu
- macOS
- windows
toolchain:
- stable
- beta
- nightly
exclude:
- crate: juniper_codegen_tests
toolchain: stable
- crate: juniper_codegen_tests
toolchain: beta
- crate: juniper_codegen_tests
os: macOS
- crate: juniper_codegen_tests
os: windows
- crate: juniper_book_tests
toolchain: beta
- crate: juniper_book_tests
toolchain: nightly
# TODO: LLVM ERROR: out of memory
- crate: juniper_integration_tests
os: windows
toolchain: beta
- crate: juniper_integration_tests
os: windows
toolchain: nightly
runs-on: ${{ matrix.os }}-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.toolchain }}
override: true
- run: make test.cargo crate=${{ matrix.crate }}
wasm: wasm:
runs-on: ${{ matrix.os }} if: ${{ github.ref == 'refs/heads/master'
|| startsWith(github.ref, 'refs/tags/juniper')
|| !contains(github.event.head_commit.message, '[skip ci]') }}
strategy: strategy:
fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macOS-latest] crate:
- juniper_codegen
- juniper
toolchain:
- stable
- beta
- nightly
runs-on: ubuntu-latest
steps: steps:
- name: Checkout - uses: actions/checkout@v3
uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1
- name: Install rust
uses: actions-rs/toolchain@v1
with: with:
toolchain: stable
target: wasm32-unknown-unknown
profile: minimal profile: minimal
toolchain: ${{ matrix.toolchain }}
target: wasm32-unknown-unknown
override: true override: true
- name: Check - run: cargo check --target wasm32-unknown-unknown -p ${{ matrix.crate }}
uses: actions-rs/cargo@v1
#############
# Releasing #
#############
release-check:
name: Check release automation
if: ${{ !startsWith(github.ref, 'refs/tags/juniper')
&& (github.ref == 'refs/heads/master'
|| !contains(github.event.head_commit.message, '[skip ci]')) }}
strategy:
fail-fast: false
matrix:
crate:
- juniper_codegen
- juniper
- juniper_subscriptions
- juniper_graphql_ws
- juniper_actix
- juniper_hyper
- juniper_iron
- juniper_rocket
- juniper_warp
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with: with:
command: check profile: minimal
args: --target wasm32-unknown-unknown --package juniper --package juniper_codegen toolchain: stable
################################################### - run: cargo install cargo-release
# Releases
###################################################
#release: - run: make cargo.release crate=${{ matrix.crate }} ver=minor
# name: Check release automation exec=no install=no
# runs-on: ubuntu-latest release-github:
name: Release on GitHub
needs:
- clippy
- example
- feature
- package
- rustfmt
- test
- wasm
if: ${{ startsWith(github.ref, 'refs/tags/juniper') }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# steps: - name: Parse crate name
# - name: Checkout id: crate
# uses: actions/checkout@v2 run: echo ::set-output
# with: name=NAME::$(printf "$GITHUB_REF" | cut -d '/' -f3
# fetch-depth: 20 | cut -d '@' -f1)
- name: Parse release version
id: release
run: echo ::set-output
name=VERSION::$(printf "$GITHUB_REF" | cut -d '@' -f2)
# - name: Install rust - name: Verify release version matches crate's Cargo manifest
# uses: actions-rs/toolchain@v1 run: >-
# with: test "${{ steps.release.outputs.VERSION }}" \
# toolchain: stable == "$(grep -m1 'version = "' ${{ steps.crate.outputs.NAME }}/Cargo.toml | cut -d '"' -f2)"
# profile: minimal - name: Parse CHANGELOG link
# override: true id: changelog
run: echo ::set-output
name=LINK::https://github.com/${{ github.repository }}/blob/${{ steps.crate.outputs.NAME }}%40${{ steps.release.outputs.VERSION }}//${{ steps.crate.outputs.NAME }}/CHANGELOG.md#$(sed -n '/^## \[${{ steps.release.outputs.VERSION }}\]/{s/^## \[\(.*\)\][^0-9]*\([0-9].*\)/\1--\2/;s/[^0-9a-z-]*//g;p;}' ${{ steps.crate.outputs.NAME }}/CHANGELOG.md)
# - uses: davidB/rust-cargo-make@v1 - uses: softprops/action-gh-release@v1
# with: env:
# version: '0.20.0' GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
name: ${{ steps.crate.outputs.NAME }} ${{ steps.release.outputs.VERSION }}
body: |
[API docs](https://docs.rs/${{ steps.crate.outputs.NAME }}/${{ steps.release.outputs.VERSION }})
[Changelog](${{ steps.changelog.outputs.LINK }})
prerelease: ${{ contains(steps.release.outputs.VERSION, '-') }}
# - name: Install cargo-release release-crate:
# uses: actions-rs/cargo@v1 name: Release on crates.io
# with: needs: ["release-github"]
# command: install if: ${{ startsWith(github.ref, 'refs/tags/juniper') }}
# args: --version=0.19.4 cargo-release runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
# - name: Setup git - name: Parse crate name
# run: | id: crate
# git config --global user.email "juniper@example.com" run: echo ::set-output
# git config --global user.name "Release Test Bot" name=NAME::$(printf "$GITHUB_REF" | cut -d '/' -f3
| cut -d '@' -f1)
# - name: Dry run mode - name: Publish crate
# env: run: cargo publish -p ${{ steps.crate.outputs.NAME }}
# RELEASE_LEVEL: minor --token ${{ secrets.CRATESIO_TOKEN }}
# run: |
# cargo make release-dry-run
# - name: Local test mode
# env:
# RELEASE_LEVEL: minor
# run: |
# cargo make release-local-test
# - name: Echo local changes
# run: |
# git --no-pager log -p HEAD...HEAD~20
# - name: Run tests
# run: | ##########
# cargo make workspace-ci-flow --no-workspace # Deploy #
##########
deploy-book:
name: deploy Book
needs: ["test"]
if: ${{ github.ref == 'refs/heads/master'
|| startsWith(github.ref, 'refs/tags/juniper@') }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: peaceiris/actions-mdbook@v1
- run: make book.build out=gh-pages/master
if: ${{ github.ref == 'refs/heads/master' }}
- run: make book.build out=gh-pages
if: ${{ startsWith(github.ref, 'refs/tags/juniper@') }}
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
keep_files: true
publish_dir: book/gh-pages

10
.gitignore vendored
View file

@ -1,3 +1,7 @@
target /.idea/
Cargo.lock /.vscode/
.idea /*.iml
.DS_Store
/Cargo.lock
/target/

View file

@ -1,24 +1,20 @@
[workspace] [workspace]
# Order is important as this is the order the crates will be released.
members = [ members = [
"juniper_benchmarks", "benches",
"juniper_codegen", "book/tests",
"juniper", "examples/basic_subscriptions",
"examples/basic_subscriptions", "examples/warp_async",
"examples/warp_async", "examples/warp_subscriptions",
"examples/warp_subscriptions", "examples/actix_subscriptions",
"examples/actix_subscriptions", "juniper_codegen",
"integration_tests/juniper_tests", "juniper",
"integration_tests/async_await", "juniper_hyper",
"integration_tests/codegen_fail", "juniper_iron",
"juniper_hyper", "juniper_rocket",
"juniper_iron", "juniper_subscriptions",
"juniper_rocket", "juniper_graphql_ws",
"juniper_subscriptions", "juniper_warp",
"juniper_graphql_ws", "juniper_actix",
"juniper_warp", "tests/codegen",
"juniper_actix", "tests/integration",
]
exclude = [
"docs/book/tests",
] ]

139
Makefile Normal file
View file

@ -0,0 +1,139 @@
###############################
# Common defaults/definitions #
###############################
comma := ,
# Checks two given strings for equality.
eq = $(if $(or $(1),$(2)),$(and $(findstring $(1),$(2)),\
$(findstring $(2),$(1))),1)
###########
# Aliases #
###########
book: book.build
fmt: cargo.fmt
lint: cargo.lint
test: test.cargo
release: cargo.release
##################
# Cargo commands #
##################
# Format Rust sources with rustfmt.
#
# Usage:
# make cargo.fmt [check=(no|yes)]
cargo.fmt:
cargo +nightly fmt --all $(if $(call eq,$(check),yes),-- --check,)
# Lint Rust sources with Clippy.
#
# Usage:
# make cargo.lint
cargo.lint:
cargo clippy --workspace --all-features -- -D warnings
# Release Rust crate.
#
# Read more about bump levels here:
# https://github.com/crate-ci/cargo-release/blob/master/docs/reference.md#bump-level
#
# Usage:
# make cargo.release crate=<crate-name> [ver=(release|<bump-level>)]
# ([exec=no]|exec=yes [push=(yes|no)])
# [install=(yes|no)]
cargo.release:
ifneq ($(install),no)
cargo install cargo-release
endif
cargo release -p $(crate) --all-features \
$(if $(call eq,$(exec),yes),\
--no-publish $(if $(call eq,$(push),no),--no-push,) --execute,\
-v $(if $(call eq,$(CI),),,--no-publish)) \
$(or $(ver),release)
cargo.test: test.cargo
####################
# Testing commands #
####################
# Run Rust tests of Book.
#
# Usage:
# make test.book
test.book:
@make test.cargo crate=juniper_book_tests
# Run Rust tests of project crates.
#
# Usage:
# make test.cargo [crate=<crate-name>]
test.cargo:
cargo $(if $(call eq,$(crate),juniper_codegen_tests),+nightly,) test \
$(if $(call eq,$(crate),),--workspace,-p $(crate)) --all-features
#################
# Book commands #
#################
# Build Book.
#
# Usage:
# make book.build [out=<dir>]
book.build:
mdbook build book/ $(if $(call eq,$(out),),,-d $(out))
# Serve Book on some port.
#
# Usage:
# make book.serve [port=(3000|<port>)]
book.serve:
mdbook serve book/ -p=$(or $(port),3000)
##################
# .PHONY section #
##################
.PHONY: book fmt lint release test \
book.build book.serve \
cargo.fmt cargo.lint cargo.release cargo.test \
test.book test.cargo

View file

@ -1,38 +0,0 @@
# https://github.com/sagiegurari/cargo-make#automatically-extend-workspace-makefile
[env]
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = "true"
CARGO_MAKE_CARGO_ALL_FEATURES = ""
CARGO_MAKE_WORKSPACE_SKIP_MEMBERS = "integration_tests/*;examples/*;juniper_benchmarks;"
# Run `RELEASE_LEVEL=(patch|major|minor) cargo make release` to push a new release of every crate.
#
# Run `RELEASE_LEVEL=(patch|major|minor) CARGO_MAKE_WORKSPACE_INCLUDE_MEMBERS="crate1;crate2;" cargo make release`
# to push a new release of a subset of crates.
[tasks.release]
condition = { env_set = [ "RELEASE_LEVEL" ] }
command = "cargo-release"
args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/../_build/release.toml", "--execute", "${RELEASE_LEVEL}"]
# Run `RELEASE_LEVEL=(patch|major|minor) cargo make release-dry-run` to do a dry run.
#
# Run `RELEASE_LEVEL=(patch|major|minor) CARGO_MAKE_WORKSPACE_INCLUDE_MEMBERS="crate1;crate2;" cargo make release-dry-run`
# to do a dry run of a subset of crates.
[tasks.release-dry-run]
condition = { env_set = [ "RELEASE_LEVEL" ] }
description = "Run `cargo-release --dry-run` for every crate"
command = "cargo-release"
args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/../_build/release.toml", "--no-confirm", "--no-publish", "--no-push", "--no-tag", "${RELEASE_LEVEL}"]
# Run `RELEASE_LEVEL=(patch|major|minor) cargo make release-local-test` to actually make changes locally but
# not push them up to crates.io or Github.
#
# Run `RELEASE_LEVEL=(patch|major|minor) CARGO_MAKE_WORKSPACE_INCLUDE_MEMBERS="crate1;crate2;" cargo make release-local-test` to actually make changes locally but
# not push some crates up to crates.io or Github.
[tasks.release-local-test]
condition = { env_set = [ "RELEASE_LEVEL" ] }
description = "Run `cargo-release` for every crate, but only make changes locally"
command = "cargo-release"
args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/../_build/release.toml", "--no-confirm", "${RELEASE_LEVEL}"]

View file

@ -1,74 +1,59 @@
# How to release new crate versions Releasing new crate versions
============================
Releasing of [workspace] crates of this project is performed by pushing the Git release tag (having `<crate-name>@<version>` format), following by the [CI pipeline] creating a [GitHub release] and publishing the crate to [crates.io].
> __WARNING__: Only one [workspace] crate may be released at a time. So, if you need to release multiple [workspace] crates, do this sequentially.
## Prerequisites ## Prerequisites
It is generally best to start with a clean respository dedicated to a release so that no git weirdness happens: We use [`cargo-release`] to automate crate releases. You will need to install it locally:
```bash
``` cargo install cargo-release
git clone git@github.com:graphql-rust/juniper.git juniper_release;
cd juniper_release;
``` ```
We use the `nightly` toolchain when releasing. This is because some of our crates require nightly:
`rustup default nightly`
We use [`cargo-make`](cargo-make) and [`cargo-release`](cargo-release) to automate crate releases. You will need to install them locally:
- `cargo install -f cargo-make` ## Preparing
- `cargo install -f cargo-release`
## Preparing for a release To produce a new release a [workspace] crate, perform the following steps:
There are two general classes of releases: 1. Check its `CHANGELOG.md` file to be complete and correctly formatted. The section for the new release __should start__ with `## master` header. Commit any changes you've made.
1. All public workspace crates should be released and all share the same release level ("patch", "minor", "major"). 2. Determine a new release [bump level] (`patch`, `minor`, `major`, or default `release`).
2. A subset of workspace crates need to be released, or not all crate releases share the same release level. 3. Run the release process in dry-run mode and check the produced diffs to be made in the returned output.
```bash
make release crate=juniper ver=minor
```
**All release commands must be run from the root directory of the repository.** 4. (Optional) Not everything may be captured in dry-run mode. It may be a good idea to run a local test, without pushing the created Git commit and tag.
```bash
make release crate=juniper ver=minor exec=yes push=no
```
## Determine new release level
For each crate, determine the desired release level (`patch`, `minor`, `major`). Set the `RELEASE_LEVEL` env variable to the desired release level.
## Determine which crates to release
If a subset of workspace crates need to be released, or not all crate releases share the same release level, set the `CARGO_MAKE_WORKSPACE_INCLUDE_MEMBERS` env ## Executing
variable to choose specific workspace crates. The value is a list of semicolon-delineated crate names or a regular expressions.
## Dry run Once everything is prepared and checked, just execute the releasing process:
```bash
make release crate=juniper ver=minor exec=yes
```
It is a good idea to do a dry run to sanity check what actions will be performed. Once the [CI pipeline] for the pushed Git tag successfully finishes, the crate is fully released.
- For case #1 above, run `cargo make release-dry-run`.
- For case #2 above, run `CARGO_MAKE_WORKSPACE_INCLUDE_MEMBERS="crate1;crate2" cargo make release-dry-run`.
If the command finishes super quickly with no output you likely did not set `RELEASE_LEVEL`.
## Local test
Not everything is captured in the dry run. It is a good idea to run a local test. [`cargo-release`]: https://crates.io/crates/cargo-release
In a local test, all the release actions are performed on your local checkout [CI pipeline]: /../../blob/master/.github/workflows/ci.yml
but nothing is pushed to Github or crates.io. [crates.io]: https://crates.io
[GitHub release]: https://docs.github.com/repositories/releasing-projects-on-github/about-releases
- For case #1 above, run `cargo make release-local-test`. [release level]: https://github.com/crate-ci/cargo-release/blob/master/docs/reference.md#bump-level
- For case #2 above, run `CARGO_MAKE_WORKSPACE_INCLUDE_MEMBERS="crate1;crate2" cargo make release-local-test`. [workspace]: https://doc.rust-lang.org/cargo/reference/workspaces.html
If the command finishes super quickly with no output you likely did not set `RELEASE_LEVEL`.
After, your local git repository should have the changes ready to push to Github.
Use `git rebase -i HEAD~10` and drop the new commits.
## Release
After testing locally and via a dry run, it is time to release. A release
consists of bumping versions, starting a new changelog section, pushing a tag to Github, and updating crates.io. This should all be handled by running the automated commands.
- For case #1 above, run `cargo make release`.
- For case #2 above, run `CARGO_MAKE_WORKSPACE_INCLUDE_MEMBERS="crate1;crate2" cargo make release`.
If the command finishes super quickly with no output you likely did not set `RELEASE_LEVEL`,
[cargo-make]: https://github.com/sagiegurari/cargo-make
[cargo-release]: https://github.com/sunng87/cargo-release

View file

@ -1,71 +0,0 @@
jobs:
- job: ${{ parameters.name }}
pool:
vmImage: ${{ parameters.vmImage }}
strategy:
matrix:
stable:
rustup_toolchain: stable
beta:
rustup_toolchain: beta
nightly:
rustup_toolchain: nightly
# TODO: re-enable once new versions are released.
# minimum_supported_version_plus_one:
# rustup_toolchain: 1.32.0
#minimum_supported_version:
# rustup_toolchain: 1.33.0
steps:
- ${{ if ne(parameters.name, 'Windows') }}:
# Linux and macOS.
- script: |
export CARGO_HOME="$HOME/.cargo"
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $RUSTUP_TOOLCHAIN
echo "##vso[task.setvariable variable=PATH;]$PATH:$HOME/.cargo/bin"
displayName: Install rust
- ${{ if eq(parameters.name, 'Windows') }}:
# Windows.
- script: |
set CARGO_HOME=%USERPROFILE%\.cargo
curl -sSf -o rustup-init.exe https://win.rustup.rs
rustup-init.exe -y --default-toolchain %RUSTUP_TOOLCHAIN%
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
echo "##vso[task.setvariable variable=PATH;]%PATH%;%USERPROFILE%\.cargo\bin"
displayName: Install rust (windows)
# All platforms.
- script: |
rustc -Vv
cargo -V
displayName: Query rust and cargo versions
- ${{ if eq(parameters.name, 'Linux') }}:
# Linux.
- script: _build/cargo-make.sh "0.20.0" "x86_64-unknown-linux-musl"
displayName: Install cargo-make binary
- ${{ if eq(parameters.name, 'macOS') }}:
# Mac.
- script: _build/cargo-make.sh "0.20.0" "x86_64-apple-darwin"
displayName: Install cargo-make binary
- ${{ if eq(parameters.name, 'Windows') }}:
# Windows.
- script: powershell -executionpolicy bypass -file _build/cargo-make.ps1 -version "0.20.0" -target "x86_64-pc-windows-msvc"
displayName: Install cargo-make binary
- ${{ if eq(parameters.name, 'Windows') }}:
# Windows.
- script: |
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
cargo make workspace-ci-flow --no-workspace
env: { CARGO_MAKE_RUN_CODECOV: true }
displayName: Build and run tests
- ${{ if ne(parameters.name, 'Windows') }}:
# Not Windows.
- script: |
export PATH="$PATH:$HOME/.cargo/bin";
cargo make workspace-ci-flow --no-workspace
env: { CARGO_MAKE_RUN_CODECOV: true }
displayName: Build and run tests
- script: |
rustup target add wasm32-unknown-unknown
cargo check --target wasm32-unknown-unknown --package juniper --package juniper_codegen
displayName: Check WebAssembly target
condition: eq(variables['rustup_toolchain'], 'stable')

View file

@ -1,21 +0,0 @@
param (
[Parameter(Mandatory=$true)][string]$version,
[Parameter(Mandatory=$true)][string]$target
)
# Location to put cargo-make binary.
$cargobindir = "$env:userprofile\.cargo\bin"
# Location to stage downloaded zip file.
$zipfile = "$env:temp\cargo-make.zip"
$url = "https://github.com/sagiegurari/cargo-make/releases/download/${version}/cargo-make-v${version}-${target}.zip"
# Download the zip file.
Invoke-WebRequest -Uri $url -OutFile $zipfile
# Extract the binary to the correct location.
Expand-Archive -Path $zipfile -DestinationPath $cargobindir
# Tell azure pipelines the PATH has changed for future steps.
Write-Host "##vso[task.setvariable variable=PATH;]%PATH%;$cargobindir"

View file

@ -1,19 +0,0 @@
#!/bin/bash
if [ -z ${1+x} ];
then
echo "Missing version as first argument";
exit 1
fi
if [ -z ${2+x} ];
then
echo "Missing target as second argument";
exit 1
fi
curl https://github.com/sagiegurari/cargo-make/releases/download/${1}/cargo-make-v${1}-${2}.zip -sSfL -o /tmp/cargo-make.zip;
unzip /tmp/cargo-make.zip;
mkdir -p "$HOME/.cargo/bin";
mv cargo-make-*/* $HOME/.cargo/bin;
echo "##vso[task.setvariable variable=PATH;]$PATH:$HOME/.cargo/bin"

View file

@ -1,6 +0,0 @@
pre-release-commit-message = "Release {{crate_name}} {{version}}"
post-release-commit-message = "Bump {{crate_name}} version to {{next_version}}"
tag-message = "Release {{crate_name}} {{version}}"
pre-release-replacements = [
{file="CHANGELOG.md", min=0, search="# master", replace="# master\n\n- Compatibility with the latest `juniper`.\n\n# [[{{version}}] {{date}}](https://github.com/graphql-rust/juniper/releases/tag/{{crate_name}}-{{version}})"},
]

View file

@ -1 +0,0 @@
´LÅØAtÙèù˜Û‡uÙË}k¦b÷Œ«<C592>iíãxN»ÔJÛb'OÅ€6°¤ê·ÄsÞ`(¯vZeòaˆ°Î`ëPÝW[DæW4¾®€Ïe¡·» <C2BB>«ï9¥¿4 ÀÖžgF÷ûa¸PýŒ5ò õ/8FQܪ"Bß ~þBrº¢Ž8@)†Ê0 yeÍĆ»·²Š àCù·»º´F¹"m§±òö¡wûÑ?<3F>INŽTŠ(tõlß•SÀ%K_3ð¾2ò§^Š^kMLMTJÛÕ½¾Z7cÁüzÖ&qÆsd²H¢^¨•‡

View file

@ -1,109 +0,0 @@
jobs:
###################################################
# Formatting
###################################################
- job: check_formatting
displayName: Check formatting
pool:
vmImage: 'ubuntu-latest'
steps:
- script: |
export CARGO_HOME="$HOME/.cargo"
curl https://sh.rustup.rs -sSf | sh -s -- -y
$HOME/.cargo/bin/rustup component add rustfmt
displayName: Install stable Rust
- script: |
$HOME/.cargo/bin/cargo fmt -- --check
displayName: Run rustfmt
###################################################
# Book
###################################################
- job: run_book_tests
displayName: Book code example tests
pool:
vmImage: 'ubuntu-latest'
steps:
- script: |
export CARGO_HOME="$HOME/.cargo"
curl https://sh.rustup.rs -sSf | sh -s -- -y
$HOME/.cargo/bin/rustup component add rustfmt
displayName: Install stable Rust
- script: |
cd docs/book/tests && $HOME/.cargo/bin/cargo test
displayName: Test book code examples via skeptic
- job: build_book_master
displayName: Build rendered book on master branch and push to Github
pool:
vmImage: 'ubuntu-latest'
dependsOn: run_book_tests
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
variables:
- group: github-keys
steps:
- task: InstallSSHKey@0
inputs:
hostName: $(GHSshKnownHosts)
sshPublicKey: $(GHSshPub)
sshKeySecureFile: $(GHSshPriv)
- script: |
./docs/book/ci-build.sh master
###################################################
# Main Builds
###################################################
- template: _build/azure-pipelines-template.yml
parameters:
name: Linux
vmImage: 'ubuntu-latest'
- template: _build/azure-pipelines-template.yml
parameters:
name: macOS
vmImage: 'macOS-latest'
- template: _build/azure-pipelines-template.yml
parameters:
name: Windows
vmImage: 'windows-latest'
###################################################
# Releases
###################################################
#- job: check_release_automation
# displayName: Check release automation
# pool:
# vmImage: 'ubuntu-latest'
# steps:
# - script: |
# export CARGO_HOME="$HOME/.cargo"
# curl https://sh.rustup.rs -sSf | sh -s -- -y
# echo "##vso[task.setvariable variable=PATH;]$PATH:$HOME/.cargo/bin"
# displayName: Install stable Rust
# - script: |
# _build/cargo-make.sh "0.20.0" "x86_64-unknown-linux-musl"
# displayName: Install cargo-make binary
# - script: |
# cargo install --debug --version=0.19.4 cargo-release
# displayName: Install cargo-release binary
# - script: |
# git config --local user.name "Release Test Bot"
# git config --local user.email "juniper@example.com"
# displayName: Set up git
# - script: |
# RELEASE_LEVEL="minor" cargo make release-dry-run
# displayName: Dry run mode
# - script: |
# RELEASE_LEVEL="minor" cargo make release-local-test
# displayName: Local test mode
# - script: |
# git --no-pager log -p HEAD...HEAD~20
# # NOTE: this is rolled into one task due to onerous
# # "bash not found" error on Azure.
# cargo make workspace-ci-flow --no-workspace
# displayName: Echo local changes && make sure build and tests still work

View file

@ -1,8 +1,9 @@
[package] [package]
name = "juniper_benchmarks" name = "juniper_benchmarks"
version = "0.1.0" version = "0.0.0"
edition = "2018" edition = "2018"
authors = ["Christoph Herzog <chris@theduke.at>"] authors = ["Christoph Herzog <chris@theduke.at>"]
publish = false
[dependencies] [dependencies]
futures = "0.3" futures = "0.3"
@ -10,7 +11,7 @@ juniper = { path = "../juniper" }
[dev-dependencies] [dev-dependencies]
criterion = "0.3" criterion = "0.3"
tokio = { version = "1", features = ["rt-multi-thread"] } tokio = { version = "1.0", features = ["rt-multi-thread"] }
[[bench]] [[bench]]
name = "benchmark" name = "benchmark"

2
book/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/_rendered/
/gh-pages/

67
book/README.md Normal file
View file

@ -0,0 +1,67 @@
Juniper Book
============
Book containing the [`juniper`](https://docs.rs/juniper) user guide.
## Contributing
### Requirements
The Book is built with [mdBook](https://github.com/rust-lang/mdBook).
You may install it with:
```bash
cargo install mdbook
```
### Local test server
To launch a local test server that continually re-builds the Book and auto-reloads the page, run:
```bash
mdbook serve
# or from project root dir:
make book.serve
```
### Building
You may build the Book to rendered HTML with this command:
```bash
mdbook build
# or from project root dir:
make book
```
The output will be in the `_rendered/` directory.
### Testing
To run the tests validating all code examples in the book, run:
```bash
cd tests/
cargo test
# or from project root dir:
cargo test -p juniper_book_tests
# or via shortcut from project root dir:
make test.book
```
## Test setup
All Rust code examples in the book are compiled on the CI.
This is done using the [skeptic](https://github.com/budziq/rust-skeptic) crate.

16
book/book.toml Normal file
View file

@ -0,0 +1,16 @@
[book]
title = "Juniper Book (GraphQL server for Rust)"
description = "User guide for Juniper (GraphQL server library for Rust)."
language = "en"
multilingual = false
src = "src"
[build]
build-dir = "_rendered"
create-missing = false
[output.html]
git_repository_url = "https://github.com/graphql-rs/juniper"
[rust]
edition = "2018"

View file

@ -50,12 +50,12 @@ DataLoader caching does not replace Redis, Memcache, or any other shared applica
[dependencies] [dependencies]
actix-identity = "0.4.0-beta.4" actix-identity = "0.4.0-beta.4"
actix-rt = "1.0" actix-rt = "1.0"
actix-web = {version = "2.0", features = []} actix-web = "2.0"
juniper = { git = "https://github.com/graphql-rust/juniper" }
futures = "0.3"
postgres = "0.15.2"
dataloader = "0.12.0"
async-trait = "0.1.30" async-trait = "0.1.30"
dataloader = "0.12.0"
futures = "0.3"
juniper = "0.16.0"
postgres = "0.15.2"
``` ```
```rust, ignore ```rust, ignore

View file

@ -12,8 +12,8 @@ be returned to the end user. The [`juniper_subscriptions`][juniper_subscriptions
provides a default connection implementation. Currently subscriptions are only supported on the `master` branch. Add the following to your `Cargo.toml`: provides a default connection implementation. Currently subscriptions are only supported on the `master` branch. Add the following to your `Cargo.toml`:
```toml ```toml
[dependencies] [dependencies]
juniper = { git = "https://github.com/graphql-rust/juniper", branch = "master" } juniper = "0.16.0"
juniper_subscriptions = { git = "https://github.com/graphql-rust/juniper", branch = "master" } juniper_subscriptions = "0.17.0"
``` ```
### Schema Definition ### Schema Definition

View file

@ -8,7 +8,7 @@ Juniper follows a [code-first approach][schema_approach] to defining GraphQL sch
```toml ```toml
[dependencies] [dependencies]
juniper = "0.15" juniper = "0.16.0"
``` ```
## Schema example ## Schema example

View file

@ -101,6 +101,7 @@ schema {
query: Query query: Query
} }
"; ";
# #[cfg(not(target_os = "windows"))]
assert_eq!(result, expected); assert_eq!(result, expected);
} }
``` ```

View file

@ -16,8 +16,8 @@ Juniper's Hyper integration is contained in the [`juniper_hyper`][juniper_hyper]
```toml ```toml
[dependencies] [dependencies]
juniper = "0.15.7" juniper = "0.16.0"
juniper_hyper = "0.8.0" juniper_hyper = "0.9.0"
``` ```
Included in the source is a [small example][example] which sets up a basic GraphQL and [GraphiQL] handler. Included in the source is a [small example][example] which sets up a basic GraphQL and [GraphiQL] handler.

View file

@ -11,8 +11,8 @@ Juniper's Iron integration is contained in the `juniper_iron` crate:
```toml ```toml
[dependencies] [dependencies]
juniper = "0.15.7" juniper = "0.16.0"
juniper_iron = "0.7.4" juniper_iron = "0.8.0"
``` ```
Included in the source is a [small Included in the source is a [small

View file

@ -10,8 +10,8 @@ Juniper's Rocket integration is contained in the [`juniper_rocket`][juniper_rock
```toml ```toml
[dependencies] [dependencies]
juniper = "0.15.7" juniper = "0.16.0"
juniper_rocket = "0.8.0" juniper_rocket = "0.9.0"
``` ```
Included in the source is a [small example][example] which sets up a basic GraphQL and [GraphiQL] handler. Included in the source is a [small example][example] which sets up a basic GraphQL and [GraphiQL] handler.

View file

@ -10,8 +10,8 @@ Juniper's Warp integration is contained in the [`juniper_warp`][juniper_warp] cr
```toml ```toml
[dependencies] [dependencies]
juniper = "0.15.7" juniper = "0.16.0"
juniper_warp = "0.7.0" juniper_warp = "0.8.0"
``` ```
Included in the source is a [small example][example] which sets up a basic GraphQL and [GraphiQL] handler. Included in the source is a [small example][example] which sets up a basic GraphQL and [GraphiQL] handler.

22
book/tests/Cargo.toml Normal file
View file

@ -0,0 +1,22 @@
[package]
name = "juniper_book_tests"
version = "0.0.0"
edition = "2018"
authors = ["Magnus Hallin <mhallin@fastmail.com>"]
publish = false
[dependencies]
derive_more = "0.99"
futures = "0.3"
iron = "0.5"
juniper = { path = "../../juniper" }
juniper_iron = { path = "../../juniper_iron" }
juniper_subscriptions = { path = "../../juniper_subscriptions" }
mount = "0.4"
serde_json = "1.0"
skeptic = "0.13"
tokio = { version = "1.0", features = ["macros", "rt-multi-thread", "sync"] }
uuid = "0.8"
[build-dependencies]
skeptic = "0.13"

4
book/tests/build.rs Normal file
View file

@ -0,0 +1,4 @@
fn main() {
let files = skeptic::markdown_files_of_directory("../src/");
skeptic::generate_doc_tests(&files);
}

View file

@ -1 +0,0 @@
_rendered

View file

@ -1,48 +0,0 @@
# Juniper Book
Book containing the Juniper documentation.
## Contributing
### Requirements
The book is built with [mdBook](https://github.com/rust-lang-nursery/mdBook).
You can install it with:
```bash
cargo install mdbook
```
### Starting a local test server
To launch a local test server that continually re-builds the book and autoreloads the page, run:
```bash
mdbook serve
```
### Building the book
You can build the book to rendered HTML with this command:
```bash
mdbook build
```
The output will be in the `./_rendered` directory.
### Running the tests
To run the tests validating all code examples in the book, run:
```bash
cd ./tests
cargo test
```
## Test setup
All Rust code examples in the book are compiled on the CI.
This is done using the [skeptic](https://github.com/budziq/rust-skeptic) library.

View file

@ -1,11 +0,0 @@
[book]
title = "Juniper - GraphQL Server for Rust"
description = "Documentation for juniper, a GraphQL server library for Rust."
src = "content"
[build]
build-dir = "_rendered"
create-missing = false
[output.html]
git_repository_url = "https://github.com/graphql-rs/juniper"

View file

@ -1,52 +0,0 @@
#! /usr/bin/env bash
# Usage: ./ci-build.sh VERSION
#
# This script builds the book to HTML with mdbook
# commits and pushes the contents to the repo in the "gh-pages" branch.
#
# It is only inteded for use on the CI!
# Enable strict error checking.
set -exo pipefail
DIR=$(dirname $(readlink -f $0))
MDBOOK="mdbook"
cd $DIR
# Verify version argument.
if [[ -z "$1" ]]; then
echo "Missing required argument 'version': cargo make build-book VERSION"
exit
fi
VERSION="$1"
# Download mdbook if not found.
if [ $MDBOOK -h ]; then
echo "mdbook found..."
else
echo "mdbook not found. Downloading..."
curl -L https://github.com/rust-lang-nursery/mdBook/releases/download/v0.2.0/mdbook-v0.2.0-x86_64-unknown-linux-gnu.tar.gz | tar xzf -
mv ./mdbook /tmp/mdbook
MDBOOK="/tmp/mdbook"
fi
$MDBOOK build
echo $VERSION > ./_rendered/VERSION
rm -rf /tmp/book-content
mv ./_rendered /tmp/book-content
cd $DIR/../..
git clean -fd
git checkout gh-pages
rm -rf $VERSION
mv /tmp/book-content ./$VERSION
git remote set-url --push origin git@github.com:graphql-rust/juniper.git
git config --local user.name "Juniper Bot"
git config --local user.email "juniper@example.com"
git add -A $VERSION
git diff-index --quiet HEAD || git commit -m "Updated book for $VERSION ***NO_CI***"
git push origin gh-pages

View file

@ -1,3 +0,0 @@
/target/
**/*.rs.bk
Cargo.lock

View file

@ -1,26 +0,0 @@
[package]
name = "juniper_book_tests"
version = "0.1.0"
edition = "2018"
authors = ["Magnus Hallin <mhallin@fastmail.com>"]
build = "build.rs"
[dependencies]
juniper = { path = "../../../juniper" }
juniper_iron = { path = "../../../juniper_iron" }
juniper_subscriptions = { path = "../../../juniper_subscriptions" }
derive_more = "0.99"
futures = "0.3"
iron = "0.5"
mount = "0.4"
skeptic = "0.13"
serde_json = "1.0"
tokio = { version = "1", features = ["macros", "rt-multi-thread", "sync"] }
uuid = "0.8"
[build-dependencies]
skeptic = "0.13"
[patch.crates-io]
juniper_codegen = { path = "../../../juniper_codegen" }

View file

@ -1,4 +0,0 @@
fn main() {
let files = skeptic::markdown_files_of_directory("../content/");
skeptic::generate_doc_tests(&files);
}

View file

@ -1,20 +1,20 @@
[package] [package]
name = "actix_subscriptions" name = "example_actix_subscriptions"
version = "0.1.0" version = "0.0.0"
edition = "2018" edition = "2018"
authors = ["Mihai Dinculescu <mihai.dinculescu@outlook.com>"] authors = ["Mihai Dinculescu <mihai.dinculescu@outlook.com>"]
publish = false publish = false
[dependencies] [dependencies]
actix-web = "4.0"
actix-cors = "0.6" actix-cors = "0.6"
futures = "0.3" actix-web = "4.0"
env_logger = "0.9"
serde = "1.0"
serde_json = "1.0"
rand = "0.8"
tokio = "1.0"
async-stream = "0.3" async-stream = "0.3"
env_logger = "0.9"
futures = "0.3"
juniper = { path = "../../juniper", features = ["expose-test-schema"] } juniper = { path = "../../juniper", features = ["expose-test-schema"] }
juniper_actix = { path = "../../juniper_actix", features = ["subscriptions"] } juniper_actix = { path = "../../juniper_actix", features = ["subscriptions"] }
juniper_graphql_ws = { path = "../../juniper_graphql_ws" } juniper_graphql_ws = { path = "../../juniper_graphql_ws" }
rand = "0.8"
serde = "1.0"
serde_json = "1.0"
tokio = "1.0"

View file

@ -1,15 +0,0 @@
[tasks.run]
disabled = true
[tasks.release]
disabled = true
[tasks.release-some]
disabled = true
[tasks.release-local-test]
disabled = true
[tasks.release-some-local-test]
disabled = true
[tasks.release-dry-run]
disabled = true
[tasks.release-some-dry-run]
disabled = true

View file

@ -1 +0,0 @@
target

View file

@ -1,15 +1,14 @@
[package] [package]
name = "basic_subscriptions" name = "example_basic_subscriptions"
version = "0.1.0" version = "0.0.0"
edition = "2018" edition = "2018"
publish = false
authors = ["Jordao Rosario <jordao.rosario01@gmail.com>"] authors = ["Jordao Rosario <jordao.rosario01@gmail.com>"]
publish = false
[dependencies] [dependencies]
futures = "0.3" futures = "0.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
juniper = { path = "../../juniper" } juniper = { path = "../../juniper" }
juniper_subscriptions = { path = "../../juniper_subscriptions" } juniper_subscriptions = { path = "../../juniper_subscriptions" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }

View file

@ -1,15 +0,0 @@
[tasks.run]
disabled = true
[tasks.release]
disabled = true
[tasks.release-some]
disabled = true
[tasks.release-local-test]
disabled = true
[tasks.release-some-local-test]
disabled = true
[tasks.release-dry-run]
disabled = true
[tasks.release-some-dry-run]
disabled = true

View file

@ -1 +0,0 @@
target

View file

@ -1,17 +1,16 @@
[package] [package]
name = "warp_async" name = "example_warp_async"
version = "0.1.0" version = "0.0.0"
edition = "2018" edition = "2018"
publish = false
authors = ["Christoph Herzog <chris@theduke.at>"] authors = ["Christoph Herzog <chris@theduke.at>"]
publish = false
[dependencies] [dependencies]
env_logger = "0.9"
futures = "0.3"
juniper = { path = "../../juniper" } juniper = { path = "../../juniper" }
juniper_warp = { path = "../../juniper_warp" } juniper_warp = { path = "../../juniper_warp" }
log = "0.4"
env_logger = "0.9"
futures = "0.3.1"
log = "0.4.8"
reqwest = { version = "0.11", features = ["rustls-tls"] } reqwest = { version = "0.11", features = ["rustls-tls"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
warp = "0.3" warp = "0.3"

View file

@ -1,15 +0,0 @@
[tasks.run]
disabled = true
[tasks.release]
disabled = true
[tasks.release-some]
disabled = true
[tasks.release-local-test]
disabled = true
[tasks.release-some-local-test]
disabled = true
[tasks.release-dry-run]
disabled = true
[tasks.release-some-dry-run]
disabled = true

View file

@ -1 +0,0 @@
target

View file

@ -1,19 +1,18 @@
[package] [package]
name = "warp_subscriptions" name = "example_warp_subscriptions"
version = "0.1.0" version = "0.0.0"
edition = "2018" edition = "2018"
publish = false publish = false
[dependencies] [dependencies]
async-stream = "0.3"
env_logger = "0.9" env_logger = "0.9"
futures = "0.3.1" futures = "0.3.1"
log = "0.4.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
warp = "0.3"
async-stream = "0.3"
juniper = { path = "../../juniper" } juniper = { path = "../../juniper" }
juniper_graphql_ws = { path = "../../juniper_graphql_ws" } juniper_graphql_ws = { path = "../../juniper_graphql_ws" }
juniper_warp = { path = "../../juniper_warp", features = ["subscriptions"] } juniper_warp = { path = "../../juniper_warp", features = ["subscriptions"] }
log = "0.4.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
warp = "0.3"

View file

@ -1,15 +0,0 @@
[tasks.run]
disabled = true
[tasks.release]
disabled = true
[tasks.release-some]
disabled = true
[tasks.release-local-test]
disabled = true
[tasks.release-some-local-test]
disabled = true
[tasks.release-dry-run]
disabled = true
[tasks.release-some-dry-run]
disabled = true

View file

@ -1,11 +0,0 @@
[package]
name = "async_await"
version = "0.1.0"
edition = "2018"
authors = ["Christoph Herzog <chris@theduke.at>"]
publish = false
[dependencies]
juniper = { path = "../../juniper" }
futures = "0.3.1"
tokio = { version = "1", features = ["rt", "time", "macros"] }

View file

@ -1,167 +0,0 @@
use juniper::{graphql_object, GraphQLEnum};
#[derive(GraphQLEnum)]
enum UserKind {
Admin,
User,
Guest,
}
struct User {
#[allow(dead_code)]
id: i32,
name: String,
kind: UserKind,
}
#[graphql_object]
impl User {
async fn id(&self) -> i32 {
self.id
}
async fn name(&self) -> &str {
&self.name
}
async fn friends(&self) -> Vec<User> {
(0..10)
.map(|index| User {
id: index,
name: format!("user{}", index),
kind: UserKind::User,
})
.collect()
}
async fn kind(&self) -> &UserKind {
&self.kind
}
async fn delayed() -> bool {
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
true
}
}
struct Query;
#[graphql_object]
impl Query {
fn field_sync(&self) -> &'static str {
"field_sync"
}
async fn field_async_plain() -> String {
"field_async_plain".to_string()
}
fn user(id: String) -> User {
User {
id: 1,
name: id,
kind: UserKind::User,
}
}
async fn delayed() -> bool {
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
true
}
}
fn main() {}
#[cfg(test)]
mod tests {
use juniper::{graphql_value, EmptyMutation, EmptySubscription, GraphQLError, RootNode, Value};
use super::Query;
#[tokio::test]
async fn async_simple() {
let schema = RootNode::new(Query, EmptyMutation::new(), EmptySubscription::new());
let doc = r#"query {
fieldSync
fieldAsyncPlain
delayed
user(id: "user1") {
kind
name
delayed
}
}"#;
let vars = Default::default();
let (res, errs) = juniper::execute(doc, None, &schema, &vars, &())
.await
.unwrap();
assert!(errs.is_empty());
let obj = res.into_object().unwrap();
let value = Value::Object(obj);
assert_eq!(
value,
graphql_value!({
"delayed": true,
"fieldAsyncPlain": "field_async_plain",
"fieldSync": "field_sync",
"user": {
"delayed": true,
"kind": "USER",
"name": "user1",
},
}),
);
}
#[tokio::test]
async fn async_field_validation_error() {
let schema = RootNode::new(Query, EmptyMutation::new(), EmptySubscription::new());
let doc = r#"query {
nonExistentField
fieldSync
fieldAsyncPlain
delayed
user(id: "user1") {
kind
name
delayed
}
}"#;
let vars = Default::default();
let result = juniper::execute(doc, None, &schema, &vars, &()).await;
assert!(result.is_err());
let error = result.err().unwrap();
let is_validation_error = match error {
GraphQLError::ValidationError(_) => true,
_ => false,
};
assert!(is_validation_error);
}
// FIXME: test seems broken by design, re-enable later
// #[tokio::test]
// async fn resolve_into_stream_validation_error() {
// let schema = RootNode::new(Query, EmptyMutation::new(), EmptySubscription::new());
// let doc = r#"
// subscription {
// nonExistent
// }
// "#;
// let vars = Default::default();
// let result = juniper::resolve_into_stream(doc, None, &schema, &vars, &()).await;
// assert!(result.is_err());
// let error = result.err().unwrap();
// let is_validation_error = match error {
// GraphQLError::ValidationError(_) => true,
// _ => false,
// };
// assert!(is_validation_error);
// }
}

View file

@ -1,29 +0,0 @@
[tasks.release]
disabled = true
[tasks.release-some]
disabled = true
[tasks.release-local-test]
disabled = true
[tasks.release-some-local-test]
disabled = true
[tasks.release-dry-run]
disabled = true
[tasks.release-some-dry-run]
disabled = true
[tasks.test]
condition = { channels = ["nightly"] }
[tasks.test-custom]
condition = { channels = ["nightly"] }
[tasks.test-flow]
condition = { channels = ["nightly"] }
[tasks.test-multi-flow-phase]
condition = { channels = ["nightly"] }
[tasks.test-thread-safe]
condition = { channels = ["nightly"] }
[tasks.test-verbose]
condition = { channels = ["nightly"] }
[tasks.test-with-args]
condition = { channels = ["nightly"] }
[tasks.ci-coverage-flow]
condition = { channels = ["nightly"] }

View file

@ -1,7 +0,0 @@
error[E0080]: evaluation of constant value failed
--> fail/interface/struct/attr_additional_non_nullable_argument.rs:16:5
|
16 | id: String,
| ^^ the evaluated program panicked at 'Failed to implement interface `Character` on `ObjA`: Field `id`: Argument `isPresent` of type `Boolean!` isn't present on the interface and so has to be nullable.', $DIR/fail/interface/struct/attr_additional_non_nullable_argument.rs:16:5
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,5 +0,0 @@
error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied
--> fail/interface/struct/attr_field_non_output_return_type.rs:10:9
|
10 | id: ObjB,
| ^^^^ the trait `IsOutputType<__S>` is not implemented for `ObjB`

View file

@ -1,7 +0,0 @@
error[E0080]: evaluation of constant value failed
--> fail/interface/struct/attr_missing_field.rs:11:5
|
11 | id: String,
| ^^ the evaluated program panicked at 'Failed to implement interface `Character` on `ObjA`: Field `id` isn't implemented on `ObjA`.', $DIR/fail/interface/struct/attr_missing_field.rs:11:5
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,7 +0,0 @@
error[E0080]: evaluation of constant value failed
--> fail/interface/struct/attr_non_subtype_return.rs:11:5
|
11 | id: String,
| ^^ the evaluated program panicked at 'Failed to implement interface `Character` on `ObjA`: Field `id`: implementor is expected to return a subtype of interface's return object: `[String!]!` is not a subtype of `String!`.', $DIR/fail/interface/struct/attr_non_subtype_return.rs:11:5
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,7 +0,0 @@
error[E0080]: evaluation of constant value failed
--> fail/interface/struct/derive_additional_non_nullable_argument.rs:17:5
|
17 | id: String,
| ^^ the evaluated program panicked at 'Failed to implement interface `Character` on `ObjA`: Field `id`: Argument `isPresent` of type `Boolean!` isn't present on the interface and so has to be nullable.', $DIR/fail/interface/struct/derive_additional_non_nullable_argument.rs:17:5
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,5 +0,0 @@
error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied
--> fail/interface/struct/derive_field_non_output_return_type.rs:10:9
|
10 | id: ObjB,
| ^^^^ the trait `IsOutputType<__S>` is not implemented for `ObjB`

View file

@ -1,7 +0,0 @@
error[E0080]: evaluation of constant value failed
--> fail/interface/struct/derive_missing_field.rs:12:5
|
12 | id: String,
| ^^ the evaluated program panicked at 'Failed to implement interface `Character` on `ObjA`: Field `id` isn't implemented on `ObjA`.', $DIR/fail/interface/struct/derive_missing_field.rs:12:5
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,7 +0,0 @@
error[E0080]: evaluation of constant value failed
--> fail/interface/struct/derive_non_subtype_return.rs:12:5
|
12 | id: String,
| ^^ the evaluated program panicked at 'Failed to implement interface `Character` on `ObjA`: Field `id`: implementor is expected to return a subtype of interface's return object: `[String!]!` is not a subtype of `String!`.', $DIR/fail/interface/struct/derive_non_subtype_return.rs:12:5
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,7 +0,0 @@
error[E0080]: evaluation of constant value failed
--> fail/interface/trait/additional_non_nullable_argument.rs:16:8
|
16 | fn id(&self) -> &str;
| ^^ the evaluated program panicked at 'Failed to implement interface `Character` on `ObjA`: Field `id`: Argument `isPresent` of type `Boolean!` isn't present on the interface and so has to be nullable.', $DIR/fail/interface/trait/additional_non_nullable_argument.rs:16:8
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,5 +0,0 @@
error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied
--> fail/interface/trait/field_non_output_return_type.rs:10:21
|
10 | fn id(&self) -> ObjB;
| ^^^^ the trait `IsOutputType<__S>` is not implemented for `ObjB`

View file

@ -1,7 +0,0 @@
error[E0080]: evaluation of constant value failed
--> fail/interface/trait/missing_field.rs:11:8
|
11 | fn id(&self) -> &str;
| ^^ the evaluated program panicked at 'Failed to implement interface `Character` on `ObjA`: Field `id` isn't implemented on `ObjA`.', $DIR/fail/interface/trait/missing_field.rs:11:8
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,7 +0,0 @@
error[E0080]: evaluation of constant value failed
--> fail/interface/trait/missing_field_argument.rs:16:8
|
16 | fn id(&self, is_present: bool) -> &str;
| ^^ the evaluated program panicked at 'Failed to implement interface `Character` on `ObjA`: Field `id`: Argument `isPresent` of type `Boolean!` was expected, but not found.', $DIR/fail/interface/trait/missing_field_argument.rs:16:8
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,7 +0,0 @@
error[E0080]: evaluation of constant value failed
--> fail/interface/trait/non_subtype_return.rs:11:8
|
11 | fn id(&self) -> &str;
| ^^ the evaluated program panicked at 'Failed to implement interface `Character` on `ObjA`: Field `id`: implementor is expected to return a subtype of interface's return object: `[String!]!` is not a subtype of `String!`.', $DIR/fail/interface/trait/non_subtype_return.rs:11:8
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,7 +0,0 @@
error[E0080]: evaluation of constant value failed
--> fail/interface/trait/wrong_argument_type.rs:16:8
|
16 | fn id(&self, is_present: bool) -> &str;
| ^^ the evaluated program panicked at 'Failed to implement interface `Character` on `ObjA`: Field `id`: Argument `isPresent`: expected type `Boolean!`, found: `Int!`.', $DIR/fail/interface/trait/wrong_argument_type.rs:16:8
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,26 +0,0 @@
error[E0277]: the trait bound `ObjA: IsInputType<__S>` is not satisfied
--> fail/object/argument_non_input_type.rs:12:23
|
12 | fn id(&self, obj: ObjA) -> &str {
| ^^^^ the trait `IsInputType<__S>` is not implemented for `ObjA`
error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied
--> fail/object/argument_non_input_type.rs:10:1
|
10 | #[graphql_object]
| ^^^^^^^^^^^^^^^^^ the trait `FromInputValue<__S>` is not implemented for `ObjA`
|
note: required by a bound in `Registry::<'r, S>::arg`
--> $WORKSPACE/juniper/src/executor/mod.rs
|
| T: GraphQLType<S> + FromInputValue<S>,
| ^^^^^^^^^^^^^^^^^ required by this bound in `Registry::<'r, S>::arg`
= note: this error originates in the attribute macro `graphql_object` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `ObjA: FromInputValue<__S>` is not satisfied
--> fail/object/argument_non_input_type.rs:10:1
|
10 | #[graphql_object]
| ^^^^^^^^^^^^^^^^^ the trait `FromInputValue<__S>` is not implemented for `ObjA`
|
= note: this error originates in the attribute macro `graphql_object` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,5 +0,0 @@
error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied
--> fail/object/attr_field_non_output_return_type.rs:12:21
|
12 | fn id(&self) -> ObjB {
| ^^^^ the trait `IsOutputType<__S>` is not implemented for `ObjB`

View file

@ -1,5 +0,0 @@
error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied
--> fail/object/derive_field_non_output_return_type.rs:10:9
|
10 | id: ObjB,
| ^^^^ the trait `IsOutputType<__S>` is not implemented for `ObjB`

View file

@ -1,5 +0,0 @@
error[E0277]: the trait bound `ObjB: IsOutputType<__S>` is not satisfied
--> fail/subscription/field_non_output_return_type.rs:17:27
|
17 | async fn id(&self) -> Stream<'static, ObjB> {
| ^^^^^^^^^^^^^^^^^^^^^ the trait `IsOutputType<__S>` is not implemented for `ObjB`

View file

@ -1,7 +0,0 @@
error[E0277]: the trait bound `Test: GraphQLObject<__S>` is not satisfied
--> fail/union/enum_non_object_variant.rs:9:10
|
9 | #[derive(GraphQLUnion)]
| ^^^^^^^^^^^^ the trait `GraphQLObject<__S>` is not implemented for `Test`
|
= note: this error originates in the derive macro `GraphQLUnion` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,7 +0,0 @@
error[E0277]: the trait bound `Test: GraphQLObject<__S>` is not satisfied
--> fail/union/struct_non_object_variant.rs:9:10
|
9 | #[derive(GraphQLUnion)]
| ^^^^^^^^^^^^ the trait `GraphQLObject<__S>` is not implemented for `Test`
|
= note: this error originates in the derive macro `GraphQLUnion` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,7 +0,0 @@
error[E0277]: the trait bound `Test: GraphQLObject<__S>` is not satisfied
--> fail/union/trait_non_object_variant.rs:9:1
|
9 | #[graphql_union]
| ^^^^^^^^^^^^^^^^ the trait `GraphQLObject<__S>` is not implemented for `Test`
|
= note: this error originates in the attribute macro `graphql_union` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -1,12 +0,0 @@
[tasks.release]
disabled = true
[tasks.release-some]
disabled = true
[tasks.release-local-test]
disabled = true
[tasks.release-some-local-test]
disabled = true
[tasks.release-dry-run]
disabled = true
[tasks.release-some-dry-run]
disabled = true

View file

@ -1,906 +1,110 @@
# master `juniper` changelog
===================
## Security
All user visible changes to `juniper` crate will be documented in this file. This project uses [Semantic Versioning 2.0.0].
- Fix panic on malformed queries with recursive fragments. *This is a potential denial-of-service attack vector.* Thanks to [@quapka](https://github.com/quapka) for the detailed vulnerability report and reproduction steps.
## Breaking Changes
- Replaced `Visitor` associated type with `DeserializeOwned` requirement in `ScalarValue` trait. ([#985](https://github.com/graphql-rust/juniper/pull/985)) ## master
- Removed `Serialize` implementation from `#[derive(GraphQLScalarValue)]`macro, now should be provided explicitly. ([#985](https://github.com/graphql-rust/juniper/pull/985))
- `#[graphql_object]` and `#[graphql_subscription]` macros expansion now preserves defined `impl` blocks "as is" and reuses defined methods in opaque way. ([#971](https://github.com/graphql-rust/juniper/pull/971)) [Diff](/../../compare/juniper-v0.15.9...master)
- `rename = "<policy>"` attribute's argument renamed to `rename_all = "<policy>"`. ([#971](https://github.com/graphql-rust/juniper/pull/971))
- Upgrade `bson` feature to [2.0 version of its crate](https://github.com/mongodb/bson-rust/releases/tag/v2.0.0). ([#979](https://github.com/graphql-rust/juniper/pull/979)) ### BC Breaks
- Make `FromInputValue` methods fallible to allow post-validation. ([#987](https://github.com/graphql-rust/juniper/pull/987))
- Change `Option` to `Result` in `from_input_value()` return type of `#[graphql_scalar]` macro. ([#987](https://github.com/graphql-rust/juniper/pull/987)) - [October 2021] GraphQL spec: ([#1000])
- Forbid `__typename` field on `subscription` operations [accordingly to October 2021 spec](https://spec.graphql.org/October2021/#note-bc213). ([#1001](https://github.com/graphql-rust/juniper/pull/1001), [#1000](https://github.com/graphql-rust/juniper/pull/1000)) - Forbade [`__typename` field on `subscription` operations](https://spec.graphql.org/October2021#note-bc213). ([#1001])
- Redesign `#[graphql_interface]` macro: ([#1009](https://github.com/graphql-rust/juniper/pull/1009)) - Supported `isRepeatable` field on directives. ([#1003])
- Remove support for `#[graphql_interface(dyn)]` (interface values as trait objects). - Supported `__Schema.description`, `__Type.specifiedByURL` and `__Directive.isRepeatable` fields in introspection. ([#1003])
- Remove support for `downcast` (custom resolution into implementer types). - Supported directives on variables definitions. ([#1005])
- Remove support for `async` trait methods (not required anymore). - Replaced `Visitor` associated type with `DeserializeOwned` requirement in `ScalarValue` trait. ([#985])
- Remove necessity of writing `impl Trait for Type` blocks (interfaces are implemented just by matching its fields). - `#[graphql_object]` and `#[graphql_subscription]` expansions now preserve defined `impl` blocks "as is" and reuse defined methods in opaque way. ([#971])
- Forbid default impls on non-ignored trait methods. - Renamed `rename = "<policy>"` attribute argument to `rename_all = "<policy>"` (following `serde` style). ([#971])
- Support coercion of additional nullable arguments and return sub-typing on implementer. - Upgraded [`bson` crate] integration to [2.0 version](https://github.com/mongodb/bson-rust/releases/tag/v2.0.0). ([#979])
- Redesign `#[derive(GraphQLScalar)]` macro: ([#1017](https://github.com/graphql-rust/juniper/pull/1017)) - Made `FromInputValue` trait methods fallible to allow post-validation. ([#987])
- Support generic scalars. - Redesigned `#[graphql_interface]` macro: ([#1009])
- Support structs with single named field. - Removed support for `dyn` attribute argument (interface values as trait objects).
- Support overriding resolvers. - Removed support for `downcast` attribute argument (custom resolution into implementer types).
- Redesign `#[graphql_scalar]` macro: ([#1014](https://github.com/graphql-rust/juniper/pull/1014)) - Removed support for `async` trait methods (not required anymore).
- Mirror `#[derive(GraphQLScalar)]` macro. - Removed necessity of writing `impl Trait for Type` blocks (interfaces are implemented just by matching their fields now).
- Support usage on type aliases in case `#[derive(GraphQLScalar)]` isn't applicable because of [orphan rules](https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules). - Forbade default implementations of non-ignored trait methods.
- Rename `ScalarValue::as_boolean` to `ScalarValue::as_bool`. ([#1025](https://github.com/graphql-rust/juniper/pull/1025)) - Supported coercion of additional `null`able arguments and return sub-typing on implementer.
- Change [`chrono` crate](https://docs.rs/chrono) GraphQL scalars according to the [graphql-scalars.dev](https://graphql-scalars.dev). ([#1010](https://github.com/graphql-rust/juniper/pull/1010)) - Supported `rename_all = "<policy>"` attribute argument influencing all its fields and their arguments. ([#971])
- Disable `chrono` feature by default. ([#1010](https://github.com/graphql-rust/juniper/pull/1010)) - Split `#[derive(GraphQLScalarValue)]` macro into:
- Remove `scalar-naivetime` feature. ([#1010](https://github.com/graphql-rust/juniper/pull/1010)) - `#[derive(GraphQLScalar)]` for implementing GraphQL scalar: ([#1017])
- Supported generic `ScalarValue`.
## Features - Supported structs with single named field.
- Supported overriding resolvers with external functions, methods or modules.
- Support using Rust array as GraphQL list. ([#966](https://github.com/graphql-rust/juniper/pull/966), [#918](https://github.com/graphql-rust/juniper/issues/918)) - Supported `specified_by_url` attribute argument. ([#1003], [#1000])
- Expose `GraphQLRequest` fields. ([#750](https://github.com/graphql-rust/juniper/issues/750)) - `#[derive(ScalarValue)]` for implementing `ScalarValue` trait: ([#1025])
- `#[graphql_interface]` macro now supports `rename_all = "<policy>"` argument influencing its fields and their arguments. ([#971](https://github.com/graphql-rust/juniper/pull/971)) - Removed `Serialize` implementation (now should be provided explicitly). ([#985])
- Use `null` in addition to `None` to create `Value::Null` in `graphql_value!` macro to mirror `serde_json::json!`. ([#996](https://github.com/graphql-rust/juniper/pull/996)) - Redesigned `#[graphql_scalar]` macro: ([#1014])
- Add `From` impls to `InputValue` mirroring the ones for `Value` and provide better support for `Option` handling. ([#996](https://github.com/graphql-rust/juniper/pull/996)) - Changed `from_input_value()` return type from `Option` to `Result`. ([#987])
- Implement `graphql_input_value!` and `graphql_vars!` macros. ([#996](https://github.com/graphql-rust/juniper/pull/996)) - Mirrored new `#[derive(GraphQLScalar)]` macro.
- Support [`time` crate](https://docs.rs/time) types as GraphQL scalars behind `time` feature. ([#1006](https://github.com/graphql-rust/juniper/pull/1006)) - Supported usage on type aliases in case `#[derive(GraphQLScalar)]` isn't applicable because of [orphan rules].
- Add `specified_by_url` attribute argument to `#[derive(GraphQLScalarValue)]` and `#[graphql_scalar]` macros. ([#1003](https://github.com/graphql-rust/juniper/pull/1003), [#1000](https://github.com/graphql-rust/juniper/pull/1000)) - Renamed `ScalarValue::as_boolean` method to `ScalarValue::as_bool`. ([#1025])
- Support `isRepeatable` field on directives. ([#1003](https://github.com/graphql-rust/juniper/pull/1003), [#1000](https://github.com/graphql-rust/juniper/pull/1000)) - Reworked [`chrono` crate] integration GraphQL scalars according to [graphql-scalars.dev] specs: ([#1010])
- Support `__Schema.description`, `__Type.specifiedByURL` and `__Directive.isRepeatable` fields in introspection. ([#1003](https://github.com/graphql-rust/juniper/pull/1003), [#1000](https://github.com/graphql-rust/juniper/pull/1000)) - Disabled `chrono` [Cargo feature] by default.
- Support directives on variables definitions. ([#1005](https://github.com/graphql-rust/juniper/pull/1005)) - Removed `scalar-naivetime` [Cargo feature].
- Implement `#[derive(ScalarValue)]` macro to derive `ScalarValue` on enums. ([#1025](https://github.com/graphql-rust/juniper/pull/1025))
- Implement `#[derive(GraphQLInterface)]` macro to use structs as GraphQL interfaces. ([#1026](https://github.com/graphql-rust/juniper/pull/1026))
## Fixes
- Allow spreading interface fragments on unions and other interfaces. ([#965](https://github.com/graphql-rust/juniper/pull/965), [#798](https://github.com/graphql-rust/juniper/issues/798))
- Support expressions in `graphql_value!` macro. ([#996](https://github.com/graphql-rust/juniper/pull/996), [#503](https://github.com/graphql-rust/juniper/issues/503))
- List coercion rules: `null` cannot be coerced to an `[Int!]!` or `[Int]!`. ([#1004](https://github.com/graphql-rust/juniper/pull/1004))
# [[0.15.9] 2022-02-02](https://github.com/graphql-rust/juniper/releases/tag/juniper-v0.15.9)
- Fix infinite recursion on malformed queries with nested recursive fragments. *This is a potential denial-of-service attack vector.* Thanks to [@quapka](https://github.com/quapka) for the detailed vulnerability report and reproduction steps.
# [[0.15.8] 2022-01-26](https://github.com/graphql-rust/juniper/releases/tag/juniper-v0.15.8)
- Fix panic on malformed queries with recursive fragments. *This is a potential denial-of-service attack vector.* Thanks to [@quapka](https://github.com/quapka) for the detailed vulnerability report and reproduction steps.
# [[0.15.7] 2021-07-08](https://github.com/graphql-rust/juniper/releases/tag/juniper-v0.15.7)
- Fix panic on spreading untyped union fragments ([#945](https://github.com/graphql-rust/juniper/issues/945))
# [[0.15.6] 2021-06-07](https://github.com/graphql-rust/juniper/releases/tag/juniper-v0.15.6)
- Allow `RootNode::as_schema_language` and `RootNode::as_parser_document` for arbitrary type info ([#935](https://github.com/graphql-rust/juniper/pull/935))
# [[0.15.5] 2021-05-11](https://github.com/graphql-rust/juniper/releases/tag/juniper-v0.15.5)
- Fix multiple fragments on sub types overriding each other ([#927](https://github.com/graphql-rust/juniper/pull/915))
- Fix error extensions in subscriptions ([#927](https://github.com/graphql-rust/juniper/pull/927))
- Fix fields on interfaces not being resolved when used with fragments ([#923](https://github.com/graphql-rust/juniper/pull/923))
# [[0.15.4] 2021-04-03](https://github.com/graphql-rust/juniper/releases/tag/juniper-v0.15.4)
- Un-deprecate select_child, has_child, and child_names methods ([#900](https://github.com/graphql-rust/juniper/pull/#900))
# [[0.15.3] 2021-01-27](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.15.3)
- Compatibility with the latest `syn` ([#861](https://github.com/graphql-rust/juniper/pull/861))
- Fixed a regression in GraphQL Playground ([#856](https://github.com/graphql-rust/juniper/pull/856))
# [[0.15.2] 2021-01-15](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.15.2)
- Update GraphQL Playground to v1.7.27.
- Add marker GraphQL trait implementations for Rust container types like `Box`([#847](https://github.com/graphql-rust/juniper/pull/847))
# [[0.15.1] 2020-12-12](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.15.1)
- Support `Arc` in input and output objects. ([#822](https://github.com/graphql-rust/juniper/pull/822))
# [[0.15.0] 2020-12-09](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.15.0)
## Features
- Added async support. ([#2](https://github.com/graphql-rust/juniper/issues/2))
- `execute()` is now async. Synchronous execution can still be used via `execute_sync()`.
- Field resolvers may optionally be declared as `async` and return a future.
- Added *experimental* support for GraphQL subscriptions. ([#433](https://github.com/graphql-rust/juniper/pull/433))
- Added support for generating the [GraphQL Schema Language](https://graphql.org/learn/schema/#type-language) representation of a schema using `RootNode::as_schema_language()`. ([#676](https://github.com/graphql-rust/juniper/pull/676))
- This is controlled by the `schema-language` feature and is on by default. It may be turned off if you do not need this functionality to reduce dependencies and speed up compile times.
- Note that this is for generating the GraphQL Schema Language representation from the Rust schema. For the opposite--generating a Rust schema from a GraphQL Schema Language file--see the [`juniper_from_schema`](https://github.com/davidpdrsn/juniper-from-schema) project.
- Most GraphQL spec violations are now caught at compile-time. ([#631](https://github.com/graphql-rust/juniper/pull/631))
- The enhanced error messages now include the reason and a link to the spec.
For example, if you try to declare a GraphQL object with no fields:
```rust
error: GraphQL object expects at least one field
--> $DIR/impl_no_fields.rs:4:1
|
4 | impl Object {}
| ^^^^^^^^^^^^^^
|
= note: https://spec.graphql.org/June2018/#sec-Objects
```
- [Raw identifiers](https://doc.rust-lang.org/edition-guide/rust-2018/module-system/raw-identifiers.html) are now supported in field and argument names.
- Most error types now implement `std::error::Error`. ([#419](https://github.com/graphql-rust/juniper/pull/419))
- `GraphQLError`
- `LexerError`
- `ParseError`
- `RuleError`
- Support `chrono-tz::Tz` scalar behind a `chrono-tz` feature flag. ([#519](https://github.com/graphql-rust/juniper/pull/519))
- Added support for distinguishing between between implicit and explicit null. ([#795](https://github.com/graphql-rust/juniper/pull/795))
- Implement `IntoFieldError` for `std::convert::Infallible`. ([#796](https://github.com/graphql-rust/juniper/pull/796))
- Allow using `#[graphql(Scalar = DefaultScalarValue)]` for derive macro `GraphQLScalarValue` ([#807](https://github.com/graphql-rust/juniper/pull/807))
## Fixes
- Massively improved the `#[graphql_union]` proc macro. ([#666](https://github.com/graphql-rust/juniper/pull/666)):
- Applicable to traits.
- Supports custom resolvers.
- Supports generics.
- Supports multiple `#[graphql_union]` attributes.
- Massively improved the `#[derive(GraphQLUnion)]` macro. ([#666](https://github.com/graphql-rust/juniper/pull/666)):
- Applicable to enums and structs.
- Supports custom resolvers.
- Supports generics.
- Supports multiple `#[graphql]` attributes.
- Massively improved the `#[graphql_interface]` macro. ([#682](https://github.com/graphql-rust/juniper/pull/682)):
- Applicable to traits and generates enum or trait object to represent a GraphQL interface (see the [example of migration from `graphql_interface!` macro](https://github.com/graphql-rust/juniper/commit/3472fe6d10d23472752b1a4cd26c6f3da767ae0e#diff-3506bce1e02051ceed41963a86ef59d660ee7d0cd26df1e9c87372918e3b01f0)).
- Supports passing context and executor to a field resolver.
- Supports custom downcast functions and methods.
- Supports generics.
- Supports multiple `#[graphql_interface]` attributes.
- The `GraphQLEnum` derive now supports specifying a custom context. ([#621](https://github.com/graphql-rust/juniper/pull/621))
- Example:
```rust
#[derive(juniper::GraphQLEnum)]
#[graphql(context = CustomContext)]
enum TestEnum {
A,
}
```
- Added support for renaming arguments within a GraphQL object. ([#631](https://github.com/graphql-rust/juniper/pull/631))
- Example:
```rust
#[graphql(arguments(argA(name = "test")))]
```
- `SchemaType` is now public.
- This is helpful when using `context.getSchema()` inside of your field resolvers.
- Improved lookahead visibility for aliased fields. ([#662](https://github.com/graphql-rust/juniper/pull/662))
- When enabled, the optional `bson` integration now requires `bson-1.0.0`. ([#678](https://github.com/graphql-rust/juniper/pull/678))
- Fixed panic on `executor.look_ahead()` for nested fragments ([#500](https://github.com/graphql-rust/juniper/issues/500))
## Breaking Changes
- `GraphQLType` trait was split into 2 traits: ([#685](https://github.com/graphql-rust/juniper/pull/685))
- An object-safe `GraphQLValue` trait containing resolving logic.
- A static `GraphQLType` trait containing GraphQL type information.
- `juniper::graphiql` has moved to `juniper::http::graphiql`.
- `juniper::http::graphiql::graphiql_source()` now requires a second parameter for subscriptions.
- Renamed the `object` proc macro to `graphql_object`.
- Removed the `graphql_object!` macro. Use the `#[graphql_object]` proc macro instead.
- Made `#[graphql_object]` macro to generate code generic over `ScalarValue` by default. ([#779](https://github.com/graphql-rust/juniper/pull/779))
- Renamed the `scalar` proc macro to `graphql_scalar`.
- Removed the `graphql_scalar!` macro. Use the `#[graphql_scalar]` proc macro instead.
- Removed the deprecated `ScalarValue` custom derive. Use `GraphQLScalarValue` instead.
- Removed the `graphql_interface!` macro. Use the `#[graphql_interface]` proc macro instead.
- Removed the `graphql_union!` macro. Use the `#[graphql_union]` proc macro or custom resolvers for the `#[derive(GraphQLUnion)]` instead.
- The `#[derive(GraphQLUnion)]` macro no longer generates `From` impls for enum variants. ([#666](https://github.com/graphql-rust/juniper/pull/666))
- Consider using the [`derive_more`](https//docs.rs/derive_more) crate directly.
- The `ScalarRefValue` trait has been removed as it was not required.
- Prefixing variables or fields with an underscore now matches Rust's behavior. ([#684](https://github.com/graphql-rust/juniper/pull/684))
- The return type of `GraphQLType::resolve()` has been changed to `ExecutionResult`.
- This was done to unify the return type of all resolver methods. The previous `Value` return type was just an internal artifact of
error handling.
- Subscription-related:
- Add subscription type to `RootNode`.
- Add subscription endpoint to `playground_source()`.
- Add subscription endpoint to `graphiql_source()`.
- Specifying a scalar type via a string is no longer supported. ([#631](https://github.com/graphql-rust/juniper/pull/631))
- For example, instead of `#[graphql(scalar = "DefaultScalarValue")]` use `#[graphql(scalar = DefaultScalarValue)]`. *Note the lack of quotes*.
- Integration tests:
- Renamed `http::tests::HTTPIntegration` as `http::tests::HttpIntegration`.
- Added support for `application/graphql` POST request.
- `RootNode::new()` now returns `RootNode` parametrized with `DefaultScalarValue`. For custom `ScalarValue` use `RootNode::new_with_scalar_value()` instead. ([#779](https://github.com/graphql-rust/juniper/pull/779))
- When using `LookAheadMethods` to access child selections, children are always found using their alias if it exists rather than their name. ([#662](https://github.com/graphql-rust/juniper/pull/662))
- These methods are also deprecated in favor of the new `LookAheadMethods::children()` method.
# [[0.14.2] 2019-12-16](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.14.2)
- Fix incorrect validation with non-executed operations [#455](https://github.com/graphql-rust/juniper/issues/455)
- Correctly handle raw identifiers in field and argument names.
# [[0.14.1] 2019-10-24](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.14.1)
- Fix panic when an invalid scalar is used by a client [#434](https://github.com/graphql-rust/juniper/pull/434)
- `EmptyMutation` now implements `Send` [#443](https://github.com/graphql-rust/juniper/pull/443)
# [[0.14.0] 2019-09-29](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.14.0)
- Require `url` 2.x if `url` feature is enabled.
- Improve lookahead visitability.
- Add ability to parse 'subscription'.
# [[0.13.1] 2019-07-29](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.13.1)
- Fix a regression when using lookaheads with fragments containing nested types [#404](https://github.com/graphql-rust/juniper/pull/404)
- Allow `mut` arguments for resolver functions in `#[object]` macros [#402](https://github.com/graphql-rust/juniper/pull/402)
# [[0.13.0] 2019-07-19](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.13.0)
### newtype ScalarValue derive
See [#345](https://github.com/graphql-rust/juniper/pull/345).
The newtype pattern can now be used with the `GraphQLScalarValue` custom derive
to easily implement custom scalar values that just wrap another scalar,
similar to serdes `#[serde(transparent)]` functionality.
Example:
```rust
#[derive(juniper::GraphQLScalarValue)]
struct UserId(i32);
```
### Other Changes
- The `ID` scalar now implements Serde's `Serialize` and `Deserialize`
- Add support for `dyn` trait object syntax to procedural macros
# [[0.12.0] 2019-05-16](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.12.0)
### object macro
The `graphql_object!` macro is deprecated and will be removed in the future.
It is replaced by the new [object](https://docs.rs/juniper/latest/juniper/macro.object.html) procedural macro.
[#333](https://github.com/graphql-rust/juniper/pull/333)
### 2018 Edition
All crates were refactored to the Rust 2018 edition.
This should not have any impact on your code, since juniper already was 2018 compatible.
[#345](https://github.com/graphql-rust/juniper/pull/345)
### Other changes
- The minimum required Rust version is now `1.34.0`.
- The `GraphQLType` impl for () was removed to improve compile time safefty. [#355](https://github.com/graphql-rust/juniper/pull/355)
- The `ScalarValue` custom derive has been renamed to `GraphQLScalarValue`.
- Added built-in support for the canonical schema introspection query via
`juniper::introspect()`.
[#307](https://github.com/graphql-rust/juniper/issues/307)
- Fix introspection query validity
The DirectiveLocation::InlineFragment had an invalid literal value,
which broke third party tools like apollo cli.
- Added GraphQL Playground integration.
The `DirectiveLocation::InlineFragment` had an invalid literal value,
which broke third party tools like apollo cli.
- The return type of `value::object::Object::iter/iter_mut` has changed to `impl Iter`. [#312](https://github.com/graphql-rust/juniper/pull/312)
- Add `GraphQLRequest::operation_name` [#353](https://github.com/graphql-rust/juniper/pull/353)
# [0.11.1] 2018-12-19
## Changes
- The minimum required Rust version is now `1.30`.
- All macros and the custom derives now support the macro system changes properly
and also support Rust 2018 edition crates.
[#298](https://github.com/graphql-rust/juniper/pull/298)
# [0.11.0] 2018-12-17
## Changes
- The minimum required Rust version is now `1.30.0`.
[#271](https://github.com/graphql-rust/juniper/pull/271)
- Juniper is now generic about the exact representation of scalar values. This
allows downstream crates to add support for own scalar value representations.
There are two use cases for this feature:
- You want to support new scalar types not representable by the provided default
scalar value representation like for example `i64`
- You want to support a type from a third party crate that is not supported by juniper
**Note:** This may need some changes in down stream code, especially if working with
generic code. To retain the current behaviour use `DefaultScalarValue` as scalar value type
[#251](https://github.com/graphql-rust/juniper/pull/251)
- The `GraphQLObject` and `GraphQLEnum` derives will mark graphql fields as
`@deprecated` when struct fields or enum variants are marked with the
builtin `#[deprecated]` attribute.
The deprecation reason can be set using the `note = ...` meta item
(e.g. `#[deprecated(note = "Replaced by betterField")]`).
The `since` attribute is ignored.
[#269](https://github.com/graphql-rust/juniper/pull/269)
* There is an alternative syntax for setting a field's _description_ and
_deprecation reason_ in the `graphql_object!` and `graphql_interface!` macros.
To **deprecate** a graphql field:
```rust
// Original syntax for setting deprecation reason
field deprecated "Reason" my_field() -> { ... }
// New alternative syntax for deprecation reason.
#[deprecated(note = "Reason")]
field my_field() -> { ... }
// You can now also deprecate without a reason.
#[deprecated]
field my_field() -> { ... }
```
To set the **description** of a graphql field:
```rust
// Original syntax for field descriptions
field my_field() as "Description" -> { ... }
// Original syntax for argument descriptions
field my_field(
floops: i32 as "The number of starfish to be returned. \
Can't be more than 100.",
) -> {
...
}
// New alternative syntax for field descriptions
/// Description
field my_field() -> { ... }
// New alternative syntax for argument descriptions
field my_field(
/// The number of starfish to be returned.
/// Can't be more than 100.
arg: i32,
) -> {
...
}
// You can also use raw strings and const &'static str.
//
// Multiple docstrings will be collapsed into a single
// description separated by newlines.
/// This is my field.
///
/// Make sure not to filtz the bitlet.
/// Flitzing without a bitlet has undefined behaviour.
///
#[doc = my_consts::ADDED_IN_VERSION_XYZ]
field my_field() -> { ... }
```
[#269](https://github.com/graphql-rust/juniper/pull/269)
# [0.10.0] 2018-09-13
## Changes
- Changed serialization of `NaiveDate` when using the optional `chronos` support.
**Note:** while this is not a Rust breaking change, if you relied on the serialization format (perhaps by storing serialized data in a database or making asumptions in your client code written in another language) it could be a breaking change for your application.
[#151](https://github.com/graphql-rust/juniper/pull/151)
- The `GraphQLObject`, `GraphQLInputObject`, and `GraphQLEnum` custom derives will reject
invalid [names](http://facebook.github.io/graphql/October2016/#Name) at compile time.
[#170](https://github.com/graphql-rust/juniper/pull/170)
- Large integers (> signed 32bit) are now deserialized as floats. Previously,
they produced an "integer out of range" error. For languages that do not
have a distinction between integer and floating point types (such as
javascript), this meant large whole floating point values could not be
decoded (because they were represented without a fractional value such as `.0`).
[#179](https://github.com/graphql-rust/juniper/pull/179)
- The `GraphQLObject`, `GraphQLInputObject`, and `GraphQLEnum` custom derives
now parse doc strings and use them as descriptions. This behavior can be
overridden by using an explicit GraphQL `description` annotation such as
`#[graphql(description = "my description")]`. [View documentation](https://graphql-rust.github.io/types/objects/defining_objects.html#defining-objects).
[#194](https://github.com/graphql-rust/juniper/issues/194)
- Introduced `IntoFieldError` trait to allow custom error handling
i.e. custom result type. The error type must implement this trait resolving
the errors into `FieldError`. [View documentation](https://graphql-rust.github.io/types/objects/error_handling.html#structured-errors).
[#40](https://github.com/graphql-rust/juniper/issues/40)
- `GraphQLType` and `ToInputValue` are now implemented for Arc<T>
[#212](https://github.com/graphql-rust/juniper/pull/212)
- Error responses no longer have a _data_ field, instead, error details are stored in the _extensions_ field
**Note:** while this is a breaking change, it is a necessary one to better align with the latest [GraphQL June 2018](https://facebook.github.io/graphql/June2018/#sec-Errors) specification, which defines the reserved _extensions_ field for error details. [View documentation](https://graphql-rust.github.io/types/objects/error_handling.html#structured-errors).
[#219](https://github.com/graphql-rust/juniper/pull/219)
* The `GraphQLObject` and `GraphQLInputObject` custom derives
now support lifetime annotations.
[#225](https://github.com/graphql-rust/juniper/issues/225)
* When using the `GraphQLObject` custom derive, fields can now be omitted by annotating the field with `#[graphql(skip)]`. [View documentation](https://graphql-rust.github.io/types/objects/defining_objects.html#skipping-fields).
[#220](https://github.com/graphql-rust/juniper/issues/220)
* Due to newer dependencies, the oldest Rust version supported is now 1.22.0
[#231](https://github.com/graphql-rust/juniper/pull/231)
# [0.9.2] 2018-01-13
## Changes
### `__typename` for unions
The [`__typename`](http://graphql.org/learn/queries/#meta-fields) query meta-field now works on unions.
[#112](https://github.com/graphql-rust/juniper/issues/112)
### Debug impls.
http::GraphQLRequest now implements `Debug`.
# [0.9.0] 2017-12-03
## Changes
This is the first release in a long time.
Quite a few changes have accumulated since `0.8.1`, including multiple breaking
changes.
### Custom derive & macros
Juniper has gained custom derive implementations for input objects, objects and
enums.
- `#[derive(GraphQLInputObject)]`
- `#[derive(GraphQLEnum)]`
- `#[derive(GraphQLObject)]`
The `graphql_enum!` and `graphql_input_object!` macros did not provide any more
benefits, so they have been removed!
All functionality is now covered by custom derive.
Check the [docs](https://graphql-rust.github.io) to find out more.
### Web framework integrations - Iron & Rocket
The iron and rocket integrations were removed from the main crate, and are now
available via the [juniper_iron](https://crates.io/crates/juniper_iron) and
[juniper_rocket](https://crates.io/crates/juniper_rocket) crates.
### FieldError rewrite (custom data)
The `FieldError` type now supports custom data with the `Value` type from
serde_json. Use this to populate the `data` field in returned errors.
This also means that try! and `?` now work in resolvers, which is quite nice.
Also, the `ResultExt` extension and the `jtry!` macro were removed, since they
are redundant now!
### Dynamic Schemas
Juniper has gained support for dynamic schemas, thanks to @srijs.
That also means the type of `RootNode` has changed to include a lifetime.
The repository was restructured to a multi crate workspace to enable several new
features like custom_derive and an extracted parser.
#[#66](https://github.com/graphql-rust/juniper/pull/66)
### Data Type Integrations
Integrations with multiple popular crates was added to make working with them
easier.
- uuid
- url
- chrono
### Field Order
To better comply with the specification, order of requested fields is
now preserved.
[#82](https://github.com/graphql-rust/juniper/issues/82
### From/ToInputValue
The `::from` and `::to` methods in `From/ToInputValue` were renamed to
`from/to_input_value()` to not conflict with other methods.
[#90](https://github.com/graphql-rust/juniper/pull/90)
### Other changes
- Several small performance improvements
- Use [fnv](https://github.com/servo/rust-fnv) hash map for better performance
## Contributors
A big shoutout to the many contributors for this version, sorted alphabetically.
- Cameron Eldridge <mailto:cameldridge+git@gmail.com>
- Christian Legnitto <mailto:christian@legnitto.com>
- Jacob Haslehurst <mailto:jacob@haslehurst.net>
- Jane Keibler <mailto:wanderingelf14@gmail.com>
- Magnus Hallin <mailto:mhallin@fastmail.com>
- rushmorem <mailto:rushmore@webenchanter.com>
- Rushmore Mushambi <mailto:rushmore@webenchanter.com>
- Sagie Gur-Ari <mailto:sagiegurari@gmail.com>
- Sam Rijs <mailto:srijs@airpost.net>
- Stanko Krtalić <mailto:stanko.krtalic@gmail.com>
- theduke <mailto:chris@theduke.at>
- thomas-jeepe <mailto:penguinSoccer@outlook.com>
# [0.8.1] 2017-06-15
Tiny release to fix broken crate metadata on crates.io.
# [0.8.0] 2017-06-15
## Breaking changes
- To better comply with the specification, and to avoid weird bugs with very
large positive or negative integers, support for `i64` has been completely
dropped and replaced with `i32`. `i64` is no longer a valid GraphQL type in
Juniper, and `InputValue`/`Value` can only represent 32 bit integers.
If an incoming integer is out of range for a 32 bit signed integer type, an
error will be returned to the client.
([#52](https://github.com/graphql-rust/juniper/issues/52),
[#49](https://github.com/graphql-rust/juniper/issues/49))
- Serde has been updated to 1.0. If your application depends on an older
version, you will need to first update your application before you can upgrade
to a more recent Juniper. ([#43](https://github.com/graphql-rust/juniper/pull/43))
- `rustc_serialize` support has been dropped since this library is now
deprecated. ([#51](https://github.com/graphql-rust/juniper/pull/51))
## New features
- A new `rocket-handlers` feature now includes some tools to use the
[Rocket](https://rocket.rs) framework. [A simple
example](juniper_rocket/examples/rocket-server.rs) has been added to the examples folder.
## Bugfixes
- A panic in the parser has been replaced with a proper error
([#44](https://github.com/graphql-rust/juniper/pull/44))
# [0.7.0] 2017-02-26
### Breaking changes
- The `iron-handlers` feature now depends on Iron 0.5
([#30](https://github.com/graphql-rust/juniper/pull/30)). Because of
this, support for Rust 1.12 has been dropped. It might still work if
you're not using the Iron integrations feature, however.
### New features
- Input objects defined by the `graphql_input_object!` can now be used
as default values to field arguments and other input object fields.
# [0.6.3] 2017-02-19
### New features
- Add support for default values on input object fields
([#28](https://github.com/graphql-rust/juniper/issues/28))
# [0.6.2] 2017-02-05
### New features
- The `null` literal is now supported in the GraphQL
language. ([#26](https://github.com/graphql-rust/juniper/pull/26))
- Rustc-serialize is now optional, but enabled by default. If you
_only_ want Serde support, include Juniper without default features
and enable
Serde. ([#12](https://github.com/graphql-rust/juniper/pull/12))
- The built-in `ID` type now has a public constructor and derives a
few traits (`Clone`, `Debug`, `Eq`, `PartialEq`, `From<String>`,
`Deref<Target=str>`). ([#19](https://github.com/graphql-rust/juniper/pull/19))
- Juniper is now built and tested against all Rust compilers since
version 1.12.1.
### Minor breaking change
- Serde has been updated to
0.9. ([#25](https://github.com/graphql-rust/juniper/pull/25))
### Bugfixes
- The built-in GraphiQL handler had a bug in variable serialization.
([#16](https://github.com/graphql-rust/juniper/pull/16))
- The example should now build and run without problems on
Windows. ([#15](https://github.com/graphql-rust/juniper/pull/15))
- Object types now properly implement
`__typename`. ([#22](https://github.com/graphql-rust/juniper/pull/22))
- String variables are now properly parsed into GraphQL
enums. ([#17](https://github.com/graphql-rust/juniper/pull/17))
# [0.6.1] 2017-01-06
### New features
- Optional Serde support
([#8](https://github.com/graphql-rust/juniper/pull/8))
### Improvements
- The `graphql_input_object!` macro can now be used to define input
objects as public Rust structs.
- GraphiQL in the Iron GraphiQL handler has been updated to 0.8.1
(#[#11](https://github.com/graphql-rust/juniper/pull/11))
### Minor breaking changes
Some undocumented but public APIs were changed.
- `to_snake_case` correctly renamed to `to_camel_case`
([#9](https://github.com/graphql-rust/juniper/pull/9))
- JSON serialization of `GraphQLError` changed to be more consistent
with how other values were serialized
([#10](https://github.com/graphql-rust/juniper/pull/10)).
# [0.6.0] 2017-01-02
TL;DR: Many big changes in how context types work and how they
interact with the executor. Not too much to worry about if you're only
using the macros and not deriving `GraphQLType` directly.
### Breaking changes
- The `executor` argument in all resolver methods is now
immutable. The executor instead uses interior mutability to store
errors in a thread-safe manner.
This change could open up for asynchronous or multi-threaded
execution: you can today use something like rayon in your resolve
methods to let child nodes be concurrently resolved.
**How to fix:** All field resolvers that looked like `field name(&mut executor` now should say `field name(&executor`.
- The context type of `GraphQLType` is moved to an associated type;
meaning it's no longer generic. This only affects people who
implement the trait manually, _not_ macro users.
This greatly simplifies a lot of code by ensuring that there only
can be one `GraphQLType` implementation for any given Rust
type. However, it has the downside that support for generic contexts
previously used in scalars, has been removed. Instead, use the new
context conversion features to accomplish the same task.
**How to fix:** Instead of `impl GraphQLType<MyContext> for ...`,
you use `impl GraphQLType for ... { type Context = MyContext;`.
- All context types must derive the `Context` marker trait. This is
part of an overarching change to allow different types to use
different contexts.
**How to fix:** If you have written e.g. `graphql_object!(MyType: MyContext ...)` you will need to add `impl Context for MyContext {}`. Simple as that.
- `Registry` and all meta type structs now takes one lifetime
parameter, which affects `GraphQLType`'s `meta` method. This only
affects people who implement the trait manually.
**How to fix:** Change the type signature of `meta()` to read `fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r>`.
- The type builder methods on `Registry` no longer return functions
taking types or fields. Due to how the borrow checker works with
expressions, you will have to split up the instantiation into two
statements. This only affects people who implement the `GraphQLType`
trait manually.
**How to fix:** Change the contents of your `meta()` methods to
something like this:
```rust
fn meta<'r>(registry: &mut Registry<r>) -> MetaType<'r> {
let fields = &[ /* your fields ... */ ];
registry.build_object_type::<Self>(fields).into_meta()
}
```
### Added ### Added
- Support for different contexts for different types. As GraphQL - Usage of Rust arrays as GraphQL lists. ([#966], [#918])
schemas tend to get large, narrowing down the context type to - `From` implementations for `InputValue` mirroring the ones for `Value` and better support for `Option` handling. ([#996])
exactly what a given type needs is great for - `null` in addition to `None` for creating `Value::Null` in `graphql_value!` macro (following `serde_json::json!` style). ([#996])
encapsulation. Similarly, letting different subsystems use different - `graphql_input_value!` and `graphql_vars!` macros. ([#996])
resources thorugh the context is also useful for the same reasons. - [`time` crate] integration behind `time` [Cargo feature]. ([#1006])
- `#[derive(GraphQLInterface)]` macro allowing using structs as GraphQL interfaces. ([#1026])
Juniper supports two different methods of doing this, depending on ### Changed
your needs: if you have two contexts where one can be converted into
the other _without any extra knowledge_, you can implement the new
`FromContext` trait. This is useful if you have multiple crates or
modules that all belong to the same GraphQL schema:
```rust - Made `GraphQLRequest` fields public. ([#750])
struct TopContext {
db: DatabaseConnection,
session: WebSession,
current_user: User,
}
struct ModuleOneContext { ## Fixed
db: DatabaseConnection, // This module only requires a database connection
}
impl Context for TopContext {} - Unsupported spreading GraphQL interface fragments on unions and other interfaces. ([#965], [#798])
impl Context for ModuleOneContext {} - Unsupported expressions in `graphql_value!` macro. ([#996], [#503])
- Incorrect GraphQL list coercion rules: `null` cannot be coerced to an `[Int!]!` or `[Int]!`. ([#1004])
impl FromContext<TopContext> for ModuleOneContext { [#503]: /../../issues/503
fn from(ctx: &TopContext) -> ModuleOneContext { [#750]: /../../issues/750
ModuleOneContext { [#798]: /../../issues/798
db: ctx.db.clone() [#918]: /../../issues/918
} [#965]: /../../pull/965
} [#966]: /../../pull/966
} [#971]: /../../pull/971
[#979]: /../../pull/979
[#985]: /../../pull/985
[#987]: /../../pull/987
[#996]: /../../pull/996
[#1000]: /../../issues/1000
[#1001]: /../../pull/1001
[#1003]: /../../pull/1003
[#1004]: /../../pull/1004
[#1005]: /../../pull/1005
[#1006]: /../../pull/1006
[#1009]: /../../pull/1009
[#1010]: /../../pull/1010
[#1014]: /../../pull/1014
[#1017]: /../../pull/1017
[#1025]: /../../pull/1025
[#1026]: /../../pull/1026
graphql_object!(Query: TopContext |&self| {
field item(&executor) -> Item {
executor.context().db.get_item()
}
});
// The `Item` type uses another context type - conversion is automatic
graphql_object!(Item: ModuleOneContext |&self| {
// ...
});
```
The other way is to manually perform the conversion in a field
resolver. This method is preferred when the child context needs
extra knowledge than what exists in the parent context:
```rust ## Previous releases
// Each entity has its own context
struct TopContext {
entities: HashMap<i32, EntityContext>,
db: DatabaseConnection,
}
struct EntityContext { See [old CHANGELOG](/../../blob/juniper-v0.15.9/juniper/CHANGELOG.md).
// fields
}
impl Context for TopContext {}
impl Context for EntityContext {}
graphql_object!(Query: TopContext |&self| {
// By returning a tuple (&Context, GraphQLType), you can tell the executor
// to switch out the context for the returned value. You can wrap the
// tuple in Option<>, FieldResult<>, FieldResult<Option<>>, or just return
// the tuple without wrapping it.
field entity(&executor, key: i32) -> Option<(&EntityContext, Entity)> {
executor.context().entities.get(&key)
.map(|ctx| (ctx, executor.context().db.get_entity(key)))
}
});
graphql_object!(Entity: EntityContext |&self| {
// ...
});
```
### Improvements [`bson` crate]: https://docs.rs/bson
[`chrono` crate]: https://docs.rs/chrono
- Parser and query execution has now reduced the allocation overhead [`time` crate]: https://docs.rs/time
by reusing as much as possible from the query source and meta type [Cargo feature]: https://doc.rust-lang.org/cargo/reference/features.html
information. [graphql-scalars.dev]: https://graphql-scalars.dev
[October 2021]: https://spec.graphql.org/October2021
# [0.5.3] 2016-12-05 [orphan rules]: https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
[Semantic Versioning 2.0.0]: https://semver.org
### Added
- `jtry!`: Helper macro to produce `FieldResult`s from regular
`Result`s. Wherever you would be using `try!` in a regular function
or method, you can use `jtry!` in a field resolver:
```rust
graphql_object(MyType: Database |&self| {
field count(&executor) -> FieldResult<i32> {
let txn = jtry!(executor.context().transaction());
let count = jtry!(txn.execute("SELECT COUNT(*) FROM user"));
Ok(count[0][0])
}
});
```
### Changes
- Relax context type trait requirements for the iron handler: your
contexts no longer have to be `Send + Sync`.
- `RootNode` is now `Send` and `Sync` if both the mutation and query
types implement `Send` and `Sync`.
### Bugfixes
- `return` statements inside field resolvers no longer cause syntax
errors.
## 0.5.2 2016-11-13
### Added
- Support for marking fields and enum values deprecated.
- `input_object!` helper macro
### Changes
- The included example server now uses the simple Star Wars schema
used in query/introspection tests.
### Bugfixes
- The query validators - particularly ones concerned with validation
of input data and variables - have been improved significantly. A
large number of test cases have been added.
- Macro syntax stability has also been improved. All syntactical edge
cases of the macros have gotten tests to verify their correctness.
[0.8.1]: https://github.com/graphql-rust/juniper/compare/0.8.0...0.8.1
[0.8.0]: https://github.com/graphql-rust/juniper/compare/0.7.0...0.8.0
[0.7.0]: https://github.com/graphql-rust/juniper/compare/0.6.3...0.7.0
[0.6.3]: https://github.com/graphql-rust/juniper/compare/0.6.2...0.6.3
[0.6.2]: https://github.com/graphql-rust/juniper/compare/0.6.1...0.6.2
[0.6.1]: https://github.com/graphql-rust/juniper/compare/0.6.0...0.6.1
[0.6.0]: https://github.com/graphql-rust/juniper/compare/0.5.3...0.6.0
[0.5.3]: https://github.com/graphql-rust/juniper/compare/0.5.2...0.5.3

View file

@ -1,22 +1,27 @@
[package] [package]
name = "juniper" name = "juniper"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2018"
description = "GraphQL server library."
license = "BSD-2-Clause"
authors = [ authors = [
"Magnus Hallin <mhallin@fastmail.com>", "Magnus Hallin <mhallin@fastmail.com>",
"Christoph Herzog <chris@theduke.at>", "Christoph Herzog <chris@theduke.at>",
"Christian Legnitto <christian@legnitto.com>", "Christian Legnitto <christian@legnitto.com>",
"Ilya Solovyiov <ilya.solovyiov@gmail.com>",
"Kai Ren <tyranron@gmail.com>",
] ]
description = "GraphQL server library"
license = "BSD-2-Clause"
documentation = "https://docs.rs/juniper" documentation = "https://docs.rs/juniper"
homepage = "https://graphql-rust.github.io"
repository = "https://github.com/graphql-rust/juniper" repository = "https://github.com/graphql-rust/juniper"
readme = "../README.md" readme = "README.md"
keywords = ["graphql", "server", "web", "rocket"] categories = ["asynchronous", "web-programming", "web-programming::http-server"]
categories = ["web-programming"] keywords = ["apollo", "graphql", "server", "web"]
edition = "2018" exclude = ["/release.toml"]
[badges] [package.metadata.docs.rs]
travis-ci = { repository = "graphql-rust/juniper" } all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[features] [features]
default = [ default = [
@ -27,22 +32,20 @@ default = [
] ]
chrono-clock = ["chrono", "chrono/clock"] chrono-clock = ["chrono", "chrono/clock"]
expose-test-schema = ["anyhow", "serde_json"] expose-test-schema = ["anyhow", "serde_json"]
graphql-parser-integration = ["graphql-parser"] schema-language = ["graphql-parser"]
schema-language = ["graphql-parser-integration"]
[dependencies] [dependencies]
juniper_codegen = { version = "0.16.0-dev", path = "../juniper_codegen" } anyhow = { version = "1.0.32", default-features = false, optional = true }
anyhow = { version = "1.0.32", optional = true, default-features = false }
async-trait = "0.1.39" async-trait = "0.1.39"
bson = { version = "2.0", features = ["chrono-0_4"], optional = true } bson = { version = "2.0", features = ["chrono-0_4"], optional = true }
chrono = { version = "0.4", default-features = false, optional = true } chrono = { version = "0.4", features = ["alloc"], default-features = false, optional = true }
chrono-tz = { version = "0.6", default-features = false, optional = true } chrono-tz = { version = "0.6", default-features = false, optional = true }
fnv = "1.0.3" fnv = "1.0.3"
futures = { version = "0.3.1", features = ["alloc"], default-features = false } futures = { version = "0.3.1", features = ["alloc"], default-features = false }
futures-enum = { version = "0.1.12", default-features = false } futures-enum = { version = "0.1.12", default-features = false }
graphql-parser = { version = "0.4", optional = true } graphql-parser = { version = "0.4", optional = true }
indexmap = { version = "1.0", features = ["serde-1"] } indexmap = { version = "1.0", features = ["serde-1"] }
juniper_codegen = { version = "0.16.0-dev", path = "../juniper_codegen" }
serde = { version = "1.0.8", features = ["derive"], default-features = false } serde = { version = "1.0.8", features = ["derive"], default-features = false }
serde_json = { version = "1.0.2", default-features = false, optional = true } serde_json = { version = "1.0.2", default-features = false, optional = true }
smartstring = "1.0" smartstring = "1.0"
@ -61,7 +64,7 @@ uuid = { version = "0.8", default-features = false, features = ["wasm-bindgen"],
bencher = "0.1.2" bencher = "0.1.2"
pretty_assertions = "1.0.0" pretty_assertions = "1.0.0"
serde_json = "1.0.2" serde_json = "1.0.2"
tokio = { version = "1", features = ["macros", "time", "rt-multi-thread"] } tokio = { version = "1.0", features = ["macros", "time", "rt-multi-thread"] }
[[bench]] [[bench]]
name = "bench" name = "bench"

Some files were not shown because too many files have changed in this diff Show more