learning_ai_common_plat/docs/MIGRATION_GUIDE.md
saravanakumardb1 13e53d46bf docs: add MIGRATION_GUIDE.md + update ROADMAP to 89% (248/278)
- MIGRATION_GUIDE.md: step-by-step for adopting @bytelyst/* in new projects
- ROADMAP: Phase 3B 25/28 (user/tracker keep custom auth, removed unused deps)
- ROADMAP: Phase 6 23/28 (docs updated, cleanup done, E2E needs running services)
- Test count: 277 tests across 16 suites
2026-02-13 00:09:01 -08:00

5.7 KiB

Migration Guide — Adopting @bytelyst/* Packages

Step-by-step guide for integrating @bytelyst/* shared packages into a new product or dashboard.


Prerequisites

  1. Clone both repos side-by-side:

    code/
    ├── learning_ai_common_plat/   # shared packages + services
    └── your-product/              # your product repo
    
  2. Build all packages:

    cd learning_ai_common_plat
    pnpm install
    pnpm build
    

Step 1: Add Package Dependencies

In your product's package.json, add file: references to the packages you need:

{
  "dependencies": {
    "@bytelyst/errors": "file:../learning_ai_common_plat/packages/errors",
    "@bytelyst/cosmos": "file:../learning_ai_common_plat/packages/cosmos",
    "@bytelyst/config": "file:../learning_ai_common_plat/packages/config",
    "@bytelyst/auth": "file:../learning_ai_common_plat/packages/auth",
    "@bytelyst/api-client": "file:../learning_ai_common_plat/packages/api-client",
    "@bytelyst/logger": "file:../learning_ai_common_plat/packages/logger"
  }
}

Adjust the ../ path depth based on your directory structure. Then run npm install.

Important: Run pnpm build in learning_ai_common_plat before npm install in your product. The file: refs need compiled dist/ directories.


Step 2: Wire Up Cosmos DB

Create src/lib/cosmos.ts:

import {
  getCosmosClient,
  getDatabase,
  registerContainers,
  getRegisteredContainer,
} from '@bytelyst/cosmos';

// Define your containers
const CONTAINERS = [
  'users',
  'settings',
  'audit_log',
  // ... your containers
];

let initialized = false;

export async function initializeAllContainers() {
  if (initialized) return;
  await registerContainers(CONTAINERS);
  initialized = true;
}

export function getContainer(name: string) {
  return getRegisteredContainer(name);
}

export { getCosmosClient, getDatabase, initializeAllContainers };

Required env vars: COSMOS_ENDPOINT, COSMOS_KEY, COSMOS_DATABASE


Step 3: Wire Up Auth (Server-Side)

Create src/lib/auth-server.ts:

import { createJwtUtils, hashPassword, verifyPassword } from '@bytelyst/auth';

const jwt = createJwtUtils({
  issuer: 'your-product-name',
  accessTokenExpiry: '1h',
  refreshTokenExpiry: '30d',
});

export { jwt, hashPassword, verifyPassword };

Required env var: JWT_SECRET (min 32 chars)


Step 4: Wire Up Product Identity

Create src/lib/product-config.ts:

import { loadProductIdentity } from '@bytelyst/config';

const identity = loadProductIdentity();
export const PRODUCT_ID = identity.productId;
export const PRODUCT_NAME = identity.productName;

Required env vars: DEFAULT_PRODUCT_ID (or set in shared/product.json)

Rule: Every Cosmos document MUST include a productId field using this value.


Step 5: Wire Up Service Clients (If Using Microservices)

Create src/lib/billing-client.ts (example):

import { createApiClient } from '@bytelyst/api-client';

const billingApi = createApiClient({
  baseUrl: process.env.BILLING_SERVICE_URL || 'http://localhost:4002',
  getToken: () => {
    // Return the current user's JWT token
    return localStorage.getItem('access_token');
  },
});

export async function getSubscription(userId: string) {
  return billingApi.fetch(`/api/subscriptions/${userId}`);
}

Step 6: Wire Up Error Handling

Import typed errors for consistent HTTP error responses:

import {
  BadRequestError,
  UnauthorizedError,
  ForbiddenError,
  NotFoundError,
  ConflictError,
} from '@bytelyst/errors';

// In your API routes:
if (!user) throw new NotFoundError('User not found');
if (!isAdmin) throw new ForbiddenError('Admin access required');

Step 7: Wire Up Auth Context (React Dashboards)

For admin-style dashboards, use the factory:

import { createAuthProvider } from '@bytelyst/react-auth';

interface MyUser {
  id: string;
  email: string;
  role: string;
}

const { AuthProvider, useAuth } = createAuthProvider<MyUser>({
  storagePrefix: 'myapp',
  onLoginFallback: async (email, password) => {
    const res = await fetch('/api/auth/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, password }),
    });
    if (!res.ok) return null;
    const data = await res.json();
    return { user: data.user, token: data.accessToken };
  },
});

export { AuthProvider, useAuth };

Note: If your auth flow needs SSO cookies, registration, or session restore via API calls, keep a custom auth context instead.


Docker Builds

Fastify Services (in learning_ai_common_plat)

Services use pnpm monorepo builds with repo root as context. See any service's Dockerfile for the pattern:

  • Multi-stage: pnpm install → build packages + service → pnpm deploy
  • docker-compose.yml sets context: . with dockerfile: services/<name>/Dockerfile

Next.js Dashboards (in your product repo)

Dashboards need pre-built packages copied into the build context:

  1. Run ./scripts/docker-prep-dashboards.sh to copy @bytelyst/* into .docker-deps/
  2. Dockerfile copies .docker-deps/@bytelyst/ to /learning_ai_common_plat/packages/ so file: refs resolve

Checklist

  • pnpm build in learning_ai_common_plat runs clean
  • npm install in your product resolves all @bytelyst/* deps
  • tsc --noEmit passes in your product
  • Every Cosmos document includes productId field
  • JWT_SECRET is set and shared across all services
  • No console.log in production code (use req.log or @bytelyst/logger)
  • Commit: feat(integration): wire @bytelyst/* shared packages