Coder Social home page Coder Social logo

farrow-js / farrow Goto Github PK

View Code? Open in Web Editor NEW
767.0 12.0 37.0 9.75 MB

A Type-Friendly Web Framework for Node.js

Home Page: https://www.farrowjs.com

License: MIT License

TypeScript 97.53% JavaScript 2.02% HTML 0.09% CSS 0.36%
typescript nodejs web-framework full-stack

farrow's Introduction

Farrow Logo

npm version Test Status Lint Status Benchmark Status License: MIT

Description

Farrow is A Type-Friendly Web Framework for Node.js

Getting Started

Please follow the documentation at farrowjs.com!

Benefits

  • Expressive HTTP middleware like Koa but no need to modify req/res or ctx
  • Strongly typed and type-safe from request to response via powerful schema-based validation
  • Provide React-Hooks-like mechanism which is useful for reusing code and integrating other parts of Server like database connection
  • Easy to learn and use if you were experienced in expressjs/koajs

Farrow Demo

Environment Requirement

  • TypeScript >= 4.3
  • Node.js >= 14.x

Issues

Contributions, issues and feature requests are welcome! Feel free to check issues page.

Stay In Touch

License

This project is MIT licensed.

Copyright © 2021-present, Jade Gu.

farrow's People

Contributors

circlle avatar dependabot[bot] avatar herringtondarkholme avatar lucifier129 avatar myvipbackup2 avatar sinoon avatar ssshuai1999 avatar suica avatar superhuangxu avatar tqma113 avatar uinz avatar ycaptain avatar zheeeng avatar zzj3720 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

farrow's Issues

Feature(farrow-restapi): combine request schema and response schema to be api schema.

For now, farrow-http just supporting the request schema.

We can use farrow-schema to describe the request and response of all the RESTFul API and integrate it with something like oepnapi. And seamless reusing the schema/type of all Apis in client-side for implementing type-safe fetcher.

The server-side

import { RequestType, ResponseType, toRouter } from 'farrow-restapi'

const GetUserRequest = RequestType({
  url: '/user?<id:int>'
})

const GetUserResponse = ResponseType ({
  success: Boolean,
  message:  String,
  data: {
    id: Number,
    name: String,
    email: String  
  }
})

const GetUserApi = {
  request: GetUserRequest ,
  response: GetUserResponse 
}

const Apis = {
  getUser: GetUserApi
}

const getUserRouter = toRouter(GetUserApi)

getUserRouter.impl(request => {
  // response should be GetUserResponse 
})

The client-side

The schema of API can generate an API client for client-side

import { createFarrowApiClient } from 'farrow-restapi-client'

let client= createFarrowApiClient(Apis, {
  baseurl: '/path/to/base'
})

client.getUser(GetUserRequest) -> Promise<GetUserResponse>

Feature(farrow): support retouching generated client code when farrow build

Problem description

The client code generated by farrow-api contains a specific url.
It's looks like http://localhost:3003/api/category when the env is development. I ran into a problem when I deployed project to server. The server is now running on my remote machine instead of local, however the url is still http://localhost:3003/api/category which is sent to browser. Maybe we need some approach to rewrite the url to my server host when build time.

Possible solution

Using the api config from farrow.config.js to rewrite the url in generated code When run farrow build

Extra

I will submit a pull request to solve this soon.

farrow-example can't build after bootstraping with lerna

Problem

farrow-example cannot run if the monorepo is merely initialized by lerna bootstrap (or just npm run init).

When executing npm run dev for farrow-example (in ./packages/example), there will be an error:

> [email protected] dev /Users/farrow-test/workspace/temp/farrow/packages/example
> farrow dev

internal/modules/cjs/loader.js:883
  throw err;
  ^

