This commit is contained in:
Stefan Pejcic
2024-11-07 19:03:37 +01:00
parent c6df945ed5
commit 09f9f9502d
2472 changed files with 620417 additions and 0 deletions

View File

@@ -0,0 +1,158 @@
import type { LogicalFilter, VariableOptions } from "@refinedev/core";
import camelcase from "camelcase";
import type { Client } from "graphql-ws";
import { singular } from "pluralize";
import { getOperationFields } from "../utils/graphql";
import { buildFilters } from "../utils";
export const generateCreatedSubscription = ({
resource,
filters,
meta,
}: any) => {
const gqlOperation = meta?.gqlQuery ?? meta?.gqlMutation;
const singularResourceName = camelcase(singular(resource), {
pascalCase: true,
});
const operationName = `Created${singularResourceName}`;
const operation = `created${singularResourceName}`;
const query = `
subscription ${operationName}($input: Create${singularResourceName}SubscriptionFilterInput) {
${operation}(input: $input) {
${getOperationFields(gqlOperation)}
}
}
`;
const variables: VariableOptions = {};
if (filters) {
variables["input"] = {
filter: buildFilters(
filters.filter((filter: LogicalFilter) => !filter.field.includes(".")),
),
};
}
return { query, variables, operation, operationName };
};
export const generateUpdatedSubscription = ({
id,
resource,
filters,
meta,
}: any) => {
const gqlOperation = meta?.gqlQuery ?? meta?.gqlMutation;
const singularResourceName = camelcase(singular(resource), {
pascalCase: true,
});
const operationName = `Updated${singularResourceName}`;
const operation = `updatedOne${singularResourceName}`;
const query = `
subscription ${operationName}($input: UpdateOne${singularResourceName}SubscriptionFilterInput) {
${operation}(input: $input) {
${getOperationFields(gqlOperation)}
}
}
`;
const variables: VariableOptions = {};
if (filters) {
variables["input"] = {
filter: buildFilters(
filters.filter((filter: LogicalFilter) => !filter.field.includes(".")),
),
};
}
if (id) {
variables["input"] = {
filter: {
id: { eq: id },
},
};
}
return { query, variables, operation, operationName };
};
export const generateDeletedSubscription = ({ resource, filters }: any) => {
const singularResourceName = camelcase(singular(resource), {
pascalCase: true,
});
const operationName = `Deleted${singularResourceName}`;
const operation = `deletedOne${singularResourceName}`;
const query = `
subscription ${operationName}($input: DeleteOne${singularResourceName}SubscriptionFilterInput) {
${operation}(input: $input) {
id
}
}
`;
const variables: VariableOptions = {};
if (filters) {
variables["input"] = {
filter: buildFilters(
filters.filter((filter: LogicalFilter) => !filter.field.includes(".")),
),
};
}
return { query, variables, operation, operationName };
};
export const generateSubscription = (
client: Client,
{ callback, params, meta }: any,
type: string,
) => {
const generatorMap: any = {
created: generateCreatedSubscription,
updated: generateUpdatedSubscription,
deleted: generateDeletedSubscription,
};
const { resource, filters, subscriptionType, id, ids } = params ?? {};
const generator = generatorMap[type];
const { operation, query, variables, operationName } = generator({
ids,
id,
resource,
filters,
meta,
subscriptionType,
});
const onNext = (payload: any) => {
callback(payload.data[operation]);
};
const unsubscribe = client.subscribe(
{ query, variables, operationName },
{
next: onNext,
error: console.error,
complete: () => null,
},
);
return unsubscribe;
};

View File

@@ -0,0 +1,74 @@
import type { LiveProvider } from "@refinedev/core";
import type { Client } from "graphql-ws";
import { generateSubscription } from "./helpers";
type SubscriptionAction = "created" | "updated" | "deleted";
export const createLiveProvider = (client: Client): LiveProvider => {
const subscribeToResource = (
client: Client,
callback: Function,
params: any,
meta: any,
action: SubscriptionAction,
resource: string,
unsubscribes: Function[],
) => {
const unsubscribe = generateSubscription(
client,
{ callback, params, meta },
action,
);
unsubscribes.push(unsubscribe);
};
return {
subscribe({ callback, params, meta }) {
const { resource, subscriptionType } = params ?? {};
if (!meta || !subscriptionType || !resource) {
throw new Error(
"[useSubscription]: `meta`, `subscriptionType` and `resource` are required in `params` for graphql subscriptions",
);
}
const unsubscribes: any[] = [];
if (params?.subscriptionType === "useList") {
["created", "updated", "deleted"].forEach((action) =>
subscribeToResource(
client,
callback,
params,
meta,
action as SubscriptionAction,
resource,
unsubscribes,
),
);
}
if (params?.subscriptionType === "useOne") {
subscribeToResource(
client,
callback,
params,
meta,
"updated",
resource,
unsubscribes,
);
}
const unsubscribe = () => {
unsubscribes.forEach((unsubscribe) => unsubscribe());
};
return unsubscribe;
},
unsubscribe(unsubscribe) {
unsubscribe();
},
};
};