Skip to content

Conversation

jog1t
Copy link
Collaborator

@jog1t jog1t commented Aug 14, 2025

Closes FRONT-764

TL;DR

Updated the Drizzle example to implement a functional chat application with message storage and retrieval.

What changed?

  • Fixed the README to correctly reference Drizzle ORM instead of Hono
  • Replaced the users table schema with a messages table for storing chat messages
  • Implemented actor functionality with sendMessage and getHistory actions
  • Added SQL migration files for the messages table structure
  • Updated package.json to use the SQL loader and added actor dependency
  • Enabled the server implementation to run the registry

How to test?

  1. Clone the repository
  2. Navigate to the example directory: cd rivetkit/examples/drizzle
  3. Install dependencies: pnpm install
  4. Start the development server: pnpm run dev
  5. Open the Rivet Studio at https://studio.rivet.gg/ to interact with the chat application

Why make this change?

This change provides a complete, working example of Drizzle ORM integration with RivetKit, demonstrating how to:

  • Define and migrate database schemas
  • Implement actor-based state management
  • Create actions for sending and retrieving messages
  • Broadcast events to connected clients

The example now serves as a practical reference for developers looking to build real-time applications with persistent storage using RivetKit and Drizzle.

Copy link

claude bot commented Aug 14, 2025

Claude finished @jog1t's task —— View job


Reviewing Drizzle Example PR

I've completed my review of the Drizzle example implementation. Here's my comprehensive feedback:

Todo List:

  • Read project guidelines from CLAUDE.md
  • Analyze all changed files in the Drizzle example
  • Review code quality and best practices
  • Check for potential bugs and security issues
  • Evaluate performance considerations
  • Assess test coverage
  • Provide comprehensive feedback

Review Feedback

Positive Aspects

  1. Project Structure Compliance: The example follows RivetKit's structure guidelines well
  2. Clean Database Schema: Simple, well-defined message table schema in src/db/schema.ts:3-8
  3. Proper Migration Setup: Drizzle migrations are correctly configured
  4. Actor Implementation: Good use of RivetKit's actor pattern with database integration

🔧 Issues Found

Critical Issues

  1. Incorrect Package Name (examples/drizzle/package.json:2)

    • Current: "name": "example-sqlite"
    • Should be: "name": "example-drizzle" per CLAUDE.md guidelines
  2. Missing Database Query Error Handling (src/registry.ts:15, src/registry.ts:21-26)

    • Database operations lack error handling
    • Could cause actor crashes if DB operations fail

Best Practice Issues

  1. README Title Inconsistency (examples/drizzle/README.md:1)

    • Title should follow the pattern: {human readable title} for RivetKit
    • Current: "Drizzle Integration for RivetKit"
    • Consider: "Database Integration with Drizzle for RivetKit"
  2. Missing JSDoc Comments (src/registry.ts:12, src/registry.ts:21)

    • Public actor actions lack documentation
    • Should document parameters and return types
  3. Installation Instructions (examples/drizzle/README.md:20)

    • Uses pnpm install instead of npm install as shown in CLAUDE.md template
    • Should be consistent with the template

Code Quality Issues

  1. Missing Input Validation (src/registry.ts:12)

    • sendMessage action doesn't validate sender or text parameters
    • Should use zod for runtime validation per guidelines
  2. Magic Number (src/registry.ts:26)

    • Hard-coded limit of 100 messages
    • Should be a named constant

🔒 Security Considerations

  • Text Input Sanitization: The text and sender fields in sendMessage are stored without validation
  • SQL Injection: While Drizzle ORM provides protection, explicit input validation would be safer

Performance Considerations

  • Database Indexing: Consider adding an index on the timestamp column for better query performance
  • Message Limit: The 100-message limit in getHistory is reasonable for this example

🧪 Test Coverage

  • Missing Tests: No test files included in this example
  • Recommendation: Add basic tests for actor actions and database operations

📝 Suggested Improvements

  1. Add Input Validation:

    import { z } from "zod";
    
    const messageSchema = z.object({
      sender: z.string().min(1).max(50),
      text: z.string().min(1).max(1000)
    });
  2. Add Error Handling:

    sendMessage: async (c, sender: string, text: string) => {
      try {
        // validation and insertion
      } catch (error) {
        logger().error("failed to send message", { error });
        throw new InternalError("Failed to send message");
      }
    }
  3. Add Database Indexes (in schema):

    timestamp: int().notNull(),
    }, (table) => ({
      timestampIdx: index("timestamp_idx").on(table.timestamp)
    }));

