Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Application
NODE_ENV=development
PORT=3000
HOST=0.0.0.0

# Database
DATABASE_URL="postgresql://user:password@localhost:5432/ldacapi?schema=public"

# Logging
LOG_LEVEL=info
10 changes: 10 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"arrowParens": "always",
"endOfLine": "lf"
}
218 changes: 216 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,216 @@
# ldacapi
Implementation of Arocapi for Language Data Commons
# LDAC API

Implementation of Arocapi for Language Data Commons - A REST API built with TypeScript, Fastify, and Prisma for Node.js 24.

## Features

- **TypeScript** - Type-safe development
- **Fastify** - Fast and low overhead web framework
- **Prisma** - Next-generation ORM for database operations
- **Node.js 24** - Latest Node.js runtime
- **Best Practices** - Well-organized folder structure with separation of concerns
- **Security** - Helmet for security headers and CORS support
- **Logging** - Structured logging with Pino
- **Error Handling** - Centralized error handling middleware
- **Code Quality** - ESLint and Prettier for code consistency

## Project Structure

```
src/
├── common/ # Shared utilities and configurations
│ ├── config/ # Application configuration
│ ├── middleware/ # Custom middleware
│ ├── types/ # TypeScript type definitions
│ └── utils/ # Utility functions
├── controllers/ # Request handlers
├── services/ # Business logic layer
├── routes/ # API route definitions
└── index.ts # Application entry point

prisma/
└── schema.prisma # Database schema
```

## Prerequisites

- Node.js >= 24.0.0
- PostgreSQL database (or other Prisma-supported database)

## Installation

1. Clone the repository:
```bash
git clone https://github.com/Language-Research-Technology/ldacapi.git
cd ldacapi
```

2. Install dependencies:
```bash
npm install
```

3. Set up environment variables:
```bash
cp .env.example .env
```

Edit `.env` with your configuration:
```env
NODE_ENV=development
PORT=3000
HOST=0.0.0.0
DATABASE_URL="postgresql://user:password@localhost:5432/ldacapi?schema=public"
LOG_LEVEL=info
```

4. Generate Prisma Client:
```bash
npm run prisma:generate
```

5. Run database migrations:
```bash
npm run prisma:migrate
```

## Development

Start the development server with hot reload:
```bash
npm run dev
```

The server will start at `http://localhost:3000`

## Building

Build the project for production:
```bash
npm run build
```

## Running in Production

After building, start the production server:
```bash
npm start
```

## Scripts

- `npm run dev` - Start development server with hot reload
- `npm run build` - Build the TypeScript code
- `npm start` - Start production server
- `npm run lint` - Lint the code
- `npm run lint:fix` - Lint and fix issues
- `npm run format` - Format code with Prettier
- `npm run format:check` - Check code formatting
- `npm run prisma:generate` - Generate Prisma Client
- `npm run prisma:migrate` - Run database migrations
- `npm run prisma:studio` - Open Prisma Studio

## API Endpoints

### Health Check

- **GET** `/api/v1/health` - Check API health status

Response:
```json
{
"success": true,
"data": {
"status": "healthy",
"timestamp": "2024-01-01T00:00:00.000Z",
"uptime": 123.456,
"database": {
"connected": true
}
}
}
```

### Root

- **GET** `/` - API information

Response:
```json
{
"message": "LDAC API - Language Data Commons REST API",
"version": "1.0.0",
"documentation": "/api/v1/health"
}
```

## Adding New Features

### 1. Create a Service

Create a new service in `src/services/`:

```typescript
// src/services/example.service.ts
export class ExampleService {
async getExample(id: string) {
// Business logic here
return { id, name: 'Example' };
}
}

export const exampleService = new ExampleService();
```

### 2. Create a Controller

Create a controller in `src/controllers/`:

```typescript
// src/controllers/example.controller.ts
import { FastifyReply, FastifyRequest } from 'fastify';
import { exampleService } from '../services';
import { ApiResponse } from '../common/types';

export class ExampleController {
async getExample(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) {
const { id } = request.params;
const data = await exampleService.getExample(id);
const response: ApiResponse = { success: true, data };
reply.send(response);
}
}

export const exampleController = new ExampleController();
```

### 3. Create Routes

Create routes in `src/routes/`:

```typescript
// src/routes/example.routes.ts
import { FastifyInstance } from 'fastify';
import { exampleController } from '../controllers';

export async function exampleRoutes(fastify: FastifyInstance) {
fastify.get('/:id', exampleController.getExample.bind(exampleController));
}
```

### 4. Register Routes

Update `src/routes/index.ts`:

```typescript
import { exampleRoutes } from './example.routes';

export async function registerRoutes(fastify: FastifyInstance) {
await fastify.register(healthRoutes, { prefix: '/api/v1' });
await fastify.register(exampleRoutes, { prefix: '/api/v1/examples' });
}
```

## License

Apache-2.0
40 changes: 40 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import eslint from '@eslint/js';
import tseslint from '@typescript-eslint/eslint-plugin';
import tsparser from '@typescript-eslint/parser';
import prettier from 'eslint-plugin-prettier';
import prettierConfig from 'eslint-config-prettier';

export default [
eslint.configs.recommended,
{
files: ['src/**/*.ts'],
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: './tsconfig.json',
},
globals: {
process: 'readonly',
console: 'readonly',
Buffer: 'readonly',
__dirname: 'readonly',
__filename: 'readonly',
},
},
plugins: {
'@typescript-eslint': tseslint,
prettier: prettier,
},
rules: {
...tseslint.configs.recommended.rules,
...prettierConfig.rules,
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'prettier/prettier': 'error',
'no-undef': 'off',
},
},
];
Loading