Skip to content

Commit

Permalink
Merge pull request #10 from aedart/add-service-container
Browse files Browse the repository at this point in the history
Add Service Container
  • Loading branch information
aedart committed Apr 9, 2024
2 parents ed9b6ea + b862c57 commit 54e81ff
Show file tree
Hide file tree
Showing 170 changed files with 8,446 additions and 611 deletions.
34 changes: 32 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,48 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

* Add upgrade guide from v0.7.x- to v0.10.x.
* Service Container package (`@aedart/container`).
* `Facade` abstraction, in `@aedart/support/facades`.
* `DEPENDENCIES` symbol and `Identifier` type in `@aedart/contracts/container`.
* `dependsOn()`, `dependencies()`, `hasDependencies()`, and `getDependencies()`, in `@aedart/support/container`.
* `isBindingIdentifier`, in `@aedart/support/container`.
* `ClassMethodName` and `ClassMethodReference` type aliases in `@aedart/contracts`.
* `isMethod()` util in `@aedart/support/reflections`.
* `ConstructorLike` and `Callback` type aliases, in `@aedart/constracts`.
* `CallbackWrapper` util class, in `@aedart/support`.
* `isCallbackWrapper` util, in `@aedart/support`.
* `ArbitraryData` concern, in `@aedart/support`.
* `arrayMergeOptions` in object `merge()`.
* Add upgrade guide for "v0.7.x- to v0.10.x".

### Changed

**Breaking**

* Added `hasAny()` method in `TargetRepository` interface, in `@aedart/contracts/meta`.
* Default generic for `defaultValue` changed to `undefined`, for `get()` methods in meta `Repository` and `TargetRepository`.

**Non-breaking Changes**

