@decaf-ts/for-http 0.2.4 → 0.2.6

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 CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  ## decaf's Http Module
4
4
 
5
+ A TypeScript library for seamless REST API interactions. This module provides a flexible and type-safe way to communicate with HTTP-based services using the repository pattern. It includes adapters for different HTTP clients (with Axios implementation provided), repository and service classes for CRUD operations, and comprehensive type definitions to ensure type safety throughout your API interactions.
5
6
 
6
7
 
7
8
  ![Licence](https://img.shields.io/github/license/decaf-ts/for-http.svg?style=plastic)
@@ -18,12 +19,6 @@
18
19
  ![Pull Requests](https://img.shields.io/github/issues-pr-closed/decaf-ts/for-http.svg)
19
20
  ![Maintained](https://img.shields.io/badge/Maintained%3F-yes-green.svg)
20
21
 
21
- ![Line Coverage](workdocs/reports/coverage/badge-lines.svg)
22
- ![Function Coverage](workdocs/reports/coverage/badge-functions.svg)
23
- ![Statement Coverage](workdocs/reports/coverage/badge-statements.svg)
24
- ![Branch Coverage](workdocs/reports/coverage/badge-branches.svg)
25
-
26
-
27
22
  ![Forks](https://img.shields.io/github/forks/decaf-ts/for-http.svg)
28
23
  ![Stars](https://img.shields.io/github/stars/decaf-ts/for-http.svg)
29
24
  ![Watchers](https://img.shields.io/github/watchers/decaf-ts/for-http.svg)
@@ -35,27 +30,343 @@ Documentation available [here](https://decaf-ts.github.io/for-http/)
35
30
 
36
31
  ### Description
37
32
 
38
- No one needs the hassle of setting up new repos every time.
33
+ The `@decaf-ts/for-http` library provides a robust and type-safe solution for interacting with REST APIs in TypeScript applications. Built on top of the core Decaf framework, it implements the repository pattern to offer a clean and consistent interface for HTTP operations.
34
+
35
+ #### Architecture
36
+
37
+ The library is structured around several key components:
38
+
39
+ 1. **HTTP Adapter**: The `HttpAdapter` class serves as the foundation, providing an abstract interface for HTTP operations. It handles URL construction, error parsing, and implements the adapter pattern to work with different HTTP clients.
40
+
41
+ 2. **Axios Implementation**: The library includes a concrete implementation of the HTTP adapter using Axios (`AxiosHttpAdapter`), demonstrating how to integrate with popular HTTP clients.
42
+
43
+ 3. **Repository Pattern**: The `RestRepository` class extends the core Repository class to provide a high-level interface for CRUD operations on REST resources. It works with model classes and handles the mapping between your domain models and API endpoints.
39
44
 
40
- Now you can create new repositories from this template and enjoy having everything set up for you.
45
+ 4. **Service Layer**: The `RestService` class offers both individual and bulk CRUD operations, with support for the observer pattern to notify subscribers of changes.
41
46
 
47
+ 5. **Type Definitions**: Comprehensive type definitions ensure type safety throughout your API interactions, with interfaces like `HttpFlags` and `HttpConfig` providing configuration options.
48
+
49
+ #### Key Features
50
+
51
+ - **Type Safety**: Leverages TypeScript's type system to ensure API interactions are type-safe
52
+ - **Repository Pattern**: Implements the repository pattern for clean separation of concerns
53
+ - **CRUD Operations**: Provides standard create, read, update, and delete operations
54
+ - **Bulk Operations**: Supports bulk operations for efficient handling of multiple resources
55
+ - **Extensibility**: Designed to be extended with different HTTP client implementations
56
+ - **Error Handling**: Includes robust error handling and parsing
57
+ - **Observer Pattern**: Implements the observer pattern for reactive programming
58
+
59
+ This library is ideal for applications that need to interact with REST APIs in a structured, type-safe manner, particularly those already using the Decaf framework.
42
60
 
43
61
 
44
62
  ### How to Use
45
63
 
46
- - [Initial Setup](./tutorials/For%20Developers.md#_initial-setup_)
47
- - [Installation](./tutorials/For%20Developers.md#installation)
48
- - [Scripts](./tutorials/For%20Developers.md#scripts)
49
- - [Linting](./tutorials/For%20Developers.md#testing)
50
- - [CI/CD](./tutorials/For%20Developers.md#continuous-integrationdeployment)
51
- - [Publishing](./tutorials/For%20Developers.md#publishing)
52
- - [Structure](./tutorials/For%20Developers.md#repository-structure)
53
- - [IDE Integrations](./tutorials/For%20Developers.md#ide-integrations)
54
- - [VSCode(ium)](./tutorials/For%20Developers.md#visual-studio-code-vscode)
55
- - [WebStorm](./tutorials/For%20Developers.md#webstorm)
56
- - [Considerations](./tutorials/For%20Developers.md#considerations)
64
+ - [Initial Setup](./workdocs/tutorials/For%20Developers.md#_initial-setup_)
65
+ - [Installation](./workdocs/tutorials/For%20Developers.md#installation)
66
+
67
+ ## Basic Usage
68
+
69
+ ### Setting Up an HTTP Adapter with Axios
70
+
71
+ ```typescript
72
+ import axios from 'axios';
73
+ import { AxiosHttpAdapter } from '@decaf-ts/for-http';
74
+
75
+ // Create an HTTP configuration
76
+ const config = {
77
+ protocol: 'https',
78
+ host: 'api.example.com'
79
+ };
80
+
81
+ // Create an Axios HTTP adapter
82
+ const httpAdapter = new AxiosHttpAdapter(axios.create(), config);
83
+ ```
84
+
85
+ ### Creating a Model Class
86
+
87
+ ```typescript
88
+ import { Model } from '@decaf-ts/decorator-validation';
89
+
90
+ class User extends Model {
91
+ id: string;
92
+ name: string;
93
+ email: string;
94
+
95
+ constructor(data?: Partial<User>) {
96
+ super();
97
+ Object.assign(this, data);
98
+ }
99
+ }
100
+ ```
101
+
102
+ ### Using RestRepository for CRUD Operations
103
+
104
+ ```typescript
105
+ import { RestRepository } from '@decaf-ts/for-http';
106
+
107
+ // Create a repository for the User model
108
+ const userRepository = new RestRepository(httpAdapter, User);
109
+
110
+ // Create a new user
111
+ const newUser = new User({
112
+ name: 'John Doe',
113
+ email: 'john@example.com'
114
+ });
115
+ const createdUser = await userRepository.create(newUser);
116
+
117
+ // Read a user by ID
118
+ const user = await userRepository.findById('123');
119
+
120
+ // Update a user
121
+ user.name = 'Jane Doe';
122
+ await userRepository.update(user);
123
+
124
+ // Delete a user
125
+ await userRepository.delete('123');
126
+ ```
127
+
128
+ ### Using RestService for Advanced Operations
129
+
130
+ ```typescript
131
+ import { RestService } from '@decaf-ts/for-http';
57
132
 
133
+ // Create a service for the User model
134
+ const userService = new RestService(httpAdapter, User);
58
135
 
136
+ // Create a new user
137
+ const newUser = new User({
138
+ name: 'John Doe',
139
+ email: 'john@example.com'
140
+ });
141
+ const createdUser = await userService.create(newUser);
142
+
143
+ // Read a user by ID
144
+ const user = await userService.read('123');
145
+
146
+ // Update a user
147
+ user.name = 'Jane Doe';
148
+ await userService.update(user);
149
+
150
+ // Delete a user
151
+ await userService.delete('123');
152
+ ```
153
+
154
+ ### Bulk Operations with RestService
155
+
156
+ ```typescript
157
+ import { RestService } from '@decaf-ts/for-http';
158
+
159
+ // Create a service for the User model
160
+ const userService = new RestService(httpAdapter, User);
161
+
162
+ // Create multiple users
163
+ const users = [
164
+ new User({ name: 'John Doe', email: 'john@example.com' }),
165
+ new User({ name: 'Jane Doe', email: 'jane@example.com' })
166
+ ];
167
+ const createdUsers = await userService.createAll(users);
168
+
169
+ // Read multiple users by ID
170
+ const userIds = ['123', '456'];
171
+ const fetchedUsers = await userService.readAll(userIds);
172
+
173
+ // Update multiple users
174
+ const usersToUpdate = [
175
+ new User({ id: '123', name: 'John Smith' }),
176
+ new User({ id: '456', name: 'Jane Smith' })
177
+ ];
178
+ const updatedUsers = await userService.updateAll(usersToUpdate);
179
+
180
+ // Delete multiple users
181
+ await userService.deleteAll(['123', '456']);
182
+ ```
183
+
184
+ ### Using the Observer Pattern
185
+
186
+ ```typescript
187
+ import { RestService } from '@decaf-ts/for-http';
188
+ import { Observer } from '@decaf-ts/core';
189
+
190
+ // Create a service for the User model
191
+ const userService = new RestService(httpAdapter, User);
192
+
193
+ // Create an observer
194
+ const userObserver: Observer<User> = {
195
+ update: (user) => {
196
+ console.log('User updated:', user);
197
+ }
198
+ };
199
+
200
+ // Register the observer
201
+ userService.observe(userObserver);
202
+
203
+ // When operations are performed, observers will be notified
204
+ await userService.create(new User({ name: 'John Doe' }));
205
+
206
+ // Unregister the observer when done
207
+ userService.unObserve(userObserver);
208
+ ```
209
+
210
+ ### Custom HTTP Adapter Implementation
211
+
212
+ ```typescript
213
+ import { HttpAdapter } from '@decaf-ts/for-http';
214
+ import { HttpConfig, HttpFlags } from '@decaf-ts/for-http';
215
+ import { Context } from '@decaf-ts/db-decorators';
216
+ import SomeHttpClient from 'some-http-client';
217
+
218
+ // Create a custom HTTP adapter for a different HTTP client
219
+ class CustomHttpAdapter extends HttpAdapter<
220
+ SomeHttpClient,
221
+ any,
222
+ HttpFlags,
223
+ Context<HttpFlags>
224
+ > {
225
+ constructor(native: SomeHttpClient, config: HttpConfig, alias?: string) {
226
+ super(native, config, 'custom', alias);
227
+ }
228
+
229
+ async request<V>(details: any): Promise<V> {
230
+ return this.native.sendRequest(details);
231
+ }
232
+
233
+ async create(tableName: string, id: string | number, model: Record<string, any>): Promise<Record<string, any>> {
234
+ try {
235
+ const url = this.url(tableName);
236
+ return this.native.post(url, model);
237
+ } catch (e: any) {
238
+ throw this.parseError(e);
239
+ }
240
+ }
241
+
242
+ async read(tableName: string, id: string | number | bigint): Promise<Record<string, any>> {
243
+ try {
244
+ const url = this.url(tableName, { id: id as string | number });
245
+ return this.native.get(url);
246
+ } catch (e: any) {
247
+ throw this.parseError(e);
248
+ }
249
+ }
250
+
251
+ async update(tableName: string, id: string | number, model: Record<string, any>): Promise<Record<string, any>> {
252
+ try {
253
+ const url = this.url(tableName);
254
+ return this.native.put(url, model);
255
+ } catch (e: any) {
256
+ throw this.parseError(e);
257
+ }
258
+ }
259
+
260
+ async delete(tableName: string, id: string | number | bigint): Promise<Record<string, any>> {
261
+ try {
262
+ const url = this.url(tableName, { id: id as string | number });
263
+ return this.native.delete(url);
264
+ } catch (e: any) {
265
+ throw this.parseError(e);
266
+ }
267
+ }
268
+ }
269
+ ```
270
+
271
+ ### Using HTTP Flags for Request Configuration
272
+
273
+ ```typescript
274
+ import { HttpFlags } from '@decaf-ts/for-http';
275
+
276
+ // Create custom HTTP flags with headers
277
+ const flags: HttpFlags = {
278
+ headers: {
279
+ 'Authorization': 'Bearer token123',
280
+ 'Content-Type': 'application/json'
281
+ }
282
+ };
283
+
284
+ // Use flags with repository operations
285
+ const user = await userRepository.findById('123', { flags });
286
+
287
+ // Use flags with service operations
288
+ const createdUser = await userService.create(newUser, { flags });
289
+ ```
290
+
291
+ ### Complete Application Example
292
+
293
+ ```typescript
294
+ import axios from 'axios';
295
+ import {
296
+ AxiosHttpAdapter,
297
+ RestRepository,
298
+ RestService,
299
+ HttpConfig
300
+ } from '@decaf-ts/for-http';
301
+ import { Model } from '@decaf-ts/decorator-validation';
302
+
303
+ // Define a model
304
+ class Product extends Model {
305
+ id: string;
306
+ name: string;
307
+ price: number;
308
+
309
+ constructor(data?: Partial<Product>) {
310
+ super();
311
+ Object.assign(this, data);
312
+ }
313
+ }
314
+
315
+ // Configure the HTTP adapter
316
+ const config: HttpConfig = {
317
+ protocol: 'https',
318
+ host: 'api.mystore.com'
319
+ };
320
+
321
+ // Create the adapter
322
+ const adapter = new AxiosHttpAdapter(axios.create(), config);
323
+
324
+ // Create a repository
325
+ const productRepo = new RestRepository(adapter, Product);
326
+
327
+ // Create a service
328
+ const productService = new RestService(adapter, Product);
329
+
330
+ // Example application
331
+ async function manageProducts() {
332
+ try {
333
+ // Create a new product
334
+ const newProduct = new Product({
335
+ name: 'Smartphone',
336
+ price: 699.99
337
+ });
338
+
339
+ const createdProduct = await productRepo.create(newProduct);
340
+ console.log('Created product:', createdProduct);
341
+
342
+ // Get all products
343
+ const products = await productRepo.findAll();
344
+ console.log('All products:', products);
345
+
346
+ // Update a product
347
+ createdProduct.price = 649.99;
348
+ const updatedProduct = await productService.update(createdProduct);
349
+ console.log('Updated product:', updatedProduct);
350
+
351
+ // Delete a product
352
+ await productService.delete(createdProduct.id);
353
+ console.log('Product deleted');
354
+
355
+ // Bulk operations
356
+ const bulkProducts = [
357
+ new Product({ name: 'Laptop', price: 1299.99 }),
358
+ new Product({ name: 'Tablet', price: 499.99 })
359
+ ];
360
+
361
+ const createdProducts = await productService.createAll(bulkProducts);
362
+ console.log('Created multiple products:', createdProducts);
363
+ } catch (error) {
364
+ console.error('Error managing products:', error);
365
+ }
366
+ }
367
+
368
+ manageProducts();
369
+ ```
59
370
 
60
371
 
61
372
  ### Related