From 5dd1cabb0aa4b1461971eb14cecef29360045da7 Mon Sep 17 00:00:00 2001 From: krutoo Date: Sat, 21 Mar 2026 10:31:33 +0500 Subject: [PATCH] docs: Docs improvements --- docs/docs/di/overview.mdx | 66 +------------------------- docs/docs/di/usage.mdx | 75 ++++++++++++++++++++++++++++++ docs/docs/react/use-dependency.mdx | 23 +++++++++ docs/docs/react/use-mutation.mdx | 2 +- 4 files changed, 100 insertions(+), 66 deletions(-) create mode 100644 docs/docs/di/usage.mdx diff --git a/docs/docs/di/overview.mdx b/docs/docs/di/overview.mdx index 68c632b..3417c27 100644 --- a/docs/docs/di/overview.mdx +++ b/docs/docs/di/overview.mdx @@ -84,68 +84,4 @@ What if we use an object instead of a primitive? We can easily attach a specific We'll replace the concept of an "identifier" with the concept of a "token". _Token_ - is an object that can be used as an identifier and to which a specific interface can be assigned. -## Usage - -With this library you can implement DI with next steps. -First we need to define our tokens: - -```ts title="./src/app/token.ts" -import { createToken } from '@krutoo/utils/di'; - -export const TOKEN = { - logger: createToken(), - client: createToken(), -}; -``` - -Then we need to define "component providers" - functions that returns component implementation: - -```ts title="./src/app/providers.ts" -import type { Resolve } from '@krutoo/utils/di'; -import { TOKEN } from '#app/token'; - -export function provideLogger() { - return new MyLogger(); -} - -export function provideClient(resolve: Resolve) { - // here we use logger from container as dependency of client - const logger = resolve(TOKEN.logger); - - return new HttpClient({ - onError: logger.error, - }); -} -``` - -And now we need to create container and fill it by providers: - -```ts title="./src/app/container.ts" -import { createContainer } from '@krutoo/utils/di'; -import { provideClient, provideLogger } from '#app/providers'; -import { TOKEN } from '#app/token'; - -export function createAppContainer() { - const container = createContainer(); - - container.set(TOKEN.client, provideClient); - container.set(TOKEN.logger, provideLogger); - - return container; -} -``` - -After it you can get components from container in any order and each container will automatically resolves its dependencies. - -```ts title="./src/index.ts" -import { createAppContainer } from '#app/container'; -import { TOKEN } from '#app/token'; - -const container = createAppContainer(); - -const client = container.get(TOKEN.client); - -const response = await client.get('/api/user/me'); -``` - -Here `response` will have type `HttpClient` because we use `TOKEN.client` to get it. +In TypeScript we can bind types via generics and thats why tokens are so useful abstraction. diff --git a/docs/docs/di/usage.mdx b/docs/docs/di/usage.mdx new file mode 100644 index 0000000..9b0163f --- /dev/null +++ b/docs/docs/di/usage.mdx @@ -0,0 +1,75 @@ +export const meta = { + title: 'Usage', + category: 'DI', +}; + +# Using DI utils + +With this library you can implement DI with next steps. +First we need to define our _tokens_: + +```ts title="./src/app/token.ts" +import { createToken } from '@krutoo/utils/di'; + +export const TOKEN = { + logger: createToken(), + client: createToken(), +}; +``` + +Then we need to define "providers" - functions that returns component implementation: + +```ts title="./src/app/providers.ts" +import type { Resolve } from '@krutoo/utils/di'; +import { TOKEN } from '#app/token'; + +export function provideLogger() { + return new MyLogger(); +} + +export function provideClient(resolve: Resolve) { + // here we use logger from container as dependency of client + const logger = resolve(TOKEN.logger); + + return new HttpClient({ + onError: logger.error, + }); +} +``` + +The pitfall here is that you can pass the resolve function as an argument to another function to call it internally or even later. +Don't do this! This will turn your container into a _service locator_, which is bad practice. + +--- + +And now we need to create container and fill it by providers: + +```ts title="./src/app/container.ts" +import { createContainer } from '@krutoo/utils/di'; +import { provideClient, provideLogger } from '#app/providers'; +import { TOKEN } from '#app/token'; + +export function createAppContainer() { + const container = createContainer(); + + container.set(TOKEN.client, provideClient); + container.set(TOKEN.logger, provideLogger); + + return container; +} +``` + +After it you can get components from container in any order and each container will automatically resolves its dependencies. + +```ts title="./src/index.ts" +import { createAppContainer } from '#app/container'; +import { TOKEN } from '#app/token'; + +const container = createAppContainer(); + +const client = container.get(TOKEN.client); + +const response = await client.get('/api/user/me'); +``` + +Here `response` will have type `HttpClient` because we use `TOKEN.client` to get it. diff --git a/docs/docs/react/use-dependency.mdx b/docs/docs/react/use-dependency.mdx index 9e647d3..0da7cb9 100644 --- a/docs/docs/react/use-dependency.mdx +++ b/docs/docs/react/use-dependency.mdx @@ -31,3 +31,26 @@ function App() { ); } ``` + +### Context for DI-container + +Hook `useDependency` will throw error if component is not wrapped by `ContainerContext` by design. + +You can make this in your app' entrypoint: + +```js +import { createRoot } from 'react-dom/client'; +import { createContainer } from '@krutoo/utils/di'; +import { ContainerContext } from '@krutoo/utils/react'; +import { App } from '#components/app'; + +const container = createContainer(); + +// ...fill your container + +createRoot(document.querySelector('#root')).render( + + + , +); +``` diff --git a/docs/docs/react/use-mutation.mdx b/docs/docs/react/use-mutation.mdx index 5aa4574..a9cb905 100644 --- a/docs/docs/react/use-mutation.mdx +++ b/docs/docs/react/use-mutation.mdx @@ -43,7 +43,7 @@ export default function Example() { } if (mutation.status === 'failure') { - return <>Error: {mutation.error}`; + return <>Error: {mutation.error}; } return (