[FREE PDF sample] Craft graphql apis in elixir with absinthe flexible robust services for queries mu

Page 1


and Subscriptions 1st Edition Bruce Williams

Visit to download the full and correct content document: https://textbookfull.com/product/craft-graphql-apis-in-elixir-with-absinthe-flexible-robus t-services-for-queries-mutations-and-subscriptions-1st-edition-bruce-williams/

More products digital (pdf, epub, mobi) instant download maybe you interests ...

Testing Elixir Effective and Robust Testing for Elixir and its Ecosystem 1st Edition Andrea Leopardi Jeffrey Matthias

https://textbookfull.com/product/testing-elixir-effective-androbust-testing-for-elixir-and-its-ecosystem-1st-edition-andrealeopardi-jeffrey-matthias/

Design and Build Great Web APIs Robust Reliable and Resilient 1st Edition Mike Amundsen

https://textbookfull.com/product/design-and-build-great-web-apisrobust-reliable-and-resilient-1st-edition-mike-amundsen/

ChatGPT for Java: A Hands-on Developer's Guide to ChatGPT and Open AI APIs 1st Edition Bruce Hopkins

https://textbookfull.com/product/chatgpt-for-java-a-hands-ondevelopers-guide-to-chatgpt-and-open-ai-apis-1st-edition-brucehopkins/

ChatGPT for Java: A Hands-on Developer’s Guide to ChatGPT and Open AI APIs 1st Edition Bruce Hopkins

https://textbookfull.com/product/chatgpt-for-java-a-hands-ondevelopers-guide-to-chatgpt-and-open-ai-apis-1st-edition-brucehopkins-2/

PHP Web Services APIs for the Modern Web 2nd Edition

https://textbookfull.com/product/php-web-services-apis-for-themodern-web-2nd-edition-lorna-jane-mitchell/

Fullstack GraphQL The Complete Guide to Writing GraphQL Servers and Clients with TypeScript Gaetano Checinskil

https://textbookfull.com/product/fullstack-graphql-the-completeguide-to-writing-graphql-servers-and-clients-with-typescriptgaetano-checinskil/

Stable Mutations for Evolutionary Algorithms Andrzej Obuchowicz

https://textbookfull.com/product/stable-mutations-forevolutionary-algorithms-andrzej-obuchowicz/

Beginning GraphQL with React NodeJS and Apollo Greg Lim

https://textbookfull.com/product/beginning-graphql-with-reactnodejs-and-apollo-greg-lim/

Absinthe 1st Edition Betina J. Wittels

https://textbookfull.com/product/absinthe-1st-edition-betina-jwittels/

Early Praise for Craft GraphQL APIs in Elixir with Absinthe

Like GraphQL’s meteoric rise, this book is sure to be a breakout hit for readers looking to revolutionize the way they write APIs. Ben and Bruce combine their Absinthe expertise with their production experience to take readers from the basics of GraphQL to exercising its most powerful features with Elixir and Phoenix.

➤ Chris McCord Author, Phoenix framework

If we’re lucky, about once per decade or so we’ll come across a technology that has the chance to revolutionize the Web. GraphQL is one such set of technologies. This book is written by two of the industry’s experts co-authors of one of the best and most complete GraphQL implementations. Even if you’re not planning to deploy on Elixir, this book will show you GraphQL done right.

➤ Chad Fowler Microsoft and BlueYard Capital

Absinthe single-handedly made one of the most critical and complex parts of Trailpost’s infrastructure the piece I worry about least. This book should be on the radar of anyone developing APIs in Elixir, and probably some who aren’t.

➤ Daniel Pehrson Founder, Trailpost.com

GraphQL is a broad but rewarding topic, and Bruce and Ben have covered it comprehensively. The book introduces the key GraphQL concepts in a very approachable way. It then makes sure you have all the tools and techniques to build robust, well-structured, and incredibly fast GraphQL APIs using Elixir, Absinthe, Ecto, and Phoenix. A killer combination for building amazing applications if ever there was one!

➤ Josh Price

GraphQL is a game changer, and now you can use it with Elixir! This book is an invaluable must-read for any Elixir developer. I referred to it often as I helped prepare our web team for the next generation of APIs.

➤ Daniel Berkompas

Senior Software Engineer, Infinite Red; Creator of LearnElixir.tv & LearnPhoenix.tv

Craft GraphQL APIs in Elixir with Absinthe

Flexible, Robust Services for Queries, Mutations, and Subscriptions

Bruce Williams

Ben Wilson

The Pragmatic Bookshelf

Raleigh, North Carolina

Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and The Pragmatic Programmers, LLC was aware of a trademark claim, the designations have been printed in initial capital letters or in all capitals. The Pragmatic Starter Kit, The Pragmatic Programmer, Pragmatic Programming, Pragmatic Bookshelf, PragProg and the linking g device are trademarks of The Pragmatic Programmers, LLC.

Every precaution was taken in the preparation of this book. However, the publisher assumes no responsibility for errors or omissions, or for damages that may result from the use of information (including program listings) contained herein.

Our Pragmatic books, screencasts, and audio books can help you and your team create better software and have more fun. Visit us at https://pragprog.com

The team that produced this book includes:

Publisher: Andy Hunt

VP of Operations: Janet Furlow

Managing Editor: Brian MacDonald

Supervising Editor: Jacquelyn Carter

Series Editor: Bruce A. Tate

Copy Editor: Nicole Abramowitz

Indexing: Potomac Indexing, LLC

Layout: Gilson Graphics

For sales, volume licensing, and support, please contact support@pragprog.com.

For international rights, please contact rights@pragprog.com

Copyright © 2018 The Pragmatic Programmers, LLC. All rights reserved.

No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form, or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior consent of the publisher.

Printed in the United States of America.

ISBN-13: 978-1-68050-255-8

Encoded using the finest acid-free high-entropy binary digits.

Book version: P1.0 March 2018

Acknowledgements

We’d like to thank our editor, Jackie Carter, and the rest of the staff at The Pragmatic Bookshelf for their guidance and assistance turning this book into a reality. While it’s a cliché, writing a book is hard work…and it would have been immeasurably more difficult without your help. Likewise, a small army of technical reviewers Andrea Leopardi, Brian O’Grady, Chad Wooley, Chengyin Liu, Gabor Hajba, Jack Marchant, James Fish, Jesse Cooke, Kim Shieir, Lou Xun, Mark Goody, Nate Vick, Paulo A. Pereira, Rodrigo Franco, and Sebastian Kosch helped us improve the content and code in this book. Any remaining issues fall squarely and solely on our shoulders.

Bruce would like to thank his wife, Melissa, and their three sons Braedyn, Jamis, and Cole without whose love, support, and deep, abiding well of patience, no book would be worth writing (or would get done in the first place).

He’d also like to thank Maria Gutierrez, a dear friend who he’ll eventually forgive for the gentle nudge that convinced him to invest the time to write another book.