🎯 Overall Assessment

This is a solid foundation for a Drizzle integration example, but needs refinement to meet RivetKit's standards. The core functionality is correct, but error handling, validation, and documentation need improvement.

Priority Fixes:

  1. Fix package name
  2. Add error handling to database operations
  3. Add input validation
  4. Update README to match template

Copy link
Collaborator Author

jog1t commented Aug 14, 2025

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • merge queue - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@jog1t jog1t requested a review from NathanFlurry August 14, 2025 18:54
@jog1t jog1t self-assigned this Aug 14, 2025
@jog1t jog1t marked this pull request as ready for review August 14, 2025 18:54
Copy link

linear bot commented Aug 14, 2025

@jog1t jog1t force-pushed the 08-14-feat_examples_add_drizzle_example branch from eb378c1 to bc35a94 Compare August 14, 2025 20:36
Copy link

claude bot commented Aug 14, 2025

Claude finished @jog1t's task —— View job


Reviewing Drizzle Example PR

I've completed my review of the Drizzle example implementation. Here's my comprehensive feedback:

Todo List:

  • Read project guidelines from CLAUDE.md
  • Analyze all changed files in the Drizzle example
  • Review code quality and best practices
  • Check for potential bugs and security issues
  • Evaluate performance considerations
  • Assess test coverage
  • Provide comprehensive feedback

Review Feedback

Positive Aspects

  1. Project Structure Compliance: The example follows RivetKit's structure guidelines well
  2. Clean Database Schema: Simple, well-defined message table schema in src/db/schema.ts:3-8
  3. Proper Migration Setup: Drizzle migrations are correctly configured
  4. Actor Implementation: Good use of RivetKit's actor pattern with database integration
  5. Package Naming: Correctly named as example-drizzle per guidelines
  6. Turbo Configuration: Proper turbo.json following the template

🔧 Issues Found

Code Quality Issues

  1. README Template Non-Compliance (examples/drizzle/README.md:20)

    • Uses pnpm install instead of npm install as specified in CLAUDE.md template
    • Should follow the exact template format for consistency
  2. Missing Input Validation (src/registry.ts:12)

    • sendMessage action doesn't validate sender or text parameters
    • Per CLAUDE.md: "Use zod for runtime type validation"
    • Could lead to empty or malformed data being stored
  3. Missing JSDoc Comments (src/registry.ts:12, src/registry.ts:21)

    • Public actor actions lack documentation
    • Per CLAUDE.md: "Add proper JSDoc comments for public APIs"
  4. Missing Error Handling (src/registry.ts:15, src/registry.ts:22-26)

    • Database operations lack error handling
    • Per CLAUDE.md: "Ensure proper error handling with descriptive messages"
    • Should use InternalError from RivetKit's error system
  5. Magic Number (src/registry.ts:26)

    • Hard-coded limit of 100 messages
    • Should be a named constant per best practices

Security Considerations

  1. Text Input Sanitization
    • The text and sender fields are stored without validation
    • Risk of storing extremely long strings or special characters
    • Should implement length limits and content validation

Performance Considerations

  1. Database Indexing

    • No index on timestamp column despite ordering by it
    • Could impact query performance as message volume grows
    • Consider adding: timestampIdx: index("timestamp_idx").on(table.timestamp)
  2. Unbounded Query Results

    • While limited to 100, there's no pagination support
    • Fine for an example, but worth noting for production use

🧪 Test Coverage

  • Missing Tests: No test files included in this example
  • Recommendation: Consider adding basic tests for actor actions

🔒 Security Assessment

  • SQL Injection: Protected by Drizzle ORM's query builder
  • Input Validation: Missing - should validate string lengths and content
  • Authentication: Minimal (onAuth: () => {}), appropriate for example

📝 Suggested Improvements

  1. Add Input Validation:

    import { z } from "zod";
    
    const messageSchema = z.object({
      sender: z.string().min(1).max(50),
      text: z.string().min(1).max(1000)
    });
  2. Add Error Handling:

    import { InternalError } from "@rivetkit/actor/errors";
    
    sendMessage: async (c, sender: string, text: string) => {
      try {
        // validation and insertion
      } catch (error) {
        logger().error("failed to send message", { error });
        throw new InternalError("Failed to send message");
      }
    }
  3. Fix README Installation Instructions:

    - pnpm install
    + npm install
  4. Add JSDoc Documentation:

    /**
     * Send a new message to the chat
     * @param sender - The sender's identifier
     * @param text - The message content
     * @returns The created message with timestamp
     */
    sendMessage: async (c, sender: string, text: string) => {
  5. Add Database Index (in schema):

    }, (table) => ({
      timestampIdx: index("timestamp_idx").on(table.timestamp)
    }));

