@burdenoff/microfe-devportal 2026.1108.2 → 2026.1109.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.
@@ -4,140 +4,147 @@ import { DevportalRoutes as n } from "./DevportalRoutes.js";
4
4
  import { setDevportalEventBusBridge as r } from "./events/index.js";
5
5
  import { useEffect as i } from "react";
6
6
  import { ErrorBoundary as a } from "@burdenoff/fe-libs/shared/components";
7
- import { AppWindow as o, BarChart3 as s, BookOpen as c, Building2 as l, Code2 as u, DollarSign as d, Key as f, LayoutDashboard as p, Settings as m, Shield as h, Webhook as g, Wrench as _ } from "lucide-react";
8
- import { jsx as v } from "react/jsx-runtime";
9
- import { FeatureFlagProvider as y } from "@burdenoff/fe-libs/shared/feature-flags";
10
- import { useEventBus as b } from "@burdenoff/fe-libs/shared/events";
7
+ import { AppWindow as o, BarChart3 as s, Blocks as c, BookOpen as l, Building2 as u, Code2 as d, DollarSign as f, Key as p, LayoutDashboard as m, Settings as h, Shield as g, Webhook as _, Wrench as v } from "lucide-react";
8
+ import { jsx as y } from "react/jsx-runtime";
9
+ import { FeatureFlagProvider as b } from "@burdenoff/fe-libs/shared/feature-flags";
10
+ import { useEventBus as x } from "@burdenoff/fe-libs/shared/events";
11
11
  // src/devportal/DevportalRoot.tsx
