@warleon/n8n-nodes-payload-cms 1.4.6 → 1.5.1

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.
@@ -1,19 +1,30 @@
1
1
  import { IExecuteFunctions, ILoadOptionsFunctions, INodeExecutionData, INodePropertyOptions, INodeType, INodeTypeDescription } from "n8n-workflow";
2
2
  import { AxiosRequestConfig } from "axios";
3
3
  import { SanitizedCollectionConfig, SanitizedGlobalConfig } from "./payload.types";
4
+ interface PayloadDiscoveryResponse {
5
+ collections: SanitizedCollectionConfig[];
6
+ globals: SanitizedGlobalConfig[];
7
+ endpoints: {
8
+ path: string;
9
+ method: "connect" | "delete" | "get" | "head" | "options" | "patch" | "post" | "put";
10
+ }[];
11
+ }
4
12
  export declare class PayloadCms implements INodeType {
5
13
  private static collectionsCache;
6
14
  private static globalsCache;
15
+ private static endpointsCache;
7
16
  description: INodeTypeDescription;
8
17
  methods: {
9
18
  loadOptions: {
10
19
  getCollections(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
11
20
  getGlobals(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
12
- getPayloadFields(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
21
+ getEndpoints(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
13
22
  };
14
23
  };
15
24
  discoverCollections(this: ILoadOptionsFunctions): Promise<SanitizedCollectionConfig[]>;
16
25
  discoverGlobals(this: ILoadOptionsFunctions): Promise<SanitizedGlobalConfig[]>;
26
+ discoverEndpoints(this: ILoadOptionsFunctions): Promise<PayloadDiscoveryResponse["endpoints"]>;
17
27
  makeAuthenticatedRequest(this: IExecuteFunctions | ILoadOptionsFunctions, config: AxiosRequestConfig): Promise<any>;
18
28
  execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
19
29
  }
30
+ export {};
@@ -41,10 +41,10 @@ const n8n_workflow_1 = require("n8n-workflow");
41
41
  const axios_1 = __importStar(require("axios"));
42
42
  const form_data_1 = __importDefault(require("form-data"));
43
43
  const qs_esm_1 = require("qs-esm");
44
- const utils_1 = require("./utils");
45
44
  class PayloadCms {
46
45
  static collectionsCache = new Map();
47
46
  static globalsCache = new Map();
47
+ static endpointsCache = new Map();
48
48
  description = {
49
49
  displayName: "Payload CMS",
50
50
  name: "payloadCms",
@@ -81,6 +81,10 @@ class PayloadCms {
81
81
  name: "Global",
82
82
  value: "global",
83
83
  },
84
+ {
85
+ name: "Endpoint",
86
+ value: "endpoint",
87
+ },
84
88
  ],
85
89
  },
86
90
  // Collection operations
@@ -197,6 +201,58 @@ class PayloadCms {
197
201
  },
198
202
  ],
199
203
  },
204
+ // Endpoints operations
205
+ {
206
+ displayName: "Endpoint",
207
+ name: "endpoint",
208
+ type: "options",
209
+ typeOptions: {
210
+ loadOptionsMethod: "getEndpoints",
211
+ },
212
+ required: true,
213
+ default: "",
214
+ displayOptions: {
215
+ show: {
216
+ resource: ["endpoint"],
217
+ },
218
+ },
219
+ description: "Choose the endpoint to operate on",
220
+ },
221
+ {
222
+ displayName: "Operation",
223
+ name: "operation",
224
+ type: "options",
225
+ noDataExpression: true,
226
+ required: true,
227
+ default: "get",
228
+ displayOptions: {
229
+ show: {
230
+ resource: ["endpoint"],
231
+ },
232
+ },
233
+ options: [
234
+ {
235
+ name: "Get",
236
+ value: "get",
237
+ description: "Get request",
238
+ },
239
+ {
240
+ name: "Post",
241
+ value: "post",
242
+ description: "Post request",
243
+ },
244
+ {
245
+ name: "Put",
246
+ value: "put",
247
+ description: "Put request",
248
+ },
249
+ {
250
+ name: "Delete",
251
+ value: "delete",
252
+ description: "delete request",
253
+ },
254
+ ],
255
+ },
200
256
  // ID field for operations that need it
201
257
  {
202
258
  displayName: "Document ID",
@@ -241,6 +297,20 @@ class PayloadCms {
241
297
  },
242
298
  description: "The data to send (JSON format)",
243
299
  },
300
+ {
301
+ displayName: "Data",
302
+ name: "data",
303
+ type: "json",
304
+ required: true,
305
+ default: "{}",
306
+ displayOptions: {
307
+ show: {
308
+ resource: ["endpoint"],
309
+ operation: ["post", "put", "delete"],
310
+ },
311
+ },
312
+ description: "The data to send (JSON format)",
313
+ },
244
314
  // Query parameters
245
315
  {
246
316
  displayName: "Additional Options",
@@ -305,6 +375,13 @@ class PayloadCms {
305
375
  default: "data",
306
376
  description: "Name of the binary property that contains the file to upload",
307
377
  },
378
+ {
379
+ displayName: "Query Parameters",
380
+ name: "query",
381
+ type: "json",
382
+ default: "{}",
383
+ description: "Query parameters to add to the request url",
384
+ },
308
385
  ],
309
386
  },
310
387
  ],
