@limetech/n8n-nodes-lime 2.5.4 → 2.5.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@limetech/n8n-nodes-lime",
3
- "version": "2.5.4",
3
+ "version": "2.5.5",
4
4
  "description": "n8n node to connect to Lime CRM",
5
5
  "license": "Apache-2.0",
6
6
  "main": "nodes/index.ts",
@@ -40,7 +40,6 @@
40
40
  "devDependencies": {
41
41
  "@limetech/eslint-config": "^4.0.0",
42
42
  "@semantic-release/changelog": "^6.0.3",
43
- "@semantic-release/exec": "^7.1.0",
44
43
  "@semantic-release/git": "^10.0.1",
45
44
  "@types/jest": "^30.0.0",
46
45
  "@types/node": "^24.10.1",
@@ -1,23 +0,0 @@
1
- name: Lint
2
-
3
- on:
4
- pull_request:
5
- push:
6
- branches:
7
- - main
8
-
9
- jobs:
10
- lint:
11
- runs-on: ubuntu-latest
12
- steps:
13
- - uses: actions/checkout@v4
14
- - uses: actions/setup-node@v4
15
- with:
16
- node-version: 24
17
- - run: npm ci
18
- - name: Run eslint
19
- run: npm run lint
20
- - name: Run prettier
21
- run: npm run format
22
- - name: Run knip
23
- run: npm run knip
@@ -1,21 +0,0 @@
1
- name: 'Mark stale issues and PRs'
2
- on:
3
- schedule:
4
- - cron: '30 1 * * *'
5
-
6
- permissions:
7
- actions: write
8
- issues: write
9
- pull-requests: write
10
-
11
- jobs:
12
- stale:
13
- runs-on: ubuntu-latest
14
- steps:
15
- - uses: actions/stale@v10
16
- with:
17
- stale-issue-message: 'This issue is stale because it has been open 30 days with no activity.'
18
- stale-pr-message: 'This PR is stale because it has been open 30 days with no activity.'
19
- days-before-stale: 30
20
- days-before-close: -1
21
- days-before-pr-close: -1
@@ -1,35 +0,0 @@
1
- name: Release and Push to NPM Registry
2
-
3
- on:
4
- push:
5
- branches:
6
- - main
7
- - dev
8
- - '*[0-9].*[0-9].x'
9
- - '*[0-9].x.x'
10
-
11
- jobs:
12
- release:
13
- name: Lime N8N Semantic Release
14
- runs-on: ubuntu-latest
15
- outputs:
16
- version: ${{ steps.semantic_release.outputs.version }}
17
- steps:
18
- - uses: actions/checkout@v3
19
-
20
- - uses: actions/setup-node@v3
21
- with:
22
- node-version: 24
23
-
24
- - run: npm ci
25
-
26
- - name: Semantic release
27
- id: semantic_release
28
- run: |
29
- npx semantic-release
30
- VERSION=$(cat VERSION)
31
- echo "Successfully released version: $VERSION"
32
- echo "version=$VERSION" >> $GITHUB_OUTPUT
33
- env:
34
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -1,32 +0,0 @@
1
- name: Test and build
2
-
3
- on:
4
- push:
5
- branches:
6
- - main
7
- pull_request:
8
- branches:
9
- - main
10
-
11
- jobs:
12
- publish:
13
- name: Test build
14
- runs-on: ubuntu-latest
15
-
16
- steps:
17
- - name: Checkout code
18
- uses: actions/checkout@v3
19
-
20
- - name: Set up Node.js
21
- uses: actions/setup-node@v3
22
- with:
23
- node-version: 24
24
-
25
- - name: Install dependencies
26
- run: npm install
27
-
28
- - name: Build the package
29
- run: npm run build
30
-
31
- - name: Run tests
32
- run: npm run test
package/.prettierignore DELETED
@@ -1,6 +0,0 @@
1
- dist/
2
- node_modules/
3
- restore_script/
4
- package-lock.json
5
- CHANGELOG.md
6
- README
package/.prettierrc.mjs DELETED
@@ -1 +0,0 @@
1
- export { default } from '@limetech/eslint-config/prettier.config.js';
package/.releaserc.json DELETED
@@ -1,36 +0,0 @@
1
- {
2
- "branches": [
3
- "main",
4
- {
5
- "name": "dev",
6
- "prerelease": true
7
- }
8
- ],
9
- "plugins": [
10
- "@semantic-release/commit-analyzer",
11
- "@semantic-release/release-notes-generator",
12
- [
13
- "@semantic-release/changelog",
14
- {
15
- "changelogFile": "CHANGELOG.md"
16
- }
17
- ],
18
- [
19
- "@semantic-release/git",
20
- {
21
- "assets": ["package.json", "CHANGELOG.md"],
22
- "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
23
- }
24
- ],
25
- [
26
- "@semantic-release/exec",
27
- {
28
- "prepareCmd": "npm run build",
29
- "successCmd": "echo v${nextRelease.version} > VERSION",
30
- "__note": "DO NOT CHANGE - this command is used in Release action"
31
- }
32
- ],
33
- "@semantic-release/github",
34
- "@semantic-release/npm"
35
- ]
36
- }
package/Dockerfile DELETED
File without changes
package/eslint.config.mjs DELETED
@@ -1,28 +0,0 @@
1
- import config from '@limetech/eslint-config';
2
-
3
- export default [
4
- ...config,
5
- {
6
- files: ['**/*.{ts,tsx}'],
7
- rules: {
8
- 'jsdoc/require-returns': 'off',
9
- 'jsdoc/require-param-description': 'off',
10
- 'jsdoc/require-jsdoc': 'off',
11
- // N8N prefers the upper camel case for file names
12
- 'unicorn/filename-case': 'off',
13
- 'unicorn/prefer-spread': 'off',
14
- 'no-unused-vars': 'off',
15
- '@typescript-eslint/no-unused-vars': [
16
- 'warn',
17
- {
18
- argsIgnorePattern: '^_',
19
- varsIgnorePattern: '^_',
20
- caughtErrorsIgnorePattern: '^_',
21
- },
22
- ],
23
- },
24
- },
25
- {
26
- ignores: ['jest.config.js', 'docs'],
27
- },
28
- ];
package/jest.config.js DELETED
@@ -1,11 +0,0 @@
1
- module.exports = {
2
- testEnvironment: 'node',
3
- transform: {
4
- '^.+\\.(ts|tsx)$': ['ts-jest', { tsconfig: 'tsconfig.json' }],
5
- },
6
- testMatch: ['**/tests/**/*.spec.ts'],
7
- verbose: true,
8
- testTimeout: 20_000,
9
- testPathIgnorePatterns: ['<rootDir>/dist/'],
10
- modulePathIgnorePatterns: ['<rootDir>/dist/'],
11
- };
package/knip.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/knip@5/schema.json",
3
- "ignoreExportsUsedInFile": {
4
- "interface": true,
5
- "type": true
6
- },
7
- "tags": ["-lintignore"],
8
- "entry": ["credentials/index.{js,ts}", "nodes/index.{js,ts}"]
9
- }
@@ -1,91 +0,0 @@
1
- import {
2
- getCreateMappingColumns,
3
- getUpdateMappingColumns,
4
- LimetypeProperty,
5
- SuccessResponse,
6
- } from '../../../nodes';
7
- import { ILoadOptionsFunctions } from 'n8n-workflow';
8
- import * as transport from '../../../nodes/lime-crm/transport';
9
-
10
- const mockILoadOptionFunctions = {
11
- getNodeParameter: jest.fn().mockReturnValue('company'),
12
- } as unknown as ILoadOptionsFunctions;
13
-
14
- const propertiesResponseMock = {
15
- success: true,
16
- data: [
17
- { name: 'p1', localname: 'Property 1', type: 'yesno', required: true },
18
- {
19
- name: 'p2',
20
- localname: 'Property 2',
21
- type: 'string',
22
- required: false,
23
- length: 2137,
24
- },
25
- {
26
- name: 'p3',
27
- localname: 'Property 3',
28
- type: 'option',
29
- required: true,
30
- options: [
31
- { key: 'op1', text: 'Option 1', inactive: false },
32
- { key: 'op2', text: 'Option 2', inactive: false },
33
- { key: 'op3', text: 'Option 3', inactive: true },
34
- ],
35
- },
36
- ],
37
- } as SuccessResponse<LimetypeProperty[]>;
38
-
39
- describe('resourceMapping', () => {
40
- beforeEach(() => {
41
- jest.spyOn(transport, 'getProperties').mockResolvedValue(
42
- propertiesResponseMock
43
- );
44
- });
45
- it('gets valid resource mapping for create', async () => {
46
- const columns = await getCreateMappingColumns.call(
47
- mockILoadOptionFunctions
48
- );
49
- const property1 = columns.fields.find((p) => p.id == 'p1')!;
50
-
51
- expect(property1.displayName).toBe('Property 1 [yesno]');
52
- expect(property1.required).toBe(true);
53
- expect(property1.defaultMatch).toBe(false);
54
- expect(property1.display).toBe(true);
55
- expect(property1.type).toBe('boolean');
56
- expect(property1.options).toBe(undefined);
57
-
58
- const property2 = columns.fields.find((p) => p.id == 'p2')!;
59
- expect(property2.displayName).toBe('Property 2 [string(2137)]');
60
- expect(property2.required).toBe(false);
61
- expect(property2.defaultMatch).toBe(false);
62
- expect(property2.display).toBe(true);
63
- expect(property2.type).toBe('string');
64
- expect(property2.options).toBe(undefined);
65
-
66
- const property3 = columns.fields.find((p) => p.id == 'p3')!;
67
- expect(property3.displayName).toBe('Property 3 [option]');
68
- expect(property3.required).toBe(true);
69
- expect(property3.defaultMatch).toBe(false);
70
- expect(property3.display).toBe(true);
71
- expect(property3.type).toBe('options');
72
-
73
- const options = property3.options!;
74
- expect(options).toContainEqual({
75
- value: 'op1',
76
- name: 'Option 1',
77
- });
78
- expect(options).toContainEqual({
79
- value: 'op2',
80
- name: 'Option 2',
81
- });
82
- expect(options.length).toBe(2);
83
- });
84
- it('gets proper required values for update', async () => {
85
- const columns = await getUpdateMappingColumns.call(
86
- mockILoadOptionFunctions
87
- );
88
- const requiredValues = columns.fields.map((p) => p.required);
89
- expect(requiredValues).toEqual([false, false, false]);
90
- });
91
- });
@@ -1,273 +0,0 @@
1
- jest.mock('../../../nodes/lime-crm/transport', () => ({
2
- createFile: jest.fn().mockResolvedValue({
3
- success: true,
4
- data: { id: 1 },
5
- }),
6
- getFileMetadata: jest.fn().mockResolvedValue({
7
- success: true,
8
- data: {
9
- id: '123',
10
- name: 'file.txt',
11
- },
12
- }),
13
- getFileContent: jest.fn().mockResolvedValue({
14
- success: true,
15
- data: 'some binary data',
16
- }),
17
- getTasks: jest.fn(),
18
- }));
19
-
20
- import {
21
- createFile,
22
- getFileContent,
23
- getFileMetadata,
24
- getFilenameFromHeader,
25
- getFilePropertiesNames,
26
- getWebhook,
27
- processFileResponse,
28
- setFilename,
29
- setFileProperties,
30
- verifyHmac,
31
- WebhookFunctions,
32
- } from '../../../nodes';
33
-
34
- describe('files', () => {
35
- describe('setFilename', () => {
36
- it('returns responseFileName if fileName is missing', () => {
37
- expect(
38
- setFilename({ fileExtension: 'jpg' } as any, 'default.jpg')
39
- ).toBe('default.jpg');
40
- });
41
- it('returns existing fileName if present', () => {
42
- expect(
43
- setFilename({ fileName: 'aspen.jpg' } as any, 'default.jpg')
44
- ).toBe('aspen.jpg');
45
- });
46
- });
47
-
48
- describe('getFilenameFromHeader', () => {
49
- it('returns null if header is missing', () => {
50
- expect(getFilenameFromHeader({})).toBeNull();
51
- });
52
-
53
- it('parses standard filename', () => {
54
- expect(
55
- getFilenameFromHeader({
56
- 'content-disposition': 'attachment; filename="test.txt"',
57
- })
58
- ).toBe('test.txt');
59
- });
60
-
61
- it('parses RFC 5987 filename*', () => {
62
- expect(
63
- getFilenameFromHeader({
64
- 'content-disposition':
65
- "attachment; filename*=UTF-8''test%20file.txt",
66
- })
67
- ).toBe('test file.txt');
68
- });
69
- });
70
-
71
- describe('getFilePropertiesNames', () => {
72
- const limetypes = [
73
- {
74
- name: 'company',
75
- type: 'belongsto',
76
- localname: 'company',
77
- required: false,
78
- },
79
- {
80
- name: 'name',
81
- type: 'string',
82
- localname: 'name',
83
- required: false,
84
- },
85
- {
86
- name: 'document',
87
- type: 'file',
88
- localname: 'document',
89
- required: false,
90
- },
91
- {
92
- name: 'photo',
93
- type: 'file',
94
- localname: 'photo',
95
- required: false,
96
- },
97
- ];
98
- it('returns all file property names', async () => {
99
- const result = getFilePropertiesNames(limetypes);
100
- expect(result.has('document')).toBe(true);
101
- expect(result.has('photo')).toBe(true);
102
- expect(result.has('name')).toBe(false);
103
- expect(result.has('company')).toBe(false);
104
- });
105
- it('returns allowed file property names', async () => {
106
- const result = getFilePropertiesNames(
107
- limetypes,
108
- new Set(['document'])
109
- );
110
- expect(result.has('document')).toBe(true);
111
- expect(result.has('photo')).toBe(false);
112
- expect(result.has('name')).toBe(false);
113
- expect(result.has('company')).toBe(false);
114
- });
115
- });
116
-
117
- describe('setFileProperties', () => {
118
- const mockContext: any = {
119
- helpers: {
120
- assertBinaryData: jest.fn(),
121
- },
122
- };
123
- const mockBinaryData = { data: 'some binary data' };
124
-
125
- beforeEach(() => {
126
- (createFile as jest.Mock).mockClear();
127
- mockContext.helpers.assertBinaryData.mockClear();
128
- });
129
-
130
- it('sets file properties successfully', async () => {
131
- mockContext.helpers.assertBinaryData.mockReturnValue(
132
- mockBinaryData
133
- );
134
-
135
- const definedProperties = { document: 'some binary data' };
136
- const result = await setFileProperties(
137
- mockContext,
138
- 0,
139
- new Set(['document']),
140
- definedProperties
141
- );
142
- expect(result.success).toBe(true);
143
- if (result.success) {
144
- expect(result.data.document).toBe(1);
145
- }
146
- });
147
-
148
- it('sets file ID if assertBinaryData throws an error', async () => {
149
- mockContext.helpers.assertBinaryData.mockImplementation(() => {
150
- throw new Error('Invalid binary data');
151
- });
152
- const definedProperties = { document: 2 };
153
- const result = await setFileProperties(
154
- mockContext,
155
- 0,
156
- new Set(['document']),
157
- definedProperties
158
- );
159
- expect(result.success).toBe(true);
160
- if (result.success) {
161
- expect(result.data.document).toBe(2);
162
- }
163
- });
164
- });
165
-
166
- describe('processFileResponse', () => {
167
- const mockNodeContext = {};
168
-
169
- beforeEach(() => {
170
- (getFileMetadata as jest.Mock).mockClear();
171
- (getFileContent as jest.Mock).mockClear();
172
- });
173
-
174
- it('returns file metadata without file content', async () => {
175
- const data = { document: 1 };
176
- const result = await processFileResponse<{ document: number }>(
177
- mockNodeContext as any,
178
- new Set(['document']),
179
- data
180
- );
181
- expect(result.json.success).toBe(true);
182
- if (result.json.success) {
183
- expect(result.json.data.document).toEqual({
184
- id: '123',
185
- name: 'file.txt',
186
- });
187
- expect(result.binary).toEqual({});
188
- }
189
- });
190
-
191
- it('returns file metadata with file content', async () => {
192
- const data = { document: 1 };
193
- const result = await processFileResponse<{ document: number }>(
194
- mockNodeContext as any,
195
- new Set(['document']),
196
- data,
197
- true
198
- );
199
- if (result.json.success) {
200
- expect(result.json.data.document).toEqual({
201
- id: '123',
202
- name: 'file.txt',
203
- });
204
- expect(result.binary?.document).toEqual('some binary data');
205
- }
206
- });
207
- });
208
- });
209
-
210
- describe('hmac', () => {
211
- describe('verifyHmac', () => {
212
- const key = 'my-secret-key';
213
- const data = Buffer.from('hello world');
214
- const correctHmac =
215
- 'sha256=90eb182d8396f16d4341d582047f45c0a97d73388c5377d9ced478a2212295ad';
216
-
217
- it('returns true when the HMAC matches', () => {
218
- expect(verifyHmac(key, data, correctHmac)).toBe(true);
219
- });
220
-
221
- it('returns false when the HMAC does not match', () => {
222
- expect(verifyHmac(key, data, 'wrongHmac')).toBe(false);
223
- });
224
- });
225
- });
226
-
227
- describe('webhook', () => {
228
- describe('getWebhhok', () => {
229
- let mockHookData: jest.Mocked<WebhookFunctions>;
230
-
231
- beforeEach(() => {
232
- jest.useFakeTimers().setSystemTime(
233
- new Date('2025-11-12T12:00:00Z')
234
- );
235
- mockHookData = {
236
- getNode: jest.fn().mockReturnValue({ id: '1', name: 'MyNode' }),
237
- getWorkflow: jest
238
- .fn()
239
- .mockReturnValue({ id: '2', name: 'MyWorkflow' }),
240
- getWorkflowStaticData: jest
241
- .fn()
242
- .mockReturnValue({ key: 'value' }),
243
- getNodeWebhookUrl: jest
244
- .fn()
245
- .mockReturnValue('https://example.com/hook'),
246
- getNodeParameter: jest.fn().mockReturnValue({
247
- event: [{ limetype: 'company', eventType: 'new' }],
248
- }),
249
- } as unknown as jest.Mocked<WebhookFunctions>;
250
- });
251
-
252
- afterEach(() => {
253
- jest.useRealTimers();
254
- });
255
-
256
- it('constructs a full webhook object correctly', () => {
257
- const result = getWebhook(mockHookData);
258
-
259
- expect(result).toEqual({
260
- data: { key: 'value' },
261
- events: ['company.new'],
262
- url: 'https://example.com/hook',
263
- context: {
264
- nodeId: '1',
265
- nodeName: 'MyNode',
266
- workflowId: '2',
267
- workflowName: 'MyWorkflow',
268
- },
269
- name: 'company-new-1762948800000',
270
- });
271
- });
272
- });
273
- });
package/tsconfig.json DELETED
@@ -1,30 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "strict": true,
4
- "module": "commonjs",
5
- "moduleResolution": "node",
6
- "target": "es2019",
7
- "lib": ["es2019", "es2020", "es2022"],
8
- "removeComments": true,
9
- "useUnknownInCatchVariables": false,
10
- "forceConsistentCasingInFileNames": true,
11
- "noImplicitAny": true,
12
- "noImplicitReturns": true,
13
- "noUnusedLocals": true,
14
- "strictNullChecks": true,
15
- "preserveConstEnums": true,
16
- "esModuleInterop": true,
17
- "resolveJsonModule": true,
18
- "incremental": true,
19
- "declaration": true,
20
- "sourceMap": true,
21
- "skipLibCheck": true,
22
- "outDir": "./dist/"
23
- },
24
- "include": [
25
- "credentials/**/*",
26
- "nodes/**/*",
27
- "nodes/**/*.json",
28
- "package.json"
29
- ]
30
- }
package/typedoc.css DELETED
@@ -1,9 +0,0 @@
1
- .tsd-page-toolbar {
2
- background-color: rgb(77, 182, 172);
3
- border: 0;
4
- }
5
-
6
- #tsd-search .title,
7
- #tsd-search label {
8
- --color-text: white;
9
- }
package/typedoc.json DELETED
@@ -1,19 +0,0 @@
1
- {
2
- "$schema": "https://typedoc.org/schema.json",
3
- "entryPoints": [
4
- "./nodes/lime-crm/index.ts",
5
- "./nodes/response.ts",
6
- "./credentials/index.ts"
7
- ],
8
- "entryPointStrategy": "expand",
9
- "name": "Lime N8N Documentation",
10
- "customCss": "typedoc.css",
11
- "out": "docs",
12
- "includeVersion": true,
13
- "readme": "README.md",
14
- "tsconfig": "tsconfig.json",
15
- "disableSources": true,
16
- "hideGenerator": true,
17
- "categorizeByGroup": true,
18
- "cleanOutputDir": true
19
- }