Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 17, 2025

Adds complete Release Items API with database connection testing, comprehensive query capabilities, and seed data management.

Core Service Layer

services/releaseService.js - Four query functions:

  • getReleases() - Supports filtering by products/investment areas/dates/wave, pagination, sorting (4 fields × 2 directions), and case-insensitive search across feature name/business value/details
  • getReleaseById() - Single item retrieval
  • getReleaseStats() - Aggregated counts by product/investment area/wave, total items, last sync timestamp
  • getFilterOptions() - Distinct values with counts for dropdown population

API Endpoints

routes/releases.js - Four routes:

GET /api/releases?products=PowerApps,D365&search=copilot&sortBy=gaDate&page=1&limit=50
GET /api/releases/stats
GET /api/releases/filters
GET /api/releases/:id

Comma-separated lists parsed for multi-select filters. Route ordering ensures /stats and /filters match before /:id.

Validation & Error Handling

middleware/validation.js - validateReleaseQuery():

  • Joi schema enforces: page ≥ 1, 1 ≤ limit ≤ 100, ISO dates, enum constraints for sortBy/sortOrder
  • Returns field-level error details on validation failure

middleware/errorHandler.js - Enhanced with:

  • P2002 (duplicate) → 409
  • P2025 (not found) → 404
  • ValidationError → 400 with details

Database Connection

config/database.js - testConnection() function validates connectivity with visual feedback

server.js - Tests connection on startup, logs ✅/❌ status, continues boot even on failure

Seed Data

scripts/seed.js - Upserts 3 sample releases covering:

  • Multiple products (D365 CE, Power Apps, F&O)
  • Date ranges (2024 waves)
  • Geographic variations
  • Null handling for optional fields

Added npm run seed to package.json.

Schema & Indexes

MySQL schema includes indexes on:

  • productName (idx_product)
  • gaDate (idx_ga_date)
  • investmentArea (idx_investment_area)

Case-insensitive search uses Prisma's mode: 'insensitive' (MySQL compatible).

Documentation

  • TESTING.md - curl examples for all endpoints and query combinations
  • TEST_SUMMARY.md - Test results, performance notes, deployment steps
  • IMPLEMENTATION_SUMMARY.md - Complete feature inventory

