n8n-nodes-version 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,8 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.N8nVersion = void 0;
4
4
  const n8n_workflow_1 = require("n8n-workflow");
5
5
  const VersionUtils_1 = require("../VersionUtils");
6
- const CompatibilityUtils_1 = require("../CompatibilityUtils");
7
- const GitUtils_1 = require("../GitUtils");
8
6
  class N8nVersion {
9
7
  constructor() {
10
8
  this.description = {
@@ -12,8 +10,8 @@ class N8nVersion {
12
10
  name: 'n8nVersion',
13
11
  icon: 'file:n8n-version.svg',
14
12
  group: ['transform'],
15
- version: 2,
16
- description: 'Manage n8n versions, backups, and compatibility audits',
13
+ version: 3,
14
+ description: 'Manage n8n versions and check changelogs',
17
15
  defaults: {
18
16
  name: 'n8n Version',
19
17
  },
@@ -30,14 +28,6 @@ class N8nVersion {
30
28
  name: 'Version Info',
31
29
  value: 'version',
32
30
  },
33
- {
34
- name: 'Compatibility',
35
- value: 'compatibility',
36
- },
37
- {
38
- name: 'Backup',
39
- value: 'backup',
40
- },
41
31
  ],
42
32
  default: 'version',
43
33
  },
@@ -67,46 +57,6 @@ class N8nVersion {
67
57
  ],
68
58
  default: 'getInfo',
69
59
  },
70
- {
71
- displayName: 'Operation',
72
- name: 'operation',
73
- type: 'options',
74
- noDataExpression: true,
75
- displayOptions: {
76
- show: {
77
- resource: ['compatibility'],
78
- },
79
- },
80
- options: [
81
- {
82
- name: 'Audit Nodes',
83
- value: 'audit',
84
- description: 'Audit community nodes for compatibility',
85
- action: 'Audit community nodes',
86
- },
87
- ],
88
- default: 'audit',
89
- },
90
- {
91
- displayName: 'Operation',
92
- name: 'operation',
93
- type: 'options',
94
- noDataExpression: true,
95
- displayOptions: {
96
- show: {
97
- resource: ['backup'],
98
- },
99
- },
100
- options: [
101
- {
102
- name: 'Backup to Git',
103
- value: 'gitBackup',
104
- description: 'Backup all workflows to a Git repository',
105
- action: 'Backup workflows to git',
106
- },
107
- ],
108
- default: 'gitBackup',
109
- },
110
60
  // Version Options
111
61
  {
112
62
  displayName: 'Version',
@@ -128,66 +78,35 @@ class N8nVersion {
128
78
  name: 'Current',
129
79
  value: 'current',
130
80
  },
131
- ],
132
- },
133
- {
134
- displayName: 'Strip Links',
135
- name: 'stripLinks',
136
- type: 'boolean',
137
- default: false,
138
- displayOptions: {
139
- show: {
140
- resource: ['version'],
141
- operation: ['getChangelog'],
142
- },
143
- },
144
- },
145
- // Compatibility Options
146
- {
147
- displayName: 'Target n8n Version',
148
- name: 'targetVersion',
149
- type: 'string',
150
- default: '',
151
- placeholder: 'e.g. 1.0.0',
152
- displayOptions: {
153
- show: {
154
- resource: ['compatibility'],
81
+ {
82
+ name: 'Custom',
83
+ value: 'custom',
155
84
  },
156
- },
157
- description: 'The n8n version to check compatibility against. If empty, uses latest.',
85
+ ],
158
86
  },
159
- // Backup Options
160
87
  {
161
- displayName: 'Repo URL',
162
- name: 'repoUrl',
88
+ displayName: 'Custom Version',
89
+ name: 'customVersion',
163
90
  type: 'string',
164
91
  default: '',
165
- required: true,
166
- displayOptions: {
167
- show: {
168
- resource: ['backup'],
169
- },
170
- },
171
- },
172
- {
173
- displayName: 'Branch',
174
- name: 'branch',
175
- type: 'string',
176
- default: 'main',
92
+ placeholder: '1.0.0',
177
93
  displayOptions: {
178
94
  show: {
179
- resource: ['backup'],
95
+ resource: ['version'],
96
+ operation: ['getChangelog'],
97
+ version: ['custom'],
180
98
  },
181
99
  },
182
100
  },