@@ -337,31 +414,17 @@ class PayloadCms {
337
414
  throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to load globals: ${error instanceof Error ? error.message : "Unknown error"}`);
338
415
  }
339
416
  },
340
- async getPayloadFields() {
341
- const resource = this.getCurrentNodeParameter("resource");
342
- switch (resource) {
343
- case "collection":
344
- const collectionSlug = this.getCurrentNodeParameter("collection");
345
- const collection = PayloadCms.collectionsCache
346
- .get(this.getInstanceId())
347
- ?.find((c) => c.slug === collectionSlug);
348
- if (!collection) {
349
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to load fields for collection ${collectionSlug}: collection not found`);
350
- }
351
- return collection.fields.flatMap((f) => (0, utils_1.payloadField2N8nOption)(f));
352
- break;
353
- case "global":
354
- const globalSlug = this.getCurrentNodeParameter("collection");
355
- const global = PayloadCms.globalsCache
356
- .get(this.getInstanceId())
357
- ?.find((g) => g.slug === globalSlug);
358
- if (!global) {
359
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to load fields for global ${globalSlug}: global not found`);
360
- }
361
- return global.fields.flatMap((f) => (0, utils_1.payloadField2N8nOption)(f));
362
- break;
363
- default:
364
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to load fields for resource ${resource}: resource not supported`);
417
+ async getEndpoints() {
418
+ try {
419
+ const endpoints = await PayloadCms.prototype.discoverEndpoints.call(this);
420
+ PayloadCms.endpointsCache.set(this.getInstanceId(), endpoints);
421
+ return endpoints.map((endpoint) => ({
422
+ name: endpoint.path,
423
+ value: endpoint.path,
424
+ }));
425
+ }
426
+ catch (error) {
427
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to load endpoints: ${error instanceof Error ? error.message : "Unknown error"}`);
365
428
  }
366
429
  },
367
430
  },
@@ -400,6 +463,22 @@ class PayloadCms {
400
463
  throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to load globals ensure that ${baseUrl}${reflectionEndpoint} exists. check https://github.com/warleon/n8n-payload-dynamic?tab=readme-ov-file#payload`);
401
464
  }
402
465
  }
466
+ async discoverEndpoints() {
467
+ const credentials = await this.getCredentials("payloadCmsApi");
468
+ const baseUrl = credentials.baseUrl;
469
+ const reflectionEndpoint = credentials.endpoint;
470
+ try {
471
+ // Try to get globals from a potential admin endpoint
472
+ const response = await PayloadCms.prototype.makeAuthenticatedRequest.call(this, {
473
+ method: "GET",
474
+ url: `${baseUrl}${reflectionEndpoint}`,
475
+ });
476
+ return response.data.endpoints;
477
+ }
478
+ catch (error) {
479
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to load endpoints ensure that ${baseUrl}${reflectionEndpoint} exists. check https://github.com/warleon/n8n-payload-dynamic?tab=readme-ov-file#payload`);
480
+ }
481
+ }
403
482
  // Helper method to make authenticated requests
404
483
  async makeAuthenticatedRequest(config) {
405
484
  const credentials = await this.getCredentials("payloadCmsApi");
@@ -441,7 +520,7 @@ class PayloadCms {
441
520
  let url = "";
442
521
  let method = "GET";
443
522
  let data = undefined;
444
- const params = {};
523
+ const params = additionalOptions.query ?? {};
445
524
  // Add query parameters
446
525
  if (additionalOptions.depth !== undefined)
447
526
  params.depth = additionalOptions.depth;
@@ -527,6 +606,13 @@ class PayloadCms {
527
606
  break;
528
607
  }
529
608
  }
609
+ else if (resource === "endpoint") {
610
+ const endpoint = this.getNodeParameter("endpoint", i);
611
+ url = `${baseUrl}${apiPrefix}${endpoint}`;
612
+ method = operation.toUpperCase();
613
+ if (method !== "GET")
614
+ data = this.getNodeParameter("data", i);
615
+ }
530
616
  let requestConfig = {};
531
617
  // handle binary inputs
532
618
  const binaryPropertyName = additionalOptions.upload;
@@ -549,7 +635,7 @@ class PayloadCms {
549
635
  const sanitizeData = { ...metadata, ...data };
550
636
  formData.append("_payload", JSON.stringify(sanitizeData));
551
637
  requestConfig = {
552
- method: method,
638
+ method,
553
639
  maxBodyLength: Infinity,
554
640
  url,
555
641
  params,
@@ -562,7 +648,7 @@ class PayloadCms {
562
648
  }
563
649
  else {
564
650
  requestConfig = {
565
- method: method,
651
+ method,
566
652
  url,
567
653
  params,
568
654
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warleon/n8n-nodes-payload-cms",
3
- "version": "1.4.6",
3
+ "version": "1.5.1",
4
4
  "description": "Dynamic n8n node for Payload CMS that auto-discovers collections and operations forked and extended from https://github.com/leadership-institute/n8n-payload-dynamic",
5
5
  "main": "dist/index.js",
6
6
  "author": "warleon",