Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 1 addition & 65 deletions docs/docs/di/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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<Logger>(),
client: createToken<HttpClient>(),
};
```

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.
75 changes: 75 additions & 0 deletions docs/docs/di/usage.mdx
Original file line number Diff line number Diff line change
@@ -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<Logger>(),
client: createToken<HttpClient>(),
};
```

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.
23 changes: 23 additions & 0 deletions docs/docs/react/use-dependency.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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(
<ContainerContext value={container}>
<App />
</ContainerContext>,
);
```
2 changes: 1 addition & 1 deletion docs/docs/react/use-mutation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default function Example() {
}

if (mutation.status === 'failure') {
return <>Error: {mutation.error}`</>;
return <>Error: {mutation.error}</>;
}

return (
Expand Down
Loading