### Install Brandi-React with NPM Source: https://github.com/vovaspace/brandi/blob/main/docs/brandi-react/overview.md Use this command to install the Brandi-React library via NPM. Ensure you have Node.js and NPM installed. ```bash npm install brandi-react ``` -------------------------------- ### Install Brandi-React with Yarn Source: https://github.com/vovaspace/brandi/blob/main/docs/brandi-react/overview.md Use this command to install the Brandi-React library via Yarn. Ensure you have Node.js and Yarn installed. ```bash yarn add brandi-react ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/vovaspace/brandi/blob/main/website/README.md Installs all necessary dependencies for the project using Yarn. ```console yarn install ``` -------------------------------- ### Start Local Development Server Source: https://github.com/vovaspace/brandi/blob/main/website/README.md Starts a local development server for live previewing changes. Changes are reflected without server restart. ```console yarn start ``` -------------------------------- ### Install Brandi with NPM Source: https://github.com/vovaspace/brandi/blob/main/docs/getting-started/installation.md Use this command to install the Brandi package using NPM. ```bash npm install brandi ``` -------------------------------- ### Install Brandi with Yarn Source: https://github.com/vovaspace/brandi/blob/main/docs/getting-started/installation.md Use this command to install the Brandi package using Yarn. ```bash yarn add brandi ``` -------------------------------- ### Hierarchical Container Example Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/hierarchical-containers.md Demonstrates creating a parent container, binding a service, extending it with a child container, and retrieving the service from the child. ```typescript import { Container, token } from 'brandi'; class ApiService {} const TOKENS = { apiService: token('apiService'), }; const parentContainer = new Container(); parentContainer .bind(TOKENS.apiService) .toInstance(ApiService) .inTransientScope(); const childContainer = new Container().extend(parentContainer); const apiService = childContainer.get(TOKENS.apiService); expect(apiService).toBeInstanceOf(ApiService); ``` -------------------------------- ### Bind Token to Instance with Factory for Caching Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/binding-types.md Demonstrates how to use a factory to retrieve a singleton instance. This pattern ensures that `get` always returns the same instance, effectively caching it. ```typescript import { Container, Factory, token } from 'brandi'; class ApiService { /* ... */ } const TOKENS = { apiService: token('apiService'), apiServiceFactory: token>('Factory'), }; const container = new Container(); container .bind(TOKENS.apiService) .toInstance(ApiService) .inSingletonScope() /* ← Binds the token to `ApiService` instance in singleton scope. */; container .bind(TOKENS.apiServiceFactory) .toFactory(() => container.get(TOKENS.apiService)); const apiServiceFactory = container.get(TOKENS.apiService); const firstApiService = apiServiceFactory(); const secondApiService = apiServiceFactory(); expect(firstApiService).toBe(secondApiService); ``` -------------------------------- ### Get Instance with Transient Scope Source: https://github.com/vovaspace/brandi/blob/main/docs/examples/basic-examples.md Demonstrates how to bind a token to an instance and retrieve it from the container within a transient scope. Ensure ApiService is defined. ```typescript import { Container, token } from 'brandi'; class ApiService {} const TOKENS = { /* ↓ Creates a typed token. */ apiService: token('apiService'), }; const container = new Container(); container .bind(TOKENS.apiService) .toInstance(ApiService) /* ← Binds the token to an instance */ .inTransientScope(); /* ← in transient scope. */ /* ↓ Gets the instance from the container. */ const apiService = container.get(TOKENS.apiService); expect(apiService).toBeInstanceOf(ApiService); ``` -------------------------------- ### Providing Root Container with ContainerProvider Source: https://github.com/vovaspace/brandi/blob/main/docs/brandi-react/container-provider.md Use ContainerProvider to make the root Brandi container available to your React application. This example demonstrates setting up the container, binding a service, and rendering the main App component. ```tsx import { createContainer } from 'brandi'; import { ContainerProvider } from 'brandi-react'; import React from 'react'; import ReactDOM from 'react-dom'; import { TOKENS } from './tokens'; import { ApiService } from './ApiService'; import { App } from './App'; const container = createContainer(); container.bind(TOKENS.apiService).toInstance(ApiService).inTransientScope(); ReactDOM.render( , document.getElementById('root'), ); ``` -------------------------------- ### Register Target Injections Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/pointers-and-registrators.md Shows how to use the `injected` registrator to specify dependencies for a class constructor. Includes examples of correct type binding and potential type mismatches. ```typescript import { injected } from 'brandi'; import { TOKENS } from './tokens'; import { Logger } from './Logger'; export class ApiService { constructor(private apiKey: string, private logger?: Logger) {} } injected(ApiService, TOKENS.apiKey, TOKENS.logger.optional); ``` ```typescript import { token } from 'brandi'; export const TOKENS = { strKey: token('String API Key'), numKey: token('Number API Key'), }; ``` ```typescript import { injected } from 'brandi'; import { TOKENS } from './tokens'; import { Logger } from './Logger'; export class ApiService { constructor( private apiKey: string /* ← The `string` type dependency. */, private logger?: Logger /* ← The optional dependency. */, ) {} } injected( ApiService, TOKENS.strKey /* ← Injecting the `string` type dependency. It's OK. */, TOKENS.logger.optional /* ← Injecting the optional dependency. It's OK. */, ); injected( ApiService, TOKENS.numKey, /* ← Injecting the `number` type dependency. * TS Error: `Type 'number' is not assignable to type 'string'. ts(2345)`. */ TOKENS.logger, /* ← Injecting the required value instead of the optional one. * TS Error: `Argument of type 'Token' * is not assignable to parameter of type 'OptionalToken'`. */ ); ``` -------------------------------- ### `Container.bind(token)` Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/container.md Binds a given token to an implementation within the container. This method is the starting point for defining how dependencies are provided. ```APIDOC ## `Container.bind(token)` ### Description Binds the token to an implementation. ### Method `bind(token)` ### Parameters #### Path Parameters - **token** (`Token`) - Required - A token to be bound. ### Returns [Binding Type](./binding-types.md) syntax: - [`toConstant(value)`](./binding-types.md#toconstantvalue) - [`toInstance(creator)`](./binding-types.md#toinstancecreator) - [`toFactory(creator, [initializer])`](./binding-types.md#tofactorycreator-initializer) ``` -------------------------------- ### Configure Container with Conditional Bindings Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/conditional-bindings.md Configure the Brandi container to use conditional bindings. This example shows how to bind a token to different implementations based on tags or specific target services. ```typescript import { Container, tagged } from 'brandi'; import { TOKENS } from './tokens'; import { TAGS } from './tags'; import { OnlineCacher, LocalCacher } from './Cacher'; import { UserService } from './UserService'; import { SettingsService } from './SettingsService'; import { AdminService } from './AdminService'; tagged(SettingsService, TAGS.offline); /* ← Tags `SettingsService`. */ export const container = new Container(); container .bind(TOKENS.cacher) /* ← Binds to `OnlineCacher` in common cases. */ .toInstance(OnlineCacher) .inTransientScope(); container .when(TAGS.offline) /* ← Binds to `LocalCacher` when target tagget by `offline` tag. */ .bind(TOKENS.cacher) .toInstance(LocalCacher) .inTransientScope(); container .when(AdminService) /* ← Binds to `LocalCacher` when target is `AdminService`. */ .bind(TOKENS.cacher) .toInstance(LocalCacher) .inTransientScope(); container.bind(TOKENS.userService).toInstance(UserService).inTransientScope(); container.bind(TOKENS.settingsService).toInstance(SettingsService).inTransientScope(); container.bind(TOKENS.adminService).toInstance(AdminService).inTransientScope(); ``` -------------------------------- ### Using useInjection Hook Source: https://github.com/vovaspace/brandi/blob/main/docs/brandi-react/use-injection.md Demonstrates how to use the useInjection hook to get dependencies like userService and an optional logger within a React FunctionComponent. Ensure dependencies are correctly bound in the ContainerProvider. ```tsx import { useInjection } from 'brandi-react'; import { FunctionComponent } from 'react'; import { TOKENS } from '../tokens'; export const UserComponent: FunctionComponent = () => { const userService = useInjection(TOKENS.userService); const logger = useInjection(TOKENS.logger.optional); /* ... */ return (/* ... */); } ``` -------------------------------- ### Create Custom Injection Hooks Source: https://github.com/vovaspace/brandi/blob/main/docs/brandi-react/create-injection-hooks.md Use `createInjectionHooks` to generate an array of React hooks for accessing dependencies. Each hook corresponds to a provided token. This example shows how to create hooks for an API service, user service, and an optional logger. ```typescript import { createInjectionHooks } from 'brandi-react'; import { TOKENS } from './tokens'; const [ useApiService, useUserService, useLogger, ] = createInjectionHooks( TOKENS.apiService, TOKENS.userService, TOKENS.logger.optional, ); export { useApiService, useUserService, useLogger }; ``` -------------------------------- ### Deploy Website to GitHub Pages Source: https://github.com/vovaspace/brandi/blob/main/website/README.md Builds the website and deploys it to the 'gh-pages' branch, suitable for GitHub Pages hosting. ```console GIT_USER= USE_SSH=true yarn deploy ``` -------------------------------- ### Create and Use Type-Safe Tokens Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/pointers-and-registrators.md Demonstrates creating a token for a string API key and enforcing type safety during binding and retrieval. Shows how Brandi prevents binding incorrect types to tokens. ```typescript import { Container, token } from 'brandi'; const TOKENS = { apiKey: token('API Key') /* ← The token with `string` type. */, }; const container = new Container(); /* ↓ Binding the `string` type value. It's OK. */ container.bind(TOKENS.apiKey).toConstant('#key9428'); /** * ↓ Trying to bind the `string` type token to the `number` type value: * TS Error: `Argument of type 'number' is not assignable * to parameter of type 'string'. ts(2345)`. */ container.bind(TOKENS.apiKey).toConstant(9428); const key = container.get(TOKENS.apiKey); type Key = typeof key; /* ← The type is derived from the token. `type Key = string;` */ /* ↓ TS Error: `Type 'string' is not assignable to type 'number'. ts(2322)` */ const numKey: number = container.get(TOKENS.apiKey); ``` -------------------------------- ### Run Application Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/dependency-modules.md Retrieves the App instance from the configured container and executes its run method. This is the entry point for the application logic. ```typescript import { TOKENS } from './tokens'; import { container } from './container'; const app = container.get(TOKENS.app); app.run(); ``` -------------------------------- ### toInstance(creator) Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/binding-types.md Binds a token to an instance created by a provided creator function or class. This allows for dynamic instance creation and management within different scopes. ```APIDOC ## `toInstance(creator)` Binds the token to an instance in one of the [scopes](./binding-scopes.md). ### Arguments 1. `creator`: `(new (...args: any[]) => TokenType) | ((...args: any[]) => TokenType)` — the instance creator that will be bound to the token. ### Returns [Binding Scope](./binding-scopes.md) syntax: - [`inSingletonScope()`](./binding-scopes.md#insingletonscope) - [`inTransientScope()`](./binding-scopes.md#intransientscope) - [`inContainerScope()`](./binding-scopes.md#incontainerscope) - [`inResolutionScope()`](./binding-scopes.md#inresolutionscope) ### Examples #### Class Instance ```typescript import { Container, token } from 'brandi'; class ApiService { /* ... */ } const TOKENS = { apiService: token('apiService'), }; const container = new Container(); container.bind(TOKENS.apiService).toInstance(ApiService).inTransientScope(); const apiService = container.get(TOKENS.apiService); expect(apiService).toBeInstanceOf(ApiService); ``` #### Function Call Result ```typescript import { Container, token } from 'brandi'; interface ApiService { /* ... */ } const createApiService = (): ApiService => { /* ... */ }; const TOKENS = { apiService: token('apiService'), }; const container = new Container(); container .bind(TOKENS.apiService) .toInstance(createApiService) .inTransientScope(); const apiService = container.get(TOKENS.apiService); expect(apiService).toStrictEqual({ /* ... */ }); ``` ### Injetions If the constructor or function has arguments you need to register dependencies by [`injected`](./pointers-and-registrators.md#injectedtarget-tokens) registrator. ```typescript import { injected } from 'brandi'; import { TOKENS } from './tokens'; import type { HttpClient } from './HttpClient'; export class ApiService { constructor(private http: HttpClient) {} } injected(ApiService, TOKENS.httpClient); ``` ``` -------------------------------- ### Set up Brandi Container with ContainerProvider Source: https://github.com/vovaspace/brandi/blob/main/packages/brandi-react/README.md Initialize a Brandi container and provide it to the React application using ContainerProvider. This makes the container accessible to all nested components. ```tsx // index.ts import { createContainer } from 'brandi'; import { ContainerProvider } from 'brandi-react'; import React from 'react'; import ReactDOM from 'react-dom'; import { TOKENS } from './tokens'; import { ApiService } from './ApiService'; import { App } from './App'; const container = createContainer(); container.bind(TOKENS.apiService).toInstance(ApiService).inTransientScope(); ReactDOM.render( , document.getElementById('root'), ); ``` -------------------------------- ### `Container.use(...tokens).from(module)` Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/container.md Imports bindings from a specified dependency module. This allows for modular management of dependencies. ```APIDOC ## `Container.use(...tokens).from(module)` ### Description Uses bindings from a [dependency module](./dependency-modules.md). ### Method `use(...tokens).from(module)` ### Parameters #### Path Parameters - **...tokens** (`Token[]`) - Required - Tokens to be used from a dependency module. - **module** (`DependencyModule`) - Required - A dependency module. ### Returns This method does not explicitly return a value, but modifies the container state by importing bindings. ``` -------------------------------- ### Build Static Website Content Source: https://github.com/vovaspace/brandi/blob/main/website/README.md Generates the static content for the website, typically placed in the 'build' directory. ```console yarn build ``` -------------------------------- ### Pointers and Registrators Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/api-reference.md Utilities for defining tokens, tags, and injection decorators. ```APIDOC ## Pointers and Registrators ### `token(description)` Creates a unique token with a description. ### `tag(description)` Creates a tag with a description. ### `injected(target, ...tokens)` Decorator to inject dependencies into a target. ### `tagged(target, ...tags)` Decorator to tag a target with specific tags. ``` -------------------------------- ### tag(description) Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/pointers-and-registrators.md Creates a unique tag for categorizing dependencies. Tags are useful for conditional bindings. ```APIDOC ## tag(description) ### Description Creates a unique tag for categorizing dependencies. Tags are useful for conditional bindings. ### Arguments - `description` (string) - A description of the tag to be used in logs and error messages. ### Returns - `Tag` - A unique tag. ``` -------------------------------- ### Create API Dependency Module Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/dependency-modules.md Sets up a dependency module for API-related services. It binds the API key and the ApiService, specifying a transient scope for the service. ```typescript import { DependencyModule } from 'brandi'; import { TOKENS } from '../tokens'; import { ApiService } from './ApiService'; export const apiModule = new DependencyModule(); apiModule.bind(TOKENS.apiKey).toConstant('#key9428'); apiModule.bind(TOKENS.apiService).toInstance(ApiService).inTransientScope(); ``` -------------------------------- ### Dependency Modules Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/api-reference.md Utilities for creating and managing dependency modules. ```APIDOC ## Dependency Modules ### `createDependencyModule()` Creates a new dependency module. ``` -------------------------------- ### Clone Container Instance Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/container.md Demonstrates how to create an unlinked copy of an existing container. Use this when you need a separate container instance with the same initial bindings. ```typescript import { Container } from 'brandi'; const originalContainer = new Container(); const containerClone = originalContainer.clone(); expect(containerClone).toBeInstanceOf(Container); expect(containerClone).not.toBe(originalContainer); ``` -------------------------------- ### Configure Container with API Module Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/dependency-modules.md Configures the main container by importing the API dependency module and binding the App instance. The comment highlights that only directly depended-upon tokens need explicit use, as nested dependencies are resolved automatically. ```typescript import { Container } from 'brandi'; import { TOKENS } from './tokens'; import { apiModule } from './api/module'; import { App } from './App'; export const container = new Container(); /** * ↓ We only use the `apiService` token that the `App` directly depends on. * The `apiKey` token binding will be resolved from the `apiModule` automatically * and it does not need to be bound additionally. */ container.use(TOKENS.apiService).from(apiModule); container.bind(TOKENS.app).toInstance(App).inSingletonScope(); ``` -------------------------------- ### Binding Types Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/api-reference.md Types of bindings available for dependency injection. ```APIDOC ## Binding Types ### `toConstant(value)` Binds a token to a constant value. ### `toFactory(creator, [initializer])` Binds a token to a factory function that creates instances. ### `toInstance(creator)` Binds a token to a pre-existing instance. ``` -------------------------------- ### Snapshot and Restore Container State Source: https://github.com/vovaspace/brandi/blob/main/docs/examples/basic-examples.md Shows how to capture the current state of a container, modify bindings, and then restore the original state. Useful for testing. ```typescript import { Container, token } from 'brandi'; const TOKENS = { apiKey: token('API Key'), }; const container = new Container(); container .bind(TOKENS.apiKey) .toConstant('#key9428'); /* ← Binds the token to some string. */ /* ↓ Captures (snapshots) the current container state. */ container.capture(); container .bind(TOKENS.apiKey) .toConstant('#testKey'); /* ← Binds the same token to another value. */ /* For example, this can be used in testing. */ const testKey = container.get(TOKENS.apiKey); /* ↓ Restores the captured container state. */ container.restore(); const originalKey = container.get(TOKENS.apiKey); expect(testKey).toBe('#testKey'); expect(originalKey).toBe('#key9428'); ``` -------------------------------- ### Tag Target with Tags Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/pointers-and-registrators.md Demonstrates using the `tagged` registrator to apply tags to a target, which is useful for conditional bindings as described in the Brandi documentation. ```typescript import { tagged } from 'brandi'; import { TAGS } from './tags'; export class ApiService {} tagged(ApiService, TAGS.offline); ``` -------------------------------- ### `createContainer()` Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/container.md An alias for creating a new instance of the Container class. ```APIDOC ## `createContainer()` ### Description `createContainer()` — is an alias for `new Container()`. ### Method `createContainer()` ### Returns `Container` - A new instance of the Container class. ``` -------------------------------- ### `Container.get(token)` Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/container.md Retrieves a dependency that has been bound to the specified token. ```APIDOC ## `Container.get(token)` ### Description Gets a dependency bound to the token. ### Method `get(token)` ### Parameters #### Path Parameters - **token** (`TokenValue`) - Required - Token for which a dependence will be got. ### Returns `TokenType` - A dependency bound to the token. ``` -------------------------------- ### token(description) Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/pointers-and-registrators.md Creates a unique token with the specified type and description. This mechanism provides type safety for dependency injection. ```APIDOC ## token(description) ### Description Creates a unique token with the specified type and description. This mechanism provides type safety for dependency injection. ### Arguments - `description` (string) - A description of the token to be used in logs and error messages. ### Returns - `Token` - A unique token with the type. ### Example ```typescript import { Container, token } from 'brandi'; const TOKENS = { apiKey: token('API Key') }; const container = new Container(); container.bind(TOKENS.apiKey).toConstant('#key9428'); const key = container.get(TOKENS.apiKey); type Key = typeof key; // type Key = string; ``` ``` -------------------------------- ### Bind API Key from Dependency Module Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/dependency-modules.md Demonstrates binding a constant value for an API key within a dependency module and then using that module within a container. The container automatically resolves dependencies from the module. ```typescript import { Container, DependencyModule, token } from 'brandi'; const TOKENS = { apiKey: token('apiKey'), }; const apiModule = new DependencyModule(); apiModule.bind(TOKENS.apiKey).toConstant('#key9428'); const container = new Container(); container.use(TOKENS.apiKey).from(apiModule); const key = container.get(TOKENS.apiKey); expect(key).toBe('#key9428'); ``` -------------------------------- ### Bind Token to Factory with Arguments Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/binding-types.md Binds a token to a class constructor that accepts arguments during creation. The factory function signature must match the expected arguments. ```typescript import { Container, Factory, token } from 'brandi'; class ApiService { public key: string; public setKey(key: string) { this.key = key; } /* ... */ } const TOKENS = { /* ↓ `Factory` generic with second argument. */ apiServiceFactory: token>( 'Factory', ), }; const container = new Container(); container .bind(TOKENS.apiServiceFactory) /* ↓ Binds the factory with `apiKey` argument. */ .toFactory(ApiService, (instance, apiKey) => instance.setKey(apiKey)); const apiServiceFactory = container.get(TOKENS.apiServiceFactory); const apiService = apiServiceFactory('#key9124'); expect(apiService).toBeInstanceOf(ApiService); expect(apiService.key).toBe('#key9124'); ``` -------------------------------- ### Capture and Restore Container State Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/container.md Shows how to snapshot the current state of a container and later restore it. This is useful for testing scenarios where you need to temporarily modify bindings and then revert to the original state. Note that these methods are only available in development mode. ```typescript import { Container, token } from 'brandi'; const TOKENS = { apiKey: token('API Key'), }; const container = new Container(); container.bind(TOKENS.apiKey).toConstant('#key9428'); container.capture(); container.bind(TOKENS.apiKey).toConstant('#testKey'); const testKey = container.get(TOKENS.apiKey); container.restore(); const originalKey = container.get(TOKENS.apiKey); expect(testKey).toBe('#testKey'); expect(originalKey).toBe('#key9428'); ``` -------------------------------- ### Container Methods Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/api-reference.md Methods available on the Container object for managing dependencies. ```APIDOC ## Container Methods ### `bind(token)` Binds a token to a specific binding type. ### `capture()` Captures the current state of the container. ### `clone()` Creates a deep clone of the container. ### `extend(container)` Extends the current container with bindings from another container. ### `get(token)` Retrieves an instance associated with the given token. ### `restore()` Restores the container to a previously captured state. ### `use(...tokens)` Uses tokens from a module. ### `when(condition)` Applies conditional bindings based on a given condition. ``` -------------------------------- ### createInjectionHooks Source: https://github.com/vovaspace/brandi/blob/main/docs/brandi-react/create-injection-hooks.md Creates an array of hooks, where each hook is designed to retrieve a specific dependency registered with a token. This function takes a variable number of tokens as arguments and returns an array of corresponding hooks. ```APIDOC ## createInjectionHooks ### Description Creates hooks for easily getting dependencies based on provided tokens. ### Arguments - `...tokens` (`TokenValue[]`) - An array of tokens representing the dependencies to create hooks for. ### Returns - `(() => TokenType)[]` - An array of functions, where each function is a React hook for retrieving a dependency. ### Example ```typescript import { createInjectionHooks } from 'brandi-react'; import { TOKENS } from './tokens'; const [useApiService, useUserService, useLogger] = createInjectionHooks( TOKENS.apiService, TOKENS.userService, TOKENS.logger.optional ); export { useApiService, useUserService, useLogger }; ``` ### Usage in Component ```tsx import { FunctionComponent } from 'react'; import { useUserService } from './hooks'; export const UserComponent: FunctionComponent = () => { const userService = useUserService(); /* ... */ return (/* ... */); } ``` ``` -------------------------------- ### Set up Brandi Container with Conditional Binding Source: https://github.com/vovaspace/brandi/blob/main/docs/brandi-react/tagged.md Configures the Brandi dependency injection container. It sets a default binding for `TOKENS.apiService` and then overrides it with `OfflineApiService` when the `TAGS.offline` tag is present, using `container.when(TAGS.offline)`. ```tsx import { createContainer } from 'brandi'; import { ContainerProvider } from 'brandi-react'; import React from 'react'; import ReactDOM from 'react-dom'; import { TOKENS } from './tokens'; import { TAGS } from './tags'; import { ApiService, OfflineApiService } from './ApiService'; import { App } from './App'; const container = createContainer(); container .bind(TOKENS.apiService) .toInstance(ApiService) .inTransientScope(); container .when(TAGS.offline) .bind(TOKENS.apiService) .toInstance(OfflineApiService) .inTransientScope(); ReactDOM.render( , document.getElementById('root'), ); ``` -------------------------------- ### `Container.when(condition)` Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/container.md Creates a conditional binding based on a specified condition. This allows for dynamic dependency resolution. ```APIDOC ## `Container.when(condition)` ### Description Creates a [conditional binding](./conditional-bindings.md). ### Method `when(condition)` ### Parameters #### Path Parameters - **condition** (`Tag` | `UnknownCreator`) - Required - A condition. ### Returns `bind` or `use` syntax: - [`bind(token)`](#bindtoken) - [`use(...tokens)`](#usetokensfrommodule) ``` -------------------------------- ### `Container.capture()` Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/container.md Captures the current state of the container. This is useful for testing and debugging, but only works in development mode. ```APIDOC ## `Container.capture()` ### Description Captures (snapshots) the current container state. :::note The `capture()` method works only in development mode (`process.env.NODE_ENV !== 'production'`) `Container.capture` is `undefined` in production mode. ::: ### Method `capture()` ### Returns This method does not explicitly return a value, but modifies the container state by capturing it. ``` -------------------------------- ### Hierarchical Containers with Parent Binding Source: https://github.com/vovaspace/brandi/blob/main/docs/examples/basic-examples.md Illustrates creating a child container that extends a parent container. The child can resolve bindings from the parent if not defined locally. ```typescript import { Container, token } from 'brandi'; class ApiService {} const TOKENS = { apiService: token('apiService'), }; const parentContainer = new Container(); parentContainer .bind(TOKENS.apiService) .toInstance(ApiService) .inTransientScope(); /* ↓ Creates a container with the parent. */ const childContainer = new Container().extend(parentContainer); /** ↓ That container can't satisfy the getting request, * it passes it along to its parent container. * The intsance will be gotten from the parent container. */ const apiService = childContainer.get(TOKENS.apiService); expect(apiService).toBeInstanceOf(ApiService); ``` -------------------------------- ### useInjection(token) Source: https://github.com/vovaspace/brandi/blob/main/docs/brandi-react/use-injection.md The `useInjection` hook retrieves a dependency from the `ContainerProvider`. It takes a token as an argument and returns the corresponding dependency. ```APIDOC ## useInjection(token) ### Description Retrieves a dependency from the container provided by `ContainerProvider`. ### Arguments #### `token` - **token** (`TokenValue`) - Required - The token representing the dependency to retrieve. ### Returns - `TokenType` - The dependency bound to the provided token. ### Example ```tsx import { useInjection } from 'brandi-react'; import { FunctionComponent } from 'react'; import { TOKENS } from '../tokens'; export const UserComponent: FunctionComponent = () => { const userService = useInjection(TOKENS.userService); const logger = useInjection(TOKENS.logger.optional); /* ... */ return (/* ... */); } ``` ``` -------------------------------- ### Bind Token to Async Factory Creator Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/binding-types.md Binds a token to an asynchronous function that creates an instance. The container will await the promise returned by the creator before resolving. ```typescript import { AsyncFactory, Container, token } from 'brandi'; interface ApiService { /* ... */ } /* ↓ Async creator. */ const createApiService = async (): Promise => { /* ... */ }; const TOKENS = { /* ↓ Token with `AsyncFactory` type. */ apiServiceFactory: token>( 'AsyncFactory', ), }; const container = new Container(); container.bind(TOKENS.apiServiceFactory).toFactory(createApiService); const apiServiceFactory = container.get(TOKENS.apiServiceFactory); /** * ↓ Will wait for the creation resolution * and then call the initializer, if there is one. */ const apiService = await apiServiceFactory(); expect(apiService).toStrictEqual({ /* ... */ }); ``` -------------------------------- ### Bind to Class Instance with Transient Scope Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/binding-types.md Use `toInstance` with `inTransientScope` to bind a token to a new instance of a class created each time it's requested. Ensure dependencies are registered using `injected` if the constructor requires them. ```typescript import { Container, token } from 'brandi'; class ApiService { /* ... */ } const TOKENS = { apiService: token('apiService'), }; const container = new Container(); container.bind(TOKENS.apiService).toInstance(ApiService).inTransientScope(); const apiService = container.get(TOKENS.apiService); expect(apiService).toBeInstanceOf(ApiService); ``` -------------------------------- ### Bind Token to Simple Factory Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/binding-types.md Binds a token to a class constructor, allowing the creation of new instances via a factory function. Use when you need to create multiple instances of a service. ```typescript import { Container, Factory, token } from 'brandi'; class ApiService { /* ... */ } const TOKENS = { apiServiceFactory: token>('Factory'), }; const container = new Container(); /* ↓ Binds the factory. */ container.bind(TOKENS.apiServiceFactory).toFactory(ApiService); const apiServiceFactory = container.get(TOKENS.apiServiceFactory); const apiService = apiServiceFactory(); expect(apiService).toBeInstanceOf(ApiService); ``` -------------------------------- ### `Container.restore()` Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/container.md Restores the container to a previously captured state. This method is intended for development and testing scenarios. ```APIDOC ## `Container.restore()` ### Description Restores the [captured](#capture) container state. :::note The `restore()` method works only in development mode (`process.env.NODE_ENV !== 'production'`) `Container.restore` is `undefined` in production mode. ::: ### Method `restore()` ### Returns This method does not explicitly return a value, but modifies the container state by restoring it. ### Example ```typescript import { Container, token } from 'brandi'; const TOKENS = { apiKey: token('API Key'), }; const container = new Container(); container.bind(TOKENS.apiKey).toConstant('#key9428'); container.capture(); container.bind(TOKENS.apiKey).toConstant('#testKey'); const testKey = container.get(TOKENS.apiKey); container.restore(); const originalKey = container.get(TOKENS.apiKey); expect(testKey).toBe('#testKey'); expect(originalKey).toBe('#key9428'); ``` ``` -------------------------------- ### `Container.clone()` Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/container.md Creates a shallow copy (clone) of the container without any linked parent-child relationships. ```APIDOC ## `Container.clone()` ### Description Returns an unlinked clone of the container. ### Method `clone()` ### Returns `Container` - A new container instance that is a clone of the original. ### Example ```typescript import { Container } from 'brandi'; const originalContainer = new Container(); const containerClone = originalContainer.clone(); expect(containerClone).toBeInstanceOf(Container); expect(containerClone).not.toBe(originalContainer); ``` ``` -------------------------------- ### Providing a Module's Own Container with ContainerProvider Source: https://github.com/vovaspace/brandi/blob/main/docs/brandi-react/container-provider.md Provide a module-specific Brandi container using ContainerProvider. This container automatically inherits from the parent container, allowing module components to access shared dependencies like TOKENS.apiService. ```tsx import { createContainer } from 'brandi'; import { ContainerProvider } from 'brandi-react'; import { FunctionComponent } from 'react'; import { TOKENS } from '../tokens'; import { UserService } from './UserService'; import { UserComponent } from './UserComponent'; const container = createContainer(); container.bind(TOKENS.userService).toInstance(UserService).inTransientScope(); export const UserModule: FunctionComponent = () => ( , ); ``` -------------------------------- ### Create App with ApiService Dependency Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/dependency-modules.md Defines an App class that depends on ApiService. The `injected` function registers this dependency with Brandi. ```typescript import { injected } from 'brandi'; import { TOKENS } from './tokens'; import type { ApiService } from './api/ApiService'; export class App { constructor(private apiService: ApiService) {} /* ... */ } injected(App, TOKENS.apiService); ``` -------------------------------- ### `Container.extend(container)` Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/container.md Sets a parent container for the current container, enabling hierarchical dependency resolution. ```APIDOC ## `Container.extend(container)` ### Description Sets the parent container. For more information, see [Hierarchical Containers](./hierarchical-containers.md) section. ### Method `extend(container)` ### Parameters #### Path Parameters - **container** (`Container | null`) - Required - A `Container` or `null` that will be set as the parent container. ### Returns `this` - The container instance. ``` -------------------------------- ### Binding Scopes Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/api-reference.md Scopes that define the lifecycle of bound instances. ```APIDOC ## Binding Scopes ### `inContainerScope()` Sets the binding scope to the container level. ### `inResolutionScope()` Sets the binding scope to the resolution level. ### `inSingletonScope()` Sets the binding scope to a singleton. ### `inTransientScope()` Sets the binding scope to transient (new instance each time). ``` -------------------------------- ### Bind Token to Factory with Initializer Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/binding-types.md Binds a token to a class constructor and an initializer function. The initializer is called automatically after each instance is created. ```typescript import { Container, Factory, token } from 'brandi'; class ApiService { init() { /* ... */ } /* ... */ } const TOKENS = { apiServiceFactory: token>('Factory'), }; const container = new Container(); container .bind(TOKENS.apiServiceFactory) /* ↓ Binds the factory with the initializer. */ .toFactory(ApiService, (instance) => instance.init()); const apiServiceFactory = container.get(TOKENS.apiServiceFactory); /* ↓ The initializer will be called after the instance is created. */ const apiService = apiServiceFactory(); expect(apiService).toBeInstanceOf(ApiService); ``` -------------------------------- ### Define Tokens for Services Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/conditional-bindings.md Define tokens to represent different services that will be injected. These tokens serve as identifiers for Brandi's dependency injection system. ```typescript import { token } from 'brandi'; import type { Cacher } from './Cacher'; import type { UserService } from './UserService'; import type { SettingsService } from './SettingsService'; import type { AdminService } from './AdminService'; export const TOKENS = { cacher: token('cacher'), userService: token('userService'), settingsService: token('settingsService'), adminService: token('adminService'), }; ``` -------------------------------- ### Define API Key Token Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/dependency-modules.md Defines tokens for API key, API service, and application dependencies. These tokens are used to identify and inject dependencies. ```typescript import { token } from 'brandi'; import type { ApiService } from './api/ApiService'; import type { App } from './App'; export const TOKENS = { apiKey: token('apiKey'), apiService: token('apiService'), app: token('app'), }; ``` -------------------------------- ### Register Injected Dependencies for a Class Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/binding-types.md Use the `injected` registrator to specify dependencies required by a class constructor. This allows Brandi to automatically resolve and provide these dependencies when an instance of the class is created. ```typescript import { injected } from 'brandi'; import { TOKENS } from './tokens'; import type { HttpClient } from './HttpClient'; export class ApiService { constructor(private http: HttpClient) {} } injected(ApiService, TOKENS.httpClient); ``` -------------------------------- ### Create ApiService with API Key Dependency Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/dependency-modules.md Defines an ApiService class that depends on an API key. The `injected` function is used to declare the dependency for Brandi's injection system. ```typescript import { injected } from 'brandi'; import { TOKENS } from '../tokens'; export class ApiService { constructor(private apiKey: string) {} /* ... */ } injected(ApiService, TOKENS.apiKey); ``` -------------------------------- ### Use Injection in a Standard Component Source: https://github.com/vovaspace/brandi/blob/main/docs/brandi-react/tagged.md Demonstrates how to use the `useInjection` hook to retrieve a dependency (`TOKENS.apiService`) within a functional component. Without any specific tags applied to `UserComponent`, it will receive the default `ApiService`. ```tsx import { useInjection } from 'brandi-react'; import { FunctionComponent } from 'react'; import { TOKENS } from './tokens'; export const UserComponent: FunctionComponent = () => { /* ↓ Will be `ApiService`. */ const apiService = useInjection(TOKENS.apiService); /* ... */ return (/* ... */); } ``` -------------------------------- ### Define Tags for Conditional Binding Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/conditional-bindings.md Define tags that can be applied to services to enable conditional dependency injection. Tags allow grouping services for specific binding configurations. ```typescript import { tag } from 'brandi'; export const TAGS = { offline: tag('offline'), }; ``` -------------------------------- ### toConstant(value) Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/binding-types.md Binds a token to a specific, unchanging constant value. This is useful for configuration values or static data. ```APIDOC ## `toConstant(value)` Binds the token to the constant value. ### Arguments 1. `value`: `TokenType` — the value that will be bound to the token. ### Example ```typescript import { Container, token } from 'brandi'; const TOKENS = { apiKey: token('API Key'), }; const container = new Container(); container.bind(TOKENS.apiKey).toConstant('#key9428'); const key = container.get(TOKENS.apiKey); expect(key).toBe('#key9428'); ``` ``` -------------------------------- ### Bind to Singleton Scope Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/binding-scopes.md Use `inSingletonScope()` to ensure only one instance of a dependency is created and reused across all requests. ```typescript container.bind(TOKENS.apiService).toInstance(ApiService).inSingletonScope(); const apiServiceFirst = container.get(TOKENS.apiService); const apiServiceSecond = container.get(TOKENS.apiService); expect(apiServiceFirst).toBe(apiServiceSecond); ``` -------------------------------- ### Use Injection in a Tagged Component Source: https://github.com/vovaspace/brandi/blob/main/docs/brandi-react/tagged.md Shows how to wrap a component with a tag using the `withOfflineTag` HoC. Inside `SettingsComponent`, `useInjection(TOKENS.apiService)` will now resolve to `OfflineApiService` because the component is tagged with `TAGS.offline`. ```tsx import { useInjection } from 'brandi-react'; import { TOKENS } from './tokens'; import { withOfflineTag } from './tags'; /* ↓ Tags the component. */ export const SettingsComponent = withOfflineTag(() => { /* ↓ Will be `OfflineApiService`. */ const apiService = useInjection(TOKENS.apiService); /* ... */ return (/* ... */); }); ``` -------------------------------- ### Verify Conditional Injections Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/conditional-bindings.md Retrieve services from the configured container and assert that the correct Cacher implementation was injected based on the conditional bindings. ```typescript import { TOKENS } from './tokens'; import { OnlineCacher, LocalCacher } from './Cacher'; import { container } from './container'; const userService = container.get(TOKENS.userService); const settingsService = container.get(TOKENS.settingsService); const adminService = container.get(TOKENS.adminService); expect(userService.cacher).toBeInstanceOf(OnlineCacher); expect(settingsService.cacher).toBeInstanceOf(LocalCacher); expect(adminService.cacher).toBeInstanceOf(LocalCacher); ``` -------------------------------- ### Define Services with Cacher Dependency Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/conditional-bindings.md Define services that depend on the Cacher abstraction. The `injected` function registers these dependencies with Brandi. ```typescript import { injected } from 'brandi'; import { TOKENS } from './tokens'; import { Cacher } from './Cacher'; export class UserService { constructor(private cacher: Cacher) {} /* ... */ } injected(UserService, TOKENS.cacher); ``` ```typescript import { injected } from 'brandi'; import { TOKENS } from './tokens'; import { Cacher } from './Cacher'; export class SettingsService { constructor(private cacher: Cacher) {} /* ... */ } injected(SettingsService, TOKENS.cacher); ``` ```typescript import { injected } from 'brandi'; import { TOKENS } from './tokens'; import { Cacher } from './Cacher'; export class AdminService { constructor(private cacher: Cacher) {} /* ... */ } injected(AdminService, TOKENS.cacher); ``` -------------------------------- ### Define Tags and Tagged Component Source: https://github.com/vovaspace/brandi/blob/main/docs/brandi-react/tagged.md Defines a tag and creates a higher-order component (`withOfflineTag`) using the `tagged` HoC. This HoC will attach the specified tag to any component it wraps. ```typescript import { tag } from 'brandi'; import { tagged } from 'brandi-react'; export const TAGS = { offline: tag('offline'), }; export const withOfflineTag = tagged(TAGS.offline); ``` -------------------------------- ### Bind Token to Functional Factory Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/binding-types.md Binds a token to a standalone function that creates instances. Use this when the creation logic is encapsulated in a function rather than a class. ```typescript import { Container, Factory, token } from 'brandi'; interface ApiService { /* ... */ } const createApiService = (): ApiService => { /* ... */ }; const TOKENS = { apiServiceFactory: token>('Factory'), }; const container = new Container(); container.bind(TOKENS.apiServiceFactory).toFactory(createApiService); const apiServiceFactory = container.get(TOKENS.apiServiceFactory); const apiService = apiServiceFactory(); expect(apiService).toStrictEqual({ /* ... */ }); ``` -------------------------------- ### tagged(target, ...tags) Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/pointers-and-registrators.md Tags a target (constructor or function) with specified tags. Tags are used for conditional bindings. ```APIDOC ## tagged(target, ...tags) ### Description Tags a target (constructor or function) with specified tags. Tags are used for conditional bindings. ### Arguments - `target` - Constructor or function that will be tagged. - `...tags` (`Tag[]`) - Tags. ### Returns - `target` - The first argument. ### Example ```typescript import { tagged } from 'brandi'; import { TAGS } from './tags'; export class ApiService {} tagged(ApiService, TAGS.offline); ``` ``` -------------------------------- ### Define Cacher Interface and Implementations Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/conditional-bindings.md Define a common interface for Cacher and provide two distinct implementations: OnlineCacher and LocalCacher. This sets up the scenario for conditional injection. ```typescript export interface Cacher { /* ... */ } export class OnlineCacher implements Cacher { /* ... */ } export class LocalCacher implements Cacher { /* ... */ } ``` -------------------------------- ### Bind to Transient Scope Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/binding-scopes.md Use `inTransientScope()` to create a new instance of a dependency every time it is requested. ```typescript container.bind(TOKENS.apiService).toInstance(ApiService).inTransientScope(); const apiServiceFirst = container.get(TOKENS.apiService); const apiServiceSecond = container.get(TOKENS.apiService); expect(apiServiceFirst).not.toBe(apiServiceSecond); ``` -------------------------------- ### Use Generated Injection Hooks in a React Component Source: https://github.com/vovaspace/brandi/blob/main/docs/brandi-react/create-injection-hooks.md Demonstrates how to use the custom hooks generated by `createInjectionHooks` within a React functional component. The `useUserService` hook is called to retrieve the user service instance. ```tsx import { FunctionComponent } from 'react'; import { useUserService } from './hooks'; export const UserComponent: FunctionComponent = () => { const userService = useUserService(); /* ... */ return (/* ... */); } ``` -------------------------------- ### Async Factory Binding in TypeScript Source: https://github.com/vovaspace/brandi/blob/main/docs/reference/binding-types.md Use `AsyncFactory` to bind a factory that returns a Promise. The container will wait for the Promise to resolve before returning the instance. Ensure the factory function returns a Promise. ```typescript import { AsyncFactory, Container, token } from 'brandi'; class ApiService { init(): Promise { /* ... */ } /* ... */ } const TOKENS = { /* ↓ Token with `AsyncFactory` type. */ apiServiceFactory: token>( 'AsyncFactory', ), }; const container = new Container(); container .bind(TOKENS.apiServiceFactory) /* ↓ Returns a `Promise`. */ .toFactory(createApiService, (instance) => instance.init()); const apiServiceFactory = container.get(TOKENS.apiServiceFactory); /* ↓ Will wait for the initialization resolution. */ const apiService = await apiServiceFactory(); expect(apiService).toBeInstanceOf(ApiService); ```