n8n-nodes-substack 0.0.2 → 0.1.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.
Files changed (33) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +67 -33
  3. package/dist/nodes/Substack/NoteOperations.d.ts +26 -0
  4. package/dist/nodes/Substack/NoteOperations.js +52 -0
  5. package/dist/nodes/Substack/NoteOperations.js.map +1 -0
  6. package/dist/nodes/Substack/Substack.node.d.ts +2 -1
  7. package/dist/nodes/Substack/Substack.node.js +53 -8
  8. package/dist/nodes/Substack/Substack.node.js.map +1 -1
  9. package/dist/nodes/Substack/SubstackDescription.js +40 -27
  10. package/dist/nodes/Substack/SubstackDescription.js.map +1 -1
  11. package/dist/nodes/Substack/SubstackUtils.d.ts +8 -0
  12. package/dist/nodes/Substack/SubstackUtils.js +21 -0
  13. package/dist/nodes/Substack/SubstackUtils.js.map +1 -0
  14. package/dist/package.json +4 -5
  15. package/dist/tsconfig.tsbuildinfo +1 -1
  16. package/package.json +4 -5
  17. package/dist/credentials/ExampleCredentialsApi.credentials.d.ts +0 -9
  18. package/dist/credentials/ExampleCredentialsApi.credentials.js +0 -47
  19. package/dist/credentials/ExampleCredentialsApi.credentials.js.map +0 -1
  20. package/dist/credentials/HttpBinApi.credentials.d.ts +0 -9
  21. package/dist/credentials/HttpBinApi.credentials.js +0 -43
  22. package/dist/credentials/HttpBinApi.credentials.js.map +0 -1
  23. package/dist/nodes/ExampleNode/ExampleNode.node.d.ts +0 -5
  24. package/dist/nodes/ExampleNode/ExampleNode.node.js +0 -60
  25. package/dist/nodes/ExampleNode/ExampleNode.node.js.map +0 -1
  26. package/dist/nodes/HttpBin/HttpBin.node.d.ts +0 -4
  27. package/dist/nodes/HttpBin/HttpBin.node.js +0 -56
  28. package/dist/nodes/HttpBin/HttpBin.node.js.map +0 -1
  29. package/dist/nodes/HttpBin/HttpBin.node.json +0 -18
  30. package/dist/nodes/HttpBin/HttpVerbDescription.d.ts +0 -3
  31. package/dist/nodes/HttpBin/HttpVerbDescription.js +0 -236
  32. package/dist/nodes/HttpBin/HttpVerbDescription.js.map +0 -1
  33. package/dist/nodes/HttpBin/httpbin.svg +0 -18
package/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2022 n8n
1
+ Copyright 2025 Jakub Slys
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of
4
4
  this software and associated documentation files (the "Software"), to deal in
