@hachej/boring-core 0.1.51 → 0.1.53

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.
@@ -57,7 +57,7 @@ interface CoreWorkspaceAgentFrontProps<TSession extends WorkspaceAgentSession =
57
57
  /** Default top-bar right content. Exported so apps can compose extra widgets
58
58
  * (e.g. a credit balance badge) alongside the user menu. */
59
59
  declare function DefaultTopBarRight(): react_jsx_runtime.JSX.Element;
60
- declare function CoreWorkspaceAgentFront<TSession extends WorkspaceAgentSession = WorkspaceAgentSession>({ authPages, cspNonce, children, workspaceRoute, workspaceIdParam, workspaceHref, loadingFallback, bootPreloadPaths, topBarLeft, topBarRight, appTitle, bridgeEndpoint, hotReload, chatEntryMode, chatFirstPublicShell, chatFirstPublicWorkspaceProps, publicPaths, ...workspaceProps }: CoreWorkspaceAgentFrontProps<TSession>): react_jsx_runtime.JSX.Element;
60
+ declare function CoreWorkspaceAgentFront<TSession extends WorkspaceAgentSession = WorkspaceAgentSession>({ authPages, cspNonce, children, workspaceRoute, workspaceIdParam, workspaceHref, loadingFallback, bootPreloadPaths, topBarLeft, topBarRight, appTitle, bridgeEndpoint, fullPageBasePath, hotReload, chatEntryMode, chatFirstPublicShell, chatFirstPublicWorkspaceProps, publicPaths, ...workspaceProps }: CoreWorkspaceAgentFrontProps<TSession>): react_jsx_runtime.JSX.Element;
61
61
 
62
62
  interface CreditBalanceBadgeProps {
63
63
  /** Base URL for the credits API (default: same origin). */
@@ -9,7 +9,7 @@ import {
9
9
  useSignIn,
10
10
  useSignUp,
11
11
  useWorkspaceRouteStatus
12
- } from "../../chunk-2ZTKRLVG.js";
12
+ } from "../../chunk-Q53N4QUK.js";
13
13
  import "../../chunk-HYNKZSTF.js";