Error: Cannot find module '../dist/dev'
Require stack:
- /Users/farrow-test/workspace/temp/farrow/packages/farrow/scripts/dev.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
    at Function.Module._load (internal/modules/cjs/loader.js:725:27)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (/Users/farrow-test/workspace/temp/farrow/packages/farrow/scripts/dev.js:2:13)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/farrow-test/workspace/temp/farrow/packages/farrow/scripts/dev.js'
  ]
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] dev: `farrow dev`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] dev script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/farrow-test/.npm/_logs/2021-01-16T15_36_27_978Z-debug.log

This issue also happens in farrow 1.5.0 repo.

How to reproduce

  1. clone the repo (or just delete all node_modules folders).
  2. run npm run init.
  3. cd to ./packages/example
  4. run npm run dev.

Workarounds

Since lerna reuses modules, the farrow-example package just uses the farrow in a linked fashion.
Removing node_modules and package-lock.json in example folder then a rerun of npm i in exmaple folder to reinstall dependencies could temporarily fix this.

`Type alias circularly references` and `Index signature is missing` conflict

Feature Request(farrow-pipeline): Custom callback of Counter

Support to custom callback of Counter:

For now, it is stable:

...

const createCurrentCounter = (hooks: Hooks, onLast?: (input: I) => O, onLastWithContext?: boolean) => {
    return createCounter<I, O>((index, input, next) => {
      if (index >= middlewares.length) {
        if (onLast) {
          if (onLastWithContext) {
            return runHooks(() => onLast(input), hooks)
          }
          return onLast(input)
        }
        throw new Error(`Expect returning a value, but all middlewares just calling next()`)
      }

      const middleware = middlewares[index]
      const result = runHooks(() => middleware(input, next), hooks)

      return result
    })
  }
...

Expect:

const customCounterCallback = () => { /** ... */ }
const pipeline = createPipeline(customCounterCallback)

for more way to run middlewares.

const pipeline = createPipeline<number, number>()

const foo = (a: number) => a+1
const bar = (a: number) => a*2
const baz = (a: number) => a**2
pipeline.use(foo)
pipeline.use(foo)
pipeline.use(foo)

pipeline.run(1) // 2
// only run foo

If I can custom callback of Counter:

const pipeline = createPipeline<number, number>((index, input, next) => {
  if (index >= middlewares.length) {
    return input;
  }

  return runHooks(() => next(middlewares[index](input)), hooks);
})

...

pipeline.run(1) // 16
// run: foo -> bar -> baz

JsonType 是否需要扩展为所有可 JSON 序列化的对象?

通过 ORM 查询出来的时间字段 通常都是 JS Date 对象, 通常会直接 作为结果返回
而目前 JsonType 只包含的常见的 json 类型并不包括 Date 因此 ts 类型会报错

展开来看, 我理解 farrow 序列化应该是对齐 JSON.stringify 的, 因此 JsonType 是不是可以泛化成可被 JSON.stringify 序列化的对象呢?

http.get("/posts?<skip?:int><take?:int>").use(async (req) => {
  const { skip = 0, take = 20 } = req.query;

  const posts = await prisma.post.findMany({
    orderBy: { createdAt: "asc" },
    skip,
    take,
  });

  return Response.json({ posts });
/*                     ^^^^^^^^^^
(property) posts: Post[]
类型“{ posts: Post[]; }”的参数不能赋给类型“JsonType”的参数。
  属性“posts”的类型不兼容。
    不能将类型“Post[]”分配给类型“JsonType”。
      不能将类型“Post[]”分配给类型“JsonType[]”。
        不能将类型“Post”分配给类型“JsonType”。
          不能将类型“Post”分配给类型“{ [key: string]: JsonType; }”。
            属性“createdAt”与索引签名不兼容。
              不能将类型“Date”分配给类型“JsonType”。
                不能将类型“Date”分配给类型“{ [key: string]: JsonType; }”。
                  类型“Date”中缺少索引签名。ts(2345)
 */

});

Request: Logo

I need full size logo of farrow in development of playground. Where can I get them?

[Discussion] 是否考虑过 farrow-nest?

