├── .gitignore
├── .flowconfig
├── .babelrc
├── src
├── index.js
├── reducers
│ ├── index.js
│ ├── api.js
│ ├── domain.js
│ └── network.js
├── common
│ └── actions
│ │ └── index.js
├── actions
│ └── index.js
├── helpers
│ └── api.js
└── swagger.js
├── __tests__
└── index.js
├── html
└── index-dev.html
├── lib
├── reducers
│ ├── index.js
│ ├── api.js
│ ├── domain.js
│ └── network.js
├── index.js
├── common
│ └── actions
│ │ └── index.js
├── actions
│ └── index.js
├── helpers
│ └── api.js
└── swagger.js
├── .eslintrc
├── LICENSE
├── package.json
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /build/app
3 |
--------------------------------------------------------------------------------
/.flowconfig:
--------------------------------------------------------------------------------
1 | [ignore]
2 | .*/node_modules/.*
3 | [include]
4 |
5 | [libs]
6 |
7 | [options]
8 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "transform-runtime",
4 | "transform-object-rest-spread",
5 | ["babel-plugin-root-import", { "rootPathSuffix": "src" }]
6 | ],
7 | "presets": ["env"]
8 | }
9 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import * as Action from '~/actions';
2 | import * as Helper from '~/helpers/api';
3 | import Reducer from '~/reducers';
4 | export default {
5 | Action,
6 | Helper,
7 | Reducer,
8 | };
9 |
--------------------------------------------------------------------------------
/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import api from './api';
2 | import network from './network';
3 | import domain from './domain';
4 |
5 | export default {
6 | domain,
7 | api,
8 | network,
9 | };
10 |
--------------------------------------------------------------------------------
/__tests__/index.js:
--------------------------------------------------------------------------------
1 | import {double} from 'helpers/weightCalculation';
2 | import {total} from 'helpers/priceCalculation';
3 | test('total', () => {
4 | expect(total(2 * 100, 0.8)).toBe(160);
5 | expect(double(100)).toBe(200);
6 | });
7 |
--------------------------------------------------------------------------------
/html/index-dev.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 | babel-react-rollup-starter
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/reducers/api.js:
--------------------------------------------------------------------------------
1 | export default function api(
2 | state = { protocol: "http", contentType: "", headers: {} },
3 | action
4 | ) {
5 | switch (action.type) {
6 | case "API:SET_BASE_HEADERS":
7 | return { ...state, headers: action.payload.headers };
8 | case "API:SET_SWAGGER":
9 | return { ...state, ...action.payload };
10 | case "API:SET_PROTOCOL":
11 | return { ...state, protocol: action.payload };
12 | }
13 | return state;
14 | }
15 |
--------------------------------------------------------------------------------
/src/reducers/domain.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | export default function domain(state = {}, action) {
3 | let idsRegexResult = /^(.+)S_BY_ID$/.exec(_.get(action, 'meta.data'));
4 |
5 | switch (true) {
6 | case idsRegexResult != null:
7 | let relatedIdsName = _.camelCase(idsRegexResult[1]) + 'sById';
8 | let newObjectWithIds = {};
9 | newObjectWithIds[relatedIdsName] = action.payload;
10 |
11 | return { ...state, ...newObjectWithIds };
12 | }
13 | return state;
14 | }
15 |
--------------------------------------------------------------------------------
/src/reducers/network.js:
--------------------------------------------------------------------------------
1 | export default function network(state = {}, action) {
2 | switch (true) {
3 | case action.type == 'SUCCESS':
4 | console.log('action', action);
5 | return {
6 | ...state,
7 | [action.meta.name]: 'SUCCESS',
8 | };
9 |
10 | case action.type == 'FAILURE':
11 | return {
12 | ...state,
13 | [action.meta.name]: 'FAILURE',
14 | };
15 |
16 | case action.type == 'REQUEST':
17 | return {
18 | ...state,
19 | [action.meta.name]: 'REQUEST',
20 | };
21 | }
22 | return state;
23 | }
24 |
--------------------------------------------------------------------------------
/lib/reducers/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _api = require('./api');
8 |
9 | var _api2 = _interopRequireDefault(_api);
10 |
11 | var _network = require('./network');
12 |
13 | var _network2 = _interopRequireDefault(_network);
14 |
15 | var _domain = require('./domain');
16 |
17 | var _domain2 = _interopRequireDefault(_domain);
18 |
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20 |
21 | exports.default = {
22 | domain: _domain2.default,
23 | api: _api2.default,
24 | network: _network2.default
25 | };
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "plugins": [
4 | "babel",
5 | "prettier"
6 | ],
7 | "env": {
8 | "browser": true,
9 | "es6": true
10 | },
11 | "globals": {
12 | "it": true,
13 | "test": true,
14 | "describe": true,
15 | "expect": true,
16 | "grecaptcha": true
17 | },
18 | "parserOptions": {
19 | "ecmaFeatures": {
20 | "experimentalObjectRestSpread": true,
21 | "modules": true
22 | }
23 | },
24 | "root": true,
25 | "rules": {
26 | "no-unused-vars": [
27 | "warn",
28 | {
29 | "vars": "all",
30 | "args": "after-used"
31 | }
32 | ]
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _actions = require('./actions');
8 |
9 | var Action = _interopRequireWildcard(_actions);
10 |
11 | var _api = require('./helpers/api');
12 |
13 | var Helper = _interopRequireWildcard(_api);
14 |
15 | var _reducers = require('./reducers');
16 |
17 | var _reducers2 = _interopRequireDefault(_reducers);
18 |
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20 |
21 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
22 |
23 | exports.default = {
24 | Action: Action,
25 | Helper: Helper,
26 | Reducer: _reducers2.default
27 | };
--------------------------------------------------------------------------------
/lib/reducers/api.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _extends2 = require("babel-runtime/helpers/extends");
8 |
9 | var _extends3 = _interopRequireDefault(_extends2);
10 |
11 | exports.default = api;
12 |
13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14 |
15 | function api() {
16 | var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { protocol: "http", contentType: "", headers: {} };
17 | var action = arguments[1];
18 |
19 | switch (action.type) {
20 | case "API:SET_BASE_HEADERS":
21 | return (0, _extends3.default)({}, state, { headers: action.payload.headers });
22 | case "API:SET_SWAGGER":
23 | return (0, _extends3.default)({}, state, action.payload);
24 | case "API:SET_PROTOCOL":
25 | return (0, _extends3.default)({}, state, { protocol: action.payload });
26 | }
27 | return state;
28 | }
--------------------------------------------------------------------------------
/lib/reducers/domain.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _extends2 = require('babel-runtime/helpers/extends');
8 |
9 | var _extends3 = _interopRequireDefault(_extends2);
10 |
11 | exports.default = domain;
12 |
13 | var _lodash = require('lodash');
14 |
15 | var _lodash2 = _interopRequireDefault(_lodash);
16 |
17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18 |
19 | function domain() {
20 | var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
21 | var action = arguments[1];
22 |
23 | var idsRegexResult = /^(.+)S_BY_ID$/.exec(_lodash2.default.get(action, 'meta.data'));
24 |
25 | switch (true) {
26 | case idsRegexResult != null:
27 | var relatedIdsName = _lodash2.default.camelCase(idsRegexResult[1]) + 'sById';
28 | var newObjectWithIds = {};
29 | newObjectWithIds[relatedIdsName] = action.payload;
30 |
31 | return (0, _extends3.default)({}, state, newObjectWithIds);
32 | }
33 | return state;
34 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Davy Duperron
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/lib/reducers/network.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
8 |
9 | var _defineProperty3 = _interopRequireDefault(_defineProperty2);
10 |
11 | var _extends5 = require('babel-runtime/helpers/extends');
12 |
13 | var _extends6 = _interopRequireDefault(_extends5);
14 |
15 | exports.default = network;
16 |
17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18 |
19 | function network() {
20 | var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
21 | var action = arguments[1];
22 |
23 | switch (true) {
24 | case action.type == 'SUCCESS':
25 | console.log('action', action);
26 | return (0, _extends6.default)({}, state, (0, _defineProperty3.default)({}, action.meta.name, 'SUCCESS'));
27 |
28 | case action.type == 'FAILURE':
29 | return (0, _extends6.default)({}, state, (0, _defineProperty3.default)({}, action.meta.name, 'FAILURE'));
30 |
31 | case action.type == 'REQUEST':
32 | return (0, _extends6.default)({}, state, (0, _defineProperty3.default)({}, action.meta.name, 'REQUEST'));
33 | }
34 | return state;
35 | }
--------------------------------------------------------------------------------
/src/common/actions/index.js:
--------------------------------------------------------------------------------
1 | import URI from "urijs";
2 | import { CALL_API } from "redux-api-middleware";
3 | import { stringify } from "query-string";
4 | import _ from "lodash";
5 | import { subsituteUrl, formData, processType } from "~/helpers/api";
6 | export function setProtocol(protocol) {
7 | return {
8 | type: "API:SET_PROTOCOL",
9 | payload: protocol
10 | };
11 | }
12 |
13 | export function setSwagger(swagger) {
14 | return {
15 | type: "API:SET_SWAGGER",
16 | payload: swagger
17 | };
18 | }
19 | export function setHeaders(headers) {
20 | return {
21 | type: "API:SET_BASE_HEADERS",
22 | payload: {
23 | headers: headers
24 | }
25 | };
26 | }
27 | export function request(pathName, { method, data, subst }, types) {
28 | const pathEntity = _.get(getState().api.paths, pathName);
29 |
30 | let entityPath = pathName;
31 | if (subst) {
32 | entityPath = subsituteUrl(pathName, subst);
33 | }
34 | let realPath = entityPath;
35 |
36 | // //TODO Header should be create by Header constructor instead of plain object
37 | let headers = {
38 | ...getState().api.headers,
39 | ...pathEntity.headers
40 | };
41 | let body;
42 | if (method == "get" && data) {
43 | realPath = realPath + "?" + stringify(data);
44 | } else {
45 | body = formData(data, headers["Content-Type"]);
46 | }
47 |
48 | if (headers["Content-Type"] === "multipart/form-data") {
49 | delete headers["Content-Type"];
50 | delete headers["content-type"];
51 | }
52 | //
53 | const result = {
54 | endpoint:
55 | getState().api.protocol +
56 | "://" +
57 | getState().api.host +
58 | getState().api.basePath +
59 | realPath,
60 | method: method,
61 |
62 | headers: headers,
63 | body: body,
64 | types: processType(types, pathName, method)
65 | };
66 | return {
67 | [CALL_API]: result
68 | };
69 | }
70 |
--------------------------------------------------------------------------------
/src/actions/index.js:
--------------------------------------------------------------------------------
1 | import URI from "urijs";
2 | import { CALL_API } from "redux-api-middleware";
3 | import { stringify } from "query-string";
4 | import _ from "lodash";
5 | import { subsituteUrl, formData, processType } from "~/helpers/api";
6 | export function setProtocol(protocol) {
7 | return {
8 | type: "API:SET_PROTOCOL",
9 | payload: protocol
10 | };
11 | }
12 |
13 | export function setSwagger(swagger) {
14 | return {
15 | type: "API:SET_SWAGGER",
16 | payload: swagger
17 | };
18 | }
19 | export function setHeaders(headers) {
20 | return {
21 | type: "API:SET_BASE_HEADERS",
22 | payload: {
23 | headers: headers
24 | }
25 | };
26 | }
27 | export function request(pathName, { method, data, subst }, types) {
28 | return (dispatch, getState) => {
29 | const pathEntity = _.get(getState().api.paths, pathName);
30 |
31 | let entityPath = pathName;
32 | if (subst) {
33 | entityPath = subsituteUrl(pathName, subst);
34 | }
35 | let realPath = entityPath;
36 |
37 | // //TODO Header should be create by Header constructor instead of plain object
38 | let headers = {
39 | ...getState().api.headers,
40 | ...pathEntity.headers
41 | };
42 | let body;
43 | if (method == "get" && data) {
44 | realPath = realPath + "?" + stringify(data);
45 | } else {
46 | body = formData(data, headers["Content-Type"]);
47 | }
48 |
49 | if (headers["Content-Type"] === "multipart/form-data") {
50 | delete headers["Content-Type"];
51 | delete headers["content-type"];
52 | }
53 | //
54 | const result = {
55 | endpoint:
56 | getState().api.protocol +
57 | "://" +
58 | getState().api.host +
59 | getState().api.basePath +
60 | realPath,
61 | method: method,
62 |
63 | headers: headers,
64 | body: body,
65 | types: processType(types, pathName, method)
66 | };
67 |
68 | return dispatch({
69 | [CALL_API]: result
70 | });
71 | };
72 | }
73 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "redux-api-middleware-addon",
3 | "version": "1.0.0",
4 | "title": "redux-api-middleware-addon",
5 | "main": "lib/index.js",
6 | "description": "A opinioned boilerplate for develop react component(with styled-components) and redux action,reducer with proper development tools",
7 | "keywords": [
8 | "Babel",
9 | "redux",
10 | "redux api middleware addon",
11 | "Library"
12 | ],
13 | "homepage": "https://github.com/chungchi300/redux-api-middleware-addon",
14 | "author": {
15 | "name": "Jeff Chung",
16 | "url": "https://github.com/chungchi300"
17 | },
18 | "license": "MIT",
19 | "repository": {
20 | "type": "git",
21 | "url": "https://github.com/chungchi300/redux-api-middleware-addon"
22 | },
23 | "engines": {
24 | "npm": ">=3.0.0",
25 | "node": ">=6.0.0"
26 | },
27 | "dependencies": {
28 | "babel-plugin-transform-runtime": "^6.23.0",
29 | "babel-runtime": "^6.25.0",
30 | "form-data": "^2.3.1",
31 | "isomorphic-fetch": "^2.2.1",
32 | "lodash": "^4.17.4",
33 | "query-string": "^5.0.1",
34 | "redux-api-middleware": "^2.0.1",
35 | "urijs": "^1.18.4"
36 | },
37 | "devDependencies": {
38 | "babel-cli": "^6.26.0",
39 | "babel-eslint": "^8.0.2",
40 | "babel-istanbul": "^0.12.2",
41 | "babel-plugin-root-import": "^5.1.0",
42 | "babel-plugin-transform-object-rest-spread": "^6.26.0",
43 | "babel-preset-env": "^1.6.0",
44 | "coveralls": "^3.0.0",
45 | "eslint": "^4.3.0",
46 | "eslint-plugin-babel": "^4.1.2",
47 | "eslint-plugin-prettier": "^2.1.2",
48 | "isomorphic-fetch": "^2.1.1",
49 | "nock": "^9.1.0",
50 | "prettier": "^1.5.3",
51 | "rimraf": "^2.6.2",
52 | "tap-spec": "^4.1.1 ",
53 | "tape": "^4.8.0"
54 | },
55 | "scripts": {
56 | "build": "babel src --out-dir lib",
57 | "clean": "rimraf lib coverage",
58 | "cover": "babel-node ./node_modules/.bin/babel-istanbul cover test/index.js | tap-spec",
59 | "lint": "eslint src test",
60 | "prepublish": "npm run lint && npm test && npm run clean && npm run build",
61 | "test": ""
62 | },
63 | "jest": {
64 | "modulePaths": [
65 | "./node_modules",
66 | "./src/common"
67 | ]
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Features
2 | 1. **Predictable and Ready-to-go api reducer to handle common network result for Rest API** ,E.g **Domain,Network,Api** Reducer
3 | 2. Support **swagger.json**,**documentation as code**
4 | 3. Support **file upload**
5 |
6 | ## Installation
7 | ```
8 | npm install redux-api-middleware-addon --save
9 | ```
10 | ## Example
11 |
12 | ### Swagger definitions
13 | https://github.com/chungchi300/redux-api-middleware-addon/blob/master/src/common/swagger.js
14 |
15 | ### Code Usage
16 | ```
17 | import SWAGGER from 'swagger.js';
18 |
19 | store.dispatch(Action.setProtocol('https'));
20 |
21 | store.dispatch(Action.setSwagger(SWAGGER));
22 | store.dispatch(
23 | Action.setHeaders({
24 | // 'X-Token': 'base64TokenForApiCall',
25 | Accept: 'application/json',
26 | ['Content-Type']: 'application/json',
27 | })
28 | );
29 | store
30 | .dispatch(
31 | Action.request(
32 | '/pet/findByStatus',
33 | {
34 | method: 'get',
35 | data: { status: 'available' },
36 | subst: null,
37 | },
38 | BASIC
39 | )
40 | )
41 | .then(res => console.log(res));
42 | store
43 | .dispatch(
44 | Action.request(
45 | '/pet',
46 | {
47 | method: 'post',
48 | data: {
49 | name: 'ronald',
50 | id: 3,
51 | photoUrls: [
52 | 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Letter_d.svg/1200px-Letter_d.svg.png',
53 | ],
54 | },
55 | },
56 | BASIC
57 | )
58 | )
59 | .then(res => console.log(res));
60 | store
61 | .dispatch(
62 | Action.request(
63 | '/pet/findByStatus',
64 | {
65 | method: 'get',
66 | data: { status: 'available' },
67 | subst: null,
68 | },
69 | entity('PETS_BY_ID')
70 | )
71 | )
72 | .then(res => console.log(res));
73 | ```
74 | ### Result
75 | 
76 |
77 | ## Components
78 |
79 | ### Action
80 | 1. SET_SWAGGER
81 | 2. Request
82 | 3. SET_HEADER(default empty)
83 | 4. SET_PROTOCOL(default http)
84 |
85 | ### helpers
86 | 1. Generate Basic types
87 | 2. Generate Get Entity types
88 |
89 | //TODO
90 | Generate update,delete,create which help network reducer record which api has api result that failed
91 |
92 | ### Reducer
93 | 1. network (reducer,where is network result located)
94 | 2. domain (reducer,where is CRUD resource result located)
95 | 3. api (reducer,where is the api located)
96 |
--------------------------------------------------------------------------------
/lib/common/actions/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _defineProperty2 = require("babel-runtime/helpers/defineProperty");
8 |
9 | var _defineProperty3 = _interopRequireDefault(_defineProperty2);
10 |
11 | var _extends2 = require("babel-runtime/helpers/extends");
12 |
13 | var _extends3 = _interopRequireDefault(_extends2);
14 |
15 | exports.setProtocol = setProtocol;
16 | exports.setSwagger = setSwagger;
17 | exports.setHeaders = setHeaders;
18 | exports.request = request;
19 |
20 | var _urijs = require("urijs");
21 |
22 | var _urijs2 = _interopRequireDefault(_urijs);
23 |
24 | var _reduxApiMiddleware = require("redux-api-middleware");
25 |
26 | var _queryString = require("query-string");
27 |
28 | var _lodash = require("lodash");
29 |
30 | var _lodash2 = _interopRequireDefault(_lodash);
31 |
32 | var _api = require("../../helpers/api");
33 |
34 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
35 |
36 | function setProtocol(protocol) {
37 | return {
38 | type: "API:SET_PROTOCOL",
39 | payload: protocol
40 | };
41 | }
42 |
43 | function setSwagger(swagger) {
44 | return {
45 | type: "API:SET_SWAGGER",
46 | payload: swagger
47 | };
48 | }
49 | function setHeaders(headers) {
50 | return {
51 | type: "API:SET_BASE_HEADERS",
52 | payload: {
53 | headers: headers
54 | }
55 | };
56 | }
57 | function request(pathName, _ref, types) {
58 | var method = _ref.method,
59 | data = _ref.data,
60 | subst = _ref.subst;
61 |
62 | var pathEntity = _lodash2.default.get(getState().api.paths, pathName);
63 |
64 | var entityPath = pathName;
65 | if (subst) {
66 | entityPath = (0, _api.subsituteUrl)(pathName, subst);
67 | }
68 | var realPath = entityPath;
69 |
70 | // //TODO Header should be create by Header constructor instead of plain object
71 | var headers = (0, _extends3.default)({}, getState().api.headers, pathEntity.headers);
72 | var body = void 0;
73 | if (method == "get" && data) {
74 | realPath = realPath + "?" + (0, _queryString.stringify)(data);
75 | } else {
76 | body = (0, _api.formData)(data, headers["Content-Type"]);
77 | }
78 |
79 | if (headers["Content-Type"] === "multipart/form-data") {
80 | delete headers["Content-Type"];
81 | delete headers["content-type"];
82 | }
83 | //
84 | var result = {
85 | endpoint: getState().api.protocol + "://" + getState().api.host + getState().api.basePath + realPath,
86 | method: method,
87 |
88 | headers: headers,
89 | body: body,
90 | types: (0, _api.processType)(types, pathName, method)
91 | };
92 | return (0, _defineProperty3.default)({}, _reduxApiMiddleware.CALL_API, result);
93 | }
--------------------------------------------------------------------------------
/lib/actions/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _defineProperty2 = require("babel-runtime/helpers/defineProperty");
8 |
9 | var _defineProperty3 = _interopRequireDefault(_defineProperty2);
10 |
11 | var _extends2 = require("babel-runtime/helpers/extends");
12 |
13 | var _extends3 = _interopRequireDefault(_extends2);
14 |
15 | exports.setProtocol = setProtocol;
16 | exports.setSwagger = setSwagger;
17 | exports.setHeaders = setHeaders;
18 | exports.request = request;
19 |
20 | var _urijs = require("urijs");
21 |
22 | var _urijs2 = _interopRequireDefault(_urijs);
23 |
24 | var _reduxApiMiddleware = require("redux-api-middleware");
25 |
26 | var _queryString = require("query-string");
27 |
28 | var _lodash = require("lodash");
29 |
30 | var _lodash2 = _interopRequireDefault(_lodash);
31 |
32 | var _api = require("../helpers/api");
33 |
34 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
35 |
36 | function setProtocol(protocol) {
37 | return {
38 | type: "API:SET_PROTOCOL",
39 | payload: protocol
40 | };
41 | }
42 |
43 | function setSwagger(swagger) {
44 | return {
45 | type: "API:SET_SWAGGER",
46 | payload: swagger
47 | };
48 | }
49 | function setHeaders(headers) {
50 | return {
51 | type: "API:SET_BASE_HEADERS",
52 | payload: {
53 | headers: headers
54 | }
55 | };
56 | }
57 | function request(pathName, _ref, types) {
58 | var method = _ref.method,
59 | data = _ref.data,
60 | subst = _ref.subst;
61 |
62 | return function (dispatch, getState) {
63 | var pathEntity = _lodash2.default.get(getState().api.paths, pathName);
64 |
65 | var entityPath = pathName;
66 | if (subst) {
67 | entityPath = (0, _api.subsituteUrl)(pathName, subst);
68 | }
69 | var realPath = entityPath;
70 |
71 | // //TODO Header should be create by Header constructor instead of plain object
72 | var headers = (0, _extends3.default)({}, getState().api.headers, pathEntity.headers);
73 | var body = void 0;
74 | if (method == "get" && data) {
75 | realPath = realPath + "?" + (0, _queryString.stringify)(data);
76 | } else {
77 | body = (0, _api.formData)(data, headers["Content-Type"]);
78 | }
79 |
80 | if (headers["Content-Type"] === "multipart/form-data") {
81 | delete headers["Content-Type"];
82 | delete headers["content-type"];
83 | }
84 | //
85 | var result = {
86 | endpoint: getState().api.protocol + "://" + getState().api.host + getState().api.basePath + realPath,
87 | method: method,
88 |
89 | headers: headers,
90 | body: body,
91 | types: (0, _api.processType)(types, pathName, method)
92 | };
93 |
94 | return dispatch((0, _defineProperty3.default)({}, _reduxApiMiddleware.CALL_API, result));
95 | };
96 | }
--------------------------------------------------------------------------------
/src/helpers/api.js:
--------------------------------------------------------------------------------
1 | import FormData from "form-data";
2 | import { stringify } from "query-string";
3 |
4 | // ['REQUEST', 'SUCESS', 'FAILURE'];
5 | import _ from "lodash";
6 | // mapById(['entity']);
7 | // defaultGuessing by name;
8 | export const BASIC = ["REQUEST", "SUCCESS", "FAILURE"];
9 | export function sleep(ms) {
10 | return new Promise(resolve => setTimeout(resolve, ms));
11 | }
12 | export async function waitForAWhile() {
13 | return await sleep(3000);
14 | }
15 | export function entity(name) {
16 | return [
17 | "REQUEST",
18 | {
19 | type: "SUCCESS",
20 | meta: { data: name },
21 | payload: (action, state, res) => {
22 | return res.json();
23 | }
24 | },
25 | "FAILURE"
26 | ];
27 | }
28 | export function formData(dataMap, contentType) {
29 | if (!dataMap) return null;
30 | if (contentType === "multipart/form-data") {
31 | let formData = new FormData();
32 |
33 | Object.keys(dataMap).forEach(key => formData.append(key, dataMap[key]));
34 |
35 | return formData;
36 | } else if (contentType === "application/x-www-form-urlencoded") {
37 | return stringify(dataMap);
38 | } else if (contentType === "application/json") {
39 | return JSON.stringify(dataMap);
40 | } else {
41 | throw new Error("unknown contentType for " + contentType);
42 | }
43 | }
44 | function getConventionalName(pathName, method) {
45 | return (
46 | method +
47 | pathName
48 | .replace(/\{.*\}/g, "")
49 | .replace(/\/(.)/g, function($1) {
50 | return $1.toUpperCase();
51 | })
52 | .replace(/\//g, "")
53 | );
54 | }
55 | export function processType(types, pathName, method) {
56 | let originalTypes = _.cloneDeep(types);
57 | let processedTypes = [];
58 |
59 | originalTypes = originalTypes.map(originalType => {
60 | if (typeof originalType == "string") {
61 | return { type: originalType };
62 | } else {
63 | return originalType;
64 | }
65 | });
66 | console.log("types", types);
67 | processedTypes[0] = {
68 | ...originalTypes[0],
69 | meta: {
70 | path: pathName,
71 | name: getConventionalName(pathName, method),
72 | method: method,
73 | ...originalTypes[0].meta
74 | }
75 | };
76 | processedTypes[1] = {
77 | ...originalTypes[1],
78 | meta: {
79 | path: pathName,
80 | name: getConventionalName(pathName, method),
81 | method: method,
82 | ...originalTypes[1].meta
83 | }
84 | };
85 | processedTypes[2] = {
86 | ...originalTypes[2],
87 | meta: {
88 | path: pathName,
89 | name: getConventionalName(pathName, method),
90 | method: method,
91 | ...originalTypes[2].meta
92 | }
93 | };
94 |
95 | return processedTypes;
96 | }
97 | export function subsituteUrl(url, substitues) {
98 | let finalUrl = url;
99 |
100 | Object.keys(substitues).forEach((key, index) => {
101 | finalUrl = finalUrl.replace("{" + key + "}", substitues[key]);
102 | });
103 | return finalUrl;
104 | }
105 |
--------------------------------------------------------------------------------
/lib/helpers/api.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.waitForAWhile = exports.BASIC = undefined;
7 |
8 | var _extends2 = require("babel-runtime/helpers/extends");
9 |
10 | var _extends3 = _interopRequireDefault(_extends2);
11 |
12 | var _stringify = require("babel-runtime/core-js/json/stringify");
13 |
14 | var _stringify2 = _interopRequireDefault(_stringify);
15 |
16 | var _keys = require("babel-runtime/core-js/object/keys");
17 |
18 | var _keys2 = _interopRequireDefault(_keys);
19 |
20 | var _regenerator = require("babel-runtime/regenerator");
21 |
22 | var _regenerator2 = _interopRequireDefault(_regenerator);
23 |
24 | var _asyncToGenerator2 = require("babel-runtime/helpers/asyncToGenerator");
25 |
26 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
27 |
28 | var _promise = require("babel-runtime/core-js/promise");
29 |
30 | var _promise2 = _interopRequireDefault(_promise);
31 |
32 | var waitForAWhile = exports.waitForAWhile = function () {
33 | var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee() {
34 | return _regenerator2.default.wrap(function _callee$(_context) {
35 | while (1) {
36 | switch (_context.prev = _context.next) {
37 | case 0:
38 | _context.next = 2;
39 | return sleep(3000);
40 |
41 | case 2:
42 | return _context.abrupt("return", _context.sent);
43 |
44 | case 3:
45 | case "end":
46 | return _context.stop();
47 | }
48 | }
49 | }, _callee, this);
50 | }));
51 |
52 | return function waitForAWhile() {
53 | return _ref.apply(this, arguments);
54 | };
55 | }();
56 |
57 | exports.sleep = sleep;
58 | exports.entity = entity;
59 | exports.formData = formData;
60 | exports.processType = processType;
61 | exports.subsituteUrl = subsituteUrl;
62 |
63 | var _formData2 = require("form-data");
64 |
65 | var _formData3 = _interopRequireDefault(_formData2);
66 |
67 | var _queryString = require("query-string");
68 |
69 | var _lodash = require("lodash");
70 |
71 | var _lodash2 = _interopRequireDefault(_lodash);
72 |
73 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
74 |
75 | // mapById(['entity']);
76 | // defaultGuessing by name;
77 | var BASIC = exports.BASIC = ["REQUEST", "SUCCESS", "FAILURE"];
78 |
79 | // ['REQUEST', 'SUCESS', 'FAILURE'];
80 | function sleep(ms) {
81 | return new _promise2.default(function (resolve) {
82 | return setTimeout(resolve, ms);
83 | });
84 | }
85 | function entity(name) {
86 | return ["REQUEST", {
87 | type: "SUCCESS",
88 | meta: { data: name },
89 | payload: function payload(action, state, res) {
90 | return res.json();
91 | }
92 | }, "FAILURE"];
93 | }
94 | function formData(dataMap, contentType) {
95 | if (!dataMap) return null;
96 | if (contentType === "multipart/form-data") {
97 | var _formData = new _formData3.default();
98 |
99 | (0, _keys2.default)(dataMap).forEach(function (key) {
100 | return _formData.append(key, dataMap[key]);
101 | });
102 |
103 | return _formData;
104 | } else if (contentType === "application/x-www-form-urlencoded") {
105 | return (0, _queryString.stringify)(dataMap);
106 | } else if (contentType === "application/json") {
107 | return (0, _stringify2.default)(dataMap);
108 | } else {
109 | throw new Error("unknown contentType for " + contentType);
110 | }
111 | }
112 | function getConventionalName(pathName, method) {
113 | return method + pathName.replace(/\{.*\}/g, "").replace(/\/(.)/g, function ($1) {
114 | return $1.toUpperCase();
115 | }).replace(/\//g, "");
116 | }
117 | function processType(types, pathName, method) {
118 | var originalTypes = _lodash2.default.cloneDeep(types);
119 | var processedTypes = [];
120 |
121 | originalTypes = originalTypes.map(function (originalType) {
122 | if (typeof originalType == "string") {
123 | return { type: originalType };
124 | } else {
125 | return originalType;
126 | }
127 | });
128 | console.log("types", types);
129 | processedTypes[0] = (0, _extends3.default)({}, originalTypes[0], {
130 | meta: (0, _extends3.default)({
131 | path: pathName,
132 | name: getConventionalName(pathName, method),
133 | method: method
134 | }, originalTypes[0].meta)
135 | });
136 | processedTypes[1] = (0, _extends3.default)({}, originalTypes[1], {
137 | meta: (0, _extends3.default)({
138 | path: pathName,
139 | name: getConventionalName(pathName, method),
140 | method: method
141 | }, originalTypes[1].meta)
142 | });
143 | processedTypes[2] = (0, _extends3.default)({}, originalTypes[2], {
144 | meta: (0, _extends3.default)({
145 | path: pathName,
146 | name: getConventionalName(pathName, method),
147 | method: method
148 | }, originalTypes[2].meta)
149 | });
150 |
151 | return processedTypes;
152 | }
153 | function subsituteUrl(url, substitues) {
154 | var finalUrl = url;
155 |
156 | (0, _keys2.default)(substitues).forEach(function (key, index) {
157 | finalUrl = finalUrl.replace("{" + key + "}", substitues[key]);
158 | });
159 | return finalUrl;
160 | }
--------------------------------------------------------------------------------
/lib/swagger.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.default = {
7 | swagger: '2.0',
8 | info: {
9 | description: 'This is a sample Petstore server. You can find \nout more about Swagger at \n[http://swagger.io](http://swagger.io) or on \n[irc.freenode.net, #swagger](http://swagger.io/irc/).\n',
10 | version: '1.0.0',
11 | title: 'Swagger Petstore',
12 | termsOfService: 'http://swagger.io/terms/',
13 | contact: {
14 | email: 'apiteam@swagger.io'
15 | },
16 | license: {
17 | name: 'Apache 2.0',
18 | url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
19 | }
20 | },
21 | host: 'virtserver.swaggerhub.com',
22 | basePath: '/chungchi300/Petstore-redux-api-middleware-addon/1.0.0',
23 | tags: [{
24 | name: 'pet',
25 | description: 'Everything about your Pets',
26 | externalDocs: {
27 | description: 'Find out more',
28 | url: 'http://swagger.io'
29 | }
30 | }, {
31 | name: 'store',
32 | description: 'Access to Petstore orders'
33 | }, {
34 | name: 'user',
35 | description: 'Operations about user',
36 | externalDocs: {
37 | description: 'Find out more about our store',
38 | url: 'http://swagger.io'
39 | }
40 | }],
41 | schemes: ['https', 'http'],
42 | paths: {
43 | '/pet': {
44 | post: {
45 | tags: ['pet'],
46 | summary: 'Add a new pet to the store',
47 | operationId: 'addPet',
48 | consumes: ['application/json', 'application/xml'],
49 | produces: ['application/json', 'application/xml'],
50 | parameters: [{
51 | in: 'body',
52 | name: 'body',
53 | description: 'Pet object that needs to be added to the store',
54 | required: true,
55 | schema: {
56 | $ref: '#/definitions/Pet'
57 | }
58 | }],
59 | responses: {
60 | '405': {
61 | description: 'Invalid input'
62 | }
63 | },
64 | security: [{
65 | petstore_auth: ['write:pets', 'read:pets']
66 | }]
67 | },
68 | put: {
69 | tags: ['pet'],
70 | summary: 'Update an existing pet',
71 | operationId: 'updatePet',
72 | consumes: ['application/json', 'application/xml'],
73 | produces: ['application/json', 'application/xml'],
74 | parameters: [{
75 | in: 'body',
76 | name: 'body',
77 | description: 'Pet object that needs to be added to the store',
78 | required: true,
79 | schema: {
80 | $ref: '#/definitions/Pet'
81 | }
82 | }],
83 | responses: {
84 | '400': {
85 | description: 'Invalid ID supplied'
86 | },
87 | '404': {
88 | description: 'Pet not found'
89 | },
90 | '405': {
91 | description: 'Validation exception'
92 | }
93 | },
94 | security: [{
95 | petstore_auth: ['write:pets', 'read:pets']
96 | }]
97 | }
98 | },
99 | '/pet/findByStatus': {
100 | get: {
101 | tags: ['pet'],
102 | summary: 'Finds Pets by status',
103 | description: 'Multiple status values can be provided with comma separated strings',
104 | operationId: 'findPetsByStatus',
105 | produces: ['application/json', 'application/xml'],
106 | parameters: [{
107 | name: 'status',
108 | in: 'query',
109 | description: 'Status values that need to be considered for filter',
110 | required: true,
111 | type: 'array',
112 | items: {
113 | type: 'string',
114 | enum: ['available', 'pending', 'sold'],
115 | default: 'available'
116 | },
117 | collectionFormat: 'multi'
118 | }],
119 | responses: {
120 | '200': {
121 | description: 'successful operation',
122 | schema: {
123 | type: 'array',
124 | items: {
125 | $ref: '#/definitions/Pet'
126 | }
127 | }
128 | },
129 | '400': {
130 | description: 'Invalid status value'
131 | }
132 | },
133 | security: [{
134 | petstore_auth: ['write:pets', 'read:pets']
135 | }]
136 | }
137 | },
138 | '/pet/{id}': {
139 | get: {
140 | tags: ['pet'],
141 | summary: 'Find pet by ID',
142 | description: 'Returns a single pet',
143 | operationId: 'getPetById',
144 | produces: ['application/json', 'application/xml'],
145 | parameters: [{
146 | name: 'petId',
147 | in: 'path',
148 | description: 'ID of pet to return',
149 | required: true,
150 | type: 'integer',
151 | format: 'int64'
152 | }],
153 | responses: {
154 | '200': {
155 | description: 'successful operation',
156 | schema: {
157 | $ref: '#/definitions/Pet'
158 | }
159 | },
160 | '400': {
161 | description: 'Invalid ID supplied'
162 | },
163 | '404': {
164 | description: 'Pet not found'
165 | }
166 | },
167 | security: [{
168 | api_key: []
169 | }]
170 | },
171 | post: {
172 | tags: ['pet'],
173 | summary: 'Updates a pet in the store with form data',
174 | operationId: 'updatePetWithForm',
175 | consumes: ['application/x-www-form-urlencoded'],
176 | produces: ['application/json', 'application/xml'],
177 | parameters: [{
178 | name: 'petId',
179 | in: 'path',
180 | description: 'ID of pet that needs to be updated',
181 | required: true,
182 | type: 'integer',
183 | format: 'int64'
184 | }, {
185 | name: 'name',
186 | in: 'formData',
187 | description: 'Updated name of the pet',
188 | required: false,
189 | type: 'string'
190 | }, {
191 | name: 'status',
192 | in: 'formData',
193 | description: 'Updated status of the pet',
194 | required: false,
195 | type: 'string'
196 | }],
197 | responses: {
198 | '405': {
199 | description: 'Invalid input'
200 | }
201 | },
202 | security: [{
203 | petstore_auth: ['write:pets', 'read:pets']
204 | }]
205 | },
206 | delete: {
207 | tags: ['pet'],
208 | summary: 'Deletes a pet',
209 | operationId: 'deletePet',
210 | produces: ['application/json', 'application/xml'],
211 | parameters: [{
212 | name: 'api_key',
213 | in: 'header',
214 | required: false,
215 | type: 'string'
216 | }, {
217 | name: 'petId',
218 | in: 'path',
219 | description: 'Pet id to delete',
220 | required: true,
221 | type: 'integer',
222 | format: 'int64'
223 | }],
224 | responses: {
225 | '400': {
226 | description: 'Invalid ID supplied'
227 | },
228 | '404': {
229 | description: 'Pet not found'
230 | }
231 | },
232 | security: [{
233 | petstore_auth: ['write:pets', 'read:pets']
234 | }]
235 | }
236 | }
237 | },
238 | securityDefinitions: {
239 | petstore_auth: {
240 | type: 'oauth2',
241 | authorizationUrl: 'http://petstore.swagger.io/oauth/dialog',
242 | flow: 'implicit',
243 | scopes: {
244 | 'write:pets': 'modify pets in your account',
245 | 'read:pets': 'read your pets'
246 | }
247 | },
248 | api_key: {
249 | type: 'apiKey',
250 | name: 'api_key',
251 | in: 'header'
252 | }
253 | },
254 | definitions: {
255 | Pet: {
256 | type: 'object',
257 | required: ['name', 'photoUrls'],
258 | properties: {
259 | id: {
260 | type: 'integer',
261 | format: 'int64'
262 | },
263 | category: {
264 | $ref: '#/definitions/Category'
265 | },
266 | name: {
267 | type: 'string',
268 | example: 'doggie'
269 | },
270 | photoUrls: {
271 | type: 'array',
272 | xml: {
273 | name: 'photoUrl',
274 | wrapped: true
275 | },
276 | items: {
277 | type: 'string'
278 | }
279 | },
280 | tags: {
281 | type: 'array',
282 | xml: {
283 | name: 'tag',
284 | wrapped: true
285 | },
286 | items: {
287 | $ref: '#/definitions/Tag'
288 | }
289 | },
290 | status: {
291 | type: 'string',
292 | description: 'pet status in the store',
293 | enum: ['available', 'pending', 'sold']
294 | }
295 | },
296 | example: {
297 | photoUrls: ['photoUrls', 'photoUrls'],
298 | name: 'doggie',
299 | id: 0,
300 | category: {
301 | name: 'name',
302 | id: 6
303 | },
304 | tags: [{
305 | name: 'name',
306 | id: 1
307 | }, {
308 | name: 'name',
309 | id: 1
310 | }],
311 | status: 'available'
312 | },
313 | xml: {
314 | name: 'Pet'
315 | }
316 | },
317 | ApiResponse: {
318 | type: 'object',
319 | properties: {
320 | code: {
321 | type: 'integer',
322 | format: 'int32'
323 | },
324 | type: {
325 | type: 'string'
326 | },
327 | message: {
328 | type: 'string'
329 | }
330 | },
331 | example: {
332 | code: 0,
333 | type: 'type',
334 | message: 'message'
335 | }
336 | }
337 | },
338 | externalDocs: {
339 | description: 'Find out more about Swagger',
340 | url: 'http://swagger.io'
341 | }
342 | };
--------------------------------------------------------------------------------
/src/swagger.js:
--------------------------------------------------------------------------------
1 | export default {
2 | swagger: '2.0',
3 | info: {
4 | description:
5 | 'This is a sample Petstore server. You can find \nout more about Swagger at \n[http://swagger.io](http://swagger.io) or on \n[irc.freenode.net, #swagger](http://swagger.io/irc/).\n',
6 | version: '1.0.0',
7 | title: 'Swagger Petstore',
8 | termsOfService: 'http://swagger.io/terms/',
9 | contact: {
10 | email: 'apiteam@swagger.io',
11 | },
12 | license: {
13 | name: 'Apache 2.0',
14 | url: 'http://www.apache.org/licenses/LICENSE-2.0.html',
15 | },
16 | },
17 | host: 'virtserver.swaggerhub.com',
18 | basePath: '/chungchi300/Petstore-redux-api-middleware-addon/1.0.0',
19 | tags: [
20 | {
21 | name: 'pet',
22 | description: 'Everything about your Pets',
23 | externalDocs: {
24 | description: 'Find out more',
25 | url: 'http://swagger.io',
26 | },
27 | },
28 | {
29 | name: 'store',
30 | description: 'Access to Petstore orders',
31 | },
32 | {
33 | name: 'user',
34 | description: 'Operations about user',
35 | externalDocs: {
36 | description: 'Find out more about our store',
37 | url: 'http://swagger.io',
38 | },
39 | },
40 | ],
41 | schemes: ['https', 'http'],
42 | paths: {
43 | '/pet': {
44 | post: {
45 | tags: ['pet'],
46 | summary: 'Add a new pet to the store',
47 | operationId: 'addPet',
48 | consumes: ['application/json', 'application/xml'],
49 | produces: ['application/json', 'application/xml'],
50 | parameters: [
51 | {
52 | in: 'body',
53 | name: 'body',
54 | description: 'Pet object that needs to be added to the store',
55 | required: true,
56 | schema: {
57 | $ref: '#/definitions/Pet',
58 | },
59 | },
60 | ],
61 | responses: {
62 | '405': {
63 | description: 'Invalid input',
64 | },
65 | },
66 | security: [
67 | {
68 | petstore_auth: ['write:pets', 'read:pets'],
69 | },
70 | ],
71 | },
72 | put: {
73 | tags: ['pet'],
74 | summary: 'Update an existing pet',
75 | operationId: 'updatePet',
76 | consumes: ['application/json', 'application/xml'],
77 | produces: ['application/json', 'application/xml'],
78 | parameters: [
79 | {
80 | in: 'body',
81 | name: 'body',
82 | description: 'Pet object that needs to be added to the store',
83 | required: true,
84 | schema: {
85 | $ref: '#/definitions/Pet',
86 | },
87 | },
88 | ],
89 | responses: {
90 | '400': {
91 | description: 'Invalid ID supplied',
92 | },
93 | '404': {
94 | description: 'Pet not found',
95 | },
96 | '405': {
97 | description: 'Validation exception',
98 | },
99 | },
100 | security: [
101 | {
102 | petstore_auth: ['write:pets', 'read:pets'],
103 | },
104 | ],
105 | },
106 | },
107 | '/pet/findByStatus': {
108 | get: {
109 | tags: ['pet'],
110 | summary: 'Finds Pets by status',
111 | description:
112 | 'Multiple status values can be provided with comma separated strings',
113 | operationId: 'findPetsByStatus',
114 | produces: ['application/json', 'application/xml'],
115 | parameters: [
116 | {
117 | name: 'status',
118 | in: 'query',
119 | description: 'Status values that need to be considered for filter',
120 | required: true,
121 | type: 'array',
122 | items: {
123 | type: 'string',
124 | enum: ['available', 'pending', 'sold'],
125 | default: 'available',
126 | },
127 | collectionFormat: 'multi',
128 | },
129 | ],
130 | responses: {
131 | '200': {
132 | description: 'successful operation',
133 | schema: {
134 | type: 'array',
135 | items: {
136 | $ref: '#/definitions/Pet',
137 | },
138 | },
139 | },
140 | '400': {
141 | description: 'Invalid status value',
142 | },
143 | },
144 | security: [
145 | {
146 | petstore_auth: ['write:pets', 'read:pets'],
147 | },
148 | ],
149 | },
150 | },
151 | '/pet/{id}': {
152 | get: {
153 | tags: ['pet'],
154 | summary: 'Find pet by ID',
155 | description: 'Returns a single pet',
156 | operationId: 'getPetById',
157 | produces: ['application/json', 'application/xml'],
158 | parameters: [
159 | {
160 | name: 'petId',
161 | in: 'path',
162 | description: 'ID of pet to return',
163 | required: true,
164 | type: 'integer',
165 | format: 'int64',
166 | },
167 | ],
168 | responses: {
169 | '200': {
170 | description: 'successful operation',
171 | schema: {
172 | $ref: '#/definitions/Pet',
173 | },
174 | },
175 | '400': {
176 | description: 'Invalid ID supplied',
177 | },
178 | '404': {
179 | description: 'Pet not found',
180 | },
181 | },
182 | security: [
183 | {
184 | api_key: [],
185 | },
186 | ],
187 | },
188 | post: {
189 | tags: ['pet'],
190 | summary: 'Updates a pet in the store with form data',
191 | operationId: 'updatePetWithForm',
192 | consumes: ['application/x-www-form-urlencoded'],
193 | produces: ['application/json', 'application/xml'],
194 | parameters: [
195 | {
196 | name: 'petId',
197 | in: 'path',
198 | description: 'ID of pet that needs to be updated',
199 | required: true,
200 | type: 'integer',
201 | format: 'int64',
202 | },
203 | {
204 | name: 'name',
205 | in: 'formData',
206 | description: 'Updated name of the pet',
207 | required: false,
208 | type: 'string',
209 | },
210 | {
211 | name: 'status',
212 | in: 'formData',
213 | description: 'Updated status of the pet',
214 | required: false,
215 | type: 'string',
216 | },
217 | ],
218 | responses: {
219 | '405': {
220 | description: 'Invalid input',
221 | },
222 | },
223 | security: [
224 | {
225 | petstore_auth: ['write:pets', 'read:pets'],
226 | },
227 | ],
228 | },
229 | delete: {
230 | tags: ['pet'],
231 | summary: 'Deletes a pet',
232 | operationId: 'deletePet',
233 | produces: ['application/json', 'application/xml'],
234 | parameters: [
235 | {
236 | name: 'api_key',
237 | in: 'header',
238 | required: false,
239 | type: 'string',
240 | },
241 | {
242 | name: 'petId',
243 | in: 'path',
244 | description: 'Pet id to delete',
245 | required: true,
246 | type: 'integer',
247 | format: 'int64',
248 | },
249 | ],
250 | responses: {
251 | '400': {
252 | description: 'Invalid ID supplied',
253 | },
254 | '404': {
255 | description: 'Pet not found',
256 | },
257 | },
258 | security: [
259 | {
260 | petstore_auth: ['write:pets', 'read:pets'],
261 | },
262 | ],
263 | },
264 | },
265 | },
266 | securityDefinitions: {
267 | petstore_auth: {
268 | type: 'oauth2',
269 | authorizationUrl: 'http://petstore.swagger.io/oauth/dialog',
270 | flow: 'implicit',
271 | scopes: {
272 | 'write:pets': 'modify pets in your account',
273 | 'read:pets': 'read your pets',
274 | },
275 | },
276 | api_key: {
277 | type: 'apiKey',
278 | name: 'api_key',
279 | in: 'header',
280 | },
281 | },
282 | definitions: {
283 | Pet: {
284 | type: 'object',
285 | required: ['name', 'photoUrls'],
286 | properties: {
287 | id: {
288 | type: 'integer',
289 | format: 'int64',
290 | },
291 | category: {
292 | $ref: '#/definitions/Category',
293 | },
294 | name: {
295 | type: 'string',
296 | example: 'doggie',
297 | },
298 | photoUrls: {
299 | type: 'array',
300 | xml: {
301 | name: 'photoUrl',
302 | wrapped: true,
303 | },
304 | items: {
305 | type: 'string',
306 | },
307 | },
308 | tags: {
309 | type: 'array',
310 | xml: {
311 | name: 'tag',
312 | wrapped: true,
313 | },
314 | items: {
315 | $ref: '#/definitions/Tag',
316 | },
317 | },
318 | status: {
319 | type: 'string',
320 | description: 'pet status in the store',
321 | enum: ['available', 'pending', 'sold'],
322 | },
323 | },
324 | example: {
325 | photoUrls: ['photoUrls', 'photoUrls'],
326 | name: 'doggie',
327 | id: 0,
328 | category: {
329 | name: 'name',
330 | id: 6,
331 | },
332 | tags: [
333 | {
334 | name: 'name',
335 | id: 1,
336 | },
337 | {
338 | name: 'name',
339 | id: 1,
340 | },
341 | ],
342 | status: 'available',
343 | },
344 | xml: {
345 | name: 'Pet',
346 | },
347 | },
348 | ApiResponse: {
349 | type: 'object',
350 | properties: {
351 | code: {
352 | type: 'integer',
353 | format: 'int32',
354 | },
355 | type: {
356 | type: 'string',
357 | },
358 | message: {
359 | type: 'string',
360 | },
361 | },
362 | example: {
363 | code: 0,
364 | type: 'type',
365 | message: 'message',
366 | },
367 | },
368 | },
369 | externalDocs: {
370 | description: 'Find out more about Swagger',
371 | url: 'http://swagger.io',
372 | },
373 | };
374 |
--------------------------------------------------------------------------------