Use Flow in feature flags scripts (#42814)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/42814

Improves the type safety of the feature flags generation and verification script.

Changelog: [internal]

Reviewed By: huntie

Differential Revision: D53351484

fbshipit-source-id: a71af1bb428cdec327d557de4d54bee9ece57f34
This commit is contained in:
Rubén Norte
2024-02-05 11:02:48 -08:00
committed by Facebook GitHub Bot
parent be61dcda90
commit dbbec3452f
31 changed files with 398 additions and 351 deletions
+19
View File
@@ -0,0 +1,19 @@
/**
* (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
*
* @format
* @flow strict
*/
declare module 'signedsource' {
declare type SignedSource = {
TokenNotFoundError: Error,
getSigningToken(): string,
isSigned(data: string): boolean,
signFile(data: string): string,
verifySignature(data: string): boolean,
[key: string]: mixed,
};
declare module.exports: SignedSource;
}
+2 -2
View File
@@ -90,8 +90,8 @@
],
"scripts": {
"prepack": "cp ../../README.md .",
"featureflags-check": "node ./scripts/featureflags/update.js --verify-unchanged",
"featureflags-update": "node ./scripts/featureflags/update.js"
"featureflags-check": "node ./scripts/featureflags/index.js --verify-unchanged",
"featureflags-update": "node ./scripts/featureflags/index.js"
},
"peerDependencies": {
"react": "18.2.0"
@@ -47,7 +47,8 @@ Example:
```
After any changes to this definitions, the code that provides access to them
must be regenerated executing the `update` script in this directory.
must be regenerated running `yarn featureflags-update` from the `react-native`
repository.
## Access
@@ -4,65 +4,49 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {GeneratorConfig, GeneratorResult} from './types';
const JReactNativeFeatureFlagsCxxInteropCPP = require('./templates/android/JReactNativeFeatureFlagsCxxInterop.cpp-template');
const JReactNativeFeatureFlagsCxxInteropH = require('./templates/android/JReactNativeFeatureFlagsCxxInterop.h-template');
const ReactNativeFeatureFlagsKt = require('./templates/android/ReactNativeFeatureFlags.kt-template');
const ReactNativeFeatureFlagsCxxAccessorKt = require('./templates/android/ReactNativeFeatureFlagsCxxAccessor.kt-template');
const ReactNativeFeatureFlagsCxxInteropKt = require('./templates/android/ReactNativeFeatureFlagsCxxInterop.kt-template');
const ReactNativeFeatureFlagsDefaultsKt = require('./templates/android/ReactNativeFeatureFlagsDefaults.kt-template');
const ReactNativeFeatureFlagsLocalAccessorKt = require('./templates/android/ReactNativeFeatureFlagsLocalAccessor.kt-template');
const ReactNativeFeatureFlagsProviderKt = require('./templates/android/ReactNativeFeatureFlagsProvider.kt-template');
const ReactNativeFeatureFlagsProviderHolderCPP = require('./templates/android/ReactNativeFeatureFlagsProviderHolder.cpp-template');
const ReactNativeFeatureFlagsProviderHolderH = require('./templates/android/ReactNativeFeatureFlagsProviderHolder.h-template');
const path = require('path');
import JReactNativeFeatureFlagsCxxInteropCPP from './templates/android/JReactNativeFeatureFlagsCxxInterop.cpp-template';
import JReactNativeFeatureFlagsCxxInteropH from './templates/android/JReactNativeFeatureFlagsCxxInterop.h-template';
import ReactNativeFeatureFlagsKt from './templates/android/ReactNativeFeatureFlags.kt-template';
import ReactNativeFeatureFlagsCxxAccessorKt from './templates/android/ReactNativeFeatureFlagsCxxAccessor.kt-template';
import ReactNativeFeatureFlagsCxxInteropKt from './templates/android/ReactNativeFeatureFlagsCxxInterop.kt-template';
import ReactNativeFeatureFlagsDefaultsKt from './templates/android/ReactNativeFeatureFlagsDefaults.kt-template';
import ReactNativeFeatureFlagsLocalAccessorKt from './templates/android/ReactNativeFeatureFlagsLocalAccessor.kt-template';
import ReactNativeFeatureFlagsProviderKt from './templates/android/ReactNativeFeatureFlagsProvider.kt-template';
import ReactNativeFeatureFlagsProviderHolderCPP from './templates/android/ReactNativeFeatureFlagsProviderHolder.cpp-template';
import ReactNativeFeatureFlagsProviderHolderH from './templates/android/ReactNativeFeatureFlagsProviderHolder.h-template';
import path from 'path';
export default function generateAndroidModules(
generatorConfig: GeneratorConfig,
): GeneratorResult {
const {androidPath, androidJniPath, featureFlagDefinitions} = generatorConfig;
module.exports = function generateandroidModules(
generatorConfig,
featureFlagsConfig,
) {
return {
[path.join(generatorConfig.androidPath, 'ReactNativeFeatureFlags.kt')]:
ReactNativeFeatureFlagsKt(featureFlagsConfig),
[path.join(
generatorConfig.androidPath,
'ReactNativeFeatureFlagsCxxAccessor.kt',
)]: ReactNativeFeatureFlagsCxxAccessorKt(featureFlagsConfig),
[path.join(
generatorConfig.androidPath,
'ReactNativeFeatureFlagsLocalAccessor.kt',
)]: ReactNativeFeatureFlagsLocalAccessorKt(featureFlagsConfig),
[path.join(
generatorConfig.androidPath,
'ReactNativeFeatureFlagsCxxInterop.kt',
)]: ReactNativeFeatureFlagsCxxInteropKt(featureFlagsConfig),
[path.join(
generatorConfig.androidPath,
'ReactNativeFeatureFlagsDefaults.kt',
)]: ReactNativeFeatureFlagsDefaultsKt(featureFlagsConfig),
[path.join(
generatorConfig.androidPath,
'ReactNativeFeatureFlagsProvider.kt',
)]: ReactNativeFeatureFlagsProviderKt(featureFlagsConfig),
[path.join(
generatorConfig.androidJniPath,
'ReactNativeFeatureFlagsProviderHolder.h',
)]: ReactNativeFeatureFlagsProviderHolderH(featureFlagsConfig),
[path.join(
generatorConfig.androidJniPath,
'ReactNativeFeatureFlagsProviderHolder.cpp',
)]: ReactNativeFeatureFlagsProviderHolderCPP(featureFlagsConfig),
[path.join(
generatorConfig.androidJniPath,
'JReactNativeFeatureFlagsCxxInterop.h',
)]: JReactNativeFeatureFlagsCxxInteropH(featureFlagsConfig),
[path.join(
generatorConfig.androidJniPath,
'JReactNativeFeatureFlagsCxxInterop.cpp',
)]: JReactNativeFeatureFlagsCxxInteropCPP(featureFlagsConfig),
[path.join(androidPath, 'ReactNativeFeatureFlags.kt')]:
ReactNativeFeatureFlagsKt(featureFlagDefinitions),
[path.join(androidPath, 'ReactNativeFeatureFlagsCxxAccessor.kt')]:
ReactNativeFeatureFlagsCxxAccessorKt(featureFlagDefinitions),
[path.join(androidPath, 'ReactNativeFeatureFlagsLocalAccessor.kt')]:
ReactNativeFeatureFlagsLocalAccessorKt(featureFlagDefinitions),
[path.join(androidPath, 'ReactNativeFeatureFlagsCxxInterop.kt')]:
ReactNativeFeatureFlagsCxxInteropKt(featureFlagDefinitions),
[path.join(androidPath, 'ReactNativeFeatureFlagsDefaults.kt')]:
ReactNativeFeatureFlagsDefaultsKt(featureFlagDefinitions),
[path.join(androidPath, 'ReactNativeFeatureFlagsProvider.kt')]:
ReactNativeFeatureFlagsProviderKt(featureFlagDefinitions),
[path.join(androidJniPath, 'ReactNativeFeatureFlagsProviderHolder.h')]:
ReactNativeFeatureFlagsProviderHolderH(featureFlagDefinitions),
[path.join(androidJniPath, 'ReactNativeFeatureFlagsProviderHolder.cpp')]:
ReactNativeFeatureFlagsProviderHolderCPP(featureFlagDefinitions),
[path.join(androidJniPath, 'JReactNativeFeatureFlagsCxxInterop.h')]:
JReactNativeFeatureFlagsCxxInteropH(featureFlagDefinitions),
[path.join(androidJniPath, 'JReactNativeFeatureFlagsCxxInterop.cpp')]:
JReactNativeFeatureFlagsCxxInteropCPP(featureFlagDefinitions),
};
};
}
@@ -4,43 +4,37 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {GeneratorConfig, GeneratorResult} from './types';
const ReactNativeFeatureFlagsCPP = require('./templates/common-cxx/ReactNativeFeatureFlags.cpp-template');
const ReactNativeFeatureFlagsH = require('./templates/common-cxx/ReactNativeFeatureFlags.h-template');
const ReactNativeFeatureFlagsAccessorCPP = require('./templates/common-cxx/ReactNativeFeatureFlagsAccessor.cpp-template');
const ReactNativeFeatureFlagsAccessorH = require('./templates/common-cxx/ReactNativeFeatureFlagsAccessor.h-template');
const ReactNativeFeatureFlagsDefaultsH = require('./templates/common-cxx/ReactNativeFeatureFlagsDefaults.h-template');
const ReactNativeFeatureFlagsProviderH = require('./templates/common-cxx/ReactNativeFeatureFlagsProvider.h-template');
const path = require('path');
import ReactNativeFeatureFlagsCPP from './templates/common-cxx/ReactNativeFeatureFlags.cpp-template';
import ReactNativeFeatureFlagsH from './templates/common-cxx/ReactNativeFeatureFlags.h-template';
import ReactNativeFeatureFlagsAccessorCPP from './templates/common-cxx/ReactNativeFeatureFlagsAccessor.cpp-template';
import ReactNativeFeatureFlagsAccessorH from './templates/common-cxx/ReactNativeFeatureFlagsAccessor.h-template';
import ReactNativeFeatureFlagsDefaultsH from './templates/common-cxx/ReactNativeFeatureFlagsDefaults.h-template';
import ReactNativeFeatureFlagsProviderH from './templates/common-cxx/ReactNativeFeatureFlagsProvider.h-template';
import path from 'path';
export default function generateCommonCxxModules(
generatorConfig: GeneratorConfig,
): GeneratorResult {
const {commonCxxPath, featureFlagDefinitions} = generatorConfig;
module.exports = function generateCommonCxxModules(
generatorConfig,
featureFlagsConfig,
) {
return {
[path.join(generatorConfig.commonCxxPath, 'ReactNativeFeatureFlags.h')]:
ReactNativeFeatureFlagsH(featureFlagsConfig),
[path.join(generatorConfig.commonCxxPath, 'ReactNativeFeatureFlags.cpp')]:
ReactNativeFeatureFlagsCPP(featureFlagsConfig),
[path.join(
generatorConfig.commonCxxPath,
'ReactNativeFeatureFlagsAccessor.h',
)]: ReactNativeFeatureFlagsAccessorH(featureFlagsConfig),
[path.join(
generatorConfig.commonCxxPath,
'ReactNativeFeatureFlagsAccessor.cpp',
)]: ReactNativeFeatureFlagsAccessorCPP(featureFlagsConfig),
[path.join(
generatorConfig.commonCxxPath,
'ReactNativeFeatureFlagsDefaults.h',
)]: ReactNativeFeatureFlagsDefaultsH(featureFlagsConfig),
[path.join(
generatorConfig.commonCxxPath,
'ReactNativeFeatureFlagsProvider.h',
)]: ReactNativeFeatureFlagsProviderH(featureFlagsConfig),
[path.join(commonCxxPath, 'ReactNativeFeatureFlags.h')]:
ReactNativeFeatureFlagsH(featureFlagDefinitions),
[path.join(commonCxxPath, 'ReactNativeFeatureFlags.cpp')]:
ReactNativeFeatureFlagsCPP(featureFlagDefinitions),
[path.join(commonCxxPath, 'ReactNativeFeatureFlagsAccessor.h')]:
ReactNativeFeatureFlagsAccessorH(featureFlagDefinitions),
[path.join(commonCxxPath, 'ReactNativeFeatureFlagsAccessor.cpp')]:
ReactNativeFeatureFlagsAccessorCPP(featureFlagDefinitions),
[path.join(commonCxxPath, 'ReactNativeFeatureFlagsDefaults.h')]:
ReactNativeFeatureFlagsDefaultsH(featureFlagDefinitions),
[path.join(commonCxxPath, 'ReactNativeFeatureFlagsProvider.h')]:
ReactNativeFeatureFlagsProviderH(featureFlagDefinitions),
};
};
}
+15 -27
View File
@@ -4,49 +4,37 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
const generateAndroidModules = require('./generateAndroidModules');
const generateCommonCxxModules = require('./generateCommonCxxModules');
const generateJavaScriptModules = require('./generateJavaScriptModules');
const fs = require('fs');
import type {GeneratorConfig, GeneratorOptions} from './types';
module.exports = function generateFiles(generatorConfig, generatorOptions) {
const userDefinedFeatureFlagsConfig = JSON.parse(
fs.readFileSync(generatorConfig.configPath, 'utf8'),
);
const featureFlagsConfig = Object.assign(
{jsOnly: {}, common: {}},
userDefinedFeatureFlagsConfig,
);
import generateAndroidModules from './generateAndroidModules';
import generateCommonCxxModules from './generateCommonCxxModules';
import generateJavaScriptModules from './generateJavaScriptModules';
import fs from 'fs';
export default function generateFiles(
generatorConfig: GeneratorConfig,
generatorOptions: GeneratorOptions,
): void {
fs.mkdirSync(generatorConfig.jsPath, {recursive: true});
fs.mkdirSync(generatorConfig.commonCxxPath, {recursive: true});
fs.mkdirSync(generatorConfig.commonNativeModuleCxxPath, {recursive: true});
fs.mkdirSync(generatorConfig.androidPath, {recursive: true});
fs.mkdirSync(generatorConfig.androidJniPath, {recursive: true});
const jsModules = generateJavaScriptModules(
generatorConfig,
featureFlagsConfig,
);
const jsModules = generateJavaScriptModules(generatorConfig);
const commonCxxModules = generateCommonCxxModules(
generatorConfig,
featureFlagsConfig,
);
const commonCxxModules = generateCommonCxxModules(generatorConfig);
const androidModules = generateAndroidModules(
generatorConfig,
featureFlagsConfig,
);
const androidModules = generateAndroidModules(generatorConfig);
const generatedFiles = {...jsModules, ...commonCxxModules, ...androidModules};
if (generatorOptions.verifyUnchanged) {
const existingModules = {};
const existingModules: {[string]: string} = {};
for (const moduleName of Object.keys(generatedFiles)) {
const existingModule = fs.readFileSync(moduleName, 'utf8');
existingModules[moduleName] = existingModule;
@@ -79,4 +67,4 @@ module.exports = function generateFiles(generatorConfig, generatorOptions) {
for (const [modulePath, moduleContents] of Object.entries(generatedFiles)) {
fs.writeFileSync(modulePath, moduleContents, 'utf8');
}
};
}
@@ -4,33 +4,32 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {GeneratorConfig, GeneratorResult} from './types';
const NativeReactNativeFeatureFlagsCPP = require('./templates/js/NativeReactNativeFeatureFlags.cpp-template');
const NativeReactNativeFeatureFlagsH = require('./templates/js/NativeReactNativeFeatureFlags.h-template');
const NativeReactNativeFeatureFlagsJS = require('./templates/js/NativeReactNativeFeatureFlags.js-template');
const ReactNativeFeatureFlagsJS = require('./templates/js/ReactNativeFeatureFlags.js-template');
const path = require('path');
import NativeReactNativeFeatureFlagsCPP from './templates/js/NativeReactNativeFeatureFlags.cpp-template';
import NativeReactNativeFeatureFlagsH from './templates/js/NativeReactNativeFeatureFlags.h-template';
import NativeReactNativeFeatureFlagsJS from './templates/js/NativeReactNativeFeatureFlags.js-template';
import ReactNativeFeatureFlagsJS from './templates/js/ReactNativeFeatureFlags.js-template';
import path from 'path';
export default function generateCommonCxxModules(
generatorConfig: GeneratorConfig,
): GeneratorResult {
const {jsPath, commonNativeModuleCxxPath, featureFlagDefinitions} =
generatorConfig;
module.exports = function generateCommonCxxModules(
generatorConfig,
featureFlagsConfig,
) {
return {
[path.join(generatorConfig.jsPath, 'ReactNativeFeatureFlags.js')]:
ReactNativeFeatureFlagsJS(featureFlagsConfig),
[path.join(generatorConfig.jsPath, 'NativeReactNativeFeatureFlags.js')]:
NativeReactNativeFeatureFlagsJS(featureFlagsConfig),
[path.join(
generatorConfig.commonNativeModuleCxxPath,
'NativeReactNativeFeatureFlags.h',
)]: NativeReactNativeFeatureFlagsH(featureFlagsConfig),
[path.join(
generatorConfig.commonNativeModuleCxxPath,
'NativeReactNativeFeatureFlags.cpp',
)]: NativeReactNativeFeatureFlagsCPP(featureFlagsConfig),
[path.join(jsPath, 'ReactNativeFeatureFlags.js')]:
ReactNativeFeatureFlagsJS(featureFlagDefinitions),
[path.join(jsPath, 'NativeReactNativeFeatureFlags.js')]:
NativeReactNativeFeatureFlagsJS(featureFlagDefinitions),
[path.join(commonNativeModuleCxxPath, 'NativeReactNativeFeatureFlags.h')]:
NativeReactNativeFeatureFlagsH(featureFlagDefinitions),
[path.join(commonNativeModuleCxxPath, 'NativeReactNativeFeatureFlags.cpp')]:
NativeReactNativeFeatureFlagsCPP(featureFlagDefinitions),
};
};
}
+14
View File
@@ -0,0 +1,14 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
if (require.main === module) {
require('../../../../scripts/build/babel-register').registerForMonorepo();
const update = require('./update').default;
update(process.argv.includes('--verify-unchanged'));
}
@@ -4,19 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
DO_NOT_MODIFY_COMMENT,
getCxxTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT, getCxxTypeFromDefaultValue} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -33,7 +31,7 @@ ${DO_NOT_MODIFY_COMMENT}
namespace facebook::react {
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
`${getCxxTypeFromDefaultValue(
@@ -62,7 +60,7 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"override", JReactNativeFeatureFlagsCxxInterop::override),
makeNativeMethod("dangerouslyReset", JReactNativeFeatureFlagsCxxInterop::dangerouslyReset),
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` makeNativeMethod(
@@ -75,3 +73,4 @@ ${Object.entries(config.common)
} // namespace facebook::react
`);
}
@@ -4,19 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
DO_NOT_MODIFY_COMMENT,
getCxxTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT, getCxxTypeFromDefaultValue} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -40,7 +38,7 @@ class JReactNativeFeatureFlagsCxxInterop
constexpr static auto kJavaDescriptor =
"Lcom/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop;";
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` static ${getCxxTypeFromDefaultValue(
@@ -62,3 +60,4 @@ ${Object.entries(config.common)
} // namespace facebook::react
`);
}
@@ -4,16 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {DO_NOT_MODIFY_COMMENT} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -35,7 +36,7 @@ object ReactNativeFeatureFlags {
private var accessorProvider: () -> ReactNativeFeatureFlagsAccessor = { ReactNativeFeatureFlagsCxxAccessor() }
private var accessor: ReactNativeFeatureFlagsAccessor = accessorProvider()
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` /**
@@ -90,3 +91,4 @@ ${Object.entries(config.common)
}
}
`);
}
@@ -4,19 +4,20 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
import {
DO_NOT_MODIFY_COMMENT,
getKotlinTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -30,7 +31,7 @@ ${DO_NOT_MODIFY_COMMENT}
package com.facebook.react.internal.featureflags
class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccessor {
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` private var ${flagName}Cache: ${getKotlinTypeFromDefaultValue(
@@ -39,7 +40,7 @@ ${Object.entries(config.common)
)
.join('\n')}
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) => ` override fun ${flagName}(): Boolean {
var cached = ${flagName}Cache
@@ -58,3 +59,4 @@ ${Object.entries(config.common)
override fun dangerouslyReset() = ReactNativeFeatureFlagsCxxInterop.dangerouslyReset()
}
`);
}
@@ -4,19 +4,20 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
import {
DO_NOT_MODIFY_COMMENT,
getKotlinTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -38,7 +39,7 @@ object ReactNativeFeatureFlagsCxxInterop {
SoLoader.loadLibrary("react_featureflagsjni")
}
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` @DoNotStrip @JvmStatic external fun ${flagName}(): ${getKotlinTypeFromDefaultValue(
@@ -52,3 +53,4 @@ ${Object.entries(config.common)
@DoNotStrip @JvmStatic external fun dangerouslyReset()
}
`);
}
@@ -4,19 +4,20 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
import {
DO_NOT_MODIFY_COMMENT,
getKotlinTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -33,7 +34,7 @@ open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvider {
// We could use JNI to get the defaults from C++,
// but that is more expensive than just duplicating the defaults here.
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` override fun ${flagName}(): ${getKotlinTypeFromDefaultValue(
@@ -43,3 +44,4 @@ ${Object.entries(config.common)
.join('\n\n')}
}
`);
}
@@ -4,19 +4,20 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
import {
DO_NOT_MODIFY_COMMENT,
getKotlinTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -34,7 +35,7 @@ class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAccessor {
private val accessedFeatureFlags = mutableSetOf<String>()
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` private var ${flagName}Cache: ${getKotlinTypeFromDefaultValue(
@@ -43,7 +44,7 @@ ${Object.entries(config.common)
)
.join('\n')}
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) => ` override fun ${flagName}(): Boolean {
var cached = ${flagName}Cache
@@ -72,3 +73,4 @@ ${Object.entries(config.common)
}
}
`);
}
@@ -4,19 +4,20 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
import {
DO_NOT_MODIFY_COMMENT,
getKotlinTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -33,7 +34,7 @@ import com.facebook.proguard.annotations.DoNotStrip
@DoNotStrip
interface ReactNativeFeatureFlagsProvider {
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` @DoNotStrip fun ${flagName}(): ${getKotlinTypeFromDefaultValue(
@@ -43,3 +44,4 @@ ${Object.entries(config.common)
.join('\n\n')}
}
`);
}
@@ -4,19 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
DO_NOT_MODIFY_COMMENT,
getCxxTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT, getCxxTypeFromDefaultValue} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -37,7 +35,7 @@ static jni::alias_ref<jni::JClass> getJClass() {
return jClass;
}
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
`${getCxxTypeFromDefaultValue(
@@ -52,3 +50,4 @@ ${Object.entries(config.common)
} // namespace facebook::react
`);
}
@@ -4,19 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
DO_NOT_MODIFY_COMMENT,
getCxxTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT, getCxxTypeFromDefaultValue} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -45,7 +43,7 @@ class ReactNativeFeatureFlagsProviderHolder
jni::alias_ref<jobject> javaProvider)
: javaProvider_(make_global(javaProvider)){};
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` ${getCxxTypeFromDefaultValue(
@@ -60,3 +58,4 @@ ${Object.entries(config.common)
} // namespace facebook::react
`);
}
@@ -4,19 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
DO_NOT_MODIFY_COMMENT,
getCxxTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT, getCxxTypeFromDefaultValue} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -31,7 +29,7 @@ ${DO_NOT_MODIFY_COMMENT}
namespace facebook::react {
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
`${getCxxTypeFromDefaultValue(
@@ -62,3 +60,4 @@ ReactNativeFeatureFlagsAccessor& ReactNativeFeatureFlags::getAccessor(
} // namespace facebook::react
`);
}
@@ -4,19 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
DO_NOT_MODIFY_COMMENT,
getCxxTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT, getCxxTypeFromDefaultValue} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -43,7 +41,7 @@ namespace facebook::react {
*/
class ReactNativeFeatureFlags {
public:
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` /**
@@ -95,3 +93,4 @@ ${Object.entries(config.common)
} // namespace facebook::react
`);
}
@@ -4,19 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
DO_NOT_MODIFY_COMMENT,
getCxxTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT, getCxxTypeFromDefaultValue} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -38,7 +36,7 @@ namespace facebook::react {
ReactNativeFeatureFlagsAccessor::ReactNativeFeatureFlagsAccessor()
: currentProvider_(std::make_unique<ReactNativeFeatureFlagsDefaults>()) {}
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig], flagPosition) =>
`${getCxxTypeFromDefaultValue(
@@ -98,3 +96,4 @@ void ReactNativeFeatureFlagsAccessor::ensureFlagsNotAccessed() {
} // namespace facebook::react
`);
}
@@ -4,19 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
DO_NOT_MODIFY_COMMENT,
getCxxTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT, getCxxTypeFromDefaultValue} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -41,7 +39,7 @@ class ReactNativeFeatureFlagsAccessor {
public:
ReactNativeFeatureFlagsAccessor();
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` ${getCxxTypeFromDefaultValue(flagConfig.defaultValue)} ${flagName}();`,
@@ -56,10 +54,10 @@ ${Object.entries(config.common)
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
std::array<std::atomic<const char*>, ${
Object.keys(config.common).length
Object.keys(definitions.common).length
}> accessedFeatureFlags_;
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` std::atomic<std::optional<${getCxxTypeFromDefaultValue(
@@ -71,3 +69,4 @@ ${Object.entries(config.common)
} // namespace facebook::react
`);
}
@@ -4,19 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
DO_NOT_MODIFY_COMMENT,
getCxxTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT, getCxxTypeFromDefaultValue} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -37,7 +35,7 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
public:
ReactNativeFeatureFlagsDefaults() = default;
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` ${getCxxTypeFromDefaultValue(
@@ -51,3 +49,4 @@ ${Object.entries(config.common)
} // namespace facebook::react
`);
}
@@ -4,19 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
DO_NOT_MODIFY_COMMENT,
getCxxTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT, getCxxTypeFromDefaultValue} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -35,7 +33,7 @@ class ReactNativeFeatureFlagsProvider {
public:
virtual ~ReactNativeFeatureFlagsProvider() = default;
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` virtual ${getCxxTypeFromDefaultValue(
@@ -47,3 +45,4 @@ ${Object.entries(config.common)
} // namespace facebook::react
`);
}
@@ -4,19 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
DO_NOT_MODIFY_COMMENT,
getCxxTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT, getCxxTypeFromDefaultValue} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -45,7 +43,7 @@ NativeReactNativeFeatureFlags::NativeReactNativeFeatureFlags(
std::shared_ptr<CallInvoker> jsInvoker)
: NativeReactNativeFeatureFlagsCxxSpec(std::move(jsInvoker)) {}
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
`${getCxxTypeFromDefaultValue(
@@ -59,3 +57,4 @@ ${Object.entries(config.common)
} // namespace facebook::react
`);
}
@@ -4,19 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {
DO_NOT_MODIFY_COMMENT,
getCxxTypeFromDefaultValue,
} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT, getCxxTypeFromDefaultValue} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/*
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -40,7 +38,7 @@ class NativeReactNativeFeatureFlags
public:
NativeReactNativeFeatureFlags(std::shared_ptr<CallInvoker> jsInvoker);
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` ${getCxxTypeFromDefaultValue(
@@ -52,3 +50,4 @@ ${Object.entries(config.common)
} // namespace facebook::react
`);
}
@@ -4,16 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {DO_NOT_MODIFY_COMMENT} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/**
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -30,7 +31,7 @@ import type {TurboModule} from '../../../Libraries/TurboModule/RCTExport';
import * as TurboModuleRegistry from '../../../Libraries/TurboModule/TurboModuleRegistry';
export interface Spec extends TurboModule {
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` +${flagName}?: () => ${typeof flagConfig.defaultValue};`,
@@ -44,3 +45,4 @@ const NativeReactNativeFeatureFlags: ?Spec = TurboModuleRegistry.get<Spec>(
export default NativeReactNativeFeatureFlags;
`);
}
@@ -4,16 +4,17 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {FeatureFlagDefinitions} from '../../types';
const {DO_NOT_MODIFY_COMMENT} = require('../../utils');
const signedsource = require('signedsource');
import {DO_NOT_MODIFY_COMMENT} from '../../utils';
import signedsource from 'signedsource';
module.exports = config =>
signedsource.signFile(`/**
export default function (definitions: FeatureFlagDefinitions): string {
return signedsource.signFile(`/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
@@ -33,7 +34,7 @@ import {
} from './ReactNativeFeatureFlagsBase';
export type ReactNativeFeatureFlagsJsOnly = {
${Object.entries(config.jsOnly)
${Object.entries(definitions.jsOnly)
.map(
([flagName, flagConfig]) =>
` ${flagName}: Getter<${typeof flagConfig.defaultValue}>,`,
@@ -45,7 +46,7 @@ export type ReactNativeFeatureFlagsJsOnlyOverrides = Partial<ReactNativeFeatureF
export type ReactNativeFeatureFlags = {
...ReactNativeFeatureFlagsJsOnly,
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
` ${flagName}: Getter<${typeof flagConfig.defaultValue}>,`,
@@ -53,7 +54,7 @@ ${Object.entries(config.common)
.join('\n')}
}
${Object.entries(config.jsOnly)
${Object.entries(definitions.jsOnly)
.map(
([flagName, flagConfig]) =>
`/**
@@ -65,7 +66,7 @@ export const ${flagName}: Getter<${typeof flagConfig.defaultValue}> = createJava
)
.join('\n\n')}
${Object.entries(config.common)
${Object.entries(definitions.common)
.map(
([flagName, flagConfig]) =>
`/**
@@ -83,3 +84,4 @@ export const ${flagName}: Getter<${typeof flagConfig.defaultValue}> = createNati
*/
export const override = setOverrides;
`);
}
+40
View File
@@ -0,0 +1,40 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
export type FeatureFlagValue = boolean | number | string;
export type FeatureFlagDefinitions = {
common: FeatureFlagList,
jsOnly: FeatureFlagList,
};
type FeatureFlagList = {
[flagName: string]: {
description: string,
defaultValue: FeatureFlagValue,
},
};
export type GeneratorConfig = {
featureFlagDefinitions: FeatureFlagDefinitions,
jsPath: string,
commonCxxPath: string,
commonNativeModuleCxxPath: string,
androidPath: string,
androidJniPath: string,
};
export type GeneratorOptions = {
verifyUnchanged: boolean,
};
export type GeneratorResult = {
[path: string]: string /* content */,
};
+12 -9
View File
@@ -4,18 +4,25 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
const generateFiles = require('./generateFiles');
const path = require('path');
import generateFiles from './generateFiles';
import fs from 'fs';
import path from 'path';
const REACT_NATIVE_PACKAGE_ROOT = path.join(__dirname, '..', '..');
function update() {
export default function update(verifyUnchanged: boolean): void {
generateFiles(
{
configPath: path.join(__dirname, 'ReactNativeFeatureFlags.json'),
featureFlagDefinitions: JSON.parse(
fs.readFileSync(
path.join(__dirname, 'ReactNativeFeatureFlags.json'),
'utf8',
),
),
jsPath: path.join(
REACT_NATIVE_PACKAGE_ROOT,
'src',
@@ -58,11 +65,7 @@ function update() {
),
},
{
verifyUnchanged: process.argv.includes('--verify-unchanged'),
verifyUnchanged,
},
);
}
if (require.main === module) {
update();
}
+33 -32
View File
@@ -4,41 +4,43 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
module.exports = {
getCxxTypeFromDefaultValue: defaultValue => {
switch (typeof defaultValue) {
case 'boolean':
return 'bool';
case 'number':
return 'int';
case 'string':
return 'std::string';
default:
throw new Error(
`Unsupported default value type: ${typeof defaultValue}`,
);
}
},
import type {FeatureFlagValue} from './types';
getKotlinTypeFromDefaultValue: defaultValue => {
switch (typeof defaultValue) {
case 'boolean':
return 'Boolean';
case 'number':
return 'Int';
case 'string':
return 'String';
default:
throw new Error(
`Unsupported default value type: ${typeof defaultValue}`,
);
}
},
export function getCxxTypeFromDefaultValue(
defaultValue: FeatureFlagValue,
): string {
switch (typeof defaultValue) {
case 'boolean':
return 'bool';
case 'number':
return 'int';
case 'string':
return 'std::string';
default:
throw new Error(`Unsupported default value type: ${typeof defaultValue}`);
}
}
DO_NOT_MODIFY_COMMENT: `/**
export function getKotlinTypeFromDefaultValue(
defaultValue: FeatureFlagValue,
): string {
switch (typeof defaultValue) {
case 'boolean':
return 'Boolean';
case 'number':
return 'Int';
case 'string':
return 'String';
default:
throw new Error(`Unsupported default value type: ${typeof defaultValue}`);
}
}
export const DO_NOT_MODIFY_COMMENT = `/**
* IMPORTANT: Do NOT modify this file directly.
*
* To change the definition of the flags, edit
@@ -46,5 +48,4 @@ module.exports = {
*
* To regenerate this code, run the following script from the repo root:
* yarn featureflags-update
*/`,
};
*/`;