GithubHelp home page GithubHelp logo

rapidjs / rapid.js Goto Github PK

View Code? Open in Web Editor NEW
712.0 14.0 45.0 4.19 MB

An ORM-like Interface and a Router For Your API Requests

Home Page: https://rapidjs.drewjbartlett.com

JavaScript 100.00%
js api-wrapper api ajax interface fluent rapid laravel orm model

rapid.js's Introduction

npm npm npm

An ORM-like Interface and a Router For Your API Requests
Create simple, reusable, and cleaner wrappers, define custom routes, and more for your API requests.

Read the official docs at https://rapidjs.io.

Installation

Pick your poison:

yarn add rapid.js
npm i -S rapid.js
npm install --save rapid.js

Overview

Define Simple Models

const post = new Rapid({ modelName: 'Post' });

post.find(1).then((response) => {
    // GET => /api/post/1
});

post.collection.findBy('category', 'featured').then((response) => {
    // GET => /api/posts/category/featured
});

post.withParams({ limit: 20, order: 'desc' }).all().then((response) => {
    // GET => /api/posts?limit=20&order=desc
});

post.update(25, { title: 'Rapid JS Is Awesome!' })
    // POST => /api/posts/25/update

post.destroy(9)
    // POST => /api/posts/9/destroy

post.restore(9)
    // POST => /api/posts/9/restore    

Read more about Rapid Basics.

Easily Customize Your API Requests

const post = new Rapid({
    modelName: 'Post',
    suffixes: {
        destroy: '',
        update: 'save'
    },
    methods: {
        destroy: 'delete'
    },
    trailingSlash: true
 });

post.update(25, { title: 'Rapid JS Is Awesome!' })
    // POST => /api/posts/25/save/

post.destroy(9)
    // DELETE => /api/posts/9/

Read more about Customizing Your Requests.

Create Reusable Base Models

class Base extends Rapid {
    boot () {
        this.baseURL = 'https://myapp.com/api';
        this.config.globalParameters = { key: 'MY_API_KEY' }
    }
}

const photo = new Base({ modelName: 'Photo' });
const gallery = new Base({ modelName: 'Gallery' });
const tag = new Base({ modelName: 'Tag' });

photo.find(1)
    // GET => https://myapp.com/api/photo/1?key=MY_API_KEY

tag.collection.findBy('color', 'red')
    // GET => https://myapp.com/api/tags/color/red?key=MY_API_KEY

gallery.id(23).get('tags', 'nature')
    // GET => https://myapp.com/api/gallery/23/tag/nature?key=MY_API_KEY

Read more about Base Models.

Write API Wrappers For Your Endpoints

class GalleryWrapper extends Rapid {
    boot () {
        this.baseURL = 'https://myapp.com/gallery/api';
        this.modelName = 'Gallery';
    }

    tagSearch (query) {
        return this.url('tagsearch').withParam('query', query);
    }

    json () {
        return this.url('json');
    }
}

const gallery = new GalleryWrapper({
    globalParameters: { key: 'MY_API_KEY' }
});

gallery.tagSearch('nature').json().get().then(...);
    // GET https://myapp.com/gallery/api/tagsearch/json?query=nature&key=MY_API_KEY
    // GET https://myapp.com/gallery/api/tagsearch/json?query=nature&key=MY_API_KEY

Read more about Making a Wrapper.

Define Custom Routes

const customRoutes = [
    {
        name: 'web_get_user_preferences',
        type: 'get',
        url: '/user/preferences',
    },

    {
        name: 'web_save_user_preferences',
        type: 'post',
        url: '/user/{id}/save/preferences'
    }
];

const router = new Rapid({ customRoutes, baseURL: '/api' });

router.route('web_get_user_preferences').then((response) => {}); 
// GET => /api/user/preferences

router.route('web_save_user_preferences', { id: 12 }, /* { request data } */).then((response) => {}); 
// POST => /api/user/12/save/preferences