12
- var x = (x) => {
13
- let { registerNavItems: S, registerFooterItems: C, basePath: w = "/" } = x, T = t(), E = (e, t) => (e.endsWith("/") ? e.slice(0, -1) : e) + (t.startsWith("/") ? t : `/${t}`);
12
+ var S = (S) => {
13
+ let { registerNavItems: C, registerFooterItems: w, basePath: T = "/" } = S, E = t(), D = (e, t) => (e.endsWith("/") ? e.slice(0, -1) : e) + (t.startsWith("/") ? t : `/${t}`);
14
14
  i(() => {
15
- if (!S) return;
15
+ if (!C) return;
16
16
  let e = {
17
17
  id: "devportal",
18
- label: T("devportal.developerPortal", "Developer Portal"),
19
- path: w,
20
- icon: /* @__PURE__ */ v(u, { size: 20 }),
18
+ label: E("devportal.developerPortal", "Developer Portal"),
19
+ path: T,
20
+ icon: /* @__PURE__ */ y(d, { size: 20 }),
21
21
  order: 75,
22
22
  group: "global",
23
23
  children: [
24
24
  {
25
25
  id: "devportal-dashboard",
26
- label: T("devportal.dashboard", "Dashboard"),
27
- path: w,
28
- icon: /* @__PURE__ */ v(p, { size: 16 }),
26
+ label: E("devportal.dashboard", "Dashboard"),
27
+ path: T,
28
+ icon: /* @__PURE__ */ y(m, { size: 16 }),
29
29
  order: 10
30
30
  },
31
31
  {
32
32
  id: "devportal-organizations",
33
- label: T("devportal.organizations", "Organizations"),
34
- path: E(w, "organizations"),
35
- icon: /* @__PURE__ */ v(l, { size: 16 }),
33
+ label: E("devportal.organizations", "Organizations"),
34
+ path: D(T, "organizations"),
35
+ icon: /* @__PURE__ */ y(u, { size: 16 }),
36
36
  order: 20
37
37
  },
38
38
  {
39
39
  id: "devportal-apps",
40
- label: T("devportal.myApps", "My Apps"),
41
- path: E(w, "apps"),
42
- icon: /* @__PURE__ */ v(o, { size: 16 }),
40
+ label: E("devportal.myApps", "My Apps"),
41
+ path: D(T, "apps"),
42
+ icon: /* @__PURE__ */ y(o, { size: 16 }),
43
43
  order: 30
44
44
  },
45
+ {
46
+ id: "devportal-timecampus-applets",
47
+ label: E("devportal.nav.timecampusApplets", "TimeCampus Applets"),
48
+ path: D(T, "timecampus-applets"),
49
+ icon: /* @__PURE__ */ y(c, { size: 16 }),
50
+ order: 35
51
+ },
45
52
  {
46
53
  id: "devportal-oauth",
47
- label: T("devportal.oauthClients", "OAuth Clients"),
48
- path: E(w, "oauth"),
49
- icon: /* @__PURE__ */ v(h, { size: 16 }),
54
+ label: E("devportal.oauthClients", "OAuth Clients"),
55
+ path: D(T, "oauth"),
56
+ icon: /* @__PURE__ */ y(g, { size: 16 }),
50
57
  order: 40
51
58
  },
52
59
  {
53
60
  id: "devportal-api-keys",
54
- label: T("devportal.apiKeys", "API Keys"),
55
- path: E(w, "api-keys"),
56
- icon: /* @__PURE__ */ v(f, { size: 16 }),
61
+ label: E("devportal.apiKeys", "API Keys"),
62
+ path: D(T, "api-keys"),
63
+ icon: /* @__PURE__ */ y(p, { size: 16 }),
57
64
  order: 50
58
65
  },
59
66
  {
60
67
  id: "devportal-webhooks",
61
- label: T("devportal.webhooks", "Webhooks"),
62
- path: E(w, "webhooks"),
63
- icon: /* @__PURE__ */ v(g, { size: 16 }),
68
+ label: E("devportal.webhooks", "Webhooks"),
69
+ path: D(T, "webhooks"),
70
+ icon: /* @__PURE__ */ y(_, { size: 16 }),
64
71
  order: 60
65
72
  },
66
73
  {
67
74
  id: "devportal-analytics",
68
- label: T("devportal.analytics", "Analytics"),
69
- path: E(w, "analytics"),
70
- icon: /* @__PURE__ */ v(s, { size: 16 }),
75
+ label: E("devportal.analytics", "Analytics"),
76
+ path: D(T, "analytics"),
77
+ icon: /* @__PURE__ */ y(s, { size: 16 }),
71
78
  order: 70
72
79
  },
73
80
  {
74
81
  id: "devportal-revenue",
75
- label: T("devportal.revenue", "Revenue"),
82
+ label: E("devportal.revenue", "Revenue"),
76
83
  path: "/billing/earnings",
77
- icon: /* @__PURE__ */ v(d, { size: 16 }),
84
+ icon: /* @__PURE__ */ y(f, { size: 16 }),
78
85
  order: 80
79
86
  },
80
87
  {
81
88
  id: "devportal-docs",
82
- label: T("devportal.documentation", "Documentation"),
83
- path: E(w, "docs"),
84
- icon: /* @__PURE__ */ v(c, { size: 16 }),
89
+ label: E("devportal.documentation", "Documentation"),
90
+ path: D(T, "docs"),
91
+ icon: /* @__PURE__ */ y(l, { size: 16 }),
85
92
  order: 90
86
93
  },
87
94
  {
88
95
  id: "devportal-resources",
89
- label: T("devportal.resources", "Resources"),
90
- path: E(w, "resources"),
91
- icon: /* @__PURE__ */ v(_, { size: 16 }),
96
+ label: E("devportal.resources", "Resources"),
97
+ path: D(T, "resources"),
98
+ icon: /* @__PURE__ */ y(v, { size: 16 }),
92
99
  order: 100
93
100
  },
94
101
  {
95
102
  id: "devportal-settings",
96
- label: T("devportal.settings", "Settings"),
97
- path: E(w, "settings"),
98
- icon: /* @__PURE__ */ v(m, { size: 16 }),
103
+ label: E("devportal.settings", "Settings"),
104
+ path: D(T, "settings"),
105
+ icon: /* @__PURE__ */ y(h, { size: 16 }),
99
106
  order: 110
100
107
  }
101
108
  ]
102
109
  };
103
- return S(e);
110
+ return C(e);
104
111
  }, [
105
- S,
106
- w,
107
- T
112
+ C,
113
+ T,
114
+ E
108
115
  ]), i(() => {
109
- if (!C) return;
116
+ if (!w) return;
110
117
  let e = [{
111
118
  id: "devportal-status",
112
- label: T("devportal.developerPortalReady", "Developer Portal Ready"),
119
+ label: E("devportal.developerPortalReady", "Developer Portal Ready"),
113
120
  type: "status",
114
121
  order: 10,
115
122
  section: "left"
116
123
  }];
117
- return C(e);
118
- }, [C, T]), i(() => {
124
+ return w(e);
125
+ }, [w, E]), i(() => {
119
126
  let e = window.__breadcrumbRegistry;
120
- if (e) return e.register("oauth", T("devportal.nav.oauth", "OAuth Clients")), e.register("api-keys", T("devportal.nav.apiKeys", "API Keys")), () => {
127
+ if (e) return e.register("oauth", E("devportal.nav.oauth", "OAuth Clients")), e.register("api-keys", E("devportal.nav.apiKeys", "API Keys")), () => {
121
128
  e.unregister("oauth"), e.unregister("api-keys");
122
129
  };
123
- }, [T]);
124
- let D = b();
125
- return i(() => (r(D), () => r(null)), [D]), /* @__PURE__ */ v(a, {
126
- fallback: /* @__PURE__ */ v("div", {
130
+ }, [E]);
131
+ let O = x();
132
+ return i(() => (r(O), () => r(null)), [O]), /* @__PURE__ */ y(a, {
133
+ fallback: /* @__PURE__ */ y("div", {
127
134
  className: "p-6 text-center text-text-secondary",
128
- children: T("devportal.error.moduleLoadFailed", "Something went wrong loading this module. Please refresh the page.")
135
+ children: E("devportal.error.moduleLoadFailed", "Something went wrong loading this module. Please refresh the page.")
129
136
  }),
130
- children: /* @__PURE__ */ v(y, {
137
+ children: /* @__PURE__ */ y(b, {
131
138
  workspaceId: null,
132
139
  gateway: "global",
133
140
  defaultEnabled: !0,
134
- children: /* @__PURE__ */ v(e, {
135
- ...x,
136
- children: /* @__PURE__ */ v(n, {})
141
+ children: /* @__PURE__ */ y(e, {
142
+ ...S,
143
+ children: /* @__PURE__ */ y(n, {})
137
144
  })
138
145
  })
139
146
  });
140
147
  };
141
- export { x as DevportalRoot };
148
+ export { S as DevportalRoot };
142
149
 
143
150
  //# sourceMappingURL=DevportalRoot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DevportalRoot.js","names":["DevportalRoot","props","tr","useTr","joinPath","base","path","useEffect","registerNavItems","devportalNavItem","basePath","Code2","LayoutDashboard","Building2","AppWindow","Shield","Key","Webhook","BarChart3","DollarSign","BookOpen","Wrench","Settings","registerFooterItems","footerItems","reg","sharedBus","useEventBus","setDevportalEventBusBridge","ErrorBoundary","FeatureFlagProvider","DevportalProvider","DevportalRoutes"],"sources":["../../src/devportal/DevportalRoot.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect } from \"react\";\nimport { ErrorBoundary } from \"@burdenoff/fe-libs/shared/components\";\nimport {\n Code2,\n LayoutDashboard,\n Building2,\n AppWindow,\n BookOpen,\n Settings,\n Webhook,\n Key,\n Shield,\n BarChart3,\n DollarSign,\n Wrench,\n} from \"lucide-react\";\nimport { DevportalProvider } from \"./providers/DevportalProvider\";\nimport { FeatureFlagProvider } from \"@burdenoff/fe-libs/shared/feature-flags\";\nimport { useEventBus } from \"@burdenoff/fe-libs/shared/events\";\nimport { useTr } from \"./utils/i18n\";\nimport type { NavItem, DevportalRootProps } from \"./types\";\nimport { DevportalRoutes } from \"./DevportalRoutes\";\nimport { setDevportalEventBusBridge } from \"./events\";\n\n/**\n * Root component for the Developer Portal microfrontend.\n *\n * This is the main entry point that host applications import and render.\n * It sets up the necessary providers and renders the internal routing.\n * Automatically registers navigation items with the shell if registration functions are provided.\n *\n * @example\n * ```tsx\n * import { DevportalRoot, type DevportalRootProps } from '@burdenoff/microfe-devportal';\n *\n * function App() {\n * const props: DevportalRootProps = {\n * basePath: '/devportal',\n * navigate: (path) => router.push(path),\n * currentUser: { id: '1', email: 'user@example.com' },\n * tenantId: 'tenant-123',\n * apiGatewayUrl: 'https://api.example.com',\n * authToken: 'token',\n * };\n *\n * return <DevportalRoot {...props} />;\n * }\n * ```\n */\nexport const DevportalRoot: FC<DevportalRootProps> = (props) => {\n const { registerNavItems, registerFooterItems, basePath = \"/\" } = props;\n const tr = useTr();\n\n // Helper to join paths correctly, avoiding double slashes\n const joinPath = (base: string, path: string): string => {\n const cleanBase = base.endsWith(\"/\") ? base.slice(0, -1) : base;\n const cleanPath = path.startsWith(\"/\") ? path : `/${path}`;\n return cleanBase + cleanPath;\n };\n\n // Register navigation items with the shell\n useEffect(() => {\n if (!registerNavItems) return;\n\n // Create a parent \"Developer Portal\" item with children for dropdown behavior\n const devportalNavItem: NavItem = {\n id: \"devportal\",\n label: tr(\"devportal.developerPortal\", \"Developer Portal\"),\n path: basePath,\n icon: <Code2 size={20} />,\n order: 75,\n group: \"global\",\n children: [\n {\n id: \"devportal-dashboard\",\n label: tr(\"devportal.dashboard\", \"Dashboard\"),\n path: basePath,\n icon: <LayoutDashboard size={16} />,\n order: 10,\n },\n {\n id: \"devportal-organizations\",\n label: tr(\"devportal.organizations\", \"Organizations\"),\n path: joinPath(basePath, \"organizations\"),\n icon: <Building2 size={16} />,\n order: 20,\n },\n {\n id: \"devportal-apps\",\n label: tr(\"devportal.myApps\", \"My Apps\"),\n path: joinPath(basePath, \"apps\"),\n icon: <AppWindow size={16} />,\n order: 30,\n },\n {\n id: \"devportal-oauth\",\n label: tr(\"devportal.oauthClients\", \"OAuth Clients\"),\n path: joinPath(basePath, \"oauth\"),\n icon: <Shield size={16} />,\n order: 40,\n },\n {\n id: \"devportal-api-keys\",\n label: tr(\"devportal.apiKeys\", \"API Keys\"),\n path: joinPath(basePath, \"api-keys\"),\n icon: <Key size={16} />,\n order: 50,\n },\n {\n id: \"devportal-webhooks\",\n label: tr(\"devportal.webhooks\", \"Webhooks\"),\n path: joinPath(basePath, \"webhooks\"),\n icon: <Webhook size={16} />,\n order: 60,\n },\n {\n id: \"devportal-analytics\",\n label: tr(\"devportal.analytics\", \"Analytics\"),\n path: joinPath(basePath, \"analytics\"),\n icon: <BarChart3 size={16} />,\n order: 70,\n },\n {\n id: \"devportal-revenue\",\n label: tr(\"devportal.revenue\", \"Revenue\"),\n path: \"/billing/earnings\",\n icon: <DollarSign size={16} />,\n order: 80,\n },\n {\n id: \"devportal-docs\",\n label: tr(\"devportal.documentation\", \"Documentation\"),\n path: joinPath(basePath, \"docs\"),\n icon: <BookOpen size={16} />,\n order: 90,\n },\n {\n id: \"devportal-resources\",\n label: tr(\"devportal.resources\", \"Resources\"),\n path: joinPath(basePath, \"resources\"),\n icon: <Wrench size={16} />,\n order: 100,\n },\n {\n id: \"devportal-settings\",\n label: tr(\"devportal.settings\", \"Settings\"),\n path: joinPath(basePath, \"settings\"),\n icon: <Settings size={16} />,\n order: 110,\n },\n ],\n };\n\n // Register and get cleanup function\n const cleanup = registerNavItems(devportalNavItem);\n\n // Return cleanup function to unregister on unmount\n return cleanup;\n }, [registerNavItems, basePath, tr]);\n\n // Register footer items\n useEffect(() => {\n if (!registerFooterItems) return;\n\n const footerItems = [\n {\n id: \"devportal-status\",\n label: tr(\"devportal.developerPortalReady\", \"Developer Portal Ready\"),\n type: \"status\" as const,\n order: 10,\n section: \"left\" as const,\n },\n ];\n\n const cleanup = registerFooterItems(footerItems);\n return cleanup;\n }, [registerFooterItems, tr]);\n\n // Register static breadcrumb labels for URL segments that need pretty names.\n // The AutoBreadcrumbs component reads window.__breadcrumbRegistry for all\n // segments (not just UUIDs), so segments like 'oauth' and 'api-keys' get\n // human-readable labels instead of the auto-cased URL segment.\n useEffect(() => {\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n if (!reg) return;\n reg.register(\"oauth\", tr(\"devportal.nav.oauth\", \"OAuth Clients\"));\n reg.register(\"api-keys\", tr(\"devportal.nav.apiKeys\", \"API Keys\"));\n return () => {\n reg.unregister(\"oauth\");\n reg.unregister(\"api-keys\");\n };\n }, [tr]);\n\n // Bridge fe-libs event bus -> devportal event bus so MFE pages can emit\n // domain events (`devportal.app.created`, etc.) and the shell sinks\n // (RybbitSink / BackendAuditSink / OtelBrowserSink) consume them centrally.\n // Per memory rule + spec 47: MFEs must not call Rybbit/OTel/fetch directly.\n const sharedBus = useEventBus();\n useEffect(() => {\n setDevportalEventBusBridge(\n sharedBus as unknown as { emit: (n: string, p: unknown) => void },\n );\n return () => setDevportalEventBusBridge(null);\n }, [sharedBus]);\n\n // NOTE: When running in the shell (workspaces-app), the shell's MultiGatewayProvider\n // already provides an ApolloProvider via GatewayRoute. The devportal uses that context.\n // When running standalone, the main.tsx wraps with DevPortalProvider (ApolloProvider).\n return (\n <ErrorBoundary\n fallback={\n <div className=\"p-6 text-center text-text-secondary\">\n {tr(\n \"devportal.error.moduleLoadFailed\",\n \"Something went wrong loading this module. Please refresh the page.\",\n )}\n </div>\n }\n >\n <FeatureFlagProvider\n workspaceId={null}\n gateway=\"global\"\n defaultEnabled={true}\n >\n <DevportalProvider {...props}>\n <DevportalRoutes />\n </DevportalProvider>\n </FeatureFlagProvider>\n </ErrorBoundary>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"DevportalRoot.js","names":["DevportalRoot","props","tr","useTr","joinPath","base","path","useEffect","registerNavItems","devportalNavItem","basePath","Code2","LayoutDashboard","Building2","AppWindow","Blocks","Shield","Key","Webhook","BarChart3","DollarSign","BookOpen","Wrench","Settings","registerFooterItems","footerItems","reg","sharedBus","useEventBus","setDevportalEventBusBridge","ErrorBoundary","FeatureFlagProvider","DevportalProvider","DevportalRoutes"],"sources":["../../src/devportal/DevportalRoot.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect } from \"react\";\nimport { ErrorBoundary } from \"@burdenoff/fe-libs/shared/components\";\nimport {\n Code2,\n LayoutDashboard,\n Building2,\n AppWindow,\n Blocks,\n BookOpen,\n Settings,\n Webhook,\n Key,\n Shield,\n BarChart3,\n DollarSign,\n Wrench,\n} from \"lucide-react\";\nimport { DevportalProvider } from \"./providers/DevportalProvider\";\nimport { FeatureFlagProvider } from \"@burdenoff/fe-libs/shared/feature-flags\";\nimport { useEventBus } from \"@burdenoff/fe-libs/shared/events\";\nimport { useTr } from \"./utils/i18n\";\nimport type { NavItem, DevportalRootProps } from \"./types\";\nimport { DevportalRoutes } from \"./DevportalRoutes\";\nimport { setDevportalEventBusBridge } from \"./events\";\n\n/**\n * Root component for the Developer Portal microfrontend.\n *\n * This is the main entry point that host applications import and render.\n * It sets up the necessary providers and renders the internal routing.\n * Automatically registers navigation items with the shell if registration functions are provided.\n *\n * @example\n * ```tsx\n * import { DevportalRoot, type DevportalRootProps } from '@burdenoff/microfe-devportal';\n *\n * function App() {\n * const props: DevportalRootProps = {\n * basePath: '/devportal',\n * navigate: (path) => router.push(path),\n * currentUser: { id: '1', email: 'user@example.com' },\n * tenantId: 'tenant-123',\n * apiGatewayUrl: 'https://api.example.com',\n * authToken: 'token',\n * };\n *\n * return <DevportalRoot {...props} />;\n * }\n * ```\n */\nexport const DevportalRoot: FC<DevportalRootProps> = (props) => {\n const { registerNavItems, registerFooterItems, basePath = \"/\" } = props;\n const tr = useTr();\n\n // Helper to join paths correctly, avoiding double slashes\n const joinPath = (base: string, path: string): string => {\n const cleanBase = base.endsWith(\"/\") ? base.slice(0, -1) : base;\n const cleanPath = path.startsWith(\"/\") ? path : `/${path}`;\n return cleanBase + cleanPath;\n };\n\n // Register navigation items with the shell\n useEffect(() => {\n if (!registerNavItems) return;\n\n // Create a parent \"Developer Portal\" item with children for dropdown behavior\n const devportalNavItem: NavItem = {\n id: \"devportal\",\n label: tr(\"devportal.developerPortal\", \"Developer Portal\"),\n path: basePath,\n icon: <Code2 size={20} />,\n order: 75,\n group: \"global\",\n children: [\n {\n id: \"devportal-dashboard\",\n label: tr(\"devportal.dashboard\", \"Dashboard\"),\n path: basePath,\n icon: <LayoutDashboard size={16} />,\n order: 10,\n },\n {\n id: \"devportal-organizations\",\n label: tr(\"devportal.organizations\", \"Organizations\"),\n path: joinPath(basePath, \"organizations\"),\n icon: <Building2 size={16} />,\n order: 20,\n },\n {\n id: \"devportal-apps\",\n label: tr(\"devportal.myApps\", \"My Apps\"),\n path: joinPath(basePath, \"apps\"),\n icon: <AppWindow size={16} />,\n order: 30,\n },\n {\n // TimeCampus applets (BOFF-11005): the third-party applet developer\n // flow for the active workspace.\n id: \"devportal-timecampus-applets\",\n label: tr(\"devportal.nav.timecampusApplets\", \"TimeCampus Applets\"),\n path: joinPath(basePath, \"timecampus-applets\"),\n icon: <Blocks size={16} />,\n order: 35,\n },\n {\n id: \"devportal-oauth\",\n label: tr(\"devportal.oauthClients\", \"OAuth Clients\"),\n path: joinPath(basePath, \"oauth\"),\n icon: <Shield size={16} />,\n order: 40,\n },\n {\n id: \"devportal-api-keys\",\n label: tr(\"devportal.apiKeys\", \"API Keys\"),\n path: joinPath(basePath, \"api-keys\"),\n icon: <Key size={16} />,\n order: 50,\n },\n {\n id: \"devportal-webhooks\",\n label: tr(\"devportal.webhooks\", \"Webhooks\"),\n path: joinPath(basePath, \"webhooks\"),\n icon: <Webhook size={16} />,\n order: 60,\n },\n {\n id: \"devportal-analytics\",\n label: tr(\"devportal.analytics\", \"Analytics\"),\n path: joinPath(basePath, \"analytics\"),\n icon: <BarChart3 size={16} />,\n order: 70,\n },\n {\n id: \"devportal-revenue\",\n label: tr(\"devportal.revenue\", \"Revenue\"),\n path: \"/billing/earnings\",\n icon: <DollarSign size={16} />,\n order: 80,\n },\n {\n id: \"devportal-docs\",\n label: tr(\"devportal.documentation\", \"Documentation\"),\n path: joinPath(basePath, \"docs\"),\n icon: <BookOpen size={16} />,\n order: 90,\n },\n {\n id: \"devportal-resources\",\n label: tr(\"devportal.resources\", \"Resources\"),\n path: joinPath(basePath, \"resources\"),\n icon: <Wrench size={16} />,\n order: 100,\n },\n {\n id: \"devportal-settings\",\n label: tr(\"devportal.settings\", \"Settings\"),\n path: joinPath(basePath, \"settings\"),\n icon: <Settings size={16} />,\n order: 110,\n },\n ],\n };\n\n // Register and get cleanup function\n const cleanup = registerNavItems(devportalNavItem);\n\n // Return cleanup function to unregister on unmount\n return cleanup;\n }, [registerNavItems, basePath, tr]);\n\n // Register footer items\n useEffect(() => {\n if (!registerFooterItems) return;\n\n const footerItems = [\n {\n id: \"devportal-status\",\n label: tr(\"devportal.developerPortalReady\", \"Developer Portal Ready\"),\n type: \"status\" as const,\n order: 10,\n section: \"left\" as const,\n },\n ];\n\n const cleanup = registerFooterItems(footerItems);\n return cleanup;\n }, [registerFooterItems, tr]);\n\n // Register static breadcrumb labels for URL segments that need pretty names.\n // The AutoBreadcrumbs component reads window.__breadcrumbRegistry for all\n // segments (not just UUIDs), so segments like 'oauth' and 'api-keys' get\n // human-readable labels instead of the auto-cased URL segment.\n useEffect(() => {\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n if (!reg) return;\n reg.register(\"oauth\", tr(\"devportal.nav.oauth\", \"OAuth Clients\"));\n reg.register(\"api-keys\", tr(\"devportal.nav.apiKeys\", \"API Keys\"));\n return () => {\n reg.unregister(\"oauth\");\n reg.unregister(\"api-keys\");\n };\n }, [tr]);\n\n // Bridge fe-libs event bus -> devportal event bus so MFE pages can emit\n // domain events (`devportal.app.created`, etc.) and the shell sinks\n // (RybbitSink / BackendAuditSink / OtelBrowserSink) consume them centrally.\n // Per memory rule + spec 47: MFEs must not call Rybbit/OTel/fetch directly.\n const sharedBus = useEventBus();\n useEffect(() => {\n setDevportalEventBusBridge(\n sharedBus as unknown as { emit: (n: string, p: unknown) => void },\n );\n return () => setDevportalEventBusBridge(null);\n }, [sharedBus]);\n\n // NOTE: When running in the shell (workspaces-app), the shell's MultiGatewayProvider\n // already provides an ApolloProvider via GatewayRoute. The devportal uses that context.\n // When running standalone, the main.tsx wraps with DevPortalProvider (ApolloProvider).\n return (\n <ErrorBoundary\n fallback={\n <div className=\"p-6 text-center text-text-secondary\">\n {tr(\n \"devportal.error.moduleLoadFailed\",\n \"Something went wrong loading this module. Please refresh the page.\",\n )}\n </div>\n }\n >\n <FeatureFlagProvider\n workspaceId={null}\n gateway=\"global\"\n defaultEnabled={true}\n >\n <DevportalProvider {...props}>\n <DevportalRoutes />\n </DevportalProvider>\n </FeatureFlagProvider>\n </ErrorBoundary>\n );\n};\n"],"mappings":"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"}