pgSmartTags
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.
Recommended: TagsFilePlugin
We recommend the postgraphile.tags.json5 file to most
users; you can enable it by adding the TagsFilePlugin to your preset:
import { TagsFilePlugin } from "postgraphile/utils";
export default {
// ...
plugins: [TagsFilePlugin],
};
The below plugin generators can be helpful if you have more advanced needs than can be served by this plugin.
Smart tags plugin generators
pgSmartTags and jsonPgSmartTags are plugin generators
that allows you to easily apply smart tags to various PostgreSQL entities.
pgSmartTagsFromFileis the highest level function, and loads smart tags from a JSON5 file.jsonPgSmartTagsis likepgSmartTagsFromFile, except it allows you to specify the configuration object in code rather than via a JSON5 file.pgSmartTagsis the lowest level plugin, it allows you to apply smart tags to PostgreSQL entities that match your specified rules.
pgSmartTagsFromFile
Usage example:
import { PostGraphileAmberPreset } from "postgraphile/presets/amber";
import { pgSmartTagsFromFile } from "postgraphile/utils";
const SmartTagsPlugin = pgSmartTagsFromFile(
// JSON and JSONC are also JSON5 compatible, so you can use these extensions if you prefer:
"/path/to/my/tags.file.json5",
);
const preset: GraphileConfig.Preset = {
extends: [PostGraphileAmberPreset],
plugins: [
SmartTagsPlugin,
],
};
This plugin powers the postgraphile.tags.json5 file
enabled by TagsFilePlugin. You can use it multiple times to merge smart tags
from multiple files should you wish.
jsonPgSmartTags
This plugin generator takes a JSONPgSmartTags object, and adds the relevant
tags to the relevant entities referenced. It is what powers
pgSmartTagsFromFile above, but you can also use it in your own
PostGraphile schema plugins.
Importing
import { jsonPgSmartTags } from "postgraphile/utils";
Signature
function jsonPgSmartTags(
jsonOrThunk: ThunkOrDirect<PromiseOrDirect<JSONPgSmartTags | null>>,
subscribeToJSONUpdatesCallback?: SubscribeToJSONPgSmartTagsUpdatesCallback | null,
details?: { name?: string; description?: string; version?: string },
): GraphileConfig.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>;
Example
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.
Details
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 Build enters watch
mode, 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 pgSmartTagsFromFile, which monitors a JSON5 file for
changes and triggers the schema to refresh when this file changes.
pgSmartTags
This is a more versatile, but higher effort plugin generator that powers
jsonPgSmartTags. Rather than passing a configuration object, a list
of rules (or a single rule) is passed.
Importing
import { pgSmartTags } from "postgraphile/utils";
Signature
function pgSmartTags(
initialRules: ThunkOrDirect<
PromiseOrDirect<PgSmartTagRule | PgSmartTagRule[] | null>
>,
subscribeToUpdatesCallback?: SubscribeToPgSmartTagUpdatesCallback | null,
details?: { name?: string; description?: string; version?: string },
): GraphileConfig.Plugin;
interface PgSmartTagRule<
TKind extends PgSmartTagSupportedKinds = PgSmartTagSupportedKinds,
> {
serviceName?: string;
kind: TKind;
match: string | PgSmartTagFilterFunction<PgEntityByKind[TKind]>;
tags?: PgSmartTagTags;
description?: string;
}
type PgSmartTagFilterFunction<TEntity extends PgEntity> = (
input: TEntity,
) => boolean;
type UpdatePgSmartTagRulesCallback = (
ruleOrRules: PgSmartTagRule | PgSmartTagRule[] | null,
) => void;
type SubscribeToPgSmartTagUpdatesCallback = (
cb: UpdatePgSmartTagRulesCallback | null,
) => PromiseOrDirect<void>;
Details
Rules must specify a kind (class, attribute, constraint or procedure)
and a match which could be the identifier (following the same rules as for
jsonPgSmartTags) 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
a pg-introspection entity, and must return a boolean to say whether this
entity should be matched or not.
Like with jsonPgSmartTags, 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
jsonPgSmartTags.