Skip to content

Commit 07ca4ad

Browse files
author
wafuwafu13
committed
feat: Add Dashboard API
1 parent 46d5b14 commit 07ca4ad

File tree

3 files changed

+365
-1
lines changed

3 files changed

+365
-1
lines changed

dashboard_test.ts

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
import { Dashboard } from "./dashboards.ts";
2+
import { assertEquals, mf } from "./deps.ts";
3+
import { Mackerel } from "./mackerel.ts";
4+
5+
const dummyApiKey = "dummy-apikey";
6+
const dummyBaseurl = "https://example.com/";
7+
8+
Deno.test("createDashboards", async () => {
9+
const param: Dashboard = {
10+
title: "test title",
11+
urlPath: "aaaaaaaa",
12+
memo: "this is test",
13+
widgets: [
14+
{
15+
type: "markdown",
16+
title: "test",
17+
layout: {
18+
x: 1,
19+
y: 1,
20+
width: 3,
21+
height: 3,
22+
},
23+
markdown: "### h3",
24+
},
25+
],
26+
};
27+
mf.install();
28+
mf.mock(
29+
"POST@/api/v0/dashboards",
30+
(_req, _params) => {
31+
const resp = {
32+
id: "testid",
33+
createdAt: 111111111,
34+
updatedAt: 111111111,
35+
...param,
36+
};
37+
return new Response(
38+
JSON.stringify(
39+
resp,
40+
),
41+
{ status: 200 },
42+
);
43+
},
44+
);
45+
const client = new Mackerel.Client(dummyApiKey, dummyBaseurl);
46+
const resp = await client.createDashboards(param);
47+
assertEquals(resp.id, "testid");
48+
assertEquals(resp.widgets[0].title, "test");
49+
mf.uninstall();
50+
});
51+
52+
Deno.test("getDashboards", async () => {
53+
const dashboardID = "testid";
54+
mf.install();
55+
mf.mock(`GET@/api/v0/dashboards/${dashboardID}`, (_req, _params) => {
56+
return new Response(
57+
JSON.stringify({
58+
id: dashboardID,
59+
createdAt: 1111111111,
60+
updatedAt: 2222222222,
61+
title: "Test Dashbord",
62+
urlPath: "aaaaaaaaaaa",
63+
memo: "this is test dashbord",
64+
widgets: [
65+
{
66+
type: "markdown",
67+
title: "Test Markdown",
68+
markdown: "# Markdown\n\nthis is markdown",
69+
layout: { x: 0, y: 0, width: 6, height: 6 },
70+
},
71+
{
72+
type: "graph",
73+
title: "test title",
74+
graph: {
75+
type: "role",
76+
roleFullname: "hatena-mac:hatena-mac",
77+
name: "cpu.{user,system}",
78+
isStacked: true,
79+
},
80+
layout: { x: 6, y: 0, width: 6, height: 6 },
81+
},
82+
{
83+
type: "alertStatus",
84+
title: "test title",
85+
roleFullname: "test:test",
86+
layout: { x: 12, y: 0, width: 6, height: 6 },
87+
},
88+
],
89+
}),
90+
{ status: 200 },
91+
);
92+
});
93+
const client = new Mackerel.Client(dummyApiKey, dummyBaseurl);
94+
const resp = await client.getDashboards(dashboardID);
95+
assertEquals(resp.id, dashboardID);
96+
assertEquals(resp.widgets[0].type, "markdown");
97+
});
98+
99+
Deno.test("updateDashboards", async () => {
100+
const dashboardID = "testid";
101+
const param: Dashboard = {
102+
title: "test title",
103+
urlPath: "aaaaaaaa",
104+
memo: "this is test",
105+
widgets: [
106+
{
107+
type: "markdown",
108+
title: "test",
109+
layout: {
110+
x: 1,
111+
y: 1,
112+
width: 3,
113+
height: 3,
114+
},
115+
markdown: "#### h4",
116+
},
117+
],
118+
};
119+
mf.install();
120+
mf.mock(
121+
`PUT@/api/v0/dashboards/${dashboardID}`,
122+
(_req, _params) => {
123+
const resp = {
124+
id: dashboardID,
125+
createdAt: 111111111,
126+
updatedAt: 222222222,
127+
...param,
128+
};
129+
return new Response(
130+
JSON.stringify(
131+
resp,
132+
),
133+
{ status: 200 },
134+
);
135+
},
136+
);
137+
const client = new Mackerel.Client(dummyApiKey, dummyBaseurl);
138+
const resp = await client.updateDashboards(dashboardID, param);
139+
assertEquals(resp.id, dashboardID);
140+
assertEquals(resp.widgets[0].title, "test");
141+
mf.uninstall();
142+
});
143+
144+
Deno.test("deleteDashboards", async () => {
145+
const dashboardID = "testid";
146+
mf.install();
147+
mf.mock(`DELETE@/api/v0/dashboards/${dashboardID}`, (_req, _params) => {
148+
return new Response(
149+
JSON.stringify({
150+
id: dashboardID,
151+
createdAt: 1111111111,
152+
updatedAt: 2222222222,
153+
title: "Test Dashbord",
154+
urlPath: "aaaaaaaa",
155+
memo: "this is test",
156+
}),
157+
{ status: 200 },
158+
);
159+
});
160+
const client = new Mackerel.Client(dummyApiKey, dummyBaseurl);
161+
const resp = await client.deleteDashboards(dashboardID);
162+
assertEquals(resp.id, dashboardID);
163+
assertEquals(resp.memo, "this is test");
164+
mf.uninstall();
165+
});
166+
167+
Deno.test("listDashboards", async () => {
168+
mf.install();
169+
mf.mock("GET@/api/v0/dashboards", (_req, _params) => {
170+
return new Response(
171+
JSON.stringify({
172+
dashboards: [
173+
{
174+
id: "test id",
175+
createdAt: 1111111111,
176+
updatedAt: 2222222222,
177+
title: "Test Dashbord",
178+
urlPath: "aaaaaaaa",
179+
memo: "this is test",
180+
},
181+
],
182+
}),
183+
{ status: 200 },
184+
);
185+
});
186+
const client = new Mackerel.Client(dummyApiKey, dummyBaseurl);
187+
const resp = await client.listDashboards();
188+
assertEquals(resp[0].title, "Test Dashbord");
189+
assertEquals(resp[0].memo, "this is test");
190+
mf.uninstall();
191+
});