Pagination returns: {items: [...], pagination: {total, page, totalPages, hasNext, hasPrev}}

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • checkpoint.prisma.io
    • Triggering command: /usr/local/bin/node /usr/local/bin/node /home/REDACTED/work/release-plans/release-plans/backend/node_modules/prisma/build/child {"product":"prisma","version":"5.22.0","cli_install_type":"local","information":"","local_timestamp":"2025-12-17T12:22:22Z","project_hash":"07708f6b","cli_path":"/home/REDACTED/work/release-plans/release-plans/backend/node_modules/.bin/prisma","cli_path_has (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

Database Setup & Release Items API

Implement the core database functionality and Release Items API endpoints with filtering, pagination, search, and sorting capabilities.

Database Setup

1. Prisma Migrations

  • Run initial migration to create all database tables from the schema
  • Ensure proper indexes are created for performance
  • Test database connection in backend/src/config/database.js

2. Database Connection Test

Add a connection test utility in backend/src/config/database.js:

export async function testConnection() {
  try {
    await prisma.$connect();
    console.log('✅ Database connection successful');
    return true;
  } catch (error) {
    console.error('❌ Database connection failed:', error);
    return false;
  }
}

Update backend/src/server.js to test connection on startup.

Release Items API Implementation

1. Release Service (backend/src/services/releaseService.js)

Implement the following functions:

/**
 * Get all releases with filtering, pagination, sorting, and search
 * @param {Object} options - Query options
 * @param {number} options.page - Page number (default: 1)
 * @param {number} options.limit - Items per page (default: 50, max: 100)
 * @param {string[]} options.products - Filter by product names
 * @param {string[]} options.investmentAreas - Filter by investment areas
 * @param {string} options.search - Search term for feature name, business value
 * @param {string} options.gaDateFrom - Filter GA date from (YYYY-MM-DD)
 * @param {string} options.gaDateTo - Filter GA date to (YYYY-MM-DD)
 * @param {string} options.releaseWave - Filter by release wave
 * @param {string} options.sortBy - Sort field (gaDate, productName, featureName, lastUpdated)
 * @param {string} options.sortOrder - Sort order (asc, desc)
 * @returns {Promise<{items: Array, pagination: Object}>}
 */
export async function getReleases(options) {
  // Build where clause for filtering
  // Implement search across featureName, businessValue, featureDetails
  // Add pagination logic
  // Add sorting
  // Return items + pagination metadata (total, page, totalPages, hasNext, hasPrev)
}

/**
 * Get a single release item by ID
 * @param {string} id - Release item ID
 * @returns {Promise<Object|null>}
 */
export async function getReleaseById(id) {
  // Return single release item or null if not found
}

/**
 * Get summary statistics
 * @returns {Promise<Object>} Stats object with totals, products list, investment areas list
 */
export async function getReleaseStats() {
  // Total items count
  // Unique products list with counts
  // Unique investment areas list with counts
  // Items by release wave
  // Latest sync date
}

/**
 * Get unique filter values for dropdowns
 * @returns {Promise<Object>} Filter options (products, investmentAreas, releaseWaves)
 */
export async function getFilterOptions() {
  // Get distinct products with counts
  // Get distinct investment areas with counts
  // Get distinct release waves
}

2. Release Routes (backend/src/routes/releases.js)

Implement the following endpoints:

import express from 'express';
import * as releaseService from '../services/releaseService.js';
import { validateReleaseQuery } from '../middleware/validation.js';

const router = express.Router();

/**
 * GET /api/releases
 * Query params:
 *   - page (number): Page number
 *   - limit (number): Items per page
 *   - products (string): Comma-separated product names
 *   - investmentAreas (string): Comma-separated investment areas
 *   - search (string): Search term
 *   - gaDateFrom (string): GA date from (YYYY-MM-DD)
 *   - gaDateTo (string): GA date to (YYYY-MM-DD)
 *   - releaseWave (string): Release wave filter
 *   - sortBy (string): Sort field
 *   - sortOrder (string): asc or desc
 */
router.get('/', validateReleaseQuery, async (req, res, next) => {
  // Parse query params
  // Call releaseService.getReleases()
  // Return JSON response with items and pagination
});

/**
 * GET /api/releases/stats
 * Get summary statistics
 */
router.get('/stats', async (req, res, next) => {
  // Call releaseService.getReleaseStats()
  // Return JSON response
});

/**
 * GET /api/releases/filters
 * Get available filter options
 */
router.get('/filters', async (req, res, next) => {
  // Call releaseService.getFilterOptions()
  // Return JSON response
});

/**
 * GET /api/releases/:id
 * Get single release item
 */
router.get('/:id', async (req, res, next) => {
  // Call releaseService.getReleaseById()
  // Return 404 if not found
  // Return JSON response
});

export default router;

3. Validation Middleware (backend/src/middleware/validation.js)

Implement request validation using Joi:

import Joi from 'joi';

const releaseQuerySchema = Joi.object({
  page: Joi.number().integer().min(1).default(1),
  limit: Joi.number().integer().min(1).max(100).default(50),
  products: Joi.string().allow(''),
  investmentAreas: Joi.string().allo...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

@bolt-new-by-stackblitz
Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@netlify
Copy link

netlify bot commented Dec 17, 2025

Deploy Preview for releaseplans ready!

Name Link
🔨 Latest commit 8a1be06
🔍 Latest deploy log https://app.netlify.com/projects/releaseplans/deploys/6942a257c234f800083e905e
😎 Deploy Preview https://deploy-preview-3--releaseplans.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI and others added 4 commits December 17, 2025 12:17
…seed script

Co-authored-by: jukkan <10254155+jukkan@users.noreply.github.com>
Co-authored-by: jukkan <10254155+jukkan@users.noreply.github.com>
Co-authored-by: jukkan <10254155+jukkan@users.noreply.github.com>
Co-authored-by: jukkan <10254155+jukkan@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement database setup and Release Items API endpoints Implement Release Items API with filtering, pagination, sorting, and search Dec 17, 2025
Copilot AI requested a review from jukkan December 17, 2025 12:32
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.

2 participants