A data visualization and analytics component, especially well-suited for large and/or streaming datasets.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Perspective is an interactive analytics and data visualization component, especially well-suited for large and streaming datasets. It features a fast, memory-efficient streaming query engine written in C++ and compiled for WebAssembly, with framework-agnostic user interface components and comprehensive APIs for JavaScript/TypeScript, Python, and Rust environments.
npm install @finos/perspective@finos/perspective-viewer - Web component UI@finos/perspective-react - React integration@finos/perspective-viewer-datagrid - Data grid plugin@finos/perspective-viewer-d3fc - Chart plugin@finos/perspective-jupyterlab - JupyterLab extensionBrowser Environment:
// Main Perspective engine
import perspective from "@finos/perspective";
// Web components and viewer
import "@finos/perspective-viewer";
import "@finos/perspective-viewer-datagrid";
import "@finos/perspective-viewer-d3fc";
// React components
import { PerspectiveViewer } from "@finos/perspective-react";Node.js Environment:
// Main Perspective engine (default auto-detects environment)
import perspective from "@finos/perspective";
// Explicit Node.js import
import perspective from "@finos/perspective/node";
// Server components
import { WebSocketServer, PerspectiveServer } from "@finos/perspective";CommonJS (Node.js):
const perspective = require("@finos/perspective");
const { WebSocketServer } = require("@finos/perspective");CDN (Browser):
<script src="https://unpkg.com/@finos/perspective/dist/cdn/perspective.js"></script>
<script src="https://unpkg.com/@finos/perspective-viewer/dist/cdn/perspective-viewer.js"></script>Core Data Engine:
import perspective from "@finos/perspective";
// Node.js: Direct table creation (synchronous client)
const table = await perspective.table([
{ name: "Alice", age: 25, active: true },
{ name: "Bob", age: 30, active: false },
]);
// Browser: Create Web Worker client
const client = await perspective.worker();
const table = await client.table([
{ name: "Alice", age: 25, active: true },
{ name: "Bob", age: 30, active: false },
]);
// Create a view with aggregation and filtering
const view = await table.view({
group_by: ["active"],
aggregates: { age: "mean" },
filter: [["age", ">", 20]],
});
// Export data
const data = await view.to_json();
console.log(data);
// Clean up resources
await view.delete();
await table.delete();Web Components (Browser):
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/@finos/perspective/dist/cdn/perspective.js"></script>
<script src="https://unpkg.com/@finos/perspective-viewer/dist/cdn/perspective-viewer.js"></script>
<script src="https://unpkg.com/@finos/perspective-viewer-datagrid/dist/cdn/perspective-viewer-datagrid.js"></script>
</head>
<body>
<perspective-viewer id="viewer"></perspective-viewer>
<script>
const data = [
{ name: "Alice", age: 25, sales: 1000 },
{ name: "Bob", age: 30, sales: 1500 },
];
document.getElementById("viewer").load(perspective.table(data));
</script>
</body>
</html>React Integration:
import React from "react";
import { PerspectiveViewer } from "@finos/perspective-react";
import perspective from "@finos/perspective";
function App() {
const data = [
{ name: "Alice", age: 25, sales: 1000 },
{ name: "Bob", age: 30, sales: 1500 },
];
return (
<PerspectiveViewer
table={perspective.table(data)}
group_by={["name"]}
aggregates={{ sales: "sum" }}
/>
);
}Server-Side (Node.js):
import { WebSocketServer } from "@finos/perspective";
// Create WebSocket server with static assets
const server = new WebSocketServer({
port: 8080,
assets: ["./dist", "./public"],
});
console.log("Perspective server running on http://localhost:8080");Perspective is built around several key components:
Client creation and connection management for different environments and transport protocols.
// Browser Web Worker client
function worker(worker?: Promise<SharedWorker | ServiceWorker | Worker>): Promise<Client>;
// WebSocket client (browser and Node.js)
function websocket(url: string): Promise<Client>;
// Initialization functions (browser only)
function init_client(wasm: PerspectiveWasm, disable_stage_0?: boolean): void;
function init_server(wasm: PerspectiveWasm, disable_stage_0?: boolean): void;Core table functionality for creating, updating, and managing columnar data structures.
interface Client {
table(data: TableInitData, options?: TableInitOptions): Promise<Table>;
open_table(name: string): Promise<Table>;
get_hosted_table_names(): Promise<string[]>;
}
interface Table {
schema(): Promise<Schema>;
size(): Promise<number>;
update(data: TableInitData, options?: UpdateOptions): Promise<void>;
clear(): Promise<void>;
delete(options?: DeleteOptions): Promise<void>;
}Query interface providing aggregations, pivots, filtering, and data export capabilities.
interface Table {
view(config?: ViewConfigUpdate): Promise<View>;
}
interface View {
to_json(window?: ViewWindow): Promise<Record<string, any>[]>;
to_arrow(window?: ViewWindow): Promise<ArrayBuffer>;
to_csv(window?: ViewWindow): Promise<string>;
on_update(callback: Function, options?: OnUpdateOptions): Promise<number>;
delete(): Promise<void>;
}Server-side components for hosting Perspective engines and WebSocket communication (Node.js only).
class PerspectiveServer {
constructor(options?: PerspectiveServerOptions);
make_session(send_response: (buffer: Uint8Array) => Promise<void>): Promise<Session>;
}
class WebSocketServer {
constructor(options?: { port?: number; assets?: string[]; server?: PerspectiveServer });
close(): Promise<void>;
}// Data input formats
type TableInitData = string | ArrayBuffer | Record<string, unknown[]> | Record<string, unknown>[];
// Table configuration
interface TableInitOptions {
limit?: number;
index?: string;
name?: string;
format?: "json" | "columns" | "csv" | "arrow";
}
// Update operation options
interface UpdateOptions {
format?: "json" | "columns" | "csv" | "arrow";
port_id?: number;
}
// Delete operation options
interface DeleteOptions {
lazy?: boolean;
}
// View configuration
interface ViewConfigUpdate {
columns?: string[];
group_by?: string[];
split_by?: string[];
aggregates?: Record<string, string>;
sort?: [string, "asc" | "desc"][];
filter?: [string, string, any][];
expressions?: Record<string, string>;
}
// Update callback options
interface OnUpdateOptions {
mode?: "row";
}
// Update event data
interface OnUpdateData {
port_id: number;
delta?: ArrayBuffer;
}
// Schema definition
type Schema = Record<string, "boolean" | "date" | "datetime" | "float" | "integer" | "string">;
// Data window specification
interface ViewWindow {
start_row?: number;
end_row?: number;
start_col?: number;
end_col?: number;
}
// System information
interface SystemInfo {
server_used?: number;
server_heap?: number;
client_used?: number;
client_heap?: number;
timestamp?: number;
}
// WebAssembly module types
type PerspectiveWasm = ArrayBuffer | Response | WebAssembly.Module | Promise<ArrayBuffer | Response | Object>;
// Aggregation functions
type AggregateFunction =
| "abs sum" | "and" | "any" | "avg" | "count" | "distinct count"
| "dominant" | "first" | "high" | "last" | "low" | "max" | "mean"
| "median" | "min" | "or" | "pct sum parent" | "pct sum grand total"
| "stddev" | "sum" | "sum abs" | "sum not null" | "unique" | "var";
// Filter operators
type FilterOperator =
| "==" | "!=" | ">" | "<" | ">=" | "<="
| "begins with" | "ends with" | "contains" | "in" | "not in"
| "is null" | "is not null";