dashboards.ts

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import { PayloadType } from "./mackerel.ts";
2+
3+
export type Dashboard = {
4+
id?: string;
5+
title: string;
6+
urlPath: string;
7+
createdAt?: number;
8+
updatedAt?: number;
9+
memo: string;
10+
widgets: Widget[];
11+
};
12+
13+
export type Widget = {
14+
type: string;
15+
title: string;
16+
layout: Layout;
17+
metric?: Metric;
18+
graph?: Graph;
19+
range?: Range;
20+
markdown?: string;
21+
fractionSize?: number;
22+
suffix?: string;
23+
roleFullName?: string;
24+
};
25+
26+
type Layout = {
27+
x: number;
28+
y: number;
29+
width: number;
30+
height: number;
31+
};
32+
33+
type Metric = {
34+
type: string;
35+
name?: string;
36+
hostID?: string;
37+
serviceName?: string;
38+
expression?: string;
39+
};
40+
41+
type Graph = {
42+
type: string;
43+
name?: string;
44+
hostID?: string;
45+
roleFullName?: string;
46+
isStacked?: boolean;
47+
serviceName?: string;
48+
expression?: string;
49+
};
50+
51+
type Range = {
52+
type: string;
53+
period: number;
54+
offset: number;
55+
start: number;
56+
end: number;
57+
};
58+
59+
export const createDashboards = async (
60+
param: Dashboard,
61+
postJSON: (
62+
path: string,
63+
payload: PayloadType,
64+
) => Promise<Response | Error>,
65+
): Promise<Dashboard> => {
66+
const resp = await postJSON("/api/v0/dashboards", param);
67+
if (resp instanceof Error) {
68+
throw resp;
69+
}
70+
const dashboard = await resp.json() as Dashboard;
71+
return dashboard;
72+
};
73+
74+
export const getDashboards = async (
75+
dashboardID: string,
76+
urlFor: (path: string) => URL,
77+
req: (req: Request) => Promise<Response | Error>,
78+
): Promise<Dashboard> => {
79+
const request = new Request(
80+
urlFor(`/api/v0/dashboards/${dashboardID}`).toString(),
81+
{
82+
method: "GET",
83+
},
84+
);
85+
const resp = await req(request);
86+
if (resp instanceof Error) {
87+
throw resp;
88+
}
89+
const dashboard = await resp.json() as Dashboard;
90+
return dashboard;
91+
};
92+
93+
export const updateDashboards = async (
94+
dashboardID: string,
95+
param: Dashboard,
96+
putJSON: (
97+
path: string,
98+
payload: PayloadType,
99+
) => Promise<Response | Error>,
100+
): Promise<Dashboard> => {
101+
const resp = await putJSON(`/api/v0/dashboards/${dashboardID}`, param);
102+
if (resp instanceof Error) {
103+
throw resp;
104+
}
105+
const dashboard = await resp.json() as Dashboard;
106+
return dashboard;
107+
};
108+
109+
export const deleteDashboards = async (
110+
dashboardID: string,
111+
urlFor: (path: string) => URL,
112+
req: (req: Request) => Promise<Response | Error>,
113+
): Promise<Dashboard> => {
114+
const request = new Request(
115+
urlFor(`/api/v0/dashboards/${dashboardID}`).toString(),
116+
{
117+
method: "DELETE",
118+
},
119+
);
120+
request.headers.set("Content-Type", "application/json");
121+
const resp = await req(request);
122+
if (resp instanceof Error) {
123+
throw resp;
124+
}
125+
const dashboard = await resp.json() as Dashboard;
126+
return dashboard;
127+
};
128+
129+
export const listDashboards = async (
130+
urlFor: (path: string) => URL,
131+
req: (req: Request) => Promise<Response | Error>,
132+
): Promise<Dashboard[]> => {
133+
const request = new Request(urlFor("/api/v0/dashboards").toString(), {
134+
method: "GET",
135+
});
136+
const resp = await req(request);
137+
if (resp instanceof Error) {
138+
throw resp;
139+
}
140+
const dashboards = await resp.json() as {
141+
dashboards: Dashboard[];
142+
};
143+
return dashboards["dashboards"];
144+
};