Ben is grateful to his colleagues, friends, and family for their seemingly endless willingness to listen, offer advice, and humor the most insane ideas throughout this process. In particular, Ben wants to thank his wife, Becca, whose constant care and dedication to those around her serves as both an inspiration and a daily joy.

Finally, we’d like to show our appreciation for those who have contributed to Absinthe, the project this book covers.

We deeply appreciate the time and encouragement given to us by José Valim and Chris McCord as the Absinthe project has grown. Their answers to hard questions and warnings about pitfalls, their open minds and imaginations, have made all the difference between the project becoming a fun yet subtly broken toy, and a robust, useful tool for the Elixir/Phoenix community they lead.

Acknowledgements

In the same vein, we’d like to thank the dozens of contributors to Absinthe’s many packages. Absinthe is an ambitious project. Like many ambitious projects, it started out as a crazy dream and as it turns out, it found plenty of crazy-smart, friendly people to share it...and make it so much better. Thank you!

Introduction

GraphQL is an exciting newcomer to the world of web service protocols. It arrived on the scene at exactly the right time for us, struggling as we were with a complicated, inflexible REST API that was wearing a little of the shine off our fancy new Elixir application in production.

We decided to give GraphQL a try.

Little did we know that along the way, we’d discover an approach to building APIs and collaborating across the backend/front-end divide that was more flexible, maintainable, and fun for our team.

We wrote Absinthe, the GraphQL toolkit for Elixir, because we thought GraphQL might be a good fit for our problem, our development process, and our platform. Since that time, a community has grown up around the project. We wrote this book because we think that it might just be a good fit for yours, too.

It’s certainly a great fit for Elixir!

About This Book

This book is organized into three parts.

Part I introduces you to the core concepts behind GraphQL, then guides you through building a GraphQL API in Elixir. You’ll learn about queries, mutations, and subscriptions, and end up with a functional example by the time you’re through.

Part II addresses the most common security, maintainability, and performance questions that people have about GraphQL in production, focusing on building real-world solutions that turn naive implementations into rock-solid, scalable APIs that are easy to maintain.

Part III is all about using your GraphQL API. You’ll learn how to support clientside GraphQL frameworks that access it over HTTP or directly from within your Elixir applications.

The book wraps up by providing a useful appendix to use as a quick reference when building your GraphQL schema and interacting with your API.

What This Book Isn’t

This book isn’t an introductory book on Elixir or Phoenix. While the book’s code should be straightforward reading for most developers, we will cover some more advanced topics that would benefit from a firm grounding in the Elixir language and the Phoenix web framework. We recommend the following supplementary books to readers who might be coming at this book from a different background:

• Programming Elixir ≥ 1.6 [Tho18]

• Programming Phoenix ≥ 1.4 [TV18]

This book isn’t a lengthy diatribe about REST or JSON APIs. While we’ll take time to compare GraphQL with other technologies building on your experience this isn’t going to be a point-by-point takedown of other choices; GraphQL is a compelling choice, and while we’ll often touch on why, we’ll move on to actually building things with it rather quickly.

Who This Book Is For

If you’re a developer who writes modern web APIs, this book is for you. You know the rewards and challenges of building a RESTful API using JSON, working with databases, and aggregating data from remote services. This book is for you because you’re in a good position to experience the “aha moment” of GraphQL full-force. You already know the problem space.

If you write Elixir (or Erlang) code, this book is for you. You use the Erlang/OTP platform for a reason it’s robust, fault-tolerant, and battle-tested. This book is for you because GraphQL is the web API and (data retrieval/mutation) technology that Elixir/Erlang deserves, and you’re using a platform that can take GraphQL to the next level.

If you write Node.js code, and especially if you’re already supporting GraphQL APIs for JavaScript-based web frameworks, this book is for you. Maybe you’re looking for an alternative backend technology, and you’ve heard a lot about Elixir and Phoenix. You already know a fair bit about GraphQL, but you want to take it further. This book is for you because it will help you take the jump to Elixir with the confidence and knowledge to make your APIs even better.

How to Read This Book

If you’re brand new to GraphQL and want the full background story, or if you’ve played a bit with it before but would like a solid refresher, start at the beginning. In Chapter 1, Meet GraphQL, on page 3, you’ll learn about its origins and walk through the core concepts that you’ll need as you read the rest of the book.

If you’ve used GraphQL before in another language and want to jump straight into building your first Elixir GraphQL API, then Chapter 2, Building a Schema, on page 15 is the chapter for you. It’s where you’ll be introduced to Absinthe, the GraphQL toolkit for Elixir, and start building the GraphQL schema for our example application.

Readers who have already had some experience building GraphQL APIs using Elixir and are looking for specific answers might want to start at Part II, Publish Your API, on page 121; its chapters are focused on common challenges GraphQL developers face taking their dreams to reality. If you’re ready to use your Absinthe-based GraphQL API, take a look at Part III, Use Your API, on page 193, where you’ll learn about supporting fancy JavaScript GraphQL-fluent, client-side frameworks over HTTP and even building some custom processing logic to use GraphQL directly from elsewhere in your Elixir applications.

Regardless of where you start reading the book, check out the “Moving On” section at the end of each chapter. You’re sure to find ideas and challenges there that will help you take your understanding of GraphQL and its use in Elixir to the next level.

About the Code

The sample code and examples included in this book are written using the Elixir programming language, and will focus on how to use Absinthe,1 the GraphQL toolkit for Elixir. As the authors of Absinthe, we can’t wait to show you the ropes.

Absinthe is distributed as a number of separate, focused packages, and we’ll be using several; absinthe provides the core GraphQL functionality, absinthe_plug supports handling requests over HTTP/S, and absinthe_phoenix adds support for GraphQL subscriptions over Phoenix channels. You learn about each of these, and more related packages, as we build out the examples.

1. http://absinthe-graphql.org

System Dependencies

The Elixir example code for the book assumes that you’ve installed the following system dependencies. This can be done by using your favorite package manager or downloading and installing them as pre-built binaries from the associated websites.

• Erlang2 (v20.0+)

• Elixir3 (v1.5.0+)

• PostgreSQL4 (v9.4+)

The final chapter of the book covers integration with JavaScript client-side frameworks, and we recommend Node.js5 v8.9.0+.

Online Resources

You can find all the example code for this book on its Pragmatic Bookshelf website,6 alongside a handy community forum if you’d like to reach out for help along the way.

While we’ve worked hard to make our code examples and explanations bugfree and clear in every way for our readers, we’ve written enough software to know that we’re fallible. Thanks in advance for reporting any issues that you find in the book code or text via the errata form, also conveniently found on the book website.

Welcome to the world of GraphQL using Elixir. We can’t wait to see what you build!

Bruce Williams & Benjamin Wilson March 2018

2. https://www.erlang.org

3. https://elixir-lang.org

4. https://www.postgresql.org

5. https://nodejs.org

6. https://pragprog.com/book/wwgraphql/craft-graphql-apis-in-elixir-with-absinthe

Part I

Build a GraphQL API

In this first part, you’ll learn GraphQL’s core concepts (or enjoy a refresher) and build a basic functional API in Elixir from start to finish. You’ll discover how to use queries to get information, mutations to make modifications to data, and live subscriptions over Phoenix channels to keep your API users up to date with changes.

CHAPTER 1

Meet GraphQL

There was a time when the primary job of a web server was supplying HTML content to a web browser for display, but these days to support mobile and rich client-side applications a lot of the work that we need to do on the backend involves building APIs.

Building an API that can support a wide range of possible clients can quickly become a challenge. The needs of applications that use the API can quickly diverge and force us to make tough decisions; what starts as a simple REST API can quickly become more complex as we work to make its endpoints more flexible to support clients.

Let’s explore a different way to build APIs one that addresses this modern problem head on and comes packed with other benefits: GraphQL.

GraphQL is a query language that gives the users of an API the ability to describe the data that they want, and lets creators of the API focus on data relationships and business rules instead of worrying about the various data payloads the API needs to return.

In this chapter, we’re going to look at some of the key concepts behind GraphQL, including how these query documents are structured and how a GraphQL server interprets them. Along the way, we’ll draw some comparisons with the most common technology driving web services today: REST.

On the Client

To illustrate conventional GraphQL communication practices, let’s imagine how a web or mobile application might request data from a server over HTTP. At a high level, this conversation looks something like the figure on page 4.

The application sends a GraphQL document to the server, and the server responds with a JSON document, having consulted a schema that describes

data it has available to query and to modify. Because of the schema, the server is empowered to flexibly fulfill the requests sent by clients on a caseby-case basis.

Let’s see how this compares to REST, looking at a specific example: retrieving information about a specific user record. In a REST API, we’d do an HTTP request that would look something like this (assuming a user ID of 123):

GET /users/123

As a client of this REST API, you have very limited control over what is returned. Perhaps the server will give you the user’s ID and a name, or maybe it will return the entirety of the user’s profile and every other record associated with the user. The contract between the client and the server is fairly onesided: the client gets what the server wants to give it.

REST API authors attempting to address this problem use a number of different techniques and conventions:

• Writing detailed, custom documentation about API responses, so clients at least know what to expect

• Supporting query parameters (like include and fields) that act as flags to select information, adding some limited flexibility

• Including references (either IDs or URLs) to related data, rather than embedding it, effectively splitting the query across multiple requests

• Using different resources to model different levels of data inclusion (for example, /users/123 as a full set of data and /profiles/123 as a sparse set of data), duplicating or reusing large chunks of code

• Splitting the API completely, perhaps by platform (for instance, exposing /desktop/users/123 and /mobile/users/123), to support the needs of different types of clients

• Some combination of all of these

REST’s simplicity falls away pretty suddenly as the needs of clients become more varied and the surface area of the API expands.

The GraphQL approach to this problem is more standardized (being based on a specification) and cohesive: GraphQL is an expressive query language focused on flexibly meeting API client needs. If a GraphQL client wanted to retrieve user 123’s name and email address, for instance, they’d explicitly specify those fields:

{ user(id: 123) { name email } }

We don’t need to get hung up on the details now, but what you’re looking at here are three fields: user, name, and email, with name and email being children of user. This makes sense, structurally, as a user has a name and an email address. We’re passing an id argument here, too, specifying which user we’d like to use.

The request is made to a single GraphQL endpoint (URL) via an HTTP GET or a POST request, and the structure of the GraphQL document determines exactly what the server’s response will look like. There are no hidden, default values forced upon the client; the response is tailored based on the request. Here’s an example response based on our previous GraphQL document:

{ "data": { "user": { "name": "Joe Bob", "email": "joe.bob@example.com" } } }

The GraphQL server has the schema and knows what a User is, how to retrieve one by ID, and what information it can contain. It can respond to the client with the information about the user that the client specifically requested. It knows how to find data related to the user, too.

Including Relationships

Often the most valuable pieces of data end up being the relationships between entities rather than the entities themselves. That is certainly true in social

networking applications, where the interconnectedness of people their social graph serves as the functional core of the product. Social networks could hardly be considered social without friendships.

It shouldn’t be much of a surprise then that GraphQL, originating at Facebook, excels at helping clients query across relationships across the graph of related entities. It’s even in the name!

But let’s take a step back and think about how we might handle getting related information from a REST API first. Joe our user 123 has friends, and we’d like to know their names, too.

When using a REST API, here are some questions we should probably ask ourselves:

• Can we get a user’s friends via /users/:id, or do we need to use a different resource URL?

• Are friends (or their names) included by default, or do we need to specify that we want them? How do we do that?

• When information about friends is returned, where will it be in the result?

• Is each friend’s data embedded, or just referenced, forcing us to do more requests to retrieve it? Will we need to paginate the friends list? How will this affect our performance on mobile devices, where bandwidth may be limited and additional requests have a negative effect on performance and battery life?

This is a lot of unnecessary mental overhead, requiring researching documentation (if it exists and is complete) and doing exploratory testing just to determine how to access the data we need from the API.

GraphQL Simplifies Things

GraphQL can shorten your development time because you don’t need to ask these questions.

If you know that a GraphQL server supports users having friends (you’ll learn about introspection in Running Our Query with GraphiQL, on page 24), you also know that you can query across that relationship, getting exactly the information that you want to receive in a single request, all the while using a standardized query language.

We simply ask for the data using GraphQL:

{ user(id: 123) { name email friends { ➤ name ➤ } ➤ } }

The result is much as it was with our earlier user example, but with the additional data about friends a level deeper: { "data": { "user": { "name": "Joe Bob", "email": "joe.bob@example.com", "friends": [ {"name": "Fred Jones"}, {"name": "Jane Smith"}, {"name": "Rebekah Jones"} ] } } }

Looking at the client-side code, you know exactly what you can expect to be there because you have a GraphQL query at hand that tells you the shape of the response you’ll get back from the server, taking the guesswork (and documentation spelunking) out of the picture. This lets you focus on more product-specific concerns.

From a backend perspective, because queries are coming in as a declarative query language detailing what clients need, you gain an incredibly detailed picture of what information your clients actually need. Gone are the days of sending as much data across the wire that any client, someday, might use, or building in custom inclusion and exclusion logic that you have to maintain.

This isn’t necessarily a new concept either. If you’ve ever used a database system that supports SQL, you’re already familiar with query languages that allow you to retrieve exactly what you want. GraphQL is a lot simpler than SQL for users, however, and the backend data retrieval logic (that gets the data the user wants) is a lot easier to customize.

Let’s take a closer look at that backend logic next and talk about what needs to be done on the GraphQL server for it to give us this level of flexibility.

On the Server

GraphQL is incredibly powerful, but it isn’t magic. GraphQL query documents can be flexible because the server holds a complete schema describing the shape of data that the API models and the input that it can expect from clients. This means that you, as the API developer, are responsible for accurately building a representation of your data. If this sounds like a lot of work, take heart in that it means the GraphQL server can free you up from more mundane details being mixed into your business logic.

We’ll get into the nitty gritty of how GraphQL schemas are built in the next chapter, but let’s take a look at one of the more important benefits that providing one gives us automatically: user input validation. We’ll start with a little vignette showing how this usually works in a REST API.

