Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@adonisjs/redis

Package Overview
Dependencies
Maintainers
3
Versions
74
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@adonisjs/redis - npm Package Compare versions

Comparing version 8.0.0-3 to 8.0.0-4

build/src/connections/abstract_connection.d.ts

8

build/factories/redis_manager.d.ts

@@ -1,3 +0,3 @@

import type { Application } from '@adonisjs/core/app';
import type { RedisClusterConfig, RedisConnectionConfig } from '../src/types/main.js';
import RedisManager from '../src/redis_manager.js';
import type { RedisClusterConnectionConfig, RedisConnectionConfig } from '../src/types/main.js';
/**

@@ -7,3 +7,3 @@ * Redis manager factory is used to create an instance of the redis

*/
export declare class RedisManagerFactory<ConnectionsList extends Record<string, RedisClusterConfig | RedisConnectionConfig>> {
export declare class RedisManagerFactory<ConnectionsList extends Record<string, RedisClusterConnectionConfig | RedisConnectionConfig>> {
#private;

@@ -17,3 +17,3 @@ constructor(config: {

*/
create(app: Application<any>): import("../src/types/main.js").RedisManagerContract<ConnectionsList>;
create(): RedisManager<ConnectionsList>;
}

@@ -9,3 +9,2 @@ /*

*/
import { EmitterFactory } from '@adonisjs/core/factories/events';
import RedisManager from '../src/redis_manager.js';

@@ -24,5 +23,5 @@ /**

*/
create(app) {
return new RedisManager(this.#config, new EmitterFactory().create(app));
create() {
return new RedisManager(this.#config);
}
}

@@ -5,1 +5,2 @@ import './src/types/extended.js';

export { configure } from './configure.js';
export * as errors from './src/errors.js';

@@ -13,1 +13,2 @@ /*

export { configure } from './configure.js';
export * as errors from './src/errors.js';

@@ -1,17 +0,22 @@

import { ApplicationService } from '@adonisjs/core/types';
import type { ApplicationService } from '@adonisjs/core/types';
/**
* Provider to bind redis to the container
* Registering the Redis manager as a singleton to the container
* and defining REPL bindings
*/
export default class RedisProvider {
#private;
protected app: ApplicationService;
constructor(app: ApplicationService);
/**
* Register the redis binding
* Define repl bindings
*/
protected defineReplBindings(): Promise<void>;
/**
* Register the Redis manager as a singleton with the
* container
*/
register(): void;
/**
* Registering the health check checker with HealthCheck service
* Defining repl bindings on boot
*/
boot(): void;
boot(): Promise<void>;
/**

@@ -18,0 +23,0 @@ * Gracefully shutdown connections when app goes down

@@ -9,5 +9,5 @@ /*

*/
import { defineReplBindings } from '../src/repl_bindings.js';
/**
* Provider to bind redis to the container
* Registering the Redis manager as a singleton to the container
* and defining REPL bindings
*/

@@ -22,10 +22,12 @@ export default class RedisProvider {

*/
async #defineReplBindings() {
async defineReplBindings() {
if (this.app.getEnvironment() !== 'repl') {
return;
}
const { defineReplBindings } = await import('../src/repl_bindings.js');
defineReplBindings(this.app, await this.app.container.make('repl'));
}
/**
* Register the redis binding
* Register the Redis manager as a singleton with the
* container
*/

@@ -35,12 +37,11 @@ register() {

const { default: RedisManager } = await import('../src/redis_manager.js');
const emitter = await this.app.container.make('emitter');
const config = this.app.config.get('redis', {});
return new RedisManager(config, emitter);
return new RedisManager(config);
});
}
/**
* Registering the health check checker with HealthCheck service
* Defining repl bindings on boot
*/
boot() {
this.#defineReplBindings();
async boot() {
await this.defineReplBindings();
}

@@ -47,0 +48,0 @@ /**

@@ -1,17 +0,11 @@

import type { RedisConnectionConfig, RedisClusterConfig } from './types/main.js';
import type { RedisConnectionsList } from './types/main.js';
/**
* Expected shape of the config accepted by the "defineConfig"
* method
* Define config for redis
*/
type RedisConfig = {
connections: {
[name: string]: RedisConnectionConfig | RedisClusterConfig;
};
export declare function defineConfig<Connections extends RedisConnectionsList>(config: {
connection: keyof Connections;
connections: Connections;
}): {
connection: keyof Connections;
connections: Connections;
};
/**
* Define config for redis
*/
export declare function defineConfig<T extends RedisConfig & {
connection: keyof T['connections'];
}>(config: T): T;
export {};

@@ -9,3 +9,3 @@ /*

*/
import { InvalidArgumentsException } from '@poppinss/utils';
import { RuntimeException } from '@poppinss/utils';
/**

@@ -16,11 +16,14 @@ * Define config for redis

if (!config) {
throw new InvalidArgumentsException('Invalid config. It must be a valid object');
throw new RuntimeException('Invalid config. It must be an object');
}
if (!config.connections) {
throw new InvalidArgumentsException('Invalid config. Missing property "connections" inside it');
throw new RuntimeException('Missing "connections" property in the redis config file');
}
if (!config.connection || !config.connections[config.connection]) {
throw new InvalidArgumentsException('Invalid config. Missing property "connection" or the connection name is not defined inside "connections" object');
if (!config.connection) {
throw new RuntimeException('Missing "connection" property in redis config. Specify a default connection to use');
}
if (!config.connections[config.connection]) {
throw new RuntimeException(`Missing "connections.${String(config.connection)}". It is referenced by the "default" redis connection`);
}
return config;
}

@@ -1,4 +0,9 @@

import { EmitterService } from '@adonisjs/core/types';
import { GetConnectionType, RedisConnectionContract, RedisConnectionsList, RedisManagerFactory } from './types/main.js';
export declare class RawRedisManager<ConnectionList extends RedisConnectionsList> {
import type { GetConnectionType, RedisConnectionsList } from './types/main.js';
/**
* Redis Manager exposes the API to manage multiple redis connections
* based upon user defined config.
*
* All connections are long-lived until they are closed explictly
*/
export default class RedisManager<ConnectionsList extends RedisConnectionsList> {
#private;

@@ -10,10 +15,5 @@ /**

activeConnections: {
[K in keyof ConnectionList]?: GetConnectionType<ConnectionList, K>;
[K in keyof ConnectionsList]?: GetConnectionType<ConnectionsList, K>;
};
/**
* A boolean to know whether health checks have been enabled on one
* or more redis connections or not.
*/
get healthChecksEnabled(): boolean;
/**
* Returns the length of active connections

@@ -23,9 +23,9 @@ */

constructor(config: {
connection: keyof ConnectionList;
connections: ConnectionList;
}, emitter: EmitterService);
connection: keyof ConnectionsList;
connections: ConnectionsList;
});
/**
* Returns redis factory for a given named connection
*/
connection<ConnectionName extends keyof ConnectionList>(connectionName?: ConnectionName): GetConnectionType<ConnectionList, ConnectionName>;
connection<ConnectionName extends keyof ConnectionsList>(connectionName?: ConnectionName): GetConnectionType<ConnectionsList, ConnectionName>;
/**

@@ -35,3 +35,3 @@ * Quit a named connection or the default connection when no

*/
quit<ConnectionName extends keyof ConnectionList>(name?: ConnectionName): Promise<void>;
quit<ConnectionName extends keyof ConnectionsList>(name?: ConnectionName): Promise<void>;
/**

@@ -41,3 +41,3 @@ * Disconnect a named connection or the default connection when no

*/
disconnect<ConnectionName extends keyof ConnectionList>(name?: ConnectionName): Promise<void>;
disconnect<ConnectionName extends keyof ConnectionsList>(name?: ConnectionName): Promise<void>;
/**

@@ -51,31 +51,2 @@ * Quit all connections

disconnectAll(): Promise<void>;
/**
* Returns the report for all connections marked for `healthChecks`
*/
report(): Promise<{
displayName: string;
health: {
healthy: boolean;
message: string;
};
meta: import("./types/main.js").HealthReportNode[];
}>;
/**
* Define a custom command using LUA script. You can run the
* registered command using the "runCommand" method.
*/
defineCommand(...args: Parameters<RedisConnectionContract['defineCommand']>): this;
/**
* Run a pre registered command
*/
runCommand(command: string, ...args: any[]): any;
}
/**
* Here we attach pubsub and ioRedis methods to the class.
*
* But we also need to inform typescript about the existence of
* these methods. So we are exporting the class with a
* casted type that has these methods.
*/
declare const RedisManager: RedisManagerFactory;
export default RedisManager;

@@ -9,7 +9,13 @@ /*

*/
import RedisConnection from './redis_connection.js';
import { pubsubMethods } from './pubsub_methods.js';
import { ioMethods } from './io_methods.js';
import RedisClusterConnection from './redis_cluster_connection.js';
export class RawRedisManager {
import { RuntimeException } from '@poppinss/utils';
import debug from './debug.js';
import RedisConnection from './connections/redis_connection.js';
import RedisClusterConnection from './connections/redis_cluster_connection.js';
/**
* Redis Manager exposes the API to manage multiple redis connections
* based upon user defined config.
*
* All connections are long-lived until they are closed explictly
*/
export default class RedisManager {
/**

@@ -20,11 +26,2 @@ * User provided config

/**
* Reference to the emitter
*/
#emitter;
/**
* An array of connections with health checks enabled, which means, we always
* create a connection for them, even when they are not used.
*/
#healthCheckConnections = [];
/**
* A copy of live connections. We avoid re-creating a new connection

@@ -35,9 +32,2 @@ * everytime and re-use connections.

/**
* A boolean to know whether health checks have been enabled on one
* or more redis connections or not.
*/
get healthChecksEnabled() {
return this.#healthCheckConnections.length > 0;
}
/**
* Returns the length of active connections

@@ -48,54 +38,11 @@ */

}
constructor(config, emitter) {
constructor(config) {
this.#config = config;
this.#emitter = emitter;
this.#healthCheckConnections = Object.keys(this.#config.connections).filter((connection) => this.#config.connections[connection].healthCheck);
}
/**
* Returns the default connection name
*/
#getDefaultConnection() {
return this.#config.connection;
}
/**
* Returns an existing connection using it's name or the
* default connection,
*/
#getExistingConnection(name) {
name = name || this.#getDefaultConnection();
return this.activeConnections[name];
}
/**
* Returns config for a given connection
*/
#getConnectionConfig(name) {
return this.#config.connections[name];
}
/**
* Forward events to the application event emitter
* for a given connection
*/
#forwardConnectionEvents(connection) {
connection.on('ready', () => {
this.#emitter.emit('redis:ready', { connection });
});
connection.on('ready', ($connection) => this.#emitter.emit('redis:ready', { connection: $connection }));
connection.on('connect', ($connection) => this.#emitter.emit('redis:connect', { connection: $connection }));
connection.on('error', (error, $connection) => this.#emitter.emit('redis:error', { error, connection: $connection }));
connection.on('node:added', ($connection, node) => this.#emitter.emit('redis:node:added', { node, connection: $connection }));
connection.on('node:removed', (node, $connection) => this.#emitter.emit('redis:node:removed', { node, connection: $connection }));
connection.on('node:error', (error, address, $connection) => this.#emitter.emit('redis:node:error', { error, address, connection: $connection }));
/**
* Stop tracking the connection after it's removed
*/
connection.on('end', ($connection) => {
delete this.activeConnections[$connection.connectionName];
this.#emitter.emit('redis:end', { connection: $connection });
});
}
/**
* Returns redis factory for a given named connection
*/
connection(connectionName) {
const name = connectionName || this.#getDefaultConnection();
const name = connectionName || this.#config.connection;
debug('resolving connection %s', name);
/**

@@ -105,2 +52,3 @@ * Return existing connection if already exists

if (this.activeConnections[name]) {
debug('reusing existing connection %s', name);
return this.activeConnections[name];

@@ -111,5 +59,5 @@ }

*/
const config = this.#getConnectionConfig(name);
const config = this.#config.connections[name];
if (!config) {
throw new Error(`Redis connection "${name.toString()}" is not defined`);
throw new RuntimeException(`Redis connection "${name.toString()}" is not defined`);
}

@@ -119,2 +67,3 @@ /**

*/
debug('creating new connection %s', name);
const connection = 'clusters' in config

@@ -124,9 +73,12 @@ ? new RedisClusterConnection(name, config)

/**
* Remove connection from the list of tracked connections
*/
connection.on('end', ($connection) => {
debug('%s connection closed. Removing from tracked connections list', name);
delete this.activeConnections[$connection.connectionName];
});
/**
* Cache the connection so that we can re-use it later
*/
this.activeConnections[name] = connection;
/**
* Forward ioredis events to the application event emitter
*/
this.#forwardConnectionEvents(connection);
return connection;

@@ -139,3 +91,3 @@ }

async quit(name) {
const connection = this.#getExistingConnection(name);
const connection = this.activeConnections[name || this.#config.connection];
if (!connection) {

@@ -151,3 +103,3 @@ return;

async disconnect(name) {
const connection = this.#getExistingConnection(name);
const connection = this.activeConnections[name || this.#config.connection];
if (!connection) {

@@ -170,52 +122,2 @@ return;

}
/**
* Returns the report for all connections marked for `healthChecks`
*/
async report() {
const reports = await Promise.all(this.#healthCheckConnections.map((connection) => this.connection(connection).getReport(true)));
const healthy = !reports.find((report) => !!report.error);
return {
displayName: 'Redis',
health: {
healthy,
message: healthy
? 'All connections are healthy'
: 'One or more redis connections are not healthy',
},
meta: reports,
};
}
/**
* Define a custom command using LUA script. You can run the
* registered command using the "runCommand" method.
*/
defineCommand(...args) {
this.connection().defineCommand(...args);
return this;
}
/**
* Run a pre registered command
*/
runCommand(command, ...args) {
return this.connection().runCommand(command, ...args);
}
}
/**
* Here we attach pubsub and ioRedis methods to the class.
*
* But we also need to inform typescript about the existence of
* these methods. So we are exporting the class with a
* casted type that has these methods.
*/
const RedisManager = RawRedisManager;
pubsubMethods.forEach((method) => {
RedisManager.prototype[method] = function redisManagerProxyFn(...args) {
return this.connection()[method](...args);
};
});
ioMethods.forEach((method) => {
RedisManager.prototype[method] = function redisManagerProxyFn(...args) {
return this.connection()[method](...args);
};
});
export default RedisManager;

@@ -1,3 +0,2 @@

import type { RedisClusterConnectionContract, RedisConnectionContract, RedisService } from './main.js';
import { Redis } from 'ioredis';
import type { RedisService } from './main.js';
declare module '@adonisjs/core/types' {

@@ -7,30 +6,2 @@ interface ContainerBindings {

}
interface EventsList {
'redis:ready': {
connection: RedisClusterConnectionContract | RedisConnectionContract;
};
'redis:connect': {
connection: RedisClusterConnectionContract | RedisConnectionContract;
};
'redis:error': {
error: any;
connection: RedisClusterConnectionContract | RedisConnectionContract;
};
'redis:end': {
connection: RedisClusterConnectionContract | RedisConnectionContract;
};
'redis:node:added': {
connection: RedisClusterConnectionContract;
node: Redis;
};
'redis:node:removed': {
connection: RedisClusterConnectionContract;
node: Redis;
};
'redis:node:error': {
error: any;
connection: RedisClusterConnectionContract;
address: string;
};
}
}
/// <reference types="@types/node" resolution-mode="require"/>
import { EventEmitter } from 'node:events';
import { Redis as IoRedis, RedisOptions, ClusterOptions, Cluster } from 'ioredis';
import { RawRedisClusterConnection } from '../redis_cluster_connection.js';
import { AbstractConnection } from '../abstract_connection.js';
import { RawRedisConnection } from '../redis_connection.js';
import { Emitter } from '@adonisjs/core/events';
import { RawRedisManager } from '../redis_manager.js';
import type { EventEmitter } from 'node:events';
import type { Redis as IoRedis, RedisOptions, ClusterOptions } from 'ioredis';
import type RedisManager from '../redis_manager.js';
import type RedisConnection from '../connections/redis_connection.js';
import type RedisClusterConnection from '../connections/redis_cluster_connection.js';
/**
* Pubsub subscriber
* PubSub subscriber
*/

@@ -15,13 +13,2 @@ export type PubSubChannelHandler<T extends any = string> = (data: T) => Promise<void> | void;

/**
* Redis pub/sub methods
*/
export interface RedisPubSubContract {
publish(channel: string, message: string, callback: (error: Error | null, count: number) => void): void;
publish(channel: string, message: string): Promise<number>;
subscribe(channel: string, handler: PubSubChannelHandler | string): void;
psubscribe(pattern: string, handler: PubSubPatternHandler | string): void;
unsubscribe(channel: string): void;
punsubscribe(pattern: string): void;
}
/**
* Shape of the report node for the redis connection report

@@ -37,29 +24,16 @@ */

* List of commands on the IORedis. We omit their internal events and pub/sub
* handlers, since we our own.
* handlers, since we have our own.
*/
export type IORedisCommands = Omit<IoRedis, 'Promise' | 'status' | 'connect' | 'disconnect' | 'duplicate' | 'subscribe' | 'unsubscribe' | 'psubscribe' | 'punsubscribe' | 'quit' | 'publish' | keyof EventEmitter>;
export type IORedisCommands = Omit<IoRedis, 'Promise' | 'status' | 'connect' | 'disconnect' | 'duplicate' | 'subscribe' | 'unsubscribe' | 'psubscribe' | 'punsubscribe' | 'quit' | 'publish' | 'defineCommand' | keyof EventEmitter>;
/**
* A connection. Can be a cluster or a single connection
* Configuration accepted by the redis connection. It is same
* as ioredis, except the number can be a string as well
*/
export type Connection = RedisClusterConnectionContract | RedisConnectionContract;
/**
* Shape of the connections list
*/
export type RedisConnectionsList = Record<string, RedisConnectionConfig | RedisClusterConfig>;
/**
* Extract the connection type ( either Cluster or single ) from
* a given RedisConnectionsList
*/
export type GetConnectionType<ConnectionsList extends RedisConnectionsList, T extends keyof ConnectionsList> = ConnectionsList[T] extends RedisClusterConfig ? RedisClusterConnectionContract : RedisConnectionContract;
/**
* Shape of standard Redis connection config
*/
export type RedisConnectionConfig = Omit<RedisOptions, 'port'> & {
healthCheck?: boolean;
port?: string | number;
};
/**
* Shape of cluster config
* Configuration accepted by the RedisClusterConnectionConfig.
*/
export type RedisClusterConfig = {
export type RedisClusterConnectionConfig = {
clusters: {

@@ -73,41 +47,15 @@ host: string;

/**
* Since we are dynamically addind methods to the RedisClusterConnection
* RedisConnection and RedisManager classes prototypes, we need to tell
* typescript about it. So the below types represents theses classes with
* all the methods added
* A connection can be a cluster or a single connection
*/
export type Connection = RedisClusterConnection | RedisConnection;
/**
* Type of RedisClusterConnection with dynamically added methods
* A list of multiple connections defined inside the user
* config file
*/
export type RedisClusterConnectionContract = RawRedisClusterConnection & AbstractConnection<Cluster> & IORedisCommands & RedisPubSubContract;
export type RedisConnectionsList = Record<string, RedisConnectionConfig | RedisClusterConnectionConfig>;
/**
* Type of RedisConnection with dynamically added methods
* Returns the connection class to be used based upon the config
*/
export type RedisConnectionContract = RawRedisConnection & AbstractConnection<IoRedis> & IORedisCommands & RedisPubSubContract;
export type GetConnectionType<ConnectionsList extends RedisConnectionsList, T extends keyof ConnectionsList> = ConnectionsList[T] extends RedisClusterConnectionConfig ? RedisClusterConnection : RedisConnection;
/**
* Type of RedisManager with dynamically added methods
*/
export type RedisManagerContract<ConnectionList extends RedisConnectionsList> = RawRedisManager<ConnectionList> & IORedisCommands & RedisPubSubContract;
/**
* Factory for creating RedisClusterConnection
*/
export type RedisClusterConnectionFactory = {
new (connectionName: string, config: RedisClusterConfig): RedisClusterConnectionContract;
};
/**
* Factory for creating RedisConnection
*/
export type RedisConnectionFactory = {
new (connectionName: string, config: RedisConnectionConfig): RedisConnectionContract;
};
/**
* Factory for creating RedisManager
*/
export type RedisManagerFactory = {
new <ConnectionList extends RedisConnectionsList>(config: {
connection: keyof ConnectionList;
connections: ConnectionList;
}, emitter: Emitter<any>): RedisManagerContract<ConnectionList>;
};
/**
* List of connections inferred from user config

@@ -122,5 +70,5 @@ */

* Redis service is a singleton redis instance registered
* to the container
* with the container based upon user defined config
*/
export interface RedisService extends RedisManagerContract<RedisConnections extends RedisConnectionsList ? RedisConnections : never> {
export interface RedisService extends RedisManager<RedisConnections extends RedisConnectionsList ? RedisConnections : never> {
}
{
"name": "@adonisjs/redis",
"description": "AdonisJS addon for Redis",
"version": "8.0.0-3",
"engines": {
"node": ">=18.16.0"
},
"version": "8.0.0-4",
"type": "module",
"main": "build/index.js",
"type": "module",
"files": [

@@ -23,2 +20,5 @@ "build/configure.js",

],
"engines": {
"node": ">=18.16.0"
},
"exports": {

@@ -35,3 +35,3 @@ ".": "./build/index.js",

"test:docker": "docker-compose -f docker-compose.ci.yml run --rm tests",
"quick:test": "node --enable-source-maps --loader=ts-node/esm ./bin/test.ts",
"quick:test": "node --enable-source-maps --loader=ts-node/esm ./bin/test.js",
"clean": "del-cli build",

@@ -41,3 +41,3 @@ "copy:templates": "copyfiles \"stubs/**/**/*.stub\" build",

"build": "npm run compile",
"release": "np --message=\"chore(release): %s\"",
"release": "np",
"version": "npm run build",

@@ -50,6 +50,8 @@ "prepublishOnly": "npm run build",

"devDependencies": {
"@adonisjs/core": "^6.1.5-8",
"@adonisjs/core": "^6.1.5-12",
"@adonisjs/eslint-config": "^1.1.8",
"@adonisjs/prettier-config": "^1.1.8",
"@adonisjs/tsconfig": "^1.1.8",
"@commitlint/cli": "^17.6.7",
"@commitlint/config-conventional": "^17.6.7",
"@japa/assert": "2.0.0-1",

@@ -69,2 +71,3 @@ "@japa/expect-type": "2.0.0-0",

"np": "^8.0.4",
"p-event": "^6.0.0",
"prettier": "^3.0.0",

@@ -79,3 +82,3 @@ "ts-node": "^10.9.1",

"peerDependencies": {
"@adonisjs/core": "^6.1.5-8"
"@adonisjs/core": "^6.1.5-12"
},

@@ -121,5 +124,6 @@ "author": "virk,adonisjs",

"exclude": [
"tests/**"
"tests/**",
"src/repl_bindings.ts"
]
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc