Table of Contents
makePgSmartTagsPlugin (graphile-utils v4.5.0+)
Smart Tags enable you to customize how (or if) your PostgreSQL resources are represented in your PostGraphile GraphQL schema. Before reading this page, you should familiarize yourself with Smart Tags so that you know when and why you would use them.
makePgSmartTagsPlugin and makeJSONPgSmartTagsPlugin are plugin generators
that allows you to easily apply smart tags to various PostgreSQL entities.
makePgSmartTagsFromFilePluginis the highest level function, and loads smart tags from a JSON5 file.makeJSONPgSmartTagsPluginis likemakePgSmartTagsFromFilePlugin, except it allows you to specify the configuration object in code rather than via a JSON5 file.makePgSmartTagsPluginis the lowest level plugin, it allows you to apply smart tags to PostgreSQL entities that match your specified rules.
We recommend the postgraphile.tags.json5 file to most users; but the below plugin generators can be helpful if you have more advanced needs.
makePgSmartTagsFromFilePlugin
Unlike most other plugin generators, this plugin comes from
postgraphile/plugins. The reason it's not in graphile-utils is because it
needs to access the file-system.
const { makePgSmartTagsFromFilePlugin } = require("postgraphile/plugins");Usage example:
const SmartTagsPlugin = makePgSmartTagsFromFilePlugin(
// JSON and JSONC are also JSON5 compatible, so you can use these extensions if you prefer:
"/path/to/my/tags.file.json5"
);
// ...
app.use(
postgraphile(process.env.DATABASE_URL, "app_public", {
//...
appendPlugins: [SmartTagsPlugin],
})
);This plugin powers the automatic postgraphile.tags.json5 file support in PostGraphile CLI, and can be used as above for library users. You can even use it multiple times to merge smart tags from multiple files should you wish.
makeJSONPgSmartTagsPlugin
const { makeJSONPgSmartTagsPlugin } = require("graphile-utils");function makeJSONPgSmartTagsPlugin(
json: JSONPgSmartTags | null,
subscribeToJSONUpdatesCallback?: SubscribeToJSONPgSmartTagsUpdatesCallback | null
): Plugin;
type JSONPgSmartTags = {
version: 1;
config: {
[kind in PgSmartTagSupportedKinds]?: {
[identifier: string]: {
tags?: PgSmartTagTags;
description?: string;
attribute?: {
[attributeName: string]: {
tags?: PgSmartTagTags;
description?: string;
};
};
constraint?: {
[constraintName: string]: {
tags?: PgSmartTagTags;
description?: string;
};
};
};
};
};
};
type SubscribeToJSONPgSmartTagsUpdatesCallback = (
cb: UpdateJSONPgSmartTagsCallback | null
) => void | Promise<void>;This plugin generator takes a JSONPgSmartTags object, and adds the relevant
tags to the relevant entities referenced. It is what powers
makePgSmartTagsFromFilePlugin above, but you can also use it in your own
PostGraphile schema plugins.
An example of an empty JSONPgSmartTags object would be:
{
version: 1,
config: {
class: {},
attribute: {},
constraint: {},
procedure: {},
},
}A more in-depth example of this configuration file, with comments, is available in the postgraphile.tags.json5 file documentation.
Within the config object, we can add entries for each supported "kind" of PostgreSQL entity. The supported entities include:
class- for tables, views, materialized views, compound types and other table-like entities; things you'd find in thepg_classPostgreSQL system table.attribute- for columns/attributes of aclass; things you'd find in thepg_attributePostgreSQL system table.constraint- for constraints; things you'd find in thepg_constraintPostgreSQL system table.procedure- for functions and procedures; things you'd find in thepg_procPostgreSQL system table
The value for each of these kinds would be another object, keyed by the identifier of the PostgreSQL entity, then containing the configuration for that entity type. Identifiers for each entity type differ:
class-schema_name.table_nameattribute-schema_name.table_name.column_nameconstraint-schema_name.table_name.constraint_nameprocedure-schema_name.function_name(NOTE: since PostGraphile doesn't support function overloading, function parameters are not factored into the identifier.)
For each identifier, you may present the fully qualified form as shown above, or
you may drop the left most segments, e.g. a column id in table users in
schema app_public could be specified as app_public.users.id or users.id or
just id.
Where the form used is not fully qualified, the configuration will be applied to
all entities that match. For example if you wanted to omit create/update on all
created_at/updated_at columns across all your tables, the configuration
might look like:
{
version: 1,
config: {
attribute: {
created_at: { tags: { omit: "create,update" } },
updated_at: { tags: { omit: "create,update" } },
},
},
}The configuration object for each matched entity accepts the following parameters (all optional):
tags- a map of all the tags you wish to apply; these will be merged with the tags applied through other means (overwriting tags of the same name). See the Smart Tags documentation for more information about what tags are available, and what values they can have.description- a description to apply to this resource, equivalent to usingCOMMENT ONon the underlying PostgreSQL entity (except that Smart Comment parsing does not take place).
For the class entity type, the following convenience attributes are also
available to enable you to keep tables, columns and constraints configured in
the same location. When used, the column/constraint identifiers must not be
fully qualified, since the table identifier will be automatically prepended for
you.
attribute- for columnsconstraint- for constraints
To have this plugin work in watch mode, a subscribeToJSONUpdatesCallback
method can be passed as a second argument. If/when Graphile Engine enters watch
mode (e.g. via postgraphile --watch), this callback will be called, and it
will be passed a callback function that in turn must be called when a change
takes place. When watch mode is exited, the function will be called again
without a callback, and whatever was in place for watching must be released. An
example implementation of this can be found in makePgSmartTagsFromFilePlugin
in PostGraphile itself, which monitors a JSON5 file for changes and triggers the
schema to refresh when this file changes. See:
https://github.com/graphile/postgraphile/blob/9de271ecdddcd13fd42f8eac6777f0057ee8f7e7/src/plugins.ts#L23-L47
makePgSmartTagsPlugin
const { makePgSmartTagsPlugin } = require("graphile-utils");function makePgSmartTagsPlugin(
ruleOrRules: PgSmartTagRule | PgSmartTagRule[] | null,
subscribeToUpdatesCallback?: SubscribeToPgSmartTagUpdatesCallback | null
): Plugin;
interface PgSmartTagRule<T extends PgEntity = PgEntity> {
kind: PgEntityKind;
match: string | PgSmartTagFilterFunction<T>;
tags?: PgSmartTagTags;
description?: string;
}
type PgSmartTagFilterFunction<T> = (input: T, build: Build) => boolean;
type UpdatePgSmartTagRulesCallback = (
ruleOrRules: PgSmartTagRule | PgSmartTagRule[] | null
) => void;
type SubscribeToPgSmartTagUpdatesCallback = (
cb: UpdatePgSmartTagRulesCallback | null
) => void | Promise<void>;This is a more versatile, but higher effort plugin generator that powers
makeJSONPgSmartTagsPlugin. Rather than passing a configuration object, a list
of rules (or a single rule) is passed.
Rules must specify a kind (class, attribute, constraint or procedure)
and a match which could be the identifier (following the same rules as for
makeJSONPgSmartTagsPlugin) or a matcher function. The matcher function makes
this plugin generator incredibly powerful, for example it could be used to apply
tags to all PostgreSQL entities that match a particular criteria that does not
need to relate to the entity's name. The matcher function is passed the Graphile
Engine representation of the entity type (see
PgIntrospectionPlugin
for these definitions) and the Build object, and must return a boolean to say
whether this entity should be matched or not.
Like with makeJSONPgSmartTagsPlugin, the rule may also optionally supply the
tags Smart Tags object to be merged, and a description to overwrite the
previous description.
The plugin also supports a subscribeToUpdatesCallback to enable watch mode,
which works in the same way as subscribeToJSONUpdatesCallback from
makeJSONPgSmartTagsPlugin.
Source code
Please refer to https://github.com/graphile/graphile-engine/blob/master/packages/graphile-utils/src/makePgSmartTagsPlugin.ts, https://github.com/graphile/postgraphile/blob/9de271ecdddcd13fd42f8eac6777f0057ee8f7e7/src/plugins.ts#L23-L47 and https://github.com/graphile/graphile-engine/pull/541