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,252 @@
1
+ function buildBaseUrl(subdomain) {
2
+ return `https://api.bamboohr.com/api/gateway.php/${subdomain}/v1`;
3
+ }
4
+ async function apiRequest(subdomain, apiKey, method, endpoint, body) {
5
+ const url = `${buildBaseUrl(subdomain)}/${endpoint}`;
6
+ const opts = {
7
+ method,
8
+ headers: {
9
+ "Content-Type": "application/json",
10
+ Accept: "application/json",
11
+ Authorization: `Basic ${btoa(`${apiKey}:x`)}`,
12
+ },
13
+ };
14
+ if (body && Object.keys(body).length > 0 && method !== "GET" && method !== "DELETE") {
15
+ opts.body = JSON.stringify(body);
16
+ }
17
+ const res = await fetch(url, opts);
18
+ if (!res.ok) {
19
+ const text = await res.text();
20
+ throw new Error(`BambooHR API error ${res.status}: ${text}`);
21
+ }
22
+ if (res.status === 204 || res.headers.get("content-length") === "0")
23
+ return { success: true };
24
+ const contentType = res.headers.get("content-type") ?? "";
25
+ if (contentType.includes("application/json"))
26
+ return res.json();
27
+ return { success: true };
28
+ }
29
+ function getConn(ctx) {
30
+ return {
31
+ subdomain: ctx.connection.config.subdomain,
32
+ apiKey: ctx.connection.config.apiKey,
33
+ };
34
+ }
35
+ export default function bambooHr(rl) {
36
+ rl.setName("bambooHr");
37
+ rl.setVersion("0.1.0");
38
+ rl.setConnectionSchema({
39
+ subdomain: {
40
+ type: "string",
41
+ required: true,
42
+ description: "BambooHR subdomain (e.g. 'mycompany' for mycompany.bamboohr.com)",
43
+ env: "BAMBOO_HR_SUBDOMAIN",
44
+ },
45
+ apiKey: {
46
+ type: "string",
47
+ required: true,
48
+ description: "BambooHR API key",
49
+ env: "BAMBOO_HR_API_KEY",
50
+ },
51
+ });
52
+ // ── Employee ────────────────────────────────────────
53
+ rl.registerAction("employee.create", {
54
+ description: "Create a new employee",
55
+ inputSchema: {
56
+ firstName: { type: "string", required: true, description: "First name" },
57
+ lastName: { type: "string", required: true, description: "Last name" },
58
+ department: { type: "string", required: false, description: "Department" },
59
+ division: { type: "string", required: false, description: "Division" },
60
+ employeeNumber: { type: "string", required: false, description: "Employee number" },
61
+ gender: { type: "string", required: false, description: "Gender (Male/Female)" },
62
+ hireDate: { type: "string", required: false, description: "Hire date (YYYY-MM-DD)" },
63
+ location: { type: "string", required: false, description: "Location" },
64
+ mobilePhone: { type: "string", required: false, description: "Mobile phone" },
65
+ preferredName: { type: "string", required: false, description: "Preferred name" },
66
+ },
67
+ async execute(input, ctx) {
68
+ const { subdomain, apiKey } = getConn(ctx);
69
+ const body = input;
70
+ const res = await fetch(`${buildBaseUrl(subdomain)}/employees`, {
71
+ method: "POST",
72
+ headers: {
73
+ "Content-Type": "application/json",
74
+ Accept: "application/json",
75
+ Authorization: `Basic ${btoa(`${apiKey}:x`)}`,
76
+ },
77
+ body: JSON.stringify(body),
78
+ });
79
+ if (!res.ok)
80
+ throw new Error(`BambooHR error ${res.status}: ${await res.text()}`);
81
+ const location = res.headers.get("location") ?? "";
82
+ const employeeId = location.split("/").pop();
83
+ return { id: employeeId };
84
+ },
85
+ });
86
+ rl.registerAction("employee.get", {
87
+ description: "Get an employee by ID",
88
+ inputSchema: {
89
+ employeeId: { type: "string", required: true, description: "Employee ID" },
90
+ fields: { type: "string", required: false, description: "Comma-separated field names (default: all)" },
91
+ },
92
+ async execute(input, ctx) {
93
+ const { employeeId, fields } = input;
94
+ const { subdomain, apiKey } = getConn(ctx);
95
+ let fieldList = fields ?? "all";
96
+ if (fieldList === "all") {
97
+ const dir = (await apiRequest(subdomain, apiKey, "GET", "employees/directory"));
98
+ const dirFields = dir.fields ?? [];
99
+ fieldList = dirFields.map((f) => f.id).join(",");
100
+ }
101
+ return apiRequest(subdomain, apiKey, "GET", `employees/${employeeId}?fields=${fieldList}`);
102
+ },
103
+ });
104
+ rl.registerAction("employee.list", {
105
+ description: "List all employees (directory)",
106
+ inputSchema: {
107
+ limit: { type: "number", required: false, description: "Max results to return" },
108
+ },
109
+ async execute(input, ctx) {
110
+ const { limit } = (input ?? {});
111
+ const { subdomain, apiKey } = getConn(ctx);
112
+ const data = (await apiRequest(subdomain, apiKey, "GET", "employees/directory"));
113
+ const employees = data.employees ?? [];
114
+ if (limit)
115
+ return employees.slice(0, limit);
116
+ return employees;
117
+ },
118
+ });
119
+ rl.registerAction("employee.update", {
120
+ description: "Update an employee",
121
+ inputSchema: {
122
+ employeeId: { type: "string", required: true, description: "Employee ID" },
123
+ firstName: { type: "string", required: false, description: "First name" },
124
+ lastName: { type: "string", required: false, description: "Last name" },
125
+ department: { type: "string", required: false, description: "Department" },
126
+ division: { type: "string", required: false, description: "Division" },
127
+ gender: { type: "string", required: false, description: "Gender" },
128
+ hireDate: { type: "string", required: false, description: "Hire date (YYYY-MM-DD)" },
129
+ location: { type: "string", required: false, description: "Location" },
130
+ mobilePhone: { type: "string", required: false, description: "Mobile phone" },
131
+ },
132
+ async execute(input, ctx) {
133
+ const { employeeId, ...fields } = input;
134
+ const { subdomain, apiKey } = getConn(ctx);
135
+ await apiRequest(subdomain, apiKey, "POST", `employees/${employeeId}`, fields);
136
+ return { success: true };
137
+ },
138
+ });
139
+ // ── Employee Document ───────────────────────────────
140
+ rl.registerAction("employeeDocument.list", {
141
+ description: "List documents for an employee",
142
+ inputSchema: {
143
+ employeeId: { type: "string", required: true, description: "Employee ID" },
144
+ limit: { type: "number", required: false, description: "Max results to return" },
145
+ },
146
+ async execute(input, ctx) {
147
+ const { employeeId, limit } = input;
148
+ const { subdomain, apiKey } = getConn(ctx);
149
+ const data = (await apiRequest(subdomain, apiKey, "GET", `employees/${employeeId}/files/view/`));
150
+ const categories = data.categories ?? [];
151
+ // Flatten files from all categories
152
+ const files = [];
153
+ for (const cat of categories) {
154
+ if (cat.files)
155
+ files.push(...cat.files);
156
+ }
157
+ if (limit)
158
+ return files.slice(0, limit);
159
+ return files;
160
+ },
161
+ });
162
+ rl.registerAction("employeeDocument.delete", {
163
+ description: "Delete an employee document",
164
+ inputSchema: {
165
+ employeeId: { type: "string", required: true, description: "Employee ID" },
166
+ fileId: { type: "string", required: true, description: "File ID" },
167
+ },
168
+ async execute(input, ctx) {
169
+ const { employeeId, fileId } = input;
170
+ const { subdomain, apiKey } = getConn(ctx);
171
+ await apiRequest(subdomain, apiKey, "DELETE", `employees/${employeeId}/files/${fileId}`);
172
+ return { success: true };
173
+ },
174
+ });
175
+ rl.registerAction("employeeDocument.update", {
176
+ description: "Update an employee document's metadata",
177
+ inputSchema: {
178
+ employeeId: { type: "string", required: true, description: "Employee ID" },
179
+ fileId: { type: "string", required: true, description: "File ID" },
180
+ shareWithEmployee: { type: "boolean", required: false, description: "Share file with employee" },
181
+ },
182
+ async execute(input, ctx) {
183
+ const { employeeId, fileId, shareWithEmployee } = input;
184
+ const { subdomain, apiKey } = getConn(ctx);
185
+ const body = {};
186
+ body.shareWithEmployee = shareWithEmployee ? "yes" : "no";
187
+ await apiRequest(subdomain, apiKey, "POST", `employees/${employeeId}/files/${fileId}`, body);
188
+ return { success: true };
189
+ },
190
+ });
191
+ // ── Company File ────────────────────────────────────
192
+ rl.registerAction("file.list", {
193
+ description: "List company files",
194
+ inputSchema: {
195
+ limit: { type: "number", required: false, description: "Max results to return" },
196
+ },
197
+ async execute(input, ctx) {
198
+ const { limit } = (input ?? {});
199
+ const { subdomain, apiKey } = getConn(ctx);
200
+ const data = (await apiRequest(subdomain, apiKey, "GET", "files/view"));
201
+ const categories = data.categories ?? [];
202
+ const files = [];
203
+ for (const cat of categories) {
204
+ if (cat.files)
205
+ files.push(...cat.files);
206
+ }
207
+ if (limit)
208
+ return files.slice(0, limit);
209
+ return files;
210
+ },
211
+ });
212
+ rl.registerAction("file.delete", {
213
+ description: "Delete a company file",
214
+ inputSchema: {
215
+ fileId: { type: "string", required: true, description: "File ID" },
216
+ },
217
+ async execute(input, ctx) {
218
+ const { fileId } = input;
219
+ const { subdomain, apiKey } = getConn(ctx);
220
+ await apiRequest(subdomain, apiKey, "DELETE", `files/${fileId}`);
221
+ return { success: true };
222
+ },
223
+ });
224
+ rl.registerAction("file.update", {
225
+ description: "Update a company file's metadata",
226
+ inputSchema: {
227
+ fileId: { type: "string", required: true, description: "File ID" },
228
+ shareWithEmployee: { type: "boolean", required: false, description: "Share with employees" },
229
+ },
230
+ async execute(input, ctx) {
231
+ const { fileId, shareWithEmployee } = input;
232
+ const { subdomain, apiKey } = getConn(ctx);
233
+ await apiRequest(subdomain, apiKey, "POST", `files/${fileId}`, {
234
+ shareWithEmployee: shareWithEmployee ? "yes" : "no",
235
+ });
236
+ return { success: true };
237
+ },
238
+ });
239
+ // ── Company Report ──────────────────────────────────
240
+ rl.registerAction("companyReport.get", {
241
+ description: "Get a company report",
242
+ inputSchema: {
243
+ reportId: { type: "string", required: true, description: "Report ID" },
244
+ format: { type: "string", required: false, description: "Format: JSON, CSV, XLS, XML, PDF (default: JSON)" },
245
+ },
246
+ async execute(input, ctx) {
247
+ const { reportId, format = "JSON" } = input;
248
+ const { subdomain, apiKey } = getConn(ctx);
249
+ return apiRequest(subdomain, apiKey, "GET", `reports/${reportId}/?format=${format}&fd=true&onlyCurrent=true`);
250
+ },
251
+ });
252
+ }
@@ -0,0 +1,100 @@
1
+ const BASE_URL = "https://api.bannerbear.com/v2";
2
+ async function apiRequest(apiKey, method, endpoint, body) {
3
+ const opts = {
4
+ method,
5
+ headers: {
6
+ "Content-Type": "application/json",
7
+ Accept: "application/json",
8
+ Authorization: `Bearer ${apiKey}`,
9
+ },
10
+ };
11
+ if (body && Object.keys(body).length > 0 && method !== "GET") {
12
+ opts.body = JSON.stringify(body);
13
+ }
14
+ const res = await fetch(`${BASE_URL}${endpoint}`, opts);
15
+ if (!res.ok) {
16
+ const text = await res.text();
17
+ throw new Error(`Bannerbear API error ${res.status}: ${text}`);
18
+ }
19
+ return res.json();
20
+ }
21
+ function getKey(ctx) {
22
+ return ctx.connection.config.apiKey;
23
+ }
24
+ export default function bannerbear(rl) {
25
+ rl.setName("bannerbear");
26
+ rl.setVersion("0.1.0");
27
+ rl.setConnectionSchema({
28
+ apiKey: {
29
+ type: "string",
30
+ required: true,
31
+ description: "Bannerbear API key",
32
+ env: "BANNERBEAR_API_KEY",
33
+ },
34
+ });
35
+ // ── Image ───────────────────────────────────────────
36
+ rl.registerAction("image.create", {
37
+ description: "Create an image from a template",
38
+ inputSchema: {
39
+ templateId: { type: "string", required: true, description: "Template UID" },
40
+ modifications: { type: "array", required: false, description: "Array of modification objects (name, text, color, image_url, etc.)" },
41
+ webhookUrl: { type: "string", required: false, description: "Webhook URL to notify on completion" },
42
+ metadata: { type: "string", required: false, description: "Custom metadata string" },
43
+ waitForImage: { type: "boolean", required: false, description: "Wait for image to finish processing (polls until complete)" },
44
+ maxTries: { type: "number", required: false, description: "Max poll attempts when waiting (default: 3)" },
45
+ },
46
+ async execute(input, ctx) {
47
+ const { templateId, modifications, webhookUrl, metadata, waitForImage, maxTries = 3 } = (input ?? {});
48
+ const apiKey = getKey(ctx);
49
+ const body = { template: templateId };
50
+ if (modifications)
51
+ body.modifications = modifications;
52
+ if (webhookUrl)
53
+ body.webhook_url = webhookUrl;
54
+ if (metadata)
55
+ body.metadata = metadata;
56
+ let result = (await apiRequest(apiKey, "POST", "/images", body));
57
+ if (waitForImage && result.status !== "completed") {
58
+ let tries = maxTries;
59
+ while (tries > 0) {
60
+ await new Promise((r) => setTimeout(r, 2000));
61
+ result = (await apiRequest(apiKey, "GET", `/images/${result.uid}`));
62
+ if (result.status === "completed")
63
+ break;
64
+ tries--;
65
+ }
66
+ if (result.status !== "completed") {
67
+ throw new Error("Image did not finish processing after multiple tries");
68
+ }
69
+ }
70
+ return result;
71
+ },
72
+ });
73
+ rl.registerAction("image.get", {
74
+ description: "Get an image by ID",
75
+ inputSchema: {
76
+ imageId: { type: "string", required: true, description: "Image UID" },
77
+ },
78
+ async execute(input, ctx) {
79
+ const { imageId } = input;
80
+ return apiRequest(getKey(ctx), "GET", `/images/${imageId}`);
81
+ },
82
+ });
83
+ // ── Template ────────────────────────────────────────
84
+ rl.registerAction("template.get", {
85
+ description: "Get a template by ID",
86
+ inputSchema: {
87
+ templateId: { type: "string", required: true, description: "Template UID" },
88
+ },
89
+ async execute(input, ctx) {
90
+ const { templateId } = input;
91
+ return apiRequest(getKey(ctx), "GET", `/templates/${templateId}`);
92
+ },
93
+ });
94
+ rl.registerAction("template.list", {
95
+ description: "List all templates",
96
+ async execute(_input, ctx) {
97
+ return apiRequest(getKey(ctx), "GET", "/templates");
98
+ },
99
+ });
100
+ }
@@ -0,0 +1,180 @@
1
+ async function apiRequest(host, token, method, endpoint, body, qs) {
2
+ const url = new URL(`${host}${endpoint}`);
3
+ if (qs) {
4
+ for (const [k, v] of Object.entries(qs)) {
5
+ if (v !== undefined)
6
+ url.searchParams.set(k, String(v));
7
+ }
8
+ }
9
+ const opts = {
10
+ method,
11
+ headers: {
12
+ "Content-Type": "application/json",
13
+ Authorization: `Token ${token}`,
14
+ },
15
+ };
16
+ if (body && method !== "GET" && method !== "DELETE") {
17
+ opts.body = JSON.stringify(body);
18
+ }
19
+ const res = await fetch(url.toString(), opts);
20
+ if (!res.ok) {
21
+ const text = await res.text();
22
+ throw new Error(`Baserow API error ${res.status}: ${text}`);
23
+ }
24
+ if (res.status === 204)
25
+ return { success: true };
26
+ return res.json();
27
+ }
28
+ async function paginateAll(host, token, endpoint, qs, limit) {
29
+ const results = [];
30
+ let page = 1;
31
+ const size = 100;
32
+ while (true) {
33
+ const data = (await apiRequest(host, token, "GET", endpoint, undefined, {
34
+ ...qs,
35
+ page,
36
+ size,
37
+ }));
38
+ results.push(...(data.results ?? []));
39
+ if (limit && results.length >= limit)
40
+ return results.slice(0, limit);
41
+ if (!data.next)
42
+ break;
43
+ page++;
44
+ }
45
+ return results;
46
+ }
47
+ function getConn(ctx) {
48
+ return {
49
+ host: ctx.connection.config.host.replace(/\/$/, ""),
50
+ token: ctx.connection.config.token,
51
+ };
52
+ }
53
+ export default function baserow(rl) {
54
+ rl.setName("baserow");
55
+ rl.setVersion("0.1.0");
56
+ rl.setConnectionSchema({
57
+ host: {
58
+ type: "string",
59
+ required: true,
60
+ description: "Baserow host URL (e.g. https://api.baserow.io)",
61
+ env: "BASEROW_HOST",
62
+ default: "https://api.baserow.io",
63
+ },
64
+ token: {
65
+ type: "string",
66
+ required: true,
67
+ description: "Baserow database token",
68
+ env: "BASEROW_TOKEN",
69
+ },
70
+ });
71
+ // ── Row ─────────────────────────────────────────────
72
+ rl.registerAction("row.create", {
73
+ description: "Create a row in a table",
74
+ inputSchema: {
75
+ tableId: { type: "string", required: true, description: "Table ID" },
76
+ fields: { type: "object", required: true, description: "Field values as key-value pairs (use field_N keys or field names)" },
77
+ },
78
+ async execute(input, ctx) {
79
+ const { tableId, fields } = input;
80
+ const { host, token } = getConn(ctx);
81
+ return apiRequest(host, token, "POST", `/api/database/rows/table/${tableId}/`, fields);
82
+ },
83
+ });
84
+ rl.registerAction("row.get", {
85
+ description: "Get a row by ID",
86
+ inputSchema: {
87
+ tableId: { type: "string", required: true, description: "Table ID" },
88
+ rowId: { type: "string", required: true, description: "Row ID" },
89
+ },
90
+ async execute(input, ctx) {
91
+ const { tableId, rowId } = input;
92
+ const { host, token } = getConn(ctx);
93
+ return apiRequest(host, token, "GET", `/api/database/rows/table/${tableId}/${rowId}/`);
94
+ },
95
+ });
96
+ rl.registerAction("row.list", {
97
+ description: "List rows from a table with optional filtering and sorting",
98
+ inputSchema: {
99
+ tableId: { type: "string", required: true, description: "Table ID" },
100
+ search: { type: "string", required: false, description: "Search query" },
101
+ orderBy: { type: "string", required: false, description: "Comma-separated field IDs prefixed with +/- (e.g. +field_1,-field_2)" },
102
+ limit: { type: "number", required: false, description: "Max results to return" },
103
+ },
104
+ async execute(input, ctx) {
105
+ const { tableId, search, orderBy, limit } = input;
106
+ const { host, token } = getConn(ctx);
107
+ const qs = {};
108
+ if (search)
109
+ qs.search = search;
110
+ if (orderBy)
111
+ qs.order_by = orderBy;
112
+ return paginateAll(host, token, `/api/database/rows/table/${tableId}/`, qs, limit);
113
+ },
114
+ });
115
+ rl.registerAction("row.update", {
116
+ description: "Update a row (PATCH — only updates specified fields)",
117
+ inputSchema: {
118
+ tableId: { type: "string", required: true, description: "Table ID" },
119
+ rowId: { type: "string", required: true, description: "Row ID" },
120
+ fields: { type: "object", required: true, description: "Fields to update" },
121
+ },
122
+ async execute(input, ctx) {
123
+ const { tableId, rowId, fields } = input;
124
+ const { host, token } = getConn(ctx);
125
+ return apiRequest(host, token, "PATCH", `/api/database/rows/table/${tableId}/${rowId}/`, fields);
126
+ },
127
+ });
128
+ rl.registerAction("row.delete", {
129
+ description: "Delete a row",
130
+ inputSchema: {
131
+ tableId: { type: "string", required: true, description: "Table ID" },
132
+ rowId: { type: "string", required: true, description: "Row ID" },
133
+ },
134
+ async execute(input, ctx) {
135
+ const { tableId, rowId } = input;
136
+ const { host, token } = getConn(ctx);
137
+ await apiRequest(host, token, "DELETE", `/api/database/rows/table/${tableId}/${rowId}/`);
138
+ return { success: true };
139
+ },
140
+ });
141
+ rl.registerAction("row.batchCreate", {
142
+ description: "Create up to 200 rows in one request",
143
+ inputSchema: {
144
+ tableId: { type: "string", required: true, description: "Table ID" },
145
+ items: { type: "array", required: true, description: "Array of row objects with field values" },
146
+ },
147
+ async execute(input, ctx) {
148
+ const { tableId, items } = input;
149
+ const { host, token } = getConn(ctx);
150
+ return apiRequest(host, token, "POST", `/api/database/rows/table/${tableId}/batch/`, { items });
151
+ },
152
+ });
153
+ rl.registerAction("row.batchUpdate", {
154
+ description: "Update up to 200 rows in one request",
155
+ inputSchema: {
156
+ tableId: { type: "string", required: true, description: "Table ID" },
157
+ items: { type: "array", required: true, description: "Array of { id, ...fields } objects" },
158
+ },
159
+ async execute(input, ctx) {
160
+ const { tableId, items } = input;
161
+ const { host, token } = getConn(ctx);
162
+ return apiRequest(host, token, "PATCH", `/api/database/rows/table/${tableId}/batch/`, { items });
163
+ },
164
+ });
165
+ rl.registerAction("row.batchDelete", {
166
+ description: "Delete up to 200 rows in one request",
167
+ inputSchema: {
168
+ tableId: { type: "string", required: true, description: "Table ID" },
169
+ rowIds: { type: "array", required: true, description: "Array of row IDs to delete" },
170
+ },
171
+ async execute(input, ctx) {
172
+ const { tableId, rowIds } = input;
173
+ const { host, token } = getConn(ctx);
174
+ await apiRequest(host, token, "POST", `/api/database/rows/table/${tableId}/batch-delete/`, {
175
+ items: rowIds,
176
+ });
177
+ return { success: true, deleted: rowIds };
178
+ },
179
+ });
180
+ }