@ooneex/service 0.0.1 → 0.0.5
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 +504 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.js +2 -1
- package/dist/index.js.map +4 -3
- package/package.json +17 -7
package/README.md
CHANGED
|
@@ -1 +1,505 @@
|
|
|
1
1
|
# @ooneex/service
|
|
2
|
+
|
|
3
|
+
A service layer decorator and base interface for business logic encapsulation in TypeScript applications. This package provides the foundation for creating injectable service classes with dependency injection support through the Ooneex container.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
✅ **Service Decorator** - Register services with the DI container using decorators
|
|
15
|
+
|
|
16
|
+
✅ **Interface Contract** - Standard interface for service implementations
|
|
17
|
+
|
|
18
|
+
✅ **Scope Control** - Configure singleton, transient, or request-scoped services
|
|
19
|
+
|
|
20
|
+
✅ **Type-Safe** - Full TypeScript support with proper type definitions
|
|
21
|
+
|
|
22
|
+
✅ **Container Integration** - Seamless integration with @ooneex/container
|
|
23
|
+
|
|
24
|
+
✅ **Zero Boilerplate** - Simple decorator-based registration
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
### Bun
|
|
29
|
+
```bash
|
|
30
|
+
bun add @ooneex/service
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### pnpm
|
|
34
|
+
```bash
|
|
35
|
+
pnpm add @ooneex/service
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Yarn
|
|
39
|
+
```bash
|
|
40
|
+
yarn add @ooneex/service
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### npm
|
|
44
|
+
```bash
|
|
45
|
+
npm install @ooneex/service
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Usage
|
|
49
|
+
|
|
50
|
+
### Basic Service
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { decorator, type IService } from '@ooneex/service';
|
|
54
|
+
|
|
55
|
+
interface SendEmailData {
|
|
56
|
+
to: string;
|
|
57
|
+
subject: string;
|
|
58
|
+
body: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@decorator.service()
|
|
62
|
+
class EmailService implements IService<SendEmailData> {
|
|
63
|
+
public async execute(data?: SendEmailData): Promise<void> {
|
|
64
|
+
if (!data) return;
|
|
65
|
+
|
|
66
|
+
await this.sendEmail(data.to, data.subject, data.body);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private async sendEmail(to: string, subject: string, body: string): Promise<void> {
|
|
70
|
+
// Email sending logic
|
|
71
|
+
console.log(`Sending email to ${to}: ${subject}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Resolving Services
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { container } from '@ooneex/container';
|
|
80
|
+
import { EmailService } from './services/EmailService';
|
|
81
|
+
|
|
82
|
+
// Service is automatically registered by the decorator
|
|
83
|
+
const emailService = container.get(EmailService);
|
|
84
|
+
|
|
85
|
+
await emailService.execute({
|
|
86
|
+
to: 'user@example.com',
|
|
87
|
+
subject: 'Welcome!',
|
|
88
|
+
body: 'Thank you for signing up.'
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Service with Dependencies
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { decorator, type IService } from '@ooneex/service';
|
|
96
|
+
import { container } from '@ooneex/container';
|
|
97
|
+
import type { ILogger } from '@ooneex/logger';
|
|
98
|
+
import type { ICache } from '@ooneex/cache';
|
|
99
|
+
|
|
100
|
+
interface ProcessOrderData {
|
|
101
|
+
orderId: string;
|
|
102
|
+
items: Array<{ productId: string; quantity: number }>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@decorator.service()
|
|
106
|
+
class OrderProcessingService implements IService<ProcessOrderData> {
|
|
107
|
+
private readonly logger = container.get<ILogger>('logger');
|
|
108
|
+
private readonly cache = container.get<ICache>('cache');
|
|
109
|
+
|
|
110
|
+
public async execute(data?: ProcessOrderData): Promise<void> {
|
|
111
|
+
if (!data) return;
|
|
112
|
+
|
|
113
|
+
this.logger.info('Processing order', { orderId: data.orderId });
|
|
114
|
+
|
|
115
|
+
// Process order items
|
|
116
|
+
for (const item of data.items) {
|
|
117
|
+
await this.processItem(item);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Cache the result
|
|
121
|
+
await this.cache.set(`order:${data.orderId}:status`, 'processed', 3600);
|
|
122
|
+
|
|
123
|
+
this.logger.success('Order processed', { orderId: data.orderId });
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private async processItem(item: { productId: string; quantity: number }): Promise<void> {
|
|
127
|
+
// Item processing logic
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Transient Services
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { decorator, type IService } from '@ooneex/service';
|
|
136
|
+
import { EContainerScope } from '@ooneex/container';
|
|
137
|
+
|
|
138
|
+
@decorator.service(EContainerScope.Transient)
|
|
139
|
+
class RequestContextService implements IService {
|
|
140
|
+
private readonly requestId = crypto.randomUUID();
|
|
141
|
+
|
|
142
|
+
public async execute(): Promise<void> {
|
|
143
|
+
console.log(`Request ID: ${this.requestId}`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
public getRequestId(): string {
|
|
147
|
+
return this.requestId;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Each resolution creates a new instance
|
|
152
|
+
const service1 = container.get(RequestContextService);
|
|
153
|
+
const service2 = container.get(RequestContextService);
|
|
154
|
+
console.log(service1.getRequestId() !== service2.getRequestId()); // true
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Request-Scoped Services
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import { decorator, type IService } from '@ooneex/service';
|
|
161
|
+
import { EContainerScope } from '@ooneex/container';
|
|
162
|
+
|
|
163
|
+
@decorator.service(EContainerScope.Request)
|
|
164
|
+
class UserSessionService implements IService {
|
|
165
|
+
private userId: string | null = null;
|
|
166
|
+
|
|
167
|
+
public async execute(): Promise<void> {
|
|
168
|
+
// Initialize session
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
public setUserId(id: string): void {
|
|
172
|
+
this.userId = id;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
public getUserId(): string | null {
|
|
176
|
+
return this.userId;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## API Reference
|
|
182
|
+
|
|
183
|
+
### Decorators
|
|
184
|
+
|
|
185
|
+
#### `@decorator.service(scope?)`
|
|
186
|
+
|
|
187
|
+
Decorator to register a service class with the DI container.
|
|
188
|
+
|
|
189
|
+
**Parameters:**
|
|
190
|
+
- `scope` - Container scope (default: `EContainerScope.Singleton`)
|
|
191
|
+
- `Singleton` - Single instance shared across all requests
|
|
192
|
+
- `Transient` - New instance created on every resolution
|
|
193
|
+
- `Request` - New instance per request context
|
|
194
|
+
|
|
195
|
+
**Example:**
|
|
196
|
+
```typescript
|
|
197
|
+
import { decorator } from '@ooneex/service';
|
|
198
|
+
import { EContainerScope } from '@ooneex/container';
|
|
199
|
+
|
|
200
|
+
// Singleton (default)
|
|
201
|
+
@decorator.service()
|
|
202
|
+
class MySingletonService {}
|
|
203
|
+
|
|
204
|
+
// Transient
|
|
205
|
+
@decorator.service(EContainerScope.Transient)
|
|
206
|
+
class MyTransientService {}
|
|
207
|
+
|
|
208
|
+
// Request-scoped
|
|
209
|
+
@decorator.service(EContainerScope.Request)
|
|
210
|
+
class MyRequestService {}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Interfaces
|
|
214
|
+
|
|
215
|
+
#### `IService<T>`
|
|
216
|
+
|
|
217
|
+
Interface for service implementations.
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
interface IService<T = Record<string, unknown>> {
|
|
221
|
+
execute: (data?: T) => Promise<void>;
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**Type Parameter:**
|
|
226
|
+
- `T` - The type of data the service accepts (default: `Record<string, unknown>`)
|
|
227
|
+
|
|
228
|
+
**Methods:**
|
|
229
|
+
|
|
230
|
+
##### `execute(data?: T): Promise<void>`
|
|
231
|
+
|
|
232
|
+
Execute the service's main logic.
|
|
233
|
+
|
|
234
|
+
**Parameters:**
|
|
235
|
+
- `data` - Optional data to process
|
|
236
|
+
|
|
237
|
+
**Returns:** Promise that resolves when execution completes
|
|
238
|
+
|
|
239
|
+
### Types
|
|
240
|
+
|
|
241
|
+
#### `ServiceClassType`
|
|
242
|
+
|
|
243
|
+
Type for service class constructors.
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
type ServiceClassType = new (...args: any[]) => IService;
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Advanced Usage
|
|
250
|
+
|
|
251
|
+
### Service Composition
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
import { decorator, type IService } from '@ooneex/service';
|
|
255
|
+
import { container } from '@ooneex/container';
|
|
256
|
+
|
|
257
|
+
interface CreateUserData {
|
|
258
|
+
email: string;
|
|
259
|
+
name: string;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
@decorator.service()
|
|
263
|
+
class ValidationService {
|
|
264
|
+
public validateEmail(email: string): boolean {
|
|
265
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
@decorator.service()
|
|
270
|
+
class NotificationService implements IService<{ userId: string; message: string }> {
|
|
271
|
+
public async execute(data?: { userId: string; message: string }): Promise<void> {
|
|
272
|
+
if (!data) return;
|
|
273
|
+
// Send notification
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
@decorator.service()
|
|
278
|
+
class UserCreationService implements IService<CreateUserData> {
|
|
279
|
+
private readonly validationService = container.get(ValidationService);
|
|
280
|
+
private readonly notificationService = container.get(NotificationService);
|
|
281
|
+
|
|
282
|
+
public async execute(data?: CreateUserData): Promise<void> {
|
|
283
|
+
if (!data) return;
|
|
284
|
+
|
|
285
|
+
// Validate
|
|
286
|
+
if (!this.validationService.validateEmail(data.email)) {
|
|
287
|
+
throw new Error('Invalid email');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Create user
|
|
291
|
+
const userId = await this.createUser(data);
|
|
292
|
+
|
|
293
|
+
// Notify
|
|
294
|
+
await this.notificationService.execute({
|
|
295
|
+
userId,
|
|
296
|
+
message: 'Welcome to our platform!'
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
private async createUser(data: CreateUserData): Promise<string> {
|
|
301
|
+
// User creation logic
|
|
302
|
+
return crypto.randomUUID();
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Service with Controller Integration
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
import { Route } from '@ooneex/routing';
|
|
311
|
+
import { decorator, type IService } from '@ooneex/service';
|
|
312
|
+
import { container } from '@ooneex/container';
|
|
313
|
+
import type { IController, ContextType } from '@ooneex/controller';
|
|
314
|
+
|
|
315
|
+
interface SubscriptionData {
|
|
316
|
+
userId: string;
|
|
317
|
+
plan: 'basic' | 'premium' | 'enterprise';
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
@decorator.service()
|
|
321
|
+
class SubscriptionService implements IService<SubscriptionData> {
|
|
322
|
+
public async execute(data?: SubscriptionData): Promise<void> {
|
|
323
|
+
if (!data) return;
|
|
324
|
+
await this.processSubscription(data.userId, data.plan);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
private async processSubscription(userId: string, plan: string): Promise<void> {
|
|
328
|
+
// Subscription logic
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
@Route.http({
|
|
333
|
+
name: 'api.subscriptions.create',
|
|
334
|
+
path: '/api/subscriptions',
|
|
335
|
+
method: 'POST',
|
|
336
|
+
description: 'Create a subscription'
|
|
337
|
+
})
|
|
338
|
+
class SubscriptionController implements IController {
|
|
339
|
+
private readonly subscriptionService = container.get(SubscriptionService);
|
|
340
|
+
|
|
341
|
+
public async index(context: ContextType): Promise<IResponse> {
|
|
342
|
+
const { plan } = context.payload;
|
|
343
|
+
const userId = context.user?.id;
|
|
344
|
+
|
|
345
|
+
if (!userId) {
|
|
346
|
+
return context.response.exception('Unauthorized', { status: 401 });
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
await this.subscriptionService.execute({ userId, plan });
|
|
350
|
+
|
|
351
|
+
return context.response.json({ success: true });
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Error Handling in Services
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
import { decorator, type IService } from '@ooneex/service';
|
|
360
|
+
import { Exception } from '@ooneex/exception';
|
|
361
|
+
|
|
362
|
+
interface PaymentData {
|
|
363
|
+
amount: number;
|
|
364
|
+
currency: string;
|
|
365
|
+
cardToken: string;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
class PaymentException extends Exception {
|
|
369
|
+
constructor(message: string, public readonly code: string) {
|
|
370
|
+
super(message, { status: 400, data: { code } });
|
|
371
|
+
this.name = 'PaymentException';
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
@decorator.service()
|
|
376
|
+
class PaymentService implements IService<PaymentData> {
|
|
377
|
+
public async execute(data?: PaymentData): Promise<void> {
|
|
378
|
+
if (!data) {
|
|
379
|
+
throw new PaymentException('Payment data required', 'MISSING_DATA');
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (data.amount <= 0) {
|
|
383
|
+
throw new PaymentException('Invalid amount', 'INVALID_AMOUNT');
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
try {
|
|
387
|
+
await this.processPayment(data);
|
|
388
|
+
} catch (error) {
|
|
389
|
+
throw new PaymentException('Payment processing failed', 'PROCESSING_ERROR');
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
private async processPayment(data: PaymentData): Promise<void> {
|
|
394
|
+
// Payment processing logic
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### Generic Service Pattern
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
import { decorator, type IService } from '@ooneex/service';
|
|
403
|
+
|
|
404
|
+
interface CrudData<T> {
|
|
405
|
+
action: 'create' | 'read' | 'update' | 'delete';
|
|
406
|
+
entity: T;
|
|
407
|
+
id?: string;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
@decorator.service()
|
|
411
|
+
class GenericCrudService<T extends { id?: string }> implements IService<CrudData<T>> {
|
|
412
|
+
constructor(private readonly entityName: string) {}
|
|
413
|
+
|
|
414
|
+
public async execute(data?: CrudData<T>): Promise<void> {
|
|
415
|
+
if (!data) return;
|
|
416
|
+
|
|
417
|
+
switch (data.action) {
|
|
418
|
+
case 'create':
|
|
419
|
+
await this.create(data.entity);
|
|
420
|
+
break;
|
|
421
|
+
case 'read':
|
|
422
|
+
await this.read(data.id);
|
|
423
|
+
break;
|
|
424
|
+
case 'update':
|
|
425
|
+
await this.update(data.id, data.entity);
|
|
426
|
+
break;
|
|
427
|
+
case 'delete':
|
|
428
|
+
await this.delete(data.id);
|
|
429
|
+
break;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
private async create(entity: T): Promise<void> {
|
|
434
|
+
console.log(`Creating ${this.entityName}:`, entity);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
private async read(id?: string): Promise<void> {
|
|
438
|
+
console.log(`Reading ${this.entityName}:`, id);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
private async update(id?: string, entity?: T): Promise<void> {
|
|
442
|
+
console.log(`Updating ${this.entityName}:`, id, entity);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
private async delete(id?: string): Promise<void> {
|
|
446
|
+
console.log(`Deleting ${this.entityName}:`, id);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Testing Services
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
import { describe, test, expect, beforeEach } from 'bun:test';
|
|
455
|
+
import { container } from '@ooneex/container';
|
|
456
|
+
import { EmailService } from './EmailService';
|
|
457
|
+
|
|
458
|
+
describe('EmailService', () => {
|
|
459
|
+
let emailService: EmailService;
|
|
460
|
+
|
|
461
|
+
beforeEach(() => {
|
|
462
|
+
emailService = container.get(EmailService);
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
test('should execute without data', async () => {
|
|
466
|
+
await expect(emailService.execute()).resolves.toBeUndefined();
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
test('should execute with valid data', async () => {
|
|
470
|
+
await expect(
|
|
471
|
+
emailService.execute({
|
|
472
|
+
to: 'test@example.com',
|
|
473
|
+
subject: 'Test',
|
|
474
|
+
body: 'Test body'
|
|
475
|
+
})
|
|
476
|
+
).resolves.toBeUndefined();
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
## License
|
|
482
|
+
|
|
483
|
+
This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
|
|
484
|
+
|
|
485
|
+
## Contributing
|
|
486
|
+
|
|
487
|
+
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
|
|
488
|
+
|
|
489
|
+
### Development Setup
|
|
490
|
+
|
|
491
|
+
1. Clone the repository
|
|
492
|
+
2. Install dependencies: `bun install`
|
|
493
|
+
3. Run tests: `bun run test`
|
|
494
|
+
4. Build the project: `bun run build`
|
|
495
|
+
|
|
496
|
+
### Guidelines
|
|
497
|
+
|
|
498
|
+
- Write tests for new features
|
|
499
|
+
- Follow the existing code style
|
|
500
|
+
- Update documentation for API changes
|
|
501
|
+
- Ensure all tests pass before submitting PR
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
Made with ❤️ by the Ooneex team
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { EContainerScope } from "@ooneex/container";
|
|
1
2
|
type ServiceClassType = new (...args: any[]) => IService;
|
|
2
|
-
interface IService {
|
|
3
|
-
execute: () => Promise<void>;
|
|
3
|
+
interface IService<T = Record<string, unknown>> {
|
|
4
|
+
execute: (data?: T) => Promise<void>;
|
|
4
5
|
}
|
|
5
|
-
|
|
6
|
+
declare const decorator: {
|
|
7
|
+
service: (scope?: EContainerScope) => (target: ServiceClassType) => void;
|
|
8
|
+
};
|
|
9
|
+
export { decorator, ServiceClassType, IService };
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": [],
|
|
3
|
+
"sources": ["src/decorators.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
+
"import { container, EContainerScope } from \"@ooneex/container\";\nimport type { ServiceClassType } from \"./types\";\n\nexport const decorator = {\n service: (scope: EContainerScope = EContainerScope.Singleton) => {\n return (target: ServiceClassType): void => {\n container.add(target, scope);\n };\n },\n};\n"
|
|
5
6
|
],
|
|
6
|
-
"mappings": "",
|
|
7
|
-
"debugId": "
|
|
7
|
+
"mappings": "AAAA,oBAAS,qBAAW,0BAGb,IAAM,EAAY,CACvB,QAAS,CAAC,EAAyB,EAAgB,YAAc,CAC/D,MAAO,CAAC,IAAmC,CACzC,EAAU,IAAI,EAAQ,CAAK,GAGjC",
|
|
8
|
+
"debugId": "D88AC999764E45C964756E2164756E21",
|
|
8
9
|
"names": []
|
|
9
10
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ooneex/service",
|
|
3
|
-
"description": "",
|
|
4
|
-
"version": "0.0.
|
|
3
|
+
"description": "Service layer decorator and base classes for business logic encapsulation with dependency injection support",
|
|
4
|
+
"version": "0.0.5",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist",
|
|
@@ -22,13 +22,23 @@
|
|
|
22
22
|
},
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"scripts": {
|
|
25
|
+
"test": "bun test tests",
|
|
25
26
|
"build": "bunup",
|
|
26
27
|
"lint": "tsgo --noEmit && bunx biome lint",
|
|
27
|
-
"publish
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
"npm:publish": "bun publish --tolerate-republish --access public"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@ooneex/container": "0.0.2"
|
|
30
32
|
},
|
|
31
|
-
"dependencies": {},
|
|
32
33
|
"devDependencies": {},
|
|
33
|
-
"
|
|
34
|
+
"keywords": [
|
|
35
|
+
"bun",
|
|
36
|
+
"business-logic",
|
|
37
|
+
"decorator",
|
|
38
|
+
"layer",
|
|
39
|
+
"ooneex",
|
|
40
|
+
"service",
|
|
41
|
+
"services",
|
|
42
|
+
"typescript"
|
|
43
|
+
]
|
|
34
44
|
}
|