@oomol-lab/open-connector 1.6.2 → 1.6.3
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 +27 -0
- package/assets/open-connector/catalog/apps/assured_platform.json +218 -0
- package/assets/open-connector/catalog/apps/baixiao.json +1080 -0
- package/assets/open-connector/catalog/apps/benchmarkone.json +956 -0
- package/assets/open-connector/catalog/apps/bing_webmaster.json +3097 -0
- package/assets/open-connector/catalog/apps/buzzsprout.json +1979 -0
- package/assets/open-connector/catalog/apps/feishu.json +13 -19
- package/assets/open-connector/catalog/apps/feishu_app_bot.json +10 -17
- package/assets/open-connector/catalog/apps/linkfox.json +836 -0
- package/assets/open-connector/catalog/apps/metatraderapi.json +1077 -0
- package/assets/open-connector/catalog/apps/mktindex.json +2411 -0
- package/assets/open-connector/catalog/apps/mojo_helpdesk.json +660 -0
- package/assets/open-connector/catalog/apps/mumble.json +446 -0
- package/assets/open-connector/catalog/apps/notion.json +112 -3
- package/assets/open-connector/catalog/apps/omise.json +438 -0
- package/assets/open-connector/catalog/apps/panjiva.json +2858 -0
- package/assets/open-connector/catalog/apps/papertrail.json +449 -0
- package/assets/open-connector/catalog/apps/peec.json +747 -0
- package/assets/open-connector/catalog/apps/polygon_io.json +5156 -584
- package/assets/open-connector/catalog/apps/quant_data.json +1928 -0
- package/assets/open-connector/catalog/apps/riddle_quiz_maker.json +621 -0
- package/assets/open-connector/catalog/apps/slack.json +327 -4
- package/assets/open-connector/catalog/apps/slackbot.json +280 -3
- package/assets/open-connector/catalog/apps/templatedocs.json +438 -0
- package/assets/open-connector/catalog/apps/terminus_app.json +510 -0
- package/assets/open-connector/catalog/apps/ticket_tailor.json +584 -0
- package/assets/open-connector/catalog/apps/tongdaxin.json +2612 -79
- package/assets/open-connector/catalog/apps/veremark.json +514 -0
- package/assets/open-connector/catalog/apps/walletap.json +549 -0
- package/assets/open-connector/catalog/apps/xiaohongshu_store.json +955 -39
- package/assets/open-connector/catalog/apps-index.json +1 -1
- package/package.json +5 -1
- package/src/connection-service.d.ts +2 -0
- package/src/connection-service.js +8 -1
- package/src/core/provider-id.d.ts +5 -0
- package/src/core/provider-id.js +12 -0
- package/src/oauth/oauth-credential-refresh-service.js +2 -0
- package/src/oauth/oauth-flow-service.js +2 -0
- package/src/providers/action-contracts.generated.d.ts +27 -7
- package/src/providers/assured_platform/executors.d.ts +4 -0
- package/src/providers/assured_platform/executors.js +18 -0
- package/src/providers/assured_platform/runtime.d.ts +7 -0
- package/src/providers/assured_platform/runtime.js +108 -0
- package/src/providers/baixiao/actions.d.ts +2 -0
- package/src/providers/baixiao/actions.js +377 -0
- package/src/providers/baixiao/executors.d.ts +4 -0
- package/src/providers/baixiao/executors.js +106 -0
- package/src/providers/benchmarkone/executors.d.ts +4 -0
- package/src/providers/benchmarkone/executors.js +26 -0
- package/src/providers/benchmarkone/runtime.d.ts +12 -0
- package/src/providers/benchmarkone/runtime.js +113 -0
- package/src/providers/bing_webmaster/actions.d.ts +2 -0
- package/src/providers/bing_webmaster/actions.js +113 -0
- package/src/providers/bing_webmaster/executors.d.ts +4 -0
- package/src/providers/bing_webmaster/executors.js +104 -0
- package/src/providers/bing_webmaster/management-actions.d.ts +2 -0
- package/src/providers/bing_webmaster/management-actions.js +241 -0
- package/src/providers/bing_webmaster/reporting-actions.d.ts +2 -0
- package/src/providers/bing_webmaster/reporting-actions.js +300 -0
- package/src/providers/bing_webmaster/schemas.d.ts +33 -0
- package/src/providers/bing_webmaster/schemas.js +313 -0
- package/src/providers/buzzsprout/executors.d.ts +4 -0
- package/src/providers/buzzsprout/executors.js +21 -0
- package/src/providers/buzzsprout/runtime.d.ts +12 -0
- package/src/providers/buzzsprout/runtime.js +237 -0
- package/src/providers/feishu/shared/drive-actions.d.ts +1 -0
- package/src/providers/feishu/shared/drive-actions.js +13 -9
- package/src/providers/feishu/shared/drive-runtime.js +15 -3
- package/src/providers/feishu/shared/wiki-actions.js +4 -2
- package/src/providers/hithink_finance/runtime.js +39 -60
- package/src/providers/linkfox/actions.js +2 -0
- package/src/providers/linkfox/runtime.js +70 -1
- package/src/providers/linkfox/sif-actions.d.ts +10 -0
- package/src/providers/linkfox/sif-actions.js +193 -0
- package/src/providers/metatraderapi/executors.d.ts +4 -0
- package/src/providers/metatraderapi/executors.js +18 -0
- package/src/providers/metatraderapi/runtime.d.ts +7 -0
- package/src/providers/metatraderapi/runtime.js +216 -0
- package/src/providers/mktindex/actions-mmi.d.ts +2 -0
- package/src/providers/mktindex/actions-mmi.js +510 -0
- package/src/providers/mktindex/actions.d.ts +2 -0
- package/src/providers/mktindex/actions.js +2 -0
- package/src/providers/mktindex/executors.d.ts +4 -0
- package/src/providers/mktindex/executors.js +27 -0
- package/src/providers/mktindex/request.d.ts +17 -0
- package/src/providers/mktindex/request.js +48 -0
- package/src/providers/mktindex/runtime.d.ts +9 -0
- package/src/providers/mktindex/runtime.js +492 -0
- package/src/providers/mojo_helpdesk/executors.d.ts +4 -0
- package/src/providers/mojo_helpdesk/executors.js +18 -0
- package/src/providers/mojo_helpdesk/runtime.d.ts +7 -0
- package/src/providers/mojo_helpdesk/runtime.js +173 -0
- package/src/providers/mumble/executors.d.ts +4 -0
- package/src/providers/mumble/executors.js +99 -0
- package/src/providers/notion/executors.d.ts +9 -0
- package/src/providers/notion/executors.js +161 -6
- package/src/providers/omise/executors.d.ts +4 -0
- package/src/providers/omise/executors.js +120 -0
- package/src/providers/panjiva/actions.d.ts +14 -0
- package/src/providers/panjiva/actions.js +389 -0
- package/src/providers/panjiva/executors.d.ts +4 -0
- package/src/providers/panjiva/executors.js +136 -0
- package/src/providers/papertrail/executors.d.ts +4 -0
- package/src/providers/papertrail/executors.js +15 -0
- package/src/providers/papertrail/runtime.d.ts +7 -0
- package/src/providers/papertrail/runtime.js +167 -0
- package/src/providers/peec/executors.d.ts +4 -0
- package/src/providers/peec/executors.js +15 -0
- package/src/providers/peec/runtime.d.ts +7 -0
- package/src/providers/peec/runtime.js +128 -0
- package/src/providers/polygon_io/actions.d.ts +2 -0
- package/src/providers/polygon_io/actions.js +282 -0
- package/src/providers/polygon_io/expanded-actions.d.ts +2 -0
- package/src/providers/polygon_io/expanded-actions.js +375 -0
- package/src/providers/polygon_io/expanded-runtime.d.ts +16 -0
- package/src/providers/polygon_io/expanded-runtime.js +277 -0
- package/src/providers/polygon_io/runtime.js +21 -2
- package/src/providers/quant_data/executors.d.ts +4 -0
- package/src/providers/quant_data/executors.js +15 -0
- package/src/providers/quant_data/runtime.d.ts +7 -0
- package/src/providers/quant_data/runtime.js +118 -0
- package/src/providers/registry.generated.js +20 -0
- package/src/providers/riddle_quiz_maker/executors.d.ts +4 -0
- package/src/providers/riddle_quiz_maker/executors.js +15 -0
- package/src/providers/riddle_quiz_maker/runtime.d.ts +7 -0
- package/src/providers/riddle_quiz_maker/runtime.js +145 -0
- package/src/providers/slack/actions.js +106 -3
- package/src/providers/slack/runtime.js +260 -36
- package/src/providers/slackbot/actions.js +1 -1
- package/src/providers/templatedocs/executors.d.ts +4 -0
- package/src/providers/templatedocs/executors.js +18 -0
- package/src/providers/templatedocs/runtime.d.ts +13 -0
- package/src/providers/templatedocs/runtime.js +151 -0
- package/src/providers/terminus_app/executors.d.ts +4 -0
- package/src/providers/terminus_app/executors.js +15 -0
- package/src/providers/terminus_app/runtime.d.ts +7 -0
- package/src/providers/terminus_app/runtime.js +172 -0
- package/src/providers/ticket_tailor/executors.d.ts +4 -0
- package/src/providers/ticket_tailor/executors.js +15 -0
- package/src/providers/ticket_tailor/runtime.d.ts +7 -0
- package/src/providers/ticket_tailor/runtime.js +152 -0
- package/src/providers/tongdaxin/actions.d.ts +1 -0
- package/src/providers/tongdaxin/actions.js +6 -3
- package/src/providers/tongdaxin/executors.js +51 -10
- package/src/providers/tongdaxin/named-action-output.d.ts +1 -0
- package/src/providers/tongdaxin/named-action-output.js +149 -0
- package/src/providers/tongdaxin/named-action-routing.d.ts +9 -0
- package/src/providers/tongdaxin/named-action-routing.js +417 -0
- package/src/providers/tongdaxin/named-actions.d.ts +2 -0
- package/src/providers/tongdaxin/named-actions.js +378 -0
- package/src/providers/veremark/executors.d.ts +4 -0
- package/src/providers/veremark/executors.js +129 -0
- package/src/providers/walletap/executors.d.ts +4 -0
- package/src/providers/walletap/executors.js +15 -0
- package/src/providers/walletap/runtime.d.ts +7 -0
- package/src/providers/walletap/runtime.js +147 -0
- package/src/providers/weixin_official_account/access-token.js +31 -7
- package/src/providers/weixin_store/access-token.js +33 -7
- package/src/providers/xiaohongshu_store/executors.js +152 -3
- package/src/server/api/openapi.js +3 -0
- package/src/server/connector-assets.d.ts +4 -0
- package/src/server/connector-assets.js +12 -0
- package/src/server/connector-build.d.ts +33 -0
- package/src/server/connector-build.js +73 -0
- package/src/server/connector-runtime.d.ts +1 -2
- package/src/server/connector-runtime.js +2 -8
- package/src/server/server-assets.d.ts +0 -28
- package/src/server/server-assets.js +0 -50
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { compactObject, looseArray, optionalNumber, optionalRecord, optionalString } from "../../core/cast.js";
|
|
2
|
+
import { providerInputError, ProviderRequestError, providerResponseError, providerUserAgent, readProviderJsonBody, requiredResponseRecord, runProviderRequest, } from "../provider-runtime.js";
|
|
3
|
+
export const mojoHelpdeskApiBaseUrl = "https://app.mojohelpdesk.com/api/v2";
|
|
4
|
+
const validationPath = "/ticket_queues";
|
|
5
|
+
export const mojoHelpdeskActionHandlers = {
|
|
6
|
+
async list_tickets(input, context) {
|
|
7
|
+
return {
|
|
8
|
+
tickets: requireArray(await requestMojo({
|
|
9
|
+
...context,
|
|
10
|
+
path: "/tickets",
|
|
11
|
+
query: {
|
|
12
|
+
sort_by: optionalString(input.sortBy),
|
|
13
|
+
sort_order: optionalString(input.sortOrder),
|
|
14
|
+
page: optionalNumber(input.page),
|
|
15
|
+
per_page: optionalNumber(input.perPage),
|
|
16
|
+
},
|
|
17
|
+
}), "ticket list"),
|
|
18
|
+
};
|
|
19
|
+
},
|
|
20
|
+
async search_tickets(input, context) {
|
|
21
|
+
return {
|
|
22
|
+
tickets: requireArray(await requestMojo({
|
|
23
|
+
...context,
|
|
24
|
+
path: "/tickets/search",
|
|
25
|
+
query: {
|
|
26
|
+
query: optionalString(input.query),
|
|
27
|
+
sf: optionalString(input.sortField),
|
|
28
|
+
r: input.reverse === undefined ? undefined : input.reverse ? 1 : 0,
|
|
29
|
+
page: optionalNumber(input.page),
|
|
30
|
+
per_page: optionalNumber(input.perPage),
|
|
31
|
+
},
|
|
32
|
+
}), "ticket search"),
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
async get_ticket(input, context) {
|
|
36
|
+
return {
|
|
37
|
+
ticket: requiredResponseRecord(await requestMojo({ ...context, path: `/tickets/${requireId(input.ticketId, "ticketId")}` }), "Mojo Helpdesk ticket response"),
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
async create_ticket(input, context) {
|
|
41
|
+
return {
|
|
42
|
+
ticket: requiredResponseRecord(await requestMojo({ ...context, path: "/tickets", method: "POST", body: buildTicketBody(input) }), "Mojo Helpdesk ticket response"),
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
async update_ticket(input, context) {
|
|
46
|
+
return {
|
|
47
|
+
ticket: requiredResponseRecord(await requestMojo({
|
|
48
|
+
...context,
|
|
49
|
+
path: `/tickets/${requireId(input.ticketId, "ticketId")}`,
|
|
50
|
+
method: "PUT",
|
|
51
|
+
body: buildTicketBody(input),
|
|
52
|
+
}), "Mojo Helpdesk ticket response"),
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
async list_comments(input, context) {
|
|
56
|
+
return {
|
|
57
|
+
comments: requireArray(await requestMojo({
|
|
58
|
+
...context,
|
|
59
|
+
path: `/tickets/${requireId(input.ticketId, "ticketId")}/comments`,
|
|
60
|
+
query: { page: optionalNumber(input.page), per_page: optionalNumber(input.perPage) },
|
|
61
|
+
}), "comment list"),
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
async create_comment(input, context) {
|
|
65
|
+
return {
|
|
66
|
+
comment: requiredResponseRecord(await requestMojo({
|
|
67
|
+
...context,
|
|
68
|
+
path: `/tickets/${requireId(input.ticketId, "ticketId")}/comments`,
|
|
69
|
+
method: "POST",
|
|
70
|
+
body: compactObject({
|
|
71
|
+
body: optionalString(input.body),
|
|
72
|
+
time_spent: optionalNumber(input.timeSpent),
|
|
73
|
+
cc: optionalString(input.cc),
|
|
74
|
+
user_id: optionalNumber(input.userId),
|
|
75
|
+
}),
|
|
76
|
+
}), "Mojo Helpdesk comment response"),
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
async list_ticket_queues(input, context) {
|
|
80
|
+
return {
|
|
81
|
+
ticketQueues: requireArray(await requestMojo({
|
|
82
|
+
...context,
|
|
83
|
+
path: validationPath,
|
|
84
|
+
query: { page: optionalNumber(input.page), per_page: optionalNumber(input.perPage) },
|
|
85
|
+
}), "ticket queue list"),
|
|
86
|
+
};
|
|
87
|
+
},
|
|
88
|
+
async list_tags(input, context) {
|
|
89
|
+
return {
|
|
90
|
+
tags: requireArray(await requestMojo({
|
|
91
|
+
...context,
|
|
92
|
+
path: "/tags",
|
|
93
|
+
query: { sort_by: optionalString(input.sortBy), sort_order: optionalString(input.sortOrder) },
|
|
94
|
+
}), "tag list"),
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
export async function validateMojoHelpdeskCredential(apiKey, fetcher, signal) {
|
|
99
|
+
requireArray(await requestMojo({ apiKey, fetcher, signal, path: validationPath, query: { page: 1, per_page: 1 } }), "ticket queue list");
|
|
100
|
+
return {
|
|
101
|
+
profile: { accountId: "mojo_helpdesk", displayName: "Mojo Helpdesk API Key" },
|
|
102
|
+
grantedScopes: [],
|
|
103
|
+
metadata: { apiBaseUrl: mojoHelpdeskApiBaseUrl, validationEndpoint: validationPath },
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function buildTicketBody(input) {
|
|
107
|
+
const body = compactObject({
|
|
108
|
+
title: optionalString(input.title),
|
|
109
|
+
description: optionalString(input.description),
|
|
110
|
+
ticket_queue_id: optionalNumber(input.ticketQueueId),
|
|
111
|
+
priority_id: optionalNumber(input.priorityId),
|
|
112
|
+
status_id: optionalNumber(input.statusId),
|
|
113
|
+
ticket_type_id: optionalNumber(input.ticketTypeId),
|
|
114
|
+
assigned_to_id: optionalNumber(input.assignedToId),
|
|
115
|
+
ticket_form_id: optionalNumber(input.ticketFormId),
|
|
116
|
+
user_id: optionalNumber(input.userId),
|
|
117
|
+
user: input.userEmail ? { email: input.userEmail } : undefined,
|
|
118
|
+
cc: optionalString(input.cc),
|
|
119
|
+
asset_tag: optionalString(input.assetTag),
|
|
120
|
+
asset_id: optionalNumber(input.assetId),
|
|
121
|
+
due_on: optionalString(input.dueOn),
|
|
122
|
+
scheduled_on: optionalString(input.scheduledOn),
|
|
123
|
+
resolution_id: optionalNumber(input.resolutionId),
|
|
124
|
+
});
|
|
125
|
+
for (const [key, value] of Object.entries(optionalRecord(input.customFields) ?? {})) {
|
|
126
|
+
body[`custom_field_${key}`] = value;
|
|
127
|
+
}
|
|
128
|
+
return body;
|
|
129
|
+
}
|
|
130
|
+
async function requestMojo(options) {
|
|
131
|
+
return runProviderRequest({ label: "Mojo Helpdesk", signal: options.signal }, async (signal) => {
|
|
132
|
+
const url = new URL(`${mojoHelpdeskApiBaseUrl}${options.path}`);
|
|
133
|
+
for (const [key, value] of Object.entries(options.query ?? {})) {
|
|
134
|
+
if (value !== undefined)
|
|
135
|
+
url.searchParams.set(key, String(value));
|
|
136
|
+
}
|
|
137
|
+
const headers = new Headers({
|
|
138
|
+
accept: "application/json",
|
|
139
|
+
"user-agent": providerUserAgent,
|
|
140
|
+
"x-api-key": options.apiKey,
|
|
141
|
+
});
|
|
142
|
+
if (options.body !== undefined)
|
|
143
|
+
headers.set("content-type", "application/json");
|
|
144
|
+
const response = await options.fetcher(url, {
|
|
145
|
+
method: options.method ?? "GET",
|
|
146
|
+
headers,
|
|
147
|
+
body: options.body === undefined ? undefined : JSON.stringify(options.body),
|
|
148
|
+
signal,
|
|
149
|
+
});
|
|
150
|
+
const payload = await readProviderJsonBody(response, {
|
|
151
|
+
emptyBody: {},
|
|
152
|
+
invalidJsonMessage: "Mojo Helpdesk returned invalid JSON",
|
|
153
|
+
});
|
|
154
|
+
if (!response.ok) {
|
|
155
|
+
const body = optionalRecord(payload);
|
|
156
|
+
throw new ProviderRequestError(response.status || 502, optionalString(body?.message) ??
|
|
157
|
+
optionalString(body?.error) ??
|
|
158
|
+
`Mojo Helpdesk API request failed with status ${response.status}`);
|
|
159
|
+
}
|
|
160
|
+
return payload;
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
function requireId(value, fieldName) {
|
|
164
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
|
|
165
|
+
throw providerInputError(`${fieldName} must be a positive integer`);
|
|
166
|
+
}
|
|
167
|
+
return value;
|
|
168
|
+
}
|
|
169
|
+
function requireArray(value, label) {
|
|
170
|
+
if (!Array.isArray(value))
|
|
171
|
+
throw providerResponseError(`Mojo Helpdesk ${label} must be an array`);
|
|
172
|
+
return looseArray(value);
|
|
173
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CredentialValidators, ProviderExecutors, ProviderProxyExecutor } from "../../core/types.ts";
|
|
2
|
+
export declare const executors: ProviderExecutors;
|
|
3
|
+
export declare const proxy: ProviderProxyExecutor;
|
|
4
|
+
export declare const credentialValidators: CredentialValidators;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { compactObject, optionalRecord, optionalString, objectArray, requiredBoolean, requiredRecord, requiredString, requiredStringArray, } from "../../core/cast.js";
|
|
2
|
+
import { readProviderTextBody } from "../provider-runtime.js";
|
|
3
|
+
import { defineApiKeyProviderExecutors, defineProviderProxy, ProviderRequestError, providerResponseError, providerUserAgent, } from "../provider-runtime.js";
|
|
4
|
+
const service = "mumble";
|
|
5
|
+
const baseUrl = "https://app.mumble.co.il/mumbleapi";
|
|
6
|
+
const handlers = {
|
|
7
|
+
create_customer: (input, context) => mutate("/add-new-customer", "POST", customerBody(input), context),
|
|
8
|
+
update_customer: (input, context) => mutate("/edit-customer", "POST", { ...optionalRecord(input.customFields), ...customerBody(input) }, context),
|
|
9
|
+
async get_customer(input, context) {
|
|
10
|
+
const data = requiredRecord(await request("/get-customer", "GET", context, undefined, {
|
|
11
|
+
customer_phone: requiredString(input.customerPhone, "customerPhone"),
|
|
12
|
+
}), "Mumble response");
|
|
13
|
+
return { customer: requiredRecord(data.customer, "Mumble customer") };
|
|
14
|
+
},
|
|
15
|
+
async list_customers(input, context) {
|
|
16
|
+
const data = requiredRecord(await request("/get-all-customers", "GET", context, undefined, input.page === undefined ? undefined : { page: String(input.page) }), "Mumble response");
|
|
17
|
+
return {
|
|
18
|
+
customers: objectArray(data.customers, "Mumble customers", providerResponseError),
|
|
19
|
+
total: data.total ?? null,
|
|
20
|
+
currentPage: data.current_page ?? null,
|
|
21
|
+
perPage: data.per_page ?? null,
|
|
22
|
+
totalPages: data.total_pages ?? data.pages ?? null,
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
delete_customer: (input, context) => mutate("/delete-customer", "DELETE", { customer_phone: requiredString(input.customerPhone, "customerPhone") }, context),
|
|
26
|
+
create_label: (input, context) => mutate("/add-new-label", "POST", { label_name: requiredString(input.labelName, "labelName") }, context),
|
|
27
|
+
async list_labels(_input, context) {
|
|
28
|
+
const data = requiredRecord(await request("/get-labels", "GET", context), "Mumble response");
|
|
29
|
+
return { labels: requiredStringArray(data.labels, "Mumble labels", providerResponseError) };
|
|
30
|
+
},
|
|
31
|
+
delete_label: (input, context) => mutate("/delete-label", "DELETE", { label_name: requiredString(input.labelName, "labelName") }, context),
|
|
32
|
+
};
|
|
33
|
+
export const executors = defineApiKeyProviderExecutors(service, handlers, {
|
|
34
|
+
skipDnsValidation: true,
|
|
35
|
+
});
|
|
36
|
+
export const proxy = defineProviderProxy({
|
|
37
|
+
service,
|
|
38
|
+
baseUrl,
|
|
39
|
+
auth: { type: "api_key_header", name: "Mumble-Api-Key" },
|
|
40
|
+
skipDnsValidation: true,
|
|
41
|
+
});
|
|
42
|
+
export const credentialValidators = {
|
|
43
|
+
async apiKey(input, { fetcher, signal }) {
|
|
44
|
+
const context = { apiKey: input.apiKey, fetcher, signal };
|
|
45
|
+
await handlers.list_labels({}, context);
|
|
46
|
+
return {
|
|
47
|
+
profile: { displayName: "Mumble API Key" },
|
|
48
|
+
grantedScopes: [],
|
|
49
|
+
metadata: { apiBaseUrl: baseUrl, validationEndpoint: "/get-labels" },
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
function customerBody(input) {
|
|
54
|
+
return {
|
|
55
|
+
...optionalRecord(input.marketingAttribution),
|
|
56
|
+
...compactObject({
|
|
57
|
+
customer_phone: requiredString(input.customerPhone, "customerPhone"),
|
|
58
|
+
name: optionalString(input.name),
|
|
59
|
+
email: optionalString(input.email),
|
|
60
|
+
source: optionalString(input.source),
|
|
61
|
+
bot_token: optionalString(input.botToken),
|
|
62
|
+
}),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
async function mutate(path, method, body, context) {
|
|
66
|
+
const data = requiredRecord(await request(path, method, context, body), "Mumble response");
|
|
67
|
+
return { success: requiredBoolean(data.success, "Mumble success"), message: optionalString(data.message) ?? null };
|
|
68
|
+
}
|
|
69
|
+
async function request(path, method, context, body, query) {
|
|
70
|
+
const url = new URL(`${baseUrl}${path}`);
|
|
71
|
+
for (const [key, value] of Object.entries(query ?? {}))
|
|
72
|
+
url.searchParams.set(key, value);
|
|
73
|
+
const response = await context.fetcher(url, {
|
|
74
|
+
method,
|
|
75
|
+
headers: {
|
|
76
|
+
accept: "application/json",
|
|
77
|
+
"content-type": "application/json",
|
|
78
|
+
"mumble-api-key": context.apiKey,
|
|
79
|
+
"user-agent": providerUserAgent,
|
|
80
|
+
},
|
|
81
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
82
|
+
signal: context.signal,
|
|
83
|
+
});
|
|
84
|
+
const text = await readProviderTextBody(response, "Mumble response");
|
|
85
|
+
let data = null;
|
|
86
|
+
try {
|
|
87
|
+
data = text ? JSON.parse(text) : null;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
throw new ProviderRequestError(502, "Mumble returned invalid JSON");
|
|
91
|
+
}
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
const record = optionalRecord(data);
|
|
94
|
+
throw new ProviderRequestError(response.status, optionalString(record?.message) ??
|
|
95
|
+
optionalString(record?.error) ??
|
|
96
|
+
`Mumble request failed with status ${response.status}`);
|
|
97
|
+
}
|
|
98
|
+
return data;
|
|
99
|
+
}
|
|
@@ -3,6 +3,15 @@ import type { ProviderActionHandlers } from "../provider-runtime.ts";
|
|
|
3
3
|
interface NotionActionContext {
|
|
4
4
|
accessToken: string;
|
|
5
5
|
fetcher: typeof fetch;
|
|
6
|
+
/**
|
|
7
|
+
* The stored credential's runtime metadata. For an OAuth credential this is
|
|
8
|
+
* the token-exchange response minus its secrets — `workspace_id`, `owner`,
|
|
9
|
+
* `bot_id`, `workspace_name` — merged with the `/users/me` bot object the
|
|
10
|
+
* validator stored, whose `bot` carries `workspace_id`, `owner` and
|
|
11
|
+
* `workspace_name` as well. For an internal integration only the latter
|
|
12
|
+
* exists. `get_current_user` reads both here and makes no request.
|
|
13
|
+
*/
|
|
14
|
+
metadata: Record<string, unknown>;
|
|
6
15
|
}
|
|
7
16
|
type NotionActionHandler = (input: Record<string, unknown>, context: NotionActionContext) => Promise<unknown>;
|
|
8
17
|
export declare const notionActionHandlers: ProviderActionHandlers<"notion", NotionActionHandler>;
|
|
@@ -5,6 +5,9 @@ const notionApiBaseUrl = "https://api.notion.com/v1";
|
|
|
5
5
|
const notionFetch = createProviderFetch({ skipDnsValidation: true });
|
|
6
6
|
const notionCoreVersion = "2026-03-11";
|
|
7
7
|
export const notionActionHandlers = {
|
|
8
|
+
get_current_user(_input, context) {
|
|
9
|
+
return Promise.resolve(notionGetCurrentUser(context.metadata));
|
|
10
|
+
},
|
|
8
11
|
search(input, context) {
|
|
9
12
|
return notionSearch(input, context.accessToken, context.fetcher);
|
|
10
13
|
},
|
|
@@ -86,8 +89,14 @@ export const executors = defineProviderExecutors({
|
|
|
86
89
|
handlers: notionActionHandlers,
|
|
87
90
|
skipDnsValidation: true,
|
|
88
91
|
async createContext(context, fetcher) {
|
|
89
|
-
|
|
90
|
-
|
|
92
|
+
// Resolved ONCE: a resolution may refresh the token, and the bearer
|
|
93
|
+
// helper would resolve it a second time.
|
|
94
|
+
const stored = await context.getCredential(service);
|
|
95
|
+
return {
|
|
96
|
+
accessToken: bearerTokenOf(stored),
|
|
97
|
+
fetcher,
|
|
98
|
+
metadata: stored && stored.authType !== "no_auth" ? stored.metadata : {},
|
|
99
|
+
};
|
|
91
100
|
},
|
|
92
101
|
});
|
|
93
102
|
export const proxy = async (input, context) => {
|
|
@@ -124,10 +133,89 @@ export const credentialValidators = {
|
|
|
124
133
|
async apiKey(input, { fetcher }) {
|
|
125
134
|
return validateNotionCredential(input.apiKey, fetcher);
|
|
126
135
|
},
|
|
136
|
+
/**
|
|
137
|
+
* The profile is the OWNING USER, not the bot.
|
|
138
|
+
*
|
|
139
|
+
* `GET /users/me` under an OAuth token describes the integration's bot, and
|
|
140
|
+
* a bot id is a UUID like any member's — so a consumer that linked the
|
|
141
|
+
* connecting person to this profile's `accountId` would bind them to a
|
|
142
|
+
* principal that authorizes nobody, with nothing anywhere looking wrong.
|
|
143
|
+
* The grant was requested with `owner=user`, so the exchange response
|
|
144
|
+
* already names the human; it is on `input.metadata`. The liveness call
|
|
145
|
+
* still runs, because that is what proves the token works.
|
|
146
|
+
*/
|
|
127
147
|
async oauth2(input, { fetcher }) {
|
|
128
|
-
|
|
148
|
+
const live = await validateNotionCredential(input.accessToken, fetcher);
|
|
149
|
+
const owner = grantOwner(input.metadata);
|
|
150
|
+
if (!owner) {
|
|
151
|
+
return live;
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
profile: {
|
|
155
|
+
accountId: owner.id,
|
|
156
|
+
displayName: owner.name ?? live.profile.displayName,
|
|
157
|
+
},
|
|
158
|
+
metadata: live.metadata,
|
|
159
|
+
};
|
|
129
160
|
},
|
|
130
161
|
};
|
|
162
|
+
/** The token's bearer value, whichever stored kind carries it. */
|
|
163
|
+
function bearerTokenOf(credential) {
|
|
164
|
+
if (credential?.authType === "oauth2") {
|
|
165
|
+
return credential.accessToken;
|
|
166
|
+
}
|
|
167
|
+
if (credential?.authType === "api_key") {
|
|
168
|
+
return credential.apiKey;
|
|
169
|
+
}
|
|
170
|
+
throw new ProviderRequestError(401, `Configure ${service} credentials first.`);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* The person named as the credential's owner, or `undefined` when none is
|
|
174
|
+
* (a grant whose `owner.type` is `workspace`, which is every internal
|
|
175
|
+
* integration). Notion states the owner twice: at the top level of the token
|
|
176
|
+
* exchange, and under `bot.owner` of the `/users/me` bot object the validator
|
|
177
|
+
* stored. The exchange is read first, the bot object when it is absent.
|
|
178
|
+
*/
|
|
179
|
+
function grantOwner(metadata) {
|
|
180
|
+
const owner = asObject(metadata.owner) ?? asObject(asObject(metadata.bot)?.owner);
|
|
181
|
+
if (owner?.type !== "user") {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
const user = asObject(owner.user);
|
|
185
|
+
const id = asNonEmptyString(user?.id);
|
|
186
|
+
return id ? { id, name: asNonEmptyString(user?.name) } : undefined;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* `get_current_user`: the workspace and owner of the credential, and nothing
|
|
190
|
+
* else, read from what is already stored with it.
|
|
191
|
+
*
|
|
192
|
+
* The workspace id has two sources and neither costs a request: the OAuth
|
|
193
|
+
* token exchange names it as `workspace_id`, and the `/users/me` bot object
|
|
194
|
+
* the validator stored names it as `bot.workspace_id` for OAuth grants and
|
|
195
|
+
* internal integrations alike. Refuses rather than guesses when neither is
|
|
196
|
+
* present, which means the credential was stored without its bot object and
|
|
197
|
+
* needs to be validated again.
|
|
198
|
+
*/
|
|
199
|
+
function notionGetCurrentUser(metadata) {
|
|
200
|
+
const bot = asObject(metadata.bot);
|
|
201
|
+
const workspaceId = asNonEmptyString(metadata.workspace_id) ?? asNonEmptyString(bot?.workspace_id);
|
|
202
|
+
if (!workspaceId) {
|
|
203
|
+
// No explicit code: `providerErrorCodes` is the vocabulary a provider may
|
|
204
|
+
// put on the wire, and a missing credential field is not in it. The
|
|
205
|
+
// convention this follows is `provider-runtime.ts`'s own
|
|
206
|
+
// "credential metadata is missing …" — a plain 400 — with a message that
|
|
207
|
+
// says which field and what to do instead of only naming it.
|
|
208
|
+
throw new ProviderRequestError(400, "the stored Notion credential carries no workspace_id; reconnect Notion so its bot object is stored with the credential");
|
|
209
|
+
}
|
|
210
|
+
const owner = grantOwner(metadata);
|
|
211
|
+
return {
|
|
212
|
+
workspaceId,
|
|
213
|
+
workspaceName: asNonEmptyString(metadata.workspace_name) ?? asNonEmptyString(bot?.workspace_name) ?? null,
|
|
214
|
+
userId: owner?.id ?? null,
|
|
215
|
+
userName: owner?.name ?? null,
|
|
216
|
+
isBot: owner === undefined,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
131
219
|
async function validateNotionCredential(accessToken, fetcher) {
|
|
132
220
|
const profile = await fetchNotionCurrentAccount(accessToken, fetcher);
|
|
133
221
|
return {
|
|
@@ -171,15 +259,82 @@ async function notionRetrievePage(input, accessToken, fetcher) {
|
|
|
171
259
|
}, fetcher);
|
|
172
260
|
return page ?? {};
|
|
173
261
|
}
|
|
262
|
+
/**
|
|
263
|
+
* The revision of whatever `pageId` names, and the reachability check that
|
|
264
|
+
* comes with reading it.
|
|
265
|
+
*
|
|
266
|
+
* **Pages and blocks both**, because this action's input has always been
|
|
267
|
+
* documented as "the page or block ID" and its description as "a Notion page
|
|
268
|
+
* **or block subtree**". A preflight that only knew `GET /pages/{id}` turned
|
|
269
|
+
* the advertised block-subtree flow into a 404 before the render was ever
|
|
270
|
+
* attempted — Notion answers `object_not_found` for a block id there.
|
|
271
|
+
*
|
|
272
|
+
* Pages first, since that is the overwhelmingly common input and costs one
|
|
273
|
+
* request; a 404 falls through to `/blocks/{id}`, which carries its own
|
|
274
|
+
* `last_edited_time`. Any other status propagates unchanged: a 401, 403 or
|
|
275
|
+
* 429 is an answer about the credential, not about which kind of id this is,
|
|
276
|
+
* and retrying it against a second endpoint would only double the cost and
|
|
277
|
+
* blur the error.
|
|
278
|
+
*/
|
|
279
|
+
async function notionLastEditedTime(id, accessToken, fetcher) {
|
|
280
|
+
for (const path of [`/pages/${id}`, `/blocks/${id}`]) {
|
|
281
|
+
let object;
|
|
282
|
+
try {
|
|
283
|
+
object = (await notionRequest(accessToken, { path }, fetcher)) ?? {};
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
if (error instanceof ProviderRequestError && error.status === 404 && !path.startsWith("/blocks/")) {
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
throw error;
|
|
290
|
+
}
|
|
291
|
+
// A successful answer settles which kind of id this is. Only a 404 falls
|
|
292
|
+
// through, so an object Notion returned without a revision is malformed
|
|
293
|
+
// rather than a reason to consult the other endpoint.
|
|
294
|
+
const lastEditedTime = asNonEmptyString(object.last_edited_time);
|
|
295
|
+
if (!lastEditedTime) {
|
|
296
|
+
throw new ProviderRequestError(502, `Notion returned ${id} without a last_edited_time`);
|
|
297
|
+
}
|
|
298
|
+
return lastEditedTime;
|
|
299
|
+
}
|
|
300
|
+
// Unreachable: the block attempt either returns, rethrows its own 404, or
|
|
301
|
+
// throws the 502 above. Kept so the bounded loop has an explicit tail.
|
|
302
|
+
throw new ProviderRequestError(502, `Notion answered neither /pages nor /blocks for ${id}`);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* One page or block subtree as Markdown.
|
|
306
|
+
*
|
|
307
|
+
* Two requests, the object first: it is the cheap question ("can this grant
|
|
308
|
+
* reach this, and when did it last change") and answers a 404 before the
|
|
309
|
+
* expensive render is attempted. The markdown response has no revision of its
|
|
310
|
+
* own, so `lastEditedTime` comes from that object.
|
|
311
|
+
*
|
|
312
|
+
* **Notion's fields keep Notion's names.** This action shipped with the
|
|
313
|
+
* provider, so its body is a contract SDK and CLI callers already read; the
|
|
314
|
+
* response is forwarded and the two constructed fields are added beside it.
|
|
315
|
+
* `pageId` is echoed from the INPUT — Notion may spell an id dashed or
|
|
316
|
+
* undashed in its own body, and a consumer joining rows to bindings needs the
|
|
317
|
+
* spelling it asked with.
|
|
318
|
+
*/
|
|
174
319
|
async function notionRetrievePageMarkdown(input, accessToken, fetcher) {
|
|
175
320
|
const pageId = String(input.pageId);
|
|
176
|
-
const
|
|
321
|
+
const lastEditedTime = await notionLastEditedTime(pageId, accessToken, fetcher);
|
|
322
|
+
const rendered = (await notionRequest(accessToken, {
|
|
177
323
|
path: `/pages/${pageId}/markdown`,
|
|
178
324
|
query: compactQuery({
|
|
179
325
|
include_transcript: typeof input.includeTranscript === "boolean" ? String(input.includeTranscript) : undefined,
|
|
180
326
|
}),
|
|
181
|
-
}, fetcher);
|
|
182
|
-
return
|
|
327
|
+
}, fetcher)) ?? {};
|
|
328
|
+
return {
|
|
329
|
+
...rendered,
|
|
330
|
+
markdown: typeof rendered.markdown === "string" ? rendered.markdown : "",
|
|
331
|
+
truncated: rendered.truncated === true,
|
|
332
|
+
unknown_block_ids: Array.isArray(rendered.unknown_block_ids)
|
|
333
|
+
? rendered.unknown_block_ids.filter((id) => typeof id === "string")
|
|
334
|
+
: [],
|
|
335
|
+
pageId,
|
|
336
|
+
lastEditedTime,
|
|
337
|
+
};
|
|
183
338
|
}
|
|
184
339
|
async function notionRetrievePageProperty(input, accessToken, fetcher) {
|
|
185
340
|
const payload = await notionRequest(accessToken, {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CredentialValidators, ProviderExecutors, ProviderProxyExecutor } from "../../core/types.ts";
|
|
2
|
+
export declare const executors: ProviderExecutors;
|
|
3
|
+
export declare const proxy: ProviderProxyExecutor;
|
|
4
|
+
export declare const credentialValidators: CredentialValidators;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { objectArray, optionalRecord, optionalString, requiredRecord, requiredString } from "../../core/cast.js";
|
|
2
|
+
import { readProviderTextBody } from "../provider-runtime.js";
|
|
3
|
+
import { basicAuthorizationHeader, defineApiKeyProviderExecutors, defineProviderProxy, providerInputError, providerResponseError, providerUserAgent, ProviderRequestError, } from "../provider-runtime.js";
|
|
4
|
+
const service = "omise", baseUrl = "https://api.omise.co";
|
|
5
|
+
const handlers = {
|
|
6
|
+
async get_account(_i, c) {
|
|
7
|
+
return { account: requiredRecord(await request("/account", c), "Omise account") };
|
|
8
|
+
},
|
|
9
|
+
async get_balance(_i, c) {
|
|
10
|
+
return { balance: requiredRecord(await request("/balance", c), "Omise balance") };
|
|
11
|
+
},
|
|
12
|
+
async list_customers(i, c) {
|
|
13
|
+
return normalizeList(await request("/customers", c, "GET", undefined, i), "customers");
|
|
14
|
+
},
|
|
15
|
+
async get_customer(i, c) {
|
|
16
|
+
return {
|
|
17
|
+
customer: requiredRecord(await request(`/customers/${segment(i.customer_id, "customer_id")}`, c), "Omise customer"),
|
|
18
|
+
};
|
|
19
|
+
},
|
|
20
|
+
async create_customer(i, c) {
|
|
21
|
+
return { customer: requiredRecord(await request("/customers", c, "POST", customerForm(i)), "Omise customer") };
|
|
22
|
+
},
|
|
23
|
+
async update_customer(i, c) {
|
|
24
|
+
const form = customerForm(i);
|
|
25
|
+
if (!form.size)
|
|
26
|
+
throw providerInputError("update_customer requires email, description, or metadata");
|
|
27
|
+
return {
|
|
28
|
+
customer: requiredRecord(await request(`/customers/${segment(i.customer_id, "customer_id")}`, c, "PATCH", form), "Omise customer"),
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
async delete_customer(i, c) {
|
|
32
|
+
return {
|
|
33
|
+
customer: requiredRecord(await request(`/customers/${segment(i.customer_id, "customer_id")}`, c, "DELETE"), "Omise customer"),
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
async list_charges(i, c) {
|
|
37
|
+
return normalizeList(await request("/charges", c, "GET", undefined, i), "charges");
|
|
38
|
+
},
|
|
39
|
+
async get_charge(i, c) {
|
|
40
|
+
return {
|
|
41
|
+
charge: requiredRecord(await request(`/charges/${segment(i.charge_id, "charge_id")}`, c), "Omise charge"),
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
export const executors = defineApiKeyProviderExecutors(service, handlers, {
|
|
46
|
+
skipDnsValidation: true,
|
|
47
|
+
});
|
|
48
|
+
export const proxy = defineProviderProxy({
|
|
49
|
+
service,
|
|
50
|
+
baseUrl,
|
|
51
|
+
auth: { type: "api_key_basic", suffix: ":" },
|
|
52
|
+
skipDnsValidation: true,
|
|
53
|
+
});
|
|
54
|
+
export const credentialValidators = {
|
|
55
|
+
async apiKey(input, { fetcher, signal }) {
|
|
56
|
+
const account = requiredRecord(await request("/account", { apiKey: input.apiKey, fetcher, signal }), "Omise account");
|
|
57
|
+
const id = optionalString(account.id)?.trim();
|
|
58
|
+
return {
|
|
59
|
+
profile: {
|
|
60
|
+
accountId: id,
|
|
61
|
+
displayName: optionalString(account.email)?.trim() || (id ? `Omise ${id}` : "Omise Account"),
|
|
62
|
+
},
|
|
63
|
+
grantedScopes: [],
|
|
64
|
+
metadata: { apiBaseUrl: baseUrl, validationEndpoint: "/account" },
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
function segment(value, name) {
|
|
69
|
+
return encodeURIComponent(requiredString(value, name));
|
|
70
|
+
}
|
|
71
|
+
function customerForm(input) {
|
|
72
|
+
const form = new URLSearchParams();
|
|
73
|
+
for (const key of ["email", "description"]) {
|
|
74
|
+
const value = optionalString(input[key]);
|
|
75
|
+
if (value !== undefined)
|
|
76
|
+
form.set(key, value);
|
|
77
|
+
}
|
|
78
|
+
for (const [key, value] of Object.entries(optionalRecord(input.metadata) ?? {}))
|
|
79
|
+
if (["string", "number", "boolean"].includes(typeof value))
|
|
80
|
+
form.set(`metadata[${key}]`, String(value));
|
|
81
|
+
return form;
|
|
82
|
+
}
|
|
83
|
+
function normalizeList(value, name) {
|
|
84
|
+
const record = requiredRecord(value, `Omise ${name}`);
|
|
85
|
+
const pagination = { ...record };
|
|
86
|
+
delete pagination.data;
|
|
87
|
+
return { [name]: objectArray(record.data, `Omise ${name} list data`, providerResponseError), pagination };
|
|
88
|
+
}
|
|
89
|
+
async function request(path, context, method = "GET", form, query) {
|
|
90
|
+
const url = new URL(path, baseUrl);
|
|
91
|
+
for (const [key, value] of Object.entries(query ?? {}))
|
|
92
|
+
if (typeof value === "string" || typeof value === "number")
|
|
93
|
+
url.searchParams.set(key, String(value));
|
|
94
|
+
const response = await context.fetcher(url, {
|
|
95
|
+
method,
|
|
96
|
+
headers: {
|
|
97
|
+
accept: "application/json",
|
|
98
|
+
authorization: basicAuthorizationHeader(`${context.apiKey}:`),
|
|
99
|
+
"user-agent": providerUserAgent,
|
|
100
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
101
|
+
},
|
|
102
|
+
body: form,
|
|
103
|
+
signal: context.signal,
|
|
104
|
+
});
|
|
105
|
+
const text = await readProviderTextBody(response, "Omise response");
|
|
106
|
+
let payload = null;
|
|
107
|
+
try {
|
|
108
|
+
payload = text ? JSON.parse(text) : null;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
if (response.ok)
|
|
112
|
+
throw new ProviderRequestError(502, "Omise returned invalid JSON");
|
|
113
|
+
payload = text;
|
|
114
|
+
}
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
const record = optionalRecord(payload);
|
|
117
|
+
throw new ProviderRequestError(response.status, optionalString(record?.message) ?? `Omise request failed with status ${response.status}`, payload, optionalString(record?.code));
|
|
118
|
+
}
|
|
119
|
+
return payload;
|
|
120
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ActionDefinition, JsonSchema } from "../../core/types.ts";
|
|
2
|
+
type ActionAsyncLifecycle = NonNullable<ActionDefinition["asyncLifecycle"]>;
|
|
3
|
+
interface PanjivaActionSpec {
|
|
4
|
+
name: string;
|
|
5
|
+
path: string;
|
|
6
|
+
method: "GET" | "POST";
|
|
7
|
+
description: string;
|
|
8
|
+
inputSchema: JsonSchema;
|
|
9
|
+
outputSchema: JsonSchema;
|
|
10
|
+
asyncLifecycle?: ActionAsyncLifecycle;
|
|
11
|
+
}
|
|
12
|
+
export declare const panjivaActionSpecs: PanjivaActionSpec[];
|
|
13
|
+
export declare const panjivaActions: readonly ActionDefinition[];
|
|
14
|
+
export {};
|