connect-pg-simple

repository·main·Indexed 42 days ago

https://github.com/voxpelli/node-connect-pg-simple

A minimal PostgreSQL session store for Connect and Express, designed for use with the express-session middleware. Version 10.0.0 requires PostgreSQL 9.5 or above. It supports various connection methods including pg.Pool, pg-promise, connection strings, and configuration objects. Features include automatic session table creation, customizable TTL, and configurable session pruning intervals to manage expired sessions.

Tokens
2.2K
Snippets
5
Records
10
Agent score
4%

What's inside connect-pg-simple

  1. Set up the PostgreSQL session table

    main

    After installation, you must create the session table in your database. You have three options:

    1. Manual SQL: Run the table.sql file provided in the module using psql:

      psql mydatabase < node_modules/connect-pg-simple/table.sql

      Alternatively, run the file via a GUI like pgAdminIII.

    2. Automatic Creation: Set the createTableIfMissing: true option in the store configuration to let the module create the table automatically if it doesn't exist.

    psql mydatabase < node_modules/connect-pg-simple/table.sql
  2. Configure database connections

    main

    The following connection options are evaluated in order. The first one defined is used, and others are ignored:

    • pool: (Recommended) A connection pool object compatible with pg.Pool.
    • pgPromise: A database object from pg-promise.
    • conObject: A PostgreSQL Pool connection object. If used, the module creates a new pool for you.
    • conString: A PostgreSQL connection string (e.g., postgres://user:password@host:5432/database). If no other method is specified, it falls back to the DATABASE_URL environment variable (common on platforms like Heroku).
  3. How PGStore manages database connections

    main

    The PGStore manages its own PostgreSQL connection pool unless you explicitly provide one.

    1. Managed Mode: If you do not provide pool or pgPromise, the store creates a new pg.Pool using conString or conObject. In this mode, calling store.close() will terminate the connection pool.
    2. External Mode: If you provide an existing pool or pgPromise instance, the store uses the existing connection(s) and will not close them when store.close() is called. This is the recommended pattern for applications that already manage a global database pool.
  4. Configure session behavior and pruning

    main

    Use these options to customize how sessions are stored and cleaned up:

    • ttl: Time to live for the session in seconds. Defaults to the cookie maxAge if defined, otherwise defaults to one day.
    • createTableIfMissing: Boolean. If true, creates the session table if it is missing. Defaults to false.
    • disableTouch: Boolean. If true, disables updating the TTL in the database when using touch. Defaults to false.
    • schemaName: The Postgres schema where the session table resides.
    • tableName: The name of the session table (defaults to session).
    • pruneSessionInterval: Delay in seconds for pruning expired sessions. Default is 900 (15 minutes). If set to false, automatic pruning is disabled.
    • pruneRandomizedInterval: Boolean. If false, the exact pruneSessionInterval is used without randomization. Can also be a function taking a numeric delay and returning a modified one.
    • errorLog: Method used to log errors when they cannot be returned to a callback. Defaults to console.error().
  5. Initialize PGStore for Express sessions

    main

    To use connect-pg-simple as a session store in an Express application, import the module and pass your session object to the factory function. This returns the PGStore constructor, which you then instantiate with your database configuration options.

    const session = require('express-session');
    const connectPgSimple = require('connect-pg-simple');
    
    const PGStore = connectPgSimple(session);
    
    app.use(session({
      store: new PGStore({
        conString: 'postgres://user:pass@localhost:5432/db'
      }),
      secret: 'your-secret',
      resave: false,
      saveUninitialized: false
    }));
  6. Use connect-pg-simple with express-session

    main

    To use connect-pg-simple, pass the session object from express-session into the connect-pg-simple constructor. This creates a store instance that you then pass to the store option in session().

    const session = require('express-session');
    const pgSession = require('connect-pg-simple')(session);
    
    app.use(session({
      store: new pgSession({
        // Insert connect-pg-simple options here
      }),
      secret: process.env.FOO_COOKIE_SECRET,
      resave: false,
      cookie: { maxAge: 30 * 24 * 60 * 60 * 1000 } // 30 days
    }));
  7. Manage the session store lifecycle

    main

    The session store instance provides the following methods for lifecycle management:

    • close(): Returns a Promise that resolves when the database connection is shut down. Use this for graceful shutdowns if the module created its own connection pool.
    • pruneSessions([callback(err)]): Manually triggers the pruning of old sessions. This is useful if pruneSessionInterval was set to false to gain manual control over pruning.
  8. Configure PGStore options

    main

    When instantiating new PGStore(options), you can provide several configuration settings to control how sessions are stored and managed in PostgreSQL:

    Database Connection

    • pool: An existing import('pg').Pool instance. If provided, the store will not manage the connection lifecycle.
    • pgPromise: An existing and configured instance of pg-promise. Must have a .any() method.
    • conString: A PostgreSQL connection string. If provided and conObject is missing, it will be used to create a new pg.Pool. Defaults to the DATABASE_URL environment variable.
    • conObject: A configuration object for a new pg.Pool (e.g., { host: 'localhost', user: 'postgres' }).

    Table Configuration

    • schemaName: The name of the PostgreSQL schema to use. If not provided, it defaults to the public schema.
    • tableName: The name of the session table. Defaults to 'session'.
    • createTableIfMissing: A boolean indicating whether the store should automatically create the session table if it does not exist. Defaults to false (implied by !!options.createTableIfMissing).

    Session Management

    • ttl: Time-to-live for sessions in seconds. If not set, it defaults to one day (86400 seconds).
    • disableTouch: If true, the touch method will do nothing, preventing session expiration updates on every request.
    • errorLog: A function used to log errors. Defaults to console.error.

    Pruning (Garbage Collection)

    • pruneSessionInterval: The interval in seconds between automatic session pruning runs. Defaults to 900 seconds (15 minutes). Set to false to disable pruning.
    • pruneSessionRandomizedInterval: A function (delay: number) => number used to randomize the pruning interval. This helps prevent multiple application instances from hitting the database for pruning at the exact same time. If not provided, it defaults to a randomizer that results in an interval between 50% and 150% of the specified pruneSessionInterval.
  9. Use PGStore public API methods

    main

    The PGStore class provides several public methods for manual session management, typically used by the underlying session middleware. Most methods accept a callback function (err, result) => void.

    // Example of manual usage
    const store = new PGStore({ conString: '...' });
    
    // Get a session
    store.get('session-id', (err, session) => {
      if (err) console.error(err);
      console.log(session);
    });
    
    // Set/Create a session
    store.set('session-id', { user: 'alice' }, (err) => {
      if (err) console.error(err);
    });
    
    // Destroy a session
    store.destroy('session-id', (err) => {
      if (err) console.error(err);
    });
    
    // Touch a session (updates expiration)
    store.touch('session-id', { user: 'alice' }, (err) => {
      if (err) console.error(err);
    });
    
    // Manually trigger pruning
    store.pruneSessions((err) => {
      if (err) console.error(err);
    });
    
    // Close the store and connection pool
    await store.close();