├── demo
├── .env
├── mix-manifest.json
├── rapid
│ ├── rapid.js
│ ├── Core
│ │ ├── Rapid.js
│ │ ├── Defaults.js
│ │ ├── Routes.js
│ │ ├── Url.js
│ │ ├── Crud.js
│ │ ├── Core.js
│ │ └── Request.js
│ ├── Debug
│ │ ├── Logger.js
│ │ └── Debugger.js
│ └── auth.js
├── index.html
├── src
│ └── app.js
├── package.json
├── webpack.mix.js
└── webpack.config.js
├── .npmignore
├── .gitignore
├── .travis.yml
├── src
├── rapid.js
├── common
│ └── url.js
├── core
│ ├── rapid.js
│ ├── defaults.js
│ ├── routes.js
│ ├── custom-route.js
│ ├── url.js
│ ├── crud.js
│ ├── core.js
│ └── request.js
├── debug
│ ├── logger.js
│ └── debugger.js
└── auth.js
├── dist
├── rapid.js
├── common
│ └── url.js
├── core
│ ├── defaults.js
│ ├── rapid.js
│ ├── custom-route.js
│ ├── routes.js
│ ├── url.js
│ ├── crud.js
│ ├── core.js
│ └── request.js
├── debug
│ ├── logger.js
│ └── debugger.js
└── auth.js
├── test
├── helpers.js
├── routes.test.js
├── extension.test.js
├── id.test.js
├── with.test.js
├── crud.test.js
├── base.test.js
├── auth.test.js
├── custom-route.test.js
└── request.test.js
├── .eslintrc.js
├── package.json
└── README.md
/demo/.env:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /demo
2 | demo
3 |
--------------------------------------------------------------------------------
/demo/mix-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "/dist/app.js": "/dist/app.js"
3 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 | /node_modules
3 | .nyc_output
4 | npm-debug.log
5 | demo/node_modules
6 | /demo
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - node
4 | cache:
5 | directories:
6 | - "node_modules"
7 | branches:
8 | only:
9 | - master
--------------------------------------------------------------------------------
/src/rapid.js:
--------------------------------------------------------------------------------
1 | import Rapid from './core/rapid';
2 | import Auth from './auth';
3 |
4 | module.exports = Rapid;
5 | module.exports.Rapid = Rapid;
6 | module.exports.Auth = Auth;
7 |
--------------------------------------------------------------------------------
/demo/rapid/rapid.js:
--------------------------------------------------------------------------------
1 | import Rapid from './core/rapid';
2 | import Auth from './auth';
3 |
4 | module.exports = Rapid;
5 | module.exports.Rapid = Rapid;
6 | module.exports.Auth = Auth;
7 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Rapid tests
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/dist/rapid.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _rapid = require('./core/rapid');
4 |
5 | var _rapid2 = _interopRequireDefault(_rapid);
6 |
7 | var _auth = require('./auth');
8 |
9 | var _auth2 = _interopRequireDefault(_auth);
10 |
11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12 |
13 | module.exports = _rapid2.default;
14 | module.exports.Rapid = _rapid2.default;
15 | module.exports.Auth = _auth2.default;
--------------------------------------------------------------------------------
/src/common/url.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This just makes sure there are no double slashes and no trailing
3 | * slash unless the config for it is set.
4 | *
5 | * @param {String} url a url to sanitize
6 | * @param {Boolean} keepTrailingSlash a url to sanitize
7 | * @return {String}
8 | */
9 | export function sanitizeUrl (url = '', keepTrailingSlash = false) {
10 | url = url.replace(/([^:]\/)\/+/g, '$1').replace(/\?$/, '').replace(/^(\/\/)/, '/');
11 |
12 | if (!keepTrailingSlash) {
13 | url = url.replace(/\/$/, '');
14 | }
15 |
16 | return url;
17 | }
18 |
19 | export default {
20 | sanitizeUrl,
21 | };
22 |
--------------------------------------------------------------------------------
/src/core/rapid.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Rapid.js v0.0.14
3 | * (c) 2017 Drew J Bartlett (https://drewjbartlett.com)
4 | * Released under the MIT License.
5 | */
6 |
7 | /**
8 | * The inheritance of the classes
9 | *
10 | * Core ---> Url
11 | * Url ---> Routes
12 | * Routes ---> Request
13 | * Request ---> Relationships
14 | * Relationships ---> Crud
15 | * Crud ---> Rapid
16 | *
17 | */
18 |
19 | import Crud from './crud';
20 |
21 | class Rapid extends Crud {
22 |
23 | constructor (config) {
24 | super(config);
25 | }
26 |
27 | }
28 |
29 | export default Rapid;
30 |
--------------------------------------------------------------------------------
/demo/src/app.js:
--------------------------------------------------------------------------------
1 | // import Rapid from './../rapid/rapid';
2 | import { Rapid, Auth } from './../rapid/rapid';
3 |
4 | window.Rapid = Rapid;
5 |
6 | window.test = new Rapid({ modelName: 'test', debug: true, extension: 'xml' });
7 | window.auth = new Auth({ modelName: 'user', debug: true });
8 |
9 | const routes = [
10 | {
11 | type: 'get',
12 | name: 'simple_test',
13 | url: '/hi/how/are/you',
14 | },
15 |
16 | {
17 | type: 'post',
18 | name: 'simple_test_two',
19 | url: '/user/{id}/{username}/profile',
20 | },
21 | ];
22 |
23 | window.newRapid = new Rapid({ customRoutes: routes });
--------------------------------------------------------------------------------
/demo/rapid/Core/Rapid.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Rapid.js v0.0.14
3 | * (c) 2017 Drew J Bartlett (https://drewjbartlett.com)
4 | * Released under the MIT License.
5 | */
6 |
7 | /**
8 | * The inheritance of the classes
9 | *
10 | * Core ---> Url
11 | * Url ---> Routes
12 | * Routes ---> Request
13 | * Request ---> Relationships
14 | * Relationships ---> Crud
15 | * Crud ---> Rapid
16 | *
17 | */
18 |
19 | import Crud from './crud';
20 |
21 | class Rapid extends Crud {
22 |
23 | constructor (config) {
24 | super(config);
25 | }
26 |
27 | }
28 |
29 | export default Rapid;
30 |
--------------------------------------------------------------------------------
/demo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "demo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "cross-env NODE_ENV=development webpack --progress --hide-modules",
8 | "watch": "cross-env NODE_ENV=development webpack --watch --progress --hide-modules",
9 | "hot": "cross-env NODE_ENV=development webpack-dev-server --inline --hot",
10 | "production": "cross-env NODE_ENV=production webpack --progress --hide-modules"
11 | },
12 | "keywords": [],
13 | "author": "",
14 | "license": "ISC",
15 | "devDependencies": {
16 | "babel-cli": "^6.24.0",
17 | "laravel-mix": "^0.10.0"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/test/helpers.js:
--------------------------------------------------------------------------------
1 | import Rapid from './../src/rapid';
2 | import Auth from './../src/auth';
3 |
4 | /**
5 | * Create an auth model for testing
6 | * @param {Object} config
7 | */
8 | export function createAuthModel (config) {
9 | const auth = new Auth(Object.assign(config, { debug: true }));
10 | auth.debugger.logEnabled = false;
11 |
12 | return auth;
13 | }
14 |
15 | /**
16 | * Create a model for testing
17 | * @param {Object} config
18 | */
19 | export function createModel(config) {
20 | const auth = new Rapid(Object.assign(config, { debug: true }));
21 | auth.debugger.logEnabled = false;
22 |
23 | return auth;
24 | }
25 |
26 | export default {
27 | createAuthModel,
28 | createModel,
29 | };
30 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | 'parser': 'babel-eslint',
3 | 'extends': 'airbnb-base',
4 | 'rules': {
5 | 'indent': ['error', 4],
6 | 'padded-blocks': 0,
7 | 'class-methods-use-this': ['error', { 'exceptMethods': ['boot'] }],
8 | 'no-useless-constructor': 0,
9 | 'no-param-reassign': 0,
10 | 'no-console': 0,
11 | 'no-return-assign': 0,
12 | 'prefer-rest-params': 0,
13 | 'consistent-return': 0,
14 | 'space-before-function-paren': 0
15 | },
16 | 'globals': {
17 | 'it': true,
18 | 'describe': true,
19 | 'beforeAll': true,
20 | 'beforeEach': true,
21 | 'afterEach': true,
22 | 'afterAll': true,
23 | 'before': true,
24 | 'after': true,
25 | 'expect': true,
26 | 'jest': true
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/src/debug/logger.js:
--------------------------------------------------------------------------------
1 | class Logger {
2 | constructor (prefix) {
3 | this.prefix = prefix;
4 | this.firedDebugNotice = false;
5 | this.fireDebugNotice();
6 | }
7 |
8 | fireDebugNotice () {
9 | if (!this.firedDebugNotice) {
10 | // this.debug('You are running Rapid in debug mode. All requests will be mimicked.');
11 |
12 | this.firedDebugNotice = true;
13 | }
14 | }
15 |
16 | debug (message) {
17 | console.info(`[${this.prefix}]: ${message}`);
18 | }
19 |
20 | log (message) {
21 | console.log(`[${this.prefix}]:`, message);
22 | }
23 |
24 | warn (message) {
25 | console.warn(`[${this.prefix} warn]:`, message);
26 | }
27 |
28 | }
29 |
30 | export default new Logger('rapid js');
31 |
--------------------------------------------------------------------------------
/demo/rapid/Debug/Logger.js:
--------------------------------------------------------------------------------
1 | class Logger {
2 | constructor (prefix) {
3 | this.prefix = prefix;
4 | this.firedDebugNotice = false;
5 | this.fireDebugNotice();
6 | }
7 |
8 | fireDebugNotice () {
9 | if (!this.firedDebugNotice) {
10 | // this.debug('You are running Rapid in debug mode. All requests will be mimicked.');
11 |
12 | this.firedDebugNotice = true;
13 | }
14 | }
15 |
16 | debug (message) {
17 | console.info(`[${this.prefix}]: ${message}`);
18 | }
19 |
20 | log (message) {
21 | console.log(`[${this.prefix}]:`, message);
22 | }
23 |
24 | warn (message) {
25 | console.warn(`[${this.prefix} warn]:`, message);
26 | }
27 |
28 | }
29 |
30 | export default new Logger('rapid js');
31 |
--------------------------------------------------------------------------------
/dist/common/url.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.sanitizeUrl = sanitizeUrl;
7 | /**
8 | * This just makes sure there are no double slashes and no trailing
9 | * slash unless the config for it is set.
10 | *
11 | * @param {String} url a url to sanitize
12 | * @param {Boolean} keepTrailingSlash a url to sanitize
13 | * @return {String}
14 | */
15 | function sanitizeUrl() {
16 | var url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
17 | var keepTrailingSlash = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
18 |
19 | url = url.replace(/([^:]\/)\/+/g, '$1').replace(/\?$/, '').replace(/^(\/\/)/, '/');
20 |
21 | if (!keepTrailingSlash) {
22 | url = url.replace(/\/$/, '');
23 | }
24 |
25 | return url;
26 | }
27 |
28 | exports.default = {
29 | sanitizeUrl: sanitizeUrl
30 | };
--------------------------------------------------------------------------------
/test/routes.test.js:
--------------------------------------------------------------------------------
1 | import { createModel } from './helpers';
2 |
3 | describe('The routes are generated properly based off config', () => {
4 | it('that routeDelimiter will work', () => {
5 | const postModel = createModel({
6 | modelName: 'PacificCrestTrail',
7 | routeDelimeter: '_',
8 | });
9 |
10 | postModel.find(1);
11 | expect(postModel.debugger.data.lastUrl).toBe('api/pacific_crest_trail/1');
12 |
13 | postModel.all();
14 | expect(postModel.debugger.data.lastUrl).toBe('api/pacific_crest_trails');
15 | });
16 |
17 | it('that caseSensitive will work', () => {
18 | const postModel = createModel({
19 | modelName: 'PacificCrestTrail',
20 | caseSensitive: true,
21 | });
22 |
23 | postModel.find(1);
24 | expect(postModel.debugger.data.lastUrl).toBe('api/PacificCrestTrail/1');
25 |
26 | postModel.all();
27 | expect(postModel.debugger.data.lastUrl).toBe('api/PacificCrestTrails');
28 | });
29 | });
30 |
31 |
--------------------------------------------------------------------------------
/test/extension.test.js:
--------------------------------------------------------------------------------
1 | import { createModel } from './helpers';
2 |
3 | const doc = createModel({
4 | modelName: 'document',
5 | extension: 'xml',
6 | });
7 |
8 | describe('The extension feature should work', () => {
9 | it('CRUD works with extension', () => {
10 | doc.id(23).find();
11 | expect(doc.debugger.data.lastUrl).toBe('api/document/23.xml');
12 |
13 | doc.id(234).save({});
14 | expect(doc.debugger.data.lastUrl).toBe('api/document/234/update.xml');
15 |
16 | doc.id(456).destroy();
17 | expect(doc.debugger.data.lastUrl).toBe('api/document/456/destroy.xml');
18 | });
19 |
20 | const issue = createModel({
21 | modelName: 'issue',
22 | defaultRoute: 'collection',
23 | extension: 'json',
24 | });
25 |
26 | it('works with extension', () => {
27 | issue.get();
28 | expect(issue.debugger.data.lastUrl).toBe('api/issues.json');
29 |
30 | issue.post();
31 | expect(issue.debugger.data.lastUrl).toBe('api/issues.json');
32 |
33 | issue.id(234).get();
34 | expect(issue.debugger.data.lastUrl).toBe('api/issues/234.json');
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/src/core/defaults.js:
--------------------------------------------------------------------------------
1 | export default {
2 | modelName: '',
3 |
4 | primaryKey: '',
5 |
6 | baseURL: 'api',
7 |
8 | trailingSlash: false,
9 |
10 | extension: '',
11 |
12 | caseSensitive: false,
13 |
14 | routeDelimeter: '-',
15 |
16 | globalParameters: {
17 |
18 | },
19 |
20 | suffixes: {
21 | create: 'create',
22 | update: 'update',
23 | destroy: 'destroy',
24 | },
25 |
26 | methods: {
27 | create: 'post',
28 | update: 'post',
29 | destroy: 'post',
30 | },
31 |
32 | routes: {
33 | model: '',
34 | collection: '',
35 | any: '',
36 | },
37 |
38 | customRoutes: {},
39 |
40 | defaultRoute: 'model',
41 |
42 | debug: false,
43 |
44 | apiConfig: {
45 |
46 | },
47 |
48 | allowedRequestTypes: ['get', 'post', 'put', 'patch', 'head', 'delete'],
49 |
50 | // eslint-disable-next-line no-unused-vars
51 | beforeRequest (type, url) {
52 |
53 | },
54 |
55 | // eslint-disable-next-line no-unused-vars
56 | afterRequest (response) {
57 |
58 | },
59 |
60 | // eslint-disable-next-line no-unused-vars
61 | onError (response) {
62 |
63 | },
64 | };
65 |
--------------------------------------------------------------------------------
/demo/rapid/Core/Defaults.js:
--------------------------------------------------------------------------------
1 | export default {
2 | modelName: '',
3 |
4 | primaryKey: '',
5 |
6 | baseURL: 'api',
7 |
8 | trailingSlash: false,
9 |
10 | extension: '',
11 |
12 | caseSensitive: false,
13 |
14 | routeDelimeter: '-',
15 |
16 | globalParameters: {
17 |
18 | },
19 |
20 | suffixes: {
21 | create: 'create',
22 | update: 'update',
23 | destroy: 'destroy',
24 | },
25 |
26 | methods: {
27 | create: 'post',
28 | update: 'post',
29 | destroy: 'post',
30 | },
31 |
32 | routes: {
33 | model: '',
34 | collection: '',
35 | any: '',
36 | },
37 |
38 | customRoutes: {},
39 |
40 | defaultRoute: 'model',
41 |
42 | debug: false,
43 |
44 | apiConfig: {
45 |
46 | },
47 |
48 | allowedRequestTypes: ['get', 'post', 'put', 'patch', 'head', 'delete'],
49 |
50 | // eslint-disable-next-line no-unused-vars
51 | beforeRequest (type, url) {
52 |
53 | },
54 |
55 | // eslint-disable-next-line no-unused-vars
56 | afterRequest (response) {
57 |
58 | },
59 |
60 | // eslint-disable-next-line no-unused-vars
61 | onError (response) {
62 |
63 | },
64 | };
65 |
--------------------------------------------------------------------------------
/test/id.test.js:
--------------------------------------------------------------------------------
1 | import { createModel } from './helpers';
2 |
3 |
4 | const shark = createModel({
5 | modelName: 'shark',
6 | });
7 |
8 | describe('The id() method works as it should', () => {
9 | it('works with basic CRUD', () => {
10 | shark.id(23).find();
11 | expect(shark.debugger.data.lastUrl).toBe('api/shark/23');
12 |
13 | shark.id(234).save({});
14 | expect(shark.debugger.data.lastUrl).toBe('api/shark/234/update');
15 |
16 | shark.id(456).destroy();
17 | expect(shark.debugger.data.lastUrl).toBe('api/shark/456/destroy');
18 | });
19 |
20 | it('works with other requests', () => {
21 | shark.id(23).get();
22 | expect(shark.debugger.data.lastUrl).toBe('api/shark/23');
23 |
24 | shark.id(789).get('fish', 'are', 'friends', 'not', 'food');
25 | expect(shark.debugger.data.lastUrl).toBe('api/shark/789/fish/are/friends/not/food');
26 |
27 | shark.id(23).post('swim');
28 | expect(shark.debugger.data.lastUrl).toBe('api/shark/23/swim');
29 |
30 | shark.id(234).delete('eat', 'fish');
31 | expect(shark.debugger.data.lastUrl).toBe('api/shark/234/eat/fish');
32 |
33 | shark.id(456).patch();
34 | expect(shark.debugger.data.lastUrl).toBe('api/shark/456');
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/test/with.test.js:
--------------------------------------------------------------------------------
1 | import { createModel } from './helpers';
2 |
3 | const postModel = createModel({
4 | modelName: 'post',
5 | });
6 |
7 | describe('The with methods all work as should', () => {
8 | it('that withParams works', () => {
9 | postModel.collection.withParams({ limit: 20 }).findBy('category', 'featured');
10 |
11 | expect(postModel.debugger.data.lastUrl).toBe('api/posts/category/featured?limit=20');
12 | });
13 |
14 | it('that withParam works', () => {
15 | postModel.withParam('status', 'published').get();
16 |
17 | expect(postModel.debugger.data.lastUrl).toBe('api/post?status=published');
18 |
19 | postModel.collection.withParam('status', 'published').findBy('category', 'featured');
20 |
21 | expect(postModel.debugger.data.lastUrl).toBe('api/posts/category/featured?status=published');
22 | });
23 |
24 | it('that withData works', () => {
25 | postModel.collection.withData({
26 | params: {
27 | limit: 20, published: true, orderBy: 'commentCount', order: 'desc',
28 | },
29 | }).findBy('category', 'featured');
30 |
31 | expect(postModel.debugger.data.lastUrl).toBe('api/posts/category/featured?limit=20&published=true&orderBy=commentCount&order=desc');
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/dist/core/defaults.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.default = {
7 | modelName: '',
8 |
9 | primaryKey: '',
10 |
11 | baseURL: 'api',
12 |
13 | trailingSlash: false,
14 |
15 | extension: '',
16 |
17 | caseSensitive: false,
18 |
19 | routeDelimeter: '-',
20 |
21 | globalParameters: {},
22 |
23 | suffixes: {
24 | create: 'create',
25 | update: 'update',
26 | destroy: 'destroy'
27 | },
28 |
29 | methods: {
30 | create: 'post',
31 | update: 'post',
32 | destroy: 'post'
33 | },
34 |
35 | routes: {
36 | model: '',
37 | collection: '',
38 | any: ''
39 | },
40 |
41 | customRoutes: {},
42 |
43 | defaultRoute: 'model',
44 |
45 | debug: false,
46 |
47 | apiConfig: {},
48 |
49 | allowedRequestTypes: ['get', 'post', 'put', 'patch', 'head', 'delete'],
50 |
51 | // eslint-disable-next-line no-unused-vars
52 | beforeRequest: function beforeRequest(type, url) {},
53 |
54 |
55 | // eslint-disable-next-line no-unused-vars
56 | afterRequest: function afterRequest(response) {},
57 |
58 |
59 | // eslint-disable-next-line no-unused-vars
60 | onError: function onError(response) {}
61 | };
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rapid.js",
3 | "version": "1.0.5",
4 | "description": "",
5 | "main": "dist/rapid.js",
6 | "scripts": {
7 | "test": "npm run unit",
8 | "compile": "babel --presets=es2015 -d dist src",
9 | "copy-dev": "npm run compile && rm -rf ./demo/rapid && cp -R ./dist ./demo/rapid",
10 | "prepublish": "npm run compile",
11 | "lint": "eslint src/**/*.js test/**/*.js",
12 | "unit": "jest --maxWorkers 2",
13 | "unit:watch": "jest test/**/*.test.js --watch"
14 | },
15 | "babel": {
16 | "presets": [
17 | "es2015"
18 | ]
19 | },
20 | "repository": {
21 | "type": "git",
22 | "url": "git+https://github.com/rapidjs/rapid.js.git"
23 | },
24 | "keywords": [],
25 | "author": "",
26 | "license": "ISC",
27 | "bugs": {
28 | "url": "https://github.com/rapidjs/rapid.js/issues"
29 | },
30 | "homepage": "https://github.com/rapidjs/rapid.js#readme",
31 | "devDependencies": {
32 | "babel-cli": "^6.24.0",
33 | "babel-eslint": "^8.0.2",
34 | "babel-preset-es2015": "^6.24.0",
35 | "eslint": "^4.11.0",
36 | "eslint-config-airbnb-base": "^12.1.0",
37 | "eslint-config-airbnb-standard": "^1.6.5",
38 | "eslint-plugin-import": "^2.8.0",
39 | "jest": "^21.2.1"
40 | },
41 | "dependencies": {
42 | "axios": "^0.16.0",
43 | "lodash": "^4.17.4",
44 | "pluralize": "^4.0.0",
45 | "qs": "^6.4.0"
46 | },
47 | "publishConfig": {
48 | "access": "public"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/debug/debugger.js:
--------------------------------------------------------------------------------
1 | import qs from 'qs';
2 |
3 | export default class {
4 | constructor (caller) {
5 | this.caller = caller;
6 | this.data = {};
7 | this.logEnabled = true;
8 | }
9 |
10 | fakeRequest (type, url) {
11 | const params = this.caller.parseRequestData(type);
12 | const lastUrl = this.setLastUrl(type, url, ...params);
13 |
14 | this.setLastRequest(...arguments);
15 |
16 | if (this.logEnabled) {
17 | this.caller.logger.debug(`${this.caller.config.modelName} made a ${type.toUpperCase()} request (${lastUrl})`);
18 | this.caller.logger.log(params);
19 | }
20 |
21 | this.caller.afterRequest({});
22 |
23 | return lastUrl;
24 | }
25 |
26 | setLastUrl (type, url, params = {}) {
27 | let lastUrl = '';
28 |
29 | if (['put', 'post', 'patch'].includes(type)) {
30 | lastUrl = this.caller.sanitizeUrl([this.caller.config.baseURL, url].join('/'));
31 | } else {
32 | const urlParams = params.params;
33 | const stringified = urlParams ? `?${qs.stringify(urlParams)}` : '';
34 |
35 | lastUrl = this.caller.sanitizeUrl([this.caller.config.baseURL, url].join('/')) + stringified;
36 | }
37 |
38 | lastUrl = this.caller.sanitizeUrl(lastUrl);
39 |
40 | this.data.lastUrl = lastUrl;
41 |
42 | return lastUrl;
43 | }
44 |
45 | setLastRequest (type, url, data = {}, options = {}) {
46 | this.data.lastRequest = {
47 | type,
48 | url,
49 | data,
50 | options,
51 | };
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/demo/rapid/Debug/Debugger.js:
--------------------------------------------------------------------------------
1 | import qs from 'qs';
2 |
3 | export default class {
4 | constructor (caller) {
5 | this.caller = caller;
6 | this.data = {};
7 | this.logEnabled = true;
8 | }
9 |
10 | fakeRequest (type, url) {
11 | const params = this.caller.parseRequestData(type);
12 | const lastUrl = this.setLastUrl(type, url, ...params);
13 |
14 | this.setLastRequest(...arguments);
15 |
16 | if (this.logEnabled) {
17 | this.caller.logger.debug(`${this.caller.config.modelName} made a ${type.toUpperCase()} request (${lastUrl})`);
18 | this.caller.logger.log(params);
19 | }
20 |
21 | this.caller.afterRequest({});
22 |
23 | return lastUrl;
24 | }
25 |
26 | setLastUrl (type, url, params = {}) {
27 | let lastUrl = '';
28 |
29 | if (['put', 'post', 'patch'].includes(type)) {
30 | lastUrl = this.caller.sanitizeUrl([this.caller.config.baseURL, url].join('/'));
31 | } else {
32 | const urlParams = params.params;
33 | const stringified = urlParams ? `?${qs.stringify(urlParams)}` : '';
34 |
35 | lastUrl = this.caller.sanitizeUrl([this.caller.config.baseURL, url].join('/')) + stringified;
36 | }
37 |
38 | lastUrl = this.caller.sanitizeUrl(lastUrl);
39 |
40 | this.data.lastUrl = lastUrl;
41 |
42 | return lastUrl;
43 | }
44 |
45 | setLastRequest (type, url, data = {}, options = {}) {
46 | this.data.lastRequest = {
47 | type,
48 | url,
49 | data,
50 | options,
51 | };
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/demo/rapid/auth.js:
--------------------------------------------------------------------------------
1 | import { defaultsDeep } from 'lodash';
2 | import Rapid from './core/rapid';
3 |
4 | const authConfig = {
5 | auth: {
6 | routes: {
7 | login: 'login',
8 | logout: 'logout',
9 | auth: 'auth',
10 | register: 'register',
11 | },
12 |
13 | methods: {
14 | login: 'post',
15 | logout: 'post',
16 | auth: 'get',
17 | register: 'post',
18 | },
19 |
20 | modelPrefix: false,
21 | },
22 | };
23 |
24 | class Auth extends Rapid {
25 |
26 | constructor (config) {
27 | config = defaultsDeep(config, authConfig);
28 | config.modelName = config.modelName ? config.modelName : 'auth';
29 |
30 | super(config);
31 | }
32 |
33 | login (credentials = {}) {
34 | return this[this.modelPrefix].withParams(credentials)
35 | .withOption('auth', credentials)
36 | .buildRequest(this.config.auth.methods.login, this.config.auth.routes.login);
37 | }
38 |
39 | logout () {
40 | return this[this.modelPrefix]
41 | .buildRequest(this.config.auth.methods.logout, this.config.auth.routes.logout);
42 | }
43 |
44 | check () {
45 | return this[this.modelPrefix]
46 | .buildRequest(this.config.auth.methods.auth, this.config.auth.routes.auth);
47 | }
48 |
49 | register (credentials = {}) {
50 | return this[this.modelPrefix].withParams(credentials)
51 | .buildRequest(this.config.auth.methods.register, this.config.auth.routes.register);
52 | }
53 |
54 | get modelPrefix () {
55 | return this.config.auth.modelPrefix ? 'model' : 'any';
56 | }
57 |
58 | }
59 |
60 | export default Auth;
61 |
--------------------------------------------------------------------------------
/src/auth.js:
--------------------------------------------------------------------------------
1 | import defaultsDeep from 'lodash/defaultsDeep';
2 | import Rapid from './core/rapid';
3 |
4 | const authConfig = {
5 | auth: {
6 | routes: {
7 | login: 'login',
8 | logout: 'logout',
9 | auth: 'auth',
10 | register: 'register',
11 | },
12 |
13 | methods: {
14 | login: 'post',
15 | logout: 'post',
16 | auth: 'get',
17 | register: 'post',
18 | },
19 |
20 | modelPrefix: false,
21 | },
22 | };
23 |
24 | class Auth extends Rapid {
25 |
26 | constructor (config) {
27 | config = defaultsDeep(config, authConfig);
28 | config.modelName = config.modelName ? config.modelName : 'auth';
29 |
30 | super(config);
31 | }
32 |
33 | login (credentials = {}) {
34 | return this[this.modelPrefix].withParams(credentials)
35 | .withOption('auth', credentials)
36 | .buildRequest(this.config.auth.methods.login, this.config.auth.routes.login);
37 | }
38 |
39 | logout () {
40 | return this[this.modelPrefix]
41 | .buildRequest(this.config.auth.methods.logout, this.config.auth.routes.logout);
42 | }
43 |
44 | check () {
45 | return this[this.modelPrefix]
46 | .buildRequest(this.config.auth.methods.auth, this.config.auth.routes.auth);
47 | }
48 |
49 | register (credentials = {}) {
50 | return this[this.modelPrefix].withParams(credentials)
51 | .buildRequest(this.config.auth.methods.register, this.config.auth.routes.register);
52 | }
53 |
54 | get modelPrefix () {
55 | return this.config.auth.modelPrefix ? 'model' : 'any';
56 | }
57 |
58 | }
59 |
60 | export default Auth;
61 |
--------------------------------------------------------------------------------
/demo/rapid/Core/Routes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The Rapid Routes
3 | */
4 |
5 | import { kebabCase } from 'lodash';
6 | import pluralize from 'pluralize';
7 | import Url from './url';
8 |
9 | class Routes extends Url {
10 |
11 | constructor (config) {
12 | super(config);
13 | }
14 |
15 | /**
16 | * Set the current route.
17 | * This will set the current route to either model, collection,
18 | * or any to make appropriate requests
19 | * Can also be changed by calling rapid.model.func() or rapid.collection.func()
20 | *
21 | * @param route The route to set
22 | */
23 | setCurrentRoute (route) {
24 | this.currentRoute = route;
25 | }
26 |
27 | /**
28 | * Set the routes for the URL based off model/collection and config
29 | *
30 | * @param route The key of the route to be set
31 | */
32 | setRoute (route) {
33 | let newRoute = '';
34 | const formattedRoute = {
35 | model: this.config.modelName,
36 | collection: pluralize(this.config.modelName),
37 | any: '',
38 | };
39 |
40 | if (this.config.routes[route] !== '') {
41 | newRoute = this.config.routes[route];
42 | } else {
43 | newRoute = kebabCase(formattedRoute[route]).replace(/-/g, this.config.routeDelimeter);
44 |
45 | if (this.config.caseSensitive) {
46 | newRoute = formattedRoute[route];
47 | }
48 | }
49 |
50 | this.routes[route] = newRoute;
51 | }
52 |
53 | /**
54 | * Loop through the routes and set them
55 | */
56 | setRoutes () {
57 | ['model', 'collection'].forEach(route => this.setRoute(route));
58 | }
59 | }
60 |
61 | export default Routes;
62 |
--------------------------------------------------------------------------------
/src/core/routes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The Rapid Routes
3 | */
4 |
5 | import kebabCase from 'lodash/kebabCase';
6 | import pluralize from 'pluralize';
7 | import Url from './url';
8 |
9 | class Routes extends Url {
10 |
11 | constructor (config) {
12 | super(config);
13 | }
14 |
15 | /**
16 | * Set the current route.
17 | * This will set the current route to either model, collection,
18 | * or any to make appropriate requests
19 | * Can also be changed by calling rapid.model.func() or rapid.collection.func()
20 | *
21 | * @param route The route to set
22 | */
23 | setCurrentRoute (route) {
24 | this.currentRoute = route;
25 | }
26 |
27 | /**
28 | * Set the routes for the URL based off model/collection and config
29 | *
30 | * @param route The key of the route to be set
31 | */
32 | setRoute (route) {
33 | let newRoute = '';
34 | const formattedRoute = {
35 | model: this.config.modelName,
36 | collection: pluralize(this.config.modelName),
37 | any: '',
38 | };
39 |
40 | if (this.config.routes[route] !== '') {
41 | newRoute = this.config.routes[route];
42 | } else {
43 | newRoute = kebabCase(formattedRoute[route]).replace(/-/g, this.config.routeDelimeter);
44 |
45 | if (this.config.caseSensitive) {
46 | newRoute = formattedRoute[route];
47 | }
48 | }
49 |
50 | this.routes[route] = newRoute;
51 | }
52 |
53 | /**
54 | * Loop through the routes and set them
55 | */
56 | setRoutes () {
57 | ['model', 'collection'].forEach(route => this.setRoute(route));
58 | }
59 | }
60 |
61 | export default Routes;
62 |
--------------------------------------------------------------------------------
/dist/debug/logger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8 |
9 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
10 |
11 | var Logger = function () {
12 | function Logger(prefix) {
13 | _classCallCheck(this, Logger);
14 |
15 | this.prefix = prefix;
16 | this.firedDebugNotice = false;
17 | this.fireDebugNotice();
18 | }
19 |
20 | _createClass(Logger, [{
21 | key: 'fireDebugNotice',
22 | value: function fireDebugNotice() {
23 | if (!this.firedDebugNotice) {
24 | // this.debug('You are running Rapid in debug mode. All requests will be mimicked.');
25 |
26 | this.firedDebugNotice = true;
27 | }
28 | }
29 | }, {
30 | key: 'debug',
31 | value: function debug(message) {
32 | console.info('[' + this.prefix + ']: ' + message);
33 | }
34 | }, {
35 | key: 'log',
36 | value: function log(message) {
37 | console.log('[' + this.prefix + ']:', message);
38 | }
39 | }, {
40 | key: 'warn',
41 | value: function warn(message) {
42 | console.warn('[' + this.prefix + ' warn]:', message);
43 | }
44 | }]);
45 |
46 | return Logger;
47 | }();
48 |
49 | exports.default = new Logger('rapid js');
--------------------------------------------------------------------------------
/test/crud.test.js:
--------------------------------------------------------------------------------
1 | import { createModel } from './helpers';
2 |
3 | const userModel = createModel({
4 | modelName: 'user',
5 | });
6 |
7 | describe('The basic CRUD methods should work', () => {
8 | it('that it will have the right url for find', () => {
9 | userModel.find(1);
10 |
11 | expect(userModel.debugger.data.lastUrl).toBe('api/user/1');
12 | });
13 |
14 | it('that it will have the right url for all', () => {
15 | userModel.all();
16 |
17 | expect(userModel.debugger.data.lastUrl).toBe('api/users');
18 | });
19 |
20 | const myModel = createModel({
21 | modelName: 'model',
22 | });
23 |
24 | it('that it will have the right url for findBy', () => {
25 | myModel.findBy('key', 'value');
26 |
27 | expect(myModel.debugger.data.lastUrl).toBe('api/model/key/value');
28 |
29 | myModel.collection.findBy('key', 'value');
30 |
31 | expect(myModel.debugger.data.lastUrl).toBe('api/models/key/value');
32 | });
33 |
34 | const testModel = createModel({
35 | modelName: 'testModel',
36 | suffixes: {
37 | create: 'new',
38 | update: 'save',
39 | destroy: 'delete',
40 | },
41 | });
42 |
43 | it('that create will have the correct url', () => {
44 | testModel.create({});
45 | expect(testModel.debugger.data.lastUrl).toBe('api/test-model/new');
46 | });
47 |
48 | it('that update will work', () => {
49 | testModel.update({});
50 | expect(testModel.debugger.data.lastUrl).toBe('api/test-model/save');
51 |
52 | testModel.update(12345, {});
53 | expect(testModel.debugger.data.lastUrl).toBe('api/test-model/12345/save');
54 | });
55 |
56 | it('that destroy will work', () => {
57 | testModel.destroy({});
58 | expect(testModel.debugger.data.lastUrl).toBe('api/test-model/delete');
59 |
60 | testModel.destroy(12345, {});
61 | expect(testModel.debugger.data.lastUrl).toBe('api/test-model/12345/delete');
62 | });
63 | });
64 |
--------------------------------------------------------------------------------
/demo/webpack.mix.js:
--------------------------------------------------------------------------------
1 | let mix = require('laravel-mix');
2 |
3 | /*
4 | |--------------------------------------------------------------------------
5 | | Mix Asset Management
6 | |--------------------------------------------------------------------------
7 | |
8 | | Mix provides a clean, fluent API for defining some Webpack build steps
9 | | for your Laravel application. By default, we are compiling the Sass
10 | | file for your application, as well as bundling up your JS files.
11 | |
12 | */
13 |
14 | mix.js('src/app.js', 'dist/');
15 |
16 | // Full API
17 | // mix.js(src, output);
18 | // mix.react(src, output); <-- Identical to mix.js(), but registers React Babel compilation.
19 | // mix.extract(vendorLibs);
20 | // mix.sass(src, output);
21 | // mix.less(src, output);
22 | // mix.stylus(src, output);
23 | // mix.browserSync('my-site.dev');
24 | // mix.combine(files, destination);
25 | // mix.babel(files, destination); <-- Identical to mix.combine(), but also includes Babel compilation.
26 | // mix.copy(from, to);
27 | // mix.copyDirectory(fromDir, toDir);
28 | // mix.minify(file);
29 | // mix.sourceMaps(); // Enable sourcemaps
30 | // mix.version(); // Enable versioning.
31 | // mix.disableNotifications();
32 | // mix.setPublicPath('path/to/public');
33 | // mix.setResourceRoot('prefix/for/resource/locators');
34 | // mix.autoload({}); <-- Will be passed to Webpack's ProvidePlugin.
35 | // mix.webpackConfig({}); <-- Override webpack.config.js, without editing the file directly.
36 | // mix.then(function () {}) <-- Will be triggered each time Webpack finishes building.
37 | // mix.options({
38 | // extractVueStyles: false, // Extract .vue component styling to file, rather than inline.
39 | // processCssUrls: true, // Process/optimize relative stylesheet url()'s. Set to false, if you don't want them touched.
40 | // purifyCss: false, // Remove unused CSS selectors.
41 | // uglify: {}, // Uglify-specific options. https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
42 | // postCss: [] // Post-CSS options: https://github.com/postcss/postcss/blob/master/docs/plugins.md
43 | // });
44 |
--------------------------------------------------------------------------------
/test/base.test.js:
--------------------------------------------------------------------------------
1 | import Rapid from './../src/rapid';
2 |
3 | class GalleryWrapper extends Rapid {
4 | boot () {
5 | this.baseURL = 'https://mysite.com/api';
6 | this.modelName = 'Gallery';
7 | }
8 |
9 | tagSearch (query) {
10 | return this.append('tagsearch').withParam('query', query);
11 | }
12 |
13 | categorySearch (query) {
14 | return this.append('categorysearch').withParam('query', query);
15 | }
16 |
17 | paginate (pagination) {
18 | return this.withParams(pagination);
19 | }
20 |
21 | taxonomy (taxonomy) {
22 | return this.append(taxonomy);
23 | }
24 |
25 | json () {
26 | return this.append('json');
27 | }
28 |
29 | xml () {
30 | return this.append('xml');
31 | }
32 | }
33 |
34 | describe('Extending and creating a wrapper', () => {
35 | const wrapper = new GalleryWrapper({
36 | globalParameters: {
37 | key: 'YOUR_API_KEY',
38 | },
39 | debug: true,
40 | });
41 | wrapper.debugger.logEnabled = false;
42 |
43 | it('should generate proper urls from the wrapper methods', () => {
44 | wrapper.tagSearch('orange').json().get();
45 | expect(wrapper.debugger.data.lastUrl).toBe('https://mysite.com/api/gallery/tagsearch/json?query=orange&key=YOUR_API_KEY');
46 |
47 | wrapper.categorySearch('nature').xml().get();
48 | expect(wrapper.debugger.data.lastUrl).toBe('https://mysite.com/api/gallery/categorysearch/xml?query=nature&key=YOUR_API_KEY');
49 |
50 |
51 | wrapper.id(45).taxonomy('tags').json().get();
52 | expect(wrapper.debugger.data.lastUrl).toBe('https://mysite.com/api/gallery/45/tags/json?key=YOUR_API_KEY');
53 |
54 |
55 | wrapper.id(45).taxonomy('categories').xml().get();
56 | expect(wrapper.debugger.data.lastUrl).toBe('https://mysite.com/api/gallery/45/categories/xml?key=YOUR_API_KEY');
57 |
58 | wrapper.id(45).paginate({ page: 1, perPage: 20 }).xml().get();
59 | expect(wrapper.debugger.data.lastUrl).toBe('https://mysite.com/api/gallery/45/xml?page=1&perPage=20&key=YOUR_API_KEY');
60 | });
61 | });
62 |
--------------------------------------------------------------------------------
/src/core/custom-route.js:
--------------------------------------------------------------------------------
1 | class CustomRoute {
2 | constructor (route = {}, config = {}) {
3 | // setup the default route object
4 | this.route = Object.assign({
5 | url: '',
6 | type: 'get',
7 | name: '',
8 | }, route);
9 |
10 | // setup the default config
11 | this.config = Object.assign({
12 | routeParams: {},
13 | }, config);
14 | }
15 |
16 | /**
17 | * This replaces any interpolated params with items passed in via the routeParams object
18 | *
19 | * @return {string}
20 | */
21 | replaceURLParams () {
22 | let url = this.rawURL;
23 |
24 | // only do this if we have route params && params to replace
25 | if (this.urlParams.length && Object.keys(this.config.routeParams).length !== 0) {
26 | // replace each occurrence of the param with the value passed in
27 | this.urlParams.forEach((param) => {
28 | url = url.replace(`{${param}}`, this.config.routeParams[param]);
29 | });
30 | }
31 |
32 | return url;
33 | }
34 |
35 | /**
36 | * Check if the url has interpolated {} in them
37 | *
38 | * @return {array}
39 | */
40 | get urlParams () {
41 | // eslint-disable-next-line
42 | let params = this.rawURL.match(/{\s*[\w\.]+\s*}/g);
43 |
44 | // if we have params, strip off the {}
45 | if (params !== null) {
46 | return params.map(x =>
47 | // eslint-disable-next-line
48 | x.match(/[\w\.]+/)[0]);
49 | }
50 |
51 | return [];
52 | }
53 |
54 | /**
55 | * Returns the properly prepared URL
56 | *
57 | * @return {string}
58 | */
59 | get url () {
60 | return this.replaceURLParams();
61 | }
62 |
63 | /**
64 | * Returns the raw url from the route which would
65 | * contain any interpolations
66 | *
67 | * @return {string}
68 | */
69 | get rawURL () {
70 | return this.route.url;
71 | }
72 |
73 | /**
74 | * Returns the route name
75 | *
76 | * @return {string}
77 | */
78 | get name () {
79 | return this.route.name;
80 | }
81 |
82 | /**
83 | * Returns the request type
84 | *
85 | * @return {string}
86 | */
87 | get type () {
88 | return this.route.type;
89 | }
90 | }
91 |
92 | export default CustomRoute;
93 |
--------------------------------------------------------------------------------
/test/auth.test.js:
--------------------------------------------------------------------------------
1 | import { createAuthModel } from './helpers';
2 |
3 | const user = createAuthModel({ modelName: 'user' });
4 |
5 | describe('Rapid Auth Model', () => {
6 |
7 | it('should generate the login url', () => {
8 | user.login();
9 | expect(user.debugger.data.lastUrl).toBe('api/login');
10 | });
11 |
12 | it('should generate the logout url', () => {
13 | user.logout();
14 | expect(user.debugger.data.lastUrl).toBe('api/logout');
15 | });
16 |
17 | it('should generate a route to auth check', () => {
18 | user.check();
19 | expect(user.debugger.data.lastUrl).toBe('api/auth');
20 | });
21 |
22 | it('should generate a route to auth register', () => {
23 | user.register();
24 | expect(user.debugger.data.lastUrl).toBe('api/register');
25 | });
26 |
27 | const userTwo = createAuthModel({ modelName: 'User', auth: { modelPrefix: true } });
28 |
29 | it('should contain a model prefix when set in config', () => {
30 | userTwo.register();
31 | expect(userTwo.debugger.data.lastUrl).toBe('api/user/register');
32 | });
33 |
34 | const userFour = createAuthModel({
35 | modelName: 'User',
36 | auth: {
37 | routes: {
38 | login: 'login-user',
39 | logout: ['logout', 'user'],
40 | auth: 'authenticate',
41 | register: 'new',
42 | },
43 | },
44 | });
45 |
46 | it('should allow overriding in the auth routes', () => {
47 | userFour.login();
48 | expect(userFour.debugger.data.lastUrl).toBe('api/login-user');
49 |
50 | userFour.logout();
51 | expect(userFour.debugger.data.lastUrl).toBe('api/logout/user');
52 |
53 | userFour.check();
54 | expect(userFour.debugger.data.lastUrl).toBe('api/authenticate');
55 |
56 | userFour.register();
57 | expect(userFour.debugger.data.lastUrl).toBe('api/new');
58 | });
59 |
60 | const userFive = createAuthModel({
61 | modelName: 'User',
62 | auth: {
63 | methods: {
64 | login: 'get',
65 | logout: 'delete',
66 | auth: 'get',
67 | register: 'patch',
68 | },
69 | },
70 | });
71 |
72 | it('should allow overriding the method types', () => {
73 | userFive.login();
74 | expect(userFive.debugger.data.lastRequest.type).toBe('get');
75 |
76 | userFive.logout();
77 | expect(userFive.debugger.data.lastRequest.type).toBe('delete');
78 |
79 | userFive.check();
80 | expect(userFive.debugger.data.lastRequest.type).toBe('get');
81 |
82 | userFive.register();
83 | expect(userFive.debugger.data.lastRequest.type).toBe('patch');
84 | });
85 |
86 | });
87 |
--------------------------------------------------------------------------------
/src/core/url.js:
--------------------------------------------------------------------------------
1 | /**
2 | * URL Methods
3 | */
4 |
5 | import isArray from 'lodash/isArray';
6 | import Core from './core';
7 | import { sanitizeUrl } from '../common/url';
8 |
9 | class Url extends Core {
10 | constructor (config) {
11 | super(config);
12 | }
13 |
14 | /**
15 | * Based off the current route that's set this will take a set of params
16 | * and split it into a URL. This will then reset the route to the default
17 | * route after building the URL.
18 | *
19 | * @param ...params Can be any length of params that will be joined by /
20 | */
21 | makeUrl (...params) {
22 |
23 | if (this.config.trailingSlash) {
24 | params.push('');
25 | }
26 |
27 | let url = this.sanitizeUrl([this.routes[this.currentRoute]].concat(params).join('/'));
28 |
29 | // strip the extra .
30 | // make sure routes don't need to regenerate
31 | if (this.config.extension) {
32 | url += `.${this.config.extension}`;
33 | }
34 |
35 | // reset currentRoute
36 | this.setCurrentRoute(this.config.defaultRoute);
37 |
38 | return url;
39 | }
40 |
41 | /**
42 | * This just makes sure there are no double slashes and no trailing
43 | * slash unless the config for it is set.
44 | *
45 | * @param url a url to sanitize
46 | */
47 | sanitizeUrl (url) {
48 | return sanitizeUrl(url, this.config.trailingSlash);
49 | }
50 |
51 | /**
52 | * Reset an URL params set from a relationship
53 | */
54 | resetURLParams () {
55 | this.urlParams = false;
56 | }
57 |
58 | /**
59 | * Set the URL params
60 | */
61 | setURLParams (urlParams = [], prepend = false, overwrite = false) {
62 | this.urlParams = this.urlParams || [];
63 |
64 | if (!isArray(urlParams)) {
65 | urlParams = [urlParams];
66 | }
67 |
68 | if (overwrite) {
69 | this.urlParams = urlParams;
70 |
71 | return this;
72 | }
73 |
74 | if (prepend) {
75 | this.urlParams = urlParams.concat(this.urlParams);
76 | } else {
77 | this.urlParams = this.urlParams.concat(urlParams);
78 | }
79 |
80 | return this;
81 | }
82 |
83 | // consider making a .url() alias of the above method?
84 |
85 | url (...params) {
86 | this.setURLParams(...params);
87 |
88 | return this;
89 | }
90 |
91 | prepend (params) {
92 | this.setURLParams(params, true);
93 |
94 | return this;
95 | }
96 |
97 | append (params) {
98 | this.setURLParams(params);
99 |
100 | return this;
101 | }
102 |
103 | }
104 |
105 | export default Url;
106 |
--------------------------------------------------------------------------------
/demo/rapid/Core/Url.js:
--------------------------------------------------------------------------------
1 | /**
2 | * URL Methods
3 | */
4 |
5 | import { isArray } from 'lodash';
6 | import Core from './core';
7 | import { sanitizeUrl } from '../common/url';
8 |
9 | class Url extends Core {
10 | constructor (config) {
11 | super(config);
12 | }
13 |
14 | /**
15 | * Based off the current route that's set this will take a set of params
16 | * and split it into a URL. This will then reset the route to the default
17 | * route after building the URL.
18 | *
19 | * @param ...params Can be any length of params that will be joined by /
20 | */
21 | makeUrl (...params) {
22 |
23 | if (this.config.trailingSlash) {
24 | params.push('');
25 | }
26 |
27 | let url = this.sanitizeUrl([this.routes[this.currentRoute]].concat(params).join('/'));
28 |
29 | // strip the extra .
30 | // make sure routes don't need to regenerate
31 | if (this.config.extension) {
32 | url += `.${this.config.extension}`;
33 | }
34 |
35 | // reset currentRoute
36 | this.setCurrentRoute(this.config.defaultRoute);
37 |
38 | return url;
39 | }
40 |
41 | /**
42 | * This just makes sure there are no double slashes and no trailing
43 | * slash unless the config for it is set.
44 | *
45 | * @param url a url to sanitize
46 | */
47 | sanitizeUrl (url) {
48 | return sanitizeUrl(url, this.config.trailingSlash);
49 | }
50 |
51 | /**
52 | * Reset an URL params set from a relationship
53 | */
54 | resetURLParams () {
55 | this.urlParams = false;
56 | }
57 |
58 | /**
59 | * Set the URL params
60 | */
61 | setURLParams (urlParams = [], prepend = false, overwrite = false) {
62 | this.urlParams = this.urlParams || [];
63 |
64 | if (!isArray(urlParams)) {
65 | urlParams = [urlParams];
66 | }
67 |
68 | if (overwrite) {
69 | this.urlParams = urlParams;
70 |
71 | return this;
72 | }
73 |
74 | if (prepend) {
75 | this.urlParams = urlParams.concat(this.urlParams);
76 | } else {
77 | this.urlParams = this.urlParams.concat(urlParams);
78 | }
79 |
80 | return this;
81 | }
82 |
83 | // consider making a .url() alias of the above method?
84 |
85 | url (...params) {
86 | this.setURLParams(...params);
87 |
88 | return this;
89 | }
90 |
91 | prepend (params) {
92 | this.setURLParams(params, true);
93 |
94 | return this;
95 | }
96 |
97 | append (params) {
98 | this.setURLParams(params);
99 |
100 | return this;
101 | }
102 |
103 | }
104 |
105 | export default Url;
106 |
--------------------------------------------------------------------------------
/dist/debug/debugger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8 |
9 | var _qs = require('qs');
10 |
11 | var _qs2 = _interopRequireDefault(_qs);
12 |
13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14 |
15 | function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
16 |
17 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
18 |
19 | var _class = function () {
20 | function _class(caller) {
21 | _classCallCheck(this, _class);
22 |
23 | this.caller = caller;
24 | this.data = {};
25 | this.logEnabled = true;
26 | }
27 |
28 | _createClass(_class, [{
29 | key: 'fakeRequest',
30 | value: function fakeRequest(type, url) {
31 | var params = this.caller.parseRequestData(type);
32 | var lastUrl = this.setLastUrl.apply(this, [type, url].concat(_toConsumableArray(params)));
33 |
34 | this.setLastRequest.apply(this, arguments);
35 |
36 | if (this.logEnabled) {
37 | this.caller.logger.debug(this.caller.config.modelName + ' made a ' + type.toUpperCase() + ' request (' + lastUrl + ')');
38 | this.caller.logger.log(params);
39 | }
40 |
41 | this.caller.afterRequest({});
42 |
43 | return lastUrl;
44 | }
45 | }, {
46 | key: 'setLastUrl',
47 | value: function setLastUrl(type, url) {
48 | var params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
49 |
50 | var lastUrl = '';
51 |
52 | if (['put', 'post', 'patch'].includes(type)) {
53 | lastUrl = this.caller.sanitizeUrl([this.caller.config.baseURL, url].join('/'));
54 | } else {
55 | var urlParams = params.params;
56 | var stringified = urlParams ? '?' + _qs2.default.stringify(urlParams) : '';
57 |
58 | lastUrl = this.caller.sanitizeUrl([this.caller.config.baseURL, url].join('/')) + stringified;
59 | }
60 |
61 | lastUrl = this.caller.sanitizeUrl(lastUrl);
62 |
63 | this.data.lastUrl = lastUrl;
64 |
65 | return lastUrl;
66 | }
67 | }, {
68 | key: 'setLastRequest',
69 | value: function setLastRequest(type, url) {
70 | var data = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
71 | var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
72 |
73 | this.data.lastRequest = {
74 | type: type,
75 | url: url,
76 | data: data,
77 | options: options
78 | };
79 | }
80 | }]);
81 |
82 | return _class;
83 | }();
84 |
85 | exports.default = _class;
--------------------------------------------------------------------------------
/src/core/crud.js:
--------------------------------------------------------------------------------
1 | /**
2 | * All the CRUD
3 | */
4 |
5 | import Request from './request';
6 |
7 | class Crud extends Request {
8 | /**
9 | * Model Only Functions
10 | */
11 |
12 | /**
13 | * Make a GET request to a url that would retrieve a single model.
14 | * Prepends primaryKey if set
15 | *
16 | * @param id The model's id
17 | */
18 | find (id) {
19 | return this.model.id(id).get();
20 | }
21 |
22 | /**
23 | * Make a request to update or destroy a model
24 | *
25 | * @param method The method (update or destroy)
26 | * @param ...params Can be either (id, data) OR (data)
27 | */
28 | updateOrDestroy (method, ...params) {
29 | const urlParams = [];
30 | const id = params[0];
31 | let data = params[1];
32 |
33 | if (Number.isInteger(id)) {
34 | this.id(id);
35 | } else {
36 | [data] = params;
37 | }
38 |
39 | if (Object.prototype.hasOwnProperty.call(this.config.suffixes, method)) {
40 | urlParams.push(this.config.suffixes[method]);
41 | }
42 |
43 | if (method === 'update') {
44 | this.withParams(data);
45 | }
46 |
47 | return this.model.buildRequest(this.config.methods[method], urlParams);
48 | }
49 |
50 | /**
51 | * See updateOrDestroy
52 | */
53 | update (...params) {
54 | return this.updateOrDestroy('update', ...params);
55 | }
56 |
57 | /**
58 | * Alias of update
59 | * See updateOrDestroy
60 | */
61 | save (...params) {
62 | return this.update(...params);
63 | }
64 |
65 | /**
66 | * See updateOrDestroy
67 | */
68 | destroy (...params) {
69 | return this.updateOrDestroy('destroy', ...params);
70 | }
71 |
72 | /**
73 | * Makes a request to create a new model based off the method and suffix for create
74 | *
75 | * @param data The data to be sent over for creation of model
76 | */
77 | create (data) {
78 | return this.withParams(data)
79 | .buildRequest(this.config.methods.create, this.config.suffixes.create);
80 | }
81 |
82 | /**
83 | * This sets an id for a request
84 | * currently it doens't work with any of the CRUD methods.
85 | * It should work with this.
86 | *
87 | * @param id The id of the model
88 | */
89 | id (id) {
90 | let params = [];
91 |
92 | // this is checking if primaryKey is true, not if it exists
93 | if (this.config.primaryKey) {
94 | params = [this.config.primaryKey, id];
95 | } else {
96 | params = [id];
97 | }
98 |
99 | // needs to prepend
100 | this.prepend(params);
101 |
102 | return this;
103 | }
104 |
105 | /**
106 | * Collection Only Functions
107 | */
108 |
109 | /**
110 | * Makes a GET request on a collection route
111 | */
112 | all () {
113 | return this.collection.get();
114 | }
115 |
116 | /**
117 | * Collection and Model functions
118 | */
119 |
120 | /**
121 | * Makes a GET request to find a model/collection by key, value
122 | *
123 | * @param key The key to search by
124 | * @param value The value to search by
125 | */
126 | findBy (key, value) {
127 | const urlParams = [key];
128 |
129 | if (value) {
130 | urlParams.push(value);
131 | }
132 |
133 | return this.get(...urlParams);
134 | }
135 | }
136 |
137 | export default Crud;
138 |
--------------------------------------------------------------------------------
/demo/rapid/Core/Crud.js:
--------------------------------------------------------------------------------
1 | /**
2 | * All the CRUD
3 | */
4 |
5 | import Request from './request';
6 |
7 | class Crud extends Request {
8 | /**
9 | * Model Only Functions
10 | */
11 |
12 | /**
13 | * Make a GET request to a url that would retrieve a single model.
14 | * Prepends primaryKey if set
15 | *
16 | * @param id The model's id
17 | */
18 | find (id) {
19 | return this.model.id(id).get();
20 | }
21 |
22 | /**
23 | * Make a request to update or destroy a model
24 | *
25 | * @param method The method (update or destroy)
26 | * @param ...params Can be either (id, data) OR (data)
27 | */
28 | updateOrDestroy (method, ...params) {
29 | const urlParams = [];
30 | const id = params[0];
31 | let data = params[1];
32 |
33 | if (Number.isInteger(id)) {
34 | this.id(id);
35 | } else {
36 | [data] = params;
37 | }
38 |
39 | if (Object.prototype.hasOwnProperty.call(this.config.suffixes, method)) {
40 | urlParams.push(this.config.suffixes[method]);
41 | }
42 |
43 | if (method === 'update') {
44 | this.withParams(data);
45 | }
46 |
47 | return this.model.buildRequest(this.config.methods[method], urlParams);
48 | }
49 |
50 | /**
51 | * See updateOrDestroy
52 | */
53 | update (...params) {
54 | return this.updateOrDestroy('update', ...params);
55 | }
56 |
57 | /**
58 | * Alias of update
59 | * See updateOrDestroy
60 | */
61 | save (...params) {
62 | return this.update(...params);
63 | }
64 |
65 | /**
66 | * See updateOrDestroy
67 | */
68 | destroy (...params) {
69 | return this.updateOrDestroy('destroy', ...params);
70 | }
71 |
72 | /**
73 | * Makes a request to create a new model based off the method and suffix for create
74 | *
75 | * @param data The data to be sent over for creation of model
76 | */
77 | create (data) {
78 | return this.withParams(data)
79 | .buildRequest(this.config.methods.create, this.config.suffixes.create);
80 | }
81 |
82 | /**
83 | * This sets an id for a request
84 | * currently it doens't work with any of the CRUD methods.
85 | * It should work with this.
86 | *
87 | * @param id The id of the model
88 | */
89 | id (id) {
90 | let params = [];
91 |
92 | // this is checking if primaryKey is true, not if it exists
93 | if (this.config.primaryKey) {
94 | params = [this.config.primaryKey, id];
95 | } else {
96 | params = [id];
97 | }
98 |
99 | // needs to prepend
100 | this.prepend(params);
101 |
102 | return this;
103 | }
104 |
105 | /**
106 | * Collection Only Functions
107 | */
108 |
109 | /**
110 | * Makes a GET request on a collection route
111 | */
112 | all () {
113 | return this.collection.get();
114 | }
115 |
116 | /**
117 | * Collection and Model functions
118 | */
119 |
120 | /**
121 | * Makes a GET request to find a model/collection by key, value
122 | *
123 | * @param key The key to search by
124 | * @param value The value to search by
125 | */
126 | findBy (key, value) {
127 | const urlParams = [key];
128 |
129 | if (value) {
130 | urlParams.push(value);
131 | }
132 |
133 | return this.get(...urlParams);
134 | }
135 | }
136 |
137 | export default Crud;
138 |
--------------------------------------------------------------------------------
/test/custom-route.test.js:
--------------------------------------------------------------------------------
1 | import { createModel } from './helpers';
2 |
3 | const routes = [
4 | {
5 | name: 'get_user_forget_name',
6 | type: 'get',
7 | url: '/user/forget/name',
8 | },
9 |
10 | {
11 | name: 'user_save_friends',
12 | type: 'post',
13 | url: '/user/{id}/save/friends',
14 | },
15 |
16 | {
17 | name: 'multiple_values',
18 | type: 'post',
19 | url: '/user/{id}/{username}',
20 | },
21 |
22 | {
23 | name: 'multiple_same_values',
24 | type: 'delete',
25 | url: '/user/{id}/{username}/save/{id}',
26 | },
27 | ];
28 |
29 |
30 | describe('Custom Routes should work as designed', () => {
31 | it('should create an empty object if no routes are defined', () => {
32 | const model = createModel({ name: 'Drew' });
33 |
34 | expect(model.customRoutes).toEqual({});
35 | });
36 |
37 | it('should load the custom routes into the config', () => {
38 | const model = createModel({ customRoutes: routes });
39 |
40 | expect(Object.prototype.hasOwnProperty.call(model.customRoutes, 'get_user_forget_name')).toBeTruthy();
41 | expect(Object.prototype.hasOwnProperty.call(model.customRoutes, 'user_save_friends')).toBeTruthy();
42 | });
43 |
44 | const model = createModel({ customRoutes: routes });
45 |
46 | it('should find a route when route() is called', () => {
47 | expect(model.getCustomRoute('get_user_forget_name').url).toBe('/user/forget/name');
48 | });
49 |
50 | it('should find urlParams if they exist', () => {
51 |
52 | expect(model.getCustomRoute('get_user_forget_name').urlParams).toEqual([]);
53 | expect(model.getCustomRoute('user_save_friends').urlParams).toEqual(['id']);
54 | expect(model.getCustomRoute('multiple_values').urlParams).toEqual(['id', 'username']);
55 | expect(model.getCustomRoute('multiple_same_values').urlParams).toEqual(['id', 'username', 'id']);
56 | });
57 |
58 | it('should replace interpolated variables', () => {
59 | expect(model.generate('user_save_friends3')).toBe('');
60 | expect(model.generate('user_save_friends', { id: 1 })).toBe('/api/user/1/save/friends');
61 | expect(model.generate('multiple_same_values', { id: 1, username: 'drew' })).toBe('/api/user/1/drew/save/1');
62 | });
63 |
64 | it('should fire the proper request type and url', () => {
65 | model.route('get_user_forget_name');
66 |
67 | expect(model.debugger.data.lastUrl).toBe('api/user/forget/name');
68 | expect(model.debugger.data.lastRequest.type).toBe('get');
69 |
70 | model.route('user_save_friends', { id: 123 });
71 | expect(model.debugger.data.lastUrl).toBe('api/user/123/save/friends');
72 | expect(model.debugger.data.lastRequest.type).toBe('post');
73 |
74 | model.route('multiple_values', { id: 563, username: 'drewjbartlett' });
75 | expect(model.debugger.data.lastUrl).toBe('api/user/563/drewjbartlett');
76 | expect(model.debugger.data.lastRequest.type).toBe('post');
77 |
78 | model.route('multiple_same_values', { id: 563, username: 'drewjbartlett' });
79 | expect(model.debugger.data.lastUrl).toBe('api/user/563/drewjbartlett/save/563');
80 | expect(model.debugger.data.lastRequest.type).toBe('delete');
81 | });
82 |
83 | const newModel = createModel({ baseURL: '/water', customRoutes: routes });
84 |
85 | it('should append the baseURL in the custom route', () => {
86 | expect(newModel.generate('get_user_forget_name')).toBe('/water/user/forget/name');
87 | });
88 |
89 | const anotherModel = createModel({ baseURL: '', customRoutes: routes });
90 |
91 | it('should append the baseURL in the custom route', () => {
92 | expect(anotherModel.generate('get_user_forget_name')).toBe('/user/forget/name');
93 | });
94 | });
95 |
--------------------------------------------------------------------------------
/dist/core/rapid.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _crud = require('./crud');
8 |
9 | var _crud2 = _interopRequireDefault(_crud);
10 |
11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12 |
13 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
14 |
15 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
16 |
17 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*!
18 | * Rapid.js v0.0.14
19 | * (c) 2017 Drew J Bartlett (https://drewjbartlett.com)
20 | * Released under the MIT License.
21 | */
22 |
23 | /**
24 | * The inheritance of the classes
25 | *
26 | * Core ---> Url
27 | * Url ---> Routes
28 | * Routes ---> Request
29 | * Request ---> Relationships
30 | * Relationships ---> Crud
31 | * Crud ---> Rapid
32 | *
33 | */
34 |
35 | var Rapid = function (_Crud) {
36 | _inherits(Rapid, _Crud);
37 |
38 | function Rapid(config) {
39 | _classCallCheck(this, Rapid);
40 |
41 | return _possibleConstructorReturn(this, (Rapid.__proto__ || Object.getPrototypeOf(Rapid)).call(this, config));
42 | }
43 |
44 | return Rapid;
45 | }(_crud2.default);
46 |
47 | exports.default = Rapid;
--------------------------------------------------------------------------------
/dist/auth.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8 |
9 | var _defaultsDeep = require('lodash/defaultsDeep');
10 |
11 | var _defaultsDeep2 = _interopRequireDefault(_defaultsDeep);
12 |
13 | var _rapid = require('./core/rapid');
14 |
15 | var _rapid2 = _interopRequireDefault(_rapid);
16 |
17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18 |
19 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
20 |
21 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
22 |
23 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
24 |
25 | var authConfig = {
26 | auth: {
27 | routes: {
28 | login: 'login',
29 | logout: 'logout',
30 | auth: 'auth',
31 | register: 'register'
32 | },
33 |
34 | methods: {
35 | login: 'post',
36 | logout: 'post',
37 | auth: 'get',
38 | register: 'post'
39 | },
40 |
41 | modelPrefix: false
42 | }
43 | };
44 |
45 | var Auth = function (_Rapid) {
46 | _inherits(Auth, _Rapid);
47 |
48 | function Auth(config) {
49 | _classCallCheck(this, Auth);
50 |
51 | config = (0, _defaultsDeep2.default)(config, authConfig);
52 | config.modelName = config.modelName ? config.modelName : 'auth';
53 |
54 | return _possibleConstructorReturn(this, (Auth.__proto__ || Object.getPrototypeOf(Auth)).call(this, config));
55 | }
56 |
57 | _createClass(Auth, [{
58 | key: 'login',
59 | value: function login() {
60 | var credentials = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
61 |
62 | return this[this.modelPrefix].withParams(credentials).withOption('auth', credentials).buildRequest(this.config.auth.methods.login, this.config.auth.routes.login);
63 | }
64 | }, {
65 | key: 'logout',
66 | value: function logout() {
67 | return this[this.modelPrefix].buildRequest(this.config.auth.methods.logout, this.config.auth.routes.logout);
68 | }
69 | }, {
70 | key: 'check',
71 | value: function check() {
72 | return this[this.modelPrefix].buildRequest(this.config.auth.methods.auth, this.config.auth.routes.auth);
73 | }
74 | }, {
75 | key: 'register',
76 | value: function register() {
77 | var credentials = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
78 |
79 | return this[this.modelPrefix].withParams(credentials).buildRequest(this.config.auth.methods.register, this.config.auth.routes.register);
80 | }
81 | }, {
82 | key: 'modelPrefix',
83 | get: function get() {
84 | return this.config.auth.modelPrefix ? 'model' : 'any';
85 | }
86 | }]);
87 |
88 | return Auth;
89 | }(_rapid2.default);
90 |
91 | exports.default = Auth;
--------------------------------------------------------------------------------
/demo/rapid/Core/Core.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The Caramel Core functionality of Rapid
3 | */
4 |
5 | import axios from 'axios';
6 | import { defaultsDeep } from 'lodash';
7 |
8 | import Defaults from './defaults';
9 | import Debugger from './../debug/debugger';
10 | import Logger from './../debug/logger';
11 |
12 | class Core {
13 | constructor (config) {
14 | config = config || {};
15 |
16 | config = defaultsDeep(config, Defaults);
17 |
18 | this.initialize(config);
19 | }
20 |
21 | /**
22 | * Set any config overrides in this method when extending
23 | */
24 | boot () {
25 |
26 | }
27 |
28 | /**
29 | * Setup the all of properties.
30 | */
31 | initialize (config) {
32 | this.config = config;
33 |
34 | this.initializeRoutes();
35 |
36 | this.boot();
37 |
38 | this.resetURLParams();
39 |
40 | this.fireSetters();
41 |
42 | this.initializeAPI();
43 |
44 | this.setCurrentRoute(this.config.defaultRoute);
45 |
46 | this.initializeDebugger();
47 |
48 | this.initializeLogger();
49 |
50 | this.resetRequestData();
51 |
52 | this.defineCustomRoutes();
53 | }
54 |
55 | /**
56 | * Fire the setters. This will make sure the routes are generated properly.
57 | * Consider if this is really even necessary
58 | */
59 | fireSetters () {
60 | ['baseURL', 'modelName', 'routeDelimeter', 'caseSensitive'].forEach(setter => this[setter] = this.config[setter]);
61 | }
62 |
63 | /**
64 | * Initialze the debugger if debug is set to true.
65 | */
66 | initializeDebugger () {
67 | this.debugger = this.config.debug ? new Debugger(this) : false;
68 | }
69 |
70 | /**
71 | * Initialze the debugger if debug is set to true.
72 | */
73 | initializeLogger () {
74 | this.logger = this.config.debug ? Logger : false;
75 | }
76 |
77 | /**
78 | * Initialize the API.
79 | */
80 | initializeAPI () {
81 | this.api = axios.create(defaultsDeep({ baseURL: this.config.baseURL.replace(/\/$/, '') }, this.config.apiConfig));
82 | }
83 |
84 | /**
85 | * Initialize the routes.
86 | */
87 | initializeRoutes () {
88 | this.routes = {
89 | model: '',
90 | collection: '',
91 | any: '',
92 | };
93 | }
94 |
95 | /**
96 | * Set up the custom routes if we have any
97 | */
98 | defineCustomRoutes () {
99 | this.customRoutes = {};
100 |
101 | // if we have custom routes, set up a name:route mapping
102 | if (this.config.customRoutes.length) {
103 | this.config.customRoutes.forEach((route) => {
104 | this.customRoutes[route.name] = route;
105 | });
106 | }
107 | }
108 |
109 | /**
110 | * Resets the request data
111 | */
112 | resetRequestData () {
113 | this.requestData = {
114 | params: {},
115 | options: {},
116 | };
117 | }
118 |
119 | /**
120 | * Setters and Getters
121 | */
122 |
123 | set debug (val) {
124 | if (this.config.debug) {
125 | this.logger.warn('debug mode must explicitly be turned on via the constructor in config.debug');
126 | }
127 | }
128 |
129 | get collection () {
130 | this.setCurrentRoute('collection');
131 |
132 | return this;
133 | }
134 |
135 | get model () {
136 | this.setCurrentRoute('model');
137 |
138 | return this;
139 | }
140 |
141 | get any () {
142 | this.setCurrentRoute('any');
143 |
144 | return this;
145 | }
146 |
147 | set baseURL (url) {
148 | this.config.baseURL = this.sanitizeUrl(url);
149 | this.initializeAPI();
150 | }
151 |
152 | set modelName (val) {
153 | this.config.modelName = val;
154 | this.setRoutes();
155 | }
156 |
157 | set routeDelimeter (val) {
158 | this.config.routeDelimeter = val;
159 | this.setRoutes();
160 | }
161 |
162 | set caseSensitive (val) {
163 | this.config.caseSensitive = val;
164 | this.setRoutes();
165 | }
166 | }
167 |
168 | export default Core;
169 |
--------------------------------------------------------------------------------
/src/core/core.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The Caramel Core functionality of Rapid
3 | */
4 |
5 | import axios from 'axios';
6 | import defaultsDeep from 'lodash/defaultsDeep';
7 |
8 | import Defaults from './defaults';
9 | import Debugger from './../debug/debugger';
10 | import Logger from './../debug/logger';
11 |
12 | class Core {
13 | constructor (config) {
14 | config = config || {};
15 |
16 | config = defaultsDeep(config, Defaults);
17 |
18 | this.initialize(config);
19 | }
20 |
21 | /**
22 | * Set any config overrides in this method when extending
23 | */
24 | boot () {
25 |
26 | }
27 |
28 | /**
29 | * Setup the all of properties.
30 | */
31 | initialize (config) {
32 | this.config = config;
33 |
34 | this.initializeRoutes();
35 |
36 | this.boot();
37 |
38 | this.resetURLParams();
39 |
40 | this.fireSetters();
41 |
42 | this.initializeAPI();
43 |
44 | this.setCurrentRoute(this.config.defaultRoute);
45 |
46 | this.initializeDebugger();
47 |
48 | this.initializeLogger();
49 |
50 | this.resetRequestData();
51 |
52 | this.defineCustomRoutes();
53 | }
54 |
55 | /**
56 | * Fire the setters. This will make sure the routes are generated properly.
57 | * Consider if this is really even necessary
58 | */
59 | fireSetters () {
60 | ['baseURL', 'modelName', 'routeDelimeter', 'caseSensitive'].forEach(setter => this[setter] = this.config[setter]);
61 | }
62 |
63 | /**
64 | * Initialze the debugger if debug is set to true.
65 | */
66 | initializeDebugger () {
67 | this.debugger = this.config.debug ? new Debugger(this) : false;
68 | }
69 |
70 | /**
71 | * Initialze the debugger if debug is set to true.
72 | */
73 | initializeLogger () {
74 | this.logger = this.config.debug ? Logger : false;
75 | }
76 |
77 | /**
78 | * Initialize the API.
79 | */
80 | initializeAPI () {
81 | this.api = axios.create(defaultsDeep({ baseURL: this.config.baseURL.replace(/\/$/, '') }, this.config.apiConfig));
82 | }
83 |
84 | /**
85 | * Initialize the routes.
86 | */
87 | initializeRoutes () {
88 | this.routes = {
89 | model: '',
90 | collection: '',
91 | any: '',
92 | };
93 | }
94 |
95 | /**
96 | * Set up the custom routes if we have any
97 | */
98 | defineCustomRoutes () {
99 | this.customRoutes = {};
100 |
101 | // if we have custom routes, set up a name:route mapping
102 | if (this.config.customRoutes.length) {
103 | this.config.customRoutes.forEach((route) => {
104 | this.customRoutes[route.name] = route;
105 | });
106 | }
107 | }
108 |
109 | /**
110 | * Resets the request data
111 | */
112 | resetRequestData () {
113 | this.requestData = {
114 | params: {},
115 | options: {},
116 | };
117 | }
118 |
119 | /**
120 | * Setters and Getters
121 | */
122 |
123 | set debug (val) {
124 | if (this.config.debug) {
125 | this.logger.warn('debug mode must explicitly be turned on via the constructor in config.debug');
126 | }
127 | }
128 |
129 | get collection () {
130 | this.setCurrentRoute('collection');
131 |
132 | return this;
133 | }
134 |
135 | get model () {
136 | this.setCurrentRoute('model');
137 |
138 | return this;
139 | }
140 |
141 | get any () {
142 | this.setCurrentRoute('any');
143 |
144 | return this;
145 | }
146 |
147 | set baseURL (url) {
148 | this.config.baseURL = this.sanitizeUrl(url);
149 | this.initializeAPI();
150 | }
151 |
152 | set modelName (val) {
153 | this.config.modelName = val;
154 | this.setRoutes();
155 | }
156 |
157 | set routeDelimeter (val) {
158 | this.config.routeDelimeter = val;
159 | this.setRoutes();
160 | }
161 |
162 | set caseSensitive (val) {
163 | this.config.caseSensitive = val;
164 | this.setRoutes();
165 | }
166 | }
167 |
168 | export default Core;
169 |
--------------------------------------------------------------------------------
/dist/core/custom-route.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8 |
9 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
10 |
11 | var CustomRoute = function () {
12 | function CustomRoute() {
13 | var route = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
14 | var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
15 |
16 | _classCallCheck(this, CustomRoute);
17 |
18 | // setup the default route object
19 | this.route = Object.assign({
20 | url: '',
21 | type: 'get',
22 | name: ''
23 | }, route);
24 |
25 | // setup the default config
26 | this.config = Object.assign({
27 | routeParams: {}
28 | }, config);
29 | }
30 |
31 | /**
32 | * This replaces any interpolated params with items passed in via the routeParams object
33 | *
34 | * @return {string}
35 | */
36 |
37 |
38 | _createClass(CustomRoute, [{
39 | key: 'replaceURLParams',
40 | value: function replaceURLParams() {
41 | var _this = this;
42 |
43 | var url = this.rawURL;
44 |
45 | // only do this if we have route params && params to replace
46 | if (this.urlParams.length && Object.keys(this.config.routeParams).length !== 0) {
47 | // replace each occurrence of the param with the value passed in
48 | this.urlParams.forEach(function (param) {
49 | url = url.replace('{' + param + '}', _this.config.routeParams[param]);
50 | });
51 | }
52 |
53 | return url;
54 | }
55 |
56 | /**
57 | * Check if the url has interpolated {} in them
58 | *
59 | * @return {array}
60 | */
61 |
62 | }, {
63 | key: 'urlParams',
64 | get: function get() {
65 | // eslint-disable-next-line
66 | var params = this.rawURL.match(/{\s*[\w\.]+\s*}/g);
67 |
68 | // if we have params, strip off the {}
69 | if (params !== null) {
70 | return params.map(function (x) {
71 | return (
72 | // eslint-disable-next-line
73 | x.match(/[\w\.]+/)[0]
74 | );
75 | });
76 | }
77 |
78 | return [];
79 | }
80 |
81 | /**
82 | * Returns the properly prepared URL
83 | *
84 | * @return {string}
85 | */
86 |
87 | }, {
88 | key: 'url',
89 | get: function get() {
90 | return this.replaceURLParams();
91 | }
92 |
93 | /**
94 | * Returns the raw url from the route which would
95 | * contain any interpolations
96 | *
97 | * @return {string}
98 | */
99 |
100 | }, {
101 | key: 'rawURL',
102 | get: function get() {
103 | return this.route.url;
104 | }
105 |
106 | /**
107 | * Returns the route name
108 | *
109 | * @return {string}
110 | */
111 |
112 | }, {
113 | key: 'name',
114 | get: function get() {
115 | return this.route.name;
116 | }
117 |
118 | /**
119 | * Returns the request type
120 | *
121 | * @return {string}
122 | */
123 |
124 | }, {
125 | key: 'type',
126 | get: function get() {
127 | return this.route.type;
128 | }
129 | }]);
130 |
131 | return CustomRoute;
132 | }();
133 |
134 | exports.default = CustomRoute;
--------------------------------------------------------------------------------
/test/request.test.js:
--------------------------------------------------------------------------------
1 | import { createModel } from './helpers';
2 |
3 | const lobster = createModel({ modelName: 'Lobster', baseURL: 'http://maine.com/ocean/' });
4 |
5 | describe('The request functionality should work as expected', () => {
6 |
7 | it('get() works', () => {
8 |
9 | lobster.get('butter');
10 |
11 | expect((lobster.debugger.data.lastRequest.type === 'get')).toBeTruthy();
12 |
13 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobster/butter');
14 |
15 | lobster.collection.get('butter', 'salt');
16 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobsters/butter/salt');
17 |
18 | lobster.get('butter', 'salt', 'crackers');
19 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobster/butter/salt/crackers');
20 |
21 | });
22 |
23 | it('post() works', () => {
24 |
25 | lobster.post('butter');
26 |
27 | expect((lobster.debugger.data.lastRequest.type === 'post')).toBeTruthy();
28 |
29 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobster/butter');
30 |
31 | lobster.collection.post('butter', 'salt');
32 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobsters/butter/salt');
33 |
34 | lobster.post('butter', 'salt', 'crackers');
35 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobster/butter/salt/crackers');
36 |
37 | });
38 |
39 | it('head() works', () => {
40 |
41 | lobster.head('butter');
42 |
43 | expect((lobster.debugger.data.lastRequest.type === 'head')).toBeTruthy();
44 |
45 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobster/butter');
46 |
47 | lobster.collection.head('butter', 'salt');
48 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobsters/butter/salt');
49 |
50 | lobster.head('butter', 'salt', 'crackers');
51 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobster/butter/salt/crackers');
52 |
53 | });
54 |
55 | it('put() works', () => {
56 |
57 | lobster.put('butter');
58 |
59 | expect((lobster.debugger.data.lastRequest.type === 'put')).toBeTruthy();
60 |
61 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobster/butter');
62 |
63 | lobster.collection.put('butter', 'salt');
64 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobsters/butter/salt');
65 |
66 | lobster.put('butter', 'salt', 'crackers');
67 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobster/butter/salt/crackers');
68 |
69 | });
70 |
71 | it('patch() works', () => {
72 |
73 | lobster.patch('butter');
74 |
75 | expect((lobster.debugger.data.lastRequest.type === 'patch')).toBeTruthy();
76 |
77 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobster/butter');
78 |
79 | lobster.collection.patch('butter', 'salt');
80 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobsters/butter/salt');
81 |
82 | lobster.patch('butter', 'salt', 'crackers');
83 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobster/butter/salt/crackers');
84 |
85 | });
86 |
87 | it('delete() works', () => {
88 |
89 | lobster.delete('butter');
90 |
91 | expect((lobster.debugger.data.lastRequest.type === 'delete')).toBeTruthy();
92 |
93 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobster/butter');
94 |
95 | lobster.collection.delete('butter', 'salt');
96 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobsters/butter/salt');
97 |
98 | lobster.delete('butter', 'salt', 'crackers');
99 | expect(lobster.debugger.data.lastUrl).toBe('http://maine.com/ocean/lobster/butter/salt/crackers');
100 |
101 | });
102 |
103 | it('afterRequest gets fired', () => {
104 | const callback = jest.fn();
105 | const Crab = createModel({
106 | modelName: 'Crab',
107 | baseURL: 'http://maryland.com/bay/',
108 | afterRequest() {
109 | callback();
110 | },
111 | });
112 |
113 | Crab.find(1);
114 |
115 | expect(callback.mock.calls.length).toBe(1);
116 | });
117 |
118 | it('beforeRequest gets fired', () => {
119 | const callback = jest.fn();
120 | const Crab = createModel({
121 | modelName: 'Crab',
122 | baseURL: 'http://maryland.com/bay/',
123 | beforeRequest() {
124 | callback();
125 | },
126 | });
127 |
128 | Crab.find(1);
129 |
130 | expect(callback.mock.calls.length).toBe(1);
131 | });
132 | });
133 |
--------------------------------------------------------------------------------
/dist/core/routes.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8 |
9 | var _kebabCase = require('lodash/kebabCase');
10 |
11 | var _kebabCase2 = _interopRequireDefault(_kebabCase);
12 |
13 | var _pluralize = require('pluralize');
14 |
15 | var _pluralize2 = _interopRequireDefault(_pluralize);
16 |
17 | var _url = require('./url');
18 |
19 | var _url2 = _interopRequireDefault(_url);
20 |
21 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
22 |
23 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
24 |
25 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
26 |
27 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
28 | * The Rapid Routes
29 | */
30 |
31 | var Routes = function (_Url) {
32 | _inherits(Routes, _Url);
33 |
34 | function Routes(config) {
35 | _classCallCheck(this, Routes);
36 |
37 | return _possibleConstructorReturn(this, (Routes.__proto__ || Object.getPrototypeOf(Routes)).call(this, config));
38 | }
39 |
40 | /**
41 | * Set the current route.
42 | * This will set the current route to either model, collection,
43 | * or any to make appropriate requests
44 | * Can also be changed by calling rapid.model.func() or rapid.collection.func()
45 | *
46 | * @param route The route to set
47 | */
48 |
49 |
50 | _createClass(Routes, [{
51 | key: 'setCurrentRoute',
52 | value: function setCurrentRoute(route) {
53 | this.currentRoute = route;
54 | }
55 |
56 | /**
57 | * Set the routes for the URL based off model/collection and config
58 | *
59 | * @param route The key of the route to be set
60 | */
61 |
62 | }, {
63 | key: 'setRoute',
64 | value: function setRoute(route) {
65 | var newRoute = '';
66 | var formattedRoute = {
67 | model: this.config.modelName,
68 | collection: (0, _pluralize2.default)(this.config.modelName),
69 | any: ''
70 | };
71 |
72 | if (this.config.routes[route] !== '') {
73 | newRoute = this.config.routes[route];
74 | } else {
75 | newRoute = (0, _kebabCase2.default)(formattedRoute[route]).replace(/-/g, this.config.routeDelimeter);
76 |
77 | if (this.config.caseSensitive) {
78 | newRoute = formattedRoute[route];
79 | }
80 | }
81 |
82 | this.routes[route] = newRoute;
83 | }
84 |
85 | /**
86 | * Loop through the routes and set them
87 | */
88 |
89 | }, {
90 | key: 'setRoutes',
91 | value: function setRoutes() {
92 | var _this2 = this;
93 |
94 | ['model', 'collection'].forEach(function (route) {
95 | return _this2.setRoute(route);
96 | });
97 | }
98 | }]);
99 |
100 | return Routes;
101 | }(_url2.default);
102 |
103 | exports.default = Routes;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [](https://www.npmjs.com/package/rapid.js)
6 | [](https://www.npmjs.com/package/rapid.js)
7 | [](https://www.npmjs.com/package/rapid.js)
8 |
9 | ##### An ORM-like Interface and a Router For Your API Requests
10 | ###### Create simple, resusable, and cleaner wrappers, define custom routes, and more for your API requests.
11 |
12 | Read the official docs at [https://rapidjs.io](https://rapidjs.io).
13 |
14 | ## Overview
15 | - [Define Simple Models](#define-simple-models)
16 | - [Easily Customize Your API Requests](#easily-customize-your-api-requests)
17 | - [Create Reusable Base Models](#create-reusable-base-models)
18 | - [Write API Wrappers For Your Endpoints](#write-api-wrappers-for-your-endpoints)
19 | - [Define Custom Routes (New!)](#define-custom-routes)
20 |
21 | ### Define Simple Models
22 | ```js
23 | var post = new Rapid({ modelName: 'Post' });
24 |
25 | post.find(1).then((response) => {
26 | // GET => /api/post/1
27 | });
28 |
29 | post.collection.findBy('category', 'featured').then((response) => {
30 | // GET => /api/posts/category/featured
31 | });
32 |
33 | post.withParams({ limit: 20, order: 'desc' }).all().then((response) => {
34 | // GET => /api/posts?limit=20&order=desc
35 | });
36 |
37 | post.update(25, { title: 'Rapid JS Is Awesome!' })
38 | // POST => /api/posts/25/update
39 |
40 | post.destroy(9)
41 | // POST => /api/posts/9/destroy
42 | ```
43 | Read more about [Rapid Basics](https://rapidjs.io/docs#usage).
44 |
45 | ### Easily Customize Your API Requests
46 | ```js
47 | var post = new Rapid({
48 | modelName: 'Post',
49 | suffixes: {
50 | destroy: '',
51 | update: 'save'
52 | },
53 | methods: {
54 | destroy: 'delete'
55 | },
56 | trailingSlash: true
57 | });
58 |
59 | post.update(25, { title: 'Rapid JS Is Awesome!' })
60 | // POST => /api/posts/25/save/
61 |
62 | post.destroy(9)
63 | // DELETE => /api/posts/9/
64 | ```
65 | Read more about [Customizing Your Requests](https://rapidjs.io/docs#config-builder).
66 |
67 | ### Create Reusable Base Models
68 | ```js
69 | class Base extends Rapid {
70 | boot () {
71 | this.baseURL = 'https://myapp.com/api';
72 | this.config.globalParameters = { key: 'MY_API_KEY' }
73 | }
74 | }
75 |
76 | var photo = new Base({ modelName: 'Photo' });
77 | var gallery = new Base({ modelName: 'Gallery' });
78 | var tag = new Base({ modelName: 'Tag' });
79 |
80 | photo.find(1)
81 | // GET => https://myapp.com/api/photo/1?key=MY_API_KEY
82 |
83 | tag.collection.findBy('color', 'red')
84 | // GET => https://myapp.com/api/tags/color/red?key=MY_API_KEY
85 |
86 | gallery.id(23).get('tags', 'nature')
87 | // GET => https://myapp.com/api/gallery/23/tag/nature?key=MY_API_KEY
88 | ```
89 | Read more about [Base Models](https://rapidjs.io/docs#extending-base-models).
90 |
91 | ### Write API Wrappers For Your Endpoints
92 | ```js
93 | class GalleryWrapper extends Rapid {
94 | boot () {
95 | this.baseURL = 'https://myapp.com/gallery/api';
96 | this.modelName = 'Gallery';
97 | }
98 |
99 | tagSearch (query) {
100 | return this.url('tagsearch').withParam('query', query);
101 | }
102 |
103 | json () {
104 | return this.url('json');
105 | }
106 | }
107 |
108 | var gallery = new GalleryWrapper({
109 | globalParameters: { key: 'MY_API_KEY' }
110 | });
111 |
112 | gallery.tagSearch('nature').json().get().then(...);
113 | // GET https://myapp.com/gallery/api/tagsearch/json?query=nature&key=MY_API_KEY
114 | // GET https://myapp.com/gallery/api/tagsearch/json?query=nature&key=MY_API_KEY
115 | ```
116 | Read more about [Making a Wrapper](https://rapidjs.io/docs#extending-making-a-wrapper).
117 |
118 | ### Define Custom Routes
119 |
120 | ```js
121 | const customRoutes = [
122 | {
123 | name: 'web_get_user_preferences',
124 | type: 'get',
125 | url: '/user/preferences',
126 | },
127 |
128 | {
129 | name: 'web_save_user_preferences',
130 | type: 'post',
131 | url: '/user/{id}/save/preferences'
132 | }
133 | ];
134 |
135 | const router = new Rapid({ customRoutes, baseURL: '/api' });
136 |
137 | router.route('web_get_user_preferences').then((response) => {});
138 | // GET => /api/user/preferences
139 |
140 | router.route('web_save_user_preferences', { id: 12 }, /* { request data } */).then((response) => {});
141 | // POST => /api/user/12/save/preferences
142 | ```
143 |
144 | #### Using Your Own HTTP Service
145 | ```js
146 | import http from 'some-http-service';
147 |
148 | const customRoutes = [
149 | {
150 | name: 'web_login',
151 | url: '/login'
152 | },
153 |
154 | {
155 | name: 'api_save_user_preferences',,
156 | url: '/user/{id}/save/preferences'
157 | }
158 | ];
159 |
160 | const rapid = new Rapid({ customRoutes, baseURL: '' });
161 |
162 | rapid.generate('web_login')
163 | // returns '/login'
164 |
165 | // use your own service
166 | http.post(rapid.generate('api_save_user_preferences'), { id: 1 }).then()...
167 | ```
168 | Read more about [Custom Routes](https://rapidjs.io/docs#custom-routes).
169 |
170 | Read the official docs at [https://rapidjs.io](https://rapidjs.io).
171 |
--------------------------------------------------------------------------------
/dist/core/url.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8 |
9 | var _isArray = require('lodash/isArray');
10 |
11 | var _isArray2 = _interopRequireDefault(_isArray);
12 |
13 | var _core = require('./core');
14 |
15 | var _core2 = _interopRequireDefault(_core);
16 |
17 | var _url = require('../common/url');
18 |
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20 |
21 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
22 |
23 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
24 |
25 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
26 | * URL Methods
27 | */
28 |
29 | var Url = function (_Core) {
30 | _inherits(Url, _Core);
31 |
32 | function Url(config) {
33 | _classCallCheck(this, Url);
34 |
35 | return _possibleConstructorReturn(this, (Url.__proto__ || Object.getPrototypeOf(Url)).call(this, config));
36 | }
37 |
38 | /**
39 | * Based off the current route that's set this will take a set of params
40 | * and split it into a URL. This will then reset the route to the default
41 | * route after building the URL.
42 | *
43 | * @param ...params Can be any length of params that will be joined by /
44 | */
45 |
46 |
47 | _createClass(Url, [{
48 | key: 'makeUrl',
49 | value: function makeUrl() {
50 | for (var _len = arguments.length, params = Array(_len), _key = 0; _key < _len; _key++) {
51 | params[_key] = arguments[_key];
52 | }
53 |
54 | if (this.config.trailingSlash) {
55 | params.push('');
56 | }
57 |
58 | var url = this.sanitizeUrl([this.routes[this.currentRoute]].concat(params).join('/'));
59 |
60 | // strip the extra .
61 | // make sure routes don't need to regenerate
62 | if (this.config.extension) {
63 | url += '.' + this.config.extension;
64 | }
65 |
66 | // reset currentRoute
67 | this.setCurrentRoute(this.config.defaultRoute);
68 |
69 | return url;
70 | }
71 |
72 | /**
73 | * This just makes sure there are no double slashes and no trailing
74 | * slash unless the config for it is set.
75 | *
76 | * @param url a url to sanitize
77 | */
78 |
79 | }, {
80 | key: 'sanitizeUrl',
81 | value: function sanitizeUrl(url) {
82 | return (0, _url.sanitizeUrl)(url, this.config.trailingSlash);
83 | }
84 |
85 | /**
86 | * Reset an URL params set from a relationship
87 | */
88 |
89 | }, {
90 | key: 'resetURLParams',
91 | value: function resetURLParams() {
92 | this.urlParams = false;
93 | }
94 |
95 | /**
96 | * Set the URL params
97 | */
98 |
99 | }, {
100 | key: 'setURLParams',
101 | value: function setURLParams() {
102 | var urlParams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
103 | var prepend = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
104 | var overwrite = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
105 |
106 | this.urlParams = this.urlParams || [];
107 |
108 | if (!(0, _isArray2.default)(urlParams)) {
109 | urlParams = [urlParams];
110 | }
111 |
112 | if (overwrite) {
113 | this.urlParams = urlParams;
114 |
115 | return this;
116 | }
117 |
118 | if (prepend) {
119 | this.urlParams = urlParams.concat(this.urlParams);
120 | } else {
121 | this.urlParams = this.urlParams.concat(urlParams);
122 | }
123 |
124 | return this;
125 | }
126 |
127 | // consider making a .url() alias of the above method?
128 |
129 | }, {
130 | key: 'url',
131 | value: function url() {
132 | this.setURLParams.apply(this, arguments);
133 |
134 | return this;
135 | }
136 | }, {
137 | key: 'prepend',
138 | value: function prepend(params) {
139 | this.setURLParams(params, true);
140 |
141 | return this;
142 | }
143 | }, {
144 | key: 'append',
145 | value: function append(params) {
146 | this.setURLParams(params);
147 |
148 | return this;
149 | }
150 | }]);
151 |
152 | return Url;
153 | }(_core2.default);
154 |
155 | exports.default = Url;
--------------------------------------------------------------------------------
/dist/core/crud.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8 |
9 | var _request = require('./request');
10 |
11 | var _request2 = _interopRequireDefault(_request);
12 |
13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14 |
15 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
16 |
17 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
18 |
19 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
20 | * All the CRUD
21 | */
22 |
23 | var Crud = function (_Request) {
24 | _inherits(Crud, _Request);
25 |
26 | function Crud() {
27 | _classCallCheck(this, Crud);
28 |
29 | return _possibleConstructorReturn(this, (Crud.__proto__ || Object.getPrototypeOf(Crud)).apply(this, arguments));
30 | }
31 |
32 | _createClass(Crud, [{
33 | key: 'find',
34 |
35 | /**
36 | * Model Only Functions
37 | */
38 |
39 | /**
40 | * Make a GET request to a url that would retrieve a single model.
41 | * Prepends primaryKey if set
42 | *
43 | * @param id The model's id
44 | */
45 | value: function find(id) {
46 | return this.model.id(id).get();
47 | }
48 |
49 | /**
50 | * Make a request to update or destroy a model
51 | *
52 | * @param method The method (update or destroy)
53 | * @param ...params Can be either (id, data) OR (data)
54 | */
55 |
56 | }, {
57 | key: 'updateOrDestroy',
58 | value: function updateOrDestroy(method) {
59 | var urlParams = [];
60 |
61 | for (var _len = arguments.length, params = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
62 | params[_key - 1] = arguments[_key];
63 | }
64 |
65 | var id = params[0];
66 | var data = params[1];
67 |
68 | if (Number.isInteger(id)) {
69 | this.id(id);
70 | } else {
71 | data = params[0];
72 | }
73 |
74 | if (Object.prototype.hasOwnProperty.call(this.config.suffixes, method)) {
75 | urlParams.push(this.config.suffixes[method]);
76 | }
77 |
78 | if (method === 'update') {
79 | this.withParams(data);
80 | }
81 |
82 | return this.model.buildRequest(this.config.methods[method], urlParams);
83 | }
84 |
85 | /**
86 | * See updateOrDestroy
87 | */
88 |
89 | }, {
90 | key: 'update',
91 | value: function update() {
92 | for (var _len2 = arguments.length, params = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
93 | params[_key2] = arguments[_key2];
94 | }
95 |
96 | return this.updateOrDestroy.apply(this, ['update'].concat(params));
97 | }
98 |
99 | /**
100 | * Alias of update
101 | * See updateOrDestroy
102 | */
103 |
104 | }, {
105 | key: 'save',
106 | value: function save() {
107 | return this.update.apply(this, arguments);
108 | }
109 |
110 | /**
111 | * See updateOrDestroy
112 | */
113 |
114 | }, {
115 | key: 'destroy',
116 | value: function destroy() {
117 | for (var _len3 = arguments.length, params = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
118 | params[_key3] = arguments[_key3];
119 | }
120 |
121 | return this.updateOrDestroy.apply(this, ['destroy'].concat(params));
122 | }
123 |
124 | /**
125 | * Makes a request to create a new model based off the method and suffix for create
126 | *
127 | * @param data The data to be sent over for creation of model
128 | */
129 |
130 | }, {
131 | key: 'create',
132 | value: function create(data) {
133 | return this.withParams(data).buildRequest(this.config.methods.create, this.config.suffixes.create);
134 | }
135 |
136 | /**
137 | * This sets an id for a request
138 | * currently it doens't work with any of the CRUD methods.
139 | * It should work with this.
140 | *
141 | * @param id The id of the model
142 | */
143 |
144 | }, {
145 | key: 'id',
146 | value: function id(_id) {
147 | var params = [];
148 |
149 | // this is checking if primaryKey is true, not if it exists
150 | if (this.config.primaryKey) {
151 | params = [this.config.primaryKey, _id];
152 | } else {
153 | params = [_id];
154 | }
155 |
156 | // needs to prepend
157 | this.prepend(params);
158 |
159 | return this;
160 | }
161 |
162 | /**
163 | * Collection Only Functions
164 | */
165 |
166 | /**
167 | * Makes a GET request on a collection route
168 | */
169 |
170 | }, {
171 | key: 'all',
172 | value: function all() {
173 | return this.collection.get();
174 | }
175 |
176 | /**
177 | * Collection and Model functions
178 | */
179 |
180 | /**
181 | * Makes a GET request to find a model/collection by key, value
182 | *
183 | * @param key The key to search by
184 | * @param value The value to search by
185 | */
186 |
187 | }, {
188 | key: 'findBy',
189 | value: function findBy(key, value) {
190 | var urlParams = [key];
191 |
192 | if (value) {
193 | urlParams.push(value);
194 | }
195 |
196 | return this.get.apply(this, urlParams);
197 | }
198 | }]);
199 |
200 | return Crud;
201 | }(_request2.default);
202 |
203 | exports.default = Crud;
--------------------------------------------------------------------------------
/dist/core/core.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
8 | * The Caramel Core functionality of Rapid
9 | */
10 |
11 | var _axios = require('axios');
12 |
13 | var _axios2 = _interopRequireDefault(_axios);
14 |
15 | var _defaultsDeep = require('lodash/defaultsDeep');
16 |
17 | var _defaultsDeep2 = _interopRequireDefault(_defaultsDeep);
18 |
19 | var _defaults = require('./defaults');
20 |
21 | var _defaults2 = _interopRequireDefault(_defaults);
22 |
23 | var _debugger = require('./../debug/debugger');
24 |
25 | var _debugger2 = _interopRequireDefault(_debugger);
26 |
27 | var _logger = require('./../debug/logger');
28 |
29 | var _logger2 = _interopRequireDefault(_logger);
30 |
31 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
32 |
33 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
34 |
35 | var Core = function () {
36 | function Core(config) {
37 | _classCallCheck(this, Core);
38 |
39 | config = config || {};
40 |
41 | config = (0, _defaultsDeep2.default)(config, _defaults2.default);
42 |
43 | this.initialize(config);
44 | }
45 |
46 | /**
47 | * Set any config overrides in this method when extending
48 | */
49 |
50 |
51 | _createClass(Core, [{
52 | key: 'boot',
53 | value: function boot() {}
54 |
55 | /**
56 | * Setup the all of properties.
57 | */
58 |
59 | }, {
60 | key: 'initialize',
61 | value: function initialize(config) {
62 | this.config = config;
63 |
64 | this.initializeRoutes();
65 |
66 | this.boot();
67 |
68 | this.resetURLParams();
69 |
70 | this.fireSetters();
71 |
72 | this.initializeAPI();
73 |
74 | this.setCurrentRoute(this.config.defaultRoute);
75 |
76 | this.initializeDebugger();
77 |
78 | this.initializeLogger();
79 |
80 | this.resetRequestData();
81 |
82 | this.defineCustomRoutes();
83 | }
84 |
85 | /**
86 | * Fire the setters. This will make sure the routes are generated properly.
87 | * Consider if this is really even necessary
88 | */
89 |
90 | }, {
91 | key: 'fireSetters',
92 | value: function fireSetters() {
93 | var _this = this;
94 |
95 | ['baseURL', 'modelName', 'routeDelimeter', 'caseSensitive'].forEach(function (setter) {
96 | return _this[setter] = _this.config[setter];
97 | });
98 | }
99 |
100 | /**
101 | * Initialze the debugger if debug is set to true.
102 | */
103 |
104 | }, {
105 | key: 'initializeDebugger',
106 | value: function initializeDebugger() {
107 | this.debugger = this.config.debug ? new _debugger2.default(this) : false;
108 | }
109 |
110 | /**
111 | * Initialze the debugger if debug is set to true.
112 | */
113 |
114 | }, {
115 | key: 'initializeLogger',
116 | value: function initializeLogger() {
117 | this.logger = this.config.debug ? _logger2.default : false;
118 | }
119 |
120 | /**
121 | * Initialize the API.
122 | */
123 |
124 | }, {
125 | key: 'initializeAPI',
126 | value: function initializeAPI() {
127 | this.api = _axios2.default.create((0, _defaultsDeep2.default)({ baseURL: this.config.baseURL.replace(/\/$/, '') }, this.config.apiConfig));
128 | }
129 |
130 | /**
131 | * Initialize the routes.
132 | */
133 |
134 | }, {
135 | key: 'initializeRoutes',
136 | value: function initializeRoutes() {
137 | this.routes = {
138 | model: '',
139 | collection: '',
140 | any: ''
141 | };
142 | }
143 |
144 | /**
145 | * Set up the custom routes if we have any
146 | */
147 |
148 | }, {
149 | key: 'defineCustomRoutes',
150 | value: function defineCustomRoutes() {
151 | var _this2 = this;
152 |
153 | this.customRoutes = {};
154 |
155 | // if we have custom routes, set up a name:route mapping
156 | if (this.config.customRoutes.length) {
157 | this.config.customRoutes.forEach(function (route) {
158 | _this2.customRoutes[route.name] = route;
159 | });
160 | }
161 | }
162 |
163 | /**
164 | * Resets the request data
165 | */
166 |
167 | }, {
168 | key: 'resetRequestData',
169 | value: function resetRequestData() {
170 | this.requestData = {
171 | params: {},
172 | options: {}
173 | };
174 | }
175 |
176 | /**
177 | * Setters and Getters
178 | */
179 |
180 | }, {
181 | key: 'debug',
182 | set: function set(val) {
183 | if (this.config.debug) {
184 | this.logger.warn('debug mode must explicitly be turned on via the constructor in config.debug');
185 | }
186 | }
187 | }, {
188 | key: 'collection',
189 | get: function get() {
190 | this.setCurrentRoute('collection');
191 |
192 | return this;
193 | }
194 | }, {
195 | key: 'model',
196 | get: function get() {
197 | this.setCurrentRoute('model');
198 |
199 | return this;
200 | }
201 | }, {
202 | key: 'any',
203 | get: function get() {
204 | this.setCurrentRoute('any');
205 |
206 | return this;
207 | }
208 | }, {
209 | key: 'baseURL',
210 | set: function set(url) {
211 | this.config.baseURL = this.sanitizeUrl(url);
212 | this.initializeAPI();
213 | }
214 | }, {
215 | key: 'modelName',
216 | set: function set(val) {
217 | this.config.modelName = val;
218 | this.setRoutes();
219 | }
220 | }, {
221 | key: 'routeDelimeter',
222 | set: function set(val) {
223 | this.config.routeDelimeter = val;
224 | this.setRoutes();
225 | }
226 | }, {
227 | key: 'caseSensitive',
228 | set: function set(val) {
229 | this.config.caseSensitive = val;
230 | this.setRoutes();
231 | }
232 | }]);
233 |
234 | return Core;
235 | }();
236 |
237 | exports.default = Core;
--------------------------------------------------------------------------------
/demo/rapid/Core/Request.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The Re-Quest to find the API
3 | */
4 |
5 | import { isArray, defaultsDeep, set } from 'lodash';
6 | import Routes from './routes';
7 | import CustomRoute from './custom-route';
8 |
9 | class Request extends Routes {
10 | constructor (config) {
11 | super(config);
12 | }
13 |
14 | /**
15 | * Parse the request data prior to passing it to axios
16 | *
17 | * @param type The request type
18 | */
19 | parseRequestData (type) {
20 | const requestData = [];
21 | const { options } = this.requestData;
22 | let { params } = this.requestData;
23 |
24 | // axios handles the options differently for the request type
25 | if (['put', 'post', 'patch'].includes(type)) {
26 | params = defaultsDeep(params, this.config.globalParameters);
27 | requestData.push(params);
28 | requestData.push(options);
29 | } else {
30 | options.params = defaultsDeep(params, this.config.globalParameters);
31 | requestData.push(options);
32 | }
33 |
34 | return requestData;
35 | }
36 |
37 | /**
38 | * Make the request
39 | *
40 | * @param type The Request type
41 | * @param url The url
42 | */
43 | request (type, url) {
44 | type = type.toLowerCase();
45 |
46 | if (!this.isAllowedRequestType(type)) {
47 | return;
48 | }
49 |
50 | this.beforeRequest(type, url);
51 |
52 | if (this.config.debug) {
53 | return this.debugger.fakeRequest(type, url);
54 | }
55 |
56 | return new Promise((resolve, reject) => {
57 | this.api[type].call(this, this.sanitizeUrl(url), ...this.parseRequestData(type))
58 | .then((response) => {
59 | this.afterRequest(response);
60 |
61 | resolve(response);
62 | })
63 | .catch((error) => {
64 | this.onError(error);
65 |
66 | reject(error);
67 | });
68 | });
69 | }
70 |
71 | /**
72 | * Checks if is a valid request type
73 | *
74 | * @param type The request type
75 | */
76 | isAllowedRequestType (type) {
77 | if (!this.config.allowedRequestTypes.includes(type)) {
78 | if (this.config.debug) {
79 | this.logger.warn(`'${type}' is not included in allowedRequestTypes: [${this.config.allowedRequestTypes.join(', ')}]`);
80 | }
81 |
82 | return false;
83 | }
84 |
85 | return true;
86 | }
87 |
88 | /**
89 | * to build a request url
90 | */
91 | buildRequest (type, urlParams) {
92 | if (this.urlParams) {
93 | urlParams = this.urlParams.concat(urlParams);
94 | this.resetURLParams();
95 | }
96 |
97 | const url = isArray(urlParams) ? this.makeUrl(...urlParams) : this.makeUrl(urlParams);
98 |
99 | return this.request(type, url);
100 | }
101 |
102 | /**
103 | * Make a GET request
104 | *
105 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
106 | */
107 | get (...urlParams) {
108 | return this.buildRequest('get', urlParams);
109 | }
110 |
111 | /**
112 | * Make a POST request
113 | *
114 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
115 | */
116 | post (...urlParams) {
117 | return this.buildRequest('post', urlParams);
118 | }
119 |
120 | /**
121 | * Make a PUT request
122 | *
123 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
124 | */
125 | put (...urlParams) {
126 | return this.buildRequest('put', urlParams);
127 | }
128 |
129 | /**
130 | * Make a PATCH request
131 | *
132 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
133 | */
134 | patch (...urlParams) {
135 | return this.buildRequest('patch', urlParams);
136 | }
137 |
138 | /**
139 | * Make a HEAD request
140 | *
141 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
142 | */
143 | head (...urlParams) {
144 | return this.buildRequest('head', urlParams);
145 | }
146 |
147 | /**
148 | * Make a DELETE request
149 | *
150 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
151 | */
152 | delete (...urlParams) {
153 | return this.buildRequest('delete', urlParams);
154 | }
155 |
156 | /**
157 | * Custom Routes
158 | *
159 | * These can be defined and passed via the customRoutes config attribute.
160 | * This allows you to completely override Rapid's usual functionality
161 | * and use this more like a router.
162 | */
163 |
164 | /**
165 | * Make a request to a route via a given route name
166 | * The request type depends on the type of request defined in the route
167 | *
168 | * @param {string} name
169 | * @param {object} routeParams
170 | * @param {object} requestParams
171 | */
172 | route (name = '', routeParams = {}, requestParams = {}) {
173 | const route = this.getCustomRoute(name, routeParams);
174 |
175 | // if there are request params, set them
176 | if (Object.keys(requestParams).length !== 0) {
177 | this.withParams(requestParams);
178 | }
179 |
180 | return this.request(route.type, route.url);
181 | }
182 |
183 | /**
184 | * Get a CustomRoute via given name
185 | *
186 | * @param {string} name
187 | * @param {object} routeParams
188 | */
189 | getCustomRoute (name = '', routeParams = {}) {
190 | // if a route exists, return a new instance of CustomRoute
191 | if (Object.prototype.hasOwnProperty.call(this.customRoutes, name)) {
192 | return new CustomRoute(this.customRoutes[name], {
193 | routeParams,
194 | });
195 | }
196 |
197 | // to prevent having undefined
198 | return new CustomRoute();
199 | }
200 |
201 | /**
202 | * Generate a url to a custom defined route
203 | *
204 | * @param {string} name
205 | * @param {object} routeParams
206 | */
207 | generate (name = '', routeParams = {}) {
208 | return this.getCustomRoute(name, routeParams).url;
209 | }
210 |
211 | /**
212 | * Before, after, and error
213 | */
214 |
215 | /**
216 | * This is fired before the request
217 | */
218 | beforeRequest (type, url) {
219 | return this.config.beforeRequest(type, url);
220 | }
221 |
222 | /**
223 | * This is fired after each request
224 | */
225 | afterRequest (response) {
226 | this.resetRequestData();
227 | this.config.afterRequest(response);
228 | }
229 |
230 | /**
231 | * This is fired on a request error
232 | */
233 | onError (error) {
234 | this.resetRequestData();
235 | this.config.onError(error);
236 | }
237 |
238 | /**
239 | * Params and Options
240 | */
241 |
242 | /**
243 | * Send data and options with the request
244 | *
245 | * @param data An object of params: {}, options: {}
246 | */
247 | withData (data = {}) {
248 | this.requestData = defaultsDeep(data, this.requestData);
249 |
250 | return this;
251 | }
252 |
253 | /**
254 | * Send params with the request
255 | *
256 | * @param params An object of params
257 | */
258 | withParams (params = {}) {
259 | set(this.requestData, 'params', params);
260 |
261 | return this;
262 | }
263 |
264 | /**
265 | * Send a single param with the request
266 | *
267 | * @param key The key name
268 | * @param value The value
269 | */
270 | withParam (key, value) {
271 | set(this.requestData, `params.${key}`, value);
272 |
273 | return this;
274 | }
275 |
276 | /**
277 | * Send options with the request
278 | *
279 | * @param options An object of options
280 | */
281 | withOptions (options = {}) {
282 | set(this.requestData, 'options', options);
283 |
284 | return this;
285 | }
286 |
287 | /**
288 | * Send a single option with the request
289 | *
290 | * @param key The key name
291 | * @param value The value
292 | */
293 | withOption (key, value) {
294 | set(this.requestData, `options.${key}`, value);
295 |
296 | return this;
297 | }
298 | }
299 |
300 | export default Request;
301 |
--------------------------------------------------------------------------------
/src/core/request.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The Re-Quest to find the API
3 | */
4 |
5 | import isArray from 'lodash/isArray';
6 | import defaultsDeep from 'lodash/defaultsDeep';
7 | import set from 'lodash/set';
8 | import Routes from './routes';
9 | import CustomRoute from './custom-route';
10 |
11 | class Request extends Routes {
12 | constructor (config) {
13 | super(config);
14 | }
15 |
16 | /**
17 | * Parse the request data prior to passing it to axios
18 | *
19 | * @param type The request type
20 | */
21 | parseRequestData (type) {
22 | const requestData = [];
23 | const { options } = this.requestData;
24 | let { params } = this.requestData;
25 |
26 | // axios handles the options differently for the request type
27 | if (['put', 'post', 'patch'].includes(type)) {
28 | params = defaultsDeep(params, this.config.globalParameters);
29 | requestData.push(params);
30 | requestData.push(options);
31 | } else {
32 | options.params = defaultsDeep(params, this.config.globalParameters);
33 | requestData.push(options);
34 | }
35 |
36 | return requestData;
37 | }
38 |
39 | /**
40 | * Make the request
41 | *
42 | * @param type The Request type
43 | * @param url The url
44 | */
45 | request (type, url) {
46 | type = type.toLowerCase();
47 |
48 | if (!this.isAllowedRequestType(type)) {
49 | return;
50 | }
51 |
52 | this.beforeRequest(type, url);
53 |
54 | if (this.config.debug) {
55 | return this.debugger.fakeRequest(type, url);
56 | }
57 |
58 | return new Promise((resolve, reject) => {
59 | this.api[type].call(this, this.sanitizeUrl(url), ...this.parseRequestData(type))
60 | .then((response) => {
61 | this.afterRequest(response);
62 |
63 | resolve(response);
64 | })
65 | .catch((error) => {
66 | this.onError(error);
67 |
68 | reject(error);
69 | });
70 | });
71 | }
72 |
73 | /**
74 | * Checks if is a valid request type
75 | *
76 | * @param type The request type
77 | */
78 | isAllowedRequestType (type) {
79 | if (!this.config.allowedRequestTypes.includes(type)) {
80 | if (this.config.debug) {
81 | this.logger.warn(`'${type}' is not included in allowedRequestTypes: [${this.config.allowedRequestTypes.join(', ')}]`);
82 | }
83 |
84 | return false;
85 | }
86 |
87 | return true;
88 | }
89 |
90 | /**
91 | * to build a request url
92 | */
93 | buildRequest (type, urlParams) {
94 | if (this.urlParams) {
95 | urlParams = this.urlParams.concat(urlParams);
96 | this.resetURLParams();
97 | }
98 |
99 | const url = isArray(urlParams) ? this.makeUrl(...urlParams) : this.makeUrl(urlParams);
100 |
101 | return this.request(type, url);
102 | }
103 |
104 | /**
105 | * Make a GET request
106 | *
107 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
108 | */
109 | get (...urlParams) {
110 | return this.buildRequest('get', urlParams);
111 | }
112 |
113 | /**
114 | * Make a POST request
115 | *
116 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
117 | */
118 | post (...urlParams) {
119 | return this.buildRequest('post', urlParams);
120 | }
121 |
122 | /**
123 | * Make a PUT request
124 | *
125 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
126 | */
127 | put (...urlParams) {
128 | return this.buildRequest('put', urlParams);
129 | }
130 |
131 | /**
132 | * Make a PATCH request
133 | *
134 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
135 | */
136 | patch (...urlParams) {
137 | return this.buildRequest('patch', urlParams);
138 | }
139 |
140 | /**
141 | * Make a HEAD request
142 | *
143 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
144 | */
145 | head (...urlParams) {
146 | return this.buildRequest('head', urlParams);
147 | }
148 |
149 | /**
150 | * Make a DELETE request
151 | *
152 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
153 | */
154 | delete (...urlParams) {
155 | return this.buildRequest('delete', urlParams);
156 | }
157 |
158 | /**
159 | * Custom Routes
160 | *
161 | * These can be defined and passed via the customRoutes config attribute.
162 | * This allows you to completely override Rapid's usual functionality
163 | * and use this more like a router.
164 | */
165 |
166 | /**
167 | * Make a request to a route via a given route name
168 | * The request type depends on the type of request defined in the route
169 | *
170 | * @param {string} name
171 | * @param {object} routeParams
172 | * @param {object} requestParams
173 | */
174 | route (name = '', routeParams = {}, requestParams = {}) {
175 | const route = this.getCustomRoute(name, routeParams);
176 |
177 | // if there are request params, set them
178 | if (Object.keys(requestParams).length !== 0) {
179 | this.withParams(requestParams);
180 | }
181 |
182 | return this.request(route.type, route.url);
183 | }
184 |
185 | /**
186 | * Get a CustomRoute via given name
187 | *
188 | * @param {string} name
189 | * @param {object} routeParams
190 | */
191 | getCustomRoute (name = '', routeParams = {}) {
192 | // if a route exists, return a new instance of CustomRoute
193 | if (Object.prototype.hasOwnProperty.call(this.customRoutes, name)) {
194 | return new CustomRoute(this.customRoutes[name], {
195 | routeParams,
196 | });
197 | }
198 |
199 | // to prevent having undefined
200 | return new CustomRoute();
201 | }
202 |
203 | /**
204 | * Generate a url to a custom defined route
205 | * This applies the baseURL and the trailing slash config
206 | * as well
207 | *
208 | * @param {string} name
209 | * @param {object} routeParams
210 | */
211 | generate (name = '', routeParams = {}) {
212 | const { url } = this.getCustomRoute(name, routeParams);
213 |
214 | return url !== '' ? this.makeUrl(this.config.baseURL, url) : '';
215 | }
216 |
217 | /**
218 | * Before, after, and error
219 | */
220 |
221 | /**
222 | * This is fired before the request
223 | */
224 | beforeRequest (type, url) {
225 | return this.config.beforeRequest(type, url);
226 | }
227 |
228 | /**
229 | * This is fired after each request
230 | */
231 | afterRequest (response) {
232 | this.resetRequestData();
233 | this.config.afterRequest(response);
234 | }
235 |
236 | /**
237 | * This is fired on a request error
238 | */
239 | onError (error) {
240 | this.resetRequestData();
241 | this.config.onError(error);
242 | }
243 |
244 | /**
245 | * Params and Options
246 | */
247 |
248 | /**
249 | * Send data and options with the request
250 | *
251 | * @param data An object of params: {}, options: {}
252 | */
253 | withData (data = {}) {
254 | this.requestData = defaultsDeep(data, this.requestData);
255 |
256 | return this;
257 | }
258 |
259 | /**
260 | * Send params with the request
261 | *
262 | * @param params An object of params
263 | */
264 | withParams (params = {}) {
265 | set(this.requestData, 'params', params);
266 |
267 | return this;
268 | }
269 |
270 | /**
271 | * Send a single param with the request
272 | *
273 | * @param key The key name
274 | * @param value The value
275 | */
276 | withParam (key, value) {
277 | set(this.requestData, `params.${key}`, value);
278 |
279 | return this;
280 | }
281 |
282 | /**
283 | * Send options with the request
284 | *
285 | * @param options An object of options
286 | */
287 | withOptions (options = {}) {
288 | set(this.requestData, 'options', options);
289 |
290 | return this;
291 | }
292 |
293 | /**
294 | * Send a single option with the request
295 | *
296 | * @param key The key name
297 | * @param value The value
298 | */
299 | withOption (key, value) {
300 | set(this.requestData, `options.${key}`, value);
301 |
302 | return this;
303 | }
304 | }
305 |
306 | export default Request;
307 |
--------------------------------------------------------------------------------
/demo/webpack.config.js:
--------------------------------------------------------------------------------
1 | let path = require('path');
2 | let glob = require('glob');
3 | let webpack = require('webpack');
4 | let Mix = require('laravel-mix').config;
5 | let webpackPlugins = require('laravel-mix').plugins;
6 |
7 | /*
8 | |--------------------------------------------------------------------------
9 | | Mix Initialization
10 | |--------------------------------------------------------------------------
11 | |
12 | | As our first step, we'll require the project's Laravel Mix file
13 | | and record the user's requested compilation and build steps.
14 | | Once those steps have been recorded, we may get to work.
15 | |
16 | */
17 |
18 | Mix.initialize();
19 |
20 |
21 |
22 | /*
23 | |--------------------------------------------------------------------------
24 | | Webpack Context
25 | |--------------------------------------------------------------------------
26 | |
27 | | This prop will determine the appropriate context, when running Webpack.
28 | | Since you have the option of publishing this webpack.config.js file
29 | | to your project root, we will dynamically set the path for you.
30 | |
31 | */
32 |
33 | module.exports.context = Mix.Paths.root();
34 |
35 |
36 |
37 | /*
38 | |--------------------------------------------------------------------------
39 | | Webpack Entry
40 | |--------------------------------------------------------------------------
41 | |
42 | | We'll first specify the entry point for Webpack. By default, we'll
43 | | assume a single bundled file, but you may call Mix.extract()
44 | | to make a separate bundle specifically for vendor libraries.
45 | |
46 | */
47 |
48 | module.exports.entry = Mix.entry().get();
49 |
50 |
51 |
52 | /*
53 | |--------------------------------------------------------------------------
54 | | Webpack Output
55 | |--------------------------------------------------------------------------
56 | |
57 | | Webpack naturally requires us to specify our desired output path and
58 | | file name. We'll simply echo what you passed to with Mix.js().
59 | | Note that, for Mix.version(), we'll properly hash the file.
60 | |
61 | */
62 |
63 | module.exports.output = Mix.output();
64 |
65 |
66 |
67 | /*
68 | |--------------------------------------------------------------------------
69 | | Rules
70 | |--------------------------------------------------------------------------
71 | |
72 | | Webpack rules allow us to register any number of loaders and options.
73 | | Out of the box, we'll provide a handful to get you up and running
74 | | as quickly as possible, though feel free to add to this list.
75 | |
76 | */
77 |
78 | let plugins = [];
79 |
80 | if (Mix.options.extractVueStyles) {
81 | var vueExtractTextPlugin = Mix.vueExtractTextPlugin();
82 |
83 | plugins.push(vueExtractTextPlugin);
84 | }
85 |
86 | let rules = [
87 | {
88 | test: /\.vue$/,
89 | loader: 'vue-loader',
90 | options: {
91 | loaders: Mix.options.extractVueStyles ? {
92 | js: 'babel-loader' + Mix.babelConfig(),
93 | scss: vueExtractTextPlugin.extract({
94 | use: 'css-loader!sass-loader',
95 | fallback: 'vue-style-loader'
96 | }),
97 | sass: vueExtractTextPlugin.extract({
98 | use: 'css-loader!sass-loader?indentedSyntax',
99 | fallback: 'vue-style-loader'
100 | }),
101 | stylus: vueExtractTextPlugin.extract({
102 | use: 'css-loader!stylus-loader?paths[]=node_modules',
103 | fallback: 'vue-style-loader'
104 | }),
105 | css: vueExtractTextPlugin.extract({
106 | use: 'css-loader',
107 | fallback: 'vue-style-loader'
108 | })
109 | }: {
110 | js: 'babel-loader' + Mix.babelConfig(),
111 | scss: 'vue-style-loader!css-loader!sass-loader',
112 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax',
113 | stylus: 'vue-style-loader!css-loader!stylus-loader?paths[]=node_modules'
114 | },
115 |
116 | postcss: Mix.options.postCss
117 | }
118 | },
119 |
120 | {
121 | test: /\.jsx?$/,
122 | exclude: /(node_modules|bower_components)/,
123 | loader: 'babel-loader' + Mix.babelConfig()
124 | },
125 |
126 | {
127 | test: /\.css$/,
128 | loaders: ['style-loader', 'css-loader']
129 | },
130 |
131 | {
132 | test: /\.s[ac]ss$/,
133 | include: /node_modules/,
134 | loaders: ['style-loader', 'css-loader', 'sass-loader']
135 | },
136 |
137 | {
138 | test: /\.html$/,
139 | loaders: ['html-loader']
140 | },
141 |
142 | {
143 | test: /\.(png|jpe?g|gif)$/,
144 | loaders: [
145 | {
146 | loader: 'file-loader',
147 | options: {
148 | name: path => {
149 | if (! /node_modules|bower_components/.test(path)) {
150 | return 'images/[name].[ext]?[hash]';
151 | }
152 |
153 | return 'images/vendor/' + path
154 | .replace(/\\/g, '/')
155 | .replace(
156 | /((.*(node_modules|bower_components))|images|image|img|assets)\//g, ''
157 | ) + '?[hash]';
158 | },
159 | publicPath: Mix.options.resourceRoot
160 | }
161 | },
162 | 'img-loader'
163 | ]
164 | },
165 |
166 | {
167 | test: /\.(woff2?|ttf|eot|svg|otf)$/,
168 | loader: 'file-loader',
169 | options: {
170 | name: path => {
171 | if (! /node_modules|bower_components/.test(path)) {
172 | return 'fonts/[name].[ext]?[hash]';
173 | }
174 |
175 | return 'fonts/vendor/' + path
176 | .replace(/\\/g, '/')
177 | .replace(
178 | /((.*(node_modules|bower_components))|fonts|font|assets)\//g, ''
179 | ) + '?[hash]';
180 | },
181 | publicPath: Mix.options.resourceRoot
182 | }
183 | },
184 |
185 | {
186 | test: /\.(cur|ani)$/,
187 | loader: 'file-loader',
188 | options: {
189 | name: '[name].[ext]?[hash]',
190 | publicPath: Mix.options.resourceRoot
191 | }
192 | }
193 | ];
194 |
195 | if (Mix.preprocessors) {
196 | Mix.preprocessors.forEach(preprocessor => {
197 | rules.push(preprocessor.rules());
198 |
199 | plugins.push(preprocessor.extractPlugin);
200 | });
201 | }
202 |
203 | module.exports.module = { rules };
204 |
205 |
206 |
207 | /*
208 | |--------------------------------------------------------------------------
209 | | Resolve
210 | |--------------------------------------------------------------------------
211 | |
212 | | Here, we may set any options/aliases that affect Webpack's resolving
213 | | of modules. To begin, we will provide the necessary Vue alias to
214 | | load the Vue common library. You may delete this, if needed.
215 | |
216 | */
217 |
218 | module.exports.resolve = {
219 | extensions: ['*', '.js', '.jsx', '.vue'],
220 |
221 | alias: {
222 | 'vue$': 'vue/dist/vue.common.js'
223 | }
224 | };
225 |
226 |
227 |
228 | /*
229 | |--------------------------------------------------------------------------
230 | | Stats
231 | |--------------------------------------------------------------------------
232 | |
233 | | By default, Webpack spits a lot of information out to the terminal,
234 | | each you time you compile. Let's keep things a bit more minimal
235 | | and hide a few of those bits and pieces. Adjust as you wish.
236 | |
237 | */
238 |
239 | module.exports.stats = {
240 | hash: false,
241 | version: false,
242 | timings: false,
243 | children: false,
244 | errors: false
245 | };
246 |
247 | process.noDeprecation = true;
248 |
249 | module.exports.performance = { hints: false };
250 |
251 |
252 |
253 | /*
254 | |--------------------------------------------------------------------------
255 | | Devtool
256 | |--------------------------------------------------------------------------
257 | |
258 | | Sourcemaps allow us to access our original source code within the
259 | | browser, even if we're serving a bundled script or stylesheet.
260 | | You may activate sourcemaps, by adding Mix.sourceMaps().
261 | |
262 | */
263 |
264 | module.exports.devtool = Mix.options.sourcemaps;
265 |
266 |
267 |
268 | /*
269 | |--------------------------------------------------------------------------
270 | | Webpack Dev Server Configuration
271 | |--------------------------------------------------------------------------
272 | |
273 | | If you want to use that flashy hot module replacement feature, then
274 | | we've got you covered. Here, we'll set some basic initial config
275 | | for the Node server. You very likely won't want to edit this.
276 | |
277 | */
278 | module.exports.devServer = {
279 | historyApiFallback: true,
280 | noInfo: true,
281 | compress: true,
282 | quiet: true
283 | };
284 |
285 |
286 |
287 | /*
288 | |--------------------------------------------------------------------------
289 | | Plugins
290 | |--------------------------------------------------------------------------
291 | |
292 | | Lastly, we'll register a number of plugins to extend and configure
293 | | Webpack. To get you started, we've included a handful of useful
294 | | extensions, for versioning, OS notifications, and much more.
295 | |
296 | */
297 |
298 | plugins.push(
299 | new webpack.ProvidePlugin(Mix.autoload || {}),
300 |
301 | new webpackPlugins.FriendlyErrorsWebpackPlugin({ clearConsole: Mix.options.clearConsole }),
302 |
303 | new webpackPlugins.StatsWriterPlugin({
304 | filename: 'mix-manifest.json',
305 | transform: Mix.manifest.transform.bind(Mix.manifest),
306 | }),
307 |
308 | new webpack.LoaderOptionsPlugin({
309 | minimize: Mix.inProduction,
310 | options: {
311 | postcss: Mix.options.postCss,
312 | context: __dirname,
313 | output: { path: './' }
314 | }
315 | })
316 | );
317 |
318 | if (Mix.browserSync) {
319 | plugins.push(
320 | new webpackPlugins.BrowserSyncPlugin(
321 | Object.assign({
322 | host: 'localhost',
323 | port: 3000,
324 | proxy: 'app.dev',
325 | files: [
326 | 'app/**/*.php',
327 | 'resources/views/**/*.php',
328 | 'public/js/**/*.js',
329 | 'public/css/**/*.css'
330 | ]
331 | }, Mix.browserSync),
332 | {
333 | reload: false
334 | }
335 | )
336 | );
337 | }
338 |
339 | if (Mix.options.notifications) {
340 | plugins.push(
341 | new webpackPlugins.WebpackNotifierPlugin({
342 | title: 'Laravel Mix',
343 | alwaysNotify: true,
344 | contentImage: Mix.Paths.root('node_modules/laravel-mix/icons/laravel.png')
345 | })
346 | );
347 | }
348 |
349 | if (Mix.copy) {
350 | Mix.copy.forEach(copy => {
351 | plugins.push(
352 | new webpackPlugins.CopyWebpackPlugin([copy])
353 | );
354 | });
355 | }
356 |
357 | if (Mix.entry().hasExtractions()) {
358 | plugins.push(
359 | new webpack.optimize.CommonsChunkPlugin({
360 | names: Mix.entry().getExtractions(),
361 | minChunks: Infinity
362 | })
363 | );
364 | }
365 |
366 | if (Mix.options.versioning) {
367 | plugins.push(
368 | new webpack[Mix.inProduction ? 'HashedModuleIdsPlugin': 'NamedModulesPlugin'](),
369 | new webpackPlugins.WebpackChunkHashPlugin()
370 | );
371 | }
372 |
373 | if (Mix.options.purifyCss) {
374 | let PurifyCSSPlugin = require('purifycss-webpack');
375 |
376 | // By default, we'll scan all Blade and Vue files in our project.
377 | let paths = glob.sync(Mix.Paths.root('resources/views/**/*.blade.php')).concat(
378 | Mix.entry().scripts.reduce((carry, js) => {
379 | return carry.concat(glob.sync(js.base + '/**/*.vue'));
380 | }, [])
381 | );
382 |
383 | plugins.push(new PurifyCSSPlugin(
384 | Object.assign({ paths }, Mix.options.purifyCss, { minimize: Mix.inProduction })
385 | ));
386 | }
387 |
388 | if (Mix.inProduction) {
389 | plugins.push(
390 | new webpack.DefinePlugin({
391 | 'process.env': {
392 | NODE_ENV: '"production"'
393 | }
394 | })
395 | );
396 |
397 | if (Mix.options.uglify) {
398 | plugins.push(
399 | new webpack.optimize.UglifyJsPlugin(Mix.options.uglify)
400 | );
401 | }
402 | }
403 |
404 | plugins.push(
405 | new webpackPlugins.WebpackOnBuildPlugin(
406 | stats => global.events.fire('build', stats)
407 | )
408 | );
409 |
410 | if (! Mix.entry().hasScripts()) {
411 | plugins.push(new webpackPlugins.MockEntryPlugin(Mix.output().path));
412 | }
413 |
414 | module.exports.plugins = plugins;
415 |
416 |
417 |
418 | /*
419 | |--------------------------------------------------------------------------
420 | | Mix Finalizing
421 | |--------------------------------------------------------------------------
422 | |
423 | | Now that we've declared the entirety of our Webpack configuration, the
424 | | final step is to scan for any custom configuration in the Mix file.
425 | | If mix.webpackConfig() is called, we'll merge it in, and build!
426 | |
427 | */
428 |
429 | if (Mix.webpackConfig) {
430 | module.exports = require('webpack-merge').smart(
431 | module.exports, Mix.webpackConfig
432 | );
433 | }
434 |
--------------------------------------------------------------------------------
/dist/core/request.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8 |
9 | var _isArray = require('lodash/isArray');
10 |
11 | var _isArray2 = _interopRequireDefault(_isArray);
12 |
13 | var _defaultsDeep = require('lodash/defaultsDeep');
14 |
15 | var _defaultsDeep2 = _interopRequireDefault(_defaultsDeep);
16 |
17 | var _set = require('lodash/set');
18 |
19 | var _set2 = _interopRequireDefault(_set);
20 |
21 | var _routes = require('./routes');
22 |
23 | var _routes2 = _interopRequireDefault(_routes);
24 |
25 | var _customRoute = require('./custom-route');
26 |
27 | var _customRoute2 = _interopRequireDefault(_customRoute);
28 |
29 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
30 |
31 | function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
32 |
33 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
34 |
35 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
36 |
37 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
38 | * The Re-Quest to find the API
39 | */
40 |
41 | var Request = function (_Routes) {
42 | _inherits(Request, _Routes);
43 |
44 | function Request(config) {
45 | _classCallCheck(this, Request);
46 |
47 | return _possibleConstructorReturn(this, (Request.__proto__ || Object.getPrototypeOf(Request)).call(this, config));
48 | }
49 |
50 | /**
51 | * Parse the request data prior to passing it to axios
52 | *
53 | * @param type The request type
54 | */
55 |
56 |
57 | _createClass(Request, [{
58 | key: 'parseRequestData',
59 | value: function parseRequestData(type) {
60 | var requestData = [];
61 | var options = this.requestData.options;
62 | var params = this.requestData.params;
63 |
64 | // axios handles the options differently for the request type
65 |
66 | if (['put', 'post', 'patch'].includes(type)) {
67 | params = (0, _defaultsDeep2.default)(params, this.config.globalParameters);
68 | requestData.push(params);
69 | requestData.push(options);
70 | } else {
71 | options.params = (0, _defaultsDeep2.default)(params, this.config.globalParameters);
72 | requestData.push(options);
73 | }
74 |
75 | return requestData;
76 | }
77 |
78 | /**
79 | * Make the request
80 | *
81 | * @param type The Request type
82 | * @param url The url
83 | */
84 |
85 | }, {
86 | key: 'request',
87 | value: function request(type, url) {
88 | var _this2 = this;
89 |
90 | type = type.toLowerCase();
91 |
92 | if (!this.isAllowedRequestType(type)) {
93 | return;
94 | }
95 |
96 | this.beforeRequest(type, url);
97 |
98 | if (this.config.debug) {
99 | return this.debugger.fakeRequest(type, url);
100 | }
101 |
102 | return new Promise(function (resolve, reject) {
103 | var _api$type;
104 |
105 | (_api$type = _this2.api[type]).call.apply(_api$type, [_this2, _this2.sanitizeUrl(url)].concat(_toConsumableArray(_this2.parseRequestData(type)))).then(function (response) {
106 | _this2.afterRequest(response);
107 |
108 | resolve(response);
109 | }).catch(function (error) {
110 | _this2.onError(error);
111 |
112 | reject(error);
113 | });
114 | });
115 | }
116 |
117 | /**
118 | * Checks if is a valid request type
119 | *
120 | * @param type The request type
121 | */
122 |
123 | }, {
124 | key: 'isAllowedRequestType',
125 | value: function isAllowedRequestType(type) {
126 | if (!this.config.allowedRequestTypes.includes(type)) {
127 | if (this.config.debug) {
128 | this.logger.warn('\'' + type + '\' is not included in allowedRequestTypes: [' + this.config.allowedRequestTypes.join(', ') + ']');
129 | }
130 |
131 | return false;
132 | }
133 |
134 | return true;
135 | }
136 |
137 | /**
138 | * to build a request url
139 | */
140 |
141 | }, {
142 | key: 'buildRequest',
143 | value: function buildRequest(type, urlParams) {
144 | if (this.urlParams) {
145 | urlParams = this.urlParams.concat(urlParams);
146 | this.resetURLParams();
147 | }
148 |
149 | var url = (0, _isArray2.default)(urlParams) ? this.makeUrl.apply(this, _toConsumableArray(urlParams)) : this.makeUrl(urlParams);
150 |
151 | return this.request(type, url);
152 | }
153 |
154 | /**
155 | * Make a GET request
156 | *
157 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
158 | */
159 |
160 | }, {
161 | key: 'get',
162 | value: function get() {
163 | for (var _len = arguments.length, urlParams = Array(_len), _key = 0; _key < _len; _key++) {
164 | urlParams[_key] = arguments[_key];
165 | }
166 |
167 | return this.buildRequest('get', urlParams);
168 | }
169 |
170 | /**
171 | * Make a POST request
172 | *
173 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
174 | */
175 |
176 | }, {
177 | key: 'post',
178 | value: function post() {
179 | for (var _len2 = arguments.length, urlParams = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
180 | urlParams[_key2] = arguments[_key2];
181 | }
182 |
183 | return this.buildRequest('post', urlParams);
184 | }
185 |
186 | /**
187 | * Make a PUT request
188 | *
189 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
190 | */
191 |
192 | }, {
193 | key: 'put',
194 | value: function put() {
195 | for (var _len3 = arguments.length, urlParams = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
196 | urlParams[_key3] = arguments[_key3];
197 | }
198 |
199 | return this.buildRequest('put', urlParams);
200 | }
201 |
202 | /**
203 | * Make a PATCH request
204 | *
205 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
206 | */
207 |
208 | }, {
209 | key: 'patch',
210 | value: function patch() {
211 | for (var _len4 = arguments.length, urlParams = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
212 | urlParams[_key4] = arguments[_key4];
213 | }
214 |
215 | return this.buildRequest('patch', urlParams);
216 | }
217 |
218 | /**
219 | * Make a HEAD request
220 | *
221 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
222 | */
223 |
224 | }, {
225 | key: 'head',
226 | value: function head() {
227 | for (var _len5 = arguments.length, urlParams = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
228 | urlParams[_key5] = arguments[_key5];
229 | }
230 |
231 | return this.buildRequest('head', urlParams);
232 | }
233 |
234 | /**
235 | * Make a DELETE request
236 | *
237 | * @param urlParams The url params to be concatenated to the urlParams (See buildRequest)
238 | */
239 |
240 | }, {
241 | key: 'delete',
242 | value: function _delete() {
243 | for (var _len6 = arguments.length, urlParams = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
244 | urlParams[_key6] = arguments[_key6];
245 | }
246 |
247 | return this.buildRequest('delete', urlParams);
248 | }
249 |
250 | /**
251 | * Custom Routes
252 | *
253 | * These can be defined and passed via the customRoutes config attribute.
254 | * This allows you to completely override Rapid's usual functionality
255 | * and use this more like a router.
256 | */
257 |
258 | /**
259 | * Make a request to a route via a given route name
260 | * The request type depends on the type of request defined in the route
261 | *
262 | * @param {string} name
263 | * @param {object} routeParams
264 | * @param {object} requestParams
265 | */
266 |
267 | }, {
268 | key: 'route',
269 | value: function route() {
270 | var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
271 | var routeParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
272 | var requestParams = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
273 |
274 | var route = this.getCustomRoute(name, routeParams);
275 |
276 | // if there are request params, set them
277 | if (Object.keys(requestParams).length !== 0) {
278 | this.withParams(requestParams);
279 | }
280 |
281 | return this.request(route.type, route.url);
282 | }
283 |
284 | /**
285 | * Get a CustomRoute via given name
286 | *
287 | * @param {string} name
288 | * @param {object} routeParams
289 | */
290 |
291 | }, {
292 | key: 'getCustomRoute',
293 | value: function getCustomRoute() {
294 | var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
295 | var routeParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
296 |
297 | // if a route exists, return a new instance of CustomRoute
298 | if (Object.prototype.hasOwnProperty.call(this.customRoutes, name)) {
299 | return new _customRoute2.default(this.customRoutes[name], {
300 | routeParams: routeParams
301 | });
302 | }
303 |
304 | // to prevent having undefined
305 | return new _customRoute2.default();
306 | }
307 |
308 | /**
309 | * Generate a url to a custom defined route
310 | * This applies the baseURL and the trailing slash config
311 | * as well
312 | *
313 | * @param {string} name
314 | * @param {object} routeParams
315 | */
316 |
317 | }, {
318 | key: 'generate',
319 | value: function generate() {
320 | var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
321 | var routeParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
322 |
323 | var _getCustomRoute = this.getCustomRoute(name, routeParams),
324 | url = _getCustomRoute.url;
325 |
326 | return url !== '' ? this.makeUrl(this.config.baseURL, url) : '';
327 | }
328 |
329 | /**
330 | * Before, after, and error
331 | */
332 |
333 | /**
334 | * This is fired before the request
335 | */
336 |
337 | }, {
338 | key: 'beforeRequest',
339 | value: function beforeRequest(type, url) {
340 | return this.config.beforeRequest(type, url);
341 | }
342 |
343 | /**
344 | * This is fired after each request
345 | */
346 |
347 | }, {
348 | key: 'afterRequest',
349 | value: function afterRequest(response) {
350 | this.resetRequestData();
351 | this.config.afterRequest(response);
352 | }
353 |
354 | /**
355 | * This is fired on a request error
356 | */
357 |
358 | }, {
359 | key: 'onError',
360 | value: function onError(error) {
361 | this.resetRequestData();
362 | this.config.onError(error);
363 | }
364 |
365 | /**
366 | * Params and Options
367 | */
368 |
369 | /**
370 | * Send data and options with the request
371 | *
372 | * @param data An object of params: {}, options: {}
373 | */
374 |
375 | }, {
376 | key: 'withData',
377 | value: function withData() {
378 | var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
379 |
380 | this.requestData = (0, _defaultsDeep2.default)(data, this.requestData);
381 |
382 | return this;
383 | }
384 |
385 | /**
386 | * Send params with the request
387 | *
388 | * @param params An object of params
389 | */
390 |
391 | }, {
392 | key: 'withParams',
393 | value: function withParams() {
394 | var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
395 |
396 | (0, _set2.default)(this.requestData, 'params', params);
397 |
398 | return this;
399 | }
400 |
401 | /**
402 | * Send a single param with the request
403 | *
404 | * @param key The key name
405 | * @param value The value
406 | */
407 |
408 | }, {
409 | key: 'withParam',
410 | value: function withParam(key, value) {
411 | (0, _set2.default)(this.requestData, 'params.' + key, value);
412 |
413 | return this;
414 | }
415 |
416 | /**
417 | * Send options with the request
418 | *
419 | * @param options An object of options
420 | */
421 |
422 | }, {
423 | key: 'withOptions',
424 | value: function withOptions() {
425 | var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
426 |
427 | (0, _set2.default)(this.requestData, 'options', options);
428 |
429 | return this;
430 | }
431 |
432 | /**
433 | * Send a single option with the request
434 | *
435 | * @param key The key name
436 | * @param value The value
437 | */
438 |
439 | }, {
440 | key: 'withOption',
441 | value: function withOption(key, value) {
442 | (0, _set2.default)(this.requestData, 'options.' + key, value);
443 |
444 | return this;
445 | }
446 | }]);
447 |
448 | return Request;
449 | }(_routes2.default);
450 |
451 | exports.default = Request;
--------------------------------------------------------------------------------