Package Exports
- @epochlab/epoch-protos
- @epochlab/epoch-protos/chart_def
- @epochlab/epoch-protos/common
- @epochlab/epoch-protos/table_def
- @epochlab/epoch-protos/tearsheet
- @epochlab/epoch-protos/web/chart_def
- @epochlab/epoch-protos/web/common
- @epochlab/epoch-protos/web/table_def
- @epochlab/epoch-protos/web/tearsheet
Readme
@epochlab/epoch-protos
TypeScript definitions generated from Protocol Buffers for EpochFolio models - optimized for Next.js and web applications.
🚀 Quick Start for Next.js
Installation
npm install @epochlab/epoch-protos
# or
yarn add @epochlab/epoch-protos
# or
pnpm add @epochlab/epoch-protosBasic Usage
import { ChartDef, EpochFolioDashboardWidget, EpochFolioCategory } from '@epochlab/epoch-protos';
// Create a chart definition
const chart = new ChartDef();
chart.setId('portfolio-returns');
chart.setTitle('Portfolio Returns Over Time');
chart.setType(EpochFolioDashboardWidget.EPOCH_FOLIO_DASHBOARD_WIDGET_LINES);
chart.setCategory(EpochFolioCategory.EPOCH_FOLIO_CATEGORY_STRATEGY_BENCHMARK);
console.log(chart.getTitle()); // "Portfolio Returns Over Time"📦 Bundle Size Optimization
Web-Optimized Imports (Recommended for Web Apps)
For optimal bundle size in web applications, use the web-optimized imports:
// ✅ Recommended: Web-optimized imports (smallest bundle)
import { ChartDef } from '@epochlab/epoch-protos/web/chart_def';
import { TearSheet } from '@epochlab/epoch-protos/web/tearsheet';
import { EpochFolioCategory } from '@epochlab/epoch-protos/web/common';
// ✅ Good: Standard tree-shaken imports
import { ChartDef } from '@epochlab/epoch-protos/chart_def';
import { TearSheet } from '@epochlab/epoch-protos/tearsheet';
import { EpochFolioCategory } from '@epochlab/epoch-protos/common';
// ❌ Avoid: Full import (largest bundle - 624KB+)
import { ChartDef, TearSheet, EpochFolioCategory } from '@epochlab/epoch-protos';Bundle Size Comparison
| Import Method | Bundle Size | Use Case |
|---|---|---|
/web/* imports |
~88-280KB per module | Web apps (recommended) |
| Individual imports | ~88-304KB per module | Node.js apps |
| Full import | 624KB+ | Development only |
🎯 Next.js Integration Examples
Server-Side Rendering (SSR)
// pages/api/charts.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { ChartDef, EpochFolioDashboardWidget } from '@epochlab/epoch-protos';
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const chart = new ChartDef();
chart.setId('api-chart');
chart.setTitle('Server-Generated Chart');
chart.setType(EpochFolioDashboardWidget.EPOCH_FOLIO_DASHBOARD_WIDGET_BAR);
res.status(200).json({
chart: chart.toObject()
});
}Client-Side Components
// components/PortfolioChart.tsx
import React, { useEffect, useState } from 'react';
import { ChartDef, EpochFolioDashboardWidget } from '@epochlab/epoch-protos';
export default function PortfolioChart() {
const [chart, setChart] = useState<ChartDef | null>(null);
useEffect(() => {
const chartDef = new ChartDef();
chartDef.setId('portfolio-chart');
chartDef.setTitle('Portfolio Performance');
chartDef.setType(EpochFolioDashboardWidget.EPOCH_FOLIO_DASHBOARD_WIDGET_LINES);
setChart(chartDef);
}, []);
if (!chart) return <div>Loading...</div>;
return (
<div>
<h2>{chart.getTitle()}</h2>
<p>Chart ID: {chart.getId()}</p>
</div>
);
}App Router (Next.js 13+)
// app/dashboard/page.tsx
import { ChartDef, TearSheet, EpochFolioCategory } from '@epochlab/epoch-protos';
export default function DashboardPage() {
const tearsheet = new TearSheet();
return (
<div>
<h1>Portfolio Dashboard</h1>
{/* Your dashboard content */}
</div>
);
}📊 Available Models
Common Types (common.proto)
- Enums:
EpochFolioCategory,EpochFolioDashboardWidget,EpochFolioType,AxisType - Messages:
Scalar,Array
Chart Definitions (chart_def.proto)
ChartDef,LinesDef,BarDef,HeatMapDef,HistogramDefBoxPlotDef,XRangeDef,PieDef,Point,Line
Table Definitions (table_def.proto)
Table,CardDef,ColumnDef,TableData,TableRow
TearSheet Definitions (tearsheet.proto)
TearSheet,FullTearSheet,CardDefList,ChartList,TableList
🔧 TypeScript Configuration
tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"lib": ["ES2020", "DOM"],
"module": "ESNext",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
esmExternals: true,
},
webpack: (config) => {
// Ensure proper module resolution
config.resolve.fallback = {
...config.resolve.fallback,
fs: false,
};
return config;
},
};
module.exports = nextConfig;🎨 Usage Patterns
Creating Dashboard Widgets
import {
ChartDef,
Table,
CardDef,
EpochFolioDashboardWidget,
EpochFolioCategory
} from '@epochlab/epoch-protos';
// Create a line chart
const lineChart = new ChartDef();
lineChart.setId('returns-chart');
lineChart.setTitle('Portfolio Returns');
lineChart.setType(EpochFolioDashboardWidget.EPOCH_FOLIO_DASHBOARD_WIDGET_LINES);
lineChart.setCategory(EpochFolioCategory.EPOCH_FOLIO_CATEGORY_STRATEGY_BENCHMARK);
// Create a data table
const dataTable = new Table();
dataTable.setTitle('Holdings Summary');
dataTable.setType(EpochFolioDashboardWidget.EPOCH_FOLIO_DASHBOARD_WIDGET_DATA_TABLE);
// Create a card widget
const card = new CardDef();
card.setTitle('Total Return');
card.setValue('12.5%');Working with TearSheets
import { TearSheet, FullTearSheet, ChartDef, Table } from '@epochlab/epoch-protos';
// Create a single tearsheet
const tearsheet = new TearSheet();
// Add charts to tearsheet
const chart = new ChartDef();
chart.setId('risk-chart');
chart.setTitle('Risk Analysis');
tearsheet.getChartsList().push(chart);
// Create a full tearsheet with multiple categories
const fullTearSheet = new FullTearSheet();
fullTearSheet.getCategoriesMap().set('risk', tearsheet);🚀 Performance Tips
- Use Web-Optimized Imports: Use
/web/*imports for smallest bundle size - Lazy Loading: Load protobuf models only when needed
- Server-Side Generation: Pre-generate data on the server
- Bundle Analysis: Use
@next/bundle-analyzerto monitor bundle size - Code Splitting: Split protobuf usage into separate chunks
// ✅ Best: Web-optimized lazy loading
const loadChart = async () => {
const { ChartDef } = await import('@epochlab/epoch-protos/web/chart_def');
return new ChartDef();
};
// ✅ Good: Standard lazy loading
const loadChart = async () => {
const { ChartDef } = await import('@epochlab/epoch-protos/chart_def');
return new ChartDef();
};
// ✅ Good: Server-side generation
export async function getServerSideProps() {
const { ChartDef } = await import('@epochlab/epoch-protos/web/chart_def');
const chart = new ChartDef();
// ... populate chart data
return {
props: {
chartData: chart.toObject()
}
};
}
// ✅ Good: Dynamic imports for code splitting
const ChartComponent = dynamic(() => import('./ChartComponent'), {
loading: () => <div>Loading chart...</div>
});🔍 Debugging
Enable Protobuf Debugging
// Enable debug logging
import { util } from 'protobufjs';
util.debug = true;Common Issues
- Module Resolution: Ensure your
tsconfig.jsonhas proper module resolution - Bundle Size: Use tree-shaking to reduce bundle size
- SSR Compatibility: Protobuf models work in both server and client environments
📚 API Reference
ChartDef Methods
chart.setId(id: string): void
chart.getId(): string
chart.setTitle(title: string): void
chart.getTitle(): string
chart.setType(type: EpochFolioDashboardWidget): void
chart.getType(): EpochFolioDashboardWidget
chart.toObject(): object
chart.fromObject(obj: object): voidTable Methods
table.setTitle(title: string): void
table.getTitle(): string
table.setType(type: EpochFolioDashboardWidget): void
table.getType(): EpochFolioDashboardWidget
table.getColumnsList(): ColumnDef[]
table.getDataList(): TableRow[]🤝 Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Test with Next.js applications
- Submit a pull request
📄 License
MIT License - see LICENSE file for details.