@tool-bridge/server 0.16.0 → 0.17.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/dist/{airtable-S3T4TAN7.js → airtable-NOSOMOVB.js} +106 -114
- package/dist/{alt_text_generator_ai-4DIRIDKL.js → alt_text_generator_ai-BHIJ4LW5.js} +25 -16
- package/dist/{amap-LGVGNPML.js → amap-QRLP4TWZ.js} +114 -123
- package/dist/{anthropic-27RFZO35.js → anthropic-IEOI36EV.js} +34 -56
- package/dist/{apify-6WLYAIAS.js → apify-3CCYTQVK.js} +31 -49
- package/dist/{brave_search-K2SVJ66F.js → brave_search-PZNYDQG7.js} +52 -77
- package/dist/chunk-JXHMDBAY.js +45 -0
- package/dist/chunk-LMLX3DJF.js +50 -0
- package/dist/{chunk-YB2FLNWI.js → chunk-RVWZN3CI.js} +2103 -1775
- package/dist/{chunk-BB6ZLMTU.js → chunk-TLNUIPFZ.js} +492 -300
- package/dist/chunk-U5UHT7CX.js +977 -0
- package/dist/chunk-U67V476Y.js +35 -0
- package/dist/chunk-WW2IMPQK.js +283 -0
- package/dist/{chunk-VK3V2WTY.js → chunk-YASUMV2K.js} +4 -6
- package/dist/{circleci-WV3ITU7Q.js → circleci-VSJ4O5FC.js} +36 -55
- package/dist/{clerk-NFQEFKS4.js → clerk-CC2JZBZI.js} +60 -80
- package/dist/{cloudflare_dns-2RK5ASBJ.js → cloudflare_dns-PJEBSEYQ.js} +90 -113
- package/dist/{cohere-5KEW7LWT.js → cohere-KBACYSPF.js} +33 -49
- package/dist/{confluence-SZE63S46.js → confluence-2PX3O7G5.js} +79 -115
- package/dist/{convertapi-QPG2JC5K.js → convertapi-BVOTD2PJ.js} +13 -16
- package/dist/{currencyapi-UO2APQRY.js → currencyapi-6ZQ2VNQ7.js} +30 -53
- package/dist/{deepseek-LJELIMM3.js → deepseek-MB3WVVTB.js} +30 -38
- package/dist/{docker_hub-2MFXSBOF.js → docker_hub-7CLQL2IJ.js} +141 -157
- package/dist/{dropbox-GQYNTTVA.js → dropbox-VFYDVUNK.js} +134 -141
- package/dist/{dub-KI2LHXST.js → dub-QN3EETJY.js} +61 -93
- package/dist/{e2b-WO6ISY3C.js → e2b-NKC3Y776.js} +39 -69
- package/dist/{exa-IZ7B3BPT.js → exa-KKZ6F25K.js} +49 -77
- package/dist/{fal_ai-LTMF36GJ.js → fal_ai-25LYJD2O.js} +37 -44
- package/dist/{feishu-WM7SLSFD.js → feishu-NRT55B3Q.js} +4 -6
- package/dist/{feishu_custom_bot-66W3MXH2.js → feishu_custom_bot-3W3XXUG4.js} +4 -5
- package/dist/{figma-2Z274VQZ.js → figma-4FLP35TC.js} +56 -81
- package/dist/{firehydrant-IFI4R65V.js → firehydrant-BLXPLZ3X.js} +40 -53
- package/dist/{fixer-BCCZEB3D.js → fixer-4OR62TGE.js} +31 -43
- package/dist/{fly-755FXYB5.js → fly-MYCKOZZK.js} +50 -66
- package/dist/{front-4FZKKXXK.js → front-3DFYVMF3.js} +43 -66
- package/dist/{geocodio-WYKDJ3DP.js → geocodio-CXMD6VKA.js} +37 -63
- package/dist/{ghost-5BNQTCOH.js → ghost-4UUE737W.js} +51 -57
- package/dist/{github-ULELF5VX.js → github-WFS2ON2N.js} +48 -41
- package/dist/{gmail-G34WT64J.js → gmail-KW7FXA7A.js} +26 -36
- package/dist/{googlecalendar-BQU255SC.js → googlecalendar-AMH5JQMC.js} +57 -78
- package/dist/{googledocs-HPCNQXYJ.js → googledocs-R5VA6CKD.js} +14 -22
- package/dist/{grafana-VOV24FIC.js → grafana-IT6DWIVB.js} +95 -122
- package/dist/{graphhopper-D5RXW6AP.js → graphhopper-TYFDJZWC.js} +32 -46
- package/dist/index.d.ts +57 -50
- package/dist/index.js +4 -3
- package/dist/{ip2proxy-DAYO7EKZ.js → ip2proxy-GJ4HXVXO.js} +35 -42
- package/dist/{ipgeolocation_io-XD4PSLII.js → ipgeolocation_io-OAGR6PRF.js} +40 -60
- package/dist/{ipqualityscore-K27QEAWK.js → ipqualityscore-BCKAMDGL.js} +30 -42
- package/dist/{jina_ai-E6UXFV2P.js → jina_ai-N3NXRVIZ.js} +32 -58
- package/dist/{jira-ZDSXGQ6W.js → jira-CHLBKWLO.js} +116 -126
- package/dist/{langsmith-TIFJRREW.js → langsmith-OIKOTPY3.js} +101 -121
- package/dist/{lemlist-DASEMJMA.js → lemlist-VAKYPKS3.js} +57 -68
- package/dist/{linear-KE6UP4SP.js → linear-Q6QTPJ5R.js} +109 -118
- package/dist/{logsnag-IMNDN4R5.js → logsnag-SQOQBTES.js} +31 -48
- package/dist/main.js +103 -102
- package/dist/{mattermost-HHHMUXQA.js → mattermost-G2KBEICM.js} +45 -62
- package/dist/{mem0-D2FGGOIY.js → mem0-D2FPLYDX.js} +72 -98
- package/dist/{memos-4OVIGFPH.js → memos-76PTWV5V.js} +68 -122
- package/dist/{metabase-33WCX5YD.js → metabase-TWSIDVBM.js} +47 -60
- package/dist/{mistral_ai-QIMZ2JYL.js → mistral_ai-TP7TQUEJ.js} +35 -40
- package/dist/{mother_duck-M6VWS2VH.js → mother_duck-UXY5THYU.js} +42 -62
- package/dist/{ngrok-Z2PKQBHH.js → ngrok-RZW2ISJK.js} +42 -58
- package/dist/{notes-SS4RPC4K.js → notes-B2I6FWK2.js} +3 -5
- package/dist/{notion-FJCNQ6I7.js → notion-QOKRUE6M.js} +83 -97
- package/dist/{open_exchange_rates-WU57WTT5.js → open_exchange_rates-ODLFWEJ7.js} +35 -39
- package/dist/{openai-JODZ4GKT.js → openai-ZPBPPPGT.js} +51 -55
- package/dist/{opengraph_io-SQRAUSV5.js → opengraph_io-EOI5UJKT.js} +61 -79
- package/dist/{openrouter-Q5XXEJZ7.js → openrouter-BUWLF3BG.js} +41 -55
- package/dist/{outline-RT2EHJ2X.js → outline-NXS3QRXO.js} +89 -104
- package/dist/{paddle-OF2V7GAC.js → paddle-T4MSKQ76.js} +34 -49
- package/dist/{perplexity-LNZEWLHG.js → perplexity-WW5N2LW7.js} +33 -50
- package/dist/{pinecone-JSJIXZYN.js → pinecone-RY5AZPQM.js} +65 -91
- package/dist/{pipedrive-D4CKVUXR.js → pipedrive-OHYQNZTU.js} +37 -59
- package/dist/{polar-M7ZYP6UR.js → polar-XZIAHXS5.js} +43 -53
- package/dist/{posthog-YV7CZOH4.js → posthog-DTPTWORY.js} +58 -77
- package/dist/{postmark-KYHLECRG.js → postmark-F4UCQKC3.js} +52 -71
- package/dist/{prerender-HCMHBKV2.js → prerender-P3Y2MLIC.js} +32 -50
- package/dist/{pubmed-WYVLCCN3.js → pubmed-RHU3GXFB.js} +28 -60
- package/dist/{railway-TWIRD5KR.js → railway-VB6SRLI6.js} +32 -39
- package/dist/{readwise-UZ467IQ7.js → readwise-DIMSKJZR.js} +62 -78
- package/dist/{render-MECUC5CC.js → render-XCCDCEEK.js} +48 -64
- package/dist/{replicate-A5MEK3SW.js → replicate-IUEOQ4JC.js} +41 -58
- package/dist/{resend-BC6EAWJQ.js → resend-N5MJZH5E.js} +27 -37
- package/dist/{rootly-ZM3QDUIS.js → rootly-25T4NBTU.js} +64 -76
- package/dist/{scrapfly-WAML42QJ.js → scrapfly-PK4XFXUA.js} +45 -51
- package/dist/{scrapingbee-DG7PET3V.js → scrapingbee-ITPBMWQU.js} +25 -33
- package/dist/{screenshot_fyi-HY6WTHIO.js → screenshot_fyi-5U6ZYPKR.js} +29 -47
- package/dist/{semantic_scholar-C5IZA7IP.js → semantic_scholar-BJGCI2MU.js} +37 -56
- package/dist/{sentry-OKBPSTDM.js → sentry-63IC263P.js} +66 -85
- package/dist/{shodan-PPC6DYU4.js → shodan-2WBIFHFN.js} +42 -53
- package/dist/{shopify-EWGUHBXO.js → shopify-XLLJRAGM.js} +32 -49
- package/dist/{stripe-6RPDPC5W.js → stripe-WLVCY3UN.js} +4 -5
- package/dist/{supabase-SK7DQ42N.js → supabase-BKNZ35ER.js} +69 -88
- package/dist/{tavily-YCG5VQMH.js → tavily-YFSDEUTL.js} +37 -62
- package/dist/{telegram-2OES5FYB.js → telegram-FC35W74G.js} +168 -177
- package/dist/{telnyx-POOSBBR4.js → telnyx-MI32XZUG.js} +30 -50
- package/dist/{todoist-M7YD6YSS.js → todoist-4ZFJKZC6.js} +77 -89
- package/dist/{trello-IS6V5W3E.js → trello-UOGFNMK4.js} +108 -122
- package/dist/{turso-RCFHUFVH.js → turso-YTSTW3ZS.js} +52 -64
- package/dist/{twilio-OS2RXFGO.js → twilio-XAJDFUQH.js} +48 -55
- package/dist/{umami-PQ2SJ2LN.js → umami-ZVIUBPAI.js} +49 -69
- package/dist/{unsplash-C6BPZO4E.js → unsplash-IU3PLDNS.js} +35 -52
- package/dist/{upstash_redis-WH6UER7H.js → upstash_redis-3EYJW7SY.js} +28 -40
- package/dist/{uptimerobot-M3YZGS6Z.js → uptimerobot-PJG2ASRU.js} +11 -12
- package/dist/{v2ex-R4JWTEHN.js → v2ex-KFQWWGFC.js} +36 -61
- package/dist/{vercel-FZVYUOQD.js → vercel-I2ZDOQRL.js} +124 -150
- package/dist/{webapi-VLM4IKVB.js → webapi-GW5QXWXE.js} +1 -1
- package/dist/{wolfram_alpha_api-2KOLO5DC.js → wolfram_alpha_api-BNXOJMB6.js} +26 -34
- package/dist/{wordpress-XRWGO6LG.js → wordpress-36D7BSMP.js} +87 -104
- package/dist/{workos-WR4NKOYL.js → workos-6X4JJRRC.js} +37 -56
- package/dist/{zhihu-BKZIB3WA.js → zhihu-CIXKCHIU.js} +35 -57
- package/package.json +5 -5
- package/dist/chunk-2O27H4Y2.js +0 -183
- package/dist/chunk-GKX72JMJ.js +0 -378
- package/dist/chunk-MLKGABMK.js +0 -9
|
@@ -1,22 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createProviderHttpClient
|
|
3
|
+
} from "./chunk-WW2IMPQK.js";
|
|
4
|
+
import {
|
|
5
|
+
asJsonObject,
|
|
6
|
+
booleanValue,
|
|
7
|
+
compactDefined,
|
|
8
|
+
integerValue,
|
|
9
|
+
trimmedText
|
|
10
|
+
} from "./chunk-JXHMDBAY.js";
|
|
1
11
|
import {
|
|
2
12
|
createProviderPlugin,
|
|
3
13
|
requireCredential,
|
|
4
14
|
upstreamError
|
|
5
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-YASUMV2K.js";
|
|
6
16
|
import {
|
|
7
|
-
assertPublicHttpUrl
|
|
8
|
-
|
|
9
|
-
} from "./chunk-2O27H4Y2.js";
|
|
10
|
-
import "./chunk-GKX72JMJ.js";
|
|
17
|
+
assertPublicHttpUrl
|
|
18
|
+
} from "./chunk-U5UHT7CX.js";
|
|
11
19
|
import {
|
|
12
20
|
TBError,
|
|
13
21
|
external_exports
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
22
|
+
} from "./chunk-RVWZN3CI.js";
|
|
23
|
+
import "./chunk-U67V476Y.js";
|
|
16
24
|
|
|
17
25
|
// ../plugins/src/jira/api.ts
|
|
18
26
|
var SERVICE = "jira";
|
|
19
27
|
var DEFAULT_LIMIT = 50;
|
|
28
|
+
var http = createProviderHttpClient({ service: SERVICE });
|
|
20
29
|
var DEFAULT_ISSUE_FIELD_IDS = [
|
|
21
30
|
"summary",
|
|
22
31
|
"description",
|
|
@@ -31,32 +40,13 @@ var DEFAULT_ISSUE_FIELD_IDS = [
|
|
|
31
40
|
"updated",
|
|
32
41
|
"duedate"
|
|
33
42
|
];
|
|
34
|
-
function text(value) {
|
|
35
|
-
if (typeof value !== "string") return void 0;
|
|
36
|
-
const trimmed = value.trim();
|
|
37
|
-
return trimmed === "" ? void 0 : trimmed;
|
|
38
|
-
}
|
|
39
|
-
function record(value) {
|
|
40
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
41
|
-
}
|
|
42
|
-
function integer(value) {
|
|
43
|
-
return typeof value === "number" && Number.isInteger(value) ? value : void 0;
|
|
44
|
-
}
|
|
45
|
-
function boolean(value) {
|
|
46
|
-
return typeof value === "boolean" ? value : void 0;
|
|
47
|
-
}
|
|
48
|
-
function compact(input) {
|
|
49
|
-
return Object.fromEntries(
|
|
50
|
-
Object.entries(input).filter(([, value]) => value !== void 0)
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
43
|
function stringArray(value) {
|
|
54
44
|
if (!Array.isArray(value)) return [];
|
|
55
|
-
return value.map((item) =>
|
|
45
|
+
return value.map((item) => trimmedText(item)).filter((item) => item !== void 0);
|
|
56
46
|
}
|
|
57
47
|
function recordArray(value) {
|
|
58
48
|
if (!Array.isArray(value)) return [];
|
|
59
|
-
return value.map((item) =>
|
|
49
|
+
return value.map((item) => asJsonObject(item)).filter((item) => item !== void 0);
|
|
60
50
|
}
|
|
61
51
|
function joinOptionalList(values) {
|
|
62
52
|
return values.length > 0 ? values.join(",") : void 0;
|
|
@@ -98,7 +88,7 @@ function buildUrl(base, pathOrUrl, query) {
|
|
|
98
88
|
const target = isAbsoluteUrl(pathOrUrl) ? new URL(pathOrUrl) : new URL(pathOrUrl.replace(/^\/+/, ""), `${base}/`);
|
|
99
89
|
const baseUrl = new URL(base);
|
|
100
90
|
if (target.origin !== baseUrl.origin || !target.pathname.startsWith(`${baseUrl.pathname}/`)) {
|
|
101
|
-
throw new TBError("invalid_argument",
|
|
91
|
+
throw new TBError("invalid_argument", "jira requests must target the configured API base");
|
|
102
92
|
}
|
|
103
93
|
for (const [key, value] of Object.entries(query ?? {})) {
|
|
104
94
|
if (value === void 0 || value === "") continue;
|
|
@@ -107,53 +97,53 @@ function buildUrl(base, pathOrUrl, query) {
|
|
|
107
97
|
return target.toString();
|
|
108
98
|
}
|
|
109
99
|
function errorMessage(payload) {
|
|
110
|
-
const body =
|
|
100
|
+
const body = asJsonObject(payload);
|
|
111
101
|
if (body === void 0) return "jira request failed";
|
|
112
102
|
const messages = stringArray(body.errorMessages);
|
|
113
103
|
if (messages.length > 0) return messages.join("; ");
|
|
114
|
-
const fieldErrors =
|
|
104
|
+
const fieldErrors = asJsonObject(body.errors);
|
|
115
105
|
if (fieldErrors !== void 0) {
|
|
116
106
|
const parts = [];
|
|
117
107
|
for (const [key, value] of Object.entries(fieldErrors)) {
|
|
118
|
-
const message =
|
|
108
|
+
const message = trimmedText(value);
|
|
119
109
|
if (message !== void 0) parts.push(`${key}: ${message}`);
|
|
120
110
|
}
|
|
121
111
|
if (parts.length > 0) return parts.join("; ");
|
|
122
112
|
}
|
|
123
|
-
return
|
|
113
|
+
return trimmedText(body.message) ?? "jira request failed";
|
|
124
114
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
try {
|
|
129
|
-
return JSON.parse(raw);
|
|
130
|
-
} catch {
|
|
131
|
-
return { message: raw };
|
|
132
|
-
}
|
|
115
|
+
function responsePayload(data, bodyKind) {
|
|
116
|
+
if (bodyKind === "empty") return {};
|
|
117
|
+
return bodyKind === "invalid-json" ? { message: data } : data;
|
|
133
118
|
}
|
|
134
119
|
async function requestValue(ctx, options) {
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const response = await guardedFetch(buildUrl(apiBaseUrl(ctx), options.path, options.query), {
|
|
120
|
+
const baseUrl = apiBaseUrl(ctx);
|
|
121
|
+
const result = await http.request({
|
|
122
|
+
baseUrl,
|
|
123
|
+
// create_issue 会跟随 Jira 返回的 self;buildUrl 先锁定 origin 与 REST API path 前缀。
|
|
124
|
+
path: buildUrl(baseUrl, options.path, options.query),
|
|
141
125
|
method: options.method ?? (options.body === void 0 ? "GET" : "POST"),
|
|
142
|
-
headers
|
|
143
|
-
|
|
126
|
+
headers: {
|
|
127
|
+
accept: "application/json",
|
|
128
|
+
authorization: `Bearer ${requireCredential(ctx, SERVICE, "personalAccessToken")}`
|
|
129
|
+
},
|
|
130
|
+
...options.body === void 0 ? {} : { json: options.body },
|
|
131
|
+
invalidJson: "text",
|
|
132
|
+
mapError: ({ bodyKind, data, status }) => upstreamError(
|
|
133
|
+
status,
|
|
134
|
+
errorMessage(responsePayload(data, bodyKind))
|
|
135
|
+
)
|
|
144
136
|
});
|
|
145
|
-
|
|
146
|
-
if (!response.ok) throw upstreamError(response.status, errorMessage(payload));
|
|
147
|
-
return payload;
|
|
137
|
+
return responsePayload(result.data, result.bodyKind);
|
|
148
138
|
}
|
|
149
139
|
async function requestObject(ctx, options) {
|
|
150
140
|
const payload = await requestValue(ctx, options);
|
|
151
|
-
const body =
|
|
141
|
+
const body = asJsonObject(payload);
|
|
152
142
|
if (body === void 0) throw upstreamError(502, "jira response payload must be a JSON object");
|
|
153
143
|
return body;
|
|
154
144
|
}
|
|
155
145
|
function parseCursor(value) {
|
|
156
|
-
const cursor =
|
|
146
|
+
const cursor = trimmedText(value);
|
|
157
147
|
if (cursor === void 0) return 0;
|
|
158
148
|
const parsed = Number(cursor);
|
|
159
149
|
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
@@ -168,86 +158,86 @@ function nextNumericCursor(startAt, itemCount, total, isLast) {
|
|
|
168
158
|
return String(startAt + itemCount);
|
|
169
159
|
}
|
|
170
160
|
function requireText(value, field) {
|
|
171
|
-
const result =
|
|
161
|
+
const result = trimmedText(value);
|
|
172
162
|
if (result === void 0) throw new TBError("invalid_argument", `${field} is required`);
|
|
173
163
|
return result;
|
|
174
164
|
}
|
|
175
165
|
function normalizeUser(value) {
|
|
176
|
-
const user =
|
|
166
|
+
const user = asJsonObject(value);
|
|
177
167
|
if (user === void 0) return void 0;
|
|
178
|
-
return
|
|
179
|
-
accountId:
|
|
180
|
-
accountType:
|
|
168
|
+
return compactDefined({
|
|
169
|
+
accountId: trimmedText(user.accountId),
|
|
170
|
+
accountType: trimmedText(user.accountType),
|
|
181
171
|
// DC 用 name/key 标识用户,而不是 Cloud 的 accountId。
|
|
182
|
-
name:
|
|
183
|
-
key:
|
|
184
|
-
displayName:
|
|
185
|
-
emailAddress:
|
|
186
|
-
active:
|
|
187
|
-
self:
|
|
188
|
-
timeZone:
|
|
172
|
+
name: trimmedText(user.name),
|
|
173
|
+
key: trimmedText(user.key),
|
|
174
|
+
displayName: trimmedText(user.displayName),
|
|
175
|
+
emailAddress: trimmedText(user.emailAddress),
|
|
176
|
+
active: booleanValue(user.active),
|
|
177
|
+
self: trimmedText(user.self),
|
|
178
|
+
timeZone: trimmedText(user.timeZone)
|
|
189
179
|
});
|
|
190
180
|
}
|
|
191
181
|
function normalizeNamedReference(value) {
|
|
192
|
-
const reference =
|
|
182
|
+
const reference = asJsonObject(value);
|
|
193
183
|
if (reference === void 0) return void 0;
|
|
194
|
-
return
|
|
195
|
-
id:
|
|
196
|
-
name:
|
|
197
|
-
key:
|
|
198
|
-
self:
|
|
199
|
-
description:
|
|
184
|
+
return compactDefined({
|
|
185
|
+
id: trimmedText(reference.id),
|
|
186
|
+
name: trimmedText(reference.name),
|
|
187
|
+
key: trimmedText(reference.key),
|
|
188
|
+
self: trimmedText(reference.self),
|
|
189
|
+
description: trimmedText(reference.description)
|
|
200
190
|
});
|
|
201
191
|
}
|
|
202
192
|
function normalizeProject(project) {
|
|
203
|
-
return
|
|
204
|
-
id:
|
|
205
|
-
key:
|
|
206
|
-
name:
|
|
207
|
-
self:
|
|
208
|
-
description:
|
|
209
|
-
projectTypeKey:
|
|
210
|
-
simplified:
|
|
211
|
-
style:
|
|
212
|
-
url:
|
|
193
|
+
return compactDefined({
|
|
194
|
+
id: trimmedText(project.id),
|
|
195
|
+
key: trimmedText(project.key),
|
|
196
|
+
name: trimmedText(project.name),
|
|
197
|
+
self: trimmedText(project.self),
|
|
198
|
+
description: trimmedText(project.description),
|
|
199
|
+
projectTypeKey: trimmedText(project.projectTypeKey),
|
|
200
|
+
simplified: booleanValue(project.simplified),
|
|
201
|
+
style: trimmedText(project.style),
|
|
202
|
+
url: trimmedText(project.url),
|
|
213
203
|
lead: normalizeUser(project.lead),
|
|
214
204
|
projectCategory: normalizeNamedReference(project.projectCategory),
|
|
215
|
-
avatarUrls:
|
|
205
|
+
avatarUrls: asJsonObject(project.avatarUrls),
|
|
216
206
|
raw: project
|
|
217
207
|
});
|
|
218
208
|
}
|
|
219
209
|
function normalizeIssue(issue) {
|
|
220
|
-
const fields =
|
|
221
|
-
return
|
|
222
|
-
id:
|
|
223
|
-
key:
|
|
224
|
-
self:
|
|
225
|
-
summary:
|
|
210
|
+
const fields = asJsonObject(issue.fields) ?? {};
|
|
211
|
+
return compactDefined({
|
|
212
|
+
id: trimmedText(issue.id),
|
|
213
|
+
key: trimmedText(issue.key),
|
|
214
|
+
self: trimmedText(issue.self),
|
|
215
|
+
summary: trimmedText(fields.summary),
|
|
226
216
|
description: fields.description,
|
|
227
217
|
status: normalizeNamedReference(fields.status),
|
|
228
218
|
issueType: normalizeNamedReference(fields.issuetype),
|
|
229
|
-
project:
|
|
219
|
+
project: asJsonObject(fields.project) === void 0 ? void 0 : normalizeProject(asJsonObject(fields.project)),
|
|
230
220
|
assignee: normalizeUser(fields.assignee),
|
|
231
221
|
reporter: normalizeUser(fields.reporter),
|
|
232
222
|
priority: normalizeNamedReference(fields.priority),
|
|
233
223
|
labels: stringArray(fields.labels),
|
|
234
|
-
created:
|
|
235
|
-
updated:
|
|
236
|
-
dueDate:
|
|
224
|
+
created: trimmedText(fields.created),
|
|
225
|
+
updated: trimmedText(fields.updated),
|
|
226
|
+
dueDate: trimmedText(fields.duedate),
|
|
237
227
|
fields,
|
|
238
228
|
raw: issue
|
|
239
229
|
});
|
|
240
230
|
}
|
|
241
231
|
function normalizeComment(comment) {
|
|
242
|
-
return
|
|
243
|
-
id:
|
|
244
|
-
self:
|
|
232
|
+
return compactDefined({
|
|
233
|
+
id: trimmedText(comment.id),
|
|
234
|
+
self: trimmedText(comment.self),
|
|
245
235
|
body: comment.body,
|
|
246
236
|
author: normalizeUser(comment.author),
|
|
247
237
|
updateAuthor: normalizeUser(comment.updateAuthor),
|
|
248
|
-
created:
|
|
249
|
-
updated:
|
|
250
|
-
jsdPublic:
|
|
238
|
+
created: trimmedText(comment.created),
|
|
239
|
+
updated: trimmedText(comment.updated),
|
|
240
|
+
jsdPublic: booleanValue(comment.jsdPublic),
|
|
251
241
|
raw: comment
|
|
252
242
|
});
|
|
253
243
|
}
|
|
@@ -255,19 +245,19 @@ function rawText(value) {
|
|
|
255
245
|
return typeof value === "string" && value !== "" ? value : void 0;
|
|
256
246
|
}
|
|
257
247
|
function appendAdfText(value, parts) {
|
|
258
|
-
const node =
|
|
248
|
+
const node = asJsonObject(value);
|
|
259
249
|
if (node === void 0) return;
|
|
260
|
-
const type =
|
|
250
|
+
const type = trimmedText(node.type);
|
|
261
251
|
if (type === "text") {
|
|
262
252
|
const content = rawText(node.text);
|
|
263
253
|
if (content !== void 0) parts.push(content);
|
|
264
254
|
} else if (type === "hardBreak") {
|
|
265
255
|
parts.push("\n");
|
|
266
256
|
} else if (type === "mention" || type === "emoji" || type === "date" || type === "status") {
|
|
267
|
-
const content = rawText(
|
|
257
|
+
const content = rawText(asJsonObject(node.attrs)?.text);
|
|
268
258
|
if (content !== void 0) parts.push(content);
|
|
269
259
|
} else if (type === "inlineCard") {
|
|
270
|
-
const url = rawText(
|
|
260
|
+
const url = rawText(asJsonObject(node.attrs)?.url);
|
|
271
261
|
if (url !== void 0) parts.push(url);
|
|
272
262
|
}
|
|
273
263
|
const children = Array.isArray(node.content) ? node.content : [];
|
|
@@ -286,7 +276,7 @@ async function listProjects(input, ctx) {
|
|
|
286
276
|
const startAt = parseCursor(input.cursor);
|
|
287
277
|
const payload = await requestValue(ctx, {
|
|
288
278
|
path: "/project",
|
|
289
|
-
query:
|
|
279
|
+
query: compactDefined({ expand: joinOptionalList(stringArray(input.expand)) })
|
|
290
280
|
});
|
|
291
281
|
const projects = recordArray(payload).map((project) => normalizeProject(project));
|
|
292
282
|
const page = projects.slice(startAt, startAt + limit);
|
|
@@ -300,7 +290,7 @@ async function listProjects(input, ctx) {
|
|
|
300
290
|
async function getProject(input, ctx) {
|
|
301
291
|
const payload = await requestObject(ctx, {
|
|
302
292
|
path: `/project/${encodeURIComponent(requireText(input.projectIdOrKey, "projectIdOrKey"))}`,
|
|
303
|
-
query:
|
|
293
|
+
query: compactDefined({ expand: joinOptionalList(stringArray(input.expand)) })
|
|
304
294
|
});
|
|
305
295
|
return { project: normalizeProject(payload) };
|
|
306
296
|
}
|
|
@@ -309,7 +299,7 @@ async function searchIssues(input, ctx) {
|
|
|
309
299
|
const payload = await requestObject(ctx, {
|
|
310
300
|
path: "/search",
|
|
311
301
|
method: "POST",
|
|
312
|
-
body:
|
|
302
|
+
body: compactDefined({
|
|
313
303
|
jql: requireText(input.jql, "jql"),
|
|
314
304
|
maxResults: input.limit ?? DEFAULT_LIMIT,
|
|
315
305
|
// DC 的 POST /rest/api/2/search 绑的是 SearchRequestBean,fields 与 expand 都收**数组**;
|
|
@@ -323,14 +313,14 @@ async function searchIssues(input, ctx) {
|
|
|
323
313
|
return {
|
|
324
314
|
issues: issues.map((issue) => normalizeIssue(issue)),
|
|
325
315
|
pagination: {
|
|
326
|
-
nextCursor: nextNumericCursor(startAt, issues.length,
|
|
316
|
+
nextCursor: nextNumericCursor(startAt, issues.length, integerValue(payload.total))
|
|
327
317
|
}
|
|
328
318
|
};
|
|
329
319
|
}
|
|
330
320
|
async function getIssue(input, ctx) {
|
|
331
321
|
const payload = await requestObject(ctx, {
|
|
332
322
|
path: `/issue/${encodeURIComponent(requireText(input.issueIdOrKey, "issueIdOrKey"))}`,
|
|
333
|
-
query:
|
|
323
|
+
query: compactDefined({
|
|
334
324
|
// 这个端点上 fields 是**逗号串**,不是数组。
|
|
335
325
|
fields: joinOptionalList(mergeUniqueFieldIds(DEFAULT_ISSUE_FIELD_IDS, stringArray(input.includeFields))),
|
|
336
326
|
expand: joinOptionalList(stringArray(input.expand))
|
|
@@ -339,42 +329,42 @@ async function getIssue(input, ctx) {
|
|
|
339
329
|
return { issue: normalizeIssue(payload) };
|
|
340
330
|
}
|
|
341
331
|
function projectReference(input) {
|
|
342
|
-
const projectId =
|
|
332
|
+
const projectId = trimmedText(input.projectId);
|
|
343
333
|
if (projectId !== void 0) return { id: projectId };
|
|
344
|
-
const projectKey =
|
|
334
|
+
const projectKey = trimmedText(input.projectKey);
|
|
345
335
|
if (projectKey !== void 0) return { key: projectKey };
|
|
346
336
|
throw new TBError("invalid_argument", "projectKey or projectId is required");
|
|
347
337
|
}
|
|
348
338
|
function issueTypeReference(input) {
|
|
349
|
-
const issueTypeId =
|
|
339
|
+
const issueTypeId = trimmedText(input.issueTypeId);
|
|
350
340
|
if (issueTypeId !== void 0) return { id: issueTypeId };
|
|
351
|
-
const issueTypeName =
|
|
341
|
+
const issueTypeName = trimmedText(input.issueTypeName);
|
|
352
342
|
if (issueTypeName !== void 0) return { name: issueTypeName };
|
|
353
343
|
throw new TBError("invalid_argument", "issueTypeId or issueTypeName is required");
|
|
354
344
|
}
|
|
355
345
|
async function createIssue(input, ctx) {
|
|
356
|
-
const description =
|
|
357
|
-
const explicitFields =
|
|
346
|
+
const description = asJsonObject(input.description);
|
|
347
|
+
const explicitFields = compactDefined({
|
|
358
348
|
project: projectReference(input),
|
|
359
349
|
issuetype: issueTypeReference(input),
|
|
360
350
|
summary: requireText(input.summary, "summary"),
|
|
361
351
|
// DC 的 description 是纯文本:给了 ADF 就拍平,只给了 descriptionText 就直接用。
|
|
362
|
-
description: description !== void 0 ? adfToPlainText(description) :
|
|
352
|
+
description: description !== void 0 ? adfToPlainText(description) : trimmedText(input.descriptionText),
|
|
363
353
|
// 上游这里用的是 `readStringArray`,没给 labels 时得到的是 `[]` 而非 undefined,于是
|
|
364
354
|
// 创建请求总会带上 `labels: []`。保留这个行为(创建时本就没有标签,发空数组无副作用)。
|
|
365
355
|
labels: stringArray(input.labels),
|
|
366
|
-
assignee:
|
|
367
|
-
priority:
|
|
368
|
-
duedate:
|
|
369
|
-
parent:
|
|
356
|
+
assignee: trimmedText(input.assigneeAccountId) === void 0 ? void 0 : { name: trimmedText(input.assigneeAccountId) },
|
|
357
|
+
priority: trimmedText(input.priorityId) === void 0 ? void 0 : { id: trimmedText(input.priorityId) },
|
|
358
|
+
duedate: trimmedText(input.dueDate),
|
|
359
|
+
parent: trimmedText(input.parentIssueKey) === void 0 ? void 0 : { key: trimmedText(input.parentIssueKey) }
|
|
370
360
|
});
|
|
371
361
|
const created = await requestObject(ctx, {
|
|
372
362
|
path: "/issue",
|
|
373
363
|
method: "POST",
|
|
374
364
|
// extraFields 在前:同名键由显式入参覆盖,免得裸传的 extraFields 悄悄改掉 summary 之类。
|
|
375
|
-
body: { fields: { ...
|
|
365
|
+
body: { fields: { ...asJsonObject(input.extraFields) ?? {}, ...explicitFields } }
|
|
376
366
|
});
|
|
377
|
-
const createdRef =
|
|
367
|
+
const createdRef = trimmedText(created.key) ?? trimmedText(created.id) ?? trimmedText(created.self);
|
|
378
368
|
if (createdRef === void 0) throw upstreamError(502, "missing jira created issue self");
|
|
379
369
|
const issue = await requestObject(ctx, {
|
|
380
370
|
// self 是绝对地址,`buildUrl` 会验它仍落在 base URL 之内。
|
|
@@ -388,7 +378,7 @@ async function listIssueComments(input, ctx) {
|
|
|
388
378
|
const startAt = parseCursor(input.cursor);
|
|
389
379
|
const payload = await requestObject(ctx, {
|
|
390
380
|
path: `/issue/${encodeURIComponent(requireText(input.issueIdOrKey, "issueIdOrKey"))}/comment`,
|
|
391
|
-
query:
|
|
381
|
+
query: compactDefined({
|
|
392
382
|
maxResults: String(limit),
|
|
393
383
|
startAt: String(startAt),
|
|
394
384
|
expand: joinOptionalList(stringArray(input.expand))
|
|
@@ -397,12 +387,12 @@ async function listIssueComments(input, ctx) {
|
|
|
397
387
|
const comments = recordArray(payload.comments).map((comment) => normalizeComment(comment));
|
|
398
388
|
return {
|
|
399
389
|
comments,
|
|
400
|
-
pagination: { nextCursor: nextNumericCursor(startAt, comments.length,
|
|
390
|
+
pagination: { nextCursor: nextNumericCursor(startAt, comments.length, integerValue(payload.total)) }
|
|
401
391
|
};
|
|
402
392
|
}
|
|
403
393
|
async function addComment(input, ctx) {
|
|
404
|
-
const document =
|
|
405
|
-
const body = document !== void 0 ? adfToPlainText(document) :
|
|
394
|
+
const document = asJsonObject(input.body);
|
|
395
|
+
const body = document !== void 0 ? adfToPlainText(document) : trimmedText(input.bodyText);
|
|
406
396
|
if (body === void 0 || body === "") {
|
|
407
397
|
throw new TBError("invalid_argument", "comment body or bodyText is required");
|
|
408
398
|
}
|