Skip to content

Commit a634b33

Browse files
fix: Serialize falsey values (openapi-ts#906)
* fix: Error on missing prettier config When a prettier config file is specified but can't be found a default prettier config is silently used as a fallback. This change causes an error to be raised when the specified prettier config doesn't exist. Closes openapi-ts#908 * fix: Serialize falsey defaults and examples Closes openapi-ts#890
1 parent 23dc67f commit a634b33

File tree

94 files changed

+268139
-268355
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+268139
-268355
lines changed

src/index.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { GlobalContext, OpenAPI2, OpenAPI3, SchemaObject, SwaggerToTSOptions } from "./types.js";
22
import path from "path";
3+
import fs from "fs";
34
import prettier from "prettier";
45
import parserTypescript from "prettier/parser-typescript.js";
56
import { Readable } from "stream";
@@ -115,7 +116,9 @@ async function openapiTS(
115116
};
116117
if (options && options.prettierConfig) {
117118
try {
118-
const userOptions = await prettier.resolveConfig(path.resolve(process.cwd(), options.prettierConfig));
119+
const prettierConfigFile = path.resolve(process.cwd(), options.prettierConfig);
120+
await fs.promises.access(prettierConfigFile, fs.constants.F_OK);
121+
const userOptions = await prettier.resolveConfig(prettierConfigFile);
119122
prettierOptions = {
120123
...(userOptions || {}),
121124
...prettierOptions,

src/utils.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,14 @@ export function prepareComment(v: CommentObject): string | void {
4242
const supportedJsDocTags: Array<keyof CommentObject> = ["description", "default", "example"];
4343
for (let index = 0; index < supportedJsDocTags.length; index++) {
4444
const field = supportedJsDocTags[index];
45-
if (v[field]) commentsArray.push(`@${field} ${v[field]} `);
45+
const allowEmptyString = field === "default" || field === "example";
46+
if (v[field] === undefined) {
47+
continue;
48+
}
49+
if (v[field] === "" && !allowEmptyString) {
50+
continue;
51+
}
52+
commentsArray.push(`@${field} ${v[field]} `);
4653
}
4754

4855
// * JSDOC 'Constant' without value

test/bin/cli.test.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,20 @@ describe("cli", () => {
2020
});
2121

2222
it("--prettier-config (.js)", async () => {
23-
execSync(`${cmd} specs/petstore.yaml -o generated/prettier-js.ts --prettier-config fixtures/prettier.config.js`, {
23+
execSync(`${cmd} specs/petstore.yaml -o generated/prettier-js.ts --prettier-config fixtures/prettier.config.cjs`, {
2424
cwd,
2525
});
2626
const generated = fs.readFileSync(new URL("./generated/prettier-js.ts", cwd), "utf8");
2727
const expected = eol.lf(fs.readFileSync(new URL("./expected/prettier-js.ts", cwd), "utf8"));
2828
expect(generated).to.equal(expected);
2929
});
3030

31+
it("--prettier-config (missing)", async () => {
32+
expect(() => {
33+
execSync(`${cmd} specs/petstore.yaml -o generated/prettier-missing.ts --prettier-config NO_SUCH_FILE`);
34+
}).to.throw('NO_SUCH_FILE');
35+
});
36+
3137
it("stdout", async () => {
3238
const generated = execSync(`${cmd} specs/petstore.yaml`, { cwd });
3339
const expected = eol.lf(fs.readFileSync(new URL("./expected/stdout.ts", cwd), "utf8"));

test/bin/expected/paths-enum.ts

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export interface components {
7979
* @enum {string}
8080
*/
8181
status?: "placed" | "approved" | "delivered";
82+
/** @default false */
8283
complete?: boolean;
8384
};
8485
Category: {

test/bin/expected/prettier-js.ts

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export interface components {
7979
* @enum {string}
8080
*/
8181
status?: 'placed' | 'approved' | 'delivered'
82+
/** @default false */
8283
complete?: boolean
8384
}
8485
Category: {

test/bin/expected/prettier-json.ts

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export interface components {
7979
* @enum {string}
8080
*/
8181
status?: 'placed' | 'approved' | 'delivered'
82+
/** @default false */
8283
complete?: boolean
8384
}
8485
Category: {

test/bin/expected/specs/manifold.ts

+32-2
Original file line numberDiff line numberDiff line change
@@ -688,23 +688,32 @@ export interface definitions {
688688
name: definitions["Name"];
689689
/** @enum {string} */
690690
type: "boolean" | "string" | "number";
691-
/** @description This sets whether or not the feature can be customized by a consumer. */
691+
/**
692+
* @description This sets whether or not the feature can be customized by a consumer.
693+
* @default false
694+
*/
692695
customizable?: boolean;
693696
/**
694697
* @description This sets whether or not the feature can be upgraded by the consumer after the
695698
* resource has provisioned. Upgrading means setting a higher value or selecting a
696699
* higher element in the list.
700+
*
701+
* @default false
697702
*/
698703
upgradable?: boolean;
699704
/**
700705
* @description This sets whether or not the feature can be downgraded by the consumer after the
701706
* resource has provisioned. Downgrading means setting a lower value or selecting a
702707
* lower element in the list.
708+
*
709+
* @default false
703710
*/
704711
downgradable?: boolean;
705712
/**
706713
* @description Sets if this feature’s value is trackable from the provider,
707714
* this only really affects numeric constraints.
715+
*
716+
* @default false
708717
*/
709718
measurable?: boolean;
710719
values?: definitions["FeatureValuesList"];
@@ -725,6 +734,8 @@ export interface definitions {
725734
* @description The cost that will be added to the monthly plan cost when this value
726735
* is selected or is default for the plan.
727736
* Cost is deprecated in favor of the `price.cost` field.
737+
*
738+
* @default 0
728739
*/
729740
cost?: number;
730741
/**
@@ -736,12 +747,16 @@ export interface definitions {
736747
* @description Cost is the price in cents that will be added to plan's base cost
737748
* when this value is selected or is default for the plan.
738749
* Number features should use the cost range instead.
750+
*
751+
* @default 0
739752
*/
740753
cost?: number;
741754
/**
742755
* @description When a feature is used to multiply the cost of the plan or of
743756
* another feature, multiply factor is used for calculation.
744757
* A feature cannot have both a cost and a multiply factor.
758+
*
759+
* @default 0
745760
*/
746761
multiply_factor?: number;
747762
/**
@@ -771,7 +786,10 @@ export interface definitions {
771786
* @default 1
772787
*/
773788
increment?: number;
774-
/** @description Minimum value that can be set by a user if customizable */
789+
/**
790+
* @description Minimum value that can be set by a user if customizable
791+
* @default 0
792+
*/
775793
min?: number;
776794
/** @description Maximum value that can be set by a user if customizable */
777795
max?: number;
@@ -790,6 +808,8 @@ export interface definitions {
790808
/**
791809
* @description An integer in 10,000,000ths of cents, will be multiplied by the
792810
* numeric value set in the feature to determine the cost.
811+
*
812+
* @default 0
793813
*/
794814
cost_multiple?: number;
795815
};
@@ -819,6 +839,8 @@ export interface definitions {
819839
/**
820840
* @description When true, everyone can see the product when requested. When false it will
821841
* not be visible to anyone except those on the provider team.
842+
*
843+
* @default false
822844
*/
823845
public?: boolean;
824846
/**
@@ -827,6 +849,8 @@ export interface definitions {
827849
* but can still be provisioned directly if it's label is known.
828850
* Any pages that display information about the product when not listed,
829851
* should indicate to webcrawlers that the content should not be indexed.
852+
*
853+
* @default false
830854
*/
831855
listed?: boolean;
832856
/**
@@ -842,18 +866,24 @@ export interface definitions {
842866
* @description Indicates whether or not the product is in `Beta` and should be
843867
* advertised as such. This does not have any impact on who can access the
844868
* product, it is just used to inform consumers through our clients.
869+
*
870+
* @default false
845871
*/
846872
beta?: boolean;
847873
/**
848874
* @description Indicates whether or not the product is in `New` and should be
849875
* advertised as such. This does not have any impact on who can access the
850876
* product, it is just used to inform consumers through our clients.
877+
*
878+
* @default false
851879
*/
852880
new?: boolean;
853881
/**
854882
* @description Indicates whether or not the product is in `New` and should be
855883
* advertised as such. This does not have any impact on who can access the
856884
* product, it is just used to inform consumers through our clients.
885+
*
886+
* @default false
857887
*/
858888
featured?: boolean;
859889
};

test/bin/expected/specs/petstore.ts

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export interface components {
7979
* @enum {string}
8080
*/
8181
status?: "placed" | "approved" | "delivered";
82+
/** @default false */
8283
complete?: boolean;
8384
};
8485
Category: {

test/bin/expected/stdin.ts

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export interface components {
7979
* @enum {string}
8080
*/
8181
status?: "placed" | "approved" | "delivered";
82+
/** @default false */
8283
complete?: boolean;
8384
};
8485
Category: {

test/bin/expected/stdout.ts

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export interface components {
7979
* @enum {string}
8080
*/
8181
status?: "placed" | "approved" | "delivered";
82+
/** @default false */
8283
complete?: boolean;
8384
};
8485
Category: {

test/opts/expected/remote-schema.ts

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export interface external {
9393
* @enum {string}
9494
*/
9595
status?: "placed" | "approved" | "delivered";
96+
/** @default false */
9697
complete?: boolean;
9798
};
9899
Category: {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* This file was auto-generated by openapi-typescript.
3+
* Do not make direct changes to the file.
4+
*/
5+
6+
export interface paths {
7+
'/test': {
8+
get: {
9+
parameters: {
10+
query: {
11+
search: string
12+
}
13+
}
14+
responses: {
15+
200: unknown
16+
}
17+
}
18+
}
19+
}
20+
21+
export interface definitions {
22+
TestSchema: {
23+
/**
24+
* @default false
25+
* @example false
26+
*/
27+
isEnabled?: boolean
28+
/**
29+
* @default 0
30+
* @example 0
31+
*/
32+
count?: number
33+
}
34+
}
35+
36+
export interface operations {}
37+
38+
export interface external {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* This file was auto-generated by openapi-typescript.
3+
* Do not make direct changes to the file.
4+
*/
5+
6+
export type paths = {
7+
'/test': {
8+
get: {
9+
parameters: {
10+
query: {
11+
search: string
12+
}
13+
}
14+
responses: {
15+
200: unknown
16+
}
17+
}
18+
}
19+
}
20+
21+
export type definitions = {
22+
TestSchema: {
23+
/**
24+
* @default false
25+
* @example false
26+
*/
27+
isEnabled?: boolean
28+
/**
29+
* @default 0
30+
* @example 0
31+
*/
32+
count?: number
33+
}
34+
}
35+
36+
export type operations = {}
37+
38+
export type external = {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* This file was auto-generated by openapi-typescript.
3+
* Do not make direct changes to the file.
4+
*/
5+
6+
export interface paths {
7+
readonly '/test': {
8+
readonly get: {
9+
readonly parameters: {
10+
readonly query: {
11+
readonly search: string
12+
}
13+
}
14+
readonly responses: {
15+
readonly 200: unknown
16+
}
17+
}
18+
}
19+
}
20+
21+
export interface definitions {
22+
readonly TestSchema: {
23+
/**
24+
* @default false
25+
* @example false
26+
*/
27+
readonly isEnabled?: boolean
28+
/**
29+
* @default 0
30+
* @example 0
31+
*/
32+
readonly count?: number
33+
}
34+
}
35+
36+
export interface operations {}
37+
38+
export interface external {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* This file was auto-generated by openapi-typescript.
3+
* Do not make direct changes to the file.
4+
*/
5+
6+
export interface paths {
7+
'/test': {
8+
get: {
9+
parameters: {
10+
query: {
11+
search: string
12+
}
13+
}
14+
responses: {
15+
200: unknown
16+
}
17+
}
18+
}
19+
}
20+
21+
export interface definitions {
22+
TestSchema: {
23+
/**
24+
* @default false
25+
* @example false
26+
*/
27+
isEnabled?: boolean
28+
/**
29+
* @default 0
30+
* @example 0
31+
*/
32+
count?: number
33+
}
34+
}
35+
36+
export interface operations {}
37+
38+
export interface external {}

0 commit comments

Comments
 (0)