@tangle-network/agent-integrations 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +146 -144
- package/dist/index.d.ts +56 -1
- package/dist/index.js +547 -0
- package/dist/index.js.map +1 -1
- package/docs/integration-coverage-checklist.md +9 -6
- package/examples/basic-hub.ts +47 -0
- package/examples/declarative-rest.ts +27 -0
- package/examples/first-party-adapter.ts +32 -0
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1986,6 +1986,204 @@ function readMetaString3(meta, key) {
|
|
|
1986
1986
|
return v;
|
|
1987
1987
|
}
|
|
1988
1988
|
|
|
1989
|
+
// src/connectors/adapters/declarative-rest.ts
|
|
1990
|
+
function declarativeRestConnector(spec) {
|
|
1991
|
+
const capabilities = spec.capabilities.map(operationToCapability);
|
|
1992
|
+
const adapter = {
|
|
1993
|
+
manifest: {
|
|
1994
|
+
kind: spec.kind,
|
|
1995
|
+
displayName: spec.displayName,
|
|
1996
|
+
description: spec.description,
|
|
1997
|
+
auth: spec.auth,
|
|
1998
|
+
category: spec.category,
|
|
1999
|
+
defaultConsistencyModel: spec.defaultConsistencyModel,
|
|
2000
|
+
capabilities
|
|
2001
|
+
},
|
|
2002
|
+
async executeRead(inv) {
|
|
2003
|
+
const op = readOperation(spec, inv.capabilityName, "read");
|
|
2004
|
+
const response = await executeRestRequest(spec, op.request, inv);
|
|
2005
|
+
return {
|
|
2006
|
+
data: response.data,
|
|
2007
|
+
etag: response.etag,
|
|
2008
|
+
fetchedAt: Date.now()
|
|
2009
|
+
};
|
|
2010
|
+
},
|
|
2011
|
+
async executeMutation(inv) {
|
|
2012
|
+
const op = readOperation(spec, inv.capabilityName, "mutation");
|
|
2013
|
+
const response = await executeRestRequest(spec, op.request, inv);
|
|
2014
|
+
return {
|
|
2015
|
+
status: "committed",
|
|
2016
|
+
data: response.data,
|
|
2017
|
+
etagAfter: response.etag,
|
|
2018
|
+
committedAt: Date.now(),
|
|
2019
|
+
idempotentReplay: false
|
|
2020
|
+
};
|
|
2021
|
+
},
|
|
2022
|
+
async test(source) {
|
|
2023
|
+
if (!spec.test) return { ok: true };
|
|
2024
|
+
try {
|
|
2025
|
+
await executeRestRequest(spec, spec.test, {
|
|
2026
|
+
source,
|
|
2027
|
+
capabilityName: "__test__",
|
|
2028
|
+
args: {},
|
|
2029
|
+
idempotencyKey: "test"
|
|
2030
|
+
});
|
|
2031
|
+
return { ok: true };
|
|
2032
|
+
} catch (error) {
|
|
2033
|
+
return { ok: false, reason: error instanceof Error ? error.message : "unknown error" };
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
2036
|
+
};
|
|
2037
|
+
return adapter;
|
|
2038
|
+
}
|
|
2039
|
+
function operationToCapability(op) {
|
|
2040
|
+
const base = {
|
|
2041
|
+
name: op.name,
|
|
2042
|
+
description: op.description,
|
|
2043
|
+
parameters: op.parameters,
|
|
2044
|
+
requiredScopes: op.requiredScopes
|
|
2045
|
+
};
|
|
2046
|
+
if (op.class === "read") {
|
|
2047
|
+
return { ...base, class: "read" };
|
|
2048
|
+
}
|
|
2049
|
+
return {
|
|
2050
|
+
...base,
|
|
2051
|
+
class: "mutation",
|
|
2052
|
+
cas: op.cas ?? "native-idempotency",
|
|
2053
|
+
externalEffect: op.externalEffect ?? true
|
|
2054
|
+
};
|
|
2055
|
+
}
|
|
2056
|
+
function readOperation(spec, name, expected) {
|
|
2057
|
+
const op = spec.capabilities.find((candidate) => candidate.name === name);
|
|
2058
|
+
if (!op || op.class !== expected) {
|
|
2059
|
+
throw new Error(`${spec.kind}: unknown ${expected} capability ${name}`);
|
|
2060
|
+
}
|
|
2061
|
+
return op;
|
|
2062
|
+
}
|
|
2063
|
+
async function executeRestRequest(spec, request, inv) {
|
|
2064
|
+
const baseUrl = resolveBaseUrl(spec.baseUrl, inv.source.metadata);
|
|
2065
|
+
const url = new URL(interpolate(request.path, inv.args), baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
|
|
2066
|
+
for (const [key, value] of Object.entries(request.query ?? {})) {
|
|
2067
|
+
const rendered = renderQueryValue(value, inv.args);
|
|
2068
|
+
if (rendered !== void 0 && rendered !== "") url.searchParams.set(key, String(rendered));
|
|
2069
|
+
}
|
|
2070
|
+
const headers = {
|
|
2071
|
+
accept: "application/json",
|
|
2072
|
+
...spec.defaultHeaders,
|
|
2073
|
+
...renderHeaders(request.headers ?? {}, inv.args)
|
|
2074
|
+
};
|
|
2075
|
+
applyCredentials(headers, url, spec.credentialPlacement ?? { kind: "bearer" }, inv.source.credentials);
|
|
2076
|
+
if (inv.expectedEtag) headers["if-match"] = inv.expectedEtag;
|
|
2077
|
+
if (request.method !== "GET" && request.method !== "DELETE") {
|
|
2078
|
+
headers["content-type"] = headers["content-type"] ?? "application/json";
|
|
2079
|
+
}
|
|
2080
|
+
const res = await fetch(url, {
|
|
2081
|
+
method: request.method,
|
|
2082
|
+
headers,
|
|
2083
|
+
body: request.method === "GET" || request.method === "DELETE" ? void 0 : JSON.stringify(resolveBody(request.body, inv.args)),
|
|
2084
|
+
signal: AbortSignal.timeout(2e4)
|
|
2085
|
+
});
|
|
2086
|
+
if (res.status === 401 || res.status === 403) {
|
|
2087
|
+
throw new CredentialsExpired(`${spec.displayName} rejected credentials (${res.status})`, inv.source.id);
|
|
2088
|
+
}
|
|
2089
|
+
if (res.status === 409 || res.status === 412) {
|
|
2090
|
+
return {
|
|
2091
|
+
data: {
|
|
2092
|
+
status: "conflict",
|
|
2093
|
+
message: await safeErrorText(res)
|
|
2094
|
+
},
|
|
2095
|
+
etag: res.headers.get("etag") ?? void 0
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
2098
|
+
if (res.status === 429) {
|
|
2099
|
+
return {
|
|
2100
|
+
data: {
|
|
2101
|
+
status: "rate-limited",
|
|
2102
|
+
retryAfter: res.headers.get("retry-after") ?? void 0,
|
|
2103
|
+
message: await safeErrorText(res)
|
|
2104
|
+
}
|
|
2105
|
+
};
|
|
2106
|
+
}
|
|
2107
|
+
if (!res.ok) {
|
|
2108
|
+
throw new Error(`${spec.kind} ${request.method} ${url.pathname} HTTP ${res.status}: ${(await safeErrorText(res)).slice(0, 300)}`);
|
|
2109
|
+
}
|
|
2110
|
+
const text = await res.text();
|
|
2111
|
+
const data = text ? JSON.parse(text) : null;
|
|
2112
|
+
return { data, etag: res.headers.get("etag") ?? void 0 };
|
|
2113
|
+
}
|
|
2114
|
+
function resolveBaseUrl(baseUrl, metadata) {
|
|
2115
|
+
if (typeof baseUrl === "string") return baseUrl;
|
|
2116
|
+
const value = metadata[baseUrl.metadataKey];
|
|
2117
|
+
if (typeof value === "string" && value.trim()) return value;
|
|
2118
|
+
if (baseUrl.fallback) return baseUrl.fallback;
|
|
2119
|
+
throw new Error(`missing metadata.${baseUrl.metadataKey} base URL`);
|
|
2120
|
+
}
|
|
2121
|
+
function applyCredentials(headers, url, placement, credentials) {
|
|
2122
|
+
const token = credentialToken(credentials);
|
|
2123
|
+
if (placement.kind === "bearer") headers.authorization = `Bearer ${token}`;
|
|
2124
|
+
if (placement.kind === "header") headers[placement.header] = `${placement.prefix ?? ""}${token}`;
|
|
2125
|
+
if (placement.kind === "query") url.searchParams.set(placement.parameter, token);
|
|
2126
|
+
}
|
|
2127
|
+
function credentialToken(credentials) {
|
|
2128
|
+
if (credentials.kind === "oauth2") return credentials.accessToken;
|
|
2129
|
+
if (credentials.kind === "api-key") return credentials.apiKey;
|
|
2130
|
+
throw new Error(`declarative REST connectors require oauth2 or api-key credentials, got ${credentials.kind}`);
|
|
2131
|
+
}
|
|
2132
|
+
function resolveBody(body, args) {
|
|
2133
|
+
if (!body || body === "args") return args;
|
|
2134
|
+
if (typeof body === "string") return renderValue(body, args);
|
|
2135
|
+
return renderObject(body, args);
|
|
2136
|
+
}
|
|
2137
|
+
function renderHeaders(headers, args) {
|
|
2138
|
+
return Object.fromEntries(Object.entries(headers).map(([key, value]) => [key, interpolate(value, args)]));
|
|
2139
|
+
}
|
|
2140
|
+
function renderObject(input, args) {
|
|
2141
|
+
return Object.fromEntries(Object.entries(input).map(([key, value]) => [key, renderValue(value, args)]));
|
|
2142
|
+
}
|
|
2143
|
+
function renderValue(value, args) {
|
|
2144
|
+
if (typeof value === "string") {
|
|
2145
|
+
const exact = value.match(/^\{([a-zA-Z0-9_.-]+)\}$/);
|
|
2146
|
+
if (exact) return readRequiredPath(args, exact[1]);
|
|
2147
|
+
return interpolate(value, args);
|
|
2148
|
+
}
|
|
2149
|
+
return value;
|
|
2150
|
+
}
|
|
2151
|
+
function renderQueryValue(value, args) {
|
|
2152
|
+
if (typeof value !== "string") return value;
|
|
2153
|
+
const exact = value.match(/^\{([a-zA-Z0-9_.-]+)\}$/);
|
|
2154
|
+
if (exact) return readPath(args, exact[1]);
|
|
2155
|
+
try {
|
|
2156
|
+
return interpolate(value, args);
|
|
2157
|
+
} catch {
|
|
2158
|
+
return void 0;
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
function interpolate(template, args) {
|
|
2162
|
+
return template.replace(/\{([a-zA-Z0-9_.-]+)\}/g, (_match, key) => {
|
|
2163
|
+
const value = readPath(args, key);
|
|
2164
|
+
if (value === void 0 || value === null) {
|
|
2165
|
+
throw new Error(`missing required argument: ${key}`);
|
|
2166
|
+
}
|
|
2167
|
+
return encodeURIComponent(String(value));
|
|
2168
|
+
});
|
|
2169
|
+
}
|
|
2170
|
+
function readRequiredPath(input, path) {
|
|
2171
|
+
const value = readPath(input, path);
|
|
2172
|
+
if (value === void 0 || value === null) throw new Error(`missing required argument: ${path}`);
|
|
2173
|
+
return value;
|
|
2174
|
+
}
|
|
2175
|
+
function readPath(input, path) {
|
|
2176
|
+
return path.split(".").reduce((value, part) => {
|
|
2177
|
+
if (value && typeof value === "object" && part in value) {
|
|
2178
|
+
return value[part];
|
|
2179
|
+
}
|
|
2180
|
+
return void 0;
|
|
2181
|
+
}, input);
|
|
2182
|
+
}
|
|
2183
|
+
async function safeErrorText(res) {
|
|
2184
|
+
return await res.text().catch(() => res.statusText) || res.statusText;
|
|
2185
|
+
}
|
|
2186
|
+
|
|
1989
2187
|
// src/connectors/adapters/twilio-sms.ts
|
|
1990
2188
|
var API4 = "https://api.twilio.com/2010-04-01";
|
|
1991
2189
|
var LOOKUP_API = "https://lookups.twilio.com/v1";
|
|
@@ -2654,6 +2852,349 @@ var slackEventsConnector = {
|
|
|
2654
2852
|
}
|
|
2655
2853
|
};
|
|
2656
2854
|
|
|
2855
|
+
// src/connectors/adapters/github.ts
|
|
2856
|
+
var repoParams = {
|
|
2857
|
+
type: "object",
|
|
2858
|
+
properties: {
|
|
2859
|
+
owner: { type: "string" },
|
|
2860
|
+
repo: { type: "string" }
|
|
2861
|
+
},
|
|
2862
|
+
required: ["owner", "repo"]
|
|
2863
|
+
};
|
|
2864
|
+
var githubConnector = declarativeRestConnector({
|
|
2865
|
+
kind: "github",
|
|
2866
|
+
displayName: "GitHub",
|
|
2867
|
+
description: "Search repositories/issues and create or update GitHub issues through a user-scoped token.",
|
|
2868
|
+
auth: { kind: "api-key", hint: "GitHub fine-grained personal access token or installation token." },
|
|
2869
|
+
category: "other",
|
|
2870
|
+
defaultConsistencyModel: "authoritative",
|
|
2871
|
+
baseUrl: "https://api.github.com",
|
|
2872
|
+
defaultHeaders: {
|
|
2873
|
+
"x-github-api-version": "2022-11-28"
|
|
2874
|
+
},
|
|
2875
|
+
test: { method: "GET", path: "/user" },
|
|
2876
|
+
capabilities: [
|
|
2877
|
+
{
|
|
2878
|
+
name: "repositories.get",
|
|
2879
|
+
class: "read",
|
|
2880
|
+
description: "Read repository metadata.",
|
|
2881
|
+
parameters: repoParams,
|
|
2882
|
+
request: { method: "GET", path: "/repos/{owner}/{repo}" }
|
|
2883
|
+
},
|
|
2884
|
+
{
|
|
2885
|
+
name: "issues.search",
|
|
2886
|
+
class: "read",
|
|
2887
|
+
description: "Search GitHub issues and pull requests.",
|
|
2888
|
+
parameters: {
|
|
2889
|
+
type: "object",
|
|
2890
|
+
properties: { q: { type: "string" }, per_page: { type: "integer", minimum: 1, maximum: 100 } },
|
|
2891
|
+
required: ["q"]
|
|
2892
|
+
},
|
|
2893
|
+
request: { method: "GET", path: "/search/issues", query: { q: "{q}", per_page: "{per_page}" } }
|
|
2894
|
+
},
|
|
2895
|
+
{
|
|
2896
|
+
name: "issues.create",
|
|
2897
|
+
class: "mutation",
|
|
2898
|
+
description: "Create an issue in a repository.",
|
|
2899
|
+
parameters: {
|
|
2900
|
+
type: "object",
|
|
2901
|
+
properties: {
|
|
2902
|
+
owner: { type: "string" },
|
|
2903
|
+
repo: { type: "string" },
|
|
2904
|
+
title: { type: "string" },
|
|
2905
|
+
body: { type: "string" },
|
|
2906
|
+
labels: { type: "array", items: { type: "string" } }
|
|
2907
|
+
},
|
|
2908
|
+
required: ["owner", "repo", "title"]
|
|
2909
|
+
},
|
|
2910
|
+
request: { method: "POST", path: "/repos/{owner}/{repo}/issues", body: "args" },
|
|
2911
|
+
cas: "native-idempotency"
|
|
2912
|
+
},
|
|
2913
|
+
{
|
|
2914
|
+
name: "issues.update",
|
|
2915
|
+
class: "mutation",
|
|
2916
|
+
description: "Update an issue by number.",
|
|
2917
|
+
parameters: {
|
|
2918
|
+
type: "object",
|
|
2919
|
+
properties: {
|
|
2920
|
+
owner: { type: "string" },
|
|
2921
|
+
repo: { type: "string" },
|
|
2922
|
+
issue_number: { type: "integer" },
|
|
2923
|
+
title: { type: "string" },
|
|
2924
|
+
body: { type: "string" },
|
|
2925
|
+
state: { type: "string", enum: ["open", "closed"] }
|
|
2926
|
+
},
|
|
2927
|
+
required: ["owner", "repo", "issue_number"]
|
|
2928
|
+
},
|
|
2929
|
+
request: { method: "PATCH", path: "/repos/{owner}/{repo}/issues/{issue_number}", body: "args" },
|
|
2930
|
+
cas: "etag-if-match"
|
|
2931
|
+
}
|
|
2932
|
+
]
|
|
2933
|
+
});
|
|
2934
|
+
|
|
2935
|
+
// src/connectors/adapters/gitlab.ts
|
|
2936
|
+
var gitlabConnector = declarativeRestConnector({
|
|
2937
|
+
kind: "gitlab",
|
|
2938
|
+
displayName: "GitLab",
|
|
2939
|
+
description: "Search GitLab projects/issues and create or update issues through a personal, project, or group token.",
|
|
2940
|
+
auth: { kind: "api-key", hint: "GitLab access token with api/read_api scope." },
|
|
2941
|
+
category: "other",
|
|
2942
|
+
defaultConsistencyModel: "authoritative",
|
|
2943
|
+
baseUrl: { metadataKey: "baseUrl", fallback: "https://gitlab.com/api/v4" },
|
|
2944
|
+
credentialPlacement: { kind: "header", header: "PRIVATE-TOKEN" },
|
|
2945
|
+
test: { method: "GET", path: "/user" },
|
|
2946
|
+
capabilities: [
|
|
2947
|
+
{
|
|
2948
|
+
name: "projects.search",
|
|
2949
|
+
class: "read",
|
|
2950
|
+
description: "Search projects visible to the token.",
|
|
2951
|
+
parameters: {
|
|
2952
|
+
type: "object",
|
|
2953
|
+
properties: { search: { type: "string" }, per_page: { type: "integer", minimum: 1, maximum: 100 } },
|
|
2954
|
+
required: ["search"]
|
|
2955
|
+
},
|
|
2956
|
+
request: { method: "GET", path: "/projects", query: { search: "{search}", per_page: "{per_page}" } }
|
|
2957
|
+
},
|
|
2958
|
+
{
|
|
2959
|
+
name: "issues.search",
|
|
2960
|
+
class: "read",
|
|
2961
|
+
description: "Search issues in a project.",
|
|
2962
|
+
parameters: {
|
|
2963
|
+
type: "object",
|
|
2964
|
+
properties: { projectId: { type: "string" }, search: { type: "string" }, per_page: { type: "integer" } },
|
|
2965
|
+
required: ["projectId", "search"]
|
|
2966
|
+
},
|
|
2967
|
+
request: { method: "GET", path: "/projects/{projectId}/issues", query: { search: "{search}", per_page: "{per_page}" } }
|
|
2968
|
+
},
|
|
2969
|
+
{
|
|
2970
|
+
name: "issues.create",
|
|
2971
|
+
class: "mutation",
|
|
2972
|
+
description: "Create a GitLab project issue.",
|
|
2973
|
+
parameters: {
|
|
2974
|
+
type: "object",
|
|
2975
|
+
properties: { projectId: { type: "string" }, title: { type: "string" }, description: { type: "string" } },
|
|
2976
|
+
required: ["projectId", "title"]
|
|
2977
|
+
},
|
|
2978
|
+
request: { method: "POST", path: "/projects/{projectId}/issues", body: "args" },
|
|
2979
|
+
cas: "native-idempotency"
|
|
2980
|
+
},
|
|
2981
|
+
{
|
|
2982
|
+
name: "issues.update",
|
|
2983
|
+
class: "mutation",
|
|
2984
|
+
description: "Update a GitLab issue.",
|
|
2985
|
+
parameters: {
|
|
2986
|
+
type: "object",
|
|
2987
|
+
properties: { projectId: { type: "string" }, issueIid: { type: "integer" }, title: { type: "string" }, description: { type: "string" }, state_event: { type: "string" } },
|
|
2988
|
+
required: ["projectId", "issueIid"]
|
|
2989
|
+
},
|
|
2990
|
+
request: { method: "PUT", path: "/projects/{projectId}/issues/{issueIid}", body: "args" },
|
|
2991
|
+
cas: "etag-if-match"
|
|
2992
|
+
}
|
|
2993
|
+
]
|
|
2994
|
+
});
|
|
2995
|
+
|
|
2996
|
+
// src/connectors/adapters/airtable.ts
|
|
2997
|
+
var baseTableParams = {
|
|
2998
|
+
type: "object",
|
|
2999
|
+
properties: {
|
|
3000
|
+
baseId: { type: "string" },
|
|
3001
|
+
tableName: { type: "string" }
|
|
3002
|
+
},
|
|
3003
|
+
required: ["baseId", "tableName"]
|
|
3004
|
+
};
|
|
3005
|
+
var airtableConnector = declarativeRestConnector({
|
|
3006
|
+
kind: "airtable",
|
|
3007
|
+
displayName: "Airtable",
|
|
3008
|
+
description: "Query and update Airtable records for lightweight operational databases.",
|
|
3009
|
+
auth: { kind: "api-key", hint: "Airtable personal access token." },
|
|
3010
|
+
category: "spreadsheet",
|
|
3011
|
+
defaultConsistencyModel: "authoritative",
|
|
3012
|
+
baseUrl: "https://api.airtable.com",
|
|
3013
|
+
test: { method: "GET", path: "/v0/meta/whoami" },
|
|
3014
|
+
capabilities: [
|
|
3015
|
+
{
|
|
3016
|
+
name: "records.list",
|
|
3017
|
+
class: "read",
|
|
3018
|
+
description: "List records in a table.",
|
|
3019
|
+
parameters: {
|
|
3020
|
+
...baseTableParams,
|
|
3021
|
+
properties: {
|
|
3022
|
+
...baseTableParams.properties,
|
|
3023
|
+
maxRecords: { type: "integer", minimum: 1, maximum: 100 },
|
|
3024
|
+
filterByFormula: { type: "string" }
|
|
3025
|
+
}
|
|
3026
|
+
},
|
|
3027
|
+
request: { method: "GET", path: "/v0/{baseId}/{tableName}", query: { maxRecords: "{maxRecords}", filterByFormula: "{filterByFormula}" } }
|
|
3028
|
+
},
|
|
3029
|
+
{
|
|
3030
|
+
name: "records.get",
|
|
3031
|
+
class: "read",
|
|
3032
|
+
description: "Read a single Airtable record.",
|
|
3033
|
+
parameters: {
|
|
3034
|
+
type: "object",
|
|
3035
|
+
properties: { baseId: { type: "string" }, tableName: { type: "string" }, recordId: { type: "string" } },
|
|
3036
|
+
required: ["baseId", "tableName", "recordId"]
|
|
3037
|
+
},
|
|
3038
|
+
request: { method: "GET", path: "/v0/{baseId}/{tableName}/{recordId}" }
|
|
3039
|
+
},
|
|
3040
|
+
{
|
|
3041
|
+
name: "records.create",
|
|
3042
|
+
class: "mutation",
|
|
3043
|
+
description: "Create an Airtable record.",
|
|
3044
|
+
parameters: {
|
|
3045
|
+
type: "object",
|
|
3046
|
+
properties: { baseId: { type: "string" }, tableName: { type: "string" }, fields: { type: "object" } },
|
|
3047
|
+
required: ["baseId", "tableName", "fields"]
|
|
3048
|
+
},
|
|
3049
|
+
request: { method: "POST", path: "/v0/{baseId}/{tableName}", body: { fields: "{fields}" } },
|
|
3050
|
+
cas: "native-idempotency"
|
|
3051
|
+
},
|
|
3052
|
+
{
|
|
3053
|
+
name: "records.update",
|
|
3054
|
+
class: "mutation",
|
|
3055
|
+
description: "Update an Airtable record.",
|
|
3056
|
+
parameters: {
|
|
3057
|
+
type: "object",
|
|
3058
|
+
properties: { baseId: { type: "string" }, tableName: { type: "string" }, recordId: { type: "string" }, fields: { type: "object" } },
|
|
3059
|
+
required: ["baseId", "tableName", "recordId", "fields"]
|
|
3060
|
+
},
|
|
3061
|
+
request: { method: "PATCH", path: "/v0/{baseId}/{tableName}/{recordId}", body: { fields: "{fields}" } },
|
|
3062
|
+
cas: "optimistic-read-verify"
|
|
3063
|
+
}
|
|
3064
|
+
]
|
|
3065
|
+
});
|
|
3066
|
+
|
|
3067
|
+
// src/connectors/adapters/asana.ts
|
|
3068
|
+
var asanaConnector = declarativeRestConnector({
|
|
3069
|
+
kind: "asana",
|
|
3070
|
+
displayName: "Asana",
|
|
3071
|
+
description: "Search projects/tasks and create or update Asana tasks.",
|
|
3072
|
+
auth: { kind: "api-key", hint: "Asana personal access token." },
|
|
3073
|
+
category: "other",
|
|
3074
|
+
defaultConsistencyModel: "authoritative",
|
|
3075
|
+
baseUrl: "https://app.asana.com/api/1.0",
|
|
3076
|
+
test: { method: "GET", path: "/users/me" },
|
|
3077
|
+
capabilities: [
|
|
3078
|
+
{
|
|
3079
|
+
name: "projects.search",
|
|
3080
|
+
class: "read",
|
|
3081
|
+
description: "List or search projects in a workspace.",
|
|
3082
|
+
parameters: {
|
|
3083
|
+
type: "object",
|
|
3084
|
+
properties: { workspace: { type: "string" }, archived: { type: "boolean" }, limit: { type: "integer" } },
|
|
3085
|
+
required: ["workspace"]
|
|
3086
|
+
},
|
|
3087
|
+
request: { method: "GET", path: "/projects", query: { workspace: "{workspace}", archived: "{archived}", limit: "{limit}" } }
|
|
3088
|
+
},
|
|
3089
|
+
{
|
|
3090
|
+
name: "tasks.search",
|
|
3091
|
+
class: "read",
|
|
3092
|
+
description: "Search tasks in a workspace.",
|
|
3093
|
+
parameters: {
|
|
3094
|
+
type: "object",
|
|
3095
|
+
properties: { workspace: { type: "string" }, text: { type: "string" }, limit: { type: "integer" } },
|
|
3096
|
+
required: ["workspace"]
|
|
3097
|
+
},
|
|
3098
|
+
request: { method: "GET", path: "/workspaces/{workspace}/tasks/search", query: { text: "{text}", limit: "{limit}" } }
|
|
3099
|
+
},
|
|
3100
|
+
{
|
|
3101
|
+
name: "tasks.create",
|
|
3102
|
+
class: "mutation",
|
|
3103
|
+
description: "Create an Asana task.",
|
|
3104
|
+
parameters: {
|
|
3105
|
+
type: "object",
|
|
3106
|
+
properties: { data: { type: "object" } },
|
|
3107
|
+
required: ["data"]
|
|
3108
|
+
},
|
|
3109
|
+
request: { method: "POST", path: "/tasks", body: { data: "{data}" } },
|
|
3110
|
+
cas: "native-idempotency"
|
|
3111
|
+
},
|
|
3112
|
+
{
|
|
3113
|
+
name: "tasks.update",
|
|
3114
|
+
class: "mutation",
|
|
3115
|
+
description: "Update an Asana task.",
|
|
3116
|
+
parameters: {
|
|
3117
|
+
type: "object",
|
|
3118
|
+
properties: { taskGid: { type: "string" }, data: { type: "object" } },
|
|
3119
|
+
required: ["taskGid", "data"]
|
|
3120
|
+
},
|
|
3121
|
+
request: { method: "PUT", path: "/tasks/{taskGid}", body: { data: "{data}" } },
|
|
3122
|
+
cas: "optimistic-read-verify"
|
|
3123
|
+
}
|
|
3124
|
+
]
|
|
3125
|
+
});
|
|
3126
|
+
|
|
3127
|
+
// src/connectors/adapters/salesforce.ts
|
|
3128
|
+
var salesforceConnector = declarativeRestConnector({
|
|
3129
|
+
kind: "salesforce",
|
|
3130
|
+
displayName: "Salesforce",
|
|
3131
|
+
description: "Query Salesforce records with SOQL and create or update sObjects.",
|
|
3132
|
+
auth: {
|
|
3133
|
+
kind: "oauth2",
|
|
3134
|
+
authorizationUrl: "https://login.salesforce.com/services/oauth2/authorize",
|
|
3135
|
+
tokenUrl: "https://login.salesforce.com/services/oauth2/token",
|
|
3136
|
+
scopes: ["api", "refresh_token"],
|
|
3137
|
+
clientIdEnv: "SALESFORCE_OAUTH_CLIENT_ID",
|
|
3138
|
+
clientSecretEnv: "SALESFORCE_OAUTH_CLIENT_SECRET"
|
|
3139
|
+
},
|
|
3140
|
+
category: "crm",
|
|
3141
|
+
defaultConsistencyModel: "authoritative",
|
|
3142
|
+
baseUrl: { metadataKey: "instanceUrl" },
|
|
3143
|
+
test: { method: "GET", path: "/services/data/v61.0/" },
|
|
3144
|
+
capabilities: [
|
|
3145
|
+
{
|
|
3146
|
+
name: "records.query",
|
|
3147
|
+
class: "read",
|
|
3148
|
+
description: "Run a SOQL query.",
|
|
3149
|
+
parameters: {
|
|
3150
|
+
type: "object",
|
|
3151
|
+
properties: { q: { type: "string" } },
|
|
3152
|
+
required: ["q"]
|
|
3153
|
+
},
|
|
3154
|
+
request: { method: "GET", path: "/services/data/v61.0/query", query: { q: "{q}" } },
|
|
3155
|
+
requiredScopes: ["api"]
|
|
3156
|
+
},
|
|
3157
|
+
{
|
|
3158
|
+
name: "records.get",
|
|
3159
|
+
class: "read",
|
|
3160
|
+
description: "Read a Salesforce sObject record.",
|
|
3161
|
+
parameters: {
|
|
3162
|
+
type: "object",
|
|
3163
|
+
properties: { objectName: { type: "string" }, recordId: { type: "string" } },
|
|
3164
|
+
required: ["objectName", "recordId"]
|
|
3165
|
+
},
|
|
3166
|
+
request: { method: "GET", path: "/services/data/v61.0/sobjects/{objectName}/{recordId}" },
|
|
3167
|
+
requiredScopes: ["api"]
|
|
3168
|
+
},
|
|
3169
|
+
{
|
|
3170
|
+
name: "records.create",
|
|
3171
|
+
class: "mutation",
|
|
3172
|
+
description: "Create a Salesforce sObject record.",
|
|
3173
|
+
parameters: {
|
|
3174
|
+
type: "object",
|
|
3175
|
+
properties: { objectName: { type: "string" }, fields: { type: "object" } },
|
|
3176
|
+
required: ["objectName", "fields"]
|
|
3177
|
+
},
|
|
3178
|
+
request: { method: "POST", path: "/services/data/v61.0/sobjects/{objectName}", body: "{fields}" },
|
|
3179
|
+
cas: "native-idempotency",
|
|
3180
|
+
requiredScopes: ["api"]
|
|
3181
|
+
},
|
|
3182
|
+
{
|
|
3183
|
+
name: "records.update",
|
|
3184
|
+
class: "mutation",
|
|
3185
|
+
description: "Update a Salesforce sObject record.",
|
|
3186
|
+
parameters: {
|
|
3187
|
+
type: "object",
|
|
3188
|
+
properties: { objectName: { type: "string" }, recordId: { type: "string" }, fields: { type: "object" } },
|
|
3189
|
+
required: ["objectName", "recordId", "fields"]
|
|
3190
|
+
},
|
|
3191
|
+
request: { method: "PATCH", path: "/services/data/v61.0/sobjects/{objectName}/{recordId}", body: "{fields}" },
|
|
3192
|
+
cas: "etag-if-match",
|
|
3193
|
+
requiredScopes: ["api"]
|
|
3194
|
+
}
|
|
3195
|
+
]
|
|
3196
|
+
});
|
|
3197
|
+
|
|
2657
3198
|
// src/catalog.ts
|
|
2658
3199
|
var riskRank = {
|
|
2659
3200
|
read: 0,
|
|
@@ -3874,6 +4415,8 @@ export {
|
|
|
3874
4415
|
ResourceContention,
|
|
3875
4416
|
StaticIntegrationPolicyEngine,
|
|
3876
4417
|
_resetPendingFlowsForTests,
|
|
4418
|
+
airtableConnector,
|
|
4419
|
+
asanaConnector,
|
|
3877
4420
|
assertValidConnectorManifest,
|
|
3878
4421
|
buildApprovalRequest,
|
|
3879
4422
|
buildIntegrationCoverageConnectors,
|
|
@@ -3884,8 +4427,11 @@ export {
|
|
|
3884
4427
|
createDefaultIntegrationPolicyEngine,
|
|
3885
4428
|
createHttpIntegrationProvider,
|
|
3886
4429
|
createMockIntegrationProvider,
|
|
4430
|
+
declarativeRestConnector,
|
|
3887
4431
|
exchangeAuthorizationCode,
|
|
3888
4432
|
firstHeader,
|
|
4433
|
+
githubConnector,
|
|
4434
|
+
gitlabConnector,
|
|
3889
4435
|
googleCalendar,
|
|
3890
4436
|
googleSheets,
|
|
3891
4437
|
hubspot,
|
|
@@ -3906,6 +4452,7 @@ export {
|
|
|
3906
4452
|
redactCapability,
|
|
3907
4453
|
redactInvocationEnvelope,
|
|
3908
4454
|
refreshAccessToken,
|
|
4455
|
+
salesforceConnector,
|
|
3909
4456
|
sanitizeConnection,
|
|
3910
4457
|
searchIntegrationTools,
|
|
3911
4458
|
signCapability,
|