@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
package/LICENSE.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright 2016 Kevin Locke <kevin@kevinlocke.name>. All rights reserved.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,134 @@
1
+ OpenAPI Transformers
2
+ ====================
3
+
4
+ [![Build Status](https://img.shields.io/github/actions/workflow/status/kevinoid/openapi-transformers/node.js.yml?branch=main&style=flat&label=build)](https://github.com/kevinoid/openapi-transformers/actions/workflows/node.js.yml?query=branch%3Amain)
5
+ [![Coverage](https://img.shields.io/codecov/c/github/kevinoid/openapi-transformers/main.svg?style=flat)](https://app.codecov.io/gh/kevinoid/openapi-transformers/branch/main)
6
+ [![Dependency Status](https://img.shields.io/librariesio/release/npm/@kevinoid/openapi-transformers.svg?style=flat)](https://libraries.io/npm/@kevinoid%2Fopenapi-transformers)
7
+ [![Supported Node Version](https://img.shields.io/node/v/@kevinoid/openapi-transformers.svg?style=flat)](https://www.npmjs.com/package/@kevinoid/openapi-transformers)
8
+ [![Version on NPM](https://img.shields.io/npm/v/@kevinoid/openapi-transformers.svg?style=flat)](https://www.npmjs.com/package/@kevinoid/openapi-transformers)
9
+
10
+ A collection of classes for transforming
11
+ [OpenAPI](https://github.com/OAI/OpenAPI-Specification/) documents,
12
+ particularly for compatibility with code generators like
13
+ [Autorest](https://github.com/Azure/autorest) and [OpenAPI
14
+ Generator](https://openapi-generator.tech/).
15
+
16
+
17
+ ## Introductory Example
18
+
19
+ To rename all Schema Objects defined in `components` of an OpenAPI document:
20
+
21
+ ```js
22
+ import RenameComponentsTransformer from '@kevinoid/openapi-transformers';
23
+ import openapi from './openapi.json' with { type: 'json' };
24
+
25
+ function renameSchema(schemaName) {
26
+ return `New${schemaName}`;
27
+ }
28
+
29
+ const transformer = new RenameComponentsTransformer({ schemas: renameSchema });
30
+ console.log(transformer.transformOpenApi(openapi));
31
+ ```
32
+
33
+
34
+ ## Example with [`@kevinoid/openapi-transformer-cli`](https://github.com/kevinoid/openapi-transformer-cli)
35
+
36
+ To remove `headers` from responses in an OpenAPI document:
37
+
38
+ ```sh
39
+ openapi-transformer -t @kevinoid/openapi-transformers/remove-response-headers.js <openapi-old.json >openapi-new.json
40
+ ```
41
+
42
+
43
+ ## Transformers
44
+
45
+ | **Transformer** | **Description** |
46
+ | ---------------------------------------------------------------------------------------------------- | --------------- |
47
+ | [AddTagToOperationIdsTransformer](add-tag-to-operation-ids.js) | Prefix `operationId` with the first tag name and an underscore. |
48
+ | [AddXMsEnumNameTransformer](add-x-ms-enum-name.js) | Add `x-ms-enum.name` from schema name, if not present. |
49
+ | [AddXMsEnumValueNamesTransformer](add-x-ms-enum-value-names.js) | Add `x-ms-enum.values.name` to enums where the name generated by Autorest differs from the Microsoft C# Capitalization Rules for Identifiers. |
50
+ | [AdditionalPropertiesToObjectTransformer](additional-properties-to-object.js) | Replace boolean `additionalProperties` with a Schema. |
51
+ | [AdditionalPropertiesToUnconstrainedTransformer](additional-properties-to-unconstrained.js) | Replace `additionalProperties` (and `patternProperties`) with an unconstrained schema alongside other properties. |
52
+ | [AnyOfNullToNullableTransformer](any-of-null-to-nullable.js) | Replace `type: 'null'` in `anyOf` with `nullable: true` (for OAS 3.0). |
53
+ | [BinaryStringToFileTransformer](binary-string-to-file.js) | Replace `type: string` with `format: binary` (or `format: file`) with `type: file`. |
54
+ | [BoolEnumToBoolTransformer](bool-enum-to-bool.js) | Replace `enum: [true, false]` with `type: boolean`. |
55
+ | [ClearHtmlResponseSchemaTransformer](clear-html-response-schema.js) | Remove response content for the `text/html` media type. |
56
+ | [ClientParamsToGlobalTransformer](client-params-to-global.js) | Move parameters with `x-ms-parameter-location: client` defined on Path Item Objects and Operation Objects to the Components or Definitions Object. |
57
+ | [ConstToEnumTransformer](const-to-enum.js) | Convert Schema Objects with `const` to `enum`. |
58
+ | [AssertPropertiesTransformer](assert-properties.js) | Throw an `Error` when given properties are present. |
59
+ | [EscapeEnumValuesTransformer](escape-enum-values.js) | Escape string enum values appropriately for C# string literals. |
60
+ | [ExclusiveMinMaxToBoolTransformer](exclusive-min-max-to-bool.js) | Convert Schema Objects with numeric values for `exclusiveMaximum` and/or `exclusiveMinimum` to boolean values with corresponding `maximum` and/or `minimum`. |
61
+ | [FormatToTypeTransformer](format-to-type.js) | Convert known formats in an OAS3 doc to types. |
62
+ | [InlineNonObjectSchemaTransformer](inline-non-object-schemas.js) | Inline schemas with non-object type. |
63
+ | [MergeAllOfTransformer](merge-all-of.js) | Merge `allOf` schemas into the parent schema. |
64
+ | [MergeAnyOfTransformer](merge-any-of.js) | Merge `anyOf` schemas into the parent schema. |
65
+ | [MergeOneOfTransformer](merge-one-of.js) | Merge `oneOf` schemas into the parent schema. |
66
+ | [NullableNotRequiredTransformer](nullable-not-required.js) | Make properties which are `nullable` non-`required`. |
67
+ | [NullableToTypeNullTransformer](nullable-to-type-null.js) | Add `'null'` to `type` of Schema Objects with `nullable: true` or `x-nullable: true`. |
68
+ | [OpenApi31To30Transformer](openapi31to30.js) | Convert an OpenAPI 3.1.* document to OpenAPI 3.0.3. |
69
+ | [PathParametersToOperationTransformer](path-parameters-to-operations.js) | Move parameters defined on Path Item Objects to the beginning of the parameters array of the Operation Objects. |
70
+ | [PatternPropertiesToAdditionalPropertiesTransformer](pattern-properties-to-additional-properties.js) | Combine any `patternProperties` into `additionalProperties`. |
71
+ | [QueriesToXMsPathsTransformer](queries-to-x-ms-paths.js) | Move paths with query parameters from `paths` to `x-ms-paths`. |
72
+ | [ReadOnlyNotRequiredTransformer](read-only-not-required.js) | Ensure `readOnly` schema properties are not `required`. |
73
+ | [RefPathParametersTransformer](ref-path-parameters.js) | Move Parameters defined on Path Item Objects to global parameters which are referenced in the Path Item. |
74
+ | [RemoveDefaultOnlyResponseProducesTransformer](remove-default-only-response-produces.js) | Remove `produces` from Operations with only a default response. |
75
+ | [RemovePathsWithServersTransformer](remove-paths-with-servers.js) | Remove Path Item Objects which have `servers`. |
76
+ | [RemoveQueryFromPathsTransformer](remove-query-from-paths.js) | Remove query component of path in Paths Object. |
77
+ | [RemoveRefSiblingsTransformer](remove-ref-siblings.js) | Remove properties from Reference Objects. |
78
+ | [RemoveRequestBodyTransformer](remove-request-body.js) | Remove `requestBody` from operations on a given set of HTTP methods. |
79
+ | [RemoveResponseHeadersTransformer](remove-response-headers.js) | Remove `headers` from Response objects.
80
+ | [RemoveSecuritySchemeIfTransformer](remove-security-scheme-if.js) | Remove `security` schemes matching a given predicate. |
81
+ | [RemoveTypeIfTransformer](remove-type-if.js) | Remove `type` from Schema Objects where `type` matches a given predicate. |
82
+ | [RenameComponentsTransformer](rename-components.js) | Rename `components`. |
83
+ | [ReplacedByToDescriptionTransformer](replaced-by-to-description.js) | Convert `x-deprecated.replaced-by` to `x-deprecated.description`, if not present. |
84
+ | [ServerVarsToPathParamsTransformer](server-vars-to-path-params.js) | Convert Server Variables in path portion to Parameters on Path Item Objects. |
85
+ | [ServerVarsToParamHostTransformer](server-vars-to-x-ms-parameterized-host.js) | Convert Server Variables in host portion to `x-ms-parameterized-host`. |
86
+ | [TypeNullToEnumTransformer](type-null-to-enum.js) | Convert Schema Objects with `type: 'null'` to `enum: [null]`. |
87
+ | [TypeNullToNullableTransformer](type-null-to-nullable.js) | Convert Schema Objects with `'null'` in `type` to `nullable: true`. |
88
+ | [UrlencodedToStringTransformer](urlencoded-to-string.js) | Change request parameter types to string for operations which only consume `application/x-www-form-urlencoded`. |
89
+ | [XEnumToXMsEnumTransformer](x-enum-to-ms.js) | Convert `x-enum-descriptions` and `x-enum-varnames` to `x-ms-enum`. |
90
+
91
+
92
+ ## Installation
93
+
94
+ [This package](https://www.npmjs.com/package/@kevinoid/openapi-transformers) can be
95
+ installed using [npm](https://www.npmjs.com/), either globally or locally, by
96
+ running:
97
+
98
+ ```sh
99
+ npm install @kevinoid/openapi-transformers
100
+ ```
101
+
102
+
103
+ ## Recipes
104
+
105
+ More examples can be found in the [test
106
+ specifications](https://kevinoid.github.io/openapi-transformers/spec).
107
+
108
+
109
+ ## API Docs
110
+
111
+ To use this module as a library, see the [API
112
+ Documentation](https://kevinoid.github.io/openapi-transformers/api).
113
+
114
+
115
+ ## Contributing
116
+
117
+ Contributions are appreciated. Contributors agree to abide by the [Contributor
118
+ Covenant Code of
119
+ Conduct](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html).
120
+ If this is your first time contributing to a Free and Open Source Software
121
+ project, consider reading [How to Contribute to Open
122
+ Source](https://opensource.guide/how-to-contribute/)
123
+ in the Open Source Guides.
124
+
125
+ If the desired change is large, complex, backwards-incompatible, can have
126
+ significantly differing implementations, or may not be in scope for this
127
+ project, opening an issue before writing the code can avoid frustration and
128
+ save a lot of time and effort.
129
+
130
+
131
+ ## License
132
+
133
+ This project is available under the terms of the [MIT License](LICENSE.txt).
134
+ See the [summary at TLDRLegal](https://tldrlegal.com/license/mit-license).
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @copyright Copyright 2019 Kevin Locke <kevin@kevinlocke.name>
3
+ * @license MIT
4
+ * @module "openapi-transformers/add-tag-to-operation-ids.js"
5
+ */
6
+
7
+ import { debuglog } from 'node:util';
8
+
9
+ import OpenApiTransformerBase from 'openapi-transformer-base';
10
+
11
+ const debug = debuglog('add-tag-to-operation-ids');
12
+
13
+ /**
14
+ * Transformer to prefix operationId with the first tag name and an underscore,
15
+ * which Autorest recognizes as an "operation group" represented by a separate
16
+ * API class when generating the client.
17
+ *
18
+ * See https://github.com/Azure/autorest/issues/1497#issuecomment-252082163
19
+ */
20
+ export default class AddTagToOperationIdsTransformer
21
+ extends OpenApiTransformerBase {
22
+ constructor({ tagSuffix = '' } = {}) {
23
+ super();
24
+ this.tagSuffix = String(tagSuffix);
25
+ }
26
+
27
+ transformOperation(op) {
28
+ if (op === null || typeof op !== 'object') {
29
+ debug('Not adding tag to non-object operation %O', op);
30
+ return op;
31
+ }
32
+
33
+ const { tags } = op;
34
+ if (!Array.isArray(tags) || tags.length === 0) {
35
+ debug('No tag to add for operation %O', op);
36
+ return op;
37
+ }
38
+
39
+ const { operationId } = op;
40
+ if (operationId === undefined
41
+ || operationId === null
42
+ || operationId === '') {
43
+ debug('No operationId to add for operation %O', op);
44
+ return op;
45
+ }
46
+
47
+ return {
48
+ ...op,
49
+ operationId: `${tags[0]}${this.tagSuffix}_${operationId}`,
50
+ };
51
+ }
52
+
53
+ // Override as performance optimization, since only transforming paths
54
+ transformOpenApi(spec) {
55
+ return {
56
+ ...spec,
57
+ paths: this.transformPaths(spec.paths),
58
+ };
59
+ }
60
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @copyright Copyright 2019 Kevin Locke <kevin@kevinlocke.name>
3
+ * @license MIT
4
+ * @module "openapi-transformers/add-x-ms-enum-name.js"
5
+ */
6
+
7
+ import OpenApiTransformerBase from 'openapi-transformer-base';
8
+
9
+ /**
10
+ * Transformer to add x-ms-enum.name from schema name, if not present
11
+ * (so Autorest will generate enum types).
12
+ *
13
+ * https://github.com/Azure/autorest/tree/master/docs/extensions#x-ms-enum
14
+ */
15
+ export default class AddXMsEnumNameTransformer extends OpenApiTransformerBase {
16
+ // eslint-disable-next-line class-methods-use-this
17
+ transformSchema(schema, schemaName) {
18
+ if (!schema.enum || (schema['x-ms-enum'] && schema['x-ms-enum'].name)) {
19
+ return schema;
20
+ }
21
+
22
+ return {
23
+ ...schema,
24
+ 'x-ms-enum': {
25
+ ...schema['x-ms-enum'],
26
+ name: schemaName,
27
+ },
28
+ };
29
+ }
30
+
31
+ /** Transforms Map[string,Schema] with named schemas by passing the
32
+ * name as the second argument to transformSchema.
33
+ *
34
+ * @param {!Object<string,object>|*} schemas Schmea map to transform.
35
+ * @returns {!Object<string,object>|*} If obj is a Map, a plain object with
36
+ * the same own enumerable string-keyed properties as obj with values
37
+ * returned by transformSchema. Otherwise, obj is returned unchanged.
38
+ */
39
+ transformSchemas(schemas) {
40
+ if (typeof schemas !== 'object'
41
+ || schemas === null
42
+ || Array.isArray(schemas)) {
43
+ return schemas;
44
+ }
45
+
46
+ const newSchemas = { ...schemas };
47
+ for (const [schemaName, schema] of Object.entries(schemas)) {
48
+ if (schema !== undefined) {
49
+ newSchemas[schemaName] = this.transformSchema(schema, schemaName);
50
+ }
51
+ }
52
+
53
+ return newSchemas;
54
+ }
55
+
56
+ // Optimization: Only transform schemas
57
+ transformComponents(components) {
58
+ if (!components) {
59
+ return components;
60
+ }
61
+
62
+ const { schemas } = components;
63
+ if (!schemas) {
64
+ return components;
65
+ }
66
+
67
+ return {
68
+ ...components,
69
+ schemas: this.transformSchemas(schemas),
70
+ };
71
+ }
72
+
73
+ // Optimization: Only transform components/definitions
74
+ transformOpenApi(openApi) {
75
+ if (!openApi) {
76
+ return openApi;
77
+ }
78
+
79
+ const { components, definitions } = openApi;
80
+ if (!components && !definitions) {
81
+ return openApi;
82
+ }
83
+
84
+ const newOpenApi = { ...openApi };
85
+
86
+ if (components) {
87
+ newOpenApi.components = this.transformComponents(components);
88
+ }
89
+
90
+ if (definitions) {
91
+ newOpenApi.definitions = this.transformSchemas(definitions);
92
+ }
93
+
94
+ return newOpenApi;
95
+ }
96
+ }
@@ -0,0 +1,142 @@
1
+ /**
2
+ * @copyright Copyright 2019 Kevin Locke <kevin@kevinlocke.name>
3
+ * @license MIT
4
+ * @module "openapi-transformers/add-x-ms-enum-value-names.js"
5
+ */
6
+
7
+ import assert from 'node:assert';
8
+
9
+ import dotnetCase from '@kevinoid/dotnet-identifier-case';
10
+ import OpenApiTransformerBase from 'openapi-transformer-base';
11
+
12
+ assert.ok(/\p{L}/u.test('X'), 'Unicode property escapes are supported.');
13
+
14
+ function firstToLower(word) {
15
+ if (!word) {
16
+ return word;
17
+ }
18
+
19
+ // Lower-case 2-letter acronym together (as Autorest does)
20
+ if (word.length === 2 && word === word.toUpperCase()) {
21
+ return word.toLowerCase();
22
+ }
23
+
24
+ return word.charAt(0).toLowerCase() + word.slice(1);
25
+ }
26
+
27
+ function firstToUpper(word) {
28
+ if (!word) {
29
+ return word;
30
+ }
31
+
32
+ return word.charAt(0).toUpperCase() + word.slice(1);
33
+ }
34
+
35
+ /** Returns the enum member name which would be used by Autorest.
36
+ * https://github.com/Azure/autorest.common/blob/54c21af/src/CodeNamer.cs#L178
37
+ *
38
+ * @private
39
+ */
40
+ function autorestEnumMemberName(value) {
41
+ const clean = value.replaceAll(/[^\p{L}\p{N}_-]/gu, '');
42
+ const words = clean.split(/[_-]/);
43
+
44
+ if (clean.charAt(0) === '_') {
45
+ // eslint-disable-next-line prefer-template
46
+ return '_' + words
47
+ .map((word, i) => (i > 0 ? firstToUpper(word) : firstToLower(word)))
48
+ .join('');
49
+ }
50
+
51
+ return words
52
+ .map(firstToUpper)
53
+ .join('');
54
+ }
55
+
56
+ function addXMsEnumValueNamesToSchema(schema) {
57
+ if (!schema.enum || !schema['x-ms-enum']) {
58
+ // Schema won't generate an enum
59
+ return schema;
60
+ }
61
+
62
+ const xMsEnum = schema['x-ms-enum'];
63
+ const xMsEnumValues = xMsEnum.values;
64
+ if (xMsEnumValues
65
+ && xMsEnumValues.every((v) => v.name !== null && v.name !== undefined)) {
66
+ // Names already specified for all values
67
+ return schema;
68
+ }
69
+
70
+ const values =
71
+ Array.isArray(xMsEnumValues) ? xMsEnumValues.map((v) => v.value)
72
+ : schema.enum;
73
+ const stringValues = values.map(String);
74
+ const autorestNames = stringValues.map(autorestEnumMemberName);
75
+ const microsoftNames = stringValues.map(dotnetCase);
76
+
77
+ let anyNameChanged = false;
78
+ let newXMsEnumValues;
79
+ if (Array.isArray(xMsEnumValues)) {
80
+ newXMsEnumValues = xMsEnumValues.map((xMsEnumValue, i) => {
81
+ if (xMsEnumValue.name !== null && xMsEnumValue.name !== undefined) {
82
+ return xMsEnumValue;
83
+ }
84
+
85
+ const autorestName = autorestNames[i];
86
+ const microsoftName = microsoftNames[i];
87
+ if (autorestName === microsoftName) {
88
+ return xMsEnumValue;
89
+ }
90
+
91
+ anyNameChanged = true;
92
+ return {
93
+ ...xMsEnumValue,
94
+ name: microsoftName,
95
+ };
96
+ });
97
+ } else {
98
+ newXMsEnumValues = schema.enum.map((value, i) => {
99
+ const autorestName = autorestNames[i];
100
+ const microsoftName = microsoftNames[i];
101
+ const newXMsEnumValue = { value };
102
+ if (autorestName !== microsoftName) {
103
+ anyNameChanged = true;
104
+ newXMsEnumValue.name = microsoftName;
105
+ }
106
+ return newXMsEnumValue;
107
+ });
108
+ }
109
+
110
+ if (!anyNameChanged) {
111
+ return schema;
112
+ }
113
+
114
+ return {
115
+ ...schema,
116
+ 'x-ms-enum': {
117
+ ...xMsEnum,
118
+ values: newXMsEnumValues,
119
+ },
120
+ };
121
+ }
122
+
123
+ /**
124
+ * Transformer to add x-ms-enum.values.name to enums where the name generated by
125
+ * Autorest differs from the Microsoft C# Capitalization Rules for Identifiers.
126
+ *
127
+ * https://github.com/Azure/autorest/issues/3328
128
+ */
129
+ export default class AddXMsEnumValueNamesTransformer
130
+ extends OpenApiTransformerBase {
131
+ transformSchema(schema) {
132
+ return addXMsEnumValueNamesToSchema(
133
+ super.transformSchema(schema),
134
+ );
135
+ }
136
+
137
+ transformParameter(parameter) {
138
+ return addXMsEnumValueNamesToSchema(
139
+ super.transformParameter(parameter),
140
+ );
141
+ }
142
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @copyright Copyright 2019 Kevin Locke <kevin@kevinlocke.name>
3
+ * @license MIT
4
+ * @module "openapi-transformers/additional-properties-to-object.js"
5
+ */
6
+
7
+ import OpenApiTransformerBase from 'openapi-transformer-base';
8
+
9
+ /**
10
+ * Transformer to replace boolean additionalProperties with an object schema to
11
+ * work around https://github.com/Azure/autorest/issues/3439.
12
+ */
13
+ export default class AdditionalPropertiesToObjectTransformer
14
+ extends OpenApiTransformerBase {
15
+ transformSchema(schema) {
16
+ if (typeof schema !== 'object' || schema === null) {
17
+ return schema;
18
+ }
19
+
20
+ const newSchema = super.transformSchema(schema);
21
+ const { additionalProperties } = newSchema;
22
+
23
+ if (typeof additionalProperties !== 'boolean') {
24
+ return newSchema;
25
+ }
26
+
27
+ return {
28
+ ...newSchema,
29
+
30
+ // Use schema equivalents described by current spec author Henry Andrews
31
+ // https://groups.google.com/d/msg/json-schema/Es0fEf3hj2Y/MxWmgercBAAJ
32
+ additionalProperties: additionalProperties ? {} : { not: {} },
33
+ };
34
+ }
35
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * @copyright Copyright 2019-2020 Kevin Locke <kevin@kevinlocke.name>
3
+ * @license MIT
4
+ * @module "openapi-transformers/additional-properties-to-unconstrained.js"
5
+ */
6
+
7
+ import OpenApiTransformerBase from 'openapi-transformer-base';
8
+
9
+ /** Applies a predicate to each schema which contributes to the generated
10
+ * type of a given schema.
11
+ *
12
+ * @private
13
+ */
14
+ function someCombinedSchema(schema, predicate) {
15
+ if (predicate(schema)) {
16
+ return true;
17
+ }
18
+
19
+ if (typeof schema !== 'object' || schema === null) {
20
+ return false;
21
+ }
22
+
23
+ if (['then', 'else'].some(
24
+ (key) => someCombinedSchema(schema[key], predicate),
25
+ )) {
26
+ return true;
27
+ }
28
+
29
+ return ['allOf', 'anyOf', 'oneOf'].some(
30
+ (key) => Array.isArray(schema[key])
31
+ && schema[key].some((s) => someCombinedSchema(s, predicate)),
32
+ );
33
+ }
34
+
35
+ /** Replaces additionalProperties (and patternProperties) in each schema which
36
+ * contributes to the generated type of a given schema.
37
+ *
38
+ * @private
39
+ */
40
+ function replaceAdditionalProperties(schema) {
41
+ if (typeof schema !== 'object' || schema === null) {
42
+ return schema;
43
+ }
44
+
45
+ const newSchema = { ...schema };
46
+
47
+ for (const key of ['additionalProperties', 'patternProperties']) {
48
+ const propSchema = newSchema[key];
49
+ if (typeof propSchema === 'object' && propSchema !== null) {
50
+ // Note: Use {} instead of true to work around
51
+ // https://github.com/Azure/autorest/issues/3439 and
52
+ // https://github.com/Azure/autorest/issues/2564 (marked fixed, but fix
53
+ // only covers additionalProperties on top-level schemas)
54
+ newSchema[key] = {};
55
+ }
56
+ }
57
+
58
+ for (const key of ['then', 'else']) {
59
+ if (newSchema[key] !== undefined) {
60
+ newSchema[key] = replaceAdditionalProperties(newSchema[key]);
61
+ }
62
+ }
63
+
64
+ for (const key of ['allOf', 'anyOf', 'oneOf']) {
65
+ if (Array.isArray(newSchema[key])) {
66
+ newSchema[key] = newSchema[key].map(replaceAdditionalProperties);
67
+ }
68
+ }
69
+
70
+ return newSchema;
71
+ }
72
+
73
+ /** Does a schema describe an object with at least one property?
74
+ *
75
+ * @private
76
+ */
77
+ function hasProperties(schema) {
78
+ return schema
79
+ && schema.properties
80
+ && Object.keys(schema.properties).length > 0;
81
+ }
82
+
83
+ /** Does a schema describe an object with constrained additionalProperties
84
+ * (or patternProperties)?
85
+ *
86
+ * @private
87
+ */
88
+ function hasConstrainedAdditionalProps(schema) {
89
+ return schema
90
+ && ((schema.additionalProperties
91
+ && Object.keys(schema.additionalProperties).length > 0)
92
+ || (schema.patternProperties
93
+ && Object.keys(schema.patternProperties).length > 0));
94
+ }
95
+
96
+ /**
97
+ * Transformer to replace additionalProperties (and patternProperties) with an
98
+ * unconstrained schema alongside other properties to work around
99
+ * https://github.com/Azure/autorest/issues/2469
100
+ */
101
+ export default class AdditionalPropertiesToUnconstrainedTransformer
102
+ extends OpenApiTransformerBase {
103
+ transformSchema(schema) {
104
+ let newSchema;
105
+ if (someCombinedSchema(schema, hasConstrainedAdditionalProps)
106
+ && someCombinedSchema(schema, hasProperties)) {
107
+ newSchema = replaceAdditionalProperties(schema);
108
+ } else {
109
+ newSchema = schema;
110
+ }
111
+
112
+ // Search for additionalProperties in child schemas
113
+ return super.transformSchema(newSchema);
114
+ }
115
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @copyright Copyright 2025 Kevin Locke <kevin@kevinlocke.name>
3
+ * @license MIT
4
+ * @module "openapi-transformers/any-of-null-to-nullable.js"
5
+ */
6
+
7
+ import { isDeepStrictEqual } from 'node:util';
8
+
9
+ import OpenApiTransformerBase from 'openapi-transformer-base';
10
+
11
+ /**
12
+ * Transformer to convert Schema Objects with `type: 'null'` in `anyOf` (as in
13
+ * OAS 3.1 and JSON Schema) to `nullable: true` (as in OAS 3.0).
14
+ */
15
+ export default class AnyOfNullToNullableTransformer
16
+ extends OpenApiTransformerBase {
17
+ transformSchema(schema) {
18
+ const newSchema = super.transformSchema(schema);
19
+ if (newSchema === null
20
+ || typeof newSchema !== 'object'
21
+ || Array.isArray(newSchema)) {
22
+ return newSchema;
23
+ }
24
+
25
+ const { anyOf, nullable } = newSchema;
26
+ if (nullable !== undefined && nullable !== true) {
27
+ return newSchema;
28
+ }
29
+
30
+ if (!Array.isArray(anyOf) || anyOf.length < 2) {
31
+ return newSchema;
32
+ }
33
+
34
+ const anyOfNoNull =
35
+ anyOf.filter((s) => !isDeepStrictEqual(s, { type: 'null' }));
36
+ if (anyOfNoNull.length === anyOf.length) {
37
+ return newSchema;
38
+ }
39
+
40
+ if (anyOfNoNull.length === 0) {
41
+ return newSchema;
42
+ }
43
+
44
+ return {
45
+ ...newSchema,
46
+ nullable: true,
47
+ anyOf: anyOfNoNull,
48
+ };
49
+ }
50
+ }