github graphile/crystal v4.1.0
v4.1.0 - Better webpackability (for Lambda), better functions/indexes support, enhanced GraphiQL, more plugin helpers

latest releases: v4.14.0, v4.13.0, v4.12.12...
5 years ago

Wow, this is a big release! If you have any questions about this release, please come ask in the discord chat: http://discord.gg/graphile

PostGraphile is crowd-funded open source. We use the MIT license to give you freedom in how you use it, but you should support its development by sponsoring us: https://www.graphile.org/sponsor/

View announcement for a less technical summary!

Lets jump straight in:

🚨 IMPORTANT

When updating to this version, IF you use any third-party plugins, you MUST update them too and test your application - some PostGraphile internals have changed, and although they are undocumented (and thus do not constitute a breaking change) depending on the complexity of the plugins you use they may be affected. (See below for more info.)

You should also pin your GraphQL version as this release increases the supported GraphQL version range to include v14.x which has some breaking changes.

Massively improved serverless support

Thanks to funding from Connecting Good, running PostGraphile in serverless is a lot lower latency. It's now possible to webpack up PostGraphile nice and tight, resulting is much smaller .zip files to upload to Lambda (1/10th of the previous size); massively improved unzip time (milliseconds instead of seconds); and significantly reduced I/O time during startup, leading to sub-0.5s cold-starts when combined with our caching functionality.

Instructions and a demo on how to use this are available here:

https://github.com/graphile/postgraphile-lambda-example

A documentation article should be compiled in the coming months (when someone gets time...)

Massively improved PostgreSQL function support (thanks @mattbretl!)

Thanks to a Herculean effort from @mattbretl, we now have support for many more function shapes, including IN / OUT / INOUT parameters, and the RETURNS TABLE(...) return type.

This was a massive (MASSIVE!) pull request, with a tonne of back-and-forth, and an incredibly large number of edge cases; so please do pop onto the Discord chat and congratulate Matt on a job well done!

If for some bizarre reason you don't want this awesome new functionality, Matt has even added a way for you to opt out via the --legacy-functions-only CLI flag.

--no-ignore-indexes

Following on from --no-ignore-rbac; you can now opt in to --no-ignore-indexes. If you saw my talk at GraphQL Finland you'll understand that it's very important that we only expose what the server can fulfil efficiently; this option helps you to adhere to this by not exposing relations or filters that don't have associated indexes.

It's also nice for just tidying up your GraphQL schema - you don't really want to be able to do a condition on a JSON column do you? 😁

Enhanced PostGraphiQL (header editing, prettier GraphQL, links, logo!)

Run PostGraphile with --enhance-graphiql (or enhanceGraphiql: true) and you'll get a few enhancements to GraphiQL:

  • The "Prettify" button now uses prettier under the hood, leading to much nicer GraphQL formatting
  • New "Headers" button allows you to modify the headers (e.g. to set a JWT!)
  • Links to PostGraphile docs and examples
  • Most importantly: we have a logo now, and the favicon has been updated 😂

New Plugins

Easily wrap a resolver:

module.exports = makeWrapResolversPlugin({
  User: {
    async email(resolve, source, args, context, resolveInfo) {
      const result = await resolve();
      return result.toLowerCase();
    }
  }
});

Easily change the nullability (true = nullable, false = non-nullable) of fields in your GraphQL:

module.exports = makeChangeNullabilityPlugin({
  User: {
    email: true,
  },
})

Process your entire GraphQL schema via a plugin; great for adding third-party enhancements such as graphql-shield.

module.exports = makeProcessSchemaPlugin(schema => {
  return addThirdPartyEnhancementsToSchema(schema);
});

GraphQL v14 support

We've split PostGraphiQL from the rest of PostGraphile, which has allowed us to add support for GraphQL v14 whilst still using GraphQL v0.13 with GraphiQL. GraphQL v14 has a number of breaking changes; so...

🚨 ...we recommend that you keep GraphQL pinned at whatever the current version is that you're using, but still upgrade PostGraphile.

🚨 The latest GraphQL spec changes how errors are handled. PostGraphile has embraced this, and error from --extended-errors are now located in error.extensions.exception. In order to maintain backwards compatibility (as this is only a minor release) we still expose these properties in the old location too, but version 5 will only expose the new interface (error.extensions.*) so it's advised that you move your client code over to the new format ASAP. (Even if we remove the old format, you'll still be able to add it back via a handleErrors callback, but you should probably follow the GraphQL spec too!)

