# Mana Core Integration Checklist

Use this checklist when integrating `@mana-core/nestjs-integration` into a new NestJS project.

## Prerequisites ✓

- [ ] NestJS v10+ application set up
- [ ] `@nestjs/config` installed
- [ ] Node.js v18+ and npm/yarn
- [ ] Mana Core credentials obtained:
  - [ ] `MANA_SERVICE_URL`
  - [ ] `APP_ID`
  - [ ] `MANA_SUPABASE_SECRET_KEY` (service key)

---

## Backend Integration Steps

### 1. Installation

- [ ] Install the package:
  ```bash
  npm install git+https://github.com/Memo-2023/mana-core-nestjs-package.git
  ```

- [ ] Verify in `package.json`:
  ```json
  "@mana-core/nestjs-integration": "git+https://github.com/..."
  ```

### 2. Environment Configuration

- [ ] Create/update `.env` file:
  ```env
  MANA_SERVICE_URL=https://your-mana-instance.com
  APP_ID=your-app-id
  MANA_SUPABASE_SECRET_KEY=your-service-key
  NODE_ENV=development
  ```

- [ ] Add to `.env.example` (for team reference)

- [ ] Add `.env` to `.gitignore`

### 3. Module Configuration

- [ ] Import `ManaCoreModule` in `app.module.ts`

- [ ] Configure with `forRootAsync()`:
  ```typescript
  ManaCoreModule.forRootAsync({
    imports: [ConfigModule],
    useFactory: (configService: ConfigService) => ({
      manaServiceUrl: 'your-mana-url',
      appId: 'your-app-id',
      serviceKey: configService.get('MANA_SUPABASE_SECRET_KEY'),
      debug: configService.get('NODE_ENV') === 'development',
    }),
    inject: [ConfigService],
  })
  ```

- [ ] Test backend starts without errors

### 4. Protect Routes with AuthGuard

- [ ] Import `AuthGuard` in controller:
  ```typescript
  import { AuthGuard } from '@mana-core/nestjs-integration';
  ```

- [ ] Apply to controller or route:
  ```typescript
  @Controller('protected')
  @UseGuards(AuthGuard)
  export class ProtectedController {}
  ```

- [ ] Test: Verify 401 without token

### 5. Extract User Information

- [ ] Import `@CurrentUser()` decorator:
  ```typescript
  import { CurrentUser } from '@mana-core/nestjs-integration';
  ```

- [ ] Use in route handlers:
  ```typescript
  @Get('profile')
  async getProfile(@CurrentUser() user: JwtPayload) {
    return { userId: user.sub, email: user.email };
  }
  ```

- [ ] Test: Verify user data is extracted correctly

### 6. Integrate Credit System

- [ ] Inject `CreditClientService`:
  ```typescript
  constructor(private creditClient: CreditClientService) {}
  ```

- [ ] Add pre-flight credit validation:
  ```typescript
  const validation = await this.creditClient.validateCredits(
    userId,
    'operation_type',
    creditCost,
  );
  ```

- [ ] Add credit consumption after success:
  ```typescript
  await this.creditClient.consumeCredits(
    userId,
    'operation_type',
    creditCost,
    'Description',
    metadata,
  );
  ```

- [ ] Handle `InsufficientCreditsException`:
  ```typescript
  import { InsufficientCreditsException } from '@mana-core/nestjs-integration';
  ```

- [ ] Test: Verify credits are deducted

### 7. (Optional) Custom Token Decorator

- [ ] Create `@UserToken()` decorator for RLS:
  ```typescript
  // decorators/user.decorator.ts
  export const UserToken = createParamDecorator(
    (_data: unknown, ctx: ExecutionContext): string => {
      const request = ctx.switchToHttp().getRequest();
      const authHeader = request.headers.authorization;
      if (authHeader?.startsWith('Bearer ')) {
        return authHeader.substring(7);
      }
      return request.token;
    },
  );
  ```

- [ ] Use for database RLS:
  ```typescript
  @Get()
  async getData(
    @CurrentUser() user: JwtPayload,
    @UserToken() token: string,
  ) {
    return await this.db.query(userId, token);
  }
  ```

---

## Frontend Integration Steps

### 1. Configure API Base URL

- [ ] Create `.env` file:
  ```env
  EXPO_PUBLIC_STORYTELLER_BACKEND_URL=http://localhost:3002
  ```

- [ ] Create API utility (`utils/api.ts`):
  ```typescript
  export const API_BASE_URL = process.env.EXPO_PUBLIC_BACKEND_URL;
  ```

### 2. Create Auth Service

- [ ] Create `services/authService.ts`

- [ ] Implement sign-in:
  ```typescript
  signIn: async (email: string, password: string) => {
    const deviceInfo = await getDeviceInfo();
    const response = await fetch(`${BACKEND_URL}/auth/signin`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, password, deviceInfo }),
    });
    const data = await response.json();
    await storeTokens(data.appToken, data.refreshToken);
  }
  ```

- [ ] Implement sign-up

- [ ] Implement sign-out

- [ ] Test: Verify tokens are stored securely

### 3. Create Token Manager

- [ ] Create `services/tokenManager.ts`

- [ ] Implement `getValidToken()`:
  ```typescript
  getValidToken: async () => {
    let token = await storage.getItem('appToken');
    if (isExpiringSoon(token)) {
      await this.refreshToken();
      token = await storage.getItem('appToken');
    }
    return token;
  }
  ```

