@amazon-devices/eslint-plugin-kepler 0.1.8 → 0.1.11

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.
Files changed (28) hide show
  1. package/README.md +13 -11
  2. package/dist/formatters/default.js +8 -189
  3. package/dist/formatters/default.js.LICENSE.txt +1 -0
  4. package/dist/index.js +1 -107
  5. package/package.json +1 -1
  6. package/dist/formatters/KeplerReport.js +0 -40
  7. package/dist/metrics/Metrics.js +0 -69
  8. package/dist/metrics/TelemetryService.js +0 -48
  9. package/dist/rules/apiPrivileges/ApiPrivilegeStateCheck.js +0 -102
  10. package/dist/rules/apiPrivileges/ApiPrivilegesCheck.js +0 -67
  11. package/dist/rules/apiPrivileges/apiPermissionsNeeded.js +0 -58
  12. package/dist/rules/apiPrivileges/manifestHelper.js +0 -44
  13. package/dist/rules/backwardCompatibility/BackwardCompatibility.js +0 -119
  14. package/dist/rules/backwardCompatibility/BackwardCompatibilityCopyOnPack.js +0 -101
  15. package/dist/rules/backwardCompatibility/BackwardCompatibilitySysconfCheck.js +0 -73
  16. package/dist/rules/performance/Animated.js +0 -64
  17. package/dist/rules/performance/CheckSubscription.js +0 -150
  18. package/dist/rules/performance/DetectSplashScreen.js +0 -62
  19. package/dist/rules/performance/DetectUseReportFullyDrawn.js +0 -50
  20. package/dist/rules/performance/FlatList.js +0 -39
  21. package/dist/rules/systemDistributedLibs/SDLPackageVersionCheck.js +0 -136
  22. package/dist/rules/systemDistributedLibs/SDLPackageVersionCheckImports.js +0 -58
  23. package/dist/rules/systemDistributedLibs/sdlHelpers.js +0 -232
  24. package/dist/rules/systemDistributedLibs/sdlRuleMessages.js +0 -25
  25. package/dist/state/KeplerESLintPluginStateManager.js +0 -94
  26. package/dist/utils/Constants.js +0 -40
  27. package/dist/utils/PackageUtils.js +0 -50
  28. package/dist/utils/RuleUtils.js +0 -128
