di-sacala 0.1.3 → 0.1.4
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 +55 -3
- package/dist/di-sacala.d.ts.map +1 -1
- package/dist/index.js +10 -14
- package/dist/index.umd.cjs +1 -1
- package/package.json +31 -3
package/README.md
CHANGED
|
@@ -1,12 +1,33 @@
|
|
|
1
1
|
# di-sacala
|
|
2
2
|
|
|
3
3
|
[](https://github.com/monkin/di-sacala/actions/workflows/test.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/di-sacala)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://bundlephobia.com/package/di-sacala)
|
|
4
7
|
|
|
5
8
|
`di-sacala` is a lightweight, type-safe dependency injection container for TypeScript. It leverages TypeScript's advanced type system to provide a fluent API for service registration and resolution with full type safety and autocompletion.
|
|
6
9
|
|
|
10
|
+
## Table of Contents
|
|
11
|
+
|
|
12
|
+
- [Features](#features)
|
|
13
|
+
- [Motivation](#motivation)
|
|
14
|
+
- [Installation](#installation)
|
|
15
|
+
- [Usage](#usage)
|
|
16
|
+
- [1. Defining a Service](#1-defining-a-service)
|
|
17
|
+
- [2. Basic Injection](#2-basic-injection)
|
|
18
|
+
- [3. Services with Dependencies](#3-services-with-dependencies)
|
|
19
|
+
- [4. Merging Containers](#4-merging-containers)
|
|
20
|
+
- [5. Lazy & Singleton](#5-lazy--singleton)
|
|
21
|
+
- [6. Duplicate Service Name Protection](#6-duplicate-service-name-protection)
|
|
22
|
+
- [7. Reserved Field Names](#7-reserved-field-names)
|
|
23
|
+
- [API Reference](#api-reference)
|
|
24
|
+
- [Development](#development)
|
|
25
|
+
- [License](#license)
|
|
26
|
+
|
|
7
27
|
## Features
|
|
8
28
|
|
|
9
29
|
- **Full Type Safety**: Get autocompletion and type checks for all your injected services.
|
|
30
|
+
- **No Decorators**: No need for `reflect-metadata` or experimental decorators. Pure TypeScript.
|
|
10
31
|
- **Fluent API**: Chainable service registration makes it easy to compose your container.
|
|
11
32
|
- **Container Composition**: Merge multiple containers together to share dependencies across different parts of your application.
|
|
12
33
|
- **Lazy & Singleton**: Services are instantiated only on demand (when first accessed) and reused for subsequent accesses.
|
|
@@ -60,23 +81,29 @@ To inject dependencies into a service, define its constructor to accept the cont
|
|
|
60
81
|
```typescript
|
|
61
82
|
import { Di, DiService } from 'di-sacala';
|
|
62
83
|
import { LoggerService } from './LoggerService';
|
|
84
|
+
import { ConfigService } from './ConfigService';
|
|
63
85
|
|
|
64
86
|
export class UserService implements DiService<"user"> {
|
|
65
87
|
getServiceName() {
|
|
66
88
|
return "user" as const;
|
|
67
89
|
}
|
|
68
90
|
|
|
69
|
-
//
|
|
70
|
-
constructor(private di: Di<LoggerService>) {}
|
|
91
|
+
// Single dependency:
|
|
92
|
+
// constructor(private di: Di<LoggerService>) {}
|
|
93
|
+
|
|
94
|
+
// Multiple dependencies using a tuple:
|
|
95
|
+
constructor(private di: Di<[LoggerService, ConfigService]>) {}
|
|
71
96
|
|
|
72
97
|
getUser(id: string) {
|
|
73
|
-
this.di.
|
|
98
|
+
const prefix = this.di.config.get("userPrefix");
|
|
99
|
+
this.di.logger.log(`Fetching user: ${prefix}${id}`);
|
|
74
100
|
return { id, name: "User " + id };
|
|
75
101
|
}
|
|
76
102
|
}
|
|
77
103
|
|
|
78
104
|
const container = new DiContainer()
|
|
79
105
|
.inject(LoggerService)
|
|
106
|
+
.inject(ConfigService)
|
|
80
107
|
.inject(UserService);
|
|
81
108
|
|
|
82
109
|
container.user.getUser("42");
|
|
@@ -149,6 +176,31 @@ const container = new DiContainer();
|
|
|
149
176
|
container.inject(InjectService);
|
|
150
177
|
```
|
|
151
178
|
|
|
179
|
+
## API Reference
|
|
180
|
+
|
|
181
|
+
### `DiContainer`
|
|
182
|
+
|
|
183
|
+
The main class for managing services.
|
|
184
|
+
|
|
185
|
+
- `inject(ServiceClass: new (di: this) => S): DiContainer & Di<S>`
|
|
186
|
+
Registers a service class. Returns the container instance, typed with the newly added service.
|
|
187
|
+
- `injectContainer(other: DiContainer): DiContainer & ...`
|
|
188
|
+
Copies all services from another container into this one.
|
|
189
|
+
|
|
190
|
+
### `DiService<Name>`
|
|
191
|
+
|
|
192
|
+
An interface that your service classes must implement.
|
|
193
|
+
|
|
194
|
+
- `getServiceName(this: null): Name`
|
|
195
|
+
Must return the unique name of the service as a string literal type.
|
|
196
|
+
|
|
197
|
+
### `Di<S>`
|
|
198
|
+
|
|
199
|
+
A utility type to help define dependencies in your service constructors.
|
|
200
|
+
|
|
201
|
+
- `Di<ServiceClass>`: Resolves to an object with the service name as the key and the service instance as the value.
|
|
202
|
+
- `Di<[Service1, Service2]>`: Resolves to a merged object containing all specified services.
|
|
203
|
+
|
|
152
204
|
## Development
|
|
153
205
|
|
|
154
206
|
### Installation
|
package/dist/di-sacala.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"di-sacala.d.ts","sourceRoot":"","sources":["../src/di-sacala.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,SAAS,CAAC,IAAI,SAAS,MAAM;IAC1C;;;;;OAKG;IACH,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CACpC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,GAAG,MAAM,IAAI,CAAC,GACjD,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GACjB,CAAC,SAAS,EAAE,GACV,OAAO,GACP,CAAC,SAAS,SAAS,CAAC,MAAM,IAAI,CAAC,GAC7B;KAAG,GAAG,IAAI,IAAI,GAAG,CAAC;CAAE,GACpB,KAAK,CAAC;AAIhB,KAAK,kBAAkB,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,SAAS,MAAM,WAAW,GAC3D,wBAAwB,IAAI,EAAE,GAC9B,CAAC,CAAC;AAER,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,SAAS,SAAS,CAAC,MAAM,CAAC,IACpD,OAAO,SAAS,SAAS,CAAC,MAAM,IAAI,CAAC,GAC/B,kBAAkB,CACd,IAAI,EACJ,SAAS,SAAS;KAAG,GAAG,IAAI,IAAI,GAAG,OAAO;CAAE,GACtC,2BAA2B,IAAI,EAAE,GACjC,SAAS,GAAG,EAAE,CAAC,OAAO,CAAC,CAChC,GACD,KAAK,CAAC;AAEhB,KAAK,KAAK,CAAC,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,QAAQ,GAAG,iBAAiB,CAAC,GACnE,OAAO,CAAC,MAAM,GAAG,EAAE,QAAQ,GAAG,iBAAiB,CAAC,SAAS,KAAK,GAC5D,GAAG,GAAG,GAAG,GACT,oCAAoC,CAAC,OAAO,CACxC,MAAM,GAAG,EACT,QAAQ,GAAG,iBAAiB,CAC/B,GACG,OAAO,CAAC,MAAM,GAAG,EAAE,QAAQ,GAAG,iBAAiB,CAAC,CAAC,GACjD,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"di-sacala.d.ts","sourceRoot":"","sources":["../src/di-sacala.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,SAAS,CAAC,IAAI,SAAS,MAAM;IAC1C;;;;;OAKG;IACH,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CACpC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,GAAG,MAAM,IAAI,CAAC,GACjD,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GACjB,CAAC,SAAS,EAAE,GACV,OAAO,GACP,CAAC,SAAS,SAAS,CAAC,MAAM,IAAI,CAAC,GAC7B;KAAG,GAAG,IAAI,IAAI,GAAG,CAAC;CAAE,GACpB,KAAK,CAAC;AAIhB,KAAK,kBAAkB,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,SAAS,MAAM,WAAW,GAC3D,wBAAwB,IAAI,EAAE,GAC9B,CAAC,CAAC;AAER,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,SAAS,SAAS,CAAC,MAAM,CAAC,IACpD,OAAO,SAAS,SAAS,CAAC,MAAM,IAAI,CAAC,GAC/B,kBAAkB,CACd,IAAI,EACJ,SAAS,SAAS;KAAG,GAAG,IAAI,IAAI,GAAG,OAAO;CAAE,GACtC,2BAA2B,IAAI,EAAE,GACjC,SAAS,GAAG,EAAE,CAAC,OAAO,CAAC,CAChC,GACD,KAAK,CAAC;AAEhB,KAAK,KAAK,CAAC,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,QAAQ,GAAG,iBAAiB,CAAC,GACnE,OAAO,CAAC,MAAM,GAAG,EAAE,QAAQ,GAAG,iBAAiB,CAAC,SAAS,KAAK,GAC5D,GAAG,GAAG,GAAG,GACT,oCAAoC,CAAC,OAAO,CACxC,MAAM,GAAG,EACT,QAAQ,GAAG,iBAAiB,CAC/B,GACG,OAAO,CAAC,MAAM,GAAG,EAAE,QAAQ,GAAG,iBAAiB,CAAC,CAAC,GACjD,MAAM,EAAE,CAAC;AAYnB;;;;GAIG;AACH,qBAAa,WAAW;;IAGpB;;;;;;;;OAQG;IACH,MAAM,CAAC,CAAC,SAAS,SAAS,CAAC,MAAM,CAAC,EAC9B,UAAU,EAAE,KAAK,YAAY,EAAE,IAAI,KAAK,CAAC,GAC1C,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAwBlB;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,SAAS,WAAW,EAAE,KAAK,EAAE,EAAE,GAAG,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;CAetE"}
|
package/dist/index.js
CHANGED
|
@@ -1,27 +1,23 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
for (const e in n) i(n, e) && t(e);
|
|
4
|
-
}
|
|
5
|
-
const r = (n) => {
|
|
6
|
-
throw new Error(n);
|
|
1
|
+
const a = new Set(["inject", "injectContainer"]), c = (r, t) => Object.prototype.hasOwnProperty.call(r, t), s = (r, t) => Object.keys(r).forEach(t), n = (r) => {
|
|
2
|
+
throw new Error(r);
|
|
7
3
|
};
|
|
8
|
-
class
|
|
4
|
+
class o {
|
|
9
5
|
constructor() {
|
|
10
6
|
}
|
|
11
7
|
inject(t) {
|
|
12
8
|
const e = t.prototype.getServiceName.call(null);
|
|
13
|
-
|
|
14
|
-
let
|
|
15
|
-
return Object.defineProperty(this, e, { enumerable: !0, get: () =>
|
|
9
|
+
a.has(e) && n(`Reserved field name: ${e}`), c(this, e) && n(`Duplicate service name: ${e}`);
|
|
10
|
+
let i;
|
|
11
|
+
return Object.defineProperty(this, e, { enumerable: !0, get: () => i ?? (i = new t(this)) }), this;
|
|
16
12
|
}
|
|
17
13
|
injectContainer(t) {
|
|
18
|
-
return
|
|
19
|
-
|
|
20
|
-
}),
|
|
14
|
+
return s(t, (e) => {
|
|
15
|
+
c(this, e) && n(`Containers have duplicated keys: ${String(e)}`);
|
|
16
|
+
}), s(t, (e) => {
|
|
21
17
|
Object.defineProperty(this, e, { enumerable: !0, get: () => t[e] });
|
|
22
18
|
}), this;
|
|
23
19
|
}
|
|
24
20
|
}
|
|
25
21
|
export {
|
|
26
|
-
|
|
22
|
+
o as DiContainer
|
|
27
23
|
};
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(o
|
|
1
|
+
(function(i,o){typeof exports=="object"&&typeof module<"u"?o(exports):typeof define=="function"&&define.amd?define(["exports"],o):(i=typeof globalThis<"u"?globalThis:i||self,o(i.DiSacala={}))})(this,(function(i){"use strict";const o=new Set(["inject","injectContainer"]),s=(n,t)=>Object.prototype.hasOwnProperty.call(n,t),c=(n,t)=>Object.keys(n).forEach(t),r=n=>{throw new Error(n)};class l{constructor(){}inject(t){const e=t.prototype.getServiceName.call(null);o.has(e)&&r(`Reserved field name: ${e}`),s(this,e)&&r(`Duplicate service name: ${e}`);let a;return Object.defineProperty(this,e,{enumerable:!0,get:()=>a??(a=new t(this))}),this}injectContainer(t){return c(t,e=>{s(this,e)&&r(`Containers have duplicated keys: ${String(e)}`)}),c(t,e=>{Object.defineProperty(this,e,{enumerable:!0,get:()=>t[e]})}),this}}i.DiContainer=l,Object.defineProperty(i,Symbol.toStringTag,{value:"Module"})}));
|
package/package.json
CHANGED
|
@@ -1,27 +1,55 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "di-sacala",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Small type-safe dependency injection lib",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/di-sacala.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/di-sacala.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.umd.cjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
8
15
|
"files": [
|
|
9
16
|
"dist"
|
|
10
17
|
],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18.0.0"
|
|
21
|
+
},
|
|
11
22
|
"scripts": {
|
|
12
23
|
"build": "vite build",
|
|
13
24
|
"test": "vitest run",
|
|
14
25
|
"test:watch": "vitest",
|
|
15
26
|
"lint": "eslint src --ext .ts",
|
|
16
27
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
17
|
-
"format:check": "prettier --check \"src/**/*.ts\""
|
|
28
|
+
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
29
|
+
"prepublishOnly": "npm run lint && npm run test && npm run build"
|
|
18
30
|
},
|
|
19
|
-
"keywords": [
|
|
31
|
+
"keywords": [
|
|
32
|
+
"dependency-injection",
|
|
33
|
+
"di",
|
|
34
|
+
"typescript",
|
|
35
|
+
"type-safe",
|
|
36
|
+
"container",
|
|
37
|
+
"ioc",
|
|
38
|
+
"lightweight"
|
|
39
|
+
],
|
|
20
40
|
"author": {
|
|
21
41
|
"name": "Andrei Monkin",
|
|
22
42
|
"email": "monkin.andrey@gmail.com",
|
|
23
43
|
"url": "https://github.com/monkin"
|
|
24
44
|
},
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/monkin/di-sacala.git"
|
|
48
|
+
},
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/monkin/di-sacala/issues"
|
|
51
|
+
},
|
|
52
|
+
"homepage": "https://github.com/monkin/di-sacala#readme",
|
|
25
53
|
"license": "MIT",
|
|
26
54
|
"devDependencies": {
|
|
27
55
|
"@eslint/js": "^9.39.2",
|