Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@atlaspack/feature-flags

Package Overview
Dependencies
Maintainers
0
Versions
258
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@atlaspack/feature-flags - npm Package Compare versions

Comparing version 2.12.1-dev.3401 to 2.12.1-dev.3443

39

lib/index.js

@@ -8,2 +8,3 @@ "use strict";

exports.getFeatureFlag = getFeatureFlag;
exports.runWithConsistencyCheck = runWithConsistencyCheck;
exports.setFeatureFlags = setFeatureFlags;

@@ -13,2 +14,3 @@ // We need to do these gymnastics as we don't want flow-to-ts to touch DEFAULT_FEATURE_FLAGS,

const DEFAULT_FEATURE_FLAGS = exports.DEFAULT_FEATURE_FLAGS = {
exampleConsistencyCheckFeature: 'OLD',
exampleFeature: false,

@@ -18,3 +20,6 @@ atlaspackV3: false,

importRetry: false,
ownedResolverStructures: false
fixQuadraticCacheInvalidation: 'OLD',
fastOptimizeInlineRequires: false,
useLmdbJsLite: false,
conditionalBundlingApi: false
};

@@ -28,3 +33,33 @@ let featureFlagValues = {

function getFeatureFlag(flagName) {
return featureFlagValues[flagName];
const value = featureFlagValues[flagName];
return value === true || value === 'NEW';
}
/**
* Run a function with a consistency check.
*/
function runWithConsistencyCheck(flag, oldFn, newFn, diffFn, report) {
const value = featureFlagValues[flag];
if (!value || value === false || value === 'OLD') {
return oldFn();
}
if (value === true || value === 'NEW') {
return newFn();
}
const oldStartTime = performance.now();
const oldResult = oldFn();
const oldExecutionTimeMs = performance.now() - oldStartTime;
const newStartTime = performance.now();
const newResult = newFn();
const newExecutionTimeMs = performance.now() - newStartTime;
const diff = diffFn(oldResult, newResult);
report({
isDifferent: diff.isDifferent,
oldExecutionTimeMs,
newExecutionTimeMs,
custom: diff.custom
}, oldResult, newResult);
if (value === 'NEW_AND_CHECK') {
return newResult;
}
return oldResult;
}
export type FeatureFlags = {
// This feature flag mostly exists to test the feature flag system, and doesn't have any build/runtime effect
readonly exampleFeature: boolean;
readonly exampleConsistencyCheckFeature: ConsistencyCheckFeatureFlagValue;

@@ -21,5 +22,23 @@ /**

/**
* Enable resolver refactor into owned data structures.
* Enable Rust based LMDB wrapper library
*/
ownedResolverStructures: boolean;
useLmdbJsLite: boolean;
/**
* Fixes quadratic cache invalidation issue
*/
fixQuadraticCacheInvalidation: ConsistencyCheckFeatureFlagValue;
/**
* Enable rust based inline requires optimization
*/
fastOptimizeInlineRequires: boolean;
/**
* Enables an experimental "conditional bundling" API - this allows the use of `importCond` syntax
* in order to have (consumer) feature flag driven bundling. This feature is very experimental,
* and requires server-side support.
*/
conditionalBundlingApi: boolean;
};
export type ConsistencyCheckFeatureFlagValue = "NEW" | "OLD" | "NEW_AND_CHECK" | "OLD_AND_CHECK";

6

package.json
{
"name": "@atlaspack/feature-flags",
"version": "2.12.1-dev.3401+b483af77f",
"version": "2.12.1-dev.3443+d1170cfc7",
"description": "Provides internal feature-flags for the atlaspack codebase.",
"license": "MIT",
"license": "(MIT OR Apache-2.0)",
"publishConfig": {

@@ -23,3 +23,3 @@ "access": "public"

},
"gitHead": "b483af77f02d1258c8dad156e097b94f83671d8e"
"gitHead": "d1170cfc79beb290b2a066f472f68f71f7d7cb23"
}

@@ -9,2 +9,3 @@ // @flow strict

export const DEFAULT_FEATURE_FLAGS: FeatureFlags = {
exampleConsistencyCheckFeature: 'OLD',
exampleFeature: false,

@@ -14,3 +15,6 @@ atlaspackV3: false,

importRetry: false,
ownedResolverStructures: false,
fixQuadraticCacheInvalidation: 'OLD',
fastOptimizeInlineRequires: false,
useLmdbJsLite: false,
conditionalBundlingApi: false,
};

@@ -25,3 +29,69 @@

export function getFeatureFlag(flagName: $Keys<FeatureFlags>): boolean {
return featureFlagValues[flagName];
const value = featureFlagValues[flagName];
return value === true || value === 'NEW';
}
export type DiffResult<CustomDiagnostic> = {|
isDifferent: boolean,
custom: CustomDiagnostic,
|};
export type Diagnostic<CustomDiagnostic> = {|
isDifferent: boolean,
oldExecutionTimeMs: number,
newExecutionTimeMs: number,
custom: CustomDiagnostic,
|};
/**
* Run a function with a consistency check.
*/
export function runWithConsistencyCheck<Result, CustomDiagnostic>(
flag: string,
oldFn: () => Result,
newFn: () => Result,
diffFn: (
oldResult: Result,
newResult: Result,
) => DiffResult<CustomDiagnostic>,
report: (
diagnostic: Diagnostic<CustomDiagnostic>,
oldResult: Result,
newResult: Result,
) => void,
): Result {
const value = featureFlagValues[flag];
if (!value || value === false || value === 'OLD') {
return oldFn();
}
if (value === true || value === 'NEW') {
return newFn();
}
const oldStartTime = performance.now();
const oldResult = oldFn();
const oldExecutionTimeMs = performance.now() - oldStartTime;
const newStartTime = performance.now();
const newResult = newFn();
const newExecutionTimeMs = performance.now() - newStartTime;
const diff = diffFn(oldResult, newResult);
report(
{
isDifferent: diff.isDifferent,
oldExecutionTimeMs,
newExecutionTimeMs,
custom: diff.custom,
},
oldResult,
newResult,
);
if (value === 'NEW_AND_CHECK') {
return newResult;
}
return oldResult;
}

@@ -6,2 +6,3 @@ // @flow strict

+exampleFeature: boolean,
+exampleConsistencyCheckFeature: ConsistencyCheckFeatureFlagValue,
/**

@@ -20,5 +21,25 @@ * Rust backed requests

/**
* Enable resolver refactor into owned data structures.
* Enable Rust based LMDB wrapper library
*/
ownedResolverStructures: boolean,
useLmdbJsLite: boolean,
/**
* Fixes quadratic cache invalidation issue
*/
fixQuadraticCacheInvalidation: ConsistencyCheckFeatureFlagValue,
/**
* Enable rust based inline requires optimization
*/
fastOptimizeInlineRequires: boolean,
/**
* Enables an experimental "conditional bundling" API - this allows the use of `importCond` syntax
* in order to have (consumer) feature flag driven bundling. This feature is very experimental,
* and requires server-side support.
*/
conditionalBundlingApi: boolean,
|};
export type ConsistencyCheckFeatureFlagValue =
| 'NEW'
| 'OLD'
| 'NEW_AND_CHECK'
| 'OLD_AND_CHECK';
// @flow strict
import assert from 'assert';
import {getFeatureFlag, DEFAULT_FEATURE_FLAGS, setFeatureFlags} from '../src';
import {
getFeatureFlag,
DEFAULT_FEATURE_FLAGS,
setFeatureFlags,
runWithConsistencyCheck,
} from '../src';
import sinon from 'sinon';

