{"id":29436869,"url":"https://github.com/stone-foundation/stone-js-service-container","last_synced_at":"2025-10-30T07:48:43.409Z","repository":{"id":189417323,"uuid":"680634787","full_name":"stone-foundation/stone-js-service-container","owner":"stone-foundation","description":"Javascript/Typescript IoC Service Container with proxy resolver and destructuring injection","archived":false,"fork":false,"pushed_at":"2025-06-12T02:18:35.000Z","size":594,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-12T02:26:01.062Z","etag":null,"topics":["context-aware","continuum-architecture","javascript","official-stonejs","stone-foundation","stonejs","stonejs-core","typescript"],"latest_commit_sha":null,"homepage":"https://stonejs.dev","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stone-foundation.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-08-19T22:10:04.000Z","updated_at":"2025-06-12T02:17:01.000Z","dependencies_parsed_at":"2024-04-03T02:23:47.469Z","dependency_job_id":"8347faee-60a3-448f-bbfe-77ab3ca52486","html_url":"https://github.com/stone-foundation/stone-js-service-container","commit_stats":null,"previous_names":["noowow-community/service-container-js","noowow-community/service-container","stonemjs/service-container","stone-foundation/stone-js-service-container"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/stone-foundation/stone-js-service-container","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stone-foundation%2Fstone-js-service-container","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stone-foundation%2Fstone-js-service-container/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stone-foundation%2Fstone-js-service-container/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stone-foundation%2Fstone-js-service-container/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stone-foundation","download_url":"https://codeload.github.com/stone-foundation/stone-js-service-container/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stone-foundation%2Fstone-js-service-container/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264968411,"owners_count":23690817,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["context-aware","continuum-architecture","javascript","official-stonejs","stone-foundation","stonejs","stonejs-core","typescript"],"created_at":"2025-07-13T05:06:55.012Z","updated_at":"2025-10-30T07:48:43.389Z","avatar_url":"https://github.com/stone-foundation.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Stone.js - Service Container\n\n[![npm](https://img.shields.io/npm/l/@stone-js/service-container)](https://opensource.org/licenses/MIT)\n[![npm](https://img.shields.io/npm/v/@stone-js/service-container)](https://www.npmjs.com/package/@stone-js/service-container)\n[![npm](https://img.shields.io/npm/dm/@stone-js/service-container)](https://www.npmjs.com/package/@stone-js/service-container)\n![Maintenance](https://img.shields.io/maintenance/yes/2025)\n[![Build Status](https://github.com/stone-foundation/stone-js-service-container/actions/workflows/main.yml/badge.svg)](https://github.com/stone-foundation/stone-js-service-container/actions/workflows/main.yml)\n[![Publish Package to npmjs](https://github.com/stone-foundation/stone-js-service-container/actions/workflows/release.yml/badge.svg)](https://github.com/stone-foundation/stone-js-service-container/actions/workflows/release.yml)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=stone-foundation_stone-js-service-container\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=stone-foundation_stone-js-service-container)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=stone-foundation_stone-js-service-container\u0026metric=coverage)](https://sonarcloud.io/summary/new_code?id=stone-foundation_stone-js-service-container)\n[![Security Policy](https://img.shields.io/badge/Security-Policy-blue.svg)](./SECURITY.md)\n[![CodeQL](https://github.com/stone-foundation/stone-js-service-container/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/stone-foundation/stone-js-service-container/security/code-scanning)\n[![Dependabot Status](https://img.shields.io/badge/Dependabot-enabled-brightgreen.svg)](https://github.com/stone-foundation/stone-js-service-container/network/updates)\n[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org)\n\nIoC Service Container with proxy resolver and destructuring injection provides a very simple, centralized container that stores and resolves libraries, objects, and values to better organize code, manage dependencies, and enhance testability.\n\n---\n\n## Overview\n\nThe **Service Container** is an advanced JavaScript/TypeScript library that helps you manage dependencies effectively in your applications. It utilizes the Inversion of Control (IoC) pattern to simplify dependency injection, allowing you to create highly decoupled and maintainable codebases.\n\nBy using Dependency Injection (DI), the service container ensures that objects are provided with their dependencies from an external source, rather than creating them internally. This approach improves testability, minimizes code duplication, and promotes the Single Responsibility Principle by allowing objects to focus only on their primary functions.\n\nIn addition to DI, the **Service Container** implements the Proxy pattern, which lets you access dependencies as properties of the container itself. This feature, combined with destructuring, enables a streamlined approach to dependency injection, making it easy to use dependencies without the need for extra boilerplate code.\n\nWith the **Service Container**, you can easily register, resolve, and manage dependencies, making it suitable for projects of any scale. It supports binding instances, singletons, and factories, as well as providing auto and conditional binding options. This flexibility makes your application more modular, scalable, and maintainable, while ensuring efficient dependency management throughout the development process.\n\n## Installation\n\nThe `Service Container` library is available from the [`npm registry`](https://www.npmjs.com/) and can be installed as follows:\n\n```bash\nnpm i @stone-js/service-container\n```\n\nYarn:\n\n```bash\nyarn add @stone-js/service-container\n```\n\nPNPM:\n\n```bash\npnpm add @stone-js/service-container\n```\n\n\u003e [!IMPORTANT]\n\u003e This package is **pure ESM**. Ensure your `package.json` includes `\"type\": \"module\"` or configure your bundler appropriately.\n\nMake sure your project setup is compatible with ESM. This might involve updating your `package.json` or using certain bundler configurations.\n\nThe `Service Container` module can only be imported via ESM import syntax:\n\n```typescript\nimport { Container } from '@stone-js/service-container';\n```\n\n## Getting Started\n\nTo get started with the `Service Container`, you need to import the `Container` class and create an instance of it. This instance will act as the central registry for all your dependencies in your application.\n\nLet's begin with a simple example to discover the power of the service container by logging a message.\n\n### 1. Create the `Logger` Class\n\nFirst, create a simple `Logger` class to log messages:\n\n```typescript\n// Your Logger class\nclass Logger {\n  log(message: string) {\n    console.log(message);\n  }\n}\n```\n\n### 2. Create the Class that Provides the Message\n\nNext, create a class `A` that provides a message to be logged:\n\n```typescript\n// Your class A\nclass A {\n  getMessage(): string {\n    return 'Hello World!';\n  }\n}\n```\n\n### 3. Create the Class that Logs the Message Using the Logger\n\nNow, create a class `B` that depends on `Logger` and `A` to log the message:\n\n```typescript\n// Your class B\nclass B {\n  private readonly a: A;\n  private readonly logger: Logger;\n\n  constructor({ a, logger }: { a: A, logger: Logger }) { // Dependency injection by destructuring\n    this.a = a\n    this.logger = logger\n  }\n\n  logMessage() {\n    this.logger.log(this.a.getMessage());\n  }\n}\n```\n\n### 4. Use the Container to Manage Dependencies\n\nFinally, create an instance of the `Container` class and use it to manage these dependencies:\n\n```typescript\nimport { Container } from '@stone-js/service-container';\n\n// Create a container instance\nconst container = new Container();\n\n// Auto-register components\ncontainer\n  .autoBinding(A)\n  .autoBinding(B)\n  .autoBinding(Logger)\n  .alias(A, 'a')\n  .alias(B, 'b')\n  .alias(Logger, 'logger');\n\n// Make B instance\nconst b = container.make(B);\n\n// Call logMessage method\nb.logMessage(); // Output: Hello World!\n```\n\nIn this guide, we covered how to define and register dependencies using the `Container` class, and how to leverage dependency injection through destructuring and the Proxy pattern.\n\nBy following these steps, you can effectively manage dependencies in your applications, making them more modular, testable, and maintainable.\n\n## Usage\n\nThe true power of Stone Service Container lies in its ability to simplify and enhance the management of dependencies within your application. By leveraging the Inversion of Control (IoC) and Proxy patterns, the library offers a highly flexible and intuitive way to bind, resolve, and inject dependencies. Whether you're working with simple instances, complex singletons, or dynamic factories, the Service Container provides a robust foundation for building scalable and maintainable applications.\n\n### Binding\n\nYou can bind instances, singletons, and factories to the container using various methods provided by the `Container` class.\n\n#### Instance\n\nTo bind a single instance or value to the container:\n\n```typescript\n// Bind value\ncontainer.instance('config', { apiUrl: 'https://api.example.com' });\n\n// Bind instance\ncontainer.instance('ApiUrl', new URL('https://api.example.com'));\n```\n\n#### Singleton\n\nTo bind a resolver function that returns a singleton instance:\n\n```typescript\n// Bind a singleton using a resolver function\ncontainer.singleton('logger', () =\u003e new Logger());\n\n// Resolve the singleton (same instance every time)\nconst logger1 = container.make('logger');\nconst logger2 = container.make('logger');\nconsole.log(logger1 === logger2); // Should output: true\n```\n\n#### Factory\n\nTo bind a resolver function that returns a new instance each time:\n\n```typescript\n// To bind a resolver function that returns a new instance each time\ncontainer.binding('userService', () =\u003e new UserService());\n```\n\n### Auto Binding\n\nThe `autoBinding` method in the service container simplifies the process of binding dependencies by ensuring they are only bound if not already present in the container. This method can be used implicitly or explicitly, providing flexibility in how dependencies are registered and resolved.\n\n#### Implicit Auto Binding\n\nImplicit auto binding allows you to automatically register and bind a class to the container using the class's own name. This approach simplifies dependency management by using the class name as the key for resolution.\n\n```typescript\n// Auto binding Logger\ncontainer.autoBinding(Logger);\n\n// Resolve Logger (it will be registered implicitly if not found)\nconst logger = container.make('Logger'); // Prefer to use a string key for clarity.\n```\n\n#### Explicit Auto Binding\n\nExplicit auto binding allows you to register and bind a class to the container with a specified key, as a singleton or factory, and with optional aliases. This method offers greater flexibility in naming and accessing dependencies.\n\n```typescript\n// Auto binding Logger with specified key and aliases\ncontainer.autoBinding('logger', Logger, true, ['logging', 'log']);\n\n// Resolve Logger using different aliases\nconst logger = container.make('logger');\nconst loggerByAlias = container.make('logging');\n```\n\n### Conditional Binding\n\nYou can bind instances, singletons, and factories to the container conditionally using various methods provided by the `Container` class.\n\n#### Instance\n\nTo bind a single instance or value to the container, if it is not already bound:\n\n```typescript\n// Bind value conditionally\ncontainer.instanceIf('config', { apiUrl: 'https://api.example.com' });\n\n// Bind instance conditionally\ncontainer.instanceIf('ApiUrl', new URL('https://api.example.com'));\n```\n\n#### Singleton\n\nTo bind a resolver function that returns a singleton instance, if it is not already bound:\n\n```typescript\ncontainer.singletonIf('logger', () =\u003e new Logger());\n```\n\n#### Factory\n\nTo bind a resolver function that returns a new instance each time, if it is not already bound:\n\n```typescript\ncontainer.bindingIf('userService', () =\u003e new UserService());\n```\n\n### Resolving Dependencies\n\nYou can resolve dependencies from the container using the `make` method:\n\n```typescript\nconst config = container.make('config');\nconst logger = container.make('logger');\nconst userService = container.make('userService');\n```\n\n### On-Demand Resolving\n\nThis method provides a convenient way to resolve a value from the container by its key and return it wrapped in a factory function. This approach is useful when you need to create multiple instances of a dependency on demand.\n\n```typescript\n// Get the logger factory function\nconst loggerFactory = container.factory('logger');\n\n// Resolve logger on demand\nconst logger = loggerFactory();\n```\n\n### Conditional Resolving\n\nThis method checks if the dependency is already bound in the container. If it is, the dependency is resolved. If not, the method binds the dependency and then resolves it. This ensures that dependencies are always available when needed, without redundant bindings.\n\n```typescript\n// Assuming Logger is a class that we want to ensure is bound and resolved\ncontainer.resolve('Logger', true);\n\n// Resolve the logger instance\nconst logger = container.make('Logger');\n```\n\n### Using Aliases\n\nAliases allow you to reference bindings by alternative names.\n\n#### Setting Aliases\n\nTo set an alias for a binding:\n\n```typescript\n// Set an alias for Logger\ncontainer.alias(Logger, ['logger', 'logging', 'log']);\n```\n\n#### Retrieving Aliases\n\nTo retrieve a binding by its alias:\n\n```typescript\nconst logger = container.make('logging');\n```\n\n### Checking Bindings\n\nYou can check if a binding or alias exists in the container:\n\n```typescript\n// With bound method\nconst hasLogger = container.bound(Logger); // true\n\n// Can be used with alias\nconst hasLoggerAlias = container.bound('logging'); // true\n\n// An alias of bound method\nconst hasLoggerAliasUsingHas = container.has(Logger); // true\n\n// Check if this alias exists\nconst isAlias = container.isAlias('logging'); // true\n```\n\n### Clearing the Container\n\nTo remove all bindings and reset the container:\n\n```typescript\n// Clear all bindings and aliases\ncontainer.clear();\n```\n\nWith this library, managing dependencies in your application becomes much simpler and more efficient. By adhering to the principles of Inversion of Control and Dependency Injection, you can create more modular, testable, and maintainable code.\n\n\n## Summary\n\nThe Stone Service Container simplifies dependency management in your applications, making them more modular, testable, and maintainable. It provides tools for binding instances, singletons, and factories, as well as auto and conditional binding. By leveraging Inversion of Control and dependency injection, the service container ensures efficient, flexible, and scalable management of dependencies, fitting projects of any size.\n\n## Learn More\n\nThis package is part of the Stone.js ecosystem, a modern JavaScript framework built around the Continuum Architecture.\n\nExplore the full documentation: [https://stonejs.dev](https://stonejs.dev)\n\n## API documentation\n\n- [API](https://github.com/stone-foundation/stone-js-service-container/blob/main/docs/modules.md)\n\n## Contributing\n\nSee [Contributing Guide](https://github.com/stone-foundation/stone-js-service-container/blob/main/CONTRIBUTING.md).\n\n## Credits\n- [Laravel Service Container](https://github.com/illuminate/container)\n- [Halligan JS: Service Container](https://github.com/halliganjs/service-container)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstone-foundation%2Fstone-js-service-container","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstone-foundation%2Fstone-js-service-container","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstone-foundation%2Fstone-js-service-container/lists"}