рдХреЛрдгреАрдп: рдХреЛрдб рдХреЛ рдмреИрдХ-рдПрдВрдб рдХреЗ рд▓рд┐рдП рдкрдардиреАрдп рдмрдирд╛рддреЗ рд╣реИрдВред рдмреЛрдирд╕: рд╕реНрд╡реИрдкрд┐рдВрдЧ рдПрдкреАрдЖрдИ рдФрд░ рдХреНрд╡реЗрд░реА рдХреИрд╢рд┐рдВрдЧ

рдмрд╣реБрдд рдмрд╛рд░ рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкрд░, рдмреИрдХреЗрдВрдб рд╡рд┐рдХрд╛рд╕ рдХреА рдЧрддрд┐ рдмреИрдХреЗрдВрдб рд╡рд┐рдХрд╛рд╕ рдХреА рдЧрддрд┐ рд╕реЗ рдЖрдЧреЗ рд╣реЛрддреА рд╣реИред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рджреЛ рдЪреАрдЬреЗрдВ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИрдВ:

  1. рдмреИрдХрдПрдВрдб рдХреЗ рдмрд┐рдирд╛, рдпрд╛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХреЗ рдмрд┐рдирд╛ рд╕рд╛рдордиреЗ рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛;
  2. рдмреИрдХ-рдПрдВрдб рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВ рдХрд┐ рдПрдВрдбрдкреЙрдЗрдВрдЯреНрд╕ рдХреА рдХреНрдпрд╛ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЕрдиреБрд░реЛрдз, рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдЖрджрд┐ рдХрд╛ рдкреНрд░рд╛рд░реВрдкред

рдореИрдВ рдПрдкреАрдЖрдИ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдХреЛрдб рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдиреЗ рдХреЗ рдЕрдкрдиреЗ рддрд░реАрдХреЗ рдХреЛ рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рдЬреЛ рдЗрди рджреЛрдиреЛрдВ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЖрдкрдХреЛ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдХреИрд╢ рдХрд░рдиреЗ рдХреА рднреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд░реВрдЯ рдореЗрдВ api.config.json рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ:

{
  "apiUrl": "https://api.example.com",
  "useFakeApiByDefault": false,
  "fakeEndPoints": ["Sample"]
}

рдпрд╣рд╛рдВ рд╣рдордиреЗ API рдХреЗ рд▓рд┐рдП рдЖрдзрд╛рд░ URL рд╕реЗрдЯ рдХрд┐рдпрд╛ рд╣реИ, рдпрджрд┐ useFakeApiByDefault = true рдкреИрд░рд╛рдореАрдЯрд░, рддреЛ рд╣рдорд╛рд░рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕рднреА рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдмрдЬрд╛рдп рдХреЗрд╡рд▓ рд╕реНрдЯрдмреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдЧрд╛ред рдпрджрд┐ рдЧрд▓рдд рд╣реИ, рддреЛ рдХреЗрд╡рд▓ рдлрд░реНрдЬреА рдмрд┐рдВрджреБ рдмрд┐рдВрджреБ рд╕реЗ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рд╕реНрдЯрдмреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

JSON рдХреЛ рдХреЛрдб рдореЗрдВ рдЖрдпрд╛рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо tsconfig.sson рд╕рдВрд╕реНрдХрд░рдг рдХреЗ CompilerOptions рд╕реЗрдХреНрд╢рди рдореЗрдВ рджреЛ рд▓рд╛рдЗрдиреЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ:

    "resolveJsonModule": true,
    "esModuleInterop": true,

рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рдмреЗрд╕рдЗрдВрдбрдкреЙрдЗрдВрдЯ рдмрдирд╛рдПрдВред

/src/app/api/_base.endpoint.ts:

import {ApiMethod, ApiService} from '../services/api/api.service';
import * as ApiConfig from '../../../api.config.json';
import {ErrorService} from '../services/error/error.service';
import {NgModule} from '@angular/core';

@NgModule({providers: [ApiService, ErrorService]})

export abstract class BaseEndpoint<Request, ResponseModel> {
  protected url: string;
  protected name: string;
  protected method: ApiMethod = ApiMethod.Post;
  protected sampleResponse: ResponseModel;
  protected cache: boolean = false;
  protected responseCache: ResponseModel = null;

