Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion schema.sql
Original file line number Diff line number Diff line change
@@ -1 +1,19 @@
-- Create your database schema here
create type item_type as enum (
'TOPIC'
);

create table relational_items (
id serial primary key,
type item_type not null default 'TOPIC'::item_type,
deleted_at timestamp with time zone
);

create table relational_topics (
id int primary key references relational_items,
title text not null
);

comment on table relational_items is $$
@interface mode:relational type:type
@type TOPIC references:relational_topics
$$;
65 changes: 63 additions & 2 deletions src/graphile.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,57 @@ import { PgAggregatesPreset } from "@graphile/pg-aggregates";
import { PgManyToManyPreset } from "@graphile-contrib/pg-many-to-many";
// import { PgSimplifyInflectionPreset } from "@graphile/simplify-inflection";
import PersistedPlugin from "@grafserv/persisted";
import { PgOmitArchivedPlugin } from "@graphile-contrib/pg-omit-archived";
import {
PgOmitArchivedPlugin,
custom as customPgOmitArchived,
} from "@graphile-contrib/pg-omit-archived";
import { dirname } from "path";
import { fileURLToPath } from "url";
import type { PgSQL, SQL } from "postgraphile/pg-sql2";

declare global {
namespace GraphileBuild {
interface SchemaOptions {
/**
* The name of the column to use to determine if the record is archived
* or not. Defaults to 'is_archived'
*/
pgDeletedColumnName?: string;
/**
* Set this true to invert the column logic - i.e. if your column is
* `is_visible` instead of `is_archived`.
*/
pgDeletedColumnImpliesVisible?: boolean;
/**
* If your determination of whether a record is archived or not is more complex
* than checking if a column is not null/not false then you can define an SQL
* expression instead.
*/
pgDeletedExpression?: (sql: PgSQL, tableAlias: SQL) => SQL;
/**
* The default option to use for the 'includeDeleted' argument. Defaults
* to 'NO', but will be replaced with 'INHERIT' where possible unless you set
* `pgDeletedDefaultInherit` to false.
*/
pgDeletedDefault?: "INHERIT" | "NO" | "YES" | "EXCLUSIVELY";
/**
* Set false if you don't want the system to default to 'INHERIT' if it's
* able to do so.
*/
pgDeletedDefaultInherit?: boolean;
/**
* Set true if you want related record collections to have the
* pg-omit-archived behavior if they belong to a table that explicitly
* matches.
*/
pgDeletedRelations?: boolean;
/**
* If you want the system to apply the archived filter to a specific list of tables, list their names here:
*/
pgDeletedTables?: string[];
}
}
}

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
Expand All @@ -33,7 +81,12 @@ const preset: GraphileConfig.Preset = {
PgAggregatesPreset,
// PgSimplifyInflectionPreset
],
plugins: [PersistedPlugin.default, PgOmitArchivedPlugin, TagsFilePlugin],
plugins: [
PersistedPlugin.default,
PgOmitArchivedPlugin,
customPgOmitArchived("deleted"),
TagsFilePlugin,
],
pgServices: [
makePgService({
// Database connection string:
Expand All @@ -56,6 +109,14 @@ const preset: GraphileConfig.Preset = {
grafast: {
explain: true,
},
schema: {
pgDeletedColumnName: "deleted_at",
pgDeletedColumnImpliesVisible: false,
pgDeletedRelations: false,
pgDeletedDefaultInherit: true,
pgDeletedDefault: "NO",
pgDeletedTables: [],
},
};

export default preset;
3 changes: 3 additions & 0 deletions src/server-express.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import express from "express";
import { grafserv } from "postgraphile/grafserv/express/v4";
import { postgraphile } from "postgraphile";
import preset from "./graphile.config.ts";
import { test } from "./test.ts";

// Create an express app
const app = express();
Expand All @@ -24,3 +25,5 @@ const server = app.listen(port, host, () => {
// Mount our Grafserv instance into our Express app, passing the HTTP server so
// we can attach websocket support.
serv.addTo(app, server);

test(await serv.getSchema(), serv.getPreset());
36 changes: 36 additions & 0 deletions src/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { grafast } from "postgraphile/grafast";
import type { GraphQLSchema } from "postgraphile/graphql";

/**
* Should print "column __relational_topics__.deleted_at does not exist" error
* @param schema
* @param resolvedPreset
*/
export async function test(
schema: GraphQLSchema,
resolvedPreset: GraphileConfig.ResolvedPreset
) {
const result = await grafast({
schema,
source: `query MyQuery {
allRelationalTopics {
nodes {
title
}
}
}`,
rootValue: null,
contextValue: {},
variableValues: {},
operationName: null,
resolvedPreset,
requestContext: {},
});
if (Symbol.asyncIterator in result) {
console.log("Async iterator result");
} else if (result.errors) {
console.error(result.errors);
} else {
console.log("Success");
}
}