@@ -1,58 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.API_PRIV_NEEDED = void 0;
7
- // Copyright 2025 Amazon.com, Inc. or its affiliates. All rights reserved.
8
- // AMAZON PROPRIETARY/CONFIDENTIAL
9
- // You may not use this file except in compliance with the terms and conditions
10
- // set forth in the accompanying LICENSE.TXT file.
11
- // THESE MATERIALS ARE PROVIDED ON AN "AS IS" BASIS. AMAZON SPECIFICALLY
12
- // DISCLAIMS, WITH RESPECT TO THESE MATERIALS, ALL WARRANTIES, EXPRESS,
13
- // IMPLIED, OR STATUTORY, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
14
- // FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
15
-
16
- // Add APIs here that require privileges.
17
-
18
- const API_PRIV_NEEDED = exports.API_PRIV_NEEDED = [{
19
- packageName: '@amazon-devices/kepler-amazon-device-messaging',
20
- needsPrivilege: ['com.amazon.device-messaging.privilege.access'],
21
- wantsPrivilege: [],
22
- requiresUserPrompt: false
23
- }, {
24
- packageName: '@amazon-devices/kepler-amazon-device-messaging',
25
- needsPrivilege: ['com.amazon.device-messaging.privilege.access'],
26
- wantsPrivilege: [],
27
- requiresUserPrompt: false
28
- }, {
29
- packageName: '@amazon-devices/keplerscript-audio-lib',
30
- needsPrivilege: ['com.amazon.audio.privilege.settings.control', 'com.amazon.audio.privilege.microphone.access'],
31
- wantsPrivilege: [],
32
- requiresUserPrompt: false
33
- }, {
34
- packageName: '@amazon-devices/keplerscript-audio-lib',
35
- needsPrivilege: ['com.amazon.audio.privilege.settings.control'],
36
- wantsPrivilege: [],
37
- requiresUserPrompt: false
38
- }, {
39
- packageName: '@amazon-devices/kepler-identifiers',
40
- needsPrivilege: ['com.amazon.devconf.privilege.identifiers.device-friendly-name'],
41
- wantsPrivilege: [],
42
- requiresUserPrompt: true
43
- }, {
44
- packageName: '@amazon-devices/kepler-identifiers',
45
- needsPrivilege: ['com.amazon.devconf.privilege.identifiers.device-friendly-name'],
46
- wantsPrivilege: [],
47
- requiresUserPrompt: true
48
- }, {
49
- packageName: '@amazon-devices/keplerscript-netmgr-lib',
50
- needsPrivilege: [],
51
- wantsPrivilege: ['com.amazon.network.privilege.net-info'],
52
- requiresUserPrompt: false
53
- }, {
54
- packageName: '@amazon-devices/keplerscript-netmgr-lib',
55
- needsPrivilege: [],
56
- wantsPrivilege: ['com.amazon.network.privilege.net-info'],
57
- requiresUserPrompt: false
58
- }];
@@ -1,44 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.checkManifestForPrivilege = void 0;
7
- var fs = _interopRequireWildcard(require("fs"));
8
- var path = _interopRequireWildcard(require("path"));
9
- var toml = _interopRequireWildcard(require("toml"));
10
- function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
11
- // Copyright 2025 Amazon.com, Inc. or its affiliates. All rights reserved.
12
- // AMAZON PROPRIETARY/CONFIDENTIAL
13
- // You may not use this file except in compliance with the terms and conditions
14
- // set forth in the accompanying LICENSE.TXT file.
15
- // THESE MATERIALS ARE PROVIDED ON AN "AS IS" BASIS. AMAZON SPECIFICALLY
16
- // DISCLAIMS, WITH RESPECT TO THESE MATERIALS, ALL WARRANTIES, EXPRESS,
17
- // IMPLIED, OR STATUTORY, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
18
- // FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
19
-
20
- /**
21
- * Checks if the manifest.toml contains the required privilege in the specified section
22
- */
23
- const checkManifestForPrivilege = (privilege, section) => {
24
- try {
25
- const manifestPath = path.join(process.cwd(), 'manifest.toml');
26
- if (!fs.existsSync(manifestPath)) {
27
- return false;
28
- }
29
- const manifestContent = fs.readFileSync(manifestPath, 'utf8');
30
- const manifest = toml.parse(manifestContent);
31
- if (!manifest[section] || !Array.isArray(manifest[section].privilege)) {
32
- return false;
33
- }
34
- return manifest[section].privilege.some(entry => {
35
- if (typeof entry === 'object' && entry.id === privilege) {
36
- return true;
37
- }
38
- return false;
39
- });
40
- } catch (e) {
41
- return false;
42
- }
43
- };
44
- exports.checkManifestForPrivilege = checkManifestForPrivilege;
@@ -1,119 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.BackwardCompatibility = void 0;
7
- var fs = _interopRequireWildcard(require("fs"));
8
- var path = _interopRequireWildcard(require("path"));
9
- var _RuleUtils = require("../../utils/RuleUtils");
10
- function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
11
- // Copyright 2025 Amazon.com, Inc. or its affiliates. All rights reserved.
12
- // AMAZON PROPRIETARY/CONFIDENTIAL
13
- // You may not use this file except in compliance with the terms and conditions
14
- // set forth in the accompanying LICENSE.TXT file.
15
- // THESE MATERIALS ARE PROVIDED ON AN "AS IS" BASIS. AMAZON SPECIFICALLY
16
- // DISCLAIMS, WITH RESPECT TO THESE MATERIALS, ALL WARRANTIES, EXPRESS,
17
- // IMPLIED, OR STATUTORY, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
18
- // FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
19
-
20
- /**
21
- * Gets the location of the version field in package.json for error reporting
22
- */
23
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
- const getVersionFieldLocation = sourceCode => {
25
- const text = sourceCode.getText();
26
- const versionMatch = text.match(/"version"\s*:\s*"[^"]*"/);
27
- if (versionMatch) {
28
- const start = text.indexOf(versionMatch[0]);
29
- const startPos = sourceCode.getLocFromIndex(start);
30
- const endPos = sourceCode.getLocFromIndex(start + versionMatch[0].length);
31
- return {
32
- start: startPos,
33
- end: endPos
34
- };
35
- }
36
- return {
37
- start: {
38
- line: 1,
39
- column: 0
40
- },
41
- end: {
42
- line: 1,
43
- column: 0
44
- }
45
- };
46
- };
47
-
48
- /**
49
- * Checks for backward compatibility issues in Vega system distributed library projects
50
- */
51
- const BackwardCompatibility = exports.BackwardCompatibility = {
52
- meta: {
53
- type: 'problem',
54
- docs: {
55
- description: 'Checks for backward compatibility issues in Kepler projects',
56
- recommended: true,
57
- category: 'Backward Compatibility'
58
- },
59
- schema: []
60
- },
61
- create(context) {
62
- return {
63
- Program() {
64
- // do nothing if not in a Brazil repo and/or this isn't a library
65
- if (!(0, _RuleUtils.isBrazilRepo)() || !(0, _RuleUtils.isSDLProject)()) {
66
- return;
67
- }
68
-
69
- // Use modern context.filename with fallback to deprecated context.getFilename()
70
- const filename = context.filename || context.getFilename();
71
- if (!filename.endsWith('package.json')) {
72
- return;
73
- }
74
-
75
- // Use modern context.sourceCode with fallback to deprecated context.getSourceCode()
76
- const sourceCode = context.sourceCode || context.getSourceCode();
77
- const text = sourceCode.getText();
78
- try {
79
- const packageJson = JSON.parse(text);
80
- const projectRoot = process.cwd();
81
- const compatibilityFilePath = path.join(projectRoot, 'kepler-compatibility.json');
82
- if (!fs.existsSync(compatibilityFilePath)) {
83
- context.report({
84
- node: sourceCode.ast,
85
- message: 'You project is missing a kepler-compatibility.json file. This file is required for Vega library development. Please add it.',
86
- loc: getVersionFieldLocation(sourceCode)
87
- });
88
- return;
89
- }
90
- try {
91
- const compatibilityContent = fs.readFileSync(compatibilityFilePath, 'utf8');
92
- const compatibilityData = JSON.parse(compatibilityContent);
93
- const supportedVersions = Object.keys(compatibilityData.versions || {});
94
- const currentVersion = packageJson.version;
95
- if (currentVersion && !supportedVersions.includes(currentVersion)) {
96
- context.report({
97
- node: sourceCode.ast,
98
- message: `This version of the library (${currentVersion}) is not found in the kepler-compatibility.json. Please add an entry for this version.`,
99
- loc: getVersionFieldLocation(sourceCode)
100
- });
101
- }
102
- } catch {
103
- // If kepler-compatibility.json exists but is malformed, treat as version not found
104
- const currentVersion = packageJson.version;
105
- if (currentVersion) {
106
- context.report({
107
- node: sourceCode.ast,
108
- message: `This version of the library (${currentVersion}) is not found in the kepler-compatibility.json (JSON is malformed).`,
109
- loc: getVersionFieldLocation(sourceCode)
110
- });
111
- }
112
- }
113
- } catch {
114
- // Ignore JSON parsing errors for package.json. Linting will be unreliable anyway.
115
- }
116
- }
117
- };
118
- }
119
- };
@@ -1,101 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.KEP_COMPAT_PACK_CTA = exports.BackwardCompatibilityCopyOnPack = void 0;
7
- var _RuleUtils = require("../../utils/RuleUtils");
8
- // Copyright 2025 Amazon.com, Inc. or its affiliates. All rights reserved.
9
- // AMAZON PROPRIETARY/CONFIDENTIAL
10
- // You may not use this file except in compliance with the terms and conditions
11
- // set forth in the accompanying LICENSE.TXT file.
12
- // THESE MATERIALS ARE PROVIDED ON AN "AS IS" BASIS. AMAZON SPECIFICALLY
13
- // DISCLAIMS, WITH RESPECT TO THESE MATERIALS, ALL WARRANTIES, EXPRESS,
14
- // IMPLIED, OR STATUTORY, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
15
- // FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
16
-
17
- const KEP_COMPAT_PACK_CTA = exports.KEP_COMPAT_PACK_CTA = 'kepler-compatibility.json must be included in npm packages. Please add kepler-compatibility.json to the `files` field in your package.json.';
18
-
19
- /**
20
- * Gets the location of the files field in package.json for error reporting
21
- */
22
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
- const getFilesFieldLocation = sourceCode => {
24
- const text = sourceCode.getText();
25
- const filesMatch = text.match(/"files"\s*:\s*\[[^\]]*\]/);
26
- if (filesMatch) {
27
- const start = text.indexOf(filesMatch[0]);
28
- const startPos = sourceCode.getLocFromIndex(start);
29
- const endPos = sourceCode.getLocFromIndex(start + filesMatch[0].length);
30
- return {
31
- start: startPos,
32
- end: endPos
33
- };
34
- }
35
- return {
36
- start: {
37
- line: 1,
38
- column: 0
39
- },
40
- end: {
41
- line: 1,
42
- column: 0
43
- }
44
- };
45
- };
46
-
47
- /**
48
- * Checks that kepler-compatibility.json is included in the files array of package.json
49
- */
50
- const BackwardCompatibilityCopyOnPack = exports.BackwardCompatibilityCopyOnPack = {
51
- meta: {
52
- type: 'problem',
53
- docs: {
54
- description: 'Ensures kepler-compatibility.json is included in npm packages',
55
- recommended: true,
56
- category: 'Backward Compatibility'
57
- },
58
- schema: []
59
- },
60
- create(context) {
61
- return {
62
- Program() {
63
- // do nothing if not in a Brazil repo and/or this isn't a library
64
- if (!(0, _RuleUtils.isBrazilRepo)() || !(0, _RuleUtils.isSDLProject)()) {
65
- return;
66
- }
67
-
68
- // Use modern context.filename with fallback to deprecated context.getFilename()
69
- const filename = context.filename || context.getFilename();
70
- if (!filename.endsWith('package.json')) {
71
- return;
72
- }
73
-
74
- // Use modern context.sourceCode with fallback to deprecated context.getSourceCode()
75
- const sourceCode = context.sourceCode || context.getSourceCode();
76
- const text = sourceCode.getText();
77
- try {
78
- const packageJson = JSON.parse(text);
79
- const files = packageJson.files;
80
- if (!files || !Array.isArray(files)) {
81
- context.report({
82
- node: sourceCode.ast,
83
- message: KEP_COMPAT_PACK_CTA,
84
- loc: getFilesFieldLocation(sourceCode)
85
- });
86
- return;
87
- }
88
- if (!files.includes('kepler-compatibility.json')) {
89
- context.report({
90
- node: sourceCode.ast,
91
- message: KEP_COMPAT_PACK_CTA,
92
- loc: getFilesFieldLocation(sourceCode)
93
- });
94
- }
95
- } catch {
96
- // Ignore JSON parsing errors for package.json. Linting will be unreliable anyway.
97
- }
98
- }
99
- };
100
- }
101
- };
@@ -1,73 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.BackwardCompatibilitySysconfCheck = void 0;
7
- var fs = _interopRequireWildcard(require("fs"));
8
- var path = _interopRequireWildcard(require("path"));
9
- var _RuleUtils = require("../../utils/RuleUtils");
10
- function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
11
- // Copyright 2025 Amazon.com, Inc. or its affiliates. All rights reserved.
12
- // AMAZON PROPRIETARY/CONFIDENTIAL
13
- // You may not use this file except in compliance with the terms and conditions
14
- // set forth in the accompanying LICENSE.TXT file.
15
- // THESE MATERIALS ARE PROVIDED ON AN "AS IS" BASIS. AMAZON SPECIFICALLY
16
- // DISCLAIMS, WITH RESPECT TO THESE MATERIALS, ALL WARRANTIES, EXPRESS,
17
- // IMPLIED, OR STATUTORY, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
18
- // FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
19
-
20
- /**
21
- * Validates that libraries referenced in kepler-compatibility.json exist in kepler-system-conf.toml
22
- */
23
- const BackwardCompatibilitySysconfCheck = exports.BackwardCompatibilitySysconfCheck = {
24
- meta: {
25
- type: 'problem',
26
- docs: {
27
- description: 'Validates that versions or modules in kepler-compatibility.json exist in kepler-system-conf.toml.',
28
- recommended: true,
29
- category: 'Backward Compatibility'
30
- },
31
- schema: []
32
- },
33
- create(context) {
34
- return {
35
- Program() {
36
- // do nothing if not in a Brazil repo and/or this isn't a library
37
- if (!(0, _RuleUtils.isBrazilRepo)() || !(0, _RuleUtils.isSDLProject)()) {
38
- return;
39
- }
40
-
41
- // Use modern context.filename with fallback to deprecated context.getFilename()
42
- const filename = context.filename || context.getFilename();
43
- if (!filename.endsWith('kepler-compatibility.json')) {
44
- return;
45
- }
46
-
47
- // Use modern context.sourceCode with fallback to deprecated context.getSourceCode()
48
- const sourceCode = context.sourceCode || context.getSourceCode();
49
- const text = sourceCode.getText();
50
- try {
51
- const compatibilityData = JSON.parse(text);
52
- const projectRoot = process.cwd();
53
- const sysconfPath = path.join(projectRoot, 'kepler-system-conf.toml');
54
- if (!fs.existsSync(sysconfPath)) {
55
- return;
56
- }
57
- const sysconfContent = fs.readFileSync(sysconfPath, 'utf8');
58
- const libraryIds = Object.values(compatibilityData.versions || {});
59
- for (const libraryId of libraryIds) {
60
- if (!sysconfContent.includes(`id = "${libraryId}"`)) {
61
- context.report({
62
- node: sourceCode.ast,
63
- message: `Library "${libraryId}" referenced in kepler-compatibility.json is not found in kepler-system-conf.toml. Please add the module definition.`
64
- });
65
- }
66
- }
67
- } catch {
68
- // Ignore JSON parsing errors
69
- }
70
- }
71
- };
72
- }
73
- };
@@ -1,64 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.Animated = void 0;
7
- var _Constants = require("../../utils/Constants");
8
- /* eslint-disable @typescript-eslint/explicit-function-return-type */
9
- /* eslint-disable @typescript-eslint/no-explicit-any */
10
-
11
- const USE_NATIVE_DRIVER_PROP_NAME = 'useNativeDriver';
12
- const NATIVE_DRIVER_MESSAGE = `Set ${USE_NATIVE_DRIVER_PROP_NAME} to 'true' to run animations on UI thread for better performance. ` + `See ${_Constants.VEGA_BEST_PRACTICE_URL}#the-animated-library for more.`;
13
- const Animated = exports.Animated = {
14
- meta: {
15
- type: 'suggestion',
16
- docs: {
17
- description: "Recommends performance optimization configs for 'Animated' component",
18
- recommended: true,
19
- category: 'Performance'
20
- },
21
- fixable: 'code',
22
- schema: []
23
- },
24
- create(context) {
25
- return {
26
- CallExpression(node) {
27
- const isAnimated = node.callee.type === 'MemberExpression' && node.callee.object.name === 'Animated' && (node.callee.property.name === 'timing' || node.callee.property.name === 'spring' || node.callee.property.name === 'decay');
28
- if (!isAnimated) {
29
- return;
30
- }
31
- const animatedFunction = `${node.callee.object.name}.${node.callee.property.name}()`;
32
- // Animated.timing/spring/decay() accept 2 arguments 'value' and 'config'
33
- if (node.arguments.length < 2) {
34
- return;
35
- }
36
- const configArgument = node.arguments[1];
37
-
38
- // Check if configArgument is of type object
39
- if (configArgument.type !== 'ObjectExpression') {
40
- return;
41
- }
42
-
43
- // Check if the config object has a property named 'useNativeDriver'
44
- const useNativeDriverProperty = configArgument.properties.find(prop => prop.type === 'Property' && prop.key.type === 'Identifier' && prop.key.name === USE_NATIVE_DRIVER_PROP_NAME);
45
- if (!useNativeDriverProperty) {
46
- context.report({
47
- node,
48
- message: `${animatedFunction} missing props: '${USE_NATIVE_DRIVER_PROP_NAME}'. ${NATIVE_DRIVER_MESSAGE}`
49
- });
50
- return;
51
- }
52
-
53
- // If 'useNativeDriver' exists, check if it's set to true
54
- if (useNativeDriverProperty && useNativeDriverProperty.value.type === 'Literal' && useNativeDriverProperty.value.value === true) {
55
- return;
56
- }
57
- context.report({
58
- node,
59
- message: `'${USE_NATIVE_DRIVER_PROP_NAME}' property is set to 'false'. ${NATIVE_DRIVER_MESSAGE}`
60
- });
61
- }
62
- };
63
- }
64
- };
@@ -1,150 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.CheckSubscription = void 0;
7
- var _Constants = require("../../utils/Constants");
8
- // Copyright 2025 Amazon.com, Inc. or its affiliates. All rights reserved.
9
- // AMAZON PROPRIETARY/CONFIDENTIAL
10
- // You may not use this file except in compliance with the terms and conditions
11
- // set forth in the accompanying LICENSE.TXT file.
12
- // THESE MATERIALS ARE PROVIDED ON AN "AS IS" BASIS. AMAZON SPECIFICALLY
13
- // DISCLAIMS, WITH RESPECT TO THESE MATERIALS, ALL WARRANTIES, EXPRESS,
14
- // IMPLIED, OR STATUTORY, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
15
- // FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
16
-
17
- const moreUrlMessage = `See ${_Constants.VEGA_BEST_PRACTICE_URL}#listeners-event-subscriptions-and-timers for more.`;
18
- const CheckSubscription = exports.CheckSubscription = {
19
- meta: {
20
- type: 'suggestion',
21
- docs: {
22
- description: 'Checks if subscriptions are set to be cleaned up',
23
- recommended: true,
24
- category: 'Performance'
25
- },
26
- fixable: 'code',
27
- schema: [],
28
- messages: {
29
- failedToKeepSubscription: `Subscription must be kept in variable so that it can be cleaned up on the component is detached. ${moreUrlMessage}`,
30
- missingCleanUp: `Subscription \`{{varName}}\` is not cleaned up. ${moreUrlMessage}`
31
- }
32
- },
33
- create(context) {
34
- const addListenerFuncs = new Set();
35
- const subscriptionVars = new Set();
36
- const subscriptionCollections = new Set();
37
- const stateManagerVars = new Set();
38
-
39
- // Return true if the given node is a call to adding a listener.
40
- // Ex. `addInputListener(..)` or `appStateManager.addAppStateListener(...)`
41
- function isExpressionToAddListener(node) {
42
- if (node.callee.type === 'Identifier') {
43
- return addListenerFuncs.has(node.callee.name);
44
- }
45
- if (node.callee.type === 'MemberExpression') {
46
- if (node.callee.object.type === 'Identifier' && stateManagerVars.has(node.callee.object.name) && node.callee.property.type === 'Identifier' && node.callee.property.name === 'addAppStateListener') {
47
- return true;
48
- }
49
- }
50
- return false;
51
- }
52
- return {
53
- // Collect variables containing functions to add listener.
54
- // Ex. `const ${var} = useAddKeplerAppStateListenerCallback()`
55
- 'VariableDeclarator[init.callee.name = /^useAdd(KeplerAppState|UserInput)ListenerCallback$/]': node => {
56
- if (node.id.type === 'Identifier') {
57
- const varName = node.id.name;
58
- addListenerFuncs.add(varName);
59
- }
60
- },
61
- // Collect variables containing AppStateManager.
62
- // Ex. `const ${varName} = useKeplerAppStateManager()`
63
- 'VariableDeclarator[init.callee.name = /^useKeplerAppStateManager$/]': node => {
64
- if (node.id.type === 'Identifier') {
65
- const varName = node.id.name;
66
- stateManagerVars.add(varName);
67
- }
68
- },
69
- // Check the code adding listeners and collect variables containing subscriptions.
70
- // Warn code like `useEffect(() => {...; ${addListenerFunc}(....); ...}`
71
- // Collect vars like `useEffect(() => {...; ${subscriptionVar} = ${addListenerFunc}(....); ...}`
72
- // or `useEffect(() => {...; ${subscriptionCollection}.push(${addListenerFunc}(....)); ...}`
73
- "CallExpression[callee.name='useEffect'] :function CallExpression": node => {
74
- if (isExpressionToAddListener(node)) {
75
- const sourceCode = context.sourceCode ?? context.getSourceCode();
76
- const ancestors = sourceCode.getAncestors?.(node) ?? context.getAncestors();
77
- if (ancestors.length >= 1) {
78
- const parent = ancestors[ancestors.length - 1];
79
- if (parent.type === 'VariableDeclarator' && parent.id.type == 'Identifier') {
80
- // [const|let|var] ${var} = ${addListenerFunc}(....)
81
- subscriptionVars.add(parent.id.name);
82
- return;
83
- } else if (parent.type === 'AssignmentExpression' && parent.left.type == 'Identifier') {
84
- // ${var} = ${addListenerFunc}(....)
85
- subscriptionVars.add(parent.left.name);
86
- return;
87
- } else if (parent.type === 'CallExpression' && parent.arguments[0] === node && parent.callee.type === 'MemberExpression') {
88
- const callee = parent.callee;
89
- if (
90
- // ${collection}.[add|push](${addListenerFunc}(....));
91
- callee.property.type === 'Identifier' && ['add', 'push'].includes(callee.property.name) && callee.object.type === 'Identifier') {
92
- subscriptionCollections.add(callee.object.name);
93
- return;
94
- }
95
- }
96
- }
97
- context.report({
98
- node: node,
99
- messageId: 'failedToKeepSubscription'
100
- });
101
- }
102
- },
103
- // Remove subscription vars that are cleaned up in a function returned by the effect function.
104
- // Ex. `useEffect(() => {...; return () => ${subscriptionVar}.remove()});`
105
- "CallExpression[callee.name='useEffect'] :function ReturnStatement CallExpression[callee.property.name='remove']": removeCall => {
106
- if (removeCall.callee.type === 'MemberExpression') {
107
- const callee = removeCall.callee;
108
- if (callee.object.type === 'Identifier' && subscriptionVars.has(callee.object.name)) {
109
- subscriptionVars.delete(callee.object.name);
110
- }
111
- }
112
- },
113
- // Remove subscription collections that are cleaned up in a function returned by the effect function.
114
- // Ex. `useEffect(() => {...; return () => ${subscriptionCollection}.forEach(s => s.remove())});`
115
- "CallExpression[callee.name='useEffect'] :function ReturnStatement CallExpression[callee.property.name='forEach']": forEachCall => {
116
- if (forEachCall.callee.type === 'MemberExpression') {
117
- const callee = forEachCall.callee;
118
- if (callee.object.type === 'Identifier' && subscriptionCollections.has(callee.object.name)) {
119
- // Though it would be more precise to check if each subscription is removed in the function passed to `forEach`,
120
- // it's overkill. Let's accept false-negative by now.
121
- subscriptionCollections.delete(callee.object.name);
122
- }
123
- }
124
- },
125
- // Report all subscription vars and collections that are not removed at the exit of `useEffect` call
126
- "CallExpression[callee.name='useEffect']:exit": node => {
127
- for (const varName of subscriptionVars) {
128
- context.report({
129
- node,
130
- messageId: 'missingCleanUp',
131
- data: {
132
- varName
133
- }
134
- });
135
- }
136
- for (const varName of subscriptionCollections) {
137
- context.report({
138
- node,
139
- messageId: 'missingCleanUp',
140
- data: {
141
- varName
142
- }
143
- });
144
- }
145
- subscriptionVars.clear();
146
- subscriptionCollections.clear();
147
- }
148
- };
149
- }
150
- };
@@ -1,62 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.DetectSplashScreen = void 0;
7
- var _KeplerESLintPluginStateManager = require("../../state/KeplerESLintPluginStateManager");
8
- var _RuleUtils = require("../../utils/RuleUtils");
9
- // Copyright 2025 Amazon.com, Inc. or its affiliates. All rights reserved.
10
- // AMAZON PROPRIETARY/CONFIDENTIAL
11
- // You may not use this file except in compliance with the terms and conditions
12
- // set forth in the accompanying LICENSE.TXT file.
13
- // THESE MATERIALS ARE PROVIDED ON AN "AS IS" BASIS. AMAZON SPECIFICALLY
14
- // DISCLAIMS, WITH RESPECT TO THESE MATERIALS, ALL WARRANTIES, EXPRESS,
15
- // IMPLIED, OR STATUTORY, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
16
- // FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
17
-
18
- const USE_PREVENT_HIDE_SPLASH_SCREEN = 'usePreventHideSplashScreen';
19
- const USE_HIDE_SPLASH_SCREEN_CALLBACK = 'useHideSplashScreenCallback';
20
- const DetectSplashScreen = exports.DetectSplashScreen = {
21
- meta: {
22
- type: 'suggestion',
23
- docs: {
24
- description: 'usePreventHideSplashScreen() should be used to natively render splash screen, for better App launch performance',
25
- recommended: true,
26
- category: 'Performance'
27
- },
28
- fixable: 'code',
29
- schema: []
30
- },
31
- create(context) {
32
- const usePreventHideSplashScreenAliases = new Set();
33
- const useHideSplashScreenCallbackAliases = new Set();
34
- return {
35
- VariableDeclarator(node) {
36
- // Check usePreventHideSplashScreen()
37
- if ((0, _RuleUtils.isFunctionAssignedToVariable)(node, USE_PREVENT_HIDE_SPLASH_SCREEN) || (0, _RuleUtils.isModuleFunctionAssignedToVariable)(node, USE_PREVENT_HIDE_SPLASH_SCREEN)) {
38
- usePreventHideSplashScreenAliases.add(node.id['name']);
39
- }
40
- // Check useHideSplashScreenCallback()
41
- else if ((0, _RuleUtils.isFunctionAssignedToVariable)(node, USE_HIDE_SPLASH_SCREEN_CALLBACK) || (0, _RuleUtils.isModuleFunctionAssignedToVariable)(node, USE_HIDE_SPLASH_SCREEN_CALLBACK)) {
42
- useHideSplashScreenCallbackAliases.add(node.id['name']);
43
- }
44
- },
45
- CallExpression(node) {
46
- // Check usePreventHideSplashScreen()
47
- if ((0, _RuleUtils.isDirectCall)(node, USE_PREVENT_HIDE_SPLASH_SCREEN) || (0, _RuleUtils.isAliasCall)(node, USE_PREVENT_HIDE_SPLASH_SCREEN, usePreventHideSplashScreenAliases) || (0, _RuleUtils.isNamespacedCall)(node, USE_PREVENT_HIDE_SPLASH_SCREEN)) {
48
- const keplerESLintState = _KeplerESLintPluginStateManager.KeplerESLintPluginStateManager.getInstance().getKeplerESLintState();
49
- keplerESLintState.splashScreen.usePreventHideSplashScreenFound = true;
50
- _KeplerESLintPluginStateManager.KeplerESLintPluginStateManager.getInstance().setKeplerESLintState(keplerESLintState);
51
- }
52
-
53
- // Check useHideSplashScreenCallback()
54
- else if ((0, _RuleUtils.isDirectCall)(node, USE_HIDE_SPLASH_SCREEN_CALLBACK) || (0, _RuleUtils.isAliasCall)(node, USE_HIDE_SPLASH_SCREEN_CALLBACK, useHideSplashScreenCallbackAliases) || (0, _RuleUtils.isNamespacedCall)(node, USE_HIDE_SPLASH_SCREEN_CALLBACK)) {
55
- const keplerESLintState = _KeplerESLintPluginStateManager.KeplerESLintPluginStateManager.getInstance().getKeplerESLintState();
56
- keplerESLintState.splashScreen.useHideSplashScreenCallbackFound = true;
57
- _KeplerESLintPluginStateManager.KeplerESLintPluginStateManager.getInstance().setKeplerESLintState(keplerESLintState);
58
- }
59
- }
60
- };
61
- }
62
- };