mirror of
https://github.com/YunoHost-Apps/haste_ynh.git
synced 2024-09-03 20:36:28 +02:00
commit
7fbdc13a0f
36 changed files with 0 additions and 2652 deletions
|
@ -1,2 +0,0 @@
|
||||||
**/*.min.js
|
|
||||||
config.js
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"env": {
|
|
||||||
"es6": true,
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"extends": "eslint:recommended",
|
|
||||||
"rules": {
|
|
||||||
"indent": [
|
|
||||||
"error",
|
|
||||||
2
|
|
||||||
],
|
|
||||||
"linebreak-style": [
|
|
||||||
"error",
|
|
||||||
"unix"
|
|
||||||
],
|
|
||||||
"quotes": [
|
|
||||||
"error",
|
|
||||||
"single"
|
|
||||||
],
|
|
||||||
"semi": [
|
|
||||||
"error",
|
|
||||||
"always"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
6
sources/haste-server-master/.gitignore
vendored
6
sources/haste-server-master/.gitignore
vendored
|
@ -1,6 +0,0 @@
|
||||||
npm-debug.log
|
|
||||||
node_modules
|
|
||||||
*.swp
|
|
||||||
*.swo
|
|
||||||
data
|
|
||||||
*.DS_Store
|
|
|
@ -1 +0,0 @@
|
||||||
web: node server.js
|
|
|
@ -1,271 +0,0 @@
|
||||||
# Haste
|
|
||||||
|
|
||||||
Haste is an open-source pastebin software written in node.js, which is easily
|
|
||||||
installable in any network. It can be backed by either redis or filesystem,
|
|
||||||
and has a very easy adapter interface for other stores. A publicly available
|
|
||||||
version can be found at [hastebin.com](http://hastebin.com)
|
|
||||||
|
|
||||||
Major design objectives:
|
|
||||||
|
|
||||||
* Be really pretty
|
|
||||||
* Be really simple
|
|
||||||
* Be easy to set up and use
|
|
||||||
|
|
||||||
Haste works really well with a little utility called
|
|
||||||
[haste-client](https://github.com/seejohnrun/haste-client), allowing you
|
|
||||||
to do things like:
|
|
||||||
|
|
||||||
`cat something | haste`
|
|
||||||
|
|
||||||
which will output a URL to share containing the contents of `cat something`'s
|
|
||||||
STDOUT. Check the README there for more details and usages.
|
|
||||||
|
|
||||||
## Tested Browsers
|
|
||||||
|
|
||||||
* Firefox 8
|
|
||||||
* Chrome 17
|
|
||||||
* Safari 5.3
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
1. Download the package, and expand it
|
|
||||||
2. Explore the settings inside of config.js, but the defaults should be good
|
|
||||||
3. `npm install`
|
|
||||||
4. `npm start`
|
|
||||||
|
|
||||||
## Settings
|
|
||||||
|
|
||||||
* `host` - the host the server runs on (default localhost)
|
|
||||||
* `port` - the port the server runs on (default 7777)
|
|
||||||
* `keyLength` - the length of the keys to user (default 10)
|
|
||||||
* `maxLength` - maximum length of a paste (default 400000)
|
|
||||||
* `staticMaxAge` - max age for static assets (86400)
|
|
||||||
* `recompressStaticAssets` - whether or not to compile static js assets (true)
|
|
||||||
* `documents` - static documents to serve (ex: http://hastebin.com/about.com)
|
|
||||||
in addition to static assets. These will never expire.
|
|
||||||
* `storage` - storage options (see below)
|
|
||||||
* `logging` - logging preferences
|
|
||||||
* `keyGenerator` - key generator options (see below)
|
|
||||||
* `rateLimits` - settings for rate limiting (see below)
|
|
||||||
|
|
||||||
## Rate Limiting
|
|
||||||
|
|
||||||
When present, the `rateLimits` option enables built-in rate limiting courtesy
|
|
||||||
of `connect-ratelimit`. Any of the options supported by that library can be
|
|
||||||
used and set in `config.json`.
|
|
||||||
|
|
||||||
See the README for [connect-ratelimit](https://github.com/dharmafly/connect-ratelimit)
|
|
||||||
for more information!
|
|
||||||
|
|
||||||
## Key Generation
|
|
||||||
|
|
||||||
### Phonetic
|
|
||||||
|
|
||||||
Attempts to generate phonetic keys, similar to `pwgen`
|
|
||||||
|
|
||||||
``` json
|
|
||||||
{
|
|
||||||
"type": "phonetic"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Random
|
|
||||||
|
|
||||||
Generates a random key
|
|
||||||
|
|
||||||
``` json
|
|
||||||
{
|
|
||||||
"type": "random",
|
|
||||||
"keyspace": "abcdef"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The _optional_ keySpace argument is a string of acceptable characters
|
|
||||||
for the key.
|
|
||||||
|
|
||||||
## Storage
|
|
||||||
|
|
||||||
### File
|
|
||||||
|
|
||||||
To use file storage (the default) change the storage section in `config.js` to
|
|
||||||
something like:
|
|
||||||
|
|
||||||
``` json
|
|
||||||
{
|
|
||||||
"path": "./data",
|
|
||||||
"type": "file"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
where `path` represents where you want the files stored.
|
|
||||||
|
|
||||||
File storage currently does not support paste expiration, you can follow [#191](https://github.com/seejohnrun/haste-server/issues/191) for status updates.
|
|
||||||
|
|
||||||
### Redis
|
|
||||||
|
|
||||||
To use redis storage you must install the `redis` package in npm, and have
|
|
||||||
`redis-server` running on the machine.
|
|
||||||
|
|
||||||
`npm install redis`
|
|
||||||
|
|
||||||
Once you've done that, your config section should look like:
|
|
||||||
|
|
||||||
``` json
|
|
||||||
{
|
|
||||||
"type": "redis",
|
|
||||||
"host": "localhost",
|
|
||||||
"port": 6379,
|
|
||||||
"db": 2
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also set an `expire` option to the number of seconds to expire keys in.
|
|
||||||
This is off by default, but will constantly kick back expirations on each view
|
|
||||||
or post.
|
|
||||||
|
|
||||||
All of which are optional except `type` with very logical default values.
|
|
||||||
|
|
||||||
If your Redis server is configured for password authentification, use the `password` field.
|
|
||||||
|
|
||||||
### Postgres
|
|
||||||
|
|
||||||
To use postgres storage you must install the `pg` package in npm
|
|
||||||
|
|
||||||
`npm install pg`
|
|
||||||
|
|
||||||
Once you've done that, your config section should look like:
|
|
||||||
|
|
||||||
``` json
|
|
||||||
{
|
|
||||||
"type": "postgres",
|
|
||||||
"connectionUrl": "postgres://user:password@host:5432/database"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also just set the environment variable for `DATABASE_URL` to your database connection url.
|
|
||||||
|
|
||||||
You will have to manually add a table to your postgres database:
|
|
||||||
|
|
||||||
`create table entries (id serial primary key, key varchar(255) not null, value text not null, expiration int, unique(key));`
|
|
||||||
|
|
||||||
You can also set an `expire` option to the number of seconds to expire keys in.
|
|
||||||
This is off by default, but will constantly kick back expirations on each view
|
|
||||||
or post.
|
|
||||||
|
|
||||||
All of which are optional except `type` with very logical default values.
|
|
||||||
|
|
||||||
### Memcached
|
|
||||||
|
|
||||||
To use memcache storage you must install the `memcached` package via npm
|
|
||||||
|
|
||||||
`npm install memcached`
|
|
||||||
|
|
||||||
Once you've done that, your config section should look like:
|
|
||||||
|
|
||||||
``` json
|
|
||||||
{
|
|
||||||
"type": "memcached",
|
|
||||||
"host": "127.0.0.1",
|
|
||||||
"port": 11211
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also set an `expire` option to the number of seconds to expire keys in.
|
|
||||||
This behaves just like the redis expirations, but does not push expirations
|
|
||||||
forward on GETs.
|
|
||||||
|
|
||||||
All of which are optional except `type` with very logical default values.
|
|
||||||
|
|
||||||
### RethinkDB
|
|
||||||
|
|
||||||
To use the RethinkDB storage system, you must install the `rethinkdbdash` package via npm
|
|
||||||
|
|
||||||
`npm install rethinkdbdash`
|
|
||||||
|
|
||||||
Once you've done that, your config section should look like this:
|
|
||||||
|
|
||||||
``` json
|
|
||||||
{
|
|
||||||
"type": "rethinkdb",
|
|
||||||
"host": "127.0.0.1",
|
|
||||||
"port": 28015,
|
|
||||||
"db": "haste"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
In order for this to work, the database must be pre-created before the script is ran.
|
|
||||||
Also, you must create an `uploads` table, which will store all the data for uploads.
|
|
||||||
|
|
||||||
You can optionally add the `user` and `password` properties to use a user system.
|
|
||||||
|
|
||||||
### Amazon S3
|
|
||||||
|
|
||||||
To use [Amazon S3](https://aws.amazon.com/s3/) as a storage system, you must
|
|
||||||
install the `aws-sdk` package via npm:
|
|
||||||
|
|
||||||
`npm install aws-sdk`
|
|
||||||
|
|
||||||
Once you've done that, your config section should look like this:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "amazon-s3",
|
|
||||||
"bucket": "your-bucket-name",
|
|
||||||
"region": "us-east-1"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Authentication is handled automatically by the client. Check
|
|
||||||
[Amazon's documentation](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-node.html)
|
|
||||||
for more information. You will need to grant your role these permissions to
|
|
||||||
your bucket:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"Version": "2012-10-17",
|
|
||||||
"Statement": [
|
|
||||||
{
|
|
||||||
"Action": [
|
|
||||||
"s3:GetObject",
|
|
||||||
"s3:PutObject"
|
|
||||||
],
|
|
||||||
"Effect": "Allow",
|
|
||||||
"Resource": "arn:aws:s3:::your-bucket-name-goes-here/*"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Author
|
|
||||||
|
|
||||||
John Crepezzi <john.crepezzi@gmail.com>
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
(The MIT License)
|
|
||||||
|
|
||||||
Copyright © 2011-2012 John Crepezzi
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the ‘Software’), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
||||||
of the Software, and to permit persons to whom the Software is furnished to do
|
|
||||||
so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE
|
|
||||||
|
|
||||||
### Other components:
|
|
||||||
|
|
||||||
* jQuery: MIT/GPL license
|
|
||||||
* highlight.js: Copyright © 2006, Ivan Sagalaev
|
|
||||||
* highlightjs-coffeescript: WTFPL - Copyright © 2011, Dmytrii Nagirniak
|
|
|
@ -1,61 +0,0 @@
|
||||||
# Haste
|
|
||||||
|
|
||||||
Sharing code is a good thing, and it should be _really_ easy to do it.
|
|
||||||
A lot of times, I want to show you something I'm seeing - and that's where we
|
|
||||||
use pastebins.
|
|
||||||
|
|
||||||
Haste is the prettiest, easiest to use pastebin ever made.
|
|
||||||
|
|
||||||
## Basic Usage
|
|
||||||
|
|
||||||
Type what you want me to see, click "Save", and then copy the URL. Send that
|
|
||||||
URL to someone and they'll see what you see.
|
|
||||||
|
|
||||||
To make a new entry, click "New" (or type 'control + n')
|
|
||||||
|
|
||||||
## From the Console
|
|
||||||
|
|
||||||
Most of the time I want to show you some text, it's coming from my current
|
|
||||||
console session. We should make it really easy to take code from the console
|
|
||||||
and send it to people.
|
|
||||||
|
|
||||||
`cat something | haste` # https://hastebin.com/1238193
|
|
||||||
|
|
||||||
You can even take this a step further, and cut out the last step of copying the
|
|
||||||
URL with:
|
|
||||||
|
|
||||||
* osx: `cat something | haste | pbcopy`
|
|
||||||
* linux: `cat something | haste | xsel`
|
|
||||||
* windows: check out [WinHaste](https://github.com/ajryan/WinHaste)
|
|
||||||
|
|
||||||
After running that, the STDOUT output of `cat something` will show up at a URL
|
|
||||||
which has been conveniently copied to your clipboard.
|
|
||||||
|
|
||||||
That's all there is to that, and you can install it with `gem install haste`
|
|
||||||
right now.
|
|
||||||
* osx: you will need to have an up to date version of Xcode
|
|
||||||
* linux: you will need to have rubygems and ruby-devel installed
|
|
||||||
|
|
||||||
## Duration
|
|
||||||
|
|
||||||
Pastes will stay for 30 days from their last view. They may be removed earlier
|
|
||||||
and without notice.
|
|
||||||
|
|
||||||
## Privacy
|
|
||||||
|
|
||||||
While the contents of hastebin.com are not directly crawled by any search robot
|
|
||||||
that obeys "robots.txt", there should be no great expectation of privacy. Post
|
|
||||||
things at your own risk. Not responsible for any loss of data or removed
|
|
||||||
pastes.
|
|
||||||
|
|
||||||
## Open Source
|
|
||||||
|
|
||||||
Haste can easily be installed behind your network, and it's all open source!
|
|
||||||
|
|
||||||
* [haste-client](https://github.com/seejohnrun/haste-client)
|
|
||||||
* [haste-server](https://github.com/seejohnrun/haste-server)
|
|
||||||
|
|
||||||
## Author
|
|
||||||
|
|
||||||
Code by John Crepezzi <john.crepezzi@gmail.com>
|
|
||||||
Key Design by Brian Dawson <bridawson@gmail.com>
|
|
|
@ -1,46 +0,0 @@
|
||||||
{
|
|
||||||
|
|
||||||
"host": "0.0.0.0",
|
|
||||||
"port": 7777,
|
|
||||||
|
|
||||||
"keyLength": 10,
|
|
||||||
|
|
||||||
"maxLength": 400000,
|
|
||||||
|
|
||||||
"staticMaxAge": 86400,
|
|
||||||
|
|
||||||
"recompressStaticAssets": true,
|
|
||||||
|
|
||||||
"logging": [
|
|
||||||
{
|
|
||||||
"level": "verbose",
|
|
||||||
"type": "Console",
|
|
||||||
"colorize": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
"keyGenerator": {
|
|
||||||
"type": "phonetic"
|
|
||||||
},
|
|
||||||
|
|
||||||
"rateLimits": {
|
|
||||||
"categories": {
|
|
||||||
"normal": {
|
|
||||||
"totalRequests": 500,
|
|
||||||
"every": 60000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"storage": {
|
|
||||||
"type": "memcached",
|
|
||||||
"host": "127.0.0.1",
|
|
||||||
"port": 11211,
|
|
||||||
"expire": 2592000
|
|
||||||
},
|
|
||||||
|
|
||||||
"documents": {
|
|
||||||
"about": "./about.md"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,133 +0,0 @@
|
||||||
var winston = require('winston');
|
|
||||||
var Busboy = require('busboy');
|
|
||||||
|
|
||||||
// For handling serving stored documents
|
|
||||||
|
|
||||||
var DocumentHandler = function(options) {
|
|
||||||
if (!options) {
|
|
||||||
options = {};
|
|
||||||
}
|
|
||||||
this.keyLength = options.keyLength || DocumentHandler.defaultKeyLength;
|
|
||||||
this.maxLength = options.maxLength; // none by default
|
|
||||||
this.store = options.store;
|
|
||||||
this.keyGenerator = options.keyGenerator;
|
|
||||||
};
|
|
||||||
|
|
||||||
DocumentHandler.defaultKeyLength = 10;
|
|
||||||
|
|
||||||
// Handle retrieving a document
|
|
||||||
DocumentHandler.prototype.handleGet = function(key, response, skipExpire) {
|
|
||||||
this.store.get(key, function(ret) {
|
|
||||||
if (ret) {
|
|
||||||
winston.verbose('retrieved document', { key: key });
|
|
||||||
response.writeHead(200, { 'content-type': 'application/json' });
|
|
||||||
response.end(JSON.stringify({ data: ret, key: key }));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
winston.warn('document not found', { key: key });
|
|
||||||
response.writeHead(404, { 'content-type': 'application/json' });
|
|
||||||
response.end(JSON.stringify({ message: 'Document not found.' }));
|
|
||||||
}
|
|
||||||
}, skipExpire);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle retrieving the raw version of a document
|
|
||||||
DocumentHandler.prototype.handleRawGet = function(key, response, skipExpire) {
|
|
||||||
this.store.get(key, function(ret) {
|
|
||||||
if (ret) {
|
|
||||||
winston.verbose('retrieved raw document', { key: key });
|
|
||||||
response.writeHead(200, { 'content-type': 'text/plain; charset=UTF-8' });
|
|
||||||
response.end(ret);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
winston.warn('raw document not found', { key: key });
|
|
||||||
response.writeHead(404, { 'content-type': 'application/json' });
|
|
||||||
response.end(JSON.stringify({ message: 'Document not found.' }));
|
|
||||||
}
|
|
||||||
}, skipExpire);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle adding a new Document
|
|
||||||
DocumentHandler.prototype.handlePost = function (request, response) {
|
|
||||||
var _this = this;
|
|
||||||
var buffer = '';
|
|
||||||
var cancelled = false;
|
|
||||||
|
|
||||||
// What to do when done
|
|
||||||
var onSuccess = function () {
|
|
||||||
// Check length
|
|
||||||
if (_this.maxLength && buffer.length > _this.maxLength) {
|
|
||||||
cancelled = true;
|
|
||||||
winston.warn('document >maxLength', { maxLength: _this.maxLength });
|
|
||||||
response.writeHead(400, { 'content-type': 'application/json' });
|
|
||||||
response.end(
|
|
||||||
JSON.stringify({ message: 'Document exceeds maximum length.' })
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// And then save if we should
|
|
||||||
_this.chooseKey(function (key) {
|
|
||||||
_this.store.set(key, buffer, function (res) {
|
|
||||||
if (res) {
|
|
||||||
winston.verbose('added document', { key: key });
|
|
||||||
response.writeHead(200, { 'content-type': 'application/json' });
|
|
||||||
response.end(JSON.stringify({ key: key }));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
winston.verbose('error adding document');
|
|
||||||
response.writeHead(500, { 'content-type': 'application/json' });
|
|
||||||
response.end(JSON.stringify({ message: 'Error adding document.' }));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// If we should, parse a form to grab the data
|
|
||||||
var ct = request.headers['content-type'];
|
|
||||||
if (ct && ct.split(';')[0] === 'multipart/form-data') {
|
|
||||||
var busboy = new Busboy({ headers: request.headers });
|
|
||||||
busboy.on('field', function (fieldname, val) {
|
|
||||||
if (fieldname === 'data') {
|
|
||||||
buffer = val;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
busboy.on('finish', function () {
|
|
||||||
onSuccess();
|
|
||||||
});
|
|
||||||
request.pipe(busboy);
|
|
||||||
// Otherwise, use our own and just grab flat data from POST body
|
|
||||||
} else {
|
|
||||||
request.on('data', function (data) {
|
|
||||||
buffer += data.toString();
|
|
||||||
});
|
|
||||||
request.on('end', function () {
|
|
||||||
if (cancelled) { return; }
|
|
||||||
onSuccess();
|
|
||||||
});
|
|
||||||
request.on('error', function (error) {
|
|
||||||
winston.error('connection error: ' + error.message);
|
|
||||||
response.writeHead(500, { 'content-type': 'application/json' });
|
|
||||||
response.end(JSON.stringify({ message: 'Connection error.' }));
|
|
||||||
cancelled = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Keep choosing keys until one isn't taken
|
|
||||||
DocumentHandler.prototype.chooseKey = function(callback) {
|
|
||||||
var key = this.acceptableKey();
|
|
||||||
var _this = this;
|
|
||||||
this.store.get(key, function(ret) {
|
|
||||||
if (ret) {
|
|
||||||
_this.chooseKey(callback);
|
|
||||||
} else {
|
|
||||||
callback(key);
|
|
||||||
}
|
|
||||||
}, true); // Don't bump expirations when key searching
|
|
||||||
};
|
|
||||||
|
|
||||||
DocumentHandler.prototype.acceptableKey = function() {
|
|
||||||
return this.keyGenerator.createKey(this.keyLength);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = DocumentHandler;
|
|
|
@ -1,56 +0,0 @@
|
||||||
/*global require,module,process*/
|
|
||||||
|
|
||||||
var AWS = require('aws-sdk');
|
|
||||||
var winston = require('winston');
|
|
||||||
|
|
||||||
var AmazonS3DocumentStore = function(options) {
|
|
||||||
this.expire = options.expire;
|
|
||||||
this.bucket = options.bucket;
|
|
||||||
this.client = new AWS.S3({region: options.region});
|
|
||||||
};
|
|
||||||
|
|
||||||
AmazonS3DocumentStore.prototype.get = function(key, callback, skipExpire) {
|
|
||||||
var _this = this;
|
|
||||||
|
|
||||||
var req = {
|
|
||||||
Bucket: _this.bucket,
|
|
||||||
Key: key
|
|
||||||
};
|
|
||||||
|
|
||||||
_this.client.getObject(req, function(err, data) {
|
|
||||||
if(err) {
|
|
||||||
callback(false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback(data.Body.toString('utf-8'));
|
|
||||||
if (_this.expire && !skipExpire) {
|
|
||||||
winston.warn('amazon s3 store cannot set expirations on keys');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
AmazonS3DocumentStore.prototype.set = function(key, data, callback, skipExpire) {
|
|
||||||
var _this = this;
|
|
||||||
|
|
||||||
var req = {
|
|
||||||
Bucket: _this.bucket,
|
|
||||||
Key: key,
|
|
||||||
Body: data,
|
|
||||||
ContentType: 'text/plain'
|
|
||||||
};
|
|
||||||
|
|
||||||
_this.client.putObject(req, function(err, data) {
|
|
||||||
if (err) {
|
|
||||||
callback(false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback(true);
|
|
||||||
if (_this.expire && !skipExpire) {
|
|
||||||
winston.warn('amazon s3 store cannot set expirations on keys');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = AmazonS3DocumentStore;
|
|
|
@ -1,63 +0,0 @@
|
||||||
var fs = require('fs');
|
|
||||||
var crypto = require('crypto');
|
|
||||||
|
|
||||||
var winston = require('winston');
|
|
||||||
|
|
||||||
// For storing in files
|
|
||||||
// options[type] = file
|
|
||||||
// options[path] - Where to store
|
|
||||||
|
|
||||||
var FileDocumentStore = function(options) {
|
|
||||||
this.basePath = options.path || './data';
|
|
||||||
this.expire = options.expire;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Generate md5 of a string
|
|
||||||
FileDocumentStore.md5 = function(str) {
|
|
||||||
var md5sum = crypto.createHash('md5');
|
|
||||||
md5sum.update(str);
|
|
||||||
return md5sum.digest('hex');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Save data in a file, key as md5 - since we don't know what we could
|
|
||||||
// be passed here
|
|
||||||
FileDocumentStore.prototype.set = function(key, data, callback, skipExpire) {
|
|
||||||
try {
|
|
||||||
var _this = this;
|
|
||||||
fs.mkdir(this.basePath, '700', function() {
|
|
||||||
var fn = _this.basePath + '/' + FileDocumentStore.md5(key);
|
|
||||||
fs.writeFile(fn, data, 'utf8', function(err) {
|
|
||||||
if (err) {
|
|
||||||
callback(false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback(true);
|
|
||||||
if (_this.expire && !skipExpire) {
|
|
||||||
winston.warn('file store cannot set expirations on keys');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} catch(err) {
|
|
||||||
callback(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get data from a file from key
|
|
||||||
FileDocumentStore.prototype.get = function(key, callback, skipExpire) {
|
|
||||||
var _this = this;
|
|
||||||
var fn = this.basePath + '/' + FileDocumentStore.md5(key);
|
|
||||||
fs.readFile(fn, 'utf8', function(err, data) {
|
|
||||||
if (err) {
|
|
||||||
callback(false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback(data);
|
|
||||||
if (_this.expire && !skipExpire) {
|
|
||||||
winston.warn('file store cannot set expirations on keys');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = FileDocumentStore;
|
|
|
@ -1,52 +0,0 @@
|
||||||
const memcached = require('memcached');
|
|
||||||
const winston = require('winston');
|
|
||||||
|
|
||||||
class MemcachedDocumentStore {
|
|
||||||
|
|
||||||
// Create a new store with options
|
|
||||||
constructor(options) {
|
|
||||||
this.expire = options.expire;
|
|
||||||
|
|
||||||
const host = options.host || '127.0.0.1';
|
|
||||||
const port = options.port || 11211;
|
|
||||||
const url = `${host}:${port}`;
|
|
||||||
this.connect(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a connection
|
|
||||||
connect(url) {
|
|
||||||
this.client = new memcached(url);
|
|
||||||
|
|
||||||
winston.info(`connecting to memcached on ${url}`);
|
|
||||||
|
|
||||||
this.client.on('failure', function(error) {
|
|
||||||
winston.info('error connecting to memcached', {error});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save file in a key
|
|
||||||
set(key, data, callback, skipExpire) {
|
|
||||||
this.client.set(key, data, skipExpire ? 0 : this.expire, (error) => {
|
|
||||||
callback(!error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a file from a key
|
|
||||||
get(key, callback, skipExpire) {
|
|
||||||
this.client.get(key, (error, data) => {
|
|
||||||
callback(error ? false : data);
|
|
||||||
|
|
||||||
// Update the key so that the expiration is pushed forward
|
|
||||||
if (!skipExpire) {
|
|
||||||
this.set(key, data, (updateSucceeded) => {
|
|
||||||
if (!updateSucceeded) {
|
|
||||||
winston.error('failed to update expiration on GET', {key});
|
|
||||||
}
|
|
||||||
}, skipExpire);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = MemcachedDocumentStore;
|
|
|
@ -1,79 +0,0 @@
|
||||||
/*global require,module,process*/
|
|
||||||
|
|
||||||
var postgres = require('pg');
|
|
||||||
var winston = require('winston');
|
|
||||||
|
|
||||||
// create table entries (id serial primary key, key varchar(255) not null, value text not null, expiration int, unique(key));
|
|
||||||
|
|
||||||
// A postgres document store
|
|
||||||
var PostgresDocumentStore = function (options) {
|
|
||||||
this.expireJS = options.expire;
|
|
||||||
this.connectionUrl = process.env.DATABASE_URL || options.connectionUrl;
|
|
||||||
};
|
|
||||||
|
|
||||||
PostgresDocumentStore.prototype = {
|
|
||||||
|
|
||||||
// Set a given key
|
|
||||||
set: function (key, data, callback, skipExpire) {
|
|
||||||
var now = Math.floor(new Date().getTime() / 1000);
|
|
||||||
var that = this;
|
|
||||||
this.safeConnect(function (err, client, done) {
|
|
||||||
if (err) { return callback(false); }
|
|
||||||
client.query('INSERT INTO entries (key, value, expiration) VALUES ($1, $2, $3)', [
|
|
||||||
key,
|
|
||||||
data,
|
|
||||||
that.expireJS && !skipExpire ? that.expireJS + now : null
|
|
||||||
], function (err) {
|
|
||||||
if (err) {
|
|
||||||
winston.error('error persisting value to postgres', { error: err });
|
|
||||||
return callback(false);
|
|
||||||
}
|
|
||||||
callback(true);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// Get a given key's data
|
|
||||||
get: function (key, callback, skipExpire) {
|
|
||||||
var now = Math.floor(new Date().getTime() / 1000);
|
|
||||||
var that = this;
|
|
||||||
this.safeConnect(function (err, client, done) {
|
|
||||||
if (err) { return callback(false); }
|
|
||||||
client.query('SELECT id,value,expiration from entries where KEY = $1 and (expiration IS NULL or expiration > $2)', [key, now], function (err, result) {
|
|
||||||
if (err) {
|
|
||||||
winston.error('error retrieving value from postgres', { error: err });
|
|
||||||
return callback(false);
|
|
||||||
}
|
|
||||||
callback(result.rows.length ? result.rows[0].value : false);
|
|
||||||
if (result.rows.length && that.expireJS && !skipExpire) {
|
|
||||||
client.query('UPDATE entries SET expiration = $1 WHERE ID = $2', [
|
|
||||||
that.expireJS + now,
|
|
||||||
result.rows[0].id
|
|
||||||
], function (err) {
|
|
||||||
if (!err) {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// A connection wrapper
|
|
||||||
safeConnect: function (callback) {
|
|
||||||
postgres.connect(this.connectionUrl, function (err, client, done) {
|
|
||||||
if (err) {
|
|
||||||
winston.error('error connecting to postgres', { error: err });
|
|
||||||
callback(err);
|
|
||||||
} else {
|
|
||||||
callback(undefined, client, done);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = PostgresDocumentStore;
|
|
|
@ -1,89 +0,0 @@
|
||||||
var redis = require('redis');
|
|
||||||
var winston = require('winston');
|
|
||||||
|
|
||||||
// For storing in redis
|
|
||||||
// options[type] = redis
|
|
||||||
// options[host] - The host to connect to (default localhost)
|
|
||||||
// options[port] - The port to connect to (default 5379)
|
|
||||||
// options[db] - The db to use (default 0)
|
|
||||||
// options[expire] - The time to live for each key set (default never)
|
|
||||||
|
|
||||||
var RedisDocumentStore = function(options, client) {
|
|
||||||
this.expire = options.expire;
|
|
||||||
if (client) {
|
|
||||||
winston.info('using predefined redis client');
|
|
||||||
RedisDocumentStore.client = client;
|
|
||||||
} else if (!RedisDocumentStore.client) {
|
|
||||||
winston.info('configuring redis');
|
|
||||||
RedisDocumentStore.connect(options);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create a connection according to config
|
|
||||||
RedisDocumentStore.connect = function(options) {
|
|
||||||
var host = options.host || '127.0.0.1';
|
|
||||||
var port = options.port || 6379;
|
|
||||||
var index = options.db || 0;
|
|
||||||
RedisDocumentStore.client = redis.createClient(port, host);
|
|
||||||
// authenticate if password is provided
|
|
||||||
if (options.password) {
|
|
||||||
RedisDocumentStore.client.auth(options.password);
|
|
||||||
}
|
|
||||||
|
|
||||||
RedisDocumentStore.client.on('error', function(err) {
|
|
||||||
winston.error('redis disconnected', err);
|
|
||||||
});
|
|
||||||
|
|
||||||
RedisDocumentStore.client.select(index, function(err) {
|
|
||||||
if (err) {
|
|
||||||
winston.error(
|
|
||||||
'error connecting to redis index ' + index,
|
|
||||||
{ error: err }
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
winston.info('connected to redis on ' + host + ':' + port + '/' + index);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Save file in a key
|
|
||||||
RedisDocumentStore.prototype.set = function(key, data, callback, skipExpire) {
|
|
||||||
var _this = this;
|
|
||||||
RedisDocumentStore.client.set(key, data, function(err) {
|
|
||||||
if (err) {
|
|
||||||
callback(false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!skipExpire) {
|
|
||||||
_this.setExpiration(key);
|
|
||||||
}
|
|
||||||
callback(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Expire a key in expire time if set
|
|
||||||
RedisDocumentStore.prototype.setExpiration = function(key) {
|
|
||||||
if (this.expire) {
|
|
||||||
RedisDocumentStore.client.expire(key, this.expire, function(err) {
|
|
||||||
if (err) {
|
|
||||||
winston.error('failed to set expiry on key: ' + key);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get a file from a key
|
|
||||||
RedisDocumentStore.prototype.get = function(key, callback, skipExpire) {
|
|
||||||
var _this = this;
|
|
||||||
RedisDocumentStore.client.get(key, function(err, reply) {
|
|
||||||
if (!err && !skipExpire) {
|
|
||||||
_this.setExpiration(key);
|
|
||||||
}
|
|
||||||
callback(err ? false : reply);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = RedisDocumentStore;
|
|
|
@ -1,46 +0,0 @@
|
||||||
const crypto = require('crypto');
|
|
||||||
const rethink = require('rethinkdbdash');
|
|
||||||
const winston = require('winston');
|
|
||||||
|
|
||||||
const md5 = (str) => {
|
|
||||||
const md5sum = crypto.createHash('md5');
|
|
||||||
md5sum.update(str);
|
|
||||||
return md5sum.digest('hex');
|
|
||||||
};
|
|
||||||
|
|
||||||
class RethinkDBStore {
|
|
||||||
constructor(options) {
|
|
||||||
this.client = rethink({
|
|
||||||
silent: true,
|
|
||||||
host: options.host || '127.0.0.1',
|
|
||||||
port: options.port || 28015,
|
|
||||||
db: options.db || 'haste',
|
|
||||||
user: options.user || 'admin',
|
|
||||||
password: options.password || ''
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
set(key, data, callback) {
|
|
||||||
this.client.table('uploads').insert({ id: md5(key), data: data }).run((error) => {
|
|
||||||
if (error) {
|
|
||||||
callback(false);
|
|
||||||
winston.error('failed to insert to table', error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
callback(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get(key, callback) {
|
|
||||||
this.client.table('uploads').get(md5(key)).run((error, result) => {
|
|
||||||
if (error || !result) {
|
|
||||||
callback(false);
|
|
||||||
if (error) winston.error('failed to insert to table', error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
callback(result.data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = RethinkDBStore;
|
|
|
@ -1,32 +0,0 @@
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
module.exports = class DictionaryGenerator {
|
|
||||||
|
|
||||||
constructor(options, readyCallback) {
|
|
||||||
// Check options format
|
|
||||||
if (!options) throw Error('No options passed to generator');
|
|
||||||
if (!options.path) throw Error('No dictionary path specified in options');
|
|
||||||
|
|
||||||
// Load dictionary
|
|
||||||
fs.readFile(options.path, 'utf8', (err, data) => {
|
|
||||||
if (err) throw err;
|
|
||||||
|
|
||||||
this.dictionary = data.split(/[\n\r]+/);
|
|
||||||
|
|
||||||
if (readyCallback) readyCallback();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generates a dictionary-based key, of keyLength words
|
|
||||||
createKey(keyLength) {
|
|
||||||
let text = '';
|
|
||||||
|
|
||||||
for (let i = 0; i < keyLength; i++) {
|
|
||||||
const index = Math.floor(Math.random() * this.dictionary.length);
|
|
||||||
text += this.dictionary[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
|
@ -1,27 +0,0 @@
|
||||||
// Draws inspiration from pwgen and http://tools.arantius.com/password
|
|
||||||
|
|
||||||
const randOf = (collection) => {
|
|
||||||
return () => {
|
|
||||||
return collection[Math.floor(Math.random() * collection.length)];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper methods to get an random vowel or consonant
|
|
||||||
const randVowel = randOf('aeiou');
|
|
||||||
const randConsonant = randOf('bcdfghjklmnpqrstvwxyz');
|
|
||||||
|
|
||||||
module.exports = class PhoneticKeyGenerator {
|
|
||||||
|
|
||||||
// Generate a phonetic key of alternating consonant & vowel
|
|
||||||
createKey(keyLength) {
|
|
||||||
let text = '';
|
|
||||||
const start = Math.round(Math.random());
|
|
||||||
|
|
||||||
for (let i = 0; i < keyLength; i++) {
|
|
||||||
text += (i % 2 == start) ? randConsonant() : randVowel();
|
|
||||||
}
|
|
||||||
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
|
@ -1,20 +0,0 @@
|
||||||
module.exports = class RandomKeyGenerator {
|
|
||||||
|
|
||||||
// Initialize a new generator with the given keySpace
|
|
||||||
constructor(options = {}) {
|
|
||||||
this.keyspace = options.keyspace || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a key of the given length
|
|
||||||
createKey(keyLength) {
|
|
||||||
var text = '';
|
|
||||||
|
|
||||||
for (var i = 0; i < keyLength; i++) {
|
|
||||||
const index = Math.floor(Math.random() * this.keyspace.length);
|
|
||||||
text += this.keyspace.charAt(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
548
sources/haste-server-master/package-lock.json
generated
548
sources/haste-server-master/package-lock.json
generated
|
@ -1,548 +0,0 @@
|
||||||
{
|
|
||||||
"name": "haste",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"lockfileVersion": 1,
|
|
||||||
"requires": true,
|
|
||||||
"dependencies": {
|
|
||||||
"async": {
|
|
||||||
"version": "0.1.22",
|
|
||||||
"resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz",
|
|
||||||
"integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE="
|
|
||||||
},
|
|
||||||
"async-cache": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/async-cache/-/async-cache-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-yH9tgMcrOU7g+QYe3rJNjEtiKto=",
|
|
||||||
"requires": {
|
|
||||||
"lru-cache": "2.3.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"balanced-match": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"bl": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/bl/-/bl-1.0.3.tgz",
|
|
||||||
"integrity": "sha1-/FQhoo/UImA2w7OJGmaiW8ZNIm4=",
|
|
||||||
"requires": {
|
|
||||||
"readable-stream": "2.0.6"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"isarray": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
|
||||||
},
|
|
||||||
"readable-stream": {
|
|
||||||
"version": "2.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
|
|
||||||
"integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
|
|
||||||
"requires": {
|
|
||||||
"core-util-is": "1.0.2",
|
|
||||||
"inherits": "2.0.3",
|
|
||||||
"isarray": "1.0.0",
|
|
||||||
"process-nextick-args": "1.0.7",
|
|
||||||
"string_decoder": "0.10.31",
|
|
||||||
"util-deprecate": "1.0.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"brace-expansion": {
|
|
||||||
"version": "1.1.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
|
|
||||||
"integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"balanced-match": "1.0.0",
|
|
||||||
"concat-map": "0.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"browser-stdout": {
|
|
||||||
"version": "1.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz",
|
|
||||||
"integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"buffer-writer": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-bCnDst6gyeRVofJhoZmkigT4iwg="
|
|
||||||
},
|
|
||||||
"busboy": {
|
|
||||||
"version": "0.2.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.4.tgz",
|
|
||||||
"integrity": "sha1-GXfpbh7ohGSWUevfVIypAHWLp/M=",
|
|
||||||
"requires": {
|
|
||||||
"dicer": "0.2.3",
|
|
||||||
"readable-stream": "1.1.14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"colors": {
|
|
||||||
"version": "0.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz",
|
|
||||||
"integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w="
|
|
||||||
},
|
|
||||||
"commander": {
|
|
||||||
"version": "2.9.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
|
|
||||||
"integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"graceful-readlink": "1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"concat-map": {
|
|
||||||
"version": "0.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
|
||||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"connect": {
|
|
||||||
"version": "3.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/connect/-/connect-3.4.1.tgz",
|
|
||||||
"integrity": "sha1-ohNh0/QJnvdhzabcSpc7seuwo00=",
|
|
||||||
"requires": {
|
|
||||||
"debug": "2.2.0",
|
|
||||||
"finalhandler": "0.4.1",
|
|
||||||
"parseurl": "1.3.1",
|
|
||||||
"utils-merge": "1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"connect-ratelimit": {
|
|
||||||
"version": "0.0.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/connect-ratelimit/-/connect-ratelimit-0.0.7.tgz",
|
|
||||||
"integrity": "sha1-5uCclQZJ6ElJnKsYcKQVoH9zFWg="
|
|
||||||
},
|
|
||||||
"connect-route": {
|
|
||||||
"version": "0.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/connect-route/-/connect-route-0.1.5.tgz",
|
|
||||||
"integrity": "sha1-48IYMZ0uiKiprgsOD+Cacpw5dEo="
|
|
||||||
},
|
|
||||||
"core-util-is": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
|
||||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
|
||||||
},
|
|
||||||
"cycle": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
|
|
||||||
"integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI="
|
|
||||||
},
|
|
||||||
"debug": {
|
|
||||||
"version": "2.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
|
|
||||||
"integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
|
|
||||||
"requires": {
|
|
||||||
"ms": "0.7.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dicer": {
|
|
||||||
"version": "0.2.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.3.tgz",
|
|
||||||
"integrity": "sha1-8AKBGJpVwjUe+ASQpP6fssWcSTk=",
|
|
||||||
"requires": {
|
|
||||||
"readable-stream": "1.1.14",
|
|
||||||
"streamsearch": "0.1.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"diff": {
|
|
||||||
"version": "3.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz",
|
|
||||||
"integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"ee-first": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
|
||||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
|
||||||
},
|
|
||||||
"escape-html": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
|
||||||
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
|
|
||||||
},
|
|
||||||
"escape-string-regexp": {
|
|
||||||
"version": "1.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
|
||||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"eyes": {
|
|
||||||
"version": "0.1.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
|
|
||||||
"integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A="
|
|
||||||
},
|
|
||||||
"fd": {
|
|
||||||
"version": "0.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/fd/-/fd-0.0.2.tgz",
|
|
||||||
"integrity": "sha1-4O2yvXqIzIbdnxY5HLqDJBj9h+4="
|
|
||||||
},
|
|
||||||
"finalhandler": {
|
|
||||||
"version": "0.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.1.tgz",
|
|
||||||
"integrity": "sha1-haF8bFmpRxfSYtYSMNSw6+PUoU0=",
|
|
||||||
"requires": {
|
|
||||||
"debug": "2.2.0",
|
|
||||||
"escape-html": "1.0.3",
|
|
||||||
"on-finished": "2.3.0",
|
|
||||||
"unpipe": "1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fs.realpath": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"generic-pool": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz",
|
|
||||||
"integrity": "sha1-rwTcLDJc/Ll1Aj+lK/zpYXp0Nf0="
|
|
||||||
},
|
|
||||||
"glob": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz",
|
|
||||||
"integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"fs.realpath": "1.0.0",
|
|
||||||
"inflight": "1.0.6",
|
|
||||||
"inherits": "2.0.3",
|
|
||||||
"minimatch": "3.0.4",
|
|
||||||
"once": "1.4.0",
|
|
||||||
"path-is-absolute": "1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"graceful-fs": {
|
|
||||||
"version": "4.1.11",
|
|
||||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
|
||||||
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"graceful-readlink": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"growl": {
|
|
||||||
"version": "1.9.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz",
|
|
||||||
"integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"has-flag": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"he": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
|
|
||||||
"integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"inflight": {
|
|
||||||
"version": "1.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
|
||||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"once": "1.4.0",
|
|
||||||
"wrappy": "1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"inherits": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
|
||||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
|
||||||
},
|
|
||||||
"isarray": {
|
|
||||||
"version": "0.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
|
||||||
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
|
|
||||||
},
|
|
||||||
"lru-cache": {
|
|
||||||
"version": "2.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.3.1.tgz",
|
|
||||||
"integrity": "sha1-s632s9hW6VTiw5DmzvIggSRaU9Y="
|
|
||||||
},
|
|
||||||
"mime": {
|
|
||||||
"version": "1.3.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.3.6.tgz",
|
|
||||||
"integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA="
|
|
||||||
},
|
|
||||||
"minimatch": {
|
|
||||||
"version": "3.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
|
||||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"brace-expansion": "1.1.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"minimist": {
|
|
||||||
"version": "0.0.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
|
||||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"mkdirp": {
|
|
||||||
"version": "0.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
|
||||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"minimist": "0.0.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-evDmhkoA+cBNiQQQdSKZa2b9+W2mpLoj50367lhy+Klnx9OV8XlCIhigUnn1gaTFLQCa0kdNhEGDr0hCXOQFDw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"browser-stdout": "1.3.0",
|
|
||||||
"commander": "2.9.0",
|
|
||||||
"debug": "2.2.0",
|
|
||||||
"diff": "3.2.0",
|
|
||||||
"escape-string-regexp": "1.0.5",
|
|
||||||
"glob": "7.1.1",
|
|
||||||
"growl": "1.9.2",
|
|
||||||
"he": "1.1.1",
|
|
||||||
"mkdirp": "0.5.1",
|
|
||||||
"supports-color": "3.1.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ms": {
|
|
||||||
"version": "0.7.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
|
|
||||||
"integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg="
|
|
||||||
},
|
|
||||||
"negotiator": {
|
|
||||||
"version": "0.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
|
|
||||||
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
|
|
||||||
},
|
|
||||||
"on-finished": {
|
|
||||||
"version": "2.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
|
||||||
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
|
|
||||||
"requires": {
|
|
||||||
"ee-first": "1.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"once": {
|
|
||||||
"version": "1.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
|
||||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"wrappy": "1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"packet-reader": {
|
|
||||||
"version": "0.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.2.0.tgz",
|
|
||||||
"integrity": "sha1-gZ300BC4LV6lZx+KGjrPA5vNdwA="
|
|
||||||
},
|
|
||||||
"parseurl": {
|
|
||||||
"version": "1.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz",
|
|
||||||
"integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY="
|
|
||||||
},
|
|
||||||
"path-is-absolute": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"pg": {
|
|
||||||
"version": "4.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/pg/-/pg-4.1.1.tgz",
|
|
||||||
"integrity": "sha1-mEgKz8089qP5Yhyl1FiUFVgqVzI=",
|
|
||||||
"requires": {
|
|
||||||
"buffer-writer": "1.0.0",
|
|
||||||
"generic-pool": "2.1.1",
|
|
||||||
"packet-reader": "0.2.0",
|
|
||||||
"pg-connection-string": "0.1.3",
|
|
||||||
"pg-types": "1.6.0",
|
|
||||||
"pgpass": "0.0.3",
|
|
||||||
"semver": "4.3.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pg-connection-string": {
|
|
||||||
"version": "0.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz",
|
|
||||||
"integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc="
|
|
||||||
},
|
|
||||||
"pg-types": {
|
|
||||||
"version": "1.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.6.0.tgz",
|
|
||||||
"integrity": "sha1-OHKg8ZkUMCVJf07ipl/a8A1+qLM="
|
|
||||||
},
|
|
||||||
"pgpass": {
|
|
||||||
"version": "0.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-0.0.3.tgz",
|
|
||||||
"integrity": "sha1-EuZ+NDsxicLzEgbrycwL7//PkUA=",
|
|
||||||
"requires": {
|
|
||||||
"split": "0.3.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pkginfo": {
|
|
||||||
"version": "0.2.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.2.3.tgz",
|
|
||||||
"integrity": "sha1-cjnEKl72wwuPMoQ52bn/cQQkkPg="
|
|
||||||
},
|
|
||||||
"process-nextick-args": {
|
|
||||||
"version": "1.0.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
|
|
||||||
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
|
|
||||||
},
|
|
||||||
"readable-stream": {
|
|
||||||
"version": "1.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
|
||||||
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
|
|
||||||
"requires": {
|
|
||||||
"core-util-is": "1.0.2",
|
|
||||||
"inherits": "2.0.3",
|
|
||||||
"isarray": "0.0.1",
|
|
||||||
"string_decoder": "0.10.31"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"redis": {
|
|
||||||
"version": "0.8.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/redis/-/redis-0.8.1.tgz",
|
|
||||||
"integrity": "sha1-FZ8hMFmaL3GeRLA/C0t2EvmS/LI="
|
|
||||||
},
|
|
||||||
"redis-url": {
|
|
||||||
"version": "0.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/redis-url/-/redis-url-0.1.0.tgz",
|
|
||||||
"integrity": "sha1-TaXlsYG2wMrW4aVcf1Co5u53ebs=",
|
|
||||||
"requires": {
|
|
||||||
"redis": "0.8.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"request": {
|
|
||||||
"version": "2.9.203",
|
|
||||||
"resolved": "https://registry.npmjs.org/request/-/request-2.9.203.tgz",
|
|
||||||
"integrity": "sha1-bBcRpUB/uUoRQhlWPkQUW8v0cjo="
|
|
||||||
},
|
|
||||||
"semver": {
|
|
||||||
"version": "4.3.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
|
|
||||||
"integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto="
|
|
||||||
},
|
|
||||||
"source-map": {
|
|
||||||
"version": "0.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
|
||||||
},
|
|
||||||
"split": {
|
|
||||||
"version": "0.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
|
|
||||||
"integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
|
|
||||||
"requires": {
|
|
||||||
"through": "2.3.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"st": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/st/-/st-1.1.0.tgz",
|
|
||||||
"integrity": "sha1-c7ltsLdkTZp4zjg0o+T37G6Hz3Y=",
|
|
||||||
"requires": {
|
|
||||||
"async-cache": "1.0.0",
|
|
||||||
"bl": "1.0.3",
|
|
||||||
"fd": "0.0.2",
|
|
||||||
"graceful-fs": "4.1.11",
|
|
||||||
"mime": "1.3.6",
|
|
||||||
"negotiator": "0.6.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"stack-trace": {
|
|
||||||
"version": "0.0.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
|
|
||||||
"integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA="
|
|
||||||
},
|
|
||||||
"streamsearch": {
|
|
||||||
"version": "0.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
|
|
||||||
"integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo="
|
|
||||||
},
|
|
||||||
"string_decoder": {
|
|
||||||
"version": "0.10.31",
|
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
|
||||||
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
|
|
||||||
},
|
|
||||||
"supports-color": {
|
|
||||||
"version": "3.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz",
|
|
||||||
"integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"through": {
|
|
||||||
"version": "2.3.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
|
||||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
|
|
||||||
},
|
|
||||||
"uglify-js": {
|
|
||||||
"version": "3.1.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.1.6.tgz",
|
|
||||||
"integrity": "sha512-/rseyxEKEVMBo8279lqpoJgD6C/i/CIi+9TJDvWmb+Xo6mqMKwjA8Io3IMHlcXQzj99feR6zrN8m3wqqvm/nYA==",
|
|
||||||
"requires": {
|
|
||||||
"commander": "2.11.0",
|
|
||||||
"source-map": "0.6.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"commander": {
|
|
||||||
"version": "2.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
|
|
||||||
"integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"unpipe": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
|
|
||||||
},
|
|
||||||
"util-deprecate": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
|
||||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
|
||||||
},
|
|
||||||
"utils-merge": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg="
|
|
||||||
},
|
|
||||||
"winston": {
|
|
||||||
"version": "0.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/winston/-/winston-0.6.2.tgz",
|
|
||||||
"integrity": "sha1-QUT+JYbNwZphK/jANVkBMskGS9I=",
|
|
||||||
"requires": {
|
|
||||||
"async": "0.1.22",
|
|
||||||
"colors": "0.6.2",
|
|
||||||
"cycle": "1.0.3",
|
|
||||||
"eyes": "0.1.8",
|
|
||||||
"pkginfo": "0.2.3",
|
|
||||||
"request": "2.9.203",
|
|
||||||
"stack-trace": "0.0.10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wrappy": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
|
||||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
{
|
|
||||||
"name": "haste",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"private": true,
|
|
||||||
"description": "Private Pastebin Server",
|
|
||||||
"keywords": [
|
|
||||||
"paste",
|
|
||||||
"pastebin"
|
|
||||||
],
|
|
||||||
"author": {
|
|
||||||
"name": "John Crepezzi",
|
|
||||||
"email": "john.crepezzi@gmail.com",
|
|
||||||
"url": "http://seejohncode.com/"
|
|
||||||
},
|
|
||||||
"main": "haste",
|
|
||||||
"dependencies": {
|
|
||||||
"connect-ratelimit": "0.0.7",
|
|
||||||
"connect-route": "0.1.5",
|
|
||||||
"connect": "3.4.1",
|
|
||||||
"st": "1.1.0",
|
|
||||||
"winston": "0.6.2",
|
|
||||||
"redis-url": "0.1.0",
|
|
||||||
"redis": "0.8.1",
|
|
||||||
"uglify-js": "3.1.6",
|
|
||||||
"busboy": "0.2.4",
|
|
||||||
"pg": "4.1.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"mocha": "^4.0.1"
|
|
||||||
},
|
|
||||||
"bundledDependencies": [],
|
|
||||||
"engines": {
|
|
||||||
"node": "8.1.4",
|
|
||||||
"npm": "5.2.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"haste-server": "./server.js"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"server.js",
|
|
||||||
"lib",
|
|
||||||
"static"
|
|
||||||
],
|
|
||||||
"directories": {
|
|
||||||
"lib": "./lib"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"start": "node server.js",
|
|
||||||
"test": "mocha --recursive"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,155 +0,0 @@
|
||||||
var http = require('http');
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
var uglify = require('uglify-js');
|
|
||||||
var winston = require('winston');
|
|
||||||
var connect = require('connect');
|
|
||||||
var route = require('connect-route');
|
|
||||||
var connect_st = require('st');
|
|
||||||
var connect_rate_limit = require('connect-ratelimit');
|
|
||||||
|
|
||||||
var DocumentHandler = require('./lib/document_handler');
|
|
||||||
|
|
||||||
// Load the configuration and set some defaults
|
|
||||||
var config = JSON.parse(fs.readFileSync('./config.js', 'utf8'));
|
|
||||||
config.port = process.env.PORT || config.port || 7777;
|
|
||||||
config.host = process.env.HOST || config.host || 'localhost';
|
|
||||||
|
|
||||||
// Set up the logger
|
|
||||||
if (config.logging) {
|
|
||||||
try {
|
|
||||||
winston.remove(winston.transports.Console);
|
|
||||||
} catch(e) {
|
|
||||||
/* was not present */
|
|
||||||
}
|
|
||||||
|
|
||||||
var detail, type;
|
|
||||||
for (var i = 0; i < config.logging.length; i++) {
|
|
||||||
detail = config.logging[i];
|
|
||||||
type = detail.type;
|
|
||||||
delete detail.type;
|
|
||||||
winston.add(winston.transports[type], detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// build the store from the config on-demand - so that we don't load it
|
|
||||||
// for statics
|
|
||||||
if (!config.storage) {
|
|
||||||
config.storage = { type: 'file' };
|
|
||||||
}
|
|
||||||
if (!config.storage.type) {
|
|
||||||
config.storage.type = 'file';
|
|
||||||
}
|
|
||||||
|
|
||||||
var Store, preferredStore;
|
|
||||||
|
|
||||||
if (process.env.REDISTOGO_URL && config.storage.type === 'redis') {
|
|
||||||
var redisClient = require('redis-url').connect(process.env.REDISTOGO_URL);
|
|
||||||
Store = require('./lib/document_stores/redis');
|
|
||||||
preferredStore = new Store(config.storage, redisClient);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Store = require('./lib/document_stores/' + config.storage.type);
|
|
||||||
preferredStore = new Store(config.storage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compress the static javascript assets
|
|
||||||
if (config.recompressStaticAssets) {
|
|
||||||
var list = fs.readdirSync('./static');
|
|
||||||
for (var j = 0; j < list.length; j++) {
|
|
||||||
var item = list[j];
|
|
||||||
if ((item.indexOf('.js') === item.length - 3) && (item.indexOf('.min.js') === -1)) {
|
|
||||||
var dest = item.substring(0, item.length - 3) + '.min' + item.substring(item.length - 3);
|
|
||||||
var orig_code = fs.readFileSync('./static/' + item, 'utf8');
|
|
||||||
|
|
||||||
fs.writeFileSync('./static/' + dest, uglify.minify(orig_code).code, 'utf8');
|
|
||||||
winston.info('compressed ' + item + ' into ' + dest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the static documents into the preferred store, skipping expirations
|
|
||||||
var path, data;
|
|
||||||
for (var name in config.documents) {
|
|
||||||
path = config.documents[name];
|
|
||||||
data = fs.readFileSync(path, 'utf8');
|
|
||||||
winston.info('loading static document', { name: name, path: path });
|
|
||||||
if (data) {
|
|
||||||
preferredStore.set(name, data, function(cb) {
|
|
||||||
winston.debug('loaded static document', { success: cb });
|
|
||||||
}, true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
winston.warn('failed to load static document', { name: name, path: path });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pick up a key generator
|
|
||||||
var pwOptions = config.keyGenerator || {};
|
|
||||||
pwOptions.type = pwOptions.type || 'random';
|
|
||||||
var gen = require('./lib/key_generators/' + pwOptions.type);
|
|
||||||
var keyGenerator = new gen(pwOptions);
|
|
||||||
|
|
||||||
// Configure the document handler
|
|
||||||
var documentHandler = new DocumentHandler({
|
|
||||||
store: preferredStore,
|
|
||||||
maxLength: config.maxLength,
|
|
||||||
keyLength: config.keyLength,
|
|
||||||
keyGenerator: keyGenerator
|
|
||||||
});
|
|
||||||
|
|
||||||
var app = connect();
|
|
||||||
|
|
||||||
// Rate limit all requests
|
|
||||||
if (config.rateLimits) {
|
|
||||||
config.rateLimits.end = true;
|
|
||||||
app.use(connect_rate_limit(config.rateLimits));
|
|
||||||
}
|
|
||||||
|
|
||||||
// first look at API calls
|
|
||||||
app.use(route(function(router) {
|
|
||||||
// get raw documents - support getting with extension
|
|
||||||
router.get('/raw/:id', function(request, response) {
|
|
||||||
var key = request.params.id.split('.')[0];
|
|
||||||
var skipExpire = !!config.documents[key];
|
|
||||||
return documentHandler.handleRawGet(key, response, skipExpire);
|
|
||||||
});
|
|
||||||
// add documents
|
|
||||||
router.post('/documents', function(request, response) {
|
|
||||||
return documentHandler.handlePost(request, response);
|
|
||||||
});
|
|
||||||
// get documents
|
|
||||||
router.get('/documents/:id', function(request, response) {
|
|
||||||
var key = request.params.id.split('.')[0];
|
|
||||||
var skipExpire = !!config.documents[key];
|
|
||||||
return documentHandler.handleGet(key, response, skipExpire);
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Otherwise, try to match static files
|
|
||||||
app.use(connect_st({
|
|
||||||
path: __dirname + '/static',
|
|
||||||
content: { maxAge: config.staticMaxAge },
|
|
||||||
passthrough: true,
|
|
||||||
index: false
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Then we can loop back - and everything else should be a token,
|
|
||||||
// so route it back to /
|
|
||||||
app.use(route(function(router) {
|
|
||||||
router.get('/:id', function(request, response, next) {
|
|
||||||
request.sturl = '/';
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
// And match index
|
|
||||||
app.use(connect_st({
|
|
||||||
path: __dirname + '/static',
|
|
||||||
content: { maxAge: config.staticMaxAge },
|
|
||||||
index: 'index.html'
|
|
||||||
}));
|
|
||||||
|
|
||||||
http.createServer(app).listen(config.port, config.host);
|
|
||||||
|
|
||||||
winston.info('listening on ' + config.host + ':' + config.port);
|
|
|
@ -1,171 +0,0 @@
|
||||||
body {
|
|
||||||
background: #002B36;
|
|
||||||
padding: 20px 50px;
|
|
||||||
margin: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* textarea */
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
background: transparent;
|
|
||||||
border: 0px;
|
|
||||||
color: #fff;
|
|
||||||
padding: 0px;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
font-family: monospace;
|
|
||||||
outline: none;
|
|
||||||
resize: none;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the line numbers */
|
|
||||||
|
|
||||||
#linenos {
|
|
||||||
color: #7d7d7d;
|
|
||||||
z-index: -1000;
|
|
||||||
position: absolute;
|
|
||||||
top: 20px;
|
|
||||||
left: 0px;
|
|
||||||
width: 30px; /* 30 to get 20 away from box */
|
|
||||||
font-size: 13px;
|
|
||||||
font-family: monospace;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* code box when locked */
|
|
||||||
|
|
||||||
#box {
|
|
||||||
padding: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
width: 100%;
|
|
||||||
border: 0px;
|
|
||||||
outline: none;
|
|
||||||
font-size: 13px;
|
|
||||||
overflow: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
#box code {
|
|
||||||
padding: 0px;
|
|
||||||
background: transparent !important; /* don't hide hastebox */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* key */
|
|
||||||
|
|
||||||
#key {
|
|
||||||
position: fixed;
|
|
||||||
top: 0px;
|
|
||||||
right: 0px;
|
|
||||||
z-index: +1000; /* watch out */
|
|
||||||
}
|
|
||||||
|
|
||||||
#box1 {
|
|
||||||
padding: 5px;
|
|
||||||
text-align: center;
|
|
||||||
background: #00222b;
|
|
||||||
}
|
|
||||||
|
|
||||||
#box2 {
|
|
||||||
background: #08323c;
|
|
||||||
font-size: 0px;
|
|
||||||
padding: 0px 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#box1 a.logo, #box1 a.logo:visited {
|
|
||||||
display: inline-block;
|
|
||||||
background: url(logo.png);
|
|
||||||
width: 126px;
|
|
||||||
height: 42px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#box1 a.logo:hover {
|
|
||||||
background-position: 0 bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
#box2 .function {
|
|
||||||
background: url(function-icons.png);
|
|
||||||
width: 32px;
|
|
||||||
height: 37px;
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
#box2 .link embed {
|
|
||||||
vertical-align: bottom; /* fix for zeroClipboard style */
|
|
||||||
}
|
|
||||||
|
|
||||||
#box2 .function.enabled:hover {
|
|
||||||
cursor: hand;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pointer {
|
|
||||||
display: block;
|
|
||||||
height: 5px;
|
|
||||||
width: 10px;
|
|
||||||
background: url(hover-dropdown-tip.png);
|
|
||||||
bottom: 0px;
|
|
||||||
position: absolute;
|
|
||||||
margin: auto;
|
|
||||||
left: 0px;
|
|
||||||
right: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#box3, #messages li {
|
|
||||||
background: #173e48;
|
|
||||||
font-family: Helvetica, sans-serif;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 14px;
|
|
||||||
padding: 10px 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#box3 .label, #messages li {
|
|
||||||
color: #fff;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
#box3 .shortcut {
|
|
||||||
color: #c4dce3;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
#box2 .function.save { background-position: -5px top; }
|
|
||||||
#box2 .function.enabled.save { background-position: -5px center; }
|
|
||||||
#box2 .function.enabled.save:hover { background-position: -5px bottom; }
|
|
||||||
|
|
||||||
#box2 .function.new { background-position: -42px top; }
|
|
||||||
#box2 .function.enabled.new { background-position: -42px center; }
|
|
||||||
#box2 .function.enabled.new:hover { background-position: -42px bottom; }
|
|
||||||
|
|
||||||
#box2 .function.duplicate { background-position: -79px top; }
|
|
||||||
#box2 .function.enabled.duplicate { background-position: -79px center; }
|
|
||||||
#box2 .function.enabled.duplicate:hover { background-position: -79px bottom; }
|
|
||||||
|
|
||||||
#box2 .function.raw { background-position: -116px top; }
|
|
||||||
#box2 .function.enabled.raw { background-position: -116px center; }
|
|
||||||
#box2 .function.enabled.raw:hover { background-position: -116px bottom; }
|
|
||||||
|
|
||||||
#box2 .function.twitter { background-position: -153px top; }
|
|
||||||
#box2 .function.enabled.twitter { background-position: -153px center; }
|
|
||||||
#box2 .function.enabled.twitter:hover { background-position: -153px bottom; }
|
|
||||||
#box2 .button-picture{ border-width: 0; font-size: inherit; }
|
|
||||||
|
|
||||||
#messages {
|
|
||||||
position:fixed;
|
|
||||||
top:0px;
|
|
||||||
right:138px;
|
|
||||||
margin:0;
|
|
||||||
padding:0;
|
|
||||||
width:400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#messages li {
|
|
||||||
background:rgba(23,62,72,0.8);
|
|
||||||
margin:0 auto;
|
|
||||||
list-style:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#messages li.error {
|
|
||||||
background:rgba(102,8,0,0.8);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,399 +0,0 @@
|
||||||
/* global $, hljs, window, document */
|
|
||||||
|
|
||||||
///// represents a single document
|
|
||||||
|
|
||||||
var haste_document = function() {
|
|
||||||
this.locked = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Escapes HTML tag characters
|
|
||||||
haste_document.prototype.htmlEscape = function(s) {
|
|
||||||
return s
|
|
||||||
.replace(/&/g, '&')
|
|
||||||
.replace(/>/g, '>')
|
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/"/g, '"');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get this document from the server and lock it here
|
|
||||||
haste_document.prototype.load = function(key, callback, lang) {
|
|
||||||
var _this = this;
|
|
||||||
$.ajax('/documents/' + key, {
|
|
||||||
type: 'get',
|
|
||||||
dataType: 'json',
|
|
||||||
success: function(res) {
|
|
||||||
_this.locked = true;
|
|
||||||
_this.key = key;
|
|
||||||
_this.data = res.data;
|
|
||||||
try {
|
|
||||||
var high;
|
|
||||||
if (lang === 'txt') {
|
|
||||||
high = { value: _this.htmlEscape(res.data) };
|
|
||||||
}
|
|
||||||
else if (lang) {
|
|
||||||
high = hljs.highlight(lang, res.data);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
high = hljs.highlightAuto(res.data);
|
|
||||||
}
|
|
||||||
} catch(err) {
|
|
||||||
// failed highlight, fall back on auto
|
|
||||||
high = hljs.highlightAuto(res.data);
|
|
||||||
}
|
|
||||||
callback({
|
|
||||||
value: high.value,
|
|
||||||
key: key,
|
|
||||||
language: high.language || lang,
|
|
||||||
lineCount: res.data.split('\n').length
|
|
||||||
});
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
callback(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Save this document to the server and lock it here
|
|
||||||
haste_document.prototype.save = function(data, callback) {
|
|
||||||
if (this.locked) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this.data = data;
|
|
||||||
var _this = this;
|
|
||||||
$.ajax('/documents', {
|
|
||||||
type: 'post',
|
|
||||||
data: data,
|
|
||||||
dataType: 'json',
|
|
||||||
contentType: 'application/json; charset=utf-8',
|
|
||||||
success: function(res) {
|
|
||||||
_this.locked = true;
|
|
||||||
_this.key = res.key;
|
|
||||||
var high = hljs.highlightAuto(data);
|
|
||||||
callback(null, {
|
|
||||||
value: high.value,
|
|
||||||
key: res.key,
|
|
||||||
language: high.language,
|
|
||||||
lineCount: data.split('\n').length
|
|
||||||
});
|
|
||||||
},
|
|
||||||
error: function(res) {
|
|
||||||
try {
|
|
||||||
callback($.parseJSON(res.responseText));
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
callback({message: 'Something went wrong!'});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
///// represents the paste application
|
|
||||||
|
|
||||||
var haste = function(appName, options) {
|
|
||||||
this.appName = appName;
|
|
||||||
this.$textarea = $('textarea');
|
|
||||||
this.$box = $('#box');
|
|
||||||
this.$code = $('#box code');
|
|
||||||
this.$linenos = $('#linenos');
|
|
||||||
this.options = options;
|
|
||||||
this.configureShortcuts();
|
|
||||||
this.configureButtons();
|
|
||||||
// If twitter is disabled, hide the button
|
|
||||||
if (!options.twitter) {
|
|
||||||
$('#box2 .twitter').hide();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set the page title - include the appName
|
|
||||||
haste.prototype.setTitle = function(ext) {
|
|
||||||
var title = ext ? this.appName + ' - ' + ext : this.appName;
|
|
||||||
document.title = title;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Show a message box
|
|
||||||
haste.prototype.showMessage = function(msg, cls) {
|
|
||||||
var msgBox = $('<li class="'+(cls || 'info')+'">'+msg+'</li>');
|
|
||||||
$('#messages').prepend(msgBox);
|
|
||||||
setTimeout(function() {
|
|
||||||
msgBox.slideUp('fast', function() { $(this).remove(); });
|
|
||||||
}, 3000);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Show the light key
|
|
||||||
haste.prototype.lightKey = function() {
|
|
||||||
this.configureKey(['new', 'save']);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Show the full key
|
|
||||||
haste.prototype.fullKey = function() {
|
|
||||||
this.configureKey(['new', 'duplicate', 'twitter', 'raw']);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set the key up for certain things to be enabled
|
|
||||||
haste.prototype.configureKey = function(enable) {
|
|
||||||
var $this, i = 0;
|
|
||||||
$('#box2 .function').each(function() {
|
|
||||||
$this = $(this);
|
|
||||||
for (i = 0; i < enable.length; i++) {
|
|
||||||
if ($this.hasClass(enable[i])) {
|
|
||||||
$this.addClass('enabled');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this.removeClass('enabled');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Remove the current document (if there is one)
|
|
||||||
// and set up for a new one
|
|
||||||
haste.prototype.newDocument = function(hideHistory) {
|
|
||||||
this.$box.hide();
|
|
||||||
this.doc = new haste_document();
|
|
||||||
if (!hideHistory) {
|
|
||||||
window.history.pushState(null, this.appName, '/');
|
|
||||||
}
|
|
||||||
this.setTitle();
|
|
||||||
this.lightKey();
|
|
||||||
this.$textarea.val('').show('fast', function() {
|
|
||||||
this.focus();
|
|
||||||
});
|
|
||||||
this.removeLineNumbers();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Map of common extensions
|
|
||||||
// Note: this list does not need to include anything that IS its extension,
|
|
||||||
// due to the behavior of lookupTypeByExtension and lookupExtensionByType
|
|
||||||
// Note: optimized for lookupTypeByExtension
|
|
||||||
haste.extensionMap = {
|
|
||||||
rb: 'ruby', py: 'python', pl: 'perl', php: 'php', scala: 'scala', go: 'go',
|
|
||||||
xml: 'xml', html: 'xml', htm: 'xml', css: 'css', js: 'javascript', vbs: 'vbscript',
|
|
||||||
lua: 'lua', pas: 'delphi', java: 'java', cpp: 'cpp', cc: 'cpp', m: 'objectivec',
|
|
||||||
vala: 'vala', sql: 'sql', sm: 'smalltalk', lisp: 'lisp', ini: 'ini',
|
|
||||||
diff: 'diff', bash: 'bash', sh: 'bash', tex: 'tex', erl: 'erlang', hs: 'haskell',
|
|
||||||
md: 'markdown', txt: '', coffee: 'coffee', json: 'javascript',
|
|
||||||
swift: 'swift'
|
|
||||||
};
|
|
||||||
|
|
||||||
// Look up the extension preferred for a type
|
|
||||||
// If not found, return the type itself - which we'll place as the extension
|
|
||||||
haste.prototype.lookupExtensionByType = function(type) {
|
|
||||||
for (var key in haste.extensionMap) {
|
|
||||||
if (haste.extensionMap[key] === type) return key;
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Look up the type for a given extension
|
|
||||||
// If not found, return the extension - which we'll attempt to use as the type
|
|
||||||
haste.prototype.lookupTypeByExtension = function(ext) {
|
|
||||||
return haste.extensionMap[ext] || ext;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add line numbers to the document
|
|
||||||
// For the specified number of lines
|
|
||||||
haste.prototype.addLineNumbers = function(lineCount) {
|
|
||||||
var h = '';
|
|
||||||
for (var i = 0; i < lineCount; i++) {
|
|
||||||
h += (i + 1).toString() + '<br/>';
|
|
||||||
}
|
|
||||||
$('#linenos').html(h);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Remove the line numbers
|
|
||||||
haste.prototype.removeLineNumbers = function() {
|
|
||||||
$('#linenos').html('>');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Load a document and show it
|
|
||||||
haste.prototype.loadDocument = function(key) {
|
|
||||||
// Split the key up
|
|
||||||
var parts = key.split('.', 2);
|
|
||||||
// Ask for what we want
|
|
||||||
var _this = this;
|
|
||||||
_this.doc = new haste_document();
|
|
||||||
_this.doc.load(parts[0], function(ret) {
|
|
||||||
if (ret) {
|
|
||||||
_this.$code.html(ret.value);
|
|
||||||
_this.setTitle(ret.key);
|
|
||||||
_this.fullKey();
|
|
||||||
_this.$textarea.val('').hide();
|
|
||||||
_this.$box.show().focus();
|
|
||||||
_this.addLineNumbers(ret.lineCount);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_this.newDocument();
|
|
||||||
}
|
|
||||||
}, this.lookupTypeByExtension(parts[1]));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Duplicate the current document - only if locked
|
|
||||||
haste.prototype.duplicateDocument = function() {
|
|
||||||
if (this.doc.locked) {
|
|
||||||
var currentData = this.doc.data;
|
|
||||||
this.newDocument();
|
|
||||||
this.$textarea.val(currentData);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Lock the current document
|
|
||||||
haste.prototype.lockDocument = function() {
|
|
||||||
var _this = this;
|
|
||||||
this.doc.save(this.$textarea.val(), function(err, ret) {
|
|
||||||
if (err) {
|
|
||||||
_this.showMessage(err.message, 'error');
|
|
||||||
}
|
|
||||||
else if (ret) {
|
|
||||||
_this.$code.html(ret.value);
|
|
||||||
_this.setTitle(ret.key);
|
|
||||||
var file = '/' + ret.key;
|
|
||||||
if (ret.language) {
|
|
||||||
file += '.' + _this.lookupExtensionByType(ret.language);
|
|
||||||
}
|
|
||||||
window.history.pushState(null, _this.appName + '-' + ret.key, file);
|
|
||||||
_this.fullKey();
|
|
||||||
_this.$textarea.val('').hide();
|
|
||||||
_this.$box.show().focus();
|
|
||||||
_this.addLineNumbers(ret.lineCount);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
haste.prototype.configureButtons = function() {
|
|
||||||
var _this = this;
|
|
||||||
this.buttons = [
|
|
||||||
{
|
|
||||||
$where: $('#box2 .save'),
|
|
||||||
label: 'Save',
|
|
||||||
shortcutDescription: 'control + s',
|
|
||||||
shortcut: function(evt) {
|
|
||||||
return evt.ctrlKey && (evt.keyCode === 83);
|
|
||||||
},
|
|
||||||
action: function() {
|
|
||||||
if (_this.$textarea.val().replace(/^\s+|\s+$/g, '') !== '') {
|
|
||||||
_this.lockDocument();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
$where: $('#box2 .new'),
|
|
||||||
label: 'New',
|
|
||||||
shortcut: function(evt) {
|
|
||||||
return evt.ctrlKey && evt.keyCode === 78;
|
|
||||||
},
|
|
||||||
shortcutDescription: 'control + n',
|
|
||||||
action: function() {
|
|
||||||
_this.newDocument(!_this.doc.key);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
$where: $('#box2 .duplicate'),
|
|
||||||
label: 'Duplicate & Edit',
|
|
||||||
shortcut: function(evt) {
|
|
||||||
return _this.doc.locked && evt.ctrlKey && evt.keyCode === 68;
|
|
||||||
},
|
|
||||||
shortcutDescription: 'control + d',
|
|
||||||
action: function() {
|
|
||||||
_this.duplicateDocument();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
$where: $('#box2 .raw'),
|
|
||||||
label: 'Just Text',
|
|
||||||
shortcut: function(evt) {
|
|
||||||
return evt.ctrlKey && evt.shiftKey && evt.keyCode === 82;
|
|
||||||
},
|
|
||||||
shortcutDescription: 'control + shift + r',
|
|
||||||
action: function() {
|
|
||||||
window.location.href = '/raw/' + _this.doc.key;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
$where: $('#box2 .twitter'),
|
|
||||||
label: 'Twitter',
|
|
||||||
shortcut: function(evt) {
|
|
||||||
return _this.options.twitter && _this.doc.locked && evt.shiftKey && evt.ctrlKey && evt.keyCode == 84;
|
|
||||||
},
|
|
||||||
shortcutDescription: 'control + shift + t',
|
|
||||||
action: function() {
|
|
||||||
window.open('https://twitter.com/share?url=' + encodeURI(window.location.href));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
for (var i = 0; i < this.buttons.length; i++) {
|
|
||||||
this.configureButton(this.buttons[i]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
haste.prototype.configureButton = function(options) {
|
|
||||||
// Handle the click action
|
|
||||||
options.$where.click(function(evt) {
|
|
||||||
evt.preventDefault();
|
|
||||||
if (!options.clickDisabled && $(this).hasClass('enabled')) {
|
|
||||||
options.action();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Show the label
|
|
||||||
options.$where.mouseenter(function() {
|
|
||||||
$('#box3 .label').text(options.label);
|
|
||||||
$('#box3 .shortcut').text(options.shortcutDescription || '');
|
|
||||||
$('#box3').show();
|
|
||||||
$(this).append($('#pointer').remove().show());
|
|
||||||
});
|
|
||||||
// Hide the label
|
|
||||||
options.$where.mouseleave(function() {
|
|
||||||
$('#box3').hide();
|
|
||||||
$('#pointer').hide();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Configure keyboard shortcuts for the textarea
|
|
||||||
haste.prototype.configureShortcuts = function() {
|
|
||||||
var _this = this;
|
|
||||||
$(document.body).keydown(function(evt) {
|
|
||||||
var button;
|
|
||||||
for (var i = 0 ; i < _this.buttons.length; i++) {
|
|
||||||
button = _this.buttons[i];
|
|
||||||
if (button.shortcut && button.shortcut(evt)) {
|
|
||||||
evt.preventDefault();
|
|
||||||
button.action();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
///// Tab behavior in the textarea - 2 spaces per tab
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('textarea').keydown(function(evt) {
|
|
||||||
if (evt.keyCode === 9) {
|
|
||||||
evt.preventDefault();
|
|
||||||
var myValue = ' ';
|
|
||||||
// http://stackoverflow.com/questions/946534/insert-text-into-textarea-with-jquery
|
|
||||||
// For browsers like Internet Explorer
|
|
||||||
if (document.selection) {
|
|
||||||
this.focus();
|
|
||||||
var sel = document.selection.createRange();
|
|
||||||
sel.text = myValue;
|
|
||||||
this.focus();
|
|
||||||
}
|
|
||||||
// Mozilla and Webkit
|
|
||||||
else if (this.selectionStart || this.selectionStart == '0') {
|
|
||||||
var startPos = this.selectionStart;
|
|
||||||
var endPos = this.selectionEnd;
|
|
||||||
var scrollTop = this.scrollTop;
|
|
||||||
this.value = this.value.substring(0, startPos) + myValue +
|
|
||||||
this.value.substring(endPos,this.value.length);
|
|
||||||
this.focus();
|
|
||||||
this.selectionStart = startPos + myValue.length;
|
|
||||||
this.selectionEnd = startPos + myValue.length;
|
|
||||||
this.scrollTop = scrollTop;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.value += myValue;
|
|
||||||
this.focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 6.1 KiB |
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 2.8 KiB |
|
@ -1,68 +0,0 @@
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
|
|
||||||
<title>hastebin</title>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="solarized_dark.css"/>
|
|
||||||
<link rel="stylesheet" type="text/css" href="application.css"/>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
|
|
||||||
<script type="text/javascript" src="highlight.min.js"></script>
|
|
||||||
<script type="text/javascript" src="application.min.js"></script>
|
|
||||||
|
|
||||||
<meta name="robots" content="noindex,nofollow"/>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var app = null;
|
|
||||||
// Handle pops
|
|
||||||
var handlePop = function(evt) {
|
|
||||||
var path = evt.target.location.pathname;
|
|
||||||
if (path === '/') { app.newDocument(true); }
|
|
||||||
else { app.loadDocument(path.substring(1, path.length)); }
|
|
||||||
};
|
|
||||||
// Set up the pop state to handle loads, skipping the first load
|
|
||||||
// to make chrome behave like others:
|
|
||||||
// http://code.google.com/p/chromium/issues/detail?id=63040
|
|
||||||
setTimeout(function() {
|
|
||||||
window.onpopstate = function(evt) {
|
|
||||||
try { handlePop(evt); } catch(err) { /* not loaded yet */ }
|
|
||||||
};
|
|
||||||
}, 1000);
|
|
||||||
// Construct app and load initial path
|
|
||||||
$(function() {
|
|
||||||
app = new haste('hastebin', { twitter: true });
|
|
||||||
handlePop({ target: window });
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<ul id="messages"></ul>
|
|
||||||
|
|
||||||
<div id="key">
|
|
||||||
<div id="pointer" style="display:none;"></div>
|
|
||||||
<div id="box1">
|
|
||||||
<a href="/about.md" class="logo"></a>
|
|
||||||
</div>
|
|
||||||
<div id="box2">
|
|
||||||
<button class="save function button-picture">Save</button>
|
|
||||||
<button class="new function button-picture">New</button>
|
|
||||||
<button class="duplicate function button-picture">Duplicate & Edit</button>
|
|
||||||
<button class="raw function button-picture">Just Text</button>
|
|
||||||
<button class="twitter function button-picture">Twitter</button>
|
|
||||||
</div>
|
|
||||||
<div id="box3" style="display:none;">
|
|
||||||
<div class="label"></div>
|
|
||||||
<div class="shortcut"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="linenos"></div>
|
|
||||||
<pre id="box" style="display:none;" class="hljs" tabindex="0"><code></code></pre>
|
|
||||||
<textarea spellcheck="false" style="display:none;"></textarea>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
Binary file not shown.
Before Width: | Height: | Size: 4.6 KiB |
|
@ -1,4 +0,0 @@
|
||||||
User-agent: *
|
|
||||||
Disallow: /*
|
|
||||||
Allow: /?okparam=
|
|
||||||
Allow: /$
|
|
|
@ -1,84 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull <sourdrums@gmail.com>
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
.hljs {
|
|
||||||
display: block;
|
|
||||||
overflow-x: auto;
|
|
||||||
padding: 0.5em;
|
|
||||||
background: #002b36;
|
|
||||||
color: #839496;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-comment,
|
|
||||||
.hljs-quote {
|
|
||||||
color: #586e75;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Solarized Green */
|
|
||||||
.hljs-keyword,
|
|
||||||
.hljs-selector-tag,
|
|
||||||
.hljs-addition {
|
|
||||||
color: #859900;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Solarized Cyan */
|
|
||||||
.hljs-number,
|
|
||||||
.hljs-string,
|
|
||||||
.hljs-meta .hljs-meta-string,
|
|
||||||
.hljs-literal,
|
|
||||||
.hljs-doctag,
|
|
||||||
.hljs-regexp {
|
|
||||||
color: #2aa198;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Solarized Blue */
|
|
||||||
.hljs-title,
|
|
||||||
.hljs-section,
|
|
||||||
.hljs-name,
|
|
||||||
.hljs-selector-id,
|
|
||||||
.hljs-selector-class {
|
|
||||||
color: #268bd2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Solarized Yellow */
|
|
||||||
.hljs-attribute,
|
|
||||||
.hljs-attr,
|
|
||||||
.hljs-variable,
|
|
||||||
.hljs-template-variable,
|
|
||||||
.hljs-class .hljs-title,
|
|
||||||
.hljs-type {
|
|
||||||
color: #b58900;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Solarized Orange */
|
|
||||||
.hljs-symbol,
|
|
||||||
.hljs-bullet,
|
|
||||||
.hljs-subst,
|
|
||||||
.hljs-meta,
|
|
||||||
.hljs-meta .hljs-keyword,
|
|
||||||
.hljs-selector-attr,
|
|
||||||
.hljs-selector-pseudo,
|
|
||||||
.hljs-link {
|
|
||||||
color: #cb4b16;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Solarized Red */
|
|
||||||
.hljs-built_in,
|
|
||||||
.hljs-deletion {
|
|
||||||
color: #dc322f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-formula {
|
|
||||||
background: #073642;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-emphasis {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hljs-strong {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
/* global describe, it */
|
|
||||||
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
var DocumentHandler = require('../lib/document_handler');
|
|
||||||
var Generator = require('../lib/key_generators/random');
|
|
||||||
|
|
||||||
describe('document_handler', function() {
|
|
||||||
|
|
||||||
describe('randomKey', function() {
|
|
||||||
|
|
||||||
it('should choose a key of the proper length', function() {
|
|
||||||
var gen = new Generator();
|
|
||||||
var dh = new DocumentHandler({ keyLength: 6, keyGenerator: gen });
|
|
||||||
assert.equal(6, dh.acceptableKey().length);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should choose a default key length', function() {
|
|
||||||
var gen = new Generator();
|
|
||||||
var dh = new DocumentHandler({ keyGenerator: gen });
|
|
||||||
assert.equal(dh.keyLength, DocumentHandler.defaultKeyLength);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
|
@ -1,33 +0,0 @@
|
||||||
/* global describe, it */
|
|
||||||
|
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
const Generator = require('../../lib/key_generators/dictionary');
|
|
||||||
|
|
||||||
describe('RandomKeyGenerator', function() {
|
|
||||||
describe('randomKey', function() {
|
|
||||||
it('should throw an error if given no options', () => {
|
|
||||||
assert.throws(() => {
|
|
||||||
new Generator();
|
|
||||||
}, Error);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error if given no path', () => {
|
|
||||||
assert.throws(() => {
|
|
||||||
new Generator({});
|
|
||||||
}, Error);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return a key of the proper number of words from the given dictionary', () => {
|
|
||||||
const path = '/tmp/haste-server-test-dictionary';
|
|
||||||
const words = ['cat'];
|
|
||||||
fs.writeFileSync(path, words.join('\n'));
|
|
||||||
|
|
||||||
const gen = new Generator({path}, () => {
|
|
||||||
assert.equal('catcatcat', gen.createKey(3));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,27 +0,0 @@
|
||||||
/* global describe, it */
|
|
||||||
|
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const Generator = require('../../lib/key_generators/phonetic');
|
|
||||||
|
|
||||||
const vowels = 'aeiou';
|
|
||||||
const consonants = 'bcdfghjklmnpqrstvwxyz';
|
|
||||||
|
|
||||||
describe('RandomKeyGenerator', () => {
|
|
||||||
describe('randomKey', () => {
|
|
||||||
it('should return a key of the proper length', () => {
|
|
||||||
const gen = new Generator();
|
|
||||||
assert.equal(6, gen.createKey(6).length);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should alternate consonants and vowels', () => {
|
|
||||||
const gen = new Generator();
|
|
||||||
|
|
||||||
const key = gen.createKey(3);
|
|
||||||
|
|
||||||
assert.ok(consonants.includes(key[0]));
|
|
||||||
assert.ok(consonants.includes(key[2]));
|
|
||||||
assert.ok(vowels.includes(key[1]));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,19 +0,0 @@
|
||||||
/* global describe, it */
|
|
||||||
|
|
||||||
const assert = require('assert');
|
|
||||||
|
|
||||||
const Generator = require('../../lib/key_generators/random');
|
|
||||||
|
|
||||||
describe('RandomKeyGenerator', () => {
|
|
||||||
describe('randomKey', () => {
|
|
||||||
it('should return a key of the proper length', () => {
|
|
||||||
const gen = new Generator();
|
|
||||||
assert.equal(6, gen.createKey(6).length);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use a key from the given keyset if given', () => {
|
|
||||||
const gen = new Generator({keyspace: 'A'});
|
|
||||||
assert.equal('AAAAAA', gen.createKey(6));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,54 +0,0 @@
|
||||||
/* global it, describe, afterEach */
|
|
||||||
|
|
||||||
var assert = require('assert');
|
|
||||||
|
|
||||||
var winston = require('winston');
|
|
||||||
winston.remove(winston.transports.Console);
|
|
||||||
|
|
||||||
var RedisDocumentStore = require('../lib/document_stores/redis');
|
|
||||||
|
|
||||||
describe('redis_document_store', function() {
|
|
||||||
|
|
||||||
/* reconnect to redis on each test */
|
|
||||||
afterEach(function() {
|
|
||||||
if (RedisDocumentStore.client) {
|
|
||||||
RedisDocumentStore.client.quit();
|
|
||||||
RedisDocumentStore.client = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('set', function() {
|
|
||||||
|
|
||||||
it('should be able to set a key and have an expiration set', function(done) {
|
|
||||||
var store = new RedisDocumentStore({ expire: 10 });
|
|
||||||
store.set('hello1', 'world', function() {
|
|
||||||
RedisDocumentStore.client.ttl('hello1', function(err, res) {
|
|
||||||
assert.ok(res > 1);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not set an expiration when told not to', function(done) {
|
|
||||||
var store = new RedisDocumentStore({ expire: 10 });
|
|
||||||
store.set('hello2', 'world', function() {
|
|
||||||
RedisDocumentStore.client.ttl('hello2', function(err, res) {
|
|
||||||
assert.equal(-1, res);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
}, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not set an expiration when expiration is off', function(done) {
|
|
||||||
var store = new RedisDocumentStore({ expire: false });
|
|
||||||
store.set('hello3', 'world', function() {
|
|
||||||
RedisDocumentStore.client.ttl('hello3', function(err, res) {
|
|
||||||
assert.equal(-1, res);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
Loading…
Reference in a new issue