Skip to content

Releases: graphile/crystal

v4.3.3: patch issue with DEBUG + pgPool.query

05 Feb 18:24
Compare
Choose a tag to compare

Fixes an issue one of the PostGraphile sponsors had where sharing the PgPool between their own code and PostGraphile, using pgPool.query, and setting DEBUG with the SQL-outputting debug variables caused an error to be produced. #987

v4.3.2 - GraphiQL Explorer

30 Jan 10:27
Compare
Choose a tag to compare

The lovely folks over at OneGraph sent a PR to integrate their GraphiQL Explorer into PostGraphile — this awesome feature really helps users get started with GraphQL. Make sure you're using --enhance-graphiql to use it! #981

image

Additionally @mlipscombe discovered an issue where your PgPool could become exhausted if an enough errors were thrown on COMMIT, and sent over a PR to fix: #978

v4.3.1 - filterable and sortable functions, fixed complex ranges

24 Jan 14:17
Compare
Choose a tag to compare

Important note: pgInflection should not appear anywhere in your code or that of your plugins; see below. (If it does, you'll get some warning messages, but things should continue to work for the time being.)

The main feature in this release is you can now opt-in to filtering and sorting function results (so long as they return setof table type), and enabling you to filter-by and sort-by scalar computed columns. This is opt-in behaviour on a per-function basis using smart comments because if used incautiously it could result in significant performance woes (basically: in many cases database functions are black boxes to PostgreSQL, so the full function result may have to be calculated before it can then be sorted, and if it returns millions of rows that might take a moment).

Also in this release are a number of small fixes and enhancements detailed below. See the 🚨 for a fix that may impact your schema if you were relying on broken behaviour.

PostGraphile is crowd-funded, we ask the individuals and businesses that use PostGraphile to please sponsor ongoing maintenance and development.

  • functions can now be opted into filtering and sorting via @filterable and @sortable smart comments; you can also mark the result as non-nullable via @notNull smart comment (graphile/graphile-engine#378)
  • makeWrapResolversPlugin has been enhanced to allow wrapping all resolvers that match a filter function
  • makeAddInflectorsPlugin has been enhanced to allow you to access previous inflectors (e.g. if you only want to override them in certain circumstances)
  • yet more things are named via the inflector (and thus can have their names customised) including Query, Mutation and Subscription - just override the inflection.builtin(name) inflector
  • more server plugin hooks added, enabling custom logging and tweaking GraphiQL's HTML (e.g. to add dark mode)
  • accidentally passing undefined as any of PostGraphile's options now throws an error to help you more rapidly spot issues in your code (thanks @marshall007); the PostGraphile call signature has not changed
  • adds compatibility with intarray PostgreSQL extension
  • fixes formatting of PostgreSQL ranges, ranges that require extra processing (arbitrary precision numeric, bigint, timestamps) are now processed correctly (thanks @mathroc); 🚨 if you were using the broken ranges, please test related code
  • fixed typo where the CRUD plugins used pgInflection where they meant pgIntrospection; have kept the old name too to prevent this being a breaking change, but please update your plugins to use the correct name
  • the ancient inflection option to PostGraphile (which became pgInflection internally) that was deprecated in 4.0.0-beta.6 now generates warning messages if you use it, which you should not. Instead migrate to the plugin-capable inflection system
  • added additional index information to introspection in case your plugin needs that (@mlipscombe 😉 )
  • doc fixes (thanks @petetnt, @SiM07)
  • support for Windows CRLF line-breaks in smart comments

v4.3.0 (never @latest)

17 Jan 17:34
Compare
Choose a tag to compare

4.3.0 was never promoted to @latest due to a couple of issues:

  • more people (specifically, plugins) were using the long-deprecated pgInflector argument than expected; this has been restored in 4.3.1: graphile/graphile-engine#381
  • a small issue was introduced when implementing @sortable that broke a plugin; this is also resolved in 4.3.1: graphile/graphile-engine#386
  • too many new inflectors were introduced (all taking zero arguments); this has been replaced with a single builtin inflector: graphile/graphile-engine#387

We're going to look into extending the release tests to running against some popular community plugins to ensure future releases don't introduce backwards-incompatible changes. If you'd like your plugin to be included in this effort, please get in touch.

v4.2.0 - constraints on views / materialized views

19 Dec 18:57
Compare
Choose a tag to compare

Thanks to sponsorship from ULTA.io, this release introduces support for defining constraints (e.g. foreign keys, primary keys, etc) via "smart comments". This means that VIEWs and MATERIALIZED VIEWs can now act a lot more like regular tables when viewed by PostGraphile - you can define a @primaryKey for your view, or have a @foreignKey that references another table (or another view!). You can also mark fields as @notNull For more information, see the documentation:

Smart Comment Constraints

The other change in this release is that we now surface a warning message if a foreign key constraint is skipped because it lacks an index and you're using --no-ignore-indexes or ignoreIndexes: false.

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

31 Oct 22:00
Compare
Choose a tag to compare

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 featur...
Read more

v4.0.1 - display PG notices; query builder enhancement

08 Oct 12:58
Compare
Choose a tag to compare

Main feature in this release is added support for logging PG notices and improved support for logging PG errors - including additional metadata. Thanks to @arshadkazmi42 for working with me on this! Examples:

ERROR[ERR12]: Error Message Here! | WHERE: PL/pgSQL function a.generate_error(text) line 1 at RAISE | HINT: Help!
NOTICE[NOT23]: This is a notice. | WHERE: PL/pgSQL function a.generate_notice(text) line 1 at RAISE | HINT: Help!

To enable this, make sure you are using the debug envvars: export DEBUG="postgraphile:postgres:error,postgraphile:postgres:notice"; postgraphile ...

Also in this release is a tiny patch enabling plugin authors to reference the "parent" query builder from "child" query builders. This, for example, allows them to check a column from a parent record to decide which children to include. This is necessary for the @graphile-contrib/pg-omit-archived soft deletion plugin's INHERIT option.

This release also introduces another helper to graphile-utils: makePluginByCombiningPlugins - enabling you to bundle multiple plugins into one (particularly useful for combining makeAddInflectorsPlugin and makeExtendSchemaPlugin plugins with raw Graphile Engine plugins).

Finally it makes the terminology used more consistent - "Graphile Engine schema plugins" and "PostGraphile server plugins".

PostGraphile v4.0.0

02 Oct 13:50
Compare
Choose a tag to compare

After many months of development, testing and iteration it is my great pleasure to announce that PostGraphile v4 is officially available! All PostGraphile and PostGraphQL users are recommended to update to this version at their earliest convenience. A migration guide is available for PostGraphQL (v3), most users should find the upgrade fairly painless. A full feature guide is available detailing the various enhancements incorporated into PostGraphile v4.

A lot has changed in PostGraphile v4 (though it's still broadly compatible with version 3); here are some of the features I'm most excited about:

  • Incredible performance gains - up to 55× more requests per second, up to 92% RAM usage reduction, and up to 94% reduction in request latency
  • Much tidier GraphQL schemas
    • PostgreSQL extension resources omitted by default
    • with --no-ignore-rbac, types and fields you cannot access (according to PostgreSQL GRANTs) are removed automatically
    • new smart comments feature enables you to manually omit tables, columns and functions you don't want in your GraphQL schema (alternatively rename or deprecate them)
  • Plugins plugins plugins!
    • The entire PostGraphile schema is now generated from plugins
    • You can add, remove or replace plugins
    • We've written some helpers for common plugin desires:
    • Enhance your schema's functionality with some of the community's plugins, including new powerful filtering capabilities
  • Massively improved error messages (please file issues if you think we can improve these further!)
  • Cleaner support for one-to-one relationships
  • GraphQL query batching

The biggest change in v4 is that the entire GraphQL schema generation has been re-built from the ground up to be both highly performant and highly customisable. This has been enabled with the help of the plugin-based Graphile GraphQL Engine. A few members of the community have already written some interesting plugins for PostGraphile, and we're keen to see what others come up with in the coming months!

We've also fixed a huge number of issues that affected V3, updated various dependencies, added support for PG10 features and PG11, added support for query batching, added support for a cluster mode to better make use of your many server cores, added simplified collections so you can bypass edges/nodes if you want to, greatly improved support for PostgreSQL functions, made watch mode even more reliable and useful, added a --no-server option for schema export scripts, added cache functionality to skip database introspection on startup, configuration file support, better support for common environmental variables, bundled TypeScript typings and much much more!

Check out the v4 feature guide for a full list.

RC5: improved errors, PG10 identity column support

13 Sep 14:56
Compare
Choose a tag to compare

The biggest issue people tend to face when getting started with PostGraphile are name collisions - where something in your database causes the same name for a type or a field to be generated twice in the GraphQL schema PostGraphile generates, leading to a failure to start. Errors generated previously were pretty obtuse, we now output much more information when this happens, including what the source of the two conflicting names were, and even hinting how it might be possible to fix it using smart comments:

Error: A naming conflict has occurred - two entities have tried to define the same key 'query'.

  The first entity was:

    Default field included in newWithHooks call for 'Query'. graphile-build built-in (root query type)

  The second entity was:

    Adding row by globally unique identifier field for table "public"."query". You can rename this table via:

      COMMENT ON TABLE "public"."query" IS E'@name newNameHere';

These errors can clearly be enhanced further - if this is something that interests you please get in touch!

We've also squashed a few remaining bugs, and even added a new introspection template system so we can more easily support different PostgreSQL versions (thanks @mattbretl!).

Improvements:

  • Massively improved name collision errors (graphile/graphile-engine#292)
  • PG10 identity column support (and preliminary PG11 support) thanks to @mattbretl (graphile/graphile-engine#294)
  • Multi-column relations (foreign key (col_a, col_b) references other_table(col_1, col_2)) where the column spec ((col_a, col_b)) has a unique constraint now result in a one-to-one reference instead of a connection. (The connection still exists, but it's deprecated, so this is not a breaking change.) (graphile/graphile-engine#298)
  • Added --skip-plugins option to the CLI, and documented it in the middleware thanks to @mattbretl (#853)

Fixes:

  • When paginating backwards using a before cursor combined with last option over a connection without a unique ordering constraint (such as a function, or a table with no primary key) the hasNextPage entry in pageInfo would incorrectly return false; this is now fixed. (graphile/graphile-engine#297)
  • Fixes an issue that can lead to memory exhaustion
  • Passing -A '' to postgraphile now allows you to disable JWT audience validation (as the documentation claims). (#848)

🙏 Sponsor PostGraphile Development 🙏

RC4: GraphQL 0.13.x, improved TypeScript support

24 Aug 14:57
Compare
Choose a tag to compare

A recent influx of Patreon support has enabled me to spend an extra day on PostGraphile this month, so this release contains more enhancements than expected! Thanks so much, Patreon supporters!

The biggest change in this release is to the TypeScript support - if you use PostGraphile in a TypeScript project then please remove any custom declarations you may have written for postgraphile, postgraphile-core, graphile-build, graphile-build-pg, graphile-utils, pg-sql2 and graphql-parse-resolve-info - all of these now come with their own built in TypeScript type definitions! 🎊

  • GraphQL 0.13.x support! 🎉 (We were limited to 0.12.x before) - this should hopefully help people get started a lot easier due to fewer graphql module conflicts!

  • Better TypeScript support

    • We export more types for you to use
    • postgraphile-core, graphile-utils and graphql-parse-resolve-info have been ported to TypeScript
    • graphile-build and graphile-build-pg now export .d.ts files so they should automatically work with TypeScript (ultimately we plan to move these to TypeScript too)
    • Note TypeScript support is currently experimental - please get in touch if you have any TypeScript woes!
  • graphile-utils enhancements

    • enum support thanks to @bradleyayers
    • newly added fields can require that other columns on the parent table are fetched via @requires(columns: [...]) directive
  • support for a couple more PG types:

    • hstore support
    • inet support thanks to @syndesis
  • More information in some places for plugins to use

    • jwtClaims is now available on the GraphQL context, so your plugins can reference them (thanks to @hyperparsa)
    • nested QueryBuilder instances now have a reference to parentQueryBuilder
  • Better errors in a number of places

  • Improved CLI documentation / messages

  • Smart comments:

    • now lets you replace the GraphQL description on foreign key constraints: comment on constraint person_secret_person_id_fkey on c.person_secret is E'@forwardDescription The `Person` this `PersonSecret` belongs to.\n@backwardDescription This `Person`''s `PersonSecret`.';
    • lets you set a unique key for views, which enables more efficient cursor pagination
  • Many fixes, including:

    • enable update/delete mutations for tables lacking primary keys but which have unique constraints (note that a unique index is not sufficient, it must be a unique constraint)
    • fix bug in introspection query that could in some very rare circumstances cause tables or functions to be omitted from the generated schema
    • fixing a template string that accidentally had straight quotes (thanks @mathroc)
    • more useful error message when using legacy graphql versions with graphile-utils
    • fix bug in regex for validating long aliases
    • --watch mode now watches more things
    • --body-size-limit option now applies to all body types (previously they defaulted to 100kB across the board, and only JSON was overridden with this option)
  • We now accept the X-Apollo-Tracing header which means you should be able to use hosted GraphQL Playground with a PostGraphile schema (this was causing CORS issues before)