- [ ] Implement `refreshToken()`:
  ```typescript
  refreshToken: async () => {
    const refreshToken = await storage.getItem('refreshToken');
    const deviceInfo = await getDeviceInfo();
    const response = await fetch(`${BACKEND_URL}/auth/refresh`, {
      method: 'POST',
      body: JSON.stringify({ refreshToken, deviceInfo }),
    });
    const data = await response.json();
    await storeTokens(data.appToken, data.refreshToken);
  }
  ```

- [ ] Test: Verify automatic refresh works

### 4. Create Authenticated API Client

- [ ] Create `fetchWithAuth()` function:
  ```typescript
  export async function fetchWithAuth(endpoint: string, options = {}) {
    const token = await tokenManager.getValidToken();
    const response = await fetch(`${API_BASE_URL}${endpoint}`, {
      ...options,
      headers: {
        ...options.headers,
        'Authorization': `Bearer ${token}`,
      },
    });

    if (response.status === 401) {
      await tokenManager.refreshToken();
      // Retry request
    }

    return response;
  }
  ```

- [ ] Test: Verify authenticated requests work

### 5. Handle Credit Errors

- [ ] Create error handling utility:
  ```typescript
  export function isInsufficientCreditsError(error: any) {
    return error?.error === 'insufficient_credits';
  }
  ```

- [ ] Handle in UI:
  ```typescript
  if (data.error === 'insufficient_credits') {
    showPurchaseCreditsModal({
      required: data.requiredCredits,
      available: data.availableCredits,
    });
  }
  ```

- [ ] Test: Verify error is displayed correctly

### 6. Device Management

- [ ] Create `utils/deviceManager.ts`:
  ```typescript
  export class DeviceManager {
    static async getDeviceInfo() {
      return {
        deviceId: await getOrCreateDeviceId(),
        deviceName: Platform.OS,
        deviceType: Platform.OS as 'ios' | 'android' | 'web',
        userAgent: getUserAgent(),
      };
    }
  }
  ```

- [ ] Include in auth requests

- [ ] Test: Verify device info is sent

---

## Testing Steps

### Backend Tests

- [ ] Create unit tests with mocked services:
  ```typescript
  {
    provide: CreditClientService,
    useValue: {
      validateCredits: jest.fn().mockResolvedValue({
        hasCredits: true,
      }),
      consumeCredits: jest.fn(),
    },
  }
  ```

- [ ] Create integration tests with real Mana Core module

- [ ] Test credit validation flow

- [ ] Test insufficient credits error

- [ ] Run tests: `npm run test`

### Frontend Tests

- [ ] Test authentication flow

- [ ] Test token refresh

- [ ] Test authenticated API calls

- [ ] Test credit error handling

- [ ] Run tests: `npm run test`

---

## Production Deployment

### Backend

- [ ] Set production environment variables:
  ```env
  MANA_SERVICE_URL=https://production-mana.com
  APP_ID=production-app-id
  MANA_SUPABASE_SECRET_KEY=production-key
  NODE_ENV=production
  ```

- [ ] Disable debug logging (`debug: false`)

- [ ] Test health endpoint

- [ ] Deploy and monitor logs

### Frontend

- [ ] Update `.env` for production:
  ```env
  EXPO_PUBLIC_BACKEND_URL=https://your-api.com
  ```

- [ ] Build production bundle

- [ ] Test authentication flow

- [ ] Test API calls

- [ ] Deploy to stores (iOS/Android) or web

---

## Post-Integration Verification

- [ ] Sign-up flow works end-to-end

- [ ] Sign-in flow works end-to-end

- [ ] Token refresh works automatically

- [ ] Protected routes require authentication

- [ ] Credit validation prevents operations

- [ ] Credit consumption records transactions

- [ ] Insufficient credits error handled gracefully

- [ ] Sign-out clears tokens

- [ ] Multi-device support works

---

## Documentation

- [ ] Update README with Mana Core setup instructions

- [ ] Document custom operation types and credit costs

- [ ] Add environment variable documentation

- [ ] Create troubleshooting guide

- [ ] Document API endpoints

---

## Common Issues Checklist

If something doesn't work, check:

- [ ] Environment variables are set correctly
- [ ] Backend is running and accessible
- [ ] Service key is configured (for credit operations)
- [ ] Tokens are being stored and retrieved correctly
- [ ] Token expiration is being checked
- [ ] Device info is being sent with auth requests
- [ ] CORS is configured (if using web frontend)
- [ ] Network requests are not being blocked
- [ ] Debug logging is enabled for troubleshooting

---

## Support Resources

- **Full Integration Guide**: See `MANA_CORE_INTEGRATION_GUIDE.md`
- **Mana Core Docs**: https://docs.mana-core.com
- **GitHub Issues**: https://github.com/Memo-2023/mana-core-nestjs-package/issues
- **Example Code**: Check Storyteller project for working implementation

---

## Integration Complete! 🎉

Once all items are checked, your application is fully integrated with Mana Core.

**Estimated Time**: 2-4 hours for basic integration, 1-2 days for complete implementation with testing.

**Next Steps**:
1. Define your operation types and credit costs
2. Implement purchase flow for credits
3. Add analytics and monitoring
4. Set up role-based access control (if needed)
