Skip to content
Open
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
1 change: 1 addition & 0 deletions src/N8NPropertiesBuilder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ test('enum schema', () => {
},
{
displayName: 'Type',
description: undefined,
name: 'type',
type: 'options',
default: 'type1',
Expand Down
73 changes: 63 additions & 10 deletions src/OperationsCollector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import {OptionsByResourceMap} from "./n8n/OptionsByResourceMap";
import {INodeProperties} from "n8n-workflow";
import {replacePathVarsToParameter} from "./n8n/utils";
import {IResourceParser} from "./ResourceParser";
import {
BinaryFileType,
INodeExecutionData, INodePropertyRouting,
INodeRequestOutput
} from "n8n-workflow/dist/Interfaces";
import ResponseObject = OpenAPIV3.ResponseObject;

export class BaseOperationsCollector implements OpenAPIVisitor {
public readonly _fields: INodeProperties[]
Expand Down Expand Up @@ -131,24 +137,71 @@ export class BaseOperationsCollector implements OpenAPIVisitor {
}

protected parseOperation(operation: OpenAPIV3.OperationObject, context: OperationContext) {
const method = context.method
const method = context.method;
const uri = context.pattern;
const parser = this.operationParser
const parser = this.operationParser;
let returns_raw_data = operation.responses &&
Object.entries(operation.responses)
.filter(([code, data]) =>
code.startsWith("2") && 'content' in data && data.content
)
.map(([_, data]) => (data as ResponseObject).content)
.map((content) => Object.keys(content!))
.flat()
.filter((contentType) => contentType.match(/^(image|audio|video|text)\/[a-z0-9.+-]+$|^application\/pdf$/i))
.length > 0;
let output: INodeRequestOutput | undefined = undefined
if (returns_raw_data) {
let file_type = (type: String): BinaryFileType | undefined => {
if (type.startsWith('image/')) return 'image';
if (type.startsWith('audio/')) return 'audio';
if (type.startsWith('video/')) return 'video';
if (type === 'text/html') return 'html';
if (type.startsWith('text/')) return 'text';
if (type === 'application/pdf') return 'pdf';
return undefined;
};
output = {
postReceive: [async (items, response): Promise<INodeExecutionData[]> => {
let bufferData = Buffer.from(items[0].json as unknown as ArrayBuffer);
const base64Data = bufferData.toString('base64');
return [{
binary: {
data: {
data: base64Data,
mimeType: response.headers['content-type'] as string,
fileSize: bufferData.length.toString(),
fileType: file_type(response.headers['content-type'] as string),
},
},
json: {},
}];
}],
}
}
let routing : INodePropertyRouting = {
request: {
// @ts-ignore
method: method.toUpperCase(),
url: `=${replacePathVarsToParameter(uri)}`,
},
};
if (returns_raw_data) {
routing.output = output;
routing.request!.headers = {
Accept: 'image/*',
};
routing.request!.json = false;
routing.request!.encoding = 'arraybuffer';
}
const option = {
name: parser.name(operation, context),
value: parser.value(operation, context),
action: parser.action(operation, context),
description: parser.description(operation, context),
routing: {
request: {
method: method.toUpperCase(),
url: `=${replacePathVarsToParameter(uri)}`,
},
},
routing,
};
const fields = this.parseFields(operation, context);


return {
option: option,
fields: fields,
Expand Down
Loading