@@ -21,2 +27,80 @@ describe('feature-flag test', () => {

});
describe('consistency checks', () => {
it('runs the old function if the flag is off', () => {
setFeatureFlags({
...DEFAULT_FEATURE_FLAGS,
exampleConsistencyCheckFeature: 'OLD',
});
const result = runWithConsistencyCheck(
'exampleConsistencyCheckFeature',
() => 'old',
() => 'new',
sinon.spy(),
sinon.spy(),
);
assert.equal(result, 'old');
});
it('runs the new function if the flag is on', () => {
setFeatureFlags({
...DEFAULT_FEATURE_FLAGS,
exampleConsistencyCheckFeature: 'NEW',
});
const result = runWithConsistencyCheck(
'exampleConsistencyCheckFeature',
() => 'old',
() => 'new',
sinon.spy(),
sinon.spy(),
);
assert.equal(result, 'new');
});
it('diffs old and new values if there is a diff value', () => {
setFeatureFlags({
...DEFAULT_FEATURE_FLAGS,
exampleConsistencyCheckFeature: 'OLD_AND_CHECK',
});
const reportSpy = sinon.spy();
const result = runWithConsistencyCheck(
'exampleConsistencyCheckFeature',
() => 'old',
() => 'new',
() => ({isDifferent: false, custom: 'diff'}),
reportSpy,
);
assert.equal(result, 'old');
sinon.assert.calledWith(reportSpy, {
isDifferent: false,
oldExecutionTimeMs: sinon.match.number,
newExecutionTimeMs: sinon.match.number,
custom: 'diff',
});
});
it('diffs old and new values if there is a diff new value', () => {
setFeatureFlags({
...DEFAULT_FEATURE_FLAGS,
exampleConsistencyCheckFeature: 'NEW_AND_CHECK',
});
const reportSpy = sinon.spy();
const result = runWithConsistencyCheck(
'exampleConsistencyCheckFeature',
() => 'old',
() => 'new',
() => ({isDifferent: true, custom: 'diff'}),
reportSpy,
);
assert.equal(result, 'new');
sinon.assert.calledWith(reportSpy, {
isDifferent: true,
oldExecutionTimeMs: sinon.match.number,
newExecutionTimeMs: sinon.match.number,
custom: 'diff',
});
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc