Skip to content

Instantly share code, notes, and snippets.

@hos
Created March 16, 2023 12:42
Show Gist options
  • Save hos/c9f36090d08f3c91e5da8f8b8482b7ed to your computer and use it in GitHub Desktop.
Save hos/c9f36090d08f3c91e5da8f8b8482b7ed to your computer and use it in GitHub Desktop.
import { jsonParse } from "@dataplan/json";
import { access, context, lambda, listen } from "grafast";
import { gql, makeExtendSchemaPlugin } from "graphile-utils";
import { SCHEMA_NAME } from "../config.js";
/* The JSON object that `tg__graphql_subscription()` delivers via NOTIFY */
interface TgGraphQLSubscriptionPayload {
event: string;
subject: string | null;
[key: string]: string | null;
}
const StorySubscriptionPlugin = makeExtendSchemaPlugin((build) => {
const { sql } = build;
if (!sql) {
throw new Error("sql not found");
}
const currentUserIdSource = build.input.pgSources.find((s) => s.name === "current_user_id");
if (!currentUserIdSource) {
throw new Error("Couldn't find current_user_id source");
}
const storySource = build.input.pgSources.find(
(s) => !s.parameters && s.extensions?.pg?.schemaName === SCHEMA_NAME && s.extensions.pg.name === "stories"
);
if (!storySource) {
throw new Error("Couldn't find source for app_public.stories");
}
const seasonSource = build.input.pgSources.find(
(s) => !s.parameters && s.extensions?.pg?.schemaName === SCHEMA_NAME && s.extensions.pg.name === "seasons"
);
if (!seasonSource) {
throw new Error("Couldn't find source for app_public.seasons");
}
const episodeSource = build.input.pgSources.find(
(s) => !s.parameters && s.extensions?.pg?.schemaName === SCHEMA_NAME && s.extensions.pg.name === "episodes"
);
if (!episodeSource) {
throw new Error("Couldn't find source for app_public.episodes");
}
return {
typeDefs: gql`
type StorySubscriptionPayload {
story: Story!
season: Season
episode: Episode
# This is returned directly from the PostgreSQL subscription payload (JSON object)
event: String
}
input StorySubscriptionInput {
storyId: String!
}
extend type Subscription {
"""
Triggered when the episode data changes:
- direct modifications to the user
- when their organization membership changes
"""
storyUpdated(input: StorySubscriptionInput): StorySubscriptionPayload
}
`,
plans: {
Subscription: {
storyUpdated: {
subscribePlan(_root, $args) {
const $input = $args.get("input");
const $pgSubscriber = context().get("pgSubscriber");
const $decodedToken = context().get("decodedToken");
const $topic = lambda([$input, $decodedToken], ([input, decodedToken]) => {
debugger;
return `graphql:story:${input.storyId}`;
});
return listen($pgSubscriber, $topic, (e) => {
return e;
});
},
plan($e) {
return jsonParse<TgGraphQLSubscriptionPayload>($e);
},
},
StorySubscriptionPayload: {
story($obj) {
debugger;
const $id = access($obj, "storyId");
return storySource.get({ id: $id });
},
season($obj) {
debugger;
const $id = access($obj, "seasonId");
return storySource.get({ id: $id });
},
episode($obj) {
debugger;
const $id = access($obj, "episodeId");
return storySource.get({ id: $id });
},
},
},
},
};
});
const StoryPlugin: GraphileConfig.Preset = {
plugins: [StorySubscriptionPlugin],
};
export default StoryPlugin;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment