[core] added typescript decorators (experimental)

This commit is contained in:
Bilawal Hameed
2020-03-26 13:36:41 +01:00
parent b865bdd472
commit c86387ea09
4 changed files with 60 additions and 9 deletions
+12 -8
View File
@@ -17,13 +17,15 @@
// import React, { createContext, useContext, useState, FC } from 'react';
import { FeatureFlagName } from '../plugin/types';
import { FeatureFlagsApi } from '../apis/definitions/featureFlags';
import { staticImplements } from '../../testUtils';
// TODO: figure out where to put implementations of APIs, both inside apps
// but also in core/separate package.
export class FeatureFlags implements FeatureFlagsApi {
@staticImplements<FeatureFlagsApi>()
export class FeatureFlags {
private static readonly localStorageKey = 'featureFlags';
private static getEnabledFeatureFlags(): Set<FeatureFlagName> {
private static getUserEnabledFeatureFlags(): Set<FeatureFlagName> {
if (!('localStorage' in window)) {
throw new Error(
'Feature Flags are not supported on browsers without the Local Storage API',
@@ -40,7 +42,9 @@ export class FeatureFlags implements FeatureFlagsApi {
}
}
private static saveFeatureFlags(flags: Set<FeatureFlagName>): void {
private static saveUserEnabledFeatureFlags(
flags: Set<FeatureFlagName>,
): void {
if (!('localStorage' in window)) {
throw new Error(
'Feature Flags are not supported on browsers without the Local Storage API',
@@ -56,18 +60,18 @@ export class FeatureFlags implements FeatureFlagsApi {
}
static getItem(name: FeatureFlagName): boolean {
return this.getFeatureFlags().has(name);
return this.getUserEnabledFeatureFlags().has(name);
}
static enable(name: FeatureFlagName): void {
const flags = this.getFeatureFlags();
const flags = this.getUserEnabledFeatureFlags();
flags.add(name);
this.saveFeatureFlags(flags);
this.saveUserEnabledFeatureFlags(flags);
}
static disable(name: FeatureFlagName): void {
const flags = this.getFeatureFlags();
const flags = this.getUserEnabledFeatureFlags();
flags.delete(name);
this.saveFeatureFlags(flags);
this.saveUserEnabledFeatureFlags(flags);
}
}
+45
View File
@@ -0,0 +1,45 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This utilizes an experimental TypeScript feature called decorators.
* This was originally added to allow us to expose a FeatureFlags API
* with static methods (for backwards compatibility primarily). It takes
* an existing interface and applies the types to static methods in classes.
*
* @see https://www.typescriptlang.org/docs/handbook/decorators.html
* @example
* interface StaticProps {
* append(name: string, extra: string): string;
* reverse(name: string): string;
* }
*
* @staticImplements<StaticProps>()
* class StaticPropsClass {
* static append(name, extra) {
* return `${name}${extra}`;
* }
*
* static reverse(name) {
* return name.reverse();
* }
* }
*/
export function staticImplements<T>() {
return <U extends T>(constructor: U) => {
constructor;
};
}
+1
View File
@@ -28,6 +28,7 @@ import { render } from '@testing-library/react';
export { default as Keyboard } from './Keyboard';
export { default as mockBreakpoint } from './mockBreakpoint';
export * from './logCollector';
export * from './decorators';
export function wrapInTestApp(Component, initialRouterEntries) {
const Wrapper = Component instanceof Function ? Component : () => Component;
+2 -1
View File
@@ -2,6 +2,7 @@
"extends": "../../tsconfig.json",
"include": ["src"],
"compilerOptions": {
"noImplicitAny": false
"noImplicitAny": false,
"experimentalDecorators": true
}
}