@kevinoid/openapi-transformers 0.1.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.
Files changed (50) hide show
  1. package/LICENSE.txt +19 -0
  2. package/README.md +134 -0
  3. package/add-tag-to-operation-ids.js +60 -0
  4. package/add-x-ms-enum-name.js +96 -0
  5. package/add-x-ms-enum-value-names.js +142 -0
  6. package/additional-properties-to-object.js +35 -0
  7. package/additional-properties-to-unconstrained.js +115 -0
  8. package/any-of-null-to-nullable.js +50 -0
  9. package/assert-properties.js +56 -0
  10. package/binary-string-to-file.js +54 -0
  11. package/bool-enum-to-bool.js +100 -0
  12. package/clear-html-response-schema.js +77 -0
  13. package/client-params-to-global.js +97 -0
  14. package/const-to-enum.js +49 -0
  15. package/escape-enum-values.js +211 -0
  16. package/exclusive-min-max-to-bool.js +61 -0
  17. package/format-to-type.js +54 -0
  18. package/index.js +94 -0
  19. package/inline-non-object-schemas.js +120 -0
  20. package/lib/component-manager.js +60 -0
  21. package/lib/matching-component-manager.js +74 -0
  22. package/lib/matching-parameter-manager.js +36 -0
  23. package/merge-all-of.js +60 -0
  24. package/merge-any-of.js +48 -0
  25. package/merge-one-of.js +48 -0
  26. package/nullable-not-required.js +240 -0
  27. package/nullable-to-type-null.js +46 -0
  28. package/openapi31to30.js +54 -0
  29. package/package.json +131 -0
  30. package/path-parameters-to-operations.js +63 -0
  31. package/pattern-properties-to-additional-properties.js +62 -0
  32. package/queries-to-x-ms-paths.js +63 -0
  33. package/read-only-not-required.js +111 -0
  34. package/ref-path-parameters.js +73 -0
  35. package/remove-default-only-response-produces.js +58 -0
  36. package/remove-paths-with-servers.js +34 -0
  37. package/remove-query-from-paths.js +526 -0
  38. package/remove-ref-siblings.js +78 -0
  39. package/remove-request-body.js +102 -0
  40. package/remove-response-headers.js +42 -0
  41. package/remove-security-scheme-if.js +166 -0
  42. package/remove-type-if.js +65 -0
  43. package/rename-components.js +285 -0
  44. package/replaced-by-to-description.js +50 -0
  45. package/server-vars-to-path-params.js +224 -0
  46. package/server-vars-to-x-ms-parameterized-host.js +247 -0
  47. package/type-null-to-enum.js +47 -0
  48. package/type-null-to-nullable.js +57 -0
  49. package/urlencoded-to-string.js +160 -0
  50. package/x-enum-to-ms.js +92 -0
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @copyright Copyright 2025 Kevin Locke <kevin@kevinlocke.name>
3
+ * @license MIT
4
+ * @module "openapi-transformers/assert-properties.js"
5
+ */
6
+
7
+ import OpenApiTransformerBase from 'openapi-transformer-base';
8
+
9
+ /**
10
+ * Transformer which throws an Error when given properties are present in the
11
+ * OpenAPI document.
12
+ */
13
+ export default class AssertPropertiesTransformer
14
+ extends OpenApiTransformerBase {
15
+ options = {};
16
+
17
+ constructor(options) {
18
+ super();
19
+
20
+ if (typeof options !== 'object' || options === null) {
21
+ throw new TypeError('options must be an object');
22
+ }
23
+
24
+ if (typeof options.schema !== 'object' || options.schema === null) {
25
+ throw new TypeError('options.schema must be an object');
26
+ }
27
+
28
+ if (!Array.isArray(options.schema.excludes)) {
29
+ throw new TypeError('options.schema.excludes must be an Array');
30
+ }
31
+
32
+ if (!options.schema.excludes.every((s) => typeof s === 'string')) {
33
+ throw new TypeError(
34
+ 'options.schema.excludes must only contain property names',
35
+ );
36
+ }
37
+
38
+ this.options = options;
39
+ }
40
+
41
+ transformSchema(schema) {
42
+ const newSchema = super.transformSchema(schema);
43
+ if (typeof newSchema !== 'object' || newSchema === null) {
44
+ return newSchema;
45
+ }
46
+
47
+ for (const propName of this.options.schema.excludes) {
48
+ if (newSchema[propName] !== undefined
49
+ && Object.hasOwn(newSchema, propName)) {
50
+ throw new Error(`Schema contains ${propName}`);
51
+ }
52
+ }
53
+
54
+ return newSchema;
55
+ }
56
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @copyright Copyright 2019 Kevin Locke <kevin@kevinlocke.name>
3
+ * @license MIT
4
+ * @module "openapi-transformers/binary-string-to-file.js"
5
+ */
6
+
7
+ import OpenApiTransformerBase from 'openapi-transformer-base';
8
+
9
+ function transformSchemaType(schema) {
10
+ if (schema.type === 'string'
11
+ && (schema.format === 'binary' || schema.format === 'file')) {
12
+ const newSchema = {
13
+ ...schema,
14
+ type: 'file',
15
+ };
16
+ delete newSchema.format;
17
+ return newSchema;
18
+ }
19
+
20
+ return schema;
21
+ }
22
+
23
+ /**
24
+ * Transformer to replace `type: string, format: binary` (or `format: file`)
25
+ * with `type: file` so that Autorest generates to a Stream instead of string.
26
+ */
27
+ export default class BinaryStringToFileTransformer
28
+ extends OpenApiTransformerBase {
29
+ // eslint-disable-next-line class-methods-use-this
30
+ transformSchema(schema) {
31
+ // Don't call super, since `type: file` is only allowed on root schema of
32
+ // response.
33
+ // Note: No checking is done to enforce this (due to $ref complications).
34
+ // Note: A response could $ref a property schema. Unlikely.
35
+ return transformSchemaType(schema);
36
+ }
37
+
38
+ // eslint-disable-next-line class-methods-use-this
39
+ transformParameter(parameter) {
40
+ if (parameter === null || typeof parameter !== 'object') {
41
+ return parameter;
42
+ }
43
+
44
+ let newParameter = transformSchemaType(parameter);
45
+ if (newParameter.schema) {
46
+ newParameter = {
47
+ ...newParameter,
48
+ schema: transformSchemaType(newParameter.schema),
49
+ };
50
+ }
51
+
52
+ return newParameter;
53
+ }
54
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ * @copyright Copyright 2021 Kevin Locke <kevin@kevinlocke.name>
3
+ * @license MIT
4
+ * @module "openapi-transformers/bool-enum-to-bool.js"
5
+ */
6
+
7
+ import OpenApiTransformerBase from 'openapi-transformer-base';
8
+
9
+ const inStringContextSymbol = Symbol('inStringContext');
10
+
11
+ /**
12
+ * Transformer to replace `enum: [true, false]` with `type: boolean` for
13
+ * simplicity and to assist generators.
14
+ */
15
+ export default class BoolEnumToBoolTransformer
16
+ extends OpenApiTransformerBase {
17
+ constructor() {
18
+ super();
19
+ this[inStringContextSymbol] = false;
20
+ }
21
+
22
+ transformSchemaLike(schema) {
23
+ if (schema === null
24
+ || typeof schema !== 'object'
25
+ || Array.isArray(schema)) {
26
+ return schema;
27
+ }
28
+
29
+ const { enum: enumValues, ...schemaNoEnum } = schema;
30
+ if (!Array.isArray(enumValues) || enumValues.length < 2) {
31
+ return schema;
32
+ }
33
+
34
+ const { type } = schema;
35
+ if (!this[inStringContextSymbol]
36
+ && type !== 'boolean'
37
+ && !enumValues.every((ev) => typeof ev === 'boolean')) {
38
+ // If schema validates non-boolean values in a type-sensitive context,
39
+ // limiting to boolean would change validation.
40
+ return schema;
41
+ }
42
+
43
+ if (!(enumValues.includes(true) || enumValues.includes('true'))
44
+ || !(enumValues.includes(false) || enumValues.includes('false'))
45
+ || enumValues.some((ev) => ev !== true
46
+ && ev !== false
47
+ && ev !== 'true'
48
+ && ev !== 'false')) {
49
+ // Enum must contain both true and false, and only true/false
50
+ return schema;
51
+ }
52
+
53
+ schemaNoEnum.type = 'boolean';
54
+
55
+ return schemaNoEnum;
56
+ }
57
+
58
+ transformSchema(schema) {
59
+ return this.transformSchemaLike(super.transformSchema(schema));
60
+ }
61
+
62
+ transformItems(items) {
63
+ return this.transformSchemaLike(super.transformItems(items));
64
+ }
65
+
66
+ transformHeader(header) {
67
+ const prevContext = this[inStringContextSymbol];
68
+ try {
69
+ this[inStringContextSymbol] = true;
70
+ return this.transformSchemaLike(super.transformHeader(header));
71
+ } finally {
72
+ this[inStringContextSymbol] = prevContext;
73
+ }
74
+ }
75
+
76
+ transformParameter(parameter) {
77
+ const prevContext = this[inStringContextSymbol];
78
+ try {
79
+ this[inStringContextSymbol] = parameter.in !== 'body';
80
+ return this.transformSchemaLike(super.transformParameter(parameter));
81
+ } finally {
82
+ this[inStringContextSymbol] = prevContext;
83
+ }
84
+ }
85
+
86
+ transformMediaType(mediaType) {
87
+ const prevContext = this[inStringContextSymbol];
88
+ const mediaTypeStr = this.transformPath.at(-1);
89
+ try {
90
+ this[inStringContextSymbol] =
91
+ mediaTypeStr === 'application/x-www-form-urlencoded'
92
+ || mediaTypeStr === 'multipart/form-data'
93
+ || mediaTypeStr === 'text/csv'
94
+ || mediaTypeStr === 'text/plain';
95
+ return super.transformMediaType(mediaType);
96
+ } finally {
97
+ this[inStringContextSymbol] = prevContext;
98
+ }
99
+ }
100
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * @copyright Copyright 2020 Kevin Locke <kevin@kevinlocke.name>
3
+ * @license MIT
4
+ * @module "openapi-transformers/clear-html-response-schema.js"
5
+ */
6
+
7
+ import OpenApiTransformerBase from 'openapi-transformer-base';
8
+
9
+ function isHtml(mediaType) {
10
+ return /^\s*text\/html\s*(?:;.*)?$/i.test(mediaType);
11
+ }
12
+
13
+ /**
14
+ * Transformer to remove response content for the text/html media type.
15
+ *
16
+ * Autorest does not provide a good way to consume text/html:
17
+ * - If the schema has type: string (with or without format: binary), the
18
+ * generated method attempts to JSON-decode the HTML, which fails.
19
+ * - If the schema has type: file, Autorest calls HttpContent.ReadAsStreamAsync
20
+ * and returns the Stream, which complicates conversion to string, since the
21
+ * caller can't call HttpContent.ReadAsStringAsync (which would cause
22
+ * "InvalidOperationException: The stream was already consumed. It cannot be
23
+ * read again.") and must reimplement charset detection to use on Stream.
24
+ */
25
+ export default class ClearHtmlResponseSchemaTransformer
26
+ extends OpenApiTransformerBase {
27
+ // eslint-disable-next-line class-methods-use-this
28
+ transformResponse(response) {
29
+ if (!response) {
30
+ return response;
31
+ }
32
+
33
+ let newResponse = response;
34
+
35
+ // Remove schema from OpenAPI 3 Media Type Objects
36
+ const { content, schema } = newResponse;
37
+ if (content) {
38
+ const htmlTypes = Object.keys(content).filter(isHtml);
39
+ if (htmlTypes.length > 0) {
40
+ const newContent = { ...content };
41
+ for (const htmlType of htmlTypes) {
42
+ const newMediaType = { ...content[htmlType] };
43
+ delete newMediaType.schema;
44
+ delete newMediaType.encoding;
45
+ newContent[htmlType] = newMediaType;
46
+ }
47
+ newResponse = {
48
+ ...newResponse,
49
+ content: newContent,
50
+ };
51
+ }
52
+ }
53
+
54
+ // Remove schema from OpenAPI 2 response.schema
55
+ if (schema !== undefined) {
56
+ newResponse = { ...newResponse };
57
+ delete newResponse.schema;
58
+ }
59
+
60
+ return newResponse;
61
+ }
62
+
63
+ transformOperation(operation) {
64
+ if (!operation || !operation.responses) {
65
+ return operation;
66
+ }
67
+
68
+ // Only transform OpenAPI 2.0 if the operation only produces HTML
69
+ // (since one schema is shared by all)
70
+ const { produces } = operation;
71
+ if (Array.isArray(produces) && !produces.every(isHtml)) {
72
+ return operation;
73
+ }
74
+
75
+ return super.transformOperation(operation);
76
+ }
77
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * @copyright Copyright 2020 Kevin Locke <kevin@kevinlocke.name>
3
+ * @license MIT
4
+ * @module "openapi-transformers/client-params-to-global.js"
5
+ */
6
+
7
+ // Note: Undocumented function which is part of the public API:
8
+ // https://github.com/flitbit/json-ptr/issues/29
9
+ import { encodeUriFragmentIdentifier } from 'json-ptr';
10
+ import OpenApiTransformerBase from 'openapi-transformer-base';
11
+
12
+ import MatchingParameterManager from './lib/matching-parameter-manager.js';
13
+
14
+ const parameterManagerSymbol = Symbol('parameterManager');
15
+ const parametersPathSymbol = Symbol('parametersPath');
16
+
17
+ /**
18
+ * Transformer to move parameters with x-ms-parameter-location:client defined on
19
+ * Path Item Objects and Operation Objects to the Components or Definitions
20
+ * Object (which is required for x-ms-parameter-location to have any effect).
21
+ *
22
+ * Note: Authors should define such parameters in Components or Definitions.
23
+ * This script is mostly a workaround for api-spec-converter, which inlines
24
+ * all $ref parameters.
25
+ * https://github.com/Azure/autorest/tree/master/docs/extensions#x-ms-parameter-location
26
+ */
27
+ export default class ClientParamsToGlobalTransformer
28
+ extends OpenApiTransformerBase {
29
+ transformParameter(parameter) {
30
+ if (!parameter || parameter['x-ms-parameter-location'] !== 'client') {
31
+ return parameter;
32
+ }
33
+
34
+ const defName = this[parameterManagerSymbol].add(parameter, parameter.name);
35
+ return {
36
+ $ref: encodeUriFragmentIdentifier([
37
+ ...this[parametersPathSymbol],
38
+ defName,
39
+ ]),
40
+ };
41
+ }
42
+
43
+ transformOpenApi(openApi) {
44
+ if (typeof openApi !== 'object' || openApi === null || !openApi.paths) {
45
+ return openApi;
46
+ }
47
+
48
+ const { components, openapi, paths } = openApi;
49
+ if (/^3(?:\.|$)/.test(openapi)
50
+ || (typeof components === 'object' && components !== null)) {
51
+ const newParameters = { ...components && components.parameters };
52
+ this[parameterManagerSymbol] =
53
+ new MatchingParameterManager(newParameters);
54
+ this[parametersPathSymbol] = ['components', 'parameters'];
55
+
56
+ return {
57
+ ...openApi,
58
+ components: {
59
+ ...components,
60
+ parameters: newParameters,
61
+ },
62
+ paths: this.transformPaths(paths),
63
+ };
64
+ }
65
+
66
+ const { parameters, swagger } = openApi;
67
+ if (/^2(?:\.|$)/.test(swagger)
68
+ || (typeof parameters === 'object' && parameters !== null)) {
69
+ const newParameters = { ...parameters };
70
+ this[parameterManagerSymbol] =
71
+ new MatchingParameterManager(newParameters);
72
+ this[parametersPathSymbol] = ['parameters'];
73
+
74
+ const newOpenApi = {
75
+ ...openApi,
76
+ parameters: newParameters,
77
+ paths: this.transformPaths(openApi.paths),
78
+ };
79
+
80
+ const xMsParameterizedHost = openApi['x-ms-parameterized-host'];
81
+ if (xMsParameterizedHost
82
+ && Array.isArray(xMsParameterizedHost.parameters)) {
83
+ newOpenApi['x-ms-parameterized-host'] = {
84
+ ...xMsParameterizedHost,
85
+ parameters: this.transformArray(
86
+ xMsParameterizedHost.parameters,
87
+ this.transformParameter,
88
+ ),
89
+ };
90
+ }
91
+
92
+ return newOpenApi;
93
+ }
94
+
95
+ return openApi;
96
+ }
97
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @copyright Copyright 2021 Kevin Locke <kevin@kevinlocke.name>
3
+ * @license MIT
4
+ * @module "openapi-transformers/const-to-enum.js"
5
+ */
6
+
7
+ import OpenApiTransformerBase from 'openapi-transformer-base';
8
+
9
+ /**
10
+ * Transformer to convert Schema Objects with `const` (as in OAS 3.1 and JSON
11
+ * Schema) to `enum` for OAS 3.0 and 2.0.
12
+ */
13
+ export default class ConstToEnumTransformer extends OpenApiTransformerBase {
14
+ transformSchema(schema) {
15
+ const newSchema = super.transformSchema(schema);
16
+ if (newSchema === null
17
+ || typeof newSchema !== 'object'
18
+ || Array.isArray(newSchema)) {
19
+ return newSchema;
20
+ }
21
+
22
+ const { const: constValue, ...schemaNoConst } = newSchema;
23
+ if (constValue === undefined) {
24
+ return newSchema;
25
+ }
26
+
27
+ const enumValues = schemaNoConst.enum;
28
+ if (enumValues === undefined) {
29
+ schemaNoConst.enum = [constValue];
30
+ } else if (Array.isArray(enumValues)) {
31
+ if (enumValues.includes(constValue)) {
32
+ // Schema validation would only succeed for const value.
33
+ // Safe to overwrite.
34
+ schemaNoConst.enum = [constValue];
35
+ } else if (enumValues.length > 0) {
36
+ // Schema validation would always fail (because either const or enum
37
+ // constraint would be unsatisfied). Replace with empty enum, which
38
+ // also always fails.
39
+ this.warn(
40
+ 'Using empty enum for schema with const not in enum',
41
+ newSchema,
42
+ );
43
+ schemaNoConst.enum = [];
44
+ }
45
+ }
46
+
47
+ return schemaNoConst;
48
+ }
49
+ }
@@ -0,0 +1,211 @@
1
+ /**
2
+ * @copyright Copyright 2019-2021 Kevin Locke <kevin@kevinlocke.name>
3
+ * @license MIT
4
+ * @module "openapi-transformers/escape-enum-values.js"
5
+ */
6
+
7
+ import OpenApiTransformerBase from 'openapi-transformer-base';
8
+
9
+ const escapeStringSymbol = Symbol('escapeString');
10
+
11
+ function makeEscapeString(lang) {
12
+ let charToEscape = {
13
+ '\0': '\\0',
14
+ '\x07': '\\a',
15
+ '\b': '\\b',
16
+ '\t': '\\t',
17
+ '\n': '\\n',
18
+ '\v': '\\v',
19
+ '\f': '\\f',
20
+ '\r': '\\r',
21
+ "'": "\\'",
22
+ '"': '\\"',
23
+ '\\': '\\\\',
24
+ };
25
+ // Escape control characters for all languages for readability
26
+ let charRange = '\0-\x1F\x7F';
27
+
28
+ let toAstralEscape, toCodeEscape;
29
+ switch (lang) {
30
+ case 'csharp':
31
+ // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#string-literals
32
+ charRange += '\n\r"\\\\\x85\u2028\u2029';
33
+ // Note: Although \x can be shorter, must be careful to provide 4
34
+ // digits when next character is hex digit. Use \u for consistency.
35
+ toCodeEscape =
36
+ (c) => `\\u${c.codePointAt(0).toString(16).padStart(4, '0')}`;
37
+ toAstralEscape = (code) => `\\U${code.toString(16).padStart(8, '0')}`;
38
+ break;
39
+
40
+ case 'go':
41
+ // https://golang.org/ref/spec#String_literals
42
+ charRange += '\n"\\\\';
43
+ toCodeEscape = (c) => {
44
+ const code = c.codePointAt(0);
45
+ return code <= 0xFF ? `\\x${code.toString(16).padStart(2, '0')}`
46
+ : `\\u${code.toString(16).padStart(4, '0')}`;
47
+ };
48
+ toAstralEscape = (code) => `\\U${code.toString(16).padStart(8, '0')}`;
49
+ break;
50
+
51
+ case 'java':
52
+ // https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.5
53
+ charRange += '\n"\\\\';
54
+ delete charToEscape['\0'];
55
+ delete charToEscape['\x07'];
56
+ delete charToEscape['\v'];
57
+ toCodeEscape =
58
+ (c) => `\\u${c.codePointAt(0).toString(16).padStart(4, '0')}`;
59
+ break;
60
+
61
+ case 'nodejs':
62
+ case 'typescript':
63
+ // https://www.ecma-international.org/ecma-262/6.0/#sec-literals-string-literals
64
+ // Note: AutoRest currently produces single-quoted strings, but the
65
+ // bloat from extra quoting is minor compared to risk.
66
+ charRange += '\n"\'\\\\';
67
+ delete charToEscape['\x07'];
68
+ toCodeEscape = (c) => {
69
+ const code = c.codePointAt(0);
70
+ return code <= 0xFF ? `\\x${code.toString(16).padStart(2, '0')}`
71
+ : `\\u${code.toString(16).padStart(4, '0')}`;
72
+ };
73
+ toAstralEscape = (code) => `\\u{${code.toString(16)}}`;
74
+ break;
75
+
76
+ case 'php':
77
+ // https://www.php.net/manual/en/language.types.string.php
78
+ // FIXME: Does AutoRest produce single- or double-quoted strings?
79
+ // Can't test due to https://github.com/Azure/autorest/issues/3372
80
+ charRange += '\n"\\\\';
81
+ delete charToEscape['\x07'];
82
+ delete charToEscape['\b'];
83
+ charToEscape['\x1B'] = '\\e';
84
+ toCodeEscape = (c) => {
85
+ const code = c.codePointAt(0);
86
+ return code <= 0xFF ? `\\x${code.toString(16).padStart(2, '0')}`
87
+ : `\\u{${code.toString(16)}}`;
88
+ };
89
+ toAstralEscape = (code) => `\\u{${code.toString(16)}}`;
90
+ break;
91
+
92
+ case 'python':
93
+ // https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals
94
+ // Note: AutoRest currently produces single-quoted strings, but the
95
+ // bloat from extra quoting is minor compared to risk.
96
+ charRange += '\n"\'\\\\';
97
+ toCodeEscape = (c) => {
98
+ const code = c.codePointAt(0);
99
+ return code <= 0xFF ? `\\x${code.toString(16).padStart(2, '0')}`
100
+ : `\\u${code.toString(16).padStart(4, '0')}`;
101
+ };
102
+ toAstralEscape = (code) => `\\U${code.toString(16).padStart(8, '0')}`;
103
+ break;
104
+
105
+ case 'ruby':
106
+ // Note: AutoRest currently produces single-quoted strings.
107
+ // Single-quoted strings only accept \' and \\ escapes.
108
+ // https://docs.ruby-lang.org/en/2.4.0/syntax/literals_rdoc.html#label-Strings
109
+ charRange = "'\\\\";
110
+ charToEscape = {
111
+ "'": "\\'",
112
+ '\\': '\\\\',
113
+ };
114
+ toCodeEscape = (c) => c;
115
+ break;
116
+
117
+ default:
118
+ throw new RangeError(`Unrecognized language '${lang}'`);
119
+ }
120
+
121
+ function replaceAstral(pair) {
122
+ return toAstralEscape(pair.codePointAt(0));
123
+ }
124
+ function replaceChar(c) {
125
+ return charToEscape[c] || toCodeEscape(c);
126
+ }
127
+ const charPattern = new RegExp(`[${charRange}]`, 'g');
128
+ return function escapeString(str) {
129
+ if (!str || typeof str !== 'string') {
130
+ return str;
131
+ }
132
+
133
+ const charEscaped = str.replace(charPattern, replaceChar);
134
+ const astralEscaped =
135
+ !toAstralEscape ? charEscaped : charEscaped.replaceAll(
136
+ /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
137
+ replaceAstral,
138
+ );
139
+ return astralEscaped;
140
+ };
141
+ }
142
+
143
+ function escapeInSchema(schema, escapeString) {
144
+ const xMsEnum = schema['x-ms-enum'];
145
+ if (!xMsEnum || schema.type !== 'string') {
146
+ // Schema won't generate a class/enum with string values
147
+ return schema;
148
+ }
149
+
150
+ const xMsEnumValues = xMsEnum.values;
151
+ if (xMsEnumValues) {
152
+ // generator uses .x-ms-enum.values instead of .enum
153
+ return {
154
+ ...schema,
155
+ 'x-ms-enum': {
156
+ ...xMsEnum,
157
+ values: xMsEnumValues.map((xMsEnumValue) => ({
158
+ ...xMsEnumValue,
159
+ value: escapeString(xMsEnumValue.value),
160
+ })),
161
+ },
162
+ };
163
+ }
164
+
165
+ return {
166
+ ...schema,
167
+ enum: schema.enum.map(escapeString),
168
+ };
169
+ }
170
+
171
+ /**
172
+ * Transformer to escape string enum values appropriately for C# string literals
173
+ * when code will be generated by Autorest, since it currently does not.
174
+ *
175
+ * https://github.com/Azure/autorest/issues/3371
176
+ */
177
+ export default class EscapeEnumValuesTransformer
178
+ extends OpenApiTransformerBase {
179
+ constructor({ language }) {
180
+ super();
181
+
182
+ const typeofLanguage = typeof language;
183
+ switch (typeofLanguage) {
184
+ case 'string':
185
+ this[escapeStringSymbol] = makeEscapeString(language);
186
+ break;
187
+ case 'function':
188
+ this[escapeStringSymbol] = language;
189
+ break;
190
+ default:
191
+ throw new TypeError(
192
+ `options.language must be a string or function, got ${
193
+ typeofLanguage}`,
194
+ );
195
+ }
196
+ }
197
+
198
+ transformSchema(schema) {
199
+ return escapeInSchema(
200
+ super.transformSchema(schema),
201
+ this[escapeStringSymbol],
202
+ );
203
+ }
204
+
205
+ transformParameter(parameter) {
206
+ return escapeInSchema(
207
+ super.transformParameter(parameter),
208
+ this[escapeStringSymbol],
209
+ );
210
+ }
211
+ }