syrinject 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +205 -2
- package/assets/Syringect-Black.png +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,208 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://cdn.jsdelivr.net/npm/syrinject@latest/assets/
|
|
2
|
+
<img src="https://cdn.jsdelivr.net/npm/syrinject@latest/assets/Syringect-Black.png" alt="Syrinject Logo" width="500" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
<
|
|
5
|
+
<p align="center">
|
|
6
|
+
<strong>A tiny, modern dependency injection container for TypeScript.</strong>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<hr>
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
Syrinject is a lightweight Dependency Injection (DI) container built for TypeScript. It focuses on clarity and explicitness while remaining flexible enough for small apps and larger codebases. You can register providers and resolve dependencies by token.
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- ✅ Simple DI container API.
|
|
18
|
+
- ✅ Typed tokens for safe resolution.
|
|
19
|
+
- ✅ Class, value, and factory providers.
|
|
20
|
+
- ✅ Singleton or transient lifetimes.
|
|
21
|
+
- ✅ Optional logging decorator for class usage.
|
|
22
|
+
- ✅ Clear error messages for invalid providers, missing dependencies, and circular graphs.
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install syrinject
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { Container } from "syrinject";
|
|
34
|
+
|
|
35
|
+
// Tokens can be string, symbol, or class constructors
|
|
36
|
+
const LoggerToken = "Logger";
|
|
37
|
+
|
|
38
|
+
interface Logger {
|
|
39
|
+
log(message: string): void;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
class ConsoleLogger implements Logger {
|
|
43
|
+
log(message: string) {
|
|
44
|
+
console.log(message);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const container = new Container();
|
|
49
|
+
|
|
50
|
+
// Register a token with a class provider
|
|
51
|
+
container.register(LoggerToken, {
|
|
52
|
+
useClass: ConsoleLogger,
|
|
53
|
+
singleton: true,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const logger = container.resolve<Logger>(LoggerToken);
|
|
57
|
+
logger.log("Hello from Syrinject!");
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Core Concepts
|
|
61
|
+
|
|
62
|
+
### Tokens
|
|
63
|
+
|
|
64
|
+
Tokens are identifiers for dependencies. Use a `string`, `symbol`, or a class constructor.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
export interface HttpClient {
|
|
68
|
+
get(url: string): Promise<string>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const HttpClientToken = "HttpClient";
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Providers
|
|
75
|
+
|
|
76
|
+
Providers define how a dependency is created.
|
|
77
|
+
|
|
78
|
+
#### Class Provider
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
container.register(HttpClientToken, {
|
|
82
|
+
useClass: FetchHttpClient,
|
|
83
|
+
singleton: false,
|
|
84
|
+
deps: [LoggerToken],
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
#### Value Provider
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
container.register(HttpClientToken, {
|
|
92
|
+
useValue: { get: async (url) => fetch(url).then((r) => r.text()) },
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
#### Factory Provider
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
container.register(HttpClientToken, {
|
|
100
|
+
useFactory: (c) => new FetchHttpClient(c.resolve(LoggerToken)),
|
|
101
|
+
singleton: true,
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Lifetimes
|
|
106
|
+
|
|
107
|
+
- `singleton: true` creates and caches a single instance.
|
|
108
|
+
- `singleton: false` creates a new instance on each resolve (default).
|
|
109
|
+
|
|
110
|
+
### Decorator: Logger
|
|
111
|
+
|
|
112
|
+
Syrinject includes a `Logger` decorator that logs instantiation and public method calls.
|
|
113
|
+
To show dependencies and singleton status in logs, set static `deps` (or `dependencies`) and `singleton` on the class.
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { Container, Logger } from "syrinject";
|
|
117
|
+
|
|
118
|
+
const LoggerToken = "Logger";
|
|
119
|
+
|
|
120
|
+
interface LoggerService {
|
|
121
|
+
log(message: string): void;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
class ConsoleLogger implements LoggerService {
|
|
125
|
+
log(message: string) {
|
|
126
|
+
console.log(message);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@Logger()
|
|
131
|
+
class UserService {
|
|
132
|
+
static deps = [LoggerToken];
|
|
133
|
+
static singleton = true;
|
|
134
|
+
|
|
135
|
+
constructor(private readonly logger: LoggerService) {}
|
|
136
|
+
|
|
137
|
+
createUser(name: string) {
|
|
138
|
+
this.logger.log(`Creating user: ${name}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const container = new Container();
|
|
143
|
+
container.register(LoggerToken, { useClass: ConsoleLogger, singleton: true });
|
|
144
|
+
container.register(UserService, { useClass: UserService, deps: UserService.deps, singleton: true });
|
|
145
|
+
|
|
146
|
+
const service = container.resolve(UserService);
|
|
147
|
+
service.createUser("Ada");
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Container API
|
|
151
|
+
|
|
152
|
+
### `register(token, provider)`
|
|
153
|
+
|
|
154
|
+
Registers a provider for a token.
|
|
155
|
+
|
|
156
|
+
### `resolve(token)`
|
|
157
|
+
|
|
158
|
+
Resolves an instance for the given token.
|
|
159
|
+
|
|
160
|
+
### `unregister(token)`
|
|
161
|
+
|
|
162
|
+
Removes a token from the container.
|
|
163
|
+
|
|
164
|
+
### `clear()`
|
|
165
|
+
|
|
166
|
+
Clears all registrations.
|
|
167
|
+
|
|
168
|
+
### `has(token)`
|
|
169
|
+
|
|
170
|
+
Checks if a token is registered.
|
|
171
|
+
|
|
172
|
+
### `registerClass(...)`
|
|
173
|
+
|
|
174
|
+
Registers a class provider. You can pass a token + class, or only a class.
|
|
175
|
+
When only a class is provided, the token will be the class name (string).
|
|
176
|
+
|
|
177
|
+
### `registerValue(token, value)`
|
|
178
|
+
|
|
179
|
+
Registers a value provider.
|
|
180
|
+
|
|
181
|
+
### `registerFactory(token, factory, options?)`
|
|
182
|
+
|
|
183
|
+
Registers a factory provider.
|
|
184
|
+
|
|
185
|
+
## Errors
|
|
186
|
+
|
|
187
|
+
Syrinject throws descriptive errors to simplify debugging:
|
|
188
|
+
|
|
189
|
+
- `DependencyNotFoundError` when a token is not registered.
|
|
190
|
+
- `InvalidProviderError` when a provider is malformed.
|
|
191
|
+
- `CircularDependencyError` when a dependency graph loops.
|
|
192
|
+
|
|
193
|
+
## TypeScript Configuration
|
|
194
|
+
|
|
195
|
+
If you use the `Logger` decorator, enable decorators in `tsconfig.json`:
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"compilerOptions": {
|
|
200
|
+
"experimentalDecorators": true,
|
|
201
|
+
"emitDecoratorMetadata": false
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
|
|
208
|
+
MIT
|
|
Binary file
|