Finish webhooks management POC

This commit is contained in:
Krzysztof Wolski 2023-06-26 12:34:06 +02:00
parent 7efa970079
commit bd757776f2
6 changed files with 293 additions and 0 deletions

View file

@ -8,6 +8,7 @@ import { hideBin } from "yargs/helpers";
import { installAppCommand } from "./commands/install-app-command";
import { uninstallAppCommand } from "./commands/uninstall-app-command";
import "dotenv/config";
import { webhooksCommand } from "./commands/webhooks-command";
const require = createRequire(import.meta.url);
const pkg = require("../package.json");
@ -117,6 +118,35 @@ const parser = yargs(hideBin(process.argv))
});
}
)
.command(
"webhooks",
"Print webhook details of installed app.",
(yargs) => {
return yargs
.option("instanceUrl", {
type: "string",
desc: "URL to the Saleor GraphQL API. Example: https://example.com/graphql/",
demandOption: true,
})
.option("userEmail", {
type: "string",
desc: "Dashboard user email",
demandOption: true,
})
.option("userPassword", {
type: "string",
desc: "Dashboard user password",
demandOption: true,
});
},
(argv) => {
webhooksCommand({
instanceUrl: argv.instanceUrl,
userEmail: argv.userEmail,
userPassword: argv.userPassword,
});
}
)
.demandCommand(1, "You need at least one command before moving on")
.alias("h", "help")
.wrap(null);

View file

@ -50,6 +50,11 @@ export const uninstallAppCommand = async ({
appListSpinner.succeed();
if (!installedApps.length) {
console.log("No apps installed");
return;
}
// Display CLI interface with multiselect if none of the filters were provided
if (appId || appName || manifestUrl) {
const filteredApps = filterApps({

View file

@ -0,0 +1,120 @@
import ora from "ora";
import { getAccessTokenMutation } from "../saleor-api/operations/get-access-token-mutation";
import { getAppsListQuery } from "../saleor-api/operations/get-apps-list-query";
import { select } from "@inquirer/prompts";
import { getAppWebhooksQuery } from "../saleor-api/operations/get-app-webhooks-query";
import { removeWebhookMutation } from "../saleor-api/operations/remove-webhook-mutation";
interface DumpMetadataCommandArgs {
instanceUrl: string;
userEmail: string;
userPassword: string;
}
export const webhooksCommand = async ({
instanceUrl,
userEmail,
userPassword,
}: DumpMetadataCommandArgs) => {
const loginSpinner = ora("Logging into Saleor instance").start();
const token = await getAccessTokenMutation({
email: userEmail,
password: userPassword,
saleorApiUrl: instanceUrl,
});
loginSpinner.succeed();
const appListSpinner = ora("Fetching installed apps").start();
const installedApps = await getAppsListQuery({
saleorApiUrl: instanceUrl,
token,
});
appListSpinner.succeed();
if (!installedApps.length) {
console.log("No apps installed");
return;
}
const appId = await select({
message: "Select app",
choices: installedApps.map((app) => ({
name: app.name ? `${app.name} (${app.id})` : app.id,
value: app.id,
})),
});
const webhooksData = await getAppWebhooksQuery({
appId,
saleorApiUrl: instanceUrl,
token,
});
if (!webhooksData.length) {
console.log("Application has no webhooks configured");
return;
}
const webhook = await select({
message: "Select webhook to investigate",
choices: webhooksData.map((webhook) => ({
name: `${webhook.name} (${[...webhook.syncEvents, ...webhook.asyncEvents]
.map((e) => e.name)
.join(", ")})`,
value: webhook,
description: `
Target url: ${webhook.targetUrl}
Active: ${webhook.isActive}
Captured event deliveries count: ${webhook.eventDeliveries?.edges.length}
`,
})),
});
const operation = await select({
message: "Operation",
choices: [
{
name: "List event deliveries",
value: "list",
},
{
name: "Remove webhook",
value: "remove",
},
],
});
if (operation === "list") {
console.log("Number of entries: ", webhook.eventDeliveries?.edges.length);
for (const deliveryEdge of webhook.eventDeliveries?.edges ?? []) {
const delivery = deliveryEdge.node;
console.log(`
Event type: ${delivery.eventType}
Created at: ${delivery.createdAt}
Status: ${delivery.status}`);
const attempts = delivery.attempts?.edges ?? [];
const lastAttempt = attempts[attempts.length - 1]?.node;
if (lastAttempt) {
console.log(`
Date of the last attempt: ${lastAttempt.createdAt}
Status: ${lastAttempt.status}`);
}
}
} else if (operation === "remove") {
const removeSpinner = ora("Removing webhook...").start();
await removeWebhookMutation({
saleorApiUrl: instanceUrl,
token,
webhookId: webhook.id,
});
removeSpinner.succeed();
}
};

View file

@ -0,0 +1,31 @@
import request from "graphql-request";
import { graphql } from "../generated/gql";
const getAppMetadataQueryDocument = graphql(/* GraphQL */ `
query GetAppMetadata {
app(id: "QXBwOjE=") {
metadata {
key
value
}
}
}
`);
export const getAppMetadataQuery = async ({
saleorApiUrl,
token,
}: {
saleorApiUrl: string;
token: string;
}) => {
const { app } = await request(
saleorApiUrl,
getAppMetadataQueryDocument,
{},
{ "Authorization-Bearer": token }
);
return app?.metadata ?? [];
};

View file

@ -0,0 +1,67 @@
import request from "graphql-request";
import { graphql } from "../generated/gql";
const getAppWebhooksQueryDocument = graphql(/* GraphQL */ `
query GetAppWebhooks($id: ID!) {
app(id: $id) {
webhooks {
id
name
isActive
syncEvents {
name
eventType
}
asyncEvents {
name
eventType
}
targetUrl
eventDeliveries(first: 10) {
edges {
node {
id
createdAt
status
eventType
attempts(first: 10) {
edges {
node {
id
createdAt
taskId
duration
response
status
}
}
}
}
}
}
}
}
}
`);
export const getAppWebhooksQuery = async ({
saleorApiUrl,
token,
appId,
}: {
saleorApiUrl: string;
token: string;
appId: string;
}) => {
const { app } = await request(
saleorApiUrl,
getAppWebhooksQueryDocument,
{
id: appId,
},
{ "Authorization-Bearer": token }
);
return app?.webhooks ?? [];
};

View file

@ -0,0 +1,40 @@
import request from "graphql-request";
import { graphql } from "../generated/gql";
const removeWebhookMutationDocument = graphql(/* GraphQL */ `
mutation RemoveWebhook($webhookId: ID!) {
webhookDelete(id: $webhookId) {
errors {
field
message
}
}
}
`);
export const removeWebhookMutation = async ({
saleorApiUrl,
token,
webhookId,
}: {
saleorApiUrl: string;
token: string;
webhookId: string;
}) => {
const { webhookDelete } = await request(
saleorApiUrl,
removeWebhookMutationDocument,
{
webhookId,
},
{ "Authorization-Bearer": token }
);
if (webhookDelete?.errors.length) {
console.log("Sth went wrong", webhookDelete.errors);
throw new Error(`Remove webhook mutation failed`);
}
return;
};