🎯 Overall Assessment

This is a solid foundation for a Drizzle integration example that demonstrates the core functionality well. The implementation correctly shows how to:

  • Set up Drizzle ORM with RivetKit
  • Define database schemas and migrations
  • Implement actor actions with database operations
  • Use broadcasting for real-time features

Priority Fixes:

  1. Fix README installation instructions to match template
  2. Add input validation with zod
  3. Add error handling for database operations
  4. Add JSDoc documentation for public APIs

The example successfully demonstrates Drizzle integration and would be valuable for developers, but could be more robust with the suggested improvements.

Copy link

pkg-pr-new bot commented Aug 14, 2025

More templates

@rivetkit/actor

pnpm add https://pkg.pr.new/rivet-gg/rivetkit/@rivetkit/actor@1175

@rivetkit/core

pnpm add https://pkg.pr.new/rivet-gg/rivetkit/@rivetkit/core@1175

@rivetkit/db

pnpm add https://pkg.pr.new/rivet-gg/rivetkit/@rivetkit/db@1175

rivetkit

pnpm add https://pkg.pr.new/rivet-gg/rivetkit@1175

@rivetkit/cloudflare-workers

pnpm add https://pkg.pr.new/rivet-gg/rivetkit/@rivetkit/cloudflare-workers@1175

@rivetkit/redis

pnpm add https://pkg.pr.new/rivet-gg/rivetkit/@rivetkit/redis@1175

@rivetkit/framework-base

pnpm add https://pkg.pr.new/rivet-gg/rivetkit/@rivetkit/framework-base@1175

@rivetkit/next-js

pnpm add https://pkg.pr.new/rivet-gg/rivetkit/@rivetkit/next-js@1175

@rivetkit/react

pnpm add https://pkg.pr.new/rivet-gg/rivetkit/@rivetkit/react@1175

commit: bc35a94

@jog1t jog1t force-pushed the 08-14-fix_inspector_bring_back_the_actor_inspector branch from 0ac4009 to 8d154f5 Compare August 18, 2025 23:13
@jog1t jog1t force-pushed the 08-14-feat_examples_add_drizzle_example branch from bc35a94 to 1ad7f70 Compare August 18, 2025 23:13
Copy link

claude bot commented Aug 18, 2025

Claude finished @jog1t's task —— View job


Reviewing Drizzle Example PR

Todo List:

  • Read RivetKit development guidelines from CLAUDE.md
  • Analyze all changed files systematically
  • Review code quality and adherence to best practices
  • Check for potential bugs and security issues
  • Evaluate performance considerations
  • Assess test coverage
  • Provide comprehensive feedback with specific recommendations

Review Feedback

Positive Aspects

  1. Project Structure Compliance: The example follows RivetKit's structure guidelines well
  2. Clean Database Schema: Simple, well-defined message table schema in src/db/schema.ts:3-8
  3. Proper Configuration: Turbo.json follows the template exactly
  4. Package Naming: Correctly named as example-drizzle per guidelines
  5. Dependency Management: Proper use of workspace:* dependencies
  6. Actor Implementation: Good use of RivetKit's actor pattern with database integration
  7. Migration Setup: Drizzle migrations are correctly configured

🔧 Issues Found

Critical Issues

  1. README Template Non-Compliance (examples/drizzle/README.md:20)

    • Uses pnpm install instead of npm install as specified in CLAUDE.md template
    • Per guidelines: Installation section should use npm install for consistency
  2. Missing Input Validation (src/registry.ts:12)

    • sendMessage action doesn't validate sender or text parameters
    • Per CLAUDE.md: "Use zod for runtime type validation"
    • Risk of storing empty strings, extremely long content, or malformed data
  3. Missing Error Handling (src/registry.ts:15, src/registry.ts:22-26)

    • Database operations lack error handling
    • Per CLAUDE.md: "Ensure proper error handling with descriptive messages"
    • Database failures could crash the actor

Code Quality Issues

  1. Missing JSDoc Comments (src/registry.ts:12, src/registry.ts:21)

    • Public actor actions lack documentation
    • Per CLAUDE.md: "Add proper JSDoc comments for public APIs"
  2. Magic Number (src/registry.ts:26)

    • Hard-coded limit of 100 messages
    • Should be a named constant for maintainability
  3. Inconsistent Package Manager (package.json:7)

    • Uses pnpm run dev in package.json but README should show npm run dev

