runline 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 (230) hide show
  1. package/.pi/extensions/runline-context/index.ts +135 -0
  2. package/.pi/extensions/runline-context/package.json +17 -0
  3. package/README.md +273 -0
  4. package/dist/commands/actions.d.ts +3 -0
  5. package/dist/commands/actions.js +43 -0
  6. package/dist/commands/connection.d.ts +11 -0
  7. package/dist/commands/connection.js +56 -0
  8. package/dist/commands/exec.d.ts +5 -0
  9. package/dist/commands/exec.js +46 -0
  10. package/dist/commands/init.d.ts +4 -0
  11. package/dist/commands/init.js +26 -0
  12. package/dist/commands/plugin.d.ts +10 -0
  13. package/dist/commands/plugin.js +57 -0
  14. package/dist/config/index.d.ts +3 -0
  15. package/dist/config/index.js +2 -0
  16. package/dist/config/loader.d.ts +11 -0
  17. package/dist/config/loader.js +82 -0
  18. package/dist/config/types.d.ts +9 -0
  19. package/dist/config/types.js +5 -0
  20. package/dist/core/engine.d.ts +21 -0
  21. package/dist/core/engine.js +280 -0
  22. package/dist/index.d.ts +16 -0
  23. package/dist/index.js +9 -0
  24. package/dist/main.d.ts +2 -0
  25. package/dist/main.js +127 -0
  26. package/dist/plugin/api.d.ts +32 -0
  27. package/dist/plugin/api.js +68 -0
  28. package/dist/plugin/installer.d.ts +27 -0
  29. package/dist/plugin/installer.js +181 -0
  30. package/dist/plugin/loader.d.ts +13 -0
  31. package/dist/plugin/loader.js +164 -0
  32. package/dist/plugin/registry.d.ts +18 -0
  33. package/dist/plugin/registry.js +43 -0
  34. package/dist/plugin/types.d.ts +40 -0
  35. package/dist/plugin/types.js +1 -0
  36. package/dist/plugins/actionNetwork/src/index.js +353 -0
  37. package/dist/plugins/activeCampaign/src/index.js +711 -0
  38. package/dist/plugins/adalo/src/index.js +131 -0
  39. package/dist/plugins/affinity/src/index.js +279 -0
  40. package/dist/plugins/agileCrm/src/index.js +415 -0
  41. package/dist/plugins/airtable/src/index.js +280 -0
  42. package/dist/plugins/airtop/src/index.js +527 -0
  43. package/dist/plugins/apiTemplateIo/src/index.js +86 -0
  44. package/dist/plugins/asana/src/index.js +413 -0
  45. package/dist/plugins/autopilot/src/index.js +203 -0
  46. package/dist/plugins/bambooHr/src/index.js +252 -0
  47. package/dist/plugins/bannerbear/src/index.js +100 -0
  48. package/dist/plugins/baserow/src/index.js +180 -0
  49. package/dist/plugins/beeminder/src/index.js +298 -0
  50. package/dist/plugins/bitly/src/index.js +107 -0
  51. package/dist/plugins/bitwarden/src/index.js +383 -0
  52. package/dist/plugins/box/src/index.js +300 -0
  53. package/dist/plugins/brandfetch/src/index.js +80 -0
  54. package/dist/plugins/brevo/src/index.js +305 -0
  55. package/dist/plugins/bubble/src/index.js +181 -0
  56. package/dist/plugins/chargebee/src/index.js +126 -0
  57. package/dist/plugins/circleci/src/index.js +111 -0
  58. package/dist/plugins/ciscoWebex/src/index.js +245 -0
  59. package/dist/plugins/clearbit/src/index.js +103 -0
  60. package/dist/plugins/clickup/src/index.js +1043 -0
  61. package/dist/plugins/clockify/src/index.js +443 -0
  62. package/dist/plugins/cloudflare/src/index.js +93 -0
  63. package/dist/plugins/cockpit/src/index.js +131 -0
  64. package/dist/plugins/coda/src/index.js +327 -0
  65. package/dist/plugins/coingecko/src/index.js +244 -0
  66. package/dist/plugins/contentful/src/index.js +146 -0
  67. package/dist/plugins/convertkit/src/index.js +270 -0
  68. package/dist/plugins/copper/src/index.js +140 -0
  69. package/dist/plugins/cortex/src/index.js +147 -0
  70. package/dist/plugins/currents/src/index.js +405 -0
  71. package/dist/plugins/customerIo/src/index.js +184 -0
  72. package/dist/plugins/databricks/src/index.js +342 -0
  73. package/dist/plugins/deepl/src/index.js +87 -0
  74. package/dist/plugins/demio/src/index.js +111 -0
  75. package/dist/plugins/dhl/src/index.js +40 -0
  76. package/dist/plugins/discord/src/index.js +275 -0
  77. package/dist/plugins/discourse/src/index.js +273 -0
  78. package/dist/plugins/disqus/src/index.js +145 -0
  79. package/dist/plugins/docker/src/index.js +76 -0
  80. package/dist/plugins/drift/src/index.js +89 -0
  81. package/dist/plugins/dropbox/src/index.js +159 -0
  82. package/dist/plugins/dropcontact/src/index.js +59 -0
  83. package/dist/plugins/egoi/src/index.js +151 -0
  84. package/dist/plugins/elasticsearch/src/index.js +157 -0
  85. package/dist/plugins/emelia/src/index.js +174 -0
  86. package/dist/plugins/erpnext/src/index.js +121 -0
  87. package/dist/plugins/facebookGraph/src/index.js +57 -0
  88. package/dist/plugins/freshdesk/src/index.js +320 -0
  89. package/dist/plugins/freshservice/src/index.js +146 -0
  90. package/dist/plugins/freshworksCrm/src/index.js +149 -0
  91. package/dist/plugins/getresponse/src/index.js +140 -0
  92. package/dist/plugins/ghost/src/index.js +192 -0
  93. package/dist/plugins/github/src/index.js +630 -0
  94. package/dist/plugins/gitlab/src/index.js +358 -0
  95. package/dist/plugins/gong/src/index.js +126 -0
  96. package/dist/plugins/gotify/src/index.js +77 -0
  97. package/dist/plugins/gotowebinar/src/index.js +316 -0
  98. package/dist/plugins/grafana/src/index.js +250 -0
  99. package/dist/plugins/graphql/src/index.js +78 -0
  100. package/dist/plugins/grist/src/index.js +106 -0
  101. package/dist/plugins/hackernews/src/index.js +89 -0
  102. package/dist/plugins/halopsa/src/index.js +79 -0
  103. package/dist/plugins/harvest/src/index.js +163 -0
  104. package/dist/plugins/helpscout/src/index.js +176 -0
  105. package/dist/plugins/highlevel/src/index.js +172 -0
  106. package/dist/plugins/homeAssistant/src/index.js +148 -0
  107. package/dist/plugins/hubspot/src/index.js +176 -0
  108. package/dist/plugins/humanticAi/src/index.js +60 -0
  109. package/dist/plugins/hunter/src/index.js +59 -0
  110. package/dist/plugins/intercom/src/index.js +156 -0
  111. package/dist/plugins/iterable/src/index.js +139 -0
  112. package/dist/plugins/jenkins/src/index.js +132 -0
  113. package/dist/plugins/jira/src/index.js +229 -0
  114. package/dist/plugins/keap/src/index.js +502 -0
  115. package/dist/plugins/kobotoolbox/src/index.js +281 -0
  116. package/dist/plugins/lemlist/src/index.js +231 -0
  117. package/dist/plugins/linear/src/index.js +133 -0
  118. package/dist/plugins/lingvanex/src/index.js +31 -0
  119. package/dist/plugins/linkedin/src/index.js +80 -0
  120. package/dist/plugins/lonescale/src/index.js +119 -0
  121. package/dist/plugins/magento/src/index.js +300 -0
  122. package/dist/plugins/mailcheck/src/index.js +27 -0
  123. package/dist/plugins/mailchimp/src/index.js +321 -0
  124. package/dist/plugins/mailerlite/src/index.js +123 -0
  125. package/dist/plugins/mailgun/src/index.js +48 -0
  126. package/dist/plugins/mailjet/src/index.js +155 -0
  127. package/dist/plugins/mandrill/src/index.js +145 -0
  128. package/dist/plugins/marketstack/src/index.js +97 -0
  129. package/dist/plugins/matrix/src/index.js +194 -0
  130. package/dist/plugins/mattermost/src/index.js +331 -0
  131. package/dist/plugins/mautic/src/index.js +311 -0
  132. package/dist/plugins/medium/src/index.js +77 -0
  133. package/dist/plugins/messagebird/src/index.js +57 -0
  134. package/dist/plugins/metabase/src/index.js +130 -0
  135. package/dist/plugins/misp/src/index.js +476 -0
  136. package/dist/plugins/mocean/src/index.js +67 -0
  137. package/dist/plugins/monday/src/index.js +231 -0
  138. package/dist/plugins/monicaCrm/src/index.js +52 -0
  139. package/dist/plugins/msg91/src/index.js +31 -0
  140. package/dist/plugins/nasa/src/index.js +146 -0
  141. package/dist/plugins/netlify/src/index.js +151 -0
  142. package/dist/plugins/netscalerAdc/src/index.js +131 -0
  143. package/dist/plugins/nextcloud/src/index.js +263 -0
  144. package/dist/plugins/nocodb/src/index.js +130 -0
  145. package/dist/plugins/notion/src/index.js +112 -0
  146. package/dist/plugins/npm/src/index.js +104 -0
  147. package/dist/plugins/odoo/src/index.js +157 -0
  148. package/dist/plugins/okta/src/index.js +141 -0
  149. package/dist/plugins/oneSimpleApi/src/index.js +155 -0
  150. package/dist/plugins/onfleet/src/index.js +254 -0
  151. package/dist/plugins/openThesaurus/src/index.js +32 -0
  152. package/dist/plugins/openweathermap/src/index.js +60 -0
  153. package/dist/plugins/oura/src/index.js +62 -0
  154. package/dist/plugins/paddle/src/index.js +247 -0
  155. package/dist/plugins/pagerduty/src/index.js +201 -0
  156. package/dist/plugins/paypal/src/index.js +106 -0
  157. package/dist/plugins/peekalink/src/index.js +35 -0
  158. package/dist/plugins/phantombuster/src/index.js +94 -0
  159. package/dist/plugins/philipsHue/src/index.js +98 -0
  160. package/dist/plugins/pipedrive/src/index.js +169 -0
  161. package/dist/plugins/plivo/src/index.js +66 -0
  162. package/dist/plugins/postbin/src/index.js +93 -0
  163. package/dist/plugins/posthog/src/index.js +113 -0
  164. package/dist/plugins/profitwell/src/index.js +50 -0
  165. package/dist/plugins/pushbullet/src/index.js +102 -0
  166. package/dist/plugins/pushcut/src/index.js +39 -0
  167. package/dist/plugins/pushover/src/index.js +65 -0
  168. package/dist/plugins/quickbase/src/index.js +153 -0
  169. package/dist/plugins/quickbooks/src/index.js +73 -0
  170. package/dist/plugins/quickchart/src/index.js +36 -0
  171. package/dist/plugins/raindrop/src/index.js +209 -0
  172. package/dist/plugins/reddit/src/index.js +185 -0
  173. package/dist/plugins/rocketchat/src/index.js +53 -0
  174. package/dist/plugins/rundeck/src/index.js +62 -0
  175. package/dist/plugins/salesforce/src/index.js +94 -0
  176. package/dist/plugins/salesmate/src/index.js +83 -0
  177. package/dist/plugins/securityScorecard/src/index.js +200 -0
  178. package/dist/plugins/segment/src/index.js +125 -0
  179. package/dist/plugins/sendgrid/src/index.js +187 -0
  180. package/dist/plugins/sendy/src/index.js +138 -0
  181. package/dist/plugins/sentry/src/index.js +233 -0
  182. package/dist/plugins/servicenow/src/index.js +108 -0
  183. package/dist/plugins/shopify/src/index.js +222 -0
  184. package/dist/plugins/signl4/src/index.js +61 -0
  185. package/dist/plugins/slack/src/index.js +236 -0
  186. package/dist/plugins/sms77/src/index.js +63 -0
  187. package/dist/plugins/splunk/src/index.js +207 -0
  188. package/dist/plugins/spotify/src/index.js +188 -0
  189. package/dist/plugins/stackby/src/index.js +82 -0
  190. package/dist/plugins/storyblok/src/index.js +141 -0
  191. package/dist/plugins/strapi/src/index.js +152 -0
  192. package/dist/plugins/strava/src/index.js +137 -0
  193. package/dist/plugins/stripe/src/index.js +222 -0
  194. package/dist/plugins/supabase/src/index.js +121 -0
  195. package/dist/plugins/syncromsp/src/index.js +255 -0
  196. package/dist/plugins/tapfiliate/src/index.js +125 -0
  197. package/dist/plugins/telegram/src/index.js +233 -0
  198. package/dist/plugins/thehive/src/index.js +142 -0
  199. package/dist/plugins/thehiveProject/src/index.js +194 -0
  200. package/dist/plugins/todoist/src/index.js +244 -0
  201. package/dist/plugins/travisci/src/index.js +71 -0
  202. package/dist/plugins/trello/src/index.js +341 -0
  203. package/dist/plugins/twake/src/index.js +40 -0
  204. package/dist/plugins/twilio/src/index.js +75 -0
  205. package/dist/plugins/twist/src/index.js +90 -0
  206. package/dist/plugins/twitter/src/index.js +123 -0
  207. package/dist/plugins/unleashedSoftware/src/index.js +84 -0
  208. package/dist/plugins/uplead/src/index.js +59 -0
  209. package/dist/plugins/uproc/src/index.js +34 -0
  210. package/dist/plugins/uptimerobot/src/index.js +264 -0
  211. package/dist/plugins/urlscanio/src/index.js +64 -0
  212. package/dist/plugins/vero/src/index.js +80 -0
  213. package/dist/plugins/vonage/src/index.js +42 -0
  214. package/dist/plugins/wekan/src/index.js +91 -0
  215. package/dist/plugins/woocommerce/src/index.js +92 -0
  216. package/dist/plugins/wordpress/src/index.js +121 -0
  217. package/dist/plugins/xero/src/index.js +136 -0
  218. package/dist/plugins/yourls/src/index.js +56 -0
  219. package/dist/plugins/zammad/src/index.js +91 -0
  220. package/dist/plugins/zendesk/src/index.js +137 -0
  221. package/dist/plugins/zoho/src/index.js +85 -0
  222. package/dist/plugins/zoom/src/index.js +122 -0
  223. package/dist/plugins/zulip/src/index.js +170 -0
  224. package/dist/sdk.d.ts +38 -0
  225. package/dist/sdk.js +105 -0
  226. package/dist/utils/cli.d.ts +13 -0
  227. package/dist/utils/cli.js +32 -0
  228. package/dist/utils/output.d.ts +4 -0
  229. package/dist/utils/output.js +13 -0
  230. package/package.json +57 -0