User Input Validation in REST

Suppose, in your REST API, you have an endpoint that will return a list of upcoming events. You want to support filtering these events by the date and location where they are going to take place. This would give you something like:

GET /events?date=2016-11-22&location_id=4

You can’t trust API users to give you correct input values. The location_id could be “hello world” instead of a number, for example. The date could be given in an invalid or unsupported date format. Users might even pass in superfluous parameters that they think should work, but do not.

REST, as a standard, doesn’t really have much to say about data validation, so enforcing rules about incoming data is left up to the code that handles the request code that we have to write ourselves.

This validation code can add a lot of complexity to backend controllers, which are often responsible for a long list of other tasks: retrieving the information the client wants, formatting the result as the client expects, and sending the response back across the HTTP connection. This can quickly become a mess. Here’s an example of our events endpoint using a Phoenix controller action. Remember, its only job is to return a list of filtered events, and yet…

@valid_filters ~w(date location_id name)a Line 1 def index(conn, params) dofilters =@valid_filters|> Enum.reduce(%{}, fn key, filters -> 5 case Map.fetch(params, Atom.to_string(key)) do{:ok, value} -> -

add_filter(filters, key, value)->filters 10 endend)render("index.json", events: Event.list(filters))end 15defp add_filter(filters, :date, date) docase Date.from_iso8601(date) do{:ok, date} -> -

Map.put(filters, :date, date) 20 {:error, _} ->

filters

end

end

defp add_filter(filters, key, value) do 25 Map.put(filters, key, value)end -

This is a lot of code! Did you catch where the controller action actually retrieved the requested data its main purpose? There it is on line 14, tucked away in the wash of boilerplate. This is without even trying to return nice errors to the client in the event they do something wrong, or letting them know they’ve sent something extra.

The controller is trying to do three distinct tasks:

1. Validate the input from the user.

2. Get the data the user wants.

3. Respond to the user in the correct format.

Even when you leverage packages and other utilities to try to make data validation simpler, the central problem is still the same: you’re doing too much work here that’s outside your core goal, which is getting the events.

Using GraphQL, this is a completely different story.

GraphQL Inputs

GraphQL simplifies this dramatically by inverting the problem. With GraphQL you have a predefined schema with declared types and rules about the input that you can receive from users to retrieve data. When someone sends you data, it is checked by these rules before your code is executed.

This keeps your code focused on its primary objective: doing what the user wants.

To use our previous example, you would declare that location_id has to be an integer, and that date has to be formatted as a date. Then, to support a comparable GraphQL query like the following: { events(location_id: 4, date: "2016-11-22") { name location { name } } }

You could write code that just focuses on using the filters (that will be validated and parsed for us) to get the events you want: def events(filters, _) do {:ok, Event.list(filters)} end

Validation Errors Skip Execution

A GraphQL server doesn’t just verify that a request is well formed. It also validates that it meets the requirements defined by the schema.

Requests that fail to pass validation never get the chance to execute your business logic, resulting in faster error responses and less bugs for you to track down later.

If the client sends something extra, they’ll be given a detailed error message in the response to that effect. If API users fail to send something that’s required, or if they send something that is invalid, they’ll be notified as well. As developers, we don’t have to worry about any of those scenarios! Once we have a schema in place, the input data given to our code is guaranteed to have met the rules we’ve declared about it, and we can get right down to business.

Your GraphQL server’s knowledge of your schema also helps it determine what data is available to be output.

Queries and Schemas

Remember our user example from earlier, and how our GraphQL server knew that the client could receive the name, email, and friends of a user? The reason that worked is rooted in the correspondence between the structure of GraphQL queries and the structure of the graph of types maintained in the schema. In the next couple of chapters, we’ll be covering how we actually write Elixir

code that builds this schema graph, but let’s look at a few diagrams that demonstrate this correspondence.

Let’s talk about another query returning the data for a user profile. A basic diagram of the GraphQL schema might look like this:

This is a graph showing User (a custom type in our schema) and String and Int (built-in types) as nodes, with the fields name, email, age, and friends as edges, representing the relationships between the types. (We’ll talk about QueryRootType in a moment.)

Nodes and Edges

GraphQL developers and the GraphQL community commonly borrow terms from graph theory, which is the study of mathematical structures that model the relationships between objects.

In graph theory terminology, the relationships between objects are commonly referred to as “edges” (drawn as lines), and the objects themselves are called “nodes” (drawn as shapes connected by those lines).

A User type is related to a String type both by its name and its email fields.

Because the User type has fields and represents a complex value, GraphQL refers to it as an object type, whereas Int and String are simple values that it refers to as scalar types; they have no fields of their own. GraphQL’s type system models a number of different types and defines a number of readyto-use, built-in types. You will learn more about others in the next few chapters.

Object types can have fields that point to themselves, which is what we see with the User type’s friends edge. This means that all objects in our graph that are of the User type can have friends, and that each of those friends will also be of type User.

Incoming queries are matched up against the schema. Sometimes it’s useful to represent the relationships visually. For instance, if we graph the following query document: { profile { name email friends { name } } }

It will look something like this:

We can see a lot of similarities with our schema graph. Each node in our query tree lines up exactly with the name of an edge we have in our schema graph. When we query a GraphQL schema, we’re really just walking these edges and getting the data associated with them. All queries start at a root object we have on our schema graph (we’re calling it RootQueryType). Our query then has us follow the profile edge, which gets us to a User. From there, we also want to follow the name and email edges, which get us to string values. Finally, our friends edge just gets us back to a User, letting us know that we can get a name, age, or email of the friend if we want…and their friends, too!

Building a schema presents two major categories of work: describing the types and the edges between types (both by defining them and adding built-in documentation, which you’ll see later), and writing the business logic that edges use to find their data.

If a query needs to walk from a user to its friends, how does that actually happen? Are we going to hit the database? If we do, will trying to get the friends of friends result in terrible database access patterns?

These are the kinds of questions that we’re going to take on as we work through this book. To do this, we are going to be building an application piece by piece that will put these problems front and center in a concrete way.

Absinthe and the Tech Stack

For the rest of the book, we’ll be focusing on improving an application that we’ve provided called PlateSlate. PlateSlate models the menu, ordering, and order fulfillment needs of a quick-service restaurant chain. We’ll incrementally build out the domain model and add features to its API that will expose you to deeper, trickier aspects of GraphQL (and Elixir) as we go. If you haven’t already downloaded the application, please go to Online Resources, on page xiv, and follow the instructions there.

This application makes use of a few Elixir packages, the most important of which is Absinthe. Absinthe lets you build GraphQL schemas and execute documents against them using Elixir. It provides a host of features that we’ll be covering throughout this book to make your GraphQL APIs straightforward to build, idiomatic, and perform well.

We’re also going to leverage a couple of packages for exposing our GraphQL API via the web, specifically Plug and Phoenix. In many ways, Absinthe replaces a lot of the things you’d normally find in a Phoenix-based API like controllers and views. Little to no knowledge of either of these technologies is assumed; we’ll cover the bits you need to know along the way.