结合 nest adapter ,替换 express 和 fastify ,是不是可以结合 nest 达到更好的 ts 生态,或者说某些角度上会比较省事儿。
或者说,想明确一个事情,farrow 的目标和愿景是代替 koa 还是说像 nest spring ror 那样更宏大。
如果只是代替 koa ,那么个人觉得做一个 nest-adapter 是不是也不错。

文件格式的小问题

本地环境:

  • MacBook Air (M1, 2020)
  • macos 11.0.1
  • nodejs v14.15.1
  • yarn v1.22.10

按照文档配置后,执行命令 yarn dev 出现报错

➜  farrow-test yarn dev
yarn run v1.22.10
$ farrow dev
env: node\r: No such file or directory
error Command failed with exit code 127.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

查询后类似的问题 有解决方式,但希望发布 npm 包文件能修复。

I got an error when run packages/example

I got an error when run packages/example as follow:

➜  example git:(master) ✗ yarn dev
yarn run v1.22.4
$ farrow dev
internal/modules/cjs/loader.js:969
  throw err;
  ^

Error: Cannot find module 'fs/promises'
Require stack:
- /Users/forsigner/repos/github/farrow/packages/example/node_modules/farrow/dist/bundler/server.js
- /Users/forsigner/repos/github/farrow/packages/example/node_modules/farrow/dist/dev.js
- /Users/forsigner/repos/github/farrow/packages/example/node_modules/farrow/scripts/dev.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:966:15)
    at Function.Module._load (internal/modules/cjs/loader.js:842:27)
    at Module.require (internal/modules/cjs/loader.js:1026:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at Object.<anonymous> (/Users/forsigner/repos/github/farrow/packages/example/node_modules/farrow/dist/bundler/server.js:10:42)
    at Module._compile (internal/modules/cjs/loader.js:1138:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
    at Module.load (internal/modules/cjs/loader.js:986:32)
    at Function.Module._load (internal/modules/cjs/loader.js:879:14)
    at Module.require (internal/modules/cjs/loader.js:1026:19) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/forsigner/repos/github/farrow/packages/example/node_modules/farrow/dist/bundler/server.js',
    '/Users/forsigner/repos/github/farrow/packages/example/node_modules/farrow/dist/dev.js',
    '/Users/forsigner/repos/github/farrow/packages/example/node_modules/farrow/scripts/dev.js'
  ]
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Feature request: serve static assets with cache-control

As the title, in express it is supported by option of express.static like

const express = require('express');
const server = express();

const oneHour = 3600000;    // 3600000msec == 1hour
server.use(express.static('www', { maxAge: oneHour })); // Client-side file caching

server.get('/', function(req, res) {
  res.sendFile(__dirname + '/index.html');
});

server.listen(3000);

Bug: env: node\r: No such file or directory again in [email protected]

CRLF endOfLine will be sent to npm registry when run lerna publish in windows machine if forgot running npm run format after clone farrow responsity.

When using yarn in mac, farrow dev carsh due to node\r: No such file or directory

Possible solution

  1. Publish packages in CI
  2. Add npm run format to prerelease stage

http.serve serve static assets, but not go next when the file is not exist.

Type

feature request or bug report.

Module

farrow-http -> http.serve

Current

when the file is not exist return then 500 error.

Expect

when the file is not exist go down to next handler.

demo:

http.serve("/", "./static");

http.use(async (req) => {
  const url = req.pathname;
  const html = await render(url);
  const str = ReactDOMServer.renderToString(html);

  return Response.html("<!DOCTYPE html>" + str);
});

In above demo, when request not match in http.serve("/", "./static") expect it go down to then page render handler.

Type Question: Response.json get type error: is not assignable to type 'undefined'.ts(2345)

I got a type error, however, I don't have any idea about is.

Can you help me?

There are npm type:

export interface NPM {
    name: string
    "dist-tag": {
        [tag: string]: string
    }
    maintainers: {
        name: string
        email: string
        avatar: string
    }[]
    time: {
        [version: string]: string
    }
    author: {
        name: string
        email: string
    }
    license: string
}
import { Response, Router } from "farrow-http"

export const router = Router()

router
    .match({
        pathname: "/search",
        query: {
            search: String,
            limit: Number,
        },
    })
    .use(async request => {
        const { search, limit } = request.query
        // search
        const details = await getPackageDetail(search)

        return Response.json({
            code: 0,
            data: details,
        })
    })

And will got

Argument of type '{ code: number; data: NPM[]; }' is not assignable to parameter of type 'JsonType'.
  Type '{ code: number; data: NPM[]; }' is not assignable to type 'undefined'.ts(2345)

image

[Bug] can not get context after an async operation in a middleware

This code will throw error:

http.use(async (req, next) => {
  const a = useReq();
  await delay(1000);
  const b = useReq();  // Error: Can't call useContainer out of scope, it should be placed on top of the function
  return Response.json(a === b);
});

The core problem is at

https://github.com/Lucifier129/farrow/blob/877d04f97ca260927483bb3db0ee7a4ef32d05a5/packages/pipeline/src/hook.ts#L29-L36

Once f is an async function, only the code before the first await will be run in the container scope.

I have came up with an idea to solve this problem.
https://github.com/Lucifier129/farrow/blob/877d04f97ca260927483bb3db0ee7a4ef32d05a5/packages/pipeline/src/pipeline.ts#L92-L102

Change all our middleware to generator function, and change the runHooks to a generator runner like co.

I'd like to draft a PR, but this will change a lot, so asking you.

Question(http): Can I describe form data or x-www-form-urlencoded data? Or any way to support it?

like this:

form data

const data = new URLSearchParams();
for (const pair of new FormData(formElement)) {
    data.append(pair[0], pair[1]);
}

fetch(url, {
    method: 'post',
    body: data,
})
.then();

or

x-www-form-urlencoded data

var details = {
    'userName': '[email protected]',
    'password': 'Password!',
    'grant_type': 'password'
};

var formBody = [];
for (var property in details) {
  var encodedKey = encodeURIComponent(property);
  var encodedValue = encodeURIComponent(details[property]);
  formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");

fetch('https://example.com/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
  },
  body: formBody
})

