├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── index.js ├── package.json └── test └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store* 3 | *.log 4 | *.gz 5 | 6 | node_modules 7 | coverage 8 | cache 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | node_js: 2 | - "0.8" 3 | - "0.10" 4 | - "0.11" 5 | language: node_js 6 | script: "npm run-script test-travis" 7 | after_script: "npm install coveralls@2 && cat ./coverage/lcov.info | coveralls" 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2014 Jonathan Ong me@jongleberry.com 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [!CAUTION] 2 | > **This repository is archived and no longer actively maintained.** 3 | > 4 | > We are no longer accepting issues, feature requests, or pull requests. 5 | > For additional support or questions, please visit the [Express.js Discussions page](https://github.com/expressjs/express/discussions). 6 | 7 | 8 | # flash 9 | 10 | [![NPM version][npm-image]][npm-url] 11 | [![Build status][travis-image]][travis-url] 12 | [![Test coverage][coveralls-image]][coveralls-url] 13 | [![Dependency Status][david-image]][david-url] 14 | [![License][license-image]][license-url] 15 | [![Downloads][downloads-image]][downloads-url] 16 | 17 | The simplest flash implementation for Express. 18 | 19 | ## Usage 20 | 21 | ```bash 22 | npm i flash 23 | ``` 24 | 25 | ```js 26 | app.use(session()); // session middleware 27 | app.use(require('flash')()); 28 | 29 | app.use(function (req, res) { 30 | // flash a message 31 | req.flash('info', 'hello!'); 32 | next(); 33 | }) 34 | ``` 35 | 36 | ```jade 37 | for message in flash 38 | a.alert(class='alert-' + message.type) 39 | p= message.message 40 | ``` 41 | 42 | ```jade 43 | while message = flash.shift() // consume messages as jade reads them 44 | a.alert(class='alert-' + message.type) 45 | p= message.message 46 | ``` 47 | 48 | ## API 49 | 50 | ### req.flash([type], msg) 51 | 52 | Flash a message defaulting the `type` to `info`. 53 | 54 | ### res.locals.flash 55 | 56 | An array of flash messages of the form: 57 | 58 | ```json 59 | { 60 | "type": "info", 61 | "message": "message" 62 | } 63 | ``` 64 | 65 | [npm-image]: https://img.shields.io/npm/v/flash.svg?style=flat-square 66 | [npm-url]: https://npmjs.org/package/flash 67 | [github-tag]: http://img.shields.io/github/tag/expressjs/flash.svg?style=flat-square 68 | [github-url]: https://github.com/expressjs/flash/tags 69 | [travis-image]: https://img.shields.io/travis/expressjs/flash.svg?style=flat-square 70 | [travis-url]: https://travis-ci.org/expressjs/flash 71 | [coveralls-image]: https://img.shields.io/coveralls/expressjs/flash.svg?style=flat-square 72 | [coveralls-url]: https://coveralls.io/r/expressjs/flash?branch=master 73 | [david-image]: http://img.shields.io/david/expressjs/flash.svg?style=flat-square 74 | [david-url]: https://david-dm.org/expressjs/flash 75 | [license-image]: http://img.shields.io/npm/l/flash.svg?style=flat-square 76 | [license-url]: LICENSE 77 | [downloads-image]: http://img.shields.io/npm/dm/flash.svg?style=flat-square 78 | [downloads-url]: https://npmjs.org/package/flash 79 | [gittip-image]: https://img.shields.io/gittip/jonathanong.svg?style=flat-square 80 | [gittip-url]: https://www.gittip.com/jonathanong/ 81 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | var assert = require('assert') 3 | 4 | module.exports = function () { 5 | return function (req, res, next) { 6 | assert(req.session, 'a req.session is required!') 7 | if (!Array.isArray(req.session.flash)) req.session.flash = [] 8 | res.locals.flash = req.session.flash 9 | req.flash = res.flash = push 10 | next() 11 | } 12 | } 13 | 14 | function push(type, msg) { 15 | if (!msg) { 16 | msg = type 17 | type = 'info' 18 | } 19 | msg = { 20 | message: msg, 21 | type: type 22 | } 23 | var res = this.res || this 24 | var messages = res.locals.flash 25 | // do not allow duplicate flash messages 26 | for (var i = 0; i < messages.length; i++) { 27 | var message = messages[i] 28 | if (msg.type === message.type && msg.message === message.message) return this 29 | } 30 | messages.push(msg) 31 | return this 32 | } 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flash", 3 | "description": "Simple flash messages for Express", 4 | "version": "1.1.0", 5 | "author": { 6 | "name": "Jonathan Ong", 7 | "email": "me@jongleberry.com", 8 | "url": "http://jongleberry.com", 9 | "twitter": "https://twitter.com/jongleberry" 10 | }, 11 | "license": "MIT", 12 | "repository": "expressjs/flash", 13 | "dependencies": {}, 14 | "devDependencies": { 15 | "cookie-session": "1", 16 | "supertest": "0", 17 | "express": "4", 18 | "istanbul": "0", 19 | "mocha": "1" 20 | }, 21 | "scripts": { 22 | "test": "mocha --reporter spec", 23 | "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot", 24 | "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter dot" 25 | }, 26 | "keywords": [ 27 | "flash", 28 | "messages", 29 | "express" 30 | ], 31 | "files": [ 32 | "index.js", 33 | "LICENSE" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | 2 | var session = require('cookie-session') 3 | var request = require('supertest') 4 | var express = require('express') 5 | var assert = require('assert') 6 | 7 | var flash = require('..') 8 | 9 | describe('Flash', function () { 10 | it('should set .locals.flash and .session.flash', function (done) { 11 | var app = express() 12 | app.use(session({ 13 | keys: ['a', 'b'] 14 | })) 15 | app.use(flash()) 16 | 17 | app.use(function (req, res) { 18 | assert(Array.isArray(res.locals.flash)) 19 | assert(Array.isArray(req.session.flash)) 20 | assert.equal(res.locals.flash, req.session.flash) 21 | res.end() 22 | }) 23 | 24 | request(app.listen()) 25 | .get('/') 26 | .expect(200, done) 27 | }) 28 | 29 | it('should push messages via req.flash()', function (done) { 30 | var app = express() 31 | app.use(session({ 32 | keys: ['a', 'b'] 33 | })) 34 | app.use(flash()) 35 | 36 | app.use(function (req, res) { 37 | req.flash('one') 38 | req.flash('error', 'two') 39 | assert.deepEqual(res.locals.flash, [{ 40 | type: 'info', 41 | message: 'one' 42 | }, { 43 | type: 'error', 44 | message: 'two' 45 | }]) 46 | res.end() 47 | }) 48 | 49 | request(app.listen()) 50 | .get('/') 51 | .expect(200, done) 52 | }) 53 | 54 | it('should not allow duplicate flash messages', function (done) { 55 | var app = express() 56 | app.use(session({ 57 | keys: ['a', 'b'] 58 | })) 59 | app.use(flash()) 60 | 61 | app.use(function (req, res) { 62 | req.flash('one') 63 | req.flash('one') 64 | assert.deepEqual(res.locals.flash, [{ 65 | type: 'info', 66 | message: 'one' 67 | }]) 68 | res.end() 69 | }) 70 | 71 | request(app.listen()) 72 | .get('/') 73 | .expect(200, done) 74 | }) 75 | 76 | it('should overwrite non-array flash locals', function (done) { 77 | var app = express() 78 | app.use(session({ 79 | keys: ['a', 'b'] 80 | })) 81 | app.use(function (req, res, next) { 82 | req.session.flash = {} 83 | next() 84 | }) 85 | app.use(flash()) 86 | 87 | app.use(function (req, res) { 88 | req.flash('one') 89 | req.flash('one') 90 | assert.deepEqual(res.locals.flash, [{ 91 | type: 'info', 92 | message: 'one' 93 | }]) 94 | res.end() 95 | }) 96 | 97 | request(app.listen()) 98 | .get('/') 99 | .expect(200, done) 100 | }) 101 | 102 | it('should support res.flash()', function (done) { 103 | var app = express() 104 | app.use(session({ 105 | keys: ['a', 'b'] 106 | })) 107 | app.use(flash()) 108 | 109 | app.use(function (req, res) { 110 | res.flash('one') 111 | res.flash('one') 112 | assert.deepEqual(res.locals.flash, [{ 113 | type: 'info', 114 | message: 'one' 115 | }]) 116 | res.end() 117 | }) 118 | 119 | request(app.listen()) 120 | .get('/') 121 | .expect(200, done) 122 | }) 123 | }) 124 | --------------------------------------------------------------------------------