LobeChat uses Namespace for action labels in DevTools configuration

Ramu NarasingaRamu Narasinga
3 min read

In this article, we will look at how the action labels use Namespace in LobeChat devtools. I want to provide a bit of an introduction to the terms such action labels, devtools and how/why they come into the picture.

LobeChat uses Zustand for its state management and has DevTools configured for debugging purposes. When you see DevTools configured, you will have action labels for the Zustand.

What is action label?

In the set, you will have to provide action label, otherwise this action appears as anonymous in your Redux DevTools.

Example from the documentation

addFish: () => set((state) => ({ fishes: state.fishes + 1 }),
 undefined,
 'jungle/addFish',
 ),

Action name here is a string.

How does LobeChat configure its action label?

Let’s pick this example found in Session Slice action.

switchSession: (sessionId) => {
 if (get().activeId === sessionId) return;

 set({ activeId: sessionId }, false, n(`activeSession/${sessionId}`));
},

Action name here is a function named n. What’s this n function? n is a function returned by a function named setNamespace at line 31.

const n = setNamespace('session');

setNamespace is imported from storeDebug.ts and has the below code:

export const setNamespace = (namespace: string) => {

  return (type: string, payload?: any) => {
   const name = [namespace, type].filter(Boolean).join('/');
     return payload
       ? {
       payload,
       type: name,
     } : name;
   };
};

This returns an arrow function that has two parameters:

  • type: string

  • payload?: any

This below line is interesting.

const name = [namespace, type].filter(Boolean).join('/');

I have never seen this before — applying filter with Boolean. If you were to execute this in your browser’s console using some strings as shown below:

["session", true].filter(Boolean).join('/')

["session", "true"].filter(Boolean).join('/')

["session", "true"].filter(Boolean).join('/')

["session", "switchSession/true/id-123"].filter(Boolean).join('/')

["session", "switchSession/id-123"].filter(Boolean).join('/')

When you paste the above code in the browser’s console, you will find the results shown as in this screenshot below

I asked ChatGPT to explain this line of code and it has to say this about it:

The line [namespace, type].filter(Boolean).join('/') is used to build a string representing the action name for Zustand's store configuration in LobeChat. Let’s break it down and address why filter(Boolean) is used.

Code Breakdown

[namespace, type]:

This creates an array containing two values: namespace and type.

namespace is likely a string representing a broader category or module.

type represents the specific action within that namespace, e.g., activeSession.

.filter(Boolean):

Filters out any falsy values (e.g., undefined, null, false, or an empty string) from the array.

This ensures the resulting string only includes valid components.

If namespace is not provided (e.g., namespace is undefined or ''), it will not be included in the final string.

.join('/'):

Joins the remaining array elements with a / separator to create a namespaced action name, e.g., namespace/type or just type if namespace is absent.

If the payload exists, an object is returned:

return payload
       ? {
       payload,
       type: name,
     } : name;
   };

Below example is from global/action.ts

toggleChatSideBar: (newValue) => {
    const showChatSideBar =
      typeof newValue === 'boolean' ? newValue : !get().status.showChatSideBar;

    get().updateSystemStatus({ showChatSideBar }, n('toggleAgentPanel', newValue));
},

Conclusion here is action name can be an object or a string.

About me:

Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.

I am open to work on an interesting project. Send me an email at ramu.narasinga@gmail.com

My Github - https://github.com/ramu-narasinga My website - https://ramunarasinga.com My Youtube channel - https://www.youtube.com/@thinkthroo Learning platform - https://thinkthroo.com Codebase Architecture - https://app.thinkthroo.com/architecture Best practices - https://app.thinkthroo.com/best-practices Production-grade projects - https://app.thinkthroo.com/production-grade-projects

References:

  1. https://github.com/lobehub/lobe-chat/blob/main/src/store/session/slices/session/action.ts#L31C1-L31C35

  2. https://github.com/lobehub/lobe-chat/blob/main/src/utils/storeDebug.ts#L1

  3. https://zustand.docs.pmnd.rs/middlewares/devtools#debugging-a-store

  4. https://zustand.docs.pmnd.rs/middlewares/devtools#all-action-names-are-labeled-as-'anonymous'

0
Subscribe to my newsletter

Read articles from Ramu Narasinga directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ramu Narasinga
Ramu Narasinga

I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.