183
101
  {
184
- displayName: 'Local Path',
185
- name: 'localPath',
186
- type: 'string',
187
- default: '/tmp/n8n-backup',
102
+ displayName: 'Strip Links',
103
+ name: 'stripLinks',
104
+ type: 'boolean',
105
+ default: false,
188
106
  displayOptions: {
189
107
  show: {
190
- resource: ['backup'],
108
+ resource: ['version'],
109
+ operation: ['getChangelog'],
191
110
  },
192
111
  },
193
112
  },
@@ -210,33 +129,30 @@ class N8nVersion {
210
129
  else if (operation === 'getChangelog') {
211
130
  const versionType = this.getNodeParameter('version', i);
212
131
  const stripLinks = this.getNodeParameter('stripLinks', i);
213
- let versionToFetch = versionType === 'latest'
214
- ? await (0, VersionUtils_1.getLatestN8nVersion)()
215
- : (0, VersionUtils_1.getCurrentN8nVersion)();
132
+ let versionToFetch;
133
+ if (versionType === 'latest') {
134
+ versionToFetch = await (0, VersionUtils_1.getLatestN8nVersion)();
135
+ }
136
+ else if (versionType === 'current') {
137
+ versionToFetch = (0, VersionUtils_1.getCurrentN8nVersion)();
138
+ }
139
+ else {
140
+ versionToFetch = this.getNodeParameter('customVersion', i);
141
+ }
216
142
  const changelogInfo = await (0, VersionUtils_1.getChangelog)(versionToFetch);
217
- json = { ...changelogInfo };
143
+ // Simplify output as requested
144
+ json = {
145
+ version: changelogInfo.version,
146
+ changelog: changelogInfo.changelog,
147
+ };
148
+ if (changelogInfo.error) {
149
+ json.error = changelogInfo.error;
150
+ }
218
151
  if (stripLinks && json.changelog) {
219
152
  json.changelog = json.changelog.replace(/\[([^\]]+)\]\([^\)]+\)/g, '$1');
220
153
  }
221
154
  }
222
155
  }