Using Your Own HTTP Service

import http from 'some-http-service';

const customRoutes = [
    {
        name: 'web_login',
        url: '/login'
    },

    {
        name: 'api_save_user_preferences',,
        url: '/user/{id}/save/preferences'
    }
];

const rapid = new Rapid({ customRoutes, baseURL: '' });

rapid.generate('web_login')
// returns '/login'

// use your own service
http.post(rapid.generate('api_save_user_preferences', { id: 1 }), { data }).then()...

Read more about Custom Routes.

Read the official docs at https://rapidjs.io.

rapid.js's People

Contributors

brainmaestro avatar drewjbartlett avatar mgred avatar raybenefield avatar ricklancee avatar tbroadley 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  avatar  avatar

rapid.js's Issues

Version 2

Making a place to document the changes on V2

  • Rewrite entirely in TypeScript
  • Properly declare and import type definitions #41
  • Fix all tests #46
  • api renamed to http
  • swap qs for qs-stringify since we only use that method https://www.npmjs.com/package/qs-stringify
  • Allow for other promise-based http services to be used in place of axios with injection
  • Rewrite version 2 docs to reflect updates
  • Rewrite version 2 docs in nuxt (and maybe markdown)
  • Extract debugger to allow easier testing and optionally include based off ENV
  • Extract custom routes into package
  • Add plugin system to allow syntax like rapid.use(customRouter)
  • Fix nasty inheritance chain

Properly declare and import type definitions

Run tsc -p .