请教 hook 相关的问题

如果不利用 async_hook 是不是就很难实现当前 hook 的效果?

总觉得 async_hook 实现有些黑魔法

那么在不提供 async_hook 环境里, 要如何实现 react hook like 且 Promise 友好这套 farrow hook 的机制呢?

其实我是想知道 这套设计的背后还有哪些知识点

蟹蟹

[Question] maybe we need session middleware or hook?

When I develop an inner service in my company. I find I need a session hook to manipulate user session and cookie.

So, considering the cors hooks are in official maintenance, maybe we need to add a session hook/middleware in the official repository?

似乎跟typeorm不兼容

范例

import 'reflect-metadata';
import { Http, Response } from 'farrow-http';
import { createConnection } from 'typeorm';
import { Entity, PrimaryColumn } from 'typeorm';

@Entity()
class Post {
    @PrimaryColumn()
    id!: number;
}

createConnection({
    name: 'default',
    type: 'sqlite',
    database: ':memory:',
    entities: [Post],
    synchronize: true,
    logging: false,
});

const http = Http();

// add http middleware
http.use(() => {
    // returning response in middleware
    return Response.text(`Hello Farrow`);
});

http.listen(11111);

farrow.config.js

const { createFarrowConfig } = require('farrow');
const { join } = require('path');

module.exports = createFarrowConfig({
    server: {
        entry: 'main.ts',
        src: 'server',
        dist: 'dist',
        esbuild: {
            tsconfig: join(__dirname, 'server/tsconfig.json'),
        },
    },
});

错误消息是

