targwire 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/README.md +261 -0
- package/dist/index.cjs +154 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +59 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +111 -0
- package/dist/index.js.map +1 -0
- package/package.json +33 -0
package/README.md
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# TargWire
|
|
2
|
+
|
|
3
|
+
Mini **IoC container** tipado para TypeScript com **Singleton**, **Transient (Factory)** e **Scoped** (child containers). Ideal para apps **Expo/React Native** (Hermes), web e Node — zero dependências.
|
|
4
|
+
|
|
5
|
+
- ✅ Tokens tipados (`Token<T>`)
|
|
6
|
+
- ✅ Ciclos de vida: `registerSingleton`, `registerFactory` (transient), `createScope` (scoped)
|
|
7
|
+
- ✅ Overrides e reset (testes/HMR)
|
|
8
|
+
- ✅ Plugin registry para registrar módulos do **app** e dar `bootstrapIOC()` uma vez só
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Instalação
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm i @seu-escopo/ioc
|
|
16
|
+
# ou
|
|
17
|
+
yarn add @seu-escopo/ioc
|
|
18
|
+
# ou
|
|
19
|
+
pnpm add @seu-escopo/ioc
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
> O pacote já é publicado transpilado (ESM + CJS) com typings. Não precisa configurar Metro/Babel pra transpilar TS em `node_modules`.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## TL;DR (Exemplo rápido)
|
|
27
|
+
|
|
28
|
+
**1) Defina tokens do domínio (no app):**
|
|
29
|
+
```ts
|
|
30
|
+
// src/ioc/tokens.users.ts
|
|
31
|
+
import { defineToken } from 'targwire';
|
|
32
|
+
import type { GetUsersUseCase } from '@/domain/usecases/get_users_usecase';
|
|
33
|
+
import type { UserRepository } from '@/domain/repositories/user_repository';
|
|
34
|
+
import type { UserRemoteDataSource } from '@/data/datasources/remote/user_remote_data_source';
|
|
35
|
+
|
|
36
|
+
export const TOKENS_USERS = {
|
|
37
|
+
RemoteDataSource: defineToken<UserRemoteDataSource>('Users.RemoteDataSource'),
|
|
38
|
+
Repository: defineToken<UserRepository>('Users.Repository'),
|
|
39
|
+
GetUsersUseCase: defineToken<GetUsersUseCase>('Users.GetUsersUseCase'),
|
|
40
|
+
};
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**2) Registre seu módulo via plugin (no app):**
|
|
44
|
+
```ts
|
|
45
|
+
// src/ioc/plugins.ts (side-effect)
|
|
46
|
+
import { registerIOCPlugin } from 'targwire';
|
|
47
|
+
import { TOKENS_USERS } from './tokens.users';
|
|
48
|
+
import { UserRemoteDataSourceImpl } from '@/data/datasources/remote/user_remote_data_source';
|
|
49
|
+
import { UserRepositoryImpl } from '@/data/repositories/user_repository_impl';
|
|
50
|
+
import { GetUsersUseCase } from '@/domain/usecases/get_users_usecase';
|
|
51
|
+
|
|
52
|
+
registerIOCPlugin((c) => {
|
|
53
|
+
if (!c.isRegistered(TOKENS_USERS.RemoteDataSource))
|
|
54
|
+
c.registerSingleton(TOKENS_USERS.RemoteDataSource, () => new UserRemoteDataSourceImpl());
|
|
55
|
+
if (!c.isRegistered(TOKENS_USERS.Repository))
|
|
56
|
+
c.registerSingleton(TOKENS_USERS.Repository, () =>
|
|
57
|
+
new UserRepositoryImpl(c.resolve(TOKENS_USERS.RemoteDataSource))
|
|
58
|
+
);
|
|
59
|
+
if (!c.isRegistered(TOKENS_USERS.GetUsersUseCase))
|
|
60
|
+
c.registerFactory(TOKENS_USERS.GetUsersUseCase, () =>
|
|
61
|
+
new GetUsersUseCase(c.resolve(TOKENS_USERS.Repository))
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**3) Bootstrap uma vez no entrypoint do app:**
|
|
67
|
+
```tsx
|
|
68
|
+
// App.tsx
|
|
69
|
+
import React from 'react';
|
|
70
|
+
import '@/ioc/plugins'; // importa teus módulos (efeito colateral)
|
|
71
|
+
import { bootstrapIOC } from '@seu-escopo/ioc';
|
|
72
|
+
|
|
73
|
+
bootstrapIOC();
|
|
74
|
+
|
|
75
|
+
export default function App() {
|
|
76
|
+
return null; // sua navegação/telas aqui
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**4) Consumir onde precisar:**
|
|
81
|
+
```ts
|
|
82
|
+
import { resolve } from 'targwire';
|
|
83
|
+
import { TOKENS_USERS } from '@/ioc/tokens.users';
|
|
84
|
+
|
|
85
|
+
const getUsers = resolve(TOKENS_USERS.GetUsersUseCase); // transient
|
|
86
|
+
const users = await getUsers.execute();
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## API da biblioteca
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
// Container raiz pronto:
|
|
95
|
+
import {
|
|
96
|
+
rootContainer,
|
|
97
|
+
defineToken, // <T>(name: string) => Token<T>
|
|
98
|
+
registerValue, // (token, value)
|
|
99
|
+
registerSingleton, // (token, () => T) // lazy
|
|
100
|
+
registerFactory, // (token, () => T) // transient
|
|
101
|
+
resolve, // (token) => T
|
|
102
|
+
isRegistered, // (token) => boolean
|
|
103
|
+
reset, // (tokens?) => void
|
|
104
|
+
createScope, // () => Container // scoped child
|
|
105
|
+
overrideValue,
|
|
106
|
+
overrideSingleton,
|
|
107
|
+
overrideFactory,
|
|
108
|
+
// Plugins/Bootstrap
|
|
109
|
+
registerIOCPlugin, // (registrar: (c: Container) => void)
|
|
110
|
+
bootstrapIOC, // executa todos os registrars uma vez
|
|
111
|
+
} from '@seu-escopo/ioc';
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Ciclos de vida
|
|
115
|
+
- **Singleton**: `registerSingleton(T, factory)`. A instância é criada no primeiro `resolve(T)` e reaproveitada naquele container/escopo.
|
|
116
|
+
- **Transient**: `registerFactory(T, factory)`. Uma **nova** instância a cada `resolve(T)`.
|
|
117
|
+
- **Scoped**: `const scope = rootContainer.createScope()`. Registros no escopo ficam isolados; `resolve` procura no escopo e sobe pro pai se necessário.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Padrão de plugins (módulos do app)
|
|
122
|
+
|
|
123
|
+
A lib **não** conhece teus domínios. Em vez de importar registradores manualmente no `App.tsx`, basta centralizar tudo num arquivo `src/ioc/plugins.ts`:
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
// src/ioc/plugins.ts
|
|
127
|
+
import { registerIOCPlugin } from 'targwire';
|
|
128
|
+
import { TOKENS_USERS } from './tokens.users';
|
|
129
|
+
// ...imports do módulo
|
|
130
|
+
|
|
131
|
+
registerIOCPlugin((c) => {
|
|
132
|
+
// registros do módulo Users
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// registerIOCPlugin(...); // Auth
|
|
136
|
+
// registerIOCPlugin(...); // Products
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Depois, no `App.tsx`:
|
|
140
|
+
```ts
|
|
141
|
+
import '@/ioc/plugins';
|
|
142
|
+
import { bootstrapIOC } from 'targwire';
|
|
143
|
+
bootstrapIOC();
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
> Quer reduzir a 1 import só? Crie `src/ioc/bootstrap-app.ts` com:
|
|
147
|
+
> ```ts
|
|
148
|
+
> import '@/ioc/plugins';
|
|
149
|
+
> export { bootstrapIOC as default } from 'targwire';
|
|
150
|
+
> ```
|
|
151
|
+
> E no `App.tsx`:
|
|
152
|
+
> ```ts
|
|
153
|
+
> import bootstrapIOC from '@/ioc/bootstrap-app';
|
|
154
|
+
> bootstrapIOC();
|
|
155
|
+
> ```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Exemplos
|
|
160
|
+
|
|
161
|
+
### Singleton
|
|
162
|
+
```ts
|
|
163
|
+
registerSingleton(TOKENS_USERS.Repository, () =>
|
|
164
|
+
new UserRepositoryImpl(resolve(TOKENS_USERS.RemoteDataSource))
|
|
165
|
+
);
|
|
166
|
+
const a = resolve(TOKENS_USERS.Repository);
|
|
167
|
+
const b = resolve(TOKENS_USERS.Repository);
|
|
168
|
+
console.log(a === b); // true
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Transient
|
|
172
|
+
```ts
|
|
173
|
+
registerFactory(TOKENS_USERS.GetUsersUseCase, () =>
|
|
174
|
+
new GetUsersUseCase(resolve(TOKENS_USERS.Repository))
|
|
175
|
+
);
|
|
176
|
+
const x = resolve(TOKENS_USERS.GetUsersUseCase);
|
|
177
|
+
const y = resolve(TOKENS_USERS.GetUsersUseCase);
|
|
178
|
+
console.log(x === y); // false
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Scoped por tela (React Native)
|
|
182
|
+
```tsx
|
|
183
|
+
import React, { useMemo } from 'react';
|
|
184
|
+
import { rootContainer } from 'targwire';
|
|
185
|
+
import { TOKENS_USERS } from '@/ioc/tokens.users';
|
|
186
|
+
import { UserRemoteDataSourceImpl } from '@/data/datasources/remote/user_remote_data_source';
|
|
187
|
+
import { UserRepositoryImpl } from '@/data/repositories/user_repository_impl';
|
|
188
|
+
import { GetUsersUseCase } from '@/domain/usecases/get_users_usecase';
|
|
189
|
+
|
|
190
|
+
export default function UsersScreenScoped() {
|
|
191
|
+
const scope = useMemo(() => {
|
|
192
|
+
const s = rootContainer.createScope();
|
|
193
|
+
s.registerSingleton(TOKENS_USERS.RemoteDataSource, () => new UserRemoteDataSourceImpl());
|
|
194
|
+
s.registerSingleton(TOKENS_USERS.Repository, () =>
|
|
195
|
+
new UserRepositoryImpl(s.resolve(TOKENS_USERS.RemoteDataSource))
|
|
196
|
+
);
|
|
197
|
+
s.registerFactory(TOKENS_USERS.GetUsersUseCase, () =>
|
|
198
|
+
new GetUsersUseCase(s.resolve(TOKENS_USERS.Repository))
|
|
199
|
+
);
|
|
200
|
+
return s;
|
|
201
|
+
}, []);
|
|
202
|
+
|
|
203
|
+
// use s.resolve(...) aqui
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Testes e overrides
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
import { reset, bootstrapIOC, overrideValue, resolve } from 'targwire';
|
|
214
|
+
import { TOKENS_USERS } from '@/ioc/tokens.users';
|
|
215
|
+
import '@/ioc/plugins';
|
|
216
|
+
|
|
217
|
+
beforeEach(() => {
|
|
218
|
+
reset(); // limpa o root container
|
|
219
|
+
bootstrapIOC(); // re-registra os plugins
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
test('override de use case', async () => {
|
|
223
|
+
overrideValue(TOKENS_USERS.GetUsersUseCase, {
|
|
224
|
+
execute: async () => [{ id: '1', name: 'Ana' } as any],
|
|
225
|
+
} as any);
|
|
226
|
+
|
|
227
|
+
const uc = resolve(TOKENS_USERS.GetUsersUseCase);
|
|
228
|
+
const users = await uc.execute();
|
|
229
|
+
expect(users[0].name).toBe('Ana');
|
|
230
|
+
});
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Dicas & Troubleshooting
|
|
236
|
+
|
|
237
|
+
- **`bootstrapIOC is not a function`**
|
|
238
|
+
Verifique **export/import** (nomeado vs default) **e** a ordem dos imports:
|
|
239
|
+
- Importar `@/ioc/plugins` **antes** de `bootstrapIOC()`.
|
|
240
|
+
- Use um só estilo:
|
|
241
|
+
```ts
|
|
242
|
+
import { bootstrapIOC } from '@seu-escopo/ioc'; // export nomeado
|
|
243
|
+
```
|
|
244
|
+
- **Tokens repetidos em HMR/Metro**
|
|
245
|
+
Use `Symbol.for('ioc:...')` (já fazemos) e, se necessário, `reset()` durante dev.
|
|
246
|
+
- **Alias `@`**
|
|
247
|
+
Configure o alias no Babel/Metro **do app**. A lib não precisa.
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Requisitos de runtime
|
|
252
|
+
|
|
253
|
+
- TypeScript 5+
|
|
254
|
+
- Target ES2019+ (ok para Hermes / RN 0.7x+)
|
|
255
|
+
- Sem dependências nativas
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Licença
|
|
260
|
+
|
|
261
|
+
MIT © Você
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
Container: () => Container,
|
|
24
|
+
_clearIOCPlugins: () => _clearIOCPlugins,
|
|
25
|
+
bootstrapIOC: () => bootstrapIOC,
|
|
26
|
+
createScope: () => createScope,
|
|
27
|
+
defineToken: () => defineToken,
|
|
28
|
+
getIOCPlugins: () => getIOCPlugins,
|
|
29
|
+
isRegistered: () => isRegistered,
|
|
30
|
+
overrideFactory: () => overrideFactory,
|
|
31
|
+
overrideSingleton: () => overrideSingleton,
|
|
32
|
+
overrideValue: () => overrideValue,
|
|
33
|
+
registerFactory: () => registerFactory,
|
|
34
|
+
registerIOCPlugin: () => registerIOCPlugin,
|
|
35
|
+
registerSingleton: () => registerSingleton,
|
|
36
|
+
registerValue: () => registerValue,
|
|
37
|
+
reset: () => reset,
|
|
38
|
+
resolve: () => resolve,
|
|
39
|
+
rootContainer: () => rootContainer
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(index_exports);
|
|
42
|
+
|
|
43
|
+
// src/container.ts
|
|
44
|
+
var Container = class _Container {
|
|
45
|
+
constructor(parent) {
|
|
46
|
+
this.parent = parent;
|
|
47
|
+
this.registry = /* @__PURE__ */ new Map();
|
|
48
|
+
}
|
|
49
|
+
defineToken(desc) {
|
|
50
|
+
return Symbol.for(`ioc:${desc}`);
|
|
51
|
+
}
|
|
52
|
+
registerValue(token, value) {
|
|
53
|
+
this.registry.set(token, { kind: "value", value });
|
|
54
|
+
}
|
|
55
|
+
registerSingleton(token, factory) {
|
|
56
|
+
this.registry.set(token, { kind: "singleton", factory });
|
|
57
|
+
}
|
|
58
|
+
registerFactory(token, factory) {
|
|
59
|
+
this.registry.set(token, { kind: "factory", factory });
|
|
60
|
+
}
|
|
61
|
+
isRegistered(token) {
|
|
62
|
+
return this.registry.has(token) || !!this.parent && this.parent.isRegistered(token);
|
|
63
|
+
}
|
|
64
|
+
resolve(token) {
|
|
65
|
+
if (this.registry.has(token)) {
|
|
66
|
+
const prov = this.registry.get(token);
|
|
67
|
+
switch (prov.kind) {
|
|
68
|
+
case "value":
|
|
69
|
+
return prov.value;
|
|
70
|
+
case "singleton":
|
|
71
|
+
if (prov.instance === void 0) prov.instance = prov.factory();
|
|
72
|
+
return prov.instance;
|
|
73
|
+
case "factory":
|
|
74
|
+
return prov.factory();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (this.parent) return this.parent.resolve(token);
|
|
78
|
+
throw new Error(`Token not registered: ${String(token)}`);
|
|
79
|
+
}
|
|
80
|
+
override(token, provider) {
|
|
81
|
+
this.registry.set(token, provider);
|
|
82
|
+
}
|
|
83
|
+
reset(tokens) {
|
|
84
|
+
if (!tokens) return void this.registry.clear();
|
|
85
|
+
for (const t of tokens) this.registry.delete(t);
|
|
86
|
+
}
|
|
87
|
+
createScope() {
|
|
88
|
+
return new _Container(this);
|
|
89
|
+
}
|
|
90
|
+
overrideValue(token, value) {
|
|
91
|
+
this.override(token, { kind: "value", value });
|
|
92
|
+
}
|
|
93
|
+
overrideSingleton(token, factory) {
|
|
94
|
+
this.override(token, { kind: "singleton", factory });
|
|
95
|
+
}
|
|
96
|
+
overrideFactory(token, factory) {
|
|
97
|
+
this.override(token, { kind: "factory", factory });
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
var rootContainer = new Container();
|
|
101
|
+
var defineToken = (desc) => rootContainer.defineToken(desc);
|
|
102
|
+
var registerValue = (t, v) => rootContainer.registerValue(t, v);
|
|
103
|
+
var registerSingleton = (t, f) => rootContainer.registerSingleton(t, f);
|
|
104
|
+
var registerFactory = (t, f) => rootContainer.registerFactory(t, f);
|
|
105
|
+
var resolve = (t) => rootContainer.resolve(t);
|
|
106
|
+
var isRegistered = (t) => rootContainer.isRegistered(t);
|
|
107
|
+
var reset = (tokens) => rootContainer.reset(tokens);
|
|
108
|
+
var createScope = () => rootContainer.createScope();
|
|
109
|
+
var overrideValue = (t, v) => rootContainer.overrideValue(t, v);
|
|
110
|
+
var overrideSingleton = (t, f) => rootContainer.overrideSingleton(t, f);
|
|
111
|
+
var overrideFactory = (t, f) => rootContainer.overrideFactory(t, f);
|
|
112
|
+
|
|
113
|
+
// src/plugins.ts
|
|
114
|
+
var registrars = [];
|
|
115
|
+
function registerIOCPlugin(registrar) {
|
|
116
|
+
registrars.push(registrar);
|
|
117
|
+
}
|
|
118
|
+
function getIOCPlugins() {
|
|
119
|
+
return registrars.slice();
|
|
120
|
+
}
|
|
121
|
+
function _clearIOCPlugins() {
|
|
122
|
+
registrars.length = 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// src/bootstrap.ts
|
|
126
|
+
var bootstrapped = false;
|
|
127
|
+
function bootstrapIOC() {
|
|
128
|
+
if (bootstrapped) return;
|
|
129
|
+
for (const reg of getIOCPlugins()) {
|
|
130
|
+
reg(rootContainer);
|
|
131
|
+
}
|
|
132
|
+
bootstrapped = true;
|
|
133
|
+
}
|
|
134
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
135
|
+
0 && (module.exports = {
|
|
136
|
+
Container,
|
|
137
|
+
_clearIOCPlugins,
|
|
138
|
+
bootstrapIOC,
|
|
139
|
+
createScope,
|
|
140
|
+
defineToken,
|
|
141
|
+
getIOCPlugins,
|
|
142
|
+
isRegistered,
|
|
143
|
+
overrideFactory,
|
|
144
|
+
overrideSingleton,
|
|
145
|
+
overrideValue,
|
|
146
|
+
registerFactory,
|
|
147
|
+
registerIOCPlugin,
|
|
148
|
+
registerSingleton,
|
|
149
|
+
registerValue,
|
|
150
|
+
reset,
|
|
151
|
+
resolve,
|
|
152
|
+
rootContainer
|
|
153
|
+
});
|
|
154
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/container.ts","../src/plugins.ts","../src/bootstrap.ts"],"sourcesContent":["export * from './container';\nexport * from './plugins';\nexport * from './bootstrap';\n","// src/container.ts\ntype Factory<T> = () => T;\nexport type Token<T> = symbol & { __type?: T };\n\ntype Provider<T> =\n | { kind: 'value'; value: T }\n | { kind: 'singleton'; factory: Factory<T>; instance?: T }\n | { kind: 'factory'; factory: Factory<T> };\n\nexport class Container {\n private registry = new Map<Token<any>, Provider<any>>();\n constructor(private parent?: Container) {}\n\n defineToken<T>(desc: string): Token<T> {\n return Symbol.for(`ioc:${desc}`) as Token<T>;\n }\n\n registerValue<T>(token: Token<T>, value: T) {\n this.registry.set(token, { kind: 'value', value });\n }\n registerSingleton<T>(token: Token<T>, factory: Factory<T>) {\n this.registry.set(token, { kind: 'singleton', factory });\n }\n registerFactory<T>(token: Token<T>, factory: Factory<T>) {\n this.registry.set(token, { kind: 'factory', factory });\n }\n\n isRegistered<T>(token: Token<T>): boolean {\n return this.registry.has(token) || (!!this.parent && this.parent.isRegistered(token));\n }\n\n resolve<T>(token: Token<T>): T {\n if (this.registry.has(token)) {\n const prov = this.registry.get(token)!;\n switch (prov.kind) {\n case 'value': return prov.value as T;\n case 'singleton':\n if (prov.instance === undefined) prov.instance = prov.factory();\n return prov.instance as T;\n case 'factory': return prov.factory();\n }\n }\n if (this.parent) return this.parent.resolve(token);\n throw new Error(`Token not registered: ${String(token)}`);\n }\n\n override<T>(token: Token<T>, provider: Provider<T>) {\n this.registry.set(token, provider);\n }\n\n reset(tokens?: Token<any>[]) {\n if (!tokens) return void this.registry.clear();\n for (const t of tokens) this.registry.delete(t);\n }\n\n createScope(): Container {\n return new Container(this);\n }\n\n overrideValue<T>(token: Token<T>, value: T) { this.override(token, { kind: 'value', value }); }\n overrideSingleton<T>(token: Token<T>, factory: Factory<T>) { this.override(token, { kind: 'singleton', factory }); }\n overrideFactory<T>(token: Token<T>, factory: Factory<T>) { this.override(token, { kind: 'factory', factory }); }\n}\n\n// Root container + helpers\nexport const rootContainer = new Container();\nexport const defineToken = <T>(desc: string) => rootContainer.defineToken<T>(desc);\nexport const registerValue = <T>(t: Token<T>, v: T) => rootContainer.registerValue(t, v);\nexport const registerSingleton = <T>(t: Token<T>, f: Factory<T>) => rootContainer.registerSingleton(t, f);\nexport const registerFactory = <T>(t: Token<T>, f: Factory<T>) => rootContainer.registerFactory(t, f);\nexport const resolve = <T>(t: Token<T>) => rootContainer.resolve<T>(t);\nexport const isRegistered = <T>(t: Token<T>) => rootContainer.isRegistered<T>(t);\nexport const reset = (tokens?: Token<any>[]) => rootContainer.reset(tokens);\nexport const createScope = () => rootContainer.createScope();\nexport const overrideValue = <T>(t: Token<T>, v: T) => rootContainer.overrideValue(t, v);\nexport const overrideSingleton = <T>(t: Token<T>, f: Factory<T>) => rootContainer.overrideSingleton(t, f);\nexport const overrideFactory = <T>(t: Token<T>, f: Factory<T>) => rootContainer.overrideFactory(t, f);\n","// src/plugins.ts\nimport type { Container } from './container';\n\nexport type IOCRegistrar = (c: Container) => void;\n\nconst registrars: IOCRegistrar[] = [];\n\nexport function registerIOCPlugin(registrar: IOCRegistrar) {\n registrars.push(registrar);\n}\n\n/** Apenas leitura (sem expor o array interno) */\nexport function getIOCPlugins(): IOCRegistrar[] {\n return registrars.slice();\n}\n\n/** Para testes: limpar a lista de registrars */\nexport function _clearIOCPlugins() {\n registrars.length = 0;\n}\n","// src/bootstrap.ts\nimport { rootContainer } from './container';\nimport { getIOCPlugins } from './plugins';\n\nlet bootstrapped = false;\n\n/**\n * Executa todos os registrars previamente registrados (plugins de módulos).\n * Deve ser chamado uma única vez no início do app.\n */\nexport function bootstrapIOC(): void {\n if (bootstrapped) return;\n for (const reg of getIOCPlugins()) {\n reg(rootContainer);\n }\n bootstrapped = true;\n}\n\nexport default bootstrapIOC;\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
type Factory<T> = () => T;
|
|
2
|
+
type Token<T> = symbol & {
|
|
3
|
+
__type?: T;
|
|
4
|
+
};
|
|
5
|
+
type Provider<T> = {
|
|
6
|
+
kind: 'value';
|
|
7
|
+
value: T;
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'singleton';
|
|
10
|
+
factory: Factory<T>;
|
|
11
|
+
instance?: T;
|
|
12
|
+
} | {
|
|
13
|
+
kind: 'factory';
|
|
14
|
+
factory: Factory<T>;
|
|
15
|
+
};
|
|
16
|
+
declare class Container {
|
|
17
|
+
private parent?;
|
|
18
|
+
private registry;
|
|
19
|
+
constructor(parent?: Container | undefined);
|
|
20
|
+
defineToken<T>(desc: string): Token<T>;
|
|
21
|
+
registerValue<T>(token: Token<T>, value: T): void;
|
|
22
|
+
registerSingleton<T>(token: Token<T>, factory: Factory<T>): void;
|
|
23
|
+
registerFactory<T>(token: Token<T>, factory: Factory<T>): void;
|
|
24
|
+
isRegistered<T>(token: Token<T>): boolean;
|
|
25
|
+
resolve<T>(token: Token<T>): T;
|
|
26
|
+
override<T>(token: Token<T>, provider: Provider<T>): void;
|
|
27
|
+
reset(tokens?: Token<any>[]): undefined;
|
|
28
|
+
createScope(): Container;
|
|
29
|
+
overrideValue<T>(token: Token<T>, value: T): void;
|
|
30
|
+
overrideSingleton<T>(token: Token<T>, factory: Factory<T>): void;
|
|
31
|
+
overrideFactory<T>(token: Token<T>, factory: Factory<T>): void;
|
|
32
|
+
}
|
|
33
|
+
declare const rootContainer: Container;
|
|
34
|
+
declare const defineToken: <T>(desc: string) => Token<T>;
|
|
35
|
+
declare const registerValue: <T>(t: Token<T>, v: T) => void;
|
|
36
|
+
declare const registerSingleton: <T>(t: Token<T>, f: Factory<T>) => void;
|
|
37
|
+
declare const registerFactory: <T>(t: Token<T>, f: Factory<T>) => void;
|
|
38
|
+
declare const resolve: <T>(t: Token<T>) => T;
|
|
39
|
+
declare const isRegistered: <T>(t: Token<T>) => boolean;
|
|
40
|
+
declare const reset: (tokens?: Token<any>[]) => undefined;
|
|
41
|
+
declare const createScope: () => Container;
|
|
42
|
+
declare const overrideValue: <T>(t: Token<T>, v: T) => void;
|
|
43
|
+
declare const overrideSingleton: <T>(t: Token<T>, f: Factory<T>) => void;
|
|
44
|
+
declare const overrideFactory: <T>(t: Token<T>, f: Factory<T>) => void;
|
|
45
|
+
|
|
46
|
+
type IOCRegistrar = (c: Container) => void;
|
|
47
|
+
declare function registerIOCPlugin(registrar: IOCRegistrar): void;
|
|
48
|
+
/** Apenas leitura (sem expor o array interno) */
|
|
49
|
+
declare function getIOCPlugins(): IOCRegistrar[];
|
|
50
|
+
/** Para testes: limpar a lista de registrars */
|
|
51
|
+
declare function _clearIOCPlugins(): void;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Executa todos os registrars previamente registrados (plugins de módulos).
|
|
55
|
+
* Deve ser chamado uma única vez no início do app.
|
|
56
|
+
*/
|
|
57
|
+
declare function bootstrapIOC(): void;
|
|
58
|
+
|
|
59
|
+
export { Container, type IOCRegistrar, type Token, _clearIOCPlugins, bootstrapIOC, createScope, defineToken, getIOCPlugins, isRegistered, overrideFactory, overrideSingleton, overrideValue, registerFactory, registerIOCPlugin, registerSingleton, registerValue, reset, resolve, rootContainer };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
type Factory<T> = () => T;
|
|
2
|
+
type Token<T> = symbol & {
|
|
3
|
+
__type?: T;
|
|
4
|
+
};
|
|
5
|
+
type Provider<T> = {
|
|
6
|
+
kind: 'value';
|
|
7
|
+
value: T;
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'singleton';
|
|
10
|
+
factory: Factory<T>;
|
|
11
|
+
instance?: T;
|
|
12
|
+
} | {
|
|
13
|
+
kind: 'factory';
|
|
14
|
+
factory: Factory<T>;
|
|
15
|
+
};
|
|
16
|
+
declare class Container {
|
|
17
|
+
private parent?;
|
|
18
|
+
private registry;
|
|
19
|
+
constructor(parent?: Container | undefined);
|
|
20
|
+
defineToken<T>(desc: string): Token<T>;
|
|
21
|
+
registerValue<T>(token: Token<T>, value: T): void;
|
|
22
|
+
registerSingleton<T>(token: Token<T>, factory: Factory<T>): void;
|
|
23
|
+
registerFactory<T>(token: Token<T>, factory: Factory<T>): void;
|
|
24
|
+
isRegistered<T>(token: Token<T>): boolean;
|
|
25
|
+
resolve<T>(token: Token<T>): T;
|
|
26
|
+
override<T>(token: Token<T>, provider: Provider<T>): void;
|
|
27
|
+
reset(tokens?: Token<any>[]): undefined;
|
|
28
|
+
createScope(): Container;
|
|
29
|
+
overrideValue<T>(token: Token<T>, value: T): void;
|
|
30
|
+
overrideSingleton<T>(token: Token<T>, factory: Factory<T>): void;
|
|
31
|
+
overrideFactory<T>(token: Token<T>, factory: Factory<T>): void;
|
|
32
|
+
}
|
|
33
|
+
declare const rootContainer: Container;
|
|
34
|
+
declare const defineToken: <T>(desc: string) => Token<T>;
|
|
35
|
+
declare const registerValue: <T>(t: Token<T>, v: T) => void;
|
|
36
|
+
declare const registerSingleton: <T>(t: Token<T>, f: Factory<T>) => void;
|
|
37
|
+
declare const registerFactory: <T>(t: Token<T>, f: Factory<T>) => void;
|
|
38
|
+
declare const resolve: <T>(t: Token<T>) => T;
|
|
39
|
+
declare const isRegistered: <T>(t: Token<T>) => boolean;
|
|
40
|
+
declare const reset: (tokens?: Token<any>[]) => undefined;
|
|
41
|
+
declare const createScope: () => Container;
|
|
42
|
+
declare const overrideValue: <T>(t: Token<T>, v: T) => void;
|
|
43
|
+
declare const overrideSingleton: <T>(t: Token<T>, f: Factory<T>) => void;
|
|
44
|
+
declare const overrideFactory: <T>(t: Token<T>, f: Factory<T>) => void;
|
|
45
|
+
|
|
46
|
+
type IOCRegistrar = (c: Container) => void;
|
|
47
|
+
declare function registerIOCPlugin(registrar: IOCRegistrar): void;
|
|
48
|
+
/** Apenas leitura (sem expor o array interno) */
|
|
49
|
+
declare function getIOCPlugins(): IOCRegistrar[];
|
|
50
|
+
/** Para testes: limpar a lista de registrars */
|
|
51
|
+
declare function _clearIOCPlugins(): void;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Executa todos os registrars previamente registrados (plugins de módulos).
|
|
55
|
+
* Deve ser chamado uma única vez no início do app.
|
|
56
|
+
*/
|
|
57
|
+
declare function bootstrapIOC(): void;
|
|
58
|
+
|
|
59
|
+
export { Container, type IOCRegistrar, type Token, _clearIOCPlugins, bootstrapIOC, createScope, defineToken, getIOCPlugins, isRegistered, overrideFactory, overrideSingleton, overrideValue, registerFactory, registerIOCPlugin, registerSingleton, registerValue, reset, resolve, rootContainer };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// src/container.ts
|
|
2
|
+
var Container = class _Container {
|
|
3
|
+
constructor(parent) {
|
|
4
|
+
this.parent = parent;
|
|
5
|
+
this.registry = /* @__PURE__ */ new Map();
|
|
6
|
+
}
|
|
7
|
+
defineToken(desc) {
|
|
8
|
+
return Symbol.for(`ioc:${desc}`);
|
|
9
|
+
}
|
|
10
|
+
registerValue(token, value) {
|
|
11
|
+
this.registry.set(token, { kind: "value", value });
|
|
12
|
+
}
|
|
13
|
+
registerSingleton(token, factory) {
|
|
14
|
+
this.registry.set(token, { kind: "singleton", factory });
|
|
15
|
+
}
|
|
16
|
+
registerFactory(token, factory) {
|
|
17
|
+
this.registry.set(token, { kind: "factory", factory });
|
|
18
|
+
}
|
|
19
|
+
isRegistered(token) {
|
|
20
|
+
return this.registry.has(token) || !!this.parent && this.parent.isRegistered(token);
|
|
21
|
+
}
|
|
22
|
+
resolve(token) {
|
|
23
|
+
if (this.registry.has(token)) {
|
|
24
|
+
const prov = this.registry.get(token);
|
|
25
|
+
switch (prov.kind) {
|
|
26
|
+
case "value":
|
|
27
|
+
return prov.value;
|
|
28
|
+
case "singleton":
|
|
29
|
+
if (prov.instance === void 0) prov.instance = prov.factory();
|
|
30
|
+
return prov.instance;
|
|
31
|
+
case "factory":
|
|
32
|
+
return prov.factory();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (this.parent) return this.parent.resolve(token);
|
|
36
|
+
throw new Error(`Token not registered: ${String(token)}`);
|
|
37
|
+
}
|
|
38
|
+
override(token, provider) {
|
|
39
|
+
this.registry.set(token, provider);
|
|
40
|
+
}
|
|
41
|
+
reset(tokens) {
|
|
42
|
+
if (!tokens) return void this.registry.clear();
|
|
43
|
+
for (const t of tokens) this.registry.delete(t);
|
|
44
|
+
}
|
|
45
|
+
createScope() {
|
|
46
|
+
return new _Container(this);
|
|
47
|
+
}
|
|
48
|
+
overrideValue(token, value) {
|
|
49
|
+
this.override(token, { kind: "value", value });
|
|
50
|
+
}
|
|
51
|
+
overrideSingleton(token, factory) {
|
|
52
|
+
this.override(token, { kind: "singleton", factory });
|
|
53
|
+
}
|
|
54
|
+
overrideFactory(token, factory) {
|
|
55
|
+
this.override(token, { kind: "factory", factory });
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
var rootContainer = new Container();
|
|
59
|
+
var defineToken = (desc) => rootContainer.defineToken(desc);
|
|
60
|
+
var registerValue = (t, v) => rootContainer.registerValue(t, v);
|
|
61
|
+
var registerSingleton = (t, f) => rootContainer.registerSingleton(t, f);
|
|
62
|
+
var registerFactory = (t, f) => rootContainer.registerFactory(t, f);
|
|
63
|
+
var resolve = (t) => rootContainer.resolve(t);
|
|
64
|
+
var isRegistered = (t) => rootContainer.isRegistered(t);
|
|
65
|
+
var reset = (tokens) => rootContainer.reset(tokens);
|
|
66
|
+
var createScope = () => rootContainer.createScope();
|
|
67
|
+
var overrideValue = (t, v) => rootContainer.overrideValue(t, v);
|
|
68
|
+
var overrideSingleton = (t, f) => rootContainer.overrideSingleton(t, f);
|
|
69
|
+
var overrideFactory = (t, f) => rootContainer.overrideFactory(t, f);
|
|
70
|
+
|
|
71
|
+
// src/plugins.ts
|
|
72
|
+
var registrars = [];
|
|
73
|
+
function registerIOCPlugin(registrar) {
|
|
74
|
+
registrars.push(registrar);
|
|
75
|
+
}
|
|
76
|
+
function getIOCPlugins() {
|
|
77
|
+
return registrars.slice();
|
|
78
|
+
}
|
|
79
|
+
function _clearIOCPlugins() {
|
|
80
|
+
registrars.length = 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// src/bootstrap.ts
|
|
84
|
+
var bootstrapped = false;
|
|
85
|
+
function bootstrapIOC() {
|
|
86
|
+
if (bootstrapped) return;
|
|
87
|
+
for (const reg of getIOCPlugins()) {
|
|
88
|
+
reg(rootContainer);
|
|
89
|
+
}
|
|
90
|
+
bootstrapped = true;
|
|
91
|
+
}
|
|
92
|
+
export {
|
|
93
|
+
Container,
|
|
94
|
+
_clearIOCPlugins,
|
|
95
|
+
bootstrapIOC,
|
|
96
|
+
createScope,
|
|
97
|
+
defineToken,
|
|
98
|
+
getIOCPlugins,
|
|
99
|
+
isRegistered,
|
|
100
|
+
overrideFactory,
|
|
101
|
+
overrideSingleton,
|
|
102
|
+
overrideValue,
|
|
103
|
+
registerFactory,
|
|
104
|
+
registerIOCPlugin,
|
|
105
|
+
registerSingleton,
|
|
106
|
+
registerValue,
|
|
107
|
+
reset,
|
|
108
|
+
resolve,
|
|
109
|
+
rootContainer
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/container.ts","../src/plugins.ts","../src/bootstrap.ts"],"sourcesContent":["// src/container.ts\ntype Factory<T> = () => T;\nexport type Token<T> = symbol & { __type?: T };\n\ntype Provider<T> =\n | { kind: 'value'; value: T }\n | { kind: 'singleton'; factory: Factory<T>; instance?: T }\n | { kind: 'factory'; factory: Factory<T> };\n\nexport class Container {\n private registry = new Map<Token<any>, Provider<any>>();\n constructor(private parent?: Container) {}\n\n defineToken<T>(desc: string): Token<T> {\n return Symbol.for(`ioc:${desc}`) as Token<T>;\n }\n\n registerValue<T>(token: Token<T>, value: T) {\n this.registry.set(token, { kind: 'value', value });\n }\n registerSingleton<T>(token: Token<T>, factory: Factory<T>) {\n this.registry.set(token, { kind: 'singleton', factory });\n }\n registerFactory<T>(token: Token<T>, factory: Factory<T>) {\n this.registry.set(token, { kind: 'factory', factory });\n }\n\n isRegistered<T>(token: Token<T>): boolean {\n return this.registry.has(token) || (!!this.parent && this.parent.isRegistered(token));\n }\n\n resolve<T>(token: Token<T>): T {\n if (this.registry.has(token)) {\n const prov = this.registry.get(token)!;\n switch (prov.kind) {\n case 'value': return prov.value as T;\n case 'singleton':\n if (prov.instance === undefined) prov.instance = prov.factory();\n return prov.instance as T;\n case 'factory': return prov.factory();\n }\n }\n if (this.parent) return this.parent.resolve(token);\n throw new Error(`Token not registered: ${String(token)}`);\n }\n\n override<T>(token: Token<T>, provider: Provider<T>) {\n this.registry.set(token, provider);\n }\n\n reset(tokens?: Token<any>[]) {\n if (!tokens) return void this.registry.clear();\n for (const t of tokens) this.registry.delete(t);\n }\n\n createScope(): Container {\n return new Container(this);\n }\n\n overrideValue<T>(token: Token<T>, value: T) { this.override(token, { kind: 'value', value }); }\n overrideSingleton<T>(token: Token<T>, factory: Factory<T>) { this.override(token, { kind: 'singleton', factory }); }\n overrideFactory<T>(token: Token<T>, factory: Factory<T>) { this.override(token, { kind: 'factory', factory }); }\n}\n\n// Root container + helpers\nexport const rootContainer = new Container();\nexport const defineToken = <T>(desc: string) => rootContainer.defineToken<T>(desc);\nexport const registerValue = <T>(t: Token<T>, v: T) => rootContainer.registerValue(t, v);\nexport const registerSingleton = <T>(t: Token<T>, f: Factory<T>) => rootContainer.registerSingleton(t, f);\nexport const registerFactory = <T>(t: Token<T>, f: Factory<T>) => rootContainer.registerFactory(t, f);\nexport const resolve = <T>(t: Token<T>) => rootContainer.resolve<T>(t);\nexport const isRegistered = <T>(t: Token<T>) => rootContainer.isRegistered<T>(t);\nexport const reset = (tokens?: Token<any>[]) => rootContainer.reset(tokens);\nexport const createScope = () => rootContainer.createScope();\nexport const overrideValue = <T>(t: Token<T>, v: T) => rootContainer.overrideValue(t, v);\nexport const overrideSingleton = <T>(t: Token<T>, f: Factory<T>) => rootContainer.overrideSingleton(t, f);\nexport const overrideFactory = <T>(t: Token<T>, f: Factory<T>) => rootContainer.overrideFactory(t, f);\n","// src/plugins.ts\nimport type { Container } from './container';\n\nexport type IOCRegistrar = (c: Container) => void;\n\nconst registrars: IOCRegistrar[] = [];\n\nexport function registerIOCPlugin(registrar: IOCRegistrar) {\n registrars.push(registrar);\n}\n\n/** Apenas leitura (sem expor o array interno) */\nexport function getIOCPlugins(): IOCRegistrar[] {\n return registrars.slice();\n}\n\n/** Para testes: limpar a lista de registrars */\nexport function _clearIOCPlugins() {\n registrars.length = 0;\n}\n","// src/bootstrap.ts\nimport { rootContainer } from './container';\nimport { getIOCPlugins } from './plugins';\n\nlet bootstrapped = false;\n\n/**\n * Executa todos os registrars previamente registrados (plugins de módulos).\n * Deve ser chamado uma única vez no início do app.\n */\nexport function bootstrapIOC(): void {\n if (bootstrapped) return;\n for (const reg of getIOCPlugins()) {\n reg(rootContainer);\n }\n bootstrapped = true;\n}\n\nexport default bootstrapIOC;\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "targwire",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "TargWire – mini IoC para TS/JS com Singleton, Transient e Scoped (ideal para Expo/React Native).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.cjs",
|
|
8
|
+
"module": "dist/index.mjs",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"react-native": "dist/index.mjs",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.mjs",
|
|
15
|
+
"require": "./dist/index.cjs"
|
|
16
|
+
},
|
|
17
|
+
"./package.json": "./package.json"
|
|
18
|
+
},
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsup",
|
|
25
|
+
"clean": "rimraf dist",
|
|
26
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"rimraf": "^6.0.0",
|
|
30
|
+
"tsup": "^8.5.0",
|
|
31
|
+
"typescript": "^5.5.0"
|
|
32
|
+
}
|
|
33
|
+
}
|