@@ -0,0 +1,31 @@
1
+ export default function lingvanex(rl) {
2
+ rl.setName("lingvanex");
3
+ rl.setVersion("0.1.0");
4
+ rl.setConnectionSchema({ apiKey: { type: "string", required: true, description: "Lingvanex API key", env: "LINGVANEX_API_KEY" } });
5
+ rl.registerAction("translate", {
6
+ description: "Translate text",
7
+ inputSchema: {
8
+ text: { type: "string", required: true, description: "Text to translate" },
9
+ to: { type: "string", required: true, description: "Target language code (e.g. en_GB, fr_FR)" },
10
+ from: { type: "string", required: false, description: "Source language code (auto-detect if omitted)" },
11
+ platform: { type: "string", required: false, description: "api (default)" },
12
+ translateMode: { type: "string", required: false, description: "'html' to translate preserving HTML structure, or omit for plain text" },
13
+ },
14
+ async execute(input, ctx) {
15
+ const { text, to, from: src, platform = "api", translateMode } = input;
16
+ const body = { data: text, to, platform };
17
+ if (src)
18
+ body.from = src;
19
+ if (translateMode)
20
+ body.translateMode = translateMode;
21
+ const res = await fetch("https://api-b2b.backenster.com/b1/api/v3/translate", {
22
+ method: "POST",
23
+ headers: { Authorization: `Bearer ${ctx.connection.config.apiKey}`, "Content-Type": "application/json" },
24
+ body: JSON.stringify(body),
25
+ });
26
+ if (!res.ok)
27
+ throw new Error(`Lingvanex error ${res.status}: ${await res.text()}`);
28
+ return res.json();
29
+ },
30
+ });
31
+ }
@@ -0,0 +1,80 @@
1
+ const BASE_URL = "https://api.linkedin.com";
2
+ async function apiRequest(token, method, endpoint, body) {
3
+ const isAbsolute = endpoint.startsWith("http");
4
+ const url = isAbsolute ? endpoint : `${BASE_URL}/rest${endpoint}`;
5
+ const opts = {
6
+ method,
7
+ headers: {
8
+ Authorization: `Bearer ${token}`,
9
+ Accept: "application/json",
10
+ "X-Restli-Protocol-Version": "2.0.0",
11
+ "LinkedIn-Version": "202504",
12
+ "Content-Type": "application/json",
13
+ },
14
+ };
15
+ if (body && Object.keys(body).length > 0 && method !== "GET")
16
+ opts.body = JSON.stringify(body);
17
+ const res = await fetch(url, opts);
18
+ if (res.status === 201) {
19
+ return { urn: res.headers.get("x-restli-id") };
20
+ }
21
+ if (!res.ok)
22
+ throw new Error(`LinkedIn API error ${res.status}: ${await res.text()}`);
23
+ if (res.status === 204)
24
+ return { success: true };
25
+ return res.json();
26
+ }
27
+ // LinkedIn "little text" format escaping
28
+ function escapeText(text) {
29
+ return text.replace(/[(*)\[\]{}<>@|~_]/g, (char) => "\\" + char);
30
+ }
31
+ export default function linkedin(rl) {
32
+ rl.setName("linkedin");
33
+ rl.setVersion("0.1.0");
34
+ rl.setConnectionSchema({
35
+ accessToken: { type: "string", required: true, description: "LinkedIn OAuth2 access token", env: "LINKEDIN_ACCESS_TOKEN" },
36
+ });
37
+ const tok = (ctx) => ctx.connection.config.accessToken;
38
+ rl.registerAction("post.create", {
39
+ description: "Create a post on LinkedIn. Supports text-only, article shares, and text with commentary. Image uploads require binary data and are not supported in this plugin.",
40
+ inputSchema: {
41
+ postAs: { type: "string", required: true, description: "'person' or 'organization'" },
42
+ personOrOrgId: { type: "string", required: true, description: "Person ID or Organization ID (without URN prefix)" },
43
+ text: { type: "string", required: true, description: "Post text/commentary" },
44
+ shareMediaCategory: { type: "string", required: false, description: "'NONE' (default, text only), 'ARTICLE' (link share)" },
45
+ visibility: { type: "string", required: false, description: "PUBLIC (default) or CONNECTIONS. Only applies when posting as person." },
46
+ articleUrl: { type: "string", required: false, description: "URL for article share (required when shareMediaCategory is ARTICLE)" },
47
+ articleTitle: { type: "string", required: false },
48
+ articleDescription: { type: "string", required: false },
49
+ },
50
+ async execute(input, ctx) {
51
+ const { postAs, personOrOrgId, text, shareMediaCategory = "NONE", visibility = "PUBLIC", articleUrl, articleTitle, articleDescription, } = input;
52
+ const authorUrn = postAs === "person"
53
+ ? `urn:li:person:${personOrOrgId}`
54
+ : `urn:li:organization:${personOrOrgId}`;
55
+ const escapedText = escapeText(text);
56
+ const body = {
57
+ author: authorUrn,
58
+ lifecycleState: "PUBLISHED",
59
+ distribution: {
60
+ feedDistribution: "MAIN_FEED",
61
+ thirdPartyDistributionChannels: [],
62
+ },
63
+ visibility: postAs === "person" ? visibility : "PUBLIC",
64
+ };
65
+ if (shareMediaCategory === "ARTICLE" && articleUrl) {
66
+ const article = { source: articleUrl };
67
+ if (articleTitle)
68
+ article.title = articleTitle;
69
+ if (articleDescription)
70
+ article.description = articleDescription;
71
+ body.content = { article };
72
+ body.commentary = escapedText;
73
+ }
74
+ else {
75
+ body.commentary = escapedText;
76
+ }
77
+ return apiRequest(tok(ctx), "POST", "/posts", body);
78
+ },
79
+ });
80
+ }
@@ -0,0 +1,119 @@
1
+ const BASE_URL = "https://public-api.lonescale.com";
2
+ async function apiRequest(apiKey, method, endpoint, body, qs) {
3
+ const url = new URL(`${BASE_URL}${endpoint}`);
4
+ if (qs) {
5
+ for (const [k, v] of Object.entries(qs)) {
6
+ if (v !== undefined && v !== null)
7
+ url.searchParams.set(k, String(v));
8
+ }
9
+ }
10
+ const opts = {
11
+ method,
12
+ headers: { "X-API-KEY": apiKey, "Content-Type": "application/json" },
13
+ };
14
+ if (body && Object.keys(body).length > 0 && method !== "GET" && method !== "DELETE")
15
+ opts.body = JSON.stringify(body);
16
+ const res = await fetch(url.toString(), opts);
17
+ if (!res.ok)
18
+ throw new Error(`LoneScale API error ${res.status}: ${await res.text()}`);
19
+ return res.json();
20
+ }
21
+ export default function lonescale(rl) {
22
+ rl.setName("lonescale");
23
+ rl.setVersion("0.1.0");
24
+ rl.setConnectionSchema({
25
+ apiKey: { type: "string", required: true, description: "LoneScale API key", env: "LONESCALE_API_KEY" },
26
+ });
27
+ const key = (ctx) => ctx.connection.config.apiKey;
28
+ rl.registerAction("list.create", {
29
+ description: "Create a new list",
30
+ inputSchema: {
31
+ name: { type: "string", required: true, description: "List name" },
32
+ entity: { type: "string", required: true, description: "PEOPLE or COMPANY" },
33
+ },
34
+ async execute(input, ctx) {
35
+ const { name, entity } = input;
36
+ return apiRequest(key(ctx), "POST", "/lists", { name, entity });
37
+ },
38
+ });
39
+ rl.registerAction("list.list", {
40
+ description: "List all lists, optionally filtered by entity type",
41
+ inputSchema: {
42
+ entity: { type: "string", required: false, description: "PEOPLE or COMPANY" },
43
+ },
44
+ async execute(input, ctx) {
45
+ const { entity } = (input ?? {});
46
+ const qs = {};
47
+ if (entity)
48
+ qs.entity = entity;
49
+ return apiRequest(key(ctx), "GET", "/lists", undefined, qs);
50
+ },
51
+ });
52
+ rl.registerAction("item.addPerson", {
53
+ description: "Add a person (contact) to a list",
54
+ inputSchema: {
55
+ listId: { type: "string", required: true, description: "List ID" },
56
+ firstName: { type: "string", required: true },
57
+ lastName: { type: "string", required: true },
58
+ fullName: { type: "string", required: false },
59
+ email: { type: "string", required: false },
60
+ companyName: { type: "string", required: false },
61
+ currentPosition: { type: "string", required: false },
62
+ domain: { type: "string", required: false, description: "Company domain" },
63
+ linkedinUrl: { type: "string", required: false },
64
+ location: { type: "string", required: false },
65
+ contactId: { type: "string", required: false, description: "Contact ID from your source" },
66
+ },
67
+ async execute(input, ctx) {
68
+ const { listId, firstName, lastName, fullName, email, companyName, currentPosition, domain, linkedinUrl, location, contactId } = input;
69
+ const body = {};
70
+ if (firstName)
71
+ body.first_name = firstName;
72
+ if (lastName)
73
+ body.last_name = lastName;
74
+ if (fullName)
75
+ body.full_name = fullName;
76
+ if (email)
77
+ body.email = email;
78
+ if (companyName)
79
+ body.company_name = companyName;
80
+ if (currentPosition)
81
+ body.current_position = currentPosition;
82
+ if (domain)
83
+ body.domain = domain;
84
+ if (linkedinUrl)
85
+ body.linkedin_url = linkedinUrl;
86
+ if (location)
87
+ body.location = location;
88
+ if (contactId)
89
+ body.contact_id = contactId;
90
+ return apiRequest(key(ctx), "POST", `/lists/${listId}/item`, body);
91
+ },
92
+ });
93
+ rl.registerAction("item.addCompany", {
94
+ description: "Add a company to a list",
95
+ inputSchema: {
96
+ listId: { type: "string", required: true, description: "List ID" },
97
+ companyName: { type: "string", required: true },
98
+ linkedinUrl: { type: "string", required: false },
99
+ domain: { type: "string", required: false, description: "Company domain" },
100
+ location: { type: "string", required: false },
101
+ contactId: { type: "string", required: false, description: "Contact ID from your source" },
102
+ },
103
+ async execute(input, ctx) {
104
+ const { listId, companyName, linkedinUrl, domain, location, contactId } = input;
105
+ const body = {};
106
+ if (companyName)
107
+ body.company_name = companyName;
108
+ if (linkedinUrl)
109
+ body.linkedin_url = linkedinUrl;
110
+ if (domain)
111
+ body.domain = domain;
112
+ if (location)
113
+ body.location = location;
114
+ if (contactId)
115
+ body.contact_id = contactId;
116
+ return apiRequest(key(ctx), "POST", `/lists/${listId}/item`, body);
117
+ },
118
+ });
119
+ }
@@ -0,0 +1,300 @@
1
+ async function apiRequest(host, token, method, endpoint, body, qs) {
2
+ const url = new URL(`${host}${endpoint}`);
3
+ if (qs) {
4
+ // Magento uses nested query params like search_criteria[page_size]=10
5
+ function flatten(obj, prefix = "") {
6
+ if (obj && typeof obj === "object" && !Array.isArray(obj)) {
7
+ for (const [k, v] of Object.entries(obj)) {
8
+ flatten(v, prefix ? `${prefix}[${k}]` : k);
9
+ }
10
+ }
11
+ else if (Array.isArray(obj)) {
12
+ for (let i = 0; i < obj.length; i++) {
13
+ flatten(obj[i], `${prefix}[${i}]`);
14
+ }
15
+ }
16
+ else if (obj !== undefined && obj !== null) {
17
+ url.searchParams.set(prefix, String(obj));
18
+ }
19
+ }
20
+ flatten(qs);
21
+ }
22
+ const opts = {
23
+ method,
24
+ headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
25
+ };
26
+ if (body && Object.keys(body).length > 0 && method !== "GET" && method !== "DELETE")
27
+ opts.body = JSON.stringify(body);
28
+ const res = await fetch(url.toString(), opts);
29
+ if (!res.ok)
30
+ throw new Error(`Magento API error ${res.status}: ${await res.text()}`);
31
+ if (res.status === 204)
32
+ return { success: true };
33
+ const text = await res.text();
34
+ try {
35
+ return JSON.parse(text);
36
+ }
37
+ catch {
38
+ return text;
39
+ }
40
+ }
41
+ async function searchAll(host, token, endpoint, searchCriteria = {}) {
42
+ const all = [];
43
+ searchCriteria.page_size = 100;
44
+ let currentPage = 1;
45
+ let totalCount = Infinity;
46
+ while (all.length < totalCount) {
47
+ searchCriteria.current_page = currentPage;
48
+ const data = (await apiRequest(host, token, "GET", endpoint, undefined, { search_criteria: searchCriteria }));
49
+ totalCount = data.total_count ?? 0;
50
+ const items = data.items;
51
+ if (items)
52
+ all.push(...items);
53
+ else
54
+ break;
55
+ currentPage++;
56
+ }
57
+ return all;
58
+ }
59
+ export default function magento(rl) {
60
+ rl.setName("magento");
61
+ rl.setVersion("0.1.0");
62
+ rl.setConnectionSchema({
63
+ host: { type: "string", required: true, description: "Magento store URL (e.g. https://mystore.com)", env: "MAGENTO_HOST" },
64
+ accessToken: { type: "string", required: true, description: "Integration access token", env: "MAGENTO_ACCESS_TOKEN" },
65
+ });
66
+ const conn = (ctx) => ({
67
+ host: ctx.connection.config.host.replace(/\/$/, ""),
68
+ token: ctx.connection.config.accessToken,
69
+ });
70
+ // ── Customer ────────────────────────────────────────
71
+ rl.registerAction("customer.create", {
72
+ description: "Create a customer",
73
+ inputSchema: {
74
+ email: { type: "string", required: true },
75
+ firstname: { type: "string", required: true },
76
+ lastname: { type: "string", required: true },
77
+ password: { type: "string", required: false },
78
+ addresses: { type: "array", required: false, description: "Array of address objects (street as string, city, postcode, country_id, firstname, lastname, telephone required)" },
79
+ customAttributes: { type: "array", required: false, description: "Array of {attribute_code, value} objects" },
80
+ additionalFields: { type: "object", required: false, description: "middlename, prefix, suffix, dob, gender (1=male,2=female,3=unspecified), group_id, store_id, website_id, etc." },
81
+ },
82
+ async execute(input, ctx) {
83
+ const { email, firstname, lastname, password, addresses, customAttributes, additionalFields } = input;
84
+ const { host, token } = conn(ctx);
85
+ const customer = { email, firstname, lastname };
86
+ if (addresses && Array.isArray(addresses)) {
87
+ customer.addresses = addresses.map((a) => ({
88
+ ...a,
89
+ street: Array.isArray(a.street) ? a.street : [a.street],
90
+ }));
91
+ }
92
+ if (customAttributes)
93
+ customer.custom_attributes = customAttributes;
94
+ if (additionalFields)
95
+ Object.assign(customer, additionalFields);
96
+ const body = { customer };
97
+ if (password)
98
+ body.password = password;
99
+ return apiRequest(host, token, "POST", "/rest/V1/customers", body);
100
+ },
101
+ });
102
+ rl.registerAction("customer.get", {
103
+ description: "Get a customer by ID",
104
+ inputSchema: { customerId: { type: "number", required: true } },
105
+ async execute(input, ctx) {
106
+ const { host, token } = conn(ctx);
107
+ return apiRequest(host, token, "GET", `/rest/default/V1/customers/${input.customerId}`);
108
+ },
109
+ });
110
+ rl.registerAction("customer.list", {
111
+ description: "Search/list customers using Magento search_criteria",
112
+ inputSchema: {
113
+ searchCriteria: { type: "object", required: false, description: "Magento search_criteria object (filter_groups, sort_orders, page_size). Omit for all." },
114
+ limit: { type: "number", required: false, description: "Max results (if not using searchCriteria)" },
115
+ },
116
+ async execute(input, ctx) {
117
+ const { searchCriteria, limit } = (input ?? {});
118
+ const { host, token } = conn(ctx);
119
+ if (searchCriteria) {
120
+ const data = await apiRequest(host, token, "GET", "/rest/default/V1/customers/search", undefined, { search_criteria: searchCriteria });
121
+ return data.items;
122
+ }
123
+ if (limit) {
124
+ const data = await apiRequest(host, token, "GET", "/rest/default/V1/customers/search", undefined, { search_criteria: { page_size: limit } });
125
+ return data.items;
126
+ }
127
+ return searchAll(host, token, "/rest/default/V1/customers/search");
128
+ },
129
+ });
130
+ rl.registerAction("customer.update", {
131
+ description: "Update a customer",
132
+ inputSchema: {
133
+ customerId: { type: "number", required: true },
134
+ email: { type: "string", required: true },
135
+ firstname: { type: "string", required: true },
136
+ lastname: { type: "string", required: true },
137
+ updateFields: { type: "object", required: false, description: "Fields to update (middlename, dob, gender, group_id, etc.)" },
138
+ addresses: { type: "array", required: false },
139
+ customAttributes: { type: "array", required: false },
140
+ },
141
+ async execute(input, ctx) {
142
+ const { customerId, email, firstname, lastname, updateFields, addresses, customAttributes } = input;
143
+ const { host, token } = conn(ctx);
144
+ const customer = { email, firstname, lastname, id: customerId, website_id: 0 };
145
+ if (addresses && Array.isArray(addresses)) {
146
+ customer.addresses = addresses.map((a) => ({
147
+ ...a,
148
+ street: Array.isArray(a.street) ? a.street : [a.street],
149
+ }));
150
+ }
151
+ if (customAttributes)
152
+ customer.custom_attributes = customAttributes;
153
+ if (updateFields)
154
+ Object.assign(customer, updateFields);
155
+ return apiRequest(host, token, "PUT", `/rest/V1/customers/${customerId}`, { customer });
156
+ },
157
+ });
158
+ rl.registerAction("customer.delete", {
159
+ description: "Delete a customer",
160
+ inputSchema: { customerId: { type: "number", required: true } },
161
+ async execute(input, ctx) {
162
+ const { host, token } = conn(ctx);
163
+ await apiRequest(host, token, "DELETE", `/rest/default/V1/customers/${input.customerId}`);
164
+ return { success: true };
165
+ },
166
+ });
167
+ // ── Invoice ─────────────────────────────────────────
168
+ rl.registerAction("invoice.create", {
169
+ description: "Create an invoice for an order",
170
+ inputSchema: { orderId: { type: "number", required: true } },
171
+ async execute(input, ctx) {
172
+ const { host, token } = conn(ctx);
173
+ await apiRequest(host, token, "POST", `/rest/default/V1/order/${input.orderId}/invoice`);
174
+ return { success: true };
175
+ },
176
+ });
177
+ // ── Order ───────────────────────────────────────────
178
+ rl.registerAction("order.get", {
179
+ description: "Get an order by ID",
180
+ inputSchema: { orderId: { type: "number", required: true } },
181
+ async execute(input, ctx) {
182
+ const { host, token } = conn(ctx);
183
+ return apiRequest(host, token, "GET", `/rest/default/V1/orders/${input.orderId}`);
184
+ },
185
+ });
186
+ rl.registerAction("order.list", {
187
+ description: "Search/list orders",
188
+ inputSchema: {
189
+ searchCriteria: { type: "object", required: false, description: "Magento search_criteria object" },
190
+ limit: { type: "number", required: false },
191
+ },
192
+ async execute(input, ctx) {
193
+ const { searchCriteria, limit } = (input ?? {});
194
+ const { host, token } = conn(ctx);
195
+ if (searchCriteria) {
196
+ const data = await apiRequest(host, token, "GET", "/rest/default/V1/orders", undefined, { search_criteria: searchCriteria });
197
+ return data.items;
198
+ }
199
+ if (limit) {
200
+ const data = await apiRequest(host, token, "GET", "/rest/default/V1/orders", undefined, { search_criteria: { page_size: limit } });
201
+ return data.items;
202
+ }
203
+ return searchAll(host, token, "/rest/default/V1/orders");
204
+ },
205
+ });
206
+ rl.registerAction("order.cancel", {
207
+ description: "Cancel an order",
208
+ inputSchema: { orderId: { type: "number", required: true } },
209
+ async execute(input, ctx) {
210
+ const { host, token } = conn(ctx);
211
+ await apiRequest(host, token, "POST", `/rest/default/V1/orders/${input.orderId}/cancel`);
212
+ return { success: true };
213
+ },
214
+ });
215
+ rl.registerAction("order.ship", {
216
+ description: "Ship an order",
217
+ inputSchema: { orderId: { type: "number", required: true } },
218
+ async execute(input, ctx) {
219
+ const { host, token } = conn(ctx);
220
+ await apiRequest(host, token, "POST", `/rest/default/V1/order/${input.orderId}/ship`);
221
+ return { success: true };
222
+ },
223
+ });
224
+ // ── Product ─────────────────────────────────────────
225
+ rl.registerAction("product.create", {
226
+ description: "Create a product",
227
+ inputSchema: {
228
+ sku: { type: "string", required: true },
229
+ name: { type: "string", required: true },
230
+ attributeSetId: { type: "number", required: true },
231
+ price: { type: "number", required: true },
232
+ additionalFields: { type: "object", required: false, description: "status (1=enabled,2=disabled), visibility (1-4), weight, type_id, etc." },
233
+ customAttributes: { type: "array", required: false, description: "Array of {attribute_code, value}" },
234
+ },
235
+ async execute(input, ctx) {
236
+ const { sku, name, attributeSetId, price, additionalFields, customAttributes } = input;
237
+ const { host, token } = conn(ctx);
238
+ const product = { sku, name, attribute_set_id: attributeSetId, price };
239
+ if (customAttributes)
240
+ product.custom_attributes = customAttributes;
241
+ if (additionalFields)
242
+ Object.assign(product, additionalFields);
243
+ return apiRequest(host, token, "POST", "/rest/default/V1/products", { product });
244
+ },
245
+ });
246
+ rl.registerAction("product.get", {
247
+ description: "Get a product by SKU",
248
+ inputSchema: { sku: { type: "string", required: true } },
249
+ async execute(input, ctx) {
250
+ const { host, token } = conn(ctx);
251
+ return apiRequest(host, token, "GET", `/rest/default/V1/products/${encodeURIComponent(input.sku)}`);
252
+ },
253
+ });
254
+ rl.registerAction("product.list", {
255
+ description: "Search/list products",
256
+ inputSchema: {
257
+ searchCriteria: { type: "object", required: false },
258
+ limit: { type: "number", required: false },
259
+ },
260
+ async execute(input, ctx) {
261
+ const { searchCriteria, limit } = (input ?? {});
262
+ const { host, token } = conn(ctx);
263
+ if (searchCriteria) {
264
+ const data = await apiRequest(host, token, "GET", "/rest/default/V1/products", undefined, { search_criteria: searchCriteria });
265
+ return data.items;
266
+ }
267
+ if (limit) {
268
+ const data = await apiRequest(host, token, "GET", "/rest/default/V1/products", undefined, { search_criteria: { page_size: limit } });
269
+ return data.items;
270
+ }
271
+ return searchAll(host, token, "/rest/default/V1/products");
272
+ },
273
+ });
274
+ rl.registerAction("product.update", {
275
+ description: "Update a product by SKU",
276
+ inputSchema: {
277
+ sku: { type: "string", required: true },
278
+ updateFields: { type: "object", required: true, description: "Fields to update (name, price, status, visibility, weight, attribute_set_id, etc.)" },
279
+ customAttributes: { type: "array", required: false },
280
+ },
281
+ async execute(input, ctx) {
282
+ const { sku, updateFields, customAttributes } = input;
283
+ const { host, token } = conn(ctx);
284
+ const product = { sku };
285
+ if (customAttributes)
286
+ product.custom_attributes = customAttributes;
287
+ Object.assign(product, updateFields);
288
+ return apiRequest(host, token, "PUT", `/rest/default/V1/products/${encodeURIComponent(sku)}`, { product });
289
+ },
290
+ });
291
+ rl.registerAction("product.delete", {
292
+ description: "Delete a product by SKU",
293
+ inputSchema: { sku: { type: "string", required: true } },
294
+ async execute(input, ctx) {
295
+ const { host, token } = conn(ctx);
296
+ await apiRequest(host, token, "DELETE", `/rest/default/V1/products/${encodeURIComponent(input.sku)}`);
297
+ return { success: true };
298
+ },
299
+ });
300
+ }
@@ -0,0 +1,27 @@
1
+ export default function mailcheck(rl) {
2
+ rl.setName("mailcheck");
3
+ rl.setVersion("0.1.0");
4
+ rl.setConnectionSchema({
5
+ apiKey: { type: "string", required: true, description: "Mailcheck API key", env: "MAILCHECK_API_KEY" },
6
+ });
7
+ rl.registerAction("email.check", {
8
+ description: "Verify an email address",
9
+ inputSchema: {
10
+ email: { type: "string", required: true, description: "Email address to check" },
11
+ },
12
+ async execute(input, ctx) {
13
+ const { email } = input;
14
+ const res = await fetch("https://api.mailcheck.co/v1/singleEmail:check", {
15
+ method: "POST",
16
+ headers: {
17
+ Authorization: `Bearer ${ctx.connection.config.apiKey}`,
18
+ "Content-Type": "application/json",
19
+ },
20
+ body: JSON.stringify({ email }),
21
+ });
22
+ if (!res.ok)
23
+ throw new Error(`Mailcheck API error ${res.status}: ${await res.text()}`);
24
+ return res.json();
25
+ },
26
+ });
27
+ }