├── .gitignore ├── LICENSE ├── README-en.md ├── README.MD ├── assets ├── alipay.png ├── baidu.png ├── dingding.png ├── tt.png └── wechat.png ├── exmaple ├── README.MD ├── api │ ├── index.js │ ├── requst.js │ └── wf.js ├── app.js ├── app.json ├── app.wxss ├── miniprogram_npm │ └── wefetch │ │ ├── index.js │ │ └── index.js.map ├── package-lock.json ├── package.json ├── pages │ ├── index │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ └── logs │ │ ├── logs.js │ │ ├── logs.json │ │ ├── logs.wxml │ │ └── logs.wxss ├── project.config.json ├── sitemap.json └── utils │ └── util.js ├── package-lock.json ├── package.json ├── rollup.config.js ├── server ├── app.js ├── bin │ └── www ├── package-lock.json ├── package.json ├── public │ └── stylesheets │ │ └── style.css ├── routes │ ├── index.js │ └── users.js └── views │ ├── error.jade │ ├── index.jade │ └── layout.jade ├── src └── lib │ ├── core │ ├── Events.js │ ├── Wefetch.js │ ├── addMethods.js │ ├── bind.js │ ├── dispatchRequest.js │ ├── functional.js │ ├── interceptorManager.js │ ├── platform.js │ ├── promisify.js │ └── request.js │ ├── defaults.js │ ├── utils.js │ └── wefetch.js └── wefetch ├── README.MD ├── dist └── wefetch.min.js ├── index.d.ts ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Editor directories and files 9 | .idea 10 | .vscode 11 | *.suo 12 | *.ntvs* 13 | *.njsproj 14 | *.sln -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README-en.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | 简体中文 | [English](https://github.com/jonnyshao/wefetch/blob/master/README-en.md) 2 | 3 | # wefetch 4 | [![install size](https://packagephobia.now.sh/badge?p=wefetch)](https://packagephobia.now.sh/result?p=wefetch) 5 | [![npm version](https://badgen.net/npm/v/wefetch?color=green)](https://www.npmjs.com/package/wefetch) 6 | [![gzip](https://badgen.net/badgesize/gzip/https://unpkg.com/wefetch@1.3.3/dist/wefetch.min.js)](https://unpkg.com/wefetch@1.3.2/dist/wefetch.min.js) 7 | [![downloads](https://badgen.net/npm/dm/wefetch)](https://www.npmtrends.com/wefetch) 8 | 9 | 基于Promise,链式编程。支持微信、支付宝、钉钉、头条、百度小程序 10 | ## 支持的小程序平台 11 | 12 | ![WeChat](https://github.com/jonnyshao/wefetch/blob/master/assets/wechat.png) | ![AliPay](https://github.com/jonnyshao/wefetch/blob/master/assets/alipay.png) | ![DingDing](https://github.com/jonnyshao/wefetch/blob/master/assets/dingding.png) | ![Baidu](https://github.com/jonnyshao/wefetch/blob/master/assets/baidu.png) | ![Toutiao](https://github.com/jonnyshao/wefetch/blob/master/assets/tt.png) | 13 | --- | --- | --- | --- | --- | 14 | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | 15 | 16 | ## 功能&&特点 17 | 18 | - 微信小程序 [wx.request](https://developers.weixin.qq.com/miniprogram/en/dev/api/network-request.html#wxrequestobject) API 19 | - 微信小程序 [wx.downloadFile](https://developers.weixin.qq.com/miniprogram/en/dev/api/network-file.html#wxdownloadfileobject) API 20 | - 微信小程序 [wx.uploadFile](https://developers.weixin.qq.com/miniprogram/en/dev/api/network-file.html#wxuploadfileobject) API 21 | - 支付宝小程序 [my.request](https://docs.alipay.com/mini/api/network#a-nameco0fvaamyhttprequest) API 22 | - 支付宝小程序 [my.uploadFile](https://docs.alipay.com/mini/api/network#a-namey24rltamyuploadfile) API 23 | - 支付宝小程序 [my.downloadFile](https://docs.alipay.com/mini/api/network#a-nameal4taaamydownloadfile) API 24 | - 头条小程序 [tt.request](https://developer.toutiao.com/docs/api/request.html) API 25 | - 头条小程序 [tt.downloadFile](https://developer.toutiao.com/docs/api/downloadFile.html) API 26 | - 头条小程序 [tt.uploadFile](https://developer.toutiao.com/docs/api/uploadFile.html) API 27 | - 百度小程序 [swan.request](https://smartprogram.baidu.com/docs/develop/api/net_request/#request/) API 28 | - 百度小程序 [swan.uploadFile](https://smartprogram.baidu.com/docs/develop/api/net_uploadfile/#uploadFile/) API 29 | - 百度小程序 [swan.downloadFile](https://smartprogram.baidu.com/docs/develop/api/net_uploadfile/#downloadFile/) API 30 | - 支持 [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) API 31 | - 请求、响应拦截管理 32 | - 支持小程序[RequestTask](https://developers.weixin.qq.com/miniprogram/dev/api/wx.request.html) 对象同步管理 33 | 34 | ## 安装 35 | 36 | ```js 37 | npm i wefetch 38 | ``` 39 | ## wefetch 封装示例(仅供参考) 40 | ```js 41 | const wf = require('wefetch'); 42 | 43 | class Request { 44 | // init 45 | constructor() { 46 | // 请求队列 47 | this.queue = {}; 48 | // 配置请求域名 49 | this.baseUrl = 'http://your-domain.com'; 50 | // 仅支付宝小程序支持 51 | this.timeout = 3000; 52 | // 创建 wefetch 实例 53 | this.instance = wf.create(); 54 | } 55 | // 参数合并 56 | merge(options) { 57 | return { ...options, baseUrl: this.baseUrl } 58 | } 59 | // 请求失败可设置再次请求 60 | // times 为尝试的次数 request为请求方法(必须返回一个Promise对象) timout 可选 默认1秒 61 | retry(times,request,timeout){ 62 | this.instance.retry(times,request,timeout) 63 | }, 64 | // 取消请求 或使用 wf.abort(event,callback) 65 | abort(event,callback){ 66 | this.instance.abort(event,callback) 67 | }, 68 | // 获取上传或下载进度 或使用wf.onProcess(event,handle) 69 | onProcess(event,cb){ 70 | this.instance.onProcess(event,cb) 71 | } 72 | // 设置拦截器 73 | interceptor(instance, url) { 74 | instance.before.use(req => { 75 | req.header.Authorization = 'type in your token'; 76 | if (Object.keys(this.queue).length === 0) { 77 | wx.showLoading({ 78 | title: 'Loading', 79 | mask: true 80 | }) 81 | } 82 | this.queue[url] = url; 83 | return req; 84 | }); 85 | instance.after.use(res => { 86 | delete this.queue[url] 87 | if (Object.keys(this.queue).length === 0) { 88 | wx.hideLoading() 89 | } 90 | return res; 91 | }) 92 | } 93 | // 执行 wefetch 实例 94 | request(options) { 95 | this.interceptor(this.instance, options.url) 96 | return this.instance(this.merge(options)); 97 | } 98 | } 99 | 100 | module.exports = new Request; 101 | ``` 102 | ## 示例 103 | 104 | 发送一个 `GET` 请求 105 | ```js 106 | const wf = require('wefetch') 107 | wx.showLoading({ 108 | title: '加载中...', 109 | mask: true 110 | }) 111 | wf.get('http://you-domain/api').then(res => { 112 | // .... 113 | }).catch(err => { 114 | // ... 115 | }) 116 | // 请求完成执行 117 | .finally(() => { 118 | wx.hideLoading() 119 | }) 120 | 121 | wf.get('/get', 122 | { 123 | data: { 124 | title: 'get Test', 125 | content: 'get' 126 | }, 127 | header: { Authorization: 'xxx' } 128 | }) 129 | .then(res => { 130 | // handle success 131 | console.log(res) 132 | }).catch(error => { 133 | // handle error 134 | console.log(error) 135 | }).then( _ => { 136 | // always executed 137 | }) 138 | ``` 139 | 发送一个 `POST` 请求 140 | ```js 141 | wf.post('/post',{data: { title: 'post test', content: 'post' }}) 142 | .then(res => { 143 | console.log(res) 144 | }).catch(err => { 145 | console.log(err) 146 | }) 147 | ``` 148 | 149 | 发送多个 `并发` 请求 150 | ```js 151 | const getUserInfo = prams => wf.get('/user/1', params) 152 | const getUserPermissions = params => wf.get('/user/1/permission', params) 153 | wf.all([getUserInfo(), getUserPermissions()]) 154 | .then(res => { 155 | // 所有请求完成后,将返回一个数组集合的Response 156 | }) 157 | ``` 158 | 159 | 发送一个 `上传` 请求 160 | ```js 161 | 162 | const chooseImage = wf.promisify(wx.chooseImage) 163 | // using for wechat Mini Program 164 | chooseImage().then(res => { 165 | wf.upload('/upload', { 166 | filePath: res.tempFilePaths[0], 167 | name:'file' 168 | }) 169 | .then(res =>{ 170 | console.log(res) 171 | }) 172 | }) 173 | chooseImage().then(res => { 174 | wf.upload({ 175 | url: '/upload', 176 | filePath: res.tempFilePaths[0], 177 | name:'file' 178 | }) 179 | .then(res =>{ 180 | console.log(res) 181 | }) 182 | }) 183 | ``` 184 | 185 | 发送一个 `下载` 请求 186 | ```js 187 | wf.download('/download') 188 | .then(res => { 189 | console.log(res) 190 | }) 191 | 192 | wf.download({ 193 | url:'/download' 194 | }) 195 | .then(res => { 196 | console.log(res) 197 | }) 198 | ``` 199 | ## 使用 async/await 200 | > async/await 是ECMAScript 2017规范中的,截止目前(2019.03)微信小程序还未支持, 在我们使用之前需要引入一个Facebook `regeneratorRuntime`的库 ,为了方便使用,已经单独抽离出来 201 | 202 | [wehcat-regenerator-runtime](https://github.com/jonnyshao/wehcat-regenerator-runtime) 203 | ```js 204 | const regeneratorRuntime = require('wehcat-regenerator-runtime'); 205 | 206 | // es6 write 207 | async onload () { 208 | let res = await wf.get('/get') 209 | console.log(res) 210 | 211 | // do something.... 212 | } 213 | 214 | // Es5 write 215 | onload: async function () { 216 | let res = await wf.get('/get') 217 | console.log(res) 218 | 219 | // do something.... 220 | } 221 | ``` 222 | ## 获取小程序`requestTask` 对象 223 | `get` 请求代码示例: 224 | ```js 225 | wf.get('/get',{config: {eventType: 'get'}}) 226 | 227 | // 取消请求 228 | wf.on('get', t => { 229 | t.abort() 230 | }) 231 | // 处理多个请求 232 | wf.get('/user/info',{ config: {eventType:'user'}},) 233 | wf.get('/user/permission',{ config: {eventType: 'user'}},) 234 | wf.on('user', t => { 235 | // 当前注册的user事件函数会执行两次,依次类推 236 | t.abort() 237 | }) 238 | ``` 239 | `上传` 请求代码示例: 240 | 241 | ```js 242 | // promisify 243 | const chooseImage = wf.promisify(wx.chooseImage) 244 | chooseImage().then(res => { 245 | wf.upload('http://your-domain/upload', { 246 | filePath: res.tempFilePaths[0], 247 | name: 'file', 248 | config: { eventType: 'upload'} 249 | }).then(res => { 250 | console.log(res) 251 | }); 252 | wf.on('upload', t => { 253 | t.onProgressUpdate((res) => { 254 | console.log('upload progress', res.progress) 255 | console.log('length of data already uploaded', res.totalBytesSent) 256 | console.log('total length of data expected to be uploaded', res.totalBytesExpectedToSend) 257 | }) 258 | }) 259 | }); 260 | // or like this: 261 | chooseImage().then(res => { 262 | wf.upload({ 263 | url: 'http://your-domain/upload', 264 | filePath: res.tempFilePaths[0], 265 | name: 'file', 266 | config: {eventType: 'upload'} 267 | }).then(res => { 268 | console.log(res) 269 | }); 270 | wf.on('upload', t => { 271 | t.onProgressUpdate((res) => { 272 | console.log('upload progress', res.progress) 273 | console.log('length of data already uploaded', res.totalBytesSent) 274 | console.log('total length of data expected to be uploaded', res.totalBytesExpectedToSend) 275 | }) 276 | }) 277 | }) 278 | ``` 279 | ## wefetch API 280 | API | 参数 | 类型 | 描述 | 支持的小程序 | 281 | :-: | :-: | :-: | :-: | :-: 282 | request | url/config | String/Object | 所有请求方法的基础方法 | 所有| 283 | before.use | [resolveCallback,rejectCallback] | [Function,Function] | wefetch中间件,HTTP请求拦截,可以统一配置Authorization... | 所有| 284 | after.use | [resolveCallback,rejectCallback] | [Function,Function] | wefetch中间件,HTTP响应拦截 ,可以统一处理数据格式...| 所有| 285 | get | [url,config]| [String,Object] | HTTP 请求 GET | 所有| 286 | post | [url,config]| [String,Object] | HTTP 请求 POST | 所有| 287 | head | [url,config]| [String,Object] | HTTP 请求 HEAD | 微信| 288 | connect | [url,config]| [String,Object] | HTTP 请求 CONNECT | 微信| 289 | put | [url,config]| [String,Object] | HTTP 请求 PUT | 微信| 290 | delete | [url,config]| [String,Object] | HTTP 请求 DELETE | 微信| 291 | trace | [url,config]| [String,Object] | HTTP 请求 TRACE | 微信| 292 | download | [url,config]/config| [String,Object]/Object | HTTP 请求 GET 小程序下载 | 所有| 293 | upload | [url,config]/config| [String,Object] /Object| HTTP 请求 POST 小程序上传 | 所有| 294 | on | [eventType,callback]| [String,Function] | 获取小程序RequestTask对象 | 所有| 295 | abort | [eventType,callback]| [String,Function] | 终断当前请求 | 所有| 296 | onProcess | [eventType,callback]| [String,Function] | 获取当前上传或下载时Process | 所有| 297 | retry | [times,request,timeout]| [Number,Function,Number] | times为次数,request必须返回Promise对象,timeout为间隔时间,默认为1秒 | 所有| 298 | finally | callback| Function | 当前请求完成后执行的方法| 所有| 299 | all | [request,request,...]| Array | 并发请求,请求全部完成后返回| 所有| 300 | 301 | > 默认 `Content-type` 是 各个平台小程序的默认值 302 | 303 | > 如果需要对`wf.request`进行封装,`上传` 需要配置 `method:upload`, `下载` 需要配置 `method:download` 304 | 305 | > 钉钉小程序 设置`Content-Type`为 `application/json` 时,需要对 data JSON.stringify()处理一下 306 | 307 | [钉钉官方文档说明](https://open-doc.dingtalk.com/microapp/dev/httprequest) 308 | 309 | 创建一个实例 310 | > 您可以创建实例,并自定义实例的配置 311 | ```js 312 | const instance = wf.create({ 313 | baseUrl: 'http://your-domain.com/api' 314 | //.... 315 | }) 316 | ``` 317 | 实例中的方法 318 | 319 | API | 参数 | 类型 | 描述 | 支持的小程序 | 320 | :-: | :-: | :-: | :-: | :-: 321 | request | url/config | String/Object | 所有请求方法的基础方法 | 所有| 322 | before.use | [resolveCallback,rejectCallback] | [Function,Function] | 不同的实例都可以拥有自己的拦截器| 所有| 323 | after.use | [resolveCallback,rejectCallback] | [Function,Function] | 不同的实例都可以拥有自己的拦截器 | 所有| 324 | get | [url,config]| [String,Object] | HTTP 请求 GET | 所有| 325 | post | [url,config]| [String,Object] | HTTP 请求 POST | 所有| 326 | head | [url,config]| [String,Object] | HTTP 请求 HEAD | 微信| 327 | connect | [url,config]| [String,Object] | HTTP 请求 CONNECT | 微信| 328 | put | [url,config]| [String,Object] | HTTP 请求 PUT | 微信| 329 | delete | [url,config]| [String,Object] | HTTP 请求 DELETE | 微信| 330 | trace | [url,config]| [String,Object] | HTTP 请求 TRACE | 微信| 331 | download | [url,config]/config| [String,Object]/Object | HTTP 请求 GET 小程序下载 | 所有| 332 | upload | [url,config]/config| [String,Object] /Object| HTTP 请求 POST 小程序上传 | 所有| 333 | on | [eventType,callback]| [String,Function] | 获取小程序RequestTask对象 | 所有| 334 | abort | [eventType,callback]| [String,Function] | 终断当前请求 | 所有| 335 | onProcess | [eventType,callback]| [String,Function] | 获取当前上传或下载时Process | 所有| 336 | retry | [times,request,timeout]| [Number,Function,Number] | 同上 | 所有| 337 | finally | callback| Function | 当前请求完成后执行的方法| 所有| 338 | all | [request,request,...]| Array | 并发请求,请求全部完成后返回| 所有| 339 | 340 | 341 | ## 请求参数配置 342 | ```js 343 | { 344 | // `url` 服务器请求路径 345 | url: '/user', 346 | 347 | // `baseURL` 与 `url` 会合并一个完整的 url, `baseURl` 将会在 `url` 前面 348 | baseUrl:'http://your-domain.com/api', 349 | 350 | // 默认请求 `get` 351 | method: 'get', 352 | /* 353 | * 如果您的项目请求路径、上传路径、下载路径都不一样的情况下,可以单独对`uploadUrl` and `downloadUrl`进行全局设置 354 | * */ 355 | uploadUrl:'http://your-domain.com/upload', 356 | 357 | downloadUrl: 'http://your-domain.com/download', 358 | 359 | // 仅支付宝小程序支持 360 | timeout: 0, 361 | // 后台需要的参数 362 | data: {}, 363 | // 在wefetch中,可以注册一个自定义事件,用来同步管理小程序的requestTask对象,`eventType` 是注册事件时自定义的事件名称 364 | config:{ 365 | eventType: '' 366 | } 367 | // 默认的 `Content-Type` 368 | header: {} 369 | } 370 | ``` 371 | ## 配置默认参数 372 | 373 | **全局的 wefetch 默认参数** 374 | ```js 375 | wf.defaults.baseUrl = 'http://your-domain.com/api'; 376 | wf.defaults.uploadUrl = 'http://your-domain.com/upload'; 377 | wf.defaults.downloadUrl = 'http://your-domain.com/download'; 378 | ``` 379 | **自定义实例的参数** 380 | ```js 381 | const instance = wf.create() 382 | instance.defaults.baseUrl = 'http://your-domain.com/api'; 383 | instance.defaults.uploadUrl = 'http://your-domain.com/upload'; 384 | instance.defaults.downloadUrl = 'http://your-domain.com/download'; 385 | ``` 386 | ## 拦截器 387 | > 不同的实例都可以拥有自己的拦截器 388 | ```js 389 | // 注册一个请求拦截器 390 | wf.before.use(request => { 391 | // Do something before request is sent 392 | return request; 393 | }, error => { 394 | // Do something with request error 395 | return Promise.reject(error); 396 | }) 397 | 398 | // 注册一个响应拦截器 399 | wf.after.use(response => { 400 | // Do something with response data 401 | return response; 402 | }, error => { 403 | // Do something with response error 404 | return Promise.reject(error) 405 | }) 406 | ``` 407 | 408 | ## promise化小程序的api 409 | ```js 410 | const chooseImage = wf.promisify(wx.chooseImage) 411 | // using in wechat Mini Program 412 | chooseImage().then(res => { 413 | // Do something ... 414 | console.log(res) 415 | }) 416 | ``` 417 | -------------------------------------------------------------------------------- /assets/alipay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shawn633/wefetch/5dfc3be3bc493d1a247827266cbdaf99dcd04ce5/assets/alipay.png -------------------------------------------------------------------------------- /assets/baidu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shawn633/wefetch/5dfc3be3bc493d1a247827266cbdaf99dcd04ce5/assets/baidu.png -------------------------------------------------------------------------------- /assets/dingding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shawn633/wefetch/5dfc3be3bc493d1a247827266cbdaf99dcd04ce5/assets/dingding.png -------------------------------------------------------------------------------- /assets/tt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shawn633/wefetch/5dfc3be3bc493d1a247827266cbdaf99dcd04ce5/assets/tt.png -------------------------------------------------------------------------------- /assets/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shawn633/wefetch/5dfc3be3bc493d1a247827266cbdaf99dcd04ce5/assets/wechat.png -------------------------------------------------------------------------------- /exmaple/README.MD: -------------------------------------------------------------------------------- 1 | # download 2 | ```js 3 | 4 | git clone https://github.com/jonnyshao/wefetch.git 5 | 6 | cd wefetch/server 7 | 8 | npm i 9 | 10 | npm start 11 | 12 | cd wefetch/exmaple 13 | 14 | npm i 15 | 16 | ``` 17 | -------------------------------------------------------------------------------- /exmaple/api/index.js: -------------------------------------------------------------------------------- 1 | const wf = require('./requst.js') 2 | export const get = (data,config) => { 3 | return wf.request({ 4 | url: '/get', 5 | data,config 6 | }) 7 | } 8 | export const post = (data,config) => { 9 | return wf.request({ 10 | url: '/post', 11 | method:'post', 12 | data, config 13 | }) 14 | } 15 | export const postJson = (data,config) => { 16 | return wf.request({ 17 | url: '/postJson', 18 | method: 'postJson', 19 | data, config 20 | }) 21 | } 22 | export const head = (data,config) => { 23 | return wf.request({ 24 | url: '/head', 25 | method: 'head', 26 | data, config 27 | }) 28 | } 29 | export const download = (data,config) => { 30 | return wf.request({ 31 | url:'https://github.com/jonnyshao/wefetch/archive/v1.2.4.zip', 32 | method: 'download', 33 | data, 34 | config, 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /exmaple/api/requst.js: -------------------------------------------------------------------------------- 1 | const wf = require('./wf.js'); 2 | class Request { 3 | constructor() { 4 | this.queue = {}; 5 | this.baseUrl = 'http://localhost:3000'; 6 | this.timeout = 3000; 7 | this.instance = wf.create(); 8 | } 9 | merge(options) { 10 | return { ...options, baseUrl: this.baseUrl } 11 | 12 | } 13 | setInterceptor(instance, url) { 14 | instance.before.use(req => { 15 | console.log('request--parmas', req) 16 | req.header.authorization = 'type in your token'; 17 | if (Object.keys(this.queue).length === 0) { 18 | const type = req.config.eventType 19 | if (type) { 20 | wf.onProcess(type, res => { 21 | wx.showLoading({ 22 | title: `下载进度:${res.progress}%`, 23 | mask: true 24 | }) 25 | }) 26 | } else { 27 | wx.showLoading({ 28 | title: 'Loading', 29 | mask: true 30 | }) 31 | } 32 | 33 | } 34 | this.queue[url] = url; 35 | return req; 36 | }); 37 | instance.after.use(res => { 38 | delete this.queue[url] 39 | if (Object.keys(this.queue).length === 0) { 40 | wx.hideLoading() 41 | } 42 | console.log('response', res) 43 | return res; 44 | }) 45 | } 46 | request(options) { 47 | this.setInterceptor(this.instance, options.url) 48 | return this.instance(this.merge(options)); 49 | } 50 | } 51 | 52 | module.exports = new Request; 53 | -------------------------------------------------------------------------------- /exmaple/api/wf.js: -------------------------------------------------------------------------------- 1 | /* 2 | Promise based wx.request api for Mini Program 3 | @Github https://github.com/jonnyshao/wechat-fetch 4 | wefetch beta v1.3.4 |(c) 2018-2019 By Jonny Shao 5 | */ 6 | (function (global, factory) { 7 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 8 | typeof define === 'function' && define.amd ? define(factory) : 9 | (global = global || self, global.wefetch = factory()); 10 | }(this, (function () { 'use strict'; 11 | 12 | function Events() { 13 | this.listeners = {}; 14 | } 15 | 16 | Events.prototype.on = function (type, cb) { 17 | if (!(type in this.listeners)) { 18 | this.listeners[type] = []; 19 | } 20 | this.listeners[type].push(cb); 21 | }; 22 | 23 | Events.prototype.emit = function (type, task) { 24 | var listener = this.listeners[type]; 25 | if (listener) { 26 | listener.forEach(function (h) { 27 | h(task); 28 | }); 29 | } 30 | }; 31 | 32 | var e = new Events(); 33 | 34 | function promisify (api) { 35 | return function (options) { 36 | options = options || {}; 37 | options.config = options.config || {}; 38 | for (var len = arguments.length, params = Array(len > 1 ? len - 1 : 0), key = 1; key < len; key++) { 39 | params[key - 1] = arguments[key]; 40 | } 41 | return new Promise(function (resolve, reject) { 42 | options.config.eventType ? e.emit(options.config.eventType, api.apply(undefined, [Object.assign({}, options, {success: resolve, fail: reject})].concat(params))) 43 | : api.apply(undefined, [Object.assign({}, options, {success: resolve, fail: reject})].concat(params)); 44 | }) 45 | }; 46 | } 47 | 48 | function Platform() { 49 | this.platform = null; 50 | this.api = null; 51 | } 52 | Platform.prototype.getRequest = function () { 53 | if (typeof wx !== 'undefined') { 54 | this.platform = 'wx'; 55 | this.api = wx; 56 | return promisify(wx.request) 57 | } else if (typeof my !== 'undefined') { 58 | this.platform = 'my'; 59 | this.api = my; 60 | return my.request ? promisify(my.request) : promisify(my.httpRequest) 61 | } else if (typeof tt !== 'undefined') { 62 | this.api = tt; 63 | this.platform = 'tt'; 64 | return promisify(tt.request) 65 | } else if (typeof swan !== 'undefined') { 66 | this.api = swan; 67 | this.platform = 'swan'; 68 | return promisify(swan.request) 69 | } 70 | }; 71 | Platform.prototype.getUpload = function () { 72 | return promisify(this.api.uploadFile); 73 | }; 74 | Platform.prototype.getDownload = function () { 75 | return promisify(this.api.downloadFile); 76 | }; 77 | var platform = new Platform(); 78 | 79 | var defaults = { 80 | createRequest: platform.getRequest(), 81 | header: {}, 82 | config: {}, 83 | method: 'get', 84 | timeout: 0 85 | }; 86 | 87 | function bind(fn, context) { 88 | return function wf (){ 89 | var args = new Array(arguments.length); 90 | for (var i = 0, l = args.length; i < l; i++) { 91 | args[i] = arguments[i]; 92 | } 93 | return fn.apply(context, args) 94 | } 95 | } 96 | 97 | var tostring = Object.prototype.toString; 98 | var utils = { 99 | type: (function () { 100 | var type = {}; 101 | var typeAry = ['String', 'Object', 'Number', 'Array', 'Undefined', 'Function', 'Null', 'Date']; 102 | for (var i = 0, len = typeAry.length; i < len; i++) { 103 | (function (name) { 104 | type['is' + name] = function (obj) { 105 | return tostring.call(obj) === '[object' +' '+ name + ']'; 106 | }; 107 | })(typeAry[i]); 108 | } 109 | return type; 110 | })(), 111 | normalizeHeaderName: function (header) { 112 | for (var key in header) { 113 | if (/Content-Type/ig.test(key)){ 114 | header['Content-Type'] = header[key]; 115 | delete header[key]; 116 | } 117 | } 118 | }, 119 | forEach: function (obj, fn) { 120 | if (!obj) { 121 | return; 122 | } 123 | if (typeof obj !== 'object') { 124 | obj = [obj]; 125 | } 126 | if (this.type.isArray(obj)) { 127 | for (var i = 0, l = obj.length; i < l; i++) { 128 | fn.call(null, obj[i], i, obj); 129 | } 130 | } else { 131 | for (var k in obj) { 132 | if (Object.prototype.hasOwnProperty.call(obj, k)) { 133 | fn.call(null, obj[k], k, obj); 134 | } 135 | } 136 | } 137 | }, 138 | merge: function () { 139 | var result = {}; 140 | function assignValue(val, key) { 141 | if (typeof result[key] === 'object' && typeof val === 'object') { 142 | result[key] = utils.merge(result[key], val); 143 | } else { 144 | result[key] = val; 145 | } 146 | } 147 | for (var i = 0, l = arguments.length; i < l; i++) { 148 | this.forEach(arguments[i], assignValue); 149 | } 150 | return result; 151 | }, 152 | deepMerge: function() { 153 | var result = {}; 154 | function assignValue(val, key) { 155 | if (typeof result[key] === 'object' && typeof val === 'object') { 156 | result[key] = utils.deepMerge(result[key], val); 157 | } else if (typeof val === 'object'){ 158 | result[key] = utils.deepMerge({},val); 159 | } else { 160 | result[key] = val; 161 | } 162 | } 163 | for (var i = 0, l = arguments.length; i < l; i++) { 164 | this.forEach(arguments[i], assignValue); 165 | } 166 | return result; 167 | }, 168 | mergeConfig: function(source,target){ 169 | var c = {}; target = target || {}; 170 | ['url','method', 'data','config'].forEach(function (prop) { 171 | if (target[prop]){ 172 | c[prop] = target[prop]; 173 | } 174 | }); 175 | ['header','headers'].forEach(function (prop) { 176 | if (utils.type.isObject(target[prop])){ 177 | c[prop] = utils.deepMerge(source[prop],target[prop]); 178 | } else if(target[prop]){ 179 | c[prop] = target[prop]; 180 | } else if(utils.type.isObject(source[prop])){ 181 | c[prop] = utils.deepMerge(source[prop]); 182 | } else if (source[prop]){ 183 | c[prop] = source[prop]; 184 | } 185 | }); 186 | ['baseUrl','timeout','eventType','createRequest'].forEach(function (prop) { 187 | if (target[prop] !== undefined){ 188 | c[prop] = target[prop]; 189 | } else if (source[prop] !== undefined){ 190 | c[prop] = source[prop]; 191 | } 192 | }); 193 | return c 194 | }, 195 | extends: function (extendObj, copyObj, thisArg) { 196 | this.forEach(copyObj, function (val, key) { 197 | if (thisArg && typeof val === 'function') { 198 | extendObj[key] = bind(val, thisArg); 199 | } else { 200 | extendObj[key] = val; 201 | } 202 | }); 203 | return extendObj; 204 | } 205 | }; 206 | 207 | function InterceptorManager() { 208 | this.handles = []; 209 | } 210 | 211 | InterceptorManager.prototype.use = function (fulfilled, rejected) { 212 | this.handles.push({ fulfilled: fulfilled, rejected: rejected }); 213 | return this.handles.length - 1; 214 | }; 215 | 216 | 217 | InterceptorManager.prototype.eject = function (id) { 218 | if (this.handles[id]) { 219 | this.handles[id] = null; 220 | } 221 | 222 | }; 223 | InterceptorManager.prototype.forEach = function (fn) { 224 | this.handles.forEach(function (h) { 225 | h && fn(h); 226 | }); 227 | }; 228 | 229 | function dispatchRequest(config) { 230 | utils.normalizeHeaderName(config.header || config.headers); 231 | if (config.method === 'download') { 232 | config.method = 'get'; 233 | config.createRequest = platform.getDownload(); 234 | } 235 | if (config.method === 'upload'){ 236 | config.method = 'post'; 237 | config.createRequest = platform.getUpload(); 238 | } 239 | var request = config.createRequest; 240 | return request(config).then(function (response) { 241 | return response; 242 | }, function (reason) { 243 | return Promise.reject(reason) 244 | }) 245 | } 246 | 247 | function request (config) { 248 | if (typeof config === 'string') { 249 | config = arguments[1] || {}; 250 | config.url = arguments[0]; 251 | } 252 | config = utils.mergeConfig(this.defaults, config); 253 | if (config.url.indexOf('http') === -1) { 254 | if (config.downloadUrl && config.method === 'download') { 255 | config.url = config.downloadUrl + config.url; 256 | } else if (config.uploadUrl && config.method === 'upload') { 257 | config.url = config.uploadUrl + config.url; 258 | } else { //(config.baseUrl) 259 | config.url = config.baseUrl + config.url; 260 | } 261 | } 262 | // 阿里系的header是复数 263 | if (platform.platform === 'my' ) { 264 | if (config.method !== 'download' && config.method !== 'upload') { 265 | config.headers = Object.assign({}, config.header); 266 | delete config.header; 267 | } 268 | } 269 | var chain = [dispatchRequest, undefined]; 270 | var promise = Promise.resolve(config); 271 | this.before.forEach(function (interceptor) { 272 | chain.unshift(interceptor.fulfilled, interceptor.rejected); 273 | }); 274 | this.after.forEach(function (interceptor) { 275 | chain.push(interceptor.fulfilled, interceptor.rejected); 276 | }); 277 | while (chain.length) { 278 | promise = promise.then(chain.shift(), chain.shift()); 279 | } 280 | return promise; 281 | } 282 | 283 | ['options', 'get', 'head', 'post', 'put', 'delete', 'trace', 'connect'].forEach(function (method) { 284 | WeFetch.prototype[method] = function (url, config) { 285 | return this.request(utils.merge(config || {}, { 286 | url: url, 287 | method: method 288 | })) 289 | }; 290 | }); 291 | WeFetch.prototype.download = function (url, config) { 292 | // wf.download({}) support 293 | if (utils.type.isObject(url)) { 294 | return this.request(utils.merge(url,{ method: 'download' })) 295 | } 296 | // default 297 | return this.request(utils.merge(config || {},{ 298 | url: url, 299 | method: 'download' 300 | })) 301 | }; 302 | 303 | WeFetch.prototype.upload = function (url, config) { 304 | // upload({}) support 305 | if (utils.type.isObject(url)) { 306 | return this.request(url,{ method: 'upload' }) 307 | } 308 | return this.request(utils.merge(config || {}, { 309 | url: url, 310 | method: 'upload' 311 | })) 312 | }; 313 | 314 | function WeFetch(instanceConfig) { 315 | this.defaults = instanceConfig; 316 | this.before = new InterceptorManager(); 317 | this.after = new InterceptorManager(); 318 | } 319 | 320 | WeFetch.prototype.on = function (event, cb) { 321 | e.on(event, cb); 322 | }; 323 | WeFetch.prototype.abort = function (event, cb) { 324 | this.on(event, function (t) { 325 | t.abort(); 326 | cb && cb(); 327 | }); 328 | }; 329 | WeFetch.prototype.onProcess = function (event, cb) { 330 | this.on(event, function (t) { 331 | t.onProgressUpdate(cb); 332 | }); 333 | }; 334 | WeFetch.prototype.promisify = promisify; 335 | WeFetch.prototype.request = request; 336 | 337 | function retry(times,request,timeout) { 338 | timeout = timeout || 1000; 339 | if (!times && times !== 0 || !request)throw new Error('request and times params is required'); 340 | if (typeof request !== 'function') throw new Error('request must be a function, but got a\n'+ typeof request); 341 | var p = request(); 342 | if (times > 1) { 343 | times --; 344 | return new Promise(function(resolve, reject) { 345 | p.then(resolve).catch(function () { 346 | setTimeout(function() { 347 | resolve(retry(times, request, timeout)); 348 | }, timeout); 349 | }); 350 | }) 351 | } 352 | return p; 353 | } 354 | 355 | Promise.prototype.finally = Promise.prototype.finally || function (cb) { 356 | var p = this.constructor; 357 | return this.then(function (value) { 358 | p.resolve(cb(value)).then(function () { 359 | return value 360 | }); 361 | }, function (reason) { 362 | p.resolve(cb(reason)).then(function () { 363 | return Promise.reject(reason) 364 | }); 365 | }) 366 | }; 367 | 368 | function createInstance(defaultConfig) { 369 | var context = new WeFetch(defaultConfig); 370 | var instance = bind(WeFetch.prototype.request, context); 371 | utils.extends(instance, WeFetch.prototype, context); 372 | utils.extends(instance, context); 373 | return instance; 374 | } 375 | var wf = createInstance(defaults); 376 | 377 | wf.all = function (promises) { 378 | return Promise.all(promises) 379 | }; 380 | wf.retry = retry; 381 | wf.create = function (instanceConfig) { 382 | return createInstance(utils.merge(defaults, instanceConfig)) 383 | }; 384 | 385 | return wf; 386 | 387 | }))); 388 | -------------------------------------------------------------------------------- /exmaple/app.js: -------------------------------------------------------------------------------- 1 | //app.js 2 | // const wf = require('wefetch') 3 | App({ 4 | onLaunch: function () { 5 | // 展示本地存储能力 6 | var logs = wx.getStorageSync('logs') || [] 7 | logs.unshift(Date.now()) 8 | wx.setStorageSync('logs', logs) 9 | 10 | // 登录 11 | wx.login({ 12 | success: res => { 13 | // 发送 res.code 到后台换取 openId, sessionKey, unionId 14 | } 15 | }) 16 | // 获取用户信息 17 | wx.getSetting({ 18 | success: res => { 19 | console.log(res) 20 | if (res.authSetting['scope.userInfo']) { 21 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 22 | wx.getUserInfo({ 23 | success: res => { 24 | console.log(res) 25 | // 可以将 res 发送给后台解码出 unionId 26 | this.globalData.userInfo = res.userInfo 27 | 28 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 29 | // 所以此处加入 callback 以防止这种情况 30 | if (this.userInfoReadyCallback) { 31 | this.userInfoReadyCallback(res) 32 | } 33 | } 34 | }) 35 | } 36 | } 37 | }) 38 | }, 39 | globalData: { 40 | userInfo: null 41 | } 42 | }) -------------------------------------------------------------------------------- /exmaple/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | "pages/index/index", 4 | "pages/logs/logs" 5 | ], 6 | "window": { 7 | "backgroundTextStyle": "light", 8 | "navigationBarBackgroundColor": "#fff", 9 | "navigationBarTitleText": "WeChat", 10 | "navigationBarTextStyle": "black" 11 | }, 12 | "sitemapLocation": "sitemap.json" 13 | } -------------------------------------------------------------------------------- /exmaple/app.wxss: -------------------------------------------------------------------------------- 1 | /**app.wxss**/ 2 | .container { 3 | height: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | justify-content: space-between; 8 | padding: 200rpx 0; 9 | box-sizing: border-box; 10 | } 11 | -------------------------------------------------------------------------------- /exmaple/miniprogram_npm/wefetch/index.js: -------------------------------------------------------------------------------- 1 | module.exports = (function() { 2 | var __MODS__ = {}; 3 | var __DEFINE__ = function(modId, func, req) { var m = { exports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; }; 4 | var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = { exports: {} }; __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); if(typeof m.exports === "object") { Object.keys(m.exports).forEach(function(k) { __MODS__[modId].m.exports[k] = m.exports[k]; }); if(m.exports.__esModule) Object.defineProperty(__MODS__[modId].m.exports, "__esModule", { value: true }); } else { __MODS__[modId].m.exports = m.exports; } } return __MODS__[modId].m.exports; }; 5 | var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } }; 6 | var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; }; 7 | __DEFINE__(1558338760201, function(require, module, exports) { 8 | module.exports = require('./dist/wefetch.min.js') 9 | }, function(modId) {var map = {"./dist/wefetch.min.js":1558338760202}; return __REQUIRE__(map[modId], modId); }) 10 | __DEFINE__(1558338760202, function(require, module, exports) { 11 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).wefetch=t()}(this,function(){function e(){this.listeners={}}e.prototype.on=function(e,t){e in this.listeners||(this.listeners[e]=[]),this.listeners[e].push(t)},e.prototype.emit=function(e,t){var n=this.listeners[e];n&&n.forEach(function(e){e(t)})};var i=new e;function t(r){return function(n){n=n||{};for(var e=arguments.length,o=Array(1 { 6 | console.log(req) 7 | return req 8 | }) 9 | wf.after.use(res => { 10 | console.log(res) 11 | return res 12 | }) 13 | wf.get('/get', { data: { title: '标题' },header:{title: 'this is a title'},config:{eventType: 'user'} }) 14 | //获取应用实例 15 | const app = getApp() 16 | 17 | Page({ 18 | data: { 19 | motto: 'Hello World', 20 | userInfo: {}, 21 | hasUserInfo: false, 22 | canIUse: wx.canIUse('button.open-type.getUserInfo') 23 | }, 24 | //事件处理函数 25 | bindViewTap: function() { 26 | wx.navigateTo({ 27 | url: '../logs/logs' 28 | }) 29 | }, 30 | // get 请求 31 | getRequest(){ 32 | // get({title: 'this is a get request'},{eventType:'get'}).then(() =>{ 33 | // console.log('get request') 34 | // }) 35 | wf.get('/get',{data:{title: 'title'},config:{eventTyep: 'get'},header: { 36 | Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTAyLCJ1c2VybmFtZSI6IjEzOTE2NzM5OTM4IiwiY29tcGFueSI6MTEsImlhdCI6MTU1Nzg0MTUyOSwiZXhwIjoxNTU4NDQ2MzI5fQ.7JcYLazsriB6PXENOpuVQk-dki7cOIdErPPFYIX6y6U' 37 | }}) 38 | }, 39 | // post 请求 40 | postRequest(){ 41 | post({ title: 'this is a post request' }).then(() =>{ 42 | console.log('post request') 43 | }) 44 | }, 45 | // postJson 请求 46 | postJsonRequest() { 47 | return new Promise((resolve,reject) => { 48 | postJson({ title: 'this is a postJson Request' },{ 49 | eventType: 'postJson', 50 | }).then(res => { 51 | console.log('postJsonRequest') 52 | // 失败重新建立连接 53 | reject(res) 54 | }) 55 | wf.on('postJson', t => { 56 | console.log(t) 57 | }) 58 | }) 59 | }, 60 | // head 请求 61 | headRequest() { 62 | head({title: 'this is a head Request'}).then(() => { 63 | console.log('head Request') 64 | }) 65 | }, 66 | // 下载 67 | downlaodRequest() { 68 | download({}, { eventType: 'download'}).then((res) => { 69 | console.log('download request') 70 | console.log(res) 71 | }) 72 | 73 | }, 74 | // retry 请求 75 | retryRequest(){ 76 | wf.retry(3, this.postJsonRequest,2000).then(data => { 77 | console.log(data) 78 | }).catch(err => { 79 | console.log(err) 80 | }) 81 | }, 82 | onLoad: function () { 83 | if (app.globalData.userInfo) { 84 | this.setData({ 85 | userInfo: app.globalData.userInfo, 86 | hasUserInfo: true 87 | }) 88 | } else if (this.data.canIUse){ 89 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 90 | // 所以此处加入 callback 以防止这种情况 91 | app.userInfoReadyCallback = res => { 92 | this.setData({ 93 | userInfo: res.userInfo, 94 | hasUserInfo: true 95 | }) 96 | } 97 | } else { 98 | // 在没有 open-type=getUserInfo 版本的兼容处理 99 | wx.getUserInfo({ 100 | success: res => { 101 | app.globalData.userInfo = res.userInfo 102 | this.setData({ 103 | userInfo: res.userInfo, 104 | hasUserInfo: true 105 | }) 106 | } 107 | }) 108 | } 109 | }, 110 | getUserInfo: function(e) { 111 | console.log(e) 112 | app.globalData.userInfo = e.detail.userInfo 113 | this.setData({ 114 | userInfo: e.detail.userInfo, 115 | hasUserInfo: true 116 | }) 117 | } 118 | }) 119 | -------------------------------------------------------------------------------- /exmaple/pages/index/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | } 4 | } -------------------------------------------------------------------------------- /exmaple/pages/index/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | Get request 3 | 4 | 5 | Post request 6 | 7 | 8 | PostJson request 9 | 10 | 11 | Head request 12 | 13 | 14 | Downlaod Reqeust 15 | 16 | 17 | retry 3 Reqeust 18 | -------------------------------------------------------------------------------- /exmaple/pages/index/index.wxss: -------------------------------------------------------------------------------- 1 | .example-row{ 2 | text-align: center; 3 | height: 50px; 4 | line-height: 50px; 5 | box-sizing: border-box; 6 | border-bottom: 1px solid #eee; 7 | font-size: 14px; 8 | } 9 | .example-row-text{ 10 | font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif 11 | } -------------------------------------------------------------------------------- /exmaple/pages/logs/logs.js: -------------------------------------------------------------------------------- 1 | //logs.js 2 | const util = require('../../utils/util.js') 3 | 4 | Page({ 5 | data: { 6 | logs: [] 7 | }, 8 | onLoad: function () { 9 | this.setData({ 10 | logs: (wx.getStorageSync('logs') || []).map(log => { 11 | return util.formatTime(new Date(log)) 12 | }) 13 | }) 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /exmaple/pages/logs/logs.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "查看启动日志", 3 | "usingComponents": {} 4 | } -------------------------------------------------------------------------------- /exmaple/pages/logs/logs.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{index + 1}}. {{log}} 5 | 6 | 7 | -------------------------------------------------------------------------------- /exmaple/pages/logs/logs.wxss: -------------------------------------------------------------------------------- 1 | .log-list { 2 | display: flex; 3 | flex-direction: column; 4 | padding: 40rpx; 5 | } 6 | .log-item { 7 | margin: 10rpx; 8 | } 9 | -------------------------------------------------------------------------------- /exmaple/project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件", 3 | "packOptions": { 4 | "ignore": [] 5 | }, 6 | "setting": { 7 | "urlCheck": false, 8 | "es6": true, 9 | "postcss": true, 10 | "minified": true, 11 | "newFeature": true, 12 | "autoAudits": false 13 | }, 14 | "compileType": "miniprogram", 15 | "libVersion": "2.11.0", 16 | "appid": "wx5bc84faf20ed0930", 17 | "projectname": "wefetch-example", 18 | "debugOptions": { 19 | "hidedInDevtools": [] 20 | }, 21 | "isGameTourist": false, 22 | "simulatorType": "wechat", 23 | "simulatorPluginLibVersion": {}, 24 | "condition": { 25 | "search": { 26 | "current": -1, 27 | "list": [] 28 | }, 29 | "conversation": { 30 | "current": -1, 31 | "list": [] 32 | }, 33 | "game": { 34 | "currentL": -1, 35 | "list": [] 36 | }, 37 | "miniprogram": { 38 | "current": -1, 39 | "list": [] 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /exmaple/sitemap.json: -------------------------------------------------------------------------------- 1 | { 2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", 3 | "rules": [{ 4 | "action": "allow", 5 | "page": "*" 6 | }] 7 | } -------------------------------------------------------------------------------- /exmaple/utils/util.js: -------------------------------------------------------------------------------- 1 | const formatTime = date => { 2 | const year = date.getFullYear() 3 | const month = date.getMonth() + 1 4 | const day = date.getDate() 5 | const hour = date.getHours() 6 | const minute = date.getMinutes() 7 | const second = date.getSeconds() 8 | 9 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') 10 | } 11 | 12 | const formatNumber = n => { 13 | n = n.toString() 14 | return n[1] ? n : '0' + n 15 | } 16 | 17 | module.exports = { 18 | formatTime: formatTime 19 | } 20 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wefetch", 3 | "version": "1.1.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.0.0", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", 10 | "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.0.0" 14 | } 15 | }, 16 | "@babel/highlight": { 17 | "version": "7.0.0", 18 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", 19 | "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", 20 | "dev": true, 21 | "requires": { 22 | "chalk": "^2.0.0", 23 | "esutils": "^2.0.2", 24 | "js-tokens": "^4.0.0" 25 | } 26 | }, 27 | "@types/estree": { 28 | "version": "0.0.39", 29 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", 30 | "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", 31 | "dev": true 32 | }, 33 | "@types/node": { 34 | "version": "10.12.24", 35 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.24.tgz", 36 | "integrity": "sha512-GWWbvt+z9G5otRBW8rssOFgRY87J9N/qbhqfjMZ+gUuL6zoL+Hm6gP/8qQBG4jjimqdaNLCehcVapZ/Fs2WjCQ==", 37 | "dev": true 38 | }, 39 | "acorn": { 40 | "version": "6.4.1", 41 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", 42 | "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", 43 | "dev": true 44 | }, 45 | "ansi-styles": { 46 | "version": "3.2.1", 47 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 48 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 49 | "dev": true, 50 | "requires": { 51 | "color-convert": "^1.9.0" 52 | } 53 | }, 54 | "chalk": { 55 | "version": "2.4.2", 56 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 57 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 58 | "dev": true, 59 | "requires": { 60 | "ansi-styles": "^3.2.1", 61 | "escape-string-regexp": "^1.0.5", 62 | "supports-color": "^5.3.0" 63 | } 64 | }, 65 | "color-convert": { 66 | "version": "1.9.3", 67 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 68 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 69 | "dev": true, 70 | "requires": { 71 | "color-name": "1.1.3" 72 | } 73 | }, 74 | "color-name": { 75 | "version": "1.1.3", 76 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 77 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 78 | "dev": true 79 | }, 80 | "commander": { 81 | "version": "2.17.1", 82 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", 83 | "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", 84 | "dev": true 85 | }, 86 | "core-util-is": { 87 | "version": "1.0.2", 88 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 89 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 90 | "dev": true 91 | }, 92 | "escape-string-regexp": { 93 | "version": "1.0.5", 94 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 95 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 96 | "dev": true 97 | }, 98 | "esutils": { 99 | "version": "2.0.2", 100 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 101 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 102 | "dev": true 103 | }, 104 | "has-flag": { 105 | "version": "3.0.0", 106 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 107 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 108 | "dev": true 109 | }, 110 | "inherits": { 111 | "version": "2.0.3", 112 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 113 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 114 | "dev": true 115 | }, 116 | "isarray": { 117 | "version": "1.0.0", 118 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 119 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 120 | "dev": true 121 | }, 122 | "jest-worker": { 123 | "version": "24.0.0", 124 | "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.0.0.tgz", 125 | "integrity": "sha512-s64/OThpfQvoCeHG963MiEZOAAxu8kHsaL/rCMF7lpdzo7vgF0CtPml9hfguOMgykgH/eOm4jFP4ibfHLruytg==", 126 | "dev": true, 127 | "requires": { 128 | "merge-stream": "^1.0.1", 129 | "supports-color": "^6.1.0" 130 | }, 131 | "dependencies": { 132 | "supports-color": { 133 | "version": "6.1.0", 134 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", 135 | "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", 136 | "dev": true, 137 | "requires": { 138 | "has-flag": "^3.0.0" 139 | } 140 | } 141 | } 142 | }, 143 | "js-tokens": { 144 | "version": "4.0.0", 145 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 146 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 147 | "dev": true 148 | }, 149 | "merge-stream": { 150 | "version": "1.0.1", 151 | "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", 152 | "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", 153 | "dev": true, 154 | "requires": { 155 | "readable-stream": "^2.0.1" 156 | } 157 | }, 158 | "process-nextick-args": { 159 | "version": "2.0.0", 160 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", 161 | "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", 162 | "dev": true 163 | }, 164 | "readable-stream": { 165 | "version": "2.3.6", 166 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 167 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 168 | "dev": true, 169 | "requires": { 170 | "core-util-is": "~1.0.0", 171 | "inherits": "~2.0.3", 172 | "isarray": "~1.0.0", 173 | "process-nextick-args": "~2.0.0", 174 | "safe-buffer": "~5.1.1", 175 | "string_decoder": "~1.1.1", 176 | "util-deprecate": "~1.0.1" 177 | } 178 | }, 179 | "rollup": { 180 | "version": "1.1.2", 181 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.1.2.tgz", 182 | "integrity": "sha512-OkdMxqMl8pWoQc5D8y1cIinYQPPLV8ZkfLgCzL6SytXeNA2P7UHynEQXI9tYxuAjAMsSyvRaWnyJDLHMxq0XAg==", 183 | "dev": true, 184 | "requires": { 185 | "@types/estree": "0.0.39", 186 | "@types/node": "*", 187 | "acorn": "^6.0.5" 188 | } 189 | }, 190 | "rollup-plugin-uglify": { 191 | "version": "6.0.2", 192 | "resolved": "https://registry.npmjs.org/rollup-plugin-uglify/-/rollup-plugin-uglify-6.0.2.tgz", 193 | "integrity": "sha512-qwz2Tryspn5QGtPUowq5oumKSxANKdrnfz7C0jm4lKxvRDsNe/hSGsB9FntUul7UeC4TsZEWKErVgE1qWSO0gw==", 194 | "dev": true, 195 | "requires": { 196 | "@babel/code-frame": "^7.0.0", 197 | "jest-worker": "^24.0.0", 198 | "serialize-javascript": "^1.6.1", 199 | "uglify-js": "^3.4.9" 200 | } 201 | }, 202 | "safe-buffer": { 203 | "version": "5.1.2", 204 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 205 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 206 | "dev": true 207 | }, 208 | "serialize-javascript": { 209 | "version": "1.6.1", 210 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz", 211 | "integrity": "sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==", 212 | "dev": true 213 | }, 214 | "source-map": { 215 | "version": "0.6.1", 216 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 217 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 218 | "dev": true 219 | }, 220 | "string_decoder": { 221 | "version": "1.1.1", 222 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 223 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 224 | "dev": true, 225 | "requires": { 226 | "safe-buffer": "~5.1.0" 227 | } 228 | }, 229 | "supports-color": { 230 | "version": "5.5.0", 231 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 232 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 233 | "dev": true, 234 | "requires": { 235 | "has-flag": "^3.0.0" 236 | } 237 | }, 238 | "uglify-js": { 239 | "version": "3.4.9", 240 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", 241 | "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", 242 | "dev": true, 243 | "requires": { 244 | "commander": "~2.17.1", 245 | "source-map": "~0.6.1" 246 | } 247 | }, 248 | "util-deprecate": { 249 | "version": "1.0.2", 250 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 251 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 252 | "dev": true 253 | }, 254 | "vant-weapp": { 255 | "version": "0.5.12", 256 | "resolved": "https://registry.npmjs.org/vant-weapp/-/vant-weapp-0.5.12.tgz", 257 | "integrity": "sha512-2hUvczdSLuSMQW4wboaQQlJAXnlXxbBp+vSBXs0SZfs99a1Ul/INumZPZgzZOGtwVRrQvLR9NXw2ogacsxGEnw==" 258 | }, 259 | "wefetch": { 260 | "version": "1.0.3", 261 | "resolved": "https://registry.npmjs.org/wefetch/-/wefetch-1.0.3.tgz", 262 | "integrity": "sha512-MAeMWKyQ38jincEsSH4Ax/mjS2vsJmosi7/m7utMCulA7HG10EC3YvsX22ExBsadam/YCLaySK7sBV2itYMw6g==" 263 | } 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wefetch", 3 | "version": "1.1.0", 4 | "description": "**wefetch** 基于promise,支持微信、支付宝、百度小程序", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/jonnyshao/wefetch.git" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/jonnyshao/wefetch/issues" 18 | }, 19 | "homepage": "https://github.com/jonnyshao/wefetch#readme", 20 | "dependencies": { 21 | "vant-weapp": "^0.5.12", 22 | "wefetch": "^1.0.3" 23 | }, 24 | "devDependencies": { 25 | "rollup": "^1.1.2", 26 | "rollup-plugin-uglify": "^6.0.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | const uglify = require('rollup-plugin-uglify').uglify; 2 | import pkg from './wefetch/package.json'; 3 | const banner = 4 | `/* 5 | Promise based wx.request api for Mini Program 6 | @Github https://github.com/jonnyshao/wechat-fetch 7 | wefetch beta v${pkg.version} |(c) 2018-2019 By Jonny Shao 8 | */`; 9 | //../Example/wechat/utils 10 | module.exports = [ 11 | { 12 | input: './src/lib/wefetch.js', 13 | output: { 14 | file: './exmaple/api/wf.js', 15 | format: 'umd', 16 | name: 'wefetch', 17 | sourcemap: false, 18 | banner 19 | } 20 | }, 21 | { 22 | input: './src/lib/wefetch.js', 23 | output: { 24 | file: './wefetch/dist/wefetch.min.js', 25 | format: 'umd', 26 | name: 'wefetch', 27 | sourcemap: false, 28 | banner 29 | }, 30 | plugins: [ 31 | uglify() 32 | ], 33 | 34 | } 35 | ]; 36 | -------------------------------------------------------------------------------- /server/app.js: -------------------------------------------------------------------------------- 1 | var createError = require('http-errors'); 2 | var express = require('express'); 3 | var path = require('path'); 4 | var cookieParser = require('cookie-parser'); 5 | var logger = require('morgan'); 6 | var bodyParser = require('body-parser') 7 | var indexRouter = require('./routes/index'); 8 | var usersRouter = require('./routes/users'); 9 | 10 | var app = express(); 11 | 12 | // view engine setup 13 | app.set('views', path.join(__dirname, 'views')); 14 | app.set('view engine', 'jade'); 15 | app.use(bodyParser.json({limit: 'lmb'})) 16 | app.use(bodyParser.urlencoded({extended: true})) 17 | app.use(logger('dev')); 18 | app.use(express.json()); 19 | app.use(express.urlencoded({ extended: false })); 20 | app.use(cookieParser()); 21 | app.use(express.static(path.join(__dirname, 'public'))); 22 | 23 | app.use('/', indexRouter); 24 | app.use('/users', usersRouter); 25 | 26 | // catch 404 and forward to error handler 27 | app.use(function(req, res, next) { 28 | next(createError(404)); 29 | }); 30 | 31 | // error handler 32 | app.use(function(err, req, res, next) { 33 | // set locals, only providing error in development 34 | res.locals.message = err.message; 35 | res.locals.error = req.app.get('env') === 'development' ? err : {}; 36 | 37 | // render the error page 38 | res.status(err.status || 500); 39 | res.render('error'); 40 | }); 41 | 42 | module.exports = app; 43 | -------------------------------------------------------------------------------- /server/bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('server:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '3000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "0.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.5", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", 10 | "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", 11 | "requires": { 12 | "mime-types": "~2.1.18", 13 | "negotiator": "0.6.1" 14 | } 15 | }, 16 | "acorn": { 17 | "version": "2.7.0", 18 | "resolved": "http://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", 19 | "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=" 20 | }, 21 | "acorn-globals": { 22 | "version": "1.0.9", 23 | "resolved": "http://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz", 24 | "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=", 25 | "requires": { 26 | "acorn": "^2.1.0" 27 | } 28 | }, 29 | "align-text": { 30 | "version": "0.1.4", 31 | "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", 32 | "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", 33 | "requires": { 34 | "kind-of": "^3.0.2", 35 | "longest": "^1.0.1", 36 | "repeat-string": "^1.5.2" 37 | } 38 | }, 39 | "amdefine": { 40 | "version": "1.0.1", 41 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", 42 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" 43 | }, 44 | "array-flatten": { 45 | "version": "1.1.1", 46 | "resolved": "http://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 47 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 48 | }, 49 | "asap": { 50 | "version": "1.0.0", 51 | "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz", 52 | "integrity": "sha1-sqRdpf36ILBJb8N2jMJ8EvqRan0=" 53 | }, 54 | "basic-auth": { 55 | "version": "2.0.1", 56 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", 57 | "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", 58 | "requires": { 59 | "safe-buffer": "5.1.2" 60 | } 61 | }, 62 | "body-parser": { 63 | "version": "1.18.3", 64 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", 65 | "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", 66 | "requires": { 67 | "bytes": "3.0.0", 68 | "content-type": "~1.0.4", 69 | "debug": "2.6.9", 70 | "depd": "~1.1.2", 71 | "http-errors": "~1.6.3", 72 | "iconv-lite": "0.4.23", 73 | "on-finished": "~2.3.0", 74 | "qs": "6.5.2", 75 | "raw-body": "2.3.3", 76 | "type-is": "~1.6.16" 77 | } 78 | }, 79 | "bytes": { 80 | "version": "3.0.0", 81 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 82 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 83 | }, 84 | "camelcase": { 85 | "version": "1.2.1", 86 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", 87 | "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" 88 | }, 89 | "center-align": { 90 | "version": "0.1.3", 91 | "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", 92 | "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", 93 | "requires": { 94 | "align-text": "^0.1.3", 95 | "lazy-cache": "^1.0.3" 96 | } 97 | }, 98 | "character-parser": { 99 | "version": "1.2.1", 100 | "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-1.2.1.tgz", 101 | "integrity": "sha1-wN3kqxgnE7kZuXCVmhI+zBow/NY=" 102 | }, 103 | "clean-css": { 104 | "version": "3.4.28", 105 | "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", 106 | "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", 107 | "requires": { 108 | "commander": "2.8.x", 109 | "source-map": "0.4.x" 110 | }, 111 | "dependencies": { 112 | "commander": { 113 | "version": "2.8.1", 114 | "resolved": "http://registry.npmjs.org/commander/-/commander-2.8.1.tgz", 115 | "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", 116 | "requires": { 117 | "graceful-readlink": ">= 1.0.0" 118 | } 119 | } 120 | } 121 | }, 122 | "cliui": { 123 | "version": "2.1.0", 124 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", 125 | "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", 126 | "requires": { 127 | "center-align": "^0.1.1", 128 | "right-align": "^0.1.1", 129 | "wordwrap": "0.0.2" 130 | }, 131 | "dependencies": { 132 | "wordwrap": { 133 | "version": "0.0.2", 134 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", 135 | "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" 136 | } 137 | } 138 | }, 139 | "commander": { 140 | "version": "2.6.0", 141 | "resolved": "http://registry.npmjs.org/commander/-/commander-2.6.0.tgz", 142 | "integrity": "sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0=" 143 | }, 144 | "constantinople": { 145 | "version": "3.0.2", 146 | "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.0.2.tgz", 147 | "integrity": "sha1-S5RdmTeQe82Y7ldRIsOBdRZUQUE=", 148 | "requires": { 149 | "acorn": "^2.1.0" 150 | } 151 | }, 152 | "content-disposition": { 153 | "version": "0.5.2", 154 | "resolved": "http://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 155 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" 156 | }, 157 | "content-type": { 158 | "version": "1.0.4", 159 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 160 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 161 | }, 162 | "cookie": { 163 | "version": "0.3.1", 164 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 165 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 166 | }, 167 | "cookie-parser": { 168 | "version": "1.4.3", 169 | "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz", 170 | "integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=", 171 | "requires": { 172 | "cookie": "0.3.1", 173 | "cookie-signature": "1.0.6" 174 | } 175 | }, 176 | "cookie-signature": { 177 | "version": "1.0.6", 178 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 179 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 180 | }, 181 | "css": { 182 | "version": "1.0.8", 183 | "resolved": "http://registry.npmjs.org/css/-/css-1.0.8.tgz", 184 | "integrity": "sha1-k4aBHKgrzMnuf7WnMrHioxfIo+c=", 185 | "requires": { 186 | "css-parse": "1.0.4", 187 | "css-stringify": "1.0.5" 188 | } 189 | }, 190 | "css-parse": { 191 | "version": "1.0.4", 192 | "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz", 193 | "integrity": "sha1-OLBQP7+dqfVOnB29pg4UXHcRe90=" 194 | }, 195 | "css-stringify": { 196 | "version": "1.0.5", 197 | "resolved": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz", 198 | "integrity": "sha1-sNBClG2ylTu50pKQCmy19tASIDE=" 199 | }, 200 | "debug": { 201 | "version": "2.6.9", 202 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 203 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 204 | "requires": { 205 | "ms": "2.0.0" 206 | } 207 | }, 208 | "decamelize": { 209 | "version": "1.2.0", 210 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 211 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 212 | }, 213 | "depd": { 214 | "version": "1.1.2", 215 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 216 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 217 | }, 218 | "destroy": { 219 | "version": "1.0.4", 220 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 221 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 222 | }, 223 | "ee-first": { 224 | "version": "1.1.1", 225 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 226 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 227 | }, 228 | "encodeurl": { 229 | "version": "1.0.2", 230 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 231 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 232 | }, 233 | "escape-html": { 234 | "version": "1.0.3", 235 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 236 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 237 | }, 238 | "etag": { 239 | "version": "1.8.1", 240 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 241 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 242 | }, 243 | "express": { 244 | "version": "4.16.4", 245 | "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", 246 | "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", 247 | "requires": { 248 | "accepts": "~1.3.5", 249 | "array-flatten": "1.1.1", 250 | "body-parser": "1.18.3", 251 | "content-disposition": "0.5.2", 252 | "content-type": "~1.0.4", 253 | "cookie": "0.3.1", 254 | "cookie-signature": "1.0.6", 255 | "debug": "2.6.9", 256 | "depd": "~1.1.2", 257 | "encodeurl": "~1.0.2", 258 | "escape-html": "~1.0.3", 259 | "etag": "~1.8.1", 260 | "finalhandler": "1.1.1", 261 | "fresh": "0.5.2", 262 | "merge-descriptors": "1.0.1", 263 | "methods": "~1.1.2", 264 | "on-finished": "~2.3.0", 265 | "parseurl": "~1.3.2", 266 | "path-to-regexp": "0.1.7", 267 | "proxy-addr": "~2.0.4", 268 | "qs": "6.5.2", 269 | "range-parser": "~1.2.0", 270 | "safe-buffer": "5.1.2", 271 | "send": "0.16.2", 272 | "serve-static": "1.13.2", 273 | "setprototypeof": "1.1.0", 274 | "statuses": "~1.4.0", 275 | "type-is": "~1.6.16", 276 | "utils-merge": "1.0.1", 277 | "vary": "~1.1.2" 278 | } 279 | }, 280 | "finalhandler": { 281 | "version": "1.1.1", 282 | "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", 283 | "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", 284 | "requires": { 285 | "debug": "2.6.9", 286 | "encodeurl": "~1.0.2", 287 | "escape-html": "~1.0.3", 288 | "on-finished": "~2.3.0", 289 | "parseurl": "~1.3.2", 290 | "statuses": "~1.4.0", 291 | "unpipe": "~1.0.0" 292 | } 293 | }, 294 | "forwarded": { 295 | "version": "0.1.2", 296 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 297 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 298 | }, 299 | "fresh": { 300 | "version": "0.5.2", 301 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 302 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 303 | }, 304 | "graceful-readlink": { 305 | "version": "1.0.1", 306 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 307 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" 308 | }, 309 | "http-errors": { 310 | "version": "1.6.3", 311 | "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", 312 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", 313 | "requires": { 314 | "depd": "~1.1.2", 315 | "inherits": "2.0.3", 316 | "setprototypeof": "1.1.0", 317 | "statuses": ">= 1.4.0 < 2" 318 | } 319 | }, 320 | "iconv-lite": { 321 | "version": "0.4.23", 322 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", 323 | "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", 324 | "requires": { 325 | "safer-buffer": ">= 2.1.2 < 3" 326 | } 327 | }, 328 | "inherits": { 329 | "version": "2.0.3", 330 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 331 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 332 | }, 333 | "ipaddr.js": { 334 | "version": "1.8.0", 335 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", 336 | "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" 337 | }, 338 | "is-buffer": { 339 | "version": "1.1.6", 340 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 341 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 342 | }, 343 | "is-promise": { 344 | "version": "2.1.0", 345 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 346 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" 347 | }, 348 | "jade": { 349 | "version": "1.11.0", 350 | "resolved": "https://registry.npmjs.org/jade/-/jade-1.11.0.tgz", 351 | "integrity": "sha1-nIDlOMEtP7lcjZu5VZ+gzAQEBf0=", 352 | "requires": { 353 | "character-parser": "1.2.1", 354 | "clean-css": "^3.1.9", 355 | "commander": "~2.6.0", 356 | "constantinople": "~3.0.1", 357 | "jstransformer": "0.0.2", 358 | "mkdirp": "~0.5.0", 359 | "transformers": "2.1.0", 360 | "uglify-js": "^2.4.19", 361 | "void-elements": "~2.0.1", 362 | "with": "~4.0.0" 363 | } 364 | }, 365 | "jstransformer": { 366 | "version": "0.0.2", 367 | "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-0.0.2.tgz", 368 | "integrity": "sha1-eq4pqQPRls+glz2IXT5HlH7Ndqs=", 369 | "requires": { 370 | "is-promise": "^2.0.0", 371 | "promise": "^6.0.1" 372 | } 373 | }, 374 | "kind-of": { 375 | "version": "3.2.2", 376 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 377 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 378 | "requires": { 379 | "is-buffer": "^1.1.5" 380 | } 381 | }, 382 | "lazy-cache": { 383 | "version": "1.0.4", 384 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", 385 | "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" 386 | }, 387 | "longest": { 388 | "version": "1.0.1", 389 | "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", 390 | "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" 391 | }, 392 | "media-typer": { 393 | "version": "0.3.0", 394 | "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 395 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 396 | }, 397 | "merge-descriptors": { 398 | "version": "1.0.1", 399 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 400 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 401 | }, 402 | "methods": { 403 | "version": "1.1.2", 404 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 405 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 406 | }, 407 | "mime": { 408 | "version": "1.4.1", 409 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", 410 | "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" 411 | }, 412 | "mime-db": { 413 | "version": "1.37.0", 414 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", 415 | "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" 416 | }, 417 | "mime-types": { 418 | "version": "2.1.21", 419 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", 420 | "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", 421 | "requires": { 422 | "mime-db": "~1.37.0" 423 | } 424 | }, 425 | "minimist": { 426 | "version": "0.0.8", 427 | "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 428 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 429 | }, 430 | "mkdirp": { 431 | "version": "0.5.1", 432 | "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 433 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 434 | "requires": { 435 | "minimist": "0.0.8" 436 | } 437 | }, 438 | "morgan": { 439 | "version": "1.9.1", 440 | "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", 441 | "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", 442 | "requires": { 443 | "basic-auth": "~2.0.0", 444 | "debug": "2.6.9", 445 | "depd": "~1.1.2", 446 | "on-finished": "~2.3.0", 447 | "on-headers": "~1.0.1" 448 | } 449 | }, 450 | "ms": { 451 | "version": "2.0.0", 452 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 453 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 454 | }, 455 | "negotiator": { 456 | "version": "0.6.1", 457 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 458 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" 459 | }, 460 | "on-finished": { 461 | "version": "2.3.0", 462 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 463 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 464 | "requires": { 465 | "ee-first": "1.1.1" 466 | } 467 | }, 468 | "on-headers": { 469 | "version": "1.0.1", 470 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", 471 | "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" 472 | }, 473 | "optimist": { 474 | "version": "0.3.7", 475 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", 476 | "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", 477 | "requires": { 478 | "wordwrap": "~0.0.2" 479 | } 480 | }, 481 | "parseurl": { 482 | "version": "1.3.2", 483 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 484 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 485 | }, 486 | "path-to-regexp": { 487 | "version": "0.1.7", 488 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 489 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 490 | }, 491 | "promise": { 492 | "version": "6.1.0", 493 | "resolved": "http://registry.npmjs.org/promise/-/promise-6.1.0.tgz", 494 | "integrity": "sha1-LOcp9rlLRcJoka0GAsXJDgTG7vY=", 495 | "requires": { 496 | "asap": "~1.0.0" 497 | } 498 | }, 499 | "proxy-addr": { 500 | "version": "2.0.4", 501 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", 502 | "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", 503 | "requires": { 504 | "forwarded": "~0.1.2", 505 | "ipaddr.js": "1.8.0" 506 | } 507 | }, 508 | "qs": { 509 | "version": "6.5.2", 510 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 511 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 512 | }, 513 | "range-parser": { 514 | "version": "1.2.0", 515 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 516 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" 517 | }, 518 | "raw-body": { 519 | "version": "2.3.3", 520 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", 521 | "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", 522 | "requires": { 523 | "bytes": "3.0.0", 524 | "http-errors": "1.6.3", 525 | "iconv-lite": "0.4.23", 526 | "unpipe": "1.0.0" 527 | } 528 | }, 529 | "repeat-string": { 530 | "version": "1.6.1", 531 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 532 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" 533 | }, 534 | "right-align": { 535 | "version": "0.1.3", 536 | "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", 537 | "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", 538 | "requires": { 539 | "align-text": "^0.1.1" 540 | } 541 | }, 542 | "safe-buffer": { 543 | "version": "5.1.2", 544 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 545 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 546 | }, 547 | "safer-buffer": { 548 | "version": "2.1.2", 549 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 550 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 551 | }, 552 | "send": { 553 | "version": "0.16.2", 554 | "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", 555 | "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", 556 | "requires": { 557 | "debug": "2.6.9", 558 | "depd": "~1.1.2", 559 | "destroy": "~1.0.4", 560 | "encodeurl": "~1.0.2", 561 | "escape-html": "~1.0.3", 562 | "etag": "~1.8.1", 563 | "fresh": "0.5.2", 564 | "http-errors": "~1.6.2", 565 | "mime": "1.4.1", 566 | "ms": "2.0.0", 567 | "on-finished": "~2.3.0", 568 | "range-parser": "~1.2.0", 569 | "statuses": "~1.4.0" 570 | } 571 | }, 572 | "serve-static": { 573 | "version": "1.13.2", 574 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", 575 | "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", 576 | "requires": { 577 | "encodeurl": "~1.0.2", 578 | "escape-html": "~1.0.3", 579 | "parseurl": "~1.3.2", 580 | "send": "0.16.2" 581 | } 582 | }, 583 | "setprototypeof": { 584 | "version": "1.1.0", 585 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 586 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 587 | }, 588 | "source-map": { 589 | "version": "0.4.4", 590 | "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", 591 | "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", 592 | "requires": { 593 | "amdefine": ">=0.0.4" 594 | } 595 | }, 596 | "statuses": { 597 | "version": "1.4.0", 598 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 599 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 600 | }, 601 | "transformers": { 602 | "version": "2.1.0", 603 | "resolved": "https://registry.npmjs.org/transformers/-/transformers-2.1.0.tgz", 604 | "integrity": "sha1-XSPLNVYd2F3Gf7hIIwm0fVPM6ac=", 605 | "requires": { 606 | "css": "~1.0.8", 607 | "promise": "~2.0", 608 | "uglify-js": "~2.2.5" 609 | }, 610 | "dependencies": { 611 | "is-promise": { 612 | "version": "1.0.1", 613 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz", 614 | "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU=" 615 | }, 616 | "promise": { 617 | "version": "2.0.0", 618 | "resolved": "http://registry.npmjs.org/promise/-/promise-2.0.0.tgz", 619 | "integrity": "sha1-RmSKqdYFr10ucMMCS/WUNtoCuA4=", 620 | "requires": { 621 | "is-promise": "~1" 622 | } 623 | }, 624 | "source-map": { 625 | "version": "0.1.43", 626 | "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", 627 | "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", 628 | "requires": { 629 | "amdefine": ">=0.0.4" 630 | } 631 | }, 632 | "uglify-js": { 633 | "version": "2.2.5", 634 | "resolved": "http://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", 635 | "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=", 636 | "requires": { 637 | "optimist": "~0.3.5", 638 | "source-map": "~0.1.7" 639 | } 640 | } 641 | } 642 | }, 643 | "type-is": { 644 | "version": "1.6.16", 645 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", 646 | "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", 647 | "requires": { 648 | "media-typer": "0.3.0", 649 | "mime-types": "~2.1.18" 650 | } 651 | }, 652 | "uglify-js": { 653 | "version": "2.8.29", 654 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", 655 | "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", 656 | "requires": { 657 | "source-map": "~0.5.1", 658 | "uglify-to-browserify": "~1.0.0", 659 | "yargs": "~3.10.0" 660 | }, 661 | "dependencies": { 662 | "source-map": { 663 | "version": "0.5.7", 664 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 665 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" 666 | } 667 | } 668 | }, 669 | "uglify-to-browserify": { 670 | "version": "1.0.2", 671 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", 672 | "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", 673 | "optional": true 674 | }, 675 | "unpipe": { 676 | "version": "1.0.0", 677 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 678 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 679 | }, 680 | "utils-merge": { 681 | "version": "1.0.1", 682 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 683 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 684 | }, 685 | "vary": { 686 | "version": "1.1.2", 687 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 688 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 689 | }, 690 | "void-elements": { 691 | "version": "2.0.1", 692 | "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", 693 | "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" 694 | }, 695 | "window-size": { 696 | "version": "0.1.0", 697 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", 698 | "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" 699 | }, 700 | "with": { 701 | "version": "4.0.3", 702 | "resolved": "https://registry.npmjs.org/with/-/with-4.0.3.tgz", 703 | "integrity": "sha1-7v0VTp550sjTQXtkeo8U2f7M4U4=", 704 | "requires": { 705 | "acorn": "^1.0.1", 706 | "acorn-globals": "^1.0.3" 707 | }, 708 | "dependencies": { 709 | "acorn": { 710 | "version": "1.2.2", 711 | "resolved": "http://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz", 712 | "integrity": "sha1-yM4n3grMdtiW0rH6099YjZ6C8BQ=" 713 | } 714 | } 715 | }, 716 | "wordwrap": { 717 | "version": "0.0.3", 718 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 719 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" 720 | }, 721 | "yargs": { 722 | "version": "3.10.0", 723 | "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", 724 | "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", 725 | "requires": { 726 | "camelcase": "^1.0.2", 727 | "cliui": "^2.1.0", 728 | "decamelize": "^1.0.0", 729 | "window-size": "0.1.0" 730 | } 731 | } 732 | } 733 | } 734 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "cookie-parser": "~1.4.3", 10 | "debug": "~2.6.9", 11 | "express": "~4.16.0", 12 | "http-errors": "~1.6.2", 13 | "jade": "~1.11.0", 14 | "morgan": "~1.9.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /server/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /server/routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | // interceptor request 5 | router.get('/interceptor/request', function(req, res, next) { 6 | res.json({title:'interceptor', content: 'this is a interceptor request'}); 7 | }); 8 | 9 | // interceptor response 10 | router.get('/interceptor/response', function(req, res, next) { 11 | res.set({'interceptor': true}) 12 | res.json({title:'interceptor', content: 'this is a interceptor response'}); 13 | }); 14 | 15 | // get request 16 | router.get('/get', function(req, res, next) { 17 | res.json(req.query) 18 | }) 19 | router.get('/abortGet', function (req, res, next) { 20 | setTimeout(() => { 21 | res.json(req.query) 22 | }, 5000) 23 | }) 24 | router.post('/post', function(req, res, next) { 25 | res.json(req.body) 26 | }) 27 | router.post('/postJson', function(req, res, next) { 28 | res.json(req.body) 29 | }) 30 | router.head('/head', function (req, res, next) { 31 | res.set({'title': 'Head Test'}) 32 | res.set({'content': 'this is a head request'}) 33 | res.end() 34 | }) 35 | router.put('/put', function (req, res, next) { 36 | res.json(req.body) 37 | }) 38 | router.delete('/delete', function (req, res, next) { 39 | res.json(req.body) 40 | }) 41 | router.trace('/trace', function (req, res, next) { 42 | res.json(req.body) 43 | }) 44 | router.options('/options', function (req, res, next) { 45 | res.json(req.body) 46 | }) 47 | router.options('/connect', function (req, res, next) { 48 | res.json(req.body) 49 | }) 50 | module.exports = router; 51 | -------------------------------------------------------------------------------- /server/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get('/', function(req, res, next) { 6 | res.send('respond with a resource'); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /server/views/error.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= message 5 | h2= error.status 6 | pre #{error.stack} 7 | -------------------------------------------------------------------------------- /server/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /server/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title= title 5 | link(rel='stylesheet', href='/stylesheets/style.css') 6 | body 7 | block content 8 | -------------------------------------------------------------------------------- /src/lib/core/Events.js: -------------------------------------------------------------------------------- 1 | function Events() { 2 | this.listeners = {}; 3 | } 4 | 5 | Events.prototype.on = function (type, cb) { 6 | if (!(type in this.listeners)) { 7 | this.listeners[type] = []; 8 | } 9 | this.listeners[type].push(cb) 10 | }; 11 | 12 | Events.prototype.emit = function (type, task) { 13 | var listener = this.listeners[type]; 14 | if (listener) { 15 | listener.forEach(function (h) { 16 | h(task) 17 | }) 18 | } 19 | }; 20 | 21 | export default new Events(); -------------------------------------------------------------------------------- /src/lib/core/Wefetch.js: -------------------------------------------------------------------------------- 1 | import e from './Events' 2 | import InterceptorManager from './interceptorManager' 3 | import promisify from "./promisify"; 4 | import request from "./request"; 5 | import './addMethods' 6 | 7 | function WeFetch(instanceConfig) { 8 | this.defaults = instanceConfig; 9 | this.before = new InterceptorManager(); 10 | this.after = new InterceptorManager(); 11 | } 12 | 13 | WeFetch.prototype.on = function (event, cb) { 14 | e.on(event, cb); 15 | }; 16 | WeFetch.prototype.abort = function (event, cb) { 17 | this.on(event, function (t) { 18 | t.abort(); 19 | cb && cb() 20 | }) 21 | }; 22 | WeFetch.prototype.onProcess = function (event, cb) { 23 | this.on(event, function (t) { 24 | t.onProgressUpdate(cb) 25 | }) 26 | }; 27 | WeFetch.prototype.promisify = promisify; 28 | WeFetch.prototype.request = request; 29 | export default WeFetch; 30 | -------------------------------------------------------------------------------- /src/lib/core/addMethods.js: -------------------------------------------------------------------------------- 1 | import utils from "../utils"; 2 | import WeFetch from "./Wefetch"; 3 | ['options', 'get', 'head', 'post', 'put', 'delete', 'trace', 'connect'].forEach(function (method) { 4 | WeFetch.prototype[method] = function (url, config) { 5 | return this.request(utils.merge(config || {}, { 6 | url: url, 7 | method: method 8 | })) 9 | } 10 | }); 11 | WeFetch.prototype.download = function (url, config) { 12 | // wf.download({}) support 13 | if (utils.type.isObject(url)) { 14 | return this.request(utils.merge(url,{ method: 'download' })) 15 | } 16 | // default 17 | return this.request(utils.merge(config || {},{ 18 | url: url, 19 | method: 'download' 20 | })) 21 | }; 22 | 23 | WeFetch.prototype.upload = function (url, config) { 24 | // upload({}) support 25 | if (utils.type.isObject(url)) { 26 | return this.request(url,{ method: 'upload' }) 27 | } 28 | return this.request(utils.merge(config || {}, { 29 | url: url, 30 | method: 'upload' 31 | })) 32 | }; 33 | -------------------------------------------------------------------------------- /src/lib/core/bind.js: -------------------------------------------------------------------------------- 1 | function bind(fn, context) { 2 | return function wf (){ 3 | var args = new Array(arguments.length); 4 | for (var i = 0, l = args.length; i < l; i++) { 5 | args[i] = arguments[i] 6 | } 7 | return fn.apply(context, args) 8 | } 9 | } 10 | 11 | export default bind; 12 | -------------------------------------------------------------------------------- /src/lib/core/dispatchRequest.js: -------------------------------------------------------------------------------- 1 | import platform from "./platform"; 2 | import utils from "../utils"; 3 | function dispatchRequest(config) { 4 | utils.normalizeHeaderName(config.header || config.headers); 5 | if (config.method === 'download') { 6 | config.method = 'get'; 7 | config.createRequest = platform.getDownload() 8 | } 9 | if (config.method === 'upload'){ 10 | config.method = 'post'; 11 | config.createRequest = platform.getUpload() 12 | } 13 | var request = config.createRequest; 14 | return request(config).then(function (response) { 15 | return response; 16 | }, function (reason) { 17 | return Promise.reject(reason) 18 | }) 19 | } 20 | 21 | export default dispatchRequest; 22 | -------------------------------------------------------------------------------- /src/lib/core/functional.js: -------------------------------------------------------------------------------- 1 | 2 | export function retry(times,request,timeout) { 3 | timeout = timeout || 1000; 4 | if (!times && times !== 0 || !request)throw new Error('request and times params is required'); 5 | if (typeof request !== 'function') throw new Error('request must be a function, but got a\n'+ typeof request); 6 | var p = request(); 7 | if (times > 1) { 8 | times --; 9 | return new Promise(function(resolve, reject) { 10 | p.then(resolve).catch(function () { 11 | setTimeout(function() { 12 | resolve(retry(times, request, timeout)) 13 | }, timeout); 14 | }) 15 | }) 16 | } 17 | return p; 18 | } 19 | -------------------------------------------------------------------------------- /src/lib/core/interceptorManager.js: -------------------------------------------------------------------------------- 1 | function InterceptorManager() { 2 | this.handles = [] 3 | } 4 | 5 | InterceptorManager.prototype.use = function (fulfilled, rejected) { 6 | this.handles.push({ fulfilled: fulfilled, rejected: rejected }); 7 | return this.handles.length - 1; 8 | }; 9 | 10 | 11 | InterceptorManager.prototype.eject = function (id) { 12 | if (this.handles[id]) { 13 | this.handles[id] = null 14 | } 15 | 16 | }; 17 | InterceptorManager.prototype.forEach = function (fn) { 18 | this.handles.forEach(function (h) { 19 | h && fn(h) 20 | }) 21 | }; 22 | 23 | export default InterceptorManager; -------------------------------------------------------------------------------- /src/lib/core/platform.js: -------------------------------------------------------------------------------- 1 | import promisify from './promisify' 2 | 3 | function Platform() { 4 | this.platform = null; 5 | this.api = null; 6 | } 7 | Platform.prototype.getRequest = function () { 8 | if (typeof wx !== 'undefined') { 9 | this.platform = 'wx'; 10 | this.api = wx 11 | return promisify(wx.request) 12 | } else if (typeof my !== 'undefined') { 13 | this.platform = 'my'; 14 | this.api = my 15 | return my.request ? promisify(my.request) : promisify(my.httpRequest) 16 | } else if (typeof tt !== 'undefined') { 17 | this.api = tt; 18 | this.platform = 'tt'; 19 | return promisify(tt.request) 20 | } else if (typeof swan !== 'undefined') { 21 | this.api = swan 22 | this.platform = 'swan'; 23 | return promisify(swan.request) 24 | } 25 | }; 26 | Platform.prototype.getUpload = function () { 27 | return promisify(this.api.uploadFile); 28 | }; 29 | Platform.prototype.getDownload = function () { 30 | return promisify(this.api.downloadFile); 31 | }; 32 | export default new Platform(); 33 | -------------------------------------------------------------------------------- /src/lib/core/promisify.js: -------------------------------------------------------------------------------- 1 | import e from './Events' 2 | function promisify (api) { 3 | return function (options) { 4 | options = options || {}; 5 | options.config = options.config || {}; 6 | for (var len = arguments.length, params = Array(len > 1 ? len - 1 : 0), key = 1; key < len; key++) { 7 | params[key - 1] = arguments[key]; 8 | } 9 | return new Promise(function (resolve, reject) { 10 | options.config.eventType ? e.emit(options.config.eventType, api.apply(undefined, [Object.assign({}, options, {success: resolve, fail: reject})].concat(params))) 11 | : api.apply(undefined, [Object.assign({}, options, {success: resolve, fail: reject})].concat(params)) 12 | }) 13 | }; 14 | }; 15 | 16 | export default promisify; 17 | -------------------------------------------------------------------------------- /src/lib/core/request.js: -------------------------------------------------------------------------------- 1 | import utils from "../utils"; 2 | import dispatchRequest from "./dispatchRequest"; 3 | import platform from "./platform"; 4 | function request (config) { 5 | if (typeof config === 'string') { 6 | config = arguments[1] || {}; 7 | config.url = arguments[0] 8 | } 9 | config = utils.mergeConfig(this.defaults, config); 10 | if (config.url.indexOf('http') === -1) { 11 | if (config.downloadUrl && config.method === 'download') { 12 | config.url = config.downloadUrl + config.url 13 | } else if (config.uploadUrl && config.method === 'upload') { 14 | config.url = config.uploadUrl + config.url 15 | } else { //(config.baseUrl) 16 | config.url = config.baseUrl + config.url 17 | } 18 | } 19 | // 阿里系的header是复数 20 | if (platform.platform === 'my' ) { 21 | if (config.method !== 'download' && config.method !== 'upload') { 22 | config.headers = Object.assign({}, config.header); 23 | delete config.header 24 | } 25 | } 26 | var chain = [dispatchRequest, undefined]; 27 | var promise = Promise.resolve(config); 28 | this.before.forEach(function (interceptor) { 29 | chain.unshift(interceptor.fulfilled, interceptor.rejected) 30 | }); 31 | this.after.forEach(function (interceptor) { 32 | chain.push(interceptor.fulfilled, interceptor.rejected) 33 | }); 34 | while (chain.length) { 35 | promise = promise.then(chain.shift(), chain.shift()) 36 | } 37 | return promise; 38 | } 39 | 40 | export default request 41 | -------------------------------------------------------------------------------- /src/lib/defaults.js: -------------------------------------------------------------------------------- 1 | 2 | import platform from './core/platform' 3 | export var defaults = { 4 | createRequest: platform.getRequest(), 5 | header: {}, 6 | config: {}, 7 | method: 'get', 8 | timeout: 0 9 | }; 10 | -------------------------------------------------------------------------------- /src/lib/utils.js: -------------------------------------------------------------------------------- 1 | var tostring = Object.prototype.toString; 2 | 3 | import bind from './core/bind' 4 | var utils = { 5 | type: (function () { 6 | var type = {}; 7 | var typeAry = ['String', 'Object', 'Number', 'Array', 'Undefined', 'Function', 'Null', 'Date']; 8 | for (var i = 0, len = typeAry.length; i < len; i++) { 9 | (function (name) { 10 | type['is' + name] = function (obj) { 11 | return tostring.call(obj) === '[object' +' '+ name + ']'; 12 | } 13 | })(typeAry[i]) 14 | } 15 | return type; 16 | })(), 17 | normalizeHeaderName: function (header) { 18 | for (var key in header) { 19 | if (/Content-Type/ig.test(key)){ 20 | header['Content-Type'] = header[key] 21 | delete header[key] 22 | } 23 | } 24 | }, 25 | forEach: function (obj, fn) { 26 | if (!obj) { 27 | return; 28 | } 29 | if (typeof obj !== 'object') { 30 | obj = [obj] 31 | } 32 | if (this.type.isArray(obj)) { 33 | for (var i = 0, l = obj.length; i < l; i++) { 34 | fn.call(null, obj[i], i, obj) 35 | } 36 | } else { 37 | for (var k in obj) { 38 | if (Object.prototype.hasOwnProperty.call(obj, k)) { 39 | fn.call(null, obj[k], k, obj) 40 | } 41 | } 42 | } 43 | }, 44 | merge: function () { 45 | var result = {}; 46 | function assignValue(val, key) { 47 | if (typeof result[key] === 'object' && typeof val === 'object') { 48 | result[key] = utils.merge(result[key], val); 49 | } else { 50 | result[key] = val; 51 | } 52 | } 53 | for (var i = 0, l = arguments.length; i < l; i++) { 54 | this.forEach(arguments[i], assignValue) 55 | } 56 | return result; 57 | }, 58 | deepMerge: function() { 59 | var result = {}; 60 | function assignValue(val, key) { 61 | if (typeof result[key] === 'object' && typeof val === 'object') { 62 | result[key] = utils.deepMerge(result[key], val); 63 | } else if (typeof val === 'object'){ 64 | result[key] = utils.deepMerge({},val); 65 | } else { 66 | result[key] = val 67 | } 68 | } 69 | for (var i = 0, l = arguments.length; i < l; i++) { 70 | this.forEach(arguments[i], assignValue); 71 | } 72 | return result; 73 | }, 74 | mergeConfig: function(source,target){ 75 | var c = {}; target = target || {}; 76 | ['url','method', 'data','config'].forEach(function (prop) { 77 | if (target[prop]){ 78 | c[prop] = target[prop] 79 | } 80 | }); 81 | ['header','headers'].forEach(function (prop) { 82 | if (utils.type.isObject(target[prop])){ 83 | c[prop] = utils.deepMerge(source[prop],target[prop]) 84 | } else if(target[prop]){ 85 | c[prop] = target[prop] 86 | } else if(utils.type.isObject(source[prop])){ 87 | c[prop] = utils.deepMerge(source[prop]) 88 | } else if (source[prop]){ 89 | c[prop] = source[prop] 90 | } 91 | }); 92 | ['baseUrl','timeout','eventType','createRequest'].forEach(function (prop) { 93 | if (target[prop] !== undefined){ 94 | c[prop] = target[prop] 95 | } else if (source[prop] !== undefined){ 96 | c[prop] = source[prop] 97 | } 98 | }); 99 | return c 100 | }, 101 | extends: function (extendObj, copyObj, thisArg) { 102 | this.forEach(copyObj, function (val, key) { 103 | if (thisArg && typeof val === 'function') { 104 | extendObj[key] = bind(val, thisArg) 105 | } else { 106 | extendObj[key] = val; 107 | } 108 | }); 109 | return extendObj; 110 | } 111 | } 112 | 113 | export default utils; 114 | -------------------------------------------------------------------------------- /src/lib/wefetch.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import { defaults } from './defaults' 3 | import utils from './utils' 4 | import WeFetch from './core/Wefetch' 5 | import bind from './core/bind' 6 | import { retry } from './core/functional' 7 | Promise.prototype.finally = Promise.prototype.finally || function (cb) { 8 | var p = this.constructor; 9 | return this.then(function (value) { 10 | p.resolve(cb(value)).then(function () { 11 | return value 12 | }) 13 | }, function (reason) { 14 | p.resolve(cb(reason)).then(function () { 15 | return Promise.reject(reason) 16 | }) 17 | }) 18 | }; 19 | 20 | function createInstance(defaultConfig) { 21 | var context = new WeFetch(defaultConfig); 22 | var instance = bind(WeFetch.prototype.request, context); 23 | utils.extends(instance, WeFetch.prototype, context); 24 | utils.extends(instance, context); 25 | return instance; 26 | } 27 | var wf = createInstance(defaults); 28 | 29 | wf.all = function (promises) { 30 | return Promise.all(promises) 31 | }; 32 | wf.retry = retry; 33 | wf.create = function (instanceConfig) { 34 | return createInstance(utils.merge(defaults, instanceConfig)) 35 | }; 36 | export default wf; 37 | -------------------------------------------------------------------------------- /wefetch/README.MD: -------------------------------------------------------------------------------- 1 | English | [简体中文](https://github.com/jonnyshao/wefetch) 2 | # wefetch 3 | 4 | [![install size](https://packagephobia.now.sh/badge?p=wefetch)](https://packagephobia.now.sh/result?p=wefetch) 5 | [![npm version](https://badgen.net/npm/v/wefetch?color=green)](https://www.npmjs.com/package/wefetch) 6 | [![gzip](https://badgen.net/badgesize/gzip/https://unpkg.com/wefetch@1.3.3/dist/wefetch.min.js)](https://unpkg.com/wefetch@1.2.5/dist/wefetch.min.js) 7 | [![downloads](https://badgen.net/npm/dm/wefetch)](https://www.npmtrends.com/wefetch) 8 | 9 | Promise based api for the Mini Program. Supports the `Wechat` 、`Alipay`、`Baidu`、 `DingDing`、`TouTiao` Mini-program of platform. 10 | 11 | ## Mini Program Platform Support 12 | 13 | ![WeChat](https://github.com/jonnyshao/wefetch/blob/master/assets/wechat.png) | ![AliPay](https://github.com/jonnyshao/wefetch/blob/master/assets/alipay.png) | ![DingDing](https://github.com/jonnyshao/wefetch/blob/master/assets/dingding.png) | ![Baidu](https://github.com/jonnyshao/wefetch/blob/master/assets/baidu.png) | ![Toutiao](https://github.com/jonnyshao/wefetch/blob/master/assets/tt.png) | 14 | --- | --- | --- | --- | --- | 15 | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | 16 | ## Feature 17 | 18 | - Make [wx.request](https://developers.weixin.qq.com/miniprogram/en/dev/api/network-request.html#wxrequestobject) from the Wechat Mini Program 19 | - Make [wx.downloadFile](https://developers.weixin.qq.com/miniprogram/en/dev/api/network-file.html#wxdownloadfileobject) from the Wechat Mini Program 20 | - Make [wx.uploadFile](https://developers.weixin.qq.com/miniprogram/en/dev/api/network-file.html#wxuploadfileobject) from the Wechat Mini Program 21 | - Make [my.request](https://docs.alipay.com/mini/api/network#a-nameco0fvaamyhttprequest) from the Alipay Mini Program 22 | - Make [my.uploadFile](https://docs.alipay.com/mini/api/network#a-namey24rltamyuploadfile) from the Alipay Mini Program 23 | - Make [my.downloadFile](https://docs.alipay.com/mini/api/network#a-nameal4taaamydownloadfile) from the Alipay Mini Program 24 | - Make [tt.request](https://developer.toutiao.com/docs/api/request.html) from the TouTiao Mini Program 25 | - Make [tt.downloadFile](https://developer.toutiao.com/docs/api/downloadFile.html) from the TouTiao Mini Program 26 | - Make [tt.uploadFile](https://developer.toutiao.com/docs/api/uploadFile.html) from the TouTiao Mini Program 27 | - Make [swan.request](https://smartprogram.baidu.com/docs/develop/api/net_request/#request/) from the Baidu Mini Program 28 | - Make [swan.uploadFile](https://smartprogram.baidu.com/docs/develop/api/net_uploadfile/#uploadFile/) from the Baidu Mini Program 29 | - Make [swan.downloadFile](https://smartprogram.baidu.com/docs/develop/api/net_uploadfile/#downloadFile/) from the Baidu Mini Program 30 | - Supports the [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) API 31 | - Intercept request and response 32 | - Supports the Mini Program [RequestTask](https://developers.weixin.qq.com/miniprogram/dev/api/wx.request.html) object of config 33 | 34 | ## installing 35 | 36 | ```js 37 | npm i wefetch 38 | ``` 39 | ## Sample code of Project 40 | ```js 41 | const wf = require('wefetch'); 42 | 43 | class Request { 44 | constructor() { 45 | // queue 46 | this.queue = {}; 47 | // config your domain 48 | this.baseUrl = 'http://your-domain.com'; 49 | // support of alipay mini program only 50 | this.timeout = 3000; 51 | // create wefetch instance 52 | this.instance = wf.create(); 53 | } 54 | // params merge 55 | merge(options) { 56 | return { ...options, baseUrl: this.baseUrl } 57 | } 58 | // Retries a function that returns a promise, leveraging the power of the retry module to the promise 59 | // times && request required 60 | retry(times,request,timeout){ 61 | this.instance.retry(times,request,timeout) 62 | }, 63 | // cancel current request 64 | abort(event,callback){ 65 | this.instance.abort(event,callback) 66 | }, 67 | // get `upload` or `download` processUpdate 68 | onProcess(event,cb){ 69 | this.instance.onProcess(event,cb) 70 | } 71 | // set interceptors 72 | interceptor(instance, url) { 73 | instance.before.use(req => { 74 | req.header.Authorization = 'type in your token'; 75 | if (Object.keys(this.queue).length === 0) { 76 | wx.showLoading({ 77 | title: 'Loading', 78 | mask: true 79 | }) 80 | } 81 | this.queue[url] = url; 82 | return req; 83 | }); 84 | instance.after.use(res => { 85 | delete this.queue[url] 86 | if (Object.keys(this.queue).length === 0) { 87 | wx.hideLoading() 88 | } 89 | return res; 90 | }) 91 | } 92 | // execute instance 93 | request(options) { 94 | this.interceptor(this.instance, options.url) 95 | return this.instance(this.merge(options)); 96 | } 97 | } 98 | 99 | module.exports = new Request; 100 | ``` 101 | ## Example 102 | 103 | Performing a `GET` request 104 | ```js 105 | const wf = require('wefetch') 106 | wx.showLoading({ 107 | title: 'loading', 108 | mask: true 109 | }) 110 | wf.get(url).then(res => { 111 | // .... 112 | }).catch(err => { 113 | // ... 114 | }) 115 | // request completed 116 | .finally(() => { 117 | wx.hideLoading() 118 | }) 119 | 120 | wf.get('/get', 121 | { 122 | data: { 123 | title: 'get Test', 124 | content: 'get' 125 | }, 126 | header: { demo: 'demo' } 127 | }) 128 | .then(res => { 129 | // handle success 130 | console.log(res) 131 | }).catch(error => { 132 | // handle error 133 | console.log(error) 134 | }).then( _ => { 135 | // always executed 136 | }) 137 | ``` 138 | Performing a `POST` request 139 | ```js 140 | wf.post('/post',{ data:{ title: 'post test', content: 'post' }}) 141 | .then(res => { 142 | console.log(res) 143 | }).catch(err => { 144 | console.log(err) 145 | }) 146 | ``` 147 | 148 | Performing multiple `concurrent` requests 149 | ```js 150 | const getUserInfo = prams => wf.get('/user/1', params) 151 | const getUserPermissions = params => wf.get('/user/1/permission', params) 152 | wf.all([getUserInfo(), getUserPermissions()]) 153 | .then(res => { 154 | // both requests are complete, the res as a Array back 155 | }) 156 | ``` 157 | 158 | Performing a `upload` request 159 | ```js 160 | 161 | const chooseImage = wf.promisify(wx.chooseImage) 162 | // using for wechat Mini Program 163 | chooseImage().then(res => { 164 | wf.upload('/upload', { 165 | filePath: res.tempFilePaths[0], 166 | name:'file' 167 | }) 168 | .then(res =>{ 169 | console.log(res) 170 | }) 171 | }) 172 | chooseImage().then(res => { 173 | wf.upload({ 174 | url: '/upload', 175 | filePath: res.tempFilePaths[0], 176 | name:'file' 177 | }) 178 | .then(res =>{ 179 | console.log(res) 180 | }) 181 | }) 182 | ``` 183 | 184 | Performing a `download` request 185 | ```js 186 | wf.download('/download') 187 | .then(res => { 188 | console.log(res) 189 | }) 190 | 191 | wf.download({ 192 | url:'/download' 193 | }) 194 | .then(res => { 195 | console.log(res) 196 | }) 197 | 198 | ``` 199 | ## To use async/await 200 | > async/await is part of ECMAScript 2017 and is not supported in Mini Program, before we can use it, we need introduce a `regeneratorRuntime` 201 | 202 | [wehcat-regenerator-runtime](https://github.com/jonnyshao/wehcat-regenerator-runtime) 203 | ```js 204 | const regeneratorRuntime = require('wehcat-regenerator-runtime'); 205 | 206 | // es6 write 207 | async onload () { 208 | let res = await wf.get('/get') 209 | console.log(res) 210 | 211 | // do something.... 212 | } 213 | // Es5 write 214 | onload: async function () { 215 | let res = await wf.get('/get') 216 | console.log(res) 217 | 218 | // do something.... 219 | } 220 | ``` 221 | ## Get the `requestTask` Object 222 | Sample code of get request: 223 | ```js 224 | wf.get('/get',{ config: {eventType: 'get'}}) 225 | 226 | // abort the request 227 | wf.on('get', t => { 228 | t.abort() 229 | }) 230 | // Batch Processing the requestTask Object 231 | wf.get('/user/info',{ config: {eventType:'user'}}) 232 | wf.get('/user/permission',{ config: {eventType:'user'}}) 233 | wf.on('user', t => { 234 | // this current event handle will be execute the two times 235 | t.abort() 236 | }) 237 | ``` 238 | Sample code of upload request: 239 | 240 | ```js 241 | // promisify 242 | const chooseImage = wf.promisify(wx.chooseImage) 243 | chooseImage().then(res => { 244 | wf.upload('http://your-domain/upload', { 245 | filePath: res.tempFilePaths[0], 246 | name: 'file', 247 | config: { eventType: 'upload'} 248 | }).then(res => { 249 | console.log(res) 250 | }); 251 | wf.on('upload', t => { 252 | t.onProgressUpdate((res) => { 253 | console.log('upload progress', res.progress) 254 | console.log('length of data already uploaded', res.totalBytesSent) 255 | console.log('total length of data expected to be uploaded', res.totalBytesExpectedToSend) 256 | }) 257 | }) 258 | }); 259 | // or like this: 260 | chooseImage().then(res => { 261 | wf.upload({ 262 | url: 'http://your-domain/upload', 263 | filePath: res.tempFilePaths[0], 264 | name: 'file', 265 | config: { 266 | eventType: 'upload' 267 | } 268 | }).then(res => { 269 | console.log(res) 270 | }); 271 | wf.on('upload', t => { 272 | t.onProgressUpdate((res) => { 273 | console.log('upload progress', res.progress) 274 | console.log('length of data already uploaded', res.totalBytesSent) 275 | console.log('total length of data expected to be uploaded', res.totalBytesExpectedToSend) 276 | }) 277 | }) 278 | }) 279 | ``` 280 | ## wefetch API 281 | #### wf.request(config) 282 | #### wf.get(url, {,data,config}) 283 | #### wf.post(url, {,data,config}) 284 | #### wf.head(url, {,data,config}) 285 | #### wf.put(url, {,data,config}) 286 | #### wf.get(url, {,data,config}) 287 | #### wf.trace(url, {,data,config}) 288 | #### wf.delete(url, {,data,config}) 289 | #### wf.upload(url, {,data,config}) or wf.upload(config) 290 | #### wf.download(url, {,data,config}) or wf.download(config) 291 | Creating an instance 292 | You can create a new instance of wefetch with a custom config 293 | ```js 294 | const instance = wf.create({ 295 | baseUrl: 'http://your-domain.com/api' 296 | //.... 297 | }) 298 | ``` 299 | Instance methods 300 | #### wf.request(config) 301 | #### wf.get(url, {,data,config}) 302 | #### wf.post(url, {,data,config}) 303 | #### wf.head(url, {,data,config}) 304 | #### wf.put(url, {,data,config}) 305 | #### wf.get(url, {,data,config}) 306 | #### wf.trace(url, {,data,config}) 307 | #### wf.delete(url, {,data,config}) 308 | #### wf.upload(url, {,data,config}) or wf.upload(config) 309 | #### wf.download(url, {,data,config}) or wf.download(config) 310 | 311 | ## Config Params 312 | ```js 313 | { 314 | // `url` is the server URL that will be used for the request 315 | url: '/user', 316 | 317 | // `baseURL` will be prepended to `url` 318 | baseUrl:'http://your-domain.com/api', 319 | 320 | // default method `get` 321 | method: 'get', 322 | 323 | // `uploadUrl` and `downloadUrl` will be prepended to `url`。 if your project have a different request path, you can like this to set it: 324 | uploadUrl:'http://your-domain.com/upload', 325 | 326 | downloadUrl: 'http://your-domain.com/download', 327 | 328 | // support `alipay` platform only 329 | timeout: 0, 330 | // send to back-end 331 | data:{ 332 | 333 | }, 334 | // if your want to the Mini Program to return a requestTask Object, you can custom the `eventType` 335 | // like this wf.on('your eventType', t => {...}) 336 | config:{ 337 | eventType: '' 338 | } 339 | // default `Content-Type` 340 | header: { 341 | 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' 342 | } 343 | } 344 | ``` 345 | ## Config Defaults 346 | 347 | **Global wefetch defaults** 348 | ```js 349 | wf.defaults.baseUrl = 'http://your-domain.com/api'; 350 | wf.defaults.uploadUrl = 'http://your-domain.com/upload'; 351 | wf.defaults.downloadUrl = 'http://your-domain.com/download'; 352 | ``` 353 | **Custom instance defaults** 354 | ```js 355 | const instance = wf.create() 356 | instance.defaults.baseUrl = 'http://your-domain.com/api'; 357 | instance.defaults.uploadUrl = 'http://your-domain.com/upload'; 358 | instance.defaults.downloadUrl = 'http://your-domain.com/download'; 359 | ``` 360 | ## Interceptors 361 | ```js 362 | // add a request interceptor 363 | wf.before.use(request => { 364 | // Do something before request is sent 365 | return request; 366 | }, error => { 367 | // Do something with request error 368 | return Promise.reject(error); 369 | }) 370 | 371 | // add a response interceptor 372 | wf.after.use(response => { 373 | // Do something with response data 374 | return response; 375 | }, error => { 376 | // Do something with response error 377 | return Promise.reject(error) 378 | }) 379 | ``` 380 | 381 | ## Promisify for Mini Program API 382 | ```js 383 | const chooseImage = wf.promisify(wx.chooseImage) 384 | // using in wechat Mini Program 385 | chooseImage().then(res => { 386 | // Do something ... 387 | console.log(res) 388 | }) 389 | ``` 390 | -------------------------------------------------------------------------------- /wefetch/dist/wefetch.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).wefetch=t()}(this,function(){"use strict";function e(){this.listeners={}}e.prototype.on=function(e,t){e in this.listeners||(this.listeners[e]=[]),this.listeners[e].push(t)},e.prototype.emit=function(e,t){var n=this.listeners[e];n&&n.forEach(function(e){e(t)})};var i=new e;function t(r){return function(n){(n=n||{}).config=n.config||{};for(var e=arguments.length,o=Array(1 { 28 | (option?: httpOption & { url: string }): Promise; 29 | (url: string, option?: httpOption): Promise; 30 | } 31 | 32 | interface downloadConfig { 33 | header?: httpHeader; 34 | filePath: string; 35 | [props: string]: any; 36 | } 37 | 38 | interface uploadConfig { 39 | header?: httpHeader; 40 | filePath: string; 41 | name: string; 42 | formData: { 43 | [props: string]: any; 44 | } 45 | [props: string]: any; 46 | } 47 | 48 | interface downloadType { 49 | (option?: downloadConfig & { url: string }): Promise; 50 | (url: string, option?: httpOption): Promise; 51 | } 52 | 53 | interface uploadType { 54 | (option?: uploadConfig & { url: string }): Promise; 55 | (url: string, option?: httpOption): Promise; 56 | } 57 | 58 | interface wefetch { 59 | defaults: { 60 | baseUrl: string; 61 | uploadUrl: string; 62 | downloadUrl: string; 63 | } 64 | create(options: createOption): wefetch; 65 | 66 | before: { 67 | use(resolveCallback?: (request:httpOption & { url: string }) => void, rejectCallback?: (reason:any) => void ): void 68 | eject(id: number): void; 69 | }; 70 | 71 | after: { 72 | use(resolveCallback?: (response) => void, rejectCallback?: (reason:any) => void ): void 73 | eject(id: number): void; 74 | }; 75 | 76 | request: requestType; 77 | 78 | get: requestType; 79 | 80 | post: requestType; 81 | 82 | head: requestType; 83 | 84 | connect: requestType; 85 | 86 | put: requestType; 87 | 88 | delete: requestType; 89 | 90 | trace: requestType; 91 | 92 | 93 | download: downloadType; 94 | 95 | upload: uploadType; 96 | 97 | 98 | on(eventType: string, callback: (requestTask: any) => void); 99 | 100 | abort(eventType: string, callback: () => void); 101 | 102 | onProcess(eventType: string, callback: (progress: any) => void); 103 | 104 | 105 | retry(times: number, request: requestType, timeout: number): Promise; 106 | 107 | finally(value?: any): Promise; 108 | 109 | all(promises?: Promise[]): Promise; 110 | 111 | 112 | promisify(api: any): (option: TConfig) => Promise; 113 | } 114 | 115 | declare const wefetchInstance:wefetch 116 | 117 | export default wefetchInstance 118 | -------------------------------------------------------------------------------- /wefetch/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./dist/wefetch.min.js') -------------------------------------------------------------------------------- /wefetch/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.3.5", 3 | "author": { 4 | "name": "Jonny.Shao" 5 | }, 6 | "bugs": { 7 | "url": "https://github.com/jonnyshao/wefetch/issues" 8 | }, 9 | "bundleDependencies": [], 10 | "deprecated": false, 11 | "description": "Promise based wx.request api for Mini Program,小程序请求库,基于promise设计", 12 | "homepage": "https://github.com/jonnyshao/wefetch#readme", 13 | "keywords": [ 14 | "mini-program-request", 15 | "weChat-request", 16 | "wefecth", 17 | "wechatfetch" 18 | ], 19 | "license": "MIT", 20 | "main": "index.js", 21 | "name": "wefetch", 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/jonnyshao/wefetch.git" 25 | }, 26 | "scripts": {} 27 | } --------------------------------------------------------------------------------