mirror of
				https://github.com/n8n-io/n8n-nodes-starter.git
				synced 2025-10-30 23:02:25 -05:00 
			
		
		
		
	principal node created
This commit is contained in:
		
					parent
					
						
							
								de3e6aa70b
							
						
					
				
			
			
				commit
				
					
						fc3d0df193
					
				
			
		
					 12 changed files with 1266 additions and 577 deletions
				
			
		
							
								
								
									
										196
									
								
								nodes/S4DSMain/S4DSMain.node.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								nodes/S4DSMain/S4DSMain.node.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,196 @@ | |||
| import { INodeType, INodeTypeDescription, NodeConnectionType, IExecuteFunctions, INodeExecutionData, IHttpRequestMethods } from 'n8n-workflow'; | ||||
| import { ApiHelper } from './ApiHelper'; | ||||
| 
 | ||||
| export class S4DSMain implements INodeType { | ||||
| 	description: INodeTypeDescription = { | ||||
| 		displayName: 'S4DS', | ||||
| 		name: 's4ds', | ||||
| 		icon: { light: 'file:logo_generic.png', dark: 'file:logo_generic.png' }, | ||||
| 		group: ['transform'], | ||||
| 		version: 1, | ||||
| 		subtitle: '={{$parameter["resource"]}} - {{$parameter["operation"]}}', | ||||
| 		description: 'S4DS API operations including authentication and product management', | ||||
| 		defaults: { | ||||
| 			name: 'S4DS', | ||||
| 		}, | ||||
| 		inputs: [NodeConnectionType.Main], | ||||
| 		outputs: [NodeConnectionType.Main], | ||||
| 		credentials: [ | ||||
| 			{ | ||||
| 				name: 's4dsApi', | ||||
| 				required: true, | ||||
| 			}, | ||||
| 		], | ||||
| 		requestDefaults: { | ||||
| 			baseURL: '={{$credentials.s4dsApi.baseUrl === "custom" ? $credentials.s4dsApi.customBaseUrl : $credentials.s4dsApi.baseUrl}}', | ||||
| 			url: '', | ||||
| 			headers: { | ||||
| 				Accept: 'application/json', | ||||
| 				'Content-Type': 'application/json', | ||||
| 			}, | ||||
| 		}, | ||||
| 		properties: [ | ||||
| 			...ApiHelper.getResources(), | ||||
| 			...ApiHelper.getOperations(), | ||||
| 			...ApiHelper.getFields(), | ||||
| 		], | ||||
| 	}; | ||||
| 
 | ||||
| 	async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { | ||||
| 		const items = this.getInputData(); | ||||
| 		const returnData: INodeExecutionData[] = []; | ||||
| 
 | ||||
| 		for (let i = 0; i < items.length; i++) { | ||||
| 			try { | ||||
| 				const resource = this.getNodeParameter('resource', i) as string; | ||||
| 				const operation = this.getNodeParameter('operation', i) as string; | ||||
| 				 | ||||
| 				// Obtener definición de la API
 | ||||
| 				const apiDefinition = ApiHelper.getApiDefinition(resource, operation); | ||||
| 				if (!apiDefinition) { | ||||
| 					throw new Error(`API definition not found for resource: ${resource}, operation: ${operation}`); | ||||
| 				} | ||||
| 
 | ||||
| 				// Obtener credenciales
 | ||||
| 				const credentials = await this.getCredentials('s4dsApi'); | ||||
| 				 | ||||
| 				// Determinar la URL base
 | ||||
| 				let baseUrl = credentials.baseUrl; | ||||
| 				if (baseUrl === 'custom') { | ||||
| 					baseUrl = credentials.customBaseUrl; | ||||
| 				} | ||||
| 				 | ||||
| 				if (!baseUrl) { | ||||
| 					throw new Error('Base URL is required. Please configure the S4DS API credentials.'); | ||||
| 				} | ||||
| 
 | ||||
| 				// Preparar headers
 | ||||
| 				let headers: Record<string, string> = { | ||||
| 					Accept: 'application/json', | ||||
| 					'Content-Type': 'application/json', | ||||
| 				}; | ||||
| 
 | ||||
| 				// Agregar autenticación si es requerida
 | ||||
| 				if (apiDefinition.requiresAuth) { | ||||
| 					// Siempre usar la key por defecto 's4ds_token'
 | ||||
| 					const contextKey = 's4ds_token'; | ||||
| 					const contextData = this.getWorkflowStaticData('global'); | ||||
| 					const tokenData = contextData[contextKey] as any; | ||||
| 					if (!tokenData || !tokenData.authorization_header) { | ||||
| 						throw new Error(`Token not found in context with key 's4ds_token'. Please run an authentication operation first.`); | ||||
| 					} | ||||
| 					headers.Authorization = tokenData.authorization_header; | ||||
| 				} | ||||
| 
 | ||||
| 				// Preparar parámetros de query
 | ||||
| 				const queryParams: Record<string, any> = {}; | ||||
| 				if (apiDefinition.parameters) { | ||||
| 					const queryParameters = this.getNodeParameter('queryParameters', i, {}) as Record<string, any>; | ||||
| 					apiDefinition.parameters | ||||
| 						.filter(p => p.in === 'query') | ||||
| 						.forEach(param => { | ||||
| 							if (queryParameters[param.name] !== undefined && queryParameters[param.name] !== '') { | ||||
| 								queryParams[param.name] = queryParameters[param.name]; | ||||
| 							} | ||||
| 						}); | ||||
| 				} | ||||
| 
 | ||||
| 				// Preparar body si es necesario
 | ||||
| 				let body: any = undefined; | ||||
| 				if (apiDefinition.method === 'POST' && resource === 'authentication') { | ||||
| 					body = { | ||||
| 						username: credentials.username, | ||||
| 						password: credentials.password, | ||||
| 					}; | ||||
| 				} else if (apiDefinition.requestBody && apiDefinition.requestBody.schema) { | ||||
| 					// Usar DTO para request body
 | ||||
| 					let requestBodyData = this.getNodeParameter('requestBody', i, {}); | ||||
| 					if (typeof requestBodyData === 'string') { | ||||
| 						try { | ||||
| 							requestBodyData = JSON.parse(requestBodyData); | ||||
| 						} catch (e) { | ||||
| 							throw new Error('El JSON del body no es válido: ' + e.message); | ||||
| 						} | ||||
| 					} | ||||
| 					body = requestBodyData; | ||||
| 				} else if (apiDefinition.parameters) { | ||||
| 					const bodyParameters = this.getNodeParameter('bodyParameters', i, {}) as Record<string, any>; | ||||
| 					const bodyParams = apiDefinition.parameters.filter(p => p.in === 'body'); | ||||
| 					if (bodyParams.length > 0) { | ||||
| 						body = {}; | ||||
| 						bodyParams.forEach(param => { | ||||
| 							if (bodyParameters[param.name] !== undefined && bodyParameters[param.name] !== '') { | ||||
| 								body[param.name] = bodyParameters[param.name]; | ||||
| 							} | ||||
| 						}); | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				// Construir URL con parámetros de query
 | ||||
| 				let url = `${baseUrl}${apiDefinition.endpoint}`; | ||||
| 				if (Object.keys(queryParams).length > 0) { | ||||
| 					const queryString = Object.keys(queryParams) | ||||
| 						.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`) | ||||
| 						.join('&'); | ||||
| 					url += `?${queryString}`; | ||||
| 				} | ||||
| 
 | ||||
| 				// Ejecutar la petición HTTP
 | ||||
| 				const response = await this.helpers.httpRequest({ | ||||
| 					method: apiDefinition.method as IHttpRequestMethods, | ||||
| 					url, | ||||
| 					headers, | ||||
| 					body, | ||||
| 				}); | ||||
| 
 | ||||
| 				// Procesar respuesta según el tipo de operación
 | ||||
| 				if (resource === 'authentication' && operation === 'generateToken') { | ||||
| 					// Almacenar token en contexto
 | ||||
| 					const contextKey = 's4ds_token'; | ||||
| 					const tokenData = { | ||||
| 						token: response.token, | ||||
| 						token_type: response.token_type, | ||||
| 						expires_in: response.expires_in, | ||||
| 						expires_at: new Date(Date.now() + response.expires_in * 1000).toISOString(), | ||||
| 						authorization_header: `${response.token_type} ${response.token}`, | ||||
| 					}; | ||||
| 					// Almacenar en contexto del workflow
 | ||||
| 					this.getWorkflowStaticData('global')[contextKey] = tokenData; | ||||
| 
 | ||||
| 					// Retornar respuesta sin el token por seguridad
 | ||||
| 					const secureResponse = { | ||||
| 						success: true, | ||||
| 						token_type: response.token_type, | ||||
| 						expires_in: response.expires_in, | ||||
| 						expires_at: tokenData.expires_at, | ||||
| 						message: 'Token generated successfully and stored in workflow context', | ||||
| 						context_key: contextKey, | ||||
| 					}; | ||||
| 
 | ||||
| 					returnData.push({ | ||||
| 						json: secureResponse, | ||||
| 					}); | ||||
| 				} else { | ||||
| 					// Retornar respuesta normal
 | ||||
| 					returnData.push({ | ||||
| 						json: response, | ||||
| 					}); | ||||
| 				} | ||||
| 			} catch (error) { | ||||
| 				if (this.continueOnFail()) { | ||||
| 					returnData.push({ | ||||
| 						json: { | ||||
| 							error: error.message, | ||||
| 						}, | ||||
| 					}); | ||||
| 					continue; | ||||
| 				} | ||||
| 				throw error; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return [returnData]; | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| }  | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue