@biorate/connector 3.0.2 → 3.1.1
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 +181 -21
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,49 +1,209 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @biorate/connector
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Abstract base class for creating typed, config‑driven connection managers backed by `@biorate/inversion` and `@biorate/config`.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Features
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
- **Abstract `Connector<C, R>`** — define `connect(config): Promise<R>` for any resource.
|
|
8
|
+
- **Config‑driven** — reads an array of connection configs from `this.namespace` in `@biorate/config`.
|
|
9
|
+
- **Auto‑connect** — on `@init()`, creates all connections defined in config.
|
|
10
|
+
- **Named connections** — access by name via `.connection(name)` or `.get(name)`.
|
|
11
|
+
- **Current connection** — first config entry becomes the default; switch via `.use(name)`.
|
|
12
|
+
- **Error handling** — typed errors for missing or empty connections.
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
public name: string;
|
|
14
|
+
## Installation
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add @biorate/connector
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Requires `@biorate/config`, `@biorate/errors`, `@biorate/inversion`.
|
|
21
|
+
|
|
22
|
+
## Quick start
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { Connector } from '@biorate/connector';
|
|
26
|
+
|
|
27
|
+
class Connection {
|
|
28
|
+
constructor(public name: string) {}
|
|
18
29
|
}
|
|
19
30
|
|
|
20
|
-
|
|
21
|
-
protected namespace = '
|
|
31
|
+
class MyConnector extends Connector<{ name: string }, Connection> {
|
|
32
|
+
protected namespace = 'MyConnector';
|
|
22
33
|
|
|
23
|
-
protected async connect(config) {
|
|
34
|
+
protected async connect(config: { name: string }) {
|
|
24
35
|
return new Connection(config.name);
|
|
25
36
|
}
|
|
26
37
|
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
With DI:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { Core, container, Types } from '@biorate/inversion';
|
|
44
|
+
import { IConfig, Config } from '@biorate/config';
|
|
27
45
|
|
|
28
|
-
|
|
29
|
-
@inject(
|
|
46
|
+
class Root extends Core() {
|
|
47
|
+
@inject(MyConnector) public connector: MyConnector;
|
|
30
48
|
}
|
|
31
49
|
|
|
32
50
|
container.bind(Types.Config).to(Config).inSingletonScope();
|
|
33
|
-
container.bind(
|
|
51
|
+
container.bind(MyConnector).toSelf().inSingletonScope();
|
|
34
52
|
container.bind(Root).toSelf().inSingletonScope();
|
|
35
53
|
|
|
36
54
|
container.get<IConfig>(Types.Config).merge({
|
|
37
|
-
|
|
55
|
+
MyConnector: [{ name: 'db-1' }, { name: 'db-2' }],
|
|
38
56
|
});
|
|
39
57
|
|
|
40
58
|
(async () => {
|
|
41
59
|
const root = container.get<Root>(Root);
|
|
42
60
|
await root.$run();
|
|
43
|
-
|
|
61
|
+
|
|
62
|
+
console.log(root.connector.connection('db-1')); // Connection { name: 'db-1' }
|
|
63
|
+
console.log(root.connector.current); // Connection { name: 'db-1' }
|
|
64
|
+
|
|
65
|
+
root.connector.use('db-2');
|
|
66
|
+
console.log(root.connector.current); // Connection { name: 'db-2' }
|
|
44
67
|
})();
|
|
45
68
|
```
|
|
46
69
|
|
|
70
|
+
## API Reference
|
|
71
|
+
|
|
72
|
+
### `Connector<C, R>` abstract class
|
|
73
|
+
|
|
74
|
+
| Member | Type | Description |
|
|
75
|
+
|---------------------------|-------------------------------|------------------------------------------------|
|
|
76
|
+
| `namespace` (abstract) | `string` | Config key — array of `C` objects. |
|
|
77
|
+
| `connect(config)` (abstract) | `(config: C) => Promise<R>` | Create a single connection. |
|
|
78
|
+
| `current` | `R \| undefined` | Currently selected connection. |
|
|
79
|
+
| `connections` | `Map<string, R>` | All created connections (name → instance). |
|
|
80
|
+
| `create(config)` | `(config: C) => Promise<R>` | Create connection if not already cached. |
|
|
81
|
+
| `connection(name?)` | `(name?: string) => R` | Get connection by name (or current). |
|
|
82
|
+
| `get(name?)` | `(name?: string) => R` | Alias for `connection()`. |
|
|
83
|
+
| `use(name)` | `(name: string) => void` | Switch current connection. |
|
|
84
|
+
| `initialize()` | `@init()` | Reads config array, creates all connections. |
|
|
85
|
+
|
|
86
|
+
### Config interface
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
interface IConnectorConfig {
|
|
90
|
+
name: string; // connection identifier (unique per connector)
|
|
91
|
+
// … plus any additional fields for your resource
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Errors
|
|
96
|
+
|
|
97
|
+
| Error | Condition |
|
|
98
|
+
|------------------------------------|--------------------------------------------------|
|
|
99
|
+
| `ConnectorConnectionNotExistsError`| Calling `connection(name)` / `use(name)` with unknown name. |
|
|
100
|
+
| `ConnectorEmptyConnectionsError` | Calling `connection()` when no connections exist. |
|
|
101
|
+
|
|
102
|
+
## Usage patterns
|
|
103
|
+
|
|
104
|
+
### Single connection
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
class MyConnector extends Connector<{ name: string; host: string; port: number }, Client> {
|
|
108
|
+
protected namespace = 'MyConnector';
|
|
109
|
+
|
|
110
|
+
protected async connect(config: { name: string; host: string; port: number }) {
|
|
111
|
+
const client = new Client();
|
|
112
|
+
await client.connect(config.host, config.port);
|
|
113
|
+
return client;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Config:
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"MyConnector": [{ "name": "default", "host": "localhost", "port": 5432 }]
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Multi‑connection (read replicas)
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
{
|
|
130
|
+
"MyConnector": [
|
|
131
|
+
{ "name": "primary", "host": "db-1.internal", "port": 5432 },
|
|
132
|
+
{ "name": "replica-1", "host": "db-2.internal", "port": 5432 },
|
|
133
|
+
{ "name": "replica-2", "host": "db-3.internal", "port": 5432 },
|
|
134
|
+
]
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
// Switch for read operations:
|
|
140
|
+
connector.use('replica-1');
|
|
141
|
+
const data = await connector.current.query('SELECT …');
|
|
142
|
+
|
|
143
|
+
// Switch back for writes:
|
|
144
|
+
connector.use('primary');
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Dynamic connection creation
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
class MyConnector extends Connector<{ name: string; url: string }, Resource> {
|
|
151
|
+
protected namespace = 'MyConnector';
|
|
152
|
+
protected async connect(config: { name: string; url: string }) {
|
|
153
|
+
return new Resource(config.url);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// At runtime:
|
|
158
|
+
await connector.create({ name: 'ad-hoc', url: 'https://…' });
|
|
159
|
+
const resource = connector.connection('ad-hoc');
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Type override for config
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
interface RedisConfig extends IConnectorConfig {
|
|
166
|
+
host: string;
|
|
167
|
+
port: number;
|
|
168
|
+
db: number;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
class RedisConnector extends Connector<RedisConfig, RedisClient> {
|
|
172
|
+
protected namespace = 'RedisConnector';
|
|
173
|
+
protected async connect(config: RedisConfig) {
|
|
174
|
+
return new RedisClient({ host: config.host, port: config.port, db: config.db });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Architecture
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
┌─────────────────────────────────────────────┐
|
|
183
|
+
│ Connector │ abstract class
|
|
184
|
+
├─────────────────────────────────────────────┤
|
|
185
|
+
│ namespace: string ─── config key │
|
|
186
|
+
│ #connections: Map<name, R> │
|
|
187
|
+
│ #current: R ─── selected │
|
|
188
|
+
│ │
|
|
189
|
+
│ @init() initialize() │
|
|
190
|
+
│ ├── for each config in namespace[] │
|
|
191
|
+
│ │ └── this.create(config) │
|
|
192
|
+
│ │ └── this.connect(config) ← abstract
|
|
193
|
+
│ └── set #current = first entry │
|
|
194
|
+
│ │
|
|
195
|
+
│ connection(name?) → R │
|
|
196
|
+
│ use(name) → void │
|
|
197
|
+
│ create(config) → Promise<R> │
|
|
198
|
+
└─────────────────────────────────────────────┘
|
|
199
|
+
▲ extends
|
|
200
|
+
│
|
|
201
|
+
┌─────────────────────────────────────────────┐
|
|
202
|
+
│ RedisConnector / MongoConnector … │
|
|
203
|
+
│ connect(config) → Promise<R> │
|
|
204
|
+
└─────────────────────────────────────────────┘
|
|
205
|
+
```
|
|
206
|
+
|
|
47
207
|
### Learn
|
|
48
208
|
|
|
49
209
|
- Documentation can be found here - [docs](https://biorate.github.io/core/modules/connector.html).
|
|
@@ -52,7 +212,7 @@ container.get<IConfig>(Types.Config).merge({
|
|
|
52
212
|
|
|
53
213
|
See the [CHANGELOG](https://github.com/biorate/core/blob/master/packages/%40biorate/connector/CHANGELOG.md)
|
|
54
214
|
|
|
55
|
-
|
|
215
|
+
## License
|
|
56
216
|
|
|
57
217
|
[MIT](https://github.com/biorate/core/blob/master/packages/%40biorate/connector/LICENSE)
|
|
58
218
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@biorate/connector",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.1",
|
|
4
4
|
"description": "Connector interface",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
"keywords": [],
|
|
46
46
|
"author": "llevkin",
|
|
47
47
|
"license": "MIT",
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "ff1dcf14a733ce8004ca582d2c421a2154ce97cb",
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@biorate/config": "3.1
|
|
51
|
-
"@biorate/errors": "3.
|
|
52
|
-
"@biorate/inversion": "3.
|
|
50
|
+
"@biorate/config": "3.2.1",
|
|
51
|
+
"@biorate/errors": "3.1.1",
|
|
52
|
+
"@biorate/inversion": "3.1.1"
|
|
53
53
|
}
|
|
54
54
|
}
|