Skip to content

Commit

Permalink
fix(core): Stop copying icons, and instead serve them directly from t…
Browse files Browse the repository at this point in the history
…he source path

Fixes #4973 & #5274
  • Loading branch information
netroy committed Feb 8, 2023
1 parent f9adbba commit 0dbac66
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 33 deletions.
26 changes: 1 addition & 25 deletions packages/cli/src/LoadNodesAndCredentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,7 @@ import type {
import { LoggerProxy, ErrorReporterProxy as ErrorReporter } from 'n8n-workflow';

import { createWriteStream } from 'fs';
import {
access as fsAccess,
copyFile,
mkdir,
readdir as fsReaddir,
stat as fsStat,
} from 'fs/promises';
import { access as fsAccess, mkdir, readdir as fsReaddir, stat as fsStat } from 'fs/promises';
import path from 'path';
import config from '@/config';
import type { InstalledPackages } from '@db/entities/InstalledPackages';
Expand Down Expand Up @@ -407,24 +401,6 @@ export class LoadNodesAndCredentialsClass implements INodesAndCredentials {
this.types.nodes = this.types.nodes.concat(types.nodes);
this.types.credentials = this.types.credentials.concat(types.credentials);

// Copy over all icons and set `iconUrl` for the frontend
const iconPromises = Object.entries(types).flatMap(([typeName, typesArr]) =>
typesArr.map((type) => {
if (!type.icon?.startsWith('file:')) return;
const icon = type.icon.substring(5);
const iconUrl = `icons/${typeName}/${type.name}${path.extname(icon)}`;
delete type.icon;
type.iconUrl = iconUrl;
const source = path.join(dir, icon);
const destination = path.join(GENERATED_STATIC_DIR, iconUrl);
return mkdir(path.dirname(destination), { recursive: true }).then(async () =>
copyFile(source, destination),
);
}),
);

await Promise.all(iconPromises);

// Nodes and credentials that have been loaded immediately
for (const nodeTypeName in loader.nodeTypes) {
this.loaded.nodes[nodeTypeName] = loader.nodeTypes[nodeTypeName];
Expand Down
13 changes: 13 additions & 0 deletions packages/cli/src/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,19 @@ class Server extends AbstractServer {
},
};

for (const [dir, loader] of Object.entries(this.loadNodesAndCredentials.loaders)) {
const pathPrefix = `/icons/${loader.packageName}`;
this.app.use(`${pathPrefix}/*/*.(svg|png)`, async (req, res) => {
const filePath = pathResolve(dir, req.originalUrl.substring(pathPrefix.length + 1));
try {
await fsAccess(filePath);
res.sendFile(filePath);
} catch {
res.sendStatus(404);
}
});
}

this.app.use(
'/',
express.static(GENERATED_STATIC_DIR),
Expand Down
21 changes: 13 additions & 8 deletions packages/core/src/DirectoryLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,27 +48,29 @@ export abstract class DirectoryLoader {
protected readonly includeNodes: string[] = [],
) {}

abstract packageName: string;
abstract loadAll(): Promise<void>;

protected resolvePath(file: string) {
return path.resolve(this.directory, file);
}

protected loadNodeFromFile(packageName: string, nodeName: string, filePath: string) {
protected loadNodeFromFile(nodeName: string, filePath: string) {
let tempNode: INodeType | IVersionedNodeType;
let nodeVersion = 1;
const isCustom = this.packageName === 'CUSTOM';

try {
tempNode = loadClassInIsolation(filePath, nodeName);
this.addCodex({ node: tempNode, filePath, isCustom: packageName === 'CUSTOM' });
this.addCodex({ node: tempNode, filePath, isCustom });
} catch (error) {
Logger.error(
`Error loading node "${nodeName}" from: "${filePath}" - ${(error as Error).message}`,
);
throw error;
}

const fullNodeName = `${packageName}.${tempNode.description.name}`;
const fullNodeName = `${this.packageName}.${tempNode.description.name}`;

if (this.includeNodes.length && !this.includeNodes.includes(fullNodeName)) {
return;
Expand All @@ -88,12 +90,12 @@ export abstract class DirectoryLoader {
}

const currentVersionNode = tempNode.nodeVersions[tempNode.currentVersion];
this.addCodex({ node: currentVersionNode, filePath, isCustom: packageName === 'CUSTOM' });
this.addCodex({ node: currentVersionNode, filePath, isCustom });
nodeVersion = tempNode.currentVersion;

if (currentVersionNode.hasOwnProperty('executeSingle')) {
Logger.warn(
`"executeSingle" will get deprecated soon. Please update the code of node "${packageName}.${nodeName}" to use "execute" instead!`,
`"executeSingle" will get deprecated soon. Please update the code of node "${this.packageName}.${nodeName}" to use "execute" instead!`,
{ filePath },
);
}
Expand Down Expand Up @@ -236,7 +238,8 @@ export abstract class DirectoryLoader {
if (obj.icon?.startsWith('file:')) {
const iconPath = path.join(path.dirname(filePath), obj.icon.substring(5));
const relativePath = path.relative(this.directory, iconPath);
obj.icon = `file:${relativePath}`;
obj.iconUrl = `icons/${this.packageName}/${relativePath.substring(5)}`;
delete obj.icon;
}
}
}
Expand All @@ -246,6 +249,8 @@ export abstract class DirectoryLoader {
* e.g. `~/.n8n/custom`
*/
export class CustomDirectoryLoader extends DirectoryLoader {
packageName = 'CUSTOM';

override async loadAll() {
const filePaths = await glob('**/*.@(node|credentials).js', {
cwd: this.directory,
Expand All @@ -256,7 +261,7 @@ export class CustomDirectoryLoader extends DirectoryLoader {
const [fileName, type] = path.parse(filePath).name.split('.');

if (type === 'node') {
this.loadNodeFromFile('CUSTOM', fileName, filePath);
this.loadNodeFromFile(fileName, filePath);
} else if (type === 'credentials') {
this.loadCredentialFromFile(fileName, filePath);
}
Expand Down Expand Up @@ -300,7 +305,7 @@ export class PackageDirectoryLoader extends DirectoryLoader {
const filePath = this.resolvePath(node);
const [nodeName] = path.parse(node).name.split('.');

this.loadNodeFromFile(this.packageName, nodeName, filePath);
this.loadNodeFromFile(nodeName, filePath);
}
}

Expand Down

0 comments on commit 0dbac66

Please sign in to comment.