n8n-nodes-proofofauthenticity 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 CHECKHC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # ProofOfAuthenticity
2
+
3
+ [![npm version](https://img.shields.io/npm/v/n8n-nodes-proofofauthenticity.svg)](https://www.npmjs.com/package/n8n-nodes-proofofauthenticity)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ > Developed by **[CHECKHC](https://checkhc.net)** - Blockchain content certification experts
7
+
8
+ ## Overview
9
+
10
+ **ProofOfAuthenticity** is an n8n community node that provides blockchain timestamping with optional AI authenticity detection and C2PA content authenticity metadata.
11
+
12
+ ### Features
13
+
14
+ - **Blockchain Timestamping** - SHA-256 hash certified on Solana blockchain
15
+ - **AI Authenticity Detection** - Detect AI-generated vs human-created content
16
+ - **C2PA Integration** - Content Authenticity Initiative standard metadata
17
+
18
+ ## Operations
19
+
20
+ ### Create Certificate
21
+
22
+ Certify content with blockchain timestamp.
23
+
24
+ | Parameter | Description |
25
+ |-----------|-------------|
26
+ | Input Type | URL or Base64 |
27
+ | File URL/Data | The file to certify |
28
+ | Title | Certificate title (required) |
29
+ | Author | Author name (optional) |
30
+ | Description | Description (optional) |
31
+ | Certification Mode | Simple or AI + C2PA |
32
+
33
+ ### List Certificates
34
+
35
+ List blockchain certificates with optional filters (hash, filename, signature).
36
+
37
+ ## Installation
38
+
39
+ ### Via n8n Community Nodes
40
+
41
+ 1. Go to **Settings** > **Community Nodes**
42
+ 2. Select **Install**
43
+ 3. Enter `n8n-nodes-proofofauthenticity`
44
+ 4. Click **Install**
45
+
46
+ ### Manual Installation
47
+
48
+ ```bash
49
+ cd ~/.n8n/nodes
50
+ yarn add n8n-nodes-proofofauthenticity
51
+ ```
52
+
53
+ ## Configuration
54
+
55
+ 1. Create a credential of type **ProofOfAuthenticity API**
56
+ 2. Enter your DigiCryptoStore instance URL
57
+ 3. Enter your API Key (Settings > API Keys)
58
+
59
+ ## Support
60
+
61
+ - **GitHub**: Issues/Discussions
62
+ - **Email**: contact@checkhc.net
63
+ - **Website**: [https://checkhc.net](https://checkhc.net)
64
+
65
+ ## License
66
+
67
+ MIT
68
+
69
+ ---
70
+
71
+ **Powered by [CHECKHC](https://checkhc.net)**
@@ -0,0 +1,9 @@
1
+ import { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class ProofOfAuthenticityApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ documentationUrl: string;
6
+ properties: INodeProperties[];
7
+ authenticate: IAuthenticateGeneric;
8
+ test: ICredentialTestRequest;
9
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProofOfAuthenticityApi = void 0;
4
+ class ProofOfAuthenticityApi {
5
+ constructor() {
6
+ this.name = 'proofOfAuthenticityApi';
7
+ this.displayName = 'ProofOfAuthenticity API';
8
+ this.documentationUrl = 'https://docs.checkhc.net/';
9
+ this.properties = [
10
+ {
11
+ displayName: 'DigiCryptoStore URL',
12
+ name: 'digiCryptoStoreUrl',
13
+ type: 'string',
14
+ default: 'https://localhost:3000',
15
+ placeholder: 'https://your-instance.com or https://localhost:3000',
16
+ description: 'The URL of your DigiCryptoStore instance (with HTTPS)',
17
+ required: true,
18
+ },
19
+ {
20
+ displayName: 'API Key (Bearer Token)',
21
+ name: 'apiKey',
22
+ type: 'string',
23
+ typeOptions: {
24
+ password: true,
25
+ },
26
+ default: '',
27
+ placeholder: 'your-api-key',
28
+ description: 'API Key for authentication (found in Settings > API Keys)',
29
+ required: true,
30
+ },
31
+ ];
32
+ this.authenticate = {
33
+ type: 'generic',
34
+ properties: {
35
+ headers: {
36
+ Authorization: '=Bearer {{$credentials.apiKey}}',
37
+ },
38
+ },
39
+ };
40
+ this.test = {
41
+ request: {
42
+ baseURL: '={{$credentials.digiCryptoStoreUrl}}',
43
+ url: '/api/auth/me',
44
+ method: 'GET',
45
+ },
46
+ };
47
+ }
48
+ }
49
+ exports.ProofOfAuthenticityApi = ProofOfAuthenticityApi;
@@ -0,0 +1,5 @@
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class ProofOfAuthenticity implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,425 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.ProofOfAuthenticity = void 0;
40
+ const n8n_workflow_1 = require("n8n-workflow");
41
+ const axios_1 = __importDefault(require("axios"));
42
+ const https = __importStar(require("https"));
43
+ // Security and Performance Constants
44
+ const REQUEST_TIMEOUT = 30000; // 30 seconds for API requests
45
+ const DOWNLOAD_TIMEOUT = 120000; // 2 minutes for file downloads
46
+ const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB maximum file size
47
+ /**
48
+ * Validates URL to prevent SSRF attacks
49
+ * Only allows http/https protocols and blocks private IPs
50
+ */
51
+ function validateUrl(url) {
52
+ const parsed = new URL(url);
53
+ // Only allow http/https
54
+ if (!['http:', 'https:'].includes(parsed.protocol)) {
55
+ throw new Error(`Invalid URL protocol: ${parsed.protocol}. Only http/https allowed.`);
56
+ }
57
+ // Block private IPs and localhost (except for development)
58
+ const hostname = parsed.hostname.toLowerCase();
59
+ const privatePatterns = [
60
+ /^10\./,
61
+ /^172\.(1[6-9]|2[0-9]|3[0-1])\./,
62
+ /^192\.168\./,
63
+ /^127\./,
64
+ /^0\./,
65
+ /^169\.254\./,
66
+ ];
67
+ for (const pattern of privatePatterns) {
68
+ if (pattern.test(hostname)) {
69
+ throw new Error(`URL points to private IP range: ${hostname}`);
70
+ }
71
+ }
72
+ if (hostname === 'localhost' || hostname.endsWith('.local')) {
73
+ throw new Error(`URL points to local hostname: ${hostname}`);
74
+ }
75
+ }
76
+ /**
77
+ * Creates axios config with HTTPS agent for self-signed certificates in local development
78
+ */
79
+ function getAxiosConfig(baseUrl) {
80
+ if (baseUrl.includes('localhost') || baseUrl.includes('127.0.0.1')) {
81
+ return {
82
+ httpsAgent: new https.Agent({
83
+ rejectUnauthorized: false
84
+ })
85
+ };
86
+ }
87
+ return {};
88
+ }
89
+ class ProofOfAuthenticity {
90
+ constructor() {
91
+ this.description = {
92
+ displayName: 'ProofOfAuthenticity by CHECKHC',
93
+ name: 'proofOfAuthenticity',
94
+ icon: 'file:proofofauthenticity.png',
95
+ group: ['transform'],
96
+ version: 1,
97
+ subtitle: '={{$parameter["operation"]}}',
98
+ description: 'ProofOfAuthenticity by CHECKHC - Blockchain timestamping with AI detection and C2PA authenticity. Learn more: https://www.checkhc.net',
99
+ defaults: {
100
+ name: 'ProofOfAuthenticity by CHECKHC',
101
+ },
102
+ inputs: ['main'],
103
+ outputs: ['main'],
104
+ credentials: [
105
+ {
106
+ name: 'proofOfAuthenticityApi',
107
+ required: true,
108
+ },
109
+ ],
110
+ properties: [
111
+ // Operation
112
+ {
113
+ displayName: 'Operation',
114
+ name: 'operation',
115
+ type: 'options',
116
+ noDataExpression: true,
117
+ options: [
118
+ {
119
+ name: 'Create Certificate',
120
+ value: 'createCertificate',
121
+ description: 'Create blockchain certificate with optional AI analysis and C2PA',
122
+ action: 'Create certificate',
123
+ },
124
+ {
125
+ name: 'List Certificates',
126
+ value: 'listCertificates',
127
+ description: 'List all your blockchain certificates',
128
+ action: 'List certificates',
129
+ },
130
+ ],
131
+ default: 'createCertificate',
132
+ },
133
+ // ============================================
134
+ // CERTIFICATION MODE SELECTOR
135
+ // ============================================
136
+ {
137
+ displayName: 'Certification Mode',
138
+ name: 'certificationMode',
139
+ type: 'options',
140
+ displayOptions: {
141
+ show: {
142
+ operation: ['createCertificate'],
143
+ },
144
+ },
145
+ options: [
146
+ {
147
+ name: 'Blockchain Hash Only (1 credit)',
148
+ value: 'simple',
149
+ description: 'SHA-256 hash timestamped on Solana blockchain. File stays on your device.',
150
+ },
151
+ {
152
+ name: 'Blockchain Hash + AI + C2PA (30 credits)',
153
+ value: 'ai',
154
+ description: 'Hash + AI authenticity analysis + C2PA content authenticity metadata',
155
+ },
156
+ ],
157
+ default: 'simple',
158
+ required: true,
159
+ },
160
+ // ============================================
161
+ // CREATE CERTIFICATE PARAMETERS
162
+ // ============================================
163
+ {
164
+ displayName: 'Input Type',
165
+ name: 'inputType',
166
+ type: 'options',
167
+ displayOptions: {
168
+ show: {
169
+ operation: ['createCertificate'],
170
+ },
171
+ },
172
+ options: [
173
+ {
174
+ name: 'URL',
175
+ value: 'url',
176
+ description: 'Download file from URL',
177
+ },
178
+ {
179
+ name: 'Base64 String',
180
+ value: 'base64',
181
+ description: 'File content as base64 encoded string',
182
+ },
183
+ ],
184
+ default: 'url',
185
+ description: 'How to provide the file content',
186
+ },
187
+ {
188
+ displayName: 'File URL',
189
+ name: 'fileUrl',
190
+ type: 'string',
191
+ displayOptions: {
192
+ show: {
193
+ operation: ['createCertificate'],
194
+ inputType: ['url'],
195
+ },
196
+ },
197
+ default: '',
198
+ required: true,
199
+ placeholder: 'https://example.com/image.jpg',
200
+ description: 'URL of the file to certify',
201
+ },
202
+ {
203
+ displayName: 'File Data (Base64)',
204
+ name: 'fileData',
205
+ type: 'string',
206
+ displayOptions: {
207
+ show: {
208
+ operation: ['createCertificate'],
209
+ inputType: ['base64'],
210
+ },
211
+ },
212
+ default: '',
213
+ required: true,
214
+ placeholder: 'data:image/jpeg;base64,/9j/4AAQ...',
215
+ description: 'Base64 encoded file with data URI prefix',
216
+ },
217
+ {
218
+ displayName: 'Title',
219
+ name: 'title',
220
+ type: 'string',
221
+ displayOptions: {
222
+ show: {
223
+ operation: ['createCertificate'],
224
+ },
225
+ },
226
+ default: '',
227
+ required: true,
228
+ description: 'Certificate title',
229
+ },
230
+ {
231
+ displayName: 'Author',
232
+ name: 'author',
233
+ type: 'string',
234
+ displayOptions: {
235
+ show: {
236
+ operation: ['createCertificate'],
237
+ },
238
+ },
239
+ default: '',
240
+ description: 'Author name',
241
+ },
242
+ {
243
+ displayName: 'Description',
244
+ name: 'description',
245
+ type: 'string',
246
+ displayOptions: {
247
+ show: {
248
+ operation: ['createCertificate'],
249
+ },
250
+ },
251
+ default: '',
252
+ description: 'Certificate description',
253
+ },
254
+ // ============================================
255
+ // LIST CERTIFICATES PARAMETERS
256
+ // ============================================
257
+ {
258
+ displayName: 'Filter by Hash',
259
+ name: 'filterHash',
260
+ type: 'string',
261
+ displayOptions: {
262
+ show: {
263
+ operation: ['listCertificates'],
264
+ },
265
+ },
266
+ default: '',
267
+ placeholder: '2eb0a0766d04971078ca73e1b9d2281b70fc4ca2...',
268
+ description: 'Filter certificates by hash (partial match)',
269
+ },
270
+ {
271
+ displayName: 'Filter by Filename',
272
+ name: 'filterFilename',
273
+ type: 'string',
274
+ displayOptions: {
275
+ show: {
276
+ operation: ['listCertificates'],
277
+ },
278
+ },
279
+ default: '',
280
+ placeholder: 'DSC02158.JPG',
281
+ description: 'Filter certificates by filename (partial match)',
282
+ },
283
+ {
284
+ displayName: 'Filter by Signature',
285
+ name: 'filterSignature',
286
+ type: 'string',
287
+ displayOptions: {
288
+ show: {
289
+ operation: ['listCertificates'],
290
+ },
291
+ },
292
+ default: '',
293
+ placeholder: '4ZxL8...',
294
+ description: 'Filter certificates by blockchain signature (partial match)',
295
+ },
296
+ {
297
+ displayName: 'Limit',
298
+ name: 'limit',
299
+ type: 'number',
300
+ displayOptions: {
301
+ show: {
302
+ operation: ['listCertificates'],
303
+ },
304
+ },
305
+ default: 100,
306
+ description: 'Maximum number of results to return',
307
+ },
308
+ ],
309
+ };
310
+ }
311
+ async execute() {
312
+ var _a;
313
+ const items = this.getInputData();
314
+ const returnData = [];
315
+ for (let i = 0; i < items.length; i++) {
316
+ try {
317
+ const operation = this.getNodeParameter('operation', i);
318
+ const credentials = await this.getCredentials('proofOfAuthenticityApi', i);
319
+ const baseUrl = credentials.digiCryptoStoreUrl.replace(/\/$/, '');
320
+ const apiKey = credentials.apiKey;
321
+ let responseData;
322
+ // ============================================
323
+ // CREATE CERTIFICATE OPERATION
324
+ // ============================================
325
+ if (operation === 'createCertificate') {
326
+ const title = this.getNodeParameter('title', i);
327
+ const author = this.getNodeParameter('author', i, '');
328
+ const description = this.getNodeParameter('description', i, '');
329
+ const certificationMode = this.getNodeParameter('certificationMode', i, 'simple');
330
+ const inputType = this.getNodeParameter('inputType', i, 'base64');
331
+ // Map certification mode to API parameters
332
+ const usageType = certificationMode === 'simple' ? 'simple' : 'ai';
333
+ let fileData;
334
+ if (inputType === 'url') {
335
+ const fileUrl = this.getNodeParameter('fileUrl', i);
336
+ // Validate URL to prevent SSRF
337
+ validateUrl(fileUrl);
338
+ const fileResponse = await axios_1.default.get(fileUrl, {
339
+ timeout: DOWNLOAD_TIMEOUT,
340
+ responseType: 'arraybuffer',
341
+ maxContentLength: MAX_FILE_SIZE,
342
+ maxBodyLength: MAX_FILE_SIZE,
343
+ });
344
+ const contentType = fileResponse.headers['content-type'] || 'application/octet-stream';
345
+ const base64Data = Buffer.from(fileResponse.data).toString('base64');
346
+ fileData = `data:${contentType};base64,${base64Data}`;
347
+ }
348
+ else {
349
+ fileData = this.getNodeParameter('fileData', i);
350
+ }
351
+ const requestBody = {
352
+ file_data: fileData,
353
+ title,
354
+ description,
355
+ usage_type: usageType,
356
+ payment_mode: 'credits', // Use subscription credits
357
+ };
358
+ // Add AI options if AI mode is enabled
359
+ if (usageType === 'ai') {
360
+ requestBody.ai_endpoint = 'art';
361
+ requestBody.enable_c2pa = true; // C2PA auto-enabled with AI
362
+ }
363
+ const response = await axios_1.default.post(`${baseUrl}/api/solmemo/create`, requestBody, {
364
+ timeout: usageType === 'ai' ? 60000 : REQUEST_TIMEOUT, // 60s if AI
365
+ headers: {
366
+ 'Authorization': `Bearer ${apiKey}`,
367
+ 'Content-Type': 'application/json',
368
+ },
369
+ ...getAxiosConfig(baseUrl),
370
+ });
371
+ responseData = response.data;
372
+ }
373
+ // ============================================
374
+ // LIST CERTIFICATES OPERATION
375
+ // ============================================
376
+ else if (operation === 'listCertificates') {
377
+ // Get filter parameters
378
+ const filterHash = this.getNodeParameter('filterHash', i, '');
379
+ const filterFilename = this.getNodeParameter('filterFilename', i, '');
380
+ const filterSignature = this.getNodeParameter('filterSignature', i, '');
381
+ const limit = this.getNodeParameter('limit', i, 100);
382
+ // Build query string
383
+ const queryParams = new URLSearchParams();
384
+ if (filterHash)
385
+ queryParams.append('hash', filterHash);
386
+ if (filterFilename)
387
+ queryParams.append('filename', filterFilename);
388
+ if (filterSignature)
389
+ queryParams.append('signature', filterSignature);
390
+ queryParams.append('limit', limit.toString());
391
+ const queryString = queryParams.toString();
392
+ const url = `${baseUrl}/api/solmemo/list${queryString ? '?' + queryString : ''}`;
393
+ const response = await axios_1.default.get(url, {
394
+ timeout: REQUEST_TIMEOUT,
395
+ headers: {
396
+ 'Authorization': `Bearer ${apiKey}`,
397
+ },
398
+ ...getAxiosConfig(baseUrl),
399
+ });
400
+ responseData = response.data;
401
+ }
402
+ // Return data
403
+ returnData.push({
404
+ json: responseData,
405
+ pairedItem: { item: i },
406
+ });
407
+ }
408
+ catch (error) {
409
+ if (this.continueOnFail()) {
410
+ returnData.push({
411
+ json: {
412
+ error: error.message,
413
+ details: ((_a = error.response) === null || _a === void 0 ? void 0 : _a.data) || {},
414
+ },
415
+ pairedItem: { item: i },
416
+ });
417
+ continue;
418
+ }
419
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, { itemIndex: i });
420
+ }
421
+ }
422
+ return [returnData];
423
+ }
424
+ }
425
+ exports.ProofOfAuthenticity = ProofOfAuthenticity;
package/index.js ADDED
@@ -0,0 +1,2 @@
1
+ // n8n-nodes-proofofauthenticity
2
+ module.exports = {};
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "n8n-nodes-proofofauthenticity",
3
+ "version": "1.0.0",
4
+ "description": "ProofOfAuthenticity by CHECKHC - Blockchain timestamping with AI detection and C2PA content authenticity.",
5
+ "keywords": [
6
+ "n8n",
7
+ "n8n-community-node-package",
8
+ "proofofauthenticity",
9
+ "checkhc",
10
+ "blockchain",
11
+ "solana",
12
+ "certification",
13
+ "c2pa",
14
+ "content-authenticity",
15
+ "ai-detection",
16
+ "timestamp",
17
+ "proof-of-authenticity"
18
+ ],
19
+ "license": "MIT",
20
+ "homepage": "https://www.checkhc.net",
21
+ "author": "CHECKHC <contact@checkhc.net> (https://checkhc.net)",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/checkhc/n8n-nodes-proofofauthenticity.git"
25
+ },
26
+ "main": "index.js",
27
+ "scripts": {
28
+ "build": "tsc && gulp build:icons",
29
+ "dev": "tsc --watch",
30
+ "format": "prettier credentials nodes --write",
31
+ "lint": "eslint credentials nodes package.json",
32
+ "lintfix": "eslint credentials nodes package.json --fix",
33
+ "prepublishOnly": "npm run build"
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "LICENSE"
38
+ ],
39
+ "n8n": {
40
+ "n8nNodesApiVersion": 1,
41
+ "credentials": [
42
+ "dist/credentials/ProofOfAuthenticityApi.credentials.js"
43
+ ],
44
+ "nodes": [
45
+ "dist/nodes/ProofOfAuthenticity/ProofOfAuthenticity.node.js"
46
+ ]
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^20.0.0",
50
+ "eslint": "^8.0.0",
51
+ "gulp": "^4.0.2",
52
+ "n8n-workflow": "^1.0.0",
53
+ "prettier": "^3.0.0",
54
+ "typescript": "^5.0.0"
55
+ },
56
+ "dependencies": {
57
+ "axios": "^1.7.9",
58
+ "form-data": "^4.0.4"
59
+ }
60
+ }