Security Considerations

  1. Input Sanitization Missing
    • No length limits on sender or text fields
    • Could allow extremely long strings to be stored
    • No content validation to prevent malicious input

Performance Considerations

  1. Missing Database Index (src/db/schema.ts:7)
    • No index on timestamp column despite ordering by it in queries
    • Could impact performance as message volume grows

🧪 Test Coverage

  • Missing Tests: No test files included in this example
  • Recommendation: While not required for examples, basic tests would demonstrate best practices

📝 Suggested Improvements

1. Fix README Installation Instructions

# examples/drizzle/README.md:20
- pnpm install
+ npm install

2. Add Input Validation

import { z } from "zod";

const messageSchema = z.object({
  sender: z.string().min(1).max(50),
  text: z.string().min(1).max(1000)
});

sendMessage: async (c, sender: string, text: string) => {
  const validated = messageSchema.parse({ sender, text });
  // ... rest of implementation
}

3. Add Error Handling

import { InternalError } from "@rivetkit/actor/errors";
import { logger } from "@rivetkit/actor";

sendMessage: async (c, sender: string, text: string) => {
  try {
    // validation and insertion
  } catch (error) {
    logger().error("failed to send message", { error });
    throw new InternalError("Failed to send message");
  }
}

4. Add JSDoc Documentation

/**
 * Send a new message to the chat
 * @param sender - The sender's identifier  
 * @param text - The message content
 * @returns The created message with timestamp
 */
sendMessage: async (c, sender: string, text: string) => {
  // implementation
}

/**
 * Get chat message history
 * @returns Array of recent messages, ordered by timestamp (newest first)
 */
getHistory: (c) => {
  // implementation  
}

5. Add Database Index

// src/db/schema.ts
export const messagesTable = sqliteTable("messages_table", {
  id: int().primaryKey({ autoIncrement: true }),
  sender: text().notNull(),
  text: text().notNull(),
  timestamp: int().notNull(),
}, (table) => ({
  timestampIdx: index("timestamp_idx").on(table.timestamp)
}));

6. Add Constants

const MESSAGE_HISTORY_LIMIT = 100;

getHistory: (c) =>
  c.db
    .select()
    .from(schema.messagesTable)
    .orderBy(desc(schema.messagesTable.timestamp))
    .limit(MESSAGE_HISTORY_LIMIT),

🎯 Overall Assessment

This is a solid foundation for a Drizzle integration example that successfully demonstrates:

  • Drizzle ORM setup with RivetKit
  • Database schema definition and migrations
  • Actor actions with database operations
  • Real-time broadcasting capabilities

The core functionality is correct and provides a good learning resource for developers. However, the example needs refinement to meet RivetKit's coding standards, particularly around input validation, error handling, and documentation.

Priority Fixes:

  1. Fix README installation instructions to match template
  2. Add input validation with zod
  3. Add error handling for database operations
  4. Add JSDoc documentation for public APIs

Secondary Improvements:
5. Add database indexing for better performance
6. Extract magic numbers to constants
7. Consider adding basic tests as a best practice demonstration

The example successfully demonstrates Drizzle integration and would be valuable for developers looking to build real-time applications with persistent storage using RivetKit.


Copy link

claude bot commented Aug 18, 2025

Claude finished @jog1t's task —— View job


Reviewing Drizzle Example PR

Todo List:

  • Read project guidelines from CLAUDE.md
  • Analyze all changed files in the Drizzle example
  • Review code quality and best practices
  • Check for potential bugs and security issues
  • Evaluate performance considerations
  • Assess test coverage
  • Provide comprehensive feedback

Review Feedback

Positive Aspects

  1. Project Structure Compliance: The example follows RivetKit's structure guidelines well
  2. Clean Database Schema: Simple, well-defined message table schema in src/db/schema.ts:3-8
  3. Proper Migration Setup: Drizzle migrations are correctly configured with proper journal tracking
  4. Actor Implementation: Good use of RivetKit's actor pattern with database integration
  5. Package Naming: Correctly named as example-drizzle per CLAUDE.md guidelines (package.json:2)
  6. Turbo Configuration: Proper turbo.json following the template (turbo.json:1-4)
  7. Workspace Dependencies: Correctly uses workspace:* for dependencies (package.json:12,17,18)

🔧 Issues Found

