- 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
5.7 KiB
Migration Guide — Adopting @bytelyst/* Packages
Step-by-step guide for integrating @bytelyst/* shared packages into a new product or dashboard.
Prerequisites
-
Clone both repos side-by-side:
code/ ├── learning_ai_common_plat/ # shared packages + services └── your-product/ # your product repo -
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 buildinlearning_ai_common_platbeforenpm installin your product. Thefile:refs need compileddist/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
productIdfield 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.ymlsetscontext: .withdockerfile: services/<name>/Dockerfile
Next.js Dashboards (in your product repo)
Dashboards need pre-built packages copied into the build context:
- Run
./scripts/docker-prep-dashboards.shto copy@bytelyst/*into.docker-deps/ - Dockerfile copies
.docker-deps/@bytelyst/to/learning_ai_common_plat/packages/sofile:refs resolve
Checklist
pnpm buildinlearning_ai_common_platruns cleannpm installin your product resolves all@bytelyst/*depstsc --noEmitpasses in your product- Every Cosmos document includes
productIdfield JWT_SECRETis set and shared across all services- No
console.login production code (usereq.logor@bytelyst/logger) - Commit:
feat(integration): wire @bytelyst/* shared packages