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.
- package/.pi/extensions/runline-context/index.ts +135 -0
- package/.pi/extensions/runline-context/package.json +17 -0
- package/README.md +273 -0
- package/dist/commands/actions.d.ts +3 -0
- package/dist/commands/actions.js +43 -0
- package/dist/commands/connection.d.ts +11 -0
- package/dist/commands/connection.js +56 -0
- package/dist/commands/exec.d.ts +5 -0
- package/dist/commands/exec.js +46 -0
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.js +26 -0
- package/dist/commands/plugin.d.ts +10 -0
- package/dist/commands/plugin.js +57 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.js +2 -0
- package/dist/config/loader.d.ts +11 -0
- package/dist/config/loader.js +82 -0
- package/dist/config/types.d.ts +9 -0
- package/dist/config/types.js +5 -0
- package/dist/core/engine.d.ts +21 -0
- package/dist/core/engine.js +280 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +9 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +127 -0
- package/dist/plugin/api.d.ts +32 -0
- package/dist/plugin/api.js +68 -0
- package/dist/plugin/installer.d.ts +27 -0
- package/dist/plugin/installer.js +181 -0
- package/dist/plugin/loader.d.ts +13 -0
- package/dist/plugin/loader.js +164 -0
- package/dist/plugin/registry.d.ts +18 -0
- package/dist/plugin/registry.js +43 -0
- package/dist/plugin/types.d.ts +40 -0
- package/dist/plugin/types.js +1 -0
- package/dist/plugins/actionNetwork/src/index.js +353 -0
- package/dist/plugins/activeCampaign/src/index.js +711 -0
- package/dist/plugins/adalo/src/index.js +131 -0
- package/dist/plugins/affinity/src/index.js +279 -0
- package/dist/plugins/agileCrm/src/index.js +415 -0
- package/dist/plugins/airtable/src/index.js +280 -0
- package/dist/plugins/airtop/src/index.js +527 -0
- package/dist/plugins/apiTemplateIo/src/index.js +86 -0
- package/dist/plugins/asana/src/index.js +413 -0
- package/dist/plugins/autopilot/src/index.js +203 -0
- package/dist/plugins/bambooHr/src/index.js +252 -0
- package/dist/plugins/bannerbear/src/index.js +100 -0
- package/dist/plugins/baserow/src/index.js +180 -0
- package/dist/plugins/beeminder/src/index.js +298 -0
- package/dist/plugins/bitly/src/index.js +107 -0
- package/dist/plugins/bitwarden/src/index.js +383 -0
- package/dist/plugins/box/src/index.js +300 -0
- package/dist/plugins/brandfetch/src/index.js +80 -0
- package/dist/plugins/brevo/src/index.js +305 -0
- package/dist/plugins/bubble/src/index.js +181 -0
- package/dist/plugins/chargebee/src/index.js +126 -0
- package/dist/plugins/circleci/src/index.js +111 -0
- package/dist/plugins/ciscoWebex/src/index.js +245 -0
- package/dist/plugins/clearbit/src/index.js +103 -0
- package/dist/plugins/clickup/src/index.js +1043 -0
- package/dist/plugins/clockify/src/index.js +443 -0
- package/dist/plugins/cloudflare/src/index.js +93 -0
- package/dist/plugins/cockpit/src/index.js +131 -0
- package/dist/plugins/coda/src/index.js +327 -0
- package/dist/plugins/coingecko/src/index.js +244 -0
- package/dist/plugins/contentful/src/index.js +146 -0
- package/dist/plugins/convertkit/src/index.js +270 -0
- package/dist/plugins/copper/src/index.js +140 -0
- package/dist/plugins/cortex/src/index.js +147 -0
- package/dist/plugins/currents/src/index.js +405 -0
- package/dist/plugins/customerIo/src/index.js +184 -0
- package/dist/plugins/databricks/src/index.js +342 -0
- package/dist/plugins/deepl/src/index.js +87 -0
- package/dist/plugins/demio/src/index.js +111 -0
- package/dist/plugins/dhl/src/index.js +40 -0
- package/dist/plugins/discord/src/index.js +275 -0
- package/dist/plugins/discourse/src/index.js +273 -0
- package/dist/plugins/disqus/src/index.js +145 -0
- package/dist/plugins/docker/src/index.js +76 -0
- package/dist/plugins/drift/src/index.js +89 -0
- package/dist/plugins/dropbox/src/index.js +159 -0
- package/dist/plugins/dropcontact/src/index.js +59 -0
- package/dist/plugins/egoi/src/index.js +151 -0
- package/dist/plugins/elasticsearch/src/index.js +157 -0
- package/dist/plugins/emelia/src/index.js +174 -0
- package/dist/plugins/erpnext/src/index.js +121 -0
- package/dist/plugins/facebookGraph/src/index.js +57 -0
- package/dist/plugins/freshdesk/src/index.js +320 -0
- package/dist/plugins/freshservice/src/index.js +146 -0
- package/dist/plugins/freshworksCrm/src/index.js +149 -0
- package/dist/plugins/getresponse/src/index.js +140 -0
- package/dist/plugins/ghost/src/index.js +192 -0
- package/dist/plugins/github/src/index.js +630 -0
- package/dist/plugins/gitlab/src/index.js +358 -0
- package/dist/plugins/gong/src/index.js +126 -0
- package/dist/plugins/gotify/src/index.js +77 -0
- package/dist/plugins/gotowebinar/src/index.js +316 -0
- package/dist/plugins/grafana/src/index.js +250 -0
- package/dist/plugins/graphql/src/index.js +78 -0
- package/dist/plugins/grist/src/index.js +106 -0
- package/dist/plugins/hackernews/src/index.js +89 -0
- package/dist/plugins/halopsa/src/index.js +79 -0
- package/dist/plugins/harvest/src/index.js +163 -0
- package/dist/plugins/helpscout/src/index.js +176 -0
- package/dist/plugins/highlevel/src/index.js +172 -0
- package/dist/plugins/homeAssistant/src/index.js +148 -0
- package/dist/plugins/hubspot/src/index.js +176 -0
- package/dist/plugins/humanticAi/src/index.js +60 -0
- package/dist/plugins/hunter/src/index.js +59 -0
- package/dist/plugins/intercom/src/index.js +156 -0
- package/dist/plugins/iterable/src/index.js +139 -0
- package/dist/plugins/jenkins/src/index.js +132 -0
- package/dist/plugins/jira/src/index.js +229 -0
- package/dist/plugins/keap/src/index.js +502 -0
- package/dist/plugins/kobotoolbox/src/index.js +281 -0
- package/dist/plugins/lemlist/src/index.js +231 -0
- package/dist/plugins/linear/src/index.js +133 -0
- package/dist/plugins/lingvanex/src/index.js +31 -0
- package/dist/plugins/linkedin/src/index.js +80 -0
- package/dist/plugins/lonescale/src/index.js +119 -0
- package/dist/plugins/magento/src/index.js +300 -0
- package/dist/plugins/mailcheck/src/index.js +27 -0
- package/dist/plugins/mailchimp/src/index.js +321 -0
- package/dist/plugins/mailerlite/src/index.js +123 -0
- package/dist/plugins/mailgun/src/index.js +48 -0
- package/dist/plugins/mailjet/src/index.js +155 -0
- package/dist/plugins/mandrill/src/index.js +145 -0
- package/dist/plugins/marketstack/src/index.js +97 -0
- package/dist/plugins/matrix/src/index.js +194 -0
- package/dist/plugins/mattermost/src/index.js +331 -0
- package/dist/plugins/mautic/src/index.js +311 -0
- package/dist/plugins/medium/src/index.js +77 -0
- package/dist/plugins/messagebird/src/index.js +57 -0
- package/dist/plugins/metabase/src/index.js +130 -0
- package/dist/plugins/misp/src/index.js +476 -0
- package/dist/plugins/mocean/src/index.js +67 -0
- package/dist/plugins/monday/src/index.js +231 -0
- package/dist/plugins/monicaCrm/src/index.js +52 -0
- package/dist/plugins/msg91/src/index.js +31 -0
- package/dist/plugins/nasa/src/index.js +146 -0
- package/dist/plugins/netlify/src/index.js +151 -0
- package/dist/plugins/netscalerAdc/src/index.js +131 -0
- package/dist/plugins/nextcloud/src/index.js +263 -0
- package/dist/plugins/nocodb/src/index.js +130 -0
- package/dist/plugins/notion/src/index.js +112 -0
- package/dist/plugins/npm/src/index.js +104 -0
- package/dist/plugins/odoo/src/index.js +157 -0
- package/dist/plugins/okta/src/index.js +141 -0
- package/dist/plugins/oneSimpleApi/src/index.js +155 -0
- package/dist/plugins/onfleet/src/index.js +254 -0
- package/dist/plugins/openThesaurus/src/index.js +32 -0
- package/dist/plugins/openweathermap/src/index.js +60 -0
- package/dist/plugins/oura/src/index.js +62 -0
- package/dist/plugins/paddle/src/index.js +247 -0
- package/dist/plugins/pagerduty/src/index.js +201 -0
- package/dist/plugins/paypal/src/index.js +106 -0
- package/dist/plugins/peekalink/src/index.js +35 -0
- package/dist/plugins/phantombuster/src/index.js +94 -0
- package/dist/plugins/philipsHue/src/index.js +98 -0
- package/dist/plugins/pipedrive/src/index.js +169 -0
- package/dist/plugins/plivo/src/index.js +66 -0
- package/dist/plugins/postbin/src/index.js +93 -0
- package/dist/plugins/posthog/src/index.js +113 -0
- package/dist/plugins/profitwell/src/index.js +50 -0
- package/dist/plugins/pushbullet/src/index.js +102 -0
- package/dist/plugins/pushcut/src/index.js +39 -0
- package/dist/plugins/pushover/src/index.js +65 -0
- package/dist/plugins/quickbase/src/index.js +153 -0
- package/dist/plugins/quickbooks/src/index.js +73 -0
- package/dist/plugins/quickchart/src/index.js +36 -0
- package/dist/plugins/raindrop/src/index.js +209 -0
- package/dist/plugins/reddit/src/index.js +185 -0
- package/dist/plugins/rocketchat/src/index.js +53 -0
- package/dist/plugins/rundeck/src/index.js +62 -0
- package/dist/plugins/salesforce/src/index.js +94 -0
- package/dist/plugins/salesmate/src/index.js +83 -0
- package/dist/plugins/securityScorecard/src/index.js +200 -0
- package/dist/plugins/segment/src/index.js +125 -0
- package/dist/plugins/sendgrid/src/index.js +187 -0
- package/dist/plugins/sendy/src/index.js +138 -0
- package/dist/plugins/sentry/src/index.js +233 -0
- package/dist/plugins/servicenow/src/index.js +108 -0
- package/dist/plugins/shopify/src/index.js +222 -0
- package/dist/plugins/signl4/src/index.js +61 -0
- package/dist/plugins/slack/src/index.js +236 -0
- package/dist/plugins/sms77/src/index.js +63 -0
- package/dist/plugins/splunk/src/index.js +207 -0
- package/dist/plugins/spotify/src/index.js +188 -0
- package/dist/plugins/stackby/src/index.js +82 -0
- package/dist/plugins/storyblok/src/index.js +141 -0
- package/dist/plugins/strapi/src/index.js +152 -0
- package/dist/plugins/strava/src/index.js +137 -0
- package/dist/plugins/stripe/src/index.js +222 -0
- package/dist/plugins/supabase/src/index.js +121 -0
- package/dist/plugins/syncromsp/src/index.js +255 -0
- package/dist/plugins/tapfiliate/src/index.js +125 -0
- package/dist/plugins/telegram/src/index.js +233 -0
- package/dist/plugins/thehive/src/index.js +142 -0
- package/dist/plugins/thehiveProject/src/index.js +194 -0
- package/dist/plugins/todoist/src/index.js +244 -0
- package/dist/plugins/travisci/src/index.js +71 -0
- package/dist/plugins/trello/src/index.js +341 -0
- package/dist/plugins/twake/src/index.js +40 -0
- package/dist/plugins/twilio/src/index.js +75 -0
- package/dist/plugins/twist/src/index.js +90 -0
- package/dist/plugins/twitter/src/index.js +123 -0
- package/dist/plugins/unleashedSoftware/src/index.js +84 -0
- package/dist/plugins/uplead/src/index.js +59 -0
- package/dist/plugins/uproc/src/index.js +34 -0
- package/dist/plugins/uptimerobot/src/index.js +264 -0
- package/dist/plugins/urlscanio/src/index.js +64 -0
- package/dist/plugins/vero/src/index.js +80 -0
- package/dist/plugins/vonage/src/index.js +42 -0
- package/dist/plugins/wekan/src/index.js +91 -0
- package/dist/plugins/woocommerce/src/index.js +92 -0
- package/dist/plugins/wordpress/src/index.js +121 -0
- package/dist/plugins/xero/src/index.js +136 -0
- package/dist/plugins/yourls/src/index.js +56 -0
- package/dist/plugins/zammad/src/index.js +91 -0
- package/dist/plugins/zendesk/src/index.js +137 -0
- package/dist/plugins/zoho/src/index.js +85 -0
- package/dist/plugins/zoom/src/index.js +122 -0
- package/dist/plugins/zulip/src/index.js +170 -0
- package/dist/sdk.d.ts +38 -0
- package/dist/sdk.js +105 -0
- package/dist/utils/cli.d.ts +13 -0
- package/dist/utils/cli.js +32 -0
- package/dist/utils/output.d.ts +4 -0
- package/dist/utils/output.js +13 -0
- package/package.json +57 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
function getConn(ctx) {
|
|
2
|
+
const c = ctx.connection.config;
|
|
3
|
+
const url = c.url.replace(/\/$/, "");
|
|
4
|
+
return { url, username: c.username, password: c.password };
|
|
5
|
+
}
|
|
6
|
+
async function apiRequest(conn, method, resource, body) {
|
|
7
|
+
const init = {
|
|
8
|
+
method,
|
|
9
|
+
headers: {
|
|
10
|
+
"Content-Type": "application/json",
|
|
11
|
+
"X-NITRO-USER": conn.username,
|
|
12
|
+
"X-NITRO-PASS": conn.password,
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
if (body && Object.keys(body).length > 0)
|
|
16
|
+
init.body = JSON.stringify(body);
|
|
17
|
+
const res = await fetch(`${conn.url}/nitro/v1${resource}`, init);
|
|
18
|
+
if (!res.ok)
|
|
19
|
+
throw new Error(`Netscaler ADC API error ${res.status}: ${await res.text()}`);
|
|
20
|
+
const text = await res.text();
|
|
21
|
+
return text ? JSON.parse(text) : {};
|
|
22
|
+
}
|
|
23
|
+
export default function netscalerAdc(rl) {
|
|
24
|
+
rl.setName("netscalerAdc");
|
|
25
|
+
rl.setVersion("0.1.0");
|
|
26
|
+
rl.setConnectionSchema({
|
|
27
|
+
url: { type: "string", required: true, description: "Netscaler ADC base URL (e.g. https://adc.example.com)", env: "NETSCALER_URL" },
|
|
28
|
+
username: { type: "string", required: true, description: "Nitro API username", env: "NETSCALER_USERNAME" },
|
|
29
|
+
password: { type: "string", required: true, description: "Nitro API password", env: "NETSCALER_PASSWORD" },
|
|
30
|
+
});
|
|
31
|
+
rl.registerAction("certificate.create", {
|
|
32
|
+
description: "Create an SSL certificate on the appliance",
|
|
33
|
+
inputSchema: {
|
|
34
|
+
certificateFileName: { type: "string", required: true, description: "Name (and optional path) for the generated certificate file. Default path: /nsconfig/ssl/" },
|
|
35
|
+
certificateFormat: { type: "string", required: true, description: "PEM or DER" },
|
|
36
|
+
certificateType: { type: "string", required: true, description: "ROOT_CERT, INTM_CERT, SRVR_CERT, or CLNT_CERT" },
|
|
37
|
+
certificateRequestFileName: { type: "string", required: true, description: "Name/path for the CSR file" },
|
|
38
|
+
privateKeyFileName: { type: "string", required: false, description: "Private key file name (required for ROOT_CERT)" },
|
|
39
|
+
caCertificateFileName: { type: "string", required: false, description: "CA certificate file (required for non-ROOT_CERT)" },
|
|
40
|
+
caCertificateFileFormat: { type: "string", required: false, description: "PEM or DER (for CA cert)" },
|
|
41
|
+
caPrivateKeyFileName: { type: "string", required: false, description: "CA private key file" },
|
|
42
|
+
caPrivateKeyFileFormat: { type: "string", required: false, description: "PEM or DER (for CA key)" },
|
|
43
|
+
caSerialFileNumber: { type: "string", required: false, description: "CA serial number file" },
|
|
44
|
+
pempassphrase: { type: "string", required: false, description: "PEM passphrase for encrypted key" },
|
|
45
|
+
subjectaltname: { type: "string", required: false, description: "Subject Alternative Name (SAN)" },
|
|
46
|
+
days: { type: "string", required: false, description: "Validity period in days" },
|
|
47
|
+
},
|
|
48
|
+
async execute(input, ctx) {
|
|
49
|
+
const p = input;
|
|
50
|
+
const conn = getConn(ctx);
|
|
51
|
+
const body = {
|
|
52
|
+
reqfile: p.certificateRequestFileName,
|
|
53
|
+
certfile: p.certificateFileName,
|
|
54
|
+
certform: p.certificateFormat,
|
|
55
|
+
certType: p.certificateType,
|
|
56
|
+
};
|
|
57
|
+
if (p.certificateType === "ROOT_CERT") {
|
|
58
|
+
if (p.privateKeyFileName)
|
|
59
|
+
body.keyfile = p.privateKeyFileName;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
if (p.caCertificateFileName)
|
|
63
|
+
body.cacert = p.caCertificateFileName;
|
|
64
|
+
if (p.caCertificateFileFormat)
|
|
65
|
+
body.cacertform = p.caCertificateFileFormat;
|
|
66
|
+
if (p.caPrivateKeyFileName)
|
|
67
|
+
body.cakey = p.caPrivateKeyFileName;
|
|
68
|
+
if (p.caPrivateKeyFileFormat)
|
|
69
|
+
body.cakeyform = p.caPrivateKeyFileFormat;
|
|
70
|
+
if (p.caSerialFileNumber)
|
|
71
|
+
body.caserial = p.caSerialFileNumber;
|
|
72
|
+
}
|
|
73
|
+
if (p.pempassphrase)
|
|
74
|
+
body.pempassphrase = p.pempassphrase;
|
|
75
|
+
if (p.subjectaltname)
|
|
76
|
+
body.subjectaltname = p.subjectaltname;
|
|
77
|
+
if (p.days)
|
|
78
|
+
body.days = p.days;
|
|
79
|
+
await apiRequest(conn, "POST", "/config/sslcert?action=create", { sslcert: body });
|
|
80
|
+
return { success: true };
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
rl.registerAction("certificate.install", {
|
|
84
|
+
description: "Install an SSL certificate-key pair on the appliance",
|
|
85
|
+
inputSchema: {
|
|
86
|
+
certificateKeyPairName: { type: "string", required: true, description: "Name for the certificate-key pair" },
|
|
87
|
+
certificateFileName: { type: "string", required: true, description: "X509 certificate file name/path" },
|
|
88
|
+
privateKeyFileName: { type: "string", required: true, description: "Private key file name/path" },
|
|
89
|
+
certificateFormat: { type: "string", required: true, description: "PEM or DER" },
|
|
90
|
+
password: { type: "string", required: false, description: "PEM passphrase (required for PEM format)" },
|
|
91
|
+
certificateBundle: { type: "boolean", required: false, description: "Parse certificate chain as single file (PEM only)" },
|
|
92
|
+
notifyExpiration: { type: "boolean", required: false, description: "Alert when certificate is about to expire" },
|
|
93
|
+
notificationPeriod: { type: "number", required: false, description: "Days before expiry to alert (10-100, default 10)" },
|
|
94
|
+
},
|
|
95
|
+
async execute(input, ctx) {
|
|
96
|
+
const p = input;
|
|
97
|
+
const conn = getConn(ctx);
|
|
98
|
+
const body = {
|
|
99
|
+
certkey: p.certificateKeyPairName,
|
|
100
|
+
cert: p.certificateFileName,
|
|
101
|
+
key: p.privateKeyFileName,
|
|
102
|
+
inform: p.certificateFormat,
|
|
103
|
+
};
|
|
104
|
+
if (p.certificateFormat === "PEM") {
|
|
105
|
+
if (p.password)
|
|
106
|
+
body.passplain = p.password;
|
|
107
|
+
body.bundle = p.certificateBundle ? "YES" : "NO";
|
|
108
|
+
}
|
|
109
|
+
if (p.notifyExpiration) {
|
|
110
|
+
body.expirymonitor = "ENABLED";
|
|
111
|
+
body.notificationperiod = p.notificationPeriod ?? 10;
|
|
112
|
+
}
|
|
113
|
+
await apiRequest(conn, "POST", "/config/sslcertkey", { sslcertkey: body });
|
|
114
|
+
return { success: true };
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
rl.registerAction("file.delete", {
|
|
118
|
+
description: "Delete a file from the Netscaler ADC appliance",
|
|
119
|
+
inputSchema: {
|
|
120
|
+
fileName: { type: "string", required: true, description: "File name (without path)" },
|
|
121
|
+
fileLocation: { type: "string", required: false, description: "File location (default /nsconfig/ssl/)" },
|
|
122
|
+
},
|
|
123
|
+
async execute(input, ctx) {
|
|
124
|
+
const { fileName, fileLocation } = input;
|
|
125
|
+
const conn = getConn(ctx);
|
|
126
|
+
const loc = encodeURIComponent(fileLocation ?? "/nsconfig/ssl/");
|
|
127
|
+
await apiRequest(conn, "DELETE", `/config/systemfile?args=filename:${fileName},filelocation:${loc}`);
|
|
128
|
+
return { success: true };
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
function getConn(ctx) {
|
|
2
|
+
const c = ctx.connection.config;
|
|
3
|
+
return {
|
|
4
|
+
webDavUrl: c.webDavUrl.replace(/\/$/, ""),
|
|
5
|
+
username: c.username,
|
|
6
|
+
password: c.password,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function authHeader(conn) {
|
|
10
|
+
// Nextcloud uses Basic auth for access token API
|
|
11
|
+
return "Basic " + btoa(`${conn.username}:${conn.password}`);
|
|
12
|
+
}
|
|
13
|
+
/** Base URL without /remote.php/webdav — for OCS and share APIs */
|
|
14
|
+
function baseUrl(conn) {
|
|
15
|
+
return conn.webDavUrl.replace("/remote.php/webdav", "");
|
|
16
|
+
}
|
|
17
|
+
/** Make a WebDAV request */
|
|
18
|
+
async function webdavRequest(conn, method, path, headers) {
|
|
19
|
+
const url = `${conn.webDavUrl}/${encodeURI(path.replace(/^\//, ""))}`;
|
|
20
|
+
const res = await fetch(url, {
|
|
21
|
+
method,
|
|
22
|
+
headers: { Authorization: authHeader(conn), ...headers },
|
|
23
|
+
});
|
|
24
|
+
if (!res.ok)
|
|
25
|
+
throw new Error(`Nextcloud WebDAV error ${res.status}: ${await res.text()}`);
|
|
26
|
+
return res.text();
|
|
27
|
+
}
|
|
28
|
+
/** Make an OCS API request (returns XML text) */
|
|
29
|
+
async function ocsRequest(conn, method, endpoint, body, qs) {
|
|
30
|
+
const url = new URL(`${baseUrl(conn)}/${endpoint}`);
|
|
31
|
+
if (qs) {
|
|
32
|
+
for (const [k, v] of Object.entries(qs)) {
|
|
33
|
+
if (v !== undefined && v !== null)
|
|
34
|
+
url.searchParams.set(k, String(v));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Request JSON format via OCS
|
|
38
|
+
url.searchParams.set("format", "json");
|
|
39
|
+
const headers = {
|
|
40
|
+
Authorization: authHeader(conn),
|
|
41
|
+
"OCS-APIRequest": "true",
|
|
42
|
+
};
|
|
43
|
+
const init = { method, headers };
|
|
44
|
+
if (body) {
|
|
45
|
+
headers["Content-Type"] = "application/x-www-form-urlencoded";
|
|
46
|
+
init.body = body;
|
|
47
|
+
}
|
|
48
|
+
const res = await fetch(url.toString(), init);
|
|
49
|
+
if (!res.ok)
|
|
50
|
+
throw new Error(`Nextcloud OCS error ${res.status}: ${await res.text()}`);
|
|
51
|
+
return res.text();
|
|
52
|
+
}
|
|
53
|
+
/** Parse OCS JSON response */
|
|
54
|
+
function parseOcs(text) {
|
|
55
|
+
const json = JSON.parse(text);
|
|
56
|
+
const meta = json?.ocs?.meta;
|
|
57
|
+
if (meta && meta.status !== "ok" && meta.statuscode >= 300) {
|
|
58
|
+
throw new Error(`Nextcloud OCS error: ${meta.message || meta.status}`);
|
|
59
|
+
}
|
|
60
|
+
return json?.ocs?.data;
|
|
61
|
+
}
|
|
62
|
+
export default function nextcloud(rl) {
|
|
63
|
+
rl.setName("nextcloud");
|
|
64
|
+
rl.setVersion("0.1.0");
|
|
65
|
+
rl.setConnectionSchema({
|
|
66
|
+
webDavUrl: { type: "string", required: true, description: "Nextcloud WebDAV URL (e.g. https://cloud.example.com/remote.php/webdav)", env: "NEXTCLOUD_WEBDAV_URL" },
|
|
67
|
+
username: { type: "string", required: true, description: "Nextcloud username", env: "NEXTCLOUD_USERNAME" },
|
|
68
|
+
password: { type: "string", required: true, description: "Nextcloud password or app token", env: "NEXTCLOUD_PASSWORD" },
|
|
69
|
+
});
|
|
70
|
+
// ── File/Folder operations (non-binary) ─────────────
|
|
71
|
+
rl.registerAction("file.copy", {
|
|
72
|
+
description: "Copy a file on Nextcloud",
|
|
73
|
+
inputSchema: {
|
|
74
|
+
path: { type: "string", required: true, description: "Source file path (e.g. /invoices/original.txt)" },
|
|
75
|
+
toPath: { type: "string", required: true, description: "Destination file path" },
|
|
76
|
+
},
|
|
77
|
+
async execute(input, ctx) {
|
|
78
|
+
const { path, toPath } = input;
|
|
79
|
+
const conn = getConn(ctx);
|
|
80
|
+
await webdavRequest(conn, "COPY", path, {
|
|
81
|
+
Destination: `${conn.webDavUrl}/${encodeURI(toPath.replace(/^\//, ""))}`,
|
|
82
|
+
});
|
|
83
|
+
return { success: true };
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
rl.registerAction("file.delete", {
|
|
87
|
+
description: "Delete a file on Nextcloud",
|
|
88
|
+
inputSchema: {
|
|
89
|
+
path: { type: "string", required: true, description: "File path to delete" },
|
|
90
|
+
},
|
|
91
|
+
async execute(input, ctx) {
|
|
92
|
+
const { path } = input;
|
|
93
|
+
await webdavRequest(getConn(ctx), "DELETE", path);
|
|
94
|
+
return { success: true };
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
rl.registerAction("file.move", {
|
|
98
|
+
description: "Move/rename a file on Nextcloud",
|
|
99
|
+
inputSchema: {
|
|
100
|
+
path: { type: "string", required: true, description: "Source file path" },
|
|
101
|
+
toPath: { type: "string", required: true, description: "Destination file path" },
|
|
102
|
+
},
|
|
103
|
+
async execute(input, ctx) {
|
|
104
|
+
const { path, toPath } = input;
|
|
105
|
+
const conn = getConn(ctx);
|
|
106
|
+
await webdavRequest(conn, "MOVE", path, {
|
|
107
|
+
Destination: `${conn.webDavUrl}/${encodeURI(toPath.replace(/^\//, ""))}`,
|
|
108
|
+
});
|
|
109
|
+
return { success: true };
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
rl.registerAction("file.share", {
|
|
113
|
+
description: "Share a file or folder via Nextcloud sharing API",
|
|
114
|
+
inputSchema: {
|
|
115
|
+
path: { type: "string", required: true, description: "File/folder path to share" },
|
|
116
|
+
shareType: { type: "number", required: true, description: "0=user, 1=group, 3=public link, 4=email, 7=circle" },
|
|
117
|
+
shareWith: { type: "string", required: false, description: "User, group, email, or circle ID to share with (not needed for public link)" },
|
|
118
|
+
permissions: { type: "number", required: false, description: "1=read, 2=update, 4=create, 8=delete, 31=all (default 1)" },
|
|
119
|
+
password: { type: "string", required: false, description: "Password for public link shares" },
|
|
120
|
+
},
|
|
121
|
+
async execute(input, ctx) {
|
|
122
|
+
const p = input;
|
|
123
|
+
const params = new URLSearchParams();
|
|
124
|
+
params.set("path", p.path);
|
|
125
|
+
params.set("shareType", String(p.shareType));
|
|
126
|
+
if (p.shareWith)
|
|
127
|
+
params.set("shareWith", p.shareWith);
|
|
128
|
+
if (p.permissions)
|
|
129
|
+
params.set("permissions", String(p.permissions));
|
|
130
|
+
if (p.password)
|
|
131
|
+
params.set("password", p.password);
|
|
132
|
+
const text = await ocsRequest(getConn(ctx), "POST", "ocs/v2.php/apps/files_sharing/api/v1/shares", params.toString());
|
|
133
|
+
return parseOcs(text);
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
rl.registerAction("folder.create", {
|
|
137
|
+
description: "Create a folder on Nextcloud",
|
|
138
|
+
inputSchema: {
|
|
139
|
+
path: { type: "string", required: true, description: "Folder path to create (e.g. /invoices/2019)" },
|
|
140
|
+
},
|
|
141
|
+
async execute(input, ctx) {
|
|
142
|
+
const { path } = input;
|
|
143
|
+
await webdavRequest(getConn(ctx), "MKCOL", path);
|
|
144
|
+
return { success: true };
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
rl.registerAction("folder.delete", {
|
|
148
|
+
description: "Delete a folder on Nextcloud",
|
|
149
|
+
inputSchema: {
|
|
150
|
+
path: { type: "string", required: true, description: "Folder path to delete" },
|
|
151
|
+
},
|
|
152
|
+
async execute(input, ctx) {
|
|
153
|
+
const { path } = input;
|
|
154
|
+
await webdavRequest(getConn(ctx), "DELETE", path);
|
|
155
|
+
return { success: true };
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
rl.registerAction("folder.copy", {
|
|
159
|
+
description: "Copy a folder on Nextcloud",
|
|
160
|
+
inputSchema: {
|
|
161
|
+
path: { type: "string", required: true, description: "Source folder path" },
|
|
162
|
+
toPath: { type: "string", required: true, description: "Destination folder path" },
|
|
163
|
+
},
|
|
164
|
+
async execute(input, ctx) {
|
|
165
|
+
const { path, toPath } = input;
|
|
166
|
+
const conn = getConn(ctx);
|
|
167
|
+
await webdavRequest(conn, "COPY", path, {
|
|
168
|
+
Destination: `${conn.webDavUrl}/${encodeURI(toPath.replace(/^\//, ""))}`,
|
|
169
|
+
});
|
|
170
|
+
return { success: true };
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
rl.registerAction("folder.move", {
|
|
174
|
+
description: "Move/rename a folder on Nextcloud",
|
|
175
|
+
inputSchema: {
|
|
176
|
+
path: { type: "string", required: true, description: "Source folder path" },
|
|
177
|
+
toPath: { type: "string", required: true, description: "Destination folder path" },
|
|
178
|
+
},
|
|
179
|
+
async execute(input, ctx) {
|
|
180
|
+
const { path, toPath } = input;
|
|
181
|
+
const conn = getConn(ctx);
|
|
182
|
+
await webdavRequest(conn, "MOVE", path, {
|
|
183
|
+
Destination: `${conn.webDavUrl}/${encodeURI(toPath.replace(/^\//, ""))}`,
|
|
184
|
+
});
|
|
185
|
+
return { success: true };
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
// ── User operations ─────────────────────────────────
|
|
189
|
+
rl.registerAction("user.create", {
|
|
190
|
+
description: "Create a user on Nextcloud",
|
|
191
|
+
inputSchema: {
|
|
192
|
+
userId: { type: "string", required: true, description: "Username" },
|
|
193
|
+
email: { type: "string", required: true, description: "Email address" },
|
|
194
|
+
displayName: { type: "string", required: false, description: "Display name" },
|
|
195
|
+
},
|
|
196
|
+
async execute(input, ctx) {
|
|
197
|
+
const { userId, email, displayName } = input;
|
|
198
|
+
const params = new URLSearchParams();
|
|
199
|
+
params.set("userid", userId);
|
|
200
|
+
params.set("email", email);
|
|
201
|
+
if (displayName)
|
|
202
|
+
params.set("displayName", displayName);
|
|
203
|
+
const text = await ocsRequest(getConn(ctx), "POST", "ocs/v1.php/cloud/users", params.toString());
|
|
204
|
+
return parseOcs(text);
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
rl.registerAction("user.delete", {
|
|
208
|
+
description: "Delete a user on Nextcloud",
|
|
209
|
+
inputSchema: {
|
|
210
|
+
userId: { type: "string", required: true, description: "Username" },
|
|
211
|
+
},
|
|
212
|
+
async execute(input, ctx) {
|
|
213
|
+
const { userId } = input;
|
|
214
|
+
const text = await ocsRequest(getConn(ctx), "DELETE", `ocs/v1.php/cloud/users/${userId}`);
|
|
215
|
+
return parseOcs(text);
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
rl.registerAction("user.get", {
|
|
219
|
+
description: "Get a user's information",
|
|
220
|
+
inputSchema: {
|
|
221
|
+
userId: { type: "string", required: true, description: "Username" },
|
|
222
|
+
},
|
|
223
|
+
async execute(input, ctx) {
|
|
224
|
+
const { userId } = input;
|
|
225
|
+
const text = await ocsRequest(getConn(ctx), "GET", `ocs/v1.php/cloud/users/${userId}`);
|
|
226
|
+
return parseOcs(text);
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
rl.registerAction("user.list", {
|
|
230
|
+
description: "List all users",
|
|
231
|
+
inputSchema: {
|
|
232
|
+
limit: { type: "number", required: false, description: "Max results" },
|
|
233
|
+
offset: { type: "number", required: false, description: "Offset" },
|
|
234
|
+
search: { type: "string", required: false, description: "Search string" },
|
|
235
|
+
},
|
|
236
|
+
async execute(input, ctx) {
|
|
237
|
+
const p = (input ?? {});
|
|
238
|
+
const qs = {};
|
|
239
|
+
if (p.limit)
|
|
240
|
+
qs.limit = p.limit;
|
|
241
|
+
if (p.offset)
|
|
242
|
+
qs.offset = p.offset;
|
|
243
|
+
if (p.search)
|
|
244
|
+
qs.search = p.search;
|
|
245
|
+
const text = await ocsRequest(getConn(ctx), "GET", "ocs/v1.php/cloud/users", undefined, qs);
|
|
246
|
+
return parseOcs(text);
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
rl.registerAction("user.update", {
|
|
250
|
+
description: "Update a user attribute (email, displayname, password, address, twitter, website)",
|
|
251
|
+
inputSchema: {
|
|
252
|
+
userId: { type: "string", required: true, description: "Username" },
|
|
253
|
+
key: { type: "string", required: true, description: "Attribute key: email, displayname, password, address, twitter, website" },
|
|
254
|
+
value: { type: "string", required: true, description: "New value" },
|
|
255
|
+
},
|
|
256
|
+
async execute(input, ctx) {
|
|
257
|
+
const { userId, key, value } = input;
|
|
258
|
+
const body = `key=${encodeURIComponent(key)}&value=${encodeURIComponent(value)}`;
|
|
259
|
+
const text = await ocsRequest(getConn(ctx), "PUT", `ocs/v1.php/cloud/users/${userId}`, body);
|
|
260
|
+
return parseOcs(text);
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
function getConn(ctx) {
|
|
2
|
+
const c = ctx.connection.config;
|
|
3
|
+
const host = c.host.replace(/\/$/, "");
|
|
4
|
+
return { host, token: c.apiToken };
|
|
5
|
+
}
|
|
6
|
+
async function apiRequest(conn, method, endpoint, body, qs) {
|
|
7
|
+
const url = new URL(`${conn.host}${endpoint}`);
|
|
8
|
+
if (qs) {
|
|
9
|
+
for (const [k, v] of Object.entries(qs)) {
|
|
10
|
+
if (v !== undefined && v !== null)
|
|
11
|
+
url.searchParams.set(k, String(v));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const init = {
|
|
15
|
+
method,
|
|
16
|
+
headers: {
|
|
17
|
+
"xc-token": conn.token,
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
if (body !== undefined)
|
|
22
|
+
init.body = JSON.stringify(body);
|
|
23
|
+
const res = await fetch(url.toString(), init);
|
|
24
|
+
if (!res.ok)
|
|
25
|
+
throw new Error(`NocoDB API error ${res.status}: ${await res.text()}`);
|
|
26
|
+
const text = await res.text();
|
|
27
|
+
return text ? JSON.parse(text) : {};
|
|
28
|
+
}
|
|
29
|
+
async function paginate(conn, endpoint, qs = {}) {
|
|
30
|
+
const all = [];
|
|
31
|
+
qs.limit = 100;
|
|
32
|
+
qs.offset = 0;
|
|
33
|
+
let isLast = false;
|
|
34
|
+
while (!isLast) {
|
|
35
|
+
const data = (await apiRequest(conn, "GET", endpoint, undefined, qs));
|
|
36
|
+
const list = (data.list ?? []);
|
|
37
|
+
all.push(...list);
|
|
38
|
+
const pageInfo = data.pageInfo;
|
|
39
|
+
isLast = pageInfo?.isLastPage === true || list.length === 0;
|
|
40
|
+
qs.offset = qs.offset + qs.limit;
|
|
41
|
+
}
|
|
42
|
+
return all;
|
|
43
|
+
}
|
|
44
|
+
export default function nocodb(rl) {
|
|
45
|
+
rl.setName("nocodb");
|
|
46
|
+
rl.setVersion("0.1.0");
|
|
47
|
+
rl.setConnectionSchema({
|
|
48
|
+
host: { type: "string", required: true, description: "NocoDB host URL (e.g. https://nocodb.example.com)", env: "NOCODB_HOST" },
|
|
49
|
+
apiToken: { type: "string", required: true, description: "NocoDB API token (xc-token)", env: "NOCODB_API_TOKEN" },
|
|
50
|
+
});
|
|
51
|
+
rl.registerAction("row.create", {
|
|
52
|
+
description: "Create one or more rows in a NocoDB table (v2 API)",
|
|
53
|
+
inputSchema: {
|
|
54
|
+
tableId: { type: "string", required: true, description: "Table ID" },
|
|
55
|
+
rows: { type: "object", required: true, description: "Array of row objects to create" },
|
|
56
|
+
},
|
|
57
|
+
async execute(input, ctx) {
|
|
58
|
+
const { tableId, rows } = input;
|
|
59
|
+
const conn = getConn(ctx);
|
|
60
|
+
return apiRequest(conn, "POST", `/api/v2/tables/${tableId}/records`, rows);
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
rl.registerAction("row.get", {
|
|
64
|
+
description: "Get a single row by ID",
|
|
65
|
+
inputSchema: {
|
|
66
|
+
tableId: { type: "string", required: true, description: "Table ID" },
|
|
67
|
+
rowId: { type: "string", required: true, description: "Row ID" },
|
|
68
|
+
},
|
|
69
|
+
async execute(input, ctx) {
|
|
70
|
+
const { tableId, rowId } = input;
|
|
71
|
+
return apiRequest(getConn(ctx), "GET", `/api/v2/tables/${tableId}/records/${rowId}`);
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
rl.registerAction("row.list", {
|
|
75
|
+
description: "List rows from a NocoDB table",
|
|
76
|
+
inputSchema: {
|
|
77
|
+
tableId: { type: "string", required: true, description: "Table ID" },
|
|
78
|
+
limit: { type: "number", required: false, description: "Max rows to return (default: all)" },
|
|
79
|
+
where: { type: "string", required: false, description: "Filter formula, e.g. (name,like,example%)" },
|
|
80
|
+
sort: { type: "string", required: false, description: "Sort string, e.g. -fieldName for desc" },
|
|
81
|
+
fields: { type: "string", required: false, description: "Comma-separated field names to return" },
|
|
82
|
+
viewId: { type: "string", required: false, description: "View ID to filter by" },
|
|
83
|
+
offset: { type: "number", required: false, description: "Offset for pagination" },
|
|
84
|
+
},
|
|
85
|
+
async execute(input, ctx) {
|
|
86
|
+
const p = (input ?? {});
|
|
87
|
+
const conn = getConn(ctx);
|
|
88
|
+
const endpoint = `/api/v2/tables/${p.tableId}/records`;
|
|
89
|
+
const qs = {};
|
|
90
|
+
if (p.where)
|
|
91
|
+
qs.where = p.where;
|
|
92
|
+
if (p.sort)
|
|
93
|
+
qs.sort = p.sort;
|
|
94
|
+
if (p.fields)
|
|
95
|
+
qs.fields = p.fields;
|
|
96
|
+
if (p.viewId)
|
|
97
|
+
qs.viewId = p.viewId;
|
|
98
|
+
if (p.offset)
|
|
99
|
+
qs.offset = p.offset;
|
|
100
|
+
if (p.limit) {
|
|
101
|
+
qs.limit = p.limit;
|
|
102
|
+
const data = (await apiRequest(conn, "GET", endpoint, undefined, qs));
|
|
103
|
+
return data.list;
|
|
104
|
+
}
|
|
105
|
+
return paginate(conn, endpoint, qs);
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
rl.registerAction("row.update", {
|
|
109
|
+
description: "Update one or more rows (include primary key in each row object)",
|
|
110
|
+
inputSchema: {
|
|
111
|
+
tableId: { type: "string", required: true, description: "Table ID" },
|
|
112
|
+
rows: { type: "object", required: true, description: "Array of row objects with primary key included" },
|
|
113
|
+
},
|
|
114
|
+
async execute(input, ctx) {
|
|
115
|
+
const { tableId, rows } = input;
|
|
116
|
+
return apiRequest(getConn(ctx), "PATCH", `/api/v2/tables/${tableId}/records`, rows);
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
rl.registerAction("row.delete", {
|
|
120
|
+
description: "Delete one or more rows by ID",
|
|
121
|
+
inputSchema: {
|
|
122
|
+
tableId: { type: "string", required: true, description: "Table ID" },
|
|
123
|
+
ids: { type: "object", required: true, description: "Array of objects with primary key, e.g. [{Id: 1}, {Id: 2}]" },
|
|
124
|
+
},
|
|
125
|
+
async execute(input, ctx) {
|
|
126
|
+
const { tableId, ids } = input;
|
|
127
|
+
return apiRequest(getConn(ctx), "DELETE", `/api/v2/tables/${tableId}/records`, ids);
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const BASE = "https://api.notion.com/v1";
|
|
2
|
+
const NOTION_VERSION = "2021-08-16";
|
|
3
|
+
async function api(token, method, endpoint, body, qs) {
|
|
4
|
+
const url = new URL(`${BASE}${endpoint}`);
|
|
5
|
+
if (qs) {
|
|
6
|
+
for (const [k, v] of Object.entries(qs)) {
|
|
7
|
+
if (v !== undefined && v !== null)
|
|
8
|
+
url.searchParams.set(k, String(v));
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const init = { method, headers: { Authorization: `Bearer ${token}`, "Notion-Version": NOTION_VERSION, "Content-Type": "application/json" } };
|
|
12
|
+
if (body && Object.keys(body).length > 0)
|
|
13
|
+
init.body = JSON.stringify(body);
|
|
14
|
+
const res = await fetch(url.toString(), init);
|
|
15
|
+
if (!res.ok)
|
|
16
|
+
throw new Error(`Notion error ${res.status}: ${await res.text()}`);
|
|
17
|
+
return res.json();
|
|
18
|
+
}
|
|
19
|
+
export default function notion(rl) {
|
|
20
|
+
rl.setName("notion");
|
|
21
|
+
rl.setVersion("0.1.0");
|
|
22
|
+
rl.setConnectionSchema({ apiKey: { type: "string", required: true, description: "Notion integration token (secret_...)", env: "NOTION_API_KEY" } });
|
|
23
|
+
const t = (ctx) => ctx.connection.config.apiKey;
|
|
24
|
+
// ── Block ───────────────────────────────────────────
|
|
25
|
+
rl.registerAction("block.append", { description: "Append children blocks to a block/page",
|
|
26
|
+
inputSchema: { blockId: { type: "string", required: true }, children: { type: "object", required: true, description: "Array of block objects" } },
|
|
27
|
+
async execute(input, ctx) { const p = input; return api(t(ctx), "PATCH", `/blocks/${p.blockId}/children`, { children: p.children }); } });
|
|
28
|
+
rl.registerAction("block.getChildren", { description: "Get child blocks of a block/page",
|
|
29
|
+
inputSchema: { blockId: { type: "string", required: true }, limit: { type: "number", required: false } },
|
|
30
|
+
async execute(input, ctx) {
|
|
31
|
+
const p = input;
|
|
32
|
+
const qs = {};
|
|
33
|
+
if (p.limit)
|
|
34
|
+
qs.page_size = p.limit;
|
|
35
|
+
const data = (await api(t(ctx), "GET", `/blocks/${p.blockId}/children`, undefined, qs));
|
|
36
|
+
return data.results;
|
|
37
|
+
} });
|
|
38
|
+
rl.registerAction("block.delete", { description: "Delete (archive) a block",
|
|
39
|
+
inputSchema: { blockId: { type: "string", required: true } },
|
|
40
|
+
async execute(input, ctx) { return api(t(ctx), "DELETE", `/blocks/${input.blockId}`); } });
|
|
41
|
+
// ── Database ────────────────────────────────────────
|
|
42
|
+
rl.registerAction("database.get", { description: "Get a database",
|
|
43
|
+
inputSchema: { databaseId: { type: "string", required: true } },
|
|
44
|
+
async execute(input, ctx) { return api(t(ctx), "GET", `/databases/${input.databaseId}`); } });
|
|
45
|
+
rl.registerAction("database.list", { description: "List all databases (via search)",
|
|
46
|
+
inputSchema: { limit: { type: "number", required: false } },
|
|
47
|
+
async execute(input, ctx) {
|
|
48
|
+
const body = { filter: { property: "object", value: "database" } };
|
|
49
|
+
if (input?.limit)
|
|
50
|
+
body.page_size = input.limit;
|
|
51
|
+
const data = (await api(t(ctx), "POST", "/search", body));
|
|
52
|
+
return data.results;
|
|
53
|
+
} });
|
|
54
|
+
rl.registerAction("database.query", { description: "Query a database (list pages with filters)",
|
|
55
|
+
inputSchema: { databaseId: { type: "string", required: true }, filter: { type: "object", required: false, description: "Notion filter object" }, sorts: { type: "object", required: false, description: "Array of sort objects" }, limit: { type: "number", required: false } },
|
|
56
|
+
async execute(input, ctx) {
|
|
57
|
+
const p = input;
|
|
58
|
+
const body = {};
|
|
59
|
+
if (p.filter)
|
|
60
|
+
body.filter = p.filter;
|
|
61
|
+
if (p.sorts)
|
|
62
|
+
body.sorts = p.sorts;
|
|
63
|
+
if (p.limit)
|
|
64
|
+
body.page_size = p.limit;
|
|
65
|
+
const data = (await api(t(ctx), "POST", `/databases/${p.databaseId}/query`, body));
|
|
66
|
+
return data.results;
|
|
67
|
+
} });
|
|
68
|
+
// ── Page ────────────────────────────────────────────
|
|
69
|
+
rl.registerAction("page.create", { description: "Create a page (in a database or under a page)",
|
|
70
|
+
inputSchema: { parent: { type: "object", required: true, description: "{ database_id: '...' } or { page_id: '...' }" }, properties: { type: "object", required: true, description: "Page properties" }, children: { type: "object", required: false, description: "Array of block children" }, icon: { type: "object", required: false } },
|
|
71
|
+
async execute(input, ctx) { return api(t(ctx), "POST", "/pages", input); } });
|
|
72
|
+
rl.registerAction("page.get", { description: "Get a page",
|
|
73
|
+
inputSchema: { pageId: { type: "string", required: true } },
|
|
74
|
+
async execute(input, ctx) { return api(t(ctx), "GET", `/pages/${input.pageId}`); } });
|
|
75
|
+
rl.registerAction("page.update", { description: "Update page properties",
|
|
76
|
+
inputSchema: { pageId: { type: "string", required: true }, properties: { type: "object", required: false }, archived: { type: "boolean", required: false }, icon: { type: "object", required: false } },
|
|
77
|
+
async execute(input, ctx) {
|
|
78
|
+
const { pageId, ...body } = input;
|
|
79
|
+
return api(t(ctx), "PATCH", `/pages/${pageId}`, body);
|
|
80
|
+
} });
|
|
81
|
+
rl.registerAction("page.archive", { description: "Archive a page",
|
|
82
|
+
inputSchema: { pageId: { type: "string", required: true } },
|
|
83
|
+
async execute(input, ctx) { return api(t(ctx), "PATCH", `/pages/${input.pageId}`, { archived: true }); } });
|
|
84
|
+
rl.registerAction("page.search", { description: "Search pages",
|
|
85
|
+
inputSchema: { query: { type: "string", required: false }, limit: { type: "number", required: false } },
|
|
86
|
+
async execute(input, ctx) {
|
|
87
|
+
const p = (input ?? {});
|
|
88
|
+
const body = {};
|
|
89
|
+
if (p.query)
|
|
90
|
+
body.query = p.query;
|
|
91
|
+
if (p.limit)
|
|
92
|
+
body.page_size = p.limit;
|
|
93
|
+
const data = (await api(t(ctx), "POST", "/search", body));
|
|
94
|
+
return data.results;
|
|
95
|
+
} });
|
|
96
|
+
// ── User ────────────────────────────────────────────
|
|
97
|
+
rl.registerAction("user.get", { description: "Get a user",
|
|
98
|
+
inputSchema: { userId: { type: "string", required: true } },
|
|
99
|
+
async execute(input, ctx) { return api(t(ctx), "GET", `/users/${input.userId}`); } });
|
|
100
|
+
rl.registerAction("user.list", { description: "List all users",
|
|
101
|
+
inputSchema: { limit: { type: "number", required: false } },
|
|
102
|
+
async execute(input, ctx) {
|
|
103
|
+
const qs = {};
|
|
104
|
+
if (input?.limit)
|
|
105
|
+
qs.page_size = input.limit;
|
|
106
|
+
const data = (await api(t(ctx), "GET", "/users", undefined, qs));
|
|
107
|
+
return data.results;
|
|
108
|
+
} });
|
|
109
|
+
rl.registerAction("user.me", { description: "Get the bot user",
|
|
110
|
+
inputSchema: {},
|
|
111
|
+
async execute(_input, ctx) { return api(t(ctx), "GET", "/users/me"); } });
|
|
112
|
+
}
|