Giter VIP home page Giter VIP logo

nestia's Introduction

Nestia

Nestia Logo

GitHub license npm version Downloads Build Status Guide Documents Discord Badge

Nestia is a set of helper libraries for NestJS, supporting below features:

  • @nestia/core:
    • Super-fast/easy decorators
    • Advanced WebSocket routes
  • @nestia/sdk:
    • Swagger generator evolved than ever
    • SDK library generator for clients
    • Mockup Simulator for client applications
    • Automatic E2E test functions generator
  • @nestia/migrate: Migration from Swagger to NestJS
  • @nestia/editor: Online TypeScript Swagger Editor
  • nestia: Just CLI (command line interface) tool

Note

  • Only one line required, with pure TypeScript type
  • Enhance performance 30x up
    • Runtime validator is 20,000x faster than class-validator
    • JSON serialization is 200x faster than class-transformer
  • Software Development Kit
    • Collection of typed fetch functions with DTO structures like tRPC
    • Mockup simulator means embedded backend simulator in the SDK
      • similar with msw, but fully automated

nestia-sdk-demo

Left is NestJS server code, and right is client (frontend) code utilizing SDK

Sponsors and Backers

Thanks for your support.

Your donation would encourage nestia development.

Backers

Guide Documents

Check out the document in the website:

๐Ÿ  Home

๐Ÿ“– Features

๐Ÿ”— Appendix

nestia's People

Contributors

39hn avatar 8471919 avatar bwsix avatar chanwukim avatar davidvaness avatar de-novo avatar dependabot[bot] avatar dipanc1 avatar dipanshuhappy avatar dohyuu avatar dragonol avatar jochongs avatar joeypy avatar kakasoo avatar loucass003 avatar matthew-cupist avatar mjoon-jung avatar mykhailo-monchak avatar ninthsun91 avatar nundung avatar rojiwon123 avatar samchon avatar seo-rii avatar seungjunwe avatar skyatura avatar t1mofe1 avatar theyarin avatar wibus-wee avatar windofwind avatar yj-anthonyjo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nestia's Issues

Support documentation comments

It would better to copy documentation comments from NestJS.Controller methods to the SDK functions.

Controller

export class SaleCommentsController
{
    /**
     * Get page of comments.
     * 
     * @param section Code of the target section
     * @param saleId ID of the target sale
     * @param articleId ID of the target article
     * @param input Information about pagination and searching
     * @return Page of the comments
     */
    @helper.EncryptedRoute.Get()
    public async index
        (
            @helper.TypedParam("section", "string") section: string, 
            @helper.TypedParam("saleId", "number") saleId: number, 
            @helper.TypedParam("articleId", "number") articleId: number,
            @nest.Query() input: IPage.IRequest
        ): Promise<IPage<ISaleComment>>
    {
        section;
        saleId;
        articleId;
        input;

        return null!;
    }
}

SDK

/**
 * Get page of comments.
 * 
 * @param section Code of the target section
 * @param saleId ID of the target sale
 * @param articleId ID of the target article
 * @param input Information about pagination and searching
 * @return Page of the comments
 */
export function index(connection: IConnection, section: string, saleId: number, articleId: number, input: Primitive<index.Query>): Promise<index.Output>
{
    return Fetcher.fetch
    (
        connection,
        {"input_encrypted":false,"output_encrypted":true},
        "GET",
        `consumers/${section}/sales/${saleId}/comments/${articleId}/?${new URLSearchParams(input as any).toString()}`
    );
}

Replace directory of the compiled files from `bin` to `lib`

To recommend users to IConfiguration from this nestia when configuring the nestia.config.ts, it would better to change the directory name to be compiled. The executable programs would be placed into the lib/executable, therefore no problem in the naming strategy and its representative meaning.

`ts-node` v10 shebang is not working

Must rollback to the v9.

The ts-node@10 occurs such error:

