Skip to content

Commit e75b075

Browse files
authored
Merge pull request #56 from shakrav2/feature/aep-143
Add rules for aep-143 with docs and tests
2 parents 8a155b0 + 45275ed commit e75b075

File tree

7 files changed

+875
-0
lines changed

7 files changed

+875
-0
lines changed

aep/0143.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
functionsDir: ../functions
2+
functions:
3+
- standardized-codes
4+
5+
rules:
6+
aep-143-standardized-codes:
7+
description: Field names for standardized codes must follow AEP-143 conventions.
8+
message: '{{error}}'
9+
severity: error
10+
formats: ['oas2', 'oas3']
11+
given: $.components.schemas[*]
12+
then:
13+
function: standardized-codes
14+
15+
aep-143-standardized-codes-string-type:
16+
description: Standardized code fields must be of type "string".
17+
message: 'Standardized code field "{{property}}" must be type "string"'
18+
severity: error
19+
formats: ['oas2', 'oas3']
20+
given:
21+
- $.components.schemas[*].properties[?(@property in ['content_type', 'currency_code', 'language_code'])]
22+
- $.components.schemas[*].properties[?(@property in ['region_code', 'time_zone', 'utc_offset'])]
23+
then:
24+
function: schema
25+
functionOptions:
26+
schema:
27+
type: object
28+
required: ['type']
29+
properties:
30+
type:
31+
const: string

