@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 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. Stored events remain durable
92
- when a plugin is removed, but normal transcript projection skips definitions
93
- that are not currently registered.
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();
@@ -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.123.0",
3
+ "version": "0.124.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -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,