Skip to content

Commit cac65df

Browse files
authored
New Components - bugsnag (#16866)
* new components * pnpm-lock.yaml * package.json * pnpm-lock.yaml * update prop description * pnpm-lock.yaml * pnpm-lock.yaml
1 parent 97e66e8 commit cac65df

File tree

15 files changed

+710
-20
lines changed

15 files changed

+710
-20
lines changed

components/bugsnag/.gitignore

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import bugsnag from "../../bugsnag.app.mjs";
2+
import constants from "../../common/constants.mjs";
3+
4+
export default {
5+
key: "bugsnag-create-project",
6+
name: "Create Project",
7+
description: "Create a new project for a specific organization in Bugsnag. [See the documentation](https://bugsnagapiv2.docs.apiary.io/#reference/projects/projects/create-a-project-in-an-organization)",
8+
version: "0.0.1",
9+
type: "action",
10+
props: {
11+
bugsnag,
12+
organizationId: {
13+
propDefinition: [
14+
bugsnag,
15+
"organizationId",
16+
],
17+
},
18+
name: {
19+
type: "string",
20+
label: "Project Name",
21+
description: "The name of the project",
22+
},
23+
type: {
24+
type: "string",
25+
label: "Project Type",
26+
description: "The new project's framework type",
27+
options: constants.PROJECT_TYPES,
28+
},
29+
ignoreOldBrowsers: {
30+
type: "boolean",
31+
label: "Ignore Old Browsers",
32+
description: "For javascript projects this will filter errors from older browsers",
33+
optional: true,
34+
},
35+
},
36+
async run({ $ }) {
37+
const response = await this.bugsnag.createProject({
38+
$,
39+
organizationId: this.organizationId,
40+
data: {
41+
name: this.name,
42+
type: this.type,
43+
ignore_old_browsers: this.ignoreOldBrowsers,
44+
},
45+
});
46+
47+
$.export("$summary", `Created project: ${this.name}`);
48+
return response;
49+
},
50+
};
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import bugsnag from "../../bugsnag.app.mjs";
2+
import constants from "../../common/constants.mjs";
3+
4+
export default {
5+
key: "bugsnag-update-error-severity",
6+
name: "Update Error Severity",
7+
description: "Update an the severity status of an error in Bugsnag. [See the documentation](https://bugsnagapiv2.docs.apiary.io/#reference/errors/errors/update-an-error)",
8+
version: "0.0.1",
9+
type: "action",
10+
props: {
11+
bugsnag,
12+
organizationId: {
13+
propDefinition: [
14+
bugsnag,
15+
"organizationId",
16+
],
17+
},
18+
projectId: {
19+
propDefinition: [
20+
bugsnag,
21+
"projectId",
22+
(c) => ({
23+
organizationId: c.organizationId,
24+
}),
25+
],
26+
},
27+
errorId: {
28+
propDefinition: [
29+
bugsnag,
30+
"errorId",
31+
(c) => ({
32+
projectId: c.projectId,
33+
}),
34+
],
35+
},
36+
severity: {
37+
type: "string",
38+
label: "Severity",
39+
description: "The Error's new severity. This will be reflected in the Error's `overridden_severity` property.",
40+
options: constants.ERROR_SEVERITIES,
41+
},
42+
},
43+
async run({ $ }) {
44+
const response = await this.bugsnag.updateError({
45+
$,
46+
projectId: this.projectId,
47+
errorId: this.errorId,
48+
data: {
49+
operation: "override_severity",
50+
severity: this.severity,
51+
},
52+
});
53+
54+
$.export("$summary", `Updated error ${this.errorId}`);
55+
return response;
56+
},
57+
};

components/bugsnag/app/bugsnag.app.ts

Lines changed: 0 additions & 13 deletions
This file was deleted.

components/bugsnag/bugsnag.app.mjs

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
import { axios } from "@pipedream/platform";
2+
3+
export default {
4+
type: "app",
5+
app: "bugsnag",
6+
propDefinitions: {
7+
organizationId: {
8+
type: "string",
9+
label: "Organization ID",
10+
description: "The ID of an organization",
11+
async options() {
12+
const organizations = await this.listOrganizations();
13+
return organizations?.map(({
14+
id: value, name: label,
15+
}) => ({
16+
value,
17+
label,
18+
})) || [];
19+
},
20+
},
21+
projectId: {
22+
type: "string",
23+
label: "Project ID",
24+
description: "The ID of a project",
25+
async options({
26+
organizationId, prevContext,
27+
}) {
28+
const args = {
29+
organizationId,
30+
returnFullResponse: true,
31+
};
32+
if (prevContext?.next) {
33+
args.url = prevContext.next;
34+
}
35+
const {
36+
data, headers,
37+
} = await this.listProjects(args);
38+
let next;
39+
if (headers?.link) {
40+
next = this.getNextLink(headers.link);
41+
}
42+
return {
43+
options: data?.map(({
44+
id: value, name: label,
45+
}) => ({
46+
value,
47+
label,
48+
})) || [],
49+
context: {
50+
next,
51+
},
52+
};
53+
},
54+
},
55+
errorId: {
56+
type: "string",
57+
label: "Error ID",
58+
description: "The ID of the error",
59+
async options({
60+
projectId, prevContext,
61+
}) {
62+
const args = {
63+
projectId,
64+
returnFullResponse: true,
65+
};
66+
if (prevContext?.next) {
67+
args.url = prevContext.next;
68+
}
69+
const {
70+
data, headers,
71+
} = await this.listErrors(args);
72+
let next;
73+
if (headers?.link) {
74+
next = this.getNextLink(headers.link);
75+
}
76+
return {
77+
options: data?.map(({
78+
id: value, message: label,
79+
}) => ({
80+
value,
81+
label,
82+
})) || [],
83+
context: {
84+
next,
85+
},
86+
};
87+
},
88+
},
89+
releaseStage: {
90+
type: "string",
91+
label: "Release Stage",
92+
description: "The release stage",
93+
},
94+
},
95+
methods: {
96+
_baseUrl() {
97+
return "https://api.bugsnag.com";
98+
},
99+
_makeRequest({
100+
$ = this, url, path, ...opts
101+
}) {
102+
return axios($, {
103+
url: url || `${this._baseUrl()}${path}`,
104+
headers: {
105+
"Authorization": `token ${this.$auth.api_token}`,
106+
},
107+
...opts,
108+
});
109+
},
110+
getNextLink(linkHeader) {
111+
const match = linkHeader.match(/<([^>]+)>;\s*rel="next"/); // get link to next page
112+
return match
113+
? match[1]
114+
: null;
115+
},
116+
listOrganizations(opts = {}) {
117+
return this._makeRequest({
118+
path: "/user/organizations",
119+
...opts,
120+
});
121+
},
122+
listProjects({
123+
organizationId, ...opts
124+
}) {
125+
return this._makeRequest({
126+
path: `/organizations/${organizationId}/projects`,
127+
...opts,
128+
});
129+
},
130+
listErrors({
131+
projectId, ...opts
132+
}) {
133+
return this._makeRequest({
134+
path: `/projects/${projectId}/errors`,
135+
...opts,
136+
});
137+
},
138+
listEvents({
139+
projectId, ...opts
140+
}) {
141+
return this._makeRequest({
142+
path: `/projects/${projectId}/events`,
143+
...opts,
144+
});
145+
},
146+
listReleases({
147+
projectId, ...opts
148+
}) {
149+
return this._makeRequest({
150+
path: `/projects/${projectId}/releases`,
151+
...opts,
152+
});
153+
},
154+
createProject({
155+
organizationId, ...opts
156+
}) {
157+
return this._makeRequest({
158+
method: "POST",
159+
path: `/organizations/${organizationId}/projects`,
160+
...opts,
161+
});
162+
},
163+
updateError({
164+
projectId, errorId, ...opts
165+
}) {
166+
return this._makeRequest({
167+
method: "PATCH",
168+
path: `/projects/${projectId}/errors/${errorId}`,
169+
...opts,
170+
});
171+
},
172+
async *paginate({
173+
fn, args, max,
174+
}) {
175+
args = {
176+
...args,
177+
returnFullResponse: true,
178+
};
179+
let next, count = 0;
180+
do {
181+
const {
182+
data, headers,
183+
} = await fn(args);
184+
for (const item of data) {
185+
yield item;
186+
if (max && ++count >= max) {
187+
return;
188+
}
189+
}
190+
next = headers?.link
191+
? this.getNextLink(headers.link)
192+
: false;
193+
args.url = next;
194+
args.params = undefined;
195+
} while (next);
196+
},
197+
},
198+
};

0 commit comments

Comments
 (0)