patchwork-os 0.2.0-alpha.26 → 0.2.0-alpha.27
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/deploy/bootstrap-vps.sh +1 -1
- package/deploy/deploy-dashboard.sh +164 -0
- package/deploy/deploy-landing.sh +79 -0
- package/dist/ccPermissions.js +6 -4
- package/dist/ccPermissions.js.map +1 -1
- package/dist/commands/recipe.js +1 -1
- package/dist/commands/recipe.js.map +1 -1
- package/dist/commands/recipeInstall.d.ts +72 -0
- package/dist/commands/recipeInstall.js +339 -0
- package/dist/commands/recipeInstall.js.map +1 -0
- package/dist/connectors/datadog.d.ts +116 -0
- package/dist/connectors/datadog.js +385 -0
- package/dist/connectors/datadog.js.map +1 -0
- package/dist/connectors/hubspot.d.ts +112 -0
- package/dist/connectors/hubspot.js +408 -0
- package/dist/connectors/hubspot.js.map +1 -0
- package/dist/connectors/intercom.d.ts +102 -0
- package/dist/connectors/intercom.js +402 -0
- package/dist/connectors/intercom.js.map +1 -0
- package/dist/connectors/stripe.d.ts +116 -0
- package/dist/connectors/stripe.js +379 -0
- package/dist/connectors/stripe.js.map +1 -0
- package/dist/index.js +33 -26
- package/dist/index.js.map +1 -1
- package/dist/recipes/manifest.d.ts +47 -0
- package/dist/recipes/manifest.js +141 -0
- package/dist/recipes/manifest.js.map +1 -0
- package/dist/recipes/schemaGenerator.js +3 -3
- package/dist/recipes/schemaGenerator.js.map +1 -1
- package/dist/recipes/tools/datadog.d.ts +6 -0
- package/dist/recipes/tools/datadog.js +239 -0
- package/dist/recipes/tools/datadog.js.map +1 -0
- package/dist/recipes/tools/hubspot.d.ts +6 -0
- package/dist/recipes/tools/hubspot.js +232 -0
- package/dist/recipes/tools/hubspot.js.map +1 -0
- package/dist/recipes/tools/index.d.ts +4 -0
- package/dist/recipes/tools/index.js +4 -0
- package/dist/recipes/tools/index.js.map +1 -1
- package/dist/recipes/tools/intercom.d.ts +6 -0
- package/dist/recipes/tools/intercom.js +226 -0
- package/dist/recipes/tools/intercom.js.map +1 -0
- package/dist/recipes/tools/stripe.d.ts +6 -0
- package/dist/recipes/tools/stripe.js +265 -0
- package/dist/recipes/tools/stripe.js.map +1 -0
- package/dist/recipes/yamlRunner.js +28 -0
- package/dist/recipes/yamlRunner.js.map +1 -1
- package/dist/schemas/dry-run-plan.v1.json +1 -1
- package/dist/schemas/recipe.v1.json +1 -1
- package/dist/server.js +155 -1
- package/dist/server.js.map +1 -1
- package/dist/tools/searchTools.js +1 -1
- package/dist/tools/searchTools.js.map +1 -1
- package/dist/tools/testTraceToSource.js +2 -2
- package/dist/tools/testTraceToSource.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* patchwork recipe install — download and install a recipe package.
|
|
3
|
+
* patchwork recipe list — list installed recipe packages.
|
|
4
|
+
*
|
|
5
|
+
* Supports:
|
|
6
|
+
* github:owner/repo
|
|
7
|
+
* github:owner/repo/subdir
|
|
8
|
+
* https://github.com/owner/repo
|
|
9
|
+
* ./local/path
|
|
10
|
+
*/
|
|
11
|
+
import { cpSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, } from "node:fs";
|
|
12
|
+
import https from "node:https";
|
|
13
|
+
import os from "node:os";
|
|
14
|
+
import path from "node:path";
|
|
15
|
+
import { getManifestRecipeFiles, loadManifestFromDir, parseManifest, } from "../recipes/manifest.js";
|
|
16
|
+
export const INSTALL_RECIPES_DIR = path.join(os.homedir(), ".patchwork", "recipes");
|
|
17
|
+
/**
|
|
18
|
+
* Parse a user-supplied source string into a typed InstallSource.
|
|
19
|
+
*
|
|
20
|
+
* Supported forms:
|
|
21
|
+
* github:owner/repo
|
|
22
|
+
* github:owner/repo/subdir
|
|
23
|
+
* https://github.com/owner/repo
|
|
24
|
+
* https://github.com/owner/repo/tree/branch/subdir
|
|
25
|
+
* ./relative/path
|
|
26
|
+
* /absolute/path
|
|
27
|
+
*/
|
|
28
|
+
export function parseInstallSource(source) {
|
|
29
|
+
// Local path: starts with . or /
|
|
30
|
+
if (source.startsWith("./") ||
|
|
31
|
+
source.startsWith("/") ||
|
|
32
|
+
source.startsWith("../")) {
|
|
33
|
+
return { type: "local", path: source };
|
|
34
|
+
}
|
|
35
|
+
// github: prefix
|
|
36
|
+
if (source.startsWith("github:")) {
|
|
37
|
+
return parseGithubShorthand(source.slice("github:".length));
|
|
38
|
+
}
|
|
39
|
+
// Full GitHub URL
|
|
40
|
+
const githubUrlMatch = source.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)(?:\/tree\/[^/]+\/(.+))?(?:\.git)?$/);
|
|
41
|
+
if (githubUrlMatch) {
|
|
42
|
+
const [, owner, repo, subdir] = githubUrlMatch;
|
|
43
|
+
if (!owner || !repo) {
|
|
44
|
+
throw new Error(`Invalid GitHub URL: ${source}`);
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
type: "github",
|
|
48
|
+
owner,
|
|
49
|
+
repo: repo.replace(/\.git$/, ""),
|
|
50
|
+
...(subdir ? { subdir } : {}),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
throw new Error(`Unrecognized install source: "${source}"\n` +
|
|
54
|
+
`Supported: github:owner/repo, github:owner/repo/subdir, https://github.com/owner/repo, ./local/path`);
|
|
55
|
+
}
|
|
56
|
+
function parseGithubShorthand(shorthand) {
|
|
57
|
+
// owner/repo or owner/repo/subdir (may have multiple path segments)
|
|
58
|
+
const parts = shorthand.split("/");
|
|
59
|
+
if (parts.length < 2) {
|
|
60
|
+
throw new Error(`Invalid github shorthand "${shorthand}": expected "owner/repo" or "owner/repo/subdir"`);
|
|
61
|
+
}
|
|
62
|
+
const [owner, repo, ...subdirParts] = parts;
|
|
63
|
+
if (!owner || !repo) {
|
|
64
|
+
throw new Error(`Invalid github shorthand: "${shorthand}"`);
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
type: "github",
|
|
68
|
+
owner,
|
|
69
|
+
repo,
|
|
70
|
+
...(subdirParts.length > 0 ? { subdir: subdirParts.join("/") } : {}),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// ============================================================================
|
|
74
|
+
// Install name determination
|
|
75
|
+
// ============================================================================
|
|
76
|
+
/**
|
|
77
|
+
* Determine the install directory name from the manifest or source.
|
|
78
|
+
* - Manifest present: strip leading @ and replace / with -- for filesystem safety.
|
|
79
|
+
* - GitHub source (no manifest): "owner/repo" or "owner/repo/subdir".
|
|
80
|
+
* - Local source (no manifest): basename of the directory.
|
|
81
|
+
*/
|
|
82
|
+
export function determineInstallName(manifest, source) {
|
|
83
|
+
if (manifest) {
|
|
84
|
+
// Strip leading @ and replace "/" with "--" so it's a valid directory name
|
|
85
|
+
return manifest.name.replace(/^@/, "").replace(/\//g, "--");
|
|
86
|
+
}
|
|
87
|
+
if (source.type === "github") {
|
|
88
|
+
const base = `${source.owner}/${source.repo}`;
|
|
89
|
+
return source.subdir ? `${base}/${source.subdir}` : base;
|
|
90
|
+
}
|
|
91
|
+
return path.basename(path.resolve(source.path));
|
|
92
|
+
}
|
|
93
|
+
// ============================================================================
|
|
94
|
+
// GitHub file fetching via API
|
|
95
|
+
// ============================================================================
|
|
96
|
+
async function httpsGet(url) {
|
|
97
|
+
return new Promise((resolve, reject) => {
|
|
98
|
+
const req = https.get(url, {
|
|
99
|
+
headers: {
|
|
100
|
+
"User-Agent": "patchwork-recipe-installer/1.0",
|
|
101
|
+
Accept: "application/vnd.github.v3+json",
|
|
102
|
+
},
|
|
103
|
+
}, (res) => {
|
|
104
|
+
// Follow redirects
|
|
105
|
+
if (res.statusCode &&
|
|
106
|
+
res.statusCode >= 300 &&
|
|
107
|
+
res.statusCode < 400 &&
|
|
108
|
+
res.headers.location) {
|
|
109
|
+
httpsGet(res.headers.location).then(resolve).catch(reject);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (res.statusCode && res.statusCode >= 400) {
|
|
113
|
+
reject(new Error(`HTTP ${res.statusCode} fetching ${url}`));
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const chunks = [];
|
|
117
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
118
|
+
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
119
|
+
res.on("error", reject);
|
|
120
|
+
});
|
|
121
|
+
req.on("error", reject);
|
|
122
|
+
req.end();
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async function listGitHubContents(owner, repo, dirPath, ref) {
|
|
126
|
+
const url = `https://api.github.com/repos/${owner}/${repo}/contents/${dirPath}?ref=${ref}`;
|
|
127
|
+
const body = await httpsGet(url);
|
|
128
|
+
const parsed = JSON.parse(body.toString("utf-8"));
|
|
129
|
+
if (!Array.isArray(parsed)) {
|
|
130
|
+
throw new Error(`Expected array from GitHub contents API, got: ${typeof parsed}`);
|
|
131
|
+
}
|
|
132
|
+
return parsed;
|
|
133
|
+
}
|
|
134
|
+
async function fetchGitHubFile(downloadUrl) {
|
|
135
|
+
return httpsGet(downloadUrl);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Download all .yaml/.yml files (and recipe.json if present) from a GitHub
|
|
139
|
+
* directory into `destDir`. Returns list of filenames written.
|
|
140
|
+
*/
|
|
141
|
+
async function downloadGitHubDir(owner, repo, dirPath, ref, destDir) {
|
|
142
|
+
const items = await listGitHubContents(owner, repo, dirPath, ref);
|
|
143
|
+
const written = [];
|
|
144
|
+
for (const item of items) {
|
|
145
|
+
if (item.type !== "file")
|
|
146
|
+
continue;
|
|
147
|
+
if (item.name !== "recipe.json" && !/\.ya?ml$/i.test(item.name)) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (!item.download_url)
|
|
151
|
+
continue;
|
|
152
|
+
const content = await fetchGitHubFile(item.download_url);
|
|
153
|
+
const destPath = path.join(destDir, item.name);
|
|
154
|
+
writeFileSync(destPath, content);
|
|
155
|
+
written.push(item.name);
|
|
156
|
+
}
|
|
157
|
+
return written;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Install a recipe package from a source into INSTALL_RECIPES_DIR.
|
|
161
|
+
* Returns metadata about what was installed.
|
|
162
|
+
*/
|
|
163
|
+
export async function runRecipeInstall(rawSource, options = {}) {
|
|
164
|
+
const source = parseInstallSource(rawSource);
|
|
165
|
+
const recipesDir = options.recipesDir ?? INSTALL_RECIPES_DIR;
|
|
166
|
+
// Stage into temp dir first
|
|
167
|
+
const tmpDir = mkdtempSync(path.join(os.tmpdir(), "patchwork-recipe-"));
|
|
168
|
+
try {
|
|
169
|
+
if (source.type === "local") {
|
|
170
|
+
await stageLocalSource(source, tmpDir);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
await stageGitHubSource(source, tmpDir);
|
|
174
|
+
}
|
|
175
|
+
// Read manifest if present
|
|
176
|
+
let manifest = null;
|
|
177
|
+
const manifestPath = path.join(tmpDir, "recipe.json");
|
|
178
|
+
if (existsSync(manifestPath)) {
|
|
179
|
+
manifest = parseManifest(readFileSync(manifestPath, "utf-8"));
|
|
180
|
+
}
|
|
181
|
+
// Determine which files to copy
|
|
182
|
+
let filesToCopy;
|
|
183
|
+
if (manifest) {
|
|
184
|
+
const declared = getManifestRecipeFiles(manifest);
|
|
185
|
+
// Include recipe.json + declared recipe files (that exist in tmpDir)
|
|
186
|
+
filesToCopy = ["recipe.json", ...declared].filter((f) => existsSync(path.join(tmpDir, f)));
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
// No manifest: take all .yaml/.yml files
|
|
190
|
+
filesToCopy = readdirSync(tmpDir).filter((f) => /\.ya?ml$/i.test(f));
|
|
191
|
+
}
|
|
192
|
+
if (filesToCopy.length === 0) {
|
|
193
|
+
throw new Error(`No recipe files found in source "${rawSource}". ` +
|
|
194
|
+
`Expected .yaml/.yml files or a recipe.json manifest.`);
|
|
195
|
+
}
|
|
196
|
+
const installName = determineInstallName(manifest, source);
|
|
197
|
+
const installDir = path.join(recipesDir, installName);
|
|
198
|
+
if (!existsSync(installDir)) {
|
|
199
|
+
mkdirSync(installDir, { recursive: true });
|
|
200
|
+
}
|
|
201
|
+
// Copy files
|
|
202
|
+
for (const file of filesToCopy) {
|
|
203
|
+
const src = path.join(tmpDir, file);
|
|
204
|
+
const dest = path.join(installDir, file);
|
|
205
|
+
// Ensure subdirs exist (recipe.json could declare children in subdirs)
|
|
206
|
+
const destParent = path.dirname(dest);
|
|
207
|
+
if (!existsSync(destParent)) {
|
|
208
|
+
mkdirSync(destParent, { recursive: true });
|
|
209
|
+
}
|
|
210
|
+
cpSync(src, dest);
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
name: installName,
|
|
214
|
+
version: manifest?.version,
|
|
215
|
+
installDir,
|
|
216
|
+
filesInstalled: filesToCopy,
|
|
217
|
+
manifest,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
try {
|
|
222
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
// best-effort cleanup
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async function stageLocalSource(source, tmpDir) {
|
|
230
|
+
const resolvedPath = path.resolve(source.path);
|
|
231
|
+
if (!existsSync(resolvedPath)) {
|
|
232
|
+
throw new Error(`Local path does not exist: ${resolvedPath}`);
|
|
233
|
+
}
|
|
234
|
+
if (!statSync(resolvedPath).isDirectory()) {
|
|
235
|
+
throw new Error(`Local path is not a directory: ${resolvedPath}`);
|
|
236
|
+
}
|
|
237
|
+
cpSync(resolvedPath, tmpDir, { recursive: true });
|
|
238
|
+
}
|
|
239
|
+
async function stageGitHubSource(source, tmpDir) {
|
|
240
|
+
const ref = source.ref ?? "main";
|
|
241
|
+
const dirPath = source.subdir ?? "";
|
|
242
|
+
try {
|
|
243
|
+
await downloadGitHubDir(source.owner, source.repo, dirPath, ref, tmpDir);
|
|
244
|
+
}
|
|
245
|
+
catch (err) {
|
|
246
|
+
// If main branch fails, try master
|
|
247
|
+
if (ref === "main") {
|
|
248
|
+
try {
|
|
249
|
+
await downloadGitHubDir(source.owner, source.repo, dirPath, "master", tmpDir);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
// fall through to original error
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
throw err;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
export function listInstalledRecipes(options = {}) {
|
|
260
|
+
const recipesDir = options.recipesDir ?? INSTALL_RECIPES_DIR;
|
|
261
|
+
if (!existsSync(recipesDir)) {
|
|
262
|
+
return [];
|
|
263
|
+
}
|
|
264
|
+
const entries = [];
|
|
265
|
+
function scanDir(dir, namePrefix) {
|
|
266
|
+
const items = readdirSync(dir);
|
|
267
|
+
for (const item of items) {
|
|
268
|
+
const itemPath = path.join(dir, item);
|
|
269
|
+
if (!statSync(itemPath).isDirectory())
|
|
270
|
+
continue;
|
|
271
|
+
const entryName = namePrefix ? `${namePrefix}/${item}` : item;
|
|
272
|
+
const manifest = loadManifestFromDir(itemPath);
|
|
273
|
+
if (manifest) {
|
|
274
|
+
entries.push({
|
|
275
|
+
name: entryName,
|
|
276
|
+
version: manifest.version,
|
|
277
|
+
description: manifest.description,
|
|
278
|
+
connectors: manifest.connectors,
|
|
279
|
+
mainRecipe: manifest.recipes.main,
|
|
280
|
+
hasManifest: true,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
const yamlFiles = readdirSync(itemPath).filter((f) => /\.ya?ml$/i.test(f));
|
|
285
|
+
if (yamlFiles.length > 0) {
|
|
286
|
+
entries.push({
|
|
287
|
+
name: entryName,
|
|
288
|
+
yamlFiles,
|
|
289
|
+
hasManifest: false,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
// Recurse one level for namespaced dirs like "owner/repo"
|
|
294
|
+
if (!namePrefix) {
|
|
295
|
+
scanDir(itemPath, item);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
scanDir(recipesDir, "");
|
|
302
|
+
return entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
303
|
+
}
|
|
304
|
+
// ============================================================================
|
|
305
|
+
// CLI output helpers
|
|
306
|
+
// ============================================================================
|
|
307
|
+
export function printInstallResult(result) {
|
|
308
|
+
const versionStr = result.version ? `@${result.version}` : "";
|
|
309
|
+
console.log(`✓ Installed ${result.name}${versionStr} to ${result.installDir}`);
|
|
310
|
+
if (result.manifest?.connectors && result.manifest.connectors.length > 0) {
|
|
311
|
+
console.log(` Requires connectors: ${result.manifest.connectors.join(", ")}`);
|
|
312
|
+
}
|
|
313
|
+
const mainRecipe = result.manifest?.recipes.main ?? result.filesInstalled[0];
|
|
314
|
+
if (mainRecipe) {
|
|
315
|
+
console.log(` Run with: patchwork recipe run ${path.join(result.installDir, mainRecipe)}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
export function printInstalledList(entries) {
|
|
319
|
+
if (entries.length === 0) {
|
|
320
|
+
console.log("No recipes installed. Use `patchwork recipe install <source>` to install.");
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
const maxName = Math.max(...entries.map((e) => e.name.length), 4);
|
|
324
|
+
const maxVersion = Math.max(...entries.map((e) => (e.version ?? "—").length), 7);
|
|
325
|
+
const header = `${"Name".padEnd(maxName)} ${"Version".padEnd(maxVersion)} Description / Files`;
|
|
326
|
+
console.log(header);
|
|
327
|
+
console.log("-".repeat(Math.min(header.length, 100)));
|
|
328
|
+
for (const entry of entries) {
|
|
329
|
+
const version = (entry.version ?? "—").padEnd(maxVersion);
|
|
330
|
+
const detail = entry.hasManifest
|
|
331
|
+
? (entry.description ?? "")
|
|
332
|
+
: `[${(entry.yamlFiles ?? []).join(", ")}]`;
|
|
333
|
+
console.log(`${entry.name.padEnd(maxName)} ${version} ${detail}`);
|
|
334
|
+
if (entry.connectors && entry.connectors.length > 0) {
|
|
335
|
+
console.log(`${"".padEnd(maxName)} ${"".padEnd(maxVersion)} connectors: ${entry.connectors.join(", ")}`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=recipeInstall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recipeInstall.js","sourceRoot":"","sources":["../../src/commands/recipeInstall.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Datadog connector — query metrics, monitors, alerts, and incidents.
|
|
3
|
+
*
|
|
4
|
+
* Auth: API key + Application key.
|
|
5
|
+
* - Env vars: DATADOG_API_KEY, DATADOG_APP_KEY, DATADOG_SITE (optional)
|
|
6
|
+
* - Stored: getSecretJsonSync("datadog") → DatadogTokens
|
|
7
|
+
* - Headers: DD-API-KEY + DD-APPLICATION-KEY
|
|
8
|
+
*
|
|
9
|
+
* Tools: queryMetrics, listMonitors, getMonitor, listActiveAlerts, muteMonitor, listIncidents
|
|
10
|
+
*
|
|
11
|
+
* Extends BaseConnector for unified auth, retry, rate-limit, error handling.
|
|
12
|
+
*/
|
|
13
|
+
import { type AuthContext, BaseConnector, type ConnectorError, type ConnectorStatus } from "./baseConnector.js";
|
|
14
|
+
export interface DatadogTokens {
|
|
15
|
+
apiKey: string;
|
|
16
|
+
appKey: string;
|
|
17
|
+
site?: string;
|
|
18
|
+
orgName?: string;
|
|
19
|
+
connected_at: string;
|
|
20
|
+
}
|
|
21
|
+
export interface DatadogSeries {
|
|
22
|
+
metric: string;
|
|
23
|
+
display_name: string;
|
|
24
|
+
unit: Array<{
|
|
25
|
+
family: string;
|
|
26
|
+
name: string;
|
|
27
|
+
short_name: string;
|
|
28
|
+
}> | null;
|
|
29
|
+
pointlist: Array<[number, number | null]>;
|
|
30
|
+
start: number;
|
|
31
|
+
end: number;
|
|
32
|
+
interval: number;
|
|
33
|
+
length: number;
|
|
34
|
+
aggr: string | null;
|
|
35
|
+
scope: string;
|
|
36
|
+
}
|
|
37
|
+
export interface DatadogMonitor {
|
|
38
|
+
id: number;
|
|
39
|
+
name: string;
|
|
40
|
+
type: string;
|
|
41
|
+
query: string;
|
|
42
|
+
message: string;
|
|
43
|
+
status: string;
|
|
44
|
+
state: string;
|
|
45
|
+
tags: string[];
|
|
46
|
+
created: string;
|
|
47
|
+
modified: string;
|
|
48
|
+
overall_state: string;
|
|
49
|
+
}
|
|
50
|
+
export interface DatadogIncident {
|
|
51
|
+
id: string;
|
|
52
|
+
type: string;
|
|
53
|
+
attributes: {
|
|
54
|
+
title: string;
|
|
55
|
+
status: string;
|
|
56
|
+
severity: string;
|
|
57
|
+
created: string;
|
|
58
|
+
modified: string;
|
|
59
|
+
customer_impact_scope?: string;
|
|
60
|
+
customer_impacted: boolean;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export declare class DatadogConnector extends BaseConnector {
|
|
64
|
+
readonly providerName = "datadog";
|
|
65
|
+
private tokens;
|
|
66
|
+
protected getOAuthConfig(): null;
|
|
67
|
+
authenticate(): Promise<AuthContext>;
|
|
68
|
+
healthCheck(): Promise<{
|
|
69
|
+
ok: boolean;
|
|
70
|
+
error?: ConnectorError;
|
|
71
|
+
}>;
|
|
72
|
+
normalizeError(error: unknown): ConnectorError;
|
|
73
|
+
getStatus(): ConnectorStatus;
|
|
74
|
+
queryMetrics(query: string, from: number, to: number): Promise<{
|
|
75
|
+
series: DatadogSeries[];
|
|
76
|
+
}>;
|
|
77
|
+
listMonitors(params?: {
|
|
78
|
+
groupStates?: string[];
|
|
79
|
+
tags?: string[];
|
|
80
|
+
perPage?: number;
|
|
81
|
+
}): Promise<DatadogMonitor[]>;
|
|
82
|
+
getMonitor(monitorId: number): Promise<DatadogMonitor>;
|
|
83
|
+
listActiveAlerts(params?: {
|
|
84
|
+
priority?: number;
|
|
85
|
+
}): Promise<DatadogMonitor[]>;
|
|
86
|
+
muteMonitor(monitorId: number, end?: number): Promise<DatadogMonitor>;
|
|
87
|
+
listIncidents(params?: {
|
|
88
|
+
perPage?: number;
|
|
89
|
+
}): Promise<{
|
|
90
|
+
data: DatadogIncident[];
|
|
91
|
+
}>;
|
|
92
|
+
private baseUrl;
|
|
93
|
+
private buildHeaders;
|
|
94
|
+
}
|
|
95
|
+
export declare function loadTokens(): DatadogTokens | null;
|
|
96
|
+
export declare function saveTokens(tokens: DatadogTokens): void;
|
|
97
|
+
export declare function clearTokens(): void;
|
|
98
|
+
export declare function getDatadogConnector(): DatadogConnector;
|
|
99
|
+
export { getDatadogConnector as datadog };
|
|
100
|
+
export interface ConnectorHandlerResult {
|
|
101
|
+
status: number;
|
|
102
|
+
body: string;
|
|
103
|
+
contentType?: string;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* POST /connections/datadog/connect { apiKey, appKey, site? }
|
|
107
|
+
*/
|
|
108
|
+
export declare function handleDatadogConnect(body: string): Promise<ConnectorHandlerResult>;
|
|
109
|
+
/**
|
|
110
|
+
* POST /connections/datadog/test
|
|
111
|
+
*/
|
|
112
|
+
export declare function handleDatadogTest(): Promise<ConnectorHandlerResult>;
|
|
113
|
+
/**
|
|
114
|
+
* DELETE /connections/datadog
|
|
115
|
+
*/
|
|
116
|
+
export declare function handleDatadogDisconnect(): ConnectorHandlerResult;
|