@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 +157 -86
- package/configs/babel.js +42 -0
- package/configs/eslint/globals.js +13 -0
- package/configs/eslint/helpers/index.js +61 -0
- package/configs/eslint/imports/enforced.js +29 -0
- package/configs/eslint/imports/order.js +65 -0
- package/configs/eslint/index.js +156 -0
- package/configs/eslint/overrides.js +24 -0
- package/configs/eslint/promise.js +8 -0
- package/configs/eslint/react.js +92 -0
- package/configs/prettier.js +16 -0
- package/configs/tailwind.js +13 -0
- package/configs/webpack/helpers/customize-default-rules.js +57 -0
- package/configs/webpack/index.js +41 -0
- package/configs/webpack/resolve.js +47 -0
- package/configs/webpack/rules.js +43 -0
- package/initializers.cjs.js +10 -6
- package/initializers.js +10 -6
- package/package.json +17 -6
- package/react-utils.cjs.js +124 -95
- package/react-utils.d.ts +2 -0
- package/react-utils.js +125 -96
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@
|
|
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
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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)
|
package/configs/babel.js
ADDED
|
@@ -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
|
+
};
|