Finally, we’re going to have some packages we use to get underlying data. One of the core value propositions of GraphQL is its ability to provide a common interface to different types of data stores, and we’ll try to illustrate that as we build our application. This means we’ll eventually use a basic HTTP client to make HTTP requests to other APIs and use Ecto to access an SQL database. Strong proficiency with these packages is not required, but a basic grasp of how to interact with a relational database will help.

Chapter 1. Meet GraphQL • 14

At a high level, this is how a GraphQL request is handled, using these packages:

Most of our time will be spent focusing on how to define our GraphQL schema and tie it to our application business logic, and that’s what we will move on to next.

Moving On

In this chapter, we’ve introduced a lot of key GraphQL concepts and talked about how GraphQL compares to REST. We’ve talked about how clients communicate with servers using GraphQL documents, and how servers use a schema to validate and retrieve the data requested. You’ve learned how this approach makes client requests more flexible, and how the schema simplifies the concerns that your server business logic needs to handle manually.

Here are a couple of challenges for you before we move on:

1. Think of a domain familiar to you and write down the types that belong to that domain. Draw in relationships between those types. Remember, these relationships are often what we think of as properties on an entity.

2. Add a root object, and think about how you might want to connect it with your graph. From there, write down some GraphQL queries that would be possible to handle from that point. What kinds of responses might come back for these?

Once you’ve thought through these problems, get ready to jump into defining your first GraphQL schema with Elixir using Absinthe.

CHAPTER 2

Building a Schema

GraphQL APIs are shaped by their schemas. In fact, it’s fair to say that because GraphQL schemas are more than just structural metadata and actually define behavior, they’re the API implementation itself.

The schema is used by GraphQL servers as the canonical source of information when deciding how to respond to a request. They’re the reason that GraphQL documents can be as flexible as they are, while still giving backend developers the mechanisms that they need to ensure the API is safe and reliable.

In Elixir, you can use the Absinthe package to build GraphQL APIs. In this chapter, we’ll help you get acquainted with how Absinthe’s schemas are defined by building the foundation of our example application, PlateSlate. The knowledge you’ll pick up in this chapter will serve as the foundation for the rest of the book.

First, let’s kick the tires on our example application, making sure it’s up and running and ready for a GraphQL API.

Preparing the Application

Let’s start by making sure that you’ve set up your development environment. Your system will need to have the prerequisites listed in the System Dependencies, on page xiv, installed and ready to go, and you’ll need to download the example application source code via one of the methods explained in Online Resources, on page xiv.

Once that’s done, make sure that you’re looking at the directory for this chapter. We’re going to be running a few commands using the mix build tool.

Make sure that you’re running the correct versions of Elixir, just to make sure that you don’t download and compile packages using the wrong version:

Another random document with no related content on Scribd:

CHAPTER XXI.

’ .

W the church bells were ringing daily in the tower above his head, and the old Bridford chimes, famous long ago, were heralding the birth of every hour with a fine old psalm tune that pealed out over the busy, money-making city, like an echo of the past, Cyril Culverhouse was lying at the bottom of a dark gulf of pain and confusion, and all the outer world, and all the life that he had lived, were cancelled and forgotten.

Strange images danced before his eyes like motes in the sunshine, yet seemed to him neither strange nor unexpected. He had a history of his own in that period of delirium, a new identity, new surroundings, a mad, wild world, peopled out of his own brain. Bishops and archbishops came and sat beside his bed, and held long arguments with him, figments of a mind distraught, the shadows that haunt fever-dreams, but to him intensely real. The dead came back to life to hold converse with him, and he was not surprised. No, he had always thought there was something in the ideas of the old necromancers. The elixir of life was not an impossibility. Here was Luther with his square solid face, and sensual humorous mouth. Here was Pascal, full of quaint sayings and far-reaching thoughts. The sick man talked for all of them. His talk was wildest raving to the ears that listened, but to his own fancy it was profoundest wisdom. There is no egotism, no belief in self, equal to that of the lunatic. For him the stars and moon have been made, for him God willingly performs miracles which overthrow all the laws of the universe. He is the axis of the world, and lets it go round.

How long those days and nights of fever were! That was the chief agony of them. The eternity of hours, so thickly peopled with distorted shapes that every quarter of an hour was an era. Of actual physical pain the sufferer had no consciousness; but weariness,

almost too heavy to be borne weighed upon him in the long strange nights, when the faces of his watchers changed, and the very walls of his room seemed new and unknown to him. He fancied that his nurses had removed him into new lodgings while he slept, though it seemed to him that he had never slept.

Sometimes he fancied himself in one place, sometimes in another. He was at Oxford, in those old rooms of his looking into the college garden. He was at Little Yafford, at Culverhouse, anywhere but where he really was.

And his nurses, who were they? He faintly remembered Mrs. Podmore leaning over his bed, fat and scant of breath, with a medicine-glass in her hand, coaxing him to drink. He remembered Sarah, making believe to step softly, in creaking shoes, whose every movement was agony to him. But these things were lost in the darkness of remote ages. His present nurses seemed to have been tending him during a century.

There were two, one tall and slender, dignified of bearing, yet gracious in every movement; the other short, small, and brisk. They were dressed exactly alike, in the costume of some religious order, as he supposed. They wore long black robes and white linen caps, such as he remembered to have seen worn by the Sisters of Mercy in Breton towns that he had visited years ago in one of his long vacations. Admirable caps for ugly women, for the stiff linen borders projected a quarter of a yard beyond the face, entirely concealed the profile, and overshadowed the countenance at all times.

Cyril knew only that the taller of his two nurses had dark eyes and a pale face, and that the little woman had black eyes of exceeding sharpness, that flashed at him from the cavernous cap. They were both admirable nurses, quiet, gentle, attentive, but in some phases of his delirium he hated them, and accused them of all manner of evil designs. They were poisoning him. Yes, the medicine they made him take at stated intervals contained a slow poison—the Aqua Tofana of the Middle Ages—that horrible stuff which the wicked witch Toffania made by wholesale, and sent to all the cities of the earth as the manna of St. Nicola of Bari; or it was the hemlock that Socrates

drank, or wolf’s bane, or deadly nightshade. He recognised the flavour of the murderous herb. And then he stormed at his nurses, and told them they had plotted his murder.

‘If you were honest women you would not hide your faces,’ he cried. ‘You are murderesses, and have come here to kill me.’

One night, after an age of fever and hallucination, he sank into a refreshing slumber. It was as if his spirit, newly escaped from a burning hell, had slipped unawares into Paradise. Fair meadows and flowing streams, an ineffable sense of coolness and relief, and then deep rest and stillness.

When he awoke, the summer dawn filled the room. Through the widely opened windows came the fresh breezes of the morning. A soft cool hand was on his brow, the tall nurse’s dark figure stood beside his bed.

