mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-21 02:56:40 -08:00
feat(API): Add route for schema static files (#12770)
This commit is contained in:
parent
1d33b9f4a7
commit
d981b5659a
|
@ -7,7 +7,7 @@
|
|||
"clean": "rimraf dist .turbo",
|
||||
"dev": "pnpm run watch",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && pnpm n8n-copy-icons && pnpm n8n-generate-metadata",
|
||||
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && pnpm n8n-copy-static-files && pnpm n8n-generate-metadata",
|
||||
"format": "biome format --write .",
|
||||
"format:check": "biome ci .",
|
||||
"lint": "eslint nodes credentials utils --quiet",
|
||||
|
|
|
@ -211,4 +211,44 @@ describe('LoadNodesAndCredentials', () => {
|
|||
expect(result.description.displayName).toBe('Special @#$% Node Tool');
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveSchema', () => {
|
||||
let instance: LoadNodesAndCredentials;
|
||||
|
||||
beforeEach(() => {
|
||||
instance = new LoadNodesAndCredentials(mock(), mock(), mock(), mock());
|
||||
instance.knownNodes['n8n-nodes-base.test'] = {
|
||||
className: 'Test',
|
||||
sourcePath: '/nodes-base/dist/nodes/Test/Test.node.js',
|
||||
};
|
||||
});
|
||||
|
||||
it('should return undefined if the node is not known', () => {
|
||||
const result = instance.resolveSchema({
|
||||
node: 'n8n-nodes-base.doesNotExist',
|
||||
version: '1.0.0',
|
||||
resource: 'account',
|
||||
operation: 'get',
|
||||
});
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return the correct path if the node is known', () => {
|
||||
const result = instance.resolveSchema({
|
||||
node: 'n8n-nodes-base.test',
|
||||
version: '1.0.0',
|
||||
resource: 'account',
|
||||
operation: 'get',
|
||||
});
|
||||
expect(result).toEqual('/nodes-base/dist/nodes/Test/__schema__/v1.0.0/account/get.json');
|
||||
});
|
||||
|
||||
it('should return the correct path if there is no resource or operation', () => {
|
||||
const result = instance.resolveSchema({
|
||||
node: 'n8n-nodes-base.test',
|
||||
version: '1.0.0',
|
||||
});
|
||||
expect(result).toEqual('/nodes-base/dist/nodes/Test/__schema__/v1.0.0.json');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -174,6 +174,29 @@ export class LoadNodesAndCredentials {
|
|||
return isContainedWithin(loader.directory, filePath) ? filePath : undefined;
|
||||
}
|
||||
|
||||
resolveSchema({
|
||||
node,
|
||||
version,
|
||||
resource,
|
||||
operation,
|
||||
}: {
|
||||
node: string;
|
||||
version: string;
|
||||
resource?: string;
|
||||
operation?: string;
|
||||
}): string | undefined {
|
||||
const nodePath = this.known.nodes[node]?.sourcePath;
|
||||
if (!nodePath) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const nodeParentPath = path.dirname(nodePath);
|
||||
const schemaPath = ['__schema__', `v${version}`, resource, operation].filter(Boolean).join('/');
|
||||
const filePath = path.resolve(nodeParentPath, schemaPath + '.json');
|
||||
|
||||
return isContainedWithin(nodeParentPath, filePath) ? filePath : undefined;
|
||||
}
|
||||
|
||||
getCustomDirectories(): string[] {
|
||||
const customDirectories = [this.instanceSettings.customExtensionDir];
|
||||
|
||||
|
|
|
@ -322,8 +322,27 @@ export class Server extends AbstractServer {
|
|||
res.sendStatus(404);
|
||||
};
|
||||
|
||||
const serveSchemas: express.RequestHandler = async (req, res) => {
|
||||
const { node, version, resource, operation } = req.params;
|
||||
const filePath = this.loadNodesAndCredentials.resolveSchema({
|
||||
node,
|
||||
resource,
|
||||
operation,
|
||||
version,
|
||||
});
|
||||
|
||||
if (filePath) {
|
||||
try {
|
||||
await fsAccess(filePath);
|
||||
return res.sendFile(filePath, cacheOptions);
|
||||
} catch {}
|
||||
}
|
||||
res.sendStatus(404);
|
||||
};
|
||||
|
||||
this.app.use('/icons/@:scope/:packageName/*/*.(svg|png)', serveIcons);
|
||||
this.app.use('/icons/:packageName/*/*.(svg|png)', serveIcons);
|
||||
this.app.use('/schemas/:node/:version/:resource?/:operation?.json', serveSchemas);
|
||||
|
||||
const isTLSEnabled =
|
||||
this.globalConfig.protocol === 'https' && !!(this.sslKey && this.sslCert);
|
||||
|
|
|
@ -6,13 +6,18 @@ const { cp } = require('fs/promises');
|
|||
const { packageDir } = require('./common');
|
||||
|
||||
const limiter = pLimit(20);
|
||||
const icons = glob.sync('{nodes,credentials}/**/*.{png,svg}', { cwd: packageDir });
|
||||
const staticFiles = glob.sync(
|
||||
['{nodes,credentials}/**/*.{png,svg}', 'nodes/**/__schema__/**/*.json'],
|
||||
{
|
||||
cwd: packageDir,
|
||||
},
|
||||
);
|
||||
|
||||
(async () => {
|
||||
await Promise.all(
|
||||
icons.map((icon) =>
|
||||
staticFiles.map((path) =>
|
||||
limiter(() => {
|
||||
return cp(icon, `dist/${icon}`, { recursive: true });
|
||||
return cp(path, `dist/${path}`, { recursive: true });
|
||||
}),
|
||||
),
|
||||
);
|
|
@ -5,7 +5,7 @@
|
|||
"main": "dist/index",
|
||||
"types": "dist/index.d.ts",
|
||||
"bin": {
|
||||
"n8n-copy-icons": "./bin/copy-icons",
|
||||
"n8n-copy-static-files": "./bin/copy-static-files",
|
||||
"n8n-generate-translations": "./bin/generate-translations",
|
||||
"n8n-generate-metadata": "./bin/generate-metadata"
|
||||
},
|
||||
|
|
110
packages/nodes-base/nodes/ActiveCampaign/__schema__/v1.0.0/account/get.json
vendored
Normal file
110
packages/nodes-base/nodes/ActiveCampaign/__schema__/v1.0.0/account/get.json
vendored
Normal file
|
@ -0,0 +1,110 @@
|
|||
{
|
||||
"type": "object",
|
||||
"value": [
|
||||
{
|
||||
"key": "account",
|
||||
"type": "Object",
|
||||
"value": [
|
||||
{
|
||||
"key": "accountUrl",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".account.accountUrl"
|
||||
},
|
||||
{
|
||||
"key": "createdTimestamp",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".account.createdTimestamp"
|
||||
},
|
||||
{
|
||||
"key": "id",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".account.id"
|
||||
},
|
||||
{
|
||||
"key": "links",
|
||||
"type": "Object",
|
||||
"value": [
|
||||
{
|
||||
"key": "accountContacts",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".account.links.accountContacts"
|
||||
},
|
||||
{
|
||||
"key": "accountCustomFieldData",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".account.links.accountCustomFieldData"
|
||||
},
|
||||
{
|
||||
"key": "contactEmails",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".account.links.contactEmails"
|
||||
},
|
||||
{
|
||||
"key": "emailActivities",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".account.links.emailActivities"
|
||||
},
|
||||
{
|
||||
"key": "notes",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".account.links.notes"
|
||||
},
|
||||
{
|
||||
"key": "owner",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".account.links.owner"
|
||||
},
|
||||
{
|
||||
"key": "required",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".account.links.required"
|
||||
}
|
||||
],
|
||||
"path": ".account.links"
|
||||
},
|
||||
{
|
||||
"key": "name",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".account.name"
|
||||
},
|
||||
{
|
||||
"key": "owner",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".account.owner"
|
||||
},
|
||||
{
|
||||
"key": "updatedTimestamp",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".account.updatedTimestamp"
|
||||
},
|
||||
{
|
||||
"key": "required",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".account.required"
|
||||
}
|
||||
],
|
||||
"path": ".account"
|
||||
},
|
||||
{
|
||||
"key": "required",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"path": ".required"
|
||||
}
|
||||
],
|
||||
"path": ""
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
"clean": "rimraf dist .turbo",
|
||||
"dev": "pnpm watch",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && pnpm n8n-copy-icons && pnpm n8n-generate-translations && pnpm n8n-generate-metadata",
|
||||
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && pnpm n8n-copy-static-files && pnpm n8n-generate-translations && pnpm n8n-generate-metadata",
|
||||
"format": "biome format --write .",
|
||||
"format:check": "biome ci .",
|
||||
"lint": "eslint nodes credentials utils test --quiet && node ./scripts/validate-load-options-methods.js",
|
||||
|
|
Loading…
Reference in a new issue