@bigbinary/eslint-plugin-neeto 1.6.1 → 1.6.2
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/README.md +1 -0
- package/dist/index.js +327 -261
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -71,6 +71,7 @@ of the issues identified in JavaScript code.
|
|
|
71
71
|
- [minimize-zustand-store-access-scope](./docs/src/rules/minimize-zustand-store-access-scope.md)
|
|
72
72
|
- [no-axios-import-outside-apis](./docs/src/rules/no-axios-import-outside-apis.md)
|
|
73
73
|
- [no-blacklisted-imports](./docs/src/rules/no-blacklisted-imports.md)
|
|
74
|
+
- [no-buildurl-call-with-empty-params](./docs/src/rules/no-buildurl-call-with-empty-params.md)
|
|
74
75
|
- [no-conditional-overlays](./docs/src/rules/no-conditional-overlays.md)
|
|
75
76
|
- [no-deprecated-imports-from-zustand](./docs/src/rules/no-deprecated-imports-from-zustand.md)
|
|
76
77
|
- [no-dangling-constants](./docs/src/rules/no-dangling-constants.md)
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global["@bigbinary/eslint-plugin-neeto"] = factory(global.
|
|
5
|
-
})(this, (function (fs, path$2,
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('ramda'), require('@bigbinary/neeto-cist'), require('fs'), require('path'), require('@bigbinary/neeto-commons-frontend/constants')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['ramda', '@bigbinary/neeto-cist', 'fs', 'path', '@bigbinary/neeto-commons-frontend/constants'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global["@bigbinary/eslint-plugin-neeto"] = factory(global.ramda, global["@bigbinary/neeto-cist"], global.fs, global.path$2, global.neetoCommonsConstants));
|
|
5
|
+
})(this, (function (ramda, neetoCist, fs, path$2, neetoCommonsConstants) { 'use strict';
|
|
6
6
|
|
|
7
7
|
function _interopNamespaceDefault(e) {
|
|
8
8
|
var n = Object.create(null);
|
|
@@ -23,6 +23,326 @@
|
|
|
23
23
|
|
|
24
24
|
var neetoCommonsConstants__namespace = /*#__PURE__*/_interopNamespaceDefault(neetoCommonsConstants);
|
|
25
25
|
|
|
26
|
+
const APIS_DIRECTORY = "app/javascript/src/apis";
|
|
27
|
+
const REACT_QUERY_DIRECTORY = "app/javascript/src/hooks/reactQuery";
|
|
28
|
+
const ROUTES_FILE_PATH = "app/javascript/src/routes.js";
|
|
29
|
+
const COMPONENTS_DIRECTORY = "app/javascript/src/components";
|
|
30
|
+
const BLACKLISTED_PACKAGES = ["moment", "bootstrap", "blueprint", "react-spinners", "react-table", "remixicon", "mjml", "react-select", "@bigbinary/neeto-utils"];
|
|
31
|
+
const TYPES = {
|
|
32
|
+
ARRAY_EXPRESSION: "ArrayExpression",
|
|
33
|
+
ARROW_FUNCTION_EXPRESSION: "ArrowFunctionExpression",
|
|
34
|
+
ASSIGNMENT_EXPRESSION: "AssignmentExpression",
|
|
35
|
+
ASSIGNMENT_PATTERN: "AssignmentPattern",
|
|
36
|
+
AWAIT_EXPRESSION: "AwaitExpression",
|
|
37
|
+
BINARY_EXPRESSION: "BinaryExpression",
|
|
38
|
+
BLOCK_STATEMENT: "BlockStatement",
|
|
39
|
+
BREAK_STATEMENT: "BreakStatement",
|
|
40
|
+
CALL_EXPRESSION: "CallExpression",
|
|
41
|
+
CHAIN_EXPRESSION: "ChainExpression",
|
|
42
|
+
CONDITIONAL_EXPRESSION: "ConditionalExpression",
|
|
43
|
+
EXPORT_NAMED_DECLARATION: "ExportNamedDeclaration",
|
|
44
|
+
EXPORT_DEFAULT_DECLARATION: "ExportDefaultDeclaration",
|
|
45
|
+
EXPRESSION_STATEMENT: "ExpressionStatement",
|
|
46
|
+
FUNCTION_DECLARATION: "FunctionDeclaration",
|
|
47
|
+
FUNCTION_EXPRESSION: "FunctionExpression",
|
|
48
|
+
IDENTIFIER: "Identifier",
|
|
49
|
+
IF_STATEMENT: "IfStatement",
|
|
50
|
+
IMPORT_DECLARATION: "ImportDeclaration",
|
|
51
|
+
IMPORT_DEFAULT_SPECIFIER: "ImportDefaultSpecifier",
|
|
52
|
+
IMPORT_SPECIFIER: "ImportSpecifier",
|
|
53
|
+
JSX_ATTRIBUTE: "JSXAttribute",
|
|
54
|
+
JSX_ELEMENT: "JSXElement",
|
|
55
|
+
JSX_EXPRESSION_CONTAINER: "JSXExpressionContainer",
|
|
56
|
+
JSX_IDENTIFIER: "JSXIdentifier",
|
|
57
|
+
JSX_OPENING_ELEMENT: "JSXOpeningElement",
|
|
58
|
+
JSX_SPREAD_ATTRIBUTE: "JSXSpreadAttribute",
|
|
59
|
+
JSX_TEXT: "JSXText",
|
|
60
|
+
LITERAL: "Literal",
|
|
61
|
+
LOGICAL_EXPRESSION: "LogicalExpression",
|
|
62
|
+
MEMBER_EXPRESSION: "MemberExpression",
|
|
63
|
+
OBJECT_EXPRESSION: "ObjectExpression",
|
|
64
|
+
OBJECT_PATTERN: "ObjectPattern",
|
|
65
|
+
PROGRAM: "Program",
|
|
66
|
+
PROPERTY: "Property",
|
|
67
|
+
RETURN_STATEMENT: "ReturnStatement",
|
|
68
|
+
SPREAD_ELEMENT: "SpreadElement",
|
|
69
|
+
TEMPLATE_ELEMENT: "TemplateElement",
|
|
70
|
+
TEMPLATE_LITERAL: "TemplateLiteral",
|
|
71
|
+
UNARY_EXPRESSION: "UnaryExpression",
|
|
72
|
+
VARIABLE_DECLARATION: "VariableDeclaration",
|
|
73
|
+
VARIABLE_DECLARATOR: "VariableDeclarator",
|
|
74
|
+
WHILE_STATEMENT: "WhileStatement",
|
|
75
|
+
NEW_EXPRESSION: "NewExpression"
|
|
76
|
+
};
|
|
77
|
+
const IMPORT_DECLARATION = {
|
|
78
|
+
type: TYPES.IMPORT_DECLARATION,
|
|
79
|
+
source: {
|
|
80
|
+
type: TYPES.LITERAL
|
|
81
|
+
},
|
|
82
|
+
specifiers: [{
|
|
83
|
+
type: TYPES.IMPORT_SPECIFIER
|
|
84
|
+
}]
|
|
85
|
+
};
|
|
86
|
+
const CAMEL_CASE_REGEX = /^[a-z][A-Za-z0-9]*$/;
|
|
87
|
+
const CONSTANT_CASE_REGEX = /^[A-Z0-9_]+$/;
|
|
88
|
+
const PASCAL_CASE_REGEX = /^(?:[A-Z]+[a-z0-9]+[A-Z]*)+$/;
|
|
89
|
+
const SNAKE_CASE_REGEX = /^[a-z0-9_]+$/;
|
|
90
|
+
|
|
91
|
+
// const TestComponent = () => {}
|
|
92
|
+
const COMPONENT_PATTERN = {
|
|
93
|
+
type: TYPES.VARIABLE_DECLARATION,
|
|
94
|
+
kind: "const",
|
|
95
|
+
declarations: [{
|
|
96
|
+
type: TYPES.VARIABLE_DECLARATOR,
|
|
97
|
+
init: {
|
|
98
|
+
type: TYPES.ARROW_FUNCTION_EXPRESSION
|
|
99
|
+
},
|
|
100
|
+
id: {
|
|
101
|
+
type: TYPES.IDENTIFIER,
|
|
102
|
+
name: ramda.test(PASCAL_CASE_REGEX)
|
|
103
|
+
}
|
|
104
|
+
}]
|
|
105
|
+
};
|
|
106
|
+
const PROP_FUNCTION_PATTERN = {
|
|
107
|
+
value: {
|
|
108
|
+
type: TYPES.JSX_EXPRESSION_CONTAINER,
|
|
109
|
+
expression: {
|
|
110
|
+
type: TYPES.ARROW_FUNCTION_EXPRESSION,
|
|
111
|
+
body: {
|
|
112
|
+
type: TYPES.BLOCK_STATEMENT
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
const NO_OF_LINES_ALLOWED_FOR_MULTIPLE_COMPONENTS_IN_A_FILE = 20;
|
|
118
|
+
const MAX_LINES_FOR_FUNCTIONS_INSIDE_JSX = 4;
|
|
119
|
+
|
|
120
|
+
// import { functionName } from neetocommons/utils;
|
|
121
|
+
const NEETO_COMMONS_UTILS_IMPORT_PATTERN = {
|
|
122
|
+
type: TYPES.IMPORT_DECLARATION,
|
|
123
|
+
source: {
|
|
124
|
+
type: TYPES.LITERAL,
|
|
125
|
+
value: "neetocommons/utils"
|
|
126
|
+
},
|
|
127
|
+
specifiers: [{
|
|
128
|
+
type: TYPES.IMPORT_SPECIFIER
|
|
129
|
+
}]
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const BUILD_URL_CALL_PATTERN = {
|
|
133
|
+
callee: {
|
|
134
|
+
type: TYPES.IDENTIFIER,
|
|
135
|
+
name: "buildUrl"
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
const SECOND_ARG_MISSING_PATTERN = {
|
|
139
|
+
arguments: args => args.length < 2
|
|
140
|
+
};
|
|
141
|
+
const SECOND_ARG_NULL_LITERAL_PATTERN = {
|
|
142
|
+
arguments: {
|
|
143
|
+
[1]: {
|
|
144
|
+
type: TYPES.LITERAL,
|
|
145
|
+
value: null
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
const SECOND_ARG_UNDEFINED_LITERAL_PATTERN = {
|
|
150
|
+
arguments: {
|
|
151
|
+
[1]: {
|
|
152
|
+
type: TYPES.IDENTIFIER,
|
|
153
|
+
name: "undefined"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
const SECOND_ARG_EMPTY_OBJECT_PATTERN = {
|
|
158
|
+
arguments: {
|
|
159
|
+
[1]: {
|
|
160
|
+
type: TYPES.OBJECT_EXPRESSION,
|
|
161
|
+
properties: ramda.isEmpty
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Returns a list of nodes that matches the pattern
|
|
168
|
+
* somewhere deep inside the given object-tree by
|
|
169
|
+
* partial object matching.
|
|
170
|
+
*
|
|
171
|
+
* @param {Object} obj the object tree to check
|
|
172
|
+
* @param {Object} pattern the pattern to match partially
|
|
173
|
+
* @param {Array} res list of nodes that matches the pattern
|
|
174
|
+
*/
|
|
175
|
+
const findMatchingNodesDeep = (obj, pattern, res = []) => {
|
|
176
|
+
if (typeof obj !== "object" || ramda.isNil(obj)) return res;
|
|
177
|
+
if (neetoCist.matches(pattern, obj)) return ramda.append(obj, res);
|
|
178
|
+
return Object.entries(obj).reduce((acc, [key, value]) => {
|
|
179
|
+
if (key === "parent") return acc;
|
|
180
|
+
return findMatchingNodesDeep(value, pattern, acc);
|
|
181
|
+
}, res);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Checks if any of the given pattern matches the object.
|
|
186
|
+
* @param {Object} obj The object tree to check.
|
|
187
|
+
* @param {Object[]} list The list of patterns to compare against.
|
|
188
|
+
* also @see matches
|
|
189
|
+
*/
|
|
190
|
+
const matchesAny = /*#__PURE__*/ramda.curry((list, obj) => list.some(neetoCist.matches(ramda.__, obj)));
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Checks if the given pattern exists somewhere deep inside
|
|
194
|
+
* the given object-tree by partial object matching.
|
|
195
|
+
*
|
|
196
|
+
* @param {Object} pattern the pattern to match partially
|
|
197
|
+
* @param {Object} obj the object tree to check
|
|
198
|
+
*/
|
|
199
|
+
const patternExistsDeep = /*#__PURE__*/ramda.curry((pattern, obj) => {
|
|
200
|
+
if (typeof obj !== "object" || ramda.isNil(obj)) return false;
|
|
201
|
+
if (neetoCist.matches(pattern, obj)) return true;
|
|
202
|
+
return Object.entries(obj).some(([key, value]) => {
|
|
203
|
+
if (key === "parent") return false;
|
|
204
|
+
return patternExistsDeep(pattern, value);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
const ARGUMENT_LIMIT = 3;
|
|
209
|
+
const API_ACTIONS_ARGUMENT_LIMIT = 2;
|
|
210
|
+
const FIXABLE_PARAMETER_TYPES = [TYPES.IDENTIFIER, TYPES.ASSIGNMENT_PATTERN];
|
|
211
|
+
|
|
212
|
+
/* eslint-disable @bigbinary/neeto/no-dangling-constants */
|
|
213
|
+
const addInJsconfig = aliasName => `Add path for "${aliasName}" in jsconfig.json. Refer https://bit.ly/sync-webpack-alias-and-jsconfig-paths for more details.`;
|
|
214
|
+
const canBeReplacedWith = fix => `Can be replaced with: ${fix}`;
|
|
215
|
+
const disallowUse = packageName => `Do not use the package ${packageName}`;
|
|
216
|
+
const exportedObjectShouldBe = caseStyle => `Exported object should be in ${caseStyle}. Refer https://youtu.be/uZtRIvo8-ww`;
|
|
217
|
+
const filenameShouldBe = caseStyle => `Filename should be in ${caseStyle}. Refer https://youtu.be/uZtRIvo8-ww`;
|
|
218
|
+
const moveToConstantsJs = constantName => `Move the constant ${constantName} to a constants.js file.`;
|
|
219
|
+
const preferSubscriptionUnsubscribe = replacerText => `Prefer to use ${replacerText}.unsubscribe() to prevent consumer creation boilerplate.`;
|
|
220
|
+
const renameFile = filename => `Rename this file to ${filename}`;
|
|
221
|
+
const replaceWith = fix => `Replace this with: ${fix}`;
|
|
222
|
+
const unableToResolveKey = ({
|
|
223
|
+
key,
|
|
224
|
+
lng
|
|
225
|
+
}) => `Unable to resolve localized string '${key}' in ${lng}.json`;
|
|
226
|
+
const giveCamelCaseOrPascalCaseNameFor = functionName => `Use either camelCase or PascalCase for naming the function - ${functionName}.`;
|
|
227
|
+
const replaceZustandDefaultExportWith = fix => `Zustand has deprecated the use of default exports for its functions. Replace this with: ${fix}`;
|
|
228
|
+
const replaceDayjsDefaultExportWith = fix => `Replace with: ${fix}`;
|
|
229
|
+
const replaceTailwindClass = (tailwindClass, neetoUIClass) => `Replace the class "${tailwindClass}" with its neetoui alternative "${neetoUIClass}"`;
|
|
230
|
+
const noMultipleComponentsInAFile$1 = (maxAllowedNoOfLines = 20) => `Do not have multiple component definitions that exceed ${maxAllowedNoOfLines} lines in a single file.`;
|
|
231
|
+
const avoidLargeFunctionsInsideJsx = (maxAllowedNoOfLines = 4) => `Avoid inline functions that exceed ${maxAllowedNoOfLines} lines directly inside JSX. Extract the function outside of JSX.`;
|
|
232
|
+
const reportVersionMismatch = (packageName, depType, peerVersion, correctVersion) => `Version mismatch for '${packageName}': peerDependencies (${peerVersion}) should be in sync with ${depType} (${correctVersion})`;
|
|
233
|
+
const suggestCommonConstants = (constantName, repository) => `Use "${constantName}" from "@bigbinary/${repository}"`;
|
|
234
|
+
const addRequiredPeerDependencies$1 = packageName => `${packageName} should be added to peerDependencies`;
|
|
235
|
+
const API_CONNECTOR_SHOULD_USE_DEFAULT_EXPORT_MESSAGE = "API Connector should be exported using the default export method";
|
|
236
|
+
const CAN_BE_REPLACED_WITH_HANDLE_META_CLICK = "Can be replaced with handleMetaClick function. Refer https://bit.ly/handleMetaClick";
|
|
237
|
+
const COMBINE_MULTIPLE_INDEPENDENT_AWAITS_MESSAGE = "Combine independent awaits to a single `Promise.all` call.";
|
|
238
|
+
const EXPORTED_OBJECT_AND_FILENAME_SHOULD_MATCH_MESSAGE = "Exported object and filename should match.";
|
|
239
|
+
const GLOBALPROPS_NO_ASSIGNMENT_MESSAGE = "globalProps should not be assigned to other variables";
|
|
240
|
+
const NESTED_GLOBALPROPS_NO_ASSIGNMENT_MESSAGE = "Nested properties of globalProps should not be assigned to other variables";
|
|
241
|
+
const NO_AXIOS_IMPORT_OUTSIDE_APIS_MESSAGE = "Do not use axios outside `app/javascript/src/apis`";
|
|
242
|
+
const NO_BUILD_URL_CALL_WITH_EMPTY_PARAMS = "`buildUrl` requires a valid second argument. Do not pass null, undefined, or empty values.";
|
|
243
|
+
const NO_CONDITIONAL_RENDER_OF_OVERLAYS = "Overlay components should not be rendered conditionally. Use `isOpen` attribute instead.";
|
|
244
|
+
const NO_EXCESS_API_ACTION_ARGUMENTS_MESSAGE = `API actions should use named parameters for more than ${API_ACTIONS_ARGUMENT_LIMIT} parameters`;
|
|
245
|
+
const NO_EXCESS_FUNCTION_ARGUMENTS_MESSAGE = `Functions should use named parameters for more than ${ARGUMENT_LIMIT} parameters`;
|
|
246
|
+
const NO_GLOBALPROPS_REASSIGNMENT_MESSAGE = "globalProps or its nested properties should not be re-assigned.";
|
|
247
|
+
const NO_ROUTES_ASSIGNMENT = "`routes` or its nested properties should not be assigned to other variables.";
|
|
248
|
+
const NO_ROUTES_REASSIGNMENT = "`routes` or its nested properties should not be re-assigned.";
|
|
249
|
+
const NO_NAMESPACE_SPECIFIER_IMPORT_FOR_RAMDA_MESSAGE = 'Use `import { methodsToImport } from "ramda"` instead';
|
|
250
|
+
const PREFER_EAGER_VALIDATION_MESSAGE = "Prefer to use Formik defaults for `validateOnBlur` and `validateOnChange` to ensure eager validation. Refer https://bit.ly/formik-eager-validation";
|
|
251
|
+
const PREFIX_NEETO_UI_IMPORT_ALIAS_MESSAGE = "Aliases for anything imported from neetoUI or neetoIcons should start with `NeetoUI`";
|
|
252
|
+
const REPLACE_WITH_HANDLE_META_CLICK = "Replace with handleMetaClick function";
|
|
253
|
+
const ROUTE_SHOULD_BE_A_STRING = "Route should be a plain string literal.";
|
|
254
|
+
const ROUTE_SHOULD_MATCH_OBJECT_PATH = "Route string should match with its object path.";
|
|
255
|
+
const ROUTES_HAS_ALREADY_BEEN_DECLARED = "Identifier `routes` has already been declared";
|
|
256
|
+
const ROUTES_CONSTANT_SHOULD_BE_DECLARED = "A constant object named `routes` should be declared inside routes.js";
|
|
257
|
+
const ROUTES_SHOULD_USE_DEFAULT_EXPORT = "`routes` should be exported using the default export method.";
|
|
258
|
+
const UNNECESSARY_CREATE_CONSUMER = "`createSubscription` function from `neetocommon/utils` invalidates the need of `createConsumer`";
|
|
259
|
+
const USE_ARRAY_METHODS = "Use array methods (forEach, map, filter, reduce, etc) instead of 'for' loop. Refer 'Advanced Array Methods' section in https://bit.ly/array-methods-page-1";
|
|
260
|
+
const USE_AXIOS_CONFIG_FOR_PASSING_QUERY_PARAMETERS_MESSAGE = "Use 'params attribute in axios configuration' to pass query parameters.";
|
|
261
|
+
const USE_CREATE_SUBSCRIPTION_FROM_NEETO_COMMONS = "Use `createSubscription` from @bigbinary/neeto-commons-frontend/utils instead. Refer: https://github.com/bigbinary/neeto-commons-frontend/blob/main/docs/utils/README.md#createsubscription";
|
|
262
|
+
const USE_INLINE_SVG_FOR_RENDER = "Use inline SVG instead of img tag for rendering SVGs";
|
|
263
|
+
const USE_LINK_FOR_NAVIGATION = "Use Link or NavLink component from 'react-router-dom' for click-navigation instead of onClick handler";
|
|
264
|
+
const USE_ANCHOR_FOR_NAVIGATION = "Use Anchor element (<a>) for click-navigation instead of onClick handler";
|
|
265
|
+
const USE_BUTTON_TO_FOR_LINK_NAVIGATION = "Use `to` prop of Button (<Button to='path'>) for click-navigation instead of onClick handler";
|
|
266
|
+
const USE_BUTTON_TO_FOR_ANCHOR_NAVIGATION = "Use `href` prop of Button (<Button href='path'>) for click-navigation instead of onClick handler";
|
|
267
|
+
const USE_TITLE_CASE_NEETO = "Use 'Neeto' instead of 'neeto' in strings";
|
|
268
|
+
const USE_NEETOUI_BORDER_COLOR = "Use neetoUI border color. Refer https://bit.ly/neeto-ui-border-colors for more details.";
|
|
269
|
+
const USE_NEETOUI_BORDER_RADIUS = "Use neetoUI border radius. Refer https://bit.ly/neeto-ui-border-radius for more details.";
|
|
270
|
+
const USE_NEETOUI_BOX_SHADOW = "Use neetoUI border shadow. Refer https://bit.ly/neeto-ui-box-shadows for more details.";
|
|
271
|
+
const USE_NEETOUI_TEXT_COLOR = "Use neetoUI text color. Refer https://bit.ly/neeto-ui-text-color for more details.";
|
|
272
|
+
const DONT_USE_ZUSTAND_STORE_WITHOUT_SELECTOR = "Don't use zustand store hook without a selector function. It will impact the performance";
|
|
273
|
+
const DONT_USE_ZUSTAND_STORE_WITHOUT_COMPARATOR_FUNCTION = "Don't pick multiple zustand state items without comparator function";
|
|
274
|
+
const USE_PERMISSIONS_PROP_IN_PRIVATE_ROUTE = "Use `permissions` prop of PrivateRoute component for consistency in handling permission denied pages.";
|
|
275
|
+
const USE_PROP_FOR_PICKING_SINGLE_ITEM = "Use prop instead of pick when picking single item";
|
|
276
|
+
const ENSURE_ZUSTAND_STORES_ARE_TYPE_ANNOTATED = `
|
|
277
|
+
Zustand stores should be type annotated like this:
|
|
278
|
+
/** @type {import("neetocommons/react-utils").ZustandStoreHook} */
|
|
279
|
+
const useUserStore = create(...)
|
|
280
|
+
`;
|
|
281
|
+
const USE_REACT_QUERY_FOR_MANAGING_REMOTE_DATA = "API calls should be managed using React Query";
|
|
282
|
+
const FILES_INSIDE_REACT_QUERY_FOLDER_SHOULD_END_WITH_API = "Files inside reactQuery folder should end with Api";
|
|
283
|
+
const USE_ZUSTAND_FOR_GLOBAL_STATE_MANAGEMENT = "Use zustand for global state management";
|
|
284
|
+
const AVOID_T_FUNCTIONS_IN_STRING_INTERPOLATION = "Translation function should not be used in string interpolation. Instead use a single translation key for the entire string. Refer: https://bit.ly/localization-best-practices";
|
|
285
|
+
const AVOID_MULTIPLE_T_FUNCTIONS_UNDER_SAME_PARENT = "Avoid using multiple translation functions under the same JSX parent. Instead use a single translation function with a single key. Refer: https://bit.ly/localization-best-practices";
|
|
286
|
+
const USE_TRANS_COMPONENTS_AND_VALUES_PROPS = "Instead of using numbered tags in translation string use `components` and `values` props of `Trans` to use named tag in translation string. Refer: https://bit.ly/localization-best-practices";
|
|
287
|
+
const USE_TRANSLATION_HOOK_IN_COMPONENTS = "Use translation function from `useTranslation()` hook in components.";
|
|
288
|
+
const USE_COMPONENTS_CHILDREN_PROP_IN_TRANS = "Use components children prop instead of label prop in `Trans` component to avoid multiple translation keys.";
|
|
289
|
+
const USE_I18NEXT_PLURALS = "Use plurals that comes with the `i18next` package for hard-coded strings. Refer: https://bit.ly/i18next-plurals";
|
|
290
|
+
const USE_PLURALIZE_PACKAGE = "Use `pluralize` package for dynamic values. Refer: https://bit.ly/i18next-plurals";
|
|
291
|
+
const USE_COPY_TO_CLIPBOARD_FROM_NEETO_COMMONS = "Use `copyToClipboard` from `@bigbinary/neeto-commons-frontend` package. Refer: https://bit.ly/copy-to-clipboard-utility-function";
|
|
292
|
+
const USE_ZUSTAND_PICK_TRANSFORMER = "Replace the boilerplate with zustand-pick syntax offered by babel-preset-neeto. Refer: https://bit.ly/zustand-pick-transform-doc";
|
|
293
|
+
const HARD_CODED_STRING_SHOULD_BE_LOCALIZED = "Hard-coded string should be localized";
|
|
294
|
+
const PROPS_NOT_SORTED = "Props inside spread attributes should be alphabetically sorted";
|
|
295
|
+
const MERGE_ADJACENT_SPREAD_ATTRIBUTES = "Merge spread attributes";
|
|
296
|
+
const DIFFERENT_PROPS_MUST_BE_OUTSIDE = "Props with different key and value should be outside the spread attribute";
|
|
297
|
+
const PROP_KEY_VALUE_DUPLICATE = "Prop key and value names should not be repeated";
|
|
298
|
+
const USE_WITH_IMMUTABLE_ACTIONS_WRAPPER = 'Use "withImmutableActions" wrapper from "neeto-commons-frontend" inside zustand create. Refer: https://bit.ly/withimmutableactions';
|
|
299
|
+
const USE_WITH_T_HOC_IN_DUMB_COMPONENTS = 'Use "withT" HOC from "neeto-commons-frontend" instead of useTranslation hook in Dumb components';
|
|
300
|
+
const NO_WITH_T_IN_SMART_COMPONENTS = '"withT" HOC should only be used in dumb components. "useTranslation" hook should be used here.';
|
|
301
|
+
const USE_STANDARD_DATE_TIME_FORMATS = 'Use "dateFormat/timeFormat" from "@bigbinary/neeto-commons-frontend/utils" instead. Refer: https://github.com/bigbinary/neeto-commons-frontend/blob/main/docs/utils/dateFormat.md';
|
|
302
|
+
const MOVE_SPREAD_ATTRIBUTES_TO_TOP = "Move spread attribute to top";
|
|
303
|
+
const USE_USE_MUTATION_WITH_INVALIDATION = "Use useMutationWithInvalidation from 'neetocommons/react-utils'";
|
|
304
|
+
const USE_CLASSNAMES_PACKAGE = "Use classnames package for dynamic classes";
|
|
305
|
+
const USE_USE_QUERY_CLIENT_HOOK = "Use 'useQueryClient' hook from 'react-query'";
|
|
306
|
+
const USE_EARLY_RETURN = "Use early return to avoid nested statement";
|
|
307
|
+
const NO_LOCAL_STORAGE = "Do not use localStorage directly. Use 'getFromLocalStorage()', 'setToLocalStorage()', 'removeFromLocalStorage()' or 'useLocalStorage()' from neeto-commons-frontend instead.";
|
|
308
|
+
const NO_TRANSLATION_LOWERCASE = "No need to lowercase i18next translations";
|
|
309
|
+
const AVOID_SNAKE_CASE_DESTRUCTURING_USEQUERYPARAMS_OR_GETQUERYPARAMS = "Avoid destructuring snake-cased values from getQueryParams or useQueryParams";
|
|
310
|
+
const PREFER_FUNCTION_REFERENCE = "Prefer passing function reference instead of creating a new function as the parameters and arguments are the same.";
|
|
311
|
+
const JSX_PREFER_GUARD_CLAUSE = "Prefer adding a guard clause for conditional statements left of JSX statments in the last return statement of the function.";
|
|
312
|
+
const USE_SHOW_THUMBS_UP_TOASTR_FUNCTION = "Use 'showThumbsUpToastr' function from '@bigbinary/neeto-commons-frontend/utils' for displaying thumbs up toast message.";
|
|
313
|
+
const NO_UNNECESSARY_CLASSNAMES = "classnames usage is unnecessary";
|
|
314
|
+
const USESTATE_DECLARATIONS_SHOULD_HAVE_INITIAL_VALUE = '"useState" declarations should have an initial value.';
|
|
315
|
+
const USE_NEETOUI_ACTION_BLOCK_IN_FORMIK_FORMS = 'Prefer using neetoui "ActionBlock" instead of "Button" for consistent behavior and appearance.';
|
|
316
|
+
|
|
317
|
+
var noBuildurlCallWithEmptyParams = {
|
|
318
|
+
meta: {
|
|
319
|
+
type: "problem",
|
|
320
|
+
docs: {
|
|
321
|
+
url: "https://github.com/bigbinary/eslint-plugin-neeto/blob/main/docs/src/rules/no-buildurl-call-with-empty-params.md",
|
|
322
|
+
description: "Disallow calling `buildUrl` with a missing, empty or invalid params argument"
|
|
323
|
+
},
|
|
324
|
+
fixable: "code"
|
|
325
|
+
},
|
|
326
|
+
create(context) {
|
|
327
|
+
return {
|
|
328
|
+
CallExpression(node) {
|
|
329
|
+
if (!neetoCist.matches(BUILD_URL_CALL_PATTERN, node)) return;
|
|
330
|
+
if (matchesAny([SECOND_ARG_MISSING_PATTERN, SECOND_ARG_NULL_LITERAL_PATTERN, SECOND_ARG_UNDEFINED_LITERAL_PATTERN, SECOND_ARG_EMPTY_OBJECT_PATTERN], node)) {
|
|
331
|
+
context.report({
|
|
332
|
+
node,
|
|
333
|
+
message: NO_BUILD_URL_CALL_WITH_EMPTY_PARAMS,
|
|
334
|
+
fix(fixer) {
|
|
335
|
+
const sourceCode = context.getSourceCode();
|
|
336
|
+
const firstArgText = sourceCode.getText(node.arguments[0]);
|
|
337
|
+
return fixer.replaceText(node, firstArgText);
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
|
|
26
346
|
const absolutePath$1 = jsPath => path$2.resolve(__dirname, "../../../..", jsPath);
|
|
27
347
|
const loadJS$2 = jsPath => {
|
|
28
348
|
try {
|
|
@@ -100,6 +420,7 @@
|
|
|
100
420
|
"@bigbinary/neeto/neetocommons-tips": "warn",
|
|
101
421
|
"@bigbinary/neeto/no-axios-import-outside-apis": ["error", resolve$2.alias],
|
|
102
422
|
"@bigbinary/neeto/no-blacklisted-imports": "warn",
|
|
423
|
+
"@bigbinary/neeto/no-buildurl-call-with-empty-params": "error",
|
|
103
424
|
"@bigbinary/neeto/no-conditional-overlays": "error",
|
|
104
425
|
"@bigbinary/neeto/no-deprecated-imports-from-zustand": "error",
|
|
105
426
|
"@bigbinary/neeto/no-dangling-constants": "error",
|
|
@@ -275,7 +596,7 @@
|
|
|
275
596
|
});
|
|
276
597
|
|
|
277
598
|
var name = "@bigbinary/eslint-plugin-neeto";
|
|
278
|
-
var version = "1.6.
|
|
599
|
+
var version = "1.6.1";
|
|
279
600
|
var main = "dist/index.js";
|
|
280
601
|
var license = "UNLICENSED";
|
|
281
602
|
var scripts = {
|
|
@@ -404,220 +725,6 @@
|
|
|
404
725
|
supportsAutofix: true
|
|
405
726
|
};
|
|
406
727
|
|
|
407
|
-
const APIS_DIRECTORY = "app/javascript/src/apis";
|
|
408
|
-
const REACT_QUERY_DIRECTORY = "app/javascript/src/hooks/reactQuery";
|
|
409
|
-
const ROUTES_FILE_PATH = "app/javascript/src/routes.js";
|
|
410
|
-
const COMPONENTS_DIRECTORY = "app/javascript/src/components";
|
|
411
|
-
const BLACKLISTED_PACKAGES = ["moment", "bootstrap", "blueprint", "react-spinners", "react-table", "remixicon", "mjml", "react-select", "@bigbinary/neeto-utils"];
|
|
412
|
-
const TYPES = {
|
|
413
|
-
ARRAY_EXPRESSION: "ArrayExpression",
|
|
414
|
-
ARROW_FUNCTION_EXPRESSION: "ArrowFunctionExpression",
|
|
415
|
-
ASSIGNMENT_EXPRESSION: "AssignmentExpression",
|
|
416
|
-
ASSIGNMENT_PATTERN: "AssignmentPattern",
|
|
417
|
-
AWAIT_EXPRESSION: "AwaitExpression",
|
|
418
|
-
BINARY_EXPRESSION: "BinaryExpression",
|
|
419
|
-
BLOCK_STATEMENT: "BlockStatement",
|
|
420
|
-
BREAK_STATEMENT: "BreakStatement",
|
|
421
|
-
CALL_EXPRESSION: "CallExpression",
|
|
422
|
-
CHAIN_EXPRESSION: "ChainExpression",
|
|
423
|
-
CONDITIONAL_EXPRESSION: "ConditionalExpression",
|
|
424
|
-
EXPORT_NAMED_DECLARATION: "ExportNamedDeclaration",
|
|
425
|
-
EXPORT_DEFAULT_DECLARATION: "ExportDefaultDeclaration",
|
|
426
|
-
EXPRESSION_STATEMENT: "ExpressionStatement",
|
|
427
|
-
FUNCTION_DECLARATION: "FunctionDeclaration",
|
|
428
|
-
FUNCTION_EXPRESSION: "FunctionExpression",
|
|
429
|
-
IDENTIFIER: "Identifier",
|
|
430
|
-
IF_STATEMENT: "IfStatement",
|
|
431
|
-
IMPORT_DECLARATION: "ImportDeclaration",
|
|
432
|
-
IMPORT_DEFAULT_SPECIFIER: "ImportDefaultSpecifier",
|
|
433
|
-
IMPORT_SPECIFIER: "ImportSpecifier",
|
|
434
|
-
JSX_ATTRIBUTE: "JSXAttribute",
|
|
435
|
-
JSX_ELEMENT: "JSXElement",
|
|
436
|
-
JSX_EXPRESSION_CONTAINER: "JSXExpressionContainer",
|
|
437
|
-
JSX_IDENTIFIER: "JSXIdentifier",
|
|
438
|
-
JSX_OPENING_ELEMENT: "JSXOpeningElement",
|
|
439
|
-
JSX_SPREAD_ATTRIBUTE: "JSXSpreadAttribute",
|
|
440
|
-
JSX_TEXT: "JSXText",
|
|
441
|
-
LITERAL: "Literal",
|
|
442
|
-
LOGICAL_EXPRESSION: "LogicalExpression",
|
|
443
|
-
MEMBER_EXPRESSION: "MemberExpression",
|
|
444
|
-
OBJECT_EXPRESSION: "ObjectExpression",
|
|
445
|
-
OBJECT_PATTERN: "ObjectPattern",
|
|
446
|
-
PROGRAM: "Program",
|
|
447
|
-
PROPERTY: "Property",
|
|
448
|
-
RETURN_STATEMENT: "ReturnStatement",
|
|
449
|
-
SPREAD_ELEMENT: "SpreadElement",
|
|
450
|
-
TEMPLATE_ELEMENT: "TemplateElement",
|
|
451
|
-
TEMPLATE_LITERAL: "TemplateLiteral",
|
|
452
|
-
UNARY_EXPRESSION: "UnaryExpression",
|
|
453
|
-
VARIABLE_DECLARATION: "VariableDeclaration",
|
|
454
|
-
VARIABLE_DECLARATOR: "VariableDeclarator",
|
|
455
|
-
WHILE_STATEMENT: "WhileStatement",
|
|
456
|
-
NEW_EXPRESSION: "NewExpression"
|
|
457
|
-
};
|
|
458
|
-
const IMPORT_DECLARATION = {
|
|
459
|
-
type: TYPES.IMPORT_DECLARATION,
|
|
460
|
-
source: {
|
|
461
|
-
type: TYPES.LITERAL
|
|
462
|
-
},
|
|
463
|
-
specifiers: [{
|
|
464
|
-
type: TYPES.IMPORT_SPECIFIER
|
|
465
|
-
}]
|
|
466
|
-
};
|
|
467
|
-
const CAMEL_CASE_REGEX = /^[a-z][A-Za-z0-9]*$/;
|
|
468
|
-
const CONSTANT_CASE_REGEX = /^[A-Z0-9_]+$/;
|
|
469
|
-
const PASCAL_CASE_REGEX = /^(?:[A-Z]+[a-z0-9]+[A-Z]*)+$/;
|
|
470
|
-
const SNAKE_CASE_REGEX = /^[a-z0-9_]+$/;
|
|
471
|
-
|
|
472
|
-
// const TestComponent = () => {}
|
|
473
|
-
const COMPONENT_PATTERN = {
|
|
474
|
-
type: TYPES.VARIABLE_DECLARATION,
|
|
475
|
-
kind: "const",
|
|
476
|
-
declarations: [{
|
|
477
|
-
type: TYPES.VARIABLE_DECLARATOR,
|
|
478
|
-
init: {
|
|
479
|
-
type: TYPES.ARROW_FUNCTION_EXPRESSION
|
|
480
|
-
},
|
|
481
|
-
id: {
|
|
482
|
-
type: TYPES.IDENTIFIER,
|
|
483
|
-
name: ramda.test(PASCAL_CASE_REGEX)
|
|
484
|
-
}
|
|
485
|
-
}]
|
|
486
|
-
};
|
|
487
|
-
const PROP_FUNCTION_PATTERN = {
|
|
488
|
-
value: {
|
|
489
|
-
type: TYPES.JSX_EXPRESSION_CONTAINER,
|
|
490
|
-
expression: {
|
|
491
|
-
type: TYPES.ARROW_FUNCTION_EXPRESSION,
|
|
492
|
-
body: {
|
|
493
|
-
type: TYPES.BLOCK_STATEMENT
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
};
|
|
498
|
-
const NO_OF_LINES_ALLOWED_FOR_MULTIPLE_COMPONENTS_IN_A_FILE = 20;
|
|
499
|
-
const MAX_LINES_FOR_FUNCTIONS_INSIDE_JSX = 4;
|
|
500
|
-
|
|
501
|
-
// import { functionName } from neetocommons/utils;
|
|
502
|
-
const NEETO_COMMONS_UTILS_IMPORT_PATTERN = {
|
|
503
|
-
type: TYPES.IMPORT_DECLARATION,
|
|
504
|
-
source: {
|
|
505
|
-
type: TYPES.LITERAL,
|
|
506
|
-
value: "neetocommons/utils"
|
|
507
|
-
},
|
|
508
|
-
specifiers: [{
|
|
509
|
-
type: TYPES.IMPORT_SPECIFIER
|
|
510
|
-
}]
|
|
511
|
-
};
|
|
512
|
-
|
|
513
|
-
const ARGUMENT_LIMIT = 3;
|
|
514
|
-
const API_ACTIONS_ARGUMENT_LIMIT = 2;
|
|
515
|
-
const FIXABLE_PARAMETER_TYPES = [TYPES.IDENTIFIER, TYPES.ASSIGNMENT_PATTERN];
|
|
516
|
-
|
|
517
|
-
/* eslint-disable @bigbinary/neeto/no-dangling-constants */
|
|
518
|
-
const addInJsconfig = aliasName => `Add path for "${aliasName}" in jsconfig.json. Refer https://bit.ly/sync-webpack-alias-and-jsconfig-paths for more details.`;
|
|
519
|
-
const canBeReplacedWith = fix => `Can be replaced with: ${fix}`;
|
|
520
|
-
const disallowUse = packageName => `Do not use the package ${packageName}`;
|
|
521
|
-
const exportedObjectShouldBe = caseStyle => `Exported object should be in ${caseStyle}. Refer https://youtu.be/uZtRIvo8-ww`;
|
|
522
|
-
const filenameShouldBe = caseStyle => `Filename should be in ${caseStyle}. Refer https://youtu.be/uZtRIvo8-ww`;
|
|
523
|
-
const moveToConstantsJs = constantName => `Move the constant ${constantName} to a constants.js file.`;
|
|
524
|
-
const preferSubscriptionUnsubscribe = replacerText => `Prefer to use ${replacerText}.unsubscribe() to prevent consumer creation boilerplate.`;
|
|
525
|
-
const renameFile = filename => `Rename this file to ${filename}`;
|
|
526
|
-
const replaceWith = fix => `Replace this with: ${fix}`;
|
|
527
|
-
const unableToResolveKey = ({
|
|
528
|
-
key,
|
|
529
|
-
lng
|
|
530
|
-
}) => `Unable to resolve localized string '${key}' in ${lng}.json`;
|
|
531
|
-
const giveCamelCaseOrPascalCaseNameFor = functionName => `Use either camelCase or PascalCase for naming the function - ${functionName}.`;
|
|
532
|
-
const replaceZustandDefaultExportWith = fix => `Zustand has deprecated the use of default exports for its functions. Replace this with: ${fix}`;
|
|
533
|
-
const replaceDayjsDefaultExportWith = fix => `Replace with: ${fix}`;
|
|
534
|
-
const replaceTailwindClass = (tailwindClass, neetoUIClass) => `Replace the class "${tailwindClass}" with its neetoui alternative "${neetoUIClass}"`;
|
|
535
|
-
const noMultipleComponentsInAFile$1 = (maxAllowedNoOfLines = 20) => `Do not have multiple component definitions that exceed ${maxAllowedNoOfLines} lines in a single file.`;
|
|
536
|
-
const avoidLargeFunctionsInsideJsx = (maxAllowedNoOfLines = 4) => `Avoid inline functions that exceed ${maxAllowedNoOfLines} lines directly inside JSX. Extract the function outside of JSX.`;
|
|
537
|
-
const reportVersionMismatch = (packageName, depType, peerVersion, correctVersion) => `Version mismatch for '${packageName}': peerDependencies (${peerVersion}) should be in sync with ${depType} (${correctVersion})`;
|
|
538
|
-
const suggestCommonConstants = (constantName, repository) => `Use "${constantName}" from "@bigbinary/${repository}"`;
|
|
539
|
-
const addRequiredPeerDependencies$1 = packageName => `${packageName} should be added to peerDependencies`;
|
|
540
|
-
const API_CONNECTOR_SHOULD_USE_DEFAULT_EXPORT_MESSAGE = "API Connector should be exported using the default export method";
|
|
541
|
-
const CAN_BE_REPLACED_WITH_HANDLE_META_CLICK = "Can be replaced with handleMetaClick function. Refer https://bit.ly/handleMetaClick";
|
|
542
|
-
const COMBINE_MULTIPLE_INDEPENDENT_AWAITS_MESSAGE = "Combine independent awaits to a single `Promise.all` call.";
|
|
543
|
-
const EXPORTED_OBJECT_AND_FILENAME_SHOULD_MATCH_MESSAGE = "Exported object and filename should match.";
|
|
544
|
-
const GLOBALPROPS_NO_ASSIGNMENT_MESSAGE = "globalProps should not be assigned to other variables";
|
|
545
|
-
const NESTED_GLOBALPROPS_NO_ASSIGNMENT_MESSAGE = "Nested properties of globalProps should not be assigned to other variables";
|
|
546
|
-
const NO_AXIOS_IMPORT_OUTSIDE_APIS_MESSAGE = "Do not use axios outside `app/javascript/src/apis`";
|
|
547
|
-
const NO_CONDITIONAL_RENDER_OF_OVERLAYS = "Overlay components should not be rendered conditionally. Use `isOpen` attribute instead.";
|
|
548
|
-
const NO_EXCESS_API_ACTION_ARGUMENTS_MESSAGE = `API actions should use named parameters for more than ${API_ACTIONS_ARGUMENT_LIMIT} parameters`;
|
|
549
|
-
const NO_EXCESS_FUNCTION_ARGUMENTS_MESSAGE = `Functions should use named parameters for more than ${ARGUMENT_LIMIT} parameters`;
|
|
550
|
-
const NO_GLOBALPROPS_REASSIGNMENT_MESSAGE = "globalProps or its nested properties should not be re-assigned.";
|
|
551
|
-
const NO_ROUTES_ASSIGNMENT = "`routes` or its nested properties should not be assigned to other variables.";
|
|
552
|
-
const NO_ROUTES_REASSIGNMENT = "`routes` or its nested properties should not be re-assigned.";
|
|
553
|
-
const NO_NAMESPACE_SPECIFIER_IMPORT_FOR_RAMDA_MESSAGE = 'Use `import { methodsToImport } from "ramda"` instead';
|
|
554
|
-
const PREFER_EAGER_VALIDATION_MESSAGE = "Prefer to use Formik defaults for `validateOnBlur` and `validateOnChange` to ensure eager validation. Refer https://bit.ly/formik-eager-validation";
|
|
555
|
-
const PREFIX_NEETO_UI_IMPORT_ALIAS_MESSAGE = "Aliases for anything imported from neetoUI or neetoIcons should start with `NeetoUI`";
|
|
556
|
-
const REPLACE_WITH_HANDLE_META_CLICK = "Replace with handleMetaClick function";
|
|
557
|
-
const ROUTE_SHOULD_BE_A_STRING = "Route should be a plain string literal.";
|
|
558
|
-
const ROUTE_SHOULD_MATCH_OBJECT_PATH = "Route string should match with its object path.";
|
|
559
|
-
const ROUTES_HAS_ALREADY_BEEN_DECLARED = "Identifier `routes` has already been declared";
|
|
560
|
-
const ROUTES_CONSTANT_SHOULD_BE_DECLARED = "A constant object named `routes` should be declared inside routes.js";
|
|
561
|
-
const ROUTES_SHOULD_USE_DEFAULT_EXPORT = "`routes` should be exported using the default export method.";
|
|
562
|
-
const UNNECESSARY_CREATE_CONSUMER = "`createSubscription` function from `neetocommon/utils` invalidates the need of `createConsumer`";
|
|
563
|
-
const USE_ARRAY_METHODS = "Use array methods (forEach, map, filter, reduce, etc) instead of 'for' loop. Refer 'Advanced Array Methods' section in https://bit.ly/array-methods-page-1";
|
|
564
|
-
const USE_AXIOS_CONFIG_FOR_PASSING_QUERY_PARAMETERS_MESSAGE = "Use 'params attribute in axios configuration' to pass query parameters.";
|
|
565
|
-
const USE_CREATE_SUBSCRIPTION_FROM_NEETO_COMMONS = "Use `createSubscription` from @bigbinary/neeto-commons-frontend/utils instead. Refer: https://github.com/bigbinary/neeto-commons-frontend/blob/main/docs/utils/README.md#createsubscription";
|
|
566
|
-
const USE_INLINE_SVG_FOR_RENDER = "Use inline SVG instead of img tag for rendering SVGs";
|
|
567
|
-
const USE_LINK_FOR_NAVIGATION = "Use Link or NavLink component from 'react-router-dom' for click-navigation instead of onClick handler";
|
|
568
|
-
const USE_ANCHOR_FOR_NAVIGATION = "Use Anchor element (<a>) for click-navigation instead of onClick handler";
|
|
569
|
-
const USE_BUTTON_TO_FOR_LINK_NAVIGATION = "Use `to` prop of Button (<Button to='path'>) for click-navigation instead of onClick handler";
|
|
570
|
-
const USE_BUTTON_TO_FOR_ANCHOR_NAVIGATION = "Use `href` prop of Button (<Button href='path'>) for click-navigation instead of onClick handler";
|
|
571
|
-
const USE_TITLE_CASE_NEETO = "Use 'Neeto' instead of 'neeto' in strings";
|
|
572
|
-
const USE_NEETOUI_BORDER_COLOR = "Use neetoUI border color. Refer https://bit.ly/neeto-ui-border-colors for more details.";
|
|
573
|
-
const USE_NEETOUI_BORDER_RADIUS = "Use neetoUI border radius. Refer https://bit.ly/neeto-ui-border-radius for more details.";
|
|
574
|
-
const USE_NEETOUI_BOX_SHADOW = "Use neetoUI border shadow. Refer https://bit.ly/neeto-ui-box-shadows for more details.";
|
|
575
|
-
const USE_NEETOUI_TEXT_COLOR = "Use neetoUI text color. Refer https://bit.ly/neeto-ui-text-color for more details.";
|
|
576
|
-
const DONT_USE_ZUSTAND_STORE_WITHOUT_SELECTOR = "Don't use zustand store hook without a selector function. It will impact the performance";
|
|
577
|
-
const DONT_USE_ZUSTAND_STORE_WITHOUT_COMPARATOR_FUNCTION = "Don't pick multiple zustand state items without comparator function";
|
|
578
|
-
const USE_PERMISSIONS_PROP_IN_PRIVATE_ROUTE = "Use `permissions` prop of PrivateRoute component for consistency in handling permission denied pages.";
|
|
579
|
-
const USE_PROP_FOR_PICKING_SINGLE_ITEM = "Use prop instead of pick when picking single item";
|
|
580
|
-
const ENSURE_ZUSTAND_STORES_ARE_TYPE_ANNOTATED = `
|
|
581
|
-
Zustand stores should be type annotated like this:
|
|
582
|
-
/** @type {import("neetocommons/react-utils").ZustandStoreHook} */
|
|
583
|
-
const useUserStore = create(...)
|
|
584
|
-
`;
|
|
585
|
-
const USE_REACT_QUERY_FOR_MANAGING_REMOTE_DATA = "API calls should be managed using React Query";
|
|
586
|
-
const FILES_INSIDE_REACT_QUERY_FOLDER_SHOULD_END_WITH_API = "Files inside reactQuery folder should end with Api";
|
|
587
|
-
const USE_ZUSTAND_FOR_GLOBAL_STATE_MANAGEMENT = "Use zustand for global state management";
|
|
588
|
-
const AVOID_T_FUNCTIONS_IN_STRING_INTERPOLATION = "Translation function should not be used in string interpolation. Instead use a single translation key for the entire string. Refer: https://bit.ly/localization-best-practices";
|
|
589
|
-
const AVOID_MULTIPLE_T_FUNCTIONS_UNDER_SAME_PARENT = "Avoid using multiple translation functions under the same JSX parent. Instead use a single translation function with a single key. Refer: https://bit.ly/localization-best-practices";
|
|
590
|
-
const USE_TRANS_COMPONENTS_AND_VALUES_PROPS = "Instead of using numbered tags in translation string use `components` and `values` props of `Trans` to use named tag in translation string. Refer: https://bit.ly/localization-best-practices";
|
|
591
|
-
const USE_TRANSLATION_HOOK_IN_COMPONENTS = "Use translation function from `useTranslation()` hook in components.";
|
|
592
|
-
const USE_COMPONENTS_CHILDREN_PROP_IN_TRANS = "Use components children prop instead of label prop in `Trans` component to avoid multiple translation keys.";
|
|
593
|
-
const USE_I18NEXT_PLURALS = "Use plurals that comes with the `i18next` package for hard-coded strings. Refer: https://bit.ly/i18next-plurals";
|
|
594
|
-
const USE_PLURALIZE_PACKAGE = "Use `pluralize` package for dynamic values. Refer: https://bit.ly/i18next-plurals";
|
|
595
|
-
const USE_COPY_TO_CLIPBOARD_FROM_NEETO_COMMONS = "Use `copyToClipboard` from `@bigbinary/neeto-commons-frontend` package. Refer: https://bit.ly/copy-to-clipboard-utility-function";
|
|
596
|
-
const USE_ZUSTAND_PICK_TRANSFORMER = "Replace the boilerplate with zustand-pick syntax offered by babel-preset-neeto. Refer: https://bit.ly/zustand-pick-transform-doc";
|
|
597
|
-
const HARD_CODED_STRING_SHOULD_BE_LOCALIZED = "Hard-coded string should be localized";
|
|
598
|
-
const PROPS_NOT_SORTED = "Props inside spread attributes should be alphabetically sorted";
|
|
599
|
-
const MERGE_ADJACENT_SPREAD_ATTRIBUTES = "Merge spread attributes";
|
|
600
|
-
const DIFFERENT_PROPS_MUST_BE_OUTSIDE = "Props with different key and value should be outside the spread attribute";
|
|
601
|
-
const PROP_KEY_VALUE_DUPLICATE = "Prop key and value names should not be repeated";
|
|
602
|
-
const USE_WITH_IMMUTABLE_ACTIONS_WRAPPER = 'Use "withImmutableActions" wrapper from "neeto-commons-frontend" inside zustand create. Refer: https://bit.ly/withimmutableactions';
|
|
603
|
-
const USE_WITH_T_HOC_IN_DUMB_COMPONENTS = 'Use "withT" HOC from "neeto-commons-frontend" instead of useTranslation hook in Dumb components';
|
|
604
|
-
const NO_WITH_T_IN_SMART_COMPONENTS = '"withT" HOC should only be used in dumb components. "useTranslation" hook should be used here.';
|
|
605
|
-
const USE_STANDARD_DATE_TIME_FORMATS = 'Use "dateFormat/timeFormat" from "@bigbinary/neeto-commons-frontend/utils" instead. Refer: https://github.com/bigbinary/neeto-commons-frontend/blob/main/docs/utils/dateFormat.md';
|
|
606
|
-
const MOVE_SPREAD_ATTRIBUTES_TO_TOP = "Move spread attribute to top";
|
|
607
|
-
const USE_USE_MUTATION_WITH_INVALIDATION = "Use useMutationWithInvalidation from 'neetocommons/react-utils'";
|
|
608
|
-
const USE_CLASSNAMES_PACKAGE = "Use classnames package for dynamic classes";
|
|
609
|
-
const USE_USE_QUERY_CLIENT_HOOK = "Use 'useQueryClient' hook from 'react-query'";
|
|
610
|
-
const USE_EARLY_RETURN = "Use early return to avoid nested statement";
|
|
611
|
-
const NO_LOCAL_STORAGE = "Do not use localStorage directly. Use 'getFromLocalStorage()', 'setToLocalStorage()', 'removeFromLocalStorage()' or 'useLocalStorage()' from neeto-commons-frontend instead.";
|
|
612
|
-
const NO_TRANSLATION_LOWERCASE = "No need to lowercase i18next translations";
|
|
613
|
-
const AVOID_SNAKE_CASE_DESTRUCTURING_USEQUERYPARAMS_OR_GETQUERYPARAMS = "Avoid destructuring snake-cased values from getQueryParams or useQueryParams";
|
|
614
|
-
const PREFER_FUNCTION_REFERENCE = "Prefer passing function reference instead of creating a new function as the parameters and arguments are the same.";
|
|
615
|
-
const JSX_PREFER_GUARD_CLAUSE = "Prefer adding a guard clause for conditional statements left of JSX statments in the last return statement of the function.";
|
|
616
|
-
const USE_SHOW_THUMBS_UP_TOASTR_FUNCTION = "Use 'showThumbsUpToastr' function from '@bigbinary/neeto-commons-frontend/utils' for displaying thumbs up toast message.";
|
|
617
|
-
const NO_UNNECESSARY_CLASSNAMES = "classnames usage is unnecessary";
|
|
618
|
-
const USESTATE_DECLARATIONS_SHOULD_HAVE_INITIAL_VALUE = '"useState" declarations should have an initial value.';
|
|
619
|
-
const USE_NEETOUI_ACTION_BLOCK_IN_FORMIK_FORMS = 'Prefer using neetoui "ActionBlock" instead of "Button" for consistent behavior and appearance.';
|
|
620
|
-
|
|
621
728
|
const PACKAGES_TO_CHECK = ["@bigbinary/neeto-molecules", "@bigbinary/neetoui", "@bigbinary/neeto-commons-frontend"];
|
|
622
729
|
|
|
623
730
|
// Checks if the passed package is present as a dependency
|
|
@@ -684,48 +791,6 @@
|
|
|
684
791
|
})
|
|
685
792
|
};
|
|
686
793
|
|
|
687
|
-
/**
|
|
688
|
-
* Returns a list of nodes that matches the pattern
|
|
689
|
-
* somewhere deep inside the given object-tree by
|
|
690
|
-
* partial object matching.
|
|
691
|
-
*
|
|
692
|
-
* @param {Object} obj the object tree to check
|
|
693
|
-
* @param {Object} pattern the pattern to match partially
|
|
694
|
-
* @param {Array} res list of nodes that matches the pattern
|
|
695
|
-
*/
|
|
696
|
-
const findMatchingNodesDeep = (obj, pattern, res = []) => {
|
|
697
|
-
if (typeof obj !== "object" || ramda.isNil(obj)) return res;
|
|
698
|
-
if (neetoCist.matches(pattern, obj)) return ramda.append(obj, res);
|
|
699
|
-
return Object.entries(obj).reduce((acc, [key, value]) => {
|
|
700
|
-
if (key === "parent") return acc;
|
|
701
|
-
return findMatchingNodesDeep(value, pattern, acc);
|
|
702
|
-
}, res);
|
|
703
|
-
};
|
|
704
|
-
|
|
705
|
-
/**
|
|
706
|
-
* Checks if any of the given pattern matches the object.
|
|
707
|
-
* @param {Object} obj The object tree to check.
|
|
708
|
-
* @param {Object[]} list The list of patterns to compare against.
|
|
709
|
-
* also @see matches
|
|
710
|
-
*/
|
|
711
|
-
const matchesAny = /*#__PURE__*/ramda.curry((list, obj) => list.some(neetoCist.matches(ramda.__, obj)));
|
|
712
|
-
|
|
713
|
-
/**
|
|
714
|
-
* Checks if the given pattern exists somewhere deep inside
|
|
715
|
-
* the given object-tree by partial object matching.
|
|
716
|
-
*
|
|
717
|
-
* @param {Object} pattern the pattern to match partially
|
|
718
|
-
* @param {Object} obj the object tree to check
|
|
719
|
-
*/
|
|
720
|
-
const patternExistsDeep = /*#__PURE__*/ramda.curry((pattern, obj) => {
|
|
721
|
-
if (typeof obj !== "object" || ramda.isNil(obj)) return false;
|
|
722
|
-
if (neetoCist.matches(pattern, obj)) return true;
|
|
723
|
-
return Object.entries(obj).some(([key, value]) => {
|
|
724
|
-
if (key === "parent") return false;
|
|
725
|
-
return patternExistsDeep(pattern, value);
|
|
726
|
-
});
|
|
727
|
-
});
|
|
728
|
-
|
|
729
794
|
const removeComments = json => json.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (m, g) => g ? "" : m);
|
|
730
795
|
const addNullSafeImport = (context, fixer, node) => {
|
|
731
796
|
const importPattern = ramda.assocPath(["source", "value"], "neetocist", IMPORT_DECLARATION);
|
|
@@ -11523,6 +11588,7 @@
|
|
|
11523
11588
|
"routes-should-match-object-path": routesShouldMatchObjectPath,
|
|
11524
11589
|
"use-array-methods": useArrayMethods,
|
|
11525
11590
|
"use-axios-config-for-passing-query-parameters": useAxiosConfigForPassingQueryParameters,
|
|
11591
|
+
"no-buildurl-call-with-empty-params": noBuildurlCallWithEmptyParams,
|
|
11526
11592
|
"use-camel-case-or-pascal-case-for-function-names": useCamelCaseOrPascalCaseForFunctionNames,
|
|
11527
11593
|
"use-common-routes": useCommonRoutes,
|
|
11528
11594
|
"use-components-children-prop-in-trans": useComponentsChildrenPropInTrans,
|