Comparing version 1.3.0 to 1.4.0
export declare class RedisScript { | ||
private readonly _src; | ||
private readonly _numberOfKeys; | ||
private readonly _keys; | ||
private _sha; | ||
constructor(src: string, numberOfKeys?: number); | ||
constructor(src: string, keys?: string[]); | ||
execute(client: any, ...args: any[]): Promise<boolean>; | ||
@@ -7,0 +7,0 @@ private _execute; |
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.RedisScript = void 0; | ||
const putil_promisify_1 = __importDefault(require("putil-promisify")); | ||
class RedisScript { | ||
constructor(src, numberOfKeys) { | ||
constructor(src, keys) { | ||
this._src = src; | ||
this._sha = ''; | ||
this._numberOfKeys = numberOfKeys || 0; | ||
this._keys = keys || []; | ||
} | ||
@@ -27,13 +31,20 @@ async execute(client, ...args) { | ||
await this._loadScript(client); | ||
return !!(await client.evalsha(this._sha, this._numberOfKeys, ...args)); | ||
const prms = [...this._keys]; | ||
const m = Math.max(this._keys.length, args.length); | ||
for (let i = 0; i < m; i++) { | ||
prms.push(this._keys[i] == null ? 'key' + (i + 1) : '' + this._keys[i]); | ||
} | ||
for (let i = 0; i < m; i++) { | ||
prms.push(args[i] == null ? '' : args[i]); | ||
} | ||
return !!(await putil_promisify_1.default.fromCallback(cb => client.evalsha(this._sha, m, ...prms, cb))); | ||
} | ||
async _loadScript(client) { | ||
return client.script('load', this._src).then(resp => { | ||
/* istanbul ignore next */ | ||
if (!resp) | ||
throw new Error('Unable to load redis script in to redis cache'); | ||
this._sha = resp; | ||
}); | ||
const resp = await putil_promisify_1.default.fromCallback(cb => client.script('load', this._src, cb)); | ||
/* istanbul ignore next */ | ||
if (!resp) | ||
throw new Error('Unable to load redis script in to redis cache'); | ||
this._sha = resp; | ||
} | ||
} | ||
exports.RedisScript = RedisScript; |
@@ -85,7 +85,14 @@ import { SessionManager } from './SessionManager'; | ||
* | ||
* @param {string|Object} key | ||
* @param {Object} values | ||
* @return {Promise<number>} | ||
*/ | ||
set(values: Record<string, any>): Promise<number>; | ||
/** | ||
* Stores user data to session | ||
* | ||
* @param {string} [key] | ||
* @param {*} [value] | ||
* @return {Promise<number>} | ||
*/ | ||
set(key: any, value: any): Promise<number>; | ||
set(key: string, value: any): Promise<number>; | ||
/** | ||
@@ -103,10 +110,3 @@ * Kills the session | ||
write(): Promise<void>; | ||
/** | ||
* | ||
* @param {string|Object} key | ||
* @param {*} [value] | ||
* @return {Array<String>} | ||
* @private | ||
*/ | ||
private _prepareUserData; | ||
} |
@@ -9,2 +9,3 @@ "use strict"; | ||
const zlib_1 = __importDefault(require("zlib")); | ||
const putil_promisify_1 = __importDefault(require("putil-promisify")); | ||
const unzip = util_1.default.promisify(zlib_1.default.unzip); | ||
@@ -101,6 +102,6 @@ class Session { | ||
if (manager._additionalFields) { | ||
for (const [i] of manager._additionalFields.entries()) | ||
args.push('f' + i); | ||
for (const key of manager._additionalFields.keys()) | ||
args.push('f' + key); | ||
} | ||
const resp = await client.hmget(sessKey, ...args); | ||
const resp = await putil_promisify_1.default.fromCallback(cb => client.hmget(sessKey, ...args, cb)); | ||
this._userId = resp[0] || ''; | ||
@@ -159,3 +160,3 @@ this._lastAccess = Number(resp[1]) || 0; | ||
// Query values for keys | ||
const resp = await client.hmget(sessKey, keys); | ||
const resp = await putil_promisify_1.default.fromCallback(cb => client.hmget(sessKey, keys, cb)); | ||
// Do type conversion | ||
@@ -174,15 +175,9 @@ for (const [i, v] of resp.entries()) | ||
} | ||
/** | ||
* Stores user data to session | ||
* | ||
* @param {string|Object} key | ||
* @param {*} [value] | ||
* @return {Promise<number>} | ||
*/ | ||
async set(key, value) { | ||
async set(arg0, arg1) { | ||
const manager = this._manager; | ||
const sessKey = manager._ns + ':sess_' + this.sessionId; | ||
const client = await manager._getClient(); | ||
const values = this._prepareUserData(key, value); | ||
const resp = await client.hmset(sessKey, values); | ||
const values = typeof arg0 === 'object' ? | ||
this._prepareUserData(arg0) : this._prepareUserData('' + arg0, arg1); | ||
const resp = await putil_promisify_1.default.fromCallback(cb => client.hmset(sessKey, values, cb)); | ||
/* istanbul ignore next */ | ||
@@ -229,10 +224,3 @@ if (!String(resp).includes('OK')) | ||
} | ||
/** | ||
* | ||
* @param {string|Object} key | ||
* @param {*} [value] | ||
* @return {Array<String>} | ||
* @private | ||
*/ | ||
_prepareUserData(key, value) { | ||
_prepareUserData(arg0, arg1) { | ||
const makeTyped = (v) => { | ||
@@ -250,10 +238,10 @@ if (v instanceof Buffer) | ||
let values = []; | ||
if (typeof key === 'object') { | ||
for (const k of Object.keys(key)) { | ||
if (typeof arg0 === 'object') { | ||
for (const k of Object.keys(arg0)) { | ||
values.push('$' + k); | ||
values.push(makeTyped(key[k])); | ||
values.push(makeTyped(arg0[k])); | ||
} | ||
} | ||
else | ||
values = ['$' + key, makeTyped(value)]; | ||
values = ['$' + arg0, makeTyped(arg1)]; | ||
return values; | ||
@@ -260,0 +248,0 @@ } |
@@ -1,2 +0,1 @@ | ||
import { Redis } from 'ioredis'; | ||
import { Session } from './Session'; | ||
@@ -11,2 +10,3 @@ export declare namespace SessionManager { | ||
} | ||
export declare type ResultSession = Session & Record<string, any>; | ||
/** | ||
@@ -37,3 +37,3 @@ * | ||
*/ | ||
constructor(client: Redis, props?: SessionManager.Options); | ||
constructor(client: any, props?: SessionManager.Options); | ||
get namespace(): string | undefined; | ||
@@ -67,3 +67,3 @@ get ttl(): number | undefined; | ||
[index: string]: any; | ||
}): Promise<Session>; | ||
}): Promise<ResultSession>; | ||
/** | ||
@@ -74,5 +74,5 @@ * Retrieves session by sessionId | ||
* @param {boolean} [noUpdate=false] | ||
* @return {Promise<Session>} | ||
* @return {Promise<ResultSession>} | ||
*/ | ||
get(sessionId: string, noUpdate?: boolean): Promise<Session | undefined>; | ||
get(sessionId: string, noUpdate?: boolean): Promise<ResultSession | undefined>; | ||
/** | ||
@@ -91,3 +91,3 @@ * Retrieves all session ids which were active within the last n seconds. | ||
*/ | ||
getAllUsers(secs: number): Promise<string[]>; | ||
getAllUsers(secs?: number): Promise<string[]>; | ||
/** | ||
@@ -106,5 +106,5 @@ * Retrieves session ids of single user which were active within the last n seconds. | ||
* @param {boolean} [noUpdate=false] | ||
* @return {Promise<Session>} | ||
* @return {Promise<ResultSession>} | ||
*/ | ||
getOldestUserSession(userId: string, noUpdate?: boolean): Promise<Session | undefined>; | ||
getOldestUserSession(userId: string, noUpdate?: boolean): Promise<ResultSession | undefined>; | ||
/** | ||
@@ -142,2 +142,3 @@ * Returns true if sessionId exists, false otherwise, | ||
quit(): void; | ||
wipe(): Promise<void>; | ||
/** | ||
@@ -152,3 +153,2 @@ * | ||
private _getClient; | ||
private _wipe; | ||
} |
@@ -10,2 +10,3 @@ "use strict"; | ||
const Session_1 = require("./Session"); | ||
const putil_promisify_1 = __importDefault(require("putil-promisify")); | ||
/** | ||
@@ -120,3 +121,3 @@ * | ||
const prefix = this._ns; | ||
const resp = await client.zcount(prefix + ':ACTIVITY', (secs ? Math.floor(this._now() - secs) : '-inf'), '+inf'); | ||
const resp = await putil_promisify_1.default.fromCallback(cb => client.zcount(prefix + ':ACTIVITY', (secs ? Math.floor(this._now() - secs) : '-inf'), '+inf', cb)); | ||
return Number(resp); | ||
@@ -136,4 +137,10 @@ } | ||
secs = Number(secs); | ||
const resp = await client.zcount(this._ns + ':user_' + userId, (secs ? Math.floor(this._now() - secs) : '-inf'), '+inf'); | ||
return Number(resp); | ||
return new Promise(((resolve, reject) => { | ||
client.zcount(this._ns + ':user_' + userId, (secs ? Math.floor(this._now() - secs) : '-inf'), '+inf', (err, resp) => { | ||
/* istanbul ignore next */ | ||
if (err) | ||
return reject(err); | ||
resolve(Number(resp)); | ||
}); | ||
})); | ||
} | ||
@@ -173,7 +180,7 @@ /** | ||
* @param {boolean} [noUpdate=false] | ||
* @return {Promise<Session>} | ||
* @return {Promise<ResultSession>} | ||
*/ | ||
async get(sessionId, noUpdate = false) { | ||
if (!sessionId) | ||
return Promise.reject(new TypeError('You must provide sessionId')); | ||
throw new TypeError('You must provide sessionId'); | ||
const session = new Session_1.Session(this, { sessionId }); | ||
@@ -197,3 +204,3 @@ await session.read(); | ||
secs = Number(secs); | ||
return await client.zrevrangebyscore(this._ns + ':ACTIVITY', '+inf', (secs ? Math.floor(this._now() - secs) : '-inf')); | ||
return await putil_promisify_1.default.fromCallback(cb => client.zrevrangebyscore(this._ns + ':ACTIVITY', '+inf', (secs ? Math.floor(this._now() - secs) : '-inf'), cb)); | ||
} | ||
@@ -206,6 +213,6 @@ /** | ||
*/ | ||
async getAllUsers(secs) { | ||
async getAllUsers(secs = 0) { | ||
const client = await this._getClient(); | ||
secs = Number(secs); | ||
return await client.zrevrangebyscore(this._ns + ':USERS', '+inf', (secs ? Math.floor(this._now() - secs) : '-inf')); | ||
return await putil_promisify_1.default.fromCallback(cb => client.zrevrangebyscore(this._ns + ':USERS', '+inf', (secs ? Math.floor(this._now() - secs) : '-inf'), cb)); | ||
} | ||
@@ -224,3 +231,3 @@ /** | ||
n = Number(n); | ||
return await client.zrevrangebyscore(this._ns + ':user_' + userId, '+inf', (n ? Math.floor(this._now() - n) : '-inf')); | ||
return await putil_promisify_1.default.fromCallback(cb => client.zrevrangebyscore(this._ns + ':user_' + userId, '+inf', (n ? Math.floor(this._now() - n) : '-inf'), cb)); | ||
} | ||
@@ -232,9 +239,9 @@ /** | ||
* @param {boolean} [noUpdate=false] | ||
* @return {Promise<Session>} | ||
* @return {Promise<ResultSession>} | ||
*/ | ||
async getOldestUserSession(userId, noUpdate = false) { | ||
if (!userId) | ||
return Promise.reject(new TypeError('You must provide userId')); | ||
throw new TypeError('You must provide userId'); | ||
const client = await this._getClient(); | ||
const sessionId = await client.zrevrange(this._ns + ':user_' + userId, -1, -1); | ||
const sessionId = await putil_promisify_1.default.fromCallback(cb => client.zrevrange(this._ns + ':user_' + userId, -1, -1, cb)); | ||
if (sessionId && sessionId.length) | ||
@@ -253,3 +260,3 @@ return await this.get(sessionId[0], noUpdate); | ||
const client = await this._getClient(); | ||
const resp = await client.exists(this._ns + ':sess_' + sessionId); | ||
const resp = await putil_promisify_1.default.fromCallback(cb => client.exists(this._ns + ':sess_' + sessionId, cb)); | ||
return !!Number(resp); | ||
@@ -265,3 +272,3 @@ } | ||
if (!sessionId) | ||
return Promise.reject(new TypeError('You must provide sessionId')); | ||
throw new TypeError('You must provide sessionId'); | ||
const session = await this.get(sessionId, true); | ||
@@ -279,3 +286,3 @@ if (session) | ||
if (!userId) | ||
return Promise.reject(new TypeError('You must provide userId')); | ||
throw new TypeError('You must provide userId'); | ||
const sessions = await this.getUserSessions(userId); | ||
@@ -310,2 +317,10 @@ for (const sid of sessions) { | ||
} | ||
async wipe() { | ||
if (this._wipeTimer) { | ||
clearTimeout(this._wipeTimer); | ||
this._wipeTimer = undefined; | ||
} | ||
const client = await this._getClient(); | ||
await this._wipeScript.execute(client, this._ns, this._now()); | ||
} | ||
// noinspection JSMethodCanBeStatic | ||
@@ -321,3 +336,3 @@ /** | ||
async _syncTime(client) { | ||
const resp = await client.time(); | ||
const resp = await putil_promisify_1.default.fromCallback(cb => client.time(cb)); | ||
// Synchronize redis server time with local time | ||
@@ -335,7 +350,7 @@ this._timeDiff = (Date.now() / 1000) - | ||
setTimeout(() => { | ||
this._wipe().catch(/* istanbul ignore next */ () => 1); | ||
this.wipe().catch(/* istanbul ignore next */ () => 1); | ||
}, this._wipeInterval); | ||
this._wipeTimer.unref(); | ||
} | ||
if (this._client.status !== 'ready') { | ||
if ((this._client.status !== 'ready' && !this._client.ready)) { | ||
await new Promise(resolve => { | ||
@@ -349,11 +364,3 @@ this._client.once('ready', resolve); | ||
} | ||
async _wipe() { | ||
if (this._wipeTimer) { | ||
clearTimeout(this._wipeTimer); | ||
this._wipeTimer = undefined; | ||
} | ||
const client = await this._getClient(); | ||
await this._wipeScript.execute(client, this._ns, this._now()); | ||
} | ||
} | ||
exports.SessionManager = SessionManager; |
{ | ||
"name": "redisess", | ||
"description": "Powerful redis session manager for NodeJS", | ||
"version": "1.3.0", | ||
"version": "1.4.0", | ||
"author": "Panates Ltd.", | ||
@@ -18,30 +18,33 @@ "contributors": [ | ||
"javascript", | ||
"redis", | ||
"node-redis", | ||
"ioredis", | ||
"session", | ||
"redis" | ||
"manager" | ||
], | ||
"peerDependencies": { | ||
"ioredis": "^4.x.x" | ||
}, | ||
"peerDependencies": {}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"@types/ioredis": "^4.17.6", | ||
"@types/mocha": "^8.0.3", | ||
"@types/node": "^16.0.1", | ||
"@typescript-eslint/eslint-plugin": "^4.5.0", | ||
"@typescript-eslint/parser": "^4.5.0", | ||
"@types/ioredis": "^4.26.5", | ||
"@types/mocha": "^8.2.3", | ||
"@types/node": "^16.3.0", | ||
"@types/redis": "^2.8.31", | ||
"@typescript-eslint/eslint-plugin": "^4.28.2", | ||
"@typescript-eslint/parser": "^4.28.2", | ||
"babel-eslint": "^10.1.0", | ||
"eslint": "^7.12.0", | ||
"eslint": "^7.30.0", | ||
"eslint-config-google": "^0.14.0", | ||
"ioredis": "^4.19.0", | ||
"ioredis": "^4.27.6", | ||
"redis": "^3.1.2", | ||
"mocha": "^9.0.2", | ||
"nyc": "^15.1.0", | ||
"rejected-or-not": "^2.0.0", | ||
"ts-cleanup": "^0.2.2", | ||
"putil-promisify": "^1.8.4", | ||
"ts-cleanup": "^0.2.4", | ||
"ts-loader": "^9.2.3", | ||
"ts-node": "^10.0.0", | ||
"tsconfig-paths": "^3.9.0", | ||
"typescript": "^4.0.3" | ||
"tsconfig-paths": "^3.10.1", | ||
"typescript": "^4.3.5" | ||
}, | ||
"engines": { | ||
"node": ">=8.0" | ||
"node": ">=10.0" | ||
}, | ||
@@ -48,0 +51,0 @@ "directories": { |
@@ -14,10 +14,19 @@ | ||
Redis session manager for NodeJS | ||
High performant advanced Redis session manager for NodeJS. | ||
## Installation | ||
Redisess requires a redis client library to work. | ||
It has been tested for both [node-redis](https://www.npmjs.com/package/node-redis) and | ||
[ioredis](https://www.npmjs.com/package/ioredis) libraries. | ||
```bash | ||
$ npm install redisess --save | ||
$ npm install node-redis redisess --save | ||
``` | ||
or | ||
```bash | ||
$ npm install ioredis redisess --save | ||
``` | ||
## Basic Usage | ||
@@ -24,0 +33,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
40918
0
923
397
0
19