All his delusions, all his hideous fancies, seemed to have run out of his brain, like water out of a sieve, during that one sweet sleep. Suddenly and completely as the leper at the Divine Healer’s bidding, he was made sound and whole. Very weak still, with a sense of utter helplessness and prostration, he yet felt himself cured. The fire that had made life a torture had burnt itself out.

He looked up at his nurse. How purely white that quaint old headgear of hers looked in the morning sunshine. He remembered the bright freshness of just such another morning in his holiday rambles five years ago, and just such another black-robed figure and white cap, a Sister of Mercy waiting for the starting of the diligence, in the old market square at Vannes, the white dusty square, the scanty trees, that seem to have been planted yesterday, the shabby old cathedral looking down at him.

‘You are a Frenchwoman, are you not?’ he asked, the weakness of his voice startling him a little.

‘Mais si,’ she answered, gently.

He tried to get her to talk, but she answered him only in monosyllables. He tried to see her face, but the position in which she held her head always prevented him.

‘Perhaps her cap is the prettiest thing about her, and she would rather show that than her face,’ he thought.

Even that brief conversation exhausted him, and he fell asleep again. Those weary hours of delirious wakefulness had left him long arrears of sleep to make up. He slept on till dusk, and Dr. Saunders, finding him locked in that deep slumber, pronounced him out of danger.

‘Our medicines have never been able to touch him,’ he said frankly. ‘It has been an unaided struggle between nature and disease. I ought not to say unaided, though,’ he added, apologetically, to the little nursing sister in the Breton cap. ‘Your care has been a very powerful assistance.’

The little woman thanked him effusively in her broken English. The taller nurse spoke only French, and as little of that as possible.

When Cyril awoke again, just before nightfall, the small nurse was sitting by his bed.

‘Where is the other?’ he asked.

‘Gone.’

‘Gone?’

‘Yes. You are now much better—on the high road to recovery. You no longer want two nurses. My companion has gone home.’

‘She is wanted for some other case, perhaps.’

‘No doubt she soon will be.’

‘To what order do you belong?’

‘To a community of nursing sisters.’

‘In Brittany?’

‘Yes.’

‘What part of Brittany?’

‘We never talk about ourselves. It is one of the rules of our order. We come and go like the wind.’

‘But how was it that you came to me? Who sent for you?’

‘We were not sent for. We happened to hear of your illness—and we knew you were a good man. It was our duty to come and nurse you.’

‘What me?—a Protestant?’

‘We are not sectarian. We go wherever we are wanted.’

‘But how do you—Breton nuns—come to be in England?’

‘We are not nuns. We are a nursing sisterhood, bound by no vows. We heard of the pest raging in this town, and came here to be useful.’

‘You are very good people,’ said Cyril. ‘I am sorry the other sister is gone. I should like to have talked to her, but this morning she would answer me only in monosyllables.’

‘It is not good for you to talk, and it is one of our rules to talk as little as possible.’

For three days the figure in the loose black gown was constantly at Cyril’s bedside. He heard the little woman telling her beads in the dead of night. If she were no nun she was at any rate a staunch Roman Catholic; but she did not endeavour to convert him to her own creed. She was a modest, unobtrusive little woman; but during those three days she very often broke the rule of her order, and talked to the patient a good deal. She talked of Brittany, which she knew thoroughly, and sometimes of modern French literature, which she knew better than she ought to have done as a member of a religious sisterhood.

On the fourth day she was gone, and another figure, dressed in black, with neat white cap and apron, was by Cyril’s bedside. The face of this watcher was not hidden. He knew it well, a homely English face that brought back the thought of his work in the courts and back streets of Bridford.

‘Mrs. Joyce,’ he exclaimed. ‘Have you turned nurse?’

‘What more blessed privilege can I have, sir, than to take care of you? I owe you what is a great deal more to me than my own life, the life of my beloved son. Oh, sir, if he ever comes to be a Milton or a Shakespeare, the world will bless you for your goodness, as I do now.’

Cyril smiled at her enthusiasm. Perhaps every mother whose son writes obscure verses in doubtful English believes with Mrs. Joyce that she has produced a Milton.

‘I should have come before, sir, if the two ladies hadn’t been here. But they were such good nurses I didn’t want to interfere with them.’

‘Do you know where they came from, or why they came?’

‘No, indeed, Mr. Culverhouse. They were foreigners, and I suppose they came from foreign parts.’

‘Neither of my doctors sent for them, I believe.’

‘No, sir. Dr. Saunders told me they came and went like spirits, but he was wishful there were more like them.’

‘And your son is really recovered?’

‘Yes, sir. It is a most wonderful cure. He rallied that night, and was up and about at the end of the week. To both of us it seemed like a miracle. I have read the gospel about the widow’s son every night and morning after my prayers, and I have read it two or three times to Emmanuel. Oh, sir, I hope and believe you have wrought a double cure. I think my son’s heart is turned to holy things. He has read his Bible very often lately. I have watched him, and I think he is beginning to find out that there is truth and comfort to be found in it.’

‘He cannot read the gospel long without making that discovery. Young men are too apt to form their judgment of the Bible from what other people have written about it. When they go to the fountain head they find their mistake.’

Cyril was not satisfied till he had questioned Dr. Saunders and Dr. Bolling, the latter of whom had come to see him daily, without any fee, about the two French nurses. But neither of these could tell him more than he knew already.

‘I wish I did know more about them,’ said Mr Saunders. ‘Whatever institution they belong to, it’s an admirable one, and I’m sorry we haven’t a few more institutions of that kind over here. I don’t think we should have pulled you through if it hadn’t been for that excellent nursing. No, upon my word I believe you owe those two women your life.’

‘And I do not even know their names, or where they are to be found,’ said Cyril, regretfully.

It worried him not a little to be under so deep an obligation, and to have no mode of expressing his gratitude. At one time he thought of putting an advertisement in the Times, thanking his unknown nurses for their care. But on reflection this seemed idle. They were doubtless what they represented themselves, sisters of some religious order, who did good for the love of God. They had no need of his thanks. Yet he puzzled himself not a little about the whole business. Why should he have been selected, above all other sufferers in the town of Bridford, as the recipient of this gratuitous care?

As soon as he was able to leave his bed, Dr. Bolling insisted on his going off to the sea-side to get strength before he went back to his work. This vexed him sorely, but he could not disobey

‘You’ve been as near the gates of death as a man can well go without passing through them,’ said the doctor

J. AND W. RIDER, PRINTERS, LONDON.

Corrections

The first line indicates the original, the second the correction. Contents to Vol. II

IX. ‘THOSE ARE THE KILLING GRIEFS WHICH DARE NOT SPEAK’ 138 IX. ‘THOSE ARE THE KILLING GRIEFS WHICH DARE NOT SPEAK’ 128

p. 137

Miss Scales eat her dinner Miss Schales ate her dinner

p. 172

Yes, it’s regretable. Yes, it’s regrettable

p. 268

in His earthly pilgrimage did He exereise that ineffable in His earthly pilgrimage did He exercise that ineffable

p. 305

Mrs. Piper no longer recived her morning visitors in it Mrs. Piper no longer received her morning visitors in it

