├── .DS_Store ├── .gitignore ├── .rspec ├── .travis.yml ├── Gemfile ├── Gemfile.lock ├── README.md ├── api-mock-server.rb ├── boot.rb ├── config.ru ├── lib └── api-mock-server │ ├── app.rb │ ├── assets │ ├── css │ │ ├── api-mock.css │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.min.css │ │ └── documents.css │ ├── image │ │ ├── demo.png │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── 保密协议.pdf │ └── js │ │ ├── ace.js │ │ ├── api-mock.js │ │ ├── bootstrap.min.js │ │ ├── documents.js │ │ ├── mode-json.js │ │ ├── theme-idle_fingers.js │ │ └── worker-json.js │ ├── initializers │ ├── apimockserver.rb │ └── init_status.rb │ ├── models │ ├── endpoint.rb │ └── status.rb │ └── views │ ├── api_list.erb │ ├── apis.erb │ ├── batch_show.erb │ ├── document.erb │ ├── edit.erb │ ├── form.erb │ ├── header.erb │ ├── index.erb │ ├── layout.erb │ ├── new.erb │ ├── show.erb │ └── single_route.erb ├── mongoid.yml.example └── test ├── api-mock-server_spec.rb └── spec_helper.rb /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlx/API-mock-server/29b877f1531cf1bfd5f4f9a201b05478f25e53aa/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .bundle/ 2 | vendor/bundle 3 | unicorn.rb 4 | mongoid.yml 5 | *.swp 6 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.0.0 4 | services: 5 | - mongodb 6 | 7 | before_install: cp mongoid.yml.example mongoid.yml 8 | script: bundle exec rspec test/api-mock-server_spec.rb 9 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source :rubygems 2 | 3 | gem 'rack' 4 | gem 'sinatra', require: 'sinatra/base' 5 | gem "mongoid" 6 | gem "sinatra-partial" 7 | gem 'sinatra-contrib' 8 | 9 | gem "pry" 10 | 11 | group :test do 12 | gem "rspec" 13 | gem 'rack-test' 14 | end 15 | 16 | group :production do 17 | gem 'unicorn' 18 | end 19 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: http://rubygems.org/ 3 | specs: 4 | activemodel (3.2.14) 5 | activesupport (= 3.2.14) 6 | builder (~> 3.0.0) 7 | activesupport (3.2.14) 8 | i18n (~> 0.6, >= 0.6.4) 9 | multi_json (~> 1.0) 10 | backports (3.3.5) 11 | builder (3.0.4) 12 | coderay (1.0.9) 13 | diff-lcs (1.2.4) 14 | i18n (0.6.5) 15 | kgio (2.8.1) 16 | method_source (0.8.2) 17 | mongoid (3.1.5) 18 | activemodel (~> 3.2) 19 | moped (~> 1.4) 20 | origin (~> 1.0) 21 | tzinfo (~> 0.3.29) 22 | moped (1.5.1) 23 | multi_json (1.8.1) 24 | origin (1.1.0) 25 | pry (0.9.12.2) 26 | coderay (~> 1.0.5) 27 | method_source (~> 0.8) 28 | slop (~> 3.4) 29 | rack (1.5.2) 30 | rack-protection (1.5.0) 31 | rack 32 | rack-test (0.6.2) 33 | rack (>= 1.0) 34 | raindrops (0.12.0) 35 | rspec (2.14.1) 36 | rspec-core (~> 2.14.0) 37 | rspec-expectations (~> 2.14.0) 38 | rspec-mocks (~> 2.14.0) 39 | rspec-core (2.14.6) 40 | rspec-expectations (2.14.3) 41 | diff-lcs (>= 1.1.3, < 2.0) 42 | rspec-mocks (2.14.4) 43 | sinatra (1.4.2) 44 | rack (~> 1.5, >= 1.5.2) 45 | rack-protection (~> 1.4) 46 | tilt (~> 1.3, >= 1.3.4) 47 | sinatra-contrib (1.4.1) 48 | backports (>= 2.0) 49 | multi_json 50 | rack-protection 51 | rack-test 52 | sinatra (~> 1.4.0) 53 | tilt (~> 1.3) 54 | sinatra-partial (0.4.0) 55 | sinatra 56 | slop (3.4.6) 57 | tilt (1.4.1) 58 | tzinfo (0.3.38) 59 | unicorn (4.7.0) 60 | kgio (~> 2.6) 61 | rack 62 | raindrops (~> 0.7) 63 | 64 | PLATFORMS 65 | ruby 66 | 67 | DEPENDENCIES 68 | mongoid 69 | pry 70 | rack 71 | rack-test 72 | rspec 73 | sinatra 74 | sinatra-contrib 75 | sinatra-partial 76 | unicorn 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mock API Server 2 | 3 | A Full-Featured API Mock Server 4 | 5 | [![Code Climate](https://codeclimate.com/github/zlx/API-mock-server.png)](https://codeclimate.com/github/zlx/API-mock-server) [![Build Status](https://travis-ci.org/zlx/API-mock-server.png?branch=master)](https://travis-ci.org/zlx/API-mock-server) 6 | 7 | ![Demo](https://raw.github.com/zlx/API-mock-server/master/public/image/demo.png) 8 | 9 | ## Installation 10 | 11 | ### Install Mongodb 12 | 13 | [Install MongoDB](http://docs.mongodb.org/manual/installation/) 14 | 15 | ### Clone the Project 16 | 17 | git clone git@github.com:zlx/API-mock-server.git 18 | 19 | ### Install Dependancy 20 | 21 | bundle install --path=vendor/bundle 22 | 23 | ## Usage 24 | 25 | ### Mongodb Config 26 | 27 | Configurate mongodb in mongoid.yml like below: 28 | 29 | cp mongoid.yml.example mongoid.yml 30 | 31 | 32 | ### Start Server 33 | 34 | rackup 35 | 36 | ### Visit 37 | 38 | http://localhost:9292/admin 39 | 40 | *Default username/password*: admin/admin 41 | 42 | ## HowTo 43 | 44 | ### How to config admin username/password ? 45 | 46 | 47 | Config admin_user and admin_password in [apimockserver.rb](https://github.com/zlx/API-mock-server/blob/master/initializers/apimockserver.rb) 48 | 49 | 50 | ### How to config Top Namespace ? 51 | 52 | **Top Namespace** is used for specific api version. 53 | 54 | for an example, if you config `top_namespace = "/api/v1"`, then you must visit "/api/v1/me" to reach "/me" route which you created. 55 | 56 | Top namespace is a global setting, so it will take an effect for every routes you created. 57 | 58 | To config top_namespace in in [apimockserver.rb](https://github.com/zlx/API-mock-server/blob/master/initializers/apimockserver.rb) 59 | 60 | ### How to redirect your routes to mock server 61 | 62 | 63 | #### Add redirect route at the end of your route.rb 64 | 65 | ```ruby 66 | constraints(Domain::Mockapi) do 67 | get "/*any", to: redirect { |p, req| "http://<>/#{req.fullpath}" } 68 | end 69 | ``` 70 | 71 | #### create domain/mockapi.rb file 72 | 73 | ```ruby 74 | module Domain 75 | 76 | APIs = %w{ 77 | } 78 | 79 | class Mockapi 80 | def self.matches? request 81 | api = request.fullpath.sub(/\?.*/, "") 82 | api.in? APIs 83 | end 84 | end 85 | 86 | end 87 | ``` 88 | 89 | Assign your mock apis in `APIs` 90 | 91 | 92 | [wiki](https://github.com/zlx/API-mock-server/wiki/Redirect-your-specific-routes-to-mockapi) 93 | 94 | 95 | ## Test 96 | 97 | ### Mock Data 98 | 99 | ruby seed.rb 100 | 101 | ### Test the service using a curl or your favourite tool 102 | 103 | curl http://localhost:4000 104 | { "hello": "world" } 105 | 106 | ### Postman 107 | 108 | [https://github.com/a85/POSTMan-Chrome-Extension](https://github.com/a85/POSTMan-Chrome-Extension) 109 | 110 | ## Deploy on Server 111 | 112 | ### work with unicorn 113 | 114 | [Guide for setup unicorn for rack app](http://recipes.sinatrarb.com/p/deployment/nginx_proxied_to_unicorn) 115 | 116 | 117 | Below is an simple example for unicorn configure:[wiki](https://github.com/zlx/API-mock-server/wiki/Deploy-on-server) 118 | 119 | ```ruby 120 | # set path to app that will be used to configure unicorn, 121 | # note the trailing slash in this example 122 | @dir = "/home/deploy/rails_apps/API-mock-server/" 123 | 124 | worker_processes 2 125 | working_directory @dir 126 | 127 | timeout 30 128 | 129 | # Specify path to socket unicorn listens to, 130 | # we will use this in our nginx.conf later 131 | listen "#{@dir}tmp/sockets/unicorn.sock", :backlog => 64 132 | 133 | # Set process id path 134 | pid "#{@dir}tmp/pids/unicorn.pid" 135 | 136 | # Set log file paths 137 | stderr_path "#{@dir}log/unicorn.stderr.log" 138 | stdout_path "#{@dir}log/unicorn.stdout.log" 139 | ``` 140 | 141 | ### similar projects 142 | 143 | 1. [mockable.io](http://www.mockable.io/) 144 | 2. [Mock Server](http://www.mock-server.com/) 145 | 3. [mocky](http://www.mocky.io/) 146 | -------------------------------------------------------------------------------- /api-mock-server.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require 'json' 3 | require 'app' 4 | 5 | module ApiMockServer 6 | class << self 7 | attr_accessor :top_namespace 8 | attr_accessor :admin_user, :admin_password 9 | 10 | 11 | def setup 12 | yield self 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /boot.rb: -------------------------------------------------------------------------------- 1 | require 'bundler/setup' 2 | Bundler.require(:default) 3 | 4 | $: << File.expand_path(".") 5 | $: << File.expand_path("./lib/api-mock-server") 6 | require 'sinatra/reloader' 7 | Dir[File.join(File.dirname(__FILE__), "/lib/api-mock-server/models", "*.rb")].each { |f| require f } 8 | require 'api-mock-server' 9 | Dir[File.join(File.dirname(__FILE__), "/lib/api-mock-server/initializers", "*.rb")].each { |f| require f } 10 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), 'boot') 2 | 3 | run ApiMockServer::App 4 | -------------------------------------------------------------------------------- /lib/api-mock-server/app.rb: -------------------------------------------------------------------------------- 1 | module ApiMockServer 2 | class App < Sinatra::Base 3 | 4 | configure do 5 | # for sinatra partial 6 | register Sinatra::Partial 7 | set :partial_template_engine, :erb 8 | 9 | use Rack::MethodOverride 10 | set :public_folder, File.dirname(__FILE__) + '/assets' 11 | 12 | # for sinatra reloader code when development 13 | register Sinatra::Reloader 14 | 15 | # for use mongodb as backend 16 | Mongoid.load!("mongoid.yml") 17 | end 18 | 19 | helpers do 20 | def protected! 21 | return if authorized? 22 | headers['WWW-Authenticate'] = 'Basic realm="Restricted Area"' 23 | halt 401, "Not authorized\n" 24 | end 25 | 26 | def authorized? 27 | @auth ||= Rack::Auth::Basic::Request.new(request.env) 28 | @auth.provided? and @auth.basic? and @auth.credentials and @auth.credentials == [::ApiMockServer.admin_user||'admin', ::ApiMockServer.admin_password||'admin'] 29 | end 30 | 31 | def prepare_api_list 32 | @categories = ApiMockServer::Endpoint.distinct(:category) 33 | if ApiMockServer::Endpoint.where(:category.exists => false).exists? 34 | @categories << "未分类" 35 | # 未分类可能重复添加 36 | @categories.uniq! 37 | end 38 | end 39 | end 40 | 41 | get '/document' do 42 | protected! 43 | prepare_api_list 44 | @routes = {} 45 | @categories.each do |c| 46 | if c != '未分类' 47 | @routes[c] = ApiMockServer::Endpoint.where(category: c) 48 | else 49 | @routes[c] = ApiMockServer::Endpoint.where(:category.exists => false) 50 | end 51 | end 52 | erb :apis, layout: :document 53 | end 54 | 55 | get "/admin" do 56 | protected! 57 | prepare_api_list 58 | erb :index 59 | end 60 | 61 | get "/admin/new" do 62 | protected! 63 | prepare_api_list 64 | @route = Endpoint.new 65 | erb :new 66 | end 67 | 68 | post "/admin/new" do 69 | protected! 70 | prepare_api_list 71 | @route = Endpoint.init_endpoint(params["route"]) 72 | if @route.save 73 | erb :show 74 | else 75 | @error = @route.errors.full_messages 76 | erb :new 77 | end 78 | end 79 | 80 | get "/admin/:id/edit" do 81 | protected! 82 | prepare_api_list 83 | @route = Endpoint.find(params[:id]) 84 | erb :edit 85 | end 86 | 87 | post "/admin/:id/edit" do 88 | protected! 89 | prepare_api_list 90 | @route = Endpoint.find(params[:id]) 91 | if @route.update_endpoint(params[:route]) 92 | erb :show 93 | else 94 | @error = @route.errors.full_messages 95 | erb :edit 96 | end 97 | end 98 | 99 | delete "/admin/:id" do 100 | protected! 101 | prepare_api_list 102 | content_type :json 103 | @route = Endpoint.find(params[:id]) 104 | if @route.destroy 105 | {error: '删除成功', url: '/admin'}.to_json 106 | else 107 | {error: @route.errors.full_messages.join(", "), url: "/admin/#{params[:id]}"}.to_json 108 | end 109 | end 110 | 111 | get "/admin/batch_show" do 112 | protected! 113 | prepare_api_list 114 | @routes = Endpoint.where(pattern: params["pattern"]) 115 | @route = @routes.try(:first) 116 | erb :batch_show 117 | end 118 | 119 | get "/admin/:id" do 120 | protected! 121 | prepare_api_list 122 | @route = Endpoint.find params[:id] 123 | erb :show 124 | end 125 | 126 | ::ApiMockServer::Endpoint::VALID_HTTP_VERBS.each do |verb| 127 | send verb, '*' do 128 | pattern = params["splat"].first 129 | if pattern.match(::ApiMockServer.top_namespace.to_s) 130 | pattern = pattern.sub(::ApiMockServer.top_namespace.to_s, "") 131 | @route = Endpoint.where(verb: verb, pattern: pattern, active: true).first 132 | unless @route 133 | urls = params["splat"].first.split("/")[1..-2] 134 | @route = Endpoint.where(verb: verb, pattern: /^\/#{urls[0]}\/\*/, active: true).first 135 | end 136 | if @route 137 | content_type :json 138 | status @route.status 139 | @route.response 140 | end 141 | else 142 | {error: "the route not exist now"}.to_json 143 | end 144 | end 145 | end 146 | 147 | end 148 | end 149 | -------------------------------------------------------------------------------- /lib/api-mock-server/assets/css/api-mock.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 60px; 3 | } 4 | 5 | .prettyprint { 6 | background-color: #000; 7 | -moz-border-radius: 8px; 8 | -webkit-border-radius: 8px; 9 | -o-border-radius: 8px; 10 | -ms-border-radius: 8px; 11 | -khtml-border-radius: 8px; 12 | border-radius: 8px; 13 | width: 95%; 14 | margin: 1em auto; 15 | padding: 1em; 16 | white-space: pre-wrap; 17 | color: #65B042; 18 | } 19 | 20 | .bs-sidebar.affix { 21 | position: absolute; 22 | width: 263px; 23 | } 24 | 25 | .bs-sidebar.affix-bottom { 26 | width: 263px; 27 | position: absolute; 28 | } 29 | 30 | .bs-sidenav { 31 | margin-bottom: 30px; 32 | padding-top: 10px; 33 | padding-bottom: 10px; 34 | text-shadow: 0 1px 0 #fff; 35 | background-color: #f7f5fa; 36 | border-radius: 5px; 37 | } 38 | 39 | .bs-sidebar .nav > li > a { 40 | display: block; 41 | color: #716b7a; 42 | padding: 5px 20px; 43 | } 44 | .bs-sidebar .nav > li > a:hover, 45 | .bs-sidebar .nav > li > a:focus { 46 | text-decoration: none; 47 | background-color: #e5e3e9; 48 | border-right: 1px solid #dbd8e0; 49 | } 50 | .bs-sidebar .nav > .active > a, 51 | .bs-sidebar .nav > .active:hover > a, 52 | .bs-sidebar .nav > .active:focus > a { 53 | font-weight: bold; 54 | color: #563d7c; 55 | background-color: transparent; 56 | border-right: 1px solid #563d7c; 57 | } 58 | 59 | .bs-sidebar .nav .nav { 60 | display: none; 61 | margin-bottom: 8px; 62 | } 63 | 64 | .bs-sidebar .nav > .active > ul { 65 | display: block; 66 | } 67 | 68 | .bs-sidebar .nav .nav > li > a { 69 | padding-top: 3px; 70 | padding-bottom: 3px; 71 | padding-left: 30px; 72 | font-size: 90%; 73 | } 74 | 75 | #editor { 76 | height: 400px; 77 | } 78 | -------------------------------------------------------------------------------- /lib/api-mock-server/assets/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | .btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,0%,#e6e6e6,100%);background-image:-moz-linear-gradient(top,#fff 0,#e6e6e6 100%);background-image:linear-gradient(to bottom,#fff 0,#e6e6e6 100%);background-repeat:repeat-x;border-color:#e0e0e0;border-color:#ccc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0)}.btn-default:active,.btn-default.active{background-color:#e6e6e6;border-color:#e0e0e0}.btn-primary{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;border-color:#2d6ca2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.btn-primary:active,.btn-primary.active{background-color:#3071a9;border-color:#2d6ca2}.btn-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;border-color:#419641;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.btn-success:active,.btn-success.active{background-color:#449d44;border-color:#419641}.btn-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;border-color:#eb9316;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.btn-warning:active,.btn-warning.active{background-color:#ec971f;border-color:#eb9316}.btn-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;border-color:#c12e2a;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.btn-danger:active,.btn-danger.active{background-color:#c9302c;border-color:#c12e2a}.btn-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;border-color:#2aabd2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.btn-info:active,.btn-info.active{background-color:#31b0d5;border-color:#2aabd2}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.navbar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#f8f8f8));background-image:-webkit-linear-gradient(top,#fff,0%,#f8f8f8,100%);background-image:-moz-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff8f8f8',GradientType=0);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar .navbar-nav>.active>a{background-color:#f8f8f8}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-gradient(linear,left 0,left 100%,from(#3c3c3c),to(#222));background-image:-webkit-linear-gradient(top,#3c3c3c,0%,#222,100%);background-image:-moz-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c',endColorstr='#ff222222',GradientType=0)}.navbar-inverse .navbar-nav>.active>a{background-color:#222}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#c8e5bc));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#c8e5bc,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;border-color:#b2dba1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffc8e5bc',GradientType=0)}.alert-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#b9def0));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#b9def0,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffb9def0',GradientType=0)}.alert-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#f8efc0));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#f8efc0,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;border-color:#f5e79e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fff8efc0',GradientType=0)}.alert-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#e7c3c3));background-image:-webkit-linear-gradient(top,#f2dede,0%,#e7c3c3,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;border-color:#dca7a7;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffe7c3c3',GradientType=0)}.progress{background-image:-webkit-gradient(linear,left 0,left 100%,from(#ebebeb),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#ebebeb,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff5f5f5',GradientType=0)}.progress-bar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.progress-bar-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.progress-bar-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.progress-bar-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.progress-bar-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3278b3));background-image:-webkit-linear-gradient(top,#428bca,0%,#3278b3,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3278b3',GradientType=0)}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));background-image:-webkit-linear-gradient(top,#f5f5f5,0%,#e8e8e8,100%);background-image:-moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#d0e9c6));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#d0e9c6,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffd0e9c6',GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#c4e3f3));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#c4e3f3,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffc4e3f3',GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#faf2cc));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#faf2cc,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fffaf2cc',GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#ebcccc));background-image:-webkit-linear-gradient(top,#f2dede,0%,#ebcccc,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffebcccc',GradientType=0)}.well{background-image:-webkit-gradient(linear,left 0,left 100%,from(#e8e8e8),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#e8e8e8,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} -------------------------------------------------------------------------------- /lib/api-mock-server/assets/css/documents.css: -------------------------------------------------------------------------------- 1 | .main { 2 | padding-top: 60px; 3 | } 4 | 5 | .section { 6 | background-color: #e9e9e9; 7 | width: 90%; 8 | padding: 10px; 9 | border-radius: 4px; 10 | margin-bottom: 10px; 11 | } 12 | 13 | .section .name { 14 | font-size: 25px; 15 | font-weight: 200; 16 | letter-spacing: 1px; 17 | padding-bottom: 10px; 18 | } 19 | 20 | .api { 21 | background-color: white; 22 | width: 100%; 23 | border-radius: 4px; 24 | margin: 10px auto; 25 | } 26 | 27 | .api .title { 28 | cursor: pointer; 29 | height: 30px; 30 | font-size: 15px; 31 | line-height: 30px; 32 | border-bottom: solid 1px #ddd; 33 | } 34 | 35 | .title .verb { 36 | background-color: #999; 37 | height: 100%; 38 | width: 100px; 39 | border-top-left-radius: 4px; 40 | text-align: center; 41 | display: inline-block; 42 | color: white; 43 | } 44 | 45 | .title .get:hover { 46 | background-color: #6f7ff4; 47 | } 48 | 49 | .title .delete:hover { 50 | background-color: #fd7070; 51 | } 52 | 53 | .title .patch:hover { 54 | background-color: #71dfbd; 55 | } 56 | 57 | .title .post:hover { 58 | background-color: #5dc151; 59 | } 60 | 61 | .title .url { 62 | padding-left: 5px; 63 | color: #06c; 64 | } 65 | 66 | .api .desc { 67 | padding: 20px 10px; 68 | } 69 | 70 | .example { 71 | border-top: dashed 1px #ddd; 72 | } 73 | 74 | .example .params, .example .response { 75 | min-height: 60px; 76 | margin-top: 10px; 77 | margin-left: 10px; 78 | } 79 | 80 | .params span, .response span { 81 | background-color: gray; 82 | border-radius: 4px; 83 | height: 20px; 84 | color: white; 85 | text-align: center; 86 | width: 60px; 87 | display: inline-block; 88 | margin-bottom: 20px; 89 | } 90 | 91 | .response span { 92 | width: 80px; 93 | } 94 | 95 | .params .code, .response .code { 96 | min-height: 80px; 97 | width: 90%; 98 | } 99 | -------------------------------------------------------------------------------- /lib/api-mock-server/assets/image/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlx/API-mock-server/29b877f1531cf1bfd5f4f9a201b05478f25e53aa/lib/api-mock-server/assets/image/demo.png -------------------------------------------------------------------------------- /lib/api-mock-server/assets/image/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlx/API-mock-server/29b877f1531cf1bfd5f4f9a201b05478f25e53aa/lib/api-mock-server/assets/image/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /lib/api-mock-server/assets/image/glyphicons-halflings-regular.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | -------------------------------------------------------------------------------- /lib/api-mock-server/assets/image/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlx/API-mock-server/29b877f1531cf1bfd5f4f9a201b05478f25e53aa/lib/api-mock-server/assets/image/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /lib/api-mock-server/assets/image/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlx/API-mock-server/29b877f1531cf1bfd5f4f9a201b05478f25e53aa/lib/api-mock-server/assets/image/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /lib/api-mock-server/assets/image/保密协议.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zlx/API-mock-server/29b877f1531cf1bfd5f4f9a201b05478f25e53aa/lib/api-mock-server/assets/image/保密协议.pdf -------------------------------------------------------------------------------- /lib/api-mock-server/assets/js/api-mock.js: -------------------------------------------------------------------------------- 1 | jQuery(function($) { 2 | $(".prettyprint").each(function() { 3 | $(this).text(JSON.stringify(JSON.parse($(this).text().trim() || "{}"), null, 2)); 4 | }) 5 | 6 | $('#show-params').click(function() { 7 | $('#create-api .params').show(); 8 | }) 9 | 10 | $('#show-status').click(function() { 11 | $('#create-api .status').show(); 12 | }) 13 | 14 | $('#add-params').click(function() { 15 | $('#create-api .params-value').append("
" + 16 | "" + 17 | "
"); 19 | }) 20 | 21 | $(".delete").click(function(e) { 22 | e.preventDefault(); 23 | $.post($(this).attr("href"), {_method: "delete"}, function(response){ 24 | alert(response.error); 25 | document.location = response.url; 26 | }) 27 | }) 28 | 29 | }) 30 | -------------------------------------------------------------------------------- /lib/api-mock-server/assets/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * bootstrap.js v3.0.0 by @fat and @mdo 3 | * Copyright 2013 Twitter Inc. 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | */ 6 | if(!jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(window.jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(window.jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(window.jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(window.jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(window.jQuery); -------------------------------------------------------------------------------- /lib/api-mock-server/assets/js/documents.js: -------------------------------------------------------------------------------- 1 | jQuery(function($) { 2 | 3 | $(".title").click(function() { 4 | $(this).parent().children(".example").toggle(); 5 | }); 6 | 7 | }) 8 | -------------------------------------------------------------------------------- /lib/api-mock-server/assets/js/mode-json.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./json_highlight_rules").JsonHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("./behaviour/cstyle").CstyleBehaviour,f=e("./folding/cstyle").FoldMode,l=e("../worker/worker_client").WorkerClient,c=function(){this.HighlightRules=o,this.$outdent=new u,this.$behaviour=new a,this.foldingRules=new f};r.inherits(c,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t);if(e=="start"){var i=t.match(/^.*[\{\(\[]\s*$/);i&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new l(["ace"],"ace/mode/json_worker","JsonWorker");return t.attachToDocument(e.getDocument()),t.on("error",function(t){e.setAnnotations([t.data])}),t.on("ok",function(){e.clearAnnotations()}),t}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"variable",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)'},{token:"string",regex:'"',next:"string"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"invalid.illegal",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"invalid.illegal",regex:"\\/\\/.*$"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],string:[{token:"constant.language.escape",regex:/\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"},{token:"string",regex:"",next:"start"}]}};r.inherits(s,i),t.JsonHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(e){e&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+e.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+e.end)))};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) -------------------------------------------------------------------------------- /lib/api-mock-server/assets/js/theme-idle_fingers.js: -------------------------------------------------------------------------------- 1 | ace.define("ace/theme/idle_fingers",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-idle-fingers",t.cssText=".ace-idle-fingers .ace_gutter {background: #3b3b3b;color: #fff}.ace-idle-fingers .ace_print-margin {width: 1px;background: #3b3b3b}.ace-idle-fingers {background-color: #323232;color: #FFFFFF}.ace-idle-fingers .ace_cursor {color: #91FF00}.ace-idle-fingers .ace_marker-layer .ace_selection {background: rgba(90, 100, 126, 0.88)}.ace-idle-fingers.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #323232;border-radius: 2px}.ace-idle-fingers .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-idle-fingers .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #404040}.ace-idle-fingers .ace_marker-layer .ace_active-line {background: #353637}.ace-idle-fingers .ace_gutter-active-line {background-color: #353637}.ace-idle-fingers .ace_marker-layer .ace_selected-word {border: 1px solid rgba(90, 100, 126, 0.88)}.ace-idle-fingers .ace_invisible {color: #404040}.ace-idle-fingers .ace_keyword,.ace-idle-fingers .ace_meta {color: #CC7833}.ace-idle-fingers .ace_constant,.ace-idle-fingers .ace_constant.ace_character,.ace-idle-fingers .ace_constant.ace_character.ace_escape,.ace-idle-fingers .ace_constant.ace_other,.ace-idle-fingers .ace_support.ace_constant {color: #6C99BB}.ace-idle-fingers .ace_invalid {color: #FFFFFF;background-color: #FF0000}.ace-idle-fingers .ace_fold {background-color: #CC7833;border-color: #FFFFFF}.ace-idle-fingers .ace_support.ace_function {color: #B83426}.ace-idle-fingers .ace_variable.ace_parameter {font-style: italic}.ace-idle-fingers .ace_string {color: #A5C261}.ace-idle-fingers .ace_string.ace_regexp {color: #CCCC33}.ace-idle-fingers .ace_comment {font-style: italic;color: #BC9458}.ace-idle-fingers .ace_meta.ace_tag {color: #FFE5BB}.ace-idle-fingers .ace_entity.ace_name {color: #FFC66D}.ace-idle-fingers .ace_collab.ace_user1 {color: #323232;background-color: #FFF980}.ace-idle-fingers .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWMwMjLyZYiPj/8PAAreAwAI1+g0AAAAAElFTkSuQmCC) right repeat-y;}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) -------------------------------------------------------------------------------- /lib/api-mock-server/assets/js/worker-json.js: -------------------------------------------------------------------------------- 1 | "no use strict";(function(e){if(typeof e.window!="undefined"&&e.document)return;e.console=function(){var e=Array.prototype.slice.call(arguments,0);postMessage({type:"log",data:e})},e.console.error=e.console.warn=e.console.log=e.console.trace=e.console,e.window=e,e.ace=e,e.normalizeModule=function(t,n){if(n.indexOf("!")!==-1){var r=n.split("!");return e.normalizeModule(t,r[0])+"!"+e.normalizeModule(t,r[1])}if(n.charAt(0)=="."){var i=t.split("/").slice(0,-1).join("/");n=(i?i+"/":"")+n;while(n.indexOf(".")!==-1&&s!=n){var s=n;n=n.replace(/^\.\//,"").replace(/\/\.\//,"/").replace(/[^\/]+\/\.\.\//,"")}}return n},e.require=function(t,n){n||(n=t,t=null);if(!n.charAt)throw new Error("worker.js require() accepts only (parentId, id) as arguments");n=e.normalizeModule(t,n);var r=e.require.modules[n];if(r)return r.initialized||(r.initialized=!0,r.exports=r.factory().exports),r.exports;var i=n.split("/");if(!e.require.tlns)return console.log("unable to load "+n);i[0]=e.require.tlns[i[0]]||i[0];var s=i.join("/")+".js";return e.require.id=n,importScripts(s),e.require(t,n)},e.require.modules={},e.require.tlns={},e.define=function(t,n,r){arguments.length==2?(r=n,typeof t!="string"&&(n=t,t=e.require.id)):arguments.length==1&&(r=t,n=[],t=e.require.id),n.length||(n=["require","exports","module"]);if(t.indexOf("text!")===0)return;var i=function(n){return e.require(t,n)};e.require.modules[t]={exports:{},factory:function(){var e=this,t=r.apply(this,n.map(function(t){switch(t){case"require":return i;case"exports":return e.exports;case"module":return e;default:return i(t)}}));return t&&(e.exports=t),e}}},e.define.amd={},e.initBaseUrls=function(e){require.tlns=e},e.initSender=function(){var t=e.require("ace/lib/event_emitter").EventEmitter,n=e.require("ace/lib/oop"),r=function(){};return function(){n.implement(this,t),this.callback=function(e,t){postMessage({type:"call",id:t,data:e})},this.emit=function(e,t){postMessage({type:"event",name:e,data:t})}}.call(r.prototype),new r},e.main=null,e.sender=null,e.onmessage=function(e){var t=e.data;if(t.command){if(!main[t.command])throw new Error("Unknown command:"+t.command);main[t.command].apply(main,t.args)}else if(t.init){initBaseUrls(t.tlns),require("ace/lib/es5-shim"),sender=initSender();var n=require(t.module)[t.classname];main=new n(sender)}else t.event&&sender&&sender._emit(t.event,t.data)}})(this),ace.define("ace/lib/es5-shim",["require","exports","module"],function(e,t,n){function r(){}function i(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}function s(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}function o(e){var t=typeof e;return e===null||t==="undefined"||t==="boolean"||t==="number"||t==="string"}function u(e){var t,n,r;if(o(e))return e;n=e.valueOf;if(typeof n=="function"){t=n.call(e);if(o(t))return t}r=e.toString;if(typeof r=="function"){t=r.call(e);if(o(t))return t}throw new TypeError}Function.prototype.bind||(Function.prototype.bind=function(e){var t=this;if(typeof t!="function")throw new TypeError("Function.prototype.bind called on incompatible "+t);var n=c.call(arguments,1),i=function(){if(this instanceof i){var r=t.apply(this,n.concat(c.call(arguments)));return Object(r)===r?r:this}return t.apply(e,n.concat(c.call(arguments)))};return t.prototype&&(r.prototype=t.prototype,i.prototype=new r,r.prototype=null),i});var a=Function.prototype.call,f=Array.prototype,l=Object.prototype,c=f.slice,h=a.bind(l.toString),p=a.bind(l.hasOwnProperty),d,v,m,g,y;if(y=p(l,"__defineGetter__"))d=a.bind(l.__defineGetter__),v=a.bind(l.__defineSetter__),m=a.bind(l.__lookupGetter__),g=a.bind(l.__lookupSetter__);if([1,2].splice(0).length!=2)if(!function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t=[],n;t.splice.apply(t,e(20)),t.splice.apply(t,e(26)),n=t.length,t.splice(5,0,"XXX"),n+1==t.length;if(n+1==t.length)return!0}())Array.prototype.splice=function(e,t){var n=this.length;e>0?e>n&&(e=n):e==void 0?e=0:e<0&&(e=Math.max(n+e,0)),e+tu)for(h=f;h--;)this[a+h]=this[u+h];if(s&&e===l)this.length=l,this.push.apply(this,i);else{this.length=l+s;for(h=0;h>>0;if(h(e)!="[object Function]")throw new TypeError;while(++i>>0,i=Array(r),s=arguments[1];if(h(e)!="[object Function]")throw new TypeError(e+" is not a function");for(var o=0;o>>0,i=[],s,o=arguments[1];if(h(e)!="[object Function]")throw new TypeError(e+" is not a function");for(var u=0;u>>0,i=arguments[1];if(h(e)!="[object Function]")throw new TypeError(e+" is not a function");for(var s=0;s>>0,i=arguments[1];if(h(e)!="[object Function]")throw new TypeError(e+" is not a function");for(var s=0;s>>0;if(h(e)!="[object Function]")throw new TypeError(e+" is not a function");if(!r&&arguments.length==1)throw new TypeError("reduce of empty array with no initial value");var i=0,s;if(arguments.length>=2)s=arguments[1];else do{if(i in n){s=n[i++];break}if(++i>=r)throw new TypeError("reduce of empty array with no initial value")}while(!0);for(;i>>0;if(h(e)!="[object Function]")throw new TypeError(e+" is not a function");if(!r&&arguments.length==1)throw new TypeError("reduceRight of empty array with no initial value");var i,s=r-1;if(arguments.length>=2)i=arguments[1];else do{if(s in n){i=n[s--];break}if(--s<0)throw new TypeError("reduceRight of empty array with no initial value")}while(!0);do s in this&&(i=e.call(void 0,i,n[s],s,t));while(s--);return i});if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function(e){var t=E&&h(this)=="[object String]"?this.split(""):F(this),n=t.length>>>0;if(!n)return-1;var r=0;arguments.length>1&&(r=s(arguments[1])),r=r>=0?r:Math.max(0,n+r);for(;r>>0;if(!n)return-1;var r=n-1;arguments.length>1&&(r=Math.min(r,s(arguments[1]))),r=r>=0?r:n-Math.abs(r);for(;r>=0;r--)if(r in t&&e===t[r])return r;return-1};Object.getPrototypeOf||(Object.getPrototypeOf=function(e){return e.__proto__||(e.constructor?e.constructor.prototype:l)});if(!Object.getOwnPropertyDescriptor){var S="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(e,t){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError(S+e);if(!p(e,t))return;var n,r,i;n={enumerable:!0,configurable:!0};if(y){var s=e.__proto__;e.__proto__=l;var r=m(e,t),i=g(e,t);e.__proto__=s;if(r||i)return r&&(n.get=r),i&&(n.set=i),n}return n.value=e[t],n}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(e){return Object.keys(e)});if(!Object.create){var x;Object.prototype.__proto__===null?x=function(){return{__proto__:null}}:x=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(e,t){var n;if(e===null)n=x();else{if(typeof e!="object")throw new TypeError("typeof prototype["+typeof e+"] != 'object'");var r=function(){};r.prototype=e,n=new r,n.__proto__=e}return t!==void 0&&Object.defineProperties(n,t),n}}if(Object.defineProperty){var T=i({}),N=typeof document=="undefined"||i(document.createElement("div"));if(!T||!N)var C=Object.defineProperty}if(!Object.defineProperty||C){var k="Property description must be an object: ",L="Object.defineProperty called on non-object: ",A="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(e,t,n){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError(L+e);if(typeof n!="object"&&typeof n!="function"||n===null)throw new TypeError(k+n);if(C)try{return C.call(Object,e,t,n)}catch(r){}if(p(n,"value"))if(y&&(m(e,t)||g(e,t))){var i=e.__proto__;e.__proto__=l,delete e[t],e[t]=n.value,e.__proto__=i}else e[t]=n.value;else{if(!y)throw new TypeError(A);p(n,"get")&&d(e,t,n.get),p(n,"set")&&v(e,t,n.set)}return e}}Object.defineProperties||(Object.defineProperties=function(e,t){for(var n in t)p(t,n)&&Object.defineProperty(e,n,t[n]);return e}),Object.seal||(Object.seal=function(e){return e}),Object.freeze||(Object.freeze=function(e){return e});try{Object.freeze(function(){})}catch(O){Object.freeze=function(e){return function(t){return typeof t=="function"?t:e(t)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(e){return e}),Object.isSealed||(Object.isSealed=function(e){return!1}),Object.isFrozen||(Object.isFrozen=function(e){return!1}),Object.isExtensible||(Object.isExtensible=function(e){if(Object(e)===e)throw new TypeError;var t="";while(p(e,t))t+="?";e[t]=!0;var n=p(e,t);return delete e[t],n});if(!Object.keys){var M=!0,_=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],D=_.length;for(var P in{toString:null})M=!1;Object.keys=function I(e){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError("Object.keys called on a non-object");var I=[];for(var t in e)p(e,t)&&I.push(t);if(M)for(var n=0,r=D;n=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):e.row<0&&(e.row=0),e},this.insert=function(e,t){if(!t||t.length===0)return e;e=this.$clipPosition(e),this.getLength()<=1&&this.$detectNewLine(t);var n=this.$split(t),r=n.splice(0,1)[0],i=n.length==0?null:n.splice(n.length-1,1)[0];return e=this.insertInLine(e,r),i!==null&&(e=this.insertNewLine(e),e=this._insertLines(e.row,n),e=this.insertInLine(e,i||"")),e},this.insertLines=function(e,t){return e>=this.getLength()?this.insert({row:e,column:0},"\n"+t.join("\n")):this._insertLines(Math.max(e,0),t)},this._insertLines=function(e,t){if(t.length==0)return{row:e,column:0};if(t.length>65535){var n=this._insertLines(e,t.slice(65535));t=t.slice(0,65535)}var r=[e,0];r.push.apply(r,t),this.$lines.splice.apply(this.$lines,r);var i=new s(e,0,e+t.length,0),o={action:"insertLines",range:i,lines:t};return this._emit("change",{data:o}),n||i.end},this.insertNewLine=function(e){e=this.$clipPosition(e);var t=this.$lines[e.row]||"";this.$lines[e.row]=t.substring(0,e.column),this.$lines.splice(e.row+1,0,t.substring(e.column,t.length));var n={row:e.row+1,column:0},r={action:"insertText",range:s.fromPoints(e,n),text:this.getNewLineCharacter()};return this._emit("change",{data:r}),n},this.insertInLine=function(e,t){if(t.length==0)return e;var n=this.$lines[e.row]||"";this.$lines[e.row]=n.substring(0,e.column)+t+n.substring(e.column);var r={row:e.row,column:e.column+t.length},i={action:"insertText",range:s.fromPoints(e,r),text:t};return this._emit("change",{data:i}),r},this.remove=function(e){!e instanceof s&&(e=s.fromPoints(e.start,e.end)),e.start=this.$clipPosition(e.start),e.end=this.$clipPosition(e.end);if(e.isEmpty())return e.start;var t=e.start.row,n=e.end.row;if(e.isMultiLine()){var r=e.start.column==0?t:t+1,i=n-1;e.end.column>0&&this.removeInLine(n,0,e.end.column),i>=r&&this._removeLines(r,i),r!=t&&(this.removeInLine(t,e.start.column,this.getLine(t).length),this.removeNewLine(e.start.row))}else this.removeInLine(t,e.start.column,e.end.column);return e.start},this.removeInLine=function(e,t,n){if(t==n)return;var r=new s(e,t,e,n),i=this.getLine(e),o=i.substring(t,n),u=i.substring(0,t)+i.substring(n,i.length);this.$lines.splice(e,1,u);var a={action:"removeText",range:r,text:o};return this._emit("change",{data:a}),r.start},this.removeLines=function(e,t){return e<0||t>=this.getLength()?this.remove(new s(e,0,t+1,0)):this._removeLines(e,t)},this._removeLines=function(e,t){var n=new s(e,0,t+1,0),r=this.$lines.splice(e,t-e+1),i={action:"removeLines",range:n,nl:this.getNewLineCharacter(),lines:r};return this._emit("change",{data:i}),r},this.removeNewLine=function(e){var t=this.getLine(e),n=this.getLine(e+1),r=new s(e,t.length,e+1,0),i=t+n;this.$lines.splice(e,2,i);var o={action:"removeText",range:r,text:this.getNewLineCharacter()};this._emit("change",{data:o})},this.replace=function(e,t){!e instanceof s&&(e=s.fromPoints(e.start,e.end));if(t.length==0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);if(t)var n=this.insert(e.start,t);else n=e.start;return n},this.applyDeltas=function(e){for(var t=0;t=0;t--){var n=e[t],r=s.fromPoints(n.range.start,n.range.end);n.action=="insertLines"?this._removeLines(r.start.row,r.end.row-1):n.action=="insertText"?this.remove(r):n.action=="removeLines"?this._insertLines(r.start.row,n.lines):n.action=="removeText"&&this.insert(r.start,n.text)}},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;i ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?tthis.end.column?1:0:ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};else if(this.end.rowt)var r={row:t+1,column:0};else if(this.start.rowthis.row)return;if(n.start.row==this.row&&n.start.column>this.column)return;var r=this.row,i=this.column,s=n.start,o=n.end;if(t.action==="insertText")if(s.row===r&&s.column<=i){if(s.column!==i||!this.$insertRight)s.row===o.row?i+=o.column-s.column:(i-=s.column,r+=o.row-s.row)}else s.row!==o.row&&s.row=i?i=s.column:i=Math.max(0,i-(o.column-s.column)):s.row!==o.row&&s.row=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),ace.define("ace/lib/lang",["require","exports","module"],function(e,t,n){t.stringReverse=function(e){return e.split("").reverse().join("")},t.stringRepeat=function(e,t){var n="";while(t>0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n="0"&&i<="9")t+=i,a();if(i==="."){t+=".";while(a()&&i>="0"&&i<="9")t+=i}if(i==="e"||i==="E"){t+=i,a();if(i==="-"||i==="+")t+=i,a();while(i>="0"&&i<="9")t+=i,a()}e=+t;if(!isNaN(e))return e;u("Bad number")},l=function(){var e,t,n="",r;if(i==='"')while(a()){if(i==='"')return a(),n;if(i==="\\"){a();if(i==="u"){r=0;for(t=0;t<4;t+=1){e=parseInt(a(),16);if(!isFinite(e))break;r=r*16+e}n+=String.fromCharCode(r)}else{if(typeof s[i]!="string")break;n+=s[i]}}else n+=i}u("Bad string")},c=function(){while(i&&i<=" ")a()},h=function(){switch(i){case"t":return a("t"),a("r"),a("u"),a("e"),!0;case"f":return a("f"),a("a"),a("l"),a("s"),a("e"),!1;case"n":return a("n"),a("u"),a("l"),a("l"),null}u("Unexpected '"+i+"'")},p,d=function(){var e=[];if(i==="["){a("["),c();if(i==="]")return a("]"),e;while(i){e.push(p()),c();if(i==="]")return a("]"),e;a(","),c()}}u("Bad array")},v=function(){var e,t={};if(i==="{"){a("{"),c();if(i==="}")return a("}"),t;while(i){e=l(),c(),a(":"),Object.hasOwnProperty.call(t,e)&&u('Duplicate key "'+e+'"'),t[e]=p(),c();if(i==="}")return a("}"),t;a(","),c()}}u("Bad object")};return p=function(){c();switch(i){case"{":return v();case"[":return d();case'"':return l();case"-":return f();default:return i>="0"&&i<="9"?f():h()}},function(e,t){var n;return o=e,r=0,i=" ",n=p(),c(),i&&u("Syntax error"),typeof t=="function"?function s(e,n){var r,i,o=e[n];if(o&&typeof o=="object")for(r in o)Object.hasOwnProperty.call(o,r)&&(i=s(o,r),i!==undefined?o[r]=i:delete o[r]);return t.call(e,n,o)}({"":n},""):n}}) -------------------------------------------------------------------------------- /lib/api-mock-server/initializers/apimockserver.rb: -------------------------------------------------------------------------------- 1 | ApiMockServer.setup do |config| 2 | # set top namespace for your API 3 | # config.top_namespace = "/api/v1" 4 | 5 | # set admin username and password, default: admin/admin 6 | # config.admin_user = 'admin' 7 | # config.admin_password = 'admin' 8 | end 9 | -------------------------------------------------------------------------------- /lib/api-mock-server/initializers/init_status.rb: -------------------------------------------------------------------------------- 1 | # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10 2 | { 3 | 100 => 'Continue', 4 | 101 => 'Switching Protocols', 5 | 200 => 'OK', 6 | 201 => 'Created', 7 | 202 => 'Accepted', 8 | 203 => 'Non-Authoritative Information', 9 | 204 => 'No Content', 10 | 205 => 'Reset Content', 11 | 206 => 'Partial Content', 12 | 300 => 'Multiple Choices', 13 | 301 => 'Moved Permanently', 14 | 302 => 'Found', 15 | 303 => 'See Other', 16 | 304 => 'Not Modified', 17 | 305 => 'Use Proxy', 18 | 306 => 'Switch Proxy', 19 | 307 => 'Temporary Redirect', 20 | 400 => 'Bad Request', 21 | 401 => 'Unauthorized', 22 | 402 => 'Payment Required', 23 | 403 => 'Forbidden', 24 | 404 => 'Not Found', 25 | 405 => 'Method Not Allowed', 26 | 406 => 'Not Acceptable', 27 | 407 => 'Proxy Authentication Required', 28 | 408 => 'Request Timeout', 29 | 409 => 'Conflict', 30 | 410 => 'Gone', 31 | 411 => 'Length Required', 32 | 412 => 'Precondition Failed', 33 | 413 => 'Request Entity Too Large', 34 | 414 => 'Request-URI Too Long', 35 | 415 => 'Unsupported Media Type', 36 | 416 => 'Requested Range Not Satisfiable', 37 | 417 => 'Expectation Failed', 38 | 500 => 'Internal Server Error', 39 | 501 => 'Not Implemented', 40 | 502 => 'Bad Gateway', 41 | 503 => 'Service Unavaiable', 42 | 504 => 'Gateway Timeout', 43 | 505 => 'HTTP Version Not Supported' 44 | }.each do |code, desc| 45 | ApiMockServer::Status.find_or_create_by(code: code, desc: desc) 46 | end 47 | -------------------------------------------------------------------------------- /lib/api-mock-server/models/endpoint.rb: -------------------------------------------------------------------------------- 1 | module ApiMockServer 2 | class Endpoint 3 | include Mongoid::Document 4 | 5 | field :verb, type: String 6 | field :pattern, type: String 7 | field :response, type: String 8 | field :status, type: Integer 9 | field :params, type: Hash 10 | field :active, type: Boolean, default: true 11 | field :category, type: String, default: "未分类" 12 | field :desc, type: String 13 | 14 | VALID_HTTP_VERBS = %w{get post put delete patch} 15 | 16 | validates_presence_of :response, :status, message: "不能为空" 17 | validates_inclusion_of :verb, in: VALID_HTTP_VERBS , message: "目前只支持以下方法: #{VALID_HTTP_VERBS.join(", ")}" 18 | validates_format_of :pattern, with: /\A\/\S*\Z/, message: "必须为 / 开头的合法 url" 19 | #validates_uniqueness_of :pattern, scope: [:verb], message: "和 verbs 该组合已经存在" 20 | 21 | def self.init_endpoint args 22 | args, ps = fixed_args args 23 | args = args.merge(params: ps) 24 | new(args) 25 | end 26 | 27 | def update_endpoint args 28 | args, ps = fixed_args args 29 | args = args.merge(params: ps) unless ps.empty? 30 | update_attributes(args) 31 | end 32 | 33 | private 34 | def self.fixed_args args 35 | ps ||= {} 36 | (args["params_key"]||[]).each_with_index do |params_name, index| 37 | ps[params_name] = args["params_value"][index] 38 | end 39 | ps = ps.delete_if {|k, v| k.blank? } 40 | args["status"] = args["status"].blank? ? 200 : args["status"].to_i 41 | args["active"] = !args["active"].nil? 42 | args = args.slice("verb", "pattern", "response", "status", "active", "category", "desc") 43 | return args, ps 44 | end 45 | 46 | def fixed_args args 47 | self.class.fixed_args args 48 | end 49 | 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/api-mock-server/models/status.rb: -------------------------------------------------------------------------------- 1 | module ApiMockServer 2 | class Status 3 | include Mongoid::Document 4 | 5 | field :code, type: Integer 6 | field :desc, type: String 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/api-mock-server/views/api_list.erb: -------------------------------------------------------------------------------- 1 | 23 | -------------------------------------------------------------------------------- /lib/api-mock-server/views/apis.erb: -------------------------------------------------------------------------------- 1 |
2 | <% @categories.each do |c| %> 3 |
4 |
<%= c %>
5 | The following is a section of resources related to the shopping cart 6 | 7 | <% @routes[c].each do |api| %> 8 |
9 |
10 | <%= api[:verb].upcase %> 11 | <%= api[:pattern] %> 12 |
13 |

<%= api[:desc] %>

14 | 29 |
30 | <% end %> 31 |
32 | <% end %> 33 |
34 | -------------------------------------------------------------------------------- /lib/api-mock-server/views/batch_show.erb: -------------------------------------------------------------------------------- 1 | <%= partial :single_route, collection: @routes %> 2 | -------------------------------------------------------------------------------- /lib/api-mock-server/views/document.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | API Mock Server Document 5 | 6 | 7 | 8 | 9 | 10 | <%= partial :header, locals: { from: 'new' } %> 11 | 12 |
13 | <%= yield %> 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /lib/api-mock-server/views/edit.erb: -------------------------------------------------------------------------------- 1 | <%= partial :form, locals: { from: 'edit' } %> 2 | -------------------------------------------------------------------------------- /lib/api-mock-server/views/form.erb: -------------------------------------------------------------------------------- 1 |
2 | <% if @error.present? %> 3 |
4 | <%= @error.join("
") %> 5 |
6 | <% end %> 7 |
8 |
9 | 10 |
11 |
12 | 18 |
19 |
20 | 21 |
22 |
23 |
24 |
25 | 26 |
27 | 28 |
29 |
30 |
31 |
32 | 33 |
34 | 35 |
36 |
37 |
38 | 设置参数 39 | 设置返回码 40 |
41 |
42 | 43 |
44 | <% if from == 'new' %> 45 |
46 | 47 |
48 |
49 | 50 |
51 | <% else %> 52 | <% (@route.params||[]).each do |key, value| %> 53 |
54 | 55 |
56 |
57 | 58 |
59 | <% end %> 60 | <% end %> 61 | 添加 62 |
63 |
64 |
65 | 66 |
67 | 68 |
69 |
70 | 71 |
72 | 73 |
74 | 75 |
76 | 77 |
78 |
79 |
80 | 83 |
84 |
85 |
86 |
87 |
88 | 91 |
92 |
93 |
94 | 95 | 96 | 97 | 98 | 99 | 109 | -------------------------------------------------------------------------------- /lib/api-mock-server/views/header.erb: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /lib/api-mock-server/views/index.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Select an API endpoint on the left to get started. :)

4 |
5 |
6 | -------------------------------------------------------------------------------- /lib/api-mock-server/views/layout.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | API Mock Server 5 | 6 | 7 | 8 | 9 | 10 | <%= partial :header, locals: { from: 'new' } %> 11 | 12 |
13 |
14 | <%= partial :api_list, locals: { current: @route } %> 15 |
16 |
17 | <%= yield %> 18 |
19 |
20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /lib/api-mock-server/views/new.erb: -------------------------------------------------------------------------------- 1 | <%= partial :form, locals: { from: 'new' } %> 2 | -------------------------------------------------------------------------------- /lib/api-mock-server/views/show.erb: -------------------------------------------------------------------------------- 1 | <%= partial :single_route, locals: { single_route: @route } %> 2 | -------------------------------------------------------------------------------- /lib/api-mock-server/views/single_route.erb: -------------------------------------------------------------------------------- 1 |
2 | 25 | 26 | <% if single_route.params && !single_route.params.empty? %> 27 |
28 |
Params
29 |
30 | <% single_route.params.each do |key, value| %> 31 |
32 |
33 | <%= key %>: 34 |
35 |
36 | <%= value %> 37 |
38 |
39 | <% end %> 40 |
41 |
42 | <% end %> 43 | 44 |
45 | 49 |
50 |       <%= single_route.response %>
51 |     
52 |
53 |
54 | -------------------------------------------------------------------------------- /mongoid.yml.example: -------------------------------------------------------------------------------- 1 | 2 | development: 3 | sessions: 4 | default: 5 | database: api_mock_server 6 | hosts: 7 | - localhost:27017 8 | 9 | test: 10 | sessions: 11 | default: 12 | database: api_mock_server_test 13 | hosts: 14 | - localhost:27017 15 | 16 | production: 17 | sessions: 18 | default: 19 | database: api_mock_server 20 | hosts: 21 | - localhost:27017 22 | 23 | -------------------------------------------------------------------------------- /test/api-mock-server_spec.rb: -------------------------------------------------------------------------------- 1 | require_relative './spec_helper' 2 | 3 | describe ApiMockServer do 4 | let(:app) { ApiMockServer::App } 5 | let(:route) { ApiMockServer::Endpoint.create(verb: 'get', pattern: '/me', response: '{"me": "ok"}', status: 200) } 6 | let(:login) { authorize("admin", "admin") } 7 | 8 | it "should halt when username or password is not right" do 9 | authorize 'admin', 'wrong password' 10 | get "/admin" 11 | expect(last_response.status).to eq(401) 12 | end 13 | 14 | context "Need authorize operations" do 15 | before do 16 | login 17 | end 18 | 19 | it "should render welcome page when username or password is right" do 20 | get "/admin" 21 | expect(last_response).to be_ok 22 | expect(last_response.body).to match("Select an API endpoint on the left to get started") 23 | end 24 | 25 | it "should render form for create new route" do 26 | get "/admin/new" 27 | expect(last_response).to be_ok 28 | expect(last_response.body).to match(/form action="\/admin\/new", method="post"/) 29 | end 30 | 31 | it "should create new route" do 32 | post "/admin/new", {route: {verb: 'get', pattern: '/me', active: 1, response: '{"me": "ok"}'}} 33 | expect(last_response).to be_ok 34 | expect(last_response.body).to match(/GET<\/span>/) 35 | expect(last_response.body).to match(/\/me<\/strong>/) 36 | end 37 | 38 | it "should render error when missing pattern" do 39 | post "/admin/new", {route: {verb: 'get', active: 1, response: '{"me": "ok"}'}} 40 | expect(last_response).to be_ok 41 | expect(last_response.body).to match(/Pattern 必须为 \/ 开头的合法 url/) 42 | end 43 | 44 | it "should render edit form" do 45 | get "admin/#{route.id}/edit" 46 | expect(last_response).to be_ok 47 | expect(last_response.body).to match(/form action="\/admin\/#{route.id}\/edit", method="post"/) 48 | end 49 | 50 | it "should edit route" do 51 | post "admin/#{route.id}/edit", {route: {verb: 'post'}, active: 1} 52 | expect(last_response).to be_ok 53 | expect(last_response.body).to match(/POST<\/span>/) 54 | expect(last_response.body).to match(/\/me<\/strong>/) 55 | end 56 | 57 | it "should render error when edit route not valid" do 58 | post "admin/#{route.id}/edit", {route: {verb: 'wrong'}, active: 1} 59 | expect(last_response).to be_ok 60 | expect(last_response.body).to match(/Verb 目前只支持以下方法: get, post, put, delete, patch/) 61 | end 62 | 63 | it "should delete route" do 64 | delete "/admin/#{route.id}" 65 | expect(last_response).to be_ok 66 | expect(last_response.body).to match(/\/admin/) 67 | end 68 | 69 | it "should render error when destroy fail" do 70 | ApiMockServer::Endpoint.any_instance.stub(destroy: false) 71 | delete "/admin/#{route.id}" 72 | expect(last_response).to be_ok 73 | expect(last_response.body).to match(/\/admin\/#{route.id}/) 74 | end 75 | 76 | it "should render show page" do 77 | get "/admin/#{route.id}" 78 | expect(last_response).to be_ok 79 | expect(last_response.body).to match(/GET<\/span>/) 80 | expect(last_response.body).to match(/\/me<\/strong>/) 81 | end 82 | 83 | it "should render batch show page" do 84 | get "/admin/batch_show", pattern: route.pattern 85 | expect(last_response).to be_ok 86 | expect(last_response.body).to match(/GET<\/span>/) 87 | expect(last_response.body).to match(/\/me<\/strong>/) 88 | end 89 | end 90 | 91 | it "should access the created route" do 92 | get route.pattern 93 | 94 | expect(last_response.status).to eq route.status 95 | expect(last_response.body).to eq route.response 96 | end 97 | 98 | it "should match route with regexp *" do 99 | route = ApiMockServer::Endpoint.create(verb: 'get', pattern: '/me/*', response: '{"me": "*"}', status: 200) 100 | 101 | get "/me/1" 102 | 103 | expect(last_response).to be_ok 104 | expect(last_response.body).to eq route.response 105 | end 106 | 107 | context "Configurate" do 108 | before do 109 | ApiMockServer.setup do |config| 110 | config.top_namespace = "/api/v1" 111 | config.admin_user = "admin" 112 | config.admin_password = 'zlx' 113 | end 114 | end 115 | 116 | after do 117 | ApiMockServer.setup do |config| 118 | config.top_namespace = nil 119 | config.admin_user = nil 120 | config.admin_password = nil 121 | end 122 | end 123 | 124 | it "should match top namespace when config" do 125 | route = ApiMockServer::Endpoint.create(verb: 'get', pattern: '/me/*', response: '{"me": "*"}', status: 200) 126 | 127 | get "/api/v1#{route.pattern}" 128 | 129 | expect(last_response).to be_ok 130 | expect(last_response.body).to eq route.response 131 | end 132 | 133 | it "should not match url missing top namespace when config" do 134 | route = ApiMockServer::Endpoint.create(verb: 'get', pattern: '/me/*', response: '{"me": "*"}', status: 200) 135 | 136 | get route.pattern 137 | 138 | expect(last_response).to be_ok 139 | expect(last_response.body).to eq({error: "the route not exist now"}.to_json) 140 | end 141 | 142 | it "should config admin_user and admin_password" do 143 | authorize "admin", "zlx" 144 | 145 | get "/admin" 146 | 147 | expect(last_response).to be_ok 148 | end 149 | end 150 | end 151 | -------------------------------------------------------------------------------- /test/spec_helper.rb: -------------------------------------------------------------------------------- 1 | ENV['RACK_ENV'] = 'test' 2 | 3 | require File.join(File.dirname(__FILE__), '../boot') 4 | require 'rspec' 5 | require 'rack/test' 6 | 7 | RSpec.configure do |config| 8 | config.include Rack::Test::Methods 9 | end 10 | 11 | --------------------------------------------------------------------------------