docs/0143.md

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
# Rules for AEP-143: Standardized codes
2+
3+
[aep-143]: https://aep.dev/143
4+
5+
This document covers the linting rules for [AEP-143][], which provides guidance
6+
on using standardized codes for common concepts like languages, regions,
7+
currencies, and time zones.
8+
9+
## aep-143-standardized-codes
10+
11+
**Rule**: Field names for standardized codes must follow AEP-143 conventions.
12+
13+
This rule enforces that field names use the correct standardized terminology
14+
for common concepts like languages, currencies, regions, and media types.
15+
16+
### Details
17+
18+
This rule checks schema property names and flags incorrect variants, suggesting
19+
the correct standardized field name according to AEP-143.
20+
21+
#### Limitations
22+
23+
This rule uses a **map-based detection approach** that only catches explicitly
24+
listed field name variants. While it covers the most common incorrect naming
25+
patterns, it cannot detect all possible variations developers might use.
26+
27+
**What this means:**
28+
29+
- ✅ Catches common mistakes like `lang`, `country`, `mime_type`, etc.
30+
- ❌ Won't catch creative variations like `user_locale`, `iso_country`, or
31+
`document_mime`
32+
- ✅ Low false positive rate - only flags known incorrect patterns
33+
- ❌ May miss some non-standard field names that should use standardized codes
34+
35+
**Why this approach:**
36+
37+
Pattern-based detection (e.g., flagging any field containing "language" or
38+
"country") would produce too many false positives. The map-based approach is
39+
intentionally conservative to maintain high precision.
40+
41+
**Recommendation:** Use this rule as a first-pass check, but rely on human code
42+
review to catch edge cases and uncommon field name variations. If you encounter
43+
a common variant that should be flagged, consider contributing it to the
44+
linter.
45+
46+
### Field Name Standards
47+
48+
| Concept | Correct Field Name | Incorrect Variants | Standard |
49+
| ------------------ | ------------------ | ---------------------------------------------------------- | ---------------- |
50+
| Language | `language_code` | `lang`, `language`, `locale` | IETF BCP-47 |
51+
| Country/Region | `region_code` | `country`, `country_code`, `region` | Unicode CLDR |
52+
| Currency | `currency_code` | `currency` | ISO-4217 |
53+
| Content/Media Type | `content_type` | `mime`, `mimetype`, `mime_type`, `media_type`, `mediatype` | IANA media types |
54+
| Time Zone | `time_zone` | `tz`, `timezone` | IANA TZ |
55+
56+
### Examples
57+
58+
**Incorrect** code for this rule:
59+
60+
```yaml
61+
components:
62+
schemas:
63+
book:
64+
type: object
65+
properties:
66+
title:
67+
type: string
68+
lang: # Should be language_code
69+
type: string
70+
country: # Should be region_code
71+
type: string
72+
```
73+
74+
**Correct** code for this rule:
75+
76+
```yaml
77+
components:
78+
schemas:
79+
book:
80+
type: object
81+
properties:
82+
title:
83+
type: string
84+
language_code:
85+
type: string
86+
description: IETF BCP-47 language code (e.g., en-US, de-CH)
87+
region_code:
88+
type: string
89+
description: Unicode CLDR region code (e.g., US, CH)
90+
```
91+
92+
### Disabling
93+
94+
If you need to violate this rule, add an override to your Spectral
95+
configuration:
96+
97+
```yaml
98+
overrides:
99+
- files:
100+
- 'openapi.json#/components/schemas/book'
101+
rules:
102+
aep-143-standardized-codes: 'off'
103+
```
104+
105+
## aep-143-standardized-codes-string-type
106+
107+
**Rule**: Standardized code fields must be of type string.
108+
109+
This rule enforces that all standardized code fields (language_code,
110+
region_code, currency_code, content_type, time_zone, utc_offset) use type
111+
`string`.
112+
113+
### Details
114+
115+
According to AEP-143, standardized code fields must use the appropriate data
116+
type for standard codes (usually `string`), and should not use enums even if
117+
they only allow a small subset of possible values.
118+
119+
This rule checks the following fields:
120+
121+
- `language_code`
122+
- `region_code`
123+
- `currency_code`
124+
- `content_type`
125+
- `time_zone`
126+
- `utc_offset`
127+
128+
### Examples
129+
130+
**Incorrect** code for this rule:
131+
132+
```yaml
133+
components:
134+
schemas:
135+
book:
136+
type: object
137+
properties:
138+
language_code:
139+
type: integer # Wrong type
140+
description: Language code
141+
```
142+
143+
**Correct** code for this rule:
144+
145+
```yaml
146+
components:
147+
schemas:
148+
book:
149+
type: object
150+
properties:
151+
language_code:
152+
type: string
153+
description: IETF BCP-47 language code (e.g., en-US, de-CH)
154+
```
155+
156+
### Disabling
157+
158+
If you need to violate this rule, add an override to your Spectral
159+
configuration:
160+
161+
```yaml
162+
overrides:
163+
- files:
164+
- 'openapi.json#/components/schemas/book/properties/language_code'
165+
rules:
166+
aep-143-standardized-codes-string-type: 'off'
167+
```
168+
169+
## References
170+
171+
- [AEP-143: Standardized codes][aep-143]
172+
- [IETF BCP-47 Language Tags](https://en.wikipedia.org/wiki/IETF_language_tag)
173+
- [Unicode CLDR Region Codes](http://cldr.unicode.org/)
174+
- [ISO-4217 Currency Codes](https://en.wikipedia.org/wiki/ISO_4217)
175+
- [IANA Media Types](https://www.iana.org/assignments/media-types/)
176+
- [IANA Time Zones](http://www.iana.org/time-zones)

docs/rules.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- [Rules for AEP-137](./0137.md)
1111
- [Rules for AEP-140](./0140.md)
1212
- [Rules for AEP-142](./0142.md)
13+
- [Rules for AEP-143](./0143.md)
1314
- [Rules for AEP-144](./0144.md)
1415
- [Rules for AEP-151](./0151.md)
1516
- [Rules for AEP-158](./0158.md)

functions/standardized-codes.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Validates that standardized code field names follow AEP-143 conventions.
2+
// Checks schema property names and suggests correct standardized field names.
3+
4+
// Map of incorrect field name variants to their correct standardized names
5+
const fieldNameVariants = {
6+
// Content/Media types
7+
mime: 'content_type',
8+
mimetype: 'content_type',
9+
mime_type: 'content_type',
10+
media_type: 'content_type',
11+
mediatype: 'content_type',
12+
// Countries/Regions
13+
country: 'region_code',
14+
country_code: 'region_code',
15+
region: 'region_code',
16+
// Currency
17+
currency: 'currency_code',
18+
// Language
19+
lang: 'language_code',
20+
language: 'language_code',
21+
locale: 'language_code',
22+
// Time zones
23+
tz: 'time_zone',
24+
timezone: 'time_zone',
25+
};
26+
27+
// targetVal is a schema object containing properties
28+
module.exports = (schema, _opts, paths) => {
29+
if (!schema || typeof schema !== 'object') {
30+
return [];
31+
}
32+
33+
const errors = [];
34+
const path = paths.path || paths.target || [];
35+
36+
// Check if this is a schema with properties
37+
if (schema.properties && typeof schema.properties === 'object') {
38+
Object.keys(schema.properties).forEach((propertyName) => {
39+
const correctName = fieldNameVariants[propertyName];
40+
if (correctName) {
41+
errors.push({
42+
message: `Use "${correctName}" instead of "${propertyName}" for standardized code fields.`,
43+
path: [...path, 'properties', propertyName],
44+
});
45+
}
46+
});
47+
}
48+
49+
return errors;
50+
};

spectral.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ extends:
1010
- ./aep/0137.yaml
1111
- ./aep/0140.yaml
1212
- ./aep/0142.yaml
13+
- ./aep/0143.yaml
1314
- ./aep/0144.yaml
1415
- ./aep/0151.yaml
1516
- ./aep/0158.yaml
@@ -19,6 +20,7 @@ functions:
1920
- aep-142-time-field-type
2021
- parameter-names-unique
2122
- operations-endpoint
23+
- standardized-codes
2224
rules:
2325
openapi-tags: off
2426
operation-tags: off

0 commit comments

Comments
 (0)