  constructor(private api: ApiService, private error: ErrorService) {
  }

  public execute(request: Request): Promise<ResponseModel> {
    if (this.cache && this.responseCache !== null) {
      return new Promise<ResponseModel>((resolve, reject) => {
        resolve(this.responseCache);
      });
    } else {
      if (ApiConfig.useFakeApiByDefault || ApiConfig.fakeEndPoints.includes(this.name)) {
        console.log('Fake Api Request:: ', this.name, request);
        console.log('Fake Api Response:: ', this.sampleResponse);
        return new Promise<ResponseModel>((resolve) => resolve(this.sampleResponse));
      } else {
        return new Promise<ResponseModel>((resolve, reject) => {
          this.api.execute(this.url, this.method, request).subscribe(
            (response: Response<ResponseModel>) => {
              if (response.status === 200) {
                if (this.cache) { this.responseCache = response.payload; }
                resolve(this.payloadMap(response.payload));
              } else {
                this.error.emit(response.error);
                reject(response.error);
              }
            }, response => {
              this.error.emit('    ')
              reject('    '));
           }
        });
      }
    }
  }

  protected payloadMap(payload: ResponseModel): ResponseModel { return payload; }
}

abstract class Response<T> {
  public status: number;
  public error: string;
  public payload: T;
}

<рдЕрдиреБрд░реЛрдз, ResponseModel> - рдЕрдиреБрд░реЛрдз рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рдкреНрд░рдХрд╛рд░ред рдЬрд╡рд╛рдм рдореЗрдВ, рдкреЗрд▓реЛрдб рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓рд╛ рдЬрд╛рддрд╛ рд╣реИред

рдореИрдВ ApiService рдФрд░ ErrorService рдХрдХреНрд╖рд╛рдПрдВ рдкреЛрд╕реНрдЯ рдирд╣реАрдВ рдХрд░реВрдВрдЧрд╛, рдЗрд╕рд▓рд┐рдП рдкреЛрд╕реНрдЯ рдХреЛ рдмрдврд╝рд╛рдирд╛ рдирд╣реАрдВ рд╣реИ, рд╡рд╣рд╛рдВ рдХреБрдЫ рднреА рд╡рд┐рд╢реЗрд╖ рдирд╣реАрдВ рд╣реИред ApiService http рдЕрдиреБрд░реЛрдз рднреЗрдЬрддрд╛ рд╣реИ, ErrorService рдЖрдкрдХреЛ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреА рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЙрд╕ рдШрдЯрдХ рдореЗрдВ ErrorService рдХреА рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрдиреА рд╣реЛрдЧреА, рдЬрд╣рд╛рдВ рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ (рдореИрдВ рдореБрдЦреНрдп рд▓реЗрдЖрдЙрдЯ рдкрд░ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХрд░рддрд╛ рд╣реВрдВ рдЬрд┐рд╕рдореЗрдВ рдореИрдВ рдПрдХ рдореЛрдбрд▓ рдпрд╛ рдЯреВрд▓рдЯрд┐рдк рдмрдирд╛рддрд╛ рд╣реВрдВ)ред

рдЬрд╛рджреВ рддрдм рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ рдЬрдм рд╣рдореЗрдВ рдЗрд╕ рд╡рд░реНрдЧ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдорд┐рд▓рддреА рд╣реИред

рд╡реНрдпреБрддреНрдкрдиреНрди рд╡рд░реНрдЧ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛: /src/app/api/get-users.endpoint.ts

import {BaseEndpoint} from './_base.endpoint';
import {Injectable} from '@angular/core';
import {UserModel} from '../models/user.model';

