navi-di 0.1.0 → 1.0.0
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/CONTRIBUTING.md +3 -1
- package/README.md +56 -6
- package/dist/decorators/inject.d.ts +2 -2
- package/dist/decorators/service.d.ts +2 -1
- package/dist/decorators/service.js +11 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/tokens/index.d.ts +1 -0
- package/dist/tokens/index.js +1 -0
- package/dist/tokens/token.d.ts +5 -0
- package/dist/tokens/token.js +10 -0
- package/dist/types/service.d.ts +2 -1
- package/package.json +2 -2
package/CONTRIBUTING.md
CHANGED
|
@@ -17,11 +17,13 @@ This repository is focused on a small, explicit DI core for standard ECMAScript
|
|
|
17
17
|
This repository uses Lefthook.
|
|
18
18
|
|
|
19
19
|
- `pre-commit` runs fast staged-file checks for lint and formatting.
|
|
20
|
+
- hooks are contributor-local and are not installed for package consumers.
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
Install or reinstall them locally with `bun run hooks:install`.
|
|
22
23
|
|
|
23
24
|
## Pull request checklist
|
|
24
25
|
|
|
26
|
+
- PR CI runs lint, format, typecheck, test, and build checks automatically.
|
|
25
27
|
- the change is focused and documented;
|
|
26
28
|
- scripts in the local checks section pass;
|
|
27
29
|
- package exports and Node compatibility were kept intact;
|
package/README.md
CHANGED
|
@@ -46,11 +46,17 @@ No environment variables or external services are required for local development
|
|
|
46
46
|
|
|
47
47
|
## Public entry points
|
|
48
48
|
|
|
49
|
-
The package root currently exports
|
|
49
|
+
The package root currently exports runtime values and TypeScript types.
|
|
50
|
+
|
|
51
|
+
Runtime exports:
|
|
50
52
|
|
|
51
53
|
- `Container`
|
|
52
54
|
- `Service`
|
|
53
55
|
- `Inject`
|
|
56
|
+
- `Token`
|
|
57
|
+
|
|
58
|
+
Type-only exports:
|
|
59
|
+
|
|
54
60
|
- `Constructable` / `AbstractConstructable`
|
|
55
61
|
- `ServiceIdentifier`
|
|
56
62
|
|
|
@@ -126,10 +132,16 @@ Current behavior:
|
|
|
126
132
|
|
|
127
133
|
## Decorators
|
|
128
134
|
|
|
129
|
-
### `@Service(
|
|
135
|
+
### `@Service(idOrOptions?)`
|
|
130
136
|
|
|
131
137
|
Registers a class in the default container.
|
|
132
138
|
|
|
139
|
+
Accepted forms today:
|
|
140
|
+
|
|
141
|
+
- `@Service()`
|
|
142
|
+
- `@Service(id)`
|
|
143
|
+
- `@Service({ id, scope })`
|
|
144
|
+
|
|
133
145
|
Options supported today:
|
|
134
146
|
|
|
135
147
|
- `id?: ServiceIdentifier`
|
|
@@ -146,7 +158,8 @@ class LoggerService {}
|
|
|
146
158
|
const logger = Container.of().get('logger');
|
|
147
159
|
```
|
|
148
160
|
|
|
149
|
-
|
|
161
|
+
Custom identifiers work for both `container.get(...)` and `@Inject(...)`.
|
|
162
|
+
When you use `Token` instances, resolution is based on object identity, so create the token once and reuse the same instance everywhere.
|
|
150
163
|
|
|
151
164
|
### `@Inject(dependency)`
|
|
152
165
|
|
|
@@ -161,6 +174,35 @@ Current characteristics:
|
|
|
161
174
|
- injected fields are defined as writable and configurable own properties on the created instance;
|
|
162
175
|
- injected fields are assigned after construction, so they are not available inside constructors or field initializers.
|
|
163
176
|
|
|
177
|
+
Token example:
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
import { Container, Inject, Service, Token } from 'navi-di';
|
|
181
|
+
|
|
182
|
+
interface Logger {
|
|
183
|
+
log(message: string): void;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const LOGGER = new Token<Logger>('Logger');
|
|
187
|
+
|
|
188
|
+
@Service(LOGGER)
|
|
189
|
+
class ConsoleLogger implements Logger {
|
|
190
|
+
public log(message: string) {
|
|
191
|
+
console.log(message);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@Service()
|
|
196
|
+
class HandlerService {
|
|
197
|
+
@Inject(LOGGER)
|
|
198
|
+
public logger!: Logger;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const handler = Container.of().get(HandlerService);
|
|
202
|
+
|
|
203
|
+
handler.logger.log('hello from token injection');
|
|
204
|
+
```
|
|
205
|
+
|
|
164
206
|
## Container API
|
|
165
207
|
|
|
166
208
|
### `Container.of(id?)`
|
|
@@ -193,6 +235,13 @@ Supported strategies:
|
|
|
193
235
|
|
|
194
236
|
This is especially useful in tests.
|
|
195
237
|
|
|
238
|
+
### `container.set(metadata)`
|
|
239
|
+
|
|
240
|
+
Registers or replaces service metadata for a service identifier.
|
|
241
|
+
|
|
242
|
+
This is a low-level API that powers manual registration scenarios and internal tests.
|
|
243
|
+
For application-facing code, prefer `@Service()` unless you specifically need to construct metadata yourself.
|
|
244
|
+
|
|
196
245
|
## Internal architecture
|
|
197
246
|
|
|
198
247
|
The implementation is intentionally small and split into a few focused modules:
|
|
@@ -242,9 +291,9 @@ What they do:
|
|
|
242
291
|
- `lint`: run `oxlint` with warnings denied
|
|
243
292
|
- `fmt`: format the repository with `oxfmt`
|
|
244
293
|
- `fmt:check`: verify formatting without writing changes
|
|
245
|
-
- `hooks:*`: install, validate, or run the
|
|
294
|
+
- `hooks:*`: install, validate, or run the repo-local Lefthook Git hooks
|
|
246
295
|
|
|
247
|
-
|
|
296
|
+
Git hooks are optional and repo-local. After cloning, contributors can install them with `bun run hooks:install`.
|
|
248
297
|
|
|
249
298
|
Current note: `typecheck` uses `tsconfig.json` with `noEmit: true`, while `build` uses `tsconfig.build.json` with `noEmit: false` to emit `dist/` and declaration files.
|
|
250
299
|
|
|
@@ -255,7 +304,8 @@ The repository currently enforces:
|
|
|
255
304
|
- strict TypeScript checking;
|
|
256
305
|
- `oxlint` for linting;
|
|
257
306
|
- `oxfmt` for formatting;
|
|
258
|
-
-
|
|
307
|
+
- PR CI checks for lint, format, typecheck, tests, and build;
|
|
308
|
+
- optional Lefthook `pre-commit` checks for staged TypeScript, JavaScript, Markdown, YAML, and YML files.
|
|
259
309
|
|
|
260
310
|
The package `prepack` script runs lint, format check, typecheck, and build before publishing.
|
|
261
311
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
export declare function Inject<T>(dependency:
|
|
1
|
+
import { type ServiceIdentifier } from '../types';
|
|
2
|
+
export declare function Inject<T>(dependency: ServiceIdentifier<T>): (_: undefined, context: ClassFieldDecoratorContext) => void;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import type { ServiceOption } from '../types';
|
|
1
|
+
import type { ServiceIdentifier, ServiceOption } from '../types';
|
|
2
2
|
export declare function Service(): Function;
|
|
3
|
+
export declare function Service(id: ServiceIdentifier): Function;
|
|
3
4
|
export declare function Service(options?: ServiceOption): Function;
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import { ContainerRegistry } from '../container/registry';
|
|
2
2
|
import { INJECTION_KEY, EMPTY_VALUE } from '../types';
|
|
3
|
-
|
|
3
|
+
function normalizeArguments(args) {
|
|
4
|
+
if (!args) {
|
|
5
|
+
return {};
|
|
6
|
+
}
|
|
7
|
+
if (typeof args === 'object' && ('scope' in args || 'id' in args)) {
|
|
8
|
+
return args;
|
|
9
|
+
}
|
|
10
|
+
return { id: args };
|
|
11
|
+
}
|
|
12
|
+
export function Service(idOrOptions) {
|
|
4
13
|
return function (target, context) {
|
|
14
|
+
const options = normalizeArguments(idOrOptions);
|
|
5
15
|
const injections = (context.metadata[INJECTION_KEY] ?? []);
|
|
6
16
|
ContainerRegistry.defaultContainer.set({
|
|
7
17
|
id: options?.id ?? target,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { Container } from './container';
|
|
2
2
|
export { Service, Inject } from './decorators';
|
|
3
|
+
export { Token } from './tokens';
|
|
3
4
|
export type { AbstractConstructable, Constructable } from './types/constructable.ts';
|
|
4
5
|
export type { ServiceIdentifier } from './types/service.ts';
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Token } from './token';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Token } from './token';
|
package/dist/types/service.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { Token } from '../tokens';
|
|
1
2
|
import type { AbstractConstructable, Constructable } from './constructable';
|
|
2
|
-
export type ServiceIdentifier<T = unknown, Args extends unknown[] = never[]> = Constructable<T, Args> | AbstractConstructable<T, Args> | CallableFunction | string
|
|
3
|
+
export type ServiceIdentifier<T = unknown, Args extends unknown[] = never[]> = Constructable<T, Args> | AbstractConstructable<T, Args> | CallableFunction | string | Token<T>;
|
|
3
4
|
export type ServiceScope = 'singleton' | 'container' | 'transient';
|
|
4
5
|
export interface ServiceOption {
|
|
5
6
|
id?: ServiceIdentifier;
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "navi-di",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Dependency injection for standard ECMAScript decorators.",
|
|
5
|
+
"author": "naviary-sanctuary",
|
|
5
6
|
"keywords": [
|
|
6
7
|
"bun",
|
|
7
8
|
"decorators",
|
|
@@ -51,7 +52,6 @@
|
|
|
51
52
|
"lint": "oxlint . --deny-warnings",
|
|
52
53
|
"fmt": "oxfmt --config .oxfmt.json .",
|
|
53
54
|
"fmt:check": "oxfmt --check --config .oxfmt.json .",
|
|
54
|
-
"postinstall": "lefthook install",
|
|
55
55
|
"prepack": "bun run lint && bun run fmt:check && bun run typecheck && bun run build",
|
|
56
56
|
"test": "bun test --pass-with-no-tests"
|
|
57
57
|
},
|