@keystrokehq/sentry 0.0.15 → 0.0.16-integration-id-canonicalization.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/README.md +40 -187
- package/dist/credential-sets/index.d.mts +2 -0
- package/dist/credential-sets/index.mjs +4 -0
- package/dist/index.d.mts +4 -1
- package/dist/index.mjs +6 -1
- package/dist/operations/index.d.mts +2 -0
- package/dist/operations/index.mjs +3 -0
- package/dist/{schemas.d.mts → schemas/index.d.mts} +3 -3
- package/dist/schemas/index.mjs +3 -0
- package/dist/{schemas.mjs → sentry-api-DjJ24hwX.mjs} +2 -2
- package/dist/sentry-app.credential-set-4DLRUKF9.d.mts +59 -0
- package/dist/sentry-app.credential-set-Cdj6Qxiz.mjs +23 -0
- package/dist/sentry.credential-set-2b3TPFqv.mjs +696 -0
- package/dist/view-organization-notification-actions.operation-BI2aB_Mj.mjs +4548 -0
- package/dist/view-organization-notification-actions.operation-C7pc8cl_.d.mts +6840 -0
- package/package.json +14 -121
- package/dist/_official/index.d.mts +0 -41
- package/dist/_official/index.mjs +0 -3
- package/dist/_runtime/index.d.mts +0 -2
- package/dist/_runtime/index.mjs +0 -3
- package/dist/alerts.d.mts +0 -462
- package/dist/alerts.mjs +0 -300
- package/dist/client.d.mts +0 -86
- package/dist/client.mjs +0 -233
- package/dist/connection.d.mts +0 -3
- package/dist/connection.mjs +0 -3
- package/dist/dashboards.d.mts +0 -162
- package/dist/dashboards.mjs +0 -122
- package/dist/debug-files.d.mts +0 -102
- package/dist/debug-files.mjs +0 -73
- package/dist/deploys.d.mts +0 -86
- package/dist/deploys.mjs +0 -67
- package/dist/discover.d.mts +0 -194
- package/dist/discover.mjs +0 -138
- package/dist/endpoint-factory-DcT49a8O.mjs +0 -96
- package/dist/environments.d.mts +0 -96
- package/dist/environments.mjs +0 -71
- package/dist/errors-DfEFwcTe.mjs +0 -142
- package/dist/events-api.d.mts +0 -254
- package/dist/events-api.mjs +0 -184
- package/dist/events.d.mts +0 -754
- package/dist/events.mjs +0 -142
- package/dist/feedback.d.mts +0 -82
- package/dist/feedback.mjs +0 -63
- package/dist/integration-D7KCM1-p.mjs +0 -75
- package/dist/integration-veqa_7yB.d.mts +0 -33
- package/dist/issues.d.mts +0 -458
- package/dist/issues.mjs +0 -324
- package/dist/members.d.mts +0 -308
- package/dist/members.mjs +0 -156
- package/dist/messaging.d.mts +0 -1
- package/dist/messaging.mjs +0 -1
- package/dist/monitors.d.mts +0 -458
- package/dist/monitors.mjs +0 -234
- package/dist/notifications.d.mts +0 -180
- package/dist/notifications.mjs +0 -133
- package/dist/organizations.d.mts +0 -442
- package/dist/organizations.mjs +0 -334
- package/dist/pagination-PlgAqbZt.mjs +0 -116
- package/dist/project-keys.d.mts +0 -246
- package/dist/project-keys.mjs +0 -122
- package/dist/projects.d.mts +0 -534
- package/dist/projects.mjs +0 -378
- package/dist/releases.d.mts +0 -780
- package/dist/releases.mjs +0 -479
- package/dist/replays.d.mts +0 -234
- package/dist/replays.mjs +0 -192
- package/dist/scim.d.mts +0 -324
- package/dist/scim.mjs +0 -249
- package/dist/scopes-RRU0vt-a.mjs +0 -36
- package/dist/teams.d.mts +0 -448
- package/dist/teams.mjs +0 -266
- package/dist/triggers.d.mts +0 -41
- package/dist/triggers.mjs +0 -56
- package/dist/user-emails.d.mts +0 -84
- package/dist/user-emails.mjs +0 -60
- package/dist/verification.d.mts +0 -30
- package/dist/verification.mjs +0 -83
- package/dist/webhooks.d.mts +0 -158
- package/dist/webhooks.mjs +0 -108
package/dist/alerts.mjs
DELETED
|
@@ -1,300 +0,0 @@
|
|
|
1
|
-
import { orgProjectScopeInputSchema, orgScopeInputSchema, sentryIdSchema, sentryIssueAlertRuleSchema, sentryJsonObjectSchema, sentryListInputSchema, sentryMetricAlertRuleSchema } from "./schemas.mjs";
|
|
2
|
-
import { t as defineSentryEndpoint } from "./endpoint-factory-DcT49a8O.mjs";
|
|
3
|
-
import { t as SENTRY_SCOPE } from "./scopes-RRU0vt-a.mjs";
|
|
4
|
-
import { z } from "zod";
|
|
5
|
-
|
|
6
|
-
//#region src/alerts.ts
|
|
7
|
-
/**
|
|
8
|
-
* Sentry alert-rule operations (metric + issue alert rules).
|
|
9
|
-
* Maps to PLAN.md §6.11 (11 actions).
|
|
10
|
-
*/
|
|
11
|
-
const ORG = [{
|
|
12
|
-
name: "organization_slug",
|
|
13
|
-
placeholder: "{organization_slug}"
|
|
14
|
-
}];
|
|
15
|
-
const ORG_RULE = [...ORG, {
|
|
16
|
-
name: "alert_rule_id",
|
|
17
|
-
placeholder: "{alert_rule_id}"
|
|
18
|
-
}];
|
|
19
|
-
const ORG_PROJECT = [...ORG, {
|
|
20
|
-
name: "project_slug",
|
|
21
|
-
placeholder: "{project_slug}"
|
|
22
|
-
}];
|
|
23
|
-
const ORG_PROJECT_RULE = [...ORG_PROJECT, {
|
|
24
|
-
name: "rule_id",
|
|
25
|
-
placeholder: "{rule_id}"
|
|
26
|
-
}];
|
|
27
|
-
const createOrganizationAlertRule = defineSentryEndpoint({
|
|
28
|
-
id: "sentry.create-organization-alert-rule",
|
|
29
|
-
name: "Create Metric Alert Rule",
|
|
30
|
-
description: "Create a new organization metric alert rule.",
|
|
31
|
-
method: "POST",
|
|
32
|
-
path: "/api/0/organizations/{organization_slug}/alert-rules/",
|
|
33
|
-
pathParams: ORG,
|
|
34
|
-
input: orgScopeInputSchema.extend({
|
|
35
|
-
name: z.string().min(1),
|
|
36
|
-
dataset: z.string().optional(),
|
|
37
|
-
query: z.string().optional(),
|
|
38
|
-
aggregate: z.string().min(1),
|
|
39
|
-
timeWindow: z.number().int(),
|
|
40
|
-
projects: z.array(z.string()).min(1),
|
|
41
|
-
environment: z.string().optional(),
|
|
42
|
-
comparisonDelta: z.number().int().optional(),
|
|
43
|
-
resolveThreshold: z.number().optional(),
|
|
44
|
-
thresholdType: z.number().int().optional(),
|
|
45
|
-
triggers: z.array(sentryJsonObjectSchema).min(1),
|
|
46
|
-
owner: z.string().nullable().optional()
|
|
47
|
-
}),
|
|
48
|
-
bodyFields: [
|
|
49
|
-
"name",
|
|
50
|
-
"dataset",
|
|
51
|
-
"query",
|
|
52
|
-
"aggregate",
|
|
53
|
-
"timeWindow",
|
|
54
|
-
"projects",
|
|
55
|
-
"environment",
|
|
56
|
-
"comparisonDelta",
|
|
57
|
-
"resolveThreshold",
|
|
58
|
-
"thresholdType",
|
|
59
|
-
"triggers",
|
|
60
|
-
"owner"
|
|
61
|
-
],
|
|
62
|
-
output: sentryMetricAlertRuleSchema,
|
|
63
|
-
needsApproval: true,
|
|
64
|
-
requiredOAuthScopes: [...SENTRY_SCOPE.alertsWrite]
|
|
65
|
-
});
|
|
66
|
-
const fetchOrganizationAlertRules = defineSentryEndpoint({
|
|
67
|
-
id: "sentry.fetch-organization-alert-rules",
|
|
68
|
-
name: "List Metric Alert Rules",
|
|
69
|
-
description: "List organization metric alert rules.",
|
|
70
|
-
method: "GET",
|
|
71
|
-
path: "/api/0/organizations/{organization_slug}/alert-rules/",
|
|
72
|
-
pathParams: ORG,
|
|
73
|
-
input: sentryListInputSchema.merge(orgScopeInputSchema),
|
|
74
|
-
queryFields: [
|
|
75
|
-
"cursor",
|
|
76
|
-
"per_page",
|
|
77
|
-
"query"
|
|
78
|
-
],
|
|
79
|
-
output: z.array(sentryMetricAlertRuleSchema),
|
|
80
|
-
pagination: "cursor",
|
|
81
|
-
requiredOAuthScopes: [...SENTRY_SCOPE.alertsRead]
|
|
82
|
-
});
|
|
83
|
-
const retrieveAlertRuleDetails = defineSentryEndpoint({
|
|
84
|
-
id: "sentry.retrieve-alert-rule-details",
|
|
85
|
-
name: "Retrieve Metric Alert Rule",
|
|
86
|
-
description: "Fetch a metric alert rule by id.",
|
|
87
|
-
method: "GET",
|
|
88
|
-
path: "/api/0/organizations/{organization_slug}/alert-rules/{alert_rule_id}/",
|
|
89
|
-
pathParams: ORG_RULE,
|
|
90
|
-
input: orgScopeInputSchema.extend({ alert_rule_id: sentryIdSchema }),
|
|
91
|
-
output: sentryMetricAlertRuleSchema,
|
|
92
|
-
requiredOAuthScopes: [...SENTRY_SCOPE.alertsRead]
|
|
93
|
-
});
|
|
94
|
-
const updateOrganizationAlertRules = defineSentryEndpoint({
|
|
95
|
-
id: "sentry.update-organization-alert-rules",
|
|
96
|
-
name: "Update Metric Alert Rule",
|
|
97
|
-
description: "Update a metric alert rule in place.",
|
|
98
|
-
method: "PUT",
|
|
99
|
-
path: "/api/0/organizations/{organization_slug}/alert-rules/{alert_rule_id}/",
|
|
100
|
-
pathParams: ORG_RULE,
|
|
101
|
-
input: orgScopeInputSchema.extend({
|
|
102
|
-
alert_rule_id: sentryIdSchema,
|
|
103
|
-
name: z.string().optional(),
|
|
104
|
-
dataset: z.string().optional(),
|
|
105
|
-
query: z.string().optional(),
|
|
106
|
-
aggregate: z.string().optional(),
|
|
107
|
-
timeWindow: z.number().int().optional(),
|
|
108
|
-
projects: z.array(z.string()).optional(),
|
|
109
|
-
environment: z.string().optional(),
|
|
110
|
-
comparisonDelta: z.number().int().optional(),
|
|
111
|
-
resolveThreshold: z.number().optional(),
|
|
112
|
-
thresholdType: z.number().int().optional(),
|
|
113
|
-
triggers: z.array(sentryJsonObjectSchema).optional(),
|
|
114
|
-
owner: z.string().nullable().optional()
|
|
115
|
-
}),
|
|
116
|
-
bodyFields: [
|
|
117
|
-
"name",
|
|
118
|
-
"dataset",
|
|
119
|
-
"query",
|
|
120
|
-
"aggregate",
|
|
121
|
-
"timeWindow",
|
|
122
|
-
"projects",
|
|
123
|
-
"environment",
|
|
124
|
-
"comparisonDelta",
|
|
125
|
-
"resolveThreshold",
|
|
126
|
-
"thresholdType",
|
|
127
|
-
"triggers",
|
|
128
|
-
"owner"
|
|
129
|
-
],
|
|
130
|
-
output: sentryMetricAlertRuleSchema,
|
|
131
|
-
needsApproval: true,
|
|
132
|
-
requiredOAuthScopes: [...SENTRY_SCOPE.alertsWrite]
|
|
133
|
-
});
|
|
134
|
-
const deleteOrganizationAlertRule = defineSentryEndpoint({
|
|
135
|
-
id: "sentry.delete-organization-alert-rule",
|
|
136
|
-
name: "Delete Metric Alert Rule",
|
|
137
|
-
description: "Delete a metric alert rule by id.",
|
|
138
|
-
method: "DELETE",
|
|
139
|
-
path: "/api/0/organizations/{organization_slug}/alert-rules/{alert_rule_id}/",
|
|
140
|
-
pathParams: ORG_RULE,
|
|
141
|
-
input: orgScopeInputSchema.extend({ alert_rule_id: sentryIdSchema }),
|
|
142
|
-
output: z.unknown(),
|
|
143
|
-
needsApproval: true,
|
|
144
|
-
requiredOAuthScopes: [...SENTRY_SCOPE.alertsWrite]
|
|
145
|
-
});
|
|
146
|
-
const getActivationOfAlertRuleForOrganization = defineSentryEndpoint({
|
|
147
|
-
id: "sentry.get-activation-of-alert-rule-for-organization",
|
|
148
|
-
name: "Get Alert Rule Activation",
|
|
149
|
-
description: "Fetch the activation history for a metric alert rule.",
|
|
150
|
-
method: "GET",
|
|
151
|
-
path: "/api/0/organizations/{organization_slug}/alert-rules/{alert_rule_id}/activations/",
|
|
152
|
-
pathParams: ORG_RULE,
|
|
153
|
-
input: orgScopeInputSchema.extend({
|
|
154
|
-
alert_rule_id: sentryIdSchema,
|
|
155
|
-
cursor: z.string().optional(),
|
|
156
|
-
per_page: z.number().int().optional()
|
|
157
|
-
}),
|
|
158
|
-
queryFields: ["cursor", "per_page"],
|
|
159
|
-
output: z.array(sentryJsonObjectSchema),
|
|
160
|
-
requiredOAuthScopes: [...SENTRY_SCOPE.alertsRead]
|
|
161
|
-
});
|
|
162
|
-
const createProjectRuleForAlerts = defineSentryEndpoint({
|
|
163
|
-
id: "sentry.create-project-rule-for-alerts",
|
|
164
|
-
name: "Create Issue Alert Rule",
|
|
165
|
-
description: "Create a project issue alert rule.",
|
|
166
|
-
method: "POST",
|
|
167
|
-
path: "/api/0/projects/{organization_slug}/{project_slug}/rules/",
|
|
168
|
-
pathParams: ORG_PROJECT,
|
|
169
|
-
input: orgProjectScopeInputSchema.extend({
|
|
170
|
-
name: z.string().min(1),
|
|
171
|
-
actionMatch: z.enum([
|
|
172
|
-
"all",
|
|
173
|
-
"any",
|
|
174
|
-
"none"
|
|
175
|
-
]),
|
|
176
|
-
filterMatch: z.enum([
|
|
177
|
-
"all",
|
|
178
|
-
"any",
|
|
179
|
-
"none"
|
|
180
|
-
]).optional(),
|
|
181
|
-
frequency: z.number().int(),
|
|
182
|
-
conditions: z.array(sentryJsonObjectSchema),
|
|
183
|
-
filters: z.array(sentryJsonObjectSchema).optional(),
|
|
184
|
-
actions: z.array(sentryJsonObjectSchema),
|
|
185
|
-
environment: z.string().nullable().optional(),
|
|
186
|
-
owner: z.string().nullable().optional()
|
|
187
|
-
}),
|
|
188
|
-
bodyFields: [
|
|
189
|
-
"name",
|
|
190
|
-
"actionMatch",
|
|
191
|
-
"filterMatch",
|
|
192
|
-
"frequency",
|
|
193
|
-
"conditions",
|
|
194
|
-
"filters",
|
|
195
|
-
"actions",
|
|
196
|
-
"environment",
|
|
197
|
-
"owner"
|
|
198
|
-
],
|
|
199
|
-
output: sentryIssueAlertRuleSchema,
|
|
200
|
-
needsApproval: true,
|
|
201
|
-
requiredOAuthScopes: [...SENTRY_SCOPE.alertsWrite]
|
|
202
|
-
});
|
|
203
|
-
const retrieveProjectRulesByOrgAndProjectId = defineSentryEndpoint({
|
|
204
|
-
id: "sentry.retrieve-project-rules-by-org-and-project-id",
|
|
205
|
-
name: "List Issue Alert Rules",
|
|
206
|
-
description: "List project issue alert rules.",
|
|
207
|
-
method: "GET",
|
|
208
|
-
path: "/api/0/projects/{organization_slug}/{project_slug}/rules/",
|
|
209
|
-
pathParams: ORG_PROJECT,
|
|
210
|
-
input: sentryListInputSchema.merge(orgProjectScopeInputSchema),
|
|
211
|
-
queryFields: [
|
|
212
|
-
"cursor",
|
|
213
|
-
"per_page",
|
|
214
|
-
"query"
|
|
215
|
-
],
|
|
216
|
-
output: z.array(sentryIssueAlertRuleSchema),
|
|
217
|
-
pagination: "cursor",
|
|
218
|
-
requiredOAuthScopes: [...SENTRY_SCOPE.alertsRead]
|
|
219
|
-
});
|
|
220
|
-
const getProjectRuleDetails = defineSentryEndpoint({
|
|
221
|
-
id: "sentry.get-project-rule-details",
|
|
222
|
-
name: "Get Issue Alert Rule",
|
|
223
|
-
description: "Fetch a single issue alert rule by id.",
|
|
224
|
-
method: "GET",
|
|
225
|
-
path: "/api/0/projects/{organization_slug}/{project_slug}/rules/{rule_id}/",
|
|
226
|
-
pathParams: ORG_PROJECT_RULE,
|
|
227
|
-
input: orgProjectScopeInputSchema.extend({ rule_id: sentryIdSchema }),
|
|
228
|
-
output: sentryIssueAlertRuleSchema,
|
|
229
|
-
requiredOAuthScopes: [...SENTRY_SCOPE.alertsRead]
|
|
230
|
-
});
|
|
231
|
-
const updateProjectRuleById = defineSentryEndpoint({
|
|
232
|
-
id: "sentry.update-project-rule-by-id",
|
|
233
|
-
name: "Update Issue Alert Rule",
|
|
234
|
-
description: "Update a project issue alert rule.",
|
|
235
|
-
method: "PUT",
|
|
236
|
-
path: "/api/0/projects/{organization_slug}/{project_slug}/rules/{rule_id}/",
|
|
237
|
-
pathParams: ORG_PROJECT_RULE,
|
|
238
|
-
input: orgProjectScopeInputSchema.extend({
|
|
239
|
-
rule_id: sentryIdSchema,
|
|
240
|
-
name: z.string().optional(),
|
|
241
|
-
actionMatch: z.enum([
|
|
242
|
-
"all",
|
|
243
|
-
"any",
|
|
244
|
-
"none"
|
|
245
|
-
]).optional(),
|
|
246
|
-
filterMatch: z.enum([
|
|
247
|
-
"all",
|
|
248
|
-
"any",
|
|
249
|
-
"none"
|
|
250
|
-
]).optional(),
|
|
251
|
-
frequency: z.number().int().optional(),
|
|
252
|
-
conditions: z.array(sentryJsonObjectSchema).optional(),
|
|
253
|
-
filters: z.array(sentryJsonObjectSchema).optional(),
|
|
254
|
-
actions: z.array(sentryJsonObjectSchema).optional(),
|
|
255
|
-
environment: z.string().nullable().optional(),
|
|
256
|
-
owner: z.string().nullable().optional()
|
|
257
|
-
}),
|
|
258
|
-
bodyFields: [
|
|
259
|
-
"name",
|
|
260
|
-
"actionMatch",
|
|
261
|
-
"filterMatch",
|
|
262
|
-
"frequency",
|
|
263
|
-
"conditions",
|
|
264
|
-
"filters",
|
|
265
|
-
"actions",
|
|
266
|
-
"environment",
|
|
267
|
-
"owner"
|
|
268
|
-
],
|
|
269
|
-
output: sentryIssueAlertRuleSchema,
|
|
270
|
-
needsApproval: true,
|
|
271
|
-
requiredOAuthScopes: [...SENTRY_SCOPE.alertsWrite]
|
|
272
|
-
});
|
|
273
|
-
const deleteProjectRule = defineSentryEndpoint({
|
|
274
|
-
id: "sentry.delete-project-rule",
|
|
275
|
-
name: "Delete Issue Alert Rule",
|
|
276
|
-
description: "Delete a project issue alert rule.",
|
|
277
|
-
method: "DELETE",
|
|
278
|
-
path: "/api/0/projects/{organization_slug}/{project_slug}/rules/{rule_id}/",
|
|
279
|
-
pathParams: ORG_PROJECT_RULE,
|
|
280
|
-
input: orgProjectScopeInputSchema.extend({ rule_id: sentryIdSchema }),
|
|
281
|
-
output: z.unknown(),
|
|
282
|
-
needsApproval: true,
|
|
283
|
-
requiredOAuthScopes: [...SENTRY_SCOPE.alertsWrite]
|
|
284
|
-
});
|
|
285
|
-
const sentryAlertOperations = {
|
|
286
|
-
createOrganizationAlertRule,
|
|
287
|
-
fetchOrganizationAlertRules,
|
|
288
|
-
retrieveAlertRuleDetails,
|
|
289
|
-
updateOrganizationAlertRules,
|
|
290
|
-
deleteOrganizationAlertRule,
|
|
291
|
-
getActivationOfAlertRuleForOrganization,
|
|
292
|
-
createProjectRuleForAlerts,
|
|
293
|
-
retrieveProjectRulesByOrgAndProjectId,
|
|
294
|
-
getProjectRuleDetails,
|
|
295
|
-
updateProjectRuleById,
|
|
296
|
-
deleteProjectRule
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
//#endregion
|
|
300
|
-
export { createOrganizationAlertRule, createProjectRuleForAlerts, deleteOrganizationAlertRule, deleteProjectRule, fetchOrganizationAlertRules, getActivationOfAlertRuleForOrganization, getProjectRuleDetails, retrieveAlertRuleDetails, retrieveProjectRulesByOrgAndProjectId, sentryAlertOperations, updateOrganizationAlertRules, updateProjectRuleById };
|
package/dist/client.d.mts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
//#region src/client.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Typed fetch-based client for the Sentry management API.
|
|
4
|
-
*
|
|
5
|
-
* The factory accepts the public connection credentials
|
|
6
|
-
* (`SentryCredentials`) and returns a thin object with one method per HTTP
|
|
7
|
-
* verb, plus a `paginate` helper that walks Sentry's `Link`-header cursor
|
|
8
|
-
* chain and yields decoded results one batch at a time.
|
|
9
|
-
*
|
|
10
|
-
* Design notes:
|
|
11
|
-
* - All requests go through `request()` so retry, DSN rejection, and error
|
|
12
|
-
* normalization live in one place.
|
|
13
|
-
* - Retry policy: honours `Retry-After` on 429 and does exponential backoff
|
|
14
|
-
* with jitter on 5xx; all other 4xx responses throw immediately.
|
|
15
|
-
* - Base URL: `SENTRY_REGION_URL` (persisted at install time by the OAuth
|
|
16
|
-
* hook) wins; otherwise default `https://sentry.io`. Self-hosted deployments
|
|
17
|
-
* override the region URL.
|
|
18
|
-
* - The SDK path is `/api/0/` on whatever base URL the caller resolved.
|
|
19
|
-
*/
|
|
20
|
-
interface SentryCredentials {
|
|
21
|
-
readonly SENTRY_ACCESS_TOKEN: string;
|
|
22
|
-
readonly SENTRY_REGION_URL?: string;
|
|
23
|
-
readonly SENTRY_ORG_SLUG?: string;
|
|
24
|
-
}
|
|
25
|
-
interface SentryClientOptions {
|
|
26
|
-
/** Override the fetch implementation. Used by tests and by edge runtimes. */
|
|
27
|
-
readonly fetch?: typeof fetch;
|
|
28
|
-
/** Max retry attempts on retryable status codes (default 3). */
|
|
29
|
-
readonly maxRetries?: number;
|
|
30
|
-
/** Base backoff in ms for 5xx retries (default 250). */
|
|
31
|
-
readonly retryBaseDelayMs?: number;
|
|
32
|
-
/**
|
|
33
|
-
* Max delay (ms) between retries. Clamps the exponential backoff so one
|
|
34
|
-
* request does not block the caller for more than `maxDelayMs` per wait.
|
|
35
|
-
* Default 30 seconds.
|
|
36
|
-
*/
|
|
37
|
-
readonly maxDelayMs?: number;
|
|
38
|
-
/** Per-request timeout in ms (default 30_000). */
|
|
39
|
-
readonly timeoutMs?: number;
|
|
40
|
-
/** Hook used to sleep between retries; overridden by tests. */
|
|
41
|
-
readonly sleep?: (ms: number) => Promise<void>;
|
|
42
|
-
}
|
|
43
|
-
interface SentryRequestInit {
|
|
44
|
-
readonly method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
45
|
-
readonly path: string;
|
|
46
|
-
readonly query?: Readonly<Record<string, unknown>>;
|
|
47
|
-
readonly body?: unknown;
|
|
48
|
-
readonly headers?: Readonly<Record<string, string>>;
|
|
49
|
-
/** Tell the client to return the raw `Response` instead of parsing JSON. */
|
|
50
|
-
readonly parseAs?: 'json' | 'text' | 'none';
|
|
51
|
-
/** Override the default content type. */
|
|
52
|
-
readonly contentType?: string;
|
|
53
|
-
/** Pre-encoded body (used for multipart/form uploads). */
|
|
54
|
-
readonly rawBody?: RequestInit['body'];
|
|
55
|
-
}
|
|
56
|
-
interface SentryResponseEnvelope<T = unknown> {
|
|
57
|
-
readonly data: T;
|
|
58
|
-
readonly status: number;
|
|
59
|
-
readonly headers: Headers;
|
|
60
|
-
readonly nextCursor: string | null;
|
|
61
|
-
readonly previousCursor: string | null;
|
|
62
|
-
}
|
|
63
|
-
declare const SENTRY_DEFAULT_BASE_URL = "https://sentry.io";
|
|
64
|
-
interface SentryClient {
|
|
65
|
-
readonly get: <T>(path: string, query?: Readonly<Record<string, unknown>>) => Promise<SentryResponseEnvelope<T>>;
|
|
66
|
-
readonly post: <T>(path: string, body?: unknown, query?: Readonly<Record<string, unknown>>) => Promise<SentryResponseEnvelope<T>>;
|
|
67
|
-
readonly put: <T>(path: string, body?: unknown, query?: Readonly<Record<string, unknown>>) => Promise<SentryResponseEnvelope<T>>;
|
|
68
|
-
readonly patch: <T>(path: string, body?: unknown, query?: Readonly<Record<string, unknown>>) => Promise<SentryResponseEnvelope<T>>;
|
|
69
|
-
readonly delete: <T>(path: string, query?: Readonly<Record<string, unknown>>) => Promise<SentryResponseEnvelope<T>>;
|
|
70
|
-
/** Iterates every page yielded by a `GET` list endpoint. */
|
|
71
|
-
readonly paginate: <T>(path: string, query?: Readonly<Record<string, unknown>>) => AsyncGenerator<SentryResponseEnvelope<T>, void, void>;
|
|
72
|
-
/**
|
|
73
|
-
* Concatenates all pages of a list endpoint into a single array. Use this
|
|
74
|
-
* for endpoints where the full resource fits in memory (most Sentry list
|
|
75
|
-
* endpoints have small natural bounds: teams, projects, members, alert
|
|
76
|
-
* rules).
|
|
77
|
-
*/
|
|
78
|
-
readonly listAll: <TItem>(path: string, query?: Readonly<Record<string, unknown>>) => Promise<readonly TItem[]>;
|
|
79
|
-
/** Escape hatch for multipart uploads and callers who need the full init shape. */
|
|
80
|
-
readonly request: <T>(init: SentryRequestInit) => Promise<SentryResponseEnvelope<T>>;
|
|
81
|
-
/** Resolves the base URL that credentials would use. Exposed for tests. */
|
|
82
|
-
readonly resolveBaseUrl: () => string;
|
|
83
|
-
}
|
|
84
|
-
declare function createSentryClient(credentials: SentryCredentials, options?: SentryClientOptions): SentryClient;
|
|
85
|
-
//#endregion
|
|
86
|
-
export { SENTRY_DEFAULT_BASE_URL, SentryClient, SentryClientOptions, SentryCredentials, SentryRequestInit, SentryResponseEnvelope, createSentryClient };
|
package/dist/client.mjs
DELETED
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
import { r as classifyHttpResponse, t as SentryApiError } from "./errors-DfEFwcTe.mjs";
|
|
2
|
-
import { n as parseSentryLinkHeader, t as looksLikeSentryDsn } from "./pagination-PlgAqbZt.mjs";
|
|
3
|
-
|
|
4
|
-
//#region src/client.ts
|
|
5
|
-
/**
|
|
6
|
-
* Typed fetch-based client for the Sentry management API.
|
|
7
|
-
*
|
|
8
|
-
* The factory accepts the public connection credentials
|
|
9
|
-
* (`SentryCredentials`) and returns a thin object with one method per HTTP
|
|
10
|
-
* verb, plus a `paginate` helper that walks Sentry's `Link`-header cursor
|
|
11
|
-
* chain and yields decoded results one batch at a time.
|
|
12
|
-
*
|
|
13
|
-
* Design notes:
|
|
14
|
-
* - All requests go through `request()` so retry, DSN rejection, and error
|
|
15
|
-
* normalization live in one place.
|
|
16
|
-
* - Retry policy: honours `Retry-After` on 429 and does exponential backoff
|
|
17
|
-
* with jitter on 5xx; all other 4xx responses throw immediately.
|
|
18
|
-
* - Base URL: `SENTRY_REGION_URL` (persisted at install time by the OAuth
|
|
19
|
-
* hook) wins; otherwise default `https://sentry.io`. Self-hosted deployments
|
|
20
|
-
* override the region URL.
|
|
21
|
-
* - The SDK path is `/api/0/` on whatever base URL the caller resolved.
|
|
22
|
-
*/
|
|
23
|
-
const SENTRY_DEFAULT_BASE_URL = "https://sentry.io";
|
|
24
|
-
const DEFAULT_MAX_RETRIES = 3;
|
|
25
|
-
const DEFAULT_BASE_DELAY_MS = 250;
|
|
26
|
-
const DEFAULT_MAX_DELAY_MS = 3e4;
|
|
27
|
-
const DEFAULT_TIMEOUT_MS = 3e4;
|
|
28
|
-
function createSentryClient(credentials, options = {}) {
|
|
29
|
-
const token = credentials.SENTRY_ACCESS_TOKEN;
|
|
30
|
-
if (looksLikeSentryDsn(token)) throw new SentryApiError({
|
|
31
|
-
kind: "dsn_detected",
|
|
32
|
-
message: "A Sentry DSN was passed in place of a management-API bearer token. DSNs can only be used to send events; the management API requires an OAuth access token, auth token, or internal integration token.",
|
|
33
|
-
status: null,
|
|
34
|
-
providerCode: null,
|
|
35
|
-
requestId: null,
|
|
36
|
-
retryable: false,
|
|
37
|
-
retryAfterSec: null
|
|
38
|
-
});
|
|
39
|
-
const baseUrl = (credentials.SENTRY_REGION_URL ?? SENTRY_DEFAULT_BASE_URL).replace(/\/$/u, "");
|
|
40
|
-
const fetchImpl = options.fetch ?? fetch;
|
|
41
|
-
const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
42
|
-
const retryBaseDelayMs = options.retryBaseDelayMs ?? DEFAULT_BASE_DELAY_MS;
|
|
43
|
-
const maxDelayMs = options.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;
|
|
44
|
-
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
45
|
-
const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
46
|
-
async function request(init) {
|
|
47
|
-
const url = buildUrl(baseUrl, init.path, init.query);
|
|
48
|
-
const headers = {
|
|
49
|
-
Authorization: `Bearer ${token}`,
|
|
50
|
-
Accept: "application/json",
|
|
51
|
-
...init.headers ?? {}
|
|
52
|
-
};
|
|
53
|
-
let body;
|
|
54
|
-
if (init.rawBody !== void 0) body = init.rawBody;
|
|
55
|
-
else if (init.body !== void 0 && init.method !== "GET" && init.method !== "DELETE") if (init.contentType === "application/x-www-form-urlencoded") {
|
|
56
|
-
headers["Content-Type"] = "application/x-www-form-urlencoded";
|
|
57
|
-
body = new URLSearchParams(init.body).toString();
|
|
58
|
-
} else {
|
|
59
|
-
headers["Content-Type"] = init.contentType ?? "application/json";
|
|
60
|
-
body = typeof init.body === "string" || init.body instanceof ArrayBuffer ? init.body : JSON.stringify(init.body);
|
|
61
|
-
}
|
|
62
|
-
let attempt = 0;
|
|
63
|
-
while (true) {
|
|
64
|
-
attempt += 1;
|
|
65
|
-
const controller = new AbortController();
|
|
66
|
-
const timeoutHandle = setTimeout(() => controller.abort(), timeoutMs);
|
|
67
|
-
let response;
|
|
68
|
-
try {
|
|
69
|
-
response = await fetchImpl(url, {
|
|
70
|
-
method: init.method,
|
|
71
|
-
headers,
|
|
72
|
-
body,
|
|
73
|
-
signal: controller.signal
|
|
74
|
-
});
|
|
75
|
-
} catch (cause) {
|
|
76
|
-
clearTimeout(timeoutHandle);
|
|
77
|
-
if (attempt > maxRetries) throw new SentryApiError({
|
|
78
|
-
kind: "network",
|
|
79
|
-
message: `Sentry API network error: ${extractCauseMessage(cause)}`,
|
|
80
|
-
status: null,
|
|
81
|
-
providerCode: null,
|
|
82
|
-
requestId: null,
|
|
83
|
-
retryable: true,
|
|
84
|
-
retryAfterSec: null,
|
|
85
|
-
cause
|
|
86
|
-
});
|
|
87
|
-
await sleep(computeBackoffDelay(attempt, retryBaseDelayMs, maxDelayMs));
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
clearTimeout(timeoutHandle);
|
|
91
|
-
if (response.ok) {
|
|
92
|
-
const data = await parseResponseBody(response, init.parseAs ?? "json");
|
|
93
|
-
const links = parseSentryLinkHeader(response.headers.get("link"));
|
|
94
|
-
return {
|
|
95
|
-
data,
|
|
96
|
-
status: response.status,
|
|
97
|
-
headers: response.headers,
|
|
98
|
-
nextCursor: links.next?.results ? links.next.cursor : null,
|
|
99
|
-
previousCursor: links.previous?.results ? links.previous.cursor : null
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
const errorBody = await parseErrorBody(response);
|
|
103
|
-
const error = classifyHttpResponse(response, errorBody);
|
|
104
|
-
if (!error.retryable || attempt > maxRetries) throw error;
|
|
105
|
-
await sleep(error.retryAfterSec != null ? Math.min(error.retryAfterSec * 1e3, maxDelayMs) : computeBackoffDelay(attempt, retryBaseDelayMs, maxDelayMs));
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
async function get(path, query) {
|
|
109
|
-
return request({
|
|
110
|
-
method: "GET",
|
|
111
|
-
path,
|
|
112
|
-
query
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
async function post(path, bodyValue, query) {
|
|
116
|
-
return request({
|
|
117
|
-
method: "POST",
|
|
118
|
-
path,
|
|
119
|
-
body: bodyValue,
|
|
120
|
-
query
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
async function put(path, bodyValue, query) {
|
|
124
|
-
return request({
|
|
125
|
-
method: "PUT",
|
|
126
|
-
path,
|
|
127
|
-
body: bodyValue,
|
|
128
|
-
query
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
async function patch(path, bodyValue, query) {
|
|
132
|
-
return request({
|
|
133
|
-
method: "PATCH",
|
|
134
|
-
path,
|
|
135
|
-
body: bodyValue,
|
|
136
|
-
query
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
async function del(path, query) {
|
|
140
|
-
return request({
|
|
141
|
-
method: "DELETE",
|
|
142
|
-
path,
|
|
143
|
-
query,
|
|
144
|
-
parseAs: "none"
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
async function* paginate(path, query = {}) {
|
|
148
|
-
let cursor = null;
|
|
149
|
-
do {
|
|
150
|
-
const merged = { ...query };
|
|
151
|
-
if (cursor != null) merged.cursor = cursor;
|
|
152
|
-
const page = await get(path, merged);
|
|
153
|
-
yield page;
|
|
154
|
-
cursor = page.nextCursor;
|
|
155
|
-
} while (cursor !== null);
|
|
156
|
-
}
|
|
157
|
-
async function listAll(path, query) {
|
|
158
|
-
const acc = [];
|
|
159
|
-
for await (const page of paginate(path, query)) acc.push(...page.data);
|
|
160
|
-
return acc;
|
|
161
|
-
}
|
|
162
|
-
return {
|
|
163
|
-
get,
|
|
164
|
-
post,
|
|
165
|
-
put,
|
|
166
|
-
patch,
|
|
167
|
-
delete: del,
|
|
168
|
-
paginate,
|
|
169
|
-
listAll,
|
|
170
|
-
request,
|
|
171
|
-
resolveBaseUrl: () => baseUrl
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
function buildUrl(baseUrl, path, query) {
|
|
175
|
-
const base = `${baseUrl}${path.startsWith("/") ? path : `/${path}`}`;
|
|
176
|
-
if (!query) return base;
|
|
177
|
-
const params = new URLSearchParams();
|
|
178
|
-
for (const [key, value] of Object.entries(query)) {
|
|
179
|
-
if (value == null) continue;
|
|
180
|
-
if (Array.isArray(value)) for (const v of value) {
|
|
181
|
-
if (v == null) continue;
|
|
182
|
-
params.append(key, String(v));
|
|
183
|
-
}
|
|
184
|
-
else if (typeof value === "boolean") params.append(key, value ? "true" : "false");
|
|
185
|
-
else params.append(key, String(value));
|
|
186
|
-
}
|
|
187
|
-
const qs = params.toString();
|
|
188
|
-
return qs ? `${base}?${qs}` : base;
|
|
189
|
-
}
|
|
190
|
-
async function parseResponseBody(response, mode) {
|
|
191
|
-
if (mode === "none") return void 0;
|
|
192
|
-
if (mode === "text") return await response.text();
|
|
193
|
-
if (response.status === 204) return void 0;
|
|
194
|
-
const raw = await response.text();
|
|
195
|
-
if (raw.length === 0) return void 0;
|
|
196
|
-
try {
|
|
197
|
-
return JSON.parse(raw);
|
|
198
|
-
} catch (cause) {
|
|
199
|
-
throw new SentryApiError({
|
|
200
|
-
kind: "http",
|
|
201
|
-
message: `Sentry API returned non-JSON body (status ${response.status})`,
|
|
202
|
-
status: response.status,
|
|
203
|
-
providerCode: null,
|
|
204
|
-
requestId: response.headers.get("x-request-id"),
|
|
205
|
-
retryable: false,
|
|
206
|
-
retryAfterSec: null,
|
|
207
|
-
responseBody: raw,
|
|
208
|
-
cause
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
async function parseErrorBody(response) {
|
|
213
|
-
const raw = await response.text();
|
|
214
|
-
if (raw.length === 0) return null;
|
|
215
|
-
try {
|
|
216
|
-
return JSON.parse(raw);
|
|
217
|
-
} catch {
|
|
218
|
-
return raw;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
function computeBackoffDelay(attempt, baseMs, maxMs) {
|
|
222
|
-
const exponential = baseMs * 2 ** Math.max(0, attempt - 1);
|
|
223
|
-
const jitter = Math.random() * baseMs;
|
|
224
|
-
return Math.min(exponential + jitter, maxMs);
|
|
225
|
-
}
|
|
226
|
-
function extractCauseMessage(cause) {
|
|
227
|
-
if (cause instanceof Error) return cause.message;
|
|
228
|
-
if (typeof cause === "string") return cause;
|
|
229
|
-
return "unknown network error";
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
//#endregion
|
|
233
|
-
export { SENTRY_DEFAULT_BASE_URL, createSentryClient };
|
package/dist/connection.d.mts
DELETED
package/dist/connection.mjs
DELETED