Mounting PostGraphile middleware under a subpath

This isn't officially supported; however it should work a lot better now. If you're mounting under a subpath in express then app.use("/path/to", postgraphile()) should work automatically without requiring any options. If you're using an external proxy then you must supply the base URL so that PostGraphile knows where to tell the browser the assets are located. This is all so that PostGraphile can reference different parts of itself correctly, such as the watch stream to put in the header, or the GraphQL endpoint for GraphiQL to connect to.

e.g.:

// Assuming you combine both Express subpath AND an external
// proxy which mounts your express app at `/myproxypath`, you
// should provide options like this:
app.use('/path/to', postgraphile(db, schemas, {
  externalUrlBase: '/myproxypath/path/to',
  graphqlRoute: '/graphql',
  graphiql: true,
  graphiqlRoute: '/graphiql',
}));
// Then you can load GraphiQL at `/myproxypath/path/to/graphiql`
// and it will know to connect to GraphQL at
// `/myproxypath/path/to/graphql`

Edge-case fix

Amazingly @tim-field discovered an issue that has never come up in the year of testing PostGraphile went through, which has required a little bit of restructuring of PostGraphile internals - we've mostly removed the recurseDataGeneratorsForField internal API. This has meant that the generated SQL queries are now a little differently structured, particularly when it comes to connections and mutations; as such, some third-party plugins might need some minor tweaks. If you have a plugin affected by this, please reach out to me on Discord and I'll do my best to guide you through fixing it: http://discord.gg/graphile

🚨 We've mostly removed the recurseDataGeneratorsForField internal API.

Plugins, such as filter plugins, that merely adjust the where clause should be unaffected.

Plugins implemented via makeExtendSchemaPlugin following the documentation should be safe in most cases, however if you use the @recurseDataGenerators directive then you should change your plugin to follow the new documentation to avoid a warning message (namely: change the @recurseDataGenerators directive to @pgField, and return the data property from your resolver). If your makeExtendSchemaPlugin does not use @recurseDataGenerators then you should be fine.

🚨 Plugins that wrap existing resolvers and either depend on or change the resulting data will probably need testing as the structure of the data returned from these has changed slightly.

Other changes in this release

  • Minor performance improvements
  • Massively improved SQL debugging
  • New DEBUG="postgraphile:postgres:notice" envvar for outputting notices from your PostgreSQL functions (thanks @arshadkazmi42!)
  • Better error messages when fields clash
  • "JWT expired" errors now output "401 authorization error" in the server log to help you figure out what went wrong
  • Now possible to pass true as the second argument to makeAddInflectorsPlugin in order to replace existing inflectors
  • You no longer need to list three plugins to skip the node interface, --skip-plugins graphile-build:NodePlugin should be sufficient
  • Lots of typo and similar fixes from the community (thanks @V1shvesh, @dargmuesli )
  • Fix a dependency issue (thanks @leoschweizer)
  • Fix an issue in error handling in the generated pg.Pool when the PostgreSQL connection drops.
  • Moved /_postgraphile/stream to ${graphqlRoute}/stream (i.e. /graphql/stream); but don't hard-code this - use the X-GraphQL-Event-Stream header.
  • pgSkipInstallingWatchFixtures Graphile Engine setting to allow you to skip the warning if you're using PostGraphile in the recommended way (i.e. NOT using a superuser account!)
  • Overriding how nodeIds are formed is now possible thanks to a refactor PR from @alexppxela
  • Plugins can now check for other plugins and version ranges (thanks to @mattbretl)
  • Now support overriding NULLS FIRST / NULLS LAST when ordering engine #332 (thanks to @mattbretl)
  • @deprecated smart-comment support has been extended to tables, functions and constraints engine #340 (thanks to @mattbretl)
  • graphile-utils now merges its helpers into resolveInfo (immutably) to avoid adding an extra argument
  • Fixed a possible TypeScript issue with graphql-parse-resolve-info
  • Added a couple headers to help you avoid click-jacking attacks
  • Now feature a random sponsor each time the PostGraphile CLI is executed! 🙏 Thanks sponsors!
  • Added tests for using PostGraphile with Fastify server
  • Improved startup time
  • Fixes an issues with unique orderings not being detected and causing performance woes
  • Enhances the formatting of SQL queries in debug output
  • Fixes an issue where the nullability of elements in nodes list and the edges.node entry did not match for functions which return a set of scalars (e.g. RETURNS SETOF int)

Don't miss a new crystal release

NewReleases is sending notifications on new releases.