@wervt/nuxt 0.3.6 → 0.3.7
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/runtime/email/alert.d.ts +98 -0
- package/dist/runtime/email/alert.js +114 -0
- package/dist/runtime/email/index.d.ts +2 -1
- package/dist/runtime/email/index.js +2 -1
- package/dist/runtime/server/task-handlers.d.ts +1 -1
- package/dist/runtime/server/tool-handlers.d.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { PropType } from "vue";
|
|
2
|
+
/**
|
|
3
|
+
* A saved log query matched at least as often as its alert allows: what matched, how often, a
|
|
4
|
+
* few of the entries, and a link to the logs.
|
|
5
|
+
*/
|
|
6
|
+
export declare const LogAlertEmail: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
7
|
+
/** The app whose logs matched; `all apps` for a query across apps. */
|
|
8
|
+
app: {
|
|
9
|
+
type: StringConstructor;
|
|
10
|
+
required: true;
|
|
11
|
+
};
|
|
12
|
+
/** The saved query's name. */
|
|
13
|
+
name: {
|
|
14
|
+
type: StringConstructor;
|
|
15
|
+
required: true;
|
|
16
|
+
};
|
|
17
|
+
/** Its LogsQL. */
|
|
18
|
+
query: {
|
|
19
|
+
type: StringConstructor;
|
|
20
|
+
required: true;
|
|
21
|
+
};
|
|
22
|
+
count: {
|
|
23
|
+
type: NumberConstructor;
|
|
24
|
+
required: true;
|
|
25
|
+
};
|
|
26
|
+
threshold: {
|
|
27
|
+
type: NumberConstructor;
|
|
28
|
+
required: true;
|
|
29
|
+
};
|
|
30
|
+
/** How far back it counted, e.g. `5m`. */
|
|
31
|
+
window: {
|
|
32
|
+
type: StringConstructor;
|
|
33
|
+
required: true;
|
|
34
|
+
};
|
|
35
|
+
/** How long it stays quiet now, e.g. `1h`. */
|
|
36
|
+
cooldown: {
|
|
37
|
+
type: StringConstructor;
|
|
38
|
+
required: true;
|
|
39
|
+
};
|
|
40
|
+
/** The logs, filtered to the query. */
|
|
41
|
+
url: {
|
|
42
|
+
type: StringConstructor;
|
|
43
|
+
required: true;
|
|
44
|
+
};
|
|
45
|
+
/** First lines of the newest matching entries. */
|
|
46
|
+
samples: {
|
|
47
|
+
type: PropType<string[]>;
|
|
48
|
+
default: () => never[];
|
|
49
|
+
};
|
|
50
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
51
|
+
[key: string]: any;
|
|
52
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
53
|
+
/** The app whose logs matched; `all apps` for a query across apps. */
|
|
54
|
+
app: {
|
|
55
|
+
type: StringConstructor;
|
|
56
|
+
required: true;
|
|
57
|
+
};
|
|
58
|
+
/** The saved query's name. */
|
|
59
|
+
name: {
|
|
60
|
+
type: StringConstructor;
|
|
61
|
+
required: true;
|
|
62
|
+
};
|
|
63
|
+
/** Its LogsQL. */
|
|
64
|
+
query: {
|
|
65
|
+
type: StringConstructor;
|
|
66
|
+
required: true;
|
|
67
|
+
};
|
|
68
|
+
count: {
|
|
69
|
+
type: NumberConstructor;
|
|
70
|
+
required: true;
|
|
71
|
+
};
|
|
72
|
+
threshold: {
|
|
73
|
+
type: NumberConstructor;
|
|
74
|
+
required: true;
|
|
75
|
+
};
|
|
76
|
+
/** How far back it counted, e.g. `5m`. */
|
|
77
|
+
window: {
|
|
78
|
+
type: StringConstructor;
|
|
79
|
+
required: true;
|
|
80
|
+
};
|
|
81
|
+
/** How long it stays quiet now, e.g. `1h`. */
|
|
82
|
+
cooldown: {
|
|
83
|
+
type: StringConstructor;
|
|
84
|
+
required: true;
|
|
85
|
+
};
|
|
86
|
+
/** The logs, filtered to the query. */
|
|
87
|
+
url: {
|
|
88
|
+
type: StringConstructor;
|
|
89
|
+
required: true;
|
|
90
|
+
};
|
|
91
|
+
/** First lines of the newest matching entries. */
|
|
92
|
+
samples: {
|
|
93
|
+
type: PropType<string[]>;
|
|
94
|
+
default: () => never[];
|
|
95
|
+
};
|
|
96
|
+
}>> & Readonly<{}>, {
|
|
97
|
+
samples: string[];
|
|
98
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { EmailButton, EmailDivider, EmailHeading, EmailMuted, EmailText, WervtEmail, emailTheme } from "./components.js";
|
|
2
|
+
import { defineComponent, h } from "vue";
|
|
3
|
+
// src/runtime/email/alert.ts
|
|
4
|
+
const code = (text) => h("code", { style: {
|
|
5
|
+
fontFamily: emailTheme.mono,
|
|
6
|
+
fontSize: "13px",
|
|
7
|
+
background: emailTheme.codeBackground,
|
|
8
|
+
border: `1px solid ${emailTheme.accentBorder}`,
|
|
9
|
+
borderRadius: "4px",
|
|
10
|
+
padding: "1px 5px"
|
|
11
|
+
} }, text);
|
|
12
|
+
/** `5m` → `5 minutes`. */
|
|
13
|
+
function spelledOut(duration) {
|
|
14
|
+
const match = duration.match(/^(\d+)([mhd])$/);
|
|
15
|
+
if (!match) return duration;
|
|
16
|
+
const amount = Number(match[1]);
|
|
17
|
+
const unit = {
|
|
18
|
+
m: "minute",
|
|
19
|
+
h: "hour",
|
|
20
|
+
d: "day"
|
|
21
|
+
}[match[2]];
|
|
22
|
+
return amount === 1 ? `1 ${unit}` : `${amount} ${unit}s`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A saved log query matched at least as often as its alert allows: what matched, how often, a
|
|
26
|
+
* few of the entries, and a link to the logs.
|
|
27
|
+
*/
|
|
28
|
+
const LogAlertEmail = defineComponent({
|
|
29
|
+
name: "LogAlertEmail",
|
|
30
|
+
props: {
|
|
31
|
+
/** The app whose logs matched; `all apps` for a query across apps. */
|
|
32
|
+
app: {
|
|
33
|
+
type: String,
|
|
34
|
+
required: true
|
|
35
|
+
},
|
|
36
|
+
/** The saved query's name. */
|
|
37
|
+
name: {
|
|
38
|
+
type: String,
|
|
39
|
+
required: true
|
|
40
|
+
},
|
|
41
|
+
/** Its LogsQL. */
|
|
42
|
+
query: {
|
|
43
|
+
type: String,
|
|
44
|
+
required: true
|
|
45
|
+
},
|
|
46
|
+
count: {
|
|
47
|
+
type: Number,
|
|
48
|
+
required: true
|
|
49
|
+
},
|
|
50
|
+
threshold: {
|
|
51
|
+
type: Number,
|
|
52
|
+
required: true
|
|
53
|
+
},
|
|
54
|
+
/** How far back it counted, e.g. `5m`. */
|
|
55
|
+
window: {
|
|
56
|
+
type: String,
|
|
57
|
+
required: true
|
|
58
|
+
},
|
|
59
|
+
/** How long it stays quiet now, e.g. `1h`. */
|
|
60
|
+
cooldown: {
|
|
61
|
+
type: String,
|
|
62
|
+
required: true
|
|
63
|
+
},
|
|
64
|
+
/** The logs, filtered to the query. */
|
|
65
|
+
url: {
|
|
66
|
+
type: String,
|
|
67
|
+
required: true
|
|
68
|
+
},
|
|
69
|
+
/** First lines of the newest matching entries. */
|
|
70
|
+
samples: {
|
|
71
|
+
type: Array,
|
|
72
|
+
default: () => []
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
setup(props) {
|
|
76
|
+
return () => h(WervtEmail, {
|
|
77
|
+
subject: `${props.app}: ${props.name} (${props.count} in ${props.window})`,
|
|
78
|
+
app: props.app,
|
|
79
|
+
preview: `${props.count} log ${props.count === 1 ? "entry" : "entries"} matched in the last ${spelledOut(props.window)}`,
|
|
80
|
+
footer: "Sent by wervt",
|
|
81
|
+
reason: `You received this email because you own or help run ${props.app} and it has an alert on this query.`
|
|
82
|
+
}, () => [
|
|
83
|
+
h(EmailHeading, { eyebrow: "Log alert" }, () => props.name),
|
|
84
|
+
h(EmailText, () => [
|
|
85
|
+
`${props.count} log ${props.count === 1 ? "entry" : "entries"} of ${props.app} matched `,
|
|
86
|
+
code(props.query),
|
|
87
|
+
` in the last ${spelledOut(props.window)}. The alert fires at ${props.threshold}.`
|
|
88
|
+
]),
|
|
89
|
+
...props.samples.length ? [h(EmailMuted, () => "Newest matches:"), h("pre", {
|
|
90
|
+
class: "wv-code",
|
|
91
|
+
style: {
|
|
92
|
+
margin: "0 0 24px",
|
|
93
|
+
padding: "12px 14px",
|
|
94
|
+
fontFamily: emailTheme.mono,
|
|
95
|
+
fontSize: "12px",
|
|
96
|
+
lineHeight: "18px",
|
|
97
|
+
whiteSpace: "pre-wrap",
|
|
98
|
+
wordBreak: "break-word",
|
|
99
|
+
color: emailTheme.highlighted,
|
|
100
|
+
background: emailTheme.codeBackground,
|
|
101
|
+
border: `1px solid ${emailTheme.accentBorder}`,
|
|
102
|
+
borderRadius: "8px"
|
|
103
|
+
}
|
|
104
|
+
}, props.samples.join("\n"))] : [],
|
|
105
|
+
h(EmailButton, {
|
|
106
|
+
href: props.url,
|
|
107
|
+
color: "neutral"
|
|
108
|
+
}, () => "Open the logs"),
|
|
109
|
+
h(EmailDivider),
|
|
110
|
+
h(EmailMuted, () => `No more mails about this for ${spelledOut(props.cooldown)}, even if entries keep matching. Change or turn off the alert where the query is saved.`)
|
|
111
|
+
]);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
export { LogAlertEmail };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import { LogAlertEmail } from "./alert.js";
|
|
1
2
|
import { EmailBrand, EmailButton, EmailCode, EmailDivider, EmailHeading, EmailLink, EmailMuted, EmailText, WervtEmail, emailTheme } from "./components.js";
|
|
2
3
|
import { InviteEmail } from "./invite.js";
|
|
3
4
|
import { EmailProps, RenderedEmail, renderEmail } from "./render.js";
|
|
4
|
-
export { type EmailBrand, EmailButton, EmailCode, EmailDivider, EmailHeading, EmailLink, EmailMuted, type EmailProps, EmailText, InviteEmail, type RenderedEmail, WervtEmail, emailTheme, renderEmail };
|
|
5
|
+
export { type EmailBrand, EmailButton, EmailCode, EmailDivider, EmailHeading, EmailLink, EmailMuted, type EmailProps, EmailText, InviteEmail, LogAlertEmail, type RenderedEmail, WervtEmail, emailTheme, renderEmail };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EmailButton, EmailCode, EmailDivider, EmailHeading, EmailLink, EmailMuted, EmailText, WervtEmail, emailTheme } from "./components.js";
|
|
2
|
+
import { LogAlertEmail } from "./alert.js";
|
|
2
3
|
import { InviteEmail } from "./invite.js";
|
|
3
4
|
import { renderEmail } from "./render.js";
|
|
4
|
-
export { EmailButton, EmailCode, EmailDivider, EmailHeading, EmailLink, EmailMuted, EmailText, InviteEmail, WervtEmail, emailTheme, renderEmail };
|
|
5
|
+
export { EmailButton, EmailCode, EmailDivider, EmailHeading, EmailLink, EmailMuted, EmailText, InviteEmail, LogAlertEmail, WervtEmail, emailTheme, renderEmail };
|
|
@@ -11,8 +11,8 @@ type Registry = Record<string, {
|
|
|
11
11
|
}>;
|
|
12
12
|
/** `POST /_wervt/tasks/:name`: runs a task when the control plane asks. */
|
|
13
13
|
export declare function taskRunHandler(runTask: RunTask): import("nuxt/server").EventHandler<Promise<{
|
|
14
|
-
result?: undefined;
|
|
15
14
|
error: string;
|
|
15
|
+
result?: undefined;
|
|
16
16
|
} | {
|
|
17
17
|
error?: undefined;
|
|
18
18
|
result: {} | null;
|