Skip to content

Conversation

@agcty
Copy link

@agcty agcty commented Oct 18, 2025

This PR adds the NeonRole resource for managing Postgres database roles
(users) within Neon branches.

Summary

The NeonRole resource enables programmatic management of database users
with automatic password generation, secret encryption, and full lifecycle
support.

Changes

Core Implementation

  • alchemy/src/neon/role.ts - Complete resource implementation with:
    • Automatic password generation and Secret encryption
    • Support for no-login roles via no_login flag
    • Full lifecycle management (create, update, delete)
    • Integration with NeonProject and NeonBranch resources
    • Proper error handling and 404 tolerance on deletion

Tests

  • alchemy/test/neon/role.test.ts - Comprehensive test suite:
    • ✅ Basic role creation with auto-generated password
    • ✅ Protected role creation (no-login)
    • ✅ Custom role names
    • ✅ Integration with Branch resources
    • All 4 tests passing with full cleanup verification

Documentation

  • alchemy-web/src/content/docs/providers/neon/role.md - Complete user
    documentation with 8 usage examples
  • alchemy-web/src/content/docs/providers/neon/index.md - Updated
    provider overview to include Role resource
  • alchemy-web/src/content/docs/providers/neon/branch.md - Added
    Branch documentation for completeness

Usage Example

import { NeonProject, NeonBranch, NeonRole } from "alchemy/neon";

const project = await NeonProject("db", {
  name: "My Database",
});

const branch = await NeonBranch("main", {
  project,
  endpoints: [{ type: "read_write" }],
});

// Create a role with automatic password generation
const role = await NeonRole("app-user", {
  project,
  branch,
});

console.log("Username:", role.name);
console.log("Password:", role.password.unencrypted);

Key Features

- 🔐 Automatic password encryption using Alchemy's Secret type
- 🚫 Protected roles for ownership without login access
- 🔄 Full lifecycle support with proper immutability handling
- 🧪 100% test coverage with real API integration tests
- 📚 Comprehensive documentation with multiple examples

Testing

All tests pass successfully against the live Neon API:

bun vitest alchemy/test/neon/role.test.ts --run

 alchemy/test/neon/role.test.ts (4 tests)
   NeonRole Resource > create and delete neon role
   NeonRole Resource > create no-login role
   NeonRole Resource > role with custom name
   NeonRole Resource > role with branch resource

Test Files  1 passed (1)
Tests  4 passed (4)

API Reference

- https://api-docs.neon.tech/reference/createprojectbranchrole
- https://api-docs.neon.tech/reference/getprojectbranchrole
- https://api-docs.neon.tech/reference/deleteprojectbranchrole

Checklist

- Resource implementation following Alchemy conventions
- Full test coverage with passing tests
- User documentation with examples
- Provider overview updated
- Code formatted with Biome
- No TypeScript errors
- Secret encryption for sensitive data
- Proper lifecycle management (create, update, delete)

JacobMGEvans and others added 6 commits October 9, 2025 20:13
…1093)

* test(cloudflare): comprehensive dead letter queue tests

Adds comprehensive test coverage for the dead letter queue feature in
QueueConsumer, which was fixed in PR alchemy-run#1092.

Tests cover:
- DLQ with string reference (queue name)
- DLQ with Queue object reference
- Updating consumer to add DLQ
- Worker eventSources with DLQ settings

Also includes the missing fix for build-worker-options.ts to properly
handle deadLetterQueue in Miniflare local development, and updates
queue-consumer.ts to preserve DLQ settings from props when the API
doesn't return them in the response.

Related: alchemy-run#1092

* test(cloudflare): comprehensive dead letter queue tests

Adds comprehensive test coverage for the dead letter queue feature in
QueueConsumer, which was fixed in PR alchemy-run#1092.

Tests cover:
- DLQ with string reference (queue name)
- DLQ with Queue object reference
- Updating consumer to add DLQ
- Worker eventSources with DLQ settings

Also includes the missing fix for build-worker-options.ts to properly
handle deadLetterQueue in Miniflare local development, and updates
queue-consumer.ts to preserve DLQ settings from props when the API
doesn't return them in the response.

Related: alchemy-run#1092

* Improved the DLQ test and fixed the typings for being root not in settings

* Removed DLQ response, since Cloudflare missed that DX in the API we will callback to the props instead for something to be there for the user

---------

Co-authored-by: Sam Goodwin <[email protected]>
Add NeonRole resource for managing Postgres database roles (users) in Neon branches:

- Resource implementation with automatic password generation
- Support for protected (no-login) roles
- Secret encryption for passwords
- Full lifecycle management (create, update, delete)
- Comprehensive test suite (4 test cases, all passing)
- User-facing documentation with examples
- Provider overview docs with Role included

All tests passing with 100% success rate.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Address reviewer feedback about confusing naming:
- Renamed `protected` property to `noLogin` in NeonRole
- Updated all tests to use `noLogin` instead of `protected`
- Updated documentation to reflect the change
- All 4 tests still passing

The `protected` name was confusing because:
- In NeonBranch, `protected` means "prevent deletion"
- In NeonRole, it was being used for "cannot login"

Now `noLogin` clearly indicates the role cannot be used for login,
which maps directly to the Neon API's `no_login` parameter.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Update comment to reference noLogin instead of protected
Comment on lines +150 to +163

// Create temporary preview branch that expires in 7 days
const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);

const preview = await NeonBranch(`preview-${prNumber}`, {
project,
name: `preview-pr-${prNumber}`,
parentBranch: project.branch.id,
expiresAt: expiresAt.toISOString(),
endpoints: [
{ type: "read_write" }
],
});

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does it need to expire, if this runs in a PR environment it should be torn down once the PR is merged. If a pr is open for more than 7 days this could cause problems no?

Copy link
Author

@agcty agcty Oct 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess with alchemy there isn't really a use case for expiresAt (maybe there is?) but the api supports it, your call if it should be included or not.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also this was already part of the source code, this PR just fills adds a role + fills the branch documentation gap

agcty and others added 4 commits October 18, 2025 20:43
Address code review feedback from @Mkassabov and @sam-goodwin:
- Changed from throwing an error to calling this.replace() when role name changes
- Consistent with how project/branch immutable properties are handled
- Allows Alchemy to properly replace the resource instead of failing

All tests passing (4/4).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Address code review feedback from @Mkassabov:
- Change password type from Secret to Secret<string>
- Remove markdown headings from @example blocks
- Keep only the TypeScript code in examples

All tests passing (4/4).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Add connectionUris property to NeonRole output type
- Rename RoleData → NeonRoleData for consistent naming with NeonConnectionUri
- Create createConnectionUri helper to build connection URIs from components
- Generate connection URIs during role creation from branch endpoints/databases
- Update NeonRole tests to verify connectionUris structure

This makes NeonRole consistent with NeonBranch and NeonProject, which both
provide connection URIs. The URIs are generated at creation time and persisted
in state, matching the pattern used by other Neon resources.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@coderabbitai
Copy link

coderabbitai bot commented Oct 20, 2025

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants