Skip to content

New Components - guru #16623

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 13, 2025
Merged
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
3 changes: 0 additions & 3 deletions components/guru/.gitignore

This file was deleted.

37 changes: 37 additions & 0 deletions components/guru/actions/add-tag-to-card/add-tag-to-card.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import guru from "../../guru.app.mjs";

export default {
key: "guru-add-tag-to-card",
name: "Add Tag to Card",
description: "Links an existing tag to a specified card in Guru. [See the documentation](https://developer.getguru.com/reference/getv1cardsgetextendedfact)",
version: "0.0.1",
type: "action",
props: {
guru,
cardId: {
propDefinition: [
guru,
"cardId",
],
},
tags: {
propDefinition: [
guru,
"tags",
],
type: "string",
label: "Tag",
description: "The ID of the tag to add to the card",
},
},
async run({ $ }) {
const response = await this.guru.linkTagToCard({
$,
cardId: this.cardId,
tagId: this.tags,
});

$.export("$summary", `Successfully linked tag ${this.tags} to card ${this.cardId}`);
return response;
},
};
70 changes: 70 additions & 0 deletions components/guru/actions/create-card/create-card.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { SHARE_STATUS_OPTIONS } from "../../common/constants.mjs";
import { parseObject } from "../../common/utils.mjs";
import guru from "../../guru.app.mjs";

export default {
key: "guru-create-card",
name: "Create Card",
description: "Creates a new card on your Guru account. [See the documentation](https://developer.getguru.com/reference/postv1cardscreateextendedfact)",
version: "0.0.1",
type: "action",
props: {
guru,
title: {
type: "string",
label: "Card Title",
description: "The title of the card to create",
},
content: {
type: "string",
label: "Content",
description: "The content of the card to create",
},
shareStatus: {
type: "string",
label: "Share Status",
description: "The share status of the card.",
options: SHARE_STATUS_OPTIONS,
optional: true,
},
collection: {
propDefinition: [
guru,
"collection",
],
},
folderIds: {
propDefinition: [
guru,
"folderIds",
],
},
tags: {
propDefinition: [
guru,
"tags",
],
optional: true,
},
},
async run({ $ }) {
const response = await this.guru.createCard({
$,
data: {
preferredPhrase: this.title,
content: this.content,
shareStatus: this.shareStatus,
collection: {
id: this.collection,
},
folderIds: parseObject(this.folderIds),
tags: parseObject(this.tags)?.map((item) => ({
id: item,
})),
},
});

$.export("$summary", `Created card "${this.title}" successfully`);
return response;
},
};
41 changes: 41 additions & 0 deletions components/guru/actions/export-card-to-pdf/export-card-to-pdf.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import fs from "fs";
import stream from "stream";
import { promisify } from "util";
import guru from "../../guru.app.mjs";

export default {
key: "guru-export-card-to-pdf",
name: "Export Card to PDF",
description: "Export a specific card identified by its ID to a PDF file. [See the documentation](https://developer.getguru.com/docs/download-cards-to-pdf)",
version: "0.0.1",
type: "action",
props: {
guru,
cardId: {
propDefinition: [
guru,
"cardId",
],
},
},
async run({ $ }) {
const {
headers, data,
} = await this.guru.exportCardToPdf({
$,
cardId: this.cardId,
returnFullResponse: true,
});

const fileName = headers["content-disposition"]?.split("filename=")[1]?.split("/")[1].slice(0, -1);
const filePath = `/tmp/${fileName}`;

const pipeline = promisify(stream.pipeline);
await pipeline(data, fs.createWriteStream(filePath));

$.export("$summary", `Successfully exported card ID ${this.cardId} to PDF.`);
return {
filePath,
};
},
};
13 changes: 0 additions & 13 deletions components/guru/app/guru.app.ts

This file was deleted.

