Skip to content

Commit 95380ff

Browse files
authored
Merge pull request #15 from josstn/non-ascii-services
Support non-ascii characters in service name, operation name and parameter name.
2 parents 09ff143 + 7588831 commit 95380ff

13 files changed

+172
-29
lines changed

src/openApi/v2/parser/getOperationName.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
import camelCase from 'camelcase';
22

3+
import sanitizeOperationName from '../../../utils/sanitizeOperationName';
4+
35
/**
46
* Convert the input value to a correct operation (method) classname.
57
* This will use the operation ID - if available - and otherwise fallback
68
* on a generated name from the URL
79
*/
810
export const getOperationName = (url: string, method: string, operationId?: string): string => {
911
if (operationId) {
10-
return camelCase(
11-
operationId
12-
.replace(/^[^a-zA-Z]+/g, '')
13-
.replace(/[^\w\-]+/g, '-')
14-
.trim()
15-
);
12+
return camelCase(sanitizeOperationName(operationId).trim());
1613
}
1714

1815
const urlWithoutPlaceholders = url
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
import camelCase from 'camelcase';
22

33
import { reservedWords } from '../../../utils/reservedWords';
4+
import sanitizeOperationParameterName from '../../../utils/sanitizeOperationParameterName';
45

56
/**
67
* Replaces any invalid characters from a parameter name.
78
* For example: 'filter.someProperty' becomes 'filterSomeProperty'.
89
*/
910
export const getOperationParameterName = (value: string): string => {
10-
const clean = value
11-
.replace(/^[^a-zA-Z]+/g, '')
12-
.replace(/[^\w\-]+/g, '-')
13-
.trim();
11+
const clean = sanitizeOperationParameterName(value).trim();
1412
return camelCase(clean).replace(reservedWords, '_$1');
1513
};
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import camelCase from 'camelcase';
22

3+
import sanitizeServiceName from '../../../utils/sanitizeServiceName';
4+
35
/**
46
* Convert the input value to a correct service name. This converts
57
* the input string to PascalCase.
68
*/
79
export const getServiceName = (value: string): string => {
8-
const clean = value
9-
.replace(/^[^a-zA-Z]+/g, '')
10-
.replace(/[^\w\-]+/g, '-')
11-
.trim();
10+
const clean = sanitizeServiceName(value).trim();
1211
return camelCase(clean, { pascalCase: true });
1312
};

src/openApi/v3/parser/getOperationName.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
import camelCase from 'camelcase';
22

3+
import sanitizeOperationName from '../../../utils/sanitizeOperationName';
4+
35
/**
46
* Convert the input value to a correct operation (method) classname.
57
* This will use the operation ID - if available - and otherwise fallback
68
* on a generated name from the URL
79
*/
810
export const getOperationName = (url: string, method: string, operationId?: string): string => {
911
if (operationId) {
10-
return camelCase(
11-
operationId
12-
.replace(/^[^a-zA-Z]+/g, '')
13-
.replace(/[^\w\-]+/g, '-')
14-
.trim()
15-
);
12+
return camelCase(sanitizeOperationName(operationId).trim());
1613
}
1714

1815
const urlWithoutPlaceholders = url
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
import camelCase from 'camelcase';
22

33
import { reservedWords } from '../../../utils/reservedWords';
4+
import sanitizeOperationParameterName from '../../../utils/sanitizeOperationParameterName';
45

56
/**
67
* Replaces any invalid characters from a parameter name.
78
* For example: 'filter.someProperty' becomes 'filterSomeProperty'.
89
*/
910
export const getOperationParameterName = (value: string): string => {
10-
const clean = value
11-
.replace(/^[^a-zA-Z]+/g, '')
12-
.replace('[]', 'Array')
13-
.replace(/[^\w\-]+/g, '-')
14-
.trim();
11+
const clean = sanitizeOperationParameterName(value).trim();
1512
return camelCase(clean).replace(reservedWords, '_$1');
1613
};

src/openApi/v3/parser/getServiceName.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ describe('getServiceName', () => {
99
expect(getServiceName('@fooBar')).toEqual('FooBar');
1010
expect(getServiceName('$fooBar')).toEqual('FooBar');
1111
expect(getServiceName('123fooBar')).toEqual('FooBar');
12+
expect(getServiceName('non-ascii-æøåÆØÅöôêÊ字符串')).toEqual('NonAsciiÆøåÆøÅöôêÊ字符串');
1213
});
1314
});
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import camelCase from 'camelcase';
22

3+
import sanitizeServiceName from '../../../utils/sanitizeServiceName';
4+
35
/**
46
* Convert the input value to a correct service name. This converts
57
* the input string to PascalCase.
68
*/
79
export const getServiceName = (value: string): string => {
8-
const clean = value
9-
.replace(/^[^a-zA-Z]+/g, '')
10-
.replace(/[^\w\-]+/g, '-')
11-
.trim();
10+
const clean = sanitizeServiceName(value).trim();
1211
return camelCase(clean, { pascalCase: true });
1312
};

src/utils/sanitizeOperationName.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import sanitizeServiceName from './sanitizeServiceName';
2+
3+
/**
4+
* sanitizeOperationName does the same as sanitizeServiceName.
5+
*/
6+
const sanitizeOperationName = sanitizeServiceName;
7+
export default sanitizeOperationName;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import sanitizeOperationName from './sanitizeOperationName';
2+
3+
const sanitizeOperationParameterName = (name: string): string => {
4+
const withoutBrackets = name.replace('[]', 'Array');
5+
return sanitizeOperationName(withoutBrackets);
6+
};
7+
export default sanitizeOperationParameterName;

src/utils/sanitizeServiceName.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Sanitizes service names, so they are valid typescript identifiers of a certain form.
3+
*
4+
* 1: Remove any leading characters that are illegal as starting character of a typescript identifier.
5+
* 2: Replace illegal characters in remaining part of type name with underscore (-).
6+
*
7+
* Step 1 should perhaps instead also replace illegal characters with underscore, or prefix with it, like sanitizeEnumName
8+
* does. The way this is now one could perhaps end up removing all characters, if all are illegal start characters. It
9+
* would be sort of a breaking change to do so, though, previously generated code might change then.
10+
*
11+
* Javascript identifier regexp pattern retrieved from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers
12+
*
13+
* The output of this is expected to be converted to PascalCase
14+
*/
15+
const sanitizeServiceName = (name: string) =>
16+
name.replace(/^[^\p{ID_Start}]+/u, '').replace(/[^$\u200c\u200d\p{ID_Continue}]/gu, '-');
17+
18+
export default sanitizeServiceName;

0 commit comments

Comments
 (0)