@accordproject/concerto-linter 1.0.0
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/.eslintignore +20 -0
- package/.eslintrc.yml +45 -0
- package/HEADER.md +2 -0
- package/README.md +207 -0
- package/default-ruleset/.eslintignore +20 -0
- package/default-ruleset/.eslintrc.yml +45 -0
- package/default-ruleset/README.md +300 -0
- package/default-ruleset/jest.config.js +7 -0
- package/default-ruleset/package.json +51 -0
- package/default-ruleset/src/abstract-must-subclassed.ts +29 -0
- package/default-ruleset/src/camel-case-properties.ts +35 -0
- package/default-ruleset/src/functions/check-length-validator.ts +52 -0
- package/default-ruleset/src/functions/find-abstract-declaration.ts +70 -0
- package/default-ruleset/src/functions/find-empty-declarations.ts +56 -0
- package/default-ruleset/src/namespace-version.ts +35 -0
- package/default-ruleset/src/no-empty-declarations.ts +31 -0
- package/default-ruleset/src/no-reserved-keywords.ts +43 -0
- package/default-ruleset/src/pascal-case-declarations.ts +35 -0
- package/default-ruleset/src/pascal-case-decorators.ts +38 -0
- package/default-ruleset/src/ruleset-main.ts +41 -0
- package/default-ruleset/src/string-length-validator.ts +32 -0
- package/default-ruleset/src/upper-snake-case-enum-const.ts +36 -0
- package/default-ruleset/test/fixtures/ENUM_Constans-invaild.cto +7 -0
- package/default-ruleset/test/fixtures/ENUM_Constans-vaild.cto +7 -0
- package/default-ruleset/test/fixtures/abstract-must-subclassed-invalid.cto +10 -0
- package/default-ruleset/test/fixtures/abstract-must-subclassed-valid.cto +18 -0
- package/default-ruleset/test/fixtures/declarations-valid-PascalCase.cto +21 -0
- package/default-ruleset/test/fixtures/declarations-violate-PascalCase.cto +22 -0
- package/default-ruleset/test/fixtures/decorators-valid-PascalCase.cto +8 -0
- package/default-ruleset/test/fixtures/decorators-violate-PascalCase.cto +8 -0
- package/default-ruleset/test/fixtures/namespace-invalid-version.cto +5 -0
- package/default-ruleset/test/fixtures/namespace-valid-version.cto +5 -0
- package/default-ruleset/test/fixtures/no-empty-declarations-invalid.cto +10 -0
- package/default-ruleset/test/fixtures/no-empty-declarations-valid.cto +16 -0
- package/default-ruleset/test/fixtures/no-reserved-keywords-invalid.cto +16 -0
- package/default-ruleset/test/fixtures/no-reserved-keywords-valid.cto +16 -0
- package/default-ruleset/test/fixtures/properties-valid-camelCase.cto +10 -0
- package/default-ruleset/test/fixtures/properties-violate-camelCase.cto +10 -0
- package/default-ruleset/test/fixtures/string-length-validator-invalid.cto +9 -0
- package/default-ruleset/test/fixtures/string-length-validator-valid.cto +10 -0
- package/default-ruleset/test/rules/abstract-must-subclassed.test.ts +33 -0
- package/default-ruleset/test/rules/namespace-version.test.ts +24 -0
- package/default-ruleset/test/rules/naming-ruleset.test.ts +133 -0
- package/default-ruleset/test/rules/no-empty-declarations.test.ts +33 -0
- package/default-ruleset/test/rules/no-reserved-keywords.test.ts +33 -0
- package/default-ruleset/test/rules/string-length-validator.test.ts +33 -0
- package/default-ruleset/test/test-rule.ts +30 -0
- package/default-ruleset/tsconfig.json +113 -0
- package/dist/config-loader.d.ts +6 -0
- package/dist/config-loader.js +52 -0
- package/dist/config-loader.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +135 -0
- package/dist/index.js.map +1 -0
- package/jest.config.js +11 -0
- package/package.json +54 -0
- package/src/config-loader.ts +48 -0
- package/src/index.ts +173 -0
- package/test/unit/configLoader.test.ts +76 -0
- package/test/unit/formatResults.test.ts +149 -0
- package/test/unit/lintModel.test.ts +84 -0
- package/test/unit/loadRuleset.test.ts +64 -0
- package/tsconfig.build.json +4 -0
- package/tsconfig.json +113 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@accordproject/concerto-linter-default-ruleset",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Default ruleset for the Accord Project Concerto Linter",
|
|
5
|
+
"homepage": "https://github.com/accordproject/concerto",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=18",
|
|
8
|
+
"npm": ">=10"
|
|
9
|
+
},
|
|
10
|
+
"main": "dist/ruleset-main.js",
|
|
11
|
+
"typings": "dist/ruleset-main.d.ts",
|
|
12
|
+
"scripts": {
|
|
13
|
+
"clean": "rimraf dist",
|
|
14
|
+
"prebuild": "npm-run-all clean",
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"pretest": "npm-run-all lint",
|
|
17
|
+
"lint": "eslint .",
|
|
18
|
+
"lint:fix": "eslint . --fix",
|
|
19
|
+
"test": "jest",
|
|
20
|
+
"test:watch": "jest --watchAll"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/accordproject/concerto.git",
|
|
25
|
+
"directory": "packages/concerto-linter/default-ruleset"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"concerto",
|
|
29
|
+
"linter",
|
|
30
|
+
"spectral",
|
|
31
|
+
"default-ruleset"
|
|
32
|
+
],
|
|
33
|
+
"author": "accordproject.org",
|
|
34
|
+
"license": "Apache-2.0",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@accordproject/concerto-core": "3.21.0",
|
|
37
|
+
"@stoplight/spectral-core": "1.20.0",
|
|
38
|
+
"@stoplight/spectral-functions": "1.10.1",
|
|
39
|
+
"@stoplight/spectral-parsers": "1.0.5"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"eslint": "8.57.1",
|
|
43
|
+
"@typescript-eslint/eslint-plugin": "^8.46.2",
|
|
44
|
+
"@typescript-eslint/parser": "^8.46.2",
|
|
45
|
+
"npm-run-all": "^4.1.5",
|
|
46
|
+
"rimraf": "^6.0.1",
|
|
47
|
+
"typescript": "5.7.2",
|
|
48
|
+
"jest": "^29.7.0",
|
|
49
|
+
"ts-jest": "^29.2.5"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
import { hasConcreteSubclass } from './functions/find-abstract-declaration';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Rule: Abstract Must Be Subclassed
|
|
18
|
+
* ---------------------------------
|
|
19
|
+
* Ensures that every abstract declaration in the model has at least one concrete subclass.
|
|
20
|
+
* This helps prevent unused or orphaned abstract types, enforcing better model design.
|
|
21
|
+
*/
|
|
22
|
+
export default {
|
|
23
|
+
given: '$.models[*]',
|
|
24
|
+
severity: 0, // 0 = error, 1 = warning, 2 = info, 3 = hint
|
|
25
|
+
then: {
|
|
26
|
+
function: hasConcreteSubclass,
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { casing } from '@stoplight/spectral-functions';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Rule: Camel Case Properties
|
|
19
|
+
* ---------------------------
|
|
20
|
+
* Ensures that properties of type String, Double, Integer, Long, DateTime, and Boolean
|
|
21
|
+
* are named using camelCase. This promotes consistency and readability in property naming
|
|
22
|
+
* conventions across the model.
|
|
23
|
+
*/
|
|
24
|
+
export default {
|
|
25
|
+
description: 'Properties of type String, Double, Integer, Long, DateTime, Boolean should be camelCase.',
|
|
26
|
+
given: '$.models[*].declarations[?(@.$class && @.$class != "concerto.metamodel@1.0.0.EnumDeclaration")].properties[*].name',
|
|
27
|
+
message: 'Property \'{{value}}\' should be camelCase (e.g. \'myProperty\')',
|
|
28
|
+
severity: 0, // 0 = error, 1 = warning, 2 = info, 3 = hint
|
|
29
|
+
then: {
|
|
30
|
+
function: casing,
|
|
31
|
+
functionOptions: {
|
|
32
|
+
type: 'camel',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { IFunction, IFunctionResult } from '@stoplight/spectral-core';
|
|
16
|
+
|
|
17
|
+
interface StringLengthValidator {
|
|
18
|
+
$class: 'concerto.metamodel@1.0.0.StringLengthValidator';
|
|
19
|
+
minLength: number;
|
|
20
|
+
maxLength: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface StringObject {
|
|
24
|
+
name: string;
|
|
25
|
+
lengthValidator?: StringLengthValidator;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Checks if a String object has a length validator.
|
|
30
|
+
*
|
|
31
|
+
* @param {unknown} targetVal The AST node to check, expected to be a StringProperty or StringScalar object.
|
|
32
|
+
* @returns {IFunctionResult[] | void} An array of results indicating declarations that lack a length validator.
|
|
33
|
+
* @throws {Error} If the input is not a valid object.
|
|
34
|
+
*/
|
|
35
|
+
export const checkLengthValidator: IFunction = (targetVal): IFunctionResult[] => {
|
|
36
|
+
// Validate that targetVal is a non-null object
|
|
37
|
+
if (targetVal === null || typeof targetVal !== 'object') {
|
|
38
|
+
throw new Error('Input must be a valid String AST object.');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const stringObject = targetVal as StringObject;
|
|
42
|
+
const results: IFunctionResult[] = [];
|
|
43
|
+
|
|
44
|
+
// Check for missing length validator
|
|
45
|
+
if (!stringObject.lengthValidator) {
|
|
46
|
+
results.push({
|
|
47
|
+
message: `String '${stringObject.name}' must have a length validator.`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return results;
|
|
52
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { IFunction, IFunctionResult } from '@stoplight/spectral-core';
|
|
16
|
+
|
|
17
|
+
interface Declaration {
|
|
18
|
+
name: string;
|
|
19
|
+
isAbstract?: boolean;
|
|
20
|
+
superType?: { name: string };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface Model {
|
|
24
|
+
declarations: Declaration[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Checks if each abstract declaration in the model has at least one concrete subclass.
|
|
29
|
+
*
|
|
30
|
+
* Iterates through the model's declarations, collects all abstract types,
|
|
31
|
+
* and removes any abstract type that is extended by a concrete subclass.
|
|
32
|
+
* Returns a result for each abstract type without a concrete subclass.
|
|
33
|
+
*
|
|
34
|
+
* @param {unknown} targetVal The AST model object containing declarations.
|
|
35
|
+
* @returns {IFunctionResult[] | void} An array of results for abstract declarations lacking concrete subclasses.
|
|
36
|
+
* @throws {Error} If the input is not a valid model AST.
|
|
37
|
+
*/
|
|
38
|
+
export const hasConcreteSubclass: IFunction = (
|
|
39
|
+
targetVal,
|
|
40
|
+
): IFunctionResult[] | void => {
|
|
41
|
+
const results: IFunctionResult[] = [];
|
|
42
|
+
|
|
43
|
+
// Validate that targetVal is a non-null object
|
|
44
|
+
if (typeof targetVal !== 'object' || !targetVal || !Array.isArray((targetVal as Model).declarations)) {
|
|
45
|
+
throw new Error(`${targetVal} must be a valid AST for concerto model`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const abstractNames = new Map<string, number>();
|
|
49
|
+
const allDeclarations = (targetVal as Model).declarations;
|
|
50
|
+
|
|
51
|
+
for (const [index, decl] of allDeclarations.entries()) {
|
|
52
|
+
if (decl && decl.isAbstract && typeof decl.name === 'string') {
|
|
53
|
+
abstractNames.set(decl.name, index);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
for (const decl of allDeclarations) {
|
|
58
|
+
if (decl && !decl.isAbstract && decl.superType && typeof decl.superType.name === 'string') {
|
|
59
|
+
abstractNames.delete(decl.superType.name);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (abstractNames.size > 0) {
|
|
63
|
+
for (const [abstractName] of abstractNames) {
|
|
64
|
+
results.push({
|
|
65
|
+
message: `Abstract declaration '${abstractName}' must have concrete subclasses`,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return results;
|
|
70
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { IFunction, IFunctionResult } from '@stoplight/spectral-core';
|
|
16
|
+
|
|
17
|
+
interface Declaration {
|
|
18
|
+
name: string;
|
|
19
|
+
properties?: unknown[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Finds and reports empty Concerto Declarations (i.e., declarations with no properties).
|
|
24
|
+
*
|
|
25
|
+
* @param {unknown} targetVal The AST node to check, expected to be a Concerto Declaration object.
|
|
26
|
+
* @returns {IFunctionResult[]} An array of results indicating declarations that are empty.
|
|
27
|
+
* @throws {Error} If the input is not a valid object.
|
|
28
|
+
*/
|
|
29
|
+
export const findEmptyDeclarations: IFunction = (
|
|
30
|
+
targetVal,
|
|
31
|
+
): IFunctionResult[] => {
|
|
32
|
+
const results: IFunctionResult[] = [];
|
|
33
|
+
|
|
34
|
+
// Validate that targetVal is a non-null object
|
|
35
|
+
if (typeof targetVal !== 'object' || targetVal === null) {
|
|
36
|
+
throw new Error('Value must be a valid AST object for a Concerto Declaration.');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Ensure targetVal is a Declaration with a 'properties' field (not a scalar)
|
|
40
|
+
if (!(targetVal as Declaration).properties)
|
|
41
|
+
{
|
|
42
|
+
return results;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const declaration = targetVal as Declaration;
|
|
46
|
+
const properties = declaration.properties;
|
|
47
|
+
|
|
48
|
+
// If 'properties' is missing, not an array, or empty, report an error
|
|
49
|
+
if (!Array.isArray(properties) || properties.length === 0) {
|
|
50
|
+
results.push({
|
|
51
|
+
message: `Declaration '${declaration.name}' should not be empty and must declare at least one property.`,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return results;
|
|
56
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { pattern } from '@stoplight/spectral-functions';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Rule: Namespace Should Specify a Version
|
|
19
|
+
* ----------------------------------------
|
|
20
|
+
* Ensures that the namespace declaration in the model includes a version number.
|
|
21
|
+
* This rule enforces semantic versioning in namespaces, promoting clarity and compatibility management.
|
|
22
|
+
*/
|
|
23
|
+
export default {
|
|
24
|
+
description: 'namespace should specify a version.',
|
|
25
|
+
given: '$.models[0].namespace',
|
|
26
|
+
message: 'namespace \'{{value}}\' should specify a version.',
|
|
27
|
+
severity: 0, // 0 = error, 1 = warning, 2 = info, 3 = hint
|
|
28
|
+
then: {
|
|
29
|
+
function: pattern,
|
|
30
|
+
functionOptions: {
|
|
31
|
+
match: /@\d+\.\d+\.\d+/,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { findEmptyDeclarations } from './functions/find-empty-declarations';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Rule: No Empty Declarations
|
|
19
|
+
* ---------------------------
|
|
20
|
+
* Detects and reports any model declarations that are empty.
|
|
21
|
+
* This rule helps maintain model integrity by ensuring that all declarations contain meaningful content,
|
|
22
|
+
* preventing the inclusion of unused or placeholder declarations in the model.
|
|
23
|
+
*/
|
|
24
|
+
export default {
|
|
25
|
+
given: '$.models[*].declarations[*]',
|
|
26
|
+
severity: 0, // 0 = error, 1 = warning, 2 = info, 3 = hint
|
|
27
|
+
then: {
|
|
28
|
+
function: findEmptyDeclarations
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { pattern } from '@stoplight/spectral-functions';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Rule: No Reserved Keywords with Declarations, Properties, and Decorators
|
|
19
|
+
*
|
|
20
|
+
* This rule enforces that names used for declarations, properties, and decorators
|
|
21
|
+
* in Concerto models do not use reserved keywords. Reserved keywords are language-specific
|
|
22
|
+
* terms that may cause conflicts or unexpected behavior if used as identifiers.
|
|
23
|
+
* If a name matches any of the reserved keywords (case-insensitive), the linter will
|
|
24
|
+
* report an error to prevent its usage.
|
|
25
|
+
*/
|
|
26
|
+
export default {
|
|
27
|
+
description: 'Names should not be reserved words.',
|
|
28
|
+
given: [
|
|
29
|
+
'$.models[*].declarations[*].name',
|
|
30
|
+
'$.models[*].declarations[*].properties[*].name',
|
|
31
|
+
'$.models[*].decorators[*].name',
|
|
32
|
+
'$.models[*].declarations[*].decorators[*].name',
|
|
33
|
+
'$.models[*].declarations[*].properties[*].decorators[*].name'
|
|
34
|
+
],
|
|
35
|
+
message: 'Name "{{value}}" is a reserved keyword.',
|
|
36
|
+
severity: 0, // 0 = error, 1 = warning, 2 = info, 3 = hint
|
|
37
|
+
then: {
|
|
38
|
+
function: pattern,
|
|
39
|
+
functionOptions: {
|
|
40
|
+
notMatch: '/^(String|Double|Integer|Long|DateTime|Boolean|scalar|concept|enum|asset|participant|transaction|event|map|optional|length|regex|range|default)$/i'
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { casing } from '@stoplight/spectral-functions';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Rule: Pascal Case Declarations
|
|
19
|
+
* ------------------------------
|
|
20
|
+
* Ensures that declaration names (scalar, enum, concept, asset, participant, transaction, event)
|
|
21
|
+
* follow PascalCase naming convention (e.g., 'MyDeclaration').
|
|
22
|
+
* This promotes consistency and readability across model declarations.
|
|
23
|
+
*/
|
|
24
|
+
export default {
|
|
25
|
+
description: 'Declaration names (scalar, enum, concept, asset, participant, transaction, event) should be PascalCase.',
|
|
26
|
+
given: '$.models[*].declarations[*].name',
|
|
27
|
+
message: 'Declaration \'{{value}}\' should be PascalCase (e.g. \'MyDeclaration\')',
|
|
28
|
+
severity: 0, // 0 = error, 1 = warning, 2 = info, 3 = hint
|
|
29
|
+
then: {
|
|
30
|
+
function: casing,
|
|
31
|
+
functionOptions: {
|
|
32
|
+
type: 'pascal',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { casing } from '@stoplight/spectral-functions';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Rule: Pascal Case Decorators
|
|
19
|
+
* ------------------------------
|
|
20
|
+
* Ensures that decorator names follow PascalCase naming convention (e.g., 'MyDecorator').
|
|
21
|
+
* This promotes consistency and readability across model decorators.
|
|
22
|
+
*/
|
|
23
|
+
export default {
|
|
24
|
+
description: 'Decorators names should be PascalCase.',
|
|
25
|
+
given: [
|
|
26
|
+
'$.models[*].decorators[*].name',
|
|
27
|
+
'$.models[*].declarations[*].decorators[*].name',
|
|
28
|
+
'$.models[*].declarations[*].properties[*].decorators[*].name'
|
|
29
|
+
],
|
|
30
|
+
message: 'Decorator \'{{value}}\' should be PascalCase (e.g. \'MyDecorator\')',
|
|
31
|
+
severity: 0, // 0 = error, 1 = warning, 2 = info, 3 = hint
|
|
32
|
+
then: {
|
|
33
|
+
function: casing,
|
|
34
|
+
functionOptions: {
|
|
35
|
+
type: 'pascal',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { RulesetDefinition } from '@stoplight/spectral-core';
|
|
16
|
+
|
|
17
|
+
import namespaceVersion from './namespace-version';
|
|
18
|
+
import pascalCaseDeclarations from './pascal-case-declarations';
|
|
19
|
+
import camelCaseProperties from './camel-case-properties';
|
|
20
|
+
import upperSnakeCaseEnumConst from './upper-snake-case-enum-const';
|
|
21
|
+
import pascalCaseDecorators from './pascal-case-decorators';
|
|
22
|
+
import stringLengthValidator from './string-length-validator';
|
|
23
|
+
import noReservedKeywords from './no-reserved-keywords';
|
|
24
|
+
import noEmptyDeclarations from './no-empty-declarations';
|
|
25
|
+
import abstractMustSubclassed from './abstract-must-subclassed';
|
|
26
|
+
|
|
27
|
+
const concertoRuleset: RulesetDefinition = {
|
|
28
|
+
rules: {
|
|
29
|
+
'namespace-version': namespaceVersion,
|
|
30
|
+
'no-reserved-keywords': noReservedKeywords,
|
|
31
|
+
'pascal-case-declarations': pascalCaseDeclarations,
|
|
32
|
+
'camel-case-properties': camelCaseProperties,
|
|
33
|
+
'upper-snake-case-enum-constants': upperSnakeCaseEnumConst,
|
|
34
|
+
'pascal-case-decorators': pascalCaseDecorators,
|
|
35
|
+
'string-length-validator': stringLengthValidator,
|
|
36
|
+
'no-empty-declarations': noEmptyDeclarations,
|
|
37
|
+
'abstract-must-subclassed': abstractMustSubclassed,
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default concertoRuleset;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { checkLengthValidator } from './functions/check-length-validator';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Rule: String Length
|
|
19
|
+
* ---------------------------
|
|
20
|
+
* Ensures that all string within the data model have a length validator applied.
|
|
21
|
+
* Which helps prevent inconsistent data length and ensure proper storage."
|
|
22
|
+
*/
|
|
23
|
+
export default {
|
|
24
|
+
given: [
|
|
25
|
+
'$.models[*].declarations[?(@.$class=="concerto.metamodel@1.0.0.StringScalar")]',
|
|
26
|
+
'$.models[*].declarations[*].properties[?(@.$class=="concerto.metamodel@1.0.0.StringProperty")]'
|
|
27
|
+
],
|
|
28
|
+
severity: 0, // 0 = error, 1 = warning, 2 = info, 3 = hint
|
|
29
|
+
then: {
|
|
30
|
+
function: checkLengthValidator,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { pattern } from '@stoplight/spectral-functions';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Rule: Enum Constants Must Use UPPER_SNAKE_CASE
|
|
19
|
+
* ----------------------------------------------
|
|
20
|
+
* Enforces that all enum constant names follow the UPPER_SNAKE_CASE convention.
|
|
21
|
+
* This rule checks each enum property name and reports an error if it does not match the required pattern.
|
|
22
|
+
* Ensures consistency and readability in enum naming across the model.
|
|
23
|
+
*/
|
|
24
|
+
export default {
|
|
25
|
+
|
|
26
|
+
description: 'Enum constants must use UPPER_SNAKE_CASE.',
|
|
27
|
+
given: '$.models[*].declarations[?(@.$class == "concerto.metamodel@1.0.0.EnumDeclaration")].properties[*].name',
|
|
28
|
+
message: 'Enum constant \'{{value}}\' should be UPPER_SNAKE_CASE (e.g. \'MY_CONSTANT\')',
|
|
29
|
+
severity: 0, // 0 = error, 1 = warning, 2 = info, 3 = hint
|
|
30
|
+
then: {
|
|
31
|
+
function: pattern,
|
|
32
|
+
functionOptions: {
|
|
33
|
+
match: '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
namespace org.example@1.0.0
|
|
2
|
+
|
|
3
|
+
abstract concept Vehicle {
|
|
4
|
+
o String make
|
|
5
|
+
o String model
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
concept Car extends Vehicle {
|
|
9
|
+
o Integer numberOfDoors
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
abstract asset Product {
|
|
13
|
+
o String productId
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
asset Electronics extends Product {
|
|
17
|
+
o String brand
|
|
18
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
namespace org.example@1.0.0
|
|
2
|
+
|
|
3
|
+
scalar SsnNumber extends String default="000-00-0000"
|
|
4
|
+
|
|
5
|
+
concept MyProduct {
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
asset PaymentOrder {
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
participant Customer {
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
transaction Order {
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
event LateDelivery {
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
enum Product {
|
|
21
|
+
}
|