samchon / nestia

NestJS Helper Libraries + TypeScript OpenAPI generator
https://nestia.io/
MIT License
1.76k stars 91 forks source link

How about to use the "examples" function of Swagger? for convenience to front-end developer? #820

Closed 8471919 closed 1 month ago

8471919 commented 5 months ago

I always feel thank for you to make this great library.

This function that I will suggest from now is not necessary function. but It makes that the better User Experience.

currently, if we want to use two responses from same status code, the swagger makes the two responses belong to only "oneOf" option. but, If you make that responses belong to also "examples" option, the user (especially front-end developer) can see the responses clearly as follow.

image

image

image

image

samchon commented 5 months ago

It is possible to support swagger examples.

By the way, do you think that the examples should be put into the SDK?

8471919 commented 5 months ago

It is possible to support swagger examples.

By the way, do you think that the examples should be put into the SDK?

What you mean is to put true or false option of the 'examples' in nestia.config.ts?

I can't imagine how will you put the "examples" in SDK.

samchon commented 5 months ago
/**
 * Store an article.
 *
 * @param input Content to store
 * @returns Newly archived article
 * @deprecated
 *
 * @controller BbsArticlesController.store
 * @path POST /bbs/articles
 * @nestia Generated by Nestia - https://github.com/samchon/nestia
 */
export async function store(
  connection: IConnection,
  input: store.Input,
): Promise<store.Output> {
  return PlainFetcher.fetch(
    {
      ...connection,
      headers: {
        ...connection.headers,
        "Content-Type": "application/json",
      },
    },
    {
      ...store.METADATA,
      path: store.path(),
    },
    input,
  );
}
export namespace store {
  export type Input = Primitive<IBbsArticle.IStore>;
  export type Output = Primitive<IBbsArticle>;

  export const METADATA = {
    method: "POST",
    path: "/bbs/articles",
    request: {
      type: "application/json",
      encrypted: false,
    },
    response: {
      type: "application/json",
      encrypted: false,
    },
    status: null,
  } as const;

  export const path = () => "/bbs/articles";

  export const EXAMPLES: Output[] = [...];
}

Something like this.

8471919 commented 5 months ago
/**
 * Store an article.
 *
 * @param input Content to store
 * @returns Newly archived article
 * @deprecated
 *
 * @controller BbsArticlesController.store
 * @path POST /bbs/articles
 * @nestia Generated by Nestia - https://github.com/samchon/nestia
 */
export async function store(
  connection: IConnection,
  input: store.Input,
): Promise<store.Output> {
  return PlainFetcher.fetch(
    {
      ...connection,
      headers: {
        ...connection.headers,
        "Content-Type": "application/json",
      },
    },
    {
      ...store.METADATA,
      path: store.path(),
    },
    input,
  );
}
export namespace store {
  export type Input = Primitive<IBbsArticle.IStore>;
  export type Output = Primitive<IBbsArticle>;

  export const METADATA = {
    method: "POST",
    path: "/bbs/articles",
    request: {
      type: "application/json",
      encrypted: false,
    },
    response: {
      type: "application/json",
      encrypted: false,
    },
    status: null,
  } as const;

  export const path = () => "/bbs/articles";

  export const EXAMPLES: Output[] = [...];
}

Something like this.

oh, it looks great. If this function is released, I want to try it. I think that feels me comfortable.

and this might be off topic... how about to add generic type of @TypedException to sdk? when catch the axios error, I feel inconvenint that the vscode can't infering error types. Even if I used propagate mode, in propagate mode the data couldn't infering the success data type.

samchon commented 5 months ago

I will check the propagate type again.

By the way, how to write the example data in the method? Do you have any idea?

8471919 commented 5 months ago

I will check the propagate type again.

By the way, how to write the example data in the method? Do you have any idea?

I think the "Example" of sdk should utilize as type rather than value. because It's so hard to use only type of result, and the input of "Example" is originally type. It's so convenient if I can get return type like api.typical.bbs.article.store.status<404>.Example or api.typical.bbs.article.store.Example<statusCode>

// api/typical/bbs/article
export namespace store {
  export type Example<T> = T extends 404
    ? {code: 404, message: "no articles here"} | {code: 404, message: "no bbs here"}
    : T extends 400
      ? ...etc : ...etc
}

// front
type ResponseError<T> = api.typical.bbs.article.store.Example<T>

try {
  const res = await api.functional.bbs.article.store(url)
  ...
} catch (err) {
  const errorData: ResponseError<typeof err.statusCode>;
  ...
}
samchon commented 1 month ago

https://nestia.io/docs/sdk/swagger/#nestjs-decorators

Added @SwaggerExample() decorator, but considering I should add the example values to insert to SDK or not. The example values can enhance the bundling size of the SDK package, and such enhanced bundling size is critical for frontend development side.

Therefore, just hope to satisfy only with swagger file.