mirror of
https://github.com/stefanpejcic/openpanel
synced 2025-06-26 18:28:26 +00:00
packages
This commit is contained in:
158
packages/graphql/src/liveProvider/helpers.ts
Normal file
158
packages/graphql/src/liveProvider/helpers.ts
Normal 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;
|
||||
};
|
||||
74
packages/graphql/src/liveProvider/index.ts
Normal file
74
packages/graphql/src/liveProvider/index.ts
Normal 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();
|
||||
},
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user