App.settings-角度方式?


87

我想在App Settings我的应用程序中添加一个部分,其中将包含一些const和预定义的值。

我已经阅读了使用的答案OpaqueToken但是在Angular中已弃用。此文章解释了差异,但它没有提供一个完整的例子,我的尝试均告失败。

这是我尝试过的方法(我不知道这是否正确):

//ServiceAppSettings.ts

import {InjectionToken, OpaqueToken} from "@angular/core";

const CONFIG = {
  apiUrl: 'http://my.api.com',
  theme: 'suicid-squad',
  title: 'My awesome app'
};
const FEATURE_ENABLED = true;
const API_URL = new InjectionToken<string>('apiUrl');

这是我要使用这些const的组件:

//MainPage.ts

import {...} from '@angular/core'
import {ServiceTest} from "./ServiceTest"

@Component({
  selector: 'my-app',
  template: `
   <span>Hi</span>
  ` ,  providers: [
    {
      provide: ServiceTest,
      useFactory: ( apiUrl) => {
        // create data service
      },
      deps: [

        new Inject(API_URL)
      ]
    }
  ]
})
export class MainPage {


}

但这不起作用,我得到了错误。

题:

如何以Angular方式使用“ app.settings”值?

矮人

注意:当然,我可以创建Injectable服务并将其放入NgModule的提供程序中,但是正如我所说的,我想使用InjectionTokenAngular方式进行。


您可以根据当前的官方文档在此处查看我的回答
JavierFuentes

@哈维尔号 如果两个提供程序提供的名称相同,则您的链接有问题,因此您现在遇到了问题。进入opaquetoken
Royi Namir

您知道[OpaqueToken已弃用]。(angular.io/api/core/OpaqueToken本文讨论了如何防止Angular提供程序中的名称冲突
JavierFuentes

是的,我知道,但是链接的文章仍然是错误的。
罗伊·纳米尔

2
可能在下面的链接可能对每个喜欢使用角度配置架构新体系结构的人都有用devblogs.microsoft.com/premier-developer/…–
M_Farahmand

Answers:


56

我想出了如何使用InjectionTokens做到这一点(请参见下面的示例),如果您的项目是使用来构建的Angular CLI,则可以使用其中/environments的静态环境文件(application wide settings例如API端点),但是根据项目的要求,您很可能最终因为环境文件只是对象文字,所以两者都使用,而使用的可注入配置InjectionToken可以使用环境变量,并且由于它是一个类,因此可以根据应用程序中的其他因素(例如初始http请求数据,子域)应用逻辑对其进行配置等

注入令牌示例

/app/app-config.module.ts

import { NgModule, InjectionToken } from '@angular/core';
import { environment } from '../environments/environment';

export let APP_CONFIG = new InjectionToken<AppConfig>('app.config');

export class AppConfig {
  apiEndpoint: string;
}

export const APP_DI_CONFIG: AppConfig = {
  apiEndpoint: environment.apiEndpoint
};

@NgModule({
  providers: [{
    provide: APP_CONFIG,
    useValue: APP_DI_CONFIG
  }]
})
export class AppConfigModule { }

/app/app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppConfigModule } from './app-config.module';

@NgModule({
  declarations: [
    // ...
  ],
  imports: [
    // ...
    AppConfigModule
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

现在,您可以将其直接放入任何组件,服务等中:

/app/core/auth.service.ts

import { Injectable, Inject } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

import { APP_CONFIG, AppConfig } from '../app-config.module';
import { AuthHttp } from 'angular2-jwt';

@Injectable()
export class AuthService {

  constructor(
    private http: Http,
    private router: Router,
    private authHttp: AuthHttp,
    @Inject(APP_CONFIG) private config: AppConfig
  ) { }

  /**
   * Logs a user into the application.
   * @param payload
   */
  public login(payload: { username: string, password: string }) {
    return this.http
      .post(`${this.config.apiEndpoint}/login`, payload)
      .map((response: Response) => {
        const token = response.json().token;
        sessionStorage.setItem('token', token); // TODO: can this be done else where? interceptor
        return this.handleResponse(response); // TODO:  unset token shouldn't return the token to login
      })
      .catch(this.handleError);
  }

  // ...
}

然后,您还可以使用导出的AppConfig键入检查配置。


否,但是您可以从字面上复制第一部分并将其粘贴到文件中,将其导入到app.module.ts文件中,然后在任意位置进行DI并将其输出到控制台。我将花费更长的时间将其设置为一个插销,然后再执行这些步骤。
mtpultz

哦,我以为您已经为此付出了代价:-)谢谢。
罗伊·纳米尔


1
我不认为您需要导出AppConfig接口/类。在进行DI时,您绝对不需要使用它。为了使它在一个文件中起作用,它必须是类而不是接口,但这并不重要。实际上,样式指南建议使用类而不是接口,因为这意味着更少的代码,您仍然可以使用它们来键入check。关于InjectionToken通过泛型使用的情况,您需要包括它。
mtpultz

1
我正在尝试使用Azure的环境变量和JSON转换功能动态注入API终结点,但是看起来这个答案只是从环境文件中获取apiEndpoint。您将如何从配置中获取并导出它?
阿奇博尔德

138

如果您正在使用 ,还有另一种选择:

Angular CLI提供了环境文件src/environments(默认文件是environment.ts(dev)和environment.prod.ts(生产))。

请注意,您需要在所有environment.*文件中提供config参数,例如,

environment.ts

export const environment = {
  production: false,
  apiEndpoint: 'http://localhost:8000/api/v1'
};

environment.prod.ts

export const environment = {
  production: true,
  apiEndpoint: '__your_production_server__'
};

并在您的服务中使用它们(会自动选择正确的环境文件):

api.service.ts

// ... other imports
import { environment } from '../../environments/environment';

@Injectable()
export class ApiService {     

  public apiRequest(): Observable<MyObject[]> {
    const path = environment.apiEndpoint + `/objects`;
    // ...
  }

// ...
}

Github(Angular CLI版本6)官方Angular指南(版本7)中阅读有关应用程序环境的更多信息。


2
它的工作正常。但是在移动构建时,它也被更改为bundle。我应该在移入生产后在服务中而不是在代码中更改配置
kamalav

42
这在正常的软件开发中是一种反模式。API网址只是配置。无需重新构建即可为其他环境重新配置应用程序。它应该构建一次,部署多次(预生产,登台,生产等)。
Matt Tester

3
@MattTester这实际上是现在Angular-CLI的官方故事。如果您碰巧对这个问题有一个更好的答案:请随时发布!
tilo

7
在ng构建之后可以配置吗?
NK

1
哦,好的,我看错了评论。我同意这会带来反模式,我认为动态运行时配置有个故事。
詹斯·鲍德

83

不建议将这些environment.*.ts文件用于API URL配置。似乎您应该这样做,因为它提到了“环境”一词。

使用此实际上是编译时配置。如果要更改API URL,则需要重新构建。那是你不想做的事情...只问你友好的质量保证部门:)

您需要的是运行时配置,即应用程序在启动时加载其配置。

其他一些答案也涉及到这一点,但是区别在于,应用程序启动后需要立即加载配置,以便普通服务在需要时可以使用它。

要实现运行时配置:

  1. 将JSON配置文件添加到/src/assets/文件夹(以便在构建时复制)
  2. 创建一个AppConfigService以加载和分发配置
  3. 使用 APP_INITIALIZER

1.将配置文件添加到 /src/assets

您可以将其添加到另一个文件夹,但是您需要告诉CLI它是中的资产angular.json。使用资产文件夹开始:

{
  "apiBaseUrl": "https://development.local/apiUrl"
}

2.建立 AppConfigService

这是将在需要配置值时注入的服务:

@Injectable({
  providedIn: 'root'
})
export class AppConfigService {

  private appConfig: any;

  constructor(private http: HttpClient) { }

  loadAppConfig() {
    return this.http.get('/assets/config.json')
      .toPromise()
      .then(data => {
        this.appConfig = data;
      });
  }

  // This is an example property ... you can make it however you want.
  get apiBaseUrl() {

    if (!this.appConfig) {
      throw Error('Config file not loaded!');
    }

    return this.appConfig.apiBaseUrl;
  }
}

3.使用 APP_INITIALIZER

为了在AppConfigService配置完全加载的情况下安全地注入,我们需要在应用启动时加载配置。重要的是,初始化工厂函数需要返回a,Promise以便Angular知道要等到其完成解析后才能完成启动:

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [
    {
      provide: APP_INITIALIZER,
      multi: true,
      deps: [AppConfigService],
      useFactory: (appConfigService: AppConfigService) => {
        return () => {
          //Make sure to return a promise!
          return appConfigService.loadAppConfig();
        };
      }
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

现在,您可以将其注入到任何需要的地方,所有配置都可以读取:

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {

  apiBaseUrl: string;

  constructor(private appConfigService: AppConfigService) {}

  ngOnInit(): void {
    this.apiBaseUrl = this.appConfigService.apiBaseUrl;
  }

}

我说的不够强烈,将您的API网址配置为编译时配置是一种反模式。使用运行时配置。


4
本地文件或其他服务,不应将编译时配置用于API网址。想象一下,如果您的应用程序是作为产品出售的(要购买的安装程序),您不希望它们进行编译,等等。无论哪种方式,您都不想重新编译2年前构建的内容,因为API网址已更改。风险!!
Matt Tester

1
@Bloodhound您可以拥有多个,APP_INITIALIZER但我认为您不能轻易使它们相互依赖。听起来您有个好问题要问,也许可以在这里链接到它?
Matt Tester

2
@MattTester-如果Angular实现了此功能,它将解决我们的问题:github.com/angular/angular/issues/23279#issuecomment-528417026
Mike Becatti

2
@CrhistianRamirez从应用程序的角度来看:配置直到运行时才知道,并且静态文件不在构建之内,并且可以在部署时以多种方式进行设置。静态文件适用于非敏感配置。使用相同的技术可以实现API或其他受保护的端点,但是接下来的挑战是如何进行身份验证以使其受保护。
Matt Tester

1
@DaleK在两行之间阅读,您正在使用Web Deploy进行部署。如果您使用的是诸如Azure DevOps之类的部署管道,则下一步可以正确设置配置文件。配置的设置由部署过程/管道负责,它可以覆盖默认配置文件中的值。希望能澄清。
Matt Tester

8

这是我的解决方案,从.json加载以允许更改而无需重建

import { Injectable, Inject } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Location } from '@angular/common';

@Injectable()
export class ConfigService {

    private config: any;

    constructor(private location: Location, private http: Http) {
    }

    async apiUrl(): Promise<string> {
        let conf = await this.getConfig();
        return Promise.resolve(conf.apiUrl);
    }

    private async getConfig(): Promise<any> {
        if (!this.config) {
            this.config = (await this.http.get(this.location.prepareExternalUrl('/assets/config.json')).toPromise()).json();
        }
        return Promise.resolve(this.config);
    }
}

和config.json

{
    "apiUrl": "http://localhost:3000/api"
}

1
这种方法的问题在于config.json向世界开放。您如何防止他人键入www.mywebsite.com/assetts/config.json?
阿尔贝托·L·邦菲里奥18'Mar

1
@ AlbertoL.Bonfiglio您将服务器配置为不允许从外部访问config.json文件(或将其放置在没有公共访问权限的目录中)
Alex Pandrea

这也是我最喜欢的解决方案,但仍然要担心安全风险。
Viqas

7
拜托,你能帮我做对吗?与传统的角度环境相比,它的风险如何?的全部内容environments.prod.ts后,ng build --prod将在一些.js在某些时候的文件。即使混淆,来自的数据environments.prod.ts也将以明文形式显示。作为所有.js文件,它将在最终用户计算机上可用。
伊甘

5
@ AlbertoL.Bonfiglio因为Angular应用程序本质上是客户端应用程序,并且JavaScript将用于传递数据和配置,所以其中不应使用任何秘密配置。所有秘密配置定义都应位于用户浏览器或浏览器工具无法访问的API层之后。诸如API的基本URI之类的值可供公众访问,因为基于用户登录(基于https的承载令牌),API应该具有自己的凭据和安全性。
Tommy Elliott

4

可怜的人的配置文件:

作为body标签中的第一个标签添加到index.html中:

<script lang="javascript" src="assets/config.js"></script>

添加资产/config.js:

var config = {
    apiBaseUrl: "http://localhost:8080"
}

添加config.ts:

export const config: AppConfig = window['config']

export interface AppConfig {
    apiBaseUrl: string
}

认真地说,+1是为了将解决方案简化为最基本的组件,并仍然保持类型一致性。
发光的

4

我发现APP_INITIALIZER在其他服务提供商要求注入配置的情况下,不能为此使用。可以在APP_INITIALIZER运行之前实例化它们。

我已经看到了其他解决方案,这些解决方案fetch用于读取config.json文件,并platformBrowserDynamic()在引导根模块之前使用参数中的注入令牌提供该文件。但fetch并非所有浏览器,特别是我定位的移动设备的WebView浏览器均不支持。

以下是适用于PWA和移动设备(WebView)的解决方案。注意:到目前为止,我仅在Android上进行过测试;在家工作意味着我无法使用Mac进行构建。

main.ts

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import { APP_CONFIG } from './app/lib/angular/injection-tokens';

function configListener() {
  try {
    const configuration = JSON.parse(this.responseText);

    // pass config to bootstrap process using an injection token
    platformBrowserDynamic([
      { provide: APP_CONFIG, useValue: configuration }
    ])
      .bootstrapModule(AppModule)
      .catch(err => console.error(err));

  } catch (error) {
    console.error(error);
  }
}

function configFailed(evt) {
  console.error('Error: retrieving config.json');
}

if (environment.production) {
  enableProdMode();
}

const request = new XMLHttpRequest();
request.addEventListener('load', configListener);
request.addEventListener('error', configFailed);
request.open('GET', './assets/config/config.json');
request.send();

这段代码:

  1. 启动对该config.json文件的异步请求。
  2. 请求完成后,将JSON解析为Javascript对象
  3. APP_CONFIG在引导之前,使用注入令牌提供值。
  4. 最后引导根模块。

APP_CONFIG然后可以将其注入其中的任何其他提供程序中,app-module.ts并将对其进行定义。例如,我可以使用以下命令初始化FIREBASE_OPTIONS注入令牌@angular/fire

{
      provide: FIREBASE_OPTIONS,
      useFactory: (config: IConfig) => config.firebaseConfig,
      deps: [APP_CONFIG]
}

对于非常普遍的要求,我发现整件事很难做到(而且很棘手)。希望在不久的将来会有更好的方法,例如对异步提供程序工厂的支持。

其余代码的完整性...

app/lib/angular/injection-tokens.ts

import { InjectionToken } from '@angular/core';
import { IConfig } from '../config/config';

export const APP_CONFIG = new InjectionToken<IConfig>('app-config');

并在其中app/lib/config/config.ts定义我的JSON配置文件的接口:

export interface IConfig {
    name: string;
    version: string;
    instance: string;
    firebaseConfig: {
        apiKey: string;
        // etc
    }
}

Config存储在assets/config/config.json

{
  "name": "my-app",
  "version": "#{Build.BuildNumber}#",
  "instance": "localdev",
  "firebaseConfig": {
    "apiKey": "abcd"
    ...
  }
}

注意:我使用Azure DevOps任务来插入Build.BuildNumber并在部署时将其他设置替换为不同的部署环境。


2

这是我的两个解决方案

1.存储在json文件中

只需制作一个json文件,然后按$http.get()方法进入您的组件即可。如果我需要这个很低的东西,那就好又快。

2.通过使用数据服务进行存储

如果要存储并在所有组件中使用或有大量使用,那么最好使用数据服务。像这样 :

  1. 只需在src/app文件夹内创建静态文件夹。

  2. fuels.ts在静态文件夹中创建一个名为的文件。您也可以在这里存储其他静态文件。让我们这样定义数据。假设您拥有燃料数据。

__

export const Fuels {

   Fuel: [
    { "id": 1, "type": "A" },
    { "id": 2, "type": "B" },
    { "id": 3, "type": "C" },
    { "id": 4, "type": "D" },
   ];
   }
  1. 创建文件名static.services.ts

__

import { Injectable } from "@angular/core";
import { Fuels } from "./static/fuels";

@Injectable()
export class StaticService {

  constructor() { }

  getFuelData(): Fuels[] {
    return Fuels;
  }
 }`
  1. 现在,您可以将其用于每个模块

只需像这样导入app.module.ts文件并更改提供者

import { StaticService } from './static.services';

providers: [StaticService]

现在像StaticService在任何模块中一样使用它。

就这样。


很好的解决方案,因为您不必重新编译。环境就像在代码中对其进行硬编码一样。讨厌。+1
Terrance00


0

多年前,我加入并提出了一个使用本地存储来存储用户和环境信息的解决方案之前,我们就遇到了这个问题。精确的角度为1.0天。我们以前是在运行时动态创建一个js文件,然后将生成的api网址放入一个全局变量中。如今,我们受OOP驱动更多,并且不使用本地存储来存储任何内容。

我为确定环境和api URL创建了一个更好的解决方案。

这有何不同?

除非已加载config.json文件,否则不会加载该应用程序。它使用工厂功能来创建更高级别的SOC。我可以将其封装到服务中,但是当文件的不同部分之间唯一的相似之处在于它们在文件中同时存在时,我再也看不到任何原因。如果具有工厂功能,则可以将功能直接传递到模块中(如果它可以接受功能)。最后,当工厂函数可供使用时,我可以更轻松地设置InjectionTokens。

缺点?

如果您要配置的模块不允许将工厂函数传递给forRoot()或forChild(),那么您将无法使用此设置(以及大多数其他答案),并且没有其他方法可以使用出厂功能配置程序包。

使用说明

  1. 使用获取来检索json文件,我将对象存储在window中并引发一个自定义事件。-记住安装whatwg-fetch并将其添加到您的polyfills.ts中以实现IE兼容性
  2. 让事件监听器监听自定义事件。
  3. 事件侦听器接收事件,从窗口检索对象以传递给可观察对象,并清除窗口中存储的内容。
  4. 引导角

-这是我的解决方案开始与众不同的地方-

  1. 创建一个文件,导出一个接口,该接口的结构表示您的config.json -确实有助于类型一致性,下一部分代码需要一个类型,并且不指定,{}或者any在您知道可以指定更具体的内容时
  2. 创建BehaviorSubject,您将在步骤3中将解析的json文件传递到其中。
  3. 使用工厂功能来引用配置的不同部分以维护SOC
  4. 为需要工厂功能结果的提供者创建InjectionTokens

-和/或-

  1. 将工厂函数直接传递到能够在其forRoot()或forChild()方法中接受函数的模块中。

-main.ts

我在创建事件侦听器之前检查是否未填充window [“ environment”],以允许通过main.ts中的代码在执行之前通过其他某种方式填充window [“ environment”]的解决方案。

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { configurationSubject } from './app/utils/environment-resolver';

var configurationLoadedEvent = document.createEvent('Event');
configurationLoadedEvent.initEvent('config-set', true, true);
fetch("../../assets/config.json")
.then(result => { return result.json(); })
.then(data => {
  window["environment"] = data;
  document.dispatchEvent(configurationLoadedEvent);
}, error => window.location.reload());

/*
  angular-cli only loads the first thing it finds it needs a dependency under /app in main.ts when under local scope. 
  Make AppModule the first dependency it needs and the rest are done for ya. Event listeners are 
  ran at a higher level of scope bypassing the behavior of not loading AppModule when the 
  configurationSubject is referenced before calling platformBrowserDynamic().bootstrapModule(AppModule)

  example: this will not work because configurationSubject is the first dependency the compiler realizes that lives under 
  app and will ONLY load that dependency, making AppModule an empty object.

  if(window["environment"])
  {
    if (window["environment"].production) {
      enableProdMode();
    }
    configurationSubject.next(window["environment"]);
    platformBrowserDynamic().bootstrapModule(AppModule)
    .catch(err => console.log(err));
  }
*/
if(!window["environment"]) {
  document.addEventListener('config-set', function(e){
    if (window["environment"].production) {
      enableProdMode();
    }
    configurationSubject.next(window["environment"]);
    window["environment"] = undefined;
    platformBrowserDynamic().bootstrapModule(AppModule)
    .catch(err => console.log(err));
  });
}

---环境解析器

我使用window [“ environment”]为BehaviorSubject分配了一个值,以实现冗余。您可以设计一个解决方案,其中在运行任何Angular应用程序代码时(包括main.ts中的代码),已经预先加载了配置,并且window [“ environment”]已被填充。

import { BehaviorSubject } from "rxjs";
import { IConfig } from "../config.interface";

const config = <IConfig>Object.assign({}, window["environment"]);
export const configurationSubject = new BehaviorSubject<IConfig>(config);
export function resolveEnvironment() {
  const env = configurationSubject.getValue().environment;
  let resolvedEnvironment = "";
  switch (env) {
 // case statements for determining whether this is dev, test, stage, or prod
  }
  return resolvedEnvironment;
}

export function resolveNgxLoggerConfig() {
  return configurationSubject.getValue().logging;
}

-app.module.ts-精简以便于理解

有趣的事实!较旧的NGXLogger版本要求您将一个对象传递到LoggerModule.forRoot()。实际上,LoggerModule仍然可以!NGXLogger请公开LoggerConfig,您可以重写它,从而允许使用工厂功能进行设置。

import { resolveEnvironment, resolveNgxLoggerConfig, resolveSomethingElse } from './environment-resolvers';
import { LoggerConfig } from 'ngx-logger';
@NgModule({
    modules: [
        SomeModule.forRoot(resolveSomethingElse)
    ],
    providers:[
        {
            provide: ENVIRONMENT,
            useFactory: resolveEnvironment
        },
        { 
            provide: LoggerConfig,
            useFactory: resolveNgxLoggerConfig
        }
    ]
})
export class AppModule

附录

如何解决我的API网址的创建?

我希望能够通过注释来理解每个URL的功能,并希望进行类型检查,因为与JavaScript(IMO)相比,TypeScript的最大优势是。我还想为其他开发人员创造一种体验,以添加尽可能无缝的新端点和api。

我创建了一个包含环境的类(开发,测试,阶段,产品,“”等),并将此值传递给一系列类[1-N],其工作是为每个API集合创建基本URL。 。每个ApiCollection负责为每个API集合创建基本URL。可能是我们自己的API,供应商的API,甚至是外部链接。该类会将创建的基本URL传递到它包含的每个后续api中。阅读下面的代码以查看示例。设置完成后,对于另一个开发人员而言,将另一个端点添加到Api类非常简单,而无需进行任何其他操作。

TLDR;基本的OOP原理和用于内存优化的惰性获取器

@Injectable({
    providedIn: 'root'
})
export class ApiConfig {
    public apis: Apis;

    constructor(@Inject(ENVIRONMENT) private environment: string) {
        this.apis = new Apis(environment);
    }
}

export class Apis {
    readonly microservices: MicroserviceApiCollection;

    constructor(environment: string) {
        this.microservices = new MicroserviceApiCollection(environment);
    }
}

export abstract class ApiCollection {
  protected domain: any;

  constructor(environment: string) {
      const domain = this.resolveDomain(environment);
      Object.defineProperty(ApiCollection.prototype, 'domain', {
          get() {
              Object.defineProperty(this, 'domain', { value: domain });
              return this.domain;
          },
          configurable: true
      });
  }
}

export class MicroserviceApiCollection extends ApiCollection {
  public member: MemberApi;

  constructor(environment) {
      super(environment);
      this.member = new MemberApi(this.domain);
  }

  resolveDomain(environment: string): string {
      return `https://subdomain${environment}.actualdomain.com/`;
  }
}

export class Api {
  readonly base: any;

  constructor(baseUrl: string) {
      Object.defineProperty(this, 'base', {
          get() {
              Object.defineProperty(this, 'base',
              { value: baseUrl, configurable: true});
              return this.base;
          },
          enumerable: false,
          configurable: true
      });
  }

  attachProperty(name: string, value: any, enumerable?: boolean) {
      Object.defineProperty(this, name,
      { value, writable: false, configurable: true, enumerable: enumerable || true });
  }
}

export class MemberApi extends Api {

  /**
  * This comment will show up when referencing this.apiConfig.apis.microservices.member.memberInfo
  */
  get MemberInfo() {
    this.attachProperty("MemberInfo", `${this.base}basic-info`);
    return this.MemberInfo;
  }

  constructor(baseUrl: string) {
    super(baseUrl + "member/api/");
  }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.