164 lines
4.8 KiB
TypeScript
164 lines
4.8 KiB
TypeScript
import { Controller, ForbiddenException, Get, Injectable, UseInterceptors } from '@nestjs/common';
|
|
import type { Observable } from 'rxjs';
|
|
import { map } from 'rxjs';
|
|
import {
|
|
BooleanFeatureFlag,
|
|
ObjectFeatureFlag,
|
|
NumberFeatureFlag,
|
|
OpenFeatureClient,
|
|
StringFeatureFlag,
|
|
RequireFlagsEnabled,
|
|
} from '../src';
|
|
import type { Client, EvaluationDetails, FlagValue } from '@openfeature/server-sdk';
|
|
import { EvaluationContextInterceptor } from '../src';
|
|
|
|
@Injectable()
|
|
export class OpenFeatureTestService {
|
|
constructor(
|
|
@OpenFeatureClient() public defaultClient: Client,
|
|
@OpenFeatureClient({ domain: 'domainScopedClient' }) public domainScopedClient: Client,
|
|
) {}
|
|
|
|
public async serviceMethod(flag: EvaluationDetails<FlagValue>) {
|
|
return flag.value;
|
|
}
|
|
|
|
public async serviceMethodWithDynamicContext(flagKey: string): Promise<boolean> {
|
|
return this.defaultClient.getBooleanValue(flagKey, false);
|
|
}
|
|
}
|
|
|
|
@Controller()
|
|
export class OpenFeatureController {
|
|
constructor(private testService: OpenFeatureTestService) {}
|
|
|
|
@Get('/welcome')
|
|
public async welcome(
|
|
@BooleanFeatureFlag({ flagKey: 'testBooleanFlag', defaultValue: false })
|
|
feature: Observable<EvaluationDetails<boolean>>,
|
|
) {
|
|
return feature.pipe(
|
|
map((details) =>
|
|
details.value ? 'Welcome to this OpenFeature-enabled Nest.js app!' : 'Welcome to this Nest.js app!',
|
|
),
|
|
);
|
|
}
|
|
|
|
@Get('/boolean')
|
|
public async handleBooleanRequest(
|
|
@BooleanFeatureFlag({ flagKey: 'testBooleanFlag', defaultValue: false })
|
|
feature: Observable<EvaluationDetails<boolean>>,
|
|
) {
|
|
return feature.pipe(map((details) => this.testService.serviceMethod(details)));
|
|
}
|
|
|
|
@Get('/string')
|
|
public async handleStringRequest(
|
|
@StringFeatureFlag({ flagKey: 'testStringFlag', defaultValue: 'default-value' })
|
|
feature: Observable<EvaluationDetails<string>>,
|
|
) {
|
|
return feature.pipe(map((details) => this.testService.serviceMethod(details)));
|
|
}
|
|
|
|
@Get('/number')
|
|
public async handleNumberRequest(
|
|
@NumberFeatureFlag({ flagKey: 'testNumberFlag', defaultValue: 0 })
|
|
feature: Observable<EvaluationDetails<number>>,
|
|
) {
|
|
return feature.pipe(map((details) => this.testService.serviceMethod(details)));
|
|
}
|
|
|
|
@Get('/object')
|
|
public async handleObjectRequest(
|
|
@ObjectFeatureFlag({ flagKey: 'testObjectFlag', defaultValue: {} })
|
|
feature: Observable<EvaluationDetails<number>>,
|
|
) {
|
|
return feature.pipe(map((details) => this.testService.serviceMethod(details)));
|
|
}
|
|
|
|
@Get('/dynamic-context')
|
|
public async handleDynamicContextRequest(
|
|
@BooleanFeatureFlag({
|
|
flagKey: 'testBooleanFlag',
|
|
defaultValue: false,
|
|
})
|
|
feature: Observable<EvaluationDetails<number>>,
|
|
) {
|
|
return feature.pipe(map((details) => this.testService.serviceMethod(details)));
|
|
}
|
|
|
|
@Get('/dynamic-context-in-service')
|
|
public async handleDynamicContextInServiceRequest() {
|
|
return this.testService.serviceMethodWithDynamicContext('testBooleanFlag');
|
|
}
|
|
|
|
@RequireFlagsEnabled({
|
|
flags: [{ flagKey: 'testBooleanFlag' }],
|
|
})
|
|
@Get('/flags-enabled')
|
|
public async handleGuardedBooleanRequest() {
|
|
return 'Get Boolean Flag Success!';
|
|
}
|
|
|
|
@RequireFlagsEnabled({
|
|
flags: [{ flagKey: 'testBooleanFlag' }],
|
|
exception: new ForbiddenException(),
|
|
})
|
|
@Get('/flags-enabled-custom-exception')
|
|
public async handleBooleanRequestWithCustomException() {
|
|
return 'Get Boolean Flag Success!';
|
|
}
|
|
|
|
@RequireFlagsEnabled({
|
|
flags: [{ flagKey: 'testBooleanFlag2' }],
|
|
exception: new ForbiddenException(),
|
|
context: {
|
|
targetingKey: 'user-id',
|
|
},
|
|
})
|
|
@Get('/flags-enabled-custom-exception-with-context')
|
|
public async handleBooleanRequestWithCustomExceptionAndContext() {
|
|
return 'Get Boolean Flag Success!';
|
|
}
|
|
}
|
|
|
|
@Controller()
|
|
@UseInterceptors(EvaluationContextInterceptor)
|
|
export class OpenFeatureContextScopedController {
|
|
constructor(private testService: OpenFeatureTestService) {}
|
|
|
|
@Get('/controller-context')
|
|
public async handleDynamicContextRequest(
|
|
@BooleanFeatureFlag({
|
|
flagKey: 'testBooleanFlag',
|
|
defaultValue: false,
|
|
})
|
|
feature: Observable<EvaluationDetails<number>>,
|
|
) {
|
|
return feature.pipe(map((details) => this.testService.serviceMethod(details)));
|
|
}
|
|
|
|
@RequireFlagsEnabled({
|
|
flags: [{ flagKey: 'testBooleanFlag' }],
|
|
domain: 'domainScopedClient',
|
|
})
|
|
@Get('/controller-context/flags-enabled')
|
|
public async handleBooleanRequest() {
|
|
return 'Get Boolean Flag Success!';
|
|
}
|
|
}
|
|
|
|
@Controller('require-flags-enabled')
|
|
@RequireFlagsEnabled({
|
|
flags: [{ flagKey: 'testBooleanFlag', defaultValue: false }, { flagKey: 'testBooleanFlag2' }],
|
|
exception: new ForbiddenException(),
|
|
})
|
|
export class OpenFeatureRequireFlagsEnabledController {
|
|
constructor() {}
|
|
|
|
@Get('/')
|
|
public async handleGetRequest() {
|
|
return 'Hello, world!';
|
|
}
|
|
}
|