@burdenoff/microfe-botmanor 2026.925.1 → 2026.927.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 +4 -1
- package/dist/botlit/BotmanorRootInner.js +1 -1
- package/dist/botlit/BotmanorRootInner.js.map +1 -1
- package/dist/botlit/store/botlitStore.js +14 -13
- package/dist/botlit/store/botlitStore.js.map +1 -1
- package/dist/botlit/store/renamedKeyStorage.js +15 -0
- package/dist/botlit/store/renamedKeyStorage.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
# microfe-
|
|
1
|
+
# microfe-botmanor
|
|
2
|
+
|
|
3
|
+
BotManor microfrontend (`@burdenoff/microfe-botmanor`). The repo was renamed
|
|
4
|
+
from `microfe-botlit`; GitHub redirects the old name.
|
|
2
5
|
|
|
3
6
|
Part of the [Burdenoff](https://burdenoff.com) platform by
|
|
4
7
|
[AlgoShred](https://github.com/algoshred).
|
|
@@ -11,7 +11,7 @@ import { ErrorBoundary as h } from "@burdenoff/fe-libs/shared/components";
|
|
|
11
11
|
import { FeatureFlagProvider as g } from "@burdenoff/fe-libs/shared/feature-flags";
|
|
12
12
|
import { refetchStoreNodes as _, resetFluidGridsClient as v, resetFluidGridsConfig as y, resetGlobalStoreClient as b, setFluidGridsClient as x, setFluidGridsConfig as S, setGlobalStoreClient as C } from "@burdenoff/fluidgrids-fe-sdk";
|
|
13
13
|
//#region src/botlit/BotmanorRootInner.tsx
|
|
14
|
-
var w = "
|
|
14
|
+
var w = "botmanor", T = "BotManor", E = 1e4, D = 2e3, O = new p({ defaultOptions: { queries: {
|
|
15
15
|
staleTime: 300 * 1e3,
|
|
16
16
|
retry: 1
|
|
17
17
|
} } }), k = (p) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BotmanorRootInner.js","names":[],"sources":["../../src/botlit/BotmanorRootInner.tsx"],"sourcesContent":["/**\n * BotManor Root — implementation\n * @module botlit\n *\n * The heavy half of {@link BotmanorRoot}. Everything that pulls a large\n * dependency graph lives behind this module so the package entry point stays\n * small: `BotmanorRootInner` statically imports `BotlitRoutes`, which in turn\n * pulls the whole `@burdenoff/fluidgrids-fe-sdk` barrel (workflow builder,\n * @xyflow/react, framer-motion …). `BotmanorRoot` loads this module lazily and\n * paints a skeleton meanwhile, so the host never shows an empty content\n * region while that graph downloads.\n */\n\nimport type { FC } from 'react';\nimport { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { ApolloProvider } from '@apollo/client/react';\nimport { ErrorBoundary } from '@burdenoff/fe-libs/shared/components';\nimport { BotlitProvider } from './providers/BotlitProvider';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { BotlitRoutes } from './BotlitRoutes';\nimport { RouteLoader } from './components/RouteLoader';\nimport { WorkspaceRequired } from './components/WorkspaceRequired';\nimport type { BotmanorRootProps } from './types';\n\n// FluidGrids SDK client injection (needed for workflow components)\nimport {\n setFluidGridsClient,\n resetFluidGridsClient,\n setFluidGridsConfig,\n resetFluidGridsConfig,\n setGlobalStoreClient,\n resetGlobalStoreClient,\n refetchStoreNodes,\n type WorkflowSavedResult,\n} from '@burdenoff/fluidgrids-fe-sdk';\n// Use the shared gateway Apollo clients from the shell\nimport { useGatewayClient } from '@burdenoff/fe-libs/shared/graphql';\n\n/** Product identity handed to the FluidGrids SDK when the shell does not override it. */\nconst DEFAULT_PRODUCT_ID = 'botlit';\nconst DEFAULT_PRODUCT_NAME = 'BotManor';\n\n/** How long to wait for the shell's gateway clients before showing an error. */\nconst CLIENT_READY_TIMEOUT_MS = 10_000;\n\n/**\n * How long to keep showing the loading skeleton before concluding that the\n * shell really has no active workspace.\n *\n * The shell resolves org/workspace asynchronously and passes `workspaceId=\"\"`\n * until it lands, which is indistinguishable from \"this user has no\n * workspace\". Without this settle window the guided zero state would flash on\n * every cold load — a get-started screen appearing and vanishing reads as a\n * broken page, which is exactly what this component exists to avoid.\n */\nconst WORKSPACE_SETTLE_MS = 2_000;\n\n// Create a query client for this microfrontend\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 5 * 60 * 1000,\n retry: 1,\n },\n },\n});\n\nexport const BotmanorRootInner: FC<BotmanorRootProps> = (props) => {\n // NOTE: Navigation is now handled by the shell's NavRegistration.tsx\n // The shell manages all product submenu items in a centralized way\n\n // Get shell's Apollo clients (both workspace and global for FluidGrids SDK)\n const workspaceClient = useGatewayClient('workspace');\n const globalClient = useGatewayClient('global');\n const [clientReady, setClientReady] = useState(false);\n const [clientError, setClientError] = useState<string | null>(null);\n const [workspaceSettled, setWorkspaceSettled] = useState(false);\n\n // Inject Apollo clients into FluidGrids SDK (for workflow components).\n // This synchronizes external stores (module-level client singletons in the SDK)\n // with React's lifecycle. The setState call is intentional — it gates rendering\n // so children don't mount before the SDK clients are available.\n //\n // KNOWN TRADE-OFF (mirrors microfe-bigconsole): clientReady is NOT reset in\n // cleanup. When the client references change (e.g. token refresh) children keep\n // rendering against a briefly uninitialised SDK client until the effect re-runs.\n // That avoids a spinner flash mid-session; failed requests are retried by\n // Apollo/React Query.\n useEffect(() => {\n if (workspaceClient && globalClient) {\n setFluidGridsClient(workspaceClient);\n setGlobalStoreClient(globalClient);\n // Node definitions come from the global store — refresh them now that the\n // SDK has a client, otherwise the builder palette stays empty.\n void refetchStoreNodes().catch((error: unknown) => {\n console.warn('[BotManor] Failed to refresh FluidGrids store nodes', error);\n });\n setClientReady(true);\n }\n return () => {\n resetFluidGridsClient();\n resetGlobalStoreClient();\n };\n }, [workspaceClient, globalClient]);\n\n // Timeout fallback: if gateway clients are never provided (test env, shell\n // misconfiguration, auth failure before hydration), show an error rather than\n // spinning indefinitely.\n useEffect(() => {\n if (clientReady) return;\n const timer = setTimeout(() => {\n setClientError(\n 'BotManor could not connect to the gateway. Please refresh the page or check your configuration.'\n );\n }, CLIENT_READY_TIMEOUT_MS);\n return () => clearTimeout(timer);\n }, [clientReady]);\n\n // Give the shell a bounded window to resolve the active workspace before the\n // guided zero state is allowed to render. Cancelled the moment a workspace\n // arrives — a workspace that is already present never starts the timer.\n useEffect(() => {\n if (props.workspaceId) return;\n const timer = setTimeout(() => setWorkspaceSettled(true), WORKSPACE_SETTLE_MS);\n return () => clearTimeout(timer);\n }, [props.workspaceId]);\n\n // Hook point for syncing a saved workflow back into BotManor. BotManor keeps no\n // separate workflow record (unlike BigConsole), so there is nothing to write —\n // the bridge exists so a future sync can be added without re-initialising the SDK.\n const handleWorkflowSaved = useCallback((result: WorkflowSavedResult) => {\n if (import.meta.env.DEV) {\n console.info('[BotManor] Workflow saved', result.workflowKey, result.operation);\n }\n }, []);\n\n // Ref-forwarding: decouple the callback from the SDK config effect so that\n // workspaceClient reference changes don't trigger resetFluidGridsConfig() + re-init.\n const handleWorkflowSavedRef = useRef(handleWorkflowSaved);\n useLayoutEffect(() => {\n handleWorkflowSavedRef.current = handleWorkflowSaved;\n }, [handleWorkflowSaved]);\n\n // Configure FluidGrids SDK settings\n useEffect(() => {\n if (!props.apiGatewayUrl) return;\n\n const normalizedBase = props.apiGatewayUrl.endsWith('/')\n ? props.apiGatewayUrl.slice(0, -1)\n : props.apiGatewayUrl;\n\n setFluidGridsConfig({\n apiGatewayUrl: normalizedBase,\n authToken: props.authToken,\n workspaceId: props.workspaceId ?? '',\n tenantId: props.tenantId,\n // The SDK filters workflows by productId. It MUST be this product — falling\n // back to the shell's default ('workspaces') would leak another product's\n // workflows into BotManor.\n productId: props.productId ?? DEFAULT_PRODUCT_ID,\n productName: props.productName ?? DEFAULT_PRODUCT_NAME,\n // Stable wrapper via ref — avoids SDK re-init when workspaceClient changes reference\n onWorkflowSaved: (result: WorkflowSavedResult) => handleWorkflowSavedRef.current(result),\n });\n\n return () => {\n resetFluidGridsConfig();\n };\n }, [\n props.apiGatewayUrl,\n props.authToken,\n props.workspaceId,\n props.tenantId,\n props.productId,\n props.productName,\n ]);\n\n // Without a workspace every BotManor query is unscoped and every write is\n // rejected — guide the user instead of rendering empty lists. Until the\n // settle window elapses we cannot tell \"still resolving\" from \"none\", so we\n // keep the same skeleton the shell was already showing.\n if (!props.workspaceId) {\n if (!workspaceSettled) {\n return <RouteLoader label=\"Loading your workspace…\" />;\n }\n return <WorkspaceRequired basePath={props.basePath} navigate={props.navigate} />;\n }\n\n // Don't render until clients are ready (same pattern as microfe-bigconsole)\n if (!clientReady) {\n if (clientError) {\n return (\n <div className=\"flex h-full min-h-[200px] w-full items-center justify-center p-6\">\n <div className=\"text-center\">\n <p className=\"mb-4 text-sm text-text-secondary\">{clientError}</p>\n <button\n type=\"button\"\n onClick={() => window.location.reload()}\n className=\"rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover\"\n >\n Reload Page\n </button>\n </div>\n </div>\n );\n }\n // Same skeleton as the lazy-chunk fallback, so the content region never\n // switches loading idioms between first paint and the page rendering.\n return <RouteLoader />;\n }\n\n const isIntegrated = !!props.basePath;\n\n const content = (\n <BotlitProvider {...props}>\n <BotlitRoutes />\n </BotlitProvider>\n );\n\n return (\n <ErrorBoundary\n fallback={\n <div className=\"p-6 text-center text-text-secondary\">\n Something went wrong loading BotManor. Please refresh the page.\n </div>\n }\n >\n <FeatureFlagProvider workspaceId={null} gateway=\"global\" defaultEnabled={true}>\n <QueryClientProvider client={queryClient}>\n {isIntegrated ? (\n content\n ) : (\n <ApolloProvider client={workspaceClient}>{content}</ApolloProvider>\n )}\n </QueryClientProvider>\n </FeatureFlagProvider>\n </ErrorBoundary>\n );\n};\n"],"mappings":";;;;;;;;;;;;;AAwCA,IAAM,IAAqB,UACrB,IAAuB,YAGvB,IAA0B,KAY1B,IAAsB,KAGtB,IAAc,IAAI,EAAY,EAClC,gBAAgB,EACd,SAAS;CACP,WAAW,MAAS;CACpB,OAAO;CACR,EACF,EACF,CAAC,EAEW,KAA4C,MAAU;CAKjE,IAAM,IAAkB,EAAiB,YAAY,EAC/C,IAAe,EAAiB,SAAS,EACzC,CAAC,GAAa,KAAkB,EAAS,GAAM,EAC/C,CAAC,GAAa,KAAkB,EAAwB,KAAK,EAC7D,CAAC,GAAkB,KAAuB,EAAS,GAAM;AA6C/D,CAjCA,SACM,KAAmB,MACrB,EAAoB,EAAgB,EACpC,EAAqB,EAAa,EAG7B,GAAmB,CAAC,OAAO,MAAmB;AACjD,UAAQ,KAAK,uDAAuD,EAAM;GAC1E,EACF,EAAe,GAAK,SAET;AAEX,EADA,GAAuB,EACvB,GAAwB;KAEzB,CAAC,GAAiB,EAAa,CAAC,EAKnC,QAAgB;AACd,MAAI,EAAa;EACjB,IAAM,IAAQ,iBAAiB;AAC7B,KACE,kGACD;KACA,EAAwB;AAC3B,eAAa,aAAa,EAAM;IAC/B,CAAC,EAAY,CAAC,EAKjB,QAAgB;AACd,MAAI,EAAM,YAAa;EACvB,IAAM,IAAQ,iBAAiB,EAAoB,GAAK,EAAE,EAAoB;AAC9E,eAAa,aAAa,EAAM;IAC/B,CAAC,EAAM,YAAY,CAAC;CAKvB,IAAM,IAAsB,GAAa,MAAgC,IAItE,EAAE,CAAC,EAIA,IAAyB,EAAO,EAAoB;AA2C1D,KA1CA,QAAsB;AACpB,IAAuB,UAAU;IAChC,CAAC,EAAoB,CAAC,EAGzB,QAAgB;AACT,QAAM,cAoBX,QAdA,EAAoB;GAClB,eALqB,EAAM,cAAc,SAAS,IAAI,GACpD,EAAM,cAAc,MAAM,GAAG,GAAG,GAChC,EAAM;GAIR,WAAW,EAAM;GACjB,aAAa,EAAM,eAAe;GAClC,UAAU,EAAM;GAIhB,WAAW,EAAM,aAAa;GAC9B,aAAa,EAAM,eAAe;GAElC,kBAAkB,MAAgC,EAAuB,QAAQ,EAAO;GACzF,CAAC,QAEW;AACX,MAAuB;;IAExB;EACD,EAAM;EACN,EAAM;EACN,EAAM;EACN,EAAM;EACN,EAAM;EACN,EAAM;EACP,CAAC,EAME,CAAC,EAAM,YAIT,QAHK,IAGE,kBAAC,GAAD;EAAmB,UAAU,EAAM;EAAU,UAAU,EAAM;EAAY,CAAA,GAFvE,kBAAC,GAAD,EAAa,OAAM,2BAA4B,CAAA;AAM1D,KAAI,CAAC,EAmBH,QAlBI,IAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAAoC;IAAgB,CAAA,EACjE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,OAAO,SAAS,QAAQ;IACvC,WAAU;cACX;IAEQ,CAAA,CACL;;EACF,CAAA,GAKH,kBAAC,GAAD,EAAe,CAAA;CAGxB,IAAM,IAAe,CAAC,CAAC,EAAM,UAEvB,IACJ,kBAAC,GAAD;EAAgB,GAAI;YAClB,kBAAC,GAAD,EAAgB,CAAA;EACD,CAAA;AAGnB,QACE,kBAAC,GAAD;EACE,UACE,kBAAC,OAAD;GAAK,WAAU;aAAsC;GAE/C,CAAA;YAGR,kBAAC,GAAD;GAAqB,aAAa;GAAM,SAAQ;GAAS,gBAAgB;aACvE,kBAAC,GAAD;IAAqB,QAAQ;cAC1B,IACC,IAEA,kBAAC,GAAD;KAAgB,QAAQ;eAAkB;KAAyB,CAAA;IAEjD,CAAA;GACF,CAAA;EACR,CAAA"}
|
|
1
|
+
{"version":3,"file":"BotmanorRootInner.js","names":[],"sources":["../../src/botlit/BotmanorRootInner.tsx"],"sourcesContent":["/**\n * BotManor Root — implementation\n * @module botlit\n *\n * The heavy half of {@link BotmanorRoot}. Everything that pulls a large\n * dependency graph lives behind this module so the package entry point stays\n * small: `BotmanorRootInner` statically imports `BotlitRoutes`, which in turn\n * pulls the whole `@burdenoff/fluidgrids-fe-sdk` barrel (workflow builder,\n * @xyflow/react, framer-motion …). `BotmanorRoot` loads this module lazily and\n * paints a skeleton meanwhile, so the host never shows an empty content\n * region while that graph downloads.\n */\n\nimport type { FC } from 'react';\nimport { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { ApolloProvider } from '@apollo/client/react';\nimport { ErrorBoundary } from '@burdenoff/fe-libs/shared/components';\nimport { BotlitProvider } from './providers/BotlitProvider';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { BotlitRoutes } from './BotlitRoutes';\nimport { RouteLoader } from './components/RouteLoader';\nimport { WorkspaceRequired } from './components/WorkspaceRequired';\nimport type { BotmanorRootProps } from './types';\n\n// FluidGrids SDK client injection (needed for workflow components)\nimport {\n setFluidGridsClient,\n resetFluidGridsClient,\n setFluidGridsConfig,\n resetFluidGridsConfig,\n setGlobalStoreClient,\n resetGlobalStoreClient,\n refetchStoreNodes,\n type WorkflowSavedResult,\n} from '@burdenoff/fluidgrids-fe-sdk';\n// Use the shared gateway Apollo clients from the shell\nimport { useGatewayClient } from '@burdenoff/fe-libs/shared/graphql';\n\n/**\n * Product identity handed to the FluidGrids SDK when the shell does not override it.\n * `botmanor` since the Botlit -> BotManor rename's Stage 5a; workflow\n * definitions stored under the legacy `botlit` were migrated, and the workflow\n * service matches either slug.\n */\nconst DEFAULT_PRODUCT_ID = 'botmanor';\nconst DEFAULT_PRODUCT_NAME = 'BotManor';\n\n/** How long to wait for the shell's gateway clients before showing an error. */\nconst CLIENT_READY_TIMEOUT_MS = 10_000;\n\n/**\n * How long to keep showing the loading skeleton before concluding that the\n * shell really has no active workspace.\n *\n * The shell resolves org/workspace asynchronously and passes `workspaceId=\"\"`\n * until it lands, which is indistinguishable from \"this user has no\n * workspace\". Without this settle window the guided zero state would flash on\n * every cold load — a get-started screen appearing and vanishing reads as a\n * broken page, which is exactly what this component exists to avoid.\n */\nconst WORKSPACE_SETTLE_MS = 2_000;\n\n// Create a query client for this microfrontend\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 5 * 60 * 1000,\n retry: 1,\n },\n },\n});\n\nexport const BotmanorRootInner: FC<BotmanorRootProps> = (props) => {\n // NOTE: Navigation is now handled by the shell's NavRegistration.tsx\n // The shell manages all product submenu items in a centralized way\n\n // Get shell's Apollo clients (both workspace and global for FluidGrids SDK)\n const workspaceClient = useGatewayClient('workspace');\n const globalClient = useGatewayClient('global');\n const [clientReady, setClientReady] = useState(false);\n const [clientError, setClientError] = useState<string | null>(null);\n const [workspaceSettled, setWorkspaceSettled] = useState(false);\n\n // Inject Apollo clients into FluidGrids SDK (for workflow components).\n // This synchronizes external stores (module-level client singletons in the SDK)\n // with React's lifecycle. The setState call is intentional — it gates rendering\n // so children don't mount before the SDK clients are available.\n //\n // KNOWN TRADE-OFF (mirrors microfe-bigconsole): clientReady is NOT reset in\n // cleanup. When the client references change (e.g. token refresh) children keep\n // rendering against a briefly uninitialised SDK client until the effect re-runs.\n // That avoids a spinner flash mid-session; failed requests are retried by\n // Apollo/React Query.\n useEffect(() => {\n if (workspaceClient && globalClient) {\n setFluidGridsClient(workspaceClient);\n setGlobalStoreClient(globalClient);\n // Node definitions come from the global store — refresh them now that the\n // SDK has a client, otherwise the builder palette stays empty.\n void refetchStoreNodes().catch((error: unknown) => {\n console.warn('[BotManor] Failed to refresh FluidGrids store nodes', error);\n });\n setClientReady(true);\n }\n return () => {\n resetFluidGridsClient();\n resetGlobalStoreClient();\n };\n }, [workspaceClient, globalClient]);\n\n // Timeout fallback: if gateway clients are never provided (test env, shell\n // misconfiguration, auth failure before hydration), show an error rather than\n // spinning indefinitely.\n useEffect(() => {\n if (clientReady) return;\n const timer = setTimeout(() => {\n setClientError(\n 'BotManor could not connect to the gateway. Please refresh the page or check your configuration.'\n );\n }, CLIENT_READY_TIMEOUT_MS);\n return () => clearTimeout(timer);\n }, [clientReady]);\n\n // Give the shell a bounded window to resolve the active workspace before the\n // guided zero state is allowed to render. Cancelled the moment a workspace\n // arrives — a workspace that is already present never starts the timer.\n useEffect(() => {\n if (props.workspaceId) return;\n const timer = setTimeout(() => setWorkspaceSettled(true), WORKSPACE_SETTLE_MS);\n return () => clearTimeout(timer);\n }, [props.workspaceId]);\n\n // Hook point for syncing a saved workflow back into BotManor. BotManor keeps no\n // separate workflow record (unlike BigConsole), so there is nothing to write —\n // the bridge exists so a future sync can be added without re-initialising the SDK.\n const handleWorkflowSaved = useCallback((result: WorkflowSavedResult) => {\n if (import.meta.env.DEV) {\n console.info('[BotManor] Workflow saved', result.workflowKey, result.operation);\n }\n }, []);\n\n // Ref-forwarding: decouple the callback from the SDK config effect so that\n // workspaceClient reference changes don't trigger resetFluidGridsConfig() + re-init.\n const handleWorkflowSavedRef = useRef(handleWorkflowSaved);\n useLayoutEffect(() => {\n handleWorkflowSavedRef.current = handleWorkflowSaved;\n }, [handleWorkflowSaved]);\n\n // Configure FluidGrids SDK settings\n useEffect(() => {\n if (!props.apiGatewayUrl) return;\n\n const normalizedBase = props.apiGatewayUrl.endsWith('/')\n ? props.apiGatewayUrl.slice(0, -1)\n : props.apiGatewayUrl;\n\n setFluidGridsConfig({\n apiGatewayUrl: normalizedBase,\n authToken: props.authToken,\n workspaceId: props.workspaceId ?? '',\n tenantId: props.tenantId,\n // The SDK filters workflows by productId. It MUST be this product — falling\n // back to the shell's default ('workspaces') would leak another product's\n // workflows into BotManor.\n productId: props.productId ?? DEFAULT_PRODUCT_ID,\n productName: props.productName ?? DEFAULT_PRODUCT_NAME,\n // Stable wrapper via ref — avoids SDK re-init when workspaceClient changes reference\n onWorkflowSaved: (result: WorkflowSavedResult) => handleWorkflowSavedRef.current(result),\n });\n\n return () => {\n resetFluidGridsConfig();\n };\n }, [\n props.apiGatewayUrl,\n props.authToken,\n props.workspaceId,\n props.tenantId,\n props.productId,\n props.productName,\n ]);\n\n // Without a workspace every BotManor query is unscoped and every write is\n // rejected — guide the user instead of rendering empty lists. Until the\n // settle window elapses we cannot tell \"still resolving\" from \"none\", so we\n // keep the same skeleton the shell was already showing.\n if (!props.workspaceId) {\n if (!workspaceSettled) {\n return <RouteLoader label=\"Loading your workspace…\" />;\n }\n return <WorkspaceRequired basePath={props.basePath} navigate={props.navigate} />;\n }\n\n // Don't render until clients are ready (same pattern as microfe-bigconsole)\n if (!clientReady) {\n if (clientError) {\n return (\n <div className=\"flex h-full min-h-[200px] w-full items-center justify-center p-6\">\n <div className=\"text-center\">\n <p className=\"mb-4 text-sm text-text-secondary\">{clientError}</p>\n <button\n type=\"button\"\n onClick={() => window.location.reload()}\n className=\"rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover\"\n >\n Reload Page\n </button>\n </div>\n </div>\n );\n }\n // Same skeleton as the lazy-chunk fallback, so the content region never\n // switches loading idioms between first paint and the page rendering.\n return <RouteLoader />;\n }\n\n const isIntegrated = !!props.basePath;\n\n const content = (\n <BotlitProvider {...props}>\n <BotlitRoutes />\n </BotlitProvider>\n );\n\n return (\n <ErrorBoundary\n fallback={\n <div className=\"p-6 text-center text-text-secondary\">\n Something went wrong loading BotManor. Please refresh the page.\n </div>\n }\n >\n <FeatureFlagProvider workspaceId={null} gateway=\"global\" defaultEnabled={true}>\n <QueryClientProvider client={queryClient}>\n {isIntegrated ? (\n content\n ) : (\n <ApolloProvider client={workspaceClient}>{content}</ApolloProvider>\n )}\n </QueryClientProvider>\n </FeatureFlagProvider>\n </ErrorBoundary>\n );\n};\n"],"mappings":";;;;;;;;;;;;;AA6CA,IAAM,IAAqB,YACrB,IAAuB,YAGvB,IAA0B,KAY1B,IAAsB,KAGtB,IAAc,IAAI,EAAY,EAClC,gBAAgB,EACd,SAAS;CACP,WAAW,MAAS;CACpB,OAAO;CACR,EACF,EACF,CAAC,EAEW,KAA4C,MAAU;CAKjE,IAAM,IAAkB,EAAiB,YAAY,EAC/C,IAAe,EAAiB,SAAS,EACzC,CAAC,GAAa,KAAkB,EAAS,GAAM,EAC/C,CAAC,GAAa,KAAkB,EAAwB,KAAK,EAC7D,CAAC,GAAkB,KAAuB,EAAS,GAAM;AA6C/D,CAjCA,SACM,KAAmB,MACrB,EAAoB,EAAgB,EACpC,EAAqB,EAAa,EAG7B,GAAmB,CAAC,OAAO,MAAmB;AACjD,UAAQ,KAAK,uDAAuD,EAAM;GAC1E,EACF,EAAe,GAAK,SAET;AAEX,EADA,GAAuB,EACvB,GAAwB;KAEzB,CAAC,GAAiB,EAAa,CAAC,EAKnC,QAAgB;AACd,MAAI,EAAa;EACjB,IAAM,IAAQ,iBAAiB;AAC7B,KACE,kGACD;KACA,EAAwB;AAC3B,eAAa,aAAa,EAAM;IAC/B,CAAC,EAAY,CAAC,EAKjB,QAAgB;AACd,MAAI,EAAM,YAAa;EACvB,IAAM,IAAQ,iBAAiB,EAAoB,GAAK,EAAE,EAAoB;AAC9E,eAAa,aAAa,EAAM;IAC/B,CAAC,EAAM,YAAY,CAAC;CAKvB,IAAM,IAAsB,GAAa,MAAgC,IAItE,EAAE,CAAC,EAIA,IAAyB,EAAO,EAAoB;AA2C1D,KA1CA,QAAsB;AACpB,IAAuB,UAAU;IAChC,CAAC,EAAoB,CAAC,EAGzB,QAAgB;AACT,QAAM,cAoBX,QAdA,EAAoB;GAClB,eALqB,EAAM,cAAc,SAAS,IAAI,GACpD,EAAM,cAAc,MAAM,GAAG,GAAG,GAChC,EAAM;GAIR,WAAW,EAAM;GACjB,aAAa,EAAM,eAAe;GAClC,UAAU,EAAM;GAIhB,WAAW,EAAM,aAAa;GAC9B,aAAa,EAAM,eAAe;GAElC,kBAAkB,MAAgC,EAAuB,QAAQ,EAAO;GACzF,CAAC,QAEW;AACX,MAAuB;;IAExB;EACD,EAAM;EACN,EAAM;EACN,EAAM;EACN,EAAM;EACN,EAAM;EACN,EAAM;EACP,CAAC,EAME,CAAC,EAAM,YAIT,QAHK,IAGE,kBAAC,GAAD;EAAmB,UAAU,EAAM;EAAU,UAAU,EAAM;EAAY,CAAA,GAFvE,kBAAC,GAAD,EAAa,OAAM,2BAA4B,CAAA;AAM1D,KAAI,CAAC,EAmBH,QAlBI,IAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAAoC;IAAgB,CAAA,EACjE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,OAAO,SAAS,QAAQ;IACvC,WAAU;cACX;IAEQ,CAAA,CACL;;EACF,CAAA,GAKH,kBAAC,GAAD,EAAe,CAAA;CAGxB,IAAM,IAAe,CAAC,CAAC,EAAM,UAEvB,IACJ,kBAAC,GAAD;EAAgB,GAAI;YAClB,kBAAC,GAAD,EAAgB,CAAA;EACD,CAAA;AAGnB,QACE,kBAAC,GAAD;EACE,UACE,kBAAC,OAAD;GAAK,WAAU;aAAsC;GAE/C,CAAA;YAGR,kBAAC,GAAD;GAAqB,aAAa;GAAM,SAAQ;GAAS,gBAAgB;aACvE,kBAAC,GAAD;IAAqB,QAAQ;cAC1B,IACC,IAEA,kBAAC,GAAD;KAAgB,QAAQ;eAAkB;KAAyB,CAAA;IAEjD,CAAA;GACF,CAAA;EACR,CAAA"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { withRenamedKey as e } from "./renamedKeyStorage.js";
|
|
2
|
+
import { create as t } from "zustand";
|
|
3
|
+
import { devtools as n, persist as r } from "zustand/middleware";
|
|
4
|
+
import { createProfileScopedStorage as i } from "@burdenoff/fe-libs/shared/utils";
|
|
4
5
|
//#region src/botlit/store/botlitStore.ts
|
|
5
|
-
var
|
|
6
|
+
var a = {
|
|
6
7
|
viewMode: "grid",
|
|
7
8
|
sidebarCollapsed: !1,
|
|
8
9
|
activeTab: "bots",
|
|
@@ -40,8 +41,8 @@ var i = {
|
|
|
40
41
|
recentBots: [],
|
|
41
42
|
recentAgents: [],
|
|
42
43
|
recentConversations: []
|
|
43
|
-
},
|
|
44
|
-
...
|
|
44
|
+
}, o = t()(n(r((e) => ({
|
|
45
|
+
...a,
|
|
45
46
|
setViewMode: (t) => e({ viewMode: t }),
|
|
46
47
|
toggleSidebar: () => e((e) => ({ sidebarCollapsed: !e.sidebarCollapsed })),
|
|
47
48
|
setActiveTab: (t) => e({ activeTab: t }),
|
|
@@ -62,9 +63,9 @@ var i = {
|
|
|
62
63
|
...t
|
|
63
64
|
} })),
|
|
64
65
|
resetFilters: () => e({
|
|
65
|
-
botFilter:
|
|
66
|
-
agentFilter:
|
|
67
|
-
conversationFilter:
|
|
66
|
+
botFilter: a.botFilter,
|
|
67
|
+
agentFilter: a.agentFilter,
|
|
68
|
+
conversationFilter: a.conversationFilter
|
|
68
69
|
}),
|
|
69
70
|
setIsCreatingBot: (t) => e({ isCreatingBot: t }),
|
|
70
71
|
setIsCreatingAgent: (t) => e({ isCreatingAgent: t }),
|
|
@@ -80,10 +81,10 @@ var i = {
|
|
|
80
81
|
addRecentBot: (t) => e((e) => ({ recentBots: [t, ...e.recentBots.filter((e) => e !== t)].slice(0, 10) })),
|
|
81
82
|
addRecentAgent: (t) => e((e) => ({ recentAgents: [t, ...e.recentAgents.filter((e) => e !== t)].slice(0, 10) })),
|
|
82
83
|
addRecentConversation: (t) => e((e) => ({ recentConversations: [t, ...e.recentConversations.filter((e) => e !== t)].slice(0, 10) })),
|
|
83
|
-
reset: () => e(
|
|
84
|
+
reset: () => e(a)
|
|
84
85
|
}), {
|
|
85
|
-
name: "burdenoff-
|
|
86
|
-
storage:
|
|
86
|
+
name: "burdenoff-botmanor-storage",
|
|
87
|
+
storage: e(i(), "burdenoff-botlit-storage"),
|
|
87
88
|
partialize: (e) => ({
|
|
88
89
|
viewMode: e.viewMode,
|
|
89
90
|
sidebarCollapsed: e.sidebarCollapsed,
|
|
@@ -96,6 +97,6 @@ var i = {
|
|
|
96
97
|
enabled: !1
|
|
97
98
|
}));
|
|
98
99
|
//#endregion
|
|
99
|
-
export {
|
|
100
|
+
export { o as useBotlitStore };
|
|
100
101
|
|
|
101
102
|
//# sourceMappingURL=botlitStore.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"botlitStore.js","names":[],"sources":["../../../src/botlit/store/botlitStore.ts"],"sourcesContent":["/**\n * BotManor Zustand Store\n * @module botlit/store\n */\n\nimport { create } from 'zustand';\nimport { devtools, persist } from 'zustand/middleware';\nimport { createProfileScopedStorage } from '@burdenoff/fe-libs/shared/utils';\nimport type {\n BotSummary,\n AgentSummary,\n KnowledgeBaseSummary,\n Conversation,\n ViewMode,\n BotFilter,\n AgentFilter,\n BaseFilter,\n} from '../types';\n\n// ConversationFilter extends BaseFilter with conversation-specific fields\ninterface ConversationFilter extends BaseFilter {\n botId?: string;\n agentId?: string;\n}\n\n// ============================================================================\n// State Interface\n// ============================================================================\n\ninterface BotlitState {\n // View state\n viewMode: ViewMode;\n sidebarCollapsed: boolean;\n activeTab: string;\n\n // Selected entities\n selectedBot: BotSummary | null;\n selectedAgent: AgentSummary | null;\n selectedKnowledgeBase: KnowledgeBaseSummary | null;\n selectedConversation: Conversation | null;\n\n // Filters\n botFilter: BotFilter;\n agentFilter: AgentFilter;\n conversationFilter: ConversationFilter;\n\n // UI State\n isCreatingBot: boolean;\n isCreatingAgent: boolean;\n isUploadingDocument: boolean;\n isChatOpen: boolean;\n chatAgentId: string | null;\n\n // Recent items\n recentBots: string[];\n recentAgents: string[];\n recentConversations: string[];\n\n // Actions\n setViewMode: (mode: ViewMode) => void;\n toggleSidebar: () => void;\n setActiveTab: (tab: string) => void;\n\n setSelectedBot: (bot: BotSummary | null) => void;\n setSelectedAgent: (agent: AgentSummary | null) => void;\n setSelectedKnowledgeBase: (kb: KnowledgeBaseSummary | null) => void;\n setSelectedConversation: (conversation: Conversation | null) => void;\n\n updateBotFilter: (filter: Partial<BotFilter>) => void;\n updateAgentFilter: (filter: Partial<AgentFilter>) => void;\n updateConversationFilter: (filter: Partial<ConversationFilter>) => void;\n resetFilters: () => void;\n\n setIsCreatingBot: (value: boolean) => void;\n setIsCreatingAgent: (value: boolean) => void;\n setIsUploadingDocument: (value: boolean) => void;\n openChat: (agentId: string) => void;\n closeChat: () => void;\n\n addRecentBot: (botId: string) => void;\n addRecentAgent: (agentId: string) => void;\n addRecentConversation: (conversationId: string) => void;\n\n reset: () => void;\n}\n\n// ============================================================================\n// Initial State\n// ============================================================================\n\nconst initialState = {\n viewMode: 'grid' as ViewMode,\n sidebarCollapsed: false,\n activeTab: 'bots',\n\n selectedBot: null,\n selectedAgent: null,\n selectedKnowledgeBase: null,\n selectedConversation: null,\n\n botFilter: {\n search: '',\n status: undefined,\n sortBy: 'updatedAt' as const,\n sortOrder: 'desc' as const,\n },\n agentFilter: {\n search: '',\n appId: undefined,\n type: undefined,\n status: undefined,\n sortBy: 'updatedAt' as const,\n sortOrder: 'desc' as const,\n },\n conversationFilter: {\n search: '',\n botId: undefined,\n agentId: undefined,\n status: undefined,\n sortBy: 'updatedAt' as const,\n sortOrder: 'desc' as const,\n },\n\n isCreatingBot: false,\n isCreatingAgent: false,\n isUploadingDocument: false,\n isChatOpen: false,\n chatAgentId: null,\n\n recentBots: [] as string[],\n recentAgents: [] as string[],\n recentConversations: [] as string[],\n};\n\n// ============================================================================\n// Store\n// ============================================================================\n\nexport const useBotlitStore = create<BotlitState>()(\n devtools(\n persist(\n (set) => ({\n ...initialState,\n\n // View actions\n setViewMode: (mode) => set({ viewMode: mode }),\n toggleSidebar: () => set((state) => ({ sidebarCollapsed: !state.sidebarCollapsed })),\n setActiveTab: (tab) => set({ activeTab: tab }),\n\n // Selection actions\n setSelectedBot: (bot) => set({ selectedBot: bot }),\n setSelectedAgent: (agent) => set({ selectedAgent: agent }),\n setSelectedKnowledgeBase: (kb) => set({ selectedKnowledgeBase: kb }),\n setSelectedConversation: (conversation) => set({ selectedConversation: conversation }),\n\n // Filter actions\n updateBotFilter: (filter) =>\n set((state) => ({\n botFilter: { ...state.botFilter, ...filter },\n })),\n updateAgentFilter: (filter) =>\n set((state) => ({\n agentFilter: { ...state.agentFilter, ...filter },\n })),\n updateConversationFilter: (filter) =>\n set((state) => ({\n conversationFilter: { ...state.conversationFilter, ...filter },\n })),\n resetFilters: () =>\n set({\n botFilter: initialState.botFilter,\n agentFilter: initialState.agentFilter,\n conversationFilter: initialState.conversationFilter,\n }),\n\n // UI state actions\n setIsCreatingBot: (value) => set({ isCreatingBot: value }),\n setIsCreatingAgent: (value) => set({ isCreatingAgent: value }),\n setIsUploadingDocument: (value) => set({ isUploadingDocument: value }),\n openChat: (agentId) => set({ isChatOpen: true, chatAgentId: agentId }),\n closeChat: () => set({ isChatOpen: false, chatAgentId: null }),\n\n // Recent items actions\n addRecentBot: (botId) =>\n set((state) => ({\n recentBots: [botId, ...state.recentBots.filter((id) => id !== botId)].slice(0, 10),\n })),\n addRecentAgent: (agentId) =>\n set((state) => ({\n recentAgents: [agentId, ...state.recentAgents.filter((id) => id !== agentId)].slice(\n 0,\n 10\n ),\n })),\n addRecentConversation: (conversationId) =>\n set((state) => ({\n recentConversations: [\n conversationId,\n ...state.recentConversations.filter((id) => id !== conversationId),\n ].slice(0, 10),\n })),\n\n // Reset\n reset: () => set(initialState),\n }),\n {\n name: 'burdenoff-
|
|
1
|
+
{"version":3,"file":"botlitStore.js","names":[],"sources":["../../../src/botlit/store/botlitStore.ts"],"sourcesContent":["/**\n * BotManor Zustand Store\n * @module botlit/store\n */\n\nimport { create } from 'zustand';\nimport { devtools, persist } from 'zustand/middleware';\nimport { createProfileScopedStorage } from '@burdenoff/fe-libs/shared/utils';\nimport { withRenamedKey } from './renamedKeyStorage';\nimport type {\n BotSummary,\n AgentSummary,\n KnowledgeBaseSummary,\n Conversation,\n ViewMode,\n BotFilter,\n AgentFilter,\n BaseFilter,\n} from '../types';\n\n// ConversationFilter extends BaseFilter with conversation-specific fields\ninterface ConversationFilter extends BaseFilter {\n botId?: string;\n agentId?: string;\n}\n\n// ============================================================================\n// State Interface\n// ============================================================================\n\ninterface BotlitState {\n // View state\n viewMode: ViewMode;\n sidebarCollapsed: boolean;\n activeTab: string;\n\n // Selected entities\n selectedBot: BotSummary | null;\n selectedAgent: AgentSummary | null;\n selectedKnowledgeBase: KnowledgeBaseSummary | null;\n selectedConversation: Conversation | null;\n\n // Filters\n botFilter: BotFilter;\n agentFilter: AgentFilter;\n conversationFilter: ConversationFilter;\n\n // UI State\n isCreatingBot: boolean;\n isCreatingAgent: boolean;\n isUploadingDocument: boolean;\n isChatOpen: boolean;\n chatAgentId: string | null;\n\n // Recent items\n recentBots: string[];\n recentAgents: string[];\n recentConversations: string[];\n\n // Actions\n setViewMode: (mode: ViewMode) => void;\n toggleSidebar: () => void;\n setActiveTab: (tab: string) => void;\n\n setSelectedBot: (bot: BotSummary | null) => void;\n setSelectedAgent: (agent: AgentSummary | null) => void;\n setSelectedKnowledgeBase: (kb: KnowledgeBaseSummary | null) => void;\n setSelectedConversation: (conversation: Conversation | null) => void;\n\n updateBotFilter: (filter: Partial<BotFilter>) => void;\n updateAgentFilter: (filter: Partial<AgentFilter>) => void;\n updateConversationFilter: (filter: Partial<ConversationFilter>) => void;\n resetFilters: () => void;\n\n setIsCreatingBot: (value: boolean) => void;\n setIsCreatingAgent: (value: boolean) => void;\n setIsUploadingDocument: (value: boolean) => void;\n openChat: (agentId: string) => void;\n closeChat: () => void;\n\n addRecentBot: (botId: string) => void;\n addRecentAgent: (agentId: string) => void;\n addRecentConversation: (conversationId: string) => void;\n\n reset: () => void;\n}\n\n// ============================================================================\n// Initial State\n// ============================================================================\n\nconst initialState = {\n viewMode: 'grid' as ViewMode,\n sidebarCollapsed: false,\n activeTab: 'bots',\n\n selectedBot: null,\n selectedAgent: null,\n selectedKnowledgeBase: null,\n selectedConversation: null,\n\n botFilter: {\n search: '',\n status: undefined,\n sortBy: 'updatedAt' as const,\n sortOrder: 'desc' as const,\n },\n agentFilter: {\n search: '',\n appId: undefined,\n type: undefined,\n status: undefined,\n sortBy: 'updatedAt' as const,\n sortOrder: 'desc' as const,\n },\n conversationFilter: {\n search: '',\n botId: undefined,\n agentId: undefined,\n status: undefined,\n sortBy: 'updatedAt' as const,\n sortOrder: 'desc' as const,\n },\n\n isCreatingBot: false,\n isCreatingAgent: false,\n isUploadingDocument: false,\n isChatOpen: false,\n chatAgentId: null,\n\n recentBots: [] as string[],\n recentAgents: [] as string[],\n recentConversations: [] as string[],\n};\n\n// ============================================================================\n// Store\n// ============================================================================\n\nexport const useBotlitStore = create<BotlitState>()(\n devtools(\n persist(\n (set) => ({\n ...initialState,\n\n // View actions\n setViewMode: (mode) => set({ viewMode: mode }),\n toggleSidebar: () => set((state) => ({ sidebarCollapsed: !state.sidebarCollapsed })),\n setActiveTab: (tab) => set({ activeTab: tab }),\n\n // Selection actions\n setSelectedBot: (bot) => set({ selectedBot: bot }),\n setSelectedAgent: (agent) => set({ selectedAgent: agent }),\n setSelectedKnowledgeBase: (kb) => set({ selectedKnowledgeBase: kb }),\n setSelectedConversation: (conversation) => set({ selectedConversation: conversation }),\n\n // Filter actions\n updateBotFilter: (filter) =>\n set((state) => ({\n botFilter: { ...state.botFilter, ...filter },\n })),\n updateAgentFilter: (filter) =>\n set((state) => ({\n agentFilter: { ...state.agentFilter, ...filter },\n })),\n updateConversationFilter: (filter) =>\n set((state) => ({\n conversationFilter: { ...state.conversationFilter, ...filter },\n })),\n resetFilters: () =>\n set({\n botFilter: initialState.botFilter,\n agentFilter: initialState.agentFilter,\n conversationFilter: initialState.conversationFilter,\n }),\n\n // UI state actions\n setIsCreatingBot: (value) => set({ isCreatingBot: value }),\n setIsCreatingAgent: (value) => set({ isCreatingAgent: value }),\n setIsUploadingDocument: (value) => set({ isUploadingDocument: value }),\n openChat: (agentId) => set({ isChatOpen: true, chatAgentId: agentId }),\n closeChat: () => set({ isChatOpen: false, chatAgentId: null }),\n\n // Recent items actions\n addRecentBot: (botId) =>\n set((state) => ({\n recentBots: [botId, ...state.recentBots.filter((id) => id !== botId)].slice(0, 10),\n })),\n addRecentAgent: (agentId) =>\n set((state) => ({\n recentAgents: [agentId, ...state.recentAgents.filter((id) => id !== agentId)].slice(\n 0,\n 10\n ),\n })),\n addRecentConversation: (conversationId) =>\n set((state) => ({\n recentConversations: [\n conversationId,\n ...state.recentConversations.filter((id) => id !== conversationId),\n ].slice(0, 10),\n })),\n\n // Reset\n reset: () => set(initialState),\n }),\n {\n name: 'burdenoff-botmanor-storage',\n // Renamed from the Botlit-era key; saved UI state moves over on first load.\n storage: withRenamedKey(createProfileScopedStorage(), 'burdenoff-botlit-storage'),\n partialize: (state) => ({\n viewMode: state.viewMode,\n sidebarCollapsed: state.sidebarCollapsed,\n recentBots: state.recentBots,\n recentAgents: state.recentAgents,\n recentConversations: state.recentConversations,\n }),\n }\n ),\n { name: 'BotManor Store', enabled: import.meta.env?.DEV === true }\n )\n);\n"],"mappings":";;;;;AA2FA,IAAM,IAAe;CACnB,UAAU;CACV,kBAAkB;CAClB,WAAW;CAEX,aAAa;CACb,eAAe;CACf,uBAAuB;CACvB,sBAAsB;CAEtB,WAAW;EACT,QAAQ;EACR,QAAQ,KAAA;EACR,QAAQ;EACR,WAAW;EACZ;CACD,aAAa;EACX,QAAQ;EACR,OAAO,KAAA;EACP,MAAM,KAAA;EACN,QAAQ,KAAA;EACR,QAAQ;EACR,WAAW;EACZ;CACD,oBAAoB;EAClB,QAAQ;EACR,OAAO,KAAA;EACP,SAAS,KAAA;EACT,QAAQ,KAAA;EACR,QAAQ;EACR,WAAW;EACZ;CAED,eAAe;CACf,iBAAiB;CACjB,qBAAqB;CACrB,YAAY;CACZ,aAAa;CAEb,YAAY,EAAE;CACd,cAAc,EAAE;CAChB,qBAAqB,EAAE;CACxB,EAMY,IAAiB,GAAqB,CACjD,EACE,GACG,OAAS;CACR,GAAG;CAGH,cAAc,MAAS,EAAI,EAAE,UAAU,GAAM,CAAC;CAC9C,qBAAqB,GAAK,OAAW,EAAE,kBAAkB,CAAC,EAAM,kBAAkB,EAAE;CACpF,eAAe,MAAQ,EAAI,EAAE,WAAW,GAAK,CAAC;CAG9C,iBAAiB,MAAQ,EAAI,EAAE,aAAa,GAAK,CAAC;CAClD,mBAAmB,MAAU,EAAI,EAAE,eAAe,GAAO,CAAC;CAC1D,2BAA2B,MAAO,EAAI,EAAE,uBAAuB,GAAI,CAAC;CACpE,0BAA0B,MAAiB,EAAI,EAAE,sBAAsB,GAAc,CAAC;CAGtF,kBAAkB,MAChB,GAAK,OAAW,EACd,WAAW;EAAE,GAAG,EAAM;EAAW,GAAG;EAAQ,EAC7C,EAAE;CACL,oBAAoB,MAClB,GAAK,OAAW,EACd,aAAa;EAAE,GAAG,EAAM;EAAa,GAAG;EAAQ,EACjD,EAAE;CACL,2BAA2B,MACzB,GAAK,OAAW,EACd,oBAAoB;EAAE,GAAG,EAAM;EAAoB,GAAG;EAAQ,EAC/D,EAAE;CACL,oBACE,EAAI;EACF,WAAW,EAAa;EACxB,aAAa,EAAa;EAC1B,oBAAoB,EAAa;EAClC,CAAC;CAGJ,mBAAmB,MAAU,EAAI,EAAE,eAAe,GAAO,CAAC;CAC1D,qBAAqB,MAAU,EAAI,EAAE,iBAAiB,GAAO,CAAC;CAC9D,yBAAyB,MAAU,EAAI,EAAE,qBAAqB,GAAO,CAAC;CACtE,WAAW,MAAY,EAAI;EAAE,YAAY;EAAM,aAAa;EAAS,CAAC;CACtE,iBAAiB,EAAI;EAAE,YAAY;EAAO,aAAa;EAAM,CAAC;CAG9D,eAAe,MACb,GAAK,OAAW,EACd,YAAY,CAAC,GAAO,GAAG,EAAM,WAAW,QAAQ,MAAO,MAAO,EAAM,CAAC,CAAC,MAAM,GAAG,GAAG,EACnF,EAAE;CACL,iBAAiB,MACf,GAAK,OAAW,EACd,cAAc,CAAC,GAAS,GAAG,EAAM,aAAa,QAAQ,MAAO,MAAO,EAAQ,CAAC,CAAC,MAC5E,GACA,GACD,EACF,EAAE;CACL,wBAAwB,MACtB,GAAK,OAAW,EACd,qBAAqB,CACnB,GACA,GAAG,EAAM,oBAAoB,QAAQ,MAAO,MAAO,EAAe,CACnE,CAAC,MAAM,GAAG,GAAG,EACf,EAAE;CAGL,aAAa,EAAI,EAAa;CAC/B,GACD;CACE,MAAM;CAEN,SAAS,EAAe,GAA4B,EAAE,2BAA2B;CACjF,aAAa,OAAW;EACtB,UAAU,EAAM;EAChB,kBAAkB,EAAM;EACxB,YAAY,EAAM;EAClB,cAAc,EAAM;EACpB,qBAAqB,EAAM;EAC5B;CACF,CACF,EACD;CAAE,MAAM;CAAkB,SAAS;CAA+B,CACnE,CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/botlit/store/renamedKeyStorage.ts
|
|
2
|
+
function e(e, t) {
|
|
3
|
+
return e instanceof Promise ? e.then(t) : t(e);
|
|
4
|
+
}
|
|
5
|
+
function t(t, n) {
|
|
6
|
+
return t && {
|
|
7
|
+
getItem: (r) => e(t.getItem(r), (i) => i !== null || r === n ? i : e(t.getItem(n), (i) => i === null ? null : e(t.setItem(r, i), () => e(t.removeItem(n), () => i)))),
|
|
8
|
+
setItem: (e, n) => t.setItem(e, n),
|
|
9
|
+
removeItem: (r) => e(t.removeItem(r), () => r === n ? void 0 : t.removeItem(n))
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { t as withRenamedKey };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=renamedKeyStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renamedKeyStorage.js","names":[],"sources":["../../../src/botlit/store/renamedKeyStorage.ts"],"sourcesContent":["/**\n * Zustand persist storage that moves a store's saved state from a renamed key.\n * @module botlit/store/renamedKeyStorage\n */\n\nimport type { PersistStorage, StorageValue } from 'zustand/middleware';\n\ntype MaybePromise<T> = T | Promise<T>;\n\nfunction then<T, R>(value: MaybePromise<T>, fn: (resolved: T) => MaybePromise<R>): MaybePromise<R> {\n return value instanceof Promise ? value.then(fn) : fn(value);\n}\n\n/**\n * Wrap a persist storage so a store renamed from `legacyName` keeps its\n * saved state. On a read that finds nothing under the new name, the value\n * under `legacyName` is copied to the new name and the legacy entry is\n * removed, so the move happens once, on first load. Writes and removals go\n * to the new name only (removals also clear any legacy leftover).\n *\n * Used for the Botlit -> BotManor rename (`burdenoff-botlit-storage` ->\n * `burdenoff-botmanor-storage`); the wrapped storage keeps its own profile\n * scoping, so each profile's entry moves independently.\n */\nexport function withRenamedKey<S>(\n inner: PersistStorage<S> | undefined,\n legacyName: string\n): PersistStorage<S> | undefined {\n if (!inner) return inner;\n return {\n getItem: (name) =>\n then(inner.getItem(name), (current): MaybePromise<StorageValue<S> | null> => {\n if (current !== null || name === legacyName) return current;\n return then(inner.getItem(legacyName), (legacy) => {\n if (legacy === null) return null;\n return then(inner.setItem(name, legacy), () =>\n then(inner.removeItem(legacyName), () => legacy)\n );\n });\n }),\n setItem: (name, value) => inner.setItem(name, value),\n removeItem: (name) =>\n then(inner.removeItem(name), () =>\n name === legacyName ? undefined : inner.removeItem(legacyName)\n ),\n };\n}\n"],"mappings":";AASA,SAAS,EAAW,GAAwB,GAAuD;AACjG,QAAO,aAAiB,UAAU,EAAM,KAAK,EAAG,GAAG,EAAG,EAAM;;AAc9D,SAAgB,EACd,GACA,GAC+B;AAE/B,QADK,KACE;EACL,UAAU,MACR,EAAK,EAAM,QAAQ,EAAK,GAAG,MACrB,MAAY,QAAQ,MAAS,IAAmB,IAC7C,EAAK,EAAM,QAAQ,EAAW,GAAG,MAClC,MAAW,OAAa,OACrB,EAAK,EAAM,QAAQ,GAAM,EAAO,QACrC,EAAK,EAAM,WAAW,EAAW,QAAQ,EAAO,CACjD,CACD,CACF;EACJ,UAAU,GAAM,MAAU,EAAM,QAAQ,GAAM,EAAM;EACpD,aAAa,MACX,EAAK,EAAM,WAAW,EAAK,QACzB,MAAS,IAAa,KAAA,IAAY,EAAM,WAAW,EAAW,CAC/D;EACJ"}
|
package/package.json
CHANGED