ColumnTypeUndefinedError: Column type for Post#id is not defined and cannot be guessed. Make sure you have turned on an "emitDecoratorMetadata": true option in tsconfig.json. 
Also make sure you have imported "reflect-metadata" on top of the main entry file in your application (before any entity imported).If you are using JavaScript instead of TypeScript you must explicitly provide a column type.

我通过 jest + ts-jest 测试的时候,typeorm是正常的,但是用farrow启动就会报错,我验证了emitDecoratorMetadata是正常的,然后自己写了reflect-metadata的代码也是正常的,但是typeorm的Entity就不正常了,我粗略看了一下源码也没找到原因,应该是tsconfig的原因,但是farrow也没有默认的tsconfig,我也指定了我自己的tsconfig,想请教一下还有什么情况造成了这个错误。

[IDEA] `farrow instrospect` instrospect the api since it has already known args type and response type

http.match({
  url: '/product/<id:number>?<a:number>&<b:string>&<c:boolean>',
  method: 'POST',
  body: {
    a: Number,
    b: String,
    c: Boolean,
  },
  headers: {
    a: Number,
    b: String,
    c: Boolean,
  },
  cookies: {
    a: Number,
    b: String,
    c: Boolean,
  },
}).use(async (req, next) => {
  return Response.json({ name: 'xialvjun', age: 29 });
})

then use typescript compiler api, farrow instrospect generate json file:

{
  apis: [{
    url: '/product/<id:number>?<a:number>&<b:string>&<c:boolean>',
    method: 'POST',
    body: {
      a: 'number',
      b: 'string',
      c: 'boolean',
    },
    headers: {
      a: 'number',
      b: 'string',
      c: 'boolean',
    },
    cookies: {
      a: 'number',
      b: 'string',
      c: 'boolean',
    },
    response: {
      name: 'string',
      age: 'number'
    }
  }],
}

then farrow generate --plugin=fetch generate js client code:

export const productById = (id: number, query: {a:number,b:string,c:boolean}, xxxx): Promise<{name:string,age:number}> => {xxxx}

I know, this is a huge workload.

Eg the match schema body: {a:Number,b:String,c:Boolean} with constructor is naive. yup is much better which can also give you the validated request type.

I just came up with this idea. I don't really need it since I use graphql.

So I'm not going to contribute on this, I'm trying to translate apollo-koa-server to apollo-farrow-server. I know there is 'farrow-graphql', but 'apollo' and 'graphql-code-generator' works grate.

Feature(farrow): Useful modules for developing farrow app

We shall add farrow contains some useful modules for developing farrow app

  • a bundler for server-side development
  • a bundler for client-side development
  • a bundler for React Server Component

a bundler for server-side development

based on esbuild

  • farrow dev: auto re-run on file changed
  • farrow build
  • farrow start
  • farrow.config.js support

documentation

Feature(http): a question about http.match

type

feature discussion

description

http
  .match({
    pathname: '/product',
    query: {
      productId: Number,
    },
  }).use((request) => {
    // the type of request is detemined by the parameter of http.match
  })

As shown in the code above, when I use http.match, the type of parameter request is the same as the type of the parameter passing to match. However, when using http.use directly, the type of parameter request is RequestInfo.

Using http.use directly means we can detemine the type of varialbe request is just RequestInfo, no more and no less. What I am thinking about is It doesn't mean we lose other fields when we make the type of some fileds more precies. For example, when I know the pathname is /product, I should still known the type of request.method is string.

suggestion

  • Perhaps the type of request should be a merge of RequestInfo and the more precise detail from http.match.
    type RequestAfterMatch = MergeType<RequestInfo, DetailFromHttpMatch>

Code snippets in the farrow-http document cannot pass type checking

Hi, I am new to farrow.

I runned code snippets of two hooks, useBasenames and usePrefix , as provided in the farrow-http doc, and found out it just cannot pass the type checking.

Take useBasenames for example. The doc says