@Injectable()
export class GetUsersEndpoint extends BaseEndpoint<GetUsersRequest, UserModel[]> {
  protected name = 'GetUsers';
  protected url= '/getUsers';
  protected sampleResponse = [{
      id: 0,
      name: 'Ivan',
      age: 18
  },
  {
      id: 1,
      name: 'Igor',
      age: 25
   }

  protected payloadMap(payload) {
    return payload.map(user => new UserModel(user));
  }
}

export class GetUsersRequest {
   page: number;
   limit: number;
}

рдЕрдзрд┐рдХ рдХреБрдЫ рдирд╣реАрдВ, рдлрд╝рд╛рдЗрд▓ рдХреА рд╕рд╛рдордЧреНрд░реА рд╕реЗ рдпрд╣ рддреБрд░рдВрдд рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдХреМрди рд╕рд╛ URL, рдХреНрдпрд╛ рдЕрдиреБрд░реЛрдз рдкреНрд░рд╛рд░реВрдк (GetUserRequest), рдХреНрдпрд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕реНрд╡рд░реВрдкред

рдпрджрд┐ рдРрд╕реА рдлрд╛рдЗрд▓реЗрдВ рдПрдХ рдЕрд▓рдЧ рдлрд╝реЛрд▓реНрдбрд░ / рдПрдкреАрдЖрдИ рдореЗрдВ рд╣реИрдВ, рддреЛ рдкреНрд░рддреНрдпреЗрдХ рдлрд╝рд╛рдЗрд▓ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рд╕реЗ рдореЗрд▓ рдЦрд╛рддреА рд╣реИ, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕ рдлрд╝реЛрд▓реНрдбрд░ рдХреЛ рдмреИрдХ-рдПрдВрдб рдХреЛ рджрд┐рдЦрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рд░реВрдк рд╕реЗ, рдпрджрд┐ рдЖрдк рдПрдкреАрдЖрдИ рдкрд░ рдкреНрд░рд▓реЗрдЦрди рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЖрд▓рд╕реА рд╣реИрдВ, рддреЛ рдЖрдк рдЗрд╕рдХреЗ рдмрд┐рдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдк рдЕрднреА рднреА рдлрд╝реЛрд▓реНрдбрд░реЛрдВ рдХреЗ рдЕрдВрджрд░ рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдмрд┐рдЦреЗрд░ рд╕рдХрддреЗ рд╣реИрдВ / рдирд┐рдпрдВрддреНрд░рдХ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдлрд╝реЛрд▓реНрдбрд░реНрд╕ рдореЗрдВ рдПрдкреАрдЖрдИ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдпрджрд┐ рдЖрдк "рдлрд░реНрд╕реНрдЯрдПрдВрдбрдкреЙрдЗрдВрдЯреНрд╕" рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╕рд░рдгреА рдореЗрдВ 'рдЧреЗрдЯрдЕрдкрд░реНрд╕' рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рддреЛ рдХреЛрдИ рдЕрдиреБрд░реЛрдз рдирд╣реАрдВ рд╣реЛрдЧрд╛, рдФрд░ рдкреНрд░рддрд┐рд╕рд╛рдж рдХреЛ рдирдореВрдирд╛рдкреНрд░рджрд░реНрд╢рди рд╕реЗ рд╕реНрдЯрдм рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рддрд╛рдХрд┐ рдирдХрд▓реА рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдбрд┐рдмреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ (рдиреЗрдЯрд╡рд░реНрдХ рдЯреИрдм рдореЗрдВ, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рд╣рдореЗрдВ рдХреБрдЫ рднреА рджрд┐рдЦрд╛рдИ рдирд╣реАрдВ рджреЗрддрд╛), рдореИрдВрдиреЗ рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рдореЗрдВ рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рдореЗрдВ рджреЛ рд▓рд╛рдЗрдиреЛрдВ рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛:

console.log('Fake Api Request:: ', this.name, request);
console.log('Fake Api Response:: ', this.sampleResponse);

рдпрджрд┐ рдЖрдк рд╡рд░реНрдЧ рд╕рдВрдкрддреНрддрд┐ рдХреИрд╢ = рд╕рддреНрдп рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЕрдиреБрд░реЛрдз рдХреИрд╢ рд╣реЛ рдЬрд╛рдПрдЧрд╛ (рдкрд╣рд▓реА рдмрд╛рд░ рдПрдкреАрдЖрдИ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдкрд╣рд▓реЗ рдЕрдиреБрд░реЛрдз рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╣рдореЗрд╢рд╛ рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рддрд╛ рд╣реИ)ред рдпрд╣рд╛рдВ рд╕рдЪреНрдЪрд╛рдИ рдХреЛ рдЕрдВрддрд┐рдо рд░реВрдк рджреЗрдирд╛ рд╣реИ: рдЖрдкрдХреЛ рдХреЗрд╡рд▓ рдХреИрд╢рд┐рдВрдЧ рдХрд╛рд░реНрдп рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдпрджрд┐ рдЕрдиреБрд░реЛрдз рдкреИрд░рд╛рдореАрдЯрд░ (UserRequest рд╡рд░реНрдЧ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреА рд╕рд╛рдордЧреНрд░реА)ред

рдпрджрд┐ рд╣рдореЗрдВ рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рдХреЗ рдХрд┐рд╕реА рднреА рдкрд░рд┐рд╡рд░реНрддрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рд╣рдо рдкреЗрд▓реЛрдбрдкрд╛рдЗрдк рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдкреЗрд▓реЛрдб рд╕реЗ рдбреЗрдЯрд╛ рд▓реМрдЯреЗ рд╡рд╛рджреЗ рдореЗрдВ рд╣реЛрдЧрд╛ред

рдЕрдм рд╣рдо рдШрдЯрдХ рдореЗрдВ рдПрдкреАрдЖрдИ рд╕реЗ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ:

import {Component, OnInit, ViewChild} from '@angular/core';
import {UserModel} from '../../models/user.model';
import {GetUsersEndpoint, GetUsersRequest} from '../../api/get_users.endpoint';

@Component({
  selector: 'app-users',
  templateUrl: './users.component.html',
  styleUrls: ['./users.component.css'],
  providers: [GetUsersEndpoint]
})
export class UsersComponent implements OnInit {

