Skip to main content

perspective_viewer/
lib.rs

1// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2// ┃ ██████ ██████ ██████       █      █      █      █      █ █▄  ▀███ █       ┃
3// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█  ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄  ▀█ █ ▀▀▀▀▀ ┃
4// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄   █ ▄▄▄▄▄ ┃
5// ┃ █      ██████ █  ▀█▄       █ ██████      █      ███▌▐███ ███████▄ █       ┃
6// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7// ┃ Copyright (c) 2017, the Perspective Authors.                              ┃
8// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9// ┃ This file is part of the Perspective library, distributed under the terms ┃
10// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
13//! The API for the [`@perspective-dev/viewer`](https://perspective-dev.github.io)
14//! JavaScript library.
15
16// Required by yew's `html` macro.
17#![recursion_limit = "1024"]
18#![feature(const_type_name)]
19#![feature(iter_intersperse)]
20#![feature(stmt_expr_attributes)]
21#![feature(try_blocks)]
22#![allow(async_fn_in_trait)]
23#![warn(
24    clippy::all,
25    clippy::panic_in_result_fn,
26    clippy::fallible_impl_from,
27    clippy::unneeded_field_pattern
28)]
29#![deny(clippy::await_holding_refcell_ref)]
30
31#[cfg(feature = "llm-agent")]
32mod agent;
33pub mod components;
34pub mod config;
35pub mod custom_elements;
36mod custom_events;
37mod derived;
38pub mod exprtk;
39mod js;
40mod presentation;
41mod root;
42
43#[doc(hidden)]
44pub mod queries;
45mod renderer;
46mod session;
47
48#[doc(hidden)]
49pub mod tasks;
50pub mod ui;
51pub mod utils;
52mod workspace;
53
54#[macro_use]
55extern crate macro_rules_attribute;
56extern crate alloc;
57
58use std::cell::RefCell;
59
60use perspective_js::utils::*;
61use wasm_bindgen::prelude::*;
62
63use crate::custom_elements::debug_plugin::PerspectiveDebugPluginElement;
64use crate::custom_elements::viewer::PerspectiveViewerElement;
65use crate::utils::define_web_component;
66
67#[wasm_bindgen(typescript_custom_section)]
68const TS_APPEND_CONTENT: &'static str = r#"
69import type {
70    ColumnType,
71    ColumnWindow,
72    DeleteOptions,
73    Features,
74    JoinOptions,
75    OnRemoveData,
76    OnUpdateData,
77    OnUpdateOptions,
78    Scalar,
79    SystemInfo,
80    TableInitOptions,
81    TypedArrayWindow,
82    UpdateOptions,
83    ViewConfig,
84    ViewConfigUpdate,
85    ViewWindow,
86} from "@perspective-dev/client";
87
88export type * from "../../src/ts/ts-rs/ViewerConfig.d.ts";
89export type * from "../../src/ts/ts-rs/ViewerConfigUpdate.d.ts";
90export type * from "../../src/ts/ts-rs/ViewerConfigInitial.d.ts";
91export type * from "../../src/ts/ts-rs/PluginStaticConfig.d.ts";
92export type * from "../../src/ts/ts-rs/WorkspaceConfig.d.ts";
93export type * from "../../src/ts/ts-rs/TableRef.d.ts";
94export type * from "../../src/ts/ts-rs/DerivedTableConfig.d.ts";
95export type * from "../../src/ts/ts-rs/WorkspaceConfigUpdate.d.ts";
96export type * from "../../src/ts/ts-rs/ExportMethod.d.ts";
97export type * from "../../src/ts/ts-rs/PanelOptions.d.ts";
98export type * from "../../src/ts/ts-rs/RestoreOptions.d.ts";
99export type * from "../../src/ts/ts-rs/RestoreWorkspaceOptions.d.ts";
100export type * from "../../src/ts/ts-rs/AddPanelOptions.d.ts";
101export type * from "../../src/ts/ts-rs/SaveWorkspaceOptions.d.ts";
102export type * from "../../src/ts/ts-rs/ClientOptions.d.ts";
103export type * from "../../src/ts/ts-rs/ExportOptions.d.ts";
104export type * from "../../src/ts/ts-rs/GetTableOptions.d.ts";
105export type * from "../../src/ts/ts-rs/GetClientOptions.d.ts";
106export type * from "../../src/ts/ts-rs/GetViewOptions.d.ts";
107export type * from "../../src/ts/ts-rs/GetViewMode.d.ts";
108export type * from "../../src/ts/ts-rs/CustomNumberFormatConfig.d.ts";
109export type * from "../../src/ts/ts-rs/NumberFormatStyle.d.ts";
110export type * from "../../src/ts/ts-rs/Notation.d.ts";
111export type * from "../../src/ts/ts-rs/DatetimeFormatType.d.ts";
112
113import type {GetTableOptions} from "../../src/ts/ts-rs/GetTableOptions.d.ts";
114import type {PanelOptions} from "../../src/ts/ts-rs/PanelOptions.d.ts";
115import type {RestoreOptions} from "../../src/ts/ts-rs/RestoreOptions.d.ts";
116import type {RestoreWorkspaceOptions} from "../../src/ts/ts-rs/RestoreWorkspaceOptions.d.ts";
117import type {AddPanelOptions} from "../../src/ts/ts-rs/AddPanelOptions.d.ts";
118import type {SaveWorkspaceOptions} from "../../src/ts/ts-rs/SaveWorkspaceOptions.d.ts";
119import type {ExportOptions} from "../../src/ts/ts-rs/ExportOptions.d.ts";
120import type {GetClientOptions} from "../../src/ts/ts-rs/GetClientOptions.d.ts";
121import type {GetViewOptions} from "../../src/ts/ts-rs/GetViewOptions.d.ts";
122import type {ClientOptions} from "../../src/ts/ts-rs/ClientOptions.d.ts";
123import type {ViewerConfig} from "../../src/ts/ts-rs/ViewerConfig.d.ts";
124import type {ViewerConfigUpdate} from "../../src/ts/ts-rs/ViewerConfigUpdate.d.ts";
125import type {ViewerConfigInitial} from "../../src/ts/ts-rs/ViewerConfigInitial.d.ts";
126import type {WorkspaceConfig} from "../../src/ts/ts-rs/WorkspaceConfig.d.ts";
127import type {WorkspaceConfigUpdate} from "../../src/ts/ts-rs/WorkspaceConfigUpdate.d.ts";
128"#;
129
130/// Register a plugin globally.
131#[wasm_bindgen]
132#[allow(non_snake_case)]
133pub fn registerPlugin(name: &str) {
134    use crate::renderer::*;
135    PLUGIN_REGISTRY.register_plugin(name);
136}
137
138/// Register this crate's Custom Elements in the browser's current session.
139///
140/// This must occur before calling any public API methods on these Custom
141/// Elements from JavaScript, as the methods themselves won't be defined yet.
142/// By default, this crate does not register `PerspectiveViewerElement` (as to
143/// preserve backwards-compatible synchronous API).
144#[cfg(not(feature = "external-bootstrap"))]
145#[wasm_bindgen(js_name = "init")]
146pub fn js_init(module: js_sys::WebAssembly::Module, url: web_sys::Url) {
147    console_error_panic_hook::set_once();
148    perspective_js::utils::set_global_logging();
149    define_web_components!("export * as psp from '../../perspective-viewer.js'");
150    MODULE.with_borrow_mut(|f| {
151        *f = Some((module, url));
152    });
153
154    tracing::info!("Perspective initialized.");
155}
156
157thread_local! {
158    static MODULE: RefCell<Option<(js_sys::WebAssembly::Module, web_sys::Url)>> = RefCell::default();
159}
160
161#[cfg(not(feature = "external-bootstrap"))]
162#[wasm_bindgen(js_name = "get_wasm_module")]
163pub fn js_get_module() -> Result<js_sys::WebAssembly::Module, JsValue> {
164    MODULE
165        .with_borrow(|f| f.clone().map(|x| x.0))
166        .ok_or_else(|| "Uninited module".into())
167}
168
169#[cfg(not(feature = "external-bootstrap"))]
170#[wasm_bindgen(js_name = "get_worker_url")]
171pub fn js_get_worker_url() -> Result<web_sys::Url, JsValue> {
172    MODULE
173        .with_borrow(|f| f.clone().map(|x| x.1))
174        .ok_or_else(|| "Uninited module".into())
175}
176
177/// Register Web Components with the global registry, given a Perspective
178/// module.
179///
180/// This function shouldn't be called directly;  instead, use the
181/// `define_web_components!` macro to both call this method and hook the
182/// wasm_bindgen module object.
183pub fn bootstrap_web_components(psp: &JsValue) {
184    define_web_component::<PerspectiveViewerElement>(psp);
185    define_web_component::<PerspectiveDebugPluginElement>(psp);
186}
187
188/// Defining the web components needs an extern struct to reference the
189/// generated JavaSript glue. This is parameterized by an attribute macro which
190/// needs to be determined by the top-level compiled module - the JavaScript
191/// glue code emitted by `wasm-bindgen-cli`.
192#[macro_export]
193macro_rules! define_web_components {
194    ($x:expr) => {{
195        #[wasm_bindgen::prelude::wasm_bindgen(inline_js = $x)]
196        extern "C" {
197            #[wasm_bindgen::prelude::wasm_bindgen(js_name = "psp")]
198            #[wasm_bindgen::prelude::wasm_bindgen(thread_local_v2)]
199            pub static PSP: wasm_bindgen::prelude::JsValue;
200        }
201
202        PSP.with(|x| $crate::bootstrap_web_components(x));
203    }};
204}