npm package: @pineliner/simple-rest
Description: Simple REST package with Supabase-style client and Express server
Latest version: 1.0.6

# Simple REST

A Supabase-style client and Express server package for simple REST queries.

## Usage

### Client

```typescript
import { createClient } from '@pineliner/simple-rest/client';

const client = createClient('http://localhost:3000');

// Set authentication token
client.setAuthBearer('your-jwt-token');

// Using the query builder (Supabase-style)
const { data } = await client
  .from('users')
  .select('id, name, age')
  .eq('status', 'active')
  .gt('age', 18)
  .notIn('role', ['banned', 'deleted'])
  .is('verified', true)
  .isNot('deleted_at', null)
  .order('created_at', 'desc')
  .limit(20);

// Authentication methods
client.setAuthBearer('new-token');  // Set/update token
const token = client.getAuthBearer(); // Get current token
client.clearAuth();                  // Remove token

// Using raw query
const response = await client.query({
  from: "users",
  select: ["id", "name", "age"],
  where: {
    and: [
      { "=": ["status", "active"] },
      { ">": ["age", 18] }
    ]
  },
  orderBy: [["created_at", "desc"]],
  limit: 20
});
```

### Server

```typescript
import express from 'express';
import { createManager, createResolver, Resolver } from '@pineliner/simple-rest/server';

const app = express();
app.use(express.json());

// Create manager with default '/query' path
const simpleRest = createManager();

// Method 1: Direct resolver registration
simpleRest.resolver('users', async (payload, req) => {
  // Implement your users query logic here
  return {
    data: [],
    pagination: null,
    success: true
  };
});

// Method 2: Using Resolver groups (like Express Router)
const apiV1 = createResolver(); // or new Resolver()

apiV1.resolver('posts')
  .select(async (payload, req) => {
    // Handle SELECT operations
    return { data: [], success: true };
  })
  .insert(async (payload, req) => {
    // Handle INSERT operations
    return { data: payload.instruction?.payload, success: true };
  })
  .update(async (payload, req) => {
    // Handle UPDATE operations
    return { data: {}, success: true };
  })
  .delete(async (payload, req) => {
    // Handle DELETE operations
    return { data: null, success: true };
  });

apiV1.resolver('comments', async (payload, req) => {
  // Default handler for all operations
  return { data: [], success: true };
});

// Register the resolver group with path prefix
simpleRest.use('api/v1', apiV1);

// Method 3: Admin resolvers with different path
const adminResolver = createResolver();

adminResolver.resolver('users')
  .select(async (payload, req) => {
    // Admin-specific user queries
    return { data: [], success: true };
  })
  .custom('ban', async (payload, req) => {
    // Custom ban instruction
    return { data: { banned: true }, success: true };
  });

adminResolver.resolver('analytics', async (payload, req) => {
  // Analytics data
  return { data: { metrics: {} }, success: true };
});

// Register admin resolvers
simpleRest.use('admin', adminResolver);

// Apply middleware
app.use(simpleRest.middleware);

app.listen(3000, () => {
  console.log('Server running on port 3000');
  console.log('Resolvers:', simpleRest.getResolvers());
});
```

#### Using Grouped Resolvers from Client

```typescript
import { createClient } from '@pineliner/simple-rest/client';

const client = createClient('http://localhost:3000');

// Access resolvers with path prefixes
// These will query: api/v1/posts, api/v1/comments, admin/users, admin/analytics

// API v1 posts
const posts = await client.from('api/v1/posts').select('*');
const newPost = await client.from('api/v1/posts').insert({ title: 'New Post' });

// API v1 comments
const comments = await client.from('api/v1/comments').select('*');

// Admin users with custom instruction
const adminUsers = await client.from('admin/users').select('*');
const bannedUser = await client.from('admin/users')
  .instruction({ name: 'ban', payload: { reason: 'spam' } })
  .eq('id', 123);

// Admin analytics
const analytics = await client.from('admin/analytics').select('*');
```

## Build

```bash
npm run build        # Build both client and server
npm run build:client # Build client only
npm run build:server # Build server only
```