chore: Resolve master-to-3.x sync conflicts

This commit is contained in:
n8n-cat-bot[bot]
2026-10-10 06:15:33 +00:00
parent 31e9ae3db3
commit 0a69c6edbd
14 changed files with 31 additions and 89 deletions
@@ -4,8 +4,4 @@ export const NPM_COMMUNITY_NODE_SEARCH_API_URL = 'https://api.npms.io/v2/';
* Node-authoring API level this runtime supports, and so the highest
* `n8nNodesApiVersion` a node may declare to be installed.
*/
<<<<<<< HEAD
export const N8N_NODES_API_VERSION = 3;
=======
export const N8N_NODES_API_VERSION = '1.0';
>>>>>>> 7424f0ca0452f9dc9fe4cf6627ecbf0b315ed1e3
export const N8N_NODES_API_VERSION = '3.0';
+11 -13
View File
@@ -2,7 +2,17 @@
This list shows all the versions which include breaking changes and how to upgrade.
<<<<<<< HEAD
# Unreleased
## n8n Packages (preview)
Package manifest requirements now use `usedBy: [{ "kind": "workflow", "id": "workflow-id" }]`.
The `usedByWorkflows` field is no longer supported.
Re-export packages after upgrading.
Regenerate existing Promotions snapshots.
Package import errors also use `usedBy` for resource consumers.
Update API clients to read each consumer's `kind` and `id`.
# 3.0.0
### What changed?
@@ -68,19 +78,7 @@ The `$evaluateExpression()` helper was removed from the Code node. A Code node t
### When is action necessary?
If your Code nodes call `$evaluateExpression()`. Evaluate the expression in a node field instead, for example in an Edit Fields (Set) node before the Code node, and read the result from the input item. Code nodes on a secure-mode task runner, the default since 2.0, already failed on this call.
=======
# Unreleased
## n8n Packages (preview)
Package manifest requirements now use `usedBy: [{ "kind": "workflow", "id": "workflow-id" }]`.
The `usedByWorkflows` field is no longer supported.
Re-export packages after upgrading.
Regenerate existing Promotions snapshots.
Package import errors also use `usedBy` for resource consumers.
Update API clients to read each consumer's `kind` and `id`.
>>>>>>> 7424f0ca0452f9dc9fe4cf6627ecbf0b315ed1e3
# 2.0.0
### What changed?
@@ -196,16 +196,8 @@ export class N8nPackagesService {
const dependencyPolicy = request.dependencyPolicy ?? ExportDependencyPolicy.Fail;
const isReferenceOnly = dependencyPolicy === ExportDependencyPolicy.ReferenceOnly;
<<<<<<< HEAD
const workflowIds = request.workflowIds ?? [];
const folderIds = request.folderIds ?? [];
const projectIds = request.projectIds ?? [];
const includeTags = request.includeTags ?? true;
const workflowVersionPolicy = request.workflowVersionPolicy ?? WorkflowVersionPolicy.Latest;
=======
const includeTags = (request.includeTags ?? true) && !this.globalConfig.tags.disabled;
const versionPolicy = request.versionPolicy ?? ExportVersionPolicy.Latest;
>>>>>>> 7424f0ca0452f9dc9fe4cf6627ecbf0b315ed1e3
const credentialExportPolicy =
request.credentialExportPolicy ?? CredentialExportPolicy.ExpressionValuesOnly;
const includeArchivedWorkflows = request.includeArchivedWorkflows ?? false;
@@ -27,8 +27,12 @@ describe('inline sub-workflow with a deprecated node', () => {
'n8n-nodes-base.manualTrigger',
'n8n-nodes-base.executeWorkflow',
'n8n-nodes-base.executeWorkflowTrigger',
'n8n-nodes-base.function',
]);
const deprecatedNode = utils.createDeprecatedNodeType('n8n-nodes-base.function');
deprecatedNode.description.inputs = [NodeConnectionTypes.Main];
deprecatedNode.description.outputs = [NodeConnectionTypes.Main];
deprecatedNode.execute = async () => [[{ json: { ran: 'function' } }]];
nodeTypes['n8n-nodes-base.function'] = { type: deprecatedNode, sourcePath: '' };
await utils.initNodeTypes(nodeTypes);
await utils.initBinaryDataService();
@@ -16,8 +16,6 @@ import { HttpBasicAuth } from 'n8n-nodes-base/credentials/HttpBasicAuth.credenti
import { HttpHeaderAuth } from 'n8n-nodes-base/credentials/HttpHeaderAuth.credentials';
import { OpenAiApi } from 'n8n-nodes-base/credentials/OpenAiApi.credentials';
import { FormTrigger } from 'n8n-nodes-base/nodes/Form/FormTrigger.node';
import { Function as FunctionNode } from 'n8n-nodes-base/nodes/Function/Function.node';
import { FunctionItem } from 'n8n-nodes-base/nodes/FunctionItem/FunctionItem.node';
import { ManualTrigger } from 'n8n-nodes-base/nodes/ManualTrigger/ManualTrigger.node';
import { ScheduleTrigger } from 'n8n-nodes-base/nodes/Schedule/ScheduleTrigger.node';
import { Set } from 'n8n-nodes-base/nodes/Set/Set.node';
@@ -114,6 +112,15 @@ function minimalNodeType(name: string, properties: INodeProperties[] = []): INod
};
}
// Test-only definitions keep deprecation coverage after 3.x removes the legacy nodes.
export function createDeprecatedNodeType(name: string): INodeType {
const { type } = minimalNodeType(name, [
{ displayName: 'Code', name: 'functionCode', type: 'string', default: '' },
]);
type.description.deprecated = true;
return type as INodeType;
}
function buildDefaultNodes(): INodeTypeData {
ScheduleTrigger.prototype.trigger = async () => ({});
return {
@@ -140,11 +147,11 @@ function buildDefaultNodes(): INodeTypeData {
sourcePath: '',
},
'n8n-nodes-base.function': {
type: new FunctionNode(),
type: createDeprecatedNodeType('n8n-nodes-base.function'),
sourcePath: '',
},
'n8n-nodes-base.functionItem': {
type: new FunctionItem(),
type: createDeprecatedNodeType('n8n-nodes-base.functionItem'),
sourcePath: '',
},
// Minimal mocks for node types the package-import fixtures reference at typeVersion 1.
@@ -33,11 +33,6 @@ const ALLOWED_KEY_EXPORTS = [
'EXTERNAL_SECRETS_PROVIDER_MODAL_KEY',
'FROM_AI_PARAMETERS_MODAL_KEY',
'IMPORT_CURL_MODAL_KEY',
<<<<<<< HEAD
'LOG_STREAM_MODAL_KEY',
=======
'IMPORT_WORKFLOW_URL_MODAL_KEY',
>>>>>>> 7424f0ca0452f9dc9fe4cf6627ecbf0b315ed1e3
'MIGRATE_WORKFLOW_MODAL_KEY',
'NEW_ASSISTANT_SESSION_MODAL',
'NPS_SURVEY_MODAL_KEY',
@@ -9,11 +9,6 @@ import {
DELETE_SECRETS_PROVIDER_MODAL_KEY,
FROM_AI_PARAMETERS_MODAL_KEY,
IMPORT_CURL_MODAL_KEY,
<<<<<<< HEAD
LOG_STREAM_MODAL_KEY,
=======
IMPORT_WORKFLOW_URL_MODAL_KEY,
>>>>>>> 7424f0ca0452f9dc9fe4cf6627ecbf0b315ed1e3
VERSIONS_MODAL_KEY,
NEW_ASSISTANT_SESSION_MODAL,
NPS_SURVEY_MODAL_KEY,
@@ -12,11 +12,6 @@ import {
EXTERNAL_SECRETS_PROVIDER_MODAL_KEY,
FROM_AI_PARAMETERS_MODAL_KEY,
IMPORT_CURL_MODAL_KEY,
<<<<<<< HEAD
LOG_STREAM_MODAL_KEY,
=======
IMPORT_WORKFLOW_URL_MODAL_KEY,
>>>>>>> 7424f0ca0452f9dc9fe4cf6627ecbf0b315ed1e3
MIGRATE_WORKFLOW_MODAL_KEY,
NEW_ASSISTANT_SESSION_MODAL,
NPS_SURVEY_MODAL_KEY,
@@ -1,8 +0,0 @@
import { Function } from './Function.node';
describe('Function Node', () => {
it('is marked deprecated so the backend refuses new instances', () => {
const node = new Function();
expect(node.description.deprecated).toBe(true);
});
});
@@ -1,8 +0,0 @@
import { FunctionItem } from './FunctionItem.node';
describe('FunctionItem Node', () => {
it('is marked deprecated so the backend refuses new instances', () => {
const node = new FunctionItem();
expect(node.description.deprecated).toBe(true);
});
});
@@ -1,4 +1,5 @@
import { N8N_NODES_API_VERSION } from '@n8n/constants';
import { parseNodesApiLevel } from 'n8n-workflow';
import { test as base } from '../base';
import { IMPORT_MARKER_DIR, PUBLISHED_PACKAGES, type FixturePackage } from './fixture-packages';
@@ -20,7 +21,7 @@ export interface PackageDisk {
type Fixtures = {
/** Publishes every fixture package into the stack's registry, once per worker, before any test runs. */
publishedPackages: readonly FixturePackage[];
/** Node API level the instance supports: 2.x runs level 1, 3.x runs level 3. */
/** Major node API level for fixtures that require integer levels. */
supportedNodesApiVersion: number;
/** What the package left on the instance's disk; follows the main container across a restart. */
packageDisk: PackageDisk;
@@ -44,7 +45,7 @@ export const test = base.extend<
],
supportedNodesApiVersion: async ({ api: _api }, use) => {
await use(N8N_NODES_API_VERSION);
await use(parseNodesApiLevel(N8N_NODES_API_VERSION)!.major);
},
packageDisk: async ({ n8nContainer }, use) => {
@@ -164,15 +164,9 @@ test.describe(
await expect(n8n.ndv.getNodeVersion()).toContainText('Latest');
await n8n.ndv.close();
<<<<<<< HEAD
await n8n.canvas.openNode('Read Spreadsheet File');
await n8n.ndv.openSettings();
await expect(n8n.ndv.getNodeVersion()).toContainText('Spreadsheet File node version 1');
=======
await n8n.canvas.openNode('Cron');
await n8n.ndv.openSettings();
await expect(n8n.ndv.getNodeVersion()).toContainText('Cron node version 1');
>>>>>>> 7424f0ca0452f9dc9fe4cf6627ecbf0b315ed1e3
await expect(n8n.ndv.getNodeVersion()).toContainText('Deprecated');
await n8n.ndv.close();
});
@@ -38,12 +38,8 @@
"type": "n8n-nodes-base.code",
"position": [620, 420],
"parameters": {
<<<<<<< HEAD
"mode": "runOnceForAllItems",
"jsCode": "const _ = require('lodash')\n\nconst sanitize = str => _.chain(str)\n .replace(/[^A-Za-z0-9&.-]/g, '-') // sanitise via whitelist of characters\n .replace(/-(?=-)/g, '') // remove repeated dashes - https://regexr.com/6ag8h\n .trim('-') // trim any leading/trailing dashes\n .truncate({\n length: 60,\n omission: '-' // when the string ends with '-', you'll know it was truncated\n })\n .value()\n\nconst result = _.flatMap($input.all().map(item => {\n //console.log({item})\n\n // Maps each attachment to a separate item\n return _.values(item.binary).map(file => {\n console.log(\"Saving attachement:\", file.fileName, 'from:', ...item.json.from.value)\n \n // sanitize filename but exclude extension\n const filename_parts = file.fileName.split('.')\n const ext = _.slice(filename_parts, filename_parts.length-1)\n const filename_main = _.join(_.dropRight(filename_parts), '.')\n file.fileName = sanitize(filename_main) + '.' + ext\n \n return {\n json: {\n from: sanitize(item.json.from.value[0].name),\n date: sanitize(new Date(item.json.date).toISOString().split(\"T\")[0]) // get date part \"2020-01-01\"\n }, \n binary: { file }\n }\n })\n}))\n\n//console.log(result)\nreturn result"
=======
"jsCode": "const _ = require('lodash')\n\nconst sanitize = str => _.chain(str)\n .replace(/[^A-Za-z0-9&.-]/g, '-') // sanitise via whitelist of characters\n .replace(/-(?=-)/g, '') // remove repeated dashes - https://regexr.com/6ag8h\n .trim('-') // trim any leading/trailing dashes\n .truncate({\n length: 60,\n omission: '-' // when the string ends with '-', you'll know it was truncated\n })\n .value()\n\nconst result = _.flatMap(items.map(item => {\n //console.log({item})\n\n // Maps each attachment to a separate item\n return _.values(item.binary).map(file => {\n console.log(\"Saving attachement:\", file.fileName, 'from:', ...item.json.from.value)\n \n // sanitize filename but exclude extension\n const filename_parts = file.fileName.split('.')\n const ext = _.slice(filename_parts, filename_parts.length-1)\n const filename_main = _.join(_.dropRight(filename_parts), '.')\n file.fileName = sanitize(filename_main) + '.' + ext\n \n return {\n json: {\n from: sanitize(item.json.from.value[0].name),\n date: sanitize(new Date(item.json.date).toISOString().split(\"T\")[0]) // get date part \"2020-01-01\"\n }, \n binary: { file }\n }\n })\n}))\n\n//console.log(result)\nreturn result"
>>>>>>> 7424f0ca0452f9dc9fe4cf6627ecbf0b315ed1e3
},
"typeVersion": 2
}
@@ -77,12 +73,6 @@
"workflowInfo": {
"nodeCount": 3,
"nodeTypes": {
<<<<<<< HEAD
=======
"n8n-nodes-base.code": {
"count": 1
},
>>>>>>> 7424f0ca0452f9dc9fe4cf6627ecbf0b315ed1e3
"n8n-nodes-base.nextCloud": {
"count": 1
},
@@ -125,11 +115,7 @@
},
{
"id": 14,
<<<<<<< HEAD
"icon": "node:code",
=======
"icon": "fa:code",
>>>>>>> 7424f0ca0452f9dc9fe4cf6627ecbf0b315ed1e3
"name": "n8n-nodes-base.code",
"defaults": {
"name": "Code"
@@ -10,13 +10,8 @@
},
{
"id": "1ea0a87c-3395-4bd9-84fb-cf8b0f769cc4",
<<<<<<< HEAD
"name": "Read Spreadsheet File",
"type": "n8n-nodes-base.spreadsheetFile",
=======
"name": "Cron",
"type": "n8n-nodes-base.cron",
>>>>>>> 7424f0ca0452f9dc9fe4cf6627ecbf0b315ed1e3
"typeVersion": 1,
"position": [960, 460],
"parameters": {}