*** END OF THE PROJECT GUTENBERG EBOOK AN OPEN VERDICT ***

Updated editions will replace the previous one—the old editions will be renamed.

Creating the works from print editions not protected by U.S. copyright law means that no one owns a United States copyright in these works, so the Foundation (and you!) can copy and distribute it in the United States without permission and without paying copyright royalties. Special rules, set forth in the General Terms of Use part of this license, apply to copying and distributing Project Gutenberg™ electronic works to protect the PROJECT GUTENBERG™ concept and trademark. Project Gutenberg is a registered trademark, and may not be used if you charge for an eBook, except by following the terms of the trademark license, including paying royalties for use of the Project Gutenberg trademark. If you do not charge anything for copies of this eBook, complying with the trademark license is very easy. You may use this eBook for nearly any purpose such as creation of derivative works, reports, performances and research. Project Gutenberg eBooks may be modified and printed and given away—you may do practically ANYTHING in the United States with eBooks not protected by U.S. copyright law. Redistribution is subject to the trademark license, especially commercial redistribution.

START: FULL LICENSE

THE FULL PROJECT GUTENBERG LICENSE

PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK

To protect the Project Gutenberg™ mission of promoting the free distribution of electronic works, by using or distributing this work (or any other work associated in any way with the phrase “Project Gutenberg”), you agree to comply with all the terms of the Full Project Gutenberg™ License available with this file or online at www.gutenberg.org/license.

Section 1. General Terms of Use and Redistributing Project Gutenberg™ electronic works

1.A. By reading or using any part of this Project Gutenberg™ electronic work, you indicate that you have read, understand, agree to and accept all the terms of this license and intellectual property (trademark/copyright) agreement. If you do not agree to abide by all the terms of this agreement, you must cease using and return or destroy all copies of Project Gutenberg™ electronic works in your possession. If you paid a fee for obtaining a copy of or access to a Project Gutenberg™ electronic work and you do not agree to be bound by the terms of this agreement, you may obtain a refund from the person or entity to whom you paid the fee as set forth in paragraph 1.E.8.

1.B. “Project Gutenberg” is a registered trademark. It may only be used on or associated in any way with an electronic work by people who agree to be bound by the terms of this agreement. There are a few things that you can do with most Project Gutenberg™ electronic works even without complying with the full terms of this agreement. See paragraph 1.C below. There are a lot of things you can do with Project Gutenberg™ electronic works if you follow the terms of this agreement and help preserve free future access to Project Gutenberg™ electronic works. See paragraph 1.E below.

1.C. The Project Gutenberg Literary Archive Foundation (“the Foundation” or PGLAF), owns a compilation copyright in the collection of Project Gutenberg™ electronic works. Nearly all the individual works in the collection are in the public domain in the United States. If an individual work is unprotected by copyright law in the United States and you are located in the United States, we do not claim a right to prevent you from copying, distributing, performing, displaying or creating derivative works based on the work as long as all references to Project Gutenberg are removed. Of course, we hope that you will support the Project Gutenberg™ mission of promoting free access to electronic works by freely sharing Project Gutenberg™ works in compliance with the terms of this agreement for keeping the Project Gutenberg™ name associated with the work. You can easily comply with the terms of this agreement by keeping this work in the same format with its attached full Project Gutenberg™ License when you share it without charge with others.

1.D. The copyright laws of the place where you are located also govern what you can do with this work. Copyright laws in most countries are in a constant state of change. If you are outside the United States, check the laws of your country in addition to the terms of this agreement before downloading, copying, displaying, performing, distributing or creating derivative works based on this work or any other Project Gutenberg™ work. The Foundation makes no representations concerning the copyright status of any work in any country other than the United States.

1.E. Unless you have removed all references to Project Gutenberg:

1.E.1. The following sentence, with active links to, or other immediate access to, the full Project Gutenberg™ License must appear prominently whenever any copy of a Project Gutenberg™ work (any work on which the phrase “Project Gutenberg” appears, or with which the phrase “Project Gutenberg” is associated) is accessed, displayed, performed, viewed, copied or distributed:

This eBook is for the use of anyone anywhere in the United States and most other parts of the world at no cost and with almost no restrictions whatsoever. You may copy it, give it away or re-use it under the terms of the Project Gutenberg License included with this eBook or online at www.gutenberg.org. If you are not located in the United States, you will have to check the laws of the country where you are located before using this eBook.

1.E.2. If an individual Project Gutenberg™ electronic work is derived from texts not protected by U.S. copyright law (does not contain a notice indicating that it is posted with permission of the copyright holder), the work can be copied and distributed to anyone in the United States without paying any fees or charges. If you are redistributing or providing access to a work with the phrase “Project Gutenberg” associated with or appearing on the work, you must comply either with the requirements of paragraphs 1.E.1 through 1.E.7 or obtain permission for the use of the work and the Project Gutenberg™ trademark as set forth in paragraphs 1.E.8 or 1.E.9.

1.E.3. If an individual Project Gutenberg™ electronic work is posted with the permission of the copyright holder, your use and distribution must comply with both paragraphs 1.E.1 through 1.E.7 and any additional terms imposed by the copyright holder. Additional terms will be linked to the Project Gutenberg™ License for all works posted with the permission of the copyright holder found at the beginning of this work.

1.E.4. Do not unlink or detach or remove the full Project Gutenberg™ License terms from this work, or any files containing a part of this work or any other work associated with Project Gutenberg™.

1.E.5. Do not copy, display, perform, distribute or redistribute this electronic work, or any part of this electronic work, without prominently displaying the sentence set forth in paragraph 1.E.1 with active links or immediate access to the full terms of the Project Gutenberg™ License.

1.E.6. You may convert to and distribute this work in any binary, compressed, marked up, nonproprietary or proprietary form, including any word processing or hypertext form. However, if you provide access to or distribute copies of a Project Gutenberg™ work in a format other than “Plain Vanilla ASCII” or other format used in the official version posted on the official Project Gutenberg™ website (www.gutenberg.org), you must, at no additional cost, fee or expense to the user, provide a copy, a means of exporting a copy, or a means of obtaining a copy upon request, of the work in its original “Plain Vanilla ASCII” or other form. Any alternate format must include the full Project Gutenberg™ License as specified in paragraph 1.E.1.

1.E.7. Do not charge a fee for access to, viewing, displaying, performing, copying or distributing any Project Gutenberg™ works unless you comply with paragraph 1.E.8 or 1.E.9.

1.E.8. You may charge a reasonable fee for copies of or providing access to or distributing Project Gutenberg™ electronic works provided that:

• You pay a royalty fee of 20% of the gross profits you derive from the use of Project Gutenberg™ works calculated using the method you already use to calculate your applicable taxes. The fee is owed to the owner of the Project Gutenberg™ trademark, but he has agreed to donate royalties under this paragraph to the Project Gutenberg Literary Archive Foundation. Royalty payments must be paid within 60 days following each date on which you prepare (or are legally required to prepare) your periodic tax returns. Royalty payments should be clearly marked as such and sent to the Project Gutenberg Literary Archive Foundation at the address specified in Section 4, “Information about donations to the Project Gutenberg Literary Archive Foundation.”

