nuxt-users 1.30.0 → 1.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,30 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## v1.31.0
5
+
6
+ [compare changes](https://github.com/rrd108/nuxt-users/compare/v1.30.0...v1.31.0)
7
+
8
+ ### 🚀 Enhancements
9
+
10
+ - Extends NUsersList with customizable user actions ([1ea4f61](https://github.com/rrd108/nuxt-users/commit/1ea4f61))
11
+ - Adds filtering functionality to user list ([c3d25a9](https://github.com/rrd108/nuxt-users/commit/c3d25a9))
12
+
13
+ ### 🩹 Fixes
14
+
15
+ - Missing connector.options closes #96 ([#96](https://github.com/rrd108/nuxt-users/issues/96))
16
+ - Using user provided properties ([07dd6a2](https://github.com/rrd108/nuxt-users/commit/07dd6a2))
17
+ - Typo in file name ([d833e52](https://github.com/rrd108/nuxt-users/commit/d833e52))
18
+ - Includes scripts directory in the published package ([ceaa188](https://github.com/rrd108/nuxt-users/commit/ceaa188))
19
+
20
+ ### 🏡 Chore
21
+
22
+ - **release:** V1.30.0 ([08d081c](https://github.com/rrd108/nuxt-users/commit/08d081c))
23
+
24
+ ### ❤️ Contributors
25
+
26
+ - Rrd108 ([@rrd108](https://github.com/rrd108))
27
+
4
28
  ## v1.30.0
5
29
 
6
30
  [compare changes](https://github.com/rrd108/nuxt-users/compare/v1.29.1...v1.30.0)
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-users",
3
3
  "configKey": "nuxtUsers",
4
- "version": "1.30.0",
4
+ "version": "1.31.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.0"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-users",
3
- "version": "1.30.0",
3
+ "version": "1.31.0",
4
4
  "description": "A comprehensive user management module for Nuxt 3 and Nuxt 4 applications with authentication, authorization, database support, and CLI tools",
5
5
  "keywords": [
6
6
  "nuxt",
@@ -47,7 +47,8 @@
47
47
  "main": "./dist/module.mjs",
48
48
  "types": "./dist/types.d.mts",
49
49
  "files": [
50
- "dist"
50
+ "dist",
51
+ "scripts"
51
52
  ],
52
53
  "bin": {
53
54
  "nuxt-users": "./dist/cli.mjs"
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { readFileSync, existsSync } from 'node:fs'
4
+ import { join } from 'node:path'
5
+
6
+ const REQUIRED_PEERS = ['bcrypt', 'nodemailer', '@nuxt/kit']
7
+ const OPTIONAL_PEERS = ['nuxt-api-shield']
8
+
9
+ function checkPackageJson() {
10
+ const missing = []
11
+ const optional = []
12
+
13
+ try {
14
+ // Look for package.json in the consumer app (current working directory)
15
+ const pkgPath = join(process.cwd(), 'package.json')
16
+
17
+ if (!existsSync(pkgPath)) {
18
+ console.log('⚠️ Could not find package.json in current directory')
19
+ return { missing: REQUIRED_PEERS, optional: OPTIONAL_PEERS }
20
+ }
21
+
22
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
23
+
24
+ // Check all possible dependency locations
25
+ const allDeps = {
26
+ ...pkg.dependencies || {},
27
+ ...pkg.devDependencies || {},
28
+ ...pkg.peerDependencies || {}
29
+ }
30
+
31
+ // Check required dependencies
32
+ for (const dep of REQUIRED_PEERS) {
33
+ if (!allDeps[dep]) {
34
+ missing.push(dep)
35
+ }
36
+ }
37
+
38
+ // Check optional dependencies
39
+ for (const dep of OPTIONAL_PEERS) {
40
+ if (!allDeps[dep]) {
41
+ optional.push(dep)
42
+ }
43
+ }
44
+
45
+ return { missing, optional, packageName: pkg.name || 'your project' }
46
+ }
47
+ catch (error) {
48
+ console.log('⚠️ Error reading package.json:', error.message)
49
+ // If we can't read package.json, assume all deps are missing
50
+ return { missing: REQUIRED_PEERS, optional: OPTIONAL_PEERS, packageName: 'your project' }
51
+ }
52
+ }
53
+
54
+ function getPackageManagerCommand() {
55
+ // Detect package manager from lock files or environment
56
+ const cwd = process.cwd()
57
+
58
+ if (existsSync(join(cwd, 'pnpm-lock.yaml'))) {
59
+ return 'pnpm add'
60
+ }
61
+ else if (existsSync(join(cwd, 'yarn.lock'))) {
62
+ return 'yarn add'
63
+ }
64
+ else if (existsSync(join(cwd, 'package-lock.json'))) {
65
+ return 'npm install'
66
+ }
67
+ else if (process.env.npm_config_user_agent?.includes('pnpm')) {
68
+ return 'pnpm add'
69
+ }
70
+ else if (process.env.npm_config_user_agent?.includes('yarn')) {
71
+ return 'yarn add'
72
+ }
73
+
74
+ // Default fallback
75
+ return 'npm install'
76
+ }
77
+
78
+ function displayResults({ missing, optional, packageName }) {
79
+ const primaryCmd = getPackageManagerCommand()
80
+
81
+ if (missing.length > 0) {
82
+ console.log('\n🚨 nuxt-users: Missing required peer dependencies!')
83
+ console.log(`Project: ${packageName}`)
84
+ console.log('These dependencies are required for nuxt-users to work properly.\n')
85
+
86
+ console.log('💾 Missing dependencies:')
87
+ missing.forEach(dep => console.log(` - ${dep}`))
88
+ console.log('')
89
+
90
+ console.log('🔧 Install command (detected):')
91
+ console.log(` ${primaryCmd} ${missing.join(' ')}\n`)
92
+
93
+ console.log('🔧 Alternative install commands:')
94
+ console.log(` npm install ${missing.join(' ')}`)
95
+ console.log(` pnpm add ${missing.join(' ')}`)
96
+ console.log(` yarn add ${missing.join(' ')}\n`)
97
+
98
+ console.log('📚 Documentation: https://nuxt-users.webmania.cc/installation')
99
+ console.log('🐛 Issues: https://github.com/rrd108/nuxt-users/issues\n')
100
+
101
+ // Exit with error code to make installation fail
102
+ process.exit(1)
103
+ }
104
+
105
+ if (optional.length > 0 && missing.length === 0) {
106
+ console.log('\n💡 nuxt-users: Optional dependencies available!')
107
+ console.log(`Project: ${packageName}`)
108
+ console.log('These provide additional security and features:\n')
109
+
110
+ console.log('🔒 Optional dependencies:')
111
+ optional.forEach(dep => console.log(` - ${dep}`))
112
+ console.log('')
113
+
114
+ console.log('🔧 Install command (detected):')
115
+ console.log(` ${primaryCmd} ${optional.join(' ')}\n`)
116
+
117
+ console.log('🔧 Alternative install commands:')
118
+ console.log(` npm install ${optional.join(' ')}`)
119
+ console.log(` pnpm add ${optional.join(' ')}`)
120
+ console.log(` yarn add ${optional.join(' ')}\n`)
121
+ }
122
+
123
+ if (missing.length === 0 && optional.length === 0) {
124
+ console.log(`✅ nuxt-users: All dependencies found in ${packageName}!`)
125
+ }
126
+ else if (missing.length === 0) {
127
+ console.log(`✅ nuxt-users: All required dependencies found in ${packageName}!`)
128
+ }
129
+ }
130
+
131
+ async function checkPeerDependencies() {
132
+ const result = checkPackageJson()
133
+ displayResults(result)
134
+ }
135
+
136
+ // Handle both direct execution and module import
137
+ if (import.meta.url === `file://${process.argv[1]}`) {
138
+ checkPeerDependencies().catch(console.error)
139
+ }
140
+
141
+ export { checkPeerDependencies }
@@ -0,0 +1,69 @@
1
+ #!/bin/bash
2
+
3
+ # Configuration
4
+ SERVER_HOST="35.198.93.8"
5
+ SERVER_USER="sravanam"
6
+ REMOTE_DOCS_PATH="/var/www/nuxt-users.webmania.cc"
7
+ LOCAL_BUILD_PATH="docs/.vitepress/dist"
8
+
9
+ # Colors for output
10
+ RED='\033[0;31m'
11
+ GREEN='\033[0;32m'
12
+ YELLOW='\033[1;33m'
13
+ NC='\033[0m' # No Color
14
+
15
+ echo -e "${YELLOW}🚀 Starting documentation deployment...${NC}"
16
+
17
+ # Check if build directory exists
18
+ if [ ! -d "$LOCAL_BUILD_PATH" ]; then
19
+ echo -e "${RED}❌ Build directory not found: $LOCAL_BUILD_PATH${NC}"
20
+ echo -e "${YELLOW}💡 Make sure to run 'npm run docs:build' first${NC}"
21
+ exit 1
22
+ fi
23
+
24
+ # Create a temporary tar file for transfer
25
+ TEMP_TAR="docs-build-$(date +%Y%m%d-%H%M%S).tar.gz"
26
+ echo -e "${YELLOW}📦 Creating archive: $TEMP_TAR${NC}"
27
+ tar -czf "$TEMP_TAR" -C "$LOCAL_BUILD_PATH" .
28
+
29
+ # Upload and deploy
30
+ echo -e "${YELLOW}📤 Uploading to $SERVER_HOST...${NC}"
31
+ ssh "$SERVER_USER@$SERVER_HOST" << EOF
32
+ # Create backup of current docs
33
+ if [ -d "$REMOTE_DOCS_PATH" ]; then
34
+ echo "📋 Creating backup of current documentation..."
35
+ cp -r "$REMOTE_DOCS_PATH" "${REMOTE_DOCS_PATH}-backup-\$(date +%Y%m%d-%H%M%S)"
36
+ fi
37
+
38
+ # Create docs directory if it doesn't exist
39
+ mkdir -p "$REMOTE_DOCS_PATH"
40
+
41
+ # Clean the docs directory
42
+ rm -rf "$REMOTE_DOCS_PATH"/*
43
+
44
+ echo "✅ Ready for new files"
45
+ EOF
46
+
47
+ # Copy the tar file to server
48
+ scp "$TEMP_TAR" "$SERVER_USER@$SERVER_HOST:/tmp/"
49
+
50
+ # Extract and deploy on server
51
+ ssh "$SERVER_USER@$SERVER_HOST" << EOF
52
+ echo "📦 Extracting documentation..."
53
+ tar -xzf "/tmp/$TEMP_TAR" -C "$REMOTE_DOCS_PATH"
54
+
55
+ # Set proper permissions
56
+ chmod -R 755 "$REMOTE_DOCS_PATH"
57
+
58
+ # Clean up temporary files
59
+ rm "/tmp/$TEMP_TAR"
60
+
61
+ echo "✅ Documentation deployed successfully!"
62
+ echo "📁 Location: $REMOTE_DOCS_PATH"
63
+ EOF
64
+
65
+ # Clean up local temporary file
66
+ rm "$TEMP_TAR"
67
+
68
+ echo -e "${GREEN}✅ Documentation deployment completed!${NC}"
69
+ echo -e "${YELLOW}🌐 Your docs should now be available on your server${NC}"
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+ import { fileURLToPath } from 'node:url'
3
+ import { dirname, join } from 'node:path'
4
+ import { existsSync, writeFileSync, rmdirSync, unlinkSync, readdirSync, readFileSync } from 'node:fs'
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url))
7
+ const projectRoot = join(__dirname, '..')
8
+ const distDir = join(projectRoot, 'dist')
9
+ const utilsDir = join(distDir, 'utils')
10
+ const utilsIndexFile = join(utilsDir, 'index.js')
11
+ const utilsRootFile = join(distDir, 'utils.js')
12
+
13
+ // Remove existing utils directory if it exists
14
+ if (existsSync(utilsDir)) {
15
+ try {
16
+ if (existsSync(utilsIndexFile)) {
17
+ unlinkSync(utilsIndexFile)
18
+ }
19
+ rmdirSync(utilsDir)
20
+ }
21
+ catch {
22
+ // Ignore errors
23
+ }
24
+ }
25
+
26
+ // Create utils.js in the dist root to handle "../../../utils" imports
27
+ // This allows imports like "../../../utils" to resolve to a file instead of directory
28
+ const rootIndexContent = `export * from './utils.mjs'
29
+ `
30
+ writeFileSync(utilsRootFile, rootIndexContent)
31
+
32
+ // Note: Types imports should be handled by TypeScript compilation, not runtime
33
+
34
+ // Fix import paths in built files to include .js extensions for ES modules
35
+ const runtimeUtilsDir = join(distDir, 'runtime')
36
+
37
+ // Function to recursively find and fix import statements
38
+ function fixImportPaths(dir) {
39
+ const items = readdirSync(dir, { withFileTypes: true })
40
+
41
+ for (const item of items) {
42
+ const fullPath = join(dir, item.name)
43
+
44
+ if (item.isDirectory()) {
45
+ fixImportPaths(fullPath)
46
+ }
47
+ else if (item.isFile() && (item.name.endsWith('.js') || item.name.endsWith('.mjs') || item.name.endsWith('.vue') || item.name.endsWith('.ts'))) {
48
+ let content = readFileSync(fullPath, 'utf8')
49
+ let modified = false
50
+
51
+ // Transform relative imports to utils/imports back to nuxt-users/utils for consumers
52
+ const relativeImportsRegex = /from\s+["'](\.\.[/\\])*utils[/\\]imports["']/g
53
+ if (relativeImportsRegex.test(content)) {
54
+ content = content.replace(relativeImportsRegex, 'from "nuxt-users/utils"')
55
+ modified = true
56
+ }
57
+
58
+ // Transform other relative utils imports
59
+ const utilsImportRegex = /from\s+["']\.\.[/\\]utils[/\\]imports["']/g
60
+ if (utilsImportRegex.test(content)) {
61
+ content = content.replace(utilsImportRegex, 'from "nuxt-users/utils"')
62
+ modified = true
63
+ }
64
+
65
+ if (modified) {
66
+ writeFileSync(fullPath, content)
67
+ console.log(`[Nuxt Users] Transformed import paths in ${fullPath}`)
68
+ }
69
+ }
70
+ }
71
+ }
72
+
73
+ fixImportPaths(runtimeUtilsDir)
74
+
75
+ console.log('[Nuxt Users] Created utils.js file and fixed import paths for ES modules')
@@ -0,0 +1,136 @@
1
+ #!/bin/bash
2
+
3
+ # Integration test script for nuxt-users module
4
+ # Tests playground middleware functionality locally
5
+
6
+ set -e
7
+
8
+ echo "🚀 Starting nuxt-users integration tests..."
9
+
10
+ # Colors for output
11
+ RED='\033[0;31m'
12
+ GREEN='\033[0;32m'
13
+ YELLOW='\033[1;33m'
14
+ BLUE='\033[0;34m'
15
+ NC='\033[0m' # No Color
16
+
17
+ # Function to print colored output
18
+ print_status() {
19
+ local color=$1
20
+ local message=$2
21
+ echo -e "${color}${message}${NC}"
22
+ }
23
+
24
+ # Function to cleanup background processes
25
+ cleanup() {
26
+ if [ ! -z "$SERVER_PID" ]; then
27
+ print_status $YELLOW "🧹 Cleaning up server (PID: $SERVER_PID)..."
28
+ kill $SERVER_PID 2>/dev/null || true
29
+ wait $SERVER_PID 2>/dev/null || true
30
+ fi
31
+ }
32
+
33
+ # Set up trap for cleanup on script exit
34
+ trap cleanup EXIT
35
+
36
+ # Check if we're in the right directory
37
+ if [ ! -f "package.json" ] || [ ! -d "playground" ]; then
38
+ print_status $RED "❌ Please run this script from the nuxt-users root directory"
39
+ exit 1
40
+ fi
41
+
42
+ print_status $BLUE "📦 Preparing development environment..."
43
+
44
+ # Prepare the module
45
+ npm run dev:prepare
46
+
47
+ print_status $BLUE "🏗️ Building playground..."
48
+
49
+ # Build the playground
50
+ cd playground
51
+ npm run build
52
+
53
+ print_status $BLUE "🖥️ Starting production server..."
54
+
55
+ # Start the server in background
56
+ node .output/server/index.mjs &
57
+ SERVER_PID=$!
58
+
59
+ # Wait for server to start
60
+ sleep 3
61
+
62
+ # Check if server is running
63
+ if ! kill -0 $SERVER_PID 2>/dev/null; then
64
+ print_status $RED "❌ Server failed to start"
65
+ exit 1
66
+ fi
67
+
68
+ print_status $GREEN "✅ Server started successfully (PID: $SERVER_PID)"
69
+
70
+ # Wait a bit more for server to be fully ready
71
+ sleep 2
72
+
73
+ print_status $BLUE "🧪 Running integration tests..."
74
+
75
+ # Test 1: /me endpoint should require authentication (401 without token)
76
+ print_status $YELLOW "🔐 Testing /me endpoint requires authentication..."
77
+ response=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:3000/api/nuxt-users/me" || echo "000")
78
+
79
+ if [ "$response" = "401" ]; then
80
+ print_status $GREEN "✅ /me endpoint properly requires authentication (401 without token)"
81
+ else
82
+ print_status $RED "❌ /me endpoint should require authentication - expected 401, got $response"
83
+ print_status $RED " This means server middleware is not properly registered!"
84
+ exit 1
85
+ fi
86
+
87
+ # Test 2: Session endpoint should be accessible (not 401)
88
+ print_status $YELLOW "📝 Testing session endpoint /api/nuxt-users/session..."
89
+ response=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:3000/api/nuxt-users/session" -X POST || echo "000")
90
+
91
+ if [ "$response" != "401" ]; then
92
+ print_status $GREEN "✅ Session endpoint accessible (HTTP $response - auth not blocking)"
93
+ else
94
+ print_status $RED "❌ Session endpoint blocked by auth - should be accessible for login"
95
+ exit 1
96
+ fi
97
+
98
+ # Test 3: Registration endpoint should be auto-whitelisted
99
+ print_status $YELLOW "📋 Testing registration endpoint /api/nuxt-users/register..."
100
+ response=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:3000/api/nuxt-users/register" -X POST || echo "000")
101
+
102
+ if [ "$response" != "401" ]; then
103
+ print_status $GREEN "✅ Registration endpoint accessible (HTTP $response - auto-whitelisted)"
104
+ else
105
+ print_status $RED "❌ Registration endpoint blocked - auto-whitelisting not working"
106
+ exit 1
107
+ fi
108
+
109
+ # Test 4: Test a few more protected endpoints if they exist
110
+ print_status $YELLOW "🔍 Testing other protected endpoints..."
111
+
112
+ endpoints=(
113
+ "/api/nuxt-users/profile"
114
+ "/api/nuxt-users/users"
115
+ )
116
+
117
+ for endpoint in "${endpoints[@]}"; do
118
+ response=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:3000$endpoint" || echo "000")
119
+
120
+ if [ "$response" = "401" ]; then
121
+ print_status $GREEN "✅ $endpoint properly protected (401)"
122
+ elif [ "$response" = "404" ]; then
123
+ print_status $YELLOW "⚠️ $endpoint not found (404) - endpoint may not exist"
124
+ else
125
+ print_status $YELLOW "⚠️ $endpoint returned $response - verify this is expected"
126
+ fi
127
+ done
128
+
129
+ print_status $GREEN "🎉 All integration tests passed!"
130
+ print_status $BLUE "📊 Test Summary:"
131
+ print_status $BLUE " • Server middleware registration: ✅ Working"
132
+ print_status $BLUE " • Authentication enforcement: ✅ Working"
133
+ print_status $BLUE " • Auto-whitelisting: ✅ Working"
134
+ print_status $BLUE " • Endpoint accessibility: ✅ Working"
135
+
136
+ print_status $GREEN "✨ Your nuxt-users module is ready for production!"
@@ -0,0 +1,54 @@
1
+ #!/bin/bash
2
+
3
+ # MySQL Test Runner Script
4
+ # This script sets up environment variables for MySQL testing
5
+
6
+ echo "Setting up MySQL test environment..."
7
+
8
+ # Default MySQL configuration
9
+ export DB_CONNECTOR="mysql"
10
+ export DB_HOST=${DB_HOST:-"localhost"}
11
+ export DB_PORT=${DB_PORT:-"3306"}
12
+ export DB_USER=${DB_USER:-"root"}
13
+ export DB_PASSWORD=${DB_PASSWORD:-"123"}
14
+ export DB_NAME=${DB_NAME:-"test_db"}
15
+
16
+ echo "Database configuration:"
17
+ echo " Host: $DB_HOST"
18
+ echo " Port: $DB_PORT"
19
+ echo " User: $DB_USER"
20
+ echo " Database: $DB_NAME"
21
+
22
+ # Set MySQL password environment variable for consistent authentication
23
+ export MYSQL_PWD="$DB_PASSWORD"
24
+
25
+ # Wait for MySQL to be ready
26
+ echo "Waiting for MySQL connection..."
27
+ for i in {1..10}; do
28
+ if mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -e "SELECT 1;" >/dev/null 2>&1; then
29
+ echo "MySQL connection successful!"
30
+ break
31
+ fi
32
+ echo "MySQL not ready, retrying in 3 seconds... (attempt $i/10)"
33
+ sleep 3
34
+ done
35
+
36
+ # Final check if MySQL is running
37
+ if ! mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -e "SELECT 1;" >/dev/null 2>&1; then
38
+ echo "Error: Cannot connect to MySQL after multiple retries. Please ensure MySQL is running and accessible."
39
+ echo "You can start MySQL with: docker run --name mysql-test -e MYSQL_ROOT_PASSWORD=123 -e MYSQL_DATABASE=test_db -p 3306:3306 -d mysql:5.7"
40
+ exit 1
41
+ fi
42
+
43
+ # Create test database if it doesn't exist
44
+ mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -e "CREATE DATABASE IF NOT EXISTS $DB_NAME;" >/dev/null 2>&1
45
+
46
+ echo "Running tests against MySQL..."
47
+
48
+ # Check if any arguments were passed
49
+ if [ $# -eq 0 ]; then
50
+ # Run all tests except unit tests (database-independent)
51
+ vitest run --exclude="test/unit/"
52
+ else
53
+ vitest run "$@"
54
+ fi
@@ -0,0 +1,93 @@
1
+ #!/bin/bash
2
+
3
+ # PostgreSQL Test Runner Script
4
+ # This script sets up environment variables for PostgreSQL testing
5
+
6
+ echo "Setting up PostgreSQL test environment..."
7
+
8
+ # Default PostgreSQL configuration
9
+ export DB_CONNECTOR="postgresql"
10
+ export DB_HOST=${DB_HOST:-"localhost"}
11
+ export DB_PORT=${DB_PORT:-"5432"}
12
+ export DB_USER=${DB_USER:-"postgres"}
13
+ export DB_PASSWORD=${DB_PASSWORD:-"123"}
14
+ export DB_NAME=${DB_NAME:-"test_db"}
15
+
16
+ echo "Database configuration:"
17
+ echo " Host: $DB_HOST"
18
+ echo " Port: $DB_PORT"
19
+ echo " User: $DB_USER"
20
+ echo " Database: $DB_NAME"
21
+
22
+ # Wait for PostgreSQL to be ready
23
+ echo "Waiting for PostgreSQL connection..."
24
+ for i in {1..10}; do
25
+ if pg_isready -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -q; then
26
+ echo "PostgreSQL connection successful!"
27
+ break
28
+ fi
29
+ echo "PostgreSQL not ready, retrying in 3 seconds... (attempt $i/10)"
30
+ sleep 3
31
+ done
32
+
33
+ # Final check if PostgreSQL is running
34
+ if ! pg_isready -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -q; then
35
+ echo "Error: Cannot connect to PostgreSQL after multiple retries. Please ensure PostgreSQL is running and accessible."
36
+ echo "You can start PostgreSQL with: docker run --name postgres-test -e POSTGRES_PASSWORD=123 -e POSTGRES_DB=test_db -p 5432:5432 -d postgres:13"
37
+ exit 1
38
+ fi
39
+
40
+ # Recreate the test database to ensure a clean state
41
+ echo "Recreating test database '$DB_NAME'..."
42
+
43
+ # Drop database if exists (ignore errors)
44
+ PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "DROP DATABASE IF EXISTS \"$DB_NAME\";" >/dev/null 2>&1
45
+
46
+ # Create database with proper encoding to avoid collation issues
47
+ PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "CREATE DATABASE \"$DB_NAME\" WITH ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C';" >/dev/null 2>&1
48
+
49
+ # Verify database was created
50
+ if ! PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "SELECT 1;" >/dev/null 2>&1; then
51
+ echo "Error: Failed to create or connect to database '$DB_NAME'"
52
+ echo "Trying alternative approach..."
53
+
54
+ # Try creating with template0 to avoid collation issues
55
+ PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "CREATE DATABASE \"$DB_NAME\" TEMPLATE template0;" >/dev/null 2>&1
56
+
57
+ if ! PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "SELECT 1;" >/dev/null 2>&1; then
58
+ echo "Error: Still cannot create database. Please check PostgreSQL configuration."
59
+ exit 1
60
+ fi
61
+ fi
62
+
63
+ echo "Database '$DB_NAME' created successfully!"
64
+
65
+ # Wait a moment for database to be ready
66
+ sleep 2
67
+
68
+ # Configure PostgreSQL for testing (increase connection limits)
69
+ echo "Configuring PostgreSQL for testing..."
70
+ PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "ALTER SYSTEM SET max_connections = 500;" >/dev/null 2>&1
71
+ PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "ALTER SYSTEM SET shared_preload_libraries = 'pg_stat_statements';" >/dev/null 2>&1
72
+ PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "ALTER SYSTEM SET log_statement = 'none';" >/dev/null 2>&1
73
+ PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "ALTER SYSTEM SET log_min_duration_statement = -1;" >/dev/null 2>&1
74
+ PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "ALTER SYSTEM SET idle_in_transaction_session_timeout = '10s';" >/dev/null 2>&1
75
+ PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "SELECT pg_reload_conf();" >/dev/null 2>&1
76
+
77
+ # Kill any idle connections to free up slots
78
+ echo "Cleaning up idle connections..."
79
+ PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
80
+ SELECT pg_terminate_backend(pid)
81
+ FROM pg_stat_activity
82
+ WHERE state IN ('idle', 'idle in transaction') AND pid <> pg_backend_pid();
83
+ " >/dev/null 2>&1
84
+
85
+ echo "Running tests against PostgreSQL..."
86
+
87
+ # Check if any arguments were passed
88
+ if [ $# -eq 0 ]; then
89
+ # Run all tests except unit tests (database-independent)
90
+ vitest run --exclude="test/unit/"
91
+ else
92
+ vitest run "$@"
93
+ fi
@@ -0,0 +1,23 @@
1
+ #!/bin/bash
2
+
3
+ # SQLite Test Runner Script
4
+ # This script sets up environment variables for SQLite testing
5
+
6
+ echo "Setting up SQLite test environment..."
7
+
8
+ # Force SQLite configuration
9
+ export DB_CONNECTOR="sqlite"
10
+
11
+ echo "Database configuration:"
12
+ echo " Type: SQLite"
13
+ echo " Path: ./_test-db (default)"
14
+
15
+ echo "Running tests against SQLite..."
16
+
17
+ # Check if any arguments were passed
18
+ if [ $# -eq 0 ]; then
19
+ # Run all tests except unit tests (database-independent)
20
+ vitest run --exclude="test/unit/"
21
+ else
22
+ vitest run "$@"
23
+ fi
@@ -0,0 +1,15 @@
1
+ #!/bin/bash
2
+
3
+ # Unit Test Runner Script
4
+ # This script runs tests that don't require database access
5
+
6
+ echo "Running unit tests (no database required)..."
7
+
8
+ # Check if any arguments were passed
9
+ if [ $# -eq 0 ]; then
10
+ # Run all unit tests
11
+ vitest run test/unit/
12
+ else
13
+ # Run only the specified test
14
+ vitest run "$@"
15
+ fi