223
- else if (resource === 'compatibility') {
224
- const targetVersion = this.getNodeParameter('targetVersion', i) || await (0, VersionUtils_1.getLatestN8nVersion)();
225
- const auditResults = await (0, CompatibilityUtils_1.auditAllNodes)(targetVersion);
226
- json.results = auditResults;
227
- json.targetVersion = targetVersion;
228
- }
229
- else if (resource === 'backup') {
230
- const repoUrl = this.getNodeParameter('repoUrl', i);
231
- const branch = this.getNodeParameter('branch', i);
232
- const localPath = this.getNodeParameter('localPath', i);
233
- const config = { repoUrl, branch, localPath };
234
- (0, GitUtils_1.ensureGitRepo)(config);
235
- await (0, GitUtils_1.exportWorkflowsToGit)(localPath);
236
- (0, GitUtils_1.commitAndPush)(config);
237
- json.success = true;
238
- json.timestamp = new Date().toISOString();
239
- }
240
156
  returnData.push({
241
157
  json,
242
158
  pairedItem: { item: i },
@@ -1,8 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.N8nVersionTrigger = void 0;
4
- const n8n_workflow_1 = require("n8n-workflow");
5
- const cron_1 = require("cron");
6
4
  const VersionUtils_1 = require("../VersionUtils");
7
5
  class N8nVersionTrigger {
8
6
  constructor() {
@@ -11,8 +9,8 @@ class N8nVersionTrigger {
11
9
  name: 'n8nVersionTrigger',
12
10
  icon: 'file:n8n-version.svg',
13
11
  group: ['trigger'],
14
- version: 2,
15
- description: 'Triggers workflow based on n8n version status using cron schedule',
12
+ version: 3,
13
+ description: 'Triggers workflow based on n8n version status',
16
14
  defaults: {
17
15
  name: 'n8n Version Trigger',
18
16
  },
@@ -20,65 +18,25 @@ class N8nVersionTrigger {
20
18
  outputs: ['main'],
21
19
  properties: [
22
20
  {
23
- displayName: 'Trigger On',
24
- name: 'triggerOn',
25
- type: 'options',
26
- options: [
27
- {
28
- name: 'Interval',
29
- value: 'interval',
30
- },
31
- {
32
- name: 'Custom Cron Expression',
33
- value: 'custom',
34
- },
35
- ],
36
- default: 'interval',
37
- description: 'How to specify the schedule',
38
- },
39
- {
40
- displayName: 'Interval',
21
+ displayName: 'Trigger Frequency',
41
22
  name: 'interval',
42
23
  type: 'options',
43
- displayOptions: {
44
- show: {
45
- triggerOn: ['interval'],
46
- },
47
- },
48
24
  options: [
49
25
  {
50
26
  name: 'Every Minute',
51
- value: '* * * * *',
27
+ value: 60,
52
28
  },
53
29
  {
54
30
  name: 'Every Hour',
55
- value: '0 * * * *',
31
+ value: 3600,
56
32
  },
57
33
  {
58
34
  name: 'Every Day',
59
- value: '0 0 * * *',
60
- },
61
- {
62
- name: 'Every Week',
63
- value: '0 0 * * 0',
35
+ value: 86400,
64
36
  },
65
37
  ],
66
- default: '0 * * * *',
67
- description: 'How often to check for updates',
68
- },
69
- {
70
- displayName: 'Cron Expression',
71
- name: 'cronExpression',
72
- type: 'string',
73
- default: '0 * * * *',
74
- displayOptions: {
75
- show: {
76
- triggerOn: ['custom'],
77
- },
78
- },
79
- required: true,
80
- placeholder: '0 * * * *',
81
- description: 'Standard cron expression',
38
+ default: 3600,
39
+ description: 'How often to check for updates (in seconds)',
82
40
  },
83
41
  {
84
42
  displayName: 'Trigger Condition',
@@ -182,90 +140,78 @@ class N8nVersionTrigger {
182
140
  };
183
141
  }
184
142
  async trigger() {
185
- const triggerOn = this.getNodeParameter('triggerOn');
186
- let cronExpression = '';
187
- if (triggerOn === 'interval') {
188
- cronExpression = this.getNodeParameter('interval');
189
- }
190
- else {
191
- cronExpression = this.getNodeParameter('cronExpression');
192
- }
143
+ const intervalSeconds = this.getNodeParameter('interval', 3600);
193
144
  const triggerCondition = this.getNodeParameter('triggerCondition');
194
145
  const semverFilter = this.getNodeParameter('semverFilter', 'patch');
195
146
  const ignorePrerelease = this.getNodeParameter('ignorePrerelease', true);
196
147
  const fetchChangelog = this.getNodeParameter('fetchChangelog', false);
197
148
  const changelogVersion = this.getNodeParameter('changelogVersion', 'latest');
198
149
  const stripLinks = this.getNodeParameter('stripLinks', false);
199
- let job;
200
- try {
201
- job = new cron_1.CronJob(cronExpression, async () => {
202
- try {
203
- const { isLatest, currentVersion, latestVersion, updateType, error } = await (0, VersionUtils_1.checkIsLatest)();
204
- if (ignorePrerelease && (latestVersion === null || latestVersion === void 0 ? void 0 : latestVersion.includes('-'))) {
205
- return;
150
+ // Initial check immediately? usually triggers wait.
151
+ const executeTrigger = async () => {
152
+ try {
153
+ const { isLatest, currentVersion, latestVersion, updateType, error } = await (0, VersionUtils_1.checkIsLatest)();
154
+ if (ignorePrerelease && (latestVersion === null || latestVersion === void 0 ? void 0 : latestVersion.includes('-'))) {
155
+ return;
156
+ }
157
+ let shouldTrigger = false;
158
+ if (triggerCondition === 'always') {
159
+ shouldTrigger = true;
160
+ }
161
+ else if (triggerCondition === 'update' && !isLatest) {
162
+ if (semverFilter === 'patch') {
163
+ shouldTrigger = true;
206
164
  }
207
- let shouldTrigger = false;
208
- if (triggerCondition === 'always') {
165
+ else if (semverFilter === 'minor' && (updateType === 'minor' || updateType === 'major')) {
209
166
  shouldTrigger = true;
210
167
  }
211
- else if (triggerCondition === 'update' && !isLatest) {
212
- if (semverFilter === 'patch') {
213
- shouldTrigger = true;
214
- }
215
- else if (semverFilter === 'minor' && (updateType === 'minor' || updateType === 'major')) {
216
- shouldTrigger = true;
217
- }
218
- else if (semverFilter === 'major' && updateType === 'major') {
219
- shouldTrigger = true;
220
- }
168
+ else if (semverFilter === 'major' && updateType === 'major') {
169
+ shouldTrigger = true;
221
170
  }
222
- if (shouldTrigger) {
223
- const json = {
224
- currentVersion,
225
- latestVersion,
226
- isLatest,
227
- updateType,
228
- error: error || undefined,
229
- triggeredAt: new Date().toISOString(),
230
- triggerCondition,
231
- };
232
- if (fetchChangelog) {
233
- let versionToFetch = changelogVersion === 'latest'
234
- ? (latestVersion || await (0, VersionUtils_1.getLatestN8nVersion)())
235
- : currentVersion;
236
- if (versionToFetch && versionToFetch !== 'unknown') {
237
- const changelogInfo = await (0, VersionUtils_1.getChangelog)(versionToFetch);
238
- json.changelog = changelogInfo.changelog;
239
- json.changelogVersion = changelogInfo.version;
240
- if (changelogInfo.error)
241
- json.changelogError = changelogInfo.error;
242
- if (stripLinks && json.changelog) {
243
- json.changelog = json.changelog.replace(/\[([^\]]+)\]\([^\)]+\)/g, '$1');
244
- }
171
+ }
172
+ if (shouldTrigger) {
173
+ const json = {
174
+ currentVersion,
175
+ latestVersion,
176
+ isLatest,
177
+ updateType,
178
+ error: error || undefined,
179
+ triggeredAt: new Date().toISOString(),
180
+ triggerCondition,
181
+ };
182
+ if (fetchChangelog) {
183
+ let versionToFetch = changelogVersion === 'latest'
184
+ ? (latestVersion || await (0, VersionUtils_1.getLatestN8nVersion)())
185
+ : currentVersion;
186
+ if (versionToFetch && versionToFetch !== 'unknown') {
187
+ const changelogInfo = await (0, VersionUtils_1.getChangelog)(versionToFetch);
188
+ json.changelog = changelogInfo.changelog;
189
+ json.changelogVersion = changelogInfo.version;
190
+ if (changelogInfo.error)
191
+ json.changelogError = changelogInfo.error;
192
+ if (stripLinks && json.changelog) {
193
+ json.changelog = json.changelog.replace(/\[([^\]]+)\]\([^\)]+\)/g, '$1');
245
194
  }
246
195
  }
247
- this.emit([
248
- [
249
- {
250
- json,
251
- },
252
- ],
253
- ]);
254
196
  }
197
+ this.emit([
198
+ [
199
+ {
200
+ json,
201
+ },
202
+ ],
203
+ ]);
255
204
  }
256
- catch (err) {
257
- console.error('[VersionTrigger] Error during cron execution:', err);
258
- }
259
- }, null, true);
260
- }
261
- catch (err) {
262
- const errorMessage = err instanceof Error ? err.message : String(err);
263
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid cron expression: ${errorMessage}. Please use standard cron format (e.g., "0 * * * *" for hourly).`);
264
- }
265
- async function closeFunction() {
266
- if (job) {
267
- job.stop();
268
205
  }
206
+ catch (err) {
207
+ console.error('[VersionTrigger] Error during check:', err);
208
+ }
209
+ };
210
+ // Run one check immediately? Standards usually say triggers start by waiting, or execute once if "Execute Trigger" logic.
211
+ // `setInterval` waits first.
212
+ const intervalId = setInterval(executeTrigger, intervalSeconds * 1000);
213
+ async function closeFunction() {
214
+ clearInterval(intervalId);
269
215
  }
270
216
  return {
271
217
  closeFunction,
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "n8n-nodes-version",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "private": false,
5
- "description": "n8n nodes to check version, monitor updates, and fetch changelogs",
5
+ "description": "n8n node to check for new n8n versions, view changelogs, and inspect workflows",
6
6
  "keywords": [
7
7
  "n8n-community-node-package"
8
8
  ],
@@ -1,78 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.auditAllNodes = exports.auditNode = exports.getInstalledCommunityNodes = void 0;
7
- const path_1 = __importDefault(require("path"));
8
- const fs_1 = __importDefault(require("fs"));
9
- /**
10
- * Scans node_modules for installed community nodes
11
- */
12
- function getInstalledCommunityNodes() {
13
- const communityNodes = [];
14
- try {
15
- const nodeModulesPath = path_1.default.join(process.cwd(), 'node_modules');
16
- if (!fs_1.default.existsSync(nodeModulesPath))
17
- return [];
18
- const dirs = fs_1.default.readdirSync(nodeModulesPath);
19
- for (const dir of dirs) {
20
- if (dir.startsWith('n8n-nodes-') || (dir.startsWith('@') && fs_1.default.readdirSync(path_1.default.join(nodeModulesPath, dir)).some(sub => sub.startsWith('n8n-nodes-')))) {
21
- // Handle scoped packages too
22
- if (dir.startsWith('@')) {
23
- const scopedDirs = fs_1.default.readdirSync(path_1.default.join(nodeModulesPath, dir));
24
- for (const scopedDir of scopedDirs) {
25
- if (scopedDir.startsWith('n8n-nodes-')) {
26
- communityNodes.push(`${dir}/${scopedDir}`);
27
- }
28
- }
29
- }
30
- else {
31
- communityNodes.push(dir);
32
- }
33
- }
34
- }
35
- }
36
- catch (err) {
37
- console.error('[CompatibilityUtils] Error scanning node_modules:', err);
38
- }
39
- return communityNodes;
40
- }
41
- exports.getInstalledCommunityNodes = getInstalledCommunityNodes;
42
- /**
43
- * Audits a specific node for compatibility with a target n8n version
44
- */
45
- async function auditNode(nodeName, targetN8nVersion) {
46
- // This is a simplified mock. In a real scenario, this would check npm or a compatibility registry.
47
- // For now, we'll return a basic structure.
48
- const packageJsonPath = path_1.default.join(process.cwd(), 'node_modules', nodeName, 'package.json');
49
- let currentVersion = 'unknown';
50
- try {
51
- if (fs_1.default.existsSync(packageJsonPath)) {
52
- const pkg = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
53
- currentVersion = pkg.version;
54
- }
55
- }
56
- catch (err) {
57
- console.error(`[CompatibilityUtils] Error reading package.json for ${nodeName}:`, err);
58
- }
59
- return {
60
- name: nodeName,
61
- currentVersion,
62
- isCompatible: true,
63
- actionRequired: 'none',
64
- };
65
- }
66
- exports.auditNode = auditNode;
67
- /**
68
- * Runs a full audit on all community nodes
69
- */
70
- async function auditAllNodes(targetN8nVersion) {
71
- const nodes = getInstalledCommunityNodes();
72
- const results = [];
73
- for (const node of nodes) {
74
- results.push(await auditNode(node, targetN8nVersion));
75
- }
76
- return results;
77
- }
78
- exports.auditAllNodes = auditAllNodes;
@@ -1,63 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.exportWorkflowsToGit = exports.commitAndPush = exports.ensureGitRepo = void 0;
7
- const child_process_1 = require("child_process");
8
- const path_1 = __importDefault(require("path"));
9
- const fs_1 = __importDefault(require("fs"));
10
- /**
11
- * Ensures the local backup directory exists and is a git repo
12
- */
13
- function ensureGitRepo(config) {
14
- if (!fs_1.default.existsSync(config.localPath)) {
15
- fs_1.default.mkdirSync(config.localPath, { recursive: true });
16
- }
17
- try {
18
- (0, child_process_1.execSync)('git rev-parse --is-inside-work-tree', { cwd: config.localPath });
19
- }
20
- catch (err) {
21
- // Not a repo, clone it
22
- (0, child_process_1.execSync)(`git clone ${config.repoUrl} .`, { cwd: config.localPath });
23
- (0, child_process_1.execSync)(`git checkout ${config.branch} || git checkout -b ${config.branch}`, { cwd: config.localPath });
24
- }
25
- }
26
- exports.ensureGitRepo = ensureGitRepo;
27
- /**
28
- * Commits and pushes changes to the repository
29
- */
30
- function commitAndPush(config) {
31
- const message = config.commitMessage || `Backup: ${new Date().toISOString()}`;
32
- try {
33
- (0, child_process_1.execSync)('git add .', { cwd: config.localPath });
34
- // Only commit if there are changes
35
- const status = (0, child_process_1.execSync)('git status --porcelain', { cwd: config.localPath }).toString();
36
- if (status) {
37
- (0, child_process_1.execSync)(`git commit -m "${message}"`, { cwd: config.localPath });
38
- (0, child_process_1.execSync)(`git push origin ${config.branch}`, { cwd: config.localPath });
39
- }
40
- }
41
- catch (err) {
42
- console.error('[GitUtils] Git operation failed:', err);
43
- throw err;
44
- }
45
- }
46
- exports.commitAndPush = commitAndPush;
47
- /**
48
- * Exports all workflows from n8n to the local git path
49
- * This assumes access to the n8n CLI or API
50
- */
51
- async function exportWorkflowsToGit(localPath) {
52
- // In a real n8n environment, this could use the n8n CLI: n8n export:workflow --all
53
- // Or fetch via API and write to files.
54
- // For this node, we'll assume the n8n CLI is available.
55
- try {
56
- (0, child_process_1.execSync)(`n8n export:workflow --all --output="${path_1.default.join(localPath, 'workflows/')}"`);
57
- }
58
- catch (err) {
59
- console.error('[GitUtils] Failed to export workflows:', err);
60
- throw err;
61
- }
62
- }
63
- exports.exportWorkflowsToGit = exportWorkflowsToGit;