* Root package Typescript dependency changed to `^5.4.2`.
* `@typescript-eslint/eslint-plugin` upgraded to `^7.1.1`, in root package.
* Decorator return types for `meta()`, `targetMeta()`, and `inheritTargetMeta()` (_continued to cause TS1270 and TS1238 errors_). [#8](https://github.com/aedart/ion/pull/8), [#9](https://github.com/aedart/ion/pull/9).
* Refactored all classes' fields, changed from private to protected visibility (_see [private is not inherited](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain) for details in_).
* Removed decorator return types for `use()`, `meta()`, `targetMeta()`, and `inheritTargetMeta()` (_continued to cause TS1270 and TS1238 errors_). [#8](https://github.com/aedart/ion/pull/8), [#9](https://github.com/aedart/ion/pull/9).
* Refactored `hasAllMethods()` to use new `isMethod()` internally, in `@aedart/support/reflections`.
* Refactored all components that used deprecated `ConstructorOrAbstractConstructor` to use new `ConstructorLike` type alias.
* Marked `isClassConstructor()` and `isCallable()` as stable, in `@aedart/support/reflections`.
* Refactored / redesigned the array `merge()` to use a new `ArrayMerger` component, that allows custom merge callback and options.

### Fixed

* Decorator types aliases (_TS1270 and TS1238 issues when applying the various decorator and decorator result types_). [#8](https://github.com/aedart/ion/pull/8).
* Broken link in docs for `isArrayLike`.
* Missing `tslib` as peer dependency for `@aedart/support` package.
* Unable to merge arrays containing functions, in `MetaRepository`.

### Deprecated

* `ConstructorOrAbstractConstructor` type alias. It has been replaced with the new `ConstructorLike` type., in `@aedart/constracts`.

## [0.10.0] - 2024-03-07

Expand Down
4 changes: 2 additions & 2 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ NOTICES AND INFORMATION
Please do not translate or Localize.

Parts of the herein provided software are considered an "adaptation", or "derivative work", of 3rd party software.
Below you will find general information about which parts are affected, or where you may find additional information
such, along with original license(s), terms and conditions as provided by the 3rd party software.
Below you will find general information about which parts are affected, or where you may find additional information,
along with original license(s), terms and conditions as provided by the 3rd party software.

3rd party software that are included as dependencies by this software is NOT covered by this NOTICE file, unless
explicitly required by 3rd party software license(s). You can find original license(s), terms and
Expand Down
5 changes: 5 additions & 0 deletions aliases.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@ module.exports = {
// conditionNames: ['require', 'import'],

alias: {
// container
'@aedart/container': path.resolve(__dirname, './packages/container/src'),

// contracts
'@aedart/contracts/container': path.resolve(__dirname, './packages/contracts/container'),
'@aedart/contracts/support/arrays': path.resolve(__dirname, './packages/contracts/support/arrays'),
'@aedart/contracts/support/concerns': path.resolve(__dirname, './packages/contracts/support/concerns'),
'@aedart/contracts/support/exceptions': path.resolve(__dirname, './packages/contracts/support/exceptions'),
'@aedart/contracts/support/facades': path.resolve(__dirname, './packages/contracts/support/facades'),
'@aedart/contracts/support/meta': path.resolve(__dirname, './packages/contracts/support/meta'),
'@aedart/contracts/support/mixins': path.resolve(__dirname, './packages/contracts/support/mixins'),
'@aedart/contracts/support/objects': path.resolve(__dirname, './packages/contracts/support/objects'),
Expand Down
26 changes: 26 additions & 0 deletions docs/.vuepress/archive/Version0x.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ export default PagesCollection.make('v0.x', '/v0x', [
collapsible: true,
children: [
'packages/',
{
text: 'Container',
collapsible: true,
children: [
'packages/container/',
'packages/container/prerequisites',
'packages/container/install',
'packages/container/container-instance',
'packages/container/bindings',
'packages/container/dependencies',
'packages/container/resolving',
'packages/container/contextual-bindings',
]
},
{
text: 'Contracts',
collapsible: true,
Expand Down Expand Up @@ -77,6 +91,13 @@ export default PagesCollection.make('v0.x', '/v0x', [
'packages/support/exceptions/customErrors',
]
},
{
text: 'Facades',
collapsible: true,
children: [
'packages/support/facades/',
]
},
{
text: 'Meta',
collapsible: true,
Expand Down Expand Up @@ -141,9 +162,13 @@ export default PagesCollection.make('v0.x', '/v0x', [
'packages/support/reflections/hasAllMethods',
'packages/support/reflections/hasMethod',
'packages/support/reflections/hasPrototypeProperty',
'packages/support/reflections/isCallable',
'packages/support/reflections/isClassConstructor',
'packages/support/reflections/isClassMethodReference',
'packages/support/reflections/isConstructor',
'packages/support/reflections/isKeySafe',
'packages/support/reflections/isKeyUnsafe',
'packages/support/reflections/isMethod',
'packages/support/reflections/isSubclass',
'packages/support/reflections/isSubclassOrLooksLike',
'packages/support/reflections/isWeakKind',
Expand All @@ -164,6 +189,7 @@ export default PagesCollection.make('v0.x', '/v0x', [
'packages/support/misc/toWeakRef',
]
},
'packages/support/CallbackWrapper',
]
},
{
Expand Down
40 changes: 40 additions & 0 deletions docs/archive/current/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,46 @@ _TBD: "To be decided"._

## `v0.x` Highlights

### Service Container <Badge type="tip" text="Available since v0.11" />

An adaptation of Laravel's Service Container that offers a way to with powerful tool to manage dependencies and perform
dependency injection.

```js
import { Container } from "@aedart/container";

container.bind('storage', () => {
return new CloudService('s3');
});

// Later in your application.
const storage = container.make('storage');
```

For additional examples, see the [Service Container documentation](./packages/container/README.md).

### Facades <Badge type="tip" text="Available since v0.11" />

Adaptation of Laravel's Facade component. It acts as an interface or gateway to an underlying object that is resolved
from the Service Container.

```js
import { Facade } from "@aedart/support/facades";

export default class ApiFacade extends Facade
{
static getIdentifier()
{
return 'api_client';
}
}

// Later in your application
const promise = ApiFacade.obtain().fetch('https://acme.com/api/users');
```

See the [Facades documentation](./packages/support/facades/README.md) for additional details.

### Concerns <Badge type="tip" text="Available since v0.9" />

Intended as an alternative to mixins, the [Concerns](./packages/support/concerns/README.md) submodule offers a different
Expand Down
83 changes: 83 additions & 0 deletions docs/archive/current/packages/container/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: Introduction
description: Ion Service Container package
sidebarDepth: 0
---

# Introduction <Badge type="tip" text="Available since v0.11" vertical="middle" /><Badge type="success" text="Browser" vertical="middle" />

The `@aedart/container` package offers an adaptation of [Laravel's Service Container](https://laravel.com/docs/11.x/container)
(_originally licensed under [MIT](https://github.com/laravel/framework/blob/11.x/src/Illuminate/Container/LICENSE.md)_).

The tools provided by this package give you a way to:
* Manage class dependencies
* Perform [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection)

## Example

### Bindings

Imagine that you have an Api client (_or any component for that matter_). Whenever it is needed, you want it to be
injected into components that depend on it.

```js
export default class ApiClient
{
// ...implementation not shown...
}
```

To ensure that dependency injection can be performed, you must first bind the component in the service container.
Each binding requires a unique identifier, e.g. a string, symbol, number...etc.

```js
import { Container } from "@aedart/container";
import { ApiClient } from "@acme/api";

const container = Container.getInstance();

// Bind 'my_api_client' to the ApiClient component...
container.bind('my_api_client', ApiClient);
```

### Define Dependencies

To define the dependencies of a component, use the `dependencies()` decorator.
By itself, the decorator does not do anything more than to associate a component with one or more dependencies
(_binding identifiers_). In other words, the decorator _**does not automatically inject**_ anything into your class.
It only registers the dependencies as [metadata](../support/meta) onto a class.

```js
import { dependencies } from "@aedart/support/container";

@dependencies('my_api_client')
export default class BookService
{
apiClient;

constructor(client) {
this.apiClient = client;
}

// ...remaining not shown...
}
```

### Resolve

When you want to resolve a component, with all of its dependencies injected into it, use the service container's `make()`
method.

```js
import { Container } from "@aedart/container";
import { BookService } from "@acme/app/services";

const bookService = Container.getInstance().make(BookService);

console.log(bookService.apiClient); // ApiClient
```

### Onward

The above shown example illustrates the most basic usage of the service container. Throughout the remaining of this
package's documentation, more examples and use-cases are covered.
Loading

0 comments on commit 54e81ff

Please sign in to comment.