swaggie 1.5.3-beta.1 → 1.5.3-beta.2

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.
package/README.md CHANGED
@@ -103,6 +103,7 @@ Sample configuration looks like this:
103
103
  "preferAny": true,
104
104
  "servicePrefix": "",
105
105
  "dateFormat": "Date", // "string" | "Date"
106
+ "nullableStrategy": "ignore", // "ignore" | "include" | "nullableAsOptional"
106
107
  "queryParamsSerialization": {
107
108
  "arrayFormat": "repeat", // "repeat" | "brackets" | "indices"
108
109
  "allowDots": true
@@ -162,6 +163,24 @@ Once you know what your backend expects, you can adjust the configuration file a
162
163
  }
163
164
  ```
164
165
 
166
+ ### Nullable Strategy
167
+
168
+ OpenAPI 3.0 allows marking fields as `nullable: true`. Swaggie provides three strategies for translating this into TypeScript, controlled by the `nullableStrategy` option:
169
+
170
+ | Value | Description |
171
+ | ---------------------- | ---------------------------------------------------------------------------------- |
172
+ | `"ignore"` (default) | `nullable: true` is ignored. Types are generated as if `nullable` was not set. |
173
+ | `"include"` | `nullable: true` appends `\| null` to the TypeScript type (e.g. `string \| null`). |
174
+ | `"nullableAsOptional"` | `nullable: true` makes the property optional (`?`) instead of adding `\| null`. |
175
+
176
+ **Examples** for a schema with `tenant: { type: 'string', nullable: true }` (required):
177
+
178
+ ```typescript
179
+ // nullableStrategy: "ignore" → tenant: string;
180
+ // nullableStrategy: "include" → tenant: string | null;
181
+ // nullableStrategy: "nullableAsOptional" → tenant?: string;
182
+ ```
183
+
165
184
  ### Code Quality
166
185
 
167
186
  > Please note that it's **recommended** to pipe Swaggie command to some prettifier like `prettier`, `biome` or `dprint` to make the generated code look not only nice, but also persistent.
@@ -98,7 +98,7 @@ function prepareClient(
98
98
  const [respObject, responseContentType] = _utils.getBestResponse.call(void 0, op);
99
99
  const returnType = _swagger.getParameterType.call(void 0, respObject, options);
100
100
 
101
- const body = getRequestBody(op.requestBody);
101
+ const body = getRequestBody(op.requestBody, options);
102
102
  const queryParams = getParams(op.parameters , options, ['query']);
103
103
  const params = getParams(op.parameters , options);
104
104
 
@@ -278,7 +278,10 @@ function prepareUrl(path) {
278
278
  );
279
279
  } exports.getParamName = getParamName;
280
280
 
281
- function getRequestBody(reqBody) {
281
+ function getRequestBody(
282
+ reqBody,
283
+ options
284
+ ) {
282
285
  if (reqBody && 'content' in reqBody) {
283
286
  const [bodyContent, contentType] = _utils.getBestContentType.call(void 0, reqBody);
284
287
  const isFormData = contentType === 'form-data';
@@ -287,7 +290,7 @@ function getRequestBody(reqBody) {
287
290
  return {
288
291
  originalName: _nullishCoalesce(reqBody['x-name'], () => ( 'body')),
289
292
  name: getParamName(_nullishCoalesce(reqBody['x-name'], () => ( 'body'))),
290
- type: isFormData ? 'FormData' : _swagger.getParameterType.call(void 0, bodyContent, {}),
293
+ type: isFormData ? 'FormData' : _swagger.getParameterType.call(void 0, bodyContent, options),
291
294
  optional: !reqBody.required,
292
295
  original: reqBody,
293
296
  contentType,
@@ -200,7 +200,14 @@ function renderTypeProp(
200
200
  if ('description' in definition || 'title' in definition) {
201
201
  lines.push(_jsDocs.renderComment.call(void 0, _nullishCoalesce(definition.description, () => ( definition.title))));
202
202
  }
203
- const optionalMark = required ? '' : '?';
203
+
204
+ // When nullableAsOptional strategy is set, nullable properties are treated as optional
205
+ const isNullableAsOptional =
206
+ options.nullableStrategy === 'nullableAsOptional' &&
207
+ !('$ref' in definition) &&
208
+ (definition ).nullable === true;
209
+ const isOptional = !required || isNullableAsOptional;
210
+ const optionalMark = isOptional ? '?' : '';
204
211
  // If prop name is not a valid identifier, we need to wrap it in quotes.
205
212
  // We can't use getSafeIdentifier here because it will affect the data model.
206
213
  const safePropName = _utils.escapePropName.call(void 0, propName);
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
2
2
 
3
3
  var _utils = require('../utils');
4
4
 
@@ -52,7 +52,9 @@ var _utils = require('../utils');
52
52
  return 'null';
53
53
  }
54
54
 
55
- const isNullableSuffix = 'nullable' in schema && schema.nullable === true ? ' | null' : '';
55
+ const isNullable = 'nullable' in schema && schema.nullable === true;
56
+ const strategy = _nullishCoalesce(options.nullableStrategy, () => ( 'ignore'));
57
+ const isNullableSuffix = isNullable && strategy === 'include' ? ' | null' : '';
56
58
  const type = getTypeFromSchemaInternal(schema, options);
57
59
 
58
60
  if (isNullableSuffix && type.endsWith('| null')) {
@@ -102,7 +104,10 @@ function getNestedTypeFromSchema(
102
104
  schema,
103
105
  options
104
106
  ) {
105
- if (('nullable' in schema && schema.nullable === true) || ('enum' in schema && schema.enum)) {
107
+ const strategy = _nullishCoalesce(options.nullableStrategy, () => ( 'ignore'));
108
+ const isNullableAndActive =
109
+ 'nullable' in schema && schema.nullable === true && strategy === 'include';
110
+ if (isNullableAndActive || ('enum' in schema && schema.enum)) {
106
111
  return `(${getTypeFromSchema(schema, options)})`;
107
112
  }
108
113
  return getTypeFromSchema(schema, options);
package/dist/types.d.ts CHANGED
@@ -20,6 +20,13 @@ export interface ClientOptions {
20
20
  servicePrefix?: string;
21
21
  /** How date should be handled. It does not do any special serialization */
22
22
  dateFormat?: DateSupport;
23
+ /**
24
+ * Controls how OpenAPI 'nullable' is translated into TypeScript types. Default: 'ignore'.
25
+ * 'include' - 'nullable: true' appends `| null` to the TypeScript type (e.g. `string | null`).
26
+ * 'nullableAsOptional' - 'nullable: true' makes the property optional (`?`) instead of adding `| null`.
27
+ * 'ignore' - 'nullable: true' is ignored.
28
+ */
29
+ nullableStrategy?: NullableStrategy;
23
30
  /** Options for query parameters serialization */
24
31
  queryParamsSerialization: QueryParamsSerializationOptions;
25
32
  /** Offers ability to adjust the OpenAPI spec before it is processed */
@@ -42,6 +49,7 @@ export type Template = 'axios' | 'fetch' | 'ng1' | 'ng2' | 'swr-axios' | 'xior'
42
49
  export type HttpMethod = 'get' | 'put' | 'post' | 'delete' | 'options' | 'head' | 'patch';
43
50
  export type DateSupport = 'string' | 'Date';
44
51
  export type ArrayFormat = 'indices' | 'repeat' | 'brackets';
52
+ export type NullableStrategy = 'include' | 'nullableAsOptional' | 'ignore';
45
53
  /**
46
54
  * Local type that represent Operation as understood by Swaggie
47
55
  **/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swaggie",
3
- "version": "1.5.3-beta.1",
3
+ "version": "1.5.3-beta.2",
4
4
  "description": "Generate TypeScript REST client code from an OpenAPI spec",
5
5
  "author": {
6
6
  "name": "Piotr Dabrowski",