  public users: UserModel[];
  public request: GetUsersRequest = {page: 1, limit: 20};

  constructor(private getUsersEndpoint: GetUsersEndpoint) {    
  }

  private load() {
    this.getUsersEndpoint.execute(this.request).then(data => {
      this.users = data;
    });
  }

  ngOnInit(): void {
    this.load();
  }
}


рдЗрд╕ рддрд░рд╣ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ, рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдЕрдкрдиреА рд╡рд┐рд╢рд▓рд┐рд╕реНрдЯ рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рджрд┐рдЦрд╛рдирд╛ рд╕рдВрднрд╡ рд╣реИ, рднрд▓реЗ рд╣реА рдЗрди рд╡рд┐рд╢рд▓рд┐рд╕реНрдЯ рдХреЗ рд▓рд┐рдП рдмреИрдХрдПрдВрдб рдкреВрд░рд╛ рдирд╣реАрдВ рд╣реБрдЖ рд╣реЛред рд╕реНрдЯрдм рдкрд░ рдЖрд╡рд╢реНрдпрдХ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдбрд╛рд▓реЗрдВ - рдФрд░ рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЛ "рд╕реНрдкрд░реНрд╢" рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдореИрдВ рд░рдЪрдирд╛рддреНрдордХ рдЖрд▓реЛрдЪрдирд╛ рдХреЗ рд▓рд┐рдП рддрддреНрдкрд░ рд╣реВрдВ рдХрд┐ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдмрдирд╛рддреЗ рд╕рдордп рдХреМрди рд╕реА рд╕рдорд╕реНрдпрд╛рдПрдВ рдЙрддреНрдкрдиреНрди рд╣реЛ рд╕рдХрддреА рд╣реИрдВ, рдЬреЛ рдХрд┐ рдЕрдиреНрдп рдиреБрдХрд╕рд╛рди рд╕рд╛рдордиреЗ рдЖ рд╕рдХрддреЗ рд╣реИрдВред

рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдореИрдВ рдЗрд╕ рд╕рдорд╛рдзрд╛рди рдХреЛ рд╡рд╛рджреЛрдВ рд╕реЗ рд╣рдЯрд╛рдХрд░ async / рдЗрдВрддрдЬрд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХреЛрдб рдФрд░ рднреА рдЕрдзрд┐рдХ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рд╣реЛрдЧрд╛ред

рд╕реНрдЯреЙрдХ рдореЗрдВ рдирд┐рдХрдЯ рднрд╡рд┐рд╖реНрдп рдореЗрдВ, рдореИрдВ рд╕рд╛рдЭрд╛ рдХрд░рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдореЗрдВ рдХреЛрдгреАрдп рдХреЗ рд▓рд┐рдП рдХрдИ рдФрд░ рдЕрдзрд┐рдХ рд╡рд╛рд╕реНрддреБ рд╕рдорд╛рдзрд╛рди рд╣реИрдВред

All Articles