@sentry/junior-plugin-api 0.123.0 → 0.124.1
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 +7 -3
- package/dist/index.js +20 -0
- package/dist/user-pages.d.ts +21 -0
- package/package.json +1 -1
- package/src/registration.ts +14 -0
- package/src/user-pages.ts +15 -0
package/README.md
CHANGED
|
@@ -60,6 +60,9 @@ Register signed-in pages through `userPages` beside `hooks`, `tasks`, and `cli`.
|
|
|
60
60
|
Each definition owns its navigation metadata and `read(ctx, input)` function,
|
|
61
61
|
so a page cannot be advertised without an implementation. List readers receive
|
|
62
62
|
validated search and cursor input and may return an opaque continuation cursor.
|
|
63
|
+
Set `navigation: "primary"` for a top-level dashboard navigation item. The
|
|
64
|
+
default `profile` placement keeps account-oriented pages in the signed-in user
|
|
65
|
+
menu. Junior always renders core System navigation after plugin pages.
|
|
63
66
|
Records may expose bounded `DELETE` actions inside their own authenticated
|
|
64
67
|
plugin API namespace. Core owns discovery, authentication, actor resolution,
|
|
65
68
|
routing, response validation, rendering, confirmation, and query state.
|
|
@@ -88,9 +91,10 @@ routing, response validation, rendering, confirmation, and query state.
|
|
|
88
91
|
Register plugin-owned event definitions through `conversationEvents`. A
|
|
89
92
|
definition owns one local name, version, content schema, and `renderEvent()`
|
|
90
93
|
projection. The active plugin context supplies the namespace, so plugins cannot
|
|
91
|
-
emit native events or impersonate another plugin.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
emit native events or impersonate another plugin. The `junior` plugin name is
|
|
95
|
+
reserved for host-owned native events. Stored events remain durable when a
|
|
96
|
+
plugin is removed, but normal transcript projection skips definitions that are
|
|
97
|
+
not currently registered.
|
|
94
98
|
|
|
95
99
|
## Database
|
|
96
100
|
|
package/dist/index.js
CHANGED
|
@@ -570,6 +570,11 @@ function defineJuniorPlugin(plugin) {
|
|
|
570
570
|
`Junior plugin registration name "${name}" must be a lowercase plugin identifier.`
|
|
571
571
|
);
|
|
572
572
|
}
|
|
573
|
+
if (name === "junior") {
|
|
574
|
+
throw new Error(
|
|
575
|
+
'Junior plugin registration name "junior" is reserved for native host events.'
|
|
576
|
+
);
|
|
577
|
+
}
|
|
573
578
|
if (typeof manifest.displayName !== "string" || !manifest.displayName.trim()) {
|
|
574
579
|
throw new Error(
|
|
575
580
|
`Junior plugin "${name}" manifest.displayName is required.`
|
|
@@ -623,6 +628,11 @@ function defineJuniorPlugin(plugin) {
|
|
|
623
628
|
`Junior plugin "${name}" user page "${page.id}" requires label and description.`
|
|
624
629
|
);
|
|
625
630
|
}
|
|
631
|
+
if (page.navigation !== void 0 && page.navigation !== "primary" && page.navigation !== "profile") {
|
|
632
|
+
throw new Error(
|
|
633
|
+
`Junior plugin "${name}" user page "${page.id}" navigation must be "primary" or "profile".`
|
|
634
|
+
);
|
|
635
|
+
}
|
|
626
636
|
if (typeof page.read !== "function") {
|
|
627
637
|
throw new Error(
|
|
628
638
|
`Junior plugin "${name}" user page "${page.id}" requires a read function.`
|
|
@@ -640,6 +650,13 @@ import { z as z10 } from "zod";
|
|
|
640
650
|
var userPageIdSchema = nonBlankStringSchema.max(64).regex(/^[a-z][a-z0-9-]*$/);
|
|
641
651
|
var userPageLabelSchema = nonBlankStringSchema.max(80);
|
|
642
652
|
var userPageDescriptionSchema = nonBlankStringSchema.max(500);
|
|
653
|
+
var userPageNavigationSchema = z10.enum(["primary", "profile"]);
|
|
654
|
+
var pluginUserPageMetricSchema = z10.object({
|
|
655
|
+
detail: nonBlankStringSchema.max(500).optional(),
|
|
656
|
+
label: nonBlankStringSchema.max(80),
|
|
657
|
+
tone: z10.enum(["good", "neutral", "warning"]).optional(),
|
|
658
|
+
value: nonBlankStringSchema.max(120)
|
|
659
|
+
}).strict();
|
|
643
660
|
var pluginUserPageMetadataSchema = z10.object({
|
|
644
661
|
label: nonBlankStringSchema.max(80),
|
|
645
662
|
value: nonBlankStringSchema.max(500)
|
|
@@ -660,6 +677,7 @@ var pluginUserPageRecordSchema = z10.object({
|
|
|
660
677
|
}).strict();
|
|
661
678
|
var pluginUserPageContentSchema = z10.object({
|
|
662
679
|
emptyText: nonBlankStringSchema.max(500).optional(),
|
|
680
|
+
metrics: z10.array(pluginUserPageMetricSchema).max(6).optional(),
|
|
663
681
|
nextCursor: nonBlankStringSchema.max(1e3).optional(),
|
|
664
682
|
records: z10.array(pluginUserPageRecordSchema).max(100),
|
|
665
683
|
searchPlaceholder: nonBlankStringSchema.max(120).optional(),
|
|
@@ -669,12 +687,14 @@ var pluginUserPageLinkSchema = z10.object({
|
|
|
669
687
|
description: userPageDescriptionSchema,
|
|
670
688
|
id: userPageIdSchema,
|
|
671
689
|
label: userPageLabelSchema,
|
|
690
|
+
navigation: userPageNavigationSchema,
|
|
672
691
|
pluginDisplayName: nonBlankStringSchema.max(200),
|
|
673
692
|
pluginName: nonBlankStringSchema.max(100)
|
|
674
693
|
}).strict();
|
|
675
694
|
var pluginUserPageLinksSchema = z10.array(pluginUserPageLinkSchema);
|
|
676
695
|
var pluginUserPageInputSchema = z10.object({
|
|
677
696
|
cursor: nonBlankStringSchema.max(1e3).optional(),
|
|
697
|
+
filter: nonBlankStringSchema.max(64).optional(),
|
|
678
698
|
limit: z10.number().int().min(1).max(50),
|
|
679
699
|
query: z10.string().trim().max(200).optional()
|
|
680
700
|
}).strict();
|
package/dist/user-pages.d.ts
CHANGED
|
@@ -9,6 +9,16 @@ import type { LocalActor, PluginContext, SlackActor } from "./context";
|
|
|
9
9
|
/** Bounded list content returned by a plugin-owned user page. */
|
|
10
10
|
export declare const pluginUserPageContentSchema: z.ZodObject<{
|
|
11
11
|
emptyText: z.ZodOptional<z.ZodString>;
|
|
12
|
+
metrics: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
13
|
+
detail: z.ZodOptional<z.ZodString>;
|
|
14
|
+
label: z.ZodString;
|
|
15
|
+
tone: z.ZodOptional<z.ZodEnum<{
|
|
16
|
+
warning: "warning";
|
|
17
|
+
good: "good";
|
|
18
|
+
neutral: "neutral";
|
|
19
|
+
}>>;
|
|
20
|
+
value: z.ZodString;
|
|
21
|
+
}, z.core.$strict>>>;
|
|
12
22
|
nextCursor: z.ZodOptional<z.ZodString>;
|
|
13
23
|
records: z.ZodArray<z.ZodObject<{
|
|
14
24
|
actions: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -38,6 +48,10 @@ export declare const pluginUserPageLinkSchema: z.ZodObject<{
|
|
|
38
48
|
description: z.ZodString;
|
|
39
49
|
id: z.ZodString;
|
|
40
50
|
label: z.ZodString;
|
|
51
|
+
navigation: z.ZodEnum<{
|
|
52
|
+
primary: "primary";
|
|
53
|
+
profile: "profile";
|
|
54
|
+
}>;
|
|
41
55
|
pluginDisplayName: z.ZodString;
|
|
42
56
|
pluginName: z.ZodString;
|
|
43
57
|
}, z.core.$strict>;
|
|
@@ -45,6 +59,10 @@ export declare const pluginUserPageLinksSchema: z.ZodArray<z.ZodObject<{
|
|
|
45
59
|
description: z.ZodString;
|
|
46
60
|
id: z.ZodString;
|
|
47
61
|
label: z.ZodString;
|
|
62
|
+
navigation: z.ZodEnum<{
|
|
63
|
+
primary: "primary";
|
|
64
|
+
profile: "profile";
|
|
65
|
+
}>;
|
|
48
66
|
pluginDisplayName: z.ZodString;
|
|
49
67
|
pluginName: z.ZodString;
|
|
50
68
|
}, z.core.$strict>>;
|
|
@@ -53,6 +71,7 @@ export type PluginUserPageLink = z.output<typeof pluginUserPageLinkSchema>;
|
|
|
53
71
|
/** Validated query state passed to one plugin user page reader. */
|
|
54
72
|
export declare const pluginUserPageInputSchema: z.ZodObject<{
|
|
55
73
|
cursor: z.ZodOptional<z.ZodString>;
|
|
74
|
+
filter: z.ZodOptional<z.ZodString>;
|
|
56
75
|
limit: z.ZodNumber;
|
|
57
76
|
query: z.ZodOptional<z.ZodString>;
|
|
58
77
|
}, z.core.$strict>;
|
|
@@ -71,5 +90,7 @@ export interface PluginUserPageDefinition {
|
|
|
71
90
|
description: string;
|
|
72
91
|
id: string;
|
|
73
92
|
label: string;
|
|
93
|
+
/** Dashboard navigation surface where this page is linked. */
|
|
94
|
+
navigation?: "primary" | "profile";
|
|
74
95
|
read(ctx: PluginUserPageContext, input: PluginUserPageInput): Promise<PluginUserPageContent> | PluginUserPageContent;
|
|
75
96
|
}
|
package/package.json
CHANGED
package/src/registration.ts
CHANGED
|
@@ -55,6 +55,11 @@ export function defineJuniorPlugin(
|
|
|
55
55
|
`Junior plugin registration name "${name}" must be a lowercase plugin identifier.`,
|
|
56
56
|
);
|
|
57
57
|
}
|
|
58
|
+
if (name === "junior") {
|
|
59
|
+
throw new Error(
|
|
60
|
+
'Junior plugin registration name "junior" is reserved for native host events.',
|
|
61
|
+
);
|
|
62
|
+
}
|
|
58
63
|
if (
|
|
59
64
|
typeof manifest.displayName !== "string" ||
|
|
60
65
|
!manifest.displayName.trim()
|
|
@@ -133,6 +138,15 @@ export function defineJuniorPlugin(
|
|
|
133
138
|
`Junior plugin "${name}" user page "${page.id}" requires label and description.`,
|
|
134
139
|
);
|
|
135
140
|
}
|
|
141
|
+
if (
|
|
142
|
+
page.navigation !== undefined &&
|
|
143
|
+
page.navigation !== "primary" &&
|
|
144
|
+
page.navigation !== "profile"
|
|
145
|
+
) {
|
|
146
|
+
throw new Error(
|
|
147
|
+
`Junior plugin "${name}" user page "${page.id}" navigation must be "primary" or "profile".`,
|
|
148
|
+
);
|
|
149
|
+
}
|
|
136
150
|
if (typeof page.read !== "function") {
|
|
137
151
|
throw new Error(
|
|
138
152
|
`Junior plugin "${name}" user page "${page.id}" requires a read function.`,
|
package/src/user-pages.ts
CHANGED
|
@@ -13,6 +13,16 @@ const userPageIdSchema = nonBlankStringSchema
|
|
|
13
13
|
.regex(/^[a-z][a-z0-9-]*$/);
|
|
14
14
|
const userPageLabelSchema = nonBlankStringSchema.max(80);
|
|
15
15
|
const userPageDescriptionSchema = nonBlankStringSchema.max(500);
|
|
16
|
+
const userPageNavigationSchema = z.enum(["primary", "profile"]);
|
|
17
|
+
|
|
18
|
+
const pluginUserPageMetricSchema = z
|
|
19
|
+
.object({
|
|
20
|
+
detail: nonBlankStringSchema.max(500).optional(),
|
|
21
|
+
label: nonBlankStringSchema.max(80),
|
|
22
|
+
tone: z.enum(["good", "neutral", "warning"]).optional(),
|
|
23
|
+
value: nonBlankStringSchema.max(120),
|
|
24
|
+
})
|
|
25
|
+
.strict();
|
|
16
26
|
|
|
17
27
|
const pluginUserPageMetadataSchema = z
|
|
18
28
|
.object({
|
|
@@ -47,6 +57,7 @@ const pluginUserPageRecordSchema = z
|
|
|
47
57
|
export const pluginUserPageContentSchema = z
|
|
48
58
|
.object({
|
|
49
59
|
emptyText: nonBlankStringSchema.max(500).optional(),
|
|
60
|
+
metrics: z.array(pluginUserPageMetricSchema).max(6).optional(),
|
|
50
61
|
nextCursor: nonBlankStringSchema.max(1_000).optional(),
|
|
51
62
|
records: z.array(pluginUserPageRecordSchema).max(100),
|
|
52
63
|
searchPlaceholder: nonBlankStringSchema.max(120).optional(),
|
|
@@ -64,6 +75,7 @@ export const pluginUserPageLinkSchema = z
|
|
|
64
75
|
description: userPageDescriptionSchema,
|
|
65
76
|
id: userPageIdSchema,
|
|
66
77
|
label: userPageLabelSchema,
|
|
78
|
+
navigation: userPageNavigationSchema,
|
|
67
79
|
pluginDisplayName: nonBlankStringSchema.max(200),
|
|
68
80
|
pluginName: nonBlankStringSchema.max(100),
|
|
69
81
|
})
|
|
@@ -78,6 +90,7 @@ export type PluginUserPageLink = z.output<typeof pluginUserPageLinkSchema>;
|
|
|
78
90
|
export const pluginUserPageInputSchema = z
|
|
79
91
|
.object({
|
|
80
92
|
cursor: nonBlankStringSchema.max(1_000).optional(),
|
|
93
|
+
filter: nonBlankStringSchema.max(64).optional(),
|
|
81
94
|
limit: z.number().int().min(1).max(50),
|
|
82
95
|
query: z.string().trim().max(200).optional(),
|
|
83
96
|
})
|
|
@@ -101,6 +114,8 @@ export interface PluginUserPageDefinition {
|
|
|
101
114
|
description: string;
|
|
102
115
|
id: string;
|
|
103
116
|
label: string;
|
|
117
|
+
/** Dashboard navigation surface where this page is linked. */
|
|
118
|
+
navigation?: "primary" | "profile";
|
|
104
119
|
read(
|
|
105
120
|
ctx: PluginUserPageContext,
|
|
106
121
|
input: PluginUserPageInput,
|