Skip to content
This repository was archived by the owner on Apr 21, 2024. It is now read-only.

Commit 7765406

Browse files
authored
Merge pull request #4 from Coder-Spirit/sync-and-async-deps
Split synchronous & asynchronous resolution
2 parents 5d8414a + de6c673 commit 7765406

10 files changed

+672
-255
lines changed

README.md

+36-4
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,51 @@ import { ... } from 'https://deno.land/x/lambda_ioc@[VERSION]/lambda-ioc/deno/in
5858
## Example
5959

6060
```ts
61-
import { createContainer } from '@coderspirit/lambda-ioc'
61+
import {
62+
constructor,
63+
createContainer,
64+
func
65+
} from '@coderspirit/lambda-ioc'
6266

6367
function printNameAndAge(name: string, age: number) {
6468
console.log(`${name} is aged ${age}`)
6569
}
70+
71+
class Person {
72+
constructor(
73+
public readonly age: number,
74+
public readonly name: string
75+
) {}
76+
}
6677
6778
const container = createContainer()
6879
.registerValue('someAge', 5)
6980
.registerValue('someName', 'Timmy')
81+
// We can register functions
7082
.register('fn', func(printNameAndAge, 'someName', 'someAge'))
83+
// And constructors too
84+
.register('Person', constructor(Person, 'someAge', 'someName'))
7185
72-
// For now it's always async, we'll improve its API to decide when to expose
73-
// the registered dependencies synchronously or asynchronoyusly in a smart way.
74-
const print = await container.resolve('fn')
86+
const print = container.resolve('fn')
7587
print() // Prints "Timmy is aged 5"
88+
89+
const person = container.resolve('Person')
90+
console.print(person.age) // Prints "5"
91+
console.print(person.name) // Prints "Timmy"
7692
```
93+
94+
It is also possible to register and resolve asynchronous factories and
95+
dependencies. They are not documented yet because some "helpers" are missing,
96+
and therefore it's a bit more annoying to take advantage of that feature.
97+
98+
If you are curious, just try out:
99+
- `registerAsync`
100+
- `resolveAsync`
101+
102+
## Differences respect to Diddly
103+
104+
- First-class support for Deno.
105+
- First-class support for asynchronous dependency resolution.
106+
- The container interface has been split into `ReaderContainer` and
107+
`WriterContainer`, making it easier to use precise types.
108+
- More extense documentation.

lambda-ioc/deno/combinators.ts

+34-27
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
22
ContainerKey,
3-
DependencyFactory,
43
ReadableContainer,
4+
SyncDependencyFactory,
55
} from './container.ts';
66
import { ParamsToResolverKeys, TupleO, Zip } from './util.ts';
77

@@ -13,13 +13,15 @@ export function singleton<
1313
TVal,
1414
TDependencies extends Record<ContainerKey, unknown>,
1515
>(
16-
factory: DependencyFactory<TVal, ReadableContainer<TDependencies>>,
17-
): DependencyFactory<TVal, ReadableContainer<TDependencies>> {
18-
let result: TVal | undefined
16+
// eslint-disable-next-line @typescript-eslint/ban-types
17+
factory: SyncDependencyFactory<TVal, ReadableContainer<TDependencies, {}>>,
18+
// eslint-disable-next-line @typescript-eslint/ban-types
19+
): SyncDependencyFactory<TVal, ReadableContainer<TDependencies, {}>> {
20+
let result: Awaited<TVal> | undefined
1921

20-
return async (container) => {
22+
return (container) => {
2123
if (!result) {
22-
result = await factory(container)
24+
result = factory(container)
2325
}
2426
return result
2527
}
@@ -37,17 +39,19 @@ export function func<
3739
>(
3840
fn: (...args: TParams) => Awaited<TReturn>,
3941
...args: TDependencies
40-
): DependencyFactory<() => TReturn, FuncContainer<TParams, TDependencies>> {
41-
return async (container: FuncContainer<TParams, TDependencies>) => {
42-
const argPromises = args.map((arg) =>
42+
): SyncDependencyFactory<
43+
() => TReturn,
44+
SyncFuncContainer<TParams, TDependencies>
45+
> {
46+
return (container: SyncFuncContainer<TParams, TDependencies>) => {
47+
const resolvedArgs = args.map((arg) =>
4348
container.resolve(
4449
// This is ugly as hell, but I did not want to apply ts-ignore
45-
arg as Parameters<FuncContainer<TParams, TDependencies>['resolve']>[0],
50+
arg as Parameters<
51+
SyncFuncContainer<TParams, TDependencies>['resolve']
52+
>[0],
4653
),
47-
)
48-
const resolvedArgs = (await Promise.all(
49-
argPromises as Promise<unknown>[],
50-
)) as unknown as TParams
54+
) as unknown as TParams
5155

5256
return () => fn(...resolvedArgs)
5357
}
@@ -62,19 +66,18 @@ export function constructor<
6266
TClass,
6367
TDependencies extends ParamsToResolverKeys<TParams>,
6468
>(
65-
constructor: new (...args: TParams) => TClass,
69+
constructor: new (...args: TParams) => Awaited<TClass>,
6670
...args: TDependencies
67-
): DependencyFactory<TClass, FuncContainer<TParams, TDependencies>> {
68-
return async (container: FuncContainer<TParams, TDependencies>) => {
69-
const argPromises = args.map((arg) =>
71+
): SyncDependencyFactory<TClass, SyncFuncContainer<TParams, TDependencies>> {
72+
return (container: SyncFuncContainer<TParams, TDependencies>) => {
73+
const resolvedArgs = args.map((arg) =>
7074
container.resolve(
7175
// This is ugly as hell, but I did not want to apply ts-ignore
72-
arg as Parameters<FuncContainer<TParams, TDependencies>['resolve']>[0],
76+
arg as Parameters<
77+
SyncFuncContainer<TParams, TDependencies>['resolve']
78+
>[0],
7379
),
74-
)
75-
const resolvedArgs = (await Promise.all(
76-
argPromises as Promise<unknown>[],
77-
)) as unknown as TParams
80+
) as unknown as TParams
7881

7982
return new constructor(...resolvedArgs)
8083
}
@@ -83,10 +86,14 @@ export function constructor<
8386
// -----------------------------------------------------------------------------
8487
// Private Types
8588
// -----------------------------------------------------------------------------
86-
type FuncContainer<
89+
type SyncFuncContainer<
8790
TParams extends readonly unknown[],
88-
TDependencies extends ParamsToResolverKeys<TParams>,
91+
TSyncDependencies extends ParamsToResolverKeys<TParams>,
8992
> = ReadableContainer<
90-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
91-
TupleO<Extract<Zip<TDependencies, TParams>, readonly [ContainerKey, any][]>>
93+
TupleO<
94+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
95+
Extract<Zip<TSyncDependencies, TParams>, readonly [ContainerKey, any][]>
96+
>,
97+
// eslint-disable-next-line @typescript-eslint/ban-types
98+
{}
9299
>

0 commit comments

Comments
 (0)