mackerel.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ import {
1919
UpdateAWSIntegrationParam,
2020
updateAwsIntegrationSettings,
2121
} from "./awsintegrations.ts";
22+
import {
23+
createDashboards,
24+
Dashboard,
25+
deleteDashboards,
26+
getDashboards,
27+
listDashboards,
28+
updateDashboards,
29+
Widget,
30+
} from "./dashboards.ts";
2231

2332
export const defaultBaseURL = "https://api.mackerelio.com/";
2433

@@ -38,7 +47,7 @@ type ErrorType = {
3847
export type PayloadType =
3948
| Record<
4049
never | string,
41-
never | string | number | null | AWSIntegrationServices
50+
never | string | number | null | AWSIntegrationServices | Widget[]
4251
>
4352
| null;
4453

@@ -118,6 +127,26 @@ export namespace Mackerel {
118127
return deleteService(serviceName, this.urlFor, this.request);
119128
};
120129

130+
createDashboards = (param: Dashboard) => {
131+
return createDashboards(param, this.postJSON);
132+
};
133+
134+
getDashboards = (dashboardID: string) => {
135+
return getDashboards(dashboardID, this.urlFor, this.request);
136+
};
137+
138+
updateDashboards = (dashboardID: string, param: Dashboard) => {
139+
return updateDashboards(dashboardID, param, this.putJSON);
140+
};
141+
142+
deleteDashboards = (dashboardID: string) => {
143+
return deleteDashboards(dashboardID, this.urlFor, this.request);
144+
};
145+
146+
listDashboards = () => {
147+
return listDashboards(this.urlFor, this.request);
148+
};
149+
121150
listAwsIntegrationSettings = (): Promise<AWSIntegration[]> => {
122151
return listAwsIntegrationSettings(this.urlFor, this.request);
123152
};

0 commit comments

Comments
 (0)