tsconfig.json(49,5): error TS5023: Unknown compiler option 'esModuleInterop'.
src/auth.ts(36,33): error TS2339: Property 'auth' does not exist on type 'Config'.
src/auth.ts(36,65): error TS2339: Property 'auth' does not exist on type 'Config'.
src/auth.ts(41,33): error TS2339: Property 'auth' does not exist on type 'Config'.
src/auth.ts(41,66): error TS2339: Property 'auth' does not exist on type 'Config'.
src/auth.ts(46,33): error TS2339: Property 'auth' does not exist on type 'Config'.
src/auth.ts(46,64): error TS2339: Property 'auth' does not exist on type 'Config'.
src/auth.ts(51,33): error TS2339: Property 'auth' does not exist on type 'Config'.
src/auth.ts(51,68): error TS2339: Property 'auth' does not exist on type 'Config'.
src/auth.ts(55,24): error TS2339: Property 'auth' does not exist on type 'Config'.
src/core/core.ts(77,60): error TS2345: Argument of type 'string' is not assignable to parameter of type 'Route'.
src/core/core.ts(133,17): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
src/core/custom-route.ts(4,10): error TS2339: Property 'route' does not exist on type 'CustomRoute'.
src/core/custom-route.ts(11,10): error TS2339: Property 'config' does not exist on type 'CustomRoute'.
src/core/custom-route.ts(25,51): error TS2339: Property 'config' does not exist on type 'CustomRoute'.
src/core/custom-route.ts(28,46): error TS2339: Property 'config' does not exist on type 'CustomRoute'.
src/core/custom-route.ts(70,17): error TS2339: Property 'route' does not exist on type 'CustomRoute'.
src/core/custom-route.ts(79,17): error TS2339: Property 'route' does not exist on type 'CustomRoute'.
src/core/custom-route.ts(88,17): error TS2339: Property 'route' does not exist on type 'CustomRoute'.
src/core/request.ts(26,49): error TS2339: Property 'globalParameters' does not exist on type 'Config'.
src/core/request.ts(30,15): error TS2339: Property 'params' does not exist on type 'object'.
src/core/request.ts(30,57): error TS2339: Property 'globalParameters' does not exist on type 'Config'.
src/core/request.ts(45,5): error TS2322: Type 'string' is not assignable to type 'RequestType'.
src/core/request.ts(79,22): error TS2339: Property 'allowedRequestTypes' does not exist on type 'Config'.
src/core/request.ts(81,80): error TS2339: Property 'allowedRequestTypes' does not exist on type 'Config'.
src/core/request.ts(241,24): error TS2339: Property 'beforeRequest' does not exist on type 'Config'.
src/core/request.ts(251,17): error TS2339: Property 'afterRequest' does not exist on type 'Config'.
src/core/request.ts(261,17): error TS2339: Property 'onError' does not exist on type 'Config'.
src/core/url.ts(4,8): error TS6133: 'store' is declared but its value is never read.
src/core/url.ts(4,19): error TS2307: Cannot find module '../store/index'.
src/core/url.ts(28,21): error TS2339: Property 'extension' does not exist on type 'Config'.
src/core/url.ts(29,30): error TS2339: Property 'extension' does not exist on type 'Config'.
src/debug/debugger.ts(5,10): error TS2339: Property 'caller' does not exist on type 'default'.
src/debug/debugger.ts(6,10): error TS2339: Property 'data' does not exist on type 'default'.
src/debug/debugger.ts(7,10): error TS2339: Property 'logEnabled' does not exist on type 'default'.
src/debug/debugger.ts(11,25): error TS2339: Property 'caller' does not exist on type 'default'.
src/debug/debugger.ts(14,5): error TS2556: Expected 2-4 arguments, but got a minimum of 0.
src/debug/debugger.ts(16,14): error TS2339: Property 'logEnabled' does not exist on type 'default'.
src/debug/debugger.ts(17,12): error TS2339: Property 'caller' does not exist on type 'default'.
src/debug/debugger.ts(17,40): error TS2339: Property 'caller' does not exist on type 'default'.
src/debug/debugger.ts(18,12): error TS2339: Property 'caller' does not exist on type 'default'.
src/debug/debugger.ts(21,10): error TS2339: Property 'caller' does not exist on type 'default'.
src/debug/debugger.ts(30,22): error TS2339: Property 'caller' does not exist on type 'default'.
src/debug/debugger.ts(30,47): error TS2339: Property 'caller' does not exist on type 'default'.
src/debug/debugger.ts(32,32): error TS2339: Property 'params' does not exist on type '{}'.
src/debug/debugger.ts(35,22): error TS2339: Property 'caller' does not exist on type 'default'.
src/debug/debugger.ts(35,47): error TS2339: Property 'caller' does not exist on type 'default'.
src/debug/debugger.ts(38,20): error TS2339: Property 'caller' does not exist on type 'default'.
src/debug/debugger.ts(40,10): error TS2339: Property 'data' does not exist on type 'default'.
src/debug/debugger.ts(46,10): error TS2339: Property 'data' does not exist on type 'default'.
src/rapid.ts(4,1): error TS2304: Cannot find name 'module'.
src/rapid.ts(5,1): error TS2304: Cannot find name 'module'.
src/rapid.ts(6,1): error TS2304: Cannot find name 'module'.

Add typescript definitions

For people that prefer to work in typescript, would you be interested in adding type definitions? I can work on the PR if you are.

Version 2 Checklist

Version 2 Checklist

Documentation
  • Rewrite version 2 docs to reflect updates
  • Rewrite version 2 docs in nuxt (and maybe markdown)
  • Add guide for writing tests
Fixes
  • allow data with DELETE
  • Fix polluted params issue when where params send twice