Critical Issues

  1. README Template Non-Compliance (README.md:20)

    • Uses pnpm install instead of npm install as specified in CLAUDE.md template
    • Per CLAUDE.md line 194: Installation should use npm install
    • Should be consistent with the exact template format
  2. Missing Input Validation (src/registry.ts:12)

    • sendMessage action doesn't validate sender or text parameters
    • Per CLAUDE.md line 133: "Use zod for runtime type validation"
    • Could lead to empty strings, null values, or extremely long content being stored
    • Risk of malformed data causing database or application issues

Code Quality Issues

  1. Missing JSDoc Comments (src/registry.ts:12, src/registry.ts:21)

    • Public actor actions lack documentation
    • Per CLAUDE.md line 135: "Add proper JSDoc comments for public APIs"
    • Should document parameters, return types, and behavior
  2. Missing Error Handling (src/registry.ts:15, src/registry.ts:22-26)

    • Database operations lack error handling
    • Per CLAUDE.md line 136: "Ensure proper error handling with descriptive messages"
    • Should use InternalError from RivetKit's error system for database failures
  3. Magic Number (src/registry.ts:26)

    • Hard-coded limit of 100 messages
    • Should be a named constant for maintainability

Security Considerations

  1. Text Input Sanitization

    • The text and sender fields are stored without validation (src/registry.ts:12-13)
    • Risk of storing extremely long strings that could impact performance
    • No length limits or content validation
    • Should implement reasonable length constraints
  2. Authentication Bypass (src/registry.ts:9)

    • Empty onAuth function allows unrestricted access
    • While appropriate for an example, worth noting for production use

Performance Considerations

  1. Database Indexing

    • No index on timestamp column despite ordering by it (src/registry.ts:25)
    • Could impact query performance as message volume grows
    • Consider adding: timestampIdx: index("timestamp_idx").on(table.timestamp)
  2. Query Optimization

    • Fixed limit of 100 without pagination support
    • Fine for an example, but could be improved with offset/cursor-based pagination

🧪 Test Coverage

  • Missing Tests: No test files included in this example
  • Recommendation: Consider adding basic tests for actor actions and database operations
  • Per RivetKit pattern, tests would verify message storage and retrieval functionality

📝 Suggested Improvements

  1. Add Input Validation:

    import { z } from "zod";
    
    const messageSchema = z.object({
      sender: z.string().min(1).max(50),
      text: z.string().min(1).max(1000)
    });
    
    sendMessage: async (c, sender: string, text: string) => {
      const validated = messageSchema.parse({ sender, text });
      // ... rest of implementation
    }
  2. Add Error Handling:

    import { InternalError } from "@rivetkit/actor/errors";
    import { logger } from "@rivetkit/core";
    
    sendMessage: async (c, sender: string, text: string) => {
      try {
        // validation and insertion
      } catch (error) {
        logger().error("failed to send message", { error });
        throw new InternalError("Failed to send message");
      }
    }
  3. Fix README Installation Instructions:

    - pnpm install
    + npm install
  4. Add JSDoc Documentation:

    /**
     * Send a new message to the chat
     * @param sender - The sender's identifier
     * @param text - The message content
     * @returns The created message with timestamp
     */
    sendMessage: async (c, sender: string, text: string) => {
  5. Add Database Index (in schema):

    export const messagesTable = sqliteTable("messages_table", {
      // ... existing fields
    }, (table) => ({
      timestampIdx: index("timestamp_idx").on(table.timestamp)
    }));
  6. Add Constants:

    const MESSAGE_HISTORY_LIMIT = 100;
    
    getHistory: (c) =>
      c.db
        .select()
        .from(schema.messagesTable)
        .orderBy(desc(schema.messagesTable.timestamp))
        .limit(MESSAGE_HISTORY_LIMIT),

🎯 Overall Assessment

This is a solid foundation for a Drizzle integration example that demonstrates the core functionality well. The implementation correctly shows how to:

  • Set up Drizzle ORM with RivetKit
  • Define database schemas and migrations
  • Implement actor actions with database operations
  • Use broadcasting for real-time features

Priority Fixes:

  1. Fix README installation instructions to match template
  2. Add input validation with zod
  3. Add error handling for database operations
  4. Add JSDoc documentation for public APIs

The example successfully demonstrates Drizzle integration and would be valuable for developers, but needs these improvements to meet RivetKit's quality standards and provide a more robust reference implementation.


@jog1t jog1t changed the base branch from 08-14-fix_inspector_bring_back_the_actor_inspector to graphite-base/1175 August 27, 2025 22:19
@NathanFlurry NathanFlurry mentioned this pull request Sep 2, 2025
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.

1 participant