const http = Http({
  basename: ['/base0'],
})
http.route('/base1', () => {
  // basenames will be ['/base0', '/base1'] if user accessed /base0/base1
  let basenames = useBasenames()
})

My version, which passes the type checking:

import { Http, Response, useBasenames } from "farrow-http";

const http = Http({
  basenames: ['/base0'],
})

http.route('/base1').use((res)=>{
    let basenames = useBasenames();
    return Response.text(basenames.value.toString());
})

(I also add imports, in case I just import from wrong lib)

The type checker suggests that there are following issues:

  1. basenames is mistakenly written as basename;
  2. the usage of route is out of date, now its function signature is (name: string) => Pipeline<RequestInfo, MaybeAsyncResponse>;;
  3. the use method should return a response, but not undefined.

Maybe the doc is a little bit out of date, or I use the snippets in an incorrect way or imcompatible environments? Many thanks!

[Advice] allow the not specific type info

now:

http.get('/ping').use((req) => {
  // req.body; -- ts complains about "Property 'body' does not exist on type '{ readonly pathname: string; readonly method: string; }'.ts(2339)"
  return Response.text('pong');
});

But I don't want to use farrow's match, I prefer to use zod validator.

Optimize Request: farrow-api-client codegen

For now, the generated code is like this:

import { apiPipeline } from 'farrow-api-client'

...  // type declaration

export const url = '/api'

export const api = {
  /**
   * @remarks get note content
   */
  getNote: (input: GetNoteInput) =>
    apiPipeline.invoke(url, { path: ['getNote'], input }) as Promise<
      GetNoteSuccess | NoteNotExist | NoteIsBroken | SystemError
    >,

  ... // anthor apis
}

in this segment, the url is constant but need pass to api.invoke everytime. IMO, I prefer:

import { createApiPipeline } from 'farrow-api-client'

...  // type declaration

export const url = '/api'
export const apiPipeline = createApiPipeline(url)

export const api = {
  /**
   * @remarks get note content
   */
  getNote: (input: GetNoteInput) =>
    apiPipeline.invoke({ path: ['getNote'], input }) as Promise<
      GetNoteSuccess | NoteNotExist | NoteIsBroken | SystemError
    >,

  ... // anthor apis
}

reason:

  • generated code splited to file by services
  • services defined in farrow.config.js and url is independent in each service
  • one url -> one service -> one file generated -> one api created by createApiPipeline

Question(Pipeline): Should run `onLast` with same context with other middlewares?

const createCurrentCounter = (hooks: Hooks, onLast?: (input: I) => O) => {
    return createCounter<I, O>((index, input, next) => {
      if (index >= middlewares.length) {
        if (onLast) return onLast(input)
        throw new Error(`Expect returning a value, but all middlewares just calling next()`)
      }

      const middleware = middlewares[index]
      const result = runHooks(() => middleware(input, next), hooks)

      return result
    })
  }

All middlewares run with runHooks but the onLast is not, is it a feature or could improve?

Feature request: merge query into one request like graphql

As the title.

expected

// server
...

export const entries = {
  addTodo,
  removeTodo,
}

export const service = ApiService({
  entries,
})

export const services = Router()

services.route('/api/todo').use(TodoService)

let http = Http()

http.use(services)

http.listen(3000, () => {
  console.log('server started at http://localhost:3002')
})
// client
import { api as TodoApi } from '../api/todo'

// `ApiMerge` need to implement
const addAndRemove = ApiMerge(TodoApi.addTodo, TodoApi.removeTodo)

const addInput = { ... }
const removeInput = { ... }

// only one request has been send
const [addResult, removeResult]= await addAndRemove(addInput, removeInput)

usage: how to run farrow with `esno` ?

  1. Can't find the entrance to run farrow separately, can't it run independently without farrow cli? (It seems that there is only one more generation step)
  2. The default interface generated by farrow cli will automatically send a request. Is there a configuration to turn off this? cause it looks weird.
  3. how to get a esm verion of farrow-api-client, so i can use it quickly

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.