14
14
  import {
15
15
  isRuntimeEmailVerificationEnabled
@@ -20,8 +20,13 @@ import "../../chunk-MLKGABMK.js";
20
20
  // src/app/front/CoreWorkspaceAgentFront.tsx
21
21
  import { useEffect as useEffect3, useMemo, useState as useState3 } from "react";
22
22
  import { Navigate, Route, useLocation as useLocation2, useParams } from "react-router-dom";
23
+ import { WorkspaceProvider } from "@hachej/boring-workspace";
24
+ import { ErrorState } from "@hachej/boring-ui-kit";
23
25
  import {
24
- WorkspaceAgentFront as WorkspaceAgentFront2
26
+ parseFullPagePanelLocation,
27
+ WorkspaceAgentFront as WorkspaceAgentFront2,
28
+ WorkspaceBootGate,
29
+ WorkspaceFullPagePanel
25
30
  } from "@hachej/boring-workspace/app/front";
26
31
 
27
32
  // src/app/front/chatFirst/ChatFirstAuthenticatedShell.tsx
@@ -503,6 +508,7 @@ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-run
503
508
  installVitePreloadRecovery();
504
509
  var DEFAULT_WORKSPACE_ROUTE = "/workspace/:id";
505
510
  var DEFAULT_WORKSPACE_ID_PARAM = "id";
511
+ var DEFAULT_FULL_PAGE_BASE_PATH = "/full-page";
506
512
  function DefaultTopBarRight() {
507
513
  return /* @__PURE__ */ jsx5(UserMenu, {});
508
514
  }
@@ -689,6 +695,10 @@ function WorkspaceRoute({
689
695
  () => ({ ...resolvedWorkspaceProps.authHeaders, "x-boring-workspace-id": workspaceId }),
690
696
  [workspaceId, resolvedWorkspaceProps.authHeaders]
691
697
  );
698
+ const scopedFullPageBasePath = useMemo(
699
+ () => resolvedWorkspaceProps.fullPageBasePath ? withWorkspaceIdSearch(resolvedWorkspaceProps.fullPageBasePath, workspaceId) : void 0,
700
+ [resolvedWorkspaceProps.fullPageBasePath, workspaceId]
701
+ );
692
702
  if (!workspaceId) return /* @__PURE__ */ jsx5(Fragment3, { children: resolvedLoadingFallback });
693
703
  if (!session.data?.user && chatEntryMode === "chat-first") {
694
704
  return /* @__PURE__ */ jsx5(
@@ -736,6 +746,7 @@ function WorkspaceRoute({
736
746
  workspaceLabel: resolvedWorkspaceProps.workspaceLabel ?? currentWorkspace.name,
737
747
  requestHeaders,
738
748
  authHeaders,
749
+ fullPageBasePath: scopedFullPageBasePath,
739
750
  chatParams,
740
751
  bootPreloadPaths,
741
752
  frontPluginHotReload: false,
@@ -745,6 +756,110 @@ function WorkspaceRoute({
745
756
  workspaceId
746
757
  );
747
758
  }
759
+ function fullPageRoutePath(basePath) {
760
+ const path = basePath.split(/[?#]/, 1)[0]?.trim();
761
+ return path || DEFAULT_FULL_PAGE_BASE_PATH;
762
+ }
763
+ function workspaceIdFromFullPageSearch(search) {
764
+ const workspaceId = new URLSearchParams(search).get("workspaceId")?.trim();
765
+ return workspaceId || null;
766
+ }
767
+ function withWorkspaceIdSearch(basePath, workspaceId) {
768
+ const [pathWithSearch, hash = ""] = basePath.split("#", 2);
769
+ const [path, rawSearch = ""] = pathWithSearch.split("?", 2);
770
+ const search = new URLSearchParams(rawSearch);
771
+ search.set("workspaceId", workspaceId);
772
+ return `${path}?${search.toString()}${hash ? `#${hash}` : ""}`;
773
+ }
774
+ function scopedWorkspaceHeaders(workspaceId, headers) {
775
+ return { ...headers ?? {}, "x-boring-workspace-id": workspaceId };
776
+ }
777
+ function FullPageRouteErrorPage({ code, title, description }) {
778
+ return /* @__PURE__ */ jsx5(
779
+ "div",
780
+ {
781
+ className: "flex min-h-screen items-center justify-center bg-background p-6 text-foreground",
782
+ "data-testid": "full-page-error-state",
783
+ "data-full-page-error-code": code,
784
+ children: /* @__PURE__ */ jsx5(ErrorState, { className: "w-full max-w-lg", title, description })
785
+ }
786
+ );
787
+ }
788
+ function CoreFullPagePanelRoute({
789
+ fullPageBasePath,
790
+ loadingFallback,
791
+ bootPreloadPaths,
792
+ workspaceProps,
793
+ appTitle
794
+ }) {
795
+ const location = useLocation2();
796
+ const parsed = useMemo(() => parseFullPagePanelLocation(location.search), [location.search]);
797
+ const currentWorkspace = useCurrentWorkspace();
798
+ const workspaceId = workspaceIdFromFullPageSearch(location.search) ?? currentWorkspace?.id ?? "";
799
+ const scopedFullPageBasePath = workspaceId ? withWorkspaceIdSearch(fullPageBasePath, workspaceId) : fullPageBasePath;
800
+ const requestHeaders = workspaceId ? scopedWorkspaceHeaders(workspaceId, workspaceProps.requestHeaders) : workspaceProps.requestHeaders;
801
+ const authHeaders = workspaceId ? scopedWorkspaceHeaders(workspaceId, { ...workspaceProps.requestHeaders ?? {}, ...workspaceProps.authHeaders ?? {} }) : { ...workspaceProps.requestHeaders ?? {}, ...workspaceProps.authHeaders ?? {} };
802
+ if (parsed.error || !parsed.componentId) {
803
+ return /* @__PURE__ */ jsx5(
804
+ FullPageRouteErrorPage,
805
+ {
806
+ code: parsed.error?.code ?? "FULL_PAGE_PANEL_MISSING_COMPONENT",
807
+ title: "Invalid full-page panel route",
808
+ description: parsed.error?.message ?? "Missing full-page panel component id."
809
+ }
810
+ );
811
+ }
812
+ if (!workspaceId) {
813
+ return /* @__PURE__ */ jsx5(Fragment3, { children: loadingFallback ?? /* @__PURE__ */ jsx5(
814
+ FullPageRouteErrorPage,
815
+ {
816
+ code: "FULL_PAGE_PANEL_MISSING_WORKSPACE",
817
+ title: "Workspace unavailable",
818
+ description: "The full-page panel route needs a workspace id. Open it from a workspace or include workspaceId in the URL."
819
+ }
820
+ ) });
821
+ }
822
+ return /* @__PURE__ */ jsx5(
823
+ WorkspaceProvider,
824
+ {
825
+ chatPanel: workspaceProps.chatPanel,
826
+ plugins: workspaceProps.plugins,
827
+ excludeDefaults: workspaceProps.excludeDefaults,
828
+ panels: workspaceProps.panels,
829
+ commands: workspaceProps.commands,
830
+ catalogs: workspaceProps.catalogs,
831
+ capabilities: workspaceProps.capabilities,
832
+ apiBaseUrl: workspaceProps.apiBaseUrl,
833
+ authHeaders,
834
+ apiTimeout: workspaceProps.apiTimeout,
835
+ defaultTheme: workspaceProps.defaultTheme,
836
+ onThemeChange: workspaceProps.onThemeChange,
837
+ workspaceId,
838
+ workspaceLabel: currentWorkspace?.id === workspaceId ? currentWorkspace.name : workspaceProps.workspaceLabel,
839
+ appTitle,
840
+ storageKey: workspaceProps.providerStorageKey ?? `boring-ui-v2:layout:${workspaceId}`,
841
+ persistenceEnabled: workspaceProps.persistenceEnabled,
842
+ manageDocumentTitle: false,
843
+ bridgeEndpoint: null,
844
+ onAuthError: workspaceProps.onAuthError,
845
+ onOpenFile: workspaceProps.onOpenFile,
846
+ debug: workspaceProps.debug,
847
+ frontPluginHotReload: false,
848
+ fullPageBasePath: scopedFullPageBasePath,
849
+ children: /* @__PURE__ */ jsx5(
850
+ WorkspaceBootGate,
851
+ {
852
+ workspaceId,
853
+ requestHeaders,
854
+ apiBaseUrl: workspaceProps.apiBaseUrl,
855
+ preloadPaths: bootPreloadPaths,
856
+ provisionWorkspace: workspaceProps.provisionWorkspace,
857
+ children: /* @__PURE__ */ jsx5(WorkspaceFullPagePanel, { componentId: parsed.componentId, params: parsed.params })
858
+ }
859
+ )
860
+ }
861
+ );
862
+ }
748
863
  function chatFirstPublicPaths(workspaceRoute) {
749
864
  return Array.from(/* @__PURE__ */ new Set(["/", workspaceRoute, "/workspace/:id", "/w/:id"]));
750
865
  }
@@ -761,6 +876,7 @@ function CoreWorkspaceAgentFront({
761
876
  topBarRight = /* @__PURE__ */ jsx5(DefaultTopBarRight, {}),
762
877
  appTitle,
763
878
  bridgeEndpoint = "/api/v1/ui",
879
+ fullPageBasePath = DEFAULT_FULL_PAGE_BASE_PATH,
764
880
  hotReload = false,
765
881
  chatEntryMode = "auth-first",
766
882
  chatFirstPublicShell,
@@ -775,7 +891,8 @@ function CoreWorkspaceAgentFront({
775
891
  }
776
892
  const routedWorkspaceProps = {
777
893
  ...workspaceProps,
778
- bridgeEndpoint
894
+ bridgeEndpoint,
895
+ fullPageBasePath
779
896
  };
780
897
  return /* @__PURE__ */ jsxs4(
781
898
  CoreFront,
@@ -828,6 +945,22 @@ function CoreWorkspaceAgentFront({
828
945
  )
829
946
  }
830
947
  ),
948
+ /* @__PURE__ */ jsx5(
949
+ Route,
950
+ {
951
+ path: fullPageRoutePath(fullPageBasePath),
952
+ element: /* @__PURE__ */ jsx5(
953
+ CoreFullPagePanelRoute,
954
+ {
955
+ fullPageBasePath,
956
+ loadingFallback,
957
+ bootPreloadPaths,
958
+ workspaceProps: routedWorkspaceProps,
959
+ appTitle
960
+ }
961
+ )
962
+ }
963
+ ),
831
964
  children
832
965
  ]
833
966
  }
@@ -1463,15 +1463,25 @@ function SettingsTopBar() {
1463
1463
  className: "relative flex h-[52px] items-center justify-between gap-3 border-b border-border/40 bg-background px-4",
1464
1464
  "aria-label": "App top bar",
1465
1465
  children: /* @__PURE__ */ jsxs6("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: [
1466
- /* @__PURE__ */ jsx13(
1467
- "div",
1466
+ /* @__PURE__ */ jsxs6(
1467
+ "a",
1468
1468
  {
1469
- "aria-hidden": "true",
1470
- className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background",
1471
- children: appInitial
1469
+ href: "/",
1470
+ "aria-label": `${appTitle} home`,
1471
+ className: "flex min-w-0 items-center gap-2.5 rounded-md outline-none transition-opacity hover:opacity-80 focus-visible:ring-2 focus-visible:ring-ring",
1472
+ children: [
1473
+ /* @__PURE__ */ jsx13(
1474
+ "div",
1475
+ {
1476
+ "aria-hidden": "true",
1477
+ className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background",
1478
+ children: appInitial
1479
+ }
1480
+ ),
1481
+ /* @__PURE__ */ jsx13("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: appTitle })
1482
+ ]
1472
1483
  }
1473
1484
  ),
1474
- /* @__PURE__ */ jsx13("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: appTitle }),
1475
1485
  /* @__PURE__ */ jsx13("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
1476
1486
  /* @__PURE__ */ jsx13("span", { className: "truncate text-[13px] text-muted-foreground", children: "Account settings" })
1477
1487
  ] })
@@ -58,7 +58,7 @@ import {
58
58
  useWorkspaceMembers,
59
59
  useWorkspaceRole,
60
60
  useWorkspaceRouteStatus
61
- } from "../chunk-2ZTKRLVG.js";
61
+ } from "../chunk-Q53N4QUK.js";
62
62
  import {
63
63
  TopBarSlotProvider,
64
64
  useTopBarSlot
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hachej/boring-core",
3
- "version": "0.1.51",
3
+ "version": "0.1.53",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Foundation package for boring-ui-v2 apps: DB, auth, config, HTTP app factory, and frontend app shell.",
@@ -79,9 +79,9 @@
79
79
  "react-router-dom": "^7.14.2",
80
80
  "smol-toml": "^1.6.1",
81
81
  "zod": "^3.25.76",
82
- "@hachej/boring-agent": "0.1.51",
83
- "@hachej/boring-ui-kit": "0.1.51",
84
- "@hachej/boring-workspace": "0.1.51"
82
+ "@hachej/boring-agent": "0.1.53",
83
+ "@hachej/boring-workspace": "0.1.53",
84
+ "@hachej/boring-ui-kit": "0.1.53"
85
85
  },
86
86
  "devDependencies": {
87
87
  "@testing-library/jest-dom": "^6.9.1",