• You provide a full refund of any money paid by a user who notifies you in writing (or by e-mail) within 30 days of receipt that s/he does not agree to the terms of the full Project Gutenberg™ License. You must require such a user to return or destroy all

copies of the works possessed in a physical medium and discontinue all use of and all access to other copies of Project Gutenberg™ works.

• You provide, in accordance with paragraph 1.F.3, a full refund of any money paid for a work or a replacement copy, if a defect in the electronic work is discovered and reported to you within 90 days of receipt of the work.

• You comply with all other terms of this agreement for free distribution of Project Gutenberg™ works.

1.E.9. If you wish to charge a fee or distribute a Project Gutenberg™ electronic work or group of works on different terms than are set forth in this agreement, you must obtain permission in writing from the Project Gutenberg Literary Archive Foundation, the manager of the Project Gutenberg™ trademark. Contact the Foundation as set forth in Section 3 below.

1.F.

1.F.1. Project Gutenberg volunteers and employees expend considerable effort to identify, do copyright research on, transcribe and proofread works not protected by U.S. copyright law in creating the Project Gutenberg™ collection. Despite these efforts, Project Gutenberg™ electronic works, and the medium on which they may be stored, may contain “Defects,” such as, but not limited to, incomplete, inaccurate or corrupt data, transcription errors, a copyright or other intellectual property infringement, a defective or damaged disk or other medium, a computer virus, or computer codes that damage or cannot be read by your equipment.

1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the “Right of Replacement or Refund” described in paragraph 1.F.3, the Project Gutenberg Literary Archive Foundation, the owner of the Project Gutenberg™ trademark, and any other party distributing a Project Gutenberg™ electronic work under this agreement, disclaim all liability to you for damages, costs and

expenses, including legal fees. YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE PROVIDED IN PARAGRAPH 1.F.3. YOU AGREE THAT THE FOUNDATION, THE TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH DAMAGE.

1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a defect in this electronic work within 90 days of receiving it, you can receive a refund of the money (if any) you paid for it by sending a written explanation to the person you received the work from. If you received the work on a physical medium, you must return the medium with your written explanation. The person or entity that provided you with the defective work may elect to provide a replacement copy in lieu of a refund. If you received the work electronically, the person or entity providing it to you may choose to give you a second opportunity to receive the work electronically in lieu of a refund. If the second copy is also defective, you may demand a refund in writing without further opportunities to fix the problem.

1.F.4. Except for the limited right of replacement or refund set forth in paragraph 1.F.3, this work is provided to you ‘AS-IS’, WITH NO OTHER WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.

1.F.5. Some states do not allow disclaimers of certain implied warranties or the exclusion or limitation of certain types of damages. If any disclaimer or limitation set forth in this agreement violates the law of the state applicable to this agreement, the agreement shall be interpreted to make the maximum disclaimer or limitation permitted by the applicable state law. The invalidity or unenforceability of any provision of this agreement shall not void the remaining provisions.

1.F.6. INDEMNITY - You agree to indemnify and hold the Foundation, the trademark owner, any agent or employee of the Foundation, anyone providing copies of Project Gutenberg™ electronic works in accordance with this agreement, and any volunteers associated with the production, promotion and distribution of Project Gutenberg™ electronic works, harmless from all liability, costs and expenses, including legal fees, that arise directly or indirectly from any of the following which you do or cause to occur: (a) distribution of this or any Project Gutenberg™ work, (b) alteration, modification, or additions or deletions to any Project Gutenberg™ work, and (c) any Defect you cause.

Section 2. Information about the Mission of Project Gutenberg™

Project Gutenberg™ is synonymous with the free distribution of electronic works in formats readable by the widest variety of computers including obsolete, old, middle-aged and new computers. It exists because of the efforts of hundreds of volunteers and donations from people in all walks of life.

Volunteers and financial support to provide volunteers with the assistance they need are critical to reaching Project Gutenberg™’s goals and ensuring that the Project Gutenberg™ collection will remain freely available for generations to come. In 2001, the Project Gutenberg Literary Archive Foundation was created to provide a secure and permanent future for Project Gutenberg™ and future generations. To learn more about the Project Gutenberg Literary Archive Foundation and how your efforts and donations can help, see Sections 3 and 4 and the Foundation information page at www.gutenberg.org.

Section 3. Information about the Project Gutenberg Literary Archive Foundation

The Project Gutenberg Literary Archive Foundation is a non-profit 501(c)(3) educational corporation organized under the laws of the state of Mississippi and granted tax exempt status by the Internal Revenue Service. The Foundation’s EIN or federal tax identification number is 64-6221541. Contributions to the Project Gutenberg Literary Archive Foundation are tax deductible to the full extent permitted by U.S. federal laws and your state’s laws.

The Foundation’s business office is located at 809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887. Email contact links and up to date contact information can be found at the Foundation’s website and official page at www.gutenberg.org/contact

Section 4. Information about Donations to the Project Gutenberg Literary Archive Foundation

Project Gutenberg™ depends upon and cannot survive without widespread public support and donations to carry out its mission of increasing the number of public domain and licensed works that can be freely distributed in machine-readable form accessible by the widest array of equipment including outdated equipment. Many small donations ($1 to $5,000) are particularly important to maintaining tax exempt status with the IRS.

The Foundation is committed to complying with the laws regulating charities and charitable donations in all 50 states of the United States. Compliance requirements are not uniform and it takes a considerable effort, much paperwork and many fees to meet and keep up with these requirements. We do not solicit donations in locations where we have not received written confirmation of compliance. To SEND DONATIONS or determine the status of compliance for any particular state visit www.gutenberg.org/donate.

While we cannot and do not solicit contributions from states where we have not met the solicitation requirements, we know of no

prohibition against accepting unsolicited donations from donors in such states who approach us with offers to donate.

International donations are gratefully accepted, but we cannot make any statements concerning tax treatment of donations received from outside the United States. U.S. laws alone swamp our small staff.

Please check the Project Gutenberg web pages for current donation methods and addresses. Donations are accepted in a number of other ways including checks, online payments and credit card donations. To donate, please visit: www.gutenberg.org/donate.

Section 5. General Information About Project Gutenberg™ electronic works

Professor Michael S. Hart was the originator of the Project Gutenberg™ concept of a library of electronic works that could be freely shared with anyone. For forty years, he produced and distributed Project Gutenberg™ eBooks with only a loose network of volunteer support.

Project Gutenberg™ eBooks are often created from several printed editions, all of which are confirmed as not protected by copyright in the U.S. unless a copyright notice is included. Thus, we do not necessarily keep eBooks in compliance with any particular paper edition.

Most people start at our website which has the main PG search facility: www.gutenberg.org.

This website includes information about Project Gutenberg™, including how to make donations to the Project Gutenberg Literary Archive Foundation, how to help produce our new eBooks, and how to subscribe to our email newsletter to hear about new eBooks.

Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.