@bigbinary/neeto-commons-frontend 2.0.25 → 2.0.27

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 CHANGED
@@ -3,12 +3,161 @@
3
3
  A library encapsulating common boilerplate frontend code required for all neeto
4
4
  products.
5
5
 
6
+ <table>
7
+ <thead>
8
+ <tr>
9
+ <th>
10
+
11
+ Name
12
+
13
+ </th>
14
+ <th>
15
+
16
+ Category
17
+
18
+ </th>
19
+ </tr>
20
+ </thead>
21
+ <tbody>
22
+
23
+ <tr>
24
+ <td style="vertical-align: top;">
25
+
26
+ - [Set up axios](./docs/initializers/axios.md)
27
+ - [Set up globalProps](./docs/initializers/globalProps.md)
28
+ - [Set up translations](./docs/initializers/translation.md)
29
+ - [Set up mixpanel](./docs/initializers/mixpanel.md)
30
+ - [Set up logger](./docs/initializers/logger.md)
31
+ </td>
32
+ <td style="vertical-align: top;">
33
+
34
+ [Initializers](./docs/initializers/README.md)
35
+
36
+ </td>
37
+ </tr>
38
+ <tr></tr>
39
+
40
+ <tr>
41
+ <td style="vertical-align: top;">
42
+
43
+ - [useDebounce](./docs/react/hooks.md#usedebounce)
44
+ - [useFuncDebounce](./docs/react/hooks.md#usefuncdebounce)
45
+ - [usePrevious](./docs/react/hooks.md#useprevious)
46
+ - [useUpdateEffect](./docs/react/hooks.md#useupdateeffect)
47
+ - [useLocalStorage](./docs/react/hooks.md#uselocalstorage)
48
+ - [useOnClickOutside](./docs/react/hooks.md#useonclickoutside)
49
+ - [useFieldSubmit](./docs/react/hooks.md#usefieldsubmit)
50
+ - [PrivateRoute](./docs/react/components.md#privateroute)
51
+ - [HoneybadgerErrorBoundary](./docs/react/components.md#honeybadgererrorboundary)
52
+ - [Sidebar](./docs/react/components.md#sidebar)
53
+ - [Error page](./docs/react/components.md#error-page)
54
+ - [Login page](./docs/react/components.md#login-page)
55
+ - [DateFormat/TimeFormat](./docs/react/components.md#dateformattimeformat)
56
+ - [Columns](./docs/react/components.md#columns)
57
+ - [NeetoWidget.EmbedCode](./docs/react/components.md#neetowidgetembedcode)
58
+ - [Schedule](./docs/react/components.md#schedule)
59
+ - [CustomDomain](./docs/react/components.md#customdomain)
60
+ - [BrowserSupport](./docs/react/components.md#browsersupport)
61
+ - [IpRestriction](./docs/react/components.md#iprestriction)
62
+ - [withImmutableActions](./docs/react/utils.md#withimmutableactions) (zustand middleware)
63
+ - [withTitle](./docs/react/utils.md#withtitle) (set browser title for pages)
64
+ - [registerBrowserNotifications](./docs/react/utils.md#registerbrowsernotifications)
65
+ (register browser subscription for push notifications)
66
+ - [destroyBrowserSubscription](./docs/react/utils.md#destroybrowsersubscription)
67
+ (destroy browser subscription for push notifications)
68
+
69
+ </td>
70
+ <td style="vertical-align: top;">
71
+
72
+ [React utilities](./docs/react/README.md)
73
+
74
+ </td>
75
+ </tr>
76
+ <tr></tr>
77
+ <tr>
78
+ <td style="vertical-align: top;">
79
+
80
+ - [findById](./docs/pure/arrays.md#findbyid)
81
+ - [findIndexById](./docs/pure/arrays.md#findindexbyid)
82
+ - [removeById](./docs/pure/arrays.md#removebyid)
83
+ - [replaceById](./docs/pure/arrays.md#replacebyid)
84
+ - [modifyById](./docs/pure/arrays.md#modifybyid)
85
+ - [existsById](./docs/pure/arrays.md#existsbyid)
86
+ - [findBy](./docs/pure/arrays.md#findby)
87
+ - [findIndexBy](./docs/pure/arrays.md#findindexby)
88
+ - [removeBy](./docs/pure/arrays.md#removeby)
89
+ - [replaceBy](./docs/pure/arrays.md#replaceby)
90
+ - [modifyBy](./docs/pure/arrays.md#modifyby)
91
+ - [existsBy](./docs/pure/arrays.md#existsby)
92
+ - [findLastBy](./docs/pure/arrays.md#findlastby)
93
+ - [findLastIndexBy](./docs/pure/arrays.md#findlastindexby)
94
+ - [filterBy](./docs/pure/arrays.md#filterby)
95
+ - [countBy](./docs/pure/arrays.md#countby)
96
+ - [renameKeys](./docs/pure/arrays.md#renamekeys)
97
+ - [copyKeys](./docs/pure/arrays.md#copykeys)
98
+ - [copyKeysDeep](./docs/pure/arrays.md#copykeysdeep)
99
+ - [transformObjectDeep](./docs/pure/objects.md#transformobjectdeep)
100
+ - [preprocessForSerialization](./docs/pure/objects.md#preprocessforserialization)
101
+ - [keysToCamelCase](./docs/pure/objects.md#keystocamelcase)
102
+ - [keysToSnakeCase](./docs/pure/objects.md#keystosnakecase)
103
+ - [deepFreezeObject](./docs/pure/objects.md#deepfreezeobject)
104
+ - [matches](./docs/pure/objects.md#matches)
105
+ - [filterNonNull](./docs/pure/objects.md#filternonnull)
106
+ - [slugify](./docs/pure/strings.md#slugify)
107
+ - [humanize](./docs/pure/strings.md#humanize)
108
+ - [snakeToCamelCase](./docs/pure/strings.md#snaketocamelcase)
109
+ - [camelToSnakeCase](./docs/pure/strings.md#cameltosnakecase)
110
+ - [capitalize](./docs/pure/strings.md#capitalize)
111
+ - [truncate](./docs/pure/strings.md#truncate)
112
+ - [noop](./docs/pure/general.md#noop)
113
+ - [toLabelAndValue](./docs/pure/general.md#tolabelandvalue)
114
+ - [getRandomInt](./docs/pure/general.md#getrandomint)
115
+ - [randomPick](./docs/pure/general.md#randompick)
116
+ - [dynamicArray](./docs/pure/general.md#dynamicarray)
117
+ - [isNotNil](./docs/pure/general.md#isnotnil)
118
+ - [isNotEmpty](./docs/pure/general.md#isnotempty)
119
+ - [isNot (alias notEquals)](./docs/pure/general.md#isnot_alias_notequals)
120
+ - [isNotEqualDeep (alias notEqualsDeep)](./docs/pure/general.md#isnotequaldeep_alias_notequalsdeep)
121
+
122
+ </td>
123
+ <td style="vertical-align: top;">
124
+
125
+ [Pure utility functions](./docs/pure/README.md)
126
+
127
+ </td>
128
+ </tr>
129
+
130
+ <tr></tr>
131
+
132
+ <tr>
133
+ <td style="vertical-align: top;">
134
+
135
+ - [withEventTargetValue](./docs/utils/README.md#witheventtargetvalue)
136
+ - [getSubdomain](./docs/utils/README.md#getsubdomain)
137
+ - [simulateApiCall](./docs/utils/README.md#simulateapicall)
138
+ - [copyToClipboard](./docs/utils/README.md#copytoclipboard)
139
+ - [buildUrl](./docs/utils/README.md#buildurl)
140
+ - [dateFormat/timeFormat](./docs/utils/README.md#dateformattimeformat)
141
+ - [toLocale](./docs/utils/README.md#tolocale)
142
+ - [getQueryParams](./docs/utils/README.md#getqueryparams)
143
+
144
+ </td>
145
+ <td style="vertical-align: top;">
146
+
147
+ [Web utility functions](./docs/utils/README.md)
148
+
149
+ </td>
150
+ </tr>
151
+
152
+ </tbody>
153
+ </table>
154
+
6
155
  ## Installation Instructions
7
156
 
8
157
  Install from npm:
9
158
 
10
159
  ```bash
11
- yarn add "@bigbinary/neeto-commons-frontend@2.0.25"
160
+ yarn add "@bigbinary/neeto-commons-frontend@latest"
12
161
  ```
13
162
 
14
163
  This package relies on the host project's tailwind configuration. So add
@@ -28,95 +177,17 @@ module.exports = {
28
177
 
29
178
  ## Usage
30
179
 
31
- This package exports four different sets of functions and components. Click on
180
+ This package exports five different sets of functions and components. Click on
32
181
  them to read more:
33
182
 
34
183
  1. [Initializers](./docs/initializers/README.md)
35
184
  2. [React utilities](./docs/react/README.md)
36
185
  3. [Pure utility functions](./docs/pure/README.md)
37
186
  4. [Web utility functions](./docs/utils/README.md)
187
+ 5. [Default configurations](./docs/configs/README.md)
188
+
189
+ ## Other references
38
190
 
39
- ## Migrating from version 1 to 2
40
-
41
- There is only a single breaking change from version 1 to version 2. The pure
42
- functions (which has only ramda as its peerDependency) have been moved to a
43
- separate bundle (named pure). You can import them from
44
- `@bigbinary/neeto-commons-frontend/pure` instead of
45
- `@bigbinary/neeto-commons-frontend/utils`.
46
-
47
- Here is a list of functions that have been moved:
48
-
49
- `removeById`, `findById`, `replaceById`, `modifyById`, `findBy`, `removeBy`,
50
- `replaceBy`,`modifyBy`, `existsById`, `existsBy`, `findLastBy`, `findIndexById`,
51
- `findIndexBy`,`findLastIndexBy`, `filterBy`, `countBy`, `copyKeys`,
52
- `renameKeys`, `copyKeysDeep`
53
-
54
- `noop`, `toLabelAndValue`, `getRandomInt`, `randomPick`, `dynamicArray`,
55
- `isNotNil`, `isNotEmpty`, `notEquals`, `isNot`, `notEqualsDeep`,
56
- `isNotEqualDeep`
57
-
58
- `transformObjectDeep`, `keysToCamelCase`, `keysToSnakeCase`, `deepFreezeObject`,
59
- `matches`, `filterNonNull`
60
-
61
- `slugify`, `humanize`, `snakeToCamelCase`, `camelToSnakeCase`, `capitalize`,
62
- `truncate`
63
-
64
- When you are migrating from version 1 to version 2, do the following:
65
-
66
- 1. Search for all imports from `@bigbinary/neeto-commons-frontend/utils` and
67
- delete the above mentioned functions from those imports.
68
- 2. Import these functions from `@bigbinary/neeto-commons-frontend/pure` instead.
69
-
70
- ## Development instructions
71
-
72
- 1. Clone this repository.
73
- 2. Run `yarn install` to download the dependencies and setup the development
74
- environment.
75
- 3. Have a host application ready.
76
- 4. Run `yarn build --watch` to automatically transpile code as you save the
77
- file. You can omit the `--watch` flag if you want to run the build only once.
78
- 5. In a different terminal, run `yalc publish` to publish the
79
- neeto-commons-frontend to the local yalc store.
80
- 6. Run `yalc add @bigbinary/neeto-commons-frontend` to install the
81
- neeto-commons-frontend to the host application.
82
- 7. After making necessary changes to `neeto-commons-frontend`, run `yalc push`
83
- to push the changes to the host application (assuming that you are in watch
84
- mode and the changes are bundled automatically).
85
- 8. Video explanation on how to use yalc: https://vimeo.com/722958162/9e931b640c
86
-
87
- ## Building and releasing.
88
-
89
- This is how releases are managed in this repo.
90
-
91
- - We will create a branch with the next release version as its name (`2.0.x`)
92
- from main branch.
93
- - Version in
94
- [README.md](https://github.com/bigbinary/neeto-commons-frontend/blob/main/README.md#L10)
95
- and
96
- [package.json](https://github.com/bigbinary/neeto-commons-frontend/blob/main/package.json#L3)
97
- will be updated to the current branch name.
98
- - We will create a draft PR of this branch targeting main. This keeps the branch
99
- in sync with main branch (bot-bigbinary will auto-merge the changes).
100
- - When all features have been built, we will deploy it to all neeto-applications
101
- locally using `yalc` package manager. We won't raise PR until the deployment
102
- and verification is successfully done locally for all neeto-applications. The
103
- usage of yalc is explained in this video:
104
- https://vimeo.com/722958162/9e931b640c
105
- - In case if we notice any problem during verification, like any missed edge
106
- cases, we will fix the problem in neeto-commons-frontend locally and re-run
107
- `yalc push` to update the local host projects.
108
- - Once everything is working fine and the verification is complete, create a PR
109
- with those bug fixes and get it merged.
110
- - We will now merge the PR `2.X.Y` to main.
111
- - We can now create a
112
- [new github release](https://github.com/bigbinary/neeto-commons-frontend/releases/new)
113
- from main branch with the current version as the tag name (`2.X.Y`).
114
- - Whenever a new release is created with a new version number, the github
115
- actions will automatically publish the built package to npm.
116
- - Immediately, we will open another branch with the next version (`2.X.Z`) and
117
- the cycle will continue.
118
- - Now we can run `yalc remove neeto-commons-frontend` to remove yalc based
119
- package and run `yarn add neeto-commons-frontend@2.X.Y` to fetch the latest
120
- changes from npm in all repos and raise PR. You might be able to slightly
121
- tweak this script to get the job done:
122
- https://gist.github.com/jagannathBhat/42a584748d97fe134f0abadb191ef29a
191
+ - [Development instructions](./docs/general/development-instructions.md)
192
+ - [Building and releasing](./docs/general/building-and-releasing.md)
193
+ - [Migrating from v1 to v2](./docs/general/migrating-from-1-to-2.md)
@@ -0,0 +1,42 @@
1
+ const VALID_ENVIRONMENTS = ["development", "test", "production"];
2
+
3
+ module.exports = function (api) {
4
+ const currentEnv = api.env();
5
+ const isDevelopmentEnv = api.env("development");
6
+ const isProductionEnv = api.env("production");
7
+ const isTestEnv = api.env("test");
8
+
9
+ if (!VALID_ENVIRONMENTS.includes(currentEnv)) {
10
+ throw new Error(
11
+ "Please specify a valid `NODE_ENV` or `BABEL_ENV` environment variables. " +
12
+ 'Valid values are "development", "test", and "production". ' +
13
+ `Instead, received: ${JSON.stringify(currentEnv)}.`
14
+ );
15
+ }
16
+
17
+ return {
18
+ presets: [
19
+ [
20
+ "@babel/preset-env",
21
+ {
22
+ forceAllTransforms: isProductionEnv,
23
+ useBuiltIns: "entry",
24
+ corejs: "3.27.0",
25
+ modules: false,
26
+ },
27
+ ],
28
+ ["@babel/preset-react", { development: isDevelopmentEnv || isTestEnv }],
29
+ ].filter(Boolean),
30
+ plugins: [
31
+ "babel-plugin-macros",
32
+ "@babel/plugin-transform-runtime",
33
+ isTestEnv
34
+ ? "babel-plugin-dynamic-import-node" // tests run in node environment
35
+ : "@babel/plugin-syntax-dynamic-import",
36
+ isProductionEnv && [
37
+ "babel-plugin-transform-react-remove-prop-types",
38
+ { removeImport: true },
39
+ ],
40
+ ].filter(Boolean),
41
+ };
42
+ };
@@ -0,0 +1,13 @@
1
+ module.exports = {
2
+ // Globals can be disabled with the string "off"
3
+ // "writable" to allow the variable to be overwritten or "readonly" to disallow overwriting.
4
+ globals: {
5
+ Atomics: "readonly",
6
+ SharedArrayBuffer: "readonly",
7
+ // Makes logger function available everywhere. Else eslint will complaint of undef-var.
8
+ logger: "readonly",
9
+ module: "writable",
10
+ // Makes props obtained from Rails backend available everywhere in this project.
11
+ globalProps: "readonly",
12
+ },
13
+ };
@@ -0,0 +1,61 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+
4
+ const { mergeDeepLeft } = require("ramda");
5
+
6
+ const loadJS = jsPath => {
7
+ try {
8
+ return require(path.resolve(__dirname, "../../../..", jsPath));
9
+ } catch (error) {
10
+ return {};
11
+ }
12
+ };
13
+
14
+ const buildPathGroupsBasedOnWebpackAliases = ({
15
+ customJSRoot = "app/javascript/",
16
+ customAliasPath = "config/webpack/resolve.js",
17
+ }) => {
18
+ const rootOfProject = `${__dirname}/../../../../../../`;
19
+
20
+ const isFile = filePath =>
21
+ fs.existsSync(filePath) && fs.lstatSync(filePath).isFile();
22
+
23
+ const isRailsProject = isFile(`${rootOfProject}Gemfile`);
24
+
25
+ const emptyPathGroups = [];
26
+
27
+ if (!isRailsProject) return emptyPathGroups;
28
+
29
+ const projectResolve = loadJS(rootOfProject + customAliasPath);
30
+ const commonResolve = loadJS(
31
+ `${rootOfProject}node_modules/@bigbinary/neeto-commons-frontend/configs/webpack/resolve.js`
32
+ );
33
+ const { alias } = mergeDeepLeft(projectResolve, commonResolve);
34
+
35
+ const railsJSFilesRoot = rootOfProject + customJSRoot;
36
+
37
+ const pathGroups = Object.entries(alias).map(([name, path]) => {
38
+ // sometimes alias might be already resolved to full absolute path
39
+ const isAlreadyAnAbsolutePath =
40
+ path.includes("cypress-tests/") || path.includes("app/");
41
+
42
+ const absolutePath = isAlreadyAnAbsolutePath
43
+ ? path
44
+ : `${railsJSFilesRoot}${path}`;
45
+ const wildCard =
46
+ isFile(`${absolutePath}.js`) || isFile(`${absolutePath}.jsx`)
47
+ ? ""
48
+ : "/**";
49
+
50
+ let group = "internal";
51
+ if (name === "neetoui") {
52
+ group = "external";
53
+ }
54
+
55
+ return { pattern: `${name}${wildCard}`, group };
56
+ });
57
+
58
+ return pathGroups;
59
+ };
60
+
61
+ module.exports = { buildPathGroupsBasedOnWebpackAliases };
@@ -0,0 +1,29 @@
1
+ module.exports = {
2
+ rules: {
3
+ // not-auto-fixable: Prefer a default export if module exports a single name.
4
+ "import/prefer-default-export": "off",
5
+ // not-auto-fixable: Forbid a module from importing a module with a dependency path back to itself.
6
+ "import/no-cycle": ["warn", { maxDepth: 1, ignoreExternal: true }],
7
+ // not-auto-fixable: Prevent unnecessary path segments in import and require statements.
8
+ "import/no-useless-path-segments": ["error", { noUselessIndex: true }],
9
+ // not-auto-fixable: Report any invalid exports, i.e. re-export of the same name.
10
+ "import/export": "error",
11
+ // not-auto-fixable: Forbid the use of mutable exports with var or let.
12
+ "import/no-mutable-exports": "error",
13
+ // not-auto-fixable: Ensure all imports appear before other statements.
14
+ "import/first": "error",
15
+ // not-auto-fixable: Ensure all exports appear after other statements.
16
+ "import/exports-last": "error",
17
+ // auto-fixable: Enforce a newline after import statements.
18
+ "import/newline-after-import": ["error", { count: 1 }],
19
+ // auto-fixable: Remove file extensions for import statements.
20
+ "import/extensions": [
21
+ "error",
22
+ "never",
23
+ {
24
+ ignorePackages: true,
25
+ pattern: { json: "always", mp3: "always", ico: "always" },
26
+ },
27
+ ],
28
+ },
29
+ };
@@ -0,0 +1,65 @@
1
+ const { buildPathGroupsBasedOnWebpackAliases } = require("../helpers");
2
+
3
+ const pathGroups = buildPathGroupsBasedOnWebpackAliases({});
4
+
5
+ const pathGroupForKeepingReactImportsAtTop = {
6
+ pattern: "react+(-native|)",
7
+ group: "external",
8
+ position: "before",
9
+ };
10
+
11
+ /*
12
+ Example pathGroups structure. Adding this here
13
+ so that if anyone wants to add custom config,
14
+ they can make use of this:
15
+ [
16
+ { pattern: 'apis/**', group: 'internal' },
17
+ { pattern: 'common/**', group: 'internal' },
18
+ { pattern: 'components/**', group: 'internal' },
19
+ { pattern: 'constants/**', group: 'internal' },
20
+ { pattern: 'contexts/**', group: 'internal' },
21
+ { pattern: 'reducers/**', group: 'internal' },
22
+ { pattern: 'Constants', group: 'internal' },
23
+ { pattern: 'neetoui/**', group: 'external' },
24
+ {
25
+ pattern: 'react+(-native|)',
26
+ group: 'external',
27
+ position: 'before'
28
+ }
29
+ ]
30
+ */
31
+ pathGroups.push(pathGroupForKeepingReactImportsAtTop);
32
+
33
+ module.exports = {
34
+ rules: {
35
+ // auto-fixable: Enforce a convention in module import order - we enforce https://www.bigbinary.com/react-best-practices/sort-import-statements
36
+ "import/order": [
37
+ "error",
38
+ {
39
+ "newlines-between": "always",
40
+ alphabetize: { order: "asc", caseInsensitive: true },
41
+ warnOnUnassignedImports: true,
42
+ groups: [
43
+ "builtin",
44
+ "external",
45
+ "internal",
46
+ "index",
47
+ "sibling",
48
+ "parent",
49
+ "object",
50
+ "type",
51
+ ],
52
+ /*
53
+ * Currently we check for existence of webpack alias
54
+ * config and then iterate over the aliases and create
55
+ * these pathGroups. Only caveat with this mechanism
56
+ * is that in VSCode eslint plugin won't dynamically
57
+ * read it. But eslint cli would!
58
+ */
59
+ pathGroups,
60
+ // Ignore react imports so that they're always ordered to the top of the file.
61
+ pathGroupsExcludedImportTypes: ["react", "react-native"],
62
+ },
63
+ ],
64
+ },
65
+ };
@@ -0,0 +1,156 @@
1
+ module.exports = {
2
+ env: {
3
+ browser: true, // window object etc part of browser are made available globally.
4
+ es2020: true, // to include BigInt support
5
+ es6: true,
6
+ commonjs: true,
7
+ node: true,
8
+ },
9
+ /*
10
+ * The order of extending each plugin matters a LOT!!
11
+ * Thus don't change order of items in this array
12
+ * unless you're sure of it.
13
+ */
14
+ extends: [
15
+ "plugin:@bigbinary/neeto/recommended",
16
+ "plugin:cypress/recommended",
17
+ "plugin:json/recommended",
18
+ "eslint:recommended",
19
+ "plugin:react/recommended",
20
+ "./node_modules/@bigbinary/neeto-commons-frontend/configs/eslint/globals",
21
+ "./node_modules/@bigbinary/neeto-commons-frontend/configs/eslint/imports/order",
22
+ "./node_modules/@bigbinary/neeto-commons-frontend/configs/eslint/overrides",
23
+ "./node_modules/@bigbinary/neeto-commons-frontend/configs/eslint/imports/enforced",
24
+ "./node_modules/@bigbinary/neeto-commons-frontend/configs/eslint/react",
25
+ "./node_modules/@bigbinary/neeto-commons-frontend/configs/eslint/promise",
26
+ "prettier",
27
+ ],
28
+ settings: {
29
+ react: {
30
+ version: "detect",
31
+ },
32
+ // We need this for the import/extensions rule to work: https://github.com/import-js/eslint-plugin-import#importextensions
33
+ "import/resolver": {
34
+ node: {
35
+ extensions: [".js", ".jsx", ".ts", ".tsx", ".svg", ".json", ".mp3"],
36
+ },
37
+ },
38
+ },
39
+ parserOptions: {
40
+ ecmaFeatures: {
41
+ jsx: true,
42
+ },
43
+ ecmaVersion: 2018,
44
+ sourceType: "module",
45
+ },
46
+ // babel-eslint is deprecated now. This is the latest package.
47
+ parser: "@babel/eslint-parser",
48
+ plugins: [
49
+ "react",
50
+ "prettier",
51
+ "import",
52
+ "react-hooks",
53
+ "promise",
54
+ "jam3",
55
+ "unused-imports",
56
+ "@bigbinary/neeto",
57
+ ],
58
+ rules: {
59
+ // auto-fixable: Respect all Prettier rules and apply it.
60
+ "prettier/prettier": "error",
61
+ // not-auto-fixable: No unused variables allowed.
62
+ "no-unused-vars": [
63
+ "error",
64
+ {
65
+ args: "all",
66
+ argsIgnorePattern: "^_",
67
+ destructuredArrayIgnorePattern: "^_",
68
+ caughtErrors: "all",
69
+ },
70
+ ],
71
+ // not-auto-fixable: No undefined variables allowed.
72
+ "no-undef": "error",
73
+ // not-auto-fixable: Dont use console statements. Use logger which babel will remove during bundling.
74
+ "no-console": "error",
75
+ // not-auto-fixable: require `return` statements to either always or never specify values.
76
+ "consistent-return": "error",
77
+ // auto-fixable: disallows repeating variable name when declaring object properties.
78
+ "object-shorthand": "error",
79
+ // auto-fixable: sadly this doesn't support guard clauses yet.
80
+ "padding-line-between-statements": [
81
+ "error",
82
+ { blankLine: "always", prev: "if", next: ["if", "return"] },
83
+ // The newline-before-return rule is deprecated in favor of the following:
84
+ { blankLine: "always", prev: "*", next: "return" },
85
+ // Add newline between function declarations
86
+ {
87
+ blankLine: "always",
88
+ prev: [
89
+ "block",
90
+ "multiline-block-like",
91
+ "function",
92
+ "iife",
93
+ "multiline-const",
94
+ "multiline-expression",
95
+ ],
96
+ next: ["function", "iife", "multiline-const", "multiline-expression"],
97
+ },
98
+ ],
99
+ // auto-fixable: Single line statements needn't have any braces. But in all other cases enforce curly braces.
100
+ curly: ["error", "multi-line"],
101
+ // auto-fixable: Remove the else part, if the "if" or "else-if" chain has a return statement
102
+ "no-else-return": "error",
103
+ // not-auto-fixable: Prevent un-sanitized dangerouslySetInnerHTML.
104
+ "jam3/no-sanitizer-with-danger": [
105
+ 2,
106
+ {
107
+ wrapperName: ["dompurify", "sanitizer", "sanitize"],
108
+ },
109
+ ],
110
+ // auto-fixable: Requires trailing commas when the last element or property is in a different line than the closing ] or }
111
+ "comma-dangle": [
112
+ "error",
113
+ {
114
+ arrays: "always-multiline",
115
+ objects: "always-multiline",
116
+ imports: "always-multiline",
117
+ exports: "always-multiline",
118
+ functions: "never",
119
+ },
120
+ ],
121
+ // auto-fixable: If a variable is never reassigned, using the const declaration is better.
122
+ "prefer-const": "error",
123
+ // auto-fixable: It is considered good practice to use the type-safe equality operators === and !==.
124
+ eqeqeq: "error",
125
+ // not-auto-fixable: Rule flags optional chaining expressions in positions where short-circuiting to undefined causes throwing a TypeError afterward.
126
+ "no-unsafe-optional-chaining": "error",
127
+ // auto-fixable: Remove all unused imports.
128
+ "unused-imports/no-unused-imports": "error",
129
+ // auto-fixable-1-level-deep: Using nested ternary operators make the code unreadable. Use if/else or switch with if/else. If it's JSX then move it out into a function or a variable. It's fine to use nestedTernary in JSX when it makes code more readable.
130
+ "no-nested-ternary": "warn",
131
+ // auto-fixable: Enforces no braces where they can be omitted.
132
+ "arrow-body-style": ["error", "as-needed"],
133
+ // auto-fixable: Suggests using template literals instead of string concatenation.
134
+ "prefer-template": "error",
135
+ // auto-fixable: Disallows ternary operators when simpler alternatives exist.
136
+ "no-unneeded-ternary": ["error", { defaultAssignment: false }],
137
+ // not-auto-fixable: Enforces declaring default params last
138
+ "default-param-last": "error",
139
+ // not-auto-fixable: Remove redundant async-awaits
140
+ "no-return-await": "warn",
141
+ // not-auto-fixable: Disallow empty block statements
142
+ "no-empty": ["error", { allowEmptyCatch: true }],
143
+ // not-auto-fixable: Enforce return statements in callbacks of array methods.
144
+ "array-callback-return": ["error"],
145
+ // auto-fixable: Partially fixable. Unless there's a need to the this keyword, there's no advantage of using a plain function.
146
+ "prefer-arrow-callback": ["error", { allowUnboundThis: true }],
147
+ // not-auto-fixable: Convert multiple imports from same module into a single import.
148
+ "no-duplicate-imports": ["error", { includeExports: true }],
149
+ // auto-fixable: Partially fixable. In JavaScript, there are a lot of different ways to convert value types. Allow only readable coercions.
150
+ "no-implicit-coercion": ["error", { allow: ["!!"] }],
151
+ // auto-fixable: Require let or const instead of var.
152
+ "no-var": "error",
153
+ // auto-fixable: This rule conflicts with prettier rules. Thus we've NOT kept this rule in react file. This rule ensures we don't add blank lines in JSX.
154
+ "react/jsx-newline": ["error", { prevent: true }],
155
+ },
156
+ };
@@ -0,0 +1,24 @@
1
+ module.exports = {
2
+ // Currently we are using this section for excluding certain files from certain rules.
3
+ overrides: [
4
+ {
5
+ files: [
6
+ ".eslintrc.js",
7
+ ".prettierrc.js",
8
+ "app/assets/**/*",
9
+ "app/javascript/packs/**/*",
10
+ "*.json",
11
+ ],
12
+ rules: {
13
+ "import/order": "off",
14
+ "react-hooks/rules-of-hooks": "off",
15
+ },
16
+ },
17
+ {
18
+ files: ["app/javascript/packs/**/*.{js,jsx}"],
19
+ rules: {
20
+ "no-redeclare": "off",
21
+ },
22
+ },
23
+ ],
24
+ };
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ rules: {
3
+ // not-auto-fixable: ensure people use async/await promising chaining rather than using "then-catch-finally" statements
4
+ "promise/prefer-await-to-then": "error",
5
+ // auto-fixable: avoid calling "new" on a Promise static method like reject, resolve etc
6
+ "promise/no-new-statics": "error",
7
+ },
8
+ };