Page MenuHomeSealhub

Phabricator.node.ts
No OneTemporary

Phabricator.node.ts

import {
IExecuteFunctions,
INodeExecutionData,
INodeType,
INodeTypeDescription,
NodeExecutionWithMetadata,
NodeParameterValueType,
} from 'n8n-workflow';
import qs from 'qs';
import { constraints } from './constraints';
import { fields, PREFIXES } from './fields';
import { methods, apps } from './methods';
import { short_descriptions } from './short-descriptions';
const APP_FILTER = ['maniphest', 'transaction', 'project'];
function evaluate(
context: IExecuteFunctions,
value: NodeParameterValueType,
index: number,
): NodeParameterValueType {
if (typeof value == 'string' && value.startsWith('=')) {
value = context.evaluateExpression(value, index);
if (typeof value == 'string' && value.startsWith('=')) {
value = value.slice(1);
}
}
return value;
}
async function runForItem(this: IExecuteFunctions, index: number): Promise<any> {
const { token, domain } = (await this.getCredentials('phabricatorApi')) as {
token: string;
domain: string;
};
const parameters = { ...this.getNode().parameters };
const { operation } = parameters;
for (const key in parameters) {
this.sendMessageToUI(key);
let value = parameters[key];
this.sendMessageToUI(value);
let actual_key = key;
value = evaluate(this, value, index);
if (parameters[key] == '') {
delete parameters[key];
continue;
}
if (key.startsWith(PREFIXES.json)) {
this.sendMessageToUI('Starts with json prefix');
this.sendMessageToUI((value as any).toString());
try {
value = JSON.parse(value as string);
} catch (e) {
if ((value as any)[PREFIXES.transaction_array] !== undefined) {
value = (value as any)[PREFIXES.transaction_array];
(value as any).value = evaluate(this, value, index);
} else {
throw e;
}
}
actual_key = actual_key.replace(PREFIXES.json, '');
delete parameters[key];
}
if (actual_key == 'attachments') {
value = Object.fromEntries((value as string[]).map((key) => [key, true]));
}
if (actual_key.startsWith(PREFIXES.constraint)) {
actual_key = actual_key.replace(PREFIXES.constraint, '');
if (!parameters.constraints) {
parameters.constraints = {};
}
(parameters.constraints as any)[actual_key] = value;
this.sendMessageToUI(actual_key);
this.sendMessageToUI(constraints[operation as string][actual_key]?.type.startsWith('list<'));
this.sendMessageToUI(!Array.isArray(value));
if (/^(Optional )?list</.test(constraints[operation as string][actual_key]?.type)) {
if (!Array.isArray(value)) {
this.sendMessageToUI('Changing to array!');
(parameters.constraints as any)[actual_key] = value?.toString().split(',') || [];
}
}
delete parameters[key];
} else {
parameters[actual_key] = value;
}
}
for (const key of ['token', 'resource', 'operation']) {
delete parameters[key];
}
const request = {
url: domain + '/api/' + this.getNodeParameter('operation', index),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: qs.stringify({ 'api.token': token, ...parameters }),
method: <const>'POST',
};
this.sendMessageToUI(request);
return this.helpers.httpRequest(request);
}
export class Phabricator implements INodeType {
description: INodeTypeDescription = {
displayName: 'Phabricator',
name: 'phabricator',
icon: 'file:phabricator.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"]}}',
description: 'Interact with Phabricator',
defaults: {
name: 'Phabricator',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'phabricatorApi',
required: true,
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: apps.map((method) => ({
name: method,
value: method,
action: method,
description: `Call ${method} Conduit method`,
})),
default: 'user.whoami',
},
...apps
.filter((app) => APP_FILTER.includes(app))
.map((app) => ({
displayName: 'Operation',
name: 'operation',
type: <const>'options',
noDataExpression: true,
description: 'Choose an operation',
required: true,
displayOptions: {
show: {
resource: [app],
},
},
options: Object.entries(methods)
.filter(([method_name]) => {
return method_name.startsWith(app + '.');
})
.map(([method_name, method]) => ({
name: method_name,
value: method_name,
description: method.description,
action:
method_name.split('.').slice(1).join('.') + ': ' + short_descriptions[method_name],
})),
default: Object.keys(methods).filter((method_name) =>
method_name.startsWith(app + '.'),
)[0],
})),
...fields,
],
};
async execute(
this: IExecuteFunctions,
): Promise<INodeExecutionData[][] | NodeExecutionWithMetadata[][] | null> {
const items = this.getInputData();
const promises = [];
for (let i = 0; i < items.length; i++) {
promises.push(runForItem.bind(this)(i));
}
const responses = await Promise.all(promises);
return [this.helpers.returnJsonArray(responses)];
}
}

File Metadata

Mime Type
text/x-java
Expires
Sat, Nov 23, 04:50 (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
547851
Default Alt Text
Phabricator.node.ts (5 KB)

Event Timeline