├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── README.md ├── client.js ├── example.js ├── index.html ├── index.js ├── package.json ├── tap-snapshots └── test.js-TAP.test.js └── test.js /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: '/' 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | - package-ecosystem: npm 9 | directory: '/' 10 | schedule: 11 | interval: daily 12 | open-pull-requests-limit: 10 13 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - 'docs/**' 7 | - '*.md' 8 | pull_request: 9 | paths-ignore: 10 | - 'docs/**' 11 | - '*.md' 12 | 13 | jobs: 14 | test: 15 | runs-on: ${{ matrix.os }} 16 | 17 | strategy: 18 | matrix: 19 | node-version: [6.x, 8.x, 9.x] 20 | os: [macOS-latest, windows-latest, ubuntu-latest] 21 | 22 | steps: 23 | - uses: actions/checkout@v2 24 | 25 | - name: Use Node.js 26 | uses: actions/setup-node@v2.1.5 27 | with: 28 | node-version: ${{ matrix.node-version }} 29 | 30 | - name: Install Dependencies 31 | run: | 32 | npm install --ignore-scripts 33 | 34 | - name: Run Tests 35 | run: | 36 | npm run test:ci 37 | 38 | - name: Coveralls Parallel 39 | uses: coverallsapp/github-action@v1.1.2 40 | with: 41 | github-token: ${{ secrets.github_token }} 42 | parallel: true 43 | flag-name: run-${{ matrix.node-version }}-${{ matrix.os }} 44 | 45 | coverage: 46 | needs: test 47 | runs-on: ubuntu-latest 48 | steps: 49 | - name: Coveralls Finished 50 | uses: coverallsapp/github-action@v1.1.2 51 | with: 52 | github-token: ${{ secrets.GITHUB_TOKEN }} 53 | parallel-finished: true 54 | 55 | automerge: 56 | needs: test 57 | runs-on: ubuntu-latest 58 | steps: 59 | - uses: fastify/github-action-merge-dependabot@v1.2.1 60 | if: ${{ github.actor == 'dependabot[bot]' && github.event_name == 'pull_request' }} 61 | with: 62 | github-token: ${{secrets.github_token}} 63 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # Snowpack dependency directory (https://snowpack.dev/) 45 | web_modules/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | .parcel-cache 78 | 79 | # Next.js build output 80 | .next 81 | out 82 | 83 | # Nuxt.js build / generate output 84 | .nuxt 85 | dist 86 | 87 | # Gatsby files 88 | .cache/ 89 | # Comment in the public line in if your project uses Gatsby and not Next.js 90 | # https://nextjs.org/blog/next-9-1#public-directory-support 91 | # public 92 | 93 | # vuepress build output 94 | .vuepress/dist 95 | 96 | # Serverless directories 97 | .serverless/ 98 | 99 | # FuseBox cache 100 | .fusebox/ 101 | 102 | # DynamoDB Local files 103 | .dynamodb/ 104 | 105 | # TernJS port file 106 | .tern-port 107 | 108 | # Stores VSCode versions used for testing VSCode extensions 109 | .vscode-test 110 | 111 | # yarn v2 112 | .yarn/cache 113 | .yarn/unplugged 114 | .yarn/build-state.yml 115 | .yarn/install-state.gz 116 | .pnp.* 117 | 118 | # Vim swap files 119 | *.swp 120 | 121 | # macOS files 122 | .DS_Store 123 | 124 | # lock files 125 | package-lock.json 126 | yarn.lock 127 | 128 | # editor files 129 | .vscode 130 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Fastify 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.md: -------------------------------------------------------------------------------- 1 | # fastify-bankai 2 | [](http://standardjs.com/) [](https://travis-ci.org/fastify/fastify-bankai) [](https://greenkeeper.io/) 3 | 4 | If you need to compile (browserify style!) your code, this plugin is for you! 5 | Internally it uses [bankai](https://github.com/yoshuawuyts/bankai), so refer to its documentation for the options. 6 | 7 | **fastify-bankai** will automatically live-reload your HTML and 8 | regenerate your bundle whenever your code change. This can be disabled 9 | in test or in production. 10 | 11 | ## Install 12 | ``` 13 | npm i fastify-bankai --save 14 | ``` 15 | 16 | ## Usage 17 | Simply require this plugin, pass the entry file and you are done! 18 | ```js 19 | const fastify = require('fastify')() 20 | 21 | fastify.register(require('fastify-bankai'), { 22 | entry: './client.js' 23 | }) 24 | 25 | fastify.listen(3000, err => { 26 | if (err) throw err 27 | console.log('Server listenting on localhost:', fastify.server.address().port) 28 | }) 29 | ``` 30 | 31 | ### In tests or in production 32 | 33 | If you are including fastify-bankai in any test run or in production, you **must** disable 34 | the automatic watch mode: 35 | 36 | ```js 37 | const fastify = require('fastify')() 38 | 39 | fastify.register(require('fastify-bankai'), { 40 | entry: './client.js', 41 | watch: false 42 | }) 43 | 44 | fastify.listen(3000, err => { 45 | if (err) throw err 46 | console.log('Server listenting on localhost:', fastify.server.address().port) 47 | }) 48 | ``` 49 | 50 | ## Options 51 | 52 | - `entry`: Your application entry point 53 | - `prefix`: prefix all paths served by fastify-bankai with the given 54 | path 55 | 56 | The option object is passed directly to bankai. 57 | 58 | ## Acknowledgements 59 | 60 | This project is kindly sponsored by: 61 | - [nearForm](http://nearform.com) 62 | - [LetzDoIt](http://www.letzdoitapp.com/) 63 | 64 | ## License 65 | 66 | Licensed under [MIT](./LICENSE). 67 | -------------------------------------------------------------------------------- /client.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | document.write('hello world!') 4 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fastify = require('fastify')() 4 | 5 | fastify.register(require('./index'), { 6 | entry: './client.js', 7 | html: './index.html' 8 | }) 9 | 10 | fastify.listen(3000, err => { 11 | if (err) throw err 12 | console.log('Server listenting on localhost:', fastify.server.address().port) 13 | }) 14 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const createReadStream = require('fs').createReadStream 4 | const resolve = require('path').resolve 5 | const bankai = require('bankai') 6 | const fp = require('fastify-plugin') 7 | 8 | function fastifyBankai (fastify, opts, next) { 9 | if (!opts.entry) { 10 | return next(new Error('missing entry file')) 11 | } 12 | if (typeof opts.entry !== 'string') { 13 | return next(new Error('entry must be a string')) 14 | } 15 | if (opts.html && typeof opts.html !== 'string') { 16 | return next(new Error('html must be a string')) 17 | } 18 | 19 | var prefix = (opts.prefix || '').replace(/^\/?(.*)\/+$/, '/$1') 20 | delete opts.prefix 21 | const html = !!opts.html 22 | const htmlPath = resolve(opts.html || '') 23 | 24 | // be quiet by default 25 | if (opts.quiet === undefined) { 26 | opts.quiet = true 27 | } 28 | 29 | const compiler = bankai(resolve(opts.entry), opts) 30 | 31 | if (prefix && prefix.indexOf('/') !== 0) { 32 | prefix = '/' + prefix 33 | } 34 | 35 | const rootRoute = `${prefix || '/'}` 36 | 37 | // TODO is this needed? 38 | if (html) { 39 | fastify.get(rootRoute, (req, reply) => { 40 | reply 41 | .header('Content-Type', 'text/html') 42 | .send(createReadStream(htmlPath)) 43 | }) 44 | } else { 45 | fastify.get(rootRoute, (req, reply) => { 46 | compiler.documents('/', (err, data) => { 47 | if (err) { 48 | reply.send(err) 49 | return 50 | } 51 | reply 52 | .header('content-type', 'text/html') 53 | .send(data.buffer) 54 | }) 55 | }) 56 | } 57 | 58 | fastify.get(`${prefix}/:file`, (req, reply) => { 59 | const [file, ext] = req.params.file.split('.') 60 | switch (ext) { 61 | case 'html': 62 | compiler.documents(req.req.url, (err, data) => { 63 | if (err) { 64 | reply.send(err) 65 | return 66 | } 67 | reply 68 | .header('content-type', 'text/html') 69 | .send(data) 70 | }) 71 | break 72 | case 'js': 73 | compiler.scripts(file, (err, data) => { 74 | if (err) { 75 | reply.send(err) 76 | return 77 | } 78 | reply 79 | .header('content-type', 'application/javascript') 80 | .send(data.buffer) 81 | }) 82 | break 83 | case 'css': 84 | compiler.styles(file, (err, data) => { 85 | if (err) { 86 | reply.send(err) 87 | return 88 | } 89 | reply 90 | .header('content-type', 'text/css') 91 | .send(data.buffer) 92 | }) 93 | break 94 | default: 95 | compiler.assets(req.req.url, (err, data) => { 96 | if (err) { 97 | return reply 98 | .code(404) 99 | .send(err) 100 | } 101 | 102 | // TODO set the correct mime type? 103 | reply.send(data.buffer) 104 | }) 105 | } 106 | }) 107 | 108 | fastify.addHook('onClose', (f, done) => { 109 | compiler.close() 110 | setImmediate(done) 111 | }) 112 | 113 | compiler.once('change', () => { next() }) 114 | } 115 | 116 | module.exports = fp(fastifyBankai, { 117 | name: 'fastify-bankai', 118 | fastify: '>= 0.40.0' 119 | }) 120 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fastify-bankai", 3 | "version": "0.3.1", 4 | "description": "Bankai assets compiler for Fastify", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "standard && tap test.js", 8 | "test:ci": "standard && tap test.js --coverage-report=lcovonly" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/fastify/fastify-bankai.git" 13 | }, 14 | "keywords": [ 15 | "browserify", 16 | "bankai", 17 | "assets", 18 | "html", 19 | "css", 20 | "js", 21 | "fastify", 22 | "compile" 23 | ], 24 | "author": "Tomas Della Vedova - @delvedor (http://delved.org)", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/fastify/fastify-bankai/issues" 28 | }, 29 | "homepage": "https://github.com/fastify/fastify-bankai#readme", 30 | "devDependencies": { 31 | "fastify": "^0.40.0", 32 | "pre-commit": "^1.2.2", 33 | "standard": "^10.0.3", 34 | "tap": "^11.0.0" 35 | }, 36 | "dependencies": { 37 | "bankai": "^9.4.0", 38 | "fastify-plugin": "^0.2.1" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tap-snapshots/test.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`test.js TAP expose a route with the assets > undefined 1`] = ` 9 |