From e72df20f46b27bf308e22da35b84ec0cb911b189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mie=20TAVIERE?= Date: Tue, 25 Feb 2025 11:43:51 +0100 Subject: [PATCH] transform array of enums in multi-options --- src/n8n/SchemaToINodeProperties.ts | 29 ++++++- tests/multioptions.spec.ts | 131 +++++++++++++++++++++++++++++ tests/samples/multioptions.json | 44 ++++++++++ 3 files changed, 200 insertions(+), 4 deletions(-) create mode 100644 tests/multioptions.spec.ts create mode 100644 tests/samples/multioptions.json diff --git a/src/n8n/SchemaToINodeProperties.ts b/src/n8n/SchemaToINodeProperties.ts index f4f70f9..51baa7d 100644 --- a/src/n8n/SchemaToINodeProperties.ts +++ b/src/n8n/SchemaToINodeProperties.ts @@ -3,6 +3,10 @@ import {INodeProperties, NodePropertyTypes} from "n8n-workflow"; import {RefResolver} from "../openapi/RefResolver"; import * as lodash from "lodash"; import {SchemaExample} from "../openapi/SchemaExample"; +import { + INodePropertyCollection, + INodePropertyOptions +} from 'n8n-workflow/dist/Interfaces' type Schema = OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject; type FromSchemaNodeProperty = Pick; @@ -43,6 +47,8 @@ export class N8NINodeProperties { let type: NodePropertyTypes; let defaultValue = this.schemaExample.extractExample(schema) + let options: Array | undefined = undefined + switch (schema.type) { case 'boolean': type = 'boolean'; @@ -58,8 +64,20 @@ export class N8NINodeProperties { defaultValue = defaultValue !== undefined ? JSON.stringify(defaultValue, null, 2) : '{}'; break; case 'array': - type = 'json'; - defaultValue = defaultValue !== undefined ? JSON.stringify(defaultValue, null, 2) : '[]'; + let schemaAsArray = schema as any; + if (schemaAsArray.items && schemaAsArray.items.enum && schemaAsArray.items.enum.length > 0) { + type = 'multiOptions'; + options = schemaAsArray.items.enum.map((value: string) => { + return { + name: lodash.startCase(value), + value: value, + }; + }); + defaultValue = defaultValue !== undefined ? defaultValue : []; + } else { + type = 'json'; + defaultValue = defaultValue !== undefined ? JSON.stringify(defaultValue, null, 2) : '[]'; + } break; case 'number': case 'integer': @@ -68,11 +86,14 @@ export class N8NINodeProperties { break; } - const field: FromSchemaNodeProperty = { + let field: FromSchemaNodeProperty = { type: type, default: defaultValue, description: schema.description, }; + if (options) { + field.options = options; + } if (schema.enum && schema.enum.length > 0) { field.type = 'options'; field.options = schema.enum.map((value: string) => { @@ -115,7 +136,7 @@ export class N8NINodeProperties { send: { type: 'query', property: parameter.name, - value: '={{ $value }}', + value: fieldSchemaKeys.type === "multiOptions" && !parameter.explode ? "={{ $value.join(',') }}" : '={{ $value }}', propertyInDotNotation: false, }, }; diff --git a/tests/multioptions.spec.ts b/tests/multioptions.spec.ts new file mode 100644 index 0000000..9576f81 --- /dev/null +++ b/tests/multioptions.spec.ts @@ -0,0 +1,131 @@ +import {N8NPropertiesBuilder} from "../src/N8NPropertiesBuilder"; +import {INodeProperties} from "n8n-workflow"; + +test('petstore.json', () => { + const doc = require('./samples/multioptions.json'); + const config = {} + const parser = new N8NPropertiesBuilder(doc, config); + const result = parser.build() + + console.log(JSON.stringify(result, null, 2)) + const expected: INodeProperties[] = [ + { + "displayName": "Resource", + "name": "resource", + "type": "options", + "noDataExpression": true, + "options": [ + { + "name": "Default", + "value": "Default", + "description": "" + } + ], + "default": "" + }, + { + "displayName": "Operation", + "name": "operation", + "type": "options", + "noDataExpression": true, + "displayOptions": { + "show": { + "resource": [ + "Default" + ] + } + }, + "options": [ + { + "name": "Create Model Fields Only", + "value": "Create Model Fields Only", + "action": "Create a model with field selection", + "description": "Create a model with field selection", + "routing": { + "request": { + "method": "POST", + "url": "=/model/" + } + } + } + ], + "default": "" + }, + { + "displayName": "POST /model/", + "name": "operation", + "type": "notice", + "typeOptions": { + "theme": "info" + }, + "default": "", + "displayOptions": { + "show": { + "resource": [ + "Default" + ], + "operation": [ + "Create Model Fields Only" + ] + } + } + }, + { + "displayName": "Fields Model", + "name": "fields%5Bmodel%5D", + "description": "Specifies which fields should be returned.", + "default": [], + "type": "multiOptions", + "options": [ + { + "name": "Component Type", + "value": "componentType" + }, + { + "name": "Count", + "value": "count" + }, + { + "name": "Array", + "value": "array" + }, + { + "name": "Model Type", + "value": "modelType" + }, + { + "name": "Sub Model", + "value": "subModel" + }, + { + "name": "View", + "value": "view" + }, + { + "name": "Name", + "value": "name" + } + ], + "routing": { + "send": { + "type": "query", + "property": "fields[model]", + "value": "={{ $value.join(',') }}", + "propertyInDotNotation": false + } + }, + "displayOptions": { + "show": { + "resource": [ + "Default" + ], + "operation": [ + "Create Model Fields Only" + ] + } + } + } + ] + ; + expect(result).toEqual(expected); +}) \ No newline at end of file diff --git a/tests/samples/multioptions.json b/tests/samples/multioptions.json new file mode 100644 index 0000000..4c6508f --- /dev/null +++ b/tests/samples/multioptions.json @@ -0,0 +1,44 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Multi Option Example", + "version": "0.1.0" + }, + "paths": { + "/model/": { + "post": { + "summary": "Create a model with field selection", + "operationId": "create_model_fields_only", + "parameters": [ + { + "name": "fields[model]", + "in": "query", + "description": "Specifies which fields should be returned.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "componentType", + "count", + "array", + "modelType", + "subModel", + "view", + "name" + ] + } + }, + "explode": false + } + ], + "responses": { + "200": { + "description": "Request accepted with specified fields." + } + } + } + } + } +} \ No newline at end of file