@sentry/junior-plugin-api 0.124.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 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.
package/dist/index.js CHANGED
@@ -628,6 +628,11 @@ function defineJuniorPlugin(plugin) {
628
628
  `Junior plugin "${name}" user page "${page.id}" requires label and description.`
629
629
  );
630
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
+ }
631
636
  if (typeof page.read !== "function") {
632
637
  throw new Error(
633
638
  `Junior plugin "${name}" user page "${page.id}" requires a read function.`
@@ -645,6 +650,13 @@ import { z as z10 } from "zod";
645
650
  var userPageIdSchema = nonBlankStringSchema.max(64).regex(/^[a-z][a-z0-9-]*$/);
646
651
  var userPageLabelSchema = nonBlankStringSchema.max(80);
647
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();
648
660
  var pluginUserPageMetadataSchema = z10.object({
649
661
  label: nonBlankStringSchema.max(80),
650
662
  value: nonBlankStringSchema.max(500)
@@ -665,6 +677,7 @@ var pluginUserPageRecordSchema = z10.object({
665
677
  }).strict();
666
678
  var pluginUserPageContentSchema = z10.object({
667
679
  emptyText: nonBlankStringSchema.max(500).optional(),
680
+ metrics: z10.array(pluginUserPageMetricSchema).max(6).optional(),
668
681
  nextCursor: nonBlankStringSchema.max(1e3).optional(),
669
682
  records: z10.array(pluginUserPageRecordSchema).max(100),
670
683
  searchPlaceholder: nonBlankStringSchema.max(120).optional(),
@@ -674,12 +687,14 @@ var pluginUserPageLinkSchema = z10.object({
674
687
  description: userPageDescriptionSchema,
675
688
  id: userPageIdSchema,
676
689
  label: userPageLabelSchema,
690
+ navigation: userPageNavigationSchema,
677
691
  pluginDisplayName: nonBlankStringSchema.max(200),
678
692
  pluginName: nonBlankStringSchema.max(100)
679
693
  }).strict();
680
694
  var pluginUserPageLinksSchema = z10.array(pluginUserPageLinkSchema);
681
695
  var pluginUserPageInputSchema = z10.object({
682
696
  cursor: nonBlankStringSchema.max(1e3).optional(),
697
+ filter: nonBlankStringSchema.max(64).optional(),
683
698
  limit: z10.number().int().min(1).max(50),
684
699
  query: z10.string().trim().max(200).optional()
685
700
  }).strict();
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior-plugin-api",
3
- "version": "0.124.0",
3
+ "version": "0.124.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -138,6 +138,15 @@ export function defineJuniorPlugin(
138
138
  `Junior plugin "${name}" user page "${page.id}" requires label and description.`,
139
139
  );
140
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
+ }
141
150
  if (typeof page.read !== "function") {
142
151
  throw new Error(
143
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,