import { Service } from 'typedi'; import uniq from 'lodash/uniq'; import { createWriteStream } from 'fs'; import { mkdir } from 'fs/promises'; import path from 'path'; import type { ICredentialType, INodeTypeBaseDescription } from 'n8n-workflow'; import { GENERATED_STATIC_DIR } from '@/constants'; import { CredentialsOverwrites } from '@/CredentialsOverwrites'; import { CredentialTypes } from '@/CredentialTypes'; import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials'; @Service() export class FrontendService { constructor( private readonly loadNodesAndCredentials: LoadNodesAndCredentials, private readonly credentialTypes: CredentialTypes, private readonly credentialsOverwrites: CredentialsOverwrites, ) {} async generateTypes() { this.overwriteCredentialsProperties(); // pre-render all the node and credential types as static json files await mkdir(path.join(GENERATED_STATIC_DIR, 'types'), { recursive: true }); const { credentials, nodes } = this.loadNodesAndCredentials.types; this.writeStaticJSON('nodes', nodes); this.writeStaticJSON('credentials', credentials); } private writeStaticJSON(name: string, data: INodeTypeBaseDescription[] | ICredentialType[]) { const filePath = path.join(GENERATED_STATIC_DIR, `types/${name}.json`); const stream = createWriteStream(filePath, 'utf-8'); stream.write('[\n'); data.forEach((entry, index) => { stream.write(JSON.stringify(entry)); if (index !== data.length - 1) stream.write(','); stream.write('\n'); }); stream.write(']\n'); stream.end(); } private overwriteCredentialsProperties() { const { credentials } = this.loadNodesAndCredentials.types; const credentialsOverwrites = this.credentialsOverwrites.getAll(); for (const credential of credentials) { const overwrittenProperties = []; this.credentialTypes .getParentTypes(credential.name) .reverse() .map((name) => credentialsOverwrites[name]) .forEach((overwrite) => { if (overwrite) overwrittenProperties.push(...Object.keys(overwrite)); }); if (credential.name in credentialsOverwrites) { overwrittenProperties.push(...Object.keys(credentialsOverwrites[credential.name])); } if (overwrittenProperties.length) { credential.__overwrittenProperties = uniq(overwrittenProperties); } } } }