├── .github └── workflows │ └── npm_publish.yml ├── .gitignore ├── LICENSE ├── README.md ├── docs └── v3 │ └── README.md ├── lib └── defaults.json ├── package.json ├── server ├── bootstrap.js ├── config │ └── index.js ├── destroy.js ├── index.js ├── middlewares │ └── index.js └── register.js ├── strapi-server.js └── yarn.lock /.github/workflows/npm_publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Library 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | publish-npm: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - uses: actions/setup-node@v2 14 | with: 15 | node-version: 14 16 | registry-url: https://registry.npmjs.org/ 17 | - run: npm publish 18 | env: 19 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,node 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,node 3 | 4 | ### Node ### 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | 13 | # Diagnostic reports (https://nodejs.org/api/report.html) 14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 15 | 16 | # Runtime data 17 | pids 18 | *.pid 19 | *.seed 20 | *.pid.lock 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | lib-cov 24 | 25 | # Coverage directory used by tools like istanbul 26 | coverage 27 | *.lcov 28 | 29 | # nyc test coverage 30 | .nyc_output 31 | 32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 33 | .grunt 34 | 35 | # Bower dependency directory (https://bower.io/) 36 | bower_components 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # Compiled binary addons (https://nodejs.org/api/addons.html) 42 | build/Release 43 | 44 | # Dependency directories 45 | node_modules/ 46 | jspm_packages/ 47 | 48 | # TypeScript v1 declaration files 49 | typings/ 50 | 51 | # TypeScript cache 52 | *.tsbuildinfo 53 | 54 | # Optional npm cache directory 55 | .npm 56 | 57 | # Optional eslint cache 58 | .eslintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variables file 76 | .env 77 | .env.test 78 | .env*.local 79 | 80 | # parcel-bundler cache (https://parceljs.org/) 81 | .cache 82 | .parcel-cache 83 | 84 | # Next.js build output 85 | .next 86 | 87 | # Nuxt.js build / generate output 88 | .nuxt 89 | dist 90 | 91 | # Gatsby files 92 | .cache/ 93 | # Comment in the public line in if your project uses Gatsby and not Next.js 94 | # https://nextjs.org/blog/next-9-1#public-directory-support 95 | # public 96 | 97 | # vuepress build output 98 | .vuepress/dist 99 | 100 | # Serverless directories 101 | .serverless/ 102 | 103 | # FuseBox cache 104 | .fusebox/ 105 | 106 | # DynamoDB Local files 107 | .dynamodb/ 108 | 109 | # TernJS port file 110 | .tern-port 111 | 112 | # Stores VSCode versions used for testing VSCode extensions 113 | .vscode-test 114 | 115 | ### VisualStudioCode ### 116 | .vscode/* 117 | !.vscode/tasks.json 118 | !.vscode/launch.json 119 | *.code-workspace 120 | 121 | ### VisualStudioCode Patch ### 122 | # Ignore all local history of files 123 | .history 124 | .ionide 125 | 126 | # End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,node -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Alexander Kainzinger 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # strapi-middleware-upload-plugin-cache 2 | 3 | ## Use case 4 | 5 | - `@strapi/provider-upload-local` is in use for uploading assets via `Media Library` in Strapi (default) 6 | - The need for configurable cache-control HTTP response headers (e.g. `cache-control: max-age=1234`) + [ETag HTTP response header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) for each asset 7 | - More information and differences between `koa-static` (used in `@strapi/provider-upload-local`) and `koa-static-cache` (used in this middleware-plugin) can be found [here](https://github.com/koajs/static-cache) 8 | 9 | ## Installing 10 | 11 | ### For Strapi 4.3+ 12 | 13 | [Strapi 4.3](https://github.com/strapi/strapi/releases/tag/v4.3.0) had breaking changes with asset organization through folders. 14 | 15 | Make sure you are using at least v2.1.0 of this library with Strapi 4.3+! 16 | 17 | Using npm 18 | 19 | ``` 20 | npm install strapi-middleware-upload-plugin-cache 21 | ``` 22 | 23 | Using yarn 24 | 25 | ``` 26 | yarn add strapi-middleware-upload-plugin-cache 27 | ``` 28 | 29 | ### For Strapi 4.0.0 - 4.2.X 30 | 31 | Using npm 32 | 33 | ``` 34 | npm install strapi-middleware-upload-plugin-cache@2.0.0 35 | ``` 36 | 37 | Using yarn 38 | 39 | ``` 40 | yarn add strapi-middleware-upload-plugin-cache@2.0.0 41 | ``` 42 | 43 | ### For Strapi 3 44 | 45 | Version 2.X.X+ of this library is **NOT** compatible with Strapi v3! 46 | 47 | Please make sure to check out the [Strapi v3 Docs](docs/v3/README.md) for the installation & setup. 48 | 49 | ## Setup 50 | 51 | For Strapi, add a `plugins.js` file within the config folder 52 | 53 | e.g. 54 | 55 | ``` 56 | touch config/plugins.js 57 | ``` 58 | 59 | containing 60 | 61 | ``` 62 | module.exports = { 63 | "upload-plugin-cache": { 64 | enabled: true, 65 | config: { 66 | maxAge: 86_400_000, 67 | }, 68 | } 69 | }; 70 | ``` 71 | 72 | Starting Strapi in dev-mode should log the following: 73 | 74 | ``` 75 | [2022-02-22 22:22:22.222] debug: [upload-plugin-cache] Initializing ... 76 | [2022-02-22 22:22:22.222] debug: [upload-plugin-cache] Middleware initialized for endpoint='/uploads/(.*)' [maxAge=300000] 77 | ``` 78 | 79 | ## Configuration Options 80 | 81 | With the option `dynamic: true` files which are not cached on initializations are dynamically loaded. To avoid OOM errors a [LRU-cache can be used](https://www.npmjs.com/package/@zhennann/koa-static-cache#using-a-lru-cache-to-avoid-oom-when-dynamic-mode-enabled). For config options of lru-cache use these [docs](https://www.npmjs.com/package/lru-cache) and insert them at `lruCache`. 82 | 83 | ``` 84 | module.exports = { 85 | "upload-plugin-cache": { 86 | enabled: true, 87 | config: { 88 | maxAge: 86_400_000, 89 | dynamic: true, 90 | lruCache: { 91 | max: 1000 92 | }, 93 | }, 94 | } 95 | }; 96 | ``` 97 | 98 | ## Resources 99 | 100 | - [License](LICENSE) 101 | 102 | ## Links 103 | 104 | - [Strapi website](http://strapi.io/) 105 | - [Strapi community on Slack](http://slack.strapi.io) 106 | - [Strapi news on Twitter](https://twitter.com/strapijs) 107 | -------------------------------------------------------------------------------- /docs/v3/README.md: -------------------------------------------------------------------------------- 1 | # strapi-middleware-upload-plugin-cache 2 | 3 | ## Use case 4 | - ``@strapi/provider-upload-local`` is in use for uploading assets via ``Media Library`` in Strapi (default) 5 | - The need for configurable cache-control HTTP response headers (e.g. ``cache-control: max-age=1234``) + [ETag HTTP response header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) for each asset 6 | - More information and differences between ``koa-static`` (used in ``@strapi/provider-upload-local``) and ``koa-static-cache`` (used in this middleware-plugin) can be found [here](https://github.com/koajs/static-cache) 7 | 8 | ## Installing 9 | 10 | ### For Strapi 4 11 | Please make sure to check out the [Strapi v4 Docs](../../README.md) for the installation & setup. 12 | 13 | 14 | ### For Strapi 3 15 | Using npm 16 | 17 | ``` 18 | npm install --save strapi-middleware-upload-plugin-cache@1 19 | ``` 20 | 21 | Using yarn 22 | 23 | ``` 24 | yarn add strapi-middleware-upload-plugin-cache@1 25 | ``` 26 | 27 | 28 | ## Setup 29 | For Strapi, add a ``middleware.js`` file within the config folder 30 | 31 | e.g. 32 | ``` 33 | touch config/middleware.js 34 | ``` 35 | 36 | containing 37 | 38 | ``` 39 | module.exports = ({ env }) => ({ 40 | settings: { 41 | 'upload-plugin-cache': { 42 | enabled: true, 43 | maxAge: 86400000 44 | } 45 | } 46 | }); 47 | ``` 48 | 49 | Starting Strapi in dev-mode should log the following: 50 | ``` 51 | [2022-02-22 22:22:22.222] debug [UploadCache] Initializing middleware ... 52 | [2022-02-22 22:22:22.222] debug [UploadCache] Middleware initialized for endpoint='/uploads/(.*)' [maxAge=86400000] 53 | ``` 54 | 55 | 56 | ## Configuration Options 57 | With the option ``dynamic: true`` files which are not cached on initializations are dynamically loaded. To avoid OOM errors a [LRU-cache can be used](https://www.npmjs.com/package/@zhennann/koa-static-cache#using-a-lru-cache-to-avoid-oom-when-dynamic-mode-enabled). For config options of lru-cache use these [docs](https://www.npmjs.com/package/lru-cache) and insert them at ``lruCache``. 58 | 59 | ``` 60 | module.exports = ({ env }) => ({ 61 | settings: { 62 | 'upload-plugin-cache': { 63 | enabled: true, 64 | maxAge: 86400000, 65 | dynamic: true, 66 | lruCache: { 67 | max: 1000 68 | } 69 | } 70 | } 71 | }); 72 | ``` 73 | 74 | ## Resources 75 | 76 | - [License](LICENSE) 77 | 78 | ## Links 79 | 80 | - [Strapi website](http://strapi.io/) 81 | - [Strapi community on Slack](http://slack.strapi.io) 82 | - [Strapi news on Twitter](https://twitter.com/strapijs) -------------------------------------------------------------------------------- /lib/defaults.json: -------------------------------------------------------------------------------- 1 | { 2 | "upload-plugin-cache": { 3 | "enabled": true, 4 | "maxAge": 86400000 5 | } 6 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "strapi-middleware-upload-plugin-cache", 3 | "version": "2.1.0", 4 | "description": "Adds middleware for caching uploaded assets when using @strapi/provider-upload-local", 5 | "license": "MIT", 6 | "author": { 7 | "name": "Alexander Kainzinger", 8 | "email": "office@kainzinger.dev", 9 | "url": "https://kainzinger.dev" 10 | }, 11 | "maintainers": [ 12 | { 13 | "name": "Alexander Kainzinger", 14 | "email": "office@kainzinger.dev", 15 | "url": "https://kainzinger.dev" 16 | } 17 | ], 18 | "keywords": [ 19 | "strapi", 20 | "cache", 21 | "uploads" 22 | ], 23 | "strapi": { 24 | "name": "upload-plugin-cache", 25 | "description": "Adds middleware for caching uploaded assets when using @strapi/provider-upload-local", 26 | "kind": "plugin" 27 | }, 28 | "scripts": { 29 | "test": "echo \"Error: no test specified\" && exit 1" 30 | }, 31 | "dependencies": { 32 | "koa-range": "^0.3.0", 33 | "koa-static-cache": "^5.1.4", 34 | "lru-cache": "^7.4.0" 35 | }, 36 | "repository": { 37 | "type": "git", 38 | "url": "git+https://github.com/alexkainzinger/strapi-middleware-upload-plugin-cache.git" 39 | }, 40 | "bugs": { 41 | "url": "https://github.com/alexkainzinger/strapi-middleware-upload-plugin-cache/issues" 42 | }, 43 | "homepage": "https://github.com/alexkainzinger/strapi-middleware-upload-plugin-cache#readme" 44 | } -------------------------------------------------------------------------------- /server/bootstrap.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const uploadCacheMiddleware = require('./middlewares'); 4 | 5 | module.exports = async ({ strapi }) => { 6 | uploadCacheMiddleware({ strapi }); 7 | }; 8 | -------------------------------------------------------------------------------- /server/config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | default: { 5 | dynamic: false, 6 | maxAge: 86_400_000, 7 | lruOptions: { 8 | max: 1000 9 | } 10 | }, 11 | validator() {}, 12 | }; 13 | -------------------------------------------------------------------------------- /server/destroy.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = ({ strapi }) => { 4 | // destroy phase 5 | }; 6 | -------------------------------------------------------------------------------- /server/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const register = require('./register'); 4 | const bootstrap = require('./bootstrap'); 5 | const destroy = require('./destroy'); 6 | const config = require('./config'); 7 | 8 | module.exports = { 9 | register, 10 | bootstrap, 11 | destroy, 12 | config, 13 | }; 14 | -------------------------------------------------------------------------------- /server/middlewares/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const range = require("koa-range"); 4 | const staticCache = require("koa-static-cache"); 5 | const LRU = require("lru-cache"); 6 | 7 | const PLUGIN_NAME = "upload-plugin-cache"; 8 | const UPLOAD_PATH = "/uploads/(.*)"; 9 | 10 | /** 11 | * Creates the middleware for strapi 12 | * @param {{ strapi: import('@strapi/strapi').Strapi }} 13 | */ 14 | module.exports = ({ strapi }) => { 15 | /** 16 | * 17 | * @param {string} msg message which should be printed 18 | */ 19 | const debug = (msg) => strapi.log.debug(`[${PLUGIN_NAME}] ${msg}`); 20 | 21 | debug("Initializing ..."); 22 | 23 | const options = strapi.config.get(`plugin.${PLUGIN_NAME}`, {}); 24 | 25 | const dynamic = !!options.dynamic; 26 | const files = dynamic ? new LRU(options.lruOptions) : {}; 27 | 28 | debug( 29 | `Middleware initialized for endpoint='${UPLOAD_PATH}' [maxAge=${options.maxAge}]` 30 | ); 31 | 32 | const publicDir = 33 | typeof strapi.dirs.static === "object" 34 | ? strapi.dirs.static.public // Strapi 4.3+ 35 | : strapi.dirs.public; // Strapi < 4.3 36 | 37 | strapi.server.routes([ 38 | { 39 | method: "GET", 40 | path: UPLOAD_PATH, 41 | handler: [range, staticCache(publicDir, { ...options, files })], 42 | config: { auth: false }, 43 | }, 44 | ]); 45 | }; 46 | -------------------------------------------------------------------------------- /server/register.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = ({ strapi }) => { 4 | // registeration phase 5 | }; 6 | -------------------------------------------------------------------------------- /strapi-server.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = require("./server"); 4 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | any-promise@^1.0.0: 6 | version "1.3.0" 7 | resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" 8 | integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= 9 | 10 | compressible@^2.0.6: 11 | version "2.0.18" 12 | resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" 13 | integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== 14 | dependencies: 15 | mime-db ">= 1.43.0 < 2" 16 | 17 | debug@^3.1.0: 18 | version "3.2.7" 19 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" 20 | integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== 21 | dependencies: 22 | ms "^2.1.1" 23 | 24 | fs-readdir-recursive@^1.0.0: 25 | version "1.1.0" 26 | resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" 27 | integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== 28 | 29 | koa-range@^0.3.0: 30 | version "0.3.0" 31 | resolved "https://registry.yarnpkg.com/koa-range/-/koa-range-0.3.0.tgz#3588e3496473a839a1bd264d2a42b1d85bd7feac" 32 | integrity sha1-NYjjSWRzqDmhvSZNKkKx2FvX/qw= 33 | dependencies: 34 | stream-slice "^0.1.2" 35 | 36 | koa-static-cache@^5.1.4: 37 | version "5.1.4" 38 | resolved "https://registry.yarnpkg.com/koa-static-cache/-/koa-static-cache-5.1.4.tgz#bb24bbae4845316d101da2f8a1d89088e1916afe" 39 | integrity sha512-abVWOHY6z6qSTvNtapWMAnvHS9SUiUCaQQQubClSAT9ybQPsZ6ioKcRarnownS4fMD0sXQgQ5ey8CYEuwoa1Yg== 40 | dependencies: 41 | compressible "^2.0.6" 42 | debug "^3.1.0" 43 | fs-readdir-recursive "^1.0.0" 44 | mime-types "^2.1.8" 45 | mz "^2.7.0" 46 | 47 | lru-cache@^7.4.0: 48 | version "7.14.0" 49 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.14.0.tgz#21be64954a4680e303a09e9468f880b98a0b3c7f" 50 | integrity sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ== 51 | 52 | mime-db@1.51.0: 53 | version "1.51.0" 54 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" 55 | integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== 56 | 57 | "mime-db@>= 1.43.0 < 2": 58 | version "1.52.0" 59 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 60 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 61 | 62 | mime-types@^2.1.8: 63 | version "2.1.34" 64 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" 65 | integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== 66 | dependencies: 67 | mime-db "1.51.0" 68 | 69 | ms@^2.1.1: 70 | version "2.1.3" 71 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 72 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 73 | 74 | mz@^2.7.0: 75 | version "2.7.0" 76 | resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" 77 | integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== 78 | dependencies: 79 | any-promise "^1.0.0" 80 | object-assign "^4.0.1" 81 | thenify-all "^1.0.0" 82 | 83 | object-assign@^4.0.1: 84 | version "4.1.1" 85 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 86 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 87 | 88 | stream-slice@^0.1.2: 89 | version "0.1.2" 90 | resolved "https://registry.yarnpkg.com/stream-slice/-/stream-slice-0.1.2.tgz#2dc4f4e1b936fb13f3eb39a2def1932798d07a4b" 91 | integrity sha1-LcT04bk2+xPz6zmi3vGTJ5jQeks= 92 | 93 | thenify-all@^1.0.0: 94 | version "1.6.0" 95 | resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" 96 | integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= 97 | dependencies: 98 | thenify ">= 3.1.0 < 4" 99 | 100 | "thenify@>= 3.1.0 < 4": 101 | version "3.3.1" 102 | resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" 103 | integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== 104 | dependencies: 105 | any-promise "^1.0.0" 106 | --------------------------------------------------------------------------------