# @saleandwin/config

Configuration center for framework-ts projects. Provides a complete configuration management solution with database persistence, Zod validation, and type safety.

## Installation

```bash
pnpm add @saleandwin/config
```

## Features

- **Database Persistence**: Store configurations in Cloudflare D1 database
- **Direct Database Access**: Real-time data consistency without caching complexity
- **Zod Validation**: Strict input validation with detailed error messages
- **Type Safety**: Full TypeScript support with auto-generated types
- **Configuration History**: Track all configuration changes with triggers
- **Custom Validation**: Extensible validation rules for business logic
- **Batch Operations**: Efficient bulk configuration management
- **Handler Pattern**: Clean separation of concerns with handler -> service -> table architecture

## Architecture

The library follows a clean architecture pattern:

```
Handler -> Service -> Table
```

- **Handler**: HTTP request handling for Next.js routes
- **Service**: Business logic, validation, and data processing
- **Table**: Database access layer with prepared statements

## Quick Start

### 1. Database Setup

Run the migration script to create the required tables:

```sql
-- See migrations.sql for the complete schema
```

### 2. Basic Usage

```typescript
import { ConfigHandler } from '@saleandwin/config';

// Create handler instance
const configHandler = await ConfigHandler.createInstance();

// In your Next.js API route
export async function POST(request: NextRequest) {
  const body = await request.json();
  return await configHandler.handleCreate(body);
}

export async function GET(request: NextRequest, { params }: { params: { key: string } }) {
  return await configHandler.handleGet(params.key);
}
```

### 3. Service Layer Usage

```typescript
import { ConfigService, ConfigValidator } from '@saleandwin/config';

const configService = await ConfigService.createInstance();

// Create configuration
await configService.createConfig({
  key: 'api.rate_limit',
  value: '100',
  type: 'number',
  namespace: 'api',
  description: 'API rate limit per minute',
  is_encrypted: false
});

// Get configuration value (direct from database)
const rateLimit = await configService.getConfig('api.rate_limit'); // Returns: 100

// Get multiple configurations
const configs = await configService.getConfigs(['api.rate_limit', 'api.timeout']);
```

## Configuration Types

The system supports five configuration types:

- **string**: Plain text values
- **number**: Numeric values (automatically parsed)
- **boolean**: Boolean values (`'true'` / `'false'`)
- **json**: JSON objects (automatically parsed)
- **array**: Array values (stored as JSON)

## API Endpoints

### Create Configuration
```http
POST /api/config
Content-Type: application/json

{
  "key": "feature.new_ui",
  "value": "true",
  "type": "boolean",
  "namespace": "feature",
  "description": "Enable new UI features",
  "is_encrypted": false
}
```

### Get Configuration Value
```http
GET /api/config/{key}
```

### Update Configuration
```http
PUT /api/config/{id}
Content-Type: application/json

{
  "value": "false",
  "updated_by": "admin"
}
```

### List Configurations
```http
GET /api/config?page=1&limit=10&namespace=system&search=debug
```

### Get Namespaces
```http
GET /api/config/namespaces
```

### Batch Get Configurations
```http
POST /api/config/batch
Content-Type: application/json

{
  "keys": ["system.debug", "api.rate_limit", "cache.ttl"]
}
```

## Zod Validation

Built-in Zod validation for all configuration operations:

```typescript
import { ConfigValidator } from '@saleandwin/config';

// Validate create request
const createData = {
  key: 'api.rate_limit',
  value: '100',
  type: 'number',
  namespace: 'api',
  description: 'API rate limit per minute',
  is_encrypted: false
};

const validation = ConfigValidator.validateCreateRequest(createData);
if (validation.success) {
  console.log('Valid data:', validation.data);
} else {
  console.log('Validation errors:', validation.error);
}

// Validate update request
const updateValidation = ConfigValidator.validateUpdateRequest({
  value: '200',
  updated_by: 'admin'
});

// Validate batch get request
const batchValidation = ConfigValidator.validateBatchGetRequest({
  keys: ['api.rate_limit', 'cache.ttl']
});

// All validation includes:
// - Key format validation (must start with letter, alphanumeric + . _ -)
// - Value type validation (string, number, boolean, json, array)
// - Length constraints (key: 1-100 chars, value: 1-10000 chars)
// - Namespace format validation
// - JSON/Array format validation for respective types
```

## Configuration Templates

Use predefined templates for common configuration patterns:

```typescript
import { CONFIG_TEMPLATES, ConfigUtils } from '@saleandwin/config';

// Use predefined templates
const databaseConfigs = CONFIG_TEMPLATES.DATABASE.configs;
const cacheConfigs = CONFIG_TEMPLATES.CACHE.configs;

// Create from environment variables
const envConfigs = ConfigUtils.batchFromEnv([
  { envKey: 'DATABASE_URL', configKey: 'database.url', type: 'string' },
  { envKey: 'REDIS_TTL', configKey: 'cache.ttl', type: 'number', defaultValue: '3600' }
]);
```

## Utilities

```typescript
import { ConfigUtils } from '@saleandwin/config';

// Validate key format
ConfigUtils.isValidKey('api.rate_limit'); // true
ConfigUtils.isValidKey('123invalid'); // false

// Parse values
ConfigUtils.parseValue('123', 'number'); // 123
ConfigUtils.parseValue('true', 'boolean'); // true
ConfigUtils.parseValue('{"key": "value"}', 'json'); // { key: "value" }

// Serialize values
ConfigUtils.serializeValue(123, 'number'); // "123"
ConfigUtils.serializeValue({ key: 'value' }, 'json'); // '{"key":"value"}'

// Generate key suggestions
ConfigUtils.suggestKey('API Settings', 'Rate Limit'); // "api_settings.rate_limit"
```

## Configuration History

Track all configuration changes automatically:

```typescript
// Get configuration history
const history = await configService.getConfigHistory('api.rate_limit', 10);

// History includes:
// - old_value and new_value
// - action (create, update, delete)
// - changed_at timestamp
// - changed_by user
```

## Error Handling

The library provides comprehensive error handling:

```typescript
try {
  await configService.createConfig(invalidConfig);
} catch (error) {
  // Validation errors
  if (error.message.includes('格式')) {
    // Handle format validation error
  }
  
  // Duplicate key errors
  if (error.message.includes('已存在')) {
    // Handle duplicate key error
  }
}
```

## Best Practices

1. **Use Namespaces**: Organize configurations by namespace (system, api, database, etc.)
2. **Add Descriptions**: Always provide meaningful descriptions
3. **Validate Input**: Use validation rules for critical configurations
4. **Monitor Changes**: Track who changes what and when
5. **Real-time Data**: Direct database access ensures data consistency
6. **Environment Sync**: Use utilities to sync from environment variables

## Requirements

- Node.js >= 18.0.0
- Cloudflare Workers environment
- Cloudflare D1 database
- `@saleandwin/common` package
- `@opennextjs/cloudflare` peer dependency

## Development

```bash
# Install dependencies
pnpm install

# Build the package
pnpm run build

# Run tests
pnpm test

# Watch mode for development
pnpm run dev
```

## License

MIT