package/README.md CHANGED
@@ -1,48 +1,82 @@
1
- ![Banner image](https://user-images.githubusercontent.com/10284570/173569848-c624317f-42b1-45a6-ab09-f0ea3c247648.png)
1
+ # n8n-nodes-substack
2
2
 
3
- # n8n-nodes-starter
3
+ [![npm version](https://badge.fury.io/js/n8n-nodes-substack.svg)](https://badge.fury.io/js/n8n-nodes-substack)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
5
 
5
- This repo contains example nodes to help you get started building your own custom integrations for [n8n](https://n8n.io). It includes the node linter and other dependencies.
6
+ This n8n community node allows interaction with the Substack API, enabling you to automate content creation and management workflows directly from n8n.
6
7
 
7
- To make your custom node available to the community, you must create it as an npm package, and [submit it to the npm registry](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry).
8
+ [n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/reference/license/) workflow automation platform.
8
9
 
9
- If you would like your node to be available on n8n cloud you can also [submit your node for verification](https://docs.n8n.io/integrations/creating-nodes/deploy/submit-community-nodes/).
10
+ ## Features
10
11
 
11
- ## Prerequisites
12
+ - **Authenticate with Substack**: Secure API key authentication
13
+ - **Create Notes**: Publish Substack notes programmatically
14
+ - **Future Features** (coming soon):
15
+ - Fetch subscribers and manage mailing lists
16
+ - Create and publish full posts
17
+ - Access publication statistics and analytics
12
18
 
13
- You need the following installed on your development machine:
19
+ ## Quick Start
14
20
 
15
- * [git](https://git-scm.com/downloads)
16
- * Node.js and npm. Minimum version Node 20. You can find instructions on how to install both using nvm (Node Version Manager) for Linux, Mac, and WSL [here](https://github.com/nvm-sh/nvm). For Windows users, refer to Microsoft's guide to [Install NodeJS on Windows](https://docs.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-windows).
17
- * Install n8n with:
18
- ```
19
- npm install n8n -g
20
- ```
21
- * Recommended: follow n8n's guide to [set up your development environment](https://docs.n8n.io/integrations/creating-nodes/build/node-development-environment/).
21
+ Here's a simple workflow that creates a Substack note:
22
22
 
23
- ## Using this starter
23
+ ```json
24
+ {
25
+ "nodes": [
26
+ {
27
+ "name": "Create Substack Note",
28
+ "type": "n8n-nodes-substack.substack",
29
+ "parameters": {
30
+ "resource": "note",
31
+ "operation": "create",
32
+ "title": "Hello from n8n!",
33
+ "body": "This note was created automatically using n8n."
34
+ },
35
+ "credentials": {
36
+ "substackApi": "your-credential-id"
37
+ }
38
+ }
39
+ ]
40
+ }
41
+ ```
24
42
 
25
- These are the basic steps for working with the starter. For detailed guidance on creating and publishing nodes, refer to the [documentation](https://docs.n8n.io/integrations/creating-nodes/).
43
+ ## Installation
26
44
 
27
- 1. [Generate a new repository](https://github.com/n8n-io/n8n-nodes-starter/generate) from this template repository.
28
- 2. Clone your new repo:
29
- ```
30
- git clone https://github.com/<your organization>/<your-repo-name>.git
31
- ```
32
- 3. Run `npm i` to install dependencies.
33
- 4. Open the project in your editor.
34
- 5. Browse the examples in `/nodes` and `/credentials`. Modify the examples, or replace them with your own nodes.
35
- 6. Update the `package.json` to match your details.
36
- 7. Run `npm run lint` to check for errors or `npm run lintfix` to automatically fix errors when possible.
37
- 8. Test your node locally. Refer to [Run your node locally](https://docs.n8n.io/integrations/creating-nodes/test/run-node-locally/) for guidance.
38
- 9. Replace this README with documentation for your node. Use the [README_TEMPLATE](README_TEMPLATE.md) to get started.
39
- 10. Update the LICENSE file to use your details.
40
- 11. [Publish](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry) your package to npm.
45
+ ### n8n Cloud
41
46
 
42
- ## More information
47
+ 1. Go to **Settings** > **Community Nodes**
48
+ 2. Click **Install a community node**
49
+ 3. Enter `n8n-nodes-substack`
50
+ 4. Click **Install**
43
51
 
44
- Refer to our [documentation on creating nodes](https://docs.n8n.io/integrations/creating-nodes/) for detailed information on building your own nodes.
52
+ ### Self-hosted n8n
53
+
54
+ Install the node in your n8n installation directory:
55
+
56
+ ```bash
57
+ npm install n8n-nodes-substack
58
+ ```
59
+
60
+ Then restart your n8n instance.
61
+
62
+ ### Credentials Setup
63
+
64
+ 1. Add the Substack node to your workflow
65
+ 2. Create new credentials with:
66
+ - **Publication Address**: Your Substack domain (e.g., `myblog.substack.com`)
67
+ - **API Key**: Your Substack API key
68
+
69
+ ## Documentation
70
+
71
+ For comprehensive usage instructions, configuration options, and examples:
72
+
73
+ 📖 **[Full Documentation](docs/n8n-usage.md)**
74
+
75
+ Additional resources:
76
+ - [API Reference](docs/api-reference.md)
77
+ - [Examples](docs/examples.md)
78
+ - [Development Guide](docs/development.md)
45
79
 
46
80
  ## License
47
81
 
48
- [MIT](https://github.com/n8n-io/n8n-nodes-starter/blob/master/LICENSE.md)
82
+ [MIT](LICENSE.md)
@@ -0,0 +1,26 @@
1
+ import { IExecuteFunctions } from 'n8n-workflow';
2
+ import { Substack as SubstackClient } from 'substack-api';
3
+ export declare class NoteOperations {
4
+ static create(executeFunctions: IExecuteFunctions, client: SubstackClient, publicationAddress: string, itemIndex: number): Promise<{
5
+ success: boolean;
6
+ title: string;
7
+ noteId: number;
8
+ url: string;
9
+ date: string;
10
+ status: "published";
11
+ userId: number;
12
+ }>;
13
+ static get(executeFunctions: IExecuteFunctions, client: SubstackClient, publicationAddress: string, itemIndex: number): Promise<{
14
+ noteId: number;
15
+ title: string;
16
+ body: string;
17
+ url: string;
18
+ date: string;
19
+ status: string;
20
+ userId: number;
21
+ likes: number;
22
+ restacks: number;
23
+ type: string;
24
+ entityKey: string;
25
+ }[]>;
26
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NoteOperations = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ class NoteOperations {
6
+ static async create(executeFunctions, client, publicationAddress, itemIndex) {
7
+ const title = executeFunctions.getNodeParameter('title', itemIndex);
8
+ const body = executeFunctions.getNodeParameter('body', itemIndex);
9
+ if (!title || !body) {
10
+ throw new n8n_workflow_1.NodeOperationError(executeFunctions.getNode(), 'Title and body are required', { itemIndex });
11
+ }
12
+ const noteContent = title + '\n\n' + body;
13
+ const response = await client.publishNote(noteContent);
14
+ return {
15
+ success: true,
16
+ title: title,
17
+ noteId: response.id,
18
+ url: `https://${publicationAddress}/p/${response.id}`,
19
+ date: response.date,
20
+ status: response.status,
21
+ userId: response.user_id,
22
+ };
23
+ }
24
+ static async get(executeFunctions, client, publicationAddress, itemIndex) {
25
+ const limit = executeFunctions.getNodeParameter('limit', itemIndex, 10);
26
+ const offset = executeFunctions.getNodeParameter('offset', itemIndex, 0);
27
+ const response = await client.getNotes({ limit, offset });
28
+ const notes = response.items || [];
29
+ const formattedNotes = [];
30
+ for (const note of notes) {
31
+ const comment = note.comment;
32
+ if (comment) {
33
+ formattedNotes.push({
34
+ noteId: comment.id,
35
+ title: '',
36
+ body: comment.body || '',
37
+ url: `https://${publicationAddress}/p/${comment.id}`,
38
+ date: comment.date,
39
+ status: 'published',
40
+ userId: comment.user_id,
41
+ likes: comment.reaction_count || 0,
42
+ restacks: comment.restacks || 0,
43
+ type: comment.type,
44
+ entityKey: note.entity_key,
45
+ });
46
+ }
47
+ }
48
+ return formattedNotes;
49
+ }
50
+ }
51
+ exports.NoteOperations = NoteOperations;
52
+ //# sourceMappingURL=NoteOperations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoteOperations.js","sourceRoot":"","sources":["../../../nodes/Substack/NoteOperations.ts"],"names":[],"mappings":";;;AAAA,+CAAqE;AAGrE,MAAa,cAAc;IAC1B,MAAM,CAAC,KAAK,CAAC,MAAM,CAClB,gBAAmC,EACnC,MAAsB,EACtB,kBAA0B,EAC1B,SAAiB;QAGjB,MAAM,KAAK,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAW,CAAC;QAC9E,MAAM,IAAI,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,MAAM,EAAE,SAAS,CAAW,CAAC;QAE5E,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YACrB,MAAM,IAAI,iCAAkB,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE,6BAA6B,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QACxG,CAAC;QAID,MAAM,WAAW,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,CAAC;QAG1C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAGvD,OAAO;YACN,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,QAAQ,CAAC,EAAE;YACnB,GAAG,EAAE,WAAW,kBAAkB,MAAM,QAAQ,CAAC,EAAE,EAAE;YACrD,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,MAAM,EAAE,QAAQ,CAAC,OAAO;SACxB,CAAC;IACH,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,GAAG,CACf,gBAAmC,EACnC,MAAsB,EACtB,kBAA0B,EAC1B,SAAiB;QAGjB,MAAM,KAAK,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,CAAW,CAAC;QAClF,MAAM,MAAM,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAW,CAAC;QAGnF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAG1D,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;QACnC,MAAM,cAAc,GAAG,EAAE,CAAC;QAG1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAE1B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;YAC7B,IAAI,OAAO,EAAE,CAAC;gBACb,cAAc,CAAC,IAAI,CAAC;oBACnB,MAAM,EAAE,OAAO,CAAC,EAAE;oBAClB,KAAK,EAAE,EAAE;oBACT,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;oBACxB,GAAG,EAAE,WAAW,kBAAkB,MAAM,OAAO,CAAC,EAAE,EAAE;oBACpD,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,MAAM,EAAE,WAAW;oBACnB,MAAM,EAAE,OAAO,CAAC,OAAO;oBACvB,KAAK,EAAE,OAAO,CAAC,cAAc,IAAI,CAAC;oBAClC,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC;oBAC/B,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,SAAS,EAAE,IAAI,CAAC,UAAU;iBAC1B,CAAC,CAAC;YACJ,CAAC;QACF,CAAC;QAED,OAAO,cAAc,CAAC;IACvB,CAAC;CACD;AA1ED,wCA0EC"}
@@ -1,4 +1,5 @@
1
- import { INodeType, INodeTypeDescription } from 'n8n-workflow';
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
2
  export declare class Substack implements INodeType {
3
3
  description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
4
5
  }
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Substack = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
4
5
  const SubstackDescription_1 = require("./SubstackDescription");
6
+ const NoteOperations_1 = require("./NoteOperations");
7
+ const SubstackUtils_1 = require("./SubstackUtils");
5
8
  class Substack {
6
9
  constructor() {
7
10
  this.description = {
@@ -24,14 +27,6 @@ class Substack {
24
27
  required: true,
25
28
  },
26
29
  ],
27
- requestDefaults: {
28
- baseURL: '={{$credentials?.publicationAddress ? "https://" + $credentials.publicationAddress : "https://substack.com"}}',
29
- url: '',
30
- headers: {
31
- Accept: 'application/json',
32
- 'Content-Type': 'application/json',
33
- },
34
- },
35
30
  properties: [
36
31
  {
37
32
  displayName: 'Resource',
@@ -51,6 +46,56 @@ class Substack {
51
46
  ],
52
47
  };
53
48
  }
49
+ async execute() {
50
+ const items = this.getInputData();
51
+ const returnData = [];
52
+ for (let i = 0; i < items.length; i++) {
53
+ try {
54
+ const resource = this.getNodeParameter('resource', i);
55
+ const operation = this.getNodeParameter('operation', i);
56
+ const { client, publicationAddress } = await SubstackUtils_1.SubstackUtils.initializeClient(this, i);
57
+ if (resource === 'note') {
58
+ if (operation === 'create') {
59
+ const outputData = await NoteOperations_1.NoteOperations.create(this, client, publicationAddress, i);
60
+ returnData.push({
61
+ json: outputData,
62
+ pairedItem: { item: i },
63
+ });
64
+ }
65
+ else if (operation === 'get') {
66
+ const notes = await NoteOperations_1.NoteOperations.get(this, client, publicationAddress, i);
67
+ for (const note of notes) {
68
+ returnData.push({
69
+ json: note,
70
+ pairedItem: { item: i },
71
+ });
72
+ }
73
+ }
74
+ else {
75
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation: ${operation}`, { itemIndex: i });
76
+ }
77
+ }
78
+ else {
79
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown resource: ${resource}`, { itemIndex: i });
80
+ }
81
+ }
82
+ catch (error) {
83
+ if (this.continueOnFail()) {
84
+ returnData.push({
85
+ json: {
86
+ error: error.message,
87
+ success: false
88
+ },
89
+ pairedItem: { item: i },
90
+ });
91
+ }
92
+ else {
93
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, { itemIndex: i });
94
+ }
95
+ }
96
+ }
97
+ return [returnData];
98
+ }
54
99
  }
55
100
  exports.Substack = Substack;
56
101
  //# sourceMappingURL=Substack.node.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Substack.node.js","sourceRoot":"","sources":["../../../nodes/Substack/Substack.node.ts"],"names":[],"mappings":";;;AACA,+DAAmE;AAEnE,MAAa,QAAQ;IAArB;QACC,gBAAW,GAAyB;YACnC,WAAW,EAAE,UAAU;YACvB,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,mBAAmB,EAAE;YAC/D,KAAK,EAAE,CAAC,QAAQ,CAAC;YACjB,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,8DAA8D;YACxE,WAAW,EAAE,4BAA4B;YACzC,QAAQ,EAAE;gBACT,IAAI,EAAE,UAAU;aAChB;YACD,MAAM,EAAE,QAAyB;YACjC,OAAO,EAAE,QAAyB;YAClC,YAAY,EAAE,IAAI;YAClB,WAAW,EAAE;gBACZ;oBACC,IAAI,EAAE,aAAa;oBACnB,QAAQ,EAAE,IAAI;iBACd;aACD;YACD,eAAe,EAAE;gBAChB,OAAO,EAAE,+GAA+G;gBACxH,GAAG,EAAE,EAAE;gBACP,OAAO,EAAE;oBACR,MAAM,EAAE,kBAAkB;oBAC1B,cAAc,EAAE,kBAAkB;iBAClC;aACD;YACD,UAAU,EAAE;gBACX;oBACC,WAAW,EAAE,UAAU;oBACvB,IAAI,EAAE,UAAU;oBAChB,IAAI,EAAE,SAAS;oBACf,gBAAgB,EAAE,IAAI;oBACtB,OAAO,EAAE;wBACR;4BACC,IAAI,EAAE,MAAM;4BACZ,KAAK,EAAE,MAAM;yBACb;qBACD;oBACD,OAAO,EAAE,MAAM;iBACf;gBAED,GAAG,oCAAc;gBACjB,GAAG,gCAAU;aACb;SACD,CAAC;IACH,CAAC;CAAA;AAhDD,4BAgDC"}
1
+ {"version":3,"file":"Substack.node.js","sourceRoot":"","sources":["../../../nodes/Substack/Substack.node.ts"],"names":[],"mappings":"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"}
@@ -18,22 +18,12 @@ exports.noteOperations = [
18
18
  value: 'create',
19
19
  description: 'Create a new Substack note',
20
20
  action: 'Create a note',
21
- routing: {
22
- request: {
23
- method: 'POST',
24
- url: '/api/v1/notes',
25
- },
26
- output: {
27
- postReceive: [
28
- {
29
- type: 'set',
30
- properties: {
31
- value: '={{ { "title": $response.body.title || $parameter.title, "success": true, "noteId": $response.body.id, "url": $response.body.url } }}',
32
- },
33
- },
34
- ],
35
- },
36
- },
21
+ },
22
+ {
23
+ name: 'Get',
24
+ value: 'get',
25
+ description: 'Retrieve notes from the publication',
26
+ action: 'Get notes',
37
27
  },
38
28
  ],
39
29
  default: 'create',
@@ -53,12 +43,6 @@ const createOperation = [
53
43
  operation: ['create'],
54
44
  },
55
45
  },
56
- routing: {
57
- send: {
58
- property: 'title',
59
- type: 'body',
60
- },
61
- },
62
46
  required: true,
63
47
  },
64
48
  {
@@ -77,16 +61,45 @@ const createOperation = [
77
61
  operation: ['create'],
78
62
  },
79
63
  },
80
- routing: {
81
- send: {
82
- property: 'body',
83
- type: 'body',
64
+ required: true,
65
+ },
66
+ ];
67
+ const getOperation = [
68
+ {
69
+ displayName: 'Limit',
70
+ name: 'limit',
71
+ type: 'number',
72
+ default: 50,
73
+ description: 'Max number of results to return',
74
+ displayOptions: {
75
+ show: {
76
+ resource: ['note'],
77
+ operation: ['get'],
84
78
  },
85
79
  },
86
- required: true,
80
+ typeOptions: {
81
+ minValue: 1,
82
+ },
83
+ },
84
+ {
85
+ displayName: 'Offset',
86
+ name: 'offset',
87
+ type: 'number',
88
+ default: 0,
89
+ description: 'Number of notes to skip',
90
+ displayOptions: {
91
+ show: {
92
+ resource: ['note'],
93
+ operation: ['get'],
94
+ },
95
+ },
96
+ typeOptions: {
97
+ minValue: 0,
98
+ },
87
99
  },
88
100
  ];
89
101
  exports.noteFields = [
90
102
  ...createOperation,
103
+ ...getOperation,
91
104
  ];
92
105
  //# sourceMappingURL=SubstackDescription.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SubstackDescription.js","sourceRoot":"","sources":["../../../nodes/Substack/SubstackDescription.ts"],"names":[],"mappings":";;;AAGa,QAAA,cAAc,GAAsB;IAChD;QACC,WAAW,EAAE,WAAW;QACxB,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,SAAS;QACf,gBAAgB,EAAE,IAAI;QACtB,cAAc,EAAE;YACf,IAAI,EAAE;gBACL,QAAQ,EAAE,CAAC,MAAM,CAAC;aAClB;SACD;QACD,OAAO,EAAE;YACR;gBACC,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,QAAQ;gBACf,WAAW,EAAE,4BAA4B;gBACzC,MAAM,EAAE,eAAe;gBACvB,OAAO,EAAE;oBACR,OAAO,EAAE;wBACR,MAAM,EAAE,MAAM;wBACd,GAAG,EAAE,eAAe;qBACpB;oBACD,MAAM,EAAE;wBACP,WAAW,EAAE;4BACZ;gCACC,IAAI,EAAE,KAAK;gCACX,UAAU,EAAE;oCACX,KAAK,EAAE,uIAAuI;iCAC9I;6BACD;yBACD;qBACD;iBACD;aACD;SACD;QACD,OAAO,EAAE,QAAQ;KACjB;CACD,CAAC;AAGF,MAAM,eAAe,GAAsB;IAC1C;QACC,WAAW,EAAE,OAAO;QACpB,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,EAAE;QACX,WAAW,EAAE,YAAY;QACzB,WAAW,EAAE,0BAA0B;QACvC,cAAc,EAAE;YACf,IAAI,EAAE;gBACL,QAAQ,EAAE,CAAC,MAAM,CAAC;gBAClB,SAAS,EAAE,CAAC,QAAQ,CAAC;aACrB;SACD;QACD,OAAO,EAAE;YACR,IAAI,EAAE;gBACL,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE,MAAM;aACZ;SACD;QACD,QAAQ,EAAE,IAAI;KACd;IACD;QACC,WAAW,EAAE,MAAM;QACnB,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE;YACZ,IAAI,EAAE,CAAC;SACP;QACD,OAAO,EAAE,EAAE;QACX,WAAW,EAAE,iBAAiB;QAC9B,WAAW,EAAE,8CAA8C;QAC3D,cAAc,EAAE;YACf,IAAI,EAAE;gBACL,QAAQ,EAAE,CAAC,MAAM,CAAC;gBAClB,SAAS,EAAE,CAAC,QAAQ,CAAC;aACrB;SACD;QACD,OAAO,EAAE;YACR,IAAI,EAAE;gBACL,QAAQ,EAAE,MAAM;gBAChB,IAAI,EAAE,MAAM;aACZ;SACD;QACD,QAAQ,EAAE,IAAI;KACd;CACD,CAAC;AAEW,QAAA,UAAU,GAAsB;IAI5C,GAAG,eAAe;CAClB,CAAC"}
1
+ {"version":3,"file":"SubstackDescription.js","sourceRoot":"","sources":["../../../nodes/Substack/SubstackDescription.ts"],"names":[],"mappings":";;;AAGa,QAAA,cAAc,GAAsB;IAChD;QACC,WAAW,EAAE,WAAW;QACxB,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,SAAS;QACf,gBAAgB,EAAE,IAAI;QACtB,cAAc,EAAE;YACf,IAAI,EAAE;gBACL,QAAQ,EAAE,CAAC,MAAM,CAAC;aAClB;SACD;QACD,OAAO,EAAE;YACR;gBACC,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,QAAQ;gBACf,WAAW,EAAE,4BAA4B;gBACzC,MAAM,EAAE,eAAe;aACvB;YACD;gBACC,IAAI,EAAE,KAAK;gBACX,KAAK,EAAE,KAAK;gBACZ,WAAW,EAAE,qCAAqC;gBAClD,MAAM,EAAE,WAAW;aACnB;SACD;QACD,OAAO,EAAE,QAAQ;KACjB;CACD,CAAC;AAGF,MAAM,eAAe,GAAsB;IAC1C;QACC,WAAW,EAAE,OAAO;QACpB,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,EAAE;QACX,WAAW,EAAE,YAAY;QACzB,WAAW,EAAE,0BAA0B;QACvC,cAAc,EAAE;YACf,IAAI,EAAE;gBACL,QAAQ,EAAE,CAAC,MAAM,CAAC;gBAClB,SAAS,EAAE,CAAC,QAAQ,CAAC;aACrB;SACD;QACD,QAAQ,EAAE,IAAI;KACd;IACD;QACC,WAAW,EAAE,MAAM;QACnB,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE;YACZ,IAAI,EAAE,CAAC;SACP;QACD,OAAO,EAAE,EAAE;QACX,WAAW,EAAE,iBAAiB;QAC9B,WAAW,EAAE,8CAA8C;QAC3D,cAAc,EAAE;YACf,IAAI,EAAE;gBACL,QAAQ,EAAE,CAAC,MAAM,CAAC;gBAClB,SAAS,EAAE,CAAC,QAAQ,CAAC;aACrB;SACD;QACD,QAAQ,EAAE,IAAI;KACd;CACD,CAAC;AAGF,MAAM,YAAY,GAAsB;IACvC;QACC,WAAW,EAAE,OAAO;QACpB,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,EAAE;QACX,WAAW,EAAE,iCAAiC;QAC9C,cAAc,EAAE;YACf,IAAI,EAAE;gBACL,QAAQ,EAAE,CAAC,MAAM,CAAC;gBAClB,SAAS,EAAE,CAAC,KAAK,CAAC;aAClB;SACD;QACD,WAAW,EAAE;YACZ,QAAQ,EAAE,CAAC;SACX;KACD;IACD;QACC,WAAW,EAAE,QAAQ;QACrB,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,CAAC;QACV,WAAW,EAAE,yBAAyB;QACtC,cAAc,EAAE;YACf,IAAI,EAAE;gBACL,QAAQ,EAAE,CAAC,MAAM,CAAC;gBAClB,SAAS,EAAE,CAAC,KAAK,CAAC;aAClB;SACD;QACD,WAAW,EAAE;YACZ,QAAQ,EAAE,CAAC;SACX;KACD;CACD,CAAC;AAEW,QAAA,UAAU,GAAsB;IAI5C,GAAG,eAAe;IAIlB,GAAG,YAAY;CACf,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { IExecuteFunctions } from 'n8n-workflow';
2
+ import { Substack as SubstackClient } from 'substack-api';
3
+ export declare class SubstackUtils {
4
+ static initializeClient(executeFunctions: IExecuteFunctions, itemIndex: number): Promise<{
5
+ client: SubstackClient;
6
+ publicationAddress: string;
7
+ }>;
8
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SubstackUtils = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const substack_api_1 = require("substack-api");
6
+ class SubstackUtils {
7
+ static async initializeClient(executeFunctions, itemIndex) {
8
+ const credentials = await executeFunctions.getCredentials('substackApi');
9
+ const { publicationAddress, apiKey } = credentials;
10
+ if (!apiKey) {
11
+ throw new n8n_workflow_1.NodeOperationError(executeFunctions.getNode(), 'API key is required', { itemIndex });
12
+ }
13
+ const client = new substack_api_1.Substack({
14
+ hostname: publicationAddress,
15
+ apiKey: apiKey,
16
+ });
17
+ return { client, publicationAddress: publicationAddress };
18
+ }
19
+ }
20
+ exports.SubstackUtils = SubstackUtils;
21
+ //# sourceMappingURL=SubstackUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubstackUtils.js","sourceRoot":"","sources":["../../../nodes/Substack/SubstackUtils.ts"],"names":[],"mappings":";;;AAAA,+CAAqE;AACrE,+CAA0D;AAE1D,MAAa,aAAa;IACzB,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,gBAAmC,EAAE,SAAiB;QAEnF,MAAM,WAAW,GAAG,MAAM,gBAAgB,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QACzE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,GAAG,WAAW,CAAC;QAEnD,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,MAAM,IAAI,iCAAkB,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE,qBAAqB,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAChG,CAAC;QAGD,MAAM,MAAM,GAAG,IAAI,uBAAc,CAAC;YACjC,QAAQ,EAAE,kBAA4B;YACtC,MAAM,EAAE,MAAgB;SACxB,CAAC,CAAC;QAEH,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,kBAA4B,EAAE,CAAC;IACrE,CAAC;CACD;AAlBD,sCAkBC"}
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-substack",
3
- "version": "0.0.2",
3
+ "version": "0.1.0",
4
4
  "description": "n8n community node for Substack API integration",
5
5
  "keywords": [
6
6
  "n8n-community-node-package"
@@ -33,13 +33,9 @@
33
33
  "n8n": {
34
34
  "n8nNodesApiVersion": 1,
35
35
  "credentials": [
36
- "dist/credentials/ExampleCredentialsApi.credentials.js",
37
- "dist/credentials/HttpBinApi.credentials.js",
38
36
  "dist/credentials/SubstackApi.credentials.js"
39
37
  ],
40
38
  "nodes": [
41
- "dist/nodes/ExampleNode/ExampleNode.node.js",
42
- "dist/nodes/HttpBin/HttpBin.node.js",
43
39
  "dist/nodes/Substack/Substack.node.js"
44
40
  ]
45
41
  },
@@ -53,5 +49,8 @@
53
49
  },
54
50
  "peerDependencies": {
55
51
  "n8n-workflow": "*"
52
+ },
53
+ "dependencies": {
54
+ "substack-api": "^0.5.0"
56
55
  }
57
56
  }