Enhancements
  • api renamed to http
  • rename apiConfig to httpConfig
  • swap qs for qs-stringify since we only use that method https://www.npmjs.com/package/qs-stringify
  • Allow for other promise-based http services to be used in place of axios with injection
  • Fix nasty inheritance chain
  • Add .default helper to go with model / collection
  • Remove spread from request methods (it's not really useful)
  • Allow data to be passed into request like photo.get('/tags', { order: orders.ASC })
  • Add TypeScript Support while maintaining .js files
  • Properly declare and import type definitions #41
  • Rewrite Auth to be a mixin and extract to package -- rewrite tests for it
  • Use deepmerge instead of lodash
  • Rename withData to withConfig
  • Remove Custom Routes
  • Remove interceptors
  • Remove qs-stringify with old debugger
  • Remove axios entirely
  • Remove httpConfig from config
  • Remove debug from config
  • Add mixins array to allow for creating new methods (auth / base)
Build
  • Add build tool to minify or gzip files on dist
  • Remove prepublish hook and replace with: Use prepare for build steps and prepublishOnly for upload-only.
Tests
  • Extract debugger to allow easier testing
  • Write new debugging library (mockid)
  • Rewrite tests for CRUD
  • Rewrite tests for custom-route
  • Rewrite tests for extensions
  • Rewrite tests for id
  • Rewrite tests for request
  • Rewrite tests for request-hooks
  • Rewrite tests for routes
  • Rewrite tests for with
  • Write tests for model, collection, default

I can add a contributing guide for this. But for now:

  1. Please run npm run unit:watch while working on new features and fixes. Do you best to make small changes while always keeping the tests green.
  2. Only submit small pull requests that are specific to the task. (Horizontal refactoring). If you see something else unrelated that needs fixing, make a ticket or write down a note to address it later

For now we can use issues or projects. @mgred I have not used projects for this but we can look into it!

Start Using Releases on Github

Problem

  • There are currently no releases on github or tags on this repository.
  • There does seem to be versioning within the package.json.

Reasoning

  • This allows for snapshots and marks a time within commits that a certain code was a specific version.
  • This allows for more accurate issues, you can more easily compare code against a specific version.

Solution

Thoughts

  • You may be able to tag older commits, but I think you can only create releases on github for the latest commit on master.

Return data instead of response

Hi and thank you for rapid.js, it's awesome!

When a request is made using rapid, the entire response gets returned. While that may be correct in general I would like to have a way to return only the data.

Because usually the final methods that use my Api doesn't know anything, and should not, about the response. It only expect the data and if there is any error retrieving it, it is the Api Class the one that deals with it.

// current approach
const response = await ApiR.withParams(query).all()
data = response.data

// a not very good solution
const { data } = await ApiR.withParams(query).all()

I'm not sure about the best approach to solve it, perhaps a config or a new method, but would like to hear your thoughts.

Incorrect types for setters in Core

The setters of the Core class are wrongly typed in the declaration file index.d.ts

declare class Core {
    debug: void;
    baseURL: void;
    modelName: void;
    routeDelimiter: void;
    caseSensitive: void;
}

Therefore the typescript compiler complains at the following code:

import { Rapid } from 'rapid.js';

class Resource extends Rapid {
        boot() {
                this.modelName = 'my-resource';
        }
}

with the following error:

error TS2322: Type '"my-resource"' is not assignable to type 'void'

According to the defaults.js they simply need to have this types defined:

declare class Core {
    debug: boolean;
    baseURL: string;
    modelName: string;
    routeDelimiter: string;
    caseSensitive: boolean;
}

Expose axios interceptor api

There is a problem with the current behaviour of the interceptor as explained by @M3psipax in detail here.
Basically:

a reject handler cannot be added

We should use axios InterceptorManager to fully expose axios interceptor capabilities.

add ability for children

Say I have a User model and that user has Notifications. It'd be nice to either say this:

class User extends Rapid {
    boot () {
        this.notifications = new Rapid({ childOf: this });
    }
}

Or it'd be nice to:

let User = new Rapid({
    modelName: 'user',
    children: [{ modelName: 'notifications' }, { modelName: 'meta' }]
})

this would result in being able to do:

User.notifications.post('mark-as-read'); // => /api/user/notifications/mark-as-read

Starting with a Capital on instances which aren't function constructors is against convention

I might be nitpicking here but since the classes return instances (objects) and not function constructors they should (per convention) not start with a Capital in the readme.

var Post = new Rapid({ modelName: 'Post' });

Post.find(1).then((response) => {
    // GET => /api/post/1
});

Should be:

var post = new Rapid({ modelName: 'Post' });

post.find(1).then((response) => {
    // GET => /api/post/1
});

By convention, functions that are intended to be used with new should be given names with initial capital letters, and names with initial capital letters should be used only with constructor functions that take the new prefix. This convention gives us a visual cue that can help spot expensive mistakes that the language itself is keen to overlook.
http://archive.oreilly.com/pub/a/javascript/excerpts/javascript-good-parts/bad-parts.html

POST polluted with params from previous GET

Hi, I am using rapid.js v1.0.11 and seems there is a bug.

const query = {...}
Api.withParams(query).all()
  // sending Query string parameters - OK

const data = {...}
Api.withParams(data).post()
  // sending Request Payload - OK
  // sending Query string parameters from previous request - NOT OK

Or perhaps I am missing something...

[Question]: How do imports work?

I see that there's no top level index.js or even on in the src folder that reexports Rapid and Auth. The docs suggest import Rapid from 'rapid.js'; which seems like it clearly won't work.
Am I missing something here?

Config option to use file extensions

Is there a way, or you planning to implement a config option where i can set a file extension prefix?

I wanted to try this library a project of mine, but the API (Redmine) which i'm using is not following the REST standards at all.
In my case, an url looks like this: //example.com/issues/3.json or //example.com/users.json so i always have to specify the file extension, but in the docs i have not found option to to do this.

response on catch?

How to get a response from the server in "catch"?

    model
    .withParams(credentials)
    .post()
    .then((success) => {
      /* Set data. */
     commit('setUser', success.data.data.user);
    })
    .catch((error) => {
      if (error.data.data.message) {
        commit('setErrors', [error.data.data.message]);
      }
    });

Instead, the error object:

Error: Request failed with status code 422
    at createError (D:\Projects\Desionlab\Alex south\fastPanel\terminal\Source\node_modules\axios\lib\core\createError.js:16)
    at settle (D:\Projects\Desionlab\Alex south\fastPanel\terminal\Source\node_modules\axios\lib\core\settle.js:18)
    at XMLHttpRequest.handleLoad (D:\Projects\Desionlab\Alex south\fastPanel\terminal\Source\node_modules\axios\lib\adapters\xhr.js:77)

Thanks in advance.

save, update not work.

export default new Base({
  routes: {
    model: 'data/account/user',
    collection: 'data/account/user'
  },
  suffixes: {
    create: '',
    update: '',
    destroy: ''
  },
  methods: {
    update: 'put',
    destroy: 'delete'
  }
});

Not work

await Phone.update(phone.id, phone);
await Phone.save(phone.id, phone);

Work

await Phone
.id(phone.id)
.withParams(phone)
.put();

CLI tool or generator

Hi. Just stumbled upon this library and it looks really interesting.

One feature I would like to see is a CLI tool or a yeoman generator for building custom config files (similar to the config builder tool on the website) and custom routes which then could be instantly added to the project. Just a suggestion the would make the whole proces of building a routing even faster.

Thanks for your work so far.

Cannot find module './core/rapid'

Error thrown on linux when booting a file that extends RapidJS.

Error: Cannot find module './core/rapid'
    at Function.Module._resolveFilename (module.js:536:15)
    at Function.Module._load (module.js:466:25)
    at Module.require (module.js:579:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/var/lib/jenkins/workspace/vernight_highstreet_develop-Z4EJGYUMCGUJXLSZ5RREIJWO3ZYMIKFLYOSGEMPIHGYF6PMVVKIQ/node_modules/rapid.js/dist/rapid.js:3:14)

My dist folder looks like this:
image

Looks like a problem with case insensitivity

Add a gitter chatroom

Just stumbled onto this library. It is extremely interesting and fresh but its a shame that there doesn't seems to be a community around it. Adding a simple Gitter chatroom will a step in this direction.

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.