Expose configuration
This section describes how to expose configuration of a plugin.
Background
The heart of Nocto is the architecture which lets you dynamically expose interface of plugins to everyone else.
One of such functionalities is the exposing the configuration. Plugins can define how they can be configured by the others.
Slots vs configuration:
You can think about the configuration as just passing the arguments to your plugin. For instance, you can expose some column names, endpoints, table title etc., so something which can be fast and easy changed. Slots on the other hand requires changing the whole UI. If someone wants to hide or change the column name in the table, the better option is just use the configuration.
Config schema
Your plugin definition is in index.tsx
, but the plugin's implementation can contain many different files. Let's assume that you have a file called plugin.tsx
which will export the very simple component (as entry point to your plugin).
import { Text, Container } from "@medusajs/ui"
export const Slot1 = () => {
return (
<Container>
<Text>Your custom plugin in a slot 1</Text>
</Container>
)
}
export default Slot1
And here is your definition of the plugin in index.tsx
:
export const myPlugin = {
id: "@my-plugin",
routes: () => [
{
path: "/my-plugin",
layout: "main",
lazy: () =>
import("./plugin").then((mod) => ({
Component: () => mod.default(),
})),
},
],
}
You can see that your plugin exposes a route under /my-plugin
and renders default components from ./plugin
which is the Slot1
.
Now, if you want to expose configuration, you need firstly define schema. We are using zod
for this task.
Let's say you want to give possibility to change the text via configuration. Your schema can look like this:
import * as z from "zod"
export const ConfigSchema = z.object({
text: z.string().default("Your custom plugin in a slot 1"),
})
In that schema, we are defining text
which is a string
and by default it is Your custom plugin in a slot 1
.
Default values:
We encourage to always set default value if possible. It is easier for maintainance as the configuration might not be used, even if it is exposed.
Use above schema to put it in index.tsx
under configSchema
parameter.
import { ConfigSchema } from "./plugin";
export const myPlugin = {
id: "@my-plugin",
configSchema: ConfigSchema,
routes: () => [
{
path: "/my-plugin",
layout: "main",
lazy: () =>
import("./plugin").then((mod) => ({
Component: () => mod.default(),
})),
},
],
}
Finally, let's start using this configuration in your plugin so people can dynamically change it. For that task, we are going to use nocto context
and created schema. Here is the example in plugin.tsx
:
import { Text, Container } from "@medusajs/ui"
import { useNoctoPluginContext } from "@rsc-labs/noctojs-plugin-system"
import * as z from "zod"
export const ConfigSchema = z.object({
text: z.string().default("Your custom plugin in a slot 1"),
})
type ConfigData = z.infer<typeof ConfigSchema>;
export const Slot1 = () => {
const { pluginConfigRegistry } = useNoctoPluginContext()
const config = pluginConfigRegistry.get<ConfigData>("@my-plugin");
return (
<Container>
<Text>{config && config.text}</Text>
</Container>
)
}
export default Slot1
You can see that firstly we are using nocto context
to get the pluginConfigRegistry
and then we are using it to get our config which is a type coming from zod.
At the end the config.text
is used to render the text.
Future:
We are going to simplify this mechanism in the future, including schema definition and usage of config.
Now, users can use your plugin and define their configuration, for instance:
import { NoctoConfig } from "@rsc-labs/noctojs-plugin-system"
import {
Sparkles,
} from "@medusajs/icons"
export const noctoConfig: NoctoConfig = {
plugins: {
"@login": {
config: {
title: "Welcome to Nocto",
hint: "Sign in to access",
mainIcon: Sparkles
}
},
"@order-detail": {},
"@campaigns-routes": {},
"@categories-routes": {},
"@collections-routes": {},
"@core-routes": {},
"@customer-groups-routes": {},
"@public-routes": {},
"@reservations-routes": {},
"@settings-routes": {},
"@my-plugin": {
config: {
text: "My configuration text"
}
}
},
sidebar: {
"@orders": { order: 1 },
"@products": { order: 2 },
"@inventory": { order: 3 },
"@customers": { order: 4 },
"@promotions": { order: 5 },
"@price-lists": { order: 6 },
}
}
Based on the above, it will render My configuration text
intead of Your custom plugin in a slot 1
,