Skip to content

Commit

Permalink
feat(Dpe 135): naming rules (#85)
Browse files Browse the repository at this point in the history
+ updated the camel case rule to use the built in casing function
instead of regex to get performance
+ Addressed all the comments on the confluence page
+ Updated documentation with links

---------

Signed-off-by: Ethan Honzik <105084033+EthanHonzikSPS@users.noreply.github.com>
Co-authored-by: Brandon Sahadeo <50463922+brandonsahadeo@users.noreply.github.com>
  • Loading branch information
EthanHonzikSPS and brandonsahadeo authored Jul 17, 2024
1 parent 0995d49 commit cd1301c
Show file tree
Hide file tree
Showing 25 changed files with 3,826 additions and 1,730 deletions.
3,753 changes: 2,160 additions & 1,593 deletions rulesets/package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions rulesets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
"@stoplight/spectral-ruleset-bundler": "^1.2.1",
"@stoplight/spectral-runtime": "^1.1.2",
"@stoplight/types": "^13.3.0",
"jest": "^28.1.1"
"@types/jest": "^29.5.12",
"@types/node": "^20.14.9",
"jest": "^28.1.3"
},
"scripts": {
"test": "jest"
Expand All @@ -20,4 +22,4 @@
"linting",
"spscommerce"
]
}
}
201 changes: 193 additions & 8 deletions rulesets/src/naming.ruleset.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,46 @@
rules:
# domain references (URN-like values)
##### General #####
sps-no-keyword-conflicts:
description: Names that may conflict with keywords in common programming languages SHOULD NOT be used.
severity: warn
given: "$..properties.*~"
then:
function: pattern
functionOptions:
notMatch: ^(abstract|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|volatile|const|float|native|super|while)$

##### Property Names #####
sps-camel-case-properties:
description: Property names and acronyms MUST be in camelCase.
severity: error
formats: [oas3]
given: "$..properties.*~"
then:
function: casing
functionOptions:
type: camel

sps-disallowed-prepositions:
description: Property names SHOULD NOT include prepositions (e.g. "for", "during", "at", etc.)
severity: warn
formats: [oas3]
given: "$..properties.*~"
then:
function: pattern
functionOptions:
notMatch: (^(about|above|across|after|against|among|around|at|before|behind|below|beside|between|down|during|for|from|in|inside|into|near|of|off|on|out|over|through|to|toward|under|up|with|as|but|like|since|than|till|unlike|until|upon|within|without)([A-Z]|$)|.*(About|Above|Across|After|Against|Among|Around|At|Before|Behind|Below|Beside|Between|Down|During|For|From|In|Inside|Into|Near|Of|Off|On|Out|Over|Through|To|Toward|Under|Up|With|As|But|Like|Since|Than|Till|Unlike|Until|Upon|Within|Without)([A-Z]|$)).*

sps-disallowed-boolean-prefixes:
description: Boolean properties SHOULD NOT use is, has, or another prefix.
severity: warn
formats: [oas3]
given: "$..properties[?(@ && @.type == 'boolean')]~"
then:
function: pattern
functionOptions:
notMatch: "^(is|has|was|will|needs|uses|should|can)([A-Z]|$).*"

##### Domain References #####
sps-ref-property-name:
description: Property with the name 'ref' MUST be of type 'sps-ref' following URN-like reference formats.
severity: error
Expand Down Expand Up @@ -52,19 +93,152 @@ rules:
functionOptions:
match: "^string$"

# fingerprint property usage and naming
sps-fingerprint-naming:
description: Rather than property names refering to the implementation for 'hash' or 'hashkey', you MUST use the property name 'fingerprint'.
message: "{{property}} is not using property name fingerprint."
##### Standard Properties #####
sps-invalid-id-type:
description: id SHOULD use a data type of 'string'.
severity: warn
formats: [oas3]
given: '$..[?(@property === "id")].type'
then:
function: pattern
functionOptions:
match: "^string$"

sps-mandate-abbreviations-identifier:
description: Use abbreviations instead of long form names, i.e. identifier SHOULD BE id.
severity: warn
formats: [oas3]
given: '$..properties.*~'
then:
function: pattern
functionOptions:
notMatch: "(^identifier([A-Z]|$)|.*Identifier([A-Z]|$))"

sps-mandate-abbreviations-organization:
description: Use abbreviations instead of long form names, i.e. organization SHOULD BE org.
severity: warn
formats: [oas3]
given: '$..properties.*~'
then:
function: pattern
functionOptions:
notMatch: "(^organization([A-Z]|$)|Organization([A-Z]|$))"

sps-invalid-ref-type:
description: ref MUST use a data type of 'string'.
severity: error
formats: [oas3]
given: "$.components.schemas..properties.*~"
given: '$..[?(@property === "ref")].type'
then:
function: pattern
functionOptions:
notMatch: "^hashkey|hashKey|hash$"
match: "^string$"