import * as cp from "child_process";
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    at Module._compile (node:internal/modules/cjs/loader:1065:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Object.require.extensions.<computed> [as .ts] (D:\github\archidraw\erp-backend\node_modules\ts-node\src\index.ts:1045:43)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at main (D:\github\archidraw\erp-backend\node_modules\ts-node\src\bin.ts:198:14)
    at Object.<anonymous> (D:\github\archidraw\erp-backend\node_modules\ts-node\src\bin.ts:288:3)

`typescript-transform-paths` to be optional as it's too slow

I've adopted the typescript-transform-paths library to support the path alias - #20. However, when building an SDK libary with the typescript-transform-paths, elapsed time be about three times.

Therefore, it would better to turn it on only when the alias path has been configured. In the same reason, typescript-is would be turned on only when the assert mode in on - #32.

nestia sdk command even considers output as input

If type a nestia command like below, even the output directory api would be considered as one of the input directories.

nestia sdk src/controllers --out api

Also, if a developer types a mis-programmed script in some files who are generated by the nestia, nestia never can re-build the SDK library, because compile error would be occured by considering the output directory as one of the input directories.

Therefore, I need to fix the but that output directory would not be considered as one of the input directories. Also, I need to exclude some files and directories that are generated by the nestia, for the exceptional case that developer manually types mis-programmed script in the SDK function files that can cause compile error.

Invalid URL parameter binding

export function index(connection: IConnection, section: string, saleId: number, articleId: number): Promise<index.Output>
{
return Fetcher.fetch
(
connection,
{"input_encrypted":false,"output_encrypted":true},
"GET",
`consumers/"${section}"/sales/"${saleId}"/comments/"${articleId}"/`
);
}

Traveling SDK generated scripts, I found that URL parameter binding is weird.

  • Wrong: consumers/"${section}"/sales/"${saleId}"/comments/"${articleId}"
  • Must be: consumers/${section}/sales/${saleId}/comments/${articleId}

`functional/` is empty when ECMAScript version is over the `es6`

๐Ÿ˜ณ What's up?

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-04-15 แ„‹แ…ฉแ„’แ…ฎ 12 12 23

An empty index file is created. (Works well with 2.0.0 version)

โŽ Reproducible repo

git clone https://github.com/hmmhmmhm/nestia-issue-report-1
cd nestia-issue-report-1
npx nestia sdk

โœ… Environment

  • MAC Big Sur
  • Node.js v16.13.0
  • Nestia v2.0.9

Conditional compilation for alias options

To resolve the #20 and #27 problems, let nestia to install the tsconfig-paths and execute the conditional compilation for the alias options. If the tsconfig.json file exists and it has the compilerOptions.paths property, generate the SDK program through the tsconfig-paths. If the compilerOptions.baseUrl does not exist, update the tsconfig.json to have the property temporary.

Otherwise, there's not the tsconfig.json file or compilerOptions.paths property, do not utilize th tsconfig-paths.

npx ts-node -r tsconfig-paths/register executable/nestia sdk ~
npx ts-node executable/nestia sdk ~

How to reflect comments written on the Controller?

If some comments are written on a Controller, I want to reflect the comments to the SDK, who would built by the nestia.

However, when the SDK has been generated and the comments of the Controller has been reflected to the matched re-export symbol, it never be appeared as an IDE hint. Of course, appering the comments as a hint by IDE would possible if the nestia reflects the controller module using the export import something = require("./something") statement. However, the require statement only works when the compilation mode is CommonJS.

Therefore, I wanna your help to show the reflected comment in the IDE level. If you know a good solution, please inform me.

//----
// BACKEND SOURCE
//----
/**
 * Some comments written on a Controller.
 */
@nest.Controller("something")
export class SomeController
{
    /**
     * Some comments written on a function.
     */
    @nest.Get()
    public index(): Promise<IPage<Something>>;
}

//----
// SDK GENERATED BY THE NESTIA - functional/index.ts
//----
/**
 * Some comments written on a Controller.
 *
 * @nestia Generated by Nestia - https://github.com/samchon/nestia
 */
export * as something from "./something";
// export import something = require("./something"); // only works when CommonJS

//----
// SDK GENERATED BY THE NESTIA - functional/something/index.ts
//----
export function something(connection: IConnection): Promise<IPage<ISomething>>;

Support union or intersection alias type

Support those union or intersection alias types

export type ISaleEntireArtcle 
    = ISaleQuestion 
    | ISaleReview;
export namespace ISaleEntireArtcle
{
    export type ISummary 
        = ISaleQuestion.ISummary 
        | ISaleReview.ISummary;

    export type IRequest
        = ISaleQuestion.IRequest
        | ISaleReview.IRequest;
}
export abstract class SaleEntireArticlesController
{
    @helper.EncryptedRoute.Get()
    public async index
        (
            @helper.TypedParam("section", "string") section: string, 
            @helper.TypedParam("saleId", "number") saleId: number, 
            @nest.Query() input: IPage.IRequest
        ): Promise<IPage<ISaleEntireArtcle.ISummary>>
    {
        section;
        saleId;
        input;
        
        return null!;
    }

    @helper.EncryptedRoute.Get(":id")
    public async at
        (
            @helper.TypedParam("section", "string") section: string, 
            @helper.TypedParam("saleId", "number") saleId: number, 
            @helper.TypedParam("id", "number") id: number
        ): Promise<ISaleEntireArtcle>
    {
        section;
        saleId;
        id;

        return null!;
    }
}

2.0.3 SDK Build Error

$ npx nestia sdk
env: node: No such file or directory
Command failed: npx ts-node -C ttypescript /Users/hamin/Desktop/Workspace/platform-programming/backend/platform-api-nest/node_modules/nestia/src/bin/../executable/sdk

An error is generated that is presumed to be a problem with path resolve.

Implement test programs for the alias

Implement some test programs to the #20 issue.

The 1st is defining alias @api only for the src/api folder and 2nd is defining alias @src for the entire src folder.

Error when no parameter exists

When declaring a controller method that has not any parameter, it becomes an error.

import * as helper from "encrypted-nestjs";
import * as nest from "@nestjs/common";

@nest.Controller("bbs/articles")
export class BbsArticleController
{
    @helper.EncryptedRoute.Get()
    public async index(): Promise<IPage<IBbsArticle.ISummary>>;
}

Provide a solution that server let clients to set their headers

I'm considering how to provide a solution that server let clients to set their headers automatically. I'm considering this way: If returned object (response body of json type) from the server has an object typed __set_headers__ variable, key and values in the __set_headers__ object would be assigned to client's request headers.

export function login(input: login.Input): Promise<login.Output>;
export namespace login
{
    export interface Input
    {
        email: string;
        password: string;
    }

    export interface Output
    {
        Authorization: `Bearer ${string}`;
    }
}

When only one controller method exists in an URL

If there're only one controller method in an URL, it would better not to separate the matched SDK function to an independent TypeScript file. Therefore, only one controller method exists in an URL, gather the matched SDK function into its parent URL's namespace scope.

Example Case

@nest.Controller("markets/sellers/authenticate")
export class SellerAuthenticateController
{
    @helper.EncryptedRoute.Post("join")
    public async join
        (
            @helper.EncryptedBody() input: ISeller.IJoin
        ): Promise<ISeller>;

     @helper.EncryptedRoute.Post("login")
    public async login
        (
            @helper.EncryptedBody() input: ISeller.ILogin
        ): Promise<ISeller>;
}

Ordinary SDK

await api.functional.markets.sellers.authenticate.join.join();
await api.functional.markets.sellers.authenticate.login.login();

New SDK

await api.functional.markets.sellers.authenticate.join();
await api.functional.markets.sellers.authenticate.login();

`NestiaApplication`.`IConfiguration`

export class NestiaApplication
{
    public constructor(config: NestiaApplication.IConfiguration);
    public generate(): Promise<void>;
}
export namespace NestiaApplication
{
    export interface IConfiguration
    {
        input: string[];
        output: string;
        compilerOptions?: tsc.CompilerOptions;
    }
}

Give up using native `ts-node` with shebang

I've tried to publish nestia module to run up the native ts-node. However, too many domestic problems have happened.

Therefore, give up it and turn back to the JS shebang. The ts-node would be registered in the JS program and emending the tsconfig.json would be done in the memory level. Therefore, nestia no more emend the tsconfig.json physically. However, there would not be any problem although the physical emension has been halted.

Import aliases

PS C:\Users\afons\Desktop\vettted> yarn nestia sdk ".\src\backend\controllers" --out ".\src\xapi"
yarn run v1.22.15
$ C:\Users\afons\Desktop\vettted\node_modules\.bin\nestia sdk .\src\backend\controllers --out .\src\xapi
src/backend/controllers/category.controller.ts:2:51 - error TS2307: Cannot find module '@/backend/services/category.service' or its corresponding type declarations.

2 import { CategoryService, ICategoryService } from "@/backend/services/category.service";
                                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

New property `IConfiguration.assert` with `typescript-is`

If the IConfiguration.assert be true, all of the input parameters of the API functions, their types would be checked in the runtime through the typescript-is. When this issue has been implemented, SDK library function would form like below:

import { assertType } from "typescript-is";

export function store
    (
        connection: IConnection,
        section: string,
        saleId: number,
        input: Primitive<store.Input>
    ): Promise<store.Output>
{
    assertType<typeof section>(section);
    assertType<typeof saleId>(saleId);
    assertType<typeof input>(input);

    return Fetcher.fetch
    (
        connection,
        store.ENCRYPTED,
        store.METHOD,
        store.path(section, saleId),
        input
    );
}

POST issue in 2.0.0

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-04-12 แ„‹แ…ฉแ„’แ…ฎ 6 45 32

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-04-12 แ„‹แ…ฉแ„’แ…ฎ 6 45 37

It seems that the value entering the fetcher is being generated incorrectly.

Comment on `IConfiguration`

As users of the nestia are recommended to import the IConfiguration type, detailed comments are required.

`FunctionGenerator` omits the semicolon `;`

When the json options has been turned on, the FunctionGenerator omits the semicolon ; at the tail.

export namespace some_path
{
    export const stringify = createStringifier<T>()
}

Support alias paths by `typescript-transform-paths`

Rather than tsconfig-paths, typescript-transform-paths seems much better. It's because the typescript-transform-paths changes the alias path import statements to be relative by transforming the TypeScript code in the compilation level. Beside, the tsconfig-paths runs on the runtime level like https://github.com/ilearnio/module-alias who
never can avoid the module not found error in the TS-NODE

Therefore, try to use the typescript-transform-paths and test some complicate projects who occurs the #20 error.

Change import statement construction algorithm

When nestia generates an SDK library, nestia implements the import statements by analyzing which types are used in the paramters and return value of the methods who are declared in the controller classes. Iterating the parameters and return types of the controller methods, nestia memorizes where those types are defined in.

After those analyses, nestia archives the import statements converting the import path to be adequate. If the target instance is capsuled in a namespace, the parent namespace would be imported. If the parent namespace is also being capsuled in another grandparent namespace, the grandparent would be imported.

Such import statement construction algorithm are correct in most case, however, there're some exceptional cases in the @types/node/index.d.ts, a typical types library for the NodeJS. As its object construction structure is very abnormal, when generating an SDK library function targeting a NestJS controller who are using the NodeJS object directly, such terrible output would be generated.

Therefore, to resolve such abnormal case, I need to change import statement construction algorithm in the basic level.

NestJS Controller

@nest.Controller("performance")
export class PerformanceController
{
    @helper.EncryptedRoute.Get("memory")
    public memory(): NodeJS.MemoryUsage
    {
        return process.memoryUsage();
    }
}

SDK function generated by the Nestia

/**
 * @controller PerformanceController.memory()
 * @path GET performance/memory
 */
export function memory(connection: IConnection): Promise<memory.Output>
{
    return Fetcher.fetch
    (
        connection,
        {"input_encrypted":false,"output_encrypted":true},
        "GET",
        `performance/memory`
    );
}
export namespace memory
{
    export type Output = Primitive<"process".global.NodeJS.MemoryUsage>;
}

Constant values in the functional namespaces

Shifts principle properties of the fetcher from function body to its namespace like below:

export function store
    (
        connection: IConnection,
        section: string,
        saleId: number,
        inquiryId: number,
        input: Primitive<store.Input>
    ): Promise<store.Output>
{
    return Fetcher.fetch
    (
        connection,
        store.CONFIG,
        store.METHOD,
        store.path(section, saleId, inquiryId),
        input
    );
}
export namespace store
{
    export type Input = Primitive<ISaleArticle.IContent>;
    export type Output = Primitive<ISaleInquiry<ISaleReview.IContent>>;

    export const METHOD = "POST";
    export const PATH = "/sellers/:section/sales/:saleId/reviews/:inquiryId";
    export const CONFIG = {
        input_encrypted: true,
        output_encrypted: true,
    };

    export function path(section: string, saleId: number, inquiryId: number): string
    {
        return `/sellers/${section}/sales/${saleId}/reviews/${inquiryId}`;
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.