@atlaskit/eslint-plugin-platform 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/index.js +10 -2
- package/dist/cjs/rules/ensure-feature-flag-prefix/index.js +83 -0
- package/dist/cjs/rules/ensure-feature-flag-registration/index.js +4 -42
- package/dist/cjs/rules/no-invalid-storybook-decorator-usage/index.js +38 -0
- package/dist/cjs/rules/util/registration-utils.js +47 -0
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/index.js +10 -2
- package/dist/es2019/rules/ensure-feature-flag-prefix/index.js +64 -0
- package/dist/es2019/rules/ensure-feature-flag-registration/index.js +1 -40
- package/dist/es2019/rules/no-invalid-storybook-decorator-usage/index.js +31 -0
- package/dist/es2019/rules/util/registration-utils.js +39 -0
- package/dist/es2019/version.json +1 -1
- package/dist/esm/index.js +10 -2
- package/dist/esm/rules/ensure-feature-flag-prefix/index.js +75 -0
- package/dist/esm/rules/ensure-feature-flag-registration/index.js +1 -40
- package/dist/esm/rules/no-invalid-storybook-decorator-usage/index.js +30 -0
- package/dist/esm/rules/util/registration-utils.js +39 -0
- package/dist/esm/version.json +1 -1
- package/dist/types/index.d.ts +6 -0
- package/dist/types/rules/ensure-feature-flag-prefix/index.d.ts +3 -0
- package/dist/types/rules/no-invalid-storybook-decorator-usage/index.d.ts +3 -0
- package/dist/types/rules/util/registration-utils.d.ts +19 -0
- package/package.json +1 -1
- package/report.api.md +9 -0
- package/src/index.tsx +9 -0
- package/src/rules/ensure-feature-flag-prefix/__tests__/unit/rule.test.tsx +53 -0
- package/src/rules/ensure-feature-flag-prefix/index.tsx +91 -0
- package/src/rules/ensure-feature-flag-registration/index.tsx +4 -60
- package/src/rules/no-invalid-storybook-decorator-usage/__tests__/unit/rule.test.tsx +18 -0
- package/src/rules/no-invalid-storybook-decorator-usage/index.tsx +40 -0
- package/src/rules/util/registration-utils.ts +58 -0
- package/tmp/api-report-tmp.d.ts +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @atlaskit/eslint-plugin-platform
|
|
2
2
|
|
|
3
|
+
## 0.1.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`e8a8808f299`](https://bitbucket.org/atlassian/atlassian-frontend/commits/e8a8808f299) - Add a new eslint rule that enforces prefixes on platform feature flags. Ignore existing usages.
|
|
8
|
+
|
|
9
|
+
## 0.1.5
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [`b47e48ad163`](https://bitbucket.org/atlassian/atlassian-frontend/commits/b47e48ad163) - Adds an eslint rule to confirm that storybooks only get passed an object - to ensure that codemods work correctly.
|
|
14
|
+
|
|
3
15
|
## 0.1.4
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/cjs/index.js
CHANGED
|
@@ -10,12 +10,16 @@ var _noPrePostInstalls = _interopRequireDefault(require("./rules/no-pre-post-ins
|
|
|
10
10
|
var _ensureTestRunnerArguments = _interopRequireDefault(require("./rules/ensure-test-runner-arguments"));
|
|
11
11
|
var _ensureTestRunnerNestedCount = _interopRequireDefault(require("./rules/ensure-test-runner-nested-count"));
|
|
12
12
|
var _noInvalidFeatureFlagUsage = _interopRequireDefault(require("./rules/no-invalid-feature-flag-usage"));
|
|
13
|
+
var _ensureFeatureFlagPrefix = _interopRequireDefault(require("./rules/ensure-feature-flag-prefix"));
|
|
14
|
+
var _noInvalidStorybookDecoratorUsage = _interopRequireDefault(require("./rules/no-invalid-storybook-decorator-usage"));
|
|
13
15
|
var rules = {
|
|
14
16
|
'ensure-feature-flag-registration': _ensureFeatureFlagRegistration.default,
|
|
17
|
+
'ensure-feature-flag-prefix': _ensureFeatureFlagPrefix.default,
|
|
15
18
|
'ensure-test-runner-arguments': _ensureTestRunnerArguments.default,
|
|
16
19
|
'ensure-test-runner-nested-count': _ensureTestRunnerNestedCount.default,
|
|
17
20
|
'no-invalid-feature-flag-usage': _noInvalidFeatureFlagUsage.default,
|
|
18
|
-
'no-pre-post-install-scripts': _noPrePostInstalls.default
|
|
21
|
+
'no-pre-post-install-scripts': _noPrePostInstalls.default,
|
|
22
|
+
'no-invalid-storybook-decorator-usage': _noInvalidStorybookDecoratorUsage.default
|
|
19
23
|
};
|
|
20
24
|
exports.rules = rules;
|
|
21
25
|
var configs = {
|
|
@@ -23,9 +27,13 @@ var configs = {
|
|
|
23
27
|
plugins: ['@atlaskit/platform'],
|
|
24
28
|
rules: {
|
|
25
29
|
'@atlaskit/platform/ensure-feature-flag-registration': 'error',
|
|
30
|
+
'@atlaskit/platform/ensure-feature-flag-prefix': ['error', {
|
|
31
|
+
allowedPrefixes: ['platform.']
|
|
32
|
+
}],
|
|
26
33
|
'@atlaskit/platform/ensure-test-runner-arguments': 'error',
|
|
27
34
|
'@atlaskit/platform/ensure-test-runner-nested-count': 'warn',
|
|
28
|
-
'@atlaskit/platform/no-invalid-feature-flag-usage': 'error'
|
|
35
|
+
'@atlaskit/platform/no-invalid-feature-flag-usage': 'error',
|
|
36
|
+
'@atlaskit/platform/no-invalid-storybook-decorator-usage': 'error'
|
|
29
37
|
}
|
|
30
38
|
}
|
|
31
39
|
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = void 0;
|
|
8
|
+
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
|
9
|
+
var _registrationUtils = require("../util/registration-utils");
|
|
10
|
+
var rule = {
|
|
11
|
+
meta: {
|
|
12
|
+
docs: {
|
|
13
|
+
recommended: false
|
|
14
|
+
},
|
|
15
|
+
type: 'problem',
|
|
16
|
+
messages: {
|
|
17
|
+
featureFlagIncorrectPrefix: "Please change your flag \"{{ featureFlag }}\" to have a valid prefix, options are [{{ allowedPrefixes }}]. See http://go/pff-eslint for details"
|
|
18
|
+
},
|
|
19
|
+
hasSuggestions: true,
|
|
20
|
+
schema: [{
|
|
21
|
+
type: 'object',
|
|
22
|
+
properties: {
|
|
23
|
+
allowedPrefixes: {
|
|
24
|
+
type: 'array',
|
|
25
|
+
items: [{
|
|
26
|
+
type: 'string'
|
|
27
|
+
}]
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
required: ['allowedPrefixes']
|
|
31
|
+
}]
|
|
32
|
+
},
|
|
33
|
+
create: function create(context) {
|
|
34
|
+
var _ref2, _context$options;
|
|
35
|
+
var _ref = (_ref2 = (_context$options = context.options) === null || _context$options === void 0 ? void 0 : _context$options[0]) !== null && _ref2 !== void 0 ? _ref2 : {},
|
|
36
|
+
allowedPrefixes = _ref.allowedPrefixes;
|
|
37
|
+
return Object.fromEntries(Object.keys(_registrationUtils.getterIdentifierToFlagTypeMap).map(function (getterIdentifier) {
|
|
38
|
+
return ["CallExpression[callee.name=/".concat(getterIdentifier, "/]"), function (node) {
|
|
39
|
+
// to make typescript happy
|
|
40
|
+
if (node.type === 'CallExpression') {
|
|
41
|
+
var args = node.arguments;
|
|
42
|
+
var filename = context.getFilename();
|
|
43
|
+
var _getMetadataForFilena = (0, _registrationUtils.getMetadataForFilename)(filename),
|
|
44
|
+
packageJson = _getMetadataForFilena.pkgJson;
|
|
45
|
+
var platformFeatureFlags = packageJson['platform-feature-flags'];
|
|
46
|
+
|
|
47
|
+
// existence of registration section is done in 'ensure-feature-flag-registration'
|
|
48
|
+
if (!platformFeatureFlags) {
|
|
49
|
+
return {};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// check registration section for valid feature flag prefixes.
|
|
53
|
+
// this checks all flags at every call site to ensure that new flags show errors as soon as possible.
|
|
54
|
+
var _loop = function _loop(featureFlag) {
|
|
55
|
+
if (!allowedPrefixes.some(function (prefix) {
|
|
56
|
+
return featureFlag.startsWith(prefix);
|
|
57
|
+
})) {
|
|
58
|
+
return {
|
|
59
|
+
v: context.report({
|
|
60
|
+
node: args[0],
|
|
61
|
+
messageId: 'featureFlagIncorrectPrefix',
|
|
62
|
+
data: {
|
|
63
|
+
allowedPrefixes: allowedPrefixes.map(function (p) {
|
|
64
|
+
return "".concat(p);
|
|
65
|
+
}).join(','),
|
|
66
|
+
featureFlag: featureFlag
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
for (var featureFlag in platformFeatureFlags) {
|
|
73
|
+
var _ret = _loop(featureFlag);
|
|
74
|
+
if ((0, _typeof2.default)(_ret) === "object") return _ret.v;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return {};
|
|
78
|
+
}];
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
var _default = rule;
|
|
83
|
+
exports.default = _default;
|
|
@@ -6,47 +6,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.default = void 0;
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
-
var
|
|
10
|
-
var _readPkgUp = _interopRequireDefault(require("read-pkg-up"));
|
|
11
|
-
var _path = _interopRequireDefault(require("path"));
|
|
12
|
-
var _fuse = _interopRequireDefault(require("fuse.js"));
|
|
9
|
+
var _registrationUtils = require("../util/registration-utils");
|
|
13
10
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
14
11
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
15
|
-
// defines a "getter" to "type" map, if more types are required for feature flags (like string) add it here!
|
|
16
|
-
// if you don't want to verify the type use `null` as the value
|
|
17
|
-
var getterIdentifierToFlagTypeMap = {
|
|
18
|
-
getBooleanFF: 'boolean',
|
|
19
|
-
ffTest: 'boolean'
|
|
20
|
-
};
|
|
21
|
-
// make sure we cache reading the package.json so we don't end up reading it for every instance of this rule.
|
|
22
|
-
var pkgJsonCache = new Map();
|
|
23
|
-
|
|
24
|
-
// get the ancestor package.json for a given file
|
|
25
|
-
var getMetadataForFilename = function getMetadataForFilename(filename) {
|
|
26
|
-
var splitFilename = filename.split(_path.default.sep);
|
|
27
|
-
for (var i = 0; i < splitFilename.length; i++) {
|
|
28
|
-
// attempt to search using the filename in the cache to see if we've read the package.json for a sibling file before
|
|
29
|
-
var searchPath = _path.default.join.apply(_path.default, (0, _toConsumableArray2.default)(splitFilename.splice(0, i)));
|
|
30
|
-
var cachedMetaData = pkgJsonCache.get(searchPath);
|
|
31
|
-
if (cachedMetaData) {
|
|
32
|
-
return cachedMetaData;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
var _ref = _readPkgUp.default.sync({
|
|
36
|
-
cwd: filename,
|
|
37
|
-
normalize: false
|
|
38
|
-
}),
|
|
39
|
-
packageJson = _ref.packageJson,
|
|
40
|
-
pkgJsonPath = _ref.path;
|
|
41
|
-
var pkgJson = packageJson;
|
|
42
|
-
var fuse = packageJson['platform-feature-flags'] == null ? null : new _fuse.default(Object.keys(pkgJson['platform-feature-flags']));
|
|
43
|
-
var metaData = {
|
|
44
|
-
pkgJson: pkgJson,
|
|
45
|
-
fuse: fuse
|
|
46
|
-
};
|
|
47
|
-
pkgJsonCache.set(pkgJsonPath, metaData);
|
|
48
|
-
return metaData;
|
|
49
|
-
};
|
|
50
12
|
var rule = {
|
|
51
13
|
meta: {
|
|
52
14
|
docs: {
|
|
@@ -62,13 +24,13 @@ var rule = {
|
|
|
62
24
|
hasSuggestions: true
|
|
63
25
|
},
|
|
64
26
|
create: function create(context) {
|
|
65
|
-
return Object.fromEntries(Object.keys(getterIdentifierToFlagTypeMap).map(function (getterIdentifier) {
|
|
27
|
+
return Object.fromEntries(Object.keys(_registrationUtils.getterIdentifierToFlagTypeMap).map(function (getterIdentifier) {
|
|
66
28
|
return ["CallExpression[callee.name=/".concat(getterIdentifier, "/]"), function (node) {
|
|
67
29
|
// to make typescript happy
|
|
68
30
|
if (node.type === 'CallExpression') {
|
|
69
31
|
var args = node.arguments;
|
|
70
32
|
var filename = context.getFilename();
|
|
71
|
-
var _getMetadataForFilena = getMetadataForFilename(filename),
|
|
33
|
+
var _getMetadataForFilena = (0, _registrationUtils.getMetadataForFilename)(filename),
|
|
72
34
|
packageJson = _getMetadataForFilena.pkgJson,
|
|
73
35
|
fuse = _getMetadataForFilena.fuse;
|
|
74
36
|
var platformFeatureFlags = packageJson['platform-feature-flags'];
|
|
@@ -81,7 +43,7 @@ var rule = {
|
|
|
81
43
|
if (args.length === 1 && args[0].type === 'Literal' && args[0].raw) {
|
|
82
44
|
var featureFlag = args[0].value;
|
|
83
45
|
var featureFlagRegistration = platformFeatureFlags[featureFlag];
|
|
84
|
-
var expectedType = getterIdentifierToFlagTypeMap[getterIdentifier];
|
|
46
|
+
var expectedType = _registrationUtils.getterIdentifierToFlagTypeMap[getterIdentifier];
|
|
85
47
|
|
|
86
48
|
// ensure the flag type matches what is registered
|
|
87
49
|
if (featureFlagRegistration != null && expectedType != null && (featureFlagRegistration === null || featureFlagRegistration === void 0 ? void 0 : featureFlagRegistration.type) !== expectedType) {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = void 0;
|
|
8
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
+
var STORYBOOK_DECORATOR_IDENTIFIER = 'withPlatformFeatureFlags';
|
|
10
|
+
var rule = {
|
|
11
|
+
meta: {
|
|
12
|
+
hasSuggestions: false,
|
|
13
|
+
docs: {
|
|
14
|
+
recommended: false
|
|
15
|
+
},
|
|
16
|
+
type: 'problem',
|
|
17
|
+
messages: {
|
|
18
|
+
onlyObjectExpression: 'Only object literals allowed in the storybook decorator! See http://go/pff-eslint for more details'
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
create: function create(context) {
|
|
22
|
+
return (0, _defineProperty2.default)({}, "CallExpression[callee.name=/".concat(STORYBOOK_DECORATOR_IDENTIFIER, "/]"), function CallExpressionCalleeName(node) {
|
|
23
|
+
// to make typescript happy
|
|
24
|
+
if (node.type === 'CallExpression') {
|
|
25
|
+
var args = node.arguments;
|
|
26
|
+
if (args.length === 1 && args[0].type !== 'ObjectExpression') {
|
|
27
|
+
return context.report({
|
|
28
|
+
node: node,
|
|
29
|
+
messageId: 'onlyObjectExpression'
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return {};
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var _default = rule;
|
|
38
|
+
exports.default = _default;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.getterIdentifierToFlagTypeMap = exports.getMetadataForFilename = void 0;
|
|
8
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
|
+
var _readPkgUp = _interopRequireDefault(require("read-pkg-up"));
|
|
10
|
+
var _path = _interopRequireDefault(require("path"));
|
|
11
|
+
var _fuse = _interopRequireDefault(require("fuse.js"));
|
|
12
|
+
// defines a "getter" to "type" map, if more types are required for feature flags (like string) add it here!
|
|
13
|
+
// if you don't want to verify the type use `null` as the value
|
|
14
|
+
var getterIdentifierToFlagTypeMap = {
|
|
15
|
+
getBooleanFF: 'boolean',
|
|
16
|
+
ffTest: 'boolean'
|
|
17
|
+
};
|
|
18
|
+
exports.getterIdentifierToFlagTypeMap = getterIdentifierToFlagTypeMap;
|
|
19
|
+
// make sure we cache reading the package.json so we don't end up reading it for every instance of this rule.
|
|
20
|
+
var pkgJsonCache = new Map();
|
|
21
|
+
// get the ancestor package.json for a given file
|
|
22
|
+
var getMetadataForFilename = function getMetadataForFilename(filename) {
|
|
23
|
+
var splitFilename = filename.split(_path.default.sep);
|
|
24
|
+
for (var i = 0; i < splitFilename.length; i++) {
|
|
25
|
+
// attempt to search using the filename in the cache to see if we've read the package.json for a sibling file before
|
|
26
|
+
var searchPath = _path.default.join.apply(_path.default, (0, _toConsumableArray2.default)(splitFilename.splice(0, i)));
|
|
27
|
+
var cachedMetaData = pkgJsonCache.get(searchPath);
|
|
28
|
+
if (cachedMetaData) {
|
|
29
|
+
return cachedMetaData;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
var _ref = _readPkgUp.default.sync({
|
|
33
|
+
cwd: filename,
|
|
34
|
+
normalize: false
|
|
35
|
+
}),
|
|
36
|
+
packageJson = _ref.packageJson,
|
|
37
|
+
pkgJsonPath = _ref.path;
|
|
38
|
+
var pkgJson = packageJson;
|
|
39
|
+
var fuse = packageJson['platform-feature-flags'] == null ? null : new _fuse.default(Object.keys(pkgJson['platform-feature-flags']));
|
|
40
|
+
var metaData = {
|
|
41
|
+
pkgJson: pkgJson,
|
|
42
|
+
fuse: fuse
|
|
43
|
+
};
|
|
44
|
+
pkgJsonCache.set(pkgJsonPath, metaData);
|
|
45
|
+
return metaData;
|
|
46
|
+
};
|
|
47
|
+
exports.getMetadataForFilename = getMetadataForFilename;
|
package/dist/cjs/version.json
CHANGED
package/dist/es2019/index.js
CHANGED
|
@@ -3,21 +3,29 @@ import noPreAndPostInstallScripts from './rules/no-pre-post-installs';
|
|
|
3
3
|
import ensureTestRunnerArguments from './rules/ensure-test-runner-arguments';
|
|
4
4
|
import ensureTestRunnerNestedCount from './rules/ensure-test-runner-nested-count';
|
|
5
5
|
import noInvalidFeatureFlagUsage from './rules/no-invalid-feature-flag-usage';
|
|
6
|
+
import ensureFeatureFlagPrefix from './rules/ensure-feature-flag-prefix';
|
|
7
|
+
import noInvalidStorybookDecoratorUsage from './rules/no-invalid-storybook-decorator-usage';
|
|
6
8
|
export const rules = {
|
|
7
9
|
'ensure-feature-flag-registration': ensureFeatureFlagRegistration,
|
|
10
|
+
'ensure-feature-flag-prefix': ensureFeatureFlagPrefix,
|
|
8
11
|
'ensure-test-runner-arguments': ensureTestRunnerArguments,
|
|
9
12
|
'ensure-test-runner-nested-count': ensureTestRunnerNestedCount,
|
|
10
13
|
'no-invalid-feature-flag-usage': noInvalidFeatureFlagUsage,
|
|
11
|
-
'no-pre-post-install-scripts': noPreAndPostInstallScripts
|
|
14
|
+
'no-pre-post-install-scripts': noPreAndPostInstallScripts,
|
|
15
|
+
'no-invalid-storybook-decorator-usage': noInvalidStorybookDecoratorUsage
|
|
12
16
|
};
|
|
13
17
|
export const configs = {
|
|
14
18
|
recommended: {
|
|
15
19
|
plugins: ['@atlaskit/platform'],
|
|
16
20
|
rules: {
|
|
17
21
|
'@atlaskit/platform/ensure-feature-flag-registration': 'error',
|
|
22
|
+
'@atlaskit/platform/ensure-feature-flag-prefix': ['error', {
|
|
23
|
+
allowedPrefixes: ['platform.']
|
|
24
|
+
}],
|
|
18
25
|
'@atlaskit/platform/ensure-test-runner-arguments': 'error',
|
|
19
26
|
'@atlaskit/platform/ensure-test-runner-nested-count': 'warn',
|
|
20
|
-
'@atlaskit/platform/no-invalid-feature-flag-usage': 'error'
|
|
27
|
+
'@atlaskit/platform/no-invalid-feature-flag-usage': 'error',
|
|
28
|
+
'@atlaskit/platform/no-invalid-storybook-decorator-usage': 'error'
|
|
21
29
|
}
|
|
22
30
|
}
|
|
23
31
|
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { getMetadataForFilename, getterIdentifierToFlagTypeMap } from '../util/registration-utils';
|
|
2
|
+
const rule = {
|
|
3
|
+
meta: {
|
|
4
|
+
docs: {
|
|
5
|
+
recommended: false
|
|
6
|
+
},
|
|
7
|
+
type: 'problem',
|
|
8
|
+
messages: {
|
|
9
|
+
featureFlagIncorrectPrefix: `Please change your flag "{{ featureFlag }}" to have a valid prefix, options are [{{ allowedPrefixes }}]. See http://go/pff-eslint for details`
|
|
10
|
+
},
|
|
11
|
+
hasSuggestions: true,
|
|
12
|
+
schema: [{
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
allowedPrefixes: {
|
|
16
|
+
type: 'array',
|
|
17
|
+
items: [{
|
|
18
|
+
type: 'string'
|
|
19
|
+
}]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
required: ['allowedPrefixes']
|
|
23
|
+
}]
|
|
24
|
+
},
|
|
25
|
+
create(context) {
|
|
26
|
+
var _ref, _context$options;
|
|
27
|
+
const {
|
|
28
|
+
allowedPrefixes
|
|
29
|
+
} = (_ref = (_context$options = context.options) === null || _context$options === void 0 ? void 0 : _context$options[0]) !== null && _ref !== void 0 ? _ref : {};
|
|
30
|
+
return Object.fromEntries(Object.keys(getterIdentifierToFlagTypeMap).map(getterIdentifier => [`CallExpression[callee.name=/${getterIdentifier}/]`, node => {
|
|
31
|
+
// to make typescript happy
|
|
32
|
+
if (node.type === 'CallExpression') {
|
|
33
|
+
const args = node.arguments;
|
|
34
|
+
const filename = context.getFilename();
|
|
35
|
+
const {
|
|
36
|
+
pkgJson: packageJson
|
|
37
|
+
} = getMetadataForFilename(filename);
|
|
38
|
+
const platformFeatureFlags = packageJson['platform-feature-flags'];
|
|
39
|
+
|
|
40
|
+
// existence of registration section is done in 'ensure-feature-flag-registration'
|
|
41
|
+
if (!platformFeatureFlags) {
|
|
42
|
+
return {};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// check registration section for valid feature flag prefixes.
|
|
46
|
+
// this checks all flags at every call site to ensure that new flags show errors as soon as possible.
|
|
47
|
+
for (const featureFlag in platformFeatureFlags) {
|
|
48
|
+
if (!allowedPrefixes.some(prefix => featureFlag.startsWith(prefix))) {
|
|
49
|
+
return context.report({
|
|
50
|
+
node: args[0],
|
|
51
|
+
messageId: 'featureFlagIncorrectPrefix',
|
|
52
|
+
data: {
|
|
53
|
+
allowedPrefixes: allowedPrefixes.map(p => `${p}`).join(','),
|
|
54
|
+
featureFlag
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return {};
|
|
61
|
+
}]));
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
export default rule;
|
|
@@ -1,43 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import Fuse from 'fuse.js';
|
|
4
|
-
|
|
5
|
-
// defines a "getter" to "type" map, if more types are required for feature flags (like string) add it here!
|
|
6
|
-
// if you don't want to verify the type use `null` as the value
|
|
7
|
-
const getterIdentifierToFlagTypeMap = {
|
|
8
|
-
getBooleanFF: 'boolean',
|
|
9
|
-
ffTest: 'boolean'
|
|
10
|
-
};
|
|
11
|
-
// make sure we cache reading the package.json so we don't end up reading it for every instance of this rule.
|
|
12
|
-
const pkgJsonCache = new Map();
|
|
13
|
-
|
|
14
|
-
// get the ancestor package.json for a given file
|
|
15
|
-
const getMetadataForFilename = filename => {
|
|
16
|
-
const splitFilename = filename.split(path.sep);
|
|
17
|
-
for (let i = 0; i < splitFilename.length; i++) {
|
|
18
|
-
// attempt to search using the filename in the cache to see if we've read the package.json for a sibling file before
|
|
19
|
-
const searchPath = path.join(...splitFilename.splice(0, i));
|
|
20
|
-
const cachedMetaData = pkgJsonCache.get(searchPath);
|
|
21
|
-
if (cachedMetaData) {
|
|
22
|
-
return cachedMetaData;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
const {
|
|
26
|
-
packageJson,
|
|
27
|
-
path: pkgJsonPath
|
|
28
|
-
} = readPkgUp.sync({
|
|
29
|
-
cwd: filename,
|
|
30
|
-
normalize: false
|
|
31
|
-
});
|
|
32
|
-
const pkgJson = packageJson;
|
|
33
|
-
const fuse = packageJson['platform-feature-flags'] == null ? null : new Fuse(Object.keys(pkgJson['platform-feature-flags']));
|
|
34
|
-
const metaData = {
|
|
35
|
-
pkgJson,
|
|
36
|
-
fuse
|
|
37
|
-
};
|
|
38
|
-
pkgJsonCache.set(pkgJsonPath, metaData);
|
|
39
|
-
return metaData;
|
|
40
|
-
};
|
|
1
|
+
import { getMetadataForFilename, getterIdentifierToFlagTypeMap } from '../util/registration-utils';
|
|
41
2
|
const rule = {
|
|
42
3
|
meta: {
|
|
43
4
|
docs: {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const STORYBOOK_DECORATOR_IDENTIFIER = 'withPlatformFeatureFlags';
|
|
2
|
+
const rule = {
|
|
3
|
+
meta: {
|
|
4
|
+
hasSuggestions: false,
|
|
5
|
+
docs: {
|
|
6
|
+
recommended: false
|
|
7
|
+
},
|
|
8
|
+
type: 'problem',
|
|
9
|
+
messages: {
|
|
10
|
+
onlyObjectExpression: 'Only object literals allowed in the storybook decorator! See http://go/pff-eslint for more details'
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
create(context) {
|
|
14
|
+
return {
|
|
15
|
+
[`CallExpression[callee.name=/${STORYBOOK_DECORATOR_IDENTIFIER}/]`]: node => {
|
|
16
|
+
// to make typescript happy
|
|
17
|
+
if (node.type === 'CallExpression') {
|
|
18
|
+
const args = node.arguments;
|
|
19
|
+
if (args.length === 1 && args[0].type !== 'ObjectExpression') {
|
|
20
|
+
return context.report({
|
|
21
|
+
node,
|
|
22
|
+
messageId: 'onlyObjectExpression'
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
export default rule;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import readPkgUp from 'read-pkg-up';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import Fuse from 'fuse.js';
|
|
4
|
+
|
|
5
|
+
// defines a "getter" to "type" map, if more types are required for feature flags (like string) add it here!
|
|
6
|
+
// if you don't want to verify the type use `null` as the value
|
|
7
|
+
export const getterIdentifierToFlagTypeMap = {
|
|
8
|
+
getBooleanFF: 'boolean',
|
|
9
|
+
ffTest: 'boolean'
|
|
10
|
+
};
|
|
11
|
+
// make sure we cache reading the package.json so we don't end up reading it for every instance of this rule.
|
|
12
|
+
const pkgJsonCache = new Map();
|
|
13
|
+
// get the ancestor package.json for a given file
|
|
14
|
+
export const getMetadataForFilename = filename => {
|
|
15
|
+
const splitFilename = filename.split(path.sep);
|
|
16
|
+
for (let i = 0; i < splitFilename.length; i++) {
|
|
17
|
+
// attempt to search using the filename in the cache to see if we've read the package.json for a sibling file before
|
|
18
|
+
const searchPath = path.join(...splitFilename.splice(0, i));
|
|
19
|
+
const cachedMetaData = pkgJsonCache.get(searchPath);
|
|
20
|
+
if (cachedMetaData) {
|
|
21
|
+
return cachedMetaData;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const {
|
|
25
|
+
packageJson,
|
|
26
|
+
path: pkgJsonPath
|
|
27
|
+
} = readPkgUp.sync({
|
|
28
|
+
cwd: filename,
|
|
29
|
+
normalize: false
|
|
30
|
+
});
|
|
31
|
+
const pkgJson = packageJson;
|
|
32
|
+
const fuse = packageJson['platform-feature-flags'] == null ? null : new Fuse(Object.keys(pkgJson['platform-feature-flags']));
|
|
33
|
+
const metaData = {
|
|
34
|
+
pkgJson,
|
|
35
|
+
fuse
|
|
36
|
+
};
|
|
37
|
+
pkgJsonCache.set(pkgJsonPath, metaData);
|
|
38
|
+
return metaData;
|
|
39
|
+
};
|
package/dist/es2019/version.json
CHANGED
package/dist/esm/index.js
CHANGED
|
@@ -3,21 +3,29 @@ import noPreAndPostInstallScripts from './rules/no-pre-post-installs';
|
|
|
3
3
|
import ensureTestRunnerArguments from './rules/ensure-test-runner-arguments';
|
|
4
4
|
import ensureTestRunnerNestedCount from './rules/ensure-test-runner-nested-count';
|
|
5
5
|
import noInvalidFeatureFlagUsage from './rules/no-invalid-feature-flag-usage';
|
|
6
|
+
import ensureFeatureFlagPrefix from './rules/ensure-feature-flag-prefix';
|
|
7
|
+
import noInvalidStorybookDecoratorUsage from './rules/no-invalid-storybook-decorator-usage';
|
|
6
8
|
export var rules = {
|
|
7
9
|
'ensure-feature-flag-registration': ensureFeatureFlagRegistration,
|
|
10
|
+
'ensure-feature-flag-prefix': ensureFeatureFlagPrefix,
|
|
8
11
|
'ensure-test-runner-arguments': ensureTestRunnerArguments,
|
|
9
12
|
'ensure-test-runner-nested-count': ensureTestRunnerNestedCount,
|
|
10
13
|
'no-invalid-feature-flag-usage': noInvalidFeatureFlagUsage,
|
|
11
|
-
'no-pre-post-install-scripts': noPreAndPostInstallScripts
|
|
14
|
+
'no-pre-post-install-scripts': noPreAndPostInstallScripts,
|
|
15
|
+
'no-invalid-storybook-decorator-usage': noInvalidStorybookDecoratorUsage
|
|
12
16
|
};
|
|
13
17
|
export var configs = {
|
|
14
18
|
recommended: {
|
|
15
19
|
plugins: ['@atlaskit/platform'],
|
|
16
20
|
rules: {
|
|
17
21
|
'@atlaskit/platform/ensure-feature-flag-registration': 'error',
|
|
22
|
+
'@atlaskit/platform/ensure-feature-flag-prefix': ['error', {
|
|
23
|
+
allowedPrefixes: ['platform.']
|
|
24
|
+
}],
|
|
18
25
|
'@atlaskit/platform/ensure-test-runner-arguments': 'error',
|
|
19
26
|
'@atlaskit/platform/ensure-test-runner-nested-count': 'warn',
|
|
20
|
-
'@atlaskit/platform/no-invalid-feature-flag-usage': 'error'
|
|
27
|
+
'@atlaskit/platform/no-invalid-feature-flag-usage': 'error',
|
|
28
|
+
'@atlaskit/platform/no-invalid-storybook-decorator-usage': 'error'
|
|
21
29
|
}
|
|
22
30
|
}
|
|
23
31
|
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import _typeof from "@babel/runtime/helpers/typeof";
|
|
2
|
+
import { getMetadataForFilename, getterIdentifierToFlagTypeMap } from '../util/registration-utils';
|
|
3
|
+
var rule = {
|
|
4
|
+
meta: {
|
|
5
|
+
docs: {
|
|
6
|
+
recommended: false
|
|
7
|
+
},
|
|
8
|
+
type: 'problem',
|
|
9
|
+
messages: {
|
|
10
|
+
featureFlagIncorrectPrefix: "Please change your flag \"{{ featureFlag }}\" to have a valid prefix, options are [{{ allowedPrefixes }}]. See http://go/pff-eslint for details"
|
|
11
|
+
},
|
|
12
|
+
hasSuggestions: true,
|
|
13
|
+
schema: [{
|
|
14
|
+
type: 'object',
|
|
15
|
+
properties: {
|
|
16
|
+
allowedPrefixes: {
|
|
17
|
+
type: 'array',
|
|
18
|
+
items: [{
|
|
19
|
+
type: 'string'
|
|
20
|
+
}]
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
required: ['allowedPrefixes']
|
|
24
|
+
}]
|
|
25
|
+
},
|
|
26
|
+
create: function create(context) {
|
|
27
|
+
var _ref2, _context$options;
|
|
28
|
+
var _ref = (_ref2 = (_context$options = context.options) === null || _context$options === void 0 ? void 0 : _context$options[0]) !== null && _ref2 !== void 0 ? _ref2 : {},
|
|
29
|
+
allowedPrefixes = _ref.allowedPrefixes;
|
|
30
|
+
return Object.fromEntries(Object.keys(getterIdentifierToFlagTypeMap).map(function (getterIdentifier) {
|
|
31
|
+
return ["CallExpression[callee.name=/".concat(getterIdentifier, "/]"), function (node) {
|
|
32
|
+
// to make typescript happy
|
|
33
|
+
if (node.type === 'CallExpression') {
|
|
34
|
+
var args = node.arguments;
|
|
35
|
+
var filename = context.getFilename();
|
|
36
|
+
var _getMetadataForFilena = getMetadataForFilename(filename),
|
|
37
|
+
packageJson = _getMetadataForFilena.pkgJson;
|
|
38
|
+
var platformFeatureFlags = packageJson['platform-feature-flags'];
|
|
39
|
+
|
|
40
|
+
// existence of registration section is done in 'ensure-feature-flag-registration'
|
|
41
|
+
if (!platformFeatureFlags) {
|
|
42
|
+
return {};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// check registration section for valid feature flag prefixes.
|
|
46
|
+
// this checks all flags at every call site to ensure that new flags show errors as soon as possible.
|
|
47
|
+
var _loop = function _loop(featureFlag) {
|
|
48
|
+
if (!allowedPrefixes.some(function (prefix) {
|
|
49
|
+
return featureFlag.startsWith(prefix);
|
|
50
|
+
})) {
|
|
51
|
+
return {
|
|
52
|
+
v: context.report({
|
|
53
|
+
node: args[0],
|
|
54
|
+
messageId: 'featureFlagIncorrectPrefix',
|
|
55
|
+
data: {
|
|
56
|
+
allowedPrefixes: allowedPrefixes.map(function (p) {
|
|
57
|
+
return "".concat(p);
|
|
58
|
+
}).join(','),
|
|
59
|
+
featureFlag: featureFlag
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
for (var featureFlag in platformFeatureFlags) {
|
|
66
|
+
var _ret = _loop(featureFlag);
|
|
67
|
+
if (_typeof(_ret) === "object") return _ret.v;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return {};
|
|
71
|
+
}];
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
export default rule;
|
|
@@ -1,46 +1,7 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
-
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
3
2
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
4
3
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
5
|
-
import
|
|
6
|
-
import path from 'path';
|
|
7
|
-
import Fuse from 'fuse.js';
|
|
8
|
-
|
|
9
|
-
// defines a "getter" to "type" map, if more types are required for feature flags (like string) add it here!
|
|
10
|
-
// if you don't want to verify the type use `null` as the value
|
|
11
|
-
var getterIdentifierToFlagTypeMap = {
|
|
12
|
-
getBooleanFF: 'boolean',
|
|
13
|
-
ffTest: 'boolean'
|
|
14
|
-
};
|
|
15
|
-
// make sure we cache reading the package.json so we don't end up reading it for every instance of this rule.
|
|
16
|
-
var pkgJsonCache = new Map();
|
|
17
|
-
|
|
18
|
-
// get the ancestor package.json for a given file
|
|
19
|
-
var getMetadataForFilename = function getMetadataForFilename(filename) {
|
|
20
|
-
var splitFilename = filename.split(path.sep);
|
|
21
|
-
for (var i = 0; i < splitFilename.length; i++) {
|
|
22
|
-
// attempt to search using the filename in the cache to see if we've read the package.json for a sibling file before
|
|
23
|
-
var searchPath = path.join.apply(path, _toConsumableArray(splitFilename.splice(0, i)));
|
|
24
|
-
var cachedMetaData = pkgJsonCache.get(searchPath);
|
|
25
|
-
if (cachedMetaData) {
|
|
26
|
-
return cachedMetaData;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
var _ref = readPkgUp.sync({
|
|
30
|
-
cwd: filename,
|
|
31
|
-
normalize: false
|
|
32
|
-
}),
|
|
33
|
-
packageJson = _ref.packageJson,
|
|
34
|
-
pkgJsonPath = _ref.path;
|
|
35
|
-
var pkgJson = packageJson;
|
|
36
|
-
var fuse = packageJson['platform-feature-flags'] == null ? null : new Fuse(Object.keys(pkgJson['platform-feature-flags']));
|
|
37
|
-
var metaData = {
|
|
38
|
-
pkgJson: pkgJson,
|
|
39
|
-
fuse: fuse
|
|
40
|
-
};
|
|
41
|
-
pkgJsonCache.set(pkgJsonPath, metaData);
|
|
42
|
-
return metaData;
|
|
43
|
-
};
|
|
4
|
+
import { getMetadataForFilename, getterIdentifierToFlagTypeMap } from '../util/registration-utils';
|
|
44
5
|
var rule = {
|
|
45
6
|
meta: {
|
|
46
7
|
docs: {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
var STORYBOOK_DECORATOR_IDENTIFIER = 'withPlatformFeatureFlags';
|
|
3
|
+
var rule = {
|
|
4
|
+
meta: {
|
|
5
|
+
hasSuggestions: false,
|
|
6
|
+
docs: {
|
|
7
|
+
recommended: false
|
|
8
|
+
},
|
|
9
|
+
type: 'problem',
|
|
10
|
+
messages: {
|
|
11
|
+
onlyObjectExpression: 'Only object literals allowed in the storybook decorator! See http://go/pff-eslint for more details'
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
create: function create(context) {
|
|
15
|
+
return _defineProperty({}, "CallExpression[callee.name=/".concat(STORYBOOK_DECORATOR_IDENTIFIER, "/]"), function CallExpressionCalleeName(node) {
|
|
16
|
+
// to make typescript happy
|
|
17
|
+
if (node.type === 'CallExpression') {
|
|
18
|
+
var args = node.arguments;
|
|
19
|
+
if (args.length === 1 && args[0].type !== 'ObjectExpression') {
|
|
20
|
+
return context.report({
|
|
21
|
+
node: node,
|
|
22
|
+
messageId: 'onlyObjectExpression'
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return {};
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
export default rule;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
|
+
import readPkgUp from 'read-pkg-up';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import Fuse from 'fuse.js';
|
|
5
|
+
|
|
6
|
+
// defines a "getter" to "type" map, if more types are required for feature flags (like string) add it here!
|
|
7
|
+
// if you don't want to verify the type use `null` as the value
|
|
8
|
+
export var getterIdentifierToFlagTypeMap = {
|
|
9
|
+
getBooleanFF: 'boolean',
|
|
10
|
+
ffTest: 'boolean'
|
|
11
|
+
};
|
|
12
|
+
// make sure we cache reading the package.json so we don't end up reading it for every instance of this rule.
|
|
13
|
+
var pkgJsonCache = new Map();
|
|
14
|
+
// get the ancestor package.json for a given file
|
|
15
|
+
export var getMetadataForFilename = function getMetadataForFilename(filename) {
|
|
16
|
+
var splitFilename = filename.split(path.sep);
|
|
17
|
+
for (var i = 0; i < splitFilename.length; i++) {
|
|
18
|
+
// attempt to search using the filename in the cache to see if we've read the package.json for a sibling file before
|
|
19
|
+
var searchPath = path.join.apply(path, _toConsumableArray(splitFilename.splice(0, i)));
|
|
20
|
+
var cachedMetaData = pkgJsonCache.get(searchPath);
|
|
21
|
+
if (cachedMetaData) {
|
|
22
|
+
return cachedMetaData;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
var _ref = readPkgUp.sync({
|
|
26
|
+
cwd: filename,
|
|
27
|
+
normalize: false
|
|
28
|
+
}),
|
|
29
|
+
packageJson = _ref.packageJson,
|
|
30
|
+
pkgJsonPath = _ref.path;
|
|
31
|
+
var pkgJson = packageJson;
|
|
32
|
+
var fuse = packageJson['platform-feature-flags'] == null ? null : new Fuse(Object.keys(pkgJson['platform-feature-flags']));
|
|
33
|
+
var metaData = {
|
|
34
|
+
pkgJson: pkgJson,
|
|
35
|
+
fuse: fuse
|
|
36
|
+
};
|
|
37
|
+
pkgJsonCache.set(pkgJsonPath, metaData);
|
|
38
|
+
return metaData;
|
|
39
|
+
};
|
package/dist/esm/version.json
CHANGED
package/dist/types/index.d.ts
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
import type { Linter } from 'eslint';
|
|
2
2
|
export declare const rules: {
|
|
3
3
|
'ensure-feature-flag-registration': import("eslint").Rule.RuleModule;
|
|
4
|
+
'ensure-feature-flag-prefix': import("eslint").Rule.RuleModule;
|
|
4
5
|
'ensure-test-runner-arguments': import("eslint").Rule.RuleModule;
|
|
5
6
|
'ensure-test-runner-nested-count': import("eslint").Rule.RuleModule;
|
|
6
7
|
'no-invalid-feature-flag-usage': import("eslint").Rule.RuleModule;
|
|
7
8
|
'no-pre-post-install-scripts': import("eslint").Rule.RuleModule;
|
|
9
|
+
'no-invalid-storybook-decorator-usage': import("eslint").Rule.RuleModule;
|
|
8
10
|
};
|
|
9
11
|
export declare const configs: {
|
|
10
12
|
recommended: {
|
|
11
13
|
plugins: string[];
|
|
12
14
|
rules: {
|
|
13
15
|
'@atlaskit/platform/ensure-feature-flag-registration': string;
|
|
16
|
+
'@atlaskit/platform/ensure-feature-flag-prefix': (string | {
|
|
17
|
+
allowedPrefixes: string[];
|
|
18
|
+
})[];
|
|
14
19
|
'@atlaskit/platform/ensure-test-runner-arguments': string;
|
|
15
20
|
'@atlaskit/platform/ensure-test-runner-nested-count': string;
|
|
16
21
|
'@atlaskit/platform/no-invalid-feature-flag-usage': string;
|
|
22
|
+
'@atlaskit/platform/no-invalid-storybook-decorator-usage': string;
|
|
17
23
|
};
|
|
18
24
|
};
|
|
19
25
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import readPkgUp from 'read-pkg-up';
|
|
2
|
+
import Fuse from 'fuse.js';
|
|
3
|
+
export declare const getterIdentifierToFlagTypeMap: {
|
|
4
|
+
readonly getBooleanFF: "boolean";
|
|
5
|
+
readonly ffTest: "boolean";
|
|
6
|
+
};
|
|
7
|
+
export declare type PlatformFeatureFlagRegistrationSection = {
|
|
8
|
+
[key: string]: {
|
|
9
|
+
type: typeof getterIdentifierToFlagTypeMap[keyof typeof getterIdentifierToFlagTypeMap];
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export declare type EnhancedPackageJson = readPkgUp.PackageJson & {
|
|
13
|
+
'platform-feature-flags'?: PlatformFeatureFlagRegistrationSection;
|
|
14
|
+
};
|
|
15
|
+
export declare type PkgJsonMetaData = {
|
|
16
|
+
pkgJson: EnhancedPackageJson;
|
|
17
|
+
fuse: Fuse<string> | null;
|
|
18
|
+
};
|
|
19
|
+
export declare const getMetadataForFilename: (filename: string) => PkgJsonMetaData;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/eslint-plugin-platform",
|
|
3
3
|
"description": "The essential plugin for use with Atlassian frontend platform tools",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.6",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"atlassian": {
|
|
7
7
|
"team": "UIP - Platform Integration Trust (PITa)",
|
package/report.api.md
CHANGED
|
@@ -24,9 +24,16 @@ export const configs: {
|
|
|
24
24
|
plugins: string[];
|
|
25
25
|
rules: {
|
|
26
26
|
'@atlaskit/platform/ensure-feature-flag-registration': string;
|
|
27
|
+
'@atlaskit/platform/ensure-feature-flag-prefix': (
|
|
28
|
+
| string
|
|
29
|
+
| {
|
|
30
|
+
allowedPrefixes: string[];
|
|
31
|
+
}
|
|
32
|
+
)[];
|
|
27
33
|
'@atlaskit/platform/ensure-test-runner-arguments': string;
|
|
28
34
|
'@atlaskit/platform/ensure-test-runner-nested-count': string;
|
|
29
35
|
'@atlaskit/platform/no-invalid-feature-flag-usage': string;
|
|
36
|
+
'@atlaskit/platform/no-invalid-storybook-decorator-usage': string;
|
|
30
37
|
};
|
|
31
38
|
};
|
|
32
39
|
};
|
|
@@ -39,10 +46,12 @@ export const processors: {
|
|
|
39
46
|
// @public (undocumented)
|
|
40
47
|
export const rules: {
|
|
41
48
|
'ensure-feature-flag-registration': Rule.RuleModule;
|
|
49
|
+
'ensure-feature-flag-prefix': Rule.RuleModule;
|
|
42
50
|
'ensure-test-runner-arguments': Rule.RuleModule;
|
|
43
51
|
'ensure-test-runner-nested-count': Rule.RuleModule;
|
|
44
52
|
'no-invalid-feature-flag-usage': Rule.RuleModule;
|
|
45
53
|
'no-pre-post-install-scripts': Rule.RuleModule;
|
|
54
|
+
'no-invalid-storybook-decorator-usage': Rule.RuleModule;
|
|
46
55
|
};
|
|
47
56
|
|
|
48
57
|
// (No @packageDocumentation comment for this package)
|
package/src/index.tsx
CHANGED
|
@@ -4,13 +4,17 @@ import noPreAndPostInstallScripts from './rules/no-pre-post-installs';
|
|
|
4
4
|
import ensureTestRunnerArguments from './rules/ensure-test-runner-arguments';
|
|
5
5
|
import ensureTestRunnerNestedCount from './rules/ensure-test-runner-nested-count';
|
|
6
6
|
import noInvalidFeatureFlagUsage from './rules/no-invalid-feature-flag-usage';
|
|
7
|
+
import ensureFeatureFlagPrefix from './rules/ensure-feature-flag-prefix';
|
|
8
|
+
import noInvalidStorybookDecoratorUsage from './rules/no-invalid-storybook-decorator-usage';
|
|
7
9
|
|
|
8
10
|
export const rules = {
|
|
9
11
|
'ensure-feature-flag-registration': ensureFeatureFlagRegistration,
|
|
12
|
+
'ensure-feature-flag-prefix': ensureFeatureFlagPrefix,
|
|
10
13
|
'ensure-test-runner-arguments': ensureTestRunnerArguments,
|
|
11
14
|
'ensure-test-runner-nested-count': ensureTestRunnerNestedCount,
|
|
12
15
|
'no-invalid-feature-flag-usage': noInvalidFeatureFlagUsage,
|
|
13
16
|
'no-pre-post-install-scripts': noPreAndPostInstallScripts,
|
|
17
|
+
'no-invalid-storybook-decorator-usage': noInvalidStorybookDecoratorUsage,
|
|
14
18
|
};
|
|
15
19
|
|
|
16
20
|
export const configs = {
|
|
@@ -18,9 +22,14 @@ export const configs = {
|
|
|
18
22
|
plugins: ['@atlaskit/platform'],
|
|
19
23
|
rules: {
|
|
20
24
|
'@atlaskit/platform/ensure-feature-flag-registration': 'error',
|
|
25
|
+
'@atlaskit/platform/ensure-feature-flag-prefix': [
|
|
26
|
+
'error',
|
|
27
|
+
{ allowedPrefixes: ['platform.'] },
|
|
28
|
+
],
|
|
21
29
|
'@atlaskit/platform/ensure-test-runner-arguments': 'error',
|
|
22
30
|
'@atlaskit/platform/ensure-test-runner-nested-count': 'warn',
|
|
23
31
|
'@atlaskit/platform/no-invalid-feature-flag-usage': 'error',
|
|
32
|
+
'@atlaskit/platform/no-invalid-storybook-decorator-usage': 'error',
|
|
24
33
|
},
|
|
25
34
|
},
|
|
26
35
|
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { tester } from '../../../../__tests__/utils/_tester';
|
|
2
|
+
import rule from '../../index';
|
|
3
|
+
import { PackageJson } from 'read-pkg-up';
|
|
4
|
+
|
|
5
|
+
let mockPath = 'test/package.json';
|
|
6
|
+
|
|
7
|
+
let mockPackageJson: PackageJson = {
|
|
8
|
+
'platform-feature-flags': {
|
|
9
|
+
'test-flag': {
|
|
10
|
+
type: 'boolean',
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
jest.mock('read-pkg-up', () => ({
|
|
15
|
+
sync: () => ({
|
|
16
|
+
path: mockPath,
|
|
17
|
+
packageJson: mockPackageJson,
|
|
18
|
+
}),
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
describe('with flag with invalid prefix', () => {
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
mockPath = 'test/package.json';
|
|
24
|
+
|
|
25
|
+
mockPackageJson = {
|
|
26
|
+
'platform-feature-flags': {
|
|
27
|
+
'no-prefix-flag': {
|
|
28
|
+
type: 'boolean',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// this isolates the invalid case so we can test the suggestion properly
|
|
35
|
+
tester.run('ensure-feature-flag-registration', rule, {
|
|
36
|
+
valid: [],
|
|
37
|
+
invalid: [
|
|
38
|
+
{
|
|
39
|
+
options: [{ allowedPrefixes: ['prefix'] }],
|
|
40
|
+
code: `ffTest('no-prefix-flag')`,
|
|
41
|
+
errors: [
|
|
42
|
+
{
|
|
43
|
+
messageId: 'featureFlagIncorrectPrefix',
|
|
44
|
+
data: {
|
|
45
|
+
featureFlag: 'no-prefix-flag',
|
|
46
|
+
allowedPrefixes: 'prefix',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { Rule } from 'eslint';
|
|
2
|
+
import {
|
|
3
|
+
getMetadataForFilename,
|
|
4
|
+
getterIdentifierToFlagTypeMap,
|
|
5
|
+
} from '../util/registration-utils';
|
|
6
|
+
|
|
7
|
+
type RuleOptions = {
|
|
8
|
+
allowedPrefixes: string[];
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const rule: Rule.RuleModule = {
|
|
12
|
+
meta: {
|
|
13
|
+
docs: {
|
|
14
|
+
recommended: false,
|
|
15
|
+
},
|
|
16
|
+
type: 'problem',
|
|
17
|
+
messages: {
|
|
18
|
+
featureFlagIncorrectPrefix: `Please change your flag "{{ featureFlag }}" to have a valid prefix, options are [{{ allowedPrefixes }}]. See http://go/pff-eslint for details`,
|
|
19
|
+
},
|
|
20
|
+
hasSuggestions: true,
|
|
21
|
+
schema: [
|
|
22
|
+
{
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
allowedPrefixes: {
|
|
26
|
+
type: 'array',
|
|
27
|
+
items: [
|
|
28
|
+
{
|
|
29
|
+
type: 'string',
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
required: ['allowedPrefixes'],
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
create(context) {
|
|
39
|
+
const { allowedPrefixes } = (context.options?.[0] as RuleOptions) ?? {};
|
|
40
|
+
|
|
41
|
+
return Object.fromEntries(
|
|
42
|
+
(
|
|
43
|
+
Object.keys(
|
|
44
|
+
getterIdentifierToFlagTypeMap,
|
|
45
|
+
) as (keyof typeof getterIdentifierToFlagTypeMap)[]
|
|
46
|
+
).map((getterIdentifier) => [
|
|
47
|
+
`CallExpression[callee.name=/${getterIdentifier}/]`,
|
|
48
|
+
(node: Rule.Node) => {
|
|
49
|
+
// to make typescript happy
|
|
50
|
+
if (node.type === 'CallExpression') {
|
|
51
|
+
const args = node.arguments;
|
|
52
|
+
|
|
53
|
+
const filename = context.getFilename();
|
|
54
|
+
const { pkgJson: packageJson } = getMetadataForFilename(filename);
|
|
55
|
+
const platformFeatureFlags = packageJson['platform-feature-flags'];
|
|
56
|
+
|
|
57
|
+
// existence of registration section is done in 'ensure-feature-flag-registration'
|
|
58
|
+
if (!platformFeatureFlags) {
|
|
59
|
+
return {};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// check registration section for valid feature flag prefixes.
|
|
63
|
+
// this checks all flags at every call site to ensure that new flags show errors as soon as possible.
|
|
64
|
+
for (const featureFlag in platformFeatureFlags) {
|
|
65
|
+
if (
|
|
66
|
+
!allowedPrefixes.some((prefix) =>
|
|
67
|
+
featureFlag.startsWith(prefix),
|
|
68
|
+
)
|
|
69
|
+
) {
|
|
70
|
+
return context.report({
|
|
71
|
+
node: args[0],
|
|
72
|
+
messageId: 'featureFlagIncorrectPrefix',
|
|
73
|
+
data: {
|
|
74
|
+
allowedPrefixes: allowedPrefixes
|
|
75
|
+
.map((p) => `${p}`)
|
|
76
|
+
.join(','),
|
|
77
|
+
featureFlag,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {};
|
|
85
|
+
},
|
|
86
|
+
]),
|
|
87
|
+
);
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export default rule;
|
|
@@ -1,64 +1,8 @@
|
|
|
1
1
|
import type { Rule } from 'eslint';
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// defines a "getter" to "type" map, if more types are required for feature flags (like string) add it here!
|
|
7
|
-
// if you don't want to verify the type use `null` as the value
|
|
8
|
-
const getterIdentifierToFlagTypeMap = {
|
|
9
|
-
getBooleanFF: 'boolean' as const,
|
|
10
|
-
ffTest: 'boolean' as const,
|
|
11
|
-
} as const;
|
|
12
|
-
|
|
13
|
-
type PlatformFeatureFlagRegistrationSection = {
|
|
14
|
-
[key: string]: {
|
|
15
|
-
// get the values of the object above
|
|
16
|
-
type: typeof getterIdentifierToFlagTypeMap[keyof typeof getterIdentifierToFlagTypeMap];
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
type EnhancedPackageJson = readPkgUp.PackageJson & {
|
|
21
|
-
'platform-feature-flags'?: PlatformFeatureFlagRegistrationSection;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
type PkgJsonMetaData = {
|
|
25
|
-
pkgJson: EnhancedPackageJson;
|
|
26
|
-
fuse: Fuse<string> | null;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
// make sure we cache reading the package.json so we don't end up reading it for every instance of this rule.
|
|
30
|
-
const pkgJsonCache = new Map<string, PkgJsonMetaData>();
|
|
31
|
-
|
|
32
|
-
// get the ancestor package.json for a given file
|
|
33
|
-
const getMetadataForFilename = (filename: string): PkgJsonMetaData => {
|
|
34
|
-
const splitFilename = filename.split(path.sep);
|
|
35
|
-
for (let i = 0; i < splitFilename.length; i++) {
|
|
36
|
-
// attempt to search using the filename in the cache to see if we've read the package.json for a sibling file before
|
|
37
|
-
const searchPath = path.join(...splitFilename.splice(0, i));
|
|
38
|
-
const cachedMetaData = pkgJsonCache.get(searchPath);
|
|
39
|
-
|
|
40
|
-
if (cachedMetaData) {
|
|
41
|
-
return cachedMetaData;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const { packageJson, path: pkgJsonPath } = readPkgUp.sync({
|
|
46
|
-
cwd: filename,
|
|
47
|
-
normalize: false,
|
|
48
|
-
})!;
|
|
49
|
-
|
|
50
|
-
const pkgJson = packageJson as EnhancedPackageJson;
|
|
51
|
-
|
|
52
|
-
const fuse =
|
|
53
|
-
packageJson['platform-feature-flags'] == null
|
|
54
|
-
? null
|
|
55
|
-
: new Fuse(Object.keys(pkgJson['platform-feature-flags']!));
|
|
56
|
-
|
|
57
|
-
const metaData = { pkgJson, fuse };
|
|
58
|
-
|
|
59
|
-
pkgJsonCache.set(pkgJsonPath, metaData);
|
|
60
|
-
return metaData;
|
|
61
|
-
};
|
|
2
|
+
import {
|
|
3
|
+
getMetadataForFilename,
|
|
4
|
+
getterIdentifierToFlagTypeMap,
|
|
5
|
+
} from '../util/registration-utils';
|
|
62
6
|
|
|
63
7
|
const rule: Rule.RuleModule = {
|
|
64
8
|
meta: {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { tester } from '../../../../__tests__/utils/_tester';
|
|
2
|
+
import rule from '../../index';
|
|
3
|
+
|
|
4
|
+
describe('no-invalid-storybook-decorator-usage tests', () => {
|
|
5
|
+
tester.run('no-invalid-storybook-decorator-usage', rule, {
|
|
6
|
+
valid: [
|
|
7
|
+
{
|
|
8
|
+
code: `withPlatformFeatureFlags({})(<SampleComponent/>)`,
|
|
9
|
+
},
|
|
10
|
+
],
|
|
11
|
+
invalid: [
|
|
12
|
+
{
|
|
13
|
+
code: `const flags = {'uip.sample.color': true}; withPlatformFeatureFlags(flags)(<SampleComponent/>)`,
|
|
14
|
+
errors: [{ messageId: 'onlyObjectExpression' }],
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Rule } from 'eslint';
|
|
2
|
+
|
|
3
|
+
const STORYBOOK_DECORATOR_IDENTIFIER = 'withPlatformFeatureFlags' as const;
|
|
4
|
+
|
|
5
|
+
const rule: Rule.RuleModule = {
|
|
6
|
+
meta: {
|
|
7
|
+
hasSuggestions: false,
|
|
8
|
+
docs: {
|
|
9
|
+
recommended: false,
|
|
10
|
+
},
|
|
11
|
+
type: 'problem',
|
|
12
|
+
messages: {
|
|
13
|
+
onlyObjectExpression:
|
|
14
|
+
'Only object literals allowed in the storybook decorator! See http://go/pff-eslint for more details',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
create(context) {
|
|
18
|
+
return {
|
|
19
|
+
[`CallExpression[callee.name=/${STORYBOOK_DECORATOR_IDENTIFIER}/]`]: (
|
|
20
|
+
node: Rule.Node,
|
|
21
|
+
) => {
|
|
22
|
+
// to make typescript happy
|
|
23
|
+
if (node.type === 'CallExpression') {
|
|
24
|
+
const args = node.arguments;
|
|
25
|
+
|
|
26
|
+
if (args.length === 1 && args[0].type !== 'ObjectExpression') {
|
|
27
|
+
return context.report({
|
|
28
|
+
node,
|
|
29
|
+
messageId: 'onlyObjectExpression',
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {};
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default rule;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import readPkgUp from 'read-pkg-up';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import Fuse from 'fuse.js';
|
|
4
|
+
|
|
5
|
+
// defines a "getter" to "type" map, if more types are required for feature flags (like string) add it here!
|
|
6
|
+
// if you don't want to verify the type use `null` as the value
|
|
7
|
+
export const getterIdentifierToFlagTypeMap = {
|
|
8
|
+
getBooleanFF: 'boolean' as const,
|
|
9
|
+
ffTest: 'boolean' as const,
|
|
10
|
+
} as const;
|
|
11
|
+
|
|
12
|
+
export type PlatformFeatureFlagRegistrationSection = {
|
|
13
|
+
[key: string]: {
|
|
14
|
+
// get the values of the object above
|
|
15
|
+
type: typeof getterIdentifierToFlagTypeMap[keyof typeof getterIdentifierToFlagTypeMap];
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type EnhancedPackageJson = readPkgUp.PackageJson & {
|
|
20
|
+
'platform-feature-flags'?: PlatformFeatureFlagRegistrationSection;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type PkgJsonMetaData = {
|
|
24
|
+
pkgJson: EnhancedPackageJson;
|
|
25
|
+
fuse: Fuse<string> | null;
|
|
26
|
+
};
|
|
27
|
+
// make sure we cache reading the package.json so we don't end up reading it for every instance of this rule.
|
|
28
|
+
const pkgJsonCache = new Map<string, PkgJsonMetaData>();
|
|
29
|
+
// get the ancestor package.json for a given file
|
|
30
|
+
export const getMetadataForFilename = (filename: string): PkgJsonMetaData => {
|
|
31
|
+
const splitFilename = filename.split(path.sep);
|
|
32
|
+
for (let i = 0; i < splitFilename.length; i++) {
|
|
33
|
+
// attempt to search using the filename in the cache to see if we've read the package.json for a sibling file before
|
|
34
|
+
const searchPath = path.join(...splitFilename.splice(0, i));
|
|
35
|
+
const cachedMetaData = pkgJsonCache.get(searchPath);
|
|
36
|
+
|
|
37
|
+
if (cachedMetaData) {
|
|
38
|
+
return cachedMetaData;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const { packageJson, path: pkgJsonPath } = readPkgUp.sync({
|
|
43
|
+
cwd: filename,
|
|
44
|
+
normalize: false,
|
|
45
|
+
})!;
|
|
46
|
+
|
|
47
|
+
const pkgJson = packageJson as EnhancedPackageJson;
|
|
48
|
+
|
|
49
|
+
const fuse =
|
|
50
|
+
packageJson['platform-feature-flags'] == null
|
|
51
|
+
? null
|
|
52
|
+
: new Fuse(Object.keys(pkgJson['platform-feature-flags']!));
|
|
53
|
+
|
|
54
|
+
const metaData = { pkgJson, fuse };
|
|
55
|
+
|
|
56
|
+
pkgJsonCache.set(pkgJsonPath, metaData);
|
|
57
|
+
return metaData;
|
|
58
|
+
};
|
package/tmp/api-report-tmp.d.ts
CHANGED
|
@@ -13,9 +13,13 @@ export const configs: {
|
|
|
13
13
|
plugins: string[];
|
|
14
14
|
rules: {
|
|
15
15
|
'@atlaskit/platform/ensure-feature-flag-registration': string;
|
|
16
|
+
'@atlaskit/platform/ensure-feature-flag-prefix': (string | {
|
|
17
|
+
allowedPrefixes: string[];
|
|
18
|
+
})[];
|
|
16
19
|
'@atlaskit/platform/ensure-test-runner-arguments': string;
|
|
17
20
|
'@atlaskit/platform/ensure-test-runner-nested-count': string;
|
|
18
21
|
'@atlaskit/platform/no-invalid-feature-flag-usage': string;
|
|
22
|
+
'@atlaskit/platform/no-invalid-storybook-decorator-usage': string;
|
|
19
23
|
};
|
|
20
24
|
};
|
|
21
25
|
};
|
|
@@ -28,10 +32,12 @@ export const processors: {
|
|
|
28
32
|
// @public (undocumented)
|
|
29
33
|
export const rules: {
|
|
30
34
|
'ensure-feature-flag-registration': Rule.RuleModule;
|
|
35
|
+
'ensure-feature-flag-prefix': Rule.RuleModule;
|
|
31
36
|
'ensure-test-runner-arguments': Rule.RuleModule;
|
|
32
37
|
'ensure-test-runner-nested-count': Rule.RuleModule;
|
|
33
38
|
'no-invalid-feature-flag-usage': Rule.RuleModule;
|
|
34
39
|
'no-pre-post-install-scripts': Rule.RuleModule;
|
|
40
|
+
'no-invalid-storybook-decorator-usage': Rule.RuleModule;
|
|
35
41
|
};
|
|
36
42
|
|
|
37
43
|
// (No @packageDocumentation comment for this package)
|