@algolia/n8n-nodes-algolia 0.4.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/LICENSE.md ADDED
@@ -0,0 +1,19 @@
1
+ Copyright 2022 n8n
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # n8n-nodes-algolia
2
+
3
+ This is an n8n community node. It lets you use Algolia in your n8n workflows.
4
+
5
+ Algolia is a hosted search API that provides search-as-a-service solutions. It offers powerful search capabilities including full-text search, faceting, geo-search, and instant search with typo tolerance.
6
+
7
+ [n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/reference/license/) workflow automation platform.
8
+
9
+ [Installation](#installation)
10
+ [Operations](#operations)
11
+ [Credentials](#credentials)
12
+ [Compatibility](#compatibility)
13
+ [Resources](#resources)
14
+
15
+ ## Installation
16
+
17
+ Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.
18
+
19
+ ## Operations
20
+
21
+ This node supports the following operations:
22
+
23
+ **Index**
24
+
25
+ - List Indices: List all indices in your Algolia application
26
+ - Search Index: Search for records in a specific index
27
+
28
+ **Objects**
29
+
30
+ - Add Object: Add a new object to an index
31
+
32
+ ## Credentials
33
+
34
+ To use this node, you need to authenticate with Algolia using API credentials.
35
+
36
+ ### Prerequisites
37
+
38
+ 1. Sign up for an [Algolia account](https://www.algolia.com)
39
+ 2. Create an application in your Algolia dashboard
40
+
41
+ ### Authentication Setup
42
+
43
+ 1. In your Algolia dashboard, go to Settings > API Keys
44
+ 2. Copy your Application ID
45
+ 3. Copy your Admin API Key (required for write operations)
46
+ 4. In n8n, create new Algolia API credentials with:
47
+ - **Application ID**: Your Algolia Application ID
48
+ - **Admin API Key**: Your Algolia Admin API Key
49
+
50
+ ## Compatibility
51
+
52
+ This node requires n8n version 1.0.0 or higher and Node.js 20.15 or higher.
53
+
54
+ ## Resources
55
+
56
+ - [n8n community nodes documentation](https://docs.n8n.io/integrations/#community-nodes)
57
+ - [Algolia API documentation](https://www.algolia.com/doc/api-reference/)
58
+ - [Algolia dashboard](https://www.algolia.com/apps)
@@ -0,0 +1,41 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ class AlgoliaApi {
6
+ constructor() {
7
+ this.name = "algoliaApi";
8
+ this.displayName = "Algolia API";
9
+ this.documentationUrl = "https://www.algolia.com";
10
+ this.properties = [
11
+ {
12
+ displayName: "Application ID",
13
+ name: "appId",
14
+ type: "string",
15
+ required: true,
16
+ default: ""
17
+ },
18
+ {
19
+ displayName: "Admin API Key",
20
+ name: "adminApiKey",
21
+ type: "string",
22
+ typeOptions: {
23
+ password: true
24
+ },
25
+ required: true,
26
+ default: ""
27
+ }
28
+ ];
29
+ this.authenticate = {
30
+ type: "generic",
31
+ properties: {
32
+ headers: {
33
+ "X-Algolia-Application-Id": "={{ $credentials.appId }}",
34
+ "X-Algolia-API-Key": "={{ $credentials.adminApiKey }}"
35
+ }
36
+ }
37
+ };
38
+ }
39
+ }
40
+
41
+ exports.AlgoliaApi = AlgoliaApi;
@@ -0,0 +1,21 @@
1
+ {
2
+ "node": "n8n-nodes-base.Algolia",
3
+ "nodeVersion": "1.0",
4
+ "codexVersion": "1.0",
5
+ "categories": [
6
+ "Data & Storage",
7
+ "Development"
8
+ ],
9
+ "resources": {
10
+ "credentialDocumentation": [
11
+ {
12
+ "url": "https://www.algolia.com/doc/guides/security/api-keys/"
13
+ }
14
+ ],
15
+ "primaryDocumentation": [
16
+ {
17
+ "url": "https://www.algolia.com/doc/rest-api/search/"
18
+ }
19
+ ]
20
+ }
21
+ }
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{fill:#003dff;}.cls-2{fill:#fff;}</style></defs><rect class="cls-1" x="0" y="0" width="500" height="500" rx="250" ry="250"/><path class="cls-2" d="M239.73,122.82c-69.46,0-126.08,56-127.08,125.23-1.02,70.3,56.02,128.56,126.33,128.96,21.72,.13,42.63-5.18,61.2-15.28,1.81-.98,2.09-3.47,.55-4.84l-11.89-10.54c-2.42-2.14-5.86-2.75-8.83-1.48-12.96,5.52-27.05,8.33-41.57,8.16-56.81-.7-102.72-47.97-101.81-104.78,.89-56.09,46.8-101.45,103.1-101.45h103.12v183.28l-58.5-51.98c-1.89-1.68-4.79-1.35-6.32,.67-9.39,12.43-24.69,20.17-41.68,18.99-23.57-1.63-42.67-20.6-44.43-44.16-2.11-28.1,20.16-51.64,47.82-51.64,25.02,0,45.62,19.26,47.77,43.73,.19,2.18,1.17,4.21,2.81,5.66l15.24,13.51c1.73,1.53,4.47,.59,4.9-1.68,1.1-5.87,1.48-12,1.05-18.27-2.45-35.78-31.44-64.57-67.24-66.78-41.04-2.53-75.36,29.58-76.45,69.83-1.06,39.22,31.07,73.03,70.3,73.9,16.38,.36,31.55-4.79,43.82-13.71l76.44,67.76c3.28,2.9,8.45,.58,8.45-3.8V127.64c0-2.66-2.16-4.82-4.82-4.82h-122.27Z"/></svg>
@@ -0,0 +1,579 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ const n8nWorkflow = require('n8n-workflow');
6
+
7
+ class Description {
8
+ /**
9
+ * This helper creates a node description that can be added to an n8n node class.
10
+ * @param description A node description as specified by the n8n reference
11
+ * @see https://docs.n8n.io/integrations/creating-nodes/build/reference/node-base-files/#outline-structure-for-a-declarative-style-node
12
+ */
13
+ constructor(description) {
14
+ this.resources = [];
15
+ this.description = {
16
+ version: 1,
17
+ group: [],
18
+ inputs: [n8nWorkflow.NodeConnectionType.Main],
19
+ outputs: [n8nWorkflow.NodeConnectionType.Main],
20
+ properties: [],
21
+ ...description
22
+ };
23
+ this.resourcesDescription = {
24
+ displayName: "Resource",
25
+ name: "resource",
26
+ noDataExpression: true,
27
+ default: void 0,
28
+ // TODO: allow customizing resource type
29
+ // https://docs.n8n.io/integrations/creating-nodes/build/reference/node-base-files/#resource-objects
30
+ type: "options",
31
+ options: []
32
+ };
33
+ }
34
+ /**
35
+ * Adds a {@link Resource} to this Description.
36
+ * @param resource The resource's option object as specified by the n8n reference
37
+ * @param setDefault Whether to make this Resource selected by default
38
+ * @chainable
39
+ * @see https://docs.n8n.io/integrations/creating-nodes/build/reference/node-base-files/#resource-objects
40
+ */
41
+ addResource(resource, setDefault = false) {
42
+ this.resources.push(resource);
43
+ if (setDefault) {
44
+ this.resourcesDescription.default = resource.value;
45
+ }
46
+ return this;
47
+ }
48
+ /**
49
+ * Returns a description that is compatible with n8n.
50
+ */
51
+ apply() {
52
+ const resourcesData = this.resources.reduce(
53
+ ({ resources, operations, fields }, resource) => {
54
+ const {
55
+ definition,
56
+ operations: resourceOperations,
57
+ fields: resourceFields
58
+ } = resource.apply();
59
+ return {
60
+ resources: [...resources, definition],
61
+ operations: [...operations, resourceOperations],
62
+ fields: [...fields, ...resourceFields]
63
+ };
64
+ },
65
+ { resources: [], operations: [], fields: [] }
66
+ );
67
+ return {
68
+ ...this.description,
69
+ properties: [
70
+ {
71
+ ...this.resourcesDescription,
72
+ default: this.resourcesDescription.default || this.resources[0]?.value,
73
+ options: resourcesData.resources
74
+ },
75
+ ...resourcesData.operations,
76
+ ...resourcesData.fields
77
+ ]
78
+ };
79
+ }
80
+ }
81
+
82
+ class Operation {
83
+ /**
84
+ * This helper creates an operation that can be added to a {@link Resource}.
85
+ * @param operation An operation's option object as specified by the n8n reference
86
+ * @param additionalParams
87
+ * @see https://docs.n8n.io/integrations/creating-nodes/build/reference/node-base-files/#operations-objects
88
+ */
89
+ constructor(operation, additionalParams = {
90
+ additionalFieldsLabel: "Additional Fields"
91
+ }) {
92
+ this.operation = operation;
93
+ this.additionalParams = additionalParams;
94
+ this.fields = [];
95
+ this.additionalFields = [];
96
+ }
97
+ /**
98
+ * Adds a field to this Operation.
99
+ * `displayOptions` is automatically applied by the Operation.
100
+ * @param field The UI element object as specified by the n8n reference
101
+ * @chainable
102
+ * @see https://docs.n8n.io/integrations/creating-nodes/build/reference/ui-elements/
103
+ */
104
+ addField(...field) {
105
+ this.fields.push(...field);
106
+ return this;
107
+ }
108
+ /**
109
+ * Adds a field to this Operation's additional fields drawer.
110
+ * @param field The UI element object as specified by the n8n reference
111
+ * @chainable
112
+ * @see https://docs.n8n.io/integrations/creating-nodes/build/reference/ui-elements/
113
+ */
114
+ addAdditionalField(...field) {
115
+ this.additionalFields.push(...field);
116
+ return this;
117
+ }
118
+ /**
119
+ * Adds a `postReceive` transformation on the routing output and a UI field that give users the ability to receive a simplified version of the data.
120
+ * @param transformFn The transform method that will return a simplified version of the provided output
121
+ * @chainable
122
+ */
123
+ addSimplifiedOutput(transformFn) {
124
+ if (!this.operation.routing) {
125
+ throw new Error(
126
+ `The operation "${this.operation.name}" needs a routing object in order to transform its output.`
127
+ );
128
+ }
129
+ if (!this.operation.routing.output?.postReceive) {
130
+ this.operation.routing.output = {
131
+ ...this.operation.routing.output || {},
132
+ postReceive: this.operation.routing.output?.postReceive || []
133
+ };
134
+ }
135
+ this.operation.routing.output.postReceive.push(async function postReceiveFn(items) {
136
+ if (!this.getNodeParameter("simplify", false)) {
137
+ return items;
138
+ }
139
+ return items.map((item) => ({
140
+ ...item,
141
+ json: transformFn(item.json)
142
+ }));
143
+ });
144
+ if (!this.fields.find(({ name }) => name === "simplify")) {
145
+ this.addField({
146
+ displayName: "Simplify",
147
+ name: "simplify",
148
+ description: "Whether to return a simplified version of the response instead of the raw data",
149
+ type: "boolean",
150
+ default: false
151
+ });
152
+ }
153
+ return this;
154
+ }
155
+ /**
156
+ * Returns a description of this Operation, to be used by the Resource and the Description helpers in order to create a compatible n8n Node description.
157
+ * @internal
158
+ */
159
+ apply() {
160
+ const additionalFields = this.additionalFields.length > 0 ? [
161
+ {
162
+ displayName: this.additionalParams.additionalFieldsLabel,
163
+ name: "additionalFields",
164
+ type: "collection",
165
+ default: {},
166
+ options: this.additionalFields
167
+ }
168
+ ] : [];
169
+ return {
170
+ definition: this.operation,
171
+ fields: this.fields.sort((field1, field2) => {
172
+ if (field1.name === "simplify" && field2.name !== "simplify") {
173
+ return 1;
174
+ } else if (field1.name !== "simplify" && field2.name === "simplify") {
175
+ return -1;
176
+ }
177
+ return 0;
178
+ }).concat(additionalFields).map((field) => ({
179
+ ...field,
180
+ displayOptions: {
181
+ show: {
182
+ ...field.displayOptions?.show || {},
183
+ operation: [this.operation.value]
184
+ }
185
+ }
186
+ }))
187
+ };
188
+ }
189
+ /**
190
+ * The Operation's identifier
191
+ */
192
+ get value() {
193
+ return this.operation.value;
194
+ }
195
+ }
196
+
197
+ class Resource {
198
+ /**
199
+ * This helper creates a resource that can be added to a {@link Description}.
200
+ * @param resource A resource's option object as specified by the n8n reference
201
+ * @param additionalParameters
202
+ * @see https://docs.n8n.io/integrations/creating-nodes/build/reference/node-base-files/#resource-objects
203
+ */
204
+ constructor(resource) {
205
+ this.resource = resource;
206
+ this.operations = [];
207
+ this.operationDescription = {
208
+ displayName: "Operation",
209
+ name: "operation",
210
+ // TODO: allow customizing operation type
211
+ // https://docs.n8n.io/integrations/creating-nodes/build/reference/node-base-files/#operations-objects
212
+ type: "options",
213
+ noDataExpression: true,
214
+ default: void 0,
215
+ options: []
216
+ };
217
+ }
218
+ /**
219
+ * Adds an {@link Operation} to this Resource.
220
+ * `displayOptions` is automatically applied by the Resource.
221
+ * @param operation The operation's option object as specified by the n8n reference
222
+ * @param setDefault Whether to make this Operation selected by default
223
+ * @chainable
224
+ * @see https://docs.n8n.io/integrations/creating-nodes/build/reference/node-base-files/#operations-objects
225
+ */
226
+ addOperation(operation, setDefault = false) {
227
+ this.operations.push(operation);
228
+ if (setDefault) {
229
+ this.operationDescription.default = operation.value;
230
+ }
231
+ return this;
232
+ }
233
+ /**
234
+ * Returns a description of the Resource, to be used by the {@link Description} helper in order to create a compatible n8n Node description.
235
+ * @internal
236
+ */
237
+ apply() {
238
+ const operationsData = this.operations.reduce(
239
+ ({ operations: operations2, fields }, operation) => {
240
+ const { definition, fields: operationFields } = operation.apply();
241
+ return {
242
+ operations: [...operations2, definition],
243
+ fields: [...fields, ...operationFields]
244
+ };
245
+ },
246
+ { operations: [], fields: [] }
247
+ );
248
+ if (this.operations.length === 0) {
249
+ throw new Error(
250
+ `The resource "${this.resource.name}" needs to contain at least one operation.`
251
+ );
252
+ }
253
+ const operations = {
254
+ ...this.operationDescription,
255
+ displayOptions: {
256
+ show: {
257
+ resource: [this.resource.value]
258
+ }
259
+ },
260
+ default: this.operationDescription.default || this.operations[0]?.value || "",
261
+ options: operationsData.operations
262
+ };
263
+ return {
264
+ definition: this.resource,
265
+ operations,
266
+ fields: operationsData.fields
267
+ };
268
+ }
269
+ /**
270
+ * The resource's identifier
271
+ */
272
+ get value() {
273
+ return this.resource.value;
274
+ }
275
+ }
276
+
277
+ const name = "@algolia/n8n-nodes-algolia";
278
+ const version = "0.4.2";
279
+ const pkg = {
280
+ name,
281
+ version};
282
+
283
+ const listIndices = new Operation({
284
+ name: "List Indices",
285
+ action: "List indices",
286
+ value: "listIndices",
287
+ description: "List all indices",
288
+ routing: {
289
+ request: {
290
+ method: "GET",
291
+ url: "/1/indexes"
292
+ }
293
+ }
294
+ }).addSimplifiedOutput((json) => json.items);
295
+
296
+ const attributesToRetrieve = {
297
+ displayName: "Attributes to Retrieve",
298
+ name: "attributesToRetrieve",
299
+ type: "string",
300
+ default: [],
301
+ typeOptions: {
302
+ multipleValues: true,
303
+ multipleValueButtonText: "Add attribute"
304
+ },
305
+ routing: {
306
+ request: {
307
+ body: {
308
+ attributesToRetrieve: "={{ $value }}"
309
+ }
310
+ }
311
+ }
312
+ };
313
+
314
+ const hitsPerPage = {
315
+ displayName: "hitsPerPage",
316
+ name: "hitsPerPage",
317
+ description: "The number of hits per page",
318
+ type: "number",
319
+ default: 20,
320
+ typeOptions: {
321
+ minValue: 0,
322
+ maxValue: 1e3
323
+ },
324
+ routing: {
325
+ request: {
326
+ body: {
327
+ hitsPerPage: "={{ $value }}"
328
+ }
329
+ }
330
+ }
331
+ };
332
+
333
+ const indexName = {
334
+ displayName: "Index Name",
335
+ name: "indexName",
336
+ type: "options",
337
+ required: true,
338
+ default: "",
339
+ typeOptions: {
340
+ loadOptions: {
341
+ routing: {
342
+ request: {
343
+ method: "GET",
344
+ url: "/1/indexes"
345
+ },
346
+ output: {
347
+ postReceive: [
348
+ {
349
+ type: "rootProperty",
350
+ properties: {
351
+ property: "items"
352
+ }
353
+ },
354
+ {
355
+ type: "setKeyValue",
356
+ properties: {
357
+ name: "={{ $responseItem.name }}",
358
+ value: "={{ $responseItem.name }}"
359
+ }
360
+ }
361
+ ]
362
+ }
363
+ }
364
+ }
365
+ }
366
+ };
367
+
368
+ const page = {
369
+ // eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
370
+ displayName: "page",
371
+ name: "page",
372
+ description: "The page to retrieve",
373
+ type: "number",
374
+ default: 0,
375
+ typeOptions: {
376
+ minValue: 0
377
+ },
378
+ routing: {
379
+ request: {
380
+ body: {
381
+ page: "={{ $value }}"
382
+ }
383
+ }
384
+ }
385
+ };
386
+
387
+ const query = {
388
+ displayName: "Query",
389
+ name: "query",
390
+ type: "string",
391
+ description: "The text used to search an index",
392
+ default: "",
393
+ routing: {
394
+ request: {
395
+ body: {
396
+ query: "={{ $value }}"
397
+ }
398
+ }
399
+ }
400
+ };
401
+
402
+ const searchIndex = new Operation(
403
+ {
404
+ name: "Search Index",
405
+ action: "Search index",
406
+ value: "searchIndex",
407
+ description: "Returns objects in an index that match the query",
408
+ routing: {
409
+ request: {
410
+ method: "POST",
411
+ url: "=/1/indexes/{{ $parameter.indexName }}/query"
412
+ }
413
+ }
414
+ },
415
+ {
416
+ additionalFieldsLabel: "Search Parameters"
417
+ }
418
+ ).addField(indexName, query).addAdditionalField(attributesToRetrieve, hitsPerPage, page).addSimplifiedOutput((json) => json.hits);
419
+
420
+ const index = new Resource({
421
+ name: "Index",
422
+ value: "index"
423
+ }).addOperation(listIndices).addOperation(searchIndex);
424
+
425
+ const objectTypeSelector = {
426
+ displayName: "Object",
427
+ name: "object",
428
+ type: "options",
429
+ default: "json",
430
+ options: [
431
+ {
432
+ name: "From JSON",
433
+ value: "json"
434
+ },
435
+ {
436
+ name: "Using Fields Below",
437
+ value: "keypair"
438
+ }
439
+ ]
440
+ };
441
+ const jsonObject = {
442
+ displayName: "JSON",
443
+ name: "json",
444
+ type: "json",
445
+ default: "",
446
+ placeholder: `{
447
+ "firstname": "John",
448
+ "lastname": "Doe",
449
+ "age": 25
450
+ }`,
451
+ typeOptions: {
452
+ rows: 5
453
+ },
454
+ displayOptions: {
455
+ show: {
456
+ object: ["json"]
457
+ }
458
+ }
459
+ };
460
+ const formObject = {
461
+ displayName: "Object Fields",
462
+ name: "keypair",
463
+ type: "fixedCollection",
464
+ placeholder: "Add Field",
465
+ default: {},
466
+ typeOptions: {
467
+ multipleValues: true
468
+ },
469
+ displayOptions: {
470
+ show: {
471
+ object: ["keypair"]
472
+ }
473
+ },
474
+ options: [
475
+ {
476
+ displayName: "Field",
477
+ name: "list",
478
+ values: [
479
+ {
480
+ displayName: "Name",
481
+ name: "name",
482
+ type: "string",
483
+ default: ""
484
+ },
485
+ {
486
+ displayName: "Value",
487
+ name: "value",
488
+ type: "string",
489
+ default: ""
490
+ }
491
+ ]
492
+ }
493
+ ]
494
+ };
495
+ const object = [objectTypeSelector, jsonObject, formObject];
496
+
497
+ const addObject = new Operation({
498
+ name: "Add Object",
499
+ action: "Add Object",
500
+ value: "addObject",
501
+ description: "Add an object to the index, automatically assigning it an object ID",
502
+ routing: {
503
+ request: {
504
+ method: "POST",
505
+ url: "=/1/indexes/{{ $parameter.indexName }}",
506
+ json: true,
507
+ body: '={{ $parameter.object === "keypair" ? $parameter.keypair.list.smartJoin("name", "value") : JSON.parse($parameter.json) }}'
508
+ }
509
+ }
510
+ }).addField(indexName).addField(...object);
511
+
512
+ const attributesToRetrieveQuery = {
513
+ ...attributesToRetrieve,
514
+ routing: {
515
+ request: {
516
+ qs: {
517
+ attributesToRetrieve: '={{ $value.filter(attr => attr.trim() !== "").length > 0 ? $value.filter(attr => attr.trim() !== "").join(",") : undefined }}'
518
+ }
519
+ }
520
+ }
521
+ };
522
+
523
+ const objectId = {
524
+ displayName: "Object ID",
525
+ name: "objectId",
526
+ type: "string",
527
+ default: "",
528
+ required: true,
529
+ description: "The unique identifier of the object to retrieve",
530
+ placeholder: "e.g., myObjectId123"
531
+ };
532
+
533
+ const getObject = new Operation({
534
+ name: "Get Object",
535
+ action: "Get object",
536
+ value: "getObject",
537
+ description: "Retrieve a single object from an index using its object ID",
538
+ routing: {
539
+ request: {
540
+ method: "GET",
541
+ url: "=/1/indexes/{{ $parameter.indexName }}/{{ $parameter.objectId }}"
542
+ }
543
+ }
544
+ }).addField(indexName, objectId).addAdditionalField(attributesToRetrieveQuery);
545
+
546
+ const objects = new Resource({
547
+ name: "Objects",
548
+ value: "objects"
549
+ }).addOperation(addObject).addOperation(getObject);
550
+
551
+ const description = new Description({
552
+ name: "Algolia",
553
+ displayName: "Algolia",
554
+ description: "Use Algolia in your n8n workflows",
555
+ subtitle: '={{ $parameter.operation.replace(/([a-z])([A-Z])/g, "$1 $2").toTitleCase() }}',
556
+ icon: "file:algolia.svg",
557
+ defaults: {
558
+ name: "Algolia"
559
+ },
560
+ credentials: [
561
+ {
562
+ name: "algoliaApi",
563
+ required: true
564
+ }
565
+ ],
566
+ requestDefaults: {
567
+ baseURL: "=https://{{ $credentials.appId }}.algolia.net",
568
+ headers: {
569
+ "User-Agent": `${pkg.name} (${pkg.version})`
570
+ }
571
+ }
572
+ }).addResource(index).addResource(objects);
573
+ class Algolia {
574
+ constructor() {
575
+ this.description = description.apply();
576
+ }
577
+ }
578
+
579
+ exports.Algolia = Algolia;
package/index.js ADDED
File without changes
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@algolia/n8n-nodes-algolia",
3
+ "version": "0.4.2",
4
+ "description": "Algolia nodes for n8n",
5
+ "keywords": [
6
+ "n8n-community-node-package",
7
+ "algolia",
8
+ "n8n"
9
+ ],
10
+ "license": "MIT",
11
+ "homepage": "https://github.com/algolia/n8n-nodes-algolia",
12
+ "author": {
13
+ "name": "Algolia",
14
+ "email": "support@algolia.com"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/algolia/n8n-nodes-algolia.git"
19
+ },
20
+ "engines": {
21
+ "node": ">=20.15"
22
+ },
23
+ "main": "index.js",
24
+ "scripts": {
25
+ "build": "vite build",
26
+ "dev": "vite build --watch",
27
+ "format": "prettier nodes credentials --write",
28
+ "lint": "eslint nodes credentials package.json",
29
+ "lintfix": "eslint nodes credentials package.json --fix",
30
+ "prepublishOnly": "npm run build && npm run lint -c .eslintrc.prepublish.js nodes credentials package.json",
31
+ "release": "shipjs prepare"
32
+ },
33
+ "files": [
34
+ "dist"
35
+ ],
36
+ "n8n": {
37
+ "n8nNodesApiVersion": 1,
38
+ "credentials": [
39
+ "dist/credentials/AlgoliaApi.credentials.js"
40
+ ],
41
+ "nodes": [
42
+ "dist/nodes/Algolia/Algolia.node.js"
43
+ ]
44
+ },
45
+ "devDependencies": {
46
+ "@typescript-eslint/parser": "~8.32.0",
47
+ "concurrently": "^9.2.0",
48
+ "eslint": "^8.57.0",
49
+ "eslint-plugin-n8n-nodes-base": "^1.16.3",
50
+ "prettier": "^3.5.3",
51
+ "shelljs": "^0.10.0",
52
+ "shipjs": "^0.27.0",
53
+ "tsc-alias": "^1.8.16",
54
+ "typescript": "^5.8.2",
55
+ "vite": "^7.0.6",
56
+ "vite-plugin-static-copy": "^3.1.1"
57
+ },
58
+ "peerDependencies": {
59
+ "n8n-workflow": "*"
60
+ }
61
+ }