@getsoren/shared-module
v2.44.0
Published
> This package contains shared components, hooks and utilities. > This package use dependencies only with injection.
Readme
@getsoren/shared-module
This package contains shared components, hooks and utilities. This package use dependencies only with injection.
Installation
yarn add @getsoren/shared-moduleUsage
import { InitializeAxiosConfig } from "@getsoren/shared-module";Inject dependencies with provider
import { InjectDependenciesProvider, InitializeAxiosConfig } from "@getsoren/shared-module";
const App = () => (
<InjectDependenciesProvider apiURL={import.meta.env.VITE_API_URL} libraries={{
axios,
}}>
<InitializeAxiosConfig/>
...
</InjectDependenciesProvider>
);
export default App;Providers
| Module | Description | Dependencies | |-------------------------------|-------------------------------------------------------|--------------| | InjectDependenciesProvider | Inject dependencies for other shared component | - | | QueryClientProviderWithConfig | React Query provider with default config | React Query | | ChatProvider | Shared WebSocket chat connection provider via context | - |
Components
| Module | Type | Description | Dependencies | |------------------------|-----------------|-----------------------------------------------------|------------------------------------------------------------| | RequireAuth | React Component | Component for protected routing | Axios & react-router-dom | | GTMSendPageView | React Component | Send page view event to Google Tag Manager | @getsoren/react-google-tag-manager & react-router-dom | | InitializeAxiosConfig | React Component | Initialize Axios with custom default config options | Axios | | InitializeI18nConfig | React Component | Initialize i18n with custom config options | i18next & react-i18next & i18next-browser-languagedetector | | InitializeSentryConfig | React Component | Initialize Sentry | @sentry/react & react-router-dom | | InitializeMapBoxConfig | React Component | Initialize MapBox | mapbox-gl | | InitializeDaysJSConfig | React Component | Initialize DayJS | dayjs | | InitializeHubSpot | React Component | Initialize HubSpot chat widget | - | | PreloadErrorHandler | React Component | his component is used to handle preload error. | dayjs |
Hooks
| Module | Description | Dependencies | |---------------------|----------------------------------------------------------------------------|-------------------| | useAdapter | Hook with several adapter | - | | useAuth | Hook for authentification management | Axios | | useHubSpot | Hook to interact with the HubSpot chat widget (toggle, availability) | InitializeHubSpot | | useResponseError | This hook is used to print error messages from the API | i18next | | useInfiniteDataGrid | This hook is used to handle the infinite scroll of the DataGrid component. | - | | useCurrentLanguage | This get the current language of app | - | | useFilters | Hook to handle filter | - | | useChat | Hook to consume the ChatProvider context (threads, messaging, presence) | ChatProvider |
WebSocket
Chat
The chat module provides a WebSocket client for thread subscription, messaging, read receipts, and presence events.
With the React provider (recommended):
First, wrap your app with ChatProvider (inside InjectDependenciesProvider):
import { ChatProvider, InjectDependenciesProvider } from "@getsoren/shared-module";
const App = () => (
<InjectDependenciesProvider apiURL={import.meta.env.VITE_API_URL} libraries={libraries} localStorageKeys={localStorageKeys}>
<ChatProvider>
<MyApp />
</ChatProvider>
</InjectDependenciesProvider>
);Then use useChat() in any component:
import { useChat } from "@getsoren/shared-module";
const Chat = ({ threadId }: { threadId: string }) => {
const { isReady, sendMessage, joinThread } = useChat();
return (
<div>
<p>{isReady ? "Connected" : "Connecting..."}</p>
<button onClick={() => joinThread(threadId)}>Join</button>
<button onClick={() => sendMessage(threadId, "Hello!")}>Send</button>
</div>
);
};The provider reads apiURL and the user token from InjectDependenciesProvider automatically. You can override both via props:
<ChatProvider url="wss://api.example.com/v2/threads/ws" token="my-jwt">Without React (class only):
import { ChatClient } from "@getsoren/shared-module";
const client = new ChatClient({
url: "wss://api.example.com/v2/threads/ws",
getToken: () => "my-jwt",
onEvent: (event) => console.log(event),
onConnectionChange: (connected) => console.log("connected:", connected),
});
client.connect();
client.joinThread("thread-1");
client.sendMessage("thread-1", "Hello!");| Module | Description | Dependencies | |--------------|-----------------------------------------------------------|--------------| | ChatClient | Framework-agnostic WebSocket client for the chat protocol | - | | ChatProvider | Provider for shared WebSocket connection via context | - | | useChat | React hook to consume the ChatProvider context | ChatProvider |
Orval
The @getsoren/shared-module/orval entry point provides everything needed to write an orval.config.ts.
⚠️ This entry relies on Node built-ins (
fs,child_process) and must only be imported fromorval.config.tsfiles, never from browser code.
// orval.config.ts
import { getOrvalConfig } from "@getsoren/shared-module/orval";
import { defineConfig } from "orval";
const config = getOrvalConfig([
{ customAxiosInstancePath: "./src/api/customSaasInstance.ts", input: { host: "saas" } },
{ customAxiosInstancePath: "./src/api/customAuthInstance.ts", input: { host: "auth" } },
{ customAxiosInstancePath: "./src/api/customSupplierInstance.ts", input: { host: "supplier" } },
]);
export default defineConfig(config);Input resolution
When input is an object, the OpenAPI schema target is resolved with the following priorities:
- Local file (
./openapi.<name>.json) — pulled schema snapshot - Local service (
https://<subdomain>.api.tracktor.test/openapi.json) — docker compose back environment, probed via cURL - Upstream deployed service (
https://<subdomain>.api.dev.tracktor.fr/openapi.json) — dev cluster, fallback
Host
host is the API name ("saas" | "auth" | "supplier") and derives all defaults:
| Derived value | Default |
|-------------------|----------------------------------------------------------|
| overrideApiName | <host> → generated folders src/api/<host>/ |
| localFile | ./openapi.<host>.json |
| localUrl | https://<subdomain>.api.tracktor.test/openapi.json |
| upstreamUrl | https://<subdomain>.api.dev.tracktor.fr/openapi.json |
The subdomain matches the host, except saas which is served on the app subdomain.
Every derived value can be overridden individually:
// Target a specific environment
input: { host: "saas", upstreamUrl: "https://app.api.rc.tracktor.fr/openapi.json" }
// Fully custom, without host
input: {
localFile: "./openapi.custom.json",
localUrl: "https://custom.test/openapi.json",
upstreamUrl: "https://custom.fr/openapi.json",
}
// Plain path or URL, no resolution
input: "./openapi.json"customAxiosInstancePath is required: each API needs a dedicated axios instance file
(its own baseURL env variable) which orval uses as mutator.
| Module | Description | |-----------------------|----------------------------------------------------------------------| | getOrvalConfig | Build the orval config (input resolution included) | | resolveOrvalInput | Standalone schema target resolution (local file → local → upstream) |
Utils function
| Module | Description | |---------------------|----------------------| | dateAdapter | Adapt given date | | distanceAdapter | Adapt given distance | | worksiteNameAdapter | Adapt worksite name |