@zivego/n8n-nodes-dfir-iris 3.0.0 → 4.0.2

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.
package/README.md CHANGED
@@ -1,25 +1,43 @@
1
1
  # @zivego/n8n-nodes-dfir-iris
2
2
 
3
- Community node for [n8n](https://n8n.io/) that integrates with DFIR IRIS.
3
+ DFIR IRIS node integration for [n8n](https://n8n.io/).
4
4
 
5
- This fork keeps the same runtime identifiers as upstream:
5
+ Repository: `zivego/dfir-iris-n8n-node`
6
6
 
7
- - node type: `dfirIris`
8
- - credential type: `dfirIrisApi`
7
+ This package uses its own runtime identifiers to avoid collisions with the built-in DFIR IRIS integration in modern `n8n`:
9
8
 
10
- That means existing workflows can keep working after you replace the original package with this fork.
9
+ - node type: `zivegoDfirIris`
10
+ - credential type: `zivegoDfirIrisApi`
11
+ - node label in the editor: `DFIR IRIS (Zivego)`
12
+ - credential label in the editor: `DFIR IRIS API (Zivego)`
11
13
 
12
- ## Install From npm
14
+ This is a breaking change. Existing workflows and credentials that point at upstream `dfirIris` / `dfirIrisApi` need to be recreated manually.
15
+ If you already moved to `4.0.0`, `4.0.2` keeps the same runtime ids and updates only labels, packaging checks, pagination coverage, and edge-case handling.
13
16
 
14
- After this package is published to npm:
17
+ ## Build Requirements
18
+
19
+ Local build and release tasks require `Node.js 20+`.
20
+
21
+ If your host uses an older runtime, use the container-safe commands instead:
22
+
23
+ ```sh
24
+ npm run build:container
25
+ npm run pack:container
26
+ ```
27
+
28
+ These commands install `pnpm` ephemerally inside the container and do not require root access.
29
+
30
+ ## Install
15
31
 
16
32
  ```sh
17
33
  cd ~/.n8n/nodes
18
- npm install @zivego/n8n-nodes-dfir-iris@3.0.0
34
+ npm install @zivego/n8n-nodes-dfir-iris@4.0.2
19
35
  ```
20
36
 
21
37
  Restart `n8n` after installation.
22
38
 
39
+ If your `n8n` instance also ships the built-in DFIR IRIS integration, look for the `(Zivego)` suffix in the node and credential picker.
40
+
23
41
  ## Install Before npm Publish
24
42
 
25
43
  If you want to test a local build before publishing:
@@ -28,28 +46,26 @@ If you want to test a local build before publishing:
28
46
  pnpm install
29
47
  pnpm run pack:tarball
30
48
  cd ~/.n8n/nodes
31
- npm install /path/to/zivego-n8n-nodes-dfir-iris-3.0.0.tgz
49
+ npm install /path/to/zivego-n8n-nodes-dfir-iris-4.0.2.tgz
32
50
  ```
33
51
 
34
52
  Restart `n8n` after installation.
35
53
 
36
54
  ## Replace the upstream package
37
55
 
38
- Do not keep the upstream package and this fork installed at the same time.
56
+ Do not keep the upstream package and this package installed at the same time.
39
57
 
40
58
  ```sh
41
59
  cd ~/.n8n/nodes
42
60
  npm uninstall n8n-nodes-dfir-iris
43
61
  rm -rf ~/.n8n/nodes/node_modules/n8n-nodes-dfir-iris
44
- npm install @zivego/n8n-nodes-dfir-iris@3.0.0
62
+ npm install @zivego/n8n-nodes-dfir-iris@4.0.2
45
63
  ```
46
64
 
47
65
  Restart `n8n` after the replacement.
48
66
 
49
67
  ## Update
50
68
 
51
- After a newer version is published to npm:
52
-
53
69
  ```sh
54
70
  cd ~/.n8n/nodes
55
71
  npm update @zivego/n8n-nodes-dfir-iris
@@ -59,14 +75,28 @@ Or install a specific version:
59
75
 
60
76
  ```sh
61
77
  cd ~/.n8n/nodes
62
- npm install @zivego/n8n-nodes-dfir-iris@3.0.1
78
+ npm install @zivego/n8n-nodes-dfir-iris@4.0.2
79
+ ```
80
+
81
+ ## Release Checks
82
+
83
+ ```sh
84
+ pnpm install
85
+ npm run release:check
86
+ ```
87
+
88
+ If you previously built inside Docker and `dist` became root-owned, either fix ownership or use the container-safe path:
89
+
90
+ ```sh
91
+ npm run build:container
92
+ npm run pack:container
63
93
  ```
64
94
 
65
95
  ## Publish
66
96
 
67
97
  ```sh
68
98
  pnpm install
69
- pnpm run build
99
+ npm run release:check
70
100
  npm publish --access public
71
101
  ```
72
102
 
@@ -4,9 +4,9 @@ exports.DfirIrisApi = void 0;
4
4
  const compatibility_1 = require("../nodes/DfirIris/v1/compatibility");
5
5
  class DfirIrisApi {
6
6
  constructor() {
7
- this.name = 'dfirIrisApi';
8
- this.displayName = 'DFIR IRIS API';
9
- this.documentationUrl = 'https://docs.dfir-iris.org/latest/_static/iris_api_reference_v2.0.4.html';
7
+ this.name = 'zivegoDfirIrisApi';
8
+ this.displayName = 'DFIR IRIS API (Zivego)';
9
+ this.documentationUrl = 'https://docs.dfir-iris.org/latest/operations/api/';
10
10
  this.icon = { light: "file:icons/iris.svg", dark: "file:icons/iris.svg" };
11
11
  this.properties = [
12
12
  {
@@ -6,8 +6,8 @@ const DfirIrisV1_node_1 = require("./v1/DfirIrisV1.node");
6
6
  class DfirIris extends n8n_workflow_1.VersionedNodeType {
7
7
  constructor() {
8
8
  const baseDescription = {
9
- displayName: 'DFIR IRIS',
10
- name: 'dfirIris',
9
+ displayName: 'DFIR IRIS (Zivego)',
10
+ name: 'zivegoDfirIris',
11
11
  icon: { light: "file:iris.svg", dark: "file:iris.svg" },
12
12
  group: ['input'],
13
13
  subtitle: '={{ $parameter["resource"] + ": " + $parameter["operation"] }}',
@@ -37,7 +37,7 @@ async function execute(i) {
37
37
  let response;
38
38
  const apiMode = await transport_1.getCredentialApiMode.call(this);
39
39
  if (apiMode === 'next') {
40
- response = await transport_1.apiRequestAllNext.call(this, 'GET', (0, compatibility_1.buildNextCaseScopedEndpoint)(cid, 'assets'), {}, {}, 100, this.getNodeParameter('options.startPage', i, 1));
40
+ response = await transport_1.apiRequestAllNext.call(this, 'GET', (0, compatibility_1.buildNextCaseScopedEndpoint)(cid, 'assets'), {}, {}, 0, this.getNodeParameter('options.startPage', i, 1));
41
41
  }
42
42
  else {
43
43
  try {
@@ -74,6 +74,24 @@ const displayOptions = {
74
74
  },
75
75
  };
76
76
  exports.description = (0, n8n_workflow_1.updateDisplayOptions)(displayOptions, properties);
77
+ function getFileNameFromContentDisposition(value) {
78
+ if (!value) {
79
+ return undefined;
80
+ }
81
+ const utf8Match = value.match(/filename\*=UTF-8''([^;]+)/i);
82
+ if (utf8Match === null || utf8Match === void 0 ? void 0 : utf8Match[1]) {
83
+ return decodeURIComponent(utf8Match[1].replace(/^"(.*)"$/, '$1'));
84
+ }
85
+ const fileNameMatch = value.match(/filename="?([^"]+)"?/i);
86
+ return fileNameMatch === null || fileNameMatch === void 0 ? void 0 : fileNameMatch[1];
87
+ }
88
+ function normalizeOptionalFileName(value) {
89
+ if (typeof value !== 'string') {
90
+ return undefined;
91
+ }
92
+ const trimmedValue = value.trim();
93
+ return trimmedValue.length > 0 ? trimmedValue : undefined;
94
+ }
77
95
  async function execute(i) {
78
96
  var _a, _b, _c, _d, _e;
79
97
  const query = { cid: this.getNodeParameter('cid', i, 0) };
@@ -88,10 +106,10 @@ async function execute(i) {
88
106
  const headers = response.headers;
89
107
  const mimeType = (_a = headers === null || headers === void 0 ? void 0 : headers['content-type']) !== null && _a !== void 0 ? _a : undefined;
90
108
  const contentDisposition = ((_b = headers['content-disposition']) !== null && _b !== void 0 ? _b : undefined);
91
- const fileName = (_e = (_c = body.fileName) !== null && _c !== void 0 ? _c : (_d = response.contentDisposition) === null || _d === void 0 ? void 0 : _d.filename) !== null && _e !== void 0 ? _e : contentDisposition
92
- .split('; ')
93
- .filter((d) => d.indexOf('filename') >= 0)[0]
94
- .replace('filename=', '');
109
+ const fallbackFileName = `iris-file-${this.getNodeParameter('file_id', i)}`;
110
+ const customFileName = normalizeOptionalFileName(body.fileName);
111
+ const responseFileName = normalizeOptionalFileName((_c = response.contentDisposition) === null || _c === void 0 ? void 0 : _c.filename);
112
+ const fileName = (_e = (_d = customFileName !== null && customFileName !== void 0 ? customFileName : responseFileName) !== null && _d !== void 0 ? _d : getFileNameFromContentDisposition(contentDisposition)) !== null && _e !== void 0 ? _e : fallbackFileName;
95
113
  let item = this.getInputData()[i];
96
114
  const newItem = {
97
115
  json: item.json,
@@ -31,7 +31,7 @@ async function execute(i) {
31
31
  const apiMode = await transport_1.getCredentialApiMode.call(this);
32
32
  response =
33
33
  apiMode === 'next'
34
- ? await transport_1.apiRequestAllNext.call(this, 'GET', (0, compatibility_1.buildNextCaseScopedEndpoint)(cid, 'iocs'), {}, {}, 100, 1)
34
+ ? await transport_1.apiRequestAllNext.call(this, 'GET', (0, compatibility_1.buildNextCaseScopedEndpoint)(cid, 'iocs'), {}, {}, 0, 1)
35
35
  : await transport_1.apiRequest.call(this, 'GET', `${IOC_resource_1.endpoint}/list`, {}, query);
36
36
  const options = this.getNodeParameter('options', i, {});
37
37
  const isRaw = options.isRaw || false;
@@ -49,7 +49,7 @@ async function execute(i) {
49
49
  const apiMode = await transport_1.getCredentialApiMode.call(this);
50
50
  response =
51
51
  apiMode === 'next'
52
- ? await transport_1.apiRequestAllNext.call(this, 'GET', (0, compatibility_1.buildNextCaseScopedEndpoint)(cid, 'tasks'), {}, {}, 100, 1)
52
+ ? await transport_1.apiRequestAllNext.call(this, 'GET', (0, compatibility_1.buildNextCaseScopedEndpoint)(cid, 'tasks'), {}, {}, 0, 1)
53
53
  : await transport_1.apiRequest.call(this, 'GET', `${Task_resource_1.endpoint}/list`, {}, query);
54
54
  const options = this.getNodeParameter('options', i, {});
55
55
  const isRaw = options.isRaw || false;
@@ -53,20 +53,20 @@ const timeline = __importStar(require("./timeline/Timeline.resource"));
53
53
  const compatibility_1 = require("../compatibility");
54
54
  const types_1 = require("../helpers/types");
55
55
  exports.versionDescription = {
56
- displayName: 'DFIR IRIS',
57
- name: 'dfirIris',
56
+ displayName: 'DFIR IRIS (Zivego)',
57
+ name: 'zivegoDfirIris',
58
58
  group: ['input'],
59
59
  version: [1, 2],
60
60
  subtitle: '={{ $parameter["resource"] + ": " + $parameter["operation"] }}',
61
61
  description: 'works with DFIR IRIS IRP',
62
62
  defaults: {
63
- name: 'DFIR IRIS',
63
+ name: 'DFIR IRIS (Zivego)',
64
64
  },
65
65
  inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
66
66
  outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
67
67
  credentials: [
68
68
  {
69
- name: 'dfirIrisApi',
69
+ name: 'zivegoDfirIrisApi',
70
70
  required: true,
71
71
  },
72
72
  ],
@@ -25,7 +25,7 @@ exports.compatibilityDefaults = compatibility_manifest_json_1.default;
25
25
  function resolveApiMode(value) {
26
26
  return value === 'next' ? 'next' : 'stable';
27
27
  }
28
- async function getApiMode(credentialType = 'dfirIrisApi') {
28
+ async function getApiMode(credentialType = 'zivegoDfirIrisApi') {
29
29
  try {
30
30
  const credentials = await this.getCredentials(credentialType);
31
31
  return resolveApiMode(credentials.apiMode);
@@ -88,7 +88,7 @@ async function getAssets() {
88
88
  const query = { cid };
89
89
  let response;
90
90
  if (apiMode === 'next') {
91
- response = await index_1.apiRequestAllNext.call(this, 'GET', (0, compatibility_1.buildNextCaseScopedEndpoint)(cid, 'assets'), {}, {}, 100, 1);
91
+ response = await index_1.apiRequestAllNext.call(this, 'GET', (0, compatibility_1.buildNextCaseScopedEndpoint)(cid, 'assets'), {}, {}, 0, 1);
92
92
  }
93
93
  else {
94
94
  try {
@@ -151,7 +151,7 @@ async function getTasks() {
151
151
  const cid = this.getNodeParameter('cid');
152
152
  const query = { cid };
153
153
  const response = apiMode === 'next'
154
- ? await index_1.apiRequestAllNext.call(this, 'GET', (0, compatibility_1.buildNextCaseScopedEndpoint)(cid, 'tasks'), {}, {}, 100, 1)
154
+ ? await index_1.apiRequestAllNext.call(this, 'GET', (0, compatibility_1.buildNextCaseScopedEndpoint)(cid, 'tasks'), {}, {}, 0, 1)
155
155
  : await index_1.apiRequest.call(this, 'GET', 'case/tasks/list', {}, query);
156
156
  if (response === undefined) {
157
157
  throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No data got returned');
@@ -214,7 +214,7 @@ async function getIOCs() {
214
214
  const cid = this.getNodeParameter('cid');
215
215
  const query = { cid };
216
216
  const response = apiMode === 'next'
217
- ? await index_1.apiRequestAllNext.call(this, 'GET', (0, compatibility_1.buildNextCaseScopedEndpoint)(cid, 'iocs'), {}, {}, 100, 1)
217
+ ? await index_1.apiRequestAllNext.call(this, 'GET', (0, compatibility_1.buildNextCaseScopedEndpoint)(cid, 'iocs'), {}, {}, 0, 1)
218
218
  : await index_1.apiRequest.call(this, 'GET', 'case/ioc/list', {}, query);
219
219
  if (response === undefined) {
220
220
  throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No data got returned');
@@ -109,26 +109,32 @@ function buildRequestOptions(method, baseUrl, endpoint, body, query = {}, option
109
109
  });
110
110
  return options;
111
111
  }
112
+ function getUnexpectedPaginationError(message) {
113
+ return {
114
+ message,
115
+ description: 'The DFIR IRIS API returned an unexpected pagination payload.',
116
+ };
117
+ }
112
118
  async function apiRequest(method, endpoint, body, query, option = {}, isFormData = false) {
113
- const credentials = await this.getCredentials('dfirIrisApi');
119
+ const credentials = await this.getCredentials('zivegoDfirIrisApi');
114
120
  (0, utils_1.enableDebug)(credentials === null || credentials === void 0 ? void 0 : credentials.enableDebug);
115
121
  const irisLogger = new utils_1.IrisLog(this.logger);
116
122
  const { baseUrl, skipSslCertificateValidation } = getConnectionSettings(credentials);
117
123
  const options = buildRequestOptions(method, baseUrl, endpoint, body, query || {}, option, isFormData, skipSslCertificateValidation);
118
124
  try {
119
125
  irisLogger.info('options', { options });
120
- return await this.helpers.httpRequestWithAuthentication.call(this, 'dfirIrisApi', options);
126
+ return await this.helpers.httpRequestWithAuthentication.call(this, 'zivegoDfirIrisApi', options);
121
127
  }
122
128
  catch (error) {
123
129
  throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
124
130
  }
125
131
  }
126
132
  async function getCredentialApiMode() {
127
- const credentials = await this.getCredentials('dfirIrisApi');
133
+ const credentials = await this.getCredentials('zivegoDfirIrisApi');
128
134
  return (0, compatibility_1.resolveApiMode)(credentials === null || credentials === void 0 ? void 0 : credentials.apiMode);
129
135
  }
130
136
  async function apiRequestAll(method, endpoint, body = {}, query, max_items = 0, start_page = 1, propKey) {
131
- const credentials = await this.getCredentials('dfirIrisApi');
137
+ const credentials = await this.getCredentials('zivegoDfirIrisApi');
132
138
  (0, utils_1.enableDebug)(credentials === null || credentials === void 0 ? void 0 : credentials.enableDebug);
133
139
  const { baseUrl, skipSslCertificateValidation } = getConnectionSettings(credentials);
134
140
  const headers = { 'content-type': 'application/json; charset=utf-8' };
@@ -139,9 +145,6 @@ async function apiRequestAll(method, endpoint, body = {}, query, max_items = 0,
139
145
  let proceed = true;
140
146
  query.page = start_page;
141
147
  query.per_page = max_items > 0 && max_items < 100 ? max_items : 100;
142
- if (start_page > 1) {
143
- query.page = Math.floor((start_page * max_items) / query.per_page);
144
- }
145
148
  const options = {
146
149
  headers: headers,
147
150
  method,
@@ -150,7 +153,7 @@ async function apiRequestAll(method, endpoint, body = {}, query, max_items = 0,
150
153
  qs: query,
151
154
  json: true,
152
155
  skipSslCertificateValidation,
153
- ignoreHttpStatusErrors: true,
156
+ ignoreHttpStatusErrors: false,
154
157
  };
155
158
  Object.assign(options, {
156
159
  rejectUnauthorized: !skipSslCertificateValidation,
@@ -158,11 +161,18 @@ async function apiRequestAll(method, endpoint, body = {}, query, max_items = 0,
158
161
  irisLogger.info('req options: ', { options });
159
162
  do {
160
163
  try {
161
- responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'dfirIrisApi', options);
164
+ responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'zivegoDfirIrisApi', options);
162
165
  }
163
166
  catch (error) {
164
167
  throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
165
168
  }
169
+ if (!responseData ||
170
+ typeof responseData !== 'object' ||
171
+ !responseData.data ||
172
+ typeof responseData.data !== 'object' ||
173
+ !Array.isArray(responseData.data[propKey])) {
174
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), getUnexpectedPaginationError(`Missing paginated array payload at data.${propKey}.`));
175
+ }
166
176
  irisLogger.info('responseData', { responseData });
167
177
  irisLogger.info('current_page: ', responseData.data.current_page);
168
178
  irisLogger.info('next_page: ', responseData.data.next_page);
@@ -191,7 +201,7 @@ async function apiRequestAll(method, endpoint, body = {}, query, max_items = 0,
191
201
  return responseData;
192
202
  }
193
203
  async function apiRequestAllNext(method, endpoint, body = {}, query = {}, maxItems = 0, startPage = 1) {
194
- const credentials = await this.getCredentials('dfirIrisApi');
204
+ const credentials = await this.getCredentials('zivegoDfirIrisApi');
195
205
  (0, utils_1.enableDebug)(credentials === null || credentials === void 0 ? void 0 : credentials.enableDebug);
196
206
  const { baseUrl, skipSslCertificateValidation } = getConnectionSettings(credentials);
197
207
  const headers = { 'content-type': 'application/json; charset=utf-8' };
@@ -216,21 +226,24 @@ async function apiRequestAllNext(method, endpoint, body = {}, query = {}, maxIte
216
226
  },
217
227
  json: true,
218
228
  skipSslCertificateValidation,
219
- ignoreHttpStatusErrors: true,
229
+ ignoreHttpStatusErrors: false,
220
230
  };
221
231
  Object.assign(options, {
222
232
  rejectUnauthorized: !skipSslCertificateValidation,
223
233
  });
224
234
  let responseData;
225
235
  try {
226
- responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'dfirIrisApi', options);
236
+ responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'zivegoDfirIrisApi', options);
227
237
  }
228
238
  catch (error) {
229
239
  throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
230
240
  }
231
241
  irisLogger.info('next responseData', { responseData });
232
242
  const payload = extractNextPaginatedPayload(responseData);
233
- const items = Array.isArray(payload.data) ? payload.data : [];
243
+ if (!Array.isArray(payload.data)) {
244
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), getUnexpectedPaginationError('Missing paginated array payload at data.'));
245
+ }
246
+ const items = payload.data;
234
247
  returnData.push(...items);
235
248
  total = Number(payload.total || returnData.length);
236
249
  lastPage = Number(payload.last_page || currentPage);
package/dist/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@zivego/n8n-nodes-dfir-iris",
3
- "version": "3.0.0",
4
- "description": "n8n node for DFIR IRIS IRP",
3
+ "version": "4.0.2",
4
+ "description": "DFIR IRIS node integration for n8n with stable and next API support",
5
5
  "license": "MIT",
6
- "homepage": "https://github.com/zivego/iris-n8n-fork",
6
+ "homepage": "https://github.com/zivego/dfir-iris-n8n-node",
7
7
  "keywords": [
8
8
  "n8n-community-node-package",
9
9
  "dfir-iris",
@@ -16,23 +16,32 @@
16
16
  },
17
17
  "repository": {
18
18
  "type": "git",
19
- "url": "https://github.com/zivego/iris-n8n-fork.git"
19
+ "url": "https://github.com/zivego/dfir-iris-n8n-node.git"
20
20
  },
21
21
  "bugs": {
22
- "url": "https://github.com/zivego/iris-n8n-fork/issues"
22
+ "url": "https://github.com/zivego/dfir-iris-n8n-node/issues"
23
23
  },
24
24
  "publishConfig": {
25
25
  "access": "public"
26
26
  },
27
+ "engines": {
28
+ "node": ">=20"
29
+ },
27
30
  "scripts": {
28
- "clean": "node -e \"const fs=require('fs'); const path=require('path'); const rm=function(target){ if(!fs.existsSync(target)) return; const stat=fs.lstatSync(target); if(stat.isDirectory()){ fs.readdirSync(target).forEach(function(name){ rm(path.join(target,name)); }); fs.rmdirSync(target); } else { fs.unlinkSync(target); } }; rm('dist');\"",
29
- "prune:dist": "node -e \"const fs=require('fs'); const path=require('path'); const walk=function(dir){ if(!fs.existsSync(dir)) return; fs.readdirSync(dir).forEach(function(name){ const full=path.join(dir,name); const stat=fs.lstatSync(full); if(stat.isDirectory()) return walk(full); if(/\\\\.map$|\\\\.d\\\\.ts$|tsconfig\\\\.tsbuildinfo$/.test(full)) fs.unlinkSync(full); }); }; walk('dist');\"",
30
- "build": "npm run clean && n8n-node build && npm run prune:dist",
31
+ "check:node": "node scripts/check-node-version.mjs",
32
+ "clean": "node scripts/clean-dist.mjs",
33
+ "prune:dist": "node scripts/prune-dist.mjs",
34
+ "build": "npm run check:node && npm run clean && n8n-node build && npm run prune:dist",
31
35
  "build:watch": "tsc --watch",
32
- "dev": "n8n-node dev",
36
+ "dev": "npm run check:node && n8n-node dev",
37
+ "build:container": "docker run --rm --user \"$(id -u):$(id -g)\" -v \"$PWD:/workspace\" -w /workspace node:20-bookworm bash -lc \"npx -y pnpm@10.22.0 install --frozen-lockfile && npx -y pnpm@10.22.0 run build\"",
33
38
  "pack:tarball": "npm run build && npm pack --pack-destination artifacts",
34
- "prepack": "npm run build",
35
- "prepublishOnly": "npm run build"
39
+ "pack:container": "docker run --rm --user \"$(id -u):$(id -g)\" -v \"$PWD:/workspace\" -w /workspace node:20-bookworm bash -lc \"npx -y pnpm@10.22.0 install --frozen-lockfile && npx -y pnpm@10.22.0 run pack:tarball\"",
40
+ "validate:types": "node scripts/validate-types.mjs",
41
+ "validate:package": "node scripts/validate-package.mjs",
42
+ "release:check": "npm run build && npm run validate:types && npm run validate:package",
43
+ "prepack": "npm run build && npm run validate:types",
44
+ "prepublishOnly": "npm run release:check"
36
45
  },
37
46
  "files": [
38
47
  "dist"
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@zivego/n8n-nodes-dfir-iris",
3
- "version": "3.0.0",
4
- "description": "n8n node for DFIR IRIS IRP",
3
+ "version": "4.0.2",
4
+ "description": "DFIR IRIS node integration for n8n with stable and next API support",
5
5
  "license": "MIT",
6
- "homepage": "https://github.com/zivego/iris-n8n-fork",
6
+ "homepage": "https://github.com/zivego/dfir-iris-n8n-node",
7
7
  "keywords": [
8
8
  "n8n-community-node-package",
9
9
  "dfir-iris",
@@ -16,23 +16,32 @@
16
16
  },
17
17
  "repository": {
18
18
  "type": "git",
19
- "url": "https://github.com/zivego/iris-n8n-fork.git"
19
+ "url": "https://github.com/zivego/dfir-iris-n8n-node.git"
20
20
  },
21
21
  "bugs": {
22
- "url": "https://github.com/zivego/iris-n8n-fork/issues"
22
+ "url": "https://github.com/zivego/dfir-iris-n8n-node/issues"
23
23
  },
24
24
  "publishConfig": {
25
25
  "access": "public"
26
26
  },
27
+ "engines": {
28
+ "node": ">=20"
29
+ },
27
30
  "scripts": {
28
- "clean": "node -e \"const fs=require('fs'); const path=require('path'); const rm=function(target){ if(!fs.existsSync(target)) return; const stat=fs.lstatSync(target); if(stat.isDirectory()){ fs.readdirSync(target).forEach(function(name){ rm(path.join(target,name)); }); fs.rmdirSync(target); } else { fs.unlinkSync(target); } }; rm('dist');\"",
29
- "prune:dist": "node -e \"const fs=require('fs'); const path=require('path'); const walk=function(dir){ if(!fs.existsSync(dir)) return; fs.readdirSync(dir).forEach(function(name){ const full=path.join(dir,name); const stat=fs.lstatSync(full); if(stat.isDirectory()) return walk(full); if(/\\\\.map$|\\\\.d\\\\.ts$|tsconfig\\\\.tsbuildinfo$/.test(full)) fs.unlinkSync(full); }); }; walk('dist');\"",
30
- "build": "npm run clean && n8n-node build && npm run prune:dist",
31
+ "check:node": "node scripts/check-node-version.mjs",
32
+ "clean": "node scripts/clean-dist.mjs",
33
+ "prune:dist": "node scripts/prune-dist.mjs",
34
+ "build": "npm run check:node && npm run clean && n8n-node build && npm run prune:dist",
31
35
  "build:watch": "tsc --watch",
32
- "dev": "n8n-node dev",
36
+ "dev": "npm run check:node && n8n-node dev",
37
+ "build:container": "docker run --rm --user \"$(id -u):$(id -g)\" -v \"$PWD:/workspace\" -w /workspace node:20-bookworm bash -lc \"npx -y pnpm@10.22.0 install --frozen-lockfile && npx -y pnpm@10.22.0 run build\"",
33
38
  "pack:tarball": "npm run build && npm pack --pack-destination artifacts",
34
- "prepack": "npm run build",
35
- "prepublishOnly": "npm run build"
39
+ "pack:container": "docker run --rm --user \"$(id -u):$(id -g)\" -v \"$PWD:/workspace\" -w /workspace node:20-bookworm bash -lc \"npx -y pnpm@10.22.0 install --frozen-lockfile && npx -y pnpm@10.22.0 run pack:tarball\"",
40
+ "validate:types": "node scripts/validate-types.mjs",
41
+ "validate:package": "node scripts/validate-package.mjs",
42
+ "release:check": "npm run build && npm run validate:types && npm run validate:package",
43
+ "prepack": "npm run build && npm run validate:types",
44
+ "prepublishOnly": "npm run release:check"
36
45
  },
37
46
  "files": [
38
47
  "dist"