4 changes: 4 additions & 0 deletions components/guru/common/constants.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const SHARE_STATUS_OPTIONS = [
"TEAM",
"PRIVATE",
];
24 changes: 24 additions & 0 deletions components/guru/common/utils.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export const parseObject = (obj) => {
if (!obj) return undefined;

if (Array.isArray(obj)) {
return obj.map((item) => {
if (typeof item === "string") {
try {
return JSON.parse(item);
} catch (e) {
return item;
}
}
return item;
});
}
if (typeof obj === "string") {
try {
return JSON.parse(obj);
} catch (e) {
return obj;
}
}
return obj;
};
190 changes: 190 additions & 0 deletions components/guru/guru.app.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import { axios } from "@pipedream/platform";

export default {
type: "app",
app: "guru",
propDefinitions: {
collection: {
type: "string",
label: "Collection",
description: "The collection to create the card in",
async options() {
const data = await this.listCollections();

return data.map(({
id: value, name: label,
}) => ({
label,
value,
}));
},
},
folderIds: {
type: "string[]",
label: "Folder Ids",
description: "The IDs of the folders to create the card in",
async options() {
const data = await this.listFolders();

return data.map(({
id: value, title: label,
}) => ({
label,
value,
}));
},
},
tags: {
type: "string[]",
label: "Tags",
description: "The IDs of the tags to add to the card",
async options() {
const { team: { id: teamId } } = await this.whoAmI();
const data = await this.listTags({
teamId,
});

return data[0]?.tags.map(({
id: value, value: label,
}) => ({
label,
value,
}));
},
},
cardId: {
type: "string",
label: "Card ID",
description: "The ID of the card",
async options({ prevContext }) {
const {
data, headers,
} = await this.listCards({
params: {
token: prevContext.token,
},
});
let token;

if (headers.link) {
const link = headers.link.split(">")[0].slice(1);
const url = new URL(link);
const params = new URLSearchParams(url.search);
token = params.get("token");
}
return {
options: data.map(({
id: value, preferredPhrase: label,
}) => ({
label,
value,
})),
context: {
token,
},
};
},
},

folderId: {
type: "string",
label: "Folder ID",
description: "The ID of the folder to export to PDF",
},
},
methods: {
_baseUrl() {
return "https://api.getguru.com/api/v1";
},
_auth() {
return {
username: `${this.$auth.username}`,
password: `${this.$auth.api_key}`,
};
},
_makeRequest({
$ = this, path, ...opts
}) {
return axios($, {
url: this._baseUrl() + path,
auth: this._auth(),
...opts,
});
},
whoAmI(opts = {}) {
return this._makeRequest({
path: "/whoami",
...opts,
});
},
createCard(opts = {}) {
return this._makeRequest({
method: "POST",
path: "/cards/extended",
...opts,
});
},
linkTagToCard({
cardId, tagId, ...opts
}) {
return this._makeRequest({
method: "PUT",
path: `/cards/${cardId}/tags/${tagId}`,
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
...opts,
});
},
exportCardToPdf({
cardId, ...opts
}) {
return this._makeRequest({
path: `/cards/${cardId}/pdf`,
responseType: "stream",
...opts,
});
},
listCollections(opts = {}) {
return this._makeRequest({
path: "/collections",
...opts,
});
},
listFolders(opts = {}) {
return this._makeRequest({
path: "/folders",
...opts,
});
},
listTags({
teamId, ...opts
}) {
return this._makeRequest({
path: `/teams/${teamId}/tagcategories`,
...opts,
});
},
listCards(opts = {}) {
return this._makeRequest({
path: "/search/cardmgr",
returnFullResponse: true,
...opts,
});
},
createWebhook(opts = {}) {
return this._makeRequest({
method: "POST",
path: "/webhooks",
...opts,
});
},
deleteWebhook(webhookId) {
return this._makeRequest({
method: "DELETE",
path: `/webhooks/${webhookId}`,
});
},
},
};
Loading
Loading