{"id":17329,"library":"pg-people","title":"Hapi PostgreSQL People Plugin","description":"pg-people is a Hapi plugin designed to manage 'people' and 'organisations' data within a PostgreSQL database. As of version 2.3.0, it provides a structured approach for user management, including adding users, updating passwords, retrieving user and organization details, and toggling account activity. It integrates with Hapi by exposing its functions via the `request.server.pg.people` and `request.server.pg.organisations` objects after registration. The plugin automatically creates necessary tables (`people`, `organisations`, `tags_organisations`) if they don't exist, and offers an option to reset tables with initial data. Its release cadence appears tied to the Hapi ecosystem, targeting older Node.js environments (engine `^6.5.0`). A key differentiator is its seamless integration with Hapi's request lifecycle, extending `request.pg` which implies a reliance on another Hapi plugin to establish the underlying PostgreSQL connection.","status":"maintenance","version":"2.3.0","language":"javascript","source_language":"en","source_url":"https://github.com/postgres-plugin/people","tags":["javascript"],"install":[{"cmd":"npm install pg-people","lang":"bash","label":"npm"},{"cmd":"yarn add pg-people","lang":"bash","label":"yarn"},{"cmd":"pnpm add pg-people","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency for integration as a Hapi server plugin. The plugin decorates the Hapi server and request objects.","package":"hapi","optional":false},{"reason":"Runtime dependency for interacting with PostgreSQL. The plugin expects an underlying PostgreSQL connection, likely provided by another Hapi plugin that exposes a 'pg' client.","package":"pg","optional":false},{"reason":"Used internally for standardizing error responses, such as `Boom.notFound` for 404 errors.","package":"boom","optional":false}],"imports":[{"note":"The package uses CommonJS `module.exports`, consistent with its Node.js 6.5.0 engine requirement. It exports the plugin definition directly.","wrong":"import PgPeople from 'pg-people'; // Not directly compatible with Node 6.5 and CommonJS export","symbol":"PgPeoplePlugin","correct":"const PgPeople = require('pg-people');\n// then register with Hapi server.register({ plugin: PgPeople, options: ... })"},{"note":"Functions are exposed on the Hapi `request` or `server` objects after the plugin is registered, usually under a `pg.people` or `pg.organisations` namespace.","wrong":"import { getAllPeople } from 'pg-people'; // Functions are exposed via Hapi's request/server object, not direct imports.","symbol":"getAllPeople","correct":"await request.server.pg.people.getAllPeople();"},{"note":"As a Hapi plugin, its core functionality is accessed through the Hapi `request` or `server` context, specifically `request.server.pg.people` for user operations.","wrong":"const { add } = require('pg-people'); // Functions are not directly importable from the package.","symbol":"add","correct":"await request.server.pg.people.add(userObj, cb);"}],"quickstart":{"code":"const Hapi = require('@hapi/hapi');\nconst PgPeople = require('pg-people');\n\nconst init = async () => {\n    const server = Hapi.server({\n        port: 3000,\n        host: 'localhost'\n    });\n\n    // In a real application, you would register a Hapi plugin for PostgreSQL\n    // connectivity, e.g., hapi-pg or hapi-pg-promise, to provide `request.pg`.\n    // For this quickstart, we'll mock `request.pg` to simulate its presence.\n    await server.register({\n        plugin: {\n            name: 'mock-pg-connector',\n            version: '1.0.0',\n            register: async function (serverInstance) {\n                serverInstance.decorate('request', 'pg', {\n                    query: async (sql, params) => {\n                        console.log('Mock PG query:', sql, params);\n                        if (sql.includes('SELECT') && sql.includes('people')) {\n                            return { rows: [{ id: 1, first_name: 'Mock', last_name: 'Person', email: 'mock@example.com' }] };\n                        }\n                        return { rows: [] };\n                    }\n                });\n            }\n        }\n    });\n\n    await server.register({\n        plugin: PgPeople,\n        options: {\n            // WARNING: `reset: true` will clear existing data in `people` and `organisations` tables.\n            // Use with extreme caution, especially in production environments.\n            reset: false, \n            people: []\n        }\n    });\n\n    server.route({\n        method: 'GET',\n        path: '/people',\n        handler: async (request, h) => {\n            try {\n                // Accessing functions via request.server.pg.people as shown in README\n                const people = await request.server.pg.people.getAllPeople();\n                return h.response(people).code(200);\n            } catch (error) {\n                console.error('Error fetching people:', error.message);\n                return h.response({ message: 'Failed to fetch people' }).code(500);\n            }\n        }\n    });\n\n    await server.start();\n    console.log(`Server running on ${server.info.uri}`);\n};\n\nprocess.on('unhandledRejection', (err) => {\n    console.error(err);\n    process.exit(1);\n});\n\ninit();","lang":"javascript","description":"Sets up a basic Hapi server, registers a mock PostgreSQL connector, then registers `pg-people` and defines a route to demonstrate fetching all people from the database. This example highlights the typical Hapi plugin registration and function access pattern."},"warnings":[{"fix":"Always set `reset: false` in production environments unless a full data reset is intentionally desired. Carefully review the initial data provided in the options.","message":"The `reset: true` option in the plugin configuration will truncate and re-populate the `people`, `organisations`, and `tags_organisations` tables with the data provided in `people`, `organisations`, and `tags_orgs` options. This will lead to irreversible data loss if used carelessly.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Ensure a compatible Hapi PostgreSQL connection plugin is registered and configured *before* `pg-people` to expose the `request.pg` object.","message":"This plugin implicitly relies on an existing PostgreSQL client being exposed on the Hapi `request.pg` object. It does not provide its own database connection mechanism. Without another Hapi plugin (e.g., `hapi-pg` or `hapi-pg-promise`) that sets up `request.pg`, the plugin will fail.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Test thoroughly in your target Node.js and Hapi environment. Consider using a Node.js version closer to 6.x or carefully reviewing the package's dependencies and source for compatibility with newer environments. Migration to `@hapi/hapi` might require code adjustments.","message":"The `engines.node` specification (`^6.5.0`) in its `package.json` suggests that this package might not be fully compatible with recent Node.js versions (e.g., Node.js 14+ or 16+ which are LTS) or modern Hapi versions (@hapi/hapi v17+). This could lead to runtime errors or unexpected behavior.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Implement robust error handling and check for empty array responses when interacting with these functions to correctly manage scenarios where an entity is not found.","message":"Several exposed functions, such as `edit`, `toggleActive` (for both people and organizations), and `getBy` for `id`, return a `Boom.notFound, 404 error` (or simply an empty array for `edit` under certain conditions) if the specified `userId` or `orgId` does not exist. Developers must handle these specific error types or empty array responses.","severity":"gotcha","affected_versions":">=2.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Verify that `server.register(PgPeople)` is called correctly and that a Hapi plugin providing `request.pg` (e.g., `hapi-pg`) is registered and configured *before* `pg-people`.","cause":"The `pg-people` plugin was either not registered with the Hapi server, or the `request.pg` object (from a separate PostgreSQL connection plugin) was not available when `pg-people` attempted to decorate it.","error":"TypeError: Cannot read properties of undefined (reading 'people')"},{"fix":"Ensure your PostgreSQL connection plugin (which populates `request.pg`) is configured with the correct username, password, host, and database name, and that the user has appropriate database privileges.","cause":"The PostgreSQL database credentials used by the underlying `request.pg` connection are incorrect, or the specified database user does not have the necessary permissions.","error":"Error: Role \"your_user\" does not exist"},{"fix":"Check your database logs for table creation errors during Hapi server startup. If safe to do so (e.g., in a development environment), you might try running the plugin with `reset: true` (after backing up data) to force table recreation. Ensure no external process modifies the tables `people`, `organisations`, `tags_organisations`.","cause":"The plugin's automatic table creation might have failed, or the database schema expected by `pg-people` has been altered or is out of sync with the plugin's internal expectations.","error":"Error: Column 'column_name' does not exist"},{"fix":"Before performing update or toggle operations, verify the existence of the `userId` or `orgId` using a retrieval method. Implement client-side validation or appropriate error handling for non-existent entities.","cause":"An operation like `edit`, `toggleActive`, or `getBy(id, ...)` was attempted with a `userId` or `orgId` that does not exist in the database.","error":"Boom.notFound, 404 error"}],"ecosystem":"npm","meta_description":null}