Merge pull request #632 from automatisch/feature/extended-error-handler
Extend error handling logic to capture errors
This commit is contained in:
@@ -27,25 +27,25 @@ export default defineAction({
|
|||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
name: 'key',
|
name: 'key',
|
||||||
value: 'listRepos'
|
value: 'listRepos',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Title',
|
label: 'Title',
|
||||||
key: 'title',
|
key: 'title',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
required: true,
|
required: true,
|
||||||
variables: true
|
variables: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Body',
|
label: 'Body',
|
||||||
key: 'body',
|
key: 'body',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
required: true,
|
required: true,
|
||||||
variables: true
|
variables: true,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -59,7 +59,7 @@ export default defineAction({
|
|||||||
const title = $.step.parameters.title as string;
|
const title = $.step.parameters.title as string;
|
||||||
const body = $.step.parameters.body as string;
|
const body = $.step.parameters.body as string;
|
||||||
|
|
||||||
if (!repoParameter) throw new Error('A repo must be set!')
|
if (!repoParameter) throw new Error('A repo must be set!');
|
||||||
if (!title) throw new Error('A title must be set!');
|
if (!title) throw new Error('A title must be set!');
|
||||||
|
|
||||||
const { repoOwner, repo } = getRepoOwnerAndRepo(repoParameter);
|
const { repoOwner, repo } = getRepoOwnerAndRepo(repoParameter);
|
||||||
@@ -68,13 +68,6 @@ export default defineAction({
|
|||||||
body,
|
body,
|
||||||
});
|
});
|
||||||
|
|
||||||
const issue: IActionOutput = {
|
$.setActionItem({ raw: response.data });
|
||||||
data: {
|
|
||||||
raw: response.data,
|
|
||||||
},
|
|
||||||
error: response?.integrationError,
|
|
||||||
};
|
|
||||||
|
|
||||||
return issue;
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -1,13 +1,16 @@
|
|||||||
import { IGlobalVariable, IJSONObject } from "@automatisch/types";
|
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||||
import type { AxiosResponse } from 'axios';
|
import type { AxiosResponse } from 'axios';
|
||||||
import parseLinkHeader from '../../../helpers/parse-header-link';
|
import parseLinkHeader from '../../../helpers/parse-header-link';
|
||||||
|
|
||||||
type TResponse = {
|
type TResponse = {
|
||||||
data: IJSONObject[],
|
data: IJSONObject[];
|
||||||
error?: IJSONObject,
|
error?: IJSONObject;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default async function paginateAll($: IGlobalVariable, request: Promise<AxiosResponse>) {
|
export default async function paginateAll(
|
||||||
|
$: IGlobalVariable,
|
||||||
|
request: Promise<AxiosResponse>
|
||||||
|
) {
|
||||||
const response = await request;
|
const response = await request;
|
||||||
const aggregatedResponse: TResponse = {
|
const aggregatedResponse: TResponse = {
|
||||||
data: [...response.data],
|
data: [...response.data],
|
||||||
@@ -21,15 +24,8 @@ export default async function paginateAll($: IGlobalVariable, request: Promise<A
|
|||||||
url: links.next.uri,
|
url: links.next.uri,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (nextPageResponse.integrationError) {
|
aggregatedResponse.data.push(...nextPageResponse.data);
|
||||||
aggregatedResponse.error = nextPageResponse.integrationError;
|
links = parseLinkHeader(nextPageResponse.headers.link);
|
||||||
|
|
||||||
links = null;
|
|
||||||
} else {
|
|
||||||
aggregatedResponse.data.push(...nextPageResponse.data);
|
|
||||||
|
|
||||||
links = parseLinkHeader(nextPageResponse.headers.link);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return aggregatedResponse;
|
return aggregatedResponse;
|
||||||
|
@@ -9,7 +9,7 @@ export default defineTrigger({
|
|||||||
substeps: [
|
substeps: [
|
||||||
{
|
{
|
||||||
key: 'chooseConnection',
|
key: 'chooseConnection',
|
||||||
name: 'Choose connection'
|
name: 'Choose connection',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'chooseTrigger',
|
key: 'chooseTrigger',
|
||||||
@@ -27,10 +27,10 @@ export default defineTrigger({
|
|||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
name: 'key',
|
name: 'key',
|
||||||
value: 'listRepos'
|
value: 'listRepos',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Which types of issues should this trigger on?',
|
label: 'Which types of issues should this trigger on?',
|
||||||
@@ -43,25 +43,25 @@ export default defineTrigger({
|
|||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: 'Any issue you can see',
|
label: 'Any issue you can see',
|
||||||
value: 'all'
|
value: 'all',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Only issues assigned to you',
|
label: 'Only issues assigned to you',
|
||||||
value: 'assigned'
|
value: 'assigned',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Only issues created by you',
|
label: 'Only issues created by you',
|
||||||
value: 'created'
|
value: 'created',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: `Only issues you're mentioned in`,
|
label: `Only issues you're mentioned in`,
|
||||||
value: 'mentioned'
|
value: 'mentioned',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: `Only issues you're subscribed to`,
|
label: `Only issues you're subscribed to`,
|
||||||
value: 'subscribed'
|
value: 'subscribed',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Label',
|
label: 'Label',
|
||||||
@@ -77,24 +77,24 @@ export default defineTrigger({
|
|||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
name: 'key',
|
name: 'key',
|
||||||
value: 'listLabels'
|
value: 'listLabels',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'parameters.repo',
|
name: 'parameters.repo',
|
||||||
value: '{parameters.repo}'
|
value: '{parameters.repo}',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'testStep',
|
key: 'testStep',
|
||||||
name: 'Test trigger'
|
name: 'Test trigger',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
async run($) {
|
async run($) {
|
||||||
return await newIssues($);
|
await newIssues($);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -1,12 +1,11 @@
|
|||||||
import {
|
import { IGlobalVariable } from '@automatisch/types';
|
||||||
IGlobalVariable,
|
|
||||||
ITriggerOutput,
|
|
||||||
} from '@automatisch/types';
|
|
||||||
import getRepoOwnerAndRepo from '../../common/get-repo-owner-and-repo';
|
import getRepoOwnerAndRepo from '../../common/get-repo-owner-and-repo';
|
||||||
import parseLinkHeader from '../../../../helpers/parse-header-link';
|
import parseLinkHeader from '../../../../helpers/parse-header-link';
|
||||||
|
|
||||||
function getPathname($: IGlobalVariable) {
|
function getPathname($: IGlobalVariable) {
|
||||||
const { repoOwner, repo } = getRepoOwnerAndRepo($.step.parameters.repo as string);
|
const { repoOwner, repo } = getRepoOwnerAndRepo(
|
||||||
|
$.step.parameters.repo as string
|
||||||
|
);
|
||||||
|
|
||||||
if (repoOwner && repo) {
|
if (repoOwner && repo) {
|
||||||
return `/repos/${repoOwner}/${repo}/issues`;
|
return `/repos/${repoOwner}/${repo}/issues`;
|
||||||
@@ -26,25 +25,17 @@ const newIssues = async ($: IGlobalVariable) => {
|
|||||||
per_page: 100,
|
per_page: 100,
|
||||||
};
|
};
|
||||||
|
|
||||||
const issues: ITriggerOutput = {
|
|
||||||
data: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
let links;
|
let links;
|
||||||
do {
|
do {
|
||||||
const response = await $.http.get(pathname, { params });
|
const response = await $.http.get(pathname, { params });
|
||||||
links = parseLinkHeader(response.headers.link);
|
links = parseLinkHeader(response.headers.link);
|
||||||
|
|
||||||
if (response.integrationError) {
|
|
||||||
issues.error = response.integrationError;
|
|
||||||
return issues;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.data.length) {
|
if (response.data.length) {
|
||||||
for (const issue of response.data) {
|
for (const issue of response.data) {
|
||||||
const issueId = issue.id;
|
const issueId = issue.id;
|
||||||
|
|
||||||
if (issueId <= Number($.flow.lastInternalId) && !$.execution.testRun) return issues;
|
if (issueId <= Number($.flow.lastInternalId) && !$.execution.testRun)
|
||||||
|
return;
|
||||||
|
|
||||||
const dataItem = {
|
const dataItem = {
|
||||||
raw: issue,
|
raw: issue,
|
||||||
@@ -53,12 +44,10 @@ const newIssues = async ($: IGlobalVariable) => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
issues.data.push(dataItem);
|
$.triggerOutput.data.push(dataItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (links.next && !$.execution.testRun);
|
} while (links.next && !$.execution.testRun);
|
||||||
|
|
||||||
return issues;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default newIssues;
|
export default newIssues;
|
||||||
|
@@ -9,7 +9,7 @@ export default defineTrigger({
|
|||||||
substeps: [
|
substeps: [
|
||||||
{
|
{
|
||||||
key: 'chooseConnection',
|
key: 'chooseConnection',
|
||||||
name: 'Choose connection'
|
name: 'Choose connection',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'chooseTrigger',
|
key: 'chooseTrigger',
|
||||||
@@ -27,20 +27,20 @@ export default defineTrigger({
|
|||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
name: 'key',
|
name: 'key',
|
||||||
value: 'listRepos'
|
value: 'listRepos',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'testStep',
|
key: 'testStep',
|
||||||
name: 'Test trigger'
|
name: 'Test trigger',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
async run($) {
|
async run($) {
|
||||||
return await newPullRequests($);
|
await newPullRequests($);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -1,11 +1,8 @@
|
|||||||
import {
|
import { IGlobalVariable } from '@automatisch/types';
|
||||||
IGlobalVariable,
|
|
||||||
ITriggerOutput,
|
|
||||||
} from '@automatisch/types';
|
|
||||||
import getRepoOwnerAndRepo from '../../common/get-repo-owner-and-repo';
|
import getRepoOwnerAndRepo from '../../common/get-repo-owner-and-repo';
|
||||||
import parseLinkHeader from '../../../../helpers/parse-header-link';
|
import parseLinkHeader from '../../../../helpers/parse-header-link';
|
||||||
|
|
||||||
const fetchPullRequests = async ($: IGlobalVariable) => {
|
const newPullRequests = async ($: IGlobalVariable) => {
|
||||||
const repoParameter = $.step.parameters.repo as string;
|
const repoParameter = $.step.parameters.repo as string;
|
||||||
|
|
||||||
if (!repoParameter) throw new Error('A repo must be set!');
|
if (!repoParameter) throw new Error('A repo must be set!');
|
||||||
@@ -20,25 +17,20 @@ const fetchPullRequests = async ($: IGlobalVariable) => {
|
|||||||
per_page: 100,
|
per_page: 100,
|
||||||
};
|
};
|
||||||
|
|
||||||
const pullRequests: ITriggerOutput = {
|
|
||||||
data: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
let links;
|
let links;
|
||||||
do {
|
do {
|
||||||
const response = await $.http.get(pathname, { params });
|
const response = await $.http.get(pathname, { params });
|
||||||
links = parseLinkHeader(response.headers.link);
|
links = parseLinkHeader(response.headers.link);
|
||||||
|
|
||||||
if (response.integrationError) {
|
|
||||||
pullRequests.error = response.integrationError;
|
|
||||||
return pullRequests;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.data.length) {
|
if (response.data.length) {
|
||||||
for (const pullRequest of response.data) {
|
for (const pullRequest of response.data) {
|
||||||
const pullRequestId = pullRequest.id;
|
const pullRequestId = pullRequest.id;
|
||||||
|
|
||||||
if (pullRequestId <= Number($.flow.lastInternalId) && !$.execution.testRun) return pullRequests;
|
if (
|
||||||
|
pullRequestId <= Number($.flow.lastInternalId) &&
|
||||||
|
!$.execution.testRun
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
const dataItem = {
|
const dataItem = {
|
||||||
raw: pullRequest,
|
raw: pullRequest,
|
||||||
@@ -47,20 +39,10 @@ const fetchPullRequests = async ($: IGlobalVariable) => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pullRequests.data.push(dataItem);
|
$.pushTriggerItem(dataItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (links.next && !$.execution.testRun);
|
} while (links.next && !$.execution.testRun);
|
||||||
|
|
||||||
return pullRequests;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newPullRequests = async ($: IGlobalVariable) => {
|
|
||||||
const pullRequests = await fetchPullRequests($);
|
|
||||||
|
|
||||||
pullRequests.data.reverse();
|
|
||||||
|
|
||||||
return pullRequests;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default newPullRequests;
|
export default newPullRequests;
|
||||||
|
@@ -9,7 +9,7 @@ export default defineTrigger({
|
|||||||
substeps: [
|
substeps: [
|
||||||
{
|
{
|
||||||
key: 'chooseConnection',
|
key: 'chooseConnection',
|
||||||
name: 'Choose connection'
|
name: 'Choose connection',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'chooseTrigger',
|
key: 'chooseTrigger',
|
||||||
@@ -27,20 +27,26 @@ export default defineTrigger({
|
|||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
name: 'key',
|
name: 'key',
|
||||||
value: 'listRepos'
|
value: 'listRepos',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'testStep',
|
key: 'testStep',
|
||||||
name: 'Test trigger'
|
name: 'Test trigger',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
async run($) {
|
async run($) {
|
||||||
return await newStargazers($);
|
await newStargazers($);
|
||||||
|
},
|
||||||
|
|
||||||
|
sort(stargazerA, stargazerB) {
|
||||||
|
return (
|
||||||
|
Number(stargazerB.meta.internalId) - Number(stargazerA.meta.internalId)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -1,19 +1,17 @@
|
|||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import {
|
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||||
IGlobalVariable,
|
|
||||||
IJSONObject,
|
|
||||||
ITriggerOutput,
|
|
||||||
} from '@automatisch/types';
|
|
||||||
import getRepoOwnerAndRepo from '../../common/get-repo-owner-and-repo';
|
import getRepoOwnerAndRepo from '../../common/get-repo-owner-and-repo';
|
||||||
import parseLinkHeader from '../../../../helpers/parse-header-link';
|
import parseLinkHeader from '../../../../helpers/parse-header-link';
|
||||||
|
|
||||||
type TResponseDataItem = {
|
type TResponseDataItem = {
|
||||||
starred_at: string;
|
starred_at: string;
|
||||||
user: IJSONObject;
|
user: IJSONObject;
|
||||||
}
|
};
|
||||||
|
|
||||||
const fetchStargazers = async ($: IGlobalVariable) => {
|
const newStargazers = async ($: IGlobalVariable) => {
|
||||||
const { repoOwner, repo } = getRepoOwnerAndRepo($.step.parameters.repo as string);
|
const { repoOwner, repo } = getRepoOwnerAndRepo(
|
||||||
|
$.step.parameters.repo as string
|
||||||
|
);
|
||||||
const firstPagePathname = `/repos/${repoOwner}/${repo}/stargazers`;
|
const firstPagePathname = `/repos/${repoOwner}/${repo}/stargazers`;
|
||||||
const requestConfig = {
|
const requestConfig = {
|
||||||
params: {
|
params: {
|
||||||
@@ -22,35 +20,33 @@ const fetchStargazers = async ($: IGlobalVariable) => {
|
|||||||
headers: {
|
headers: {
|
||||||
// needed to get `starred_at` time
|
// needed to get `starred_at` time
|
||||||
Accept: 'application/vnd.github.star+json',
|
Accept: 'application/vnd.github.star+json',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
const firstPageResponse = await $.http.get<TResponseDataItem[]>(firstPagePathname, requestConfig);
|
const firstPageResponse = await $.http.get<TResponseDataItem[]>(
|
||||||
|
firstPagePathname,
|
||||||
|
requestConfig
|
||||||
|
);
|
||||||
const firstPageLinks = parseLinkHeader(firstPageResponse.headers.link);
|
const firstPageLinks = parseLinkHeader(firstPageResponse.headers.link);
|
||||||
|
|
||||||
// in case there is only single page to fetch
|
// in case there is only single page to fetch
|
||||||
let pathname = firstPageLinks.last?.uri || firstPagePathname;
|
let pathname = firstPageLinks.last?.uri || firstPagePathname;
|
||||||
|
|
||||||
const stargazers: ITriggerOutput = {
|
|
||||||
data: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
const response = await $.http.get<TResponseDataItem[]>(pathname, requestConfig);
|
const response = await $.http.get<TResponseDataItem[]>(
|
||||||
|
pathname,
|
||||||
|
requestConfig
|
||||||
|
);
|
||||||
const links = parseLinkHeader(response.headers.link);
|
const links = parseLinkHeader(response.headers.link);
|
||||||
pathname = links.prev?.uri;
|
pathname = links.prev?.uri;
|
||||||
|
|
||||||
if (response.integrationError) {
|
|
||||||
stargazers.error = response.integrationError;
|
|
||||||
return stargazers;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.data.length) {
|
if (response.data.length) {
|
||||||
for (const starEntry of response.data) {
|
for (const starEntry of response.data) {
|
||||||
const { starred_at, user } = starEntry;
|
const { starred_at, user } = starEntry;
|
||||||
const timestamp = DateTime.fromISO(starred_at).toMillis();
|
const timestamp = DateTime.fromISO(starred_at).toMillis();
|
||||||
|
|
||||||
if (timestamp <= Number($.flow.lastInternalId) && !$.execution.testRun) return stargazers;
|
if (timestamp <= Number($.flow.lastInternalId) && !$.execution.testRun)
|
||||||
|
return;
|
||||||
|
|
||||||
const dataItem = {
|
const dataItem = {
|
||||||
raw: user,
|
raw: user,
|
||||||
@@ -59,22 +55,10 @@ const fetchStargazers = async ($: IGlobalVariable) => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
stargazers.data.push(dataItem);
|
$.triggerOutput.data.push(dataItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (pathname && !$.execution.testRun);
|
} while (pathname && !$.execution.testRun);
|
||||||
|
|
||||||
return stargazers;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newStargazers = async ($: IGlobalVariable) => {
|
|
||||||
const stargazers = await fetchStargazers($);
|
|
||||||
|
|
||||||
stargazers.data.sort((stargazerA, stargazerB) => {
|
|
||||||
return Number(stargazerA.meta.internalId) - Number(stargazerB.meta.internalId);
|
|
||||||
});
|
|
||||||
|
|
||||||
return stargazers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default newStargazers;
|
export default newStargazers;
|
||||||
|
@@ -10,7 +10,7 @@ export default defineTrigger({
|
|||||||
substeps: [
|
substeps: [
|
||||||
{
|
{
|
||||||
key: 'chooseConnection',
|
key: 'chooseConnection',
|
||||||
name: 'Choose connection'
|
name: 'Choose connection',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'chooseTrigger',
|
key: 'chooseTrigger',
|
||||||
@@ -28,20 +28,24 @@ export default defineTrigger({
|
|||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
name: 'key',
|
name: 'key',
|
||||||
value: 'listRepos'
|
value: 'listRepos',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'testStep',
|
key: 'testStep',
|
||||||
name: 'Test trigger'
|
name: 'Test trigger',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
async run($) {
|
async run($) {
|
||||||
return await newWatchers($);
|
await newWatchers($);
|
||||||
|
},
|
||||||
|
|
||||||
|
sort() {
|
||||||
|
return -1;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -1,11 +1,8 @@
|
|||||||
import {
|
import { IGlobalVariable, ITriggerOutput } from '@automatisch/types';
|
||||||
IGlobalVariable,
|
|
||||||
ITriggerOutput,
|
|
||||||
} from '@automatisch/types';
|
|
||||||
import getRepoOwnerAndRepo from '../../common/get-repo-owner-and-repo';
|
import getRepoOwnerAndRepo from '../../common/get-repo-owner-and-repo';
|
||||||
import parseLinkHeader from '../../../../helpers/parse-header-link';
|
import parseLinkHeader from '../../../../helpers/parse-header-link';
|
||||||
|
|
||||||
const fetchWatchers = async ($: IGlobalVariable) => {
|
const newWatchers = async ($: IGlobalVariable) => {
|
||||||
const repoParameter = $.step.parameters.repo as string;
|
const repoParameter = $.step.parameters.repo as string;
|
||||||
|
|
||||||
if (!repoParameter) throw new Error('A repo must be set!');
|
if (!repoParameter) throw new Error('A repo must be set!');
|
||||||
@@ -15,9 +12,9 @@ const fetchWatchers = async ($: IGlobalVariable) => {
|
|||||||
const firstPagePathname = `/repos/${repoOwner}/${repo}/subscribers`;
|
const firstPagePathname = `/repos/${repoOwner}/${repo}/subscribers`;
|
||||||
const requestConfig = {
|
const requestConfig = {
|
||||||
params: {
|
params: {
|
||||||
per_page: 100
|
per_page: 100,
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
const firstPageResponse = await $.http.get(firstPagePathname, requestConfig);
|
const firstPageResponse = await $.http.get(firstPagePathname, requestConfig);
|
||||||
const firstPageLinks = parseLinkHeader(firstPageResponse.headers.link);
|
const firstPageLinks = parseLinkHeader(firstPageResponse.headers.link);
|
||||||
@@ -25,20 +22,11 @@ const fetchWatchers = async ($: IGlobalVariable) => {
|
|||||||
// in case there is only single page to fetch
|
// in case there is only single page to fetch
|
||||||
let pathname = firstPageLinks.last?.uri || firstPagePathname;
|
let pathname = firstPageLinks.last?.uri || firstPagePathname;
|
||||||
|
|
||||||
const watchers: ITriggerOutput = {
|
|
||||||
data: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
const response = await $.http.get(pathname, requestConfig);
|
const response = await $.http.get(pathname, requestConfig);
|
||||||
const links = parseLinkHeader(response.headers.link);
|
const links = parseLinkHeader(response.headers.link);
|
||||||
pathname = links.prev?.uri;
|
pathname = links.prev?.uri;
|
||||||
|
|
||||||
if (response.integrationError) {
|
|
||||||
watchers.error = response.integrationError;
|
|
||||||
return watchers;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.data.length) {
|
if (response.data.length) {
|
||||||
// to iterate reverse-chronologically
|
// to iterate reverse-chronologically
|
||||||
response.data.reverse();
|
response.data.reverse();
|
||||||
@@ -46,7 +34,8 @@ const fetchWatchers = async ($: IGlobalVariable) => {
|
|||||||
for (const watcher of response.data) {
|
for (const watcher of response.data) {
|
||||||
const watcherId = watcher.id.toString();
|
const watcherId = watcher.id.toString();
|
||||||
|
|
||||||
if ($.flow.isAlreadyProcessed(watcherId) && !$.execution.testRun) return watchers;
|
if ($.flow.isAlreadyProcessed(watcherId) && !$.execution.testRun)
|
||||||
|
return;
|
||||||
|
|
||||||
const dataItem = {
|
const dataItem = {
|
||||||
raw: watcher,
|
raw: watcher,
|
||||||
@@ -55,21 +44,10 @@ const fetchWatchers = async ($: IGlobalVariable) => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
watchers.data.push(dataItem);
|
$.pushTriggerItem(dataItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (pathname && !$.execution.testRun === false);
|
} while (pathname && !$.execution.testRun === false);
|
||||||
|
|
||||||
return watchers;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newWatchers = async ($: IGlobalVariable) => {
|
|
||||||
const watchers = await fetchWatchers($);
|
|
||||||
|
|
||||||
// to process chronologically
|
|
||||||
watchers.data.reverse();
|
|
||||||
|
|
||||||
return watchers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default newWatchers;
|
export default newWatchers;
|
||||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 13 KiB |
@@ -1,39 +0,0 @@
|
|||||||
import type { IAuthentication, IApp, IJSONObject } from '@automatisch/types';
|
|
||||||
import { Client } from 'pg';
|
|
||||||
|
|
||||||
export default class Authentication implements IAuthentication {
|
|
||||||
appData: IApp;
|
|
||||||
connectionData: IJSONObject;
|
|
||||||
client: Client;
|
|
||||||
|
|
||||||
constructor(appData: IApp, connectionData: IJSONObject) {
|
|
||||||
this.client = new Client({
|
|
||||||
host: connectionData.host as string,
|
|
||||||
port: connectionData.port as number,
|
|
||||||
database: connectionData.database as string,
|
|
||||||
user: connectionData.username as string,
|
|
||||||
password: connectionData.password as string,
|
|
||||||
ssl: connectionData.ssl as boolean,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.connectionData = connectionData;
|
|
||||||
this.appData = appData;
|
|
||||||
}
|
|
||||||
|
|
||||||
async verifyCredentials() {
|
|
||||||
await this.client.connect();
|
|
||||||
|
|
||||||
return {
|
|
||||||
screenName: this.connectionData.database,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async isStillVerified() {
|
|
||||||
try {
|
|
||||||
await this.client.connect();
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,15 +0,0 @@
|
|||||||
import Authentication from './authentication';
|
|
||||||
import {
|
|
||||||
IService,
|
|
||||||
IAuthentication,
|
|
||||||
IApp,
|
|
||||||
IJSONObject,
|
|
||||||
} from '@automatisch/types';
|
|
||||||
|
|
||||||
export default class PostgreSQL implements IService {
|
|
||||||
authenticationClient: IAuthentication;
|
|
||||||
|
|
||||||
constructor(appData: IApp, connectionData: IJSONObject) {
|
|
||||||
this.authenticationClient = new Authentication(appData, connectionData);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,201 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "PostgreSQL",
|
|
||||||
"key": "postgresql",
|
|
||||||
"iconUrl": "{BASE_URL}/apps/postgresql/assets/favicon.svg",
|
|
||||||
"docUrl": "https://automatisch.io/docs/postgresql",
|
|
||||||
"primaryColor": "2DAAE1",
|
|
||||||
"supportsConnections": true,
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"key": "host",
|
|
||||||
"label": "Host",
|
|
||||||
"type": "string",
|
|
||||||
"required": true,
|
|
||||||
"readOnly": false,
|
|
||||||
"value": null,
|
|
||||||
"placeholder": null,
|
|
||||||
"description": "The host information Automatisch will connect to.",
|
|
||||||
"docUrl": "https://automatisch.io/docs/postgresql#host",
|
|
||||||
"clickToCopy": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "port",
|
|
||||||
"label": "Port",
|
|
||||||
"type": "integer",
|
|
||||||
"required": true,
|
|
||||||
"readOnly": false,
|
|
||||||
"value": 5432,
|
|
||||||
"placeholder": null,
|
|
||||||
"description": null,
|
|
||||||
"docUrl": "https://automatisch.io/docs/postgresql#port",
|
|
||||||
"clickToCopy": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "database",
|
|
||||||
"label": "Database",
|
|
||||||
"type": "string",
|
|
||||||
"required": true,
|
|
||||||
"readOnly": false,
|
|
||||||
"value": null,
|
|
||||||
"placeholder": null,
|
|
||||||
"description": "The name of the database.",
|
|
||||||
"docUrl": "https://automatisch.io/docs/postgresql#password",
|
|
||||||
"clickToCopy": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "username",
|
|
||||||
"label": "Username",
|
|
||||||
"type": "string",
|
|
||||||
"required": true,
|
|
||||||
"readOnly": false,
|
|
||||||
"value": null,
|
|
||||||
"placeholder": null,
|
|
||||||
"description": null,
|
|
||||||
"docUrl": "https://automatisch.io/docs/postgresql#username",
|
|
||||||
"clickToCopy": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "password",
|
|
||||||
"label": "Password",
|
|
||||||
"type": "string",
|
|
||||||
"required": false,
|
|
||||||
"readOnly": false,
|
|
||||||
"value": null,
|
|
||||||
"placeholder": null,
|
|
||||||
"description": null,
|
|
||||||
"docUrl": "https://automatisch.io/docs/postgresql#password",
|
|
||||||
"clickToCopy": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "ssl",
|
|
||||||
"label": "Use SSL?",
|
|
||||||
"type": "boolean",
|
|
||||||
"required": true,
|
|
||||||
"readOnly": false,
|
|
||||||
"value": false,
|
|
||||||
"placeholder": null,
|
|
||||||
"description": null,
|
|
||||||
"docUrl": "https://automatisch.io/docs/postgresql#ssl",
|
|
||||||
"clickToCopy": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"authenticationSteps": [
|
|
||||||
{
|
|
||||||
"step": 1,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "createConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "{key}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "formattedData",
|
|
||||||
"value": null,
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"name": "host",
|
|
||||||
"value": "{fields.host}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "port",
|
|
||||||
"value": "{fields.port}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "database",
|
|
||||||
"value": "{fields.database}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "username",
|
|
||||||
"value": "{fields.username}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "password",
|
|
||||||
"value": "{fields.password}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ssl",
|
|
||||||
"value": "{fields.ssl}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 2,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "verifyConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{createConnection.id}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"reconnectionSteps": [
|
|
||||||
{
|
|
||||||
"step": 1,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "resetConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{connection.id}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 2,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "updateConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{connection.id}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "formattedData",
|
|
||||||
"value": null,
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"name": "host",
|
|
||||||
"value": "{fields.host}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "port",
|
|
||||||
"value": "{fields.port}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "database",
|
|
||||||
"value": "{fields.database}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "username",
|
|
||||||
"value": "{fields.username}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "password",
|
|
||||||
"value": "{fields.password}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ssl",
|
|
||||||
"value": "{fields.ssl}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 3,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "verifyConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{connection.id}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@@ -171,6 +171,6 @@ export default defineTrigger({
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return { data: [dataItem] };
|
$.triggerOutput.data.push(dataItem);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -65,6 +65,6 @@ export default defineTrigger({
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return { data: [dataItem] };
|
$.triggerOutput.data.push(dataItem);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -287,6 +287,6 @@ export default defineTrigger({
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return { data: [dataItem] };
|
$.triggerOutput.data.push(dataItem);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -191,6 +191,6 @@ export default defineTrigger({
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return { data: [dataItem] };
|
$.triggerOutput.data.push(dataItem);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -21,14 +21,11 @@ const findMessage = async ($: IGlobalVariable, options: FindMessageOptions) => {
|
|||||||
|
|
||||||
const data = response.data;
|
const data = response.data;
|
||||||
|
|
||||||
const message: IActionOutput = {
|
if (!data.ok && data) {
|
||||||
data: {
|
throw new Error(JSON.stringify(response.data));
|
||||||
raw: data?.messages.matches[0],
|
}
|
||||||
},
|
|
||||||
error: response?.integrationError || (!data.ok && data),
|
|
||||||
};
|
|
||||||
|
|
||||||
return message;
|
$.actionOutput.data.raw = data?.messages.matches[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default findMessage;
|
export default findMessage;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { IGlobalVariable, IActionOutput } from '@automatisch/types';
|
import { IGlobalVariable } from '@automatisch/types';
|
||||||
|
|
||||||
const postMessage = async (
|
const postMessage = async (
|
||||||
$: IGlobalVariable,
|
$: IGlobalVariable,
|
||||||
@@ -12,18 +12,15 @@ const postMessage = async (
|
|||||||
|
|
||||||
const response = await $.http.post('/chat.postMessage', params);
|
const response = await $.http.post('/chat.postMessage', params);
|
||||||
|
|
||||||
const message: IActionOutput = {
|
|
||||||
data: {
|
|
||||||
raw: response?.data?.message,
|
|
||||||
},
|
|
||||||
error: response?.integrationError,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (response.data.ok === false) {
|
if (response.data.ok === false) {
|
||||||
message.error = response.data;
|
throw new Error(JSON.stringify(response.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
return message;
|
const message = {
|
||||||
|
raw: response?.data?.message,
|
||||||
|
};
|
||||||
|
|
||||||
|
$.setActionItem(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default postMessage;
|
export default postMessage;
|
||||||
|
@@ -15,14 +15,8 @@ export default {
|
|||||||
|
|
||||||
const response = await $.http.get('/conversations.list');
|
const response = await $.http.get('/conversations.list');
|
||||||
|
|
||||||
if (response.integrationError) {
|
|
||||||
channels.error = response.integrationError;
|
|
||||||
return channels;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.data.ok === false) {
|
if (response.data.ok === false) {
|
||||||
channels.error = response.data;
|
throw new Error(response.data);
|
||||||
return channels;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
channels.data = response.data.channels.map((channel: IJSONObject) => {
|
channels.data = response.data.channels.map((channel: IJSONObject) => {
|
||||||
|
@@ -36,13 +36,6 @@ export default defineAction({
|
|||||||
text,
|
text,
|
||||||
});
|
});
|
||||||
|
|
||||||
const tweet: IActionOutput = {
|
$.actionOutput.data.raw = response.data;
|
||||||
data: {
|
|
||||||
raw: response.data,
|
|
||||||
},
|
|
||||||
error: response?.integrationError,
|
|
||||||
};
|
|
||||||
|
|
||||||
return tweet;
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -1,8 +1,4 @@
|
|||||||
import {
|
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||||
IGlobalVariable,
|
|
||||||
IJSONObject,
|
|
||||||
ITriggerOutput,
|
|
||||||
} from '@automatisch/types';
|
|
||||||
import { URLSearchParams } from 'url';
|
import { URLSearchParams } from 'url';
|
||||||
import { omitBy, isEmpty } from 'lodash';
|
import { omitBy, isEmpty } from 'lodash';
|
||||||
|
|
||||||
@@ -16,10 +12,6 @@ const getUserFollowers = async (
|
|||||||
) => {
|
) => {
|
||||||
let response;
|
let response;
|
||||||
|
|
||||||
const followers: ITriggerOutput = {
|
|
||||||
data: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
const params: IJSONObject = {
|
const params: IJSONObject = {
|
||||||
pagination_token: response?.data?.meta?.next_token,
|
pagination_token: response?.data?.meta?.next_token,
|
||||||
@@ -33,31 +25,23 @@ const getUserFollowers = async (
|
|||||||
|
|
||||||
response = await $.http.get(requestPath);
|
response = await $.http.get(requestPath);
|
||||||
|
|
||||||
if (response.integrationError) {
|
|
||||||
followers.error = response.integrationError;
|
|
||||||
return followers;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.data?.errors) {
|
if (response.data?.errors) {
|
||||||
followers.error = response.data.errors;
|
throw new Error(response.data.errors);
|
||||||
return followers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.data.meta.result_count > 0) {
|
if (response.data.meta.result_count > 0) {
|
||||||
for (const follower of response.data.data) {
|
for (const follower of response.data.data) {
|
||||||
if ($.flow.isAlreadyProcessed(follower.id as string)) {
|
if ($.flow.isAlreadyProcessed(follower.id as string)) {
|
||||||
return followers;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
followers.data.push({
|
$.pushTriggerItem({
|
||||||
raw: follower,
|
raw: follower,
|
||||||
meta: { internalId: follower.id as string },
|
meta: { internalId: follower.id as string },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (response.data.meta.next_token && !$.execution.testRun);
|
} while (response.data.meta.next_token && !$.execution.testRun);
|
||||||
|
|
||||||
return followers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default getUserFollowers;
|
export default getUserFollowers;
|
||||||
|
@@ -1,8 +1,4 @@
|
|||||||
import {
|
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||||
IGlobalVariable,
|
|
||||||
IJSONObject,
|
|
||||||
ITriggerOutput,
|
|
||||||
} from '@automatisch/types';
|
|
||||||
import { URLSearchParams } from 'url';
|
import { URLSearchParams } from 'url';
|
||||||
import omitBy from 'lodash/omitBy';
|
import omitBy from 'lodash/omitBy';
|
||||||
import isEmpty from 'lodash/isEmpty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
@@ -18,10 +14,6 @@ const fetchTweets = async ($: IGlobalVariable, username: string) => {
|
|||||||
|
|
||||||
let response;
|
let response;
|
||||||
|
|
||||||
const tweets: ITriggerOutput = {
|
|
||||||
data: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
const params: IJSONObject = {
|
const params: IJSONObject = {
|
||||||
since_id: $.execution.testRun ? null : $.flow.lastInternalId,
|
since_id: $.execution.testRun ? null : $.flow.lastInternalId,
|
||||||
@@ -36,14 +28,9 @@ const fetchTweets = async ($: IGlobalVariable, username: string) => {
|
|||||||
|
|
||||||
response = await $.http.get(requestPath);
|
response = await $.http.get(requestPath);
|
||||||
|
|
||||||
if (response.integrationError) {
|
|
||||||
tweets.error = response.integrationError;
|
|
||||||
return tweets;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.data.meta.result_count > 0) {
|
if (response.data.meta.result_count > 0) {
|
||||||
response.data.data.forEach((tweet: IJSONObject) => {
|
response.data.data.forEach((tweet: IJSONObject) => {
|
||||||
tweets.data.push({
|
$.triggerOutput.data.push({
|
||||||
raw: tweet,
|
raw: tweet,
|
||||||
meta: {
|
meta: {
|
||||||
internalId: tweet.id as string,
|
internalId: tweet.id as string,
|
||||||
@@ -53,7 +40,7 @@ const fetchTweets = async ($: IGlobalVariable, username: string) => {
|
|||||||
}
|
}
|
||||||
} while (response.data.meta.next_token && !$.execution.testRun);
|
} while (response.data.meta.next_token && !$.execution.testRun);
|
||||||
|
|
||||||
return tweets;
|
return $.triggerOutput;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getUserTweets = async (
|
const getUserTweets = async (
|
||||||
@@ -69,13 +56,7 @@ const getUserTweets = async (
|
|||||||
username = $.step.parameters.username as string;
|
username = $.step.parameters.username as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tweets = await fetchTweets($, username);
|
await fetchTweets($, username);
|
||||||
|
|
||||||
tweets.data.sort((tweet, nextTweet) => {
|
|
||||||
return Number(tweet.meta.internalId) - Number(nextTweet.meta.internalId);
|
|
||||||
});
|
|
||||||
|
|
||||||
return tweets;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default getUserTweets;
|
export default getUserTweets;
|
||||||
|
@@ -18,8 +18,10 @@ export default defineTrigger({
|
|||||||
],
|
],
|
||||||
|
|
||||||
async run($) {
|
async run($) {
|
||||||
return await getUserTweets($, {
|
await getUserTweets($, { currentUser: true });
|
||||||
currentUser: true,
|
},
|
||||||
});
|
|
||||||
|
sort(tweet, nextTweet) {
|
||||||
|
return Number(nextTweet.meta.internalId) - Number(tweet.meta.internalId);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -19,6 +19,6 @@ export default defineTrigger({
|
|||||||
],
|
],
|
||||||
|
|
||||||
async run($) {
|
async run($) {
|
||||||
return await myFollowers($);
|
await myFollowers($);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -31,6 +31,10 @@ export default defineTrigger({
|
|||||||
],
|
],
|
||||||
|
|
||||||
async run($) {
|
async run($) {
|
||||||
return await searchTweets($);
|
await searchTweets($);
|
||||||
|
},
|
||||||
|
|
||||||
|
sort(tweet, nextTweet) {
|
||||||
|
return Number(nextTweet.meta.internalId) - Number(tweet.meta.internalId);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -1,20 +1,12 @@
|
|||||||
import {
|
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||||
IGlobalVariable,
|
|
||||||
IJSONObject,
|
|
||||||
ITriggerOutput,
|
|
||||||
} from '@automatisch/types';
|
|
||||||
import qs from 'qs';
|
import qs from 'qs';
|
||||||
import { omitBy, isEmpty } from 'lodash';
|
import { omitBy, isEmpty } from 'lodash';
|
||||||
|
|
||||||
const fetchTweets = async ($: IGlobalVariable) => {
|
const searchTweets = async ($: IGlobalVariable) => {
|
||||||
const searchTerm = $.step.parameters.searchTerm as string;
|
const searchTerm = $.step.parameters.searchTerm as string;
|
||||||
|
|
||||||
let response;
|
let response;
|
||||||
|
|
||||||
const tweets: ITriggerOutput = {
|
|
||||||
data: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
const params: IJSONObject = {
|
const params: IJSONObject = {
|
||||||
query: searchTerm,
|
query: searchTerm,
|
||||||
@@ -30,14 +22,8 @@ const fetchTweets = async ($: IGlobalVariable) => {
|
|||||||
|
|
||||||
response = await $.http.get(requestPath);
|
response = await $.http.get(requestPath);
|
||||||
|
|
||||||
if (response.integrationError) {
|
|
||||||
tweets.error = response.integrationError;
|
|
||||||
return tweets;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.data.errors) {
|
if (response.data.errors) {
|
||||||
tweets.error = response.data.errors;
|
throw new Error(JSON.stringify(response.data.errors));
|
||||||
return tweets;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.data.meta.result_count > 0) {
|
if (response.data.meta.result_count > 0) {
|
||||||
@@ -49,22 +35,10 @@ const fetchTweets = async ($: IGlobalVariable) => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
tweets.data.push(dataItem);
|
$.triggerOutput.data.push(dataItem);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} while (response.data.meta.next_token && !$.execution.testRun);
|
} while (response.data.meta.next_token && !$.execution.testRun);
|
||||||
|
|
||||||
return tweets;
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchTweets = async ($: IGlobalVariable) => {
|
|
||||||
const tweets = await fetchTweets($);
|
|
||||||
|
|
||||||
tweets.data.sort((tweet, nextTweet) => {
|
|
||||||
return Number(tweet.meta.internalId) - Number(nextTweet.meta.internalId);
|
|
||||||
});
|
|
||||||
|
|
||||||
return tweets;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default searchTweets;
|
export default searchTweets;
|
||||||
|
@@ -30,8 +30,10 @@ export default defineTrigger({
|
|||||||
],
|
],
|
||||||
|
|
||||||
async run($) {
|
async run($) {
|
||||||
return await getUserTweets($, {
|
await getUserTweets($, { currentUser: false });
|
||||||
currentUser: false,
|
},
|
||||||
});
|
|
||||||
|
sort(tweet, nextTweet) {
|
||||||
|
return Number(nextTweet.meta.internalId) - Number(tweet.meta.internalId);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -3,7 +3,13 @@ import Connection from '../models/connection';
|
|||||||
import Flow from '../models/flow';
|
import Flow from '../models/flow';
|
||||||
import Step from '../models/step';
|
import Step from '../models/step';
|
||||||
import Execution from '../models/execution';
|
import Execution from '../models/execution';
|
||||||
import { IJSONObject, IApp, IGlobalVariable } from '@automatisch/types';
|
import {
|
||||||
|
IJSONObject,
|
||||||
|
IApp,
|
||||||
|
IGlobalVariable,
|
||||||
|
ITriggerItem,
|
||||||
|
IActionItem,
|
||||||
|
} from '@automatisch/types';
|
||||||
|
|
||||||
type GlobalVariableOptions = {
|
type GlobalVariableOptions = {
|
||||||
connection?: Connection;
|
connection?: Connection;
|
||||||
@@ -59,6 +65,20 @@ const globalVariable = async (
|
|||||||
id: execution?.id,
|
id: execution?.id,
|
||||||
testRun,
|
testRun,
|
||||||
},
|
},
|
||||||
|
triggerOutput: {
|
||||||
|
data: [],
|
||||||
|
},
|
||||||
|
actionOutput: {
|
||||||
|
data: {
|
||||||
|
raw: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pushTriggerItem: (triggerItem: ITriggerItem) => {
|
||||||
|
$.triggerOutput.data.push(triggerItem);
|
||||||
|
},
|
||||||
|
setActionItem: (actionItem: IActionItem) => {
|
||||||
|
$.actionOutput.data = actionItem;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
$.http = createHttpClient({
|
$.http = createHttpClient({
|
||||||
|
@@ -39,8 +39,8 @@ export default function createHttpClient({
|
|||||||
instance.interceptors.response.use(
|
instance.interceptors.response.use(
|
||||||
(response) => response,
|
(response) => response,
|
||||||
(error) => {
|
(error) => {
|
||||||
error.response.integrationError = error.response.data;
|
error.response.httpError = error.response.data;
|
||||||
return error.response;
|
throw error;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -10,12 +10,7 @@ class App {
|
|||||||
|
|
||||||
// Temporaryly restrict the apps we expose until
|
// Temporaryly restrict the apps we expose until
|
||||||
// their actions/triggers are implemented!
|
// their actions/triggers are implemented!
|
||||||
static temporaryList = [
|
static temporaryList = ['github', 'scheduler', 'slack', 'twitter'];
|
||||||
'github',
|
|
||||||
'scheduler',
|
|
||||||
'slack',
|
|
||||||
'twitter',
|
|
||||||
];
|
|
||||||
|
|
||||||
static async findAll(name?: string, stripFuncs = true): Promise<IApp[]> {
|
static async findAll(name?: string, stripFuncs = true): Promise<IApp[]> {
|
||||||
if (!name)
|
if (!name)
|
||||||
|
@@ -39,16 +39,29 @@ export const processAction = async (options: ProcessActionOptions) => {
|
|||||||
const actionCommand = await step.getActionCommand();
|
const actionCommand = await step.getActionCommand();
|
||||||
|
|
||||||
$.step.parameters = computedParameters;
|
$.step.parameters = computedParameters;
|
||||||
const actionOutput = await actionCommand.run($);
|
|
||||||
|
try {
|
||||||
|
await actionCommand.run($);
|
||||||
|
} catch (error) {
|
||||||
|
if (error?.response?.httpError) {
|
||||||
|
$.actionOutput.error = error.response.httpError;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$.actionOutput.error = JSON.parse(error.message);
|
||||||
|
} catch {
|
||||||
|
$.actionOutput.error = { error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const executionStep = await execution
|
const executionStep = await execution
|
||||||
.$relatedQuery('executionSteps')
|
.$relatedQuery('executionSteps')
|
||||||
.insertAndFetch({
|
.insertAndFetch({
|
||||||
stepId: $.step.id,
|
stepId: $.step.id,
|
||||||
status: actionOutput.error ? 'failure' : 'success',
|
status: $.actionOutput.error ? 'failure' : 'success',
|
||||||
dataIn: computedParameters,
|
dataIn: computedParameters,
|
||||||
dataOut: actionOutput.error ? null : actionOutput.data?.raw,
|
dataOut: $.actionOutput.error ? null : $.actionOutput.data?.raw,
|
||||||
errorDetails: actionOutput.error ? actionOutput.error : null,
|
errorDetails: $.actionOutput.error ? $.actionOutput.error : null,
|
||||||
});
|
});
|
||||||
|
|
||||||
return { flowId, stepId, executionId, executionStep };
|
return { flowId, stepId, executionId, executionStep };
|
||||||
|
@@ -20,5 +20,23 @@ export const processFlow = async (options: ProcessFlowOptions) => {
|
|||||||
testRun: options.testRun,
|
testRun: options.testRun,
|
||||||
});
|
});
|
||||||
|
|
||||||
return await triggerCommand.run($);
|
try {
|
||||||
|
await triggerCommand.run($);
|
||||||
|
} catch (error) {
|
||||||
|
if (error?.response?.httpError) {
|
||||||
|
$.triggerOutput.error = error.response.httpError;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$.triggerOutput.error = JSON.parse(error.message);
|
||||||
|
} catch {
|
||||||
|
$.triggerOutput.error = { error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (triggerCommand?.sort) {
|
||||||
|
$.triggerOutput.data.sort(triggerCommand.sort);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $.triggerOutput;
|
||||||
};
|
};
|
||||||
|
@@ -35,13 +35,13 @@ const testRun = async (options: TestRunOptions) => {
|
|||||||
return { executionStep: triggerExecutionStepWithError };
|
return { executionStep: triggerExecutionStepWithError };
|
||||||
}
|
}
|
||||||
|
|
||||||
const firstTriggerDataItem = data[0];
|
const firstTriggerItem = data[0];
|
||||||
|
|
||||||
const { executionId, executionStep: triggerExecutionStep } =
|
const { executionId, executionStep: triggerExecutionStep } =
|
||||||
await processTrigger({
|
await processTrigger({
|
||||||
flowId: flow.id,
|
flowId: flow.id,
|
||||||
stepId: triggerStep.id,
|
stepId: triggerStep.id,
|
||||||
triggerDataItem: firstTriggerDataItem,
|
triggerItem: firstTriggerItem,
|
||||||
testRun: true,
|
testRun: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { IJSONObject, ITriggerDataItem } from '@automatisch/types';
|
import { IJSONObject, ITriggerItem } from '@automatisch/types';
|
||||||
import Step from '../models/step';
|
import Step from '../models/step';
|
||||||
import Flow from '../models/flow';
|
import Flow from '../models/flow';
|
||||||
import Execution from '../models/execution';
|
import Execution from '../models/execution';
|
||||||
@@ -7,13 +7,13 @@ import globalVariable from '../helpers/global-variable';
|
|||||||
type ProcessTriggerOptions = {
|
type ProcessTriggerOptions = {
|
||||||
flowId: string;
|
flowId: string;
|
||||||
stepId: string;
|
stepId: string;
|
||||||
triggerDataItem?: ITriggerDataItem;
|
triggerItem?: ITriggerItem;
|
||||||
error?: IJSONObject;
|
error?: IJSONObject;
|
||||||
testRun?: boolean;
|
testRun?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const processTrigger = async (options: ProcessTriggerOptions) => {
|
export const processTrigger = async (options: ProcessTriggerOptions) => {
|
||||||
const { flowId, stepId, triggerDataItem, error, testRun } = options;
|
const { flowId, stepId, triggerItem, error, testRun } = options;
|
||||||
|
|
||||||
const step = await Step.query().findById(stepId).throwIfNotFound();
|
const step = await Step.query().findById(stepId).throwIfNotFound();
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ export const processTrigger = async (options: ProcessTriggerOptions) => {
|
|||||||
const execution = await Execution.query().insert({
|
const execution = await Execution.query().insert({
|
||||||
flowId: $.flow.id,
|
flowId: $.flow.id,
|
||||||
testRun,
|
testRun,
|
||||||
internalId: triggerDataItem?.meta.internalId,
|
internalId: triggerItem?.meta.internalId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const executionStep = await execution
|
const executionStep = await execution
|
||||||
@@ -38,7 +38,7 @@ export const processTrigger = async (options: ProcessTriggerOptions) => {
|
|||||||
stepId: $.step.id,
|
stepId: $.step.id,
|
||||||
status: error ? 'failure' : 'success',
|
status: error ? 'failure' : 'success',
|
||||||
dataIn: $.step.parameters,
|
dataIn: $.step.parameters,
|
||||||
dataOut: !error ? triggerDataItem?.raw : null,
|
dataOut: !error ? triggerItem?.raw : null,
|
||||||
errorDetails: error,
|
errorDetails: error,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -15,13 +15,15 @@ export const worker = new Worker(
|
|||||||
|
|
||||||
const { data, error } = await processFlow({ flowId });
|
const { data, error } = await processFlow({ flowId });
|
||||||
|
|
||||||
for (const triggerDataItem of data) {
|
const reversedData = data.reverse();
|
||||||
const jobName = `${triggerStep.id}-${triggerDataItem.meta.internalId}`;
|
|
||||||
|
for (const triggerItem of reversedData) {
|
||||||
|
const jobName = `${triggerStep.id}-${triggerItem.meta.internalId}`;
|
||||||
|
|
||||||
const jobPayload = {
|
const jobPayload = {
|
||||||
flowId,
|
flowId,
|
||||||
stepId: triggerStep.id,
|
stepId: triggerStep.id,
|
||||||
triggerDataItem,
|
triggerItem,
|
||||||
};
|
};
|
||||||
|
|
||||||
await triggerQueue.add(jobName, jobPayload);
|
await triggerQueue.add(jobName, jobPayload);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { Worker } from 'bullmq';
|
import { Worker } from 'bullmq';
|
||||||
import redisConfig from '../config/redis';
|
import redisConfig from '../config/redis';
|
||||||
import logger from '../helpers/logger';
|
import logger from '../helpers/logger';
|
||||||
import { IJSONObject, ITriggerDataItem } from '@automatisch/types';
|
import { IJSONObject, ITriggerItem } from '@automatisch/types';
|
||||||
import actionQueue from '../queues/action';
|
import actionQueue from '../queues/action';
|
||||||
import Step from '../models/step';
|
import Step from '../models/step';
|
||||||
import { processTrigger } from '../services/trigger';
|
import { processTrigger } from '../services/trigger';
|
||||||
@@ -9,7 +9,7 @@ import { processTrigger } from '../services/trigger';
|
|||||||
type JobData = {
|
type JobData = {
|
||||||
flowId: string;
|
flowId: string;
|
||||||
stepId: string;
|
stepId: string;
|
||||||
triggerDataItem?: ITriggerDataItem;
|
triggerItem?: ITriggerItem;
|
||||||
error?: IJSONObject;
|
error?: IJSONObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
28
packages/types/index.d.ts
vendored
28
packages/types/index.d.ts
vendored
@@ -171,7 +171,7 @@ export interface IApp {
|
|||||||
|
|
||||||
export type TBeforeRequest = {
|
export type TBeforeRequest = {
|
||||||
($: IGlobalVariable, requestConfig: AxiosRequestConfig): AxiosRequestConfig;
|
($: IGlobalVariable, requestConfig: AxiosRequestConfig): AxiosRequestConfig;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface IData {
|
export interface IData {
|
||||||
[index: string]: any;
|
[index: string]: any;
|
||||||
@@ -194,11 +194,11 @@ export interface IService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ITriggerOutput {
|
export interface ITriggerOutput {
|
||||||
data: ITriggerDataItem[];
|
data: ITriggerItem[];
|
||||||
error?: IJSONObject;
|
error?: IJSONObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITriggerDataItem {
|
export interface ITriggerItem {
|
||||||
raw: IJSONObject;
|
raw: IJSONObject;
|
||||||
meta: {
|
meta: {
|
||||||
internalId: string;
|
internalId: string;
|
||||||
@@ -212,19 +212,18 @@ export interface ITrigger {
|
|||||||
description: string;
|
description: string;
|
||||||
dedupeStrategy?: 'greatest' | 'unique' | 'last';
|
dedupeStrategy?: 'greatest' | 'unique' | 'last';
|
||||||
substeps: ISubstep[];
|
substeps: ISubstep[];
|
||||||
getInterval?(parameters: IGlobalVariable['step']['parameters']): string;
|
getInterval?(parameters: IStep['parameters']): string;
|
||||||
run($: IGlobalVariable): Promise<ITriggerOutput>;
|
run($: IGlobalVariable): Promise<void>;
|
||||||
|
sort?(item: ITriggerItem, nextItem: ITriggerItem): number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IActionOutput {
|
export interface IActionOutput {
|
||||||
data: IActionDataItem;
|
data: IActionItem;
|
||||||
error?: IJSONObject;
|
error?: IJSONObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IActionDataItem {
|
export interface IActionItem {
|
||||||
raw: {
|
raw: IJSONObject;
|
||||||
data?: IJSONObject;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAction {
|
export interface IAction {
|
||||||
@@ -232,7 +231,7 @@ export interface IAction {
|
|||||||
key: string;
|
key: string;
|
||||||
description: string;
|
description: string;
|
||||||
substeps: ISubstep[];
|
substeps: ISubstep[];
|
||||||
run($: IGlobalVariable): Promise<IActionOutput>;
|
run($: IGlobalVariable): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAuthentication {
|
export interface IAuthentication {
|
||||||
@@ -279,11 +278,14 @@ export type IGlobalVariable = {
|
|||||||
id: string;
|
id: string;
|
||||||
testRun: boolean;
|
testRun: boolean;
|
||||||
};
|
};
|
||||||
process?: (triggerDataItem: ITriggerDataItem) => Promise<void>;
|
triggerOutput?: ITriggerOutput;
|
||||||
|
actionOutput?: IActionOutput;
|
||||||
|
pushTriggerItem?: (triggerItem: ITriggerItem) => void;
|
||||||
|
setActionItem?: (actionItem: IActionItem) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
declare module 'axios' {
|
declare module 'axios' {
|
||||||
interface AxiosResponse {
|
interface AxiosResponse {
|
||||||
integrationError?: IJSONObject;
|
httpError?: IJSONObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user