@smess/networking 1.0.1 → 1.0.3

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
@@ -26,12 +26,12 @@ const configB = {
26
26
 
27
27
  ### 2. Create providers/services with config
28
28
  ```typescript
29
- import { ProductService } from './core/product.service';
30
- import { UserService } from './core/user.service';
29
+ import { ProductService, UserService, AuthService } from '@smess/networking';
31
30
 
32
31
  const productServiceA = new ProductService(configA);
33
32
  const productServiceB = new ProductService(configB);
34
33
  const userServiceA = new UserService(configA);
34
+ const authServiceA = new AuthService(configA);
35
35
  ```
36
36
 
37
37
  ### 3. Use services independently
@@ -39,12 +39,12 @@ const userServiceA = new UserService(configA);
39
39
  productServiceA.fetchAllProducts().subscribe(...);
40
40
  productServiceB.createProduct({ name: 'X', price: 10 }).subscribe(...);
41
41
  userServiceA.fetchUserById(1).subscribe(...);
42
+ authServiceA.login({ identifier: 'user', password: 'pass' }).subscribe(...);
42
43
  ```
43
44
 
44
45
  ### 4. Example: Custom Provider
45
46
  ```typescript
46
- import { BaseProvider } from './core/base.provider';
47
- import { SmessService } from './services/smess.service';
47
+ import { BaseProvider, SmessService } from '@smess/networking';
48
48
 
49
49
  const config = {
50
50
  baseUrl: 'https://custom-api',
@@ -72,27 +72,6 @@ service.request().subscribe(result => {
72
72
  });
73
73
  ```
74
74
 
75
- ### 4. Example: Custom CustomerProvider
76
-
77
- ```typescript
78
- import { CustomerProvider, CustomerTarget } from './core/customer.provider';
79
- import { SmessService } from './services/smess.service';
80
-
81
- const config = {
82
- baseUrl: 'https://api.example.com',
83
- isProd: false,
84
- clientId: 'customer-client',
85
- apiKey: 'customer-key',
86
- };
87
-
88
- const provider = new CustomerProvider(config, 'get-profile');
89
- const service = new SmessService(provider);
90
-
91
- service.request().subscribe(result => {
92
- // handle result
93
- });
94
- ```
95
-
96
75
  ---
97
76
 
98
77
  ## Private Package Usage
@@ -0,0 +1,11 @@
1
+ export * from './src/services/user.service';
2
+ export * from './src/services/product.service';
3
+ export * from './src/services/auth.service';
4
+ export * from './src/services/smess.service';
5
+ export * from './src/core/base.provider';
6
+ export * from './src/core/base.service.wrapper';
7
+ export * from './src/core/axios.observable';
8
+ export * from './src/types/types';
9
+ export { $logger } from './src/services/logger.service';
10
+ export declare const baseURL: () => string;
11
+ export declare const apiVersion: () => string;
package/dist/index.js ADDED
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.apiVersion = exports.baseURL = exports.$logger = void 0;
18
+ __exportStar(require("./src/services/user.service"), exports);
19
+ __exportStar(require("./src/services/product.service"), exports);
20
+ __exportStar(require("./src/services/auth.service"), exports);
21
+ __exportStar(require("./src/services/smess.service"), exports);
22
+ __exportStar(require("./src/core/base.provider"), exports);
23
+ __exportStar(require("./src/core/base.service.wrapper"), exports);
24
+ __exportStar(require("./src/core/axios.observable"), exports);
25
+ __exportStar(require("./src/types/types"), exports);
26
+ var logger_service_1 = require("./src/services/logger.service");
27
+ Object.defineProperty(exports, "$logger", { enumerable: true, get: function () { return logger_service_1.$logger; } });
28
+ const baseURL = () => {
29
+ return '';
30
+ };
31
+ exports.baseURL = baseURL;
32
+ const apiVersion = () => {
33
+ return 'api/v1';
34
+ };
35
+ exports.apiVersion = apiVersion;
@@ -3,15 +3,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const user_service_js_1 = require("../src/domain/user.service.js");
6
+ const user_service_1 = require("../src/services/user.service");
7
7
  const rxjs_1 = require("rxjs");
8
8
  const axios_1 = __importDefault(require("axios"));
9
+ function isNetworkingUIEventWrapped(val) {
10
+ return (typeof val === 'object' &&
11
+ val !== null &&
12
+ 'hasSuccess' in val &&
13
+ 'hasFailed' in val &&
14
+ 'response' in val);
15
+ }
9
16
  async function testUserService() {
10
17
  const config = {
11
18
  baseUrl: 'https://jsonplaceholder.typicode.com',
12
19
  isProd: false,
13
20
  };
14
- const userService = new user_service_js_1.UserService(config);
21
+ const userService = new user_service_1.UserService(config);
15
22
  let emitted = false;
16
23
  try {
17
24
  const obs$ = userService.fetchUserById(1).pipe((0, rxjs_1.timeout)({ first: 10000 }), (0, rxjs_1.catchError)(err => {
@@ -23,11 +30,11 @@ async function testUserService() {
23
30
  next: (val) => {
24
31
  emitted = true;
25
32
  console.log('UserService emission:', val);
26
- if (val && val.hasSuccess && val.response) {
33
+ if (isNetworkingUIEventWrapped(val) && val.hasSuccess && val.response) {
27
34
  console.log('✅ UserService real API test succeeded:', val.response);
28
35
  resolve(undefined);
29
36
  }
30
- else if (val && val.hasFailed) {
37
+ else if (isNetworkingUIEventWrapped(val) && val.hasFailed) {
31
38
  console.error('❌ UserService real API test failed:', val.alertModel || val);
32
39
  reject(new Error('UserService failed'));
33
40
  }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BaseServiceWrapper = void 0;
4
- const smess_service_1 = require("../domain/smess.service");
4
+ const smess_service_1 = require("../services/smess.service");
5
5
  class BaseServiceWrapper {
6
6
  constructor(provider) {
7
7
  this.provider = provider;
@@ -4,7 +4,7 @@ const base_service_wrapper_1 = require("./base.service.wrapper");
4
4
  const types_1 = require("../types/types");
5
5
  const rxjs_1 = require("rxjs");
6
6
  // Mock SmessService for testing
7
- jest.mock('../domain/smess.service', () => ({
7
+ jest.mock('../services/smess.service', () => ({
8
8
  SmessService: jest.fn().mockImplementation(() => ({
9
9
  request: jest.fn(() => (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded({ foo: 'bar' })))
10
10
  }))
@@ -0,0 +1,55 @@
1
+ import { ProviderType, NetworkingConfig, NetworkingUIEventWrapped, HttpResponse } from '../types/types';
2
+ import { SmessService } from './smess.service';
3
+ import { Observable } from "rxjs";
4
+ export interface AuthLoginRequest {
5
+ identifier: string;
6
+ password: string;
7
+ }
8
+ export interface ForgotPasswordRequest {
9
+ identifier: string;
10
+ }
11
+ export interface AuthChangePasswordRequest {
12
+ old_password: string;
13
+ password: string;
14
+ }
15
+ export interface ResetPasswordRequest {
16
+ token: string;
17
+ password: string;
18
+ }
19
+ export type AuthLoginResponse = {
20
+ token_type: unknown;
21
+ expires_in: unknown;
22
+ token: unknown;
23
+ refresh_token: unknown;
24
+ };
25
+ export type AuthTarget = 'get-profile' | 'login' | 'logout' | 'register' | 'update-profile' | 'change-password' | 'password-forgot' | 'reset-password' | 'verify-reset-password-token';
26
+ export declare class AuthProvider implements ProviderType {
27
+ private readonly config;
28
+ private readonly target;
29
+ constructor(config: NetworkingConfig, target: AuthTarget);
30
+ get baseURL(): string;
31
+ get path(): string;
32
+ get method(): string;
33
+ get headers(): Record<string, string | undefined>;
34
+ getPath(...queryParams: unknown[]): string;
35
+ }
36
+ export interface AuthServiceType {
37
+ provider(target: AuthTarget): SmessService<AuthProvider>;
38
+ login(payload: AuthLoginRequest): Observable<NetworkingUIEventWrapped<AuthLoginResponse>>;
39
+ logout(): Observable<NetworkingUIEventWrapped<void>>;
40
+ forgotPassword(payload: ForgotPasswordRequest): Observable<NetworkingUIEventWrapped<HttpResponse>>;
41
+ changePassword(payload: AuthChangePasswordRequest): Observable<NetworkingUIEventWrapped<HttpResponse>>;
42
+ resetPassword(payload: ResetPasswordRequest): Observable<NetworkingUIEventWrapped<HttpResponse>>;
43
+ verifyResetPasswordToken(token: string): Observable<NetworkingUIEventWrapped<AuthLoginResponse>>;
44
+ }
45
+ export declare class AuthService implements AuthServiceType {
46
+ private config;
47
+ constructor(config: NetworkingConfig);
48
+ provider(target: AuthTarget): SmessService<AuthProvider>;
49
+ login(payload: AuthLoginRequest): Observable<NetworkingUIEventWrapped<AuthLoginResponse>>;
50
+ logout(): Observable<NetworkingUIEventWrapped<void>>;
51
+ forgotPassword(payload: ForgotPasswordRequest): Observable<NetworkingUIEventWrapped<HttpResponse>>;
52
+ changePassword(payload: AuthChangePasswordRequest): Observable<NetworkingUIEventWrapped<HttpResponse>>;
53
+ resetPassword(payload: ResetPasswordRequest): Observable<NetworkingUIEventWrapped<HttpResponse>>;
54
+ verifyResetPasswordToken(token: string): Observable<NetworkingUIEventWrapped<AuthLoginResponse>>;
55
+ }
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AuthService = exports.AuthProvider = void 0;
4
+ const smess_service_1 = require("./smess.service");
5
+ class AuthProvider {
6
+ constructor(config, target) {
7
+ this.config = config;
8
+ this.target = target;
9
+ }
10
+ get baseURL() {
11
+ return `${this.config.baseUrl}/api/v1`;
12
+ }
13
+ get path() {
14
+ switch (this.target) {
15
+ case 'login':
16
+ return '/authentication/login_check';
17
+ case 'logout':
18
+ return '/authentication/logout';
19
+ case 'register':
20
+ return '/authentication/customer/register';
21
+ case 'get-profile':
22
+ return '/authentication/customer/get-profile';
23
+ case 'update-profile':
24
+ return '/authentication/customer/update';
25
+ case 'password-forgot':
26
+ return '/authentication/forgot-password';
27
+ case 'change-password':
28
+ return '/authentication/change-password';
29
+ case 'reset-password':
30
+ return '/authentication/reset-password';
31
+ default:
32
+ return '/authentication';
33
+ }
34
+ }
35
+ get method() {
36
+ switch (this.target) {
37
+ case 'get-profile':
38
+ return 'GET';
39
+ case 'update-profile':
40
+ return 'PUT';
41
+ default:
42
+ return 'POST';
43
+ }
44
+ }
45
+ get headers() {
46
+ switch (this.target) {
47
+ case 'login':
48
+ return smess_service_1.SmessService.getHeaders(smess_service_1.Accept.V1);
49
+ case 'register':
50
+ return smess_service_1.SmessService.getHeaders(smess_service_1.Accept.V1, null, {
51
+ shouldAddClientIdHeader: false,
52
+ });
53
+ default:
54
+ // Replace with your own auth logic as needed
55
+ return smess_service_1.SmessService.getHeaders(smess_service_1.Accept.V1, this.config.clientId);
56
+ }
57
+ }
58
+ getPath(...queryParams) {
59
+ let definedPath = this.path;
60
+ const params = definedPath.match(/\$\{(.+?)\}/g);
61
+ params === null || params === void 0 ? void 0 : params.forEach((value, index) => {
62
+ definedPath = definedPath.replace(value, String(queryParams[index]));
63
+ });
64
+ return definedPath;
65
+ }
66
+ }
67
+ exports.AuthProvider = AuthProvider;
68
+ class AuthService {
69
+ constructor(config) {
70
+ this.config = config;
71
+ }
72
+ provider(target) {
73
+ const targetWrapper = new AuthProvider(this.config, target);
74
+ return new smess_service_1.SmessService(targetWrapper);
75
+ }
76
+ login(payload) {
77
+ return this.provider('login').request(payload);
78
+ }
79
+ logout() {
80
+ return this.provider('logout').request();
81
+ }
82
+ forgotPassword(payload) {
83
+ return this.provider('password-forgot').request(payload);
84
+ }
85
+ changePassword(payload) {
86
+ return this.provider('change-password').request(payload);
87
+ }
88
+ resetPassword(payload) {
89
+ return this.provider('reset-password').request(payload);
90
+ }
91
+ verifyResetPasswordToken(token) {
92
+ return this.provider('verify-reset-password-token').request({ token });
93
+ }
94
+ }
95
+ exports.AuthService = AuthService;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const auth_service_1 = require("./auth.service");
4
+ const types_1 = require("../types/types");
5
+ const rxjs_1 = require("rxjs");
6
+ describe('AuthService', () => {
7
+ const config = {
8
+ baseUrl: 'https://api.example.com',
9
+ isProd: false,
10
+ clientId: 'test-client-id',
11
+ apiKey: 'test-api-key',
12
+ };
13
+ let service;
14
+ beforeEach(() => {
15
+ service = new auth_service_1.AuthService(config);
16
+ });
17
+ it('login success', async () => {
18
+ const payload = { identifier: 'user', password: 'pass' };
19
+ const response = {
20
+ token_type: 'Bearer',
21
+ expires_in: 3600,
22
+ token: 'token',
23
+ refresh_token: 'refresh',
24
+ };
25
+ jest.spyOn(service, 'provider').mockReturnValue({
26
+ request: () => (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded(response)),
27
+ });
28
+ const result = await service.login(payload).toPromise();
29
+ expect(result === null || result === void 0 ? void 0 : result.hasSuccess).toBe(true);
30
+ expect(result === null || result === void 0 ? void 0 : result.response).toEqual(response);
31
+ });
32
+ it('login error', async () => {
33
+ const payload = { identifier: 'user', password: 'wrong' };
34
+ jest.spyOn(service, 'provider').mockReturnValue({
35
+ request: () => (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.failed(types_1.AlertModel.default())),
36
+ });
37
+ const result = await service.login(payload).toPromise();
38
+ expect(result === null || result === void 0 ? void 0 : result.hasFailed).toBe(true);
39
+ expect(result === null || result === void 0 ? void 0 : result.alertModel).toBeInstanceOf(types_1.AlertModel);
40
+ });
41
+ it('logout success', async () => {
42
+ jest.spyOn(service, 'provider').mockReturnValue({
43
+ request: () => (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded(undefined)),
44
+ });
45
+ const result = await service.logout().toPromise();
46
+ expect(result === null || result === void 0 ? void 0 : result.hasSuccess).toBe(true);
47
+ });
48
+ it('forgotPassword success', async () => {
49
+ const payload = { identifier: 'user' };
50
+ const response = { data: 'ok' };
51
+ jest.spyOn(service, 'provider').mockReturnValue({
52
+ request: () => (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded(response)),
53
+ });
54
+ const result = await service.forgotPassword(payload).toPromise();
55
+ expect(result === null || result === void 0 ? void 0 : result.hasSuccess).toBe(true);
56
+ expect(result === null || result === void 0 ? void 0 : result.response).toEqual(response);
57
+ });
58
+ it('changePassword success', async () => {
59
+ const payload = { old_password: 'old', password: 'new' };
60
+ const response = { data: 'changed' };
61
+ jest.spyOn(service, 'provider').mockReturnValue({
62
+ request: () => (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded(response)),
63
+ });
64
+ const result = await service.changePassword(payload).toPromise();
65
+ expect(result === null || result === void 0 ? void 0 : result.hasSuccess).toBe(true);
66
+ expect(result === null || result === void 0 ? void 0 : result.response).toEqual(response);
67
+ });
68
+ it('resetPassword success', async () => {
69
+ const payload = { token: 'token', password: 'newpass' };
70
+ const response = { data: 'reset' };
71
+ jest.spyOn(service, 'provider').mockReturnValue({
72
+ request: () => (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded(response)),
73
+ });
74
+ const result = await service.resetPassword(payload).toPromise();
75
+ expect(result === null || result === void 0 ? void 0 : result.hasSuccess).toBe(true);
76
+ expect(result === null || result === void 0 ? void 0 : result.response).toEqual(response);
77
+ });
78
+ it('verifyResetPasswordToken success', async () => {
79
+ const token = 'token';
80
+ const response = {
81
+ token_type: 'Bearer',
82
+ expires_in: 3600,
83
+ token: 'token',
84
+ refresh_token: 'refresh',
85
+ };
86
+ jest.spyOn(service, 'provider').mockReturnValue({
87
+ request: () => (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded(response)),
88
+ });
89
+ const result = await service.verifyResetPasswordToken(token).toPromise();
90
+ expect(result === null || result === void 0 ? void 0 : result.hasSuccess).toBe(true);
91
+ expect(result === null || result === void 0 ? void 0 : result.response).toEqual(response);
92
+ });
93
+ it('forgotPassword error', async () => {
94
+ const payload = { identifier: 'user' };
95
+ jest.spyOn(service, 'provider').mockReturnValue({
96
+ request: () => (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.failed(types_1.AlertModel.default())),
97
+ });
98
+ const result = await service.forgotPassword(payload).toPromise();
99
+ expect(result === null || result === void 0 ? void 0 : result.hasFailed).toBe(true);
100
+ expect(result === null || result === void 0 ? void 0 : result.alertModel).toBeInstanceOf(types_1.AlertModel);
101
+ });
102
+ it('changePassword error', async () => {
103
+ const payload = { old_password: 'old', password: 'bad' };
104
+ jest.spyOn(service, 'provider').mockReturnValue({
105
+ request: () => (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.failed(types_1.AlertModel.default())),
106
+ });
107
+ const result = await service.changePassword(payload).toPromise();
108
+ expect(result === null || result === void 0 ? void 0 : result.hasFailed).toBe(true);
109
+ expect(result === null || result === void 0 ? void 0 : result.alertModel).toBeInstanceOf(types_1.AlertModel);
110
+ });
111
+ it('resetPassword error', async () => {
112
+ const payload = { token: 'bad', password: 'bad' };
113
+ jest.spyOn(service, 'provider').mockReturnValue({
114
+ request: () => (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.failed(types_1.AlertModel.default())),
115
+ });
116
+ const result = await service.resetPassword(payload).toPromise();
117
+ expect(result === null || result === void 0 ? void 0 : result.hasFailed).toBe(true);
118
+ expect(result === null || result === void 0 ? void 0 : result.alertModel).toBeInstanceOf(types_1.AlertModel);
119
+ });
120
+ it('verifyResetPasswordToken error', async () => {
121
+ const token = 'bad';
122
+ jest.spyOn(service, 'provider').mockReturnValue({
123
+ request: () => (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.failed(types_1.AlertModel.default())),
124
+ });
125
+ const result = await service.verifyResetPasswordToken(token).toPromise();
126
+ expect(result === null || result === void 0 ? void 0 : result.hasFailed).toBe(true);
127
+ expect(result === null || result === void 0 ? void 0 : result.alertModel).toBeInstanceOf(types_1.AlertModel);
128
+ });
129
+ });
@@ -0,0 +1,21 @@
1
+ import { BaseProvider } from '../core/base.provider';
2
+ import { BaseServiceWrapper } from '../core/base.service.wrapper';
3
+ import { NetworkingConfig } from '../types/types';
4
+ export interface Product {
5
+ id: number;
6
+ name: string;
7
+ price: number;
8
+ }
9
+ export declare class ProductProvider extends BaseProvider {
10
+ constructor(config: NetworkingConfig, { productId, method }?: {
11
+ productId?: number;
12
+ method?: string;
13
+ });
14
+ }
15
+ export declare class ProductService extends BaseServiceWrapper<ProductProvider> {
16
+ private config;
17
+ constructor(config: NetworkingConfig, productId?: number, method?: string);
18
+ fetchProductById(id: number): import("rxjs").Observable<import("../types/types").NetworkingUIEventWrapped<Product>>;
19
+ fetchAllProducts(): import("rxjs").Observable<import("../types/types").NetworkingUIEventWrapped<Product[]>>;
20
+ createProduct(product: Omit<Product, 'id'>): import("rxjs").Observable<import("../types/types").NetworkingUIEventWrapped<Product>>;
21
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProductService = exports.ProductProvider = void 0;
4
+ const base_provider_1 = require("../core/base.provider");
5
+ const base_service_wrapper_1 = require("../core/base.service.wrapper");
6
+ // ProductProvider implements ProviderType for product endpoints
7
+ class ProductProvider extends base_provider_1.BaseProvider {
8
+ constructor(config, { productId, method } = {}) {
9
+ super({
10
+ config,
11
+ path: productId ? `/products/${productId}` : '/products',
12
+ method: method || 'GET',
13
+ headers: { 'Content-Type': 'application/json' },
14
+ getPath: () => (productId ? `/products/${productId}` : '/products'),
15
+ });
16
+ }
17
+ }
18
+ exports.ProductProvider = ProductProvider;
19
+ // ProductService provides high-level methods for product API
20
+ class ProductService extends base_service_wrapper_1.BaseServiceWrapper {
21
+ constructor(config, productId, method) {
22
+ super(new ProductProvider(config, { productId, method }));
23
+ this.config = config;
24
+ }
25
+ // Fetch a product by ID
26
+ fetchProductById(id) {
27
+ this.provider = new ProductProvider(this.config, { productId: id });
28
+ return this.request();
29
+ }
30
+ // Fetch all products
31
+ fetchAllProducts() {
32
+ this.provider = new ProductProvider(this.config);
33
+ return this.request();
34
+ }
35
+ // Create a new product (POST)
36
+ createProduct(product) {
37
+ this.provider = new ProductProvider(this.config, { method: 'POST' });
38
+ return this.request(product);
39
+ }
40
+ }
41
+ exports.ProductService = ProductService;
42
+ // Example usage:
43
+ // setNetworkingConfig({ baseUrl: 'https://fakestoreapi.com', isProd: false });
44
+ // const productService = new ProductService();
45
+ // productService.fetchProductById(1).subscribe(result => console.log(result));
46
+ // productService.fetchAllProducts().subscribe(result => console.log(result));
47
+ // productService.createProduct({ name: 'New Product', price: 99.99 }).subscribe(result => console.log(result));
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const product_service_1 = require("./product.service");
4
+ const types_1 = require("../types/types");
5
+ const rxjs_1 = require("rxjs");
6
+ const base_service_wrapper_1 = require("../core/base.service.wrapper");
7
+ describe('ProductService', () => {
8
+ const config = {
9
+ baseUrl: 'https://jsonplaceholder.typicode.com',
10
+ isProd: false,
11
+ clientId: 'test-client',
12
+ apiKey: 'test-key',
13
+ };
14
+ const product = { id: 1, name: 'Product', price: 10 };
15
+ let requestSpy;
16
+ beforeEach(() => {
17
+ requestSpy = jest.spyOn(base_service_wrapper_1.BaseServiceWrapper.prototype, 'request').mockImplementation(() => (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded(product)));
18
+ });
19
+ afterEach(() => {
20
+ requestSpy.mockRestore();
21
+ });
22
+ it('should fetch product by id', done => {
23
+ const service = new product_service_1.ProductService(config, 1);
24
+ service.fetchProductById(1).subscribe(result => {
25
+ expect(result.response).toEqual(product);
26
+ done();
27
+ });
28
+ });
29
+ it('should fetch all products', done => {
30
+ const service = new product_service_1.ProductService(config);
31
+ service.fetchAllProducts().subscribe(result => {
32
+ expect(result.response).toEqual(product);
33
+ done();
34
+ });
35
+ });
36
+ it('should create a product', done => {
37
+ const service = new product_service_1.ProductService(config);
38
+ service.createProduct({ name: 'New Product', price: 99.99 }).subscribe(result => {
39
+ expect(result.response).toEqual(product);
40
+ done();
41
+ });
42
+ });
43
+ it('request should handle error', done => {
44
+ requestSpy.mockImplementationOnce(() => (0, rxjs_1.throwError)(() => new Error('Test error')));
45
+ const service = new product_service_1.ProductService(config);
46
+ service.request('error').subscribe({
47
+ error: err => {
48
+ expect(err).toBeInstanceOf(Error);
49
+ expect(err.message).toBe('Test error');
50
+ done();
51
+ },
52
+ });
53
+ });
54
+ });
@@ -0,0 +1,35 @@
1
+ import { HeaderType, NetworkingUIEventWrapped, ProviderType } from '../types/types';
2
+ import { Observable } from '../utils/rxjs-import';
3
+ export declare enum SMESSHeader {
4
+ ContentType = "Content-Type",
5
+ Authorization = "Authorization",
6
+ Accept = "Accept",
7
+ ApiKey = "X-Api-Key",
8
+ ClientId = "X-Client-Id"
9
+ }
10
+ export declare enum ContentType {
11
+ Json = "application/json",
12
+ FormURLEncoded = "application/x-www-form-urlencoded"
13
+ }
14
+ export declare enum Accept {
15
+ V1 = "application/json",
16
+ V2 = "application/vnd.smess.v2+json",
17
+ V3 = "application/vnd.smess.v3+json",
18
+ V4 = "application/vnd.smess.v4+json",
19
+ V5 = "application/vnd.smess.v5+json",
20
+ V6 = "application/vnd.smess.v6+json",
21
+ V7 = "application/vnd.smess.v7+json",
22
+ V8 = "application/vnd.smess.v8+json",
23
+ V9 = "application/vnd.smess.v9+json",
24
+ V10 = "application/vnd.smess.v10+json"
25
+ }
26
+ export declare class SmessService<T extends ProviderType> {
27
+ private httpService;
28
+ private target;
29
+ constructor(target: T);
30
+ static getHeaders(version: Accept, authorization?: string | null, options?: HeaderType): Partial<Record<SMESSHeader, string | undefined>>;
31
+ private static commonHeaders;
32
+ request<R = unknown>(request?: unknown, mockResponse?: R, ...queryParams: unknown[]): Observable<NetworkingUIEventWrapped<R>>;
33
+ private transformAxiosError;
34
+ private transformAxiosResponse;
35
+ }
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SmessService = exports.Accept = exports.ContentType = exports.SMESSHeader = void 0;
7
+ const types_1 = require("../types/types");
8
+ const rxjs_import_1 = require("../utils/rxjs-import");
9
+ const rx_http_service_1 = __importDefault(require("../core/rx.http.service"));
10
+ const logger_service_1 = require("../services/logger.service");
11
+ var SMESSHeader;
12
+ (function (SMESSHeader) {
13
+ SMESSHeader["ContentType"] = "Content-Type";
14
+ SMESSHeader["Authorization"] = "Authorization";
15
+ SMESSHeader["Accept"] = "Accept";
16
+ SMESSHeader["ApiKey"] = "X-Api-Key";
17
+ SMESSHeader["ClientId"] = "X-Client-Id";
18
+ })(SMESSHeader || (exports.SMESSHeader = SMESSHeader = {}));
19
+ var ContentType;
20
+ (function (ContentType) {
21
+ ContentType["Json"] = "application/json";
22
+ ContentType["FormURLEncoded"] = "application/x-www-form-urlencoded";
23
+ })(ContentType || (exports.ContentType = ContentType = {}));
24
+ var Accept;
25
+ (function (Accept) {
26
+ Accept["V1"] = "application/json";
27
+ Accept["V2"] = "application/vnd.smess.v2+json";
28
+ Accept["V3"] = "application/vnd.smess.v3+json";
29
+ Accept["V4"] = "application/vnd.smess.v4+json";
30
+ Accept["V5"] = "application/vnd.smess.v5+json";
31
+ Accept["V6"] = "application/vnd.smess.v6+json";
32
+ Accept["V7"] = "application/vnd.smess.v7+json";
33
+ Accept["V8"] = "application/vnd.smess.v8+json";
34
+ Accept["V9"] = "application/vnd.smess.v9+json";
35
+ Accept["V10"] = "application/vnd.smess.v10+json";
36
+ })(Accept || (exports.Accept = Accept = {}));
37
+ class SmessService {
38
+ constructor(target) {
39
+ this.target = target;
40
+ // Set default headers
41
+ logger_service_1.$logger.info('SmessService initialized', {
42
+ target: this.target,
43
+ baseURL: this.target.baseURL,
44
+ method: this.target.method,
45
+ headers: this.target.headers,
46
+ }, 'SmessService');
47
+ this.httpService = rx_http_service_1.default.create({
48
+ baseURL: this.target.baseURL,
49
+ headers: this.target.headers,
50
+ method: this.target.method,
51
+ });
52
+ this.httpService.interceptors.response.use((response) => response, async (error) => {
53
+ var _a;
54
+ const originalRequest = error.config;
55
+ if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 401 && !originalRequest._retry) {
56
+ originalRequest._retry = true;
57
+ logger_service_1.$logger.info('SmessService constructor - 401 retry', originalRequest, 'SmessService');
58
+ // Implement token refresh logic here
59
+ // Then retry the original request
60
+ // return httpService.request(originalRequest);
61
+ }
62
+ return Promise.reject(error);
63
+ });
64
+ }
65
+ static getHeaders(version, authorization = null, options) {
66
+ const headers = this.commonHeaders(version, options);
67
+ if (authorization) {
68
+ headers['Authorization'] = authorization;
69
+ }
70
+ return headers;
71
+ }
72
+ static commonHeaders(version, options) {
73
+ const { shouldAddClientIdHeader = true, } = options !== null && options !== void 0 ? options : {};
74
+ const headers = {
75
+ Accept: version,
76
+ Authorization: '',
77
+ 'Content-Type': ContentType.Json,
78
+ 'X-Api-Key': ''
79
+ };
80
+ return headers;
81
+ }
82
+ // MARK: - Public
83
+ request(request, mockResponse, ...queryParams) {
84
+ if (mockResponse !== undefined) {
85
+ return (0, rxjs_import_1.of)(types_1.NetworkingUIEventWrapped.succeeded(mockResponse));
86
+ }
87
+ const url = queryParams.length
88
+ ? this.target.getPath(...queryParams)
89
+ : this.target.path;
90
+ const config = { url };
91
+ let observable;
92
+ if (this.target.method === 'GET') {
93
+ if (request) {
94
+ config.data = request;
95
+ config.params = request;
96
+ }
97
+ // Note: HttpService.get expects (url, config)
98
+ observable = this.httpService.get(url, config);
99
+ }
100
+ else if (this.target.method === 'POST') {
101
+ // HttpService.post expects (url, data, config)
102
+ observable = this.httpService.post(url, request, config);
103
+ }
104
+ else if (this.target.method === 'PATCH') {
105
+ observable = this.httpService.patch(url, request, config);
106
+ }
107
+ else if (this.target.method === 'PUT') {
108
+ observable = this.httpService.put(url, request, config);
109
+ }
110
+ else {
111
+ observable = this.httpService.request(config);
112
+ }
113
+ return observable.pipe((0, rxjs_import_1.catchError)((error) => this.transformAxiosError(error, mockResponse)), (0, rxjs_import_1.mergeMap)((data) => this.transformAxiosResponse(data)), (0, rxjs_import_1.startWith)(types_1.NetworkingUIEventWrapped.waiting()));
114
+ }
115
+ // MARK: - Private
116
+ transformAxiosError(error, mockResponse) {
117
+ logger_service_1.$logger.error('transformAxiosError', error, 'SmessService');
118
+ const message = error instanceof Error ? error.message : String(error);
119
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Required for axios compatibility
120
+ const response = error.response;
121
+ const httpErrorCode = response ? response.status : 0;
122
+ const title = response === null || response === void 0 ? void 0 : response.statusText;
123
+ const alertModel = new types_1.AlertModel(message, httpErrorCode, true, title, response === null || response === void 0 ? void 0 : response.data, [types_1.AlertButtonModel.buttonYes()]);
124
+ if (mockResponse) {
125
+ return (0, rxjs_import_1.of)(types_1.NetworkingUIEventWrapped.succeeded(mockResponse));
126
+ }
127
+ return (0, rxjs_import_1.of)(types_1.NetworkingUIEventWrapped.failed(alertModel));
128
+ }
129
+ transformAxiosResponse(response) {
130
+ logger_service_1.$logger.info('transformAxiosResponse', response, 'SmessService');
131
+ if (response instanceof types_1.NetworkingUIEventWrapped) {
132
+ return (0, rxjs_import_1.of)(response);
133
+ }
134
+ return (0, rxjs_import_1.of)(types_1.NetworkingUIEventWrapped.succeeded(response.data));
135
+ }
136
+ }
137
+ exports.SmessService = SmessService;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /* eslint-disable @typescript-eslint/no-explicit-any -- Required for test mocks */
4
+ const smess_service_1 = require("./smess.service");
5
+ const types_1 = require("../types/types");
6
+ const rxjs_1 = require("rxjs");
7
+ describe('SmessService', () => {
8
+ const config = {
9
+ baseUrl: 'https://api.example.com',
10
+ isProd: false,
11
+ clientId: 'test-client',
12
+ apiKey: 'test-key',
13
+ };
14
+ const provider = {
15
+ baseURL: config.baseUrl,
16
+ path: '/resource',
17
+ method: 'GET',
18
+ headers: {},
19
+ getPath: () => '/resource',
20
+ };
21
+ it('should return succeeded for GET', done => {
22
+ const service = new smess_service_1.SmessService(provider);
23
+ service['httpService'] = {
24
+ get: jest.fn(() => (0, rxjs_1.of)({ data: { foo: 'bar' } })),
25
+ post: jest.fn(),
26
+ patch: jest.fn(),
27
+ put: jest.fn(),
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Required for test compatibility
29
+ request: jest.fn((payload) => {
30
+ if (payload === 'error') {
31
+ return (0, rxjs_1.throwError)(() => new Error('Test error'));
32
+ }
33
+ return (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded({ foo: 'bar' }));
34
+ }),
35
+ interceptors: { response: { use: jest.fn() } },
36
+ };
37
+ service.request().subscribe(result => {
38
+ expect(result).toBeInstanceOf(types_1.NetworkingUIEventWrapped);
39
+ expect(result.response).toEqual({ foo: 'bar' });
40
+ done();
41
+ });
42
+ });
43
+ it('should return succeeded for POST', done => {
44
+ const postProvider = Object.assign(Object.assign({}, provider), { method: 'POST' });
45
+ const service = new smess_service_1.SmessService(postProvider);
46
+ service['httpService'] = {
47
+ get: jest.fn(),
48
+ post: jest.fn((payload) => {
49
+ if (payload === 'error') {
50
+ return (0, rxjs_1.throwError)(() => new Error('Test error'));
51
+ }
52
+ return (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded({ foo: 'baz' }));
53
+ }),
54
+ patch: jest.fn(),
55
+ put: jest.fn(),
56
+ request: jest.fn(),
57
+ interceptors: { response: { use: jest.fn() } },
58
+ };
59
+ service.request({ some: 'data' }).subscribe(result => {
60
+ expect(result.response).toEqual({ foo: 'baz' });
61
+ done();
62
+ });
63
+ });
64
+ it('should handle error', done => {
65
+ const service = new smess_service_1.SmessService(provider);
66
+ service['httpService'] = {
67
+ get: jest.fn(() => (0, rxjs_1.throwError)(() => new Error('Test error'))),
68
+ post: jest.fn(),
69
+ patch: jest.fn(),
70
+ put: jest.fn(),
71
+ request: jest.fn(),
72
+ interceptors: { response: { use: jest.fn() } },
73
+ };
74
+ service.request().subscribe(result => {
75
+ var _a;
76
+ expect(result).toBeInstanceOf(types_1.NetworkingUIEventWrapped);
77
+ expect(result.hasFailed).toBe(true);
78
+ expect(result.alertModel).toBeTruthy();
79
+ expect((_a = result.alertModel) === null || _a === void 0 ? void 0 : _a.message).toBe('Test error');
80
+ done();
81
+ });
82
+ });
83
+ it('should return mock response if provided', done => {
84
+ const service = new smess_service_1.SmessService(provider);
85
+ service['httpService'] = {
86
+ get: jest.fn(() => (0, rxjs_1.throwError)(() => new Error('Test error'))),
87
+ post: jest.fn(),
88
+ patch: jest.fn(),
89
+ put: jest.fn(),
90
+ request: jest.fn((payload, mockResponse) => {
91
+ if (payload === 'error') {
92
+ return (0, rxjs_1.throwError)(() => new Error('Test error'));
93
+ }
94
+ if (mockResponse !== undefined) {
95
+ return (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded(mockResponse));
96
+ }
97
+ return (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded({ foo: 'mock' }));
98
+ }),
99
+ interceptors: { response: { use: jest.fn() } },
100
+ };
101
+ service.request(undefined, { foo: 'mock' }).subscribe(result => {
102
+ expect(result.response).toEqual({ foo: 'mock' });
103
+ done();
104
+ });
105
+ });
106
+ });
@@ -0,0 +1,16 @@
1
+ import { BaseProvider } from '../core/base.provider';
2
+ import { BaseServiceWrapper } from '../core/base.service.wrapper';
3
+ import { NetworkingConfig } from '../types/types';
4
+ export interface User {
5
+ id: number;
6
+ name: string;
7
+ email: string;
8
+ }
9
+ export declare class UserProvider extends BaseProvider {
10
+ constructor(config: NetworkingConfig, userId?: number);
11
+ }
12
+ export declare class UserService extends BaseServiceWrapper<UserProvider> {
13
+ constructor(config: NetworkingConfig, userId?: number);
14
+ fetchUserById(id: number): import("rxjs").Observable<import("../types/types").NetworkingUIEventWrapped<User>>;
15
+ fetchAllUsers(): import("rxjs").Observable<import("../types/types").NetworkingUIEventWrapped<User[]>>;
16
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserService = exports.UserProvider = void 0;
4
+ const base_provider_1 = require("../core/base.provider");
5
+ const base_service_wrapper_1 = require("../core/base.service.wrapper");
6
+ // UserProvider implements ProviderType for user endpoints
7
+ class UserProvider extends base_provider_1.BaseProvider {
8
+ constructor(config, userId) {
9
+ super({
10
+ config,
11
+ path: userId ? `/users/${userId}` : '/users',
12
+ method: 'GET',
13
+ headers: {},
14
+ getPath: () => (userId ? `/users/${userId}` : '/users'),
15
+ });
16
+ }
17
+ }
18
+ exports.UserProvider = UserProvider;
19
+ // UserService provides high-level methods for user API
20
+ class UserService extends base_service_wrapper_1.BaseServiceWrapper {
21
+ constructor(config, userId) {
22
+ super(new UserProvider(config, userId));
23
+ }
24
+ // Fetch a user by ID
25
+ fetchUserById(id) {
26
+ this.provider = new UserProvider({ baseUrl: 'https://jsonplaceholder.typicode.com', isProd: false }, id);
27
+ return this.request();
28
+ }
29
+ // Fetch all users
30
+ fetchAllUsers() {
31
+ this.provider = new UserProvider({ baseUrl: 'https://jsonplaceholder.typicode.com', isProd: false });
32
+ return this.request();
33
+ }
34
+ }
35
+ exports.UserService = UserService;
36
+ // Example usage:
37
+ // setNetworkingConfig({ baseUrl: 'https://jsonplaceholder.typicode.com', isProd: false });
38
+ // const userService = new UserService();
39
+ // userService.fetchUserById(1).subscribe(result => console.log(result));
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const user_service_1 = require("./user.service");
4
+ const types_1 = require("../types/types");
5
+ const rxjs_1 = require("rxjs");
6
+ const base_service_wrapper_1 = require("../core/base.service.wrapper");
7
+ describe('UserService', () => {
8
+ const config = {
9
+ baseUrl: 'https://jsonplaceholder.typicode.com',
10
+ isProd: false,
11
+ clientId: 'test-client',
12
+ apiKey: 'test-key',
13
+ };
14
+ const user = { id: 1, name: 'Test', email: 'test@example.com' };
15
+ let requestSpy;
16
+ beforeEach(() => {
17
+ requestSpy = jest.spyOn(base_service_wrapper_1.BaseServiceWrapper.prototype, 'request').mockImplementation(() => (0, rxjs_1.of)(types_1.NetworkingUIEventWrapped.succeeded(user)));
18
+ });
19
+ afterEach(() => {
20
+ requestSpy.mockRestore();
21
+ });
22
+ it('fetchUserById should return user (success)', done => {
23
+ const service = new user_service_1.UserService(config);
24
+ service.fetchUserById(1).subscribe(result => {
25
+ expect(result.response).toEqual(user);
26
+ done();
27
+ });
28
+ });
29
+ it('fetchAllUsers should return users (success)', done => {
30
+ const service = new user_service_1.UserService(config);
31
+ service.fetchAllUsers().subscribe(result => {
32
+ expect(result.response).toEqual(user);
33
+ done();
34
+ });
35
+ });
36
+ it('request should handle error', done => {
37
+ requestSpy.mockImplementationOnce(() => (0, rxjs_1.throwError)(() => new Error('Test error')));
38
+ const service = new user_service_1.UserService(config);
39
+ service.request('error').subscribe({
40
+ error: err => {
41
+ expect(err).toBeInstanceOf(Error);
42
+ expect(err.message).toBe('Test error');
43
+ done();
44
+ },
45
+ });
46
+ });
47
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smess/networking",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Networking utilities and services for SMESS platform.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",