Skip to content
This repository has been archived by the owner on Dec 6, 2022. It is now read-only.

Better use namespace export l1 #53

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
# Class name must match the name of the file it is declared in. (derived-class-names)

Expected class names for all the files **other than components** are `name + prefix` (e.g. class inside of `AddToCart.container.js` file must be called `AddToCartContainer` and not otherwise).

## Rule Details

Notice, that this rule is not applied to `component` postfix.
Class names need to be based on the file name. For example, a class declared in `Footer.component.js` must be named
`FooterComponent`.

Examples of **incorrect** code for this rule:

```js
// in MyComponent.container.js
class Abc { /** ... */ }
// in Goodbye.component.js
class HelloComponent {} // should be GoodbyeComponent

// in Footer.container.js
class FooterComponent {} // should be FooterContainer

// in Hello.component.js
class HelloComponent { /** ... */ }
class Hello {} // should be HelloComponent
```

Examples of **correct** code for this rule:

```js
// in MyComponent.container.js
class MyComponentContainer { /** ... */ }
// in Footer.component.js
class FooterComponent {}

// in Hello.component.js
class Hello { /** ... */ }
// in Footer.container.js
class FooterContainer {}
```

## Why?
Naming classes according to the filename helps keep class names consistent and predictable across the codebase.

## Note
Currently, some code in the Scandi core codebase does not follow this rule. However, all new code should adhere to it.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Declarations must be exported (export-level-one)
In Scandi, all top-level declaration need to be [exported](https://javascript.info/import-export). This ensures that
your code remains extensible. This rule applies to all top-level class, function and constant declarations.

Examples of **incorrect** code for this rule:

```js
class Header {}

const FETCH_COUNT = 5;

function formatInput(){}
```

Examples of **correct** code for this rule:

```js
export class Header {}

export const FETCH_COUNT = 5;

export function formatInput(){}
```

# Why?
Exporting all declarations ensures that your code is easily extensible using the
[Override Mechanism](https://docs.scandipwa.com/developing-with-scandi/override-mechanism). This rule helps ensure
that your code will work well with the rest of the Scandi ecosystem.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Plugin endpoints must have a namespace (use-namespace)

Exported functions and classes (as well as some other values) need to be available for extensions to plug into.
To achieve this, they must be decorated by the `@namespace` comment, and the namespace should be correct.

Examples of **incorrect** code for this rule:

```js
// no namespace:
export class HeaderComponent {}
```

```js
/** @namespace The/Wrong/Namespace/HeaderComponent */
export class HeaderComponent {}
```

Examples of **correct** code for this rule:

```js
// in TestPackage, in the file Test/Path:
/** @namespace TestPackage/Test/Path/HeaderComponent */
export class HeaderComponent {}
```

## Why?
Decorating these classes and functions with namepaces ensures that your theme will work correctly with Scandi
[extensions](https://docs.scandipwa.com/developing-with-scandi/extensions).
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,29 @@
* @fileoverview Class name must match the name of the file it is declared in.
* @author Jegors Batovs
*/
const { constructMessage } = require('../util/messages.js');
const { getIdentifierOccurrences } = require('../util/ast.js');
const { getExpectedClassNameFromFilename, shouldClassNameBeEnforced, getUnexpectedNameMessage } = require('../util/derived-class-name.js');
const { getExpectedClassNameFromFilename, shouldClassNameBeEnforced } = require('../util/derived-class-name.js');
const { getFilenameFromPath } = require("../util/path.js");

const DOCUMENTATION_LINK =
"https://github.com/scandipwa/eslint/blob/master/docs/rules/derived-class-names.md";


function getUnexpectedNameMessage(filename, expectedName, actualName) {
const error = `In Scandi, class names need to be based on the file name. Since the filename is ${ filename } the class name should be ${ expectedName }.`;
const help = `To fix this error, rename ${ actualName } to ${ expectedName }.`;

return constructMessage(error, help, DOCUMENTATION_LINK);
}

module.exports = {
meta: {
docs: {
description: 'Class name must match the name of the file it is declared in.',
category: 'Coding standard',
recommended: true,
url: DOCUMENTATION_LINK
},
fixable: 'code',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,56 @@
* @author Jegors Batovs
*/

const { constructMessage } = require('../util/messages');

const CLASS_DECLARATION = 'ClassDeclaration';
const FUNCTION_DECLARATION = 'FunctionDeclaration';
const VARIABLE_DECLARATION = 'VariableDeclaration';
const OBJECT_PATTERN = 'ObjectPattern';

const DOCUMENTATION_URL = 'https://github.com/scandipwa/eslint/blob/master/docs/rules/export-level-one.md';

const shouldGetExported = [
const exportableTypes = [
CLASS_DECLARATION,
FUNCTION_DECLARATION,
VARIABLE_DECLARATION,
];

const shouldBeExported = (node) => {
const isDestructuringAssignment = (node) => {
const { type, declarations } = node;

return (
node.type !== VARIABLE_DECLARATION ||
!node.declarations.find((one) => one.id.type === 'ObjectPattern')
type === VARIABLE_DECLARATION &&
declarations.some((declaration) => declaration.id.type === OBJECT_PATTERN)
);
};

const getName = (node) => {
const shouldBeExported = (node) => {
const { type } = node;

if (!exportableTypes.includes(type)) {
return false;
}

return !isDestructuringAssignment(node)
};

const getNameFromDeclaration = (node) => {
if ([CLASS_DECLARATION, FUNCTION_DECLARATION].includes(node.type)) {
return node.id.name;
}

return 'This variable';
return 'variable';
};

const getExportErrorMessage = (exportable) => {
const name = getNameFromDeclaration(exportable);

const error = 'In Scandi, all top-level declarations need to be exported. This ensures that your code remains' +
' extensible.';
const help = `To fix this error, export the ${ name } declaration by adding "export" before it.`;

return constructMessage(error, help, DOCUMENTATION_URL);
};

module.exports = {
Expand All @@ -35,6 +62,7 @@ module.exports = {
'Everything declared in module on the first nesting level should be exported.',
category: 'Coding standard',
recommended: false,
url: DOCUMENTATION_URL,
},
fixable: 'code',
},
Expand All @@ -44,17 +72,13 @@ module.exports = {
const { body } = node;

body
.filter((levelOneNode) => shouldGetExported.includes(levelOneNode.type))
.map((exportable) => {
if (shouldBeExported(exportable)) {
context.report({
node: exportable,
message: `${getName(
exportable
)} must be exported (as non default) to allow proper extension`,
fix: (fixer) => fixer.insertTextBefore(exportable, 'export '),
});
}
.filter((node) => shouldBeExported(node))
.map((declarationNode) => {
context.report({
node: declarationNode,
message: getExportErrorMessage(declarationNode),
fix: (fixer) => fixer.insertTextBefore(declarationNode, 'export '),
});
});
},
}),
Expand Down
Loading