Skip to content

fix: Serialize falsey values #906

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { GlobalContext, OpenAPI2, OpenAPI3, SchemaObject, SwaggerToTSOptions } from "./types.js";
import path from "path";
import fs from "fs";
import prettier from "prettier";
import parserTypescript from "prettier/parser-typescript.js";
import { Readable } from "stream";
Expand Down Expand Up @@ -115,7 +116,9 @@ async function openapiTS(
};
if (options && options.prettierConfig) {
try {
const userOptions = await prettier.resolveConfig(path.resolve(process.cwd(), options.prettierConfig));
const prettierConfigFile = path.resolve(process.cwd(), options.prettierConfig);
await fs.promises.access(prettierConfigFile, fs.constants.F_OK);
const userOptions = await prettier.resolveConfig(prettierConfigFile);
prettierOptions = {
...(userOptions || {}),
...prettierOptions,
Expand Down
9 changes: 8 additions & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,14 @@ export function prepareComment(v: CommentObject): string | void {
const supportedJsDocTags: Array<keyof CommentObject> = ["description", "default", "example"];
for (let index = 0; index < supportedJsDocTags.length; index++) {
const field = supportedJsDocTags[index];
if (v[field]) commentsArray.push(`@${field} ${v[field]} `);
const allowEmptyString = field === "default" || field === "example";
if (v[field] === undefined) {
continue;
}
if (v[field] === "" && !allowEmptyString) {
continue;
}
commentsArray.push(`@${field} ${v[field]} `);
}

// * JSDOC 'Constant' without value
Expand Down
8 changes: 7 additions & 1 deletion test/bin/cli.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,20 @@ describe("cli", () => {
});

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

it("--prettier-config (missing)", async () => {
expect(() => {
execSync(`${cmd} specs/petstore.yaml -o generated/prettier-missing.ts --prettier-config NO_SUCH_FILE`);
}).to.throw('NO_SUCH_FILE');
});

it("stdout", async () => {
const generated = execSync(`${cmd} specs/petstore.yaml`, { cwd });
const expected = eol.lf(fs.readFileSync(new URL("./expected/stdout.ts", cwd), "utf8"));
Expand Down
1 change: 1 addition & 0 deletions test/bin/expected/paths-enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export interface components {
* @enum {string}
*/
status?: "placed" | "approved" | "delivered";
/** @default false */
complete?: boolean;
};
Category: {
Expand Down
1 change: 1 addition & 0 deletions test/bin/expected/prettier-js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export interface components {
* @enum {string}
*/
status?: 'placed' | 'approved' | 'delivered'
/** @default false */
complete?: boolean
}
Category: {
Expand Down
1 change: 1 addition & 0 deletions test/bin/expected/prettier-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export interface components {
* @enum {string}
*/
status?: 'placed' | 'approved' | 'delivered'
/** @default false */
complete?: boolean
}
Category: {
Expand Down
34 changes: 32 additions & 2 deletions test/bin/expected/specs/manifold.ts
Original file line number Diff line number Diff line change
Expand Up @@ -688,23 +688,32 @@ export interface definitions {
name: definitions["Name"];
/** @enum {string} */
type: "boolean" | "string" | "number";
/** @description This sets whether or not the feature can be customized by a consumer. */
/**
* @description This sets whether or not the feature can be customized by a consumer.
* @default false
*/
customizable?: boolean;
/**
* @description This sets whether or not the feature can be upgraded by the consumer after the
* resource has provisioned. Upgrading means setting a higher value or selecting a
* higher element in the list.
*
* @default false
*/
upgradable?: boolean;
/**
* @description This sets whether or not the feature can be downgraded by the consumer after the
* resource has provisioned. Downgrading means setting a lower value or selecting a
* lower element in the list.
*
* @default false
*/
downgradable?: boolean;
/**
* @description Sets if this feature’s value is trackable from the provider,
* this only really affects numeric constraints.
*
* @default false
*/
measurable?: boolean;
values?: definitions["FeatureValuesList"];
Expand All @@ -725,6 +734,8 @@ export interface definitions {
* @description The cost that will be added to the monthly plan cost when this value
* is selected or is default for the plan.
* Cost is deprecated in favor of the `price.cost` field.
*
* @default 0
*/
cost?: number;
/**
Expand All @@ -736,12 +747,16 @@ export interface definitions {
* @description Cost is the price in cents that will be added to plan's base cost
* when this value is selected or is default for the plan.
* Number features should use the cost range instead.
*
* @default 0
*/
cost?: number;
/**
* @description When a feature is used to multiply the cost of the plan or of
* another feature, multiply factor is used for calculation.
* A feature cannot have both a cost and a multiply factor.
*
* @default 0
*/
multiply_factor?: number;
/**
Expand Down Expand Up @@ -771,7 +786,10 @@ export interface definitions {
* @default 1
*/
increment?: number;
/** @description Minimum value that can be set by a user if customizable */
/**
* @description Minimum value that can be set by a user if customizable
* @default 0
*/
min?: number;
/** @description Maximum value that can be set by a user if customizable */
max?: number;
Expand All @@ -790,6 +808,8 @@ export interface definitions {
/**
* @description An integer in 10,000,000ths of cents, will be multiplied by the
* numeric value set in the feature to determine the cost.
*
* @default 0
*/
cost_multiple?: number;
};
Expand Down Expand Up @@ -819,6 +839,8 @@ export interface definitions {
/**
* @description When true, everyone can see the product when requested. When false it will
* not be visible to anyone except those on the provider team.
*
* @default false
*/
public?: boolean;
/**
Expand All @@ -827,6 +849,8 @@ export interface definitions {
* but can still be provisioned directly if it's label is known.
* Any pages that display information about the product when not listed,
* should indicate to webcrawlers that the content should not be indexed.
*
* @default false
*/
listed?: boolean;
/**
Expand All @@ -842,18 +866,24 @@ export interface definitions {
* @description Indicates whether or not the product is in `Beta` and should be
* advertised as such. This does not have any impact on who can access the
* product, it is just used to inform consumers through our clients.
*
* @default false
*/
beta?: boolean;
/**
* @description Indicates whether or not the product is in `New` and should be
* advertised as such. This does not have any impact on who can access the
* product, it is just used to inform consumers through our clients.
*
* @default false
*/
new?: boolean;
/**
* @description Indicates whether or not the product is in `New` and should be
* advertised as such. This does not have any impact on who can access the
* product, it is just used to inform consumers through our clients.
*
* @default false
*/
featured?: boolean;
};
Expand Down
1 change: 1 addition & 0 deletions test/bin/expected/specs/petstore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export interface components {
* @enum {string}
*/
status?: "placed" | "approved" | "delivered";
/** @default false */
complete?: boolean;
};
Category: {
Expand Down
1 change: 1 addition & 0 deletions test/bin/expected/stdin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export interface components {
* @enum {string}
*/
status?: "placed" | "approved" | "delivered";
/** @default false */
complete?: boolean;
};
Category: {
Expand Down
1 change: 1 addition & 0 deletions test/bin/expected/stdout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export interface components {
* @enum {string}
*/
status?: "placed" | "approved" | "delivered";
/** @default false */
complete?: boolean;
};
Category: {
Expand Down
1 change: 1 addition & 0 deletions test/opts/expected/remote-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export interface external {
* @enum {string}
*/
status?: "placed" | "approved" | "delivered";
/** @default false */
complete?: boolean;
};
Category: {
Expand Down
38 changes: 38 additions & 0 deletions test/v2/expected/falsey-example.additional.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* This file was auto-generated by openapi-typescript.
* Do not make direct changes to the file.
*/

export interface paths {
'/test': {
get: {
parameters: {
query: {
search: string
}
}
responses: {
200: unknown
}
}
}
}

export interface definitions {
TestSchema: {
/**
* @default false
* @example false
*/
isEnabled?: boolean
/**
* @default 0
* @example 0
*/
count?: number
}
}

export interface operations {}

export interface external {}
38 changes: 38 additions & 0 deletions test/v2/expected/falsey-example.exported-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* This file was auto-generated by openapi-typescript.
* Do not make direct changes to the file.
*/

export type paths = {
'/test': {
get: {
parameters: {
query: {
search: string
}
}
responses: {
200: unknown
}
}
}
}

export type definitions = {
TestSchema: {
/**
* @default false
* @example false
*/
isEnabled?: boolean
/**
* @default 0
* @example 0
*/
count?: number
}
}

export type operations = {}

export type external = {}
38 changes: 38 additions & 0 deletions test/v2/expected/falsey-example.immutable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* This file was auto-generated by openapi-typescript.
* Do not make direct changes to the file.
*/

export interface paths {
readonly '/test': {
readonly get: {
readonly parameters: {
readonly query: {
readonly search: string
}
}
readonly responses: {
readonly 200: unknown
}
}
}
}

export interface definitions {
readonly TestSchema: {
/**
* @default false
* @example false
*/
readonly isEnabled?: boolean
/**
* @default 0
* @example 0
*/
readonly count?: number
}
}

export interface operations {}

export interface external {}
38 changes: 38 additions & 0 deletions test/v2/expected/falsey-example.support-array-length.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* This file was auto-generated by openapi-typescript.
* Do not make direct changes to the file.
*/

export interface paths {
'/test': {
get: {
parameters: {
query: {
search: string
}
}
responses: {
200: unknown
}
}
}
}

export interface definitions {
TestSchema: {
/**
* @default false
* @example false
*/
isEnabled?: boolean
/**
* @default 0
* @example 0
*/
count?: number
}
}

export interface operations {}

export interface external {}
Loading