sps-invalid-orgid-type:
description: orgId MUST use a data type of 'string'.
severity: error
formats: [oas3]
given: '$..[?(@property === "orgId")].type'
then:
function: pattern
functionOptions:
match: "^string$"

sps-fingerprint-type:
sps-invalid-name-type:
description: name MUST use a data type of 'string'.
severity: error
formats: [oas3]
given: '$..[?(@property === "name")].type'
then:
function: pattern
functionOptions:
match: "^string$"

sps-invalid-description-type:
description: description MUST use a data type of 'string'.
severity: error
formats: [oas3]
given: '$..[?(@property === "description")].type'
then:
function: pattern
functionOptions:
match: "^string$"

sps-invalid-request-id-type:
description: requestId MUST use a data type of 'string'.
severity: error
formats: [oas3]
given: '$..[?(@property === "requestId")].type'
then:
function: pattern
functionOptions:
match: "^string$"

sps-invalid-created-date-time-type:
description: createdDateTime MUST use a data type of 'string' with the format 'date-time'.
severity: error
formats: [oas3]
given: "$..properties.createdDateTime"
then:
- field: type
function: pattern
functionOptions:
match: "^string$"
- field: format
function: truthy
- field: format
function: pattern
functionOptions:
match: "^date-time$"

sps-invalid-created-by-type:
description: createdBy MUST use a data type of 'string'.
severity: error
formats: [oas3]
given: '$..[?(@property === "createdBy")].type'
then:
function: pattern
functionOptions:
match: "^string$"

sps-invalid-modified-date-time-type:
description: modifiedDateTime MUST use a data type of 'string' with the format 'date-time'.
severity: error
formats: [oas3]
given: "$..properties.modifiedDateTime"
then:
- field: type
function: pattern
functionOptions:
match: "^string$"
- field: format
function: truthy
- field: format
function: pattern
functionOptions:
match: "^date-time$"

sps-invalid-modified-by-type:
description: modifiedBy MUST use a data type of 'string'.
severity: error
formats: [oas3]
given: '$..[?(@property === "modifiedBy")].type'
then:
function: pattern
functionOptions:
match: "^string$"

sps-invalid-deleted-by-type:
description: deletedBy MUST use a data type of 'string'.
severity: error
formats: [oas3]
given: '$..[?(@property === "deletedBy")].type'
then:
function: pattern
functionOptions:
match: "^string$"

sps-invalid-fingerprint-type:
description: Fingerprint values MUST use a data type of `string`.
severity: error
formats: [oas3]
Expand All @@ -73,3 +247,14 @@ rules:
function: pattern
functionOptions:
match: "^string$"

sps-fingerprint-naming:
description: Rather than property names refering to the implementation for 'hash' or 'hashkey', you MUST use the property name 'fingerprint'.
message: "{{property}} is not using property name fingerprint."
severity: error
formats: [oas3]
given: "$.components.schemas..properties.*~"
then:
function: pattern
functionOptions:
notMatch: "^hashkey|hashKey|hash$"
2 changes: 1 addition & 1 deletion rulesets/test/harness/spectral-test-harness.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,4 @@ class SpectralTestHarness {

module.exports = {
SpectralTestHarness
};
};
110 changes: 110 additions & 0 deletions rulesets/test/naming/sps-camel-case-properties.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
const { SpectralTestHarness } = require("../harness/spectral-test-harness.js");

describe("sps-camel-case-properties", () => {
let spectral = null;
const ruleName = "sps-camel-case-properties";
const ruleset = "src/naming.ruleset.yml";

beforeEach(async () => {
spectral = new SpectralTestHarness(ruleset);
});

test("valid property names", async () => {
const spec = `
openapi: 3.0.1
paths:
/users:
post:
requestBody:
content:
application/json:
schema:
type: object
properties:
orderNumber:
type: string
lineItemNumber:
type: integer
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: object
properties:
userId:
type: string
userName:
type: string
test1:
type: string
`;

await spectral.validateSuccess(spec, ruleName);
});

test("invalid usage of camel casing in property names", async () => {
const spec = `
openapi: 3.0.1
paths:
/users:
post:
requestBody:
content:
application/json:
schema:
type: object
properties:
OrderNumber:
type: string
line_item_number:
type: integer
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: object
properties:
User_Id:
type: string
user_Name:
type: string
`;

await spectral.validateFailure(spec, ruleName, "Error", 4);
});

test("invalid usage of camel casing for acronyms", async () => {
const spec = `
openapi: 3.0.1
paths:
/users:
post:
requestBody:
content:
application/json:
schema:
type: object
properties:
orderID:
type: string
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: object
properties:
userID:
type: string
userName:
type: string
`;

await spectral.validateFailure(spec, ruleName, "Error", 2);
});
});
Loading

0 comments on commit cd1301c

Please sign in to comment.