n8n-nodes-substack-new 0.0.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.
Files changed (55) hide show
  1. package/LICENSE.md +19 -0
  2. package/README.md +139 -0
  3. package/dist/credentials/SubstackGatewayApi.credentials.d.ts +9 -0
  4. package/dist/credentials/SubstackGatewayApi.credentials.js +61 -0
  5. package/dist/credentials/SubstackGatewayApi.credentials.js.map +1 -0
  6. package/dist/nodes/SubstackGateway/Comment.fields.d.ts +2 -0
  7. package/dist/nodes/SubstackGateway/Comment.fields.js +36 -0
  8. package/dist/nodes/SubstackGateway/Comment.fields.js.map +1 -0
  9. package/dist/nodes/SubstackGateway/Comment.operations.d.ts +8 -0
  10. package/dist/nodes/SubstackGateway/Comment.operations.js +44 -0
  11. package/dist/nodes/SubstackGateway/Comment.operations.js.map +1 -0
  12. package/dist/nodes/SubstackGateway/Note.fields.d.ts +2 -0
  13. package/dist/nodes/SubstackGateway/Note.fields.js +150 -0
  14. package/dist/nodes/SubstackGateway/Note.fields.js.map +1 -0
  15. package/dist/nodes/SubstackGateway/Note.operations.d.ts +11 -0
  16. package/dist/nodes/SubstackGateway/Note.operations.js +109 -0
  17. package/dist/nodes/SubstackGateway/Note.operations.js.map +1 -0
  18. package/dist/nodes/SubstackGateway/Post.fields.d.ts +2 -0
  19. package/dist/nodes/SubstackGateway/Post.fields.js +66 -0
  20. package/dist/nodes/SubstackGateway/Post.fields.js.map +1 -0
  21. package/dist/nodes/SubstackGateway/Post.operations.d.ts +10 -0
  22. package/dist/nodes/SubstackGateway/Post.operations.js +74 -0
  23. package/dist/nodes/SubstackGateway/Post.operations.js.map +1 -0
  24. package/dist/nodes/SubstackGateway/Profile.fields.d.ts +2 -0
  25. package/dist/nodes/SubstackGateway/Profile.fields.js +61 -0
  26. package/dist/nodes/SubstackGateway/Profile.fields.js.map +1 -0
  27. package/dist/nodes/SubstackGateway/Profile.operations.d.ts +10 -0
  28. package/dist/nodes/SubstackGateway/Profile.operations.js +72 -0
  29. package/dist/nodes/SubstackGateway/Profile.operations.js.map +1 -0
  30. package/dist/nodes/SubstackGateway/Substack.node.d.ts +11 -0
  31. package/dist/nodes/SubstackGateway/Substack.node.js +148 -0
  32. package/dist/nodes/SubstackGateway/Substack.node.js.map +1 -0
  33. package/dist/nodes/SubstackGateway/Substack.node.json +22 -0
  34. package/dist/nodes/SubstackGateway/SubstackUtils.d.ts +12 -0
  35. package/dist/nodes/SubstackGateway/SubstackUtils.js +59 -0
  36. package/dist/nodes/SubstackGateway/SubstackUtils.js.map +1 -0
  37. package/dist/nodes/SubstackGateway/shared/DataFormatters.d.ts +9 -0
  38. package/dist/nodes/SubstackGateway/shared/DataFormatters.js +73 -0
  39. package/dist/nodes/SubstackGateway/shared/DataFormatters.js.map +1 -0
  40. package/dist/nodes/SubstackGateway/shared/OperationHandler.d.ts +11 -0
  41. package/dist/nodes/SubstackGateway/shared/OperationHandler.js +44 -0
  42. package/dist/nodes/SubstackGateway/shared/OperationHandler.js.map +1 -0
  43. package/dist/nodes/SubstackGateway/shared/OperationUtils.d.ts +5 -0
  44. package/dist/nodes/SubstackGateway/shared/OperationUtils.js +35 -0
  45. package/dist/nodes/SubstackGateway/shared/OperationUtils.js.map +1 -0
  46. package/dist/nodes/SubstackGateway/shared/SubstackGatewayClient.d.ts +69 -0
  47. package/dist/nodes/SubstackGateway/shared/SubstackGatewayClient.js +222 -0
  48. package/dist/nodes/SubstackGateway/shared/SubstackGatewayClient.js.map +1 -0
  49. package/dist/nodes/SubstackGateway/substack.svg +7 -0
  50. package/dist/nodes/SubstackGateway/types.d.ts +51 -0
  51. package/dist/nodes/SubstackGateway/types.js +3 -0
  52. package/dist/nodes/SubstackGateway/types.js.map +1 -0
  53. package/dist/package.json +67 -0
  54. package/dist/tsconfig.tsbuildinfo +1 -0
  55. package/package.json +66 -0
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataFormatters = void 0;
4
+ const SubstackUtils_1 = require("../SubstackUtils");
5
+ class DataFormatters {
6
+ static formatNote(note, publicationAddress) {
7
+ var _a, _b, _c;
8
+ return {
9
+ noteId: ((_a = note.id) === null || _a === void 0 ? void 0 : _a.toString()) || 'unknown',
10
+ body: note.body || '',
11
+ url: SubstackUtils_1.SubstackUtils.formatUrl(publicationAddress, `/p/${note.id || 'unknown'}`),
12
+ date: DataFormatters.formatDate(note.publishedAt || new Date()),
13
+ status: 'published',
14
+ userId: ((_c = (_b = note.author) === null || _b === void 0 ? void 0 : _b.id) === null || _c === void 0 ? void 0 : _c.toString()) || 'unknown',
15
+ likes: note.likesCount || 0,
16
+ type: 'note',
17
+ };
18
+ }
19
+ static formatPost(post, publicationAddress) {
20
+ return {
21
+ id: post.id,
22
+ title: post.title || '',
23
+ subtitle: post.subtitle || '',
24
+ slug: post.slug,
25
+ url: post.url || SubstackUtils_1.SubstackUtils.formatUrl(publicationAddress, `/p/${post.slug || post.id}`),
26
+ postDate: DataFormatters.formatDate(post.publishedAt || new Date()),
27
+ description: post.truncatedBody || post.body || '',
28
+ htmlBody: post.htmlBody || '',
29
+ markdown: post.markdown || '',
30
+ };
31
+ }
32
+ static formatComment(comment, parentPostId) {
33
+ return {
34
+ id: comment.id,
35
+ body: comment.body,
36
+ isAdmin: comment.isAdmin || false,
37
+ parentPostId: parentPostId || 0,
38
+ };
39
+ }
40
+ static formatProfile(profile) {
41
+ return {
42
+ id: profile.id,
43
+ name: profile.name,
44
+ handle: profile.handle || profile.slug,
45
+ bio: profile.bio,
46
+ url: profile.url,
47
+ avatarUrl: profile.avatarUrl,
48
+ };
49
+ }
50
+ static formatFollowing(followee, returnType) {
51
+ if (returnType === 'ids') {
52
+ return {
53
+ id: followee.id,
54
+ };
55
+ }
56
+ return {
57
+ id: followee.id,
58
+ name: followee.name,
59
+ handle: followee.handle || followee.slug,
60
+ bio: followee.bio,
61
+ url: followee.url,
62
+ avatarUrl: followee.avatarUrl,
63
+ };
64
+ }
65
+ static formatDate(date) {
66
+ if (date && !isNaN(new Date(date).getTime())) {
67
+ return new Date(date).toISOString();
68
+ }
69
+ return new Date().toISOString();
70
+ }
71
+ }
72
+ exports.DataFormatters = DataFormatters;
73
+ //# sourceMappingURL=DataFormatters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataFormatters.js","sourceRoot":"","sources":["../../../../nodes/SubstackGateway/shared/DataFormatters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { IExecuteFunctions } from 'n8n-workflow';
2
+ import { SubstackClient } from './SubstackGatewayClient';
3
+ import { IStandardResponse } from '../types';
4
+ export type OperationExecutor<T> = () => Promise<T>;
5
+ export declare class OperationHandler {
6
+ static execute<T>(executeFunctions: IExecuteFunctions, itemIndex: number, executor: OperationExecutor<T>): Promise<IStandardResponse>;
7
+ static success<T>(data: T): IStandardResponse;
8
+ static getLimit(executeFunctions: IExecuteFunctions, itemIndex: number): number;
9
+ static resolveProfile(client: SubstackClient, slug?: string): Promise<any>;
10
+ static collectFromIterable<T, R>(iterable: AsyncIterable<T>, limit: number, formatter: (item: T) => R): Promise<R[]>;
11
+ }
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OperationHandler = void 0;
4
+ const SubstackUtils_1 = require("../SubstackUtils");
5
+ const OperationUtils_1 = require("./OperationUtils");
6
+ class OperationHandler {
7
+ static async execute(executeFunctions, itemIndex, executor) {
8
+ try {
9
+ const data = await executor();
10
+ return this.success(data);
11
+ }
12
+ catch (error) {
13
+ return SubstackUtils_1.SubstackUtils.formatErrorResponse({
14
+ message: error.message,
15
+ node: executeFunctions.getNode(),
16
+ itemIndex,
17
+ });
18
+ }
19
+ }
20
+ static success(data) {
21
+ return {
22
+ success: true,
23
+ data,
24
+ metadata: {
25
+ status: 'success',
26
+ },
27
+ };
28
+ }
29
+ static getLimit(executeFunctions, itemIndex) {
30
+ const limitParam = executeFunctions.getNodeParameter('limit', itemIndex, '');
31
+ return OperationUtils_1.OperationUtils.parseLimit(limitParam);
32
+ }
33
+ static async resolveProfile(client, slug) {
34
+ if (slug) {
35
+ return client.profileForSlug(slug);
36
+ }
37
+ return client.ownProfile();
38
+ }
39
+ static async collectFromIterable(iterable, limit, formatter) {
40
+ return OperationUtils_1.OperationUtils.executeAsyncIterable(iterable, limit, formatter);
41
+ }
42
+ }
43
+ exports.OperationHandler = OperationHandler;
44
+ //# sourceMappingURL=OperationHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OperationHandler.js","sourceRoot":"","sources":["../../../../nodes/SubstackGateway/shared/OperationHandler.ts"],"names":[],"mappings":";;;AAEA,oDAAiD;AAEjD,qDAAkD;AAIlD,MAAa,gBAAgB;IAC5B,MAAM,CAAC,KAAK,CAAC,OAAO,CACnB,gBAAmC,EACnC,SAAiB,EACjB,QAA8B;QAE9B,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,6BAAa,CAAC,mBAAmB,CAAC;gBACxC,OAAO,EAAG,KAAe,CAAC,OAAO;gBACjC,IAAI,EAAE,gBAAgB,CAAC,OAAO,EAAE;gBAChC,SAAS;aACT,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAED,MAAM,CAAC,OAAO,CAAI,IAAO;QACxB,OAAO;YACN,OAAO,EAAE,IAAI;YACb,IAAI;YACJ,QAAQ,EAAE;gBACT,MAAM,EAAE,SAAS;aACjB;SACD,CAAC;IACH,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,gBAAmC,EAAE,SAAiB;QACrE,MAAM,UAAU,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QAC7E,OAAO,+BAAc,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,cAAc,CAC1B,MAAsB,EACtB,IAAa;QAEb,IAAI,IAAI,EAAE,CAAC;YACV,OAAO,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC;QACD,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC;IAC5B,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAC/B,QAA0B,EAC1B,KAAa,EACb,SAAyB;QAEzB,OAAO,+BAAc,CAAC,oBAAoB,CAAC,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IACxE,CAAC;CACD;AAlDD,4CAkDC"}
@@ -0,0 +1,5 @@
1
+ export declare class OperationUtils {
2
+ static executeAsyncIterable<T, R>(iterable: AsyncIterable<T>, limit: number, formatter: (item: T, ...args: any[]) => R, ...formatterArgs: any[]): Promise<R[]>;
3
+ static parseLimit(limitParam: any): number;
4
+ static parseNumericParam(param: any, paramName: string): number;
5
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OperationUtils = void 0;
4
+ class OperationUtils {
5
+ static async executeAsyncIterable(iterable, limit, formatter, ...formatterArgs) {
6
+ const results = [];
7
+ let count = 0;
8
+ for await (const item of iterable) {
9
+ if (count >= limit)
10
+ break;
11
+ try {
12
+ results.push(formatter(item, ...formatterArgs));
13
+ }
14
+ catch (error) {
15
+ }
16
+ count++;
17
+ }
18
+ return results;
19
+ }
20
+ static parseLimit(limitParam) {
21
+ if (limitParam !== '' && limitParam !== null && limitParam !== undefined) {
22
+ return Number(limitParam);
23
+ }
24
+ return 100;
25
+ }
26
+ static parseNumericParam(param, paramName) {
27
+ const numericValue = typeof param === 'string' ? parseInt(param, 10) : param;
28
+ if (!numericValue || isNaN(numericValue)) {
29
+ throw new Error(`Invalid ${paramName}: must be a valid number`);
30
+ }
31
+ return numericValue;
32
+ }
33
+ }
34
+ exports.OperationUtils = OperationUtils;
35
+ //# sourceMappingURL=OperationUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OperationUtils.js","sourceRoot":"","sources":["../../../../nodes/SubstackGateway/shared/OperationUtils.ts"],"names":[],"mappings":";;;AAAA,MAAa,cAAc;IAI1B,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAChC,QAA0B,EAC1B,KAAa,EACb,SAAyC,EACzC,GAAG,aAAoB;QAEvB,MAAM,OAAO,GAAQ,EAAE,CAAC;QACxB,IAAI,KAAK,GAAG,CAAC,CAAC;QAEd,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YACnC,IAAI,KAAK,IAAI,KAAK;gBAAE,MAAM;YAE1B,IAAI,CAAC;gBACJ,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,aAAa,CAAC,CAAC,CAAC;YACjD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;YAEjB,CAAC;YACD,KAAK,EAAE,CAAC;QACT,CAAC;QAED,OAAO,OAAO,CAAC;IAChB,CAAC;IAKD,MAAM,CAAC,UAAU,CAAC,UAAe;QAChC,IAAI,UAAU,KAAK,EAAE,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC1E,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,GAAG,CAAC;IACZ,CAAC;IAKD,MAAM,CAAC,iBAAiB,CAAC,KAAU,EAAE,SAAiB;QACrD,MAAM,YAAY,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAE7E,IAAI,CAAC,YAAY,IAAI,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,WAAW,SAAS,0BAA0B,CAAC,CAAC;QACjE,CAAC;QAED,OAAO,YAAY,CAAC;IACrB,CAAC;CACD;AAjDD,wCAiDC"}
@@ -0,0 +1,69 @@
1
+ export interface SubstackClientConfig {
2
+ publicationUrl: string;
3
+ token: string;
4
+ gatewayUrl?: string;
5
+ perPage?: number;
6
+ maxRequestsPerSecond?: number;
7
+ }
8
+ export interface SubstackProfileSummary {
9
+ id: number;
10
+ name: string;
11
+ handle: string;
12
+ slug: string;
13
+ url: string;
14
+ bio?: string;
15
+ avatarUrl?: string;
16
+ }
17
+ export interface SubstackProfile extends SubstackProfileSummary {
18
+ posts(): AsyncIterable<SubstackPostSummary>;
19
+ notes(): AsyncIterable<SubstackNote>;
20
+ }
21
+ export interface SubstackOwnProfile extends SubstackProfile {
22
+ following(): AsyncIterable<SubstackProfileSummary>;
23
+ publishNote(content: string, options?: {
24
+ attachment?: string;
25
+ }): Promise<SubstackPublishNoteResponse>;
26
+ }
27
+ export interface SubstackPostSummary {
28
+ id: number;
29
+ title: string;
30
+ subtitle: string;
31
+ slug?: string;
32
+ url?: string;
33
+ truncatedBody: string;
34
+ htmlBody: string;
35
+ markdown: string;
36
+ publishedAt: string;
37
+ }
38
+ export interface SubstackPost extends SubstackPostSummary {
39
+ comments(): AsyncIterable<SubstackComment>;
40
+ }
41
+ export interface SubstackNote {
42
+ id: number;
43
+ body: string;
44
+ likesCount: number;
45
+ publishedAt: string;
46
+ author: {
47
+ id: number;
48
+ name: string;
49
+ handle: string;
50
+ avatarUrl?: string;
51
+ };
52
+ }
53
+ export interface SubstackComment {
54
+ id: number;
55
+ body: string;
56
+ isAdmin: boolean;
57
+ }
58
+ export interface SubstackPublishNoteResponse {
59
+ id: number;
60
+ }
61
+ export declare class SubstackClient {
62
+ private readonly httpClient;
63
+ private readonly perPage;
64
+ constructor(config: SubstackClientConfig);
65
+ ownProfile(): Promise<SubstackOwnProfile>;
66
+ profileForSlug(slug: string): Promise<SubstackProfile>;
67
+ postForId(id: number): Promise<SubstackPost>;
68
+ noteForId(id: number): Promise<SubstackNote>;
69
+ }
@@ -0,0 +1,222 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SubstackClient = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const axios_rate_limit_1 = __importDefault(require("axios-rate-limit"));
9
+ class GatewayHttpClient {
10
+ constructor(config) {
11
+ var _a, _b;
12
+ const gatewayBase = ((_a = config.gatewayUrl) !== null && _a !== void 0 ? _a : 'https://substack-gateway.vercel.app').replace(/\/$/, '');
13
+ const baseUrl = `${gatewayBase}/api/v1`;
14
+ const maxRequestsPerSecond = (_b = config.maxRequestsPerSecond) !== null && _b !== void 0 ? _b : 25;
15
+ const axiosClient = axios_1.default.create({
16
+ baseURL: baseUrl,
17
+ headers: {
18
+ Authorization: `Bearer ${config.token}`,
19
+ 'x-publication-url': config.publicationUrl,
20
+ Accept: 'application/json',
21
+ 'Content-Type': 'application/json',
22
+ },
23
+ });
24
+ this.client = (0, axios_rate_limit_1.default)(axiosClient, {
25
+ maxRequests: maxRequestsPerSecond,
26
+ perMilliseconds: 1000,
27
+ });
28
+ }
29
+ async get(path, params) {
30
+ const response = await this.client.get(path, { params });
31
+ return response.data;
32
+ }
33
+ async post(path, payload) {
34
+ const response = await this.client.post(path, payload);
35
+ return response.data;
36
+ }
37
+ }
38
+ class GatewayProfileContext {
39
+ constructor(httpClient, perPage, rawData) {
40
+ this.httpClient = httpClient;
41
+ this.perPage = perPage;
42
+ this.id = rawData.id;
43
+ this.name = rawData.name;
44
+ this.handle = rawData.handle;
45
+ this.slug = rawData.handle;
46
+ this.url = rawData.url;
47
+ this.bio = rawData.bio;
48
+ this.avatarUrl = rawData.avatar_url;
49
+ }
50
+ async *posts() {
51
+ var _a, _b, _c, _d, _e;
52
+ let offset = 0;
53
+ while (true) {
54
+ const response = await this.httpClient.get(`/profiles/${encodeURIComponent(this.slug)}/posts`, { limit: this.perPage, offset });
55
+ const items = (_a = response.items) !== null && _a !== void 0 ? _a : [];
56
+ if (items.length === 0)
57
+ break;
58
+ for (const item of items) {
59
+ yield {
60
+ id: item.id,
61
+ title: item.title,
62
+ subtitle: (_b = item.subtitle) !== null && _b !== void 0 ? _b : '',
63
+ slug: item.slug,
64
+ url: item.url,
65
+ truncatedBody: (_c = item.truncated_body) !== null && _c !== void 0 ? _c : '',
66
+ htmlBody: (_d = item.html_body) !== null && _d !== void 0 ? _d : '',
67
+ markdown: (_e = item.markdown) !== null && _e !== void 0 ? _e : '',
68
+ publishedAt: item.published_at,
69
+ };
70
+ }
71
+ if (items.length < this.perPage)
72
+ break;
73
+ offset += this.perPage;
74
+ }
75
+ }
76
+ async *notes() {
77
+ var _a, _b, _c, _d, _e, _f;
78
+ let cursor = undefined;
79
+ while (true) {
80
+ const response = await this.httpClient.get(`/profiles/${encodeURIComponent(this.slug)}/notes`, { cursor });
81
+ const items = (_a = response.items) !== null && _a !== void 0 ? _a : [];
82
+ for (const item of items) {
83
+ yield {
84
+ id: item.id,
85
+ body: item.body,
86
+ likesCount: (_b = item.likes_count) !== null && _b !== void 0 ? _b : 0,
87
+ publishedAt: item.published_at,
88
+ author: {
89
+ id: (_c = item.author) === null || _c === void 0 ? void 0 : _c.id,
90
+ name: (_d = item.author) === null || _d === void 0 ? void 0 : _d.name,
91
+ handle: (_e = item.author) === null || _e === void 0 ? void 0 : _e.handle,
92
+ avatarUrl: (_f = item.author) === null || _f === void 0 ? void 0 : _f.avatar_url,
93
+ },
94
+ };
95
+ }
96
+ if (!response.next_cursor)
97
+ break;
98
+ cursor = response.next_cursor;
99
+ }
100
+ }
101
+ }
102
+ class GatewayOwnProfileContext extends GatewayProfileContext {
103
+ async *notes() {
104
+ var _a, _b, _c, _d, _e, _f;
105
+ let cursor = undefined;
106
+ while (true) {
107
+ const response = await this.httpClient.get('/me/notes', { cursor });
108
+ const items = (_a = response.items) !== null && _a !== void 0 ? _a : [];
109
+ for (const item of items) {
110
+ yield {
111
+ id: item.id,
112
+ body: item.body,
113
+ likesCount: (_b = item.likes_count) !== null && _b !== void 0 ? _b : 0,
114
+ publishedAt: item.published_at,
115
+ author: {
116
+ id: (_c = item.author) === null || _c === void 0 ? void 0 : _c.id,
117
+ name: (_d = item.author) === null || _d === void 0 ? void 0 : _d.name,
118
+ handle: (_e = item.author) === null || _e === void 0 ? void 0 : _e.handle,
119
+ avatarUrl: (_f = item.author) === null || _f === void 0 ? void 0 : _f.avatar_url,
120
+ },
121
+ };
122
+ }
123
+ if (!response.next_cursor)
124
+ break;
125
+ cursor = response.next_cursor;
126
+ }
127
+ }
128
+ async *following() {
129
+ var _a;
130
+ const following = await this.httpClient.get('/me/following');
131
+ for (const user of (_a = following.items) !== null && _a !== void 0 ? _a : []) {
132
+ try {
133
+ const profile = await this.httpClient.get(`/profiles/${encodeURIComponent(user.handle)}`);
134
+ yield {
135
+ id: profile.id,
136
+ name: profile.name,
137
+ handle: profile.handle,
138
+ slug: profile.handle,
139
+ url: profile.url,
140
+ bio: profile.bio,
141
+ avatarUrl: profile.avatar_url,
142
+ };
143
+ }
144
+ catch {
145
+ }
146
+ }
147
+ }
148
+ async publishNote(content, options) {
149
+ const payload = { content };
150
+ if (options === null || options === void 0 ? void 0 : options.attachment) {
151
+ payload.attachment = options.attachment;
152
+ }
153
+ const response = await this.httpClient.post('/notes', payload);
154
+ return { id: response.id };
155
+ }
156
+ }
157
+ class GatewayPostContext {
158
+ constructor(httpClient, rawData) {
159
+ var _a, _b, _c, _d;
160
+ this.httpClient = httpClient;
161
+ this.id = rawData.id;
162
+ this.title = rawData.title;
163
+ this.subtitle = (_a = rawData.subtitle) !== null && _a !== void 0 ? _a : '';
164
+ this.slug = rawData.slug;
165
+ this.url = rawData.url;
166
+ this.truncatedBody = (_b = rawData.truncated_body) !== null && _b !== void 0 ? _b : '';
167
+ this.htmlBody = (_c = rawData.html_body) !== null && _c !== void 0 ? _c : '';
168
+ this.markdown = (_d = rawData.markdown) !== null && _d !== void 0 ? _d : '';
169
+ this.publishedAt = rawData.published_at;
170
+ }
171
+ async *comments() {
172
+ var _a, _b;
173
+ const response = await this.httpClient.get(`/posts/${this.id}/comments`);
174
+ for (const item of (_a = response.items) !== null && _a !== void 0 ? _a : []) {
175
+ yield {
176
+ id: item.id,
177
+ body: item.body,
178
+ isAdmin: (_b = item.is_admin) !== null && _b !== void 0 ? _b : false,
179
+ };
180
+ }
181
+ }
182
+ }
183
+ class SubstackClient {
184
+ constructor(config) {
185
+ var _a;
186
+ this.httpClient = new GatewayHttpClient(config);
187
+ this.perPage = (_a = config.perPage) !== null && _a !== void 0 ? _a : 25;
188
+ }
189
+ async ownProfile() {
190
+ const profile = await this.httpClient.get('/me');
191
+ return new GatewayOwnProfileContext(this.httpClient, this.perPage, profile);
192
+ }
193
+ async profileForSlug(slug) {
194
+ if (!slug || slug.trim() === '') {
195
+ throw new Error('Profile slug cannot be empty');
196
+ }
197
+ const profile = await this.httpClient.get(`/profiles/${encodeURIComponent(slug)}`);
198
+ return new GatewayProfileContext(this.httpClient, this.perPage, profile);
199
+ }
200
+ async postForId(id) {
201
+ const post = await this.httpClient.get(`/posts/${id}`);
202
+ return new GatewayPostContext(this.httpClient, post);
203
+ }
204
+ async noteForId(id) {
205
+ var _a, _b, _c, _d, _e;
206
+ const note = await this.httpClient.get(`/notes/${id}`);
207
+ return {
208
+ id: note.id,
209
+ body: note.body,
210
+ likesCount: (_a = note.likes_count) !== null && _a !== void 0 ? _a : 0,
211
+ publishedAt: note.published_at,
212
+ author: {
213
+ id: (_b = note.author) === null || _b === void 0 ? void 0 : _b.id,
214
+ name: (_c = note.author) === null || _c === void 0 ? void 0 : _c.name,
215
+ handle: (_d = note.author) === null || _d === void 0 ? void 0 : _d.handle,
216
+ avatarUrl: (_e = note.author) === null || _e === void 0 ? void 0 : _e.avatar_url,
217
+ },
218
+ };
219
+ }
220
+ }
221
+ exports.SubstackClient = SubstackClient;
222
+ //# sourceMappingURL=SubstackGatewayClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubstackGatewayClient.js","sourceRoot":"","sources":["../../../../nodes/SubstackGateway/shared/SubstackGatewayClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="100" height="100">
4
+ <rect width="512" height="128" fill="#FF6719"/>
5
+ <rect y="192" width="512" height="128" fill="#FF6719"/>
6
+ <polygon points="0,384 512,384 256,512" fill="#FF6719"/>
7
+ </svg>
@@ -0,0 +1,51 @@
1
+ import { INode } from 'n8n-workflow';
2
+ export interface IStandardResponse {
3
+ success: boolean;
4
+ data: any;
5
+ error?: string;
6
+ metadata?: {
7
+ url?: string;
8
+ date?: string;
9
+ status?: string;
10
+ };
11
+ }
12
+ export interface ISubstackNote {
13
+ noteId: string;
14
+ body: string;
15
+ url: string;
16
+ date: string;
17
+ status: string;
18
+ userId: string;
19
+ likes?: number;
20
+ type?: string;
21
+ }
22
+ export interface ISubstackPost {
23
+ id: number;
24
+ title: string;
25
+ subtitle?: string;
26
+ slug?: string;
27
+ url: string;
28
+ postDate: string;
29
+ description?: string;
30
+ htmlBody?: string;
31
+ markdown?: string;
32
+ }
33
+ export interface ISubstackComment {
34
+ id: number;
35
+ body: string;
36
+ isAdmin?: boolean;
37
+ parentPostId: number;
38
+ }
39
+ export interface ISubstackFollowing {
40
+ id: number;
41
+ name?: string;
42
+ handle?: string;
43
+ bio?: string;
44
+ url?: string;
45
+ avatarUrl?: string;
46
+ }
47
+ export interface IErrorResponse {
48
+ message: string;
49
+ node: INode;
50
+ itemIndex: number;
51
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../nodes/SubstackGateway/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "n8n-nodes-substack-new",
3
+ "version": "0.0.1",
4
+ "description": "n8n community node for Substack API integration",
5
+ "keywords": [
6
+ "n8n-community-node-package"
7
+ ],
8
+ "license": "MIT",
9
+ "homepage": "",
10
+ "author": {
11
+ "name": "Jakub Slys",
12
+ "email": "jakub@slys.dev"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/jakub-k-slys/n8n-nodes-substack-new.git"
17
+ },
18
+ "engines": {
19
+ "node": ">=20.15"
20
+ },
21
+ "main": "dist/index.js",
22
+ "types": "dist/index.d.ts",
23
+ "scripts": {
24
+ "build": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\" && tsc && gulp build:icons",
25
+ "dev": "tsc --watch",
26
+ "format": "prettier nodes credentials --write",
27
+ "lint": "eslint nodes credentials package.json",
28
+ "lintfix": "eslint nodes credentials package.json --fix",
29
+ "prepublishOnly": "pnpm run build && eslint -c eslint.prepublish.config.js nodes credentials package.json",
30
+ "test": "jest",
31
+ "test:watch": "jest --watch",
32
+ "test:unit": "jest",
33
+ "test:unit:watch": "jest --watch"
34
+ },
35
+ "files": [
36
+ "dist"
37
+ ],
38
+ "n8n": {
39
+ "n8nNodesApiVersion": 1,
40
+ "credentials": [
41
+ "dist/credentials/SubstackGatewayApi.credentials.js"
42
+ ],
43
+ "nodes": [
44
+ "dist/nodes/SubstackGateway/Substack.node.js"
45
+ ]
46
+ },
47
+ "devDependencies": {
48
+ "@types/jest": "^30.0.0",
49
+ "@typescript-eslint/parser": "~8.57.2",
50
+ "eslint": ">=9.29.0 <10",
51
+ "eslint-plugin-n8n-nodes-base": "^1.16.3",
52
+ "gulp": "^5.0.0",
53
+ "jest": "^30.0.3",
54
+ "prettier": "^3.5.3",
55
+ "ts-jest": "^29.2.5",
56
+ "typescript": "^5.8.2"
57
+ },
58
+ "peerDependencies": {
59
+ "n8n-workflow": "2.13.1"
60
+ },
61
+ "dependencies": {
62
+ "axios": "^1.13.2",
63
+ "axios-rate-limit": "^1.4.0",
64
+ "fp-ts": "^2.16.10",
65
+ "io-ts": "^2.2.22"
66
+ }
67
+ }