├── .cargo └── config.toml ├── .editorconfig ├── .gitignore ├── .nvmrc ├── .yarnrc.yml ├── Cargo.toml ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── polars ├── dataframe.ts ├── index.ts ├── io.ts ├── lazy │ ├── frame │ │ └── index.ts │ └── index.ts ├── series │ └── index.ts ├── utils.ts └── worker.ts ├── rome.json ├── rust-toolchain ├── server.py ├── src ├── conversion │ ├── extern_iterator.rs │ ├── extern_struct.rs │ ├── from.rs │ ├── mod.rs │ └── prelude.rs ├── dataframe.rs ├── datatypes.rs ├── error.rs ├── io.rs ├── lazy │ ├── dataframe.rs │ ├── expr │ │ ├── conversion.rs │ │ ├── mod.rs │ │ └── string.rs │ ├── lazy_functions.rs │ └── mod.rs ├── lib.rs ├── series.rs └── utils.rs ├── tsconfig.json └── yarn.lock /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.wasm32-unknown-unknown] 2 | rustflags = ["-C", "target-feature=+atomics,+bulk-memory,+mutable-globals", "-C", "link-arg=--max-memory=4294967296"] 3 | 4 | [unstable] 5 | build-std = ["panic_abort", "std"] 6 | 7 | [build] 8 | target = "wasm32-unknown-unknown" -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | 7 | [*.{js,json,yml}] 8 | charset = utf-8 9 | indent_style = space 10 | indent_size = 2 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | bin/ 5 | pkg/ 6 | node_modules/ 7 | wasm-pack.log 8 | target/ 9 | 10 | .yarn 11 | .pnp.* 12 | 13 | coverage/ 14 | bin/ 15 | .vscode 16 | *.node 17 | docs/ 18 | dist/ 19 | examples/** -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 16 2 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | yarnPath: .yarn/releases/yarn-3.3.1.cjs 2 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Cory Grinstead"] 3 | documentation = "https://pola-rs.github.io/polars-book/" 4 | edition = "2021" 5 | homepage = "https://github.com/pola-rs/polars" 6 | license = "MIT" 7 | name = "browser" 8 | repository = "https://github.com/pola-rs/js-polars" 9 | version = "0.0.1-alpha.3" 10 | 11 | [package.metadata.wasm-pack.profile.dev] 12 | wasm-opt = false 13 | 14 | [package.metadata.wasm-pack.profile.profiling] 15 | wasm-opt = false 16 | 17 | [package.metadata.wasm-pack.profile.release] 18 | wasm-opt = false 19 | 20 | [lib] 21 | crate-type = ["cdylib"] 22 | 23 | [profile.release] 24 | codegen-units = 64 25 | lto = true 26 | opt-level = 's' 27 | 28 | [features] 29 | 30 | [dependencies] 31 | console_error_panic_hook = "0.1.7" 32 | js-sys = "0.3" 33 | paste = "1.0.6" 34 | rayon = "1.5" 35 | serde-wasm-bindgen = "0.4" 36 | thiserror = "1.0.20" 37 | wasm-bindgen = {version = "0.2"} 38 | wasm-bindgen-futures = "0.4" 39 | wasm-bindgen-rayon = {version = "1.0", features = ["no-bundler"]} 40 | 41 | [dependencies.polars] 42 | default-features = false 43 | features = [ 44 | "abs", # "diagonal_concat", 45 | "diff", # "dot_diagram", # "dtype-categorical", 46 | "dtype-full", 47 | "round_series", 48 | "is_first", 49 | "lazy", # "extract_jsonpath", # "horizontal_concat", 50 | "mode", # "object", # "performant", # "json", 51 | "csv-file", # "private", # "fmt", 52 | "product", 53 | "rank", 54 | "reinterpret", # "rolling_window", 55 | "rows", # "temporal", 56 | "strings", 57 | "string_justify", 58 | "string_encoding", 59 | "semi_anti_join", 60 | "unique_counts", 61 | ] 62 | git = "https://github.com/gitkwr/polars.git" 63 | 64 | [dependencies.web-sys] 65 | features = [ 66 | 'console', 67 | ] 68 | version = "0.3.56" 69 | 70 | [workspace] 71 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 Cory Grinstead 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @pola-rs/browser 2 | This package contains the js <--> WASM bindings for the polars library. 3 | 4 | # Warning 5 | This package is highly experimental and is not meant for production usage. It is provided as-is and may contain bugs or incomplete features. Use at your own risk. Do not rely on this package for critical applications. 6 | 7 | We make no guarantees about the stability, reliability, or performance of this package. It may undergo significant changes or be removed at any time. 8 | 9 | 10 | ## Startup overhead 11 | 12 | Please be aware that this package has significant startup overhead when run in the browser, due in part to the size of the WASM binary, as well as spawning of workers & threadpools. 13 | 14 | We recommend only using this package in cases where the benefits of the features it provides outweigh the added startup overhead. 15 | 16 | ## Example usage 17 | 18 | install via npm 19 | ``` 20 | npm i -s @pola-rs/browser 21 | ``` 22 | install via yarn 23 | ``` 24 | yarn add @pola-rs/browser 25 | ``` 26 | 27 | Usage 28 | 29 | ```js 30 | 31 | import * as pl from "@pola-rs/browser" 32 | const filepath = "https://raw.githubusercontent.com/pola-rs/polars/master/examples/datasets/foods2.csv" 33 | 34 | let df = await pl.read_csv(filepath) 35 | 36 | let lf = df.lazy(); 37 | df = await lf.collect() 38 | 39 | console.table(df.head(10).to_records()) 40 | ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pola-rs/browser", 3 | "collaborators": [ 4 | "Cory Grinstead" 5 | ], 6 | "version": "0.0.1-alpha.6", 7 | "license": "MIT", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/universalmind303/js-polars" 11 | }, 12 | "publishConfig": { 13 | "registry": "https://registry.npmjs.org/", 14 | "access": "public" 15 | }, 16 | "scripts": { 17 | "build:debug": "wasm-pack build --target web -d polars/core --dev --scope pola-rs --out-name browser && rm polars/core/package.json && rm polars/core/README.md && tsc && cp -r polars/core dist/", 18 | "build": "wasm-pack build --target web -d polars/core --scope pola-rs --out-name browser && rm polars/core/package.json && rm polars/core/README.md && tsc && cp -r polars/core dist/", 19 | "start": "rimraf dist pkg && webpack-dev-server --open -d", 20 | "test": "cargo test && wasm-pack test --headless" 21 | }, 22 | "devDependencies": { 23 | "rome": "^11.0.0", 24 | "source-map-support": "^0.5.21", 25 | "ts-node": "^10.9.1", 26 | "typedoc": "^0.23.23", 27 | "typescript": "4.9" 28 | }, 29 | "module": "dist/index.js", 30 | "files": [ 31 | "dist/", 32 | "dist/core/", 33 | "dist/core/snippets/", 34 | "dist/core/browser_bg.wasm", 35 | "dist/core/browser.js", 36 | "dist/core/browser.d.ts" 37 | ], 38 | "keywords": [ 39 | "csv", 40 | "transform", 41 | "parse", 42 | "json", 43 | "polars", 44 | "dataframe", 45 | "data-processing" 46 | ], 47 | "packageManager": "yarn@3.3.1" 48 | } 49 | -------------------------------------------------------------------------------- /polars/dataframe.ts: -------------------------------------------------------------------------------- 1 | import * as pli from "./core/browser.js"; 2 | import { LazyFrame } from "./index.js"; 3 | 4 | export class DataFrame extends pli.DataFrame { 5 | private ptr!: number; 6 | 7 | static wrap(ptr: number): DataFrame { 8 | const obj: DataFrame = Object.create(DataFrame.prototype); 9 | obj.ptr = ptr; 10 | 11 | return obj; 12 | } 13 | 14 | static __wrap_ptr(df: pli.DataFrame): DataFrame { 15 | return DataFrame.wrap((df as any).ptr); 16 | } 17 | 18 | override lazy(): LazyFrame { 19 | return LazyFrame.__wrap_ptr(super.lazy()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /polars/index.ts: -------------------------------------------------------------------------------- 1 | import { DataFrame } from "./dataframe.js"; 2 | import { Series } from "./series/index.js"; 3 | import * as pli from "./core/browser.js"; 4 | import { waitForMsgType } from "./utils.js"; 5 | import { LazyFrame } from "./lazy/frame/index.js"; 6 | 7 | const wasm = await pli.default(); 8 | const POLARS_WORKER = new Worker(new URL("./worker.js", import.meta.url), { 9 | type: "module", 10 | }); 11 | 12 | POLARS_WORKER.postMessage({ type: "start", payload: wasm.memory }); 13 | 14 | await waitForMsgType(POLARS_WORKER, "ready"); 15 | 16 | export * from "./io.js"; 17 | export * from "./lazy/index.js"; 18 | export { DataFrame, Series, LazyFrame, POLARS_WORKER }; 19 | -------------------------------------------------------------------------------- /polars/io.ts: -------------------------------------------------------------------------------- 1 | import { DataFrame, POLARS_WORKER } from "./index.js"; 2 | import { waitForMsgType } from "./utils.js"; 3 | 4 | const readCsvDefaultOptions = { 5 | inferSchemaLength: 100, 6 | hasHeader: true, 7 | ignoreErrors: true, 8 | chunkSize: 10000, 9 | skipRows: 0, 10 | sep: ",", 11 | rechunk: false, 12 | encoding: "utf8", 13 | lowMemory: false, 14 | parseDates: false, 15 | skipRowsAfterHeader: 0, 16 | }; 17 | 18 | export interface ReadCsvOptions { 19 | inferSchemaLength?: number; 20 | hasHeader?: boolean; 21 | ignoreErrors?: boolean; 22 | chunkSize?: number; 23 | skipRows?: number; 24 | sep?: string; 25 | rechunk?: boolean; 26 | encoding?: string; 27 | lowMemory?: boolean; 28 | parseDates?: boolean; 29 | skipRowsAfterHeader?: number; 30 | numRows?: number; 31 | numThreads?: number; 32 | } 33 | 34 | export async function read_csv( 35 | path: string | Uint8Array, 36 | options: ReadCsvOptions = readCsvDefaultOptions, 37 | ): Promise { 38 | let buf: Uint8Array; 39 | if (typeof path === "string") { 40 | try { 41 | const url = new URL(path); 42 | if (url.protocol === "http:" || url.protocol === "https:") { 43 | const response = await fetch(path); 44 | let arrayBuffer = await response.arrayBuffer(); 45 | buf = new Uint8Array(arrayBuffer); 46 | } else { 47 | throw new Error("Only http and https protocols are supported"); 48 | } 49 | } catch (e) { 50 | throw new Error(`${path} is not a valid url`); 51 | } 52 | } else { 53 | buf = path; 54 | } 55 | 56 | POLARS_WORKER.postMessage( 57 | { 58 | type: "read_csv", 59 | options, 60 | buf, 61 | }, 62 | [buf.buffer], 63 | ); 64 | const event: any = await waitForMsgType(POLARS_WORKER, "read_csv"); 65 | const ptr = event.data.ptr; 66 | 67 | return DataFrame.wrap(ptr); 68 | } 69 | -------------------------------------------------------------------------------- /polars/lazy/frame/index.ts: -------------------------------------------------------------------------------- 1 | import { DataFrame, POLARS_WORKER } from "../../index.js"; 2 | import * as pli from "../../core/browser.js"; 3 | import { waitForMsgType } from "../../utils.js"; 4 | 5 | export class LazyFrame extends pli.LazyFrame { 6 | private ptr!: number; 7 | 8 | static wrap(ptr: number): LazyFrame { 9 | const obj = Object.create(LazyFrame.prototype); 10 | obj.ptr = ptr; 11 | 12 | return obj; 13 | } 14 | 15 | static __wrap_ptr(lf: pli.LazyFrame): LazyFrame { 16 | return LazyFrame.wrap((lf as any).ptr); 17 | } 18 | 19 | async collect(): Promise { 20 | const ptr = this.ptr; 21 | POLARS_WORKER.postMessage({ 22 | type: "LazyFrame::collect", 23 | ptr, 24 | }); 25 | const event: any = await waitForMsgType( 26 | POLARS_WORKER, 27 | "LazyFrame::collect", 28 | ); 29 | const df_ptr = event.data.ptr; 30 | return DataFrame.wrap(df_ptr); 31 | } 32 | 33 | override select(exprs: pli.Expr[]): LazyFrame { 34 | return LazyFrame.__wrap_ptr(super.select(exprs)); 35 | } 36 | override filter(expr: pli.Expr): LazyFrame { 37 | return LazyFrame.__wrap_ptr(super.filter(expr)); 38 | } 39 | override drop_nulls(subset?: string | string[]): LazyFrame { 40 | return LazyFrame.__wrap_ptr(super.drop_nulls(subset)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /polars/lazy/index.ts: -------------------------------------------------------------------------------- 1 | export {col, cols} from "../core/browser.js"; 2 | 3 | -------------------------------------------------------------------------------- /polars/series/index.ts: -------------------------------------------------------------------------------- 1 | import * as pli from "../core/browser.js"; 2 | 3 | export class Series extends pli.Series {} 4 | -------------------------------------------------------------------------------- /polars/utils.ts: -------------------------------------------------------------------------------- 1 | export function waitForMsgType(target: any, type: any) { 2 | return new Promise(resolve => { 3 | target.addEventListener('message', function onMsg(event: any) { 4 | if (event.data == null || event.data.type !== type) return; 5 | target.removeEventListener('message', onMsg); 6 | resolve(event); 7 | }); 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /polars/worker.ts: -------------------------------------------------------------------------------- 1 | /**! 2 | * The polars worker is a web worker that is used to offload heavy computations. 3 | * Since browsers do not allow atomics on the main thread, 4 | * any function that uses the rust threadpool needs to be executed in the worker. 5 | */ 6 | import * as pli from "./core/browser.js"; 7 | import { ReadCsvOptions } from "./io.js"; 8 | 9 | let initialized = false; 10 | 11 | export async function start(mem: WebAssembly.Memory) { 12 | await pli.default(undefined, mem); 13 | await pli.initThreadPool(navigator.hardwareConcurrency); 14 | await pli.init_hooks(); 15 | initialized = true; 16 | self.postMessage({ type: "ready" }); 17 | } 18 | 19 | 20 | function read_csv(buf: Uint8Array, options: ReadCsvOptions): void { 21 | const ptr = ( 22 | pli.read_csv( 23 | buf, 24 | options.inferSchemaLength ?? 100, 25 | options.chunkSize ?? 10000, 26 | options.hasHeader ?? true, 27 | options.ignoreErrors ?? true, 28 | options.numRows, 29 | options.skipRows ?? 0, 30 | options.rechunk ?? false, 31 | options.encoding ?? "utf8", 32 | options.numThreads, 33 | options.lowMemory ?? false, 34 | options.parseDates ?? false, 35 | options.skipRowsAfterHeader ?? 0, 36 | ) as any 37 | ).ptr; 38 | return postMessage({ 39 | type: "read_csv", 40 | ptr, 41 | }); 42 | } 43 | 44 | self.addEventListener("message", async (event) => { 45 | switch (event.data.type) { 46 | case "start": { 47 | return await start(event.data.payload); 48 | } 49 | case "read_csv": { 50 | const { options } = event.data; 51 | return read_csv(event.data.buf, options); 52 | } 53 | case "LazyFrame::collect": { 54 | const lf = (pli.LazyFrame as any).__wrap(event.data.ptr); 55 | const df = await lf.__collect_from_worker(); 56 | return postMessage({ 57 | type: "LazyFrame::collect", 58 | ptr: df.ptr, 59 | }); 60 | } 61 | 62 | default: { 63 | console.log("unknown method", event.data.method); 64 | } 65 | } 66 | }); 67 | -------------------------------------------------------------------------------- /rome.json: -------------------------------------------------------------------------------- 1 | { 2 | "linter": { 3 | "enabled": true, 4 | "rules": { 5 | "recommended": true, 6 | "suspicious": { 7 | "noExplicitAny": "off" 8 | } 9 | } 10 | }, 11 | "formatter": { 12 | "enabled": true, 13 | "indentSize": 2, 14 | "indentStyle": "space" 15 | } 16 | } -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | nightly -------------------------------------------------------------------------------- /server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from http.server import HTTPServer, SimpleHTTPRequestHandler, test 3 | import sys 4 | 5 | class RequestHandler(SimpleHTTPRequestHandler): 6 | def end_headers(self): 7 | self.send_header('Cross-Origin-Opener-Policy', 'same-origin') 8 | self.send_header('Cross-Origin-Embedder-Policy', 'require-corp') 9 | SimpleHTTPRequestHandler.end_headers(self) 10 | 11 | if __name__ == '__main__': 12 | test(RequestHandler, HTTPServer, port=int(sys.argv[1]) if len(sys.argv) > 1 else 8000) 13 | -------------------------------------------------------------------------------- /src/conversion/extern_iterator.rs: -------------------------------------------------------------------------------- 1 | pub struct ExternIterator<'a, T> { 2 | pub count: usize, 3 | pub len: usize, 4 | pub array: &'a T, 5 | } 6 | 7 | #[macro_export] 8 | macro_rules! extern_iterator { 9 | ( $x:ident, $y:ty, $z:ty) => { 10 | paste::paste! { 11 | use crate::conversion::extern_struct::IntoRustStruct; 12 | #[wasm_bindgen] 13 | extern "C" { 14 | #[wasm_bindgen(method, getter = length)] 15 | fn [<$x _length>](this: &$x) -> usize; 16 | #[wasm_bindgen(method, indexing_getter)] 17 | fn [<$x _get>](this: &$x, prop: usize) -> wasm_bindgen::JsValue; 18 | } 19 | 20 | impl<'a> Iterator for crate::conversion::extern_iterator::ExternIterator<'a, $x> { 21 | type Item = $z; 22 | fn next(&mut self) -> Option { 23 | if self.count < self.len { 24 | self.count += 1; 25 | Some($y::from(self.array.[<$x _get>]( self.count)).into_rust()) 26 | } else { 27 | None 28 | } 29 | } 30 | } 31 | 32 | impl<'a> IntoIterator for &'a $x { 33 | type Item = $z; 34 | type IntoIter = crate::conversion::extern_iterator::ExternIterator<'a, $x>; 35 | fn into_iter(self) -> Self::IntoIter { 36 | crate::conversion::extern_iterator::ExternIterator { 37 | count: 0, 38 | len: self.[<$x _length>](), 39 | array: self, 40 | } 41 | } 42 | } 43 | } 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /src/conversion/extern_struct.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::convert::{FromWasmAbi, RefFromWasmAbi}; 2 | 3 | pub trait IntoRustStruct> { 4 | fn into_rust(self) -> T; 5 | } 6 | 7 | pub trait RefRustStruct<'a, T: RefFromWasmAbi> { 8 | fn ref_rust(self) -> wasm_bindgen::__rt::Ref<'static, T>; 9 | } 10 | 11 | #[macro_export] 12 | macro_rules! extern_struct { 13 | ( $x:ident, $y:ty) => { 14 | paste::paste! { 15 | use wasm_bindgen::convert::{FromWasmAbi, RefFromWasmAbi}; 16 | #[wasm_bindgen] 17 | extern "C" { 18 | #[wasm_bindgen(method, getter = ptr)] 19 | fn [<$x _ptr>](this: &$x) -> f64; 20 | } 21 | 22 | impl<'a> crate::conversion::extern_struct::IntoRustStruct<$y> for $x { 23 | fn into_rust(self) -> $y { 24 | unsafe { $y::from_abi(self.[<$x _ptr>]() as u32) } 25 | } 26 | } 27 | 28 | impl<'a> crate::conversion::extern_struct::RefRustStruct<'a, $y> for &'a $x { 29 | fn ref_rust(self) -> wasm_bindgen::__rt::Ref<'static, $y> { 30 | unsafe { $y::ref_from_abi(self.[<$x _ptr>]() as u32) } 31 | } 32 | } 33 | } 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /src/conversion/from.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | 4 | #[repr(u32)] 5 | #[wasm_bindgen(js_name=DataType)] 6 | pub enum JsDataType { 7 | Int8, 8 | Int16, 9 | Int32, 10 | Int64, 11 | UInt8, 12 | UInt16, 13 | UInt32, 14 | UInt64, 15 | Float32, 16 | Float64, 17 | Bool, 18 | Utf8, 19 | List, 20 | Date, 21 | Datetime, 22 | Time, 23 | Object, 24 | Categorical, 25 | } 26 | -------------------------------------------------------------------------------- /src/conversion/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod extern_iterator; 2 | pub mod extern_struct; 3 | pub mod from; 4 | pub mod prelude; 5 | 6 | use crate::JsResult; 7 | use polars::prelude::*; 8 | use wasm_bindgen::convert::FromWasmAbi; 9 | use wasm_bindgen::prelude::*; 10 | use wasm_bindgen::{describe::WasmDescribe, JsCast}; 11 | 12 | #[repr(transparent)] 13 | pub struct Wrap(pub T); 14 | 15 | impl Clone for Wrap 16 | where 17 | T: Clone, 18 | { 19 | fn clone(&self) -> Self { 20 | Wrap(self.0.clone()) 21 | } 22 | } 23 | impl From for Wrap { 24 | fn from(t: T) -> Self { 25 | Wrap(t) 26 | } 27 | } 28 | 29 | impl WasmDescribe for Wrap { 30 | fn describe() { 31 | wasm_bindgen::describe::inform(wasm_bindgen::describe::STRING) 32 | } 33 | } 34 | 35 | impl FromWasmAbi for Wrap { 36 | type Abi = as FromWasmAbi>::Abi; 37 | 38 | #[inline] 39 | unsafe fn from_abi(js: Self::Abi) -> Self { 40 | let s = String::from_utf8_unchecked(>::from_abi(js)); 41 | let interpol = match s.as_ref() { 42 | "nearest" => QuantileInterpolOptions::Nearest, 43 | "lower" => QuantileInterpolOptions::Lower, 44 | "higher" => QuantileInterpolOptions::Higher, 45 | "midpoint" => QuantileInterpolOptions::Midpoint, 46 | "linear" => QuantileInterpolOptions::Linear, 47 | _ => panic!("not supported"), 48 | }; 49 | interpol.into() 50 | } 51 | } 52 | 53 | impl WasmDescribe for Wrap> { 54 | fn describe() { 55 | wasm_bindgen::describe::inform(wasm_bindgen::describe::ENUM) 56 | } 57 | } 58 | 59 | impl FromWasmAbi for Wrap> { 60 | type Abi = u32; 61 | 62 | unsafe fn from_abi(js: u32) -> Self { 63 | let jsv = JsValue::from_abi(js); 64 | // todo!() 65 | Wrap(AnyValue::from_js(jsv)) 66 | } 67 | } 68 | 69 | pub trait FromJsValue: Sized + Send { 70 | fn from_js(obj: JsValue) -> Self; 71 | } 72 | 73 | impl FromJsValue for AnyValue<'_> { 74 | fn from_js(jsv: JsValue) -> Self { 75 | if jsv.is_null() || jsv.is_undefined() { 76 | return AnyValue::Null; 77 | } 78 | let ty = jsv.js_typeof().as_string().unwrap(); 79 | 80 | match ty.as_ref() { 81 | "boolean" => { 82 | let b: bool = js_sys::Boolean::unchecked_from_js(jsv).into(); 83 | AnyValue::Boolean(b) 84 | } 85 | "number" => { 86 | let n: f64 = js_sys::Number::unchecked_from_js(jsv).into(); 87 | AnyValue::Float64(n) 88 | } 89 | "string" => { 90 | let s: String = js_sys::JsString::unchecked_from_js(jsv).into(); 91 | AnyValue::Utf8(Box::leak::<'_>(s.into_boxed_str())) 92 | } 93 | "bigint" => { 94 | let num = jsv.as_string().unwrap().parse::().unwrap(); 95 | AnyValue::UInt64(num) 96 | } 97 | _ => { 98 | if js_sys::Date::is_type_of(&jsv) { 99 | let js_date = js_sys::Date::unchecked_from_js(jsv); 100 | let ms = js_date.get_milliseconds(); 101 | 102 | AnyValue::Datetime(ms as i64, TimeUnit::Milliseconds, &None) 103 | } else if js_sys::Array::is_array(&jsv) { 104 | todo!() 105 | } else { 106 | todo!() 107 | } 108 | } 109 | } 110 | } 111 | } 112 | 113 | impl From> for JsValue { 114 | fn from(val: Wrap<&Series>) -> Self { 115 | let s = val.0; 116 | let len = s.len(); 117 | let dtype = s.dtype(); 118 | 119 | match dtype { 120 | DataType::Struct(_) => { 121 | let ca = s.struct_().unwrap(); 122 | let df: DataFrame = ca.clone().into(); 123 | df_to_struct(&df).unwrap().into() 124 | } 125 | _ => { 126 | let arr = js_sys::Array::new_with_length(len as u32); 127 | 128 | for (idx, val) in s.iter().enumerate() { 129 | arr.set(idx as u32, Wrap(val).into()); 130 | } 131 | arr.into() 132 | } 133 | } 134 | } 135 | } 136 | 137 | impl From>> for JsValue { 138 | fn from(av: Wrap>) -> Self { 139 | match av.0 { 140 | AnyValue::UInt8(v) => v.into(), 141 | AnyValue::UInt16(v) => v.into(), 142 | AnyValue::UInt32(v) => v.into(), 143 | AnyValue::UInt64(v) => v.into(), 144 | AnyValue::Int8(v) => v.into(), 145 | AnyValue::Int16(v) => v.into(), 146 | AnyValue::Int32(v) => v.into(), 147 | AnyValue::Int64(v) => v.into(), 148 | AnyValue::Float32(v) => v.into(), 149 | AnyValue::Float64(v) => v.into(), 150 | AnyValue::Null => JsValue::null(), 151 | AnyValue::Boolean(v) => v.into(), 152 | AnyValue::Utf8(v) => v.into(), 153 | AnyValue::Categorical(idx, rev) => { 154 | let s = rev.get(idx); 155 | s.into() 156 | } 157 | AnyValue::Date(v) => { 158 | let jsv: JsValue = v.into(); 159 | js_sys::Date::new(&jsv).into() 160 | } 161 | AnyValue::Datetime(v, _, _) => { 162 | let jsv: JsValue = v.into(); 163 | let dt = js_sys::Date::new(&jsv); 164 | dt.into() 165 | } 166 | AnyValue::Time(v) => v.into(), 167 | _ => todo!(), 168 | } 169 | } 170 | } 171 | 172 | pub fn df_to_struct(_df: &DataFrame) -> JsResult { 173 | todo!() 174 | } 175 | -------------------------------------------------------------------------------- /src/conversion/prelude.rs: -------------------------------------------------------------------------------- 1 | pub use crate::conversion::from::*; 2 | -------------------------------------------------------------------------------- /src/dataframe.rs: -------------------------------------------------------------------------------- 1 | use super::{error::JsPolarsErr, series::*, JsResult}; 2 | use crate::conversion::*; 3 | use crate::datatypes::JsDataType; 4 | use polars::prelude::*; 5 | 6 | use wasm_bindgen::prelude::*; 7 | 8 | #[wasm_bindgen(js_name=DataFrame)] 9 | pub struct JsDataFrame { 10 | df: DataFrame, 11 | } 12 | 13 | impl JsDataFrame { 14 | pub(crate) fn new(df: DataFrame) -> Self { 15 | JsDataFrame { df } 16 | } 17 | } 18 | impl From for JsDataFrame { 19 | fn from(df: DataFrame) -> Self { 20 | Self { df } 21 | } 22 | } 23 | 24 | #[wasm_bindgen] 25 | extern "C" { 26 | #[wasm_bindgen(typescript_type = "DataFrame")] 27 | pub type ExternDataFrame; 28 | 29 | #[wasm_bindgen(typescript_type = "any")] 30 | pub type ExternAnyValue; 31 | 32 | #[wasm_bindgen(method, getter = ptr)] 33 | fn ptr(this: &ExternDataFrame) -> f64; 34 | #[wasm_bindgen(typescript_type = "DataFrame[]")] 35 | pub type DataFrameArray; 36 | } 37 | 38 | #[wasm_bindgen(js_class=DataFrame)] 39 | impl JsDataFrame { 40 | #[wasm_bindgen(constructor)] 41 | pub fn new0() -> Self { 42 | DataFrame::new_no_checks(vec![]).into() 43 | } 44 | 45 | #[wasm_bindgen(js_name = "toString")] 46 | pub fn to_string(self) -> String { 47 | format!("{}", self.df) 48 | } 49 | 50 | pub fn read_columns(columns: js_sys::Iterator) -> JsResult { 51 | let cols = to_series_collection(columns); 52 | 53 | let df = DataFrame::new(cols).map_err(JsPolarsErr::from)?; 54 | Ok(JsDataFrame::from(df)) 55 | } 56 | 57 | pub fn rechunk(&mut self) -> Self { 58 | self.df.agg_chunks().into() 59 | } 60 | 61 | /// Format `DataFrame` as String 62 | pub fn as_str(&self) -> String { 63 | format!("{:?}", self.df) 64 | } 65 | 66 | pub fn join( 67 | &self, 68 | other: &JsDataFrame, 69 | left_on: js_sys::Array, 70 | right_on: js_sys::Array, 71 | how: &str, 72 | suffix: String, 73 | ) -> JsResult { 74 | let how = match how { 75 | "left" => JoinType::Left, 76 | "inner" => JoinType::Inner, 77 | "outer" => JoinType::Outer, 78 | "cross" => JoinType::Cross, 79 | _ => panic!("not supported"), 80 | }; 81 | let left_on: Vec = left_on.iter().map(|v| v.as_string().unwrap()).collect(); 82 | let right_on: Vec = right_on.iter().map(|v| v.as_string().unwrap()).collect(); 83 | 84 | let df = self 85 | .df 86 | .join(&other.df, left_on, right_on, how, Some(suffix)) 87 | .map_err(JsPolarsErr::from)?; 88 | Ok(JsDataFrame::new(df)) 89 | } 90 | 91 | pub fn get_columns(&self) -> Vec { 92 | use wasm_bindgen::convert::IntoWasmAbi; 93 | self.df 94 | .get_columns() 95 | .clone() 96 | .into_iter() 97 | .map(|s| JsSeries::new(s).into_abi()) 98 | .collect() 99 | } 100 | 101 | /// Get column names 102 | #[wasm_bindgen(getter)] 103 | pub fn columns(&self) -> js_sys::Array { 104 | self.df 105 | .iter() 106 | .map(|s| JsValue::from_str(s.name())) 107 | .collect() 108 | } 109 | 110 | pub fn with_column(&mut self, s: JsSeries) -> JsResult { 111 | let mut df = self.df.clone(); 112 | df.with_column(s.series).map_err(JsPolarsErr::from)?; 113 | Ok(df.into()) 114 | } 115 | pub fn dtypes(&self) -> js_sys::Array { 116 | self.df 117 | .dtypes() 118 | .iter() 119 | .map(|arrow_dtype| { 120 | let dt: JsDataType = arrow_dtype.into(); 121 | let jsv: JsValue = dt.to_string().into(); 122 | jsv 123 | }) 124 | .collect() 125 | } 126 | pub fn n_chunks(&self) -> JsResult { 127 | let n = self.df.n_chunks(); 128 | Ok(n) 129 | } 130 | pub fn shape(&self) -> js_sys::Array { 131 | let (height, width) = self.df.shape(); 132 | let height: JsValue = height.into(); 133 | let width: JsValue = width.into(); 134 | js_sys::Array::of2(&height, &width) 135 | } 136 | pub fn height(&self) -> usize { 137 | self.df.height() 138 | } 139 | 140 | pub fn width(&self) -> usize { 141 | self.df.width() 142 | } 143 | pub fn hstack_mut(&mut self, columns: js_sys::Iterator) -> JsResult<()> { 144 | let cols = to_series_collection(columns); 145 | 146 | self.df.hstack_mut(&cols).map_err(JsPolarsErr::from)?; 147 | Ok(()) 148 | } 149 | 150 | pub fn hstack(&self, columns: js_sys::Iterator) -> JsResult { 151 | let columns = to_series_collection(columns); 152 | let df = self.df.hstack(&columns).map_err(JsPolarsErr::from)?; 153 | Ok(df.into()) 154 | } 155 | pub fn extend(&mut self, df: &JsDataFrame) -> JsResult<()> { 156 | self.df.extend(&df.df).map_err(JsPolarsErr::from)?; 157 | Ok(()) 158 | } 159 | pub fn vstack_mut(&mut self, df: &JsDataFrame) -> JsResult<()> { 160 | self.df.vstack_mut(&df.df).map_err(JsPolarsErr::from)?; 161 | Ok(()) 162 | } 163 | 164 | pub fn vstack(&mut self, df: &JsDataFrame) -> JsResult { 165 | let df = self.df.vstack(&df.df).map_err(JsPolarsErr::from)?; 166 | Ok(df.into()) 167 | } 168 | pub fn drop_in_place(&mut self, name: &str) -> JsResult { 169 | let s = self.df.drop_in_place(name).map_err(JsPolarsErr::from)?; 170 | Ok(JsSeries { series: s }) 171 | } 172 | pub fn drop_nulls(&self, _subset: Option) -> JsResult { 173 | todo!() 174 | } 175 | pub fn drop(&self, name: &str) -> JsResult { 176 | let df = self.df.drop(name).map_err(JsPolarsErr::from)?; 177 | Ok(JsDataFrame::new(df)) 178 | } 179 | pub fn select_at_idx(&self, idx: usize) -> Option { 180 | self.df.select_at_idx(idx).map(|s| JsSeries::new(s.clone())) 181 | } 182 | pub fn find_idx_by_name(&self, name: &str) -> Option { 183 | self.df.find_idx_by_name(name) 184 | } 185 | pub fn column(&self, name: &str) -> JsResult { 186 | let series = self 187 | .df 188 | .column(name) 189 | .map(|s| JsSeries::new(s.clone())) 190 | .map_err(JsPolarsErr::from)?; 191 | Ok(series) 192 | } 193 | pub fn select(&self, selection: js_sys::Array) -> JsResult { 194 | let selection: Vec = selection.iter().map(|v| v.as_string().unwrap()).collect(); 195 | 196 | let df = self.df.select(&selection).map_err(JsPolarsErr::from)?; 197 | Ok(JsDataFrame::new(df)) 198 | } 199 | 200 | pub fn filter(&self, mask: &JsSeries) -> JsResult { 201 | let filter_series = &mask.series; 202 | if let Ok(ca) = filter_series.bool() { 203 | let df = self.df.filter(ca).map_err(JsPolarsErr::from)?; 204 | Ok(JsDataFrame::new(df)) 205 | } else { 206 | Err(js_sys::TypeError::new("Expected a boolean mask").into()) 207 | } 208 | } 209 | pub fn take(&self, indices: js_sys::Array) -> JsResult { 210 | let indices: Vec = indices.iter().map(|v| v.as_f64().unwrap() as u32).collect(); 211 | 212 | let indices = UInt32Chunked::from_vec("", indices); 213 | let df = self.df.take(&indices).map_err(JsPolarsErr::from)?; 214 | Ok(JsDataFrame::new(df)) 215 | } 216 | 217 | pub fn take_with_series(&self, indices: &JsSeries) -> JsResult { 218 | let idx = indices.series.u32().map_err(JsPolarsErr::from)?; 219 | let df = self.df.take(idx).map_err(JsPolarsErr::from)?; 220 | Ok(JsDataFrame::new(df)) 221 | } 222 | pub fn sort(&self, by_column: &str, reverse: bool) -> JsResult { 223 | let df = self 224 | .df 225 | .sort([by_column], reverse) 226 | .map_err(JsPolarsErr::from)?; 227 | Ok(JsDataFrame::new(df)) 228 | } 229 | 230 | pub fn sort_in_place(&mut self, by_column: &str, reverse: bool) -> JsResult<()> { 231 | self.df 232 | .sort_in_place([by_column], reverse) 233 | .map_err(JsPolarsErr::from)?; 234 | Ok(()) 235 | } 236 | 237 | pub fn replace(&mut self, column: &str, new_col: JsSeries) -> JsResult<()> { 238 | self.df 239 | .replace(column, new_col.series) 240 | .map_err(JsPolarsErr::from)?; 241 | Ok(()) 242 | } 243 | 244 | pub fn rename(&mut self, column: &str, new_col: &str) -> JsResult<()> { 245 | self.df.rename(column, new_col).map_err(JsPolarsErr::from)?; 246 | Ok(()) 247 | } 248 | pub fn replace_at_idx(&mut self, index: usize, new_col: JsSeries) -> JsResult<()> { 249 | self.df 250 | .replace_at_idx(index, new_col.series) 251 | .map_err(JsPolarsErr::from)?; 252 | Ok(()) 253 | } 254 | 255 | pub fn insert_at_idx(&mut self, index: usize, new_col: JsSeries) -> JsResult<()> { 256 | self.df 257 | .insert_at_idx(index, new_col.series) 258 | .map_err(JsPolarsErr::from)?; 259 | Ok(()) 260 | } 261 | pub fn slice(&self, offset: usize, length: usize) -> Self { 262 | let df = self.df.slice(offset as i64, length); 263 | df.into() 264 | } 265 | 266 | pub fn head(&self, length: Option) -> Self { 267 | let df = self.df.head(length); 268 | JsDataFrame::new(df) 269 | } 270 | 271 | pub fn tail(&self, length: Option) -> Self { 272 | let df = self.df.tail(length); 273 | JsDataFrame::new(df) 274 | } 275 | pub fn is_unique(&self) -> JsResult { 276 | let mask = self.df.is_unique().map_err(JsPolarsErr::from)?; 277 | Ok(mask.into_series().into()) 278 | } 279 | pub fn is_duplicated(&self) -> JsResult { 280 | let mask = self.df.is_duplicated().map_err(JsPolarsErr::from)?; 281 | Ok(mask.into_series().into()) 282 | } 283 | 284 | pub fn frame_equal(&self, other: &JsDataFrame, null_equal: bool) -> bool { 285 | if null_equal { 286 | self.df.frame_equal_missing(&other.df) 287 | } else { 288 | self.df.frame_equal(&other.df) 289 | } 290 | } 291 | pub fn with_row_count(&self, name: &str, offset: Option) -> JsResult { 292 | let df = self 293 | .df 294 | .with_row_count(name, offset) 295 | .map_err(JsPolarsErr::from)?; 296 | Ok(df.into()) 297 | } 298 | pub fn clone(&self) -> Self { 299 | JsDataFrame::new(self.df.clone()) 300 | } 301 | pub fn melt(&self, id_vars: js_sys::Array, value_vars: js_sys::Array) -> JsResult { 302 | let df = self 303 | .df 304 | .melt( 305 | id_vars.iter().map(|v| v.as_string().unwrap()), 306 | value_vars.iter().map(|v| v.as_string().unwrap()), 307 | ) 308 | .map_err(JsPolarsErr::from)?; 309 | Ok(JsDataFrame::new(df)) 310 | } 311 | 312 | pub fn shift(&self, periods: f64) -> Self { 313 | self.df.shift(periods as i64).into() 314 | } 315 | pub fn unique( 316 | &self, 317 | maintain_order: bool, 318 | subset: Option, 319 | keep: &str, 320 | ) -> JsResult { 321 | let keep = match keep { 322 | "first" => UniqueKeepStrategy::First, 323 | "last" => UniqueKeepStrategy::Last, 324 | s => panic!("keep strategy {} is not supported", s), 325 | }; 326 | let subset: Option> = subset.map(|v| { 327 | let s: Vec = v.iter().map(|item| item.as_string().unwrap()).collect(); 328 | s 329 | }); 330 | 331 | let subset = subset.as_ref().map(|v| v.as_ref()); 332 | 333 | let df = match maintain_order { 334 | true => self.df.unique_stable(subset, keep), 335 | false => self.df.unique(subset, keep), 336 | } 337 | .map_err(JsPolarsErr::from) 338 | .unwrap(); 339 | Ok(JsDataFrame::new(df)) 340 | } 341 | 342 | pub fn lazy(&self) -> crate::lazy::dataframe::JsLazyFrame { 343 | self.df.clone().lazy().into() 344 | } 345 | 346 | pub fn max(&self) -> Self { 347 | self.df.max().into() 348 | } 349 | 350 | pub fn min(&self) -> Self { 351 | self.df.min().into() 352 | } 353 | 354 | pub fn sum(&self) -> Self { 355 | self.df.sum().into() 356 | } 357 | 358 | pub fn mean(&self) -> Self { 359 | self.df.mean().into() 360 | } 361 | 362 | pub fn var(&self) -> Self { 363 | todo!() 364 | } 365 | 366 | pub fn median(&self) -> Self { 367 | self.df.median().into() 368 | } 369 | pub fn null_count(&self) -> Self { 370 | let df = self.df.null_count(); 371 | df.into() 372 | } 373 | 374 | pub fn to_records(&self) -> JsResult { 375 | let height = self.df.height() as u32; 376 | let rows = js_sys::Array::new_with_length(height); 377 | 378 | for idx in 0..height { 379 | let obj = js_sys::Object::new(); 380 | 381 | for col in self.df.get_columns() { 382 | let key: JsValue = col.name().into(); 383 | let val: JsValue = Wrap(col.get(idx as usize).unwrap()).into(); 384 | js_sys::Reflect::set(&obj, &key, &val)?; 385 | } 386 | rows.set(idx, obj.into()); 387 | } 388 | Ok(rows) 389 | } 390 | 391 | pub fn handle_records(&self, f: &js_sys::Function) -> JsResult<()> { 392 | let this = JsValue::null(); 393 | 394 | let height = self.df.height() as u32; 395 | // let rows = js_sys::Array::new_with_length(height); 396 | 397 | for idx in 0..height { 398 | let obj = js_sys::Object::new(); 399 | 400 | for col in self.df.get_columns() { 401 | let key: JsValue = col.name().into(); 402 | let val: JsValue = Wrap(col.get(idx as usize).unwrap()).into(); 403 | js_sys::Reflect::set(&obj, &key, &val)?; 404 | } 405 | f.call1(&this, &obj)?; 406 | } 407 | Ok(()) 408 | } 409 | 410 | pub fn to_object(&mut self) -> JsResult { 411 | todo!() 412 | // let obj = js_sys::Object::new(); 413 | // self.df.rechunk(); 414 | 415 | // for col in self.df.get_columns() { 416 | // let key: JsValue = col.name().into(); 417 | // let val: JsValue = Wrap(col).into(); 418 | // js_sys::Reflect::set(&obj, &key, &val)?; 419 | // } 420 | 421 | // Ok(obj) 422 | } 423 | } 424 | -------------------------------------------------------------------------------- /src/datatypes.rs: -------------------------------------------------------------------------------- 1 | use polars::prelude::DataType; 2 | 3 | #[repr(u32)] 4 | pub enum JsDataType { 5 | Int8, 6 | Int16, 7 | Int32, 8 | Int64, 9 | UInt8, 10 | UInt16, 11 | UInt32, 12 | UInt64, 13 | Float32, 14 | Float64, 15 | Bool, 16 | Utf8, 17 | List, 18 | Date, 19 | Datetime, 20 | Time, 21 | // Object, 22 | Categorical, 23 | } 24 | 25 | impl JsDataType { 26 | pub fn to_string(self) -> String { 27 | match self { 28 | JsDataType::Int8 => "Int8", 29 | JsDataType::Int16 => "Int16", 30 | JsDataType::Int32 => "Int32", 31 | JsDataType::Int64 => "Int64", 32 | JsDataType::UInt8 => "UInt8", 33 | JsDataType::UInt16 => "UInt16", 34 | JsDataType::UInt32 => "UInt32", 35 | JsDataType::UInt64 => "UInt64", 36 | JsDataType::Float32 => "Float32", 37 | JsDataType::Float64 => "Float64", 38 | JsDataType::Bool => "Bool", 39 | JsDataType::Utf8 => "Utf8", 40 | JsDataType::List => "List", 41 | JsDataType::Date => "Date", 42 | JsDataType::Datetime => "Datetime", 43 | JsDataType::Time => "Time", 44 | // JsDataType::Object => "Object", 45 | JsDataType::Categorical => "Categorical", 46 | } 47 | .to_owned() 48 | } 49 | } 50 | 51 | impl From<&DataType> for JsDataType { 52 | fn from(dt: &DataType) -> Self { 53 | use JsDataType::*; 54 | match dt { 55 | DataType::Int8 => Int8, 56 | DataType::Int16 => Int16, 57 | DataType::Int32 => Int32, 58 | DataType::Int64 => Int64, 59 | DataType::UInt8 => UInt8, 60 | DataType::UInt16 => UInt16, 61 | DataType::UInt32 => UInt32, 62 | DataType::UInt64 => UInt64, 63 | DataType::Float32 => Float32, 64 | DataType::Float64 => Float64, 65 | DataType::Boolean => Bool, 66 | DataType::Utf8 => Utf8, 67 | DataType::List(_) => List, 68 | DataType::Date => Date, 69 | DataType::Datetime(_, _) => Datetime, 70 | DataType::Time => Time, 71 | 72 | // DataType::Object(_) => Object, 73 | DataType::Categorical(_) => Categorical, 74 | _ => { 75 | panic!("null or unknown not expected here") 76 | } 77 | } 78 | } 79 | } 80 | 81 | pub enum TypedArrayType { 82 | Int8(js_sys::Int8Array), 83 | Uint8(js_sys::Uint8Array), 84 | Uint8Clamped(js_sys::Uint8ClampedArray), 85 | Int16(js_sys::Int16Array), 86 | Uint16(js_sys::Uint16Array), 87 | Int32(js_sys::Int32Array), 88 | Uint32(js_sys::Uint32Array), 89 | Float32(js_sys::Float32Array), 90 | Float64(js_sys::Float64Array), 91 | BigInt64(js_sys::BigInt64Array), 92 | BigUint64(js_sys::BigUint64Array), 93 | } 94 | 95 | impl From for TypedArrayType { 96 | fn from(v: wasm_bindgen::JsValue) -> Self { 97 | use wasm_bindgen::JsCast; 98 | 99 | if js_sys::Int8Array::instanceof(&v) { 100 | TypedArrayType::Int8(v.into()) 101 | } else if js_sys::Uint8Array::instanceof(&v) { 102 | TypedArrayType::Uint8(v.into()) 103 | } else if js_sys::Uint8ClampedArray::instanceof(&v) { 104 | TypedArrayType::Uint8Clamped(v.into()) 105 | } else if js_sys::Int16Array::instanceof(&v) { 106 | TypedArrayType::Int16(v.into()) 107 | } else if js_sys::Uint16Array::instanceof(&v) { 108 | TypedArrayType::Uint16(v.into()) 109 | } else if js_sys::Int32Array::instanceof(&v) { 110 | TypedArrayType::Int32(v.into()) 111 | } else if js_sys::Uint32Array::instanceof(&v) { 112 | TypedArrayType::Uint32(v.into()) 113 | } else if js_sys::Float32Array::instanceof(&v) { 114 | TypedArrayType::Float32(v.into()) 115 | } else if js_sys::Float64Array::instanceof(&v) { 116 | TypedArrayType::Float64(v.into()) 117 | } else if js_sys::BigInt64Array::instanceof(&v) { 118 | TypedArrayType::BigInt64(v.into()) 119 | } else if js_sys::BigUint64Array::instanceof(&v) { 120 | TypedArrayType::BigUint64(v.into()) 121 | } else { 122 | panic!("unknown dtype") 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use polars::prelude::PolarsError; 2 | use thiserror::Error; 3 | use wasm_bindgen::prelude::JsValue; 4 | 5 | #[derive(Debug, Error)] 6 | pub enum JsPolarsErr { 7 | #[error(transparent)] 8 | Any(#[from] PolarsError), 9 | #[error(transparent)] 10 | Serde(#[from] serde_wasm_bindgen::Error), 11 | #[error("{0}")] 12 | Other(String), 13 | } 14 | 15 | impl std::convert::From for JsValue { 16 | fn from(err: JsPolarsErr) -> JsValue { 17 | let reason = format!("{}", err); 18 | js_sys::Error::new(&reason).into() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/io.rs: -------------------------------------------------------------------------------- 1 | use super::{error::JsPolarsErr, JsResult}; 2 | use crate::dataframe::JsDataFrame; 3 | use polars::prelude::*; 4 | use std::io::Cursor; 5 | 6 | use wasm_bindgen::prelude::*; 7 | 8 | #[wasm_bindgen] 9 | pub fn read_csv( 10 | buff: &[u8], 11 | infer_schema_length: Option, 12 | chunk_size: u32, 13 | has_header: bool, 14 | ignore_errors: bool, 15 | n_rows: Option, 16 | skip_rows: u32, 17 | rechunk: bool, 18 | encoding: String, 19 | n_threads: Option, 20 | low_memory: bool, 21 | parse_dates: bool, 22 | skip_rows_after_header: usize, 23 | ) -> JsResult { 24 | let infer_schema_length = infer_schema_length.map(|i| i as usize); 25 | let n_threads = n_threads.map(|i| i as usize); 26 | let n_rows = n_rows.map(|i| i as usize); 27 | let skip_rows = skip_rows as usize; 28 | let chunk_size = chunk_size as usize; 29 | 30 | let encoding = match encoding.as_ref() { 31 | "utf8" => CsvEncoding::Utf8, 32 | "utf8-lossy" => CsvEncoding::LossyUtf8, 33 | e => return Err(JsPolarsErr::Other(format!("encoding not {} not implemented.", e)).into()), 34 | }; 35 | 36 | let cursor = Cursor::new(buff); 37 | let df = CsvReader::new(cursor) 38 | .infer_schema(infer_schema_length) 39 | .has_header(has_header) 40 | .with_n_rows(n_rows) 41 | .with_delimiter(",".as_bytes()[0]) 42 | .with_skip_rows(skip_rows) 43 | .with_ignore_parser_errors(ignore_errors) 44 | .with_rechunk(rechunk) 45 | .with_chunk_size(chunk_size) 46 | .with_encoding(encoding) 47 | .low_memory(low_memory) 48 | .with_parse_dates(parse_dates) 49 | .with_n_threads(n_threads) 50 | .with_skip_rows_after_header(skip_rows_after_header) 51 | .finish() 52 | .map_err(JsPolarsErr::from)?; 53 | 54 | Ok(df.into()) 55 | } 56 | -------------------------------------------------------------------------------- /src/lazy/dataframe.rs: -------------------------------------------------------------------------------- 1 | use polars::prelude::*; 2 | use wasm_bindgen::prelude::*; 3 | 4 | use super::expr::JsExpr; 5 | use crate::{dataframe::JsDataFrame, error::JsPolarsErr, JsResult}; 6 | #[wasm_bindgen(js_name = LazyFrame)] 7 | #[repr(transparent)] 8 | #[derive(Clone)] 9 | pub struct JsLazyFrame { 10 | ldf: LazyFrame, 11 | } 12 | 13 | impl From for JsLazyFrame { 14 | fn from(ldf: LazyFrame) -> Self { 15 | JsLazyFrame { ldf } 16 | } 17 | } 18 | 19 | impl JsLazyFrame { 20 | fn get_schema(&self) -> JsResult { 21 | self.ldf.schema().map_err(|e| JsPolarsErr::from(e).into()) 22 | } 23 | } 24 | 25 | #[wasm_bindgen(js_class=LazyFrame)] 26 | impl JsLazyFrame { 27 | #[wasm_bindgen(getter)] 28 | pub fn columns(&self) -> JsResult { 29 | let cols: Vec = self.get_schema()?.iter_names().cloned().collect(); 30 | serde_wasm_bindgen::to_value(&cols).map_err(|e| JsPolarsErr::from(e).into()) 31 | } 32 | 33 | /// Cache the result once the execution of the physical plan hits this node. 34 | pub fn cache(&self) -> JsLazyFrame { 35 | self.ldf.clone().cache().into() 36 | } 37 | 38 | pub fn clone(&self) -> JsLazyFrame { 39 | self.ldf.clone().into() 40 | } 41 | #[wasm_bindgen(js_name = "__collect_from_worker", skip_typescript)] 42 | pub fn collect_from_worker(&self) -> JsResult { 43 | self.ldf 44 | .clone() 45 | .collect() 46 | .map_err(|e| JsPolarsErr::from(e).into()) 47 | .map(|df| df.into()) 48 | } 49 | 50 | /// A string representation of the optimized query plan. 51 | pub fn describe_optimized_plan(&self) -> JsResult { 52 | let result = self 53 | .ldf 54 | .describe_optimized_plan() 55 | .map_err(JsPolarsErr::from)?; 56 | Ok(result) 57 | } 58 | 59 | /// A string representation of the unoptimized query plan. 60 | pub fn describe_plan(&self) -> String { 61 | self.ldf.describe_plan() 62 | } 63 | 64 | /// Remove one or multiple columns from a DataFrame. 65 | pub fn drop(&self, _cols: JsValue) -> Self { 66 | // let ldf = self.ldf.clone(); 67 | todo!() 68 | // ldf.drop_columns(cols).into() 69 | } 70 | 71 | /// Drop rows with null values from this DataFrame. 72 | /// This method only drops nulls row-wise if any single value of the row is null. 73 | pub fn drop_nulls(&self, cols: JsValue) -> JsLazyFrame { 74 | if cols.is_null() | cols.is_undefined() { 75 | return self.ldf.clone().drop_nulls(None).into(); 76 | } else if cols.is_string() { 77 | return self 78 | .ldf 79 | .clone() 80 | .drop_nulls(Some(vec![col(&cols.as_string().unwrap())])) 81 | .into(); 82 | } else { 83 | let cols: Vec = serde_wasm_bindgen::from_value(cols).unwrap(); 84 | let cols: Vec = cols.iter().map(|name| col(&name)).collect(); 85 | return self.ldf.clone().drop_nulls(Some(cols)).into(); 86 | } 87 | } 88 | pub fn sort(&self, by_column: &str, reverse: bool, nulls_last: bool) -> JsLazyFrame { 89 | let ldf = self.ldf.clone(); 90 | ldf.sort( 91 | by_column, 92 | SortOptions { 93 | descending: reverse, 94 | nulls_last, 95 | }, 96 | ) 97 | .into() 98 | } 99 | 100 | pub fn sort_by_exprs( 101 | &self, 102 | by_column: &js_sys::Array, 103 | reverse: JsValue, 104 | nulls_last: bool, 105 | ) -> JsResult { 106 | let ldf = self.ldf.clone(); 107 | 108 | let reverse: Vec = 109 | serde_wasm_bindgen::from_value(reverse).map_err(JsPolarsErr::from)?; 110 | let exprs = js_exprs_to_exprs(by_column)?; 111 | Ok(ldf.sort_by_exprs(exprs, reverse, nulls_last).into()) 112 | } 113 | 114 | pub fn join( 115 | &self, 116 | other: &JsLazyFrame, 117 | left_on: &js_sys::Array, 118 | right_on: &js_sys::Array, 119 | how: &str, 120 | suffix: &str, 121 | allow_parallel: bool, 122 | force_parallel: bool, 123 | ) -> JsResult { 124 | let ldf = self.ldf.clone(); 125 | let other = other.ldf.clone(); 126 | let left_on = js_exprs_to_exprs(left_on)?; 127 | let right_on = js_exprs_to_exprs(right_on)?; 128 | let how = match how { 129 | "left" => JoinType::Left, 130 | "inner" => JoinType::Inner, 131 | "outer" => JoinType::Outer, 132 | "semi" => JoinType::Semi, 133 | "anti" => JoinType::Anti, 134 | _ => { 135 | return Err(JsPolarsErr::Other( 136 | "how should be one of inner, left, right, outer".into(), 137 | ) 138 | .into()) 139 | } 140 | }; 141 | Ok(ldf 142 | .join_builder() 143 | .with(other) 144 | .left_on(left_on) 145 | .right_on(right_on) 146 | .allow_parallel(allow_parallel) 147 | .force_parallel(force_parallel) 148 | .how(how) 149 | .suffix(suffix) 150 | .finish() 151 | .into()) 152 | } 153 | 154 | pub fn with_column(&mut self, expr: JsExpr) -> JsLazyFrame { 155 | let ldf = self.ldf.clone(); 156 | ldf.with_column(expr.inner).into() 157 | } 158 | 159 | pub fn with_columns(&mut self, exprs: &js_sys::Array) -> JsResult { 160 | let ldf = self.ldf.clone(); 161 | Ok(ldf.with_columns(js_exprs_to_exprs(exprs)?).into()) 162 | } 163 | 164 | /// Explode lists to long format. 165 | pub fn explode(&self, _cols: &JsValue) -> JsLazyFrame { 166 | todo!() 167 | } 168 | 169 | /// Filter the rows in the DataFrame based on a predicate expression. 170 | /// @param predicate - Expression that evaluates to a boolean Series. 171 | /// @example 172 | /// ```js 173 | /// > lf = pl.DataFrame({ 174 | /// ... "foo": [1, 2, 3], 175 | /// ... "bar": [6, 7, 8], 176 | /// ... "ham": ['a', 'b', 'c'] 177 | /// ... }).lazy() 178 | /// 179 | /// // Filter on one condition 180 | /// > await lf.filter(pl.col("foo").lt(3)).collect() 181 | /// shape: (2, 3) 182 | /// ┌─────┬─────┬─────┐ 183 | /// │ foo ┆ bar ┆ ham │ 184 | /// │ --- ┆ --- ┆ --- │ 185 | /// │ i64 ┆ i64 ┆ str │ 186 | /// ╞═════╪═════╪═════╡ 187 | /// │ 1 ┆ 6 ┆ a │ 188 | /// ├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤ 189 | /// │ 2 ┆ 7 ┆ b │ 190 | /// └─────┴─────┴─────┘ 191 | /// ``` 192 | pub fn filter(&self, expr: &JsExpr) -> JsResult { 193 | let ldf = self.ldf.clone(); 194 | Ok(ldf.filter(expr.inner.clone()).into()) 195 | } 196 | pub fn select(&self, exprs: &js_sys::Array) -> JsResult { 197 | let exprs = js_exprs_to_exprs(exprs)?; 198 | let ldf = self.ldf.clone(); 199 | Ok(ldf.select(&exprs).into()) 200 | } 201 | } 202 | 203 | pub(crate) fn js_exprs_to_exprs(iter: &js_sys::Array) -> JsResult> { 204 | use wasm_bindgen::convert::FromWasmAbi; 205 | use wasm_bindgen::JsCast; 206 | let iterator = js_sys::try_iter(iter)?.ok_or_else(|| "need to pass iterable JS values!")?; 207 | 208 | iterator 209 | .into_iter() 210 | .map(|jsv| { 211 | let jsv = jsv?; 212 | let key = JsValue::from_str("ptr"); 213 | let ptr = js_sys::Reflect::get(&jsv, &key)?; 214 | let n: f64 = js_sys::Number::unchecked_from_js(ptr).into(); 215 | let expr: JsExpr = unsafe { JsExpr::from_abi(n as u32) }; 216 | Ok(expr.inner) 217 | }) 218 | .collect() 219 | } 220 | -------------------------------------------------------------------------------- /src/lazy/expr/conversion.rs: -------------------------------------------------------------------------------- 1 | use super::JsExpr; 2 | use crate::{extern_iterator, extern_struct}; 3 | use polars::prelude::Expr; 4 | use wasm_bindgen::prelude::*; 5 | #[wasm_bindgen] 6 | extern "C" { 7 | #[wasm_bindgen(typescript_type = "Expr")] 8 | pub type ExternExpr; 9 | 10 | #[wasm_bindgen(method, getter = ptr)] 11 | fn ptr(this: &ExternExpr) -> f64; 12 | 13 | #[wasm_bindgen(static_method_of = ExternExpr)] 14 | fn wrap(ptr: u32) -> ExternExpr; 15 | 16 | #[wasm_bindgen(typescript_type = "Expr[]")] 17 | pub type ExprArray; 18 | 19 | } 20 | 21 | extern_struct!(ExternExpr, JsExpr); 22 | extern_iterator!(ExprArray, ExternExpr, JsExpr); 23 | 24 | impl From for JsExpr { 25 | fn from(s: Expr) -> JsExpr { 26 | JsExpr { inner: s } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/lazy/expr/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod conversion; 2 | 3 | pub mod string; 4 | 5 | pub use conversion::*; 6 | use polars::lazy::dsl; 7 | use polars::prelude::*; 8 | use wasm_bindgen::prelude::*; 9 | 10 | pub use self::string::JsStringNameSpace; 11 | 12 | #[wasm_bindgen(js_name=Expr)] 13 | #[repr(transparent)] 14 | #[derive(Clone)] 15 | pub struct JsExpr { 16 | pub(crate) inner: Expr, 17 | } 18 | 19 | #[wasm_bindgen(js_class=Expr)] 20 | impl JsExpr { 21 | #[wasm_bindgen(getter)] 22 | pub fn str(&self) -> JsStringNameSpace { 23 | JsStringNameSpace { 24 | inner: self.inner.clone(), 25 | } 26 | } 27 | 28 | /// Take absolute values 29 | pub fn abs(&self) -> JsExpr { 30 | self.clone().inner.abs().into() 31 | } 32 | 33 | /// Get the group indexes of the group by operation. 34 | /// Should be used in aggregation context only. 35 | /// @example 36 | /// ```js 37 | /// > df = pl.DataFrame({ 38 | /// ... "group": [ 39 | /// ... "one", 40 | /// ... "one", 41 | /// ... "one", 42 | /// ... "two", 43 | /// ... "two", 44 | /// ... "two", 45 | /// ... ], 46 | /// ... "value": [94, 95, 96, 97, 97, 99], 47 | /// ... }) 48 | /// >>> df.groupby("group", {maintain_order:True}).agg(pl.col("value").agg_groups()) 49 | /// shape: (2, 2) 50 | /// ┌───────┬───────────┐ 51 | /// │ group ┆ value │ 52 | /// │ --- ┆ --- │ 53 | /// │ str ┆ list[u32] │ 54 | /// ╞═══════╪═══════════╡ 55 | /// │ one ┆ [0, 1, 2] │ 56 | /// ├╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤ 57 | /// │ two ┆ [3, 4, 5] │ 58 | /// └───────┴───────────┘ 59 | /// ``` 60 | pub fn agg_groups(&self) -> JsExpr { 61 | self.clone().inner.agg_groups().into() 62 | } 63 | 64 | /// Rename the output of an expression. 65 | /// @param name - new name 66 | /// @example 67 | /// ```js 68 | /// > df = pl.DataFrame({ 69 | /// ... "a": [1, 2, 3], 70 | /// ... "b": ["a", "b", None], 71 | /// ... }) 72 | /// > df 73 | /// shape: (3, 2) 74 | /// ╭─────┬──────╮ 75 | /// │ a ┆ b │ 76 | /// │ --- ┆ --- │ 77 | /// │ i64 ┆ str │ 78 | /// ╞═════╪══════╡ 79 | /// │ 1 ┆ "a" │ 80 | /// ├╌╌╌╌╌┼╌╌╌╌╌╌┤ 81 | /// │ 2 ┆ "b" │ 82 | /// ├╌╌╌╌╌┼╌╌╌╌╌╌┤ 83 | /// │ 3 ┆ null │ 84 | /// ╰─────┴──────╯ 85 | /// > df.select([ 86 | /// ... pl.col("a").alias("bar"), 87 | /// ... pl.col("b").alias("foo"), 88 | /// ... ]) 89 | /// shape: (3, 2) 90 | /// ╭─────┬──────╮ 91 | /// │ bar ┆ foo │ 92 | /// │ --- ┆ --- │ 93 | /// │ i64 ┆ str │ 94 | /// ╞═════╪══════╡ 95 | /// │ 1 ┆ "a" │ 96 | /// ├╌╌╌╌╌┼╌╌╌╌╌╌┤ 97 | /// │ 2 ┆ "b" │ 98 | /// ├╌╌╌╌╌┼╌╌╌╌╌╌┤ 99 | /// │ 3 ┆ null │ 100 | /// ╰─────┴──────╯ 101 | /// ``` 102 | pub fn alias(&self, alias: &str) -> JsExpr { 103 | self.clone().inner.alias(alias).into() 104 | } 105 | /// Get the index of the maximal value. 106 | pub fn arg_max(&self) -> JsExpr { 107 | self.clone().inner.arg_max().into() 108 | } 109 | /// Get the index of the minimal value. 110 | pub fn arg_min(&self) -> JsExpr { 111 | self.clone().inner.arg_min().into() 112 | } 113 | /// Get the index values that would sort this column. 114 | /// @param reverse 115 | /// - false -> order from small to large. 116 | /// - true -> order from large to small. 117 | /// @returns UInt32 Series 118 | pub fn arg_sort(&self, reverse: bool) -> JsExpr { 119 | self.clone() 120 | .inner 121 | .arg_sort(SortOptions { 122 | descending: reverse, 123 | nulls_last: true, 124 | }) 125 | .into() 126 | } 127 | 128 | /// Get index of first unique value. 129 | pub fn arg_unique(&self) -> JsExpr { 130 | self.clone().inner.arg_unique().into() 131 | } 132 | 133 | /// Fill missing values with the next to be seen values 134 | pub fn backward_fill(&self) -> JsExpr { 135 | self.clone().inner.backward_fill(None).into() 136 | } 137 | 138 | /// Cast between data types. 139 | pub fn cast() -> JsExpr { 140 | todo!() 141 | } 142 | 143 | /// Count the number of values in this expression 144 | pub fn count(&self) -> JsExpr { 145 | self.clone().inner.count().into() 146 | } 147 | 148 | /// Calculate the n-th discrete difference. 149 | /// @param n - number of slots to shift 150 | /// @param nullBehavior - 'ignore' or 'drop' 151 | pub fn diff(&self) -> JsExpr { 152 | todo!() 153 | } 154 | 155 | /// Compute the dot/inner product between two Expressions 156 | /// @param other Expression to compute dot product with 157 | pub fn dot(&self, _other: &JsExpr) -> JsExpr { 158 | todo!() 159 | // self.inner.clone().dot(other.inner.clone()).into() 160 | } 161 | 162 | /// Exclude certain columns from a wildcard/regex selection. 163 | /// 164 | /// You may also use regexes in the exclude list. They must start with `^` and end with `$`. 165 | /// 166 | /// @param columns Column(s) to exclude from selection 167 | /// @example 168 | /// ```js 169 | /// > df = pl.DataFrame({ 170 | /// ... "a": [1, 2, 3], 171 | /// ... "b": ["a", "b", None], 172 | /// ... "c": [None, 2, 1], 173 | /// ...}) 174 | /// > df 175 | /// shape: (3, 3) 176 | /// ╭─────┬──────┬──────╮ 177 | /// │ a ┆ b ┆ c │ 178 | /// │ --- ┆ --- ┆ --- │ 179 | /// │ i64 ┆ str ┆ i64 │ 180 | /// ╞═════╪══════╪══════╡ 181 | /// │ 1 ┆ "a" ┆ null │ 182 | /// ├╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌┤ 183 | /// │ 2 ┆ "b" ┆ 2 │ 184 | /// ├╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌┤ 185 | /// │ 3 ┆ null ┆ 1 │ 186 | /// ╰─────┴──────┴──────╯ 187 | /// > df.select( 188 | /// ... pl.col("*").exclude("b"), 189 | /// ... ) 190 | /// shape: (3, 2) 191 | /// ╭─────┬──────╮ 192 | /// │ a ┆ c │ 193 | /// │ --- ┆ --- │ 194 | /// │ i64 ┆ i64 │ 195 | /// ╞═════╪══════╡ 196 | /// │ 1 ┆ null │ 197 | /// ├╌╌╌╌╌┼╌╌╌╌╌╌┤ 198 | /// │ 2 ┆ 2 │ 199 | /// ├╌╌╌╌╌┼╌╌╌╌╌╌┤ 200 | /// │ 3 ┆ 1 │ 201 | /// ╰─────┴──────╯ 202 | /// ``` 203 | /// / 204 | pub fn exclude(&self) -> JsExpr { 205 | todo!() 206 | } 207 | 208 | /// Explode a list or utf8 Series. 209 | /// This means that every item is expanded to a new row. 210 | pub fn explode(&self) -> JsExpr { 211 | self.clone().inner.explode().into() 212 | } 213 | pub fn extend(&self) -> JsExpr { 214 | todo!() 215 | } 216 | pub fn extend_constant(&self) -> JsExpr { 217 | todo!() 218 | } 219 | 220 | /// Fill nan value with a fill value 221 | pub fn fill_nan(&self, expr: &JsExpr) -> JsExpr { 222 | self.inner.clone().fill_nan(expr.inner.clone()).into() 223 | } 224 | /// Fill null value with a fill value or strategy 225 | pub fn fill_null(&self, expr: &JsExpr) -> JsExpr { 226 | self.clone().inner.fill_null(expr.inner.clone()).into() 227 | } 228 | 229 | /// Filter a single column. 230 | /// Mostly useful in in aggregation context. 231 | /// If you want to filter on a DataFrame level, use `LazyFrame.filter`. 232 | /// @param predicate - Boolean expression. 233 | pub fn filter(&self, predicate: &JsExpr) -> JsExpr { 234 | self.clone().inner.filter(predicate.inner.clone()).into() 235 | } 236 | 237 | /// Get the first value. 238 | pub fn first(&self) -> JsExpr { 239 | self.clone().inner.first().into() 240 | } 241 | 242 | /// Fill missing values with the latest seen values 243 | pub fn forward_fill(&self) -> JsExpr { 244 | self.clone().inner.forward_fill(None).into() 245 | } 246 | } 247 | 248 | #[wasm_bindgen(js_class=Expr)] 249 | impl JsExpr { 250 | pub fn add(&self, rhs: &JsExpr) -> JsExpr { 251 | dsl::binary_expr(self.inner.clone(), Operator::Plus, rhs.inner.clone()).into() 252 | } 253 | 254 | pub fn sub(&self, rhs: &JsExpr) -> JsExpr { 255 | dsl::binary_expr(self.inner.clone(), Operator::Minus, rhs.inner.clone()).into() 256 | } 257 | 258 | pub fn mul(&self, rhs: &JsExpr) -> JsExpr { 259 | dsl::binary_expr(self.inner.clone(), Operator::Multiply, rhs.inner.clone()).into() 260 | } 261 | 262 | pub fn truediv(&self, rhs: &JsExpr) -> JsExpr { 263 | dsl::binary_expr(self.inner.clone(), Operator::TrueDivide, rhs.inner.clone()).into() 264 | } 265 | 266 | pub fn modulus(&self, rhs: &JsExpr) -> JsExpr { 267 | dsl::binary_expr(self.inner.clone(), Operator::Modulus, rhs.inner.clone()).into() 268 | } 269 | 270 | pub fn floordiv(&self, rhs: &JsExpr) -> JsExpr { 271 | dsl::binary_expr(self.inner.clone(), Operator::Divide, rhs.inner.clone()).into() 272 | } 273 | 274 | pub fn to_string(&self) -> String { 275 | format!("{:?}", self.inner) 276 | } 277 | 278 | pub fn eq(&self, other: &JsExpr) -> JsExpr { 279 | self.clone().inner.eq(other.inner.clone()).into() 280 | } 281 | 282 | pub fn neq(&self, other: &JsExpr) -> JsExpr { 283 | self.clone().inner.neq(other.inner.clone()).into() 284 | } 285 | 286 | pub fn gt(&self, other: &JsExpr) -> JsExpr { 287 | self.clone().inner.gt(other.inner.clone()).into() 288 | } 289 | 290 | pub fn gt_eq(&self, other: &JsExpr) -> JsExpr { 291 | self.clone().inner.gt_eq(other.inner.clone()).into() 292 | } 293 | 294 | pub fn lt_eq(&self, other: &JsExpr) -> JsExpr { 295 | self.clone().inner.lt_eq(other.inner.clone()).into() 296 | } 297 | 298 | pub fn lt(&self, other: &JsExpr) -> JsExpr { 299 | self.clone().inner.lt(other.inner.clone()).into() 300 | } 301 | 302 | pub fn is_not(&self) -> JsExpr { 303 | self.clone().inner.not().into() 304 | } 305 | 306 | pub fn is_null(&self) -> JsExpr { 307 | self.clone().inner.is_null().into() 308 | } 309 | 310 | pub fn is_not_null(&self) -> JsExpr { 311 | self.clone().inner.is_not_null().into() 312 | } 313 | 314 | pub fn is_infinite(&self) -> JsExpr { 315 | self.clone().inner.is_infinite().into() 316 | } 317 | 318 | pub fn is_finite(&self) -> JsExpr { 319 | self.clone().inner.is_finite().into() 320 | } 321 | 322 | pub fn is_nan(&self) -> JsExpr { 323 | self.clone().inner.is_nan().into() 324 | } 325 | 326 | pub fn is_not_nan(&self) -> JsExpr { 327 | self.clone().inner.is_not_nan().into() 328 | } 329 | 330 | pub fn min(&self) -> JsExpr { 331 | self.clone().inner.min().into() 332 | } 333 | 334 | pub fn max(&self) -> JsExpr { 335 | self.clone().inner.max().into() 336 | } 337 | 338 | pub fn mean(&self) -> JsExpr { 339 | self.clone().inner.mean().into() 340 | } 341 | 342 | pub fn median(&self) -> JsExpr { 343 | self.clone().inner.median().into() 344 | } 345 | 346 | pub fn sum(&self) -> JsExpr { 347 | self.clone().inner.sum().into() 348 | } 349 | 350 | pub fn n_unique(&self) -> JsExpr { 351 | self.clone().inner.n_unique().into() 352 | } 353 | 354 | pub fn unique(&self) -> JsExpr { 355 | self.clone().inner.unique().into() 356 | } 357 | 358 | pub fn unique_stable(&self) -> JsExpr { 359 | self.clone().inner.unique_stable().into() 360 | } 361 | 362 | pub fn last(&self) -> JsExpr { 363 | self.clone().inner.last().into() 364 | } 365 | 366 | pub fn list(&self) -> JsExpr { 367 | self.clone().inner.list().into() 368 | } 369 | 370 | pub fn quantile(&self, _quantile: &JsExpr) -> JsExpr { 371 | todo!() 372 | } 373 | 374 | pub fn value_counts(&self, multithreaded: bool, sorted: bool) -> JsExpr { 375 | self.inner 376 | .clone() 377 | .value_counts(multithreaded, sorted) 378 | .into() 379 | } 380 | 381 | pub fn unique_counts(&self) -> JsExpr { 382 | self.inner.clone().unique_counts().into() 383 | } 384 | 385 | pub fn sort_with(&self, descending: bool, nulls_last: bool) -> JsExpr { 386 | self.clone() 387 | .inner 388 | .sort_with(SortOptions { 389 | descending, 390 | nulls_last, 391 | }) 392 | .into() 393 | } 394 | 395 | pub fn take(&self, idx: &JsExpr) -> JsExpr { 396 | self.clone().inner.take(idx.inner.clone()).into() 397 | } 398 | pub fn sort_by() -> JsExpr { 399 | todo!() 400 | } 401 | 402 | pub fn shift(&self, periods: i64) -> JsExpr { 403 | self.clone().inner.shift(periods).into() 404 | } 405 | 406 | pub fn shift_and_fill(&self, periods: i64, fill_value: &JsExpr) -> JsExpr { 407 | self.clone() 408 | .inner 409 | .shift_and_fill(periods, fill_value.inner.clone()) 410 | .into() 411 | } 412 | 413 | pub fn fill_null_with_strategy(&self) -> JsExpr { 414 | todo!() 415 | // self.inner 416 | // .clone() 417 | // .apply(move |s| s.fill_null(strategy.0), GetOutput::same_type()) 418 | // .with_fmt("fill_null") 419 | // .into() 420 | } 421 | 422 | pub fn drop_nulls(&self) -> JsExpr { 423 | self.inner.clone().drop_nulls().into() 424 | } 425 | 426 | pub fn drop_nans(&self) -> JsExpr { 427 | self.inner.clone().drop_nans().into() 428 | } 429 | 430 | pub fn reverse(&self) -> JsExpr { 431 | self.clone().inner.reverse().into() 432 | } 433 | 434 | pub fn std(&self, ddof: Option) -> JsExpr { 435 | let ddof = ddof.unwrap_or(1); 436 | self.clone().inner.std(ddof).into() 437 | } 438 | 439 | pub fn var(&self, ddof: Option) -> JsExpr { 440 | let ddof = ddof.unwrap_or(1); 441 | self.clone().inner.var(ddof).into() 442 | } 443 | pub fn is_unique(&self) -> JsExpr { 444 | self.clone().inner.is_unique().into() 445 | } 446 | 447 | pub fn is_first(&self) -> JsExpr { 448 | self.clone().inner.is_first().into() 449 | } 450 | 451 | pub fn take_every(&self, n: i64) -> JsExpr { 452 | self.clone() 453 | .inner 454 | .map( 455 | move |s: Series| Ok(s.take_every(n as usize)), 456 | GetOutput::same_type(), 457 | ) 458 | .with_fmt("take_every") 459 | .into() 460 | } 461 | 462 | pub fn tail(&self, n: Option) -> JsExpr { 463 | let n = n.map(|v| v as usize); 464 | self.clone().inner.tail(n).into() 465 | } 466 | 467 | pub fn head(&self, n: Option) -> JsExpr { 468 | let n = n.map(|v| v as usize); 469 | self.clone().inner.head(n).into() 470 | } 471 | pub fn slice(&self, offset: &JsExpr, length: &JsExpr) -> JsExpr { 472 | self.inner 473 | .clone() 474 | .slice(offset.inner.clone(), length.inner.clone()) 475 | .into() 476 | } 477 | pub fn round(&self, decimals: u32) -> JsExpr { 478 | self.clone().inner.round(decimals).into() 479 | } 480 | 481 | pub fn floor(&self) -> JsExpr { 482 | self.clone().inner.floor().into() 483 | } 484 | 485 | pub fn ceil(&self) -> JsExpr { 486 | self.clone().inner.ceil().into() 487 | } 488 | pub fn clip(&self) -> JsExpr { 489 | todo!() 490 | } 491 | 492 | pub fn is_duplicated(&self) -> JsExpr { 493 | self.clone().inner.is_duplicated().into() 494 | } 495 | } 496 | -------------------------------------------------------------------------------- /src/lazy/expr/string.rs: -------------------------------------------------------------------------------- 1 | use polars::lazy::dsl::Expr; 2 | use polars::prelude::*; 3 | use wasm_bindgen::prelude::*; 4 | 5 | use super::JsExpr; 6 | 7 | #[wasm_bindgen(js_name=StringNameSpace)] 8 | pub struct JsStringNameSpace { 9 | pub(crate) inner: Expr, 10 | } 11 | 12 | #[wasm_bindgen(js_class=StringNameSpace)] 13 | impl JsStringNameSpace { 14 | pub fn contains_literal(&self, literal: &str) -> JsExpr { 15 | self.inner.clone().str().contains_literal(literal).into() 16 | } 17 | 18 | pub fn contains(&self, pat: &str) -> JsExpr { 19 | self.inner.clone().str().contains(pat).into() 20 | } 21 | 22 | pub fn ends_with(&self, sub: &str) -> JsExpr { 23 | self.inner.clone().str().ends_with(sub).into() 24 | } 25 | 26 | pub fn starts_with(&self, sub: &str) -> JsExpr { 27 | self.inner.clone().str().starts_with(sub).into() 28 | } 29 | pub fn extract(&self, pat: &str, group_index: usize) -> JsExpr { 30 | self.inner.clone().str().extract(pat, group_index).into() 31 | } 32 | 33 | pub fn zfill(&self, alignment: usize) -> JsExpr { 34 | self.inner.clone().str().zfill(alignment).into() 35 | } 36 | pub fn ljust(&self, width: usize, fillchar: char) -> JsExpr { 37 | self.inner.clone().str().ljust(width, fillchar).into() 38 | } 39 | pub fn rjust(&self, width: usize, fillchar: char) -> JsExpr { 40 | self.inner.clone().str().rjust(width, fillchar).into() 41 | } 42 | 43 | pub fn extract_all(&self, pat: &JsExpr) -> JsExpr { 44 | self.inner 45 | .clone() 46 | .str() 47 | .extract_all(pat.inner.clone()) 48 | .into() 49 | } 50 | 51 | pub fn count_match(&self, pat: &str) -> JsExpr { 52 | self.inner.clone().str().count_match(pat).into() 53 | } 54 | 55 | pub fn lengths(&self) -> JsExpr { 56 | let function = |s: Series| { 57 | let ca = s.utf8()?; 58 | Ok(ca.str_lengths().into_series()) 59 | }; 60 | self.inner 61 | .clone() 62 | .map(function, GetOutput::from_type(DataType::UInt32)) 63 | .with_fmt("str.lengths") 64 | .into() 65 | } 66 | pub fn n_chars(&self) -> JsExpr { 67 | let function = |s: Series| { 68 | let ca = s.utf8()?; 69 | Ok(ca.str_n_chars().into_series()) 70 | }; 71 | self.inner 72 | .clone() 73 | .map(function, GetOutput::from_type(DataType::UInt32)) 74 | .with_fmt("str.n_chars") 75 | .into() 76 | } 77 | 78 | fn hex_encode(&self) -> JsExpr { 79 | self.inner 80 | .clone() 81 | .map( 82 | move |s| s.utf8().map(|s| s.hex_encode().into_series()), 83 | GetOutput::same_type(), 84 | ) 85 | .with_fmt("str.hex_encode") 86 | .into() 87 | } 88 | 89 | fn base64_encode(&self) -> JsExpr { 90 | self.inner 91 | .clone() 92 | .map( 93 | move |s| s.utf8().map(|s| s.base64_encode().into_series()), 94 | GetOutput::same_type(), 95 | ) 96 | .with_fmt("str.base64_encode") 97 | .into() 98 | } 99 | 100 | pub fn encode(&self, encoding: &str) -> JsExpr { 101 | match encoding { 102 | "hex" => self.hex_encode(), 103 | "base64" => self.base64_encode(), 104 | _ => panic!("Encoding {} not supported", encoding), 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/lazy/lazy_functions.rs: -------------------------------------------------------------------------------- 1 | use polars::lazy::dsl; 2 | use polars::prelude::*; 3 | use wasm_bindgen::prelude::*; 4 | 5 | use super::expr::JsExpr; 6 | 7 | #[wasm_bindgen] 8 | #[derive(Clone)] 9 | pub struct When { 10 | predicate: Expr, 11 | } 12 | #[wasm_bindgen] 13 | #[derive(Clone)] 14 | pub struct WhenThen { 15 | predicate: Expr, 16 | then: Expr, 17 | } 18 | 19 | #[wasm_bindgen] 20 | #[derive(Clone)] 21 | pub struct WhenThenThen { 22 | inner: dsl::WhenThenThen, 23 | } 24 | 25 | #[wasm_bindgen] 26 | impl When { 27 | pub fn then(&self, expr: &JsExpr) -> WhenThen { 28 | WhenThen { 29 | predicate: self.predicate.clone(), 30 | then: expr.inner.clone(), 31 | } 32 | } 33 | } 34 | #[wasm_bindgen] 35 | impl WhenThen { 36 | pub fn when(&self, predicate: &JsExpr) -> WhenThenThen { 37 | let e = dsl::when(self.predicate.clone()) 38 | .then(self.then.clone()) 39 | .when(predicate.inner.clone()); 40 | WhenThenThen { inner: e } 41 | } 42 | 43 | pub fn otherwise(&self, expr: &JsExpr) -> JsExpr { 44 | dsl::ternary_expr( 45 | self.predicate.clone(), 46 | self.then.clone(), 47 | expr.inner.clone(), 48 | ) 49 | .into() 50 | } 51 | } 52 | 53 | #[wasm_bindgen] 54 | impl WhenThenThen { 55 | pub fn when(&self, predicate: &JsExpr) -> WhenThenThen { 56 | Self { 57 | inner: self.inner.clone().when(predicate.inner.clone()), 58 | } 59 | } 60 | 61 | pub fn then(&self, expr: &JsExpr) -> WhenThenThen { 62 | Self { 63 | inner: self.inner.clone().then(expr.inner.clone()), 64 | } 65 | } 66 | pub fn otherwise(&self, expr: &JsExpr) -> JsExpr { 67 | self.inner.clone().otherwise(expr.inner.clone()).into() 68 | } 69 | } 70 | 71 | #[wasm_bindgen] 72 | pub fn when(predicate: &JsExpr) -> When { 73 | When { 74 | predicate: predicate.inner.clone(), 75 | } 76 | } 77 | 78 | /// __A column in a DataFrame.__ 79 | /// Can be used to select: 80 | /// - a single column by name 81 | /// - all columns by using a wildcard `"*"` 82 | /// - column by regular expression if the regex starts with `^` and ends with `$` 83 | /// @param col 84 | /// @example 85 | /// ```js 86 | /// > df = pl.DataFrame({ 87 | /// ... "ham": [1, 2, 3], 88 | /// ... "hamburger": [11, 22, 33], 89 | /// ... "foo": [3, 2, 1]}) 90 | /// > df.select(col("foo")) 91 | /// shape: (3, 1) 92 | /// ╭─────╮ 93 | /// │ foo │ 94 | /// │ --- │ 95 | /// │ i64 │ 96 | /// ╞═════╡ 97 | /// │ 3 │ 98 | /// ├╌╌╌╌╌┤ 99 | /// │ 2 │ 100 | /// ├╌╌╌╌╌┤ 101 | /// │ 1 │ 102 | /// ╰─────╯ 103 | /// > df.select(col("*")) 104 | /// shape: (3, 3) 105 | /// ╭─────┬───────────┬─────╮ 106 | /// │ ham ┆ hamburger ┆ foo │ 107 | /// │ --- ┆ --- ┆ --- │ 108 | /// │ i64 ┆ i64 ┆ i64 │ 109 | /// ╞═════╪═══════════╪═════╡ 110 | /// │ 1 ┆ 11 ┆ 3 │ 111 | /// ├╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤ 112 | /// │ 2 ┆ 22 ┆ 2 │ 113 | /// ├╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤ 114 | /// │ 3 ┆ 33 ┆ 1 │ 115 | /// ╰─────┴───────────┴─────╯ 116 | /// > df.select(col("^ham.*$")) 117 | /// shape: (3, 2) 118 | /// ╭─────┬───────────╮ 119 | /// │ ham ┆ hamburger │ 120 | /// │ --- ┆ --- │ 121 | /// │ i64 ┆ i64 │ 122 | /// ╞═════╪═══════════╡ 123 | /// │ 1 ┆ 11 │ 124 | /// ├╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤ 125 | /// │ 2 ┆ 22 │ 126 | /// ├╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤ 127 | /// │ 3 ┆ 33 │ 128 | /// ╰─────┴───────────╯ 129 | /// > df.select(col("*").exclude("ham")) 130 | /// shape: (3, 2) 131 | /// ╭───────────┬─────╮ 132 | /// │ hamburger ┆ foo │ 133 | /// │ --- ┆ --- │ 134 | /// │ i64 ┆ i64 │ 135 | /// ╞═══════════╪═════╡ 136 | /// │ 11 ┆ 3 │ 137 | /// ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤ 138 | /// │ 22 ┆ 2 │ 139 | /// ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤ 140 | /// │ 33 ┆ 1 │ 141 | /// ╰───────────┴─────╯ 142 | /// > df.select(col(["hamburger", "foo"]) 143 | /// shape: (3, 2) 144 | /// ╭───────────┬─────╮ 145 | /// │ hamburger ┆ foo │ 146 | /// │ --- ┆ --- │ 147 | /// │ i64 ┆ i64 │ 148 | /// ╞═══════════╪═════╡ 149 | /// │ 11 ┆ 3 │ 150 | /// ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤ 151 | /// │ 22 ┆ 2 │ 152 | /// ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤ 153 | /// │ 33 ┆ 1 │ 154 | /// ╰───────────┴─────╯ 155 | /// > df.select(col(pl.Series(["hamburger", "foo"])) 156 | /// shape: (3, 2) 157 | /// ╭───────────┬─────╮ 158 | /// │ hamburger ┆ foo │ 159 | /// │ --- ┆ --- │ 160 | /// │ i64 ┆ i64 │ 161 | /// ╞═══════════╪═════╡ 162 | /// │ 11 ┆ 3 │ 163 | /// ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤ 164 | /// │ 22 ┆ 2 │ 165 | /// ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤ 166 | /// │ 33 ┆ 1 │ 167 | /// ╰───────────┴─────╯ 168 | /// ``` 169 | /// / 170 | #[wasm_bindgen] 171 | pub fn col(name: String) -> JsExpr { 172 | dsl::col(&name).into() 173 | } 174 | 175 | #[wasm_bindgen] 176 | pub fn count() -> JsExpr { 177 | dsl::count().into() 178 | } 179 | 180 | #[wasm_bindgen] 181 | pub fn first() -> JsExpr { 182 | dsl::first().into() 183 | } 184 | 185 | #[wasm_bindgen] 186 | pub fn last() -> JsExpr { 187 | dsl::last().into() 188 | } 189 | 190 | #[wasm_bindgen] 191 | pub fn cols(names: JsValue) -> JsExpr { 192 | let names: Vec = serde_wasm_bindgen::from_value(names).unwrap(); 193 | dsl::cols(names).into() 194 | } 195 | -------------------------------------------------------------------------------- /src/lazy/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod dataframe; 2 | pub mod expr; 3 | pub mod lazy_functions; 4 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | mod conversion; 2 | mod dataframe; 3 | mod datatypes; 4 | mod error; 5 | mod series; 6 | mod utils; 7 | mod lazy; 8 | mod io; 9 | pub use io::*; 10 | use wasm_bindgen::prelude::*; 11 | pub use wasm_bindgen_rayon::init_thread_pool; 12 | 13 | pub type JsResult = std::result::Result; 14 | extern crate console_error_panic_hook; 15 | use std::panic; 16 | #[wasm_bindgen] 17 | pub fn init_hooks() { 18 | panic::set_hook(Box::new(console_error_panic_hook::hook)); 19 | } 20 | 21 | #[wasm_bindgen] 22 | extern "C" { 23 | #[wasm_bindgen(js_namespace = console)] 24 | fn log(s: &str); 25 | #[wasm_bindgen(js_namespace = console, js_name = log)] 26 | fn logv(x: &JsValue); 27 | } 28 | 29 | #[macro_export] 30 | macro_rules! console_log { 31 | ($($t:tt)*) => (crate::log(&format_args!($($t)*).to_string())) 32 | } 33 | -------------------------------------------------------------------------------- /src/series.rs: -------------------------------------------------------------------------------- 1 | use polars::prelude::*; 2 | use wasm_bindgen::JsCast; 3 | 4 | use crate::{ 5 | conversion::Wrap, dataframe::JsDataFrame, error::JsPolarsErr, extern_iterator, extern_struct, 6 | JsResult, 7 | }; 8 | 9 | use std::ops::Deref; 10 | use wasm_bindgen::prelude::*; 11 | 12 | #[wasm_bindgen(js_name=Series)] 13 | #[repr(transparent)] 14 | pub struct JsSeries { 15 | pub(crate) series: Series, 16 | } 17 | 18 | impl JsSeries { 19 | pub(crate) fn new(series: Series) -> Self { 20 | JsSeries { series } 21 | } 22 | } 23 | 24 | impl From for JsSeries { 25 | fn from(series: Series) -> Self { 26 | Self { series } 27 | } 28 | } 29 | 30 | impl Deref for JsSeries { 31 | type Target = Series; 32 | 33 | fn deref(&self) -> &Self::Target { 34 | &self.series 35 | } 36 | } 37 | 38 | #[wasm_bindgen] 39 | extern "C" { 40 | #[wasm_bindgen(typescript_type = "Series")] 41 | pub type ExternSeries; 42 | 43 | #[wasm_bindgen(typescript_type = "any")] 44 | pub type ExternAnyValue; 45 | 46 | #[wasm_bindgen(method, getter = ptr)] 47 | fn ptr(this: &ExternSeries) -> f64; 48 | 49 | #[wasm_bindgen(static_method_of = ExternSeries)] 50 | fn wrap(ptr: u32) -> ExternSeries; 51 | 52 | #[wasm_bindgen(typescript_type = "Series[]")] 53 | pub type SeriesArray; 54 | 55 | } 56 | 57 | extern_struct!(ExternSeries, JsSeries); 58 | extern_iterator!(SeriesArray, ExternSeries, JsSeries); 59 | 60 | #[wasm_bindgen(js_class=Series)] 61 | impl JsSeries { 62 | pub fn wrap(ptr: u32) -> JsSeries { 63 | unsafe { JsSeries::from_abi(ptr) } 64 | } 65 | pub fn new_str(name: &str, values: &js_sys::Array) -> JsResult { 66 | let series = Utf8Chunked::from_iter_options(name, values.iter().map(|v| v.as_string())) 67 | .into_series(); 68 | Ok(JsSeries { series }) 69 | } 70 | pub fn new_bool(name: &str, values: &js_sys::Array) -> JsResult { 71 | let series = BooleanChunked::from_iter_options(name, values.iter().map(|v| v.as_bool())) 72 | .into_series(); 73 | 74 | Ok(JsSeries { series }) 75 | } 76 | pub fn new_f64(name: &str, values: &js_sys::Array) -> JsResult { 77 | let series = 78 | Float64Chunked::from_iter_options(name, values.iter().map(|v: JsValue| v.as_f64())) 79 | .into_series(); 80 | Ok(JsSeries { series }) 81 | } 82 | pub fn new_i8(name: &str, values: &js_sys::Array) -> JsResult { 83 | let series = Int8Chunked::from_iter_options( 84 | name, 85 | values.iter().map(|v: JsValue| v.as_f64().map(|n| n as i8)), 86 | ) 87 | .into_series(); 88 | Ok(JsSeries { series }) 89 | } 90 | pub fn new_series_list(name: &str, val: SeriesArray, _strict: bool) -> Self { 91 | let vals = val.into_iter().map(|x| x.series).collect::>(); 92 | Series::new(name, &vals).into() 93 | } 94 | 95 | pub fn new_int_8_array(name: String, arr: &mut [i8]) -> JsSeries { 96 | Series::new(&name, arr).into() 97 | } 98 | 99 | pub fn new_uint_8_array(name: String, arr: &mut [u8]) -> JsSeries { 100 | Series::new(&name, arr).into() 101 | } 102 | 103 | pub fn new_int_16_array(name: String, arr: &mut [i16]) -> JsSeries { 104 | Series::new(&name, arr).into() 105 | } 106 | 107 | pub fn new_uint_16_array(name: String, arr: &mut [u16]) -> JsSeries { 108 | Series::new(&name, arr).into() 109 | } 110 | 111 | pub fn new_int_32_array(name: String, arr: &mut [i32]) -> JsSeries { 112 | Series::new(&name, arr).into() 113 | } 114 | 115 | pub fn new_uint_32_array(name: String, arr: &mut [u32]) -> JsSeries { 116 | Series::new(&name, arr).into() 117 | } 118 | 119 | pub fn new_int_64_array(name: String, arr: &mut [i64]) -> JsSeries { 120 | Series::new(&name, arr).into() 121 | } 122 | 123 | pub fn new_uint_64_array(name: String, arr: &mut [u64]) -> JsSeries { 124 | Series::new(&name, arr).into() 125 | } 126 | 127 | pub fn new_float_32_array(name: String, arr: &mut [f32]) -> JsSeries { 128 | Series::new(&name, arr).into() 129 | } 130 | 131 | pub fn new_float_64_array(name: String, arr: &mut [f64]) -> JsSeries { 132 | Series::new(&name, arr).into() 133 | } 134 | 135 | pub fn new_opt_str_array(name: String, arr: js_sys::Array) -> JsSeries { 136 | let len = arr.length() as usize; 137 | let mut builder = Utf8ChunkedBuilder::new(&name, len, len * 25); 138 | for value in arr.iter() { 139 | if value.is_null() { 140 | builder.append_null(); 141 | } else { 142 | builder.append_value(value.as_string().unwrap().as_str()); 143 | } 144 | } 145 | builder.finish().into_series().into() 146 | } 147 | 148 | pub fn new_opt_bool_array(name: String, arr: js_sys::Array) -> JsSeries { 149 | let len = arr.length() as usize; 150 | let mut builder = BooleanChunkedBuilder::new(&name, len); 151 | for value in arr.iter() { 152 | if value.is_null() { 153 | builder.append_null(); 154 | } else { 155 | builder.append_option(value.as_bool()); 156 | } 157 | } 158 | builder.finish().into_series().into() 159 | } 160 | 161 | pub fn get_idx(&self, idx: usize) -> JsResult { 162 | let av = self.series.get(idx).map_err(JsPolarsErr::from)?; 163 | Ok(Wrap(av).into()) 164 | } 165 | 166 | #[wasm_bindgen(getter)] 167 | pub fn name(&self) -> String { 168 | self.series.name().to_owned() 169 | } 170 | pub fn to_string(&self) -> String { 171 | format!("{}", self.series) 172 | } 173 | pub fn estimated_size(&self) -> i64 { 174 | self.series.estimated_size() as i64 175 | } 176 | 177 | pub fn rechunk(&mut self, in_place: bool) -> Option { 178 | let series = self.series.rechunk(); 179 | if in_place { 180 | self.series = series; 181 | None 182 | } else { 183 | Some(series.into()) 184 | } 185 | } 186 | 187 | pub fn bitand(&self, other: &JsSeries) -> JsResult { 188 | let out = self 189 | .series 190 | .bitand(&other.series) 191 | .map_err(JsPolarsErr::from)?; 192 | Ok(out.into()) 193 | } 194 | pub fn bitor(&self, other: &JsSeries) -> JsResult { 195 | let out = self 196 | .series 197 | .bitor(&other.series) 198 | .map_err(JsPolarsErr::from)?; 199 | Ok(out.into()) 200 | } 201 | pub fn bitxor(&self, other: &JsSeries) -> JsResult { 202 | let out = self 203 | .series 204 | .bitxor(&other.series) 205 | .map_err(JsPolarsErr::from)?; 206 | Ok(out.into()) 207 | } 208 | pub fn cumsum(&self, reverse: Option) -> JsSeries { 209 | let reverse = reverse.unwrap_or(false); 210 | self.series.cumsum(reverse).into() 211 | } 212 | pub fn cummax(&self, reverse: Option) -> JsSeries { 213 | let reverse = reverse.unwrap_or(false); 214 | self.series.cummax(reverse).into() 215 | } 216 | pub fn cummin(&self, reverse: Option) -> JsSeries { 217 | let reverse = reverse.unwrap_or(false); 218 | self.series.cummin(reverse).into() 219 | } 220 | pub fn cumprod(&self, reverse: Option) -> JsSeries { 221 | let reverse = reverse.unwrap_or(false); 222 | self.series.cumprod(reverse).into() 223 | } 224 | pub fn chunk_lengths(&self) -> Vec { 225 | self.series.chunk_lengths().map(|i| i as u32).collect() 226 | } 227 | pub fn rename(&mut self, name: String) { 228 | self.series.rename(&name); 229 | } 230 | pub fn mean(&self) -> Option { 231 | match self.series.dtype() { 232 | DataType::Boolean => { 233 | let s = self.series.cast(&DataType::UInt8).unwrap(); 234 | s.mean() 235 | } 236 | _ => self.series.mean(), 237 | } 238 | } 239 | 240 | pub fn n_chunks(&self) -> u32 { 241 | self.series.n_chunks() as u32 242 | } 243 | 244 | pub fn limit(&self, num_elements: f64) -> JsSeries { 245 | self.series.limit(num_elements as usize).into() 246 | } 247 | 248 | pub fn slice(&self, offset: i64, length: f64) -> JsSeries { 249 | self.series.slice(offset, length as usize).into() 250 | } 251 | 252 | pub fn append(&mut self, other: &JsSeries) -> JsResult<()> { 253 | self.series 254 | .append(&other.series) 255 | .map_err(JsPolarsErr::from)?; 256 | Ok(()) 257 | } 258 | 259 | pub fn extend(&mut self, other: &JsSeries) -> JsResult<()> { 260 | self.series 261 | .extend(&other.series) 262 | .map_err(JsPolarsErr::from)?; 263 | Ok(()) 264 | } 265 | pub fn filter(&self, filter: &JsSeries) -> JsResult { 266 | let filter_series = &filter.series; 267 | if let Ok(ca) = filter_series.bool() { 268 | let series = self.series.filter(ca).map_err(JsPolarsErr::from)?; 269 | Ok(JsSeries { series }) 270 | } else { 271 | let err = "Expected a boolean mask".to_string(); 272 | Err(err.into()) 273 | } 274 | } 275 | 276 | pub fn add(&self, other: &JsSeries) -> JsSeries { 277 | (&self.series + &other.series).into() 278 | } 279 | 280 | pub fn sub(&self, other: &JsSeries) -> JsSeries { 281 | (&self.series - &other.series).into() 282 | } 283 | 284 | pub fn mul(&self, other: &JsSeries) -> JsSeries { 285 | (&self.series * &other.series).into() 286 | } 287 | 288 | pub fn div(&self, other: &JsSeries) -> JsSeries { 289 | (&self.series / &other.series).into() 290 | } 291 | 292 | pub fn rem(&self, other: &JsSeries) -> JsSeries { 293 | (&self.series % &other.series).into() 294 | } 295 | 296 | pub fn head(&self, length: Option) -> JsSeries { 297 | (self.series.head(length.map(|l| l as usize))).into() 298 | } 299 | 300 | pub fn tail(&self, length: Option) -> JsSeries { 301 | (self.series.tail(length.map(|l| l as usize))).into() 302 | } 303 | 304 | pub fn sort(&self, reverse: Option) -> JsSeries { 305 | let reverse = reverse.unwrap_or(false); 306 | self.series.sort(reverse).into() 307 | } 308 | 309 | pub fn argsort(&self, reverse: bool, nulls_last: bool) -> JsSeries { 310 | self.series 311 | .argsort(SortOptions { 312 | descending: reverse, 313 | nulls_last, 314 | }) 315 | .into_series() 316 | .into() 317 | } 318 | 319 | pub fn unique(&self) -> JsResult { 320 | let unique = self.series.unique().map_err(JsPolarsErr::from)?; 321 | Ok(unique.into()) 322 | } 323 | 324 | pub fn unique_stable(&self) -> JsResult { 325 | let unique = self.series.unique_stable().map_err(JsPolarsErr::from)?; 326 | Ok(unique.into()) 327 | } 328 | 329 | pub fn value_counts(&self, sorted: bool) -> JsResult { 330 | let df = self 331 | .series 332 | .value_counts(true, sorted) 333 | .map_err(JsPolarsErr::from)?; 334 | Ok(df.into()) 335 | } 336 | 337 | pub fn arg_unique(&self) -> JsResult { 338 | let arg_unique = self.series.arg_unique().map_err(JsPolarsErr::from)?; 339 | Ok(arg_unique.into_series().into()) 340 | } 341 | 342 | pub fn arg_min(&self) -> Option { 343 | self.series.arg_min().map(|v| v as i64) 344 | } 345 | 346 | pub fn arg_max(&self) -> Option { 347 | self.series.arg_max().map(|v| v as i64) 348 | } 349 | 350 | pub fn take(&self, indices: Vec) -> JsResult { 351 | let indices = UInt32Chunked::from_vec("", indices); 352 | 353 | let take = self.series.take(&indices).map_err(JsPolarsErr::from)?; 354 | Ok(JsSeries::new(take)) 355 | } 356 | 357 | pub fn take_with_series(&self, indices: &JsSeries) -> JsResult { 358 | let idx = indices.series.u32().map_err(JsPolarsErr::from)?; 359 | let take = self.series.take(idx).map_err(JsPolarsErr::from)?; 360 | Ok(JsSeries::new(take)) 361 | } 362 | 363 | pub fn null_count(&self) -> JsResult { 364 | Ok(self.series.null_count() as i64) 365 | } 366 | 367 | pub fn has_validity(&self) -> bool { 368 | self.series.has_validity() 369 | } 370 | 371 | pub fn is_null(&self) -> JsSeries { 372 | Self::new(self.series.is_null().into_series()) 373 | } 374 | 375 | pub fn is_not_null(&self) -> JsSeries { 376 | Self::new(self.series.is_not_null().into_series()) 377 | } 378 | 379 | pub fn is_not_nan(&self) -> JsResult { 380 | let ca = self.series.is_not_nan().map_err(JsPolarsErr::from)?; 381 | Ok(ca.into_series().into()) 382 | } 383 | 384 | pub fn is_nan(&self) -> JsResult { 385 | let ca = self.series.is_nan().map_err(JsPolarsErr::from)?; 386 | Ok(ca.into_series().into()) 387 | } 388 | 389 | pub fn is_finite(&self) -> JsResult { 390 | let ca = self.series.is_finite().map_err(JsPolarsErr::from)?; 391 | Ok(ca.into_series().into()) 392 | } 393 | 394 | pub fn is_infinite(&self) -> JsResult { 395 | let ca = self.series.is_infinite().map_err(JsPolarsErr::from)?; 396 | Ok(ca.into_series().into()) 397 | } 398 | 399 | pub fn is_unique(&self) -> JsResult { 400 | let ca = self.series.is_unique().map_err(JsPolarsErr::from)?; 401 | Ok(ca.into_series().into()) 402 | } 403 | 404 | pub fn sample_frac( 405 | &self, 406 | frac: f64, 407 | with_replacement: bool, 408 | shuffle: bool, 409 | seed: Option, 410 | ) -> JsResult { 411 | // Safety: 412 | // Wrap is transparent. 413 | let s = self 414 | .series 415 | .sample_frac(frac, with_replacement, shuffle, seed) 416 | .map_err(JsPolarsErr::from)?; 417 | Ok(s.into()) 418 | } 419 | 420 | pub fn is_duplicated(&self) -> JsResult { 421 | let ca = self.series.is_duplicated().map_err(JsPolarsErr::from)?; 422 | Ok(ca.into_series().into()) 423 | } 424 | 425 | pub fn explode(&self) -> JsResult { 426 | let s = self.series.explode().map_err(JsPolarsErr::from)?; 427 | Ok(s.into()) 428 | } 429 | 430 | pub fn take_every(&self, n: i64) -> JsSeries { 431 | let s = self.series.take_every(n as usize); 432 | s.into() 433 | } 434 | 435 | pub fn series_equal(&self, other: &JsSeries, null_equal: bool, strict: bool) -> bool { 436 | if strict { 437 | self.series.eq(&other.series) 438 | } else if null_equal { 439 | self.series.series_equal_missing(&other.series) 440 | } else { 441 | self.series.series_equal(&other.series) 442 | } 443 | } 444 | 445 | pub fn eq(&self, rhs: &JsSeries) -> JsResult { 446 | Ok(Self::new( 447 | self.series 448 | .equal(&rhs.series) 449 | .map_err(JsPolarsErr::from)? 450 | .into_series(), 451 | )) 452 | } 453 | 454 | pub fn neq(&self, rhs: &JsSeries) -> JsResult { 455 | Ok(Self::new( 456 | self.series 457 | .not_equal(&rhs.series) 458 | .map_err(JsPolarsErr::from)? 459 | .into_series(), 460 | )) 461 | } 462 | 463 | pub fn gt(&self, rhs: &JsSeries) -> JsResult { 464 | Ok(Self::new( 465 | self.series 466 | .gt(&rhs.series) 467 | .map_err(JsPolarsErr::from)? 468 | .into_series(), 469 | )) 470 | } 471 | 472 | pub fn gt_eq(&self, rhs: &JsSeries) -> JsResult { 473 | Ok(Self::new( 474 | self.series 475 | .gt_eq(&rhs.series) 476 | .map_err(JsPolarsErr::from)? 477 | .into_series(), 478 | )) 479 | } 480 | 481 | pub fn lt(&self, rhs: &JsSeries) -> JsResult { 482 | Ok(Self::new( 483 | self.series 484 | .lt(&rhs.series) 485 | .map_err(JsPolarsErr::from)? 486 | .into_series(), 487 | )) 488 | } 489 | 490 | pub fn lt_eq(&self, rhs: &JsSeries) -> JsResult { 491 | Ok(Self::new( 492 | self.series 493 | .lt_eq(&rhs.series) 494 | .map_err(JsPolarsErr::from)? 495 | .into_series(), 496 | )) 497 | } 498 | 499 | pub fn _not(&self) -> JsResult { 500 | let bool = self.series.bool().map_err(JsPolarsErr::from)?; 501 | Ok((!bool).into_series().into()) 502 | } 503 | 504 | pub fn as_str(&self) -> JsResult { 505 | Ok(format!("{:?}", self.series)) 506 | } 507 | 508 | pub fn len(&self) -> i64 { 509 | self.series.len() as i64 510 | } 511 | 512 | pub fn to_physical(&self) -> JsSeries { 513 | let s = self.series.to_physical_repr().into_owned(); 514 | s.into() 515 | } 516 | pub fn to_list(&self) -> JsValue { 517 | todo!() 518 | } 519 | pub fn median(&self) -> Option { 520 | match self.series.dtype() { 521 | DataType::Boolean => { 522 | let s = self.series.cast(&DataType::UInt8).unwrap(); 523 | s.median() 524 | } 525 | _ => self.series.median(), 526 | } 527 | } 528 | pub fn as_single_ptr(&mut self) -> JsResult { 529 | let ptr = self.series.as_single_ptr().map_err(JsPolarsErr::from)?; 530 | Ok(ptr) 531 | } 532 | pub fn drop_nulls(&self) -> Self { 533 | self.series.drop_nulls().into() 534 | } 535 | pub fn fill_null(&self, strategy: &str) -> JsResult { 536 | let strat = match strategy { 537 | // "backward" => FillNullStrategy::Backward, 538 | // "forward" => FillNullStrategy::Forward, 539 | "min" => FillNullStrategy::Min, 540 | "max" => FillNullStrategy::Max, 541 | "mean" => FillNullStrategy::Mean, 542 | "zero" => FillNullStrategy::Zero, 543 | "one" => FillNullStrategy::One, 544 | s => return Err(format!("Strategy {} not supported", s).into()), 545 | }; 546 | let series = self.series.fill_null(strat).map_err(JsPolarsErr::from)?; 547 | Ok(JsSeries::new(series)) 548 | } 549 | 550 | pub fn clone(&self) -> Self { 551 | JsSeries::new(self.series.clone()) 552 | } 553 | pub fn shift(&self, periods: i64) -> Self { 554 | let s = self.series.shift(periods); 555 | JsSeries::new(s) 556 | } 557 | pub fn zip_with(&self, mask: &JsSeries, other: &JsSeries) -> JsResult { 558 | let mask = mask.series.bool().map_err(JsPolarsErr::from)?; 559 | let s = self 560 | .series 561 | .zip_with(mask, &other.series) 562 | .map_err(JsPolarsErr::from)?; 563 | Ok(JsSeries::new(s)) 564 | } 565 | 566 | // pub fn strftime(&self, fmt: &str) -> JsResult { 567 | // let s = self.series.strftime(fmt).map_err(JsPolarsErr::from)?; 568 | // Ok(s.into()) 569 | // } 570 | 571 | pub fn arr_lengths(&self) -> JsResult { 572 | let ca = self.series.list().map_err(JsPolarsErr::from)?; 573 | let s = ca.lst_lengths().into_series(); 574 | Ok(JsSeries::new(s)) 575 | } 576 | 577 | // // pub fn timestamp(&self, tu: Wrap) -> JsResult { 578 | // // let ca = self.series.timestamp(tu.0).map_err(JsPolarsErr::from)?; 579 | // // Ok(ca.into_series().into()) 580 | // // } 581 | pub fn get_list(&self, index: usize) -> Option { 582 | if let Ok(ca) = &self.series.list() { 583 | let s = ca.get(index); 584 | s.map(|s| s.into()) 585 | } else { 586 | None 587 | } 588 | } 589 | 590 | // pub fn year(&self) -> JsResult { 591 | // let s = self.series.year().map_err(JsPolarsErr::from)?; 592 | // Ok(s.into_series().into()) 593 | // } 594 | 595 | // pub fn month(&self) -> JsResult { 596 | // let s = self.series.month().map_err(JsPolarsErr::from)?; 597 | // Ok(s.into_series().into()) 598 | // } 599 | 600 | // pub fn weekday(&self) -> JsResult { 601 | // let s = self.series.weekday().map_err(JsPolarsErr::from)?; 602 | // Ok(s.into_series().into()) 603 | // } 604 | 605 | // pub fn week(&self) -> JsResult { 606 | // let s = self.series.week().map_err(JsPolarsErr::from)?; 607 | // Ok(s.into_series().into()) 608 | // } 609 | 610 | // pub fn day(&self) -> JsResult { 611 | // let s = self.series.day().map_err(JsPolarsErr::from)?; 612 | // Ok(s.into_series().into()) 613 | // } 614 | 615 | // pub fn ordinal_day(&self) -> JsResult { 616 | // let s = self.series.ordinal_day().map_err(JsPolarsErr::from)?; 617 | // Ok(s.into_series().into()) 618 | // } 619 | 620 | // pub fn hour(&self) -> JsResult { 621 | // let s = self.series.hour().map_err(JsPolarsErr::from)?; 622 | // Ok(s.into_series().into()) 623 | // } 624 | 625 | // pub fn minute(&self) -> JsResult { 626 | // let s = self.series.minute().map_err(JsPolarsErr::from)?; 627 | // Ok(s.into_series().into()) 628 | // } 629 | 630 | // pub fn second(&self) -> JsResult { 631 | // let s = self.series.second().map_err(JsPolarsErr::from)?; 632 | // Ok(s.into_series().into()) 633 | // } 634 | 635 | // pub fn nanosecond(&self) -> JsResult { 636 | // let s = self.series.nanosecond().map_err(JsPolarsErr::from)?; 637 | // Ok(s.into_series().into()) 638 | // } 639 | 640 | // pub fn dt_epoch_seconds(&self) -> JsResult { 641 | // let ms = self 642 | // .series 643 | // .timestamp(TimeUnit::Milliseconds) 644 | // .map_err(JsPolarsErr::from)?; 645 | // Ok((ms / 1000).into_series().into()) 646 | // } 647 | 648 | pub fn peak_max(&self) -> Self { 649 | self.series.peak_max().into_series().into() 650 | } 651 | 652 | pub fn peak_min(&self) -> Self { 653 | self.series.peak_min().into_series().into() 654 | } 655 | 656 | pub fn n_unique(&self) -> JsResult { 657 | let n = self.series.n_unique().map_err(JsPolarsErr::from)?; 658 | Ok(n) 659 | } 660 | 661 | pub fn is_first(&self) -> JsResult { 662 | todo!() 663 | // let out = self 664 | // .series 665 | // .is_first() 666 | // .map_err(JsPolarsErr::from)? 667 | // .into_series(); 668 | // Ok(out.into()) 669 | } 670 | 671 | pub fn round(&self, decimals: u32) -> JsResult { 672 | let s = self.series.round(decimals).map_err(JsPolarsErr::from)?; 673 | Ok(s.into()) 674 | } 675 | 676 | pub fn floor(&self) -> JsResult { 677 | let s = self.series.floor().map_err(JsPolarsErr::from)?; 678 | Ok(s.into()) 679 | } 680 | 681 | pub fn shrink_to_fit(&mut self) { 682 | self.series.shrink_to_fit(); 683 | } 684 | 685 | pub fn dot(&self, _other: &JsSeries) -> Option { 686 | todo!() 687 | // self.series.dot(&other.series) 688 | } 689 | 690 | // pub fn hash(&self, k0: u64, k1: u64, k2: u64, k3: u64) -> Self { 691 | // todo!() 692 | // let hb = polars::export::ahash::RandomState::with_seeds(k0, k1, k2, k3); 693 | // self.series.hash(hb).into_series().into() 694 | // } 695 | 696 | // pub fn reinterpret(&self, signed: bool) -> JsResult { 697 | // todo!() 698 | // let s = reinterpret(&self.series, signed).map_err(JsPolarsErr::from)?; 699 | // Ok(s.into()) 700 | // } 701 | 702 | pub fn mode(&self) -> JsResult { 703 | let s = self.series.mode().map_err(JsPolarsErr::from)?; 704 | Ok(s.into()) 705 | } 706 | 707 | pub fn interpolate(&self) -> Self { 708 | todo!() 709 | // let s = self.series.interpolate(); 710 | // s.into() 711 | } 712 | pub fn rank(&self, _method: &str, _reverse: bool) -> JsResult { 713 | todo!() 714 | // let method = str_to_rankmethod(method).unwrap(); 715 | // let options = RankOptions { 716 | // method, 717 | // descending: reverse, 718 | // }; 719 | // Ok(self.series.rank(options).into()) 720 | } 721 | 722 | pub fn dtype(&self) -> String { 723 | let dt: crate::datatypes::JsDataType = self.series.dtype().into(); 724 | dt.to_string() 725 | } 726 | pub fn inner_dtype(&self) -> Option { 727 | self.series.dtype().inner_dtype().map(|dt| { 728 | let dt: crate::datatypes::JsDataType = dt.into(); 729 | dt.to_string() 730 | }) 731 | } 732 | } 733 | 734 | // pub fn reinterpret(s: &Series, signed: bool) -> polars::prelude::Result { 735 | // match (s.dtype(), signed) { 736 | // (DataType::UInt64, true) => { 737 | // let ca = s.u64().unwrap(); 738 | // Ok(ca.reinterpret_signed().into_series()) 739 | // } 740 | // (DataType::UInt64, false) => Ok(s.clone()), 741 | // (DataType::Int64, false) => { 742 | // let ca = s.i64().unwrap(); 743 | // Ok(ca.reinterpret_unsigned().into_series()) 744 | // } 745 | // (DataType::Int64, true) => Ok(s.clone()), 746 | // _ => Err(PolarsError::ComputeError( 747 | // "reinterpret is only allowed for 64bit integers dtype, use cast otherwise".into(), 748 | // )), 749 | // } 750 | // } 751 | pub(crate) fn to_series_collection(iter: js_sys::Iterator) -> Vec { 752 | let cols: Vec = iter 753 | .into_iter() 754 | .map(|jsv| { 755 | let jsv = jsv.unwrap(); 756 | let key = JsValue::from_str("ptr"); 757 | let ptr = js_sys::Reflect::get(&jsv, &key).unwrap(); 758 | let n: f64 = js_sys::Number::unchecked_from_js(ptr).into(); 759 | let ser: JsSeries = unsafe { JsSeries::from_abi(n as u32) }; 760 | ser.series 761 | }) 762 | .collect(); 763 | cols 764 | } 765 | 766 | // pub(crate) fn to_jsseries_collection(s: Vec) -> Vec { 767 | // use wasm_bindgen::convert::IntoWasmAbi; 768 | // let s: Vec = s 769 | // .into_iter() 770 | // .map(move |series| { 771 | // let js_ser = JsSeries { series }; 772 | 773 | // js_ser.into_abi() 774 | // }) 775 | // .collect(); 776 | 777 | // s 778 | // // todo!() 779 | // } 780 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | // use polars::prelude::{DataType, TimeUnit}; 2 | // use wasm_bindgen::convert::FromWasmAbi; 3 | 4 | // use crate::{JsResult, lazy::expr::JsExpr}; 5 | 6 | // pub fn str_to_polarstype(s: &str) -> DataType { 7 | // match s { 8 | // "UInt8" => DataType::UInt8, 9 | // "UInt16" => DataType::UInt16, 10 | // "UInt32" => DataType::UInt32, 11 | // "UInt64" => DataType::UInt64, 12 | // "Int8" => DataType::Int8, 13 | // "Int16" => DataType::Int16, 14 | // "Int32" => DataType::Int32, 15 | // "Int64" => DataType::Int64, 16 | // "Float32" => DataType::Float32, 17 | // "Float64" => DataType::Float64, 18 | // "Boolean" => DataType::Boolean, 19 | // "Utf8" => DataType::Utf8, 20 | // "Date" => DataType::Date, 21 | // "Datetime" => DataType::Datetime(TimeUnit::Milliseconds, None), 22 | // "Duration" => DataType::Duration(TimeUnit::Milliseconds), 23 | // "Time" => DataType::Time, 24 | // "List" => DataType::List(DataType::Null.into()), 25 | // "Categorical" => DataType::Categorical(None), 26 | // tp => panic!("Type {} not implemented in str_to_polarstype", tp), 27 | // } 28 | // } 29 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./polars/**/*.ts"], 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "allowJs": true, 6 | 7 | "experimentalDecorators": true, 8 | "outDir": "./dist", 9 | "target": "esnext", 10 | "module": "ESNext", 11 | "declarationMap": false, 12 | 13 | "baseUrl": "./", 14 | "rootDir": "./polars", 15 | "paths": { 16 | "*": ["node_modules/*"], 17 | "polars/*": ["polars/*"], 18 | "tslib": ["node_modules/tslib"] 19 | }, 20 | 21 | "moduleResolution": "node", 22 | "lib": ["DOM", "ESNext", "ESNext.AsyncIterable"], 23 | "esModuleInterop": true, 24 | 25 | 26 | "declaration": true, 27 | "noEmitOnError": true, 28 | "removeComments": false, 29 | "noErrorTruncation": true, 30 | "downlevelIteration": true, 31 | "sourceMap": false, 32 | "inlineSources": true, 33 | "inlineSourceMap": true, 34 | "strict": true, 35 | "noImplicitAny": false, 36 | "noImplicitThis": true, 37 | "alwaysStrict": true, 38 | "strictBindCallApply": true, 39 | "strictNullChecks": true, 40 | "strictFunctionTypes": true, 41 | "strictPropertyInitialization": true, 42 | "skipLibCheck": false, 43 | "noUnusedLocals": false, 44 | "noImplicitReturns": true, 45 | "noUnusedParameters": false, 46 | "allowUnusedLabels": false, 47 | "allowUnreachableCode": false, 48 | "noStrictGenericChecks": false, 49 | "noFallthroughCasesInSwitch": true, 50 | "forceConsistentCasingInFileNames": true 51 | } 52 | } -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # This file is generated by running "yarn install" inside your project. 2 | # Manual changes might be lost - proceed with caution! 3 | 4 | __metadata: 5 | version: 6 6 | cacheKey: 8 7 | 8 | "@cspotcode/source-map-support@npm:^0.8.0": 9 | version: 0.8.1 10 | resolution: "@cspotcode/source-map-support@npm:0.8.1" 11 | dependencies: 12 | "@jridgewell/trace-mapping": 0.3.9 13 | checksum: 5718f267085ed8edb3e7ef210137241775e607ee18b77d95aa5bd7514f47f5019aa2d82d96b3bf342ef7aa890a346fa1044532ff7cc3009e7d24fce3ce6200fa 14 | languageName: node 15 | linkType: hard 16 | 17 | "@gar/promisify@npm:^1.1.3": 18 | version: 1.1.3 19 | resolution: "@gar/promisify@npm:1.1.3" 20 | checksum: 4059f790e2d07bf3c3ff3e0fec0daa8144fe35c1f6e0111c9921bd32106adaa97a4ab096ad7dab1e28ee6a9060083c4d1a4ada42a7f5f3f7a96b8812e2b757c1 21 | languageName: node 22 | linkType: hard 23 | 24 | "@jridgewell/resolve-uri@npm:^3.0.3": 25 | version: 3.0.5 26 | resolution: "@jridgewell/resolve-uri@npm:3.0.5" 27 | checksum: 1ee652b693da7979ac4007926cc3f0a32b657ffeb913e111f44e5b67153d94a2f28a1d560101cc0cf8087625468293a69a00f634a2914e1a6d0817ba2039a913 28 | languageName: node 29 | linkType: hard 30 | 31 | "@jridgewell/sourcemap-codec@npm:^1.4.10": 32 | version: 1.4.11 33 | resolution: "@jridgewell/sourcemap-codec@npm:1.4.11" 34 | checksum: 3b2afaf8400fb07a36db60e901fcce6a746cdec587310ee9035939d89878e57b2dec8173b0b8f63176f647efa352294049a53c49739098eb907ff81fec2547c8 35 | languageName: node 36 | linkType: hard 37 | 38 | "@jridgewell/trace-mapping@npm:0.3.9": 39 | version: 0.3.9 40 | resolution: "@jridgewell/trace-mapping@npm:0.3.9" 41 | dependencies: 42 | "@jridgewell/resolve-uri": ^3.0.3 43 | "@jridgewell/sourcemap-codec": ^1.4.10 44 | checksum: d89597752fd88d3f3480845691a05a44bd21faac18e2185b6f436c3b0fd0c5a859fbbd9aaa92050c4052caf325ad3e10e2e1d1b64327517471b7d51babc0ddef 45 | languageName: node 46 | linkType: hard 47 | 48 | "@npmcli/fs@npm:^2.1.0": 49 | version: 2.1.2 50 | resolution: "@npmcli/fs@npm:2.1.2" 51 | dependencies: 52 | "@gar/promisify": ^1.1.3 53 | semver: ^7.3.5 54 | checksum: 405074965e72d4c9d728931b64d2d38e6ea12066d4fad651ac253d175e413c06fe4350970c783db0d749181da8fe49c42d3880bd1cbc12cd68e3a7964d820225 55 | languageName: node 56 | linkType: hard 57 | 58 | "@npmcli/move-file@npm:^2.0.0": 59 | version: 2.0.1 60 | resolution: "@npmcli/move-file@npm:2.0.1" 61 | dependencies: 62 | mkdirp: ^1.0.4 63 | rimraf: ^3.0.2 64 | checksum: 52dc02259d98da517fae4cb3a0a3850227bdae4939dda1980b788a7670636ca2b4a01b58df03dd5f65c1e3cb70c50fa8ce5762b582b3f499ec30ee5ce1fd9380 65 | languageName: node 66 | linkType: hard 67 | 68 | "@pola-rs/browser@workspace:.": 69 | version: 0.0.0-use.local 70 | resolution: "@pola-rs/browser@workspace:." 71 | dependencies: 72 | "@rollup/plugin-wasm": ^6.1.1 73 | rollup: ^3.9.0 74 | rome: ^11.0.0 75 | source-map-support: ^0.5.21 76 | ts-node: ^10.9.1 77 | typedoc: ^0.23.23 78 | typescript: 4.9 79 | languageName: unknown 80 | linkType: soft 81 | 82 | "@rollup/plugin-wasm@npm:^6.1.1": 83 | version: 6.1.1 84 | resolution: "@rollup/plugin-wasm@npm:6.1.1" 85 | peerDependencies: 86 | rollup: ^1.20.0||^2.0.0||^3.0.0 87 | peerDependenciesMeta: 88 | rollup: 89 | optional: true 90 | checksum: d79dfabbd3f016e36f2ca6bbbd5ae28607bb46c017a4cc8a171d13cc24e9fca3f1e206a97de61f618fe6e1236d1a1fb36b7daa3cddd7e41a5d9df72566d57a67 91 | languageName: node 92 | linkType: hard 93 | 94 | "@rometools/cli-darwin-arm64@npm:11.0.0": 95 | version: 11.0.0 96 | resolution: "@rometools/cli-darwin-arm64@npm:11.0.0" 97 | conditions: os=darwin & cpu=arm64 98 | languageName: node 99 | linkType: hard 100 | 101 | "@rometools/cli-darwin-x64@npm:11.0.0": 102 | version: 11.0.0 103 | resolution: "@rometools/cli-darwin-x64@npm:11.0.0" 104 | conditions: os=darwin & cpu=x64 105 | languageName: node 106 | linkType: hard 107 | 108 | "@rometools/cli-linux-arm64@npm:11.0.0": 109 | version: 11.0.0 110 | resolution: "@rometools/cli-linux-arm64@npm:11.0.0" 111 | conditions: os=linux & cpu=arm64 112 | languageName: node 113 | linkType: hard 114 | 115 | "@rometools/cli-linux-x64@npm:11.0.0": 116 | version: 11.0.0 117 | resolution: "@rometools/cli-linux-x64@npm:11.0.0" 118 | conditions: os=linux & cpu=x64 119 | languageName: node 120 | linkType: hard 121 | 122 | "@rometools/cli-win32-arm64@npm:11.0.0": 123 | version: 11.0.0 124 | resolution: "@rometools/cli-win32-arm64@npm:11.0.0" 125 | conditions: os=win32 & cpu=arm64 126 | languageName: node 127 | linkType: hard 128 | 129 | "@rometools/cli-win32-x64@npm:11.0.0": 130 | version: 11.0.0 131 | resolution: "@rometools/cli-win32-x64@npm:11.0.0" 132 | conditions: os=win32 & cpu=x64 133 | languageName: node 134 | linkType: hard 135 | 136 | "@tootallnate/once@npm:2": 137 | version: 2.0.0 138 | resolution: "@tootallnate/once@npm:2.0.0" 139 | checksum: ad87447820dd3f24825d2d947ebc03072b20a42bfc96cbafec16bff8bbda6c1a81fcb0be56d5b21968560c5359a0af4038a68ba150c3e1694fe4c109a063bed8 140 | languageName: node 141 | linkType: hard 142 | 143 | "@tsconfig/node10@npm:^1.0.7": 144 | version: 1.0.8 145 | resolution: "@tsconfig/node10@npm:1.0.8" 146 | checksum: b8d5fffbc6b17ef64ef74f7fdbccee02a809a063ade785c3648dae59406bc207f70ea2c4296f92749b33019fa36a5ae716e42e49cc7f1bbf0fd147be0d6b970a 147 | languageName: node 148 | linkType: hard 149 | 150 | "@tsconfig/node12@npm:^1.0.7": 151 | version: 1.0.9 152 | resolution: "@tsconfig/node12@npm:1.0.9" 153 | checksum: a01b2400ab3582b86b589c6d31dcd0c0656f333adecde85d6d7d4086adb059808b82692380bb169546d189bf771ae21d02544a75b57bd6da4a5dd95f8567bec9 154 | languageName: node 155 | linkType: hard 156 | 157 | "@tsconfig/node14@npm:^1.0.0": 158 | version: 1.0.1 159 | resolution: "@tsconfig/node14@npm:1.0.1" 160 | checksum: 976345e896c0f059867f94f8d0f6ddb8b1844fb62bf36b727de8a9a68f024857e5db97ed51d3325e23e0616a5e48c034ff51a8d595b3fe7e955f3587540489be 161 | languageName: node 162 | linkType: hard 163 | 164 | "@tsconfig/node16@npm:^1.0.2": 165 | version: 1.0.2 166 | resolution: "@tsconfig/node16@npm:1.0.2" 167 | checksum: ca94d3639714672bbfd55f03521d3f56bb6a25479bd425da81faf21f13e1e9d15f40f97377dedbbf477a5841c5b0c8f4cd1b391f33553d750b9202c54c2c07aa 168 | languageName: node 169 | linkType: hard 170 | 171 | "abbrev@npm:^1.0.0": 172 | version: 1.1.1 173 | resolution: "abbrev@npm:1.1.1" 174 | checksum: a4a97ec07d7ea112c517036882b2ac22f3109b7b19077dc656316d07d308438aac28e4d9746dc4d84bf6b1e75b4a7b0a5f3cb30592419f128ca9a8cee3bcfa17 175 | languageName: node 176 | linkType: hard 177 | 178 | "acorn-walk@npm:^8.1.1": 179 | version: 8.2.0 180 | resolution: "acorn-walk@npm:8.2.0" 181 | checksum: 1715e76c01dd7b2d4ca472f9c58968516a4899378a63ad5b6c2d668bba8da21a71976c14ec5f5b75f887b6317c4ae0b897ab141c831d741dc76024d8745f1ad1 182 | languageName: node 183 | linkType: hard 184 | 185 | "acorn@npm:^8.4.1": 186 | version: 8.7.0 187 | resolution: "acorn@npm:8.7.0" 188 | bin: 189 | acorn: bin/acorn 190 | checksum: e0f79409d68923fbf1aa6d4166f3eedc47955320d25c89a20cc822e6ba7c48c5963d5bc657bc242d68f7a4ac9faf96eef033e8f73656da6c640d4219935fdfd0 191 | languageName: node 192 | linkType: hard 193 | 194 | "agent-base@npm:6, agent-base@npm:^6.0.2": 195 | version: 6.0.2 196 | resolution: "agent-base@npm:6.0.2" 197 | dependencies: 198 | debug: 4 199 | checksum: f52b6872cc96fd5f622071b71ef200e01c7c4c454ee68bc9accca90c98cfb39f2810e3e9aa330435835eedc8c23f4f8a15267f67c6e245d2b33757575bdac49d 200 | languageName: node 201 | linkType: hard 202 | 203 | "agentkeepalive@npm:^4.2.1": 204 | version: 4.2.1 205 | resolution: "agentkeepalive@npm:4.2.1" 206 | dependencies: 207 | debug: ^4.1.0 208 | depd: ^1.1.2 209 | humanize-ms: ^1.2.1 210 | checksum: 39cb49ed8cf217fd6da058a92828a0a84e0b74c35550f82ee0a10e1ee403c4b78ade7948be2279b188b7a7303f5d396ea2738b134731e464bf28de00a4f72a18 211 | languageName: node 212 | linkType: hard 213 | 214 | "aggregate-error@npm:^3.0.0": 215 | version: 3.1.0 216 | resolution: "aggregate-error@npm:3.1.0" 217 | dependencies: 218 | clean-stack: ^2.0.0 219 | indent-string: ^4.0.0 220 | checksum: 1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79 221 | languageName: node 222 | linkType: hard 223 | 224 | "ansi-regex@npm:^5.0.1": 225 | version: 5.0.1 226 | resolution: "ansi-regex@npm:5.0.1" 227 | checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b 228 | languageName: node 229 | linkType: hard 230 | 231 | "aproba@npm:^1.0.3 || ^2.0.0": 232 | version: 2.0.0 233 | resolution: "aproba@npm:2.0.0" 234 | checksum: 5615cadcfb45289eea63f8afd064ab656006361020e1735112e346593856f87435e02d8dcc7ff0d11928bc7d425f27bc7c2a84f6c0b35ab0ff659c814c138a24 235 | languageName: node 236 | linkType: hard 237 | 238 | "are-we-there-yet@npm:^3.0.0": 239 | version: 3.0.1 240 | resolution: "are-we-there-yet@npm:3.0.1" 241 | dependencies: 242 | delegates: ^1.0.0 243 | readable-stream: ^3.6.0 244 | checksum: 52590c24860fa7173bedeb69a4c05fb573473e860197f618b9a28432ee4379049336727ae3a1f9c4cb083114601c1140cee578376164d0e651217a9843f9fe83 245 | languageName: node 246 | linkType: hard 247 | 248 | "arg@npm:^4.1.0": 249 | version: 4.1.3 250 | resolution: "arg@npm:4.1.3" 251 | checksum: 544af8dd3f60546d3e4aff084d451b96961d2267d668670199692f8d054f0415d86fc5497d0e641e91546f0aa920e7c29e5250e99fc89f5552a34b5d93b77f43 252 | languageName: node 253 | linkType: hard 254 | 255 | "balanced-match@npm:^1.0.0": 256 | version: 1.0.2 257 | resolution: "balanced-match@npm:1.0.2" 258 | checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 259 | languageName: node 260 | linkType: hard 261 | 262 | "brace-expansion@npm:^1.1.7": 263 | version: 1.1.11 264 | resolution: "brace-expansion@npm:1.1.11" 265 | dependencies: 266 | balanced-match: ^1.0.0 267 | concat-map: 0.0.1 268 | checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 269 | languageName: node 270 | linkType: hard 271 | 272 | "brace-expansion@npm:^2.0.1": 273 | version: 2.0.1 274 | resolution: "brace-expansion@npm:2.0.1" 275 | dependencies: 276 | balanced-match: ^1.0.0 277 | checksum: a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 278 | languageName: node 279 | linkType: hard 280 | 281 | "buffer-from@npm:^1.0.0": 282 | version: 1.1.2 283 | resolution: "buffer-from@npm:1.1.2" 284 | checksum: 0448524a562b37d4d7ed9efd91685a5b77a50672c556ea254ac9a6d30e3403a517d8981f10e565db24e8339413b43c97ca2951f10e399c6125a0d8911f5679bb 285 | languageName: node 286 | linkType: hard 287 | 288 | "cacache@npm:^16.1.0": 289 | version: 16.1.3 290 | resolution: "cacache@npm:16.1.3" 291 | dependencies: 292 | "@npmcli/fs": ^2.1.0 293 | "@npmcli/move-file": ^2.0.0 294 | chownr: ^2.0.0 295 | fs-minipass: ^2.1.0 296 | glob: ^8.0.1 297 | infer-owner: ^1.0.4 298 | lru-cache: ^7.7.1 299 | minipass: ^3.1.6 300 | minipass-collect: ^1.0.2 301 | minipass-flush: ^1.0.5 302 | minipass-pipeline: ^1.2.4 303 | mkdirp: ^1.0.4 304 | p-map: ^4.0.0 305 | promise-inflight: ^1.0.1 306 | rimraf: ^3.0.2 307 | ssri: ^9.0.0 308 | tar: ^6.1.11 309 | unique-filename: ^2.0.0 310 | checksum: d91409e6e57d7d9a3a25e5dcc589c84e75b178ae8ea7de05cbf6b783f77a5fae938f6e8fda6f5257ed70000be27a681e1e44829251bfffe4c10216002f8f14e6 311 | languageName: node 312 | linkType: hard 313 | 314 | "chownr@npm:^2.0.0": 315 | version: 2.0.0 316 | resolution: "chownr@npm:2.0.0" 317 | checksum: c57cf9dd0791e2f18a5ee9c1a299ae6e801ff58fee96dc8bfd0dcb4738a6ce58dd252a3605b1c93c6418fe4f9d5093b28ffbf4d66648cb2a9c67eaef9679be2f 318 | languageName: node 319 | linkType: hard 320 | 321 | "clean-stack@npm:^2.0.0": 322 | version: 2.2.0 323 | resolution: "clean-stack@npm:2.2.0" 324 | checksum: 2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 325 | languageName: node 326 | linkType: hard 327 | 328 | "color-support@npm:^1.1.3": 329 | version: 1.1.3 330 | resolution: "color-support@npm:1.1.3" 331 | bin: 332 | color-support: bin.js 333 | checksum: 9b7356817670b9a13a26ca5af1c21615463b500783b739b7634a0c2047c16cef4b2865d7576875c31c3cddf9dd621fa19285e628f20198b233a5cfdda6d0793b 334 | languageName: node 335 | linkType: hard 336 | 337 | "concat-map@npm:0.0.1": 338 | version: 0.0.1 339 | resolution: "concat-map@npm:0.0.1" 340 | checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af 341 | languageName: node 342 | linkType: hard 343 | 344 | "console-control-strings@npm:^1.1.0": 345 | version: 1.1.0 346 | resolution: "console-control-strings@npm:1.1.0" 347 | checksum: 8755d76787f94e6cf79ce4666f0c5519906d7f5b02d4b884cf41e11dcd759ed69c57da0670afd9236d229a46e0f9cf519db0cd829c6dca820bb5a5c3def584ed 348 | languageName: node 349 | linkType: hard 350 | 351 | "create-require@npm:^1.1.0": 352 | version: 1.1.1 353 | resolution: "create-require@npm:1.1.1" 354 | checksum: a9a1503d4390d8b59ad86f4607de7870b39cad43d929813599a23714831e81c520bddf61bcdd1f8e30f05fd3a2b71ae8538e946eb2786dc65c2bbc520f692eff 355 | languageName: node 356 | linkType: hard 357 | 358 | "debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.3.3": 359 | version: 4.3.4 360 | resolution: "debug@npm:4.3.4" 361 | dependencies: 362 | ms: 2.1.2 363 | peerDependenciesMeta: 364 | supports-color: 365 | optional: true 366 | checksum: 3dbad3f94ea64f34431a9cbf0bafb61853eda57bff2880036153438f50fb5a84f27683ba0d8e5426bf41a8c6ff03879488120cf5b3a761e77953169c0600a708 367 | languageName: node 368 | linkType: hard 369 | 370 | "delegates@npm:^1.0.0": 371 | version: 1.0.0 372 | resolution: "delegates@npm:1.0.0" 373 | checksum: a51744d9b53c164ba9c0492471a1a2ffa0b6727451bdc89e31627fdf4adda9d51277cfcbfb20f0a6f08ccb3c436f341df3e92631a3440226d93a8971724771fd 374 | languageName: node 375 | linkType: hard 376 | 377 | "depd@npm:^1.1.2": 378 | version: 1.1.2 379 | resolution: "depd@npm:1.1.2" 380 | checksum: 6b406620d269619852885ce15965272b829df6f409724415e0002c8632ab6a8c0a08ec1f0bd2add05dc7bd7507606f7e2cc034fa24224ab829580040b835ecd9 381 | languageName: node 382 | linkType: hard 383 | 384 | "diff@npm:^4.0.1": 385 | version: 4.0.2 386 | resolution: "diff@npm:4.0.2" 387 | checksum: f2c09b0ce4e6b301c221addd83bf3f454c0bc00caa3dd837cf6c127d6edf7223aa2bbe3b688feea110b7f262adbfc845b757c44c8a9f8c0c5b15d8fa9ce9d20d 388 | languageName: node 389 | linkType: hard 390 | 391 | "emoji-regex@npm:^8.0.0": 392 | version: 8.0.0 393 | resolution: "emoji-regex@npm:8.0.0" 394 | checksum: d4c5c39d5a9868b5fa152f00cada8a936868fd3367f33f71be515ecee4c803132d11b31a6222b2571b1e5f7e13890156a94880345594d0ce7e3c9895f560f192 395 | languageName: node 396 | linkType: hard 397 | 398 | "encoding@npm:^0.1.13": 399 | version: 0.1.13 400 | resolution: "encoding@npm:0.1.13" 401 | dependencies: 402 | iconv-lite: ^0.6.2 403 | checksum: bb98632f8ffa823996e508ce6a58ffcf5856330fde839ae42c9e1f436cc3b5cc651d4aeae72222916545428e54fd0f6aa8862fd8d25bdbcc4589f1e3f3715e7f 404 | languageName: node 405 | linkType: hard 406 | 407 | "env-paths@npm:^2.2.0": 408 | version: 2.2.1 409 | resolution: "env-paths@npm:2.2.1" 410 | checksum: 65b5df55a8bab92229ab2b40dad3b387fad24613263d103a97f91c9fe43ceb21965cd3392b1ccb5d77088021e525c4e0481adb309625d0cb94ade1d1fb8dc17e 411 | languageName: node 412 | linkType: hard 413 | 414 | "err-code@npm:^2.0.2": 415 | version: 2.0.3 416 | resolution: "err-code@npm:2.0.3" 417 | checksum: 8b7b1be20d2de12d2255c0bc2ca638b7af5171142693299416e6a9339bd7d88fc8d7707d913d78e0993176005405a236b066b45666b27b797252c771156ace54 418 | languageName: node 419 | linkType: hard 420 | 421 | "fs-minipass@npm:^2.0.0, fs-minipass@npm:^2.1.0": 422 | version: 2.1.0 423 | resolution: "fs-minipass@npm:2.1.0" 424 | dependencies: 425 | minipass: ^3.0.0 426 | checksum: 1b8d128dae2ac6cc94230cc5ead341ba3e0efaef82dab46a33d171c044caaa6ca001364178d42069b2809c35a1c3c35079a32107c770e9ffab3901b59af8c8b1 427 | languageName: node 428 | linkType: hard 429 | 430 | "fs.realpath@npm:^1.0.0": 431 | version: 1.0.0 432 | resolution: "fs.realpath@npm:1.0.0" 433 | checksum: 99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0 434 | languageName: node 435 | linkType: hard 436 | 437 | "fsevents@npm:~2.3.2": 438 | version: 2.3.2 439 | resolution: "fsevents@npm:2.3.2" 440 | dependencies: 441 | node-gyp: latest 442 | checksum: 97ade64e75091afee5265e6956cb72ba34db7819b4c3e94c431d4be2b19b8bb7a2d4116da417950c3425f17c8fe693d25e20212cac583ac1521ad066b77ae31f 443 | conditions: os=darwin 444 | languageName: node 445 | linkType: hard 446 | 447 | "fsevents@patch:fsevents@~2.3.2#~builtin": 448 | version: 2.3.2 449 | resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1" 450 | dependencies: 451 | node-gyp: latest 452 | conditions: os=darwin 453 | languageName: node 454 | linkType: hard 455 | 456 | "gauge@npm:^4.0.3": 457 | version: 4.0.4 458 | resolution: "gauge@npm:4.0.4" 459 | dependencies: 460 | aproba: ^1.0.3 || ^2.0.0 461 | color-support: ^1.1.3 462 | console-control-strings: ^1.1.0 463 | has-unicode: ^2.0.1 464 | signal-exit: ^3.0.7 465 | string-width: ^4.2.3 466 | strip-ansi: ^6.0.1 467 | wide-align: ^1.1.5 468 | checksum: 788b6bfe52f1dd8e263cda800c26ac0ca2ff6de0b6eee2fe0d9e3abf15e149b651bd27bf5226be10e6e3edb5c4e5d5985a5a1a98137e7a892f75eff76467ad2d 469 | languageName: node 470 | linkType: hard 471 | 472 | "glob@npm:^7.1.3, glob@npm:^7.1.4": 473 | version: 7.2.3 474 | resolution: "glob@npm:7.2.3" 475 | dependencies: 476 | fs.realpath: ^1.0.0 477 | inflight: ^1.0.4 478 | inherits: 2 479 | minimatch: ^3.1.1 480 | once: ^1.3.0 481 | path-is-absolute: ^1.0.0 482 | checksum: 29452e97b38fa704dabb1d1045350fb2467cf0277e155aa9ff7077e90ad81d1ea9d53d3ee63bd37c05b09a065e90f16aec4a65f5b8de401d1dac40bc5605d133 483 | languageName: node 484 | linkType: hard 485 | 486 | "glob@npm:^8.0.1": 487 | version: 8.0.3 488 | resolution: "glob@npm:8.0.3" 489 | dependencies: 490 | fs.realpath: ^1.0.0 491 | inflight: ^1.0.4 492 | inherits: 2 493 | minimatch: ^5.0.1 494 | once: ^1.3.0 495 | checksum: 50bcdea19d8e79d8de5f460b1939ffc2b3299eac28deb502093fdca22a78efebc03e66bf54f0abc3d3d07d8134d19a32850288b7440d77e072aa55f9d33b18c5 496 | languageName: node 497 | linkType: hard 498 | 499 | "graceful-fs@npm:^4.2.6": 500 | version: 4.2.10 501 | resolution: "graceful-fs@npm:4.2.10" 502 | checksum: 3f109d70ae123951905d85032ebeae3c2a5a7a997430df00ea30df0e3a6c60cf6689b109654d6fdacd28810a053348c4d14642da1d075049e6be1ba5216218da 503 | languageName: node 504 | linkType: hard 505 | 506 | "has-unicode@npm:^2.0.1": 507 | version: 2.0.1 508 | resolution: "has-unicode@npm:2.0.1" 509 | checksum: 1eab07a7436512db0be40a710b29b5dc21fa04880b7f63c9980b706683127e3c1b57cb80ea96d47991bdae2dfe479604f6a1ba410106ee1046a41d1bd0814400 510 | languageName: node 511 | linkType: hard 512 | 513 | "http-cache-semantics@npm:^4.1.0": 514 | version: 4.1.0 515 | resolution: "http-cache-semantics@npm:4.1.0" 516 | checksum: 974de94a81c5474be07f269f9fd8383e92ebb5a448208223bfb39e172a9dbc26feff250192ecc23b9593b3f92098e010406b0f24bd4d588d631f80214648ed42 517 | languageName: node 518 | linkType: hard 519 | 520 | "http-proxy-agent@npm:^5.0.0": 521 | version: 5.0.0 522 | resolution: "http-proxy-agent@npm:5.0.0" 523 | dependencies: 524 | "@tootallnate/once": 2 525 | agent-base: 6 526 | debug: 4 527 | checksum: e2ee1ff1656a131953839b2a19cd1f3a52d97c25ba87bd2559af6ae87114abf60971e498021f9b73f9fd78aea8876d1fb0d4656aac8a03c6caa9fc175f22b786 528 | languageName: node 529 | linkType: hard 530 | 531 | "https-proxy-agent@npm:^5.0.0": 532 | version: 5.0.1 533 | resolution: "https-proxy-agent@npm:5.0.1" 534 | dependencies: 535 | agent-base: 6 536 | debug: 4 537 | checksum: 571fccdf38184f05943e12d37d6ce38197becdd69e58d03f43637f7fa1269cf303a7d228aa27e5b27bbd3af8f09fd938e1c91dcfefff2df7ba77c20ed8dfc765 538 | languageName: node 539 | linkType: hard 540 | 541 | "humanize-ms@npm:^1.2.1": 542 | version: 1.2.1 543 | resolution: "humanize-ms@npm:1.2.1" 544 | dependencies: 545 | ms: ^2.0.0 546 | checksum: 9c7a74a2827f9294c009266c82031030eae811ca87b0da3dceb8d6071b9bde22c9f3daef0469c3c533cc67a97d8a167cd9fc0389350e5f415f61a79b171ded16 547 | languageName: node 548 | linkType: hard 549 | 550 | "iconv-lite@npm:^0.6.2": 551 | version: 0.6.3 552 | resolution: "iconv-lite@npm:0.6.3" 553 | dependencies: 554 | safer-buffer: ">= 2.1.2 < 3.0.0" 555 | checksum: 3f60d47a5c8fc3313317edfd29a00a692cc87a19cac0159e2ce711d0ebc9019064108323b5e493625e25594f11c6236647d8e256fbe7a58f4a3b33b89e6d30bf 556 | languageName: node 557 | linkType: hard 558 | 559 | "imurmurhash@npm:^0.1.4": 560 | version: 0.1.4 561 | resolution: "imurmurhash@npm:0.1.4" 562 | checksum: 7cae75c8cd9a50f57dadd77482359f659eaebac0319dd9368bcd1714f55e65badd6929ca58569da2b6494ef13fdd5598cd700b1eba23f8b79c5f19d195a3ecf7 563 | languageName: node 564 | linkType: hard 565 | 566 | "indent-string@npm:^4.0.0": 567 | version: 4.0.0 568 | resolution: "indent-string@npm:4.0.0" 569 | checksum: 824cfb9929d031dabf059bebfe08cf3137365e112019086ed3dcff6a0a7b698cb80cf67ccccde0e25b9e2d7527aa6cc1fed1ac490c752162496caba3e6699612 570 | languageName: node 571 | linkType: hard 572 | 573 | "infer-owner@npm:^1.0.4": 574 | version: 1.0.4 575 | resolution: "infer-owner@npm:1.0.4" 576 | checksum: 181e732764e4a0611576466b4b87dac338972b839920b2a8cde43642e4ed6bd54dc1fb0b40874728f2a2df9a1b097b8ff83b56d5f8f8e3927f837fdcb47d8a89 577 | languageName: node 578 | linkType: hard 579 | 580 | "inflight@npm:^1.0.4": 581 | version: 1.0.6 582 | resolution: "inflight@npm:1.0.6" 583 | dependencies: 584 | once: ^1.3.0 585 | wrappy: 1 586 | checksum: f4f76aa072ce19fae87ce1ef7d221e709afb59d445e05d47fba710e85470923a75de35bfae47da6de1b18afc3ce83d70facf44cfb0aff89f0a3f45c0a0244dfd 587 | languageName: node 588 | linkType: hard 589 | 590 | "inherits@npm:2, inherits@npm:^2.0.3": 591 | version: 2.0.4 592 | resolution: "inherits@npm:2.0.4" 593 | checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 594 | languageName: node 595 | linkType: hard 596 | 597 | "ip@npm:^2.0.0": 598 | version: 2.0.0 599 | resolution: "ip@npm:2.0.0" 600 | checksum: cfcfac6b873b701996d71ec82a7dd27ba92450afdb421e356f44044ed688df04567344c36cbacea7d01b1c39a4c732dc012570ebe9bebfb06f27314bca625349 601 | languageName: node 602 | linkType: hard 603 | 604 | "is-fullwidth-code-point@npm:^3.0.0": 605 | version: 3.0.0 606 | resolution: "is-fullwidth-code-point@npm:3.0.0" 607 | checksum: 44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348 608 | languageName: node 609 | linkType: hard 610 | 611 | "is-lambda@npm:^1.0.1": 612 | version: 1.0.1 613 | resolution: "is-lambda@npm:1.0.1" 614 | checksum: 93a32f01940220532e5948538699ad610d5924ac86093fcee83022252b363eb0cc99ba53ab084a04e4fb62bf7b5731f55496257a4c38adf87af9c4d352c71c35 615 | languageName: node 616 | linkType: hard 617 | 618 | "isexe@npm:^2.0.0": 619 | version: 2.0.0 620 | resolution: "isexe@npm:2.0.0" 621 | checksum: 26bf6c5480dda5161c820c5b5c751ae1e766c587b1f951ea3fcfc973bafb7831ae5b54a31a69bd670220e42e99ec154475025a468eae58ea262f813fdc8d1c62 622 | languageName: node 623 | linkType: hard 624 | 625 | "jsonc-parser@npm:^3.0.0": 626 | version: 3.0.0 627 | resolution: "jsonc-parser@npm:3.0.0" 628 | checksum: 1df2326f1f9688de30c70ff19c5b2a83ba3b89a1036160da79821d1361090775e9db502dc57a67c11b56e1186fc1ed70b887f25c5febf9a3ec4f91435836c99d 629 | languageName: node 630 | linkType: hard 631 | 632 | "lru-cache@npm:^6.0.0": 633 | version: 6.0.0 634 | resolution: "lru-cache@npm:6.0.0" 635 | dependencies: 636 | yallist: ^4.0.0 637 | checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297 638 | languageName: node 639 | linkType: hard 640 | 641 | "lru-cache@npm:^7.7.1": 642 | version: 7.14.1 643 | resolution: "lru-cache@npm:7.14.1" 644 | checksum: d72c6713c6a6d86836a7a6523b3f1ac6764768cca47ec99341c3e76db06aacd4764620e5e2cda719a36848785a52a70e531822dc2b33fb071fa709683746c104 645 | languageName: node 646 | linkType: hard 647 | 648 | "lunr@npm:^2.3.9": 649 | version: 2.3.9 650 | resolution: "lunr@npm:2.3.9" 651 | checksum: 176719e24fcce7d3cf1baccce9dd5633cd8bdc1f41ebe6a180112e5ee99d80373fe2454f5d4624d437e5a8319698ca6837b9950566e15d2cae5f2a543a3db4b8 652 | languageName: node 653 | linkType: hard 654 | 655 | "make-error@npm:^1.1.1": 656 | version: 1.3.6 657 | resolution: "make-error@npm:1.3.6" 658 | checksum: b86e5e0e25f7f777b77fabd8e2cbf15737972869d852a22b7e73c17623928fccb826d8e46b9951501d3f20e51ad74ba8c59ed584f610526a48f8ccf88aaec402 659 | languageName: node 660 | linkType: hard 661 | 662 | "make-fetch-happen@npm:^10.0.3": 663 | version: 10.2.1 664 | resolution: "make-fetch-happen@npm:10.2.1" 665 | dependencies: 666 | agentkeepalive: ^4.2.1 667 | cacache: ^16.1.0 668 | http-cache-semantics: ^4.1.0 669 | http-proxy-agent: ^5.0.0 670 | https-proxy-agent: ^5.0.0 671 | is-lambda: ^1.0.1 672 | lru-cache: ^7.7.1 673 | minipass: ^3.1.6 674 | minipass-collect: ^1.0.2 675 | minipass-fetch: ^2.0.3 676 | minipass-flush: ^1.0.5 677 | minipass-pipeline: ^1.2.4 678 | negotiator: ^0.6.3 679 | promise-retry: ^2.0.1 680 | socks-proxy-agent: ^7.0.0 681 | ssri: ^9.0.0 682 | checksum: 2332eb9a8ec96f1ffeeea56ccefabcb4193693597b132cd110734d50f2928842e22b84cfa1508e921b8385cdfd06dda9ad68645fed62b50fff629a580f5fb72c 683 | languageName: node 684 | linkType: hard 685 | 686 | "marked@npm:^4.2.4": 687 | version: 4.2.5 688 | resolution: "marked@npm:4.2.5" 689 | bin: 690 | marked: bin/marked.js 691 | checksum: dd7da20a3983c66b516463fad5dc8d15dc70e137d20b6dc491e134f671e84bd2ed5f859e2c35f21e56830a122e4356b9e574bcde49b72b7ad6bc121a215a1a98 692 | languageName: node 693 | linkType: hard 694 | 695 | "minimatch@npm:^3.1.1": 696 | version: 3.1.2 697 | resolution: "minimatch@npm:3.1.2" 698 | dependencies: 699 | brace-expansion: ^1.1.7 700 | checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a 701 | languageName: node 702 | linkType: hard 703 | 704 | "minimatch@npm:^5.0.1, minimatch@npm:^5.1.1": 705 | version: 5.1.2 706 | resolution: "minimatch@npm:5.1.2" 707 | dependencies: 708 | brace-expansion: ^2.0.1 709 | checksum: 32ffda25b9fb8270a1c1beafdb7489dc0e411af553495136509a945691f63c9b6b000eeeaaf8bffe3efa609c1d6d3bc0f5a106f6c3443b5c05da649100ded964 710 | languageName: node 711 | linkType: hard 712 | 713 | "minipass-collect@npm:^1.0.2": 714 | version: 1.0.2 715 | resolution: "minipass-collect@npm:1.0.2" 716 | dependencies: 717 | minipass: ^3.0.0 718 | checksum: 14df761028f3e47293aee72888f2657695ec66bd7d09cae7ad558da30415fdc4752bbfee66287dcc6fd5e6a2fa3466d6c484dc1cbd986525d9393b9523d97f10 719 | languageName: node 720 | linkType: hard 721 | 722 | "minipass-fetch@npm:^2.0.3": 723 | version: 2.1.2 724 | resolution: "minipass-fetch@npm:2.1.2" 725 | dependencies: 726 | encoding: ^0.1.13 727 | minipass: ^3.1.6 728 | minipass-sized: ^1.0.3 729 | minizlib: ^2.1.2 730 | dependenciesMeta: 731 | encoding: 732 | optional: true 733 | checksum: 3f216be79164e915fc91210cea1850e488793c740534985da017a4cbc7a5ff50506956d0f73bb0cb60e4fe91be08b6b61ef35101706d3ef5da2c8709b5f08f91 734 | languageName: node 735 | linkType: hard 736 | 737 | "minipass-flush@npm:^1.0.5": 738 | version: 1.0.5 739 | resolution: "minipass-flush@npm:1.0.5" 740 | dependencies: 741 | minipass: ^3.0.0 742 | checksum: 56269a0b22bad756a08a94b1ffc36b7c9c5de0735a4dd1ab2b06c066d795cfd1f0ac44a0fcae13eece5589b908ecddc867f04c745c7009be0b566421ea0944cf 743 | languageName: node 744 | linkType: hard 745 | 746 | "minipass-pipeline@npm:^1.2.4": 747 | version: 1.2.4 748 | resolution: "minipass-pipeline@npm:1.2.4" 749 | dependencies: 750 | minipass: ^3.0.0 751 | checksum: b14240dac0d29823c3d5911c286069e36d0b81173d7bdf07a7e4a91ecdef92cdff4baaf31ea3746f1c61e0957f652e641223970870e2353593f382112257971b 752 | languageName: node 753 | linkType: hard 754 | 755 | "minipass-sized@npm:^1.0.3": 756 | version: 1.0.3 757 | resolution: "minipass-sized@npm:1.0.3" 758 | dependencies: 759 | minipass: ^3.0.0 760 | checksum: 79076749fcacf21b5d16dd596d32c3b6bf4d6e62abb43868fac21674078505c8b15eaca4e47ed844985a4514854f917d78f588fcd029693709417d8f98b2bd60 761 | languageName: node 762 | linkType: hard 763 | 764 | "minipass@npm:^3.0.0, minipass@npm:^3.1.1, minipass@npm:^3.1.6": 765 | version: 3.3.6 766 | resolution: "minipass@npm:3.3.6" 767 | dependencies: 768 | yallist: ^4.0.0 769 | checksum: a30d083c8054cee83cdcdc97f97e4641a3f58ae743970457b1489ce38ee1167b3aaf7d815cd39ec7a99b9c40397fd4f686e83750e73e652b21cb516f6d845e48 770 | languageName: node 771 | linkType: hard 772 | 773 | "minipass@npm:^4.0.0": 774 | version: 4.0.0 775 | resolution: "minipass@npm:4.0.0" 776 | dependencies: 777 | yallist: ^4.0.0 778 | checksum: 7a609afbf394abfcf9c48e6c90226f471676c8f2a67f07f6838871afb03215ede431d1433feffe1b855455bcb13ef0eb89162841b9796109d6fed8d89790f381 779 | languageName: node 780 | linkType: hard 781 | 782 | "minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": 783 | version: 2.1.2 784 | resolution: "minizlib@npm:2.1.2" 785 | dependencies: 786 | minipass: ^3.0.0 787 | yallist: ^4.0.0 788 | checksum: f1fdeac0b07cf8f30fcf12f4b586795b97be856edea22b5e9072707be51fc95d41487faec3f265b42973a304fe3a64acd91a44a3826a963e37b37bafde0212c3 789 | languageName: node 790 | linkType: hard 791 | 792 | "mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": 793 | version: 1.0.4 794 | resolution: "mkdirp@npm:1.0.4" 795 | bin: 796 | mkdirp: bin/cmd.js 797 | checksum: a96865108c6c3b1b8e1d5e9f11843de1e077e57737602de1b82030815f311be11f96f09cce59bd5b903d0b29834733e5313f9301e3ed6d6f6fba2eae0df4298f 798 | languageName: node 799 | linkType: hard 800 | 801 | "ms@npm:2.1.2": 802 | version: 2.1.2 803 | resolution: "ms@npm:2.1.2" 804 | checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f 805 | languageName: node 806 | linkType: hard 807 | 808 | "ms@npm:^2.0.0": 809 | version: 2.1.3 810 | resolution: "ms@npm:2.1.3" 811 | checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d 812 | languageName: node 813 | linkType: hard 814 | 815 | "negotiator@npm:^0.6.3": 816 | version: 0.6.3 817 | resolution: "negotiator@npm:0.6.3" 818 | checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 819 | languageName: node 820 | linkType: hard 821 | 822 | "node-gyp@npm:latest": 823 | version: 9.3.1 824 | resolution: "node-gyp@npm:9.3.1" 825 | dependencies: 826 | env-paths: ^2.2.0 827 | glob: ^7.1.4 828 | graceful-fs: ^4.2.6 829 | make-fetch-happen: ^10.0.3 830 | nopt: ^6.0.0 831 | npmlog: ^6.0.0 832 | rimraf: ^3.0.2 833 | semver: ^7.3.5 834 | tar: ^6.1.2 835 | which: ^2.0.2 836 | bin: 837 | node-gyp: bin/node-gyp.js 838 | checksum: b860e9976fa645ca0789c69e25387401b4396b93c8375489b5151a6c55cf2640a3b6183c212b38625ef7c508994930b72198338e3d09b9d7ade5acc4aaf51ea7 839 | languageName: node 840 | linkType: hard 841 | 842 | "nopt@npm:^6.0.0": 843 | version: 6.0.0 844 | resolution: "nopt@npm:6.0.0" 845 | dependencies: 846 | abbrev: ^1.0.0 847 | bin: 848 | nopt: bin/nopt.js 849 | checksum: 82149371f8be0c4b9ec2f863cc6509a7fd0fa729929c009f3a58e4eb0c9e4cae9920e8f1f8eb46e7d032fec8fb01bede7f0f41a67eb3553b7b8e14fa53de1dac 850 | languageName: node 851 | linkType: hard 852 | 853 | "npmlog@npm:^6.0.0": 854 | version: 6.0.2 855 | resolution: "npmlog@npm:6.0.2" 856 | dependencies: 857 | are-we-there-yet: ^3.0.0 858 | console-control-strings: ^1.1.0 859 | gauge: ^4.0.3 860 | set-blocking: ^2.0.0 861 | checksum: ae238cd264a1c3f22091cdd9e2b106f684297d3c184f1146984ecbe18aaa86343953f26b9520dedd1b1372bc0316905b736c1932d778dbeb1fcf5a1001390e2a 862 | languageName: node 863 | linkType: hard 864 | 865 | "once@npm:^1.3.0": 866 | version: 1.4.0 867 | resolution: "once@npm:1.4.0" 868 | dependencies: 869 | wrappy: 1 870 | checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 871 | languageName: node 872 | linkType: hard 873 | 874 | "p-map@npm:^4.0.0": 875 | version: 4.0.0 876 | resolution: "p-map@npm:4.0.0" 877 | dependencies: 878 | aggregate-error: ^3.0.0 879 | checksum: cb0ab21ec0f32ddffd31dfc250e3afa61e103ef43d957cc45497afe37513634589316de4eb88abdfd969fe6410c22c0b93ab24328833b8eb1ccc087fc0442a1c 880 | languageName: node 881 | linkType: hard 882 | 883 | "path-is-absolute@npm:^1.0.0": 884 | version: 1.0.1 885 | resolution: "path-is-absolute@npm:1.0.1" 886 | checksum: 060840f92cf8effa293bcc1bea81281bd7d363731d214cbe5c227df207c34cd727430f70c6037b5159c8a870b9157cba65e775446b0ab06fd5ecc7e54615a3b8 887 | languageName: node 888 | linkType: hard 889 | 890 | "promise-inflight@npm:^1.0.1": 891 | version: 1.0.1 892 | resolution: "promise-inflight@npm:1.0.1" 893 | checksum: 22749483091d2c594261517f4f80e05226d4d5ecc1fc917e1886929da56e22b5718b7f2a75f3807e7a7d471bc3be2907fe92e6e8f373ddf5c64bae35b5af3981 894 | languageName: node 895 | linkType: hard 896 | 897 | "promise-retry@npm:^2.0.1": 898 | version: 2.0.1 899 | resolution: "promise-retry@npm:2.0.1" 900 | dependencies: 901 | err-code: ^2.0.2 902 | retry: ^0.12.0 903 | checksum: f96a3f6d90b92b568a26f71e966cbbc0f63ab85ea6ff6c81284dc869b41510e6cdef99b6b65f9030f0db422bf7c96652a3fff9f2e8fb4a0f069d8f4430359429 904 | languageName: node 905 | linkType: hard 906 | 907 | "readable-stream@npm:^3.6.0": 908 | version: 3.6.0 909 | resolution: "readable-stream@npm:3.6.0" 910 | dependencies: 911 | inherits: ^2.0.3 912 | string_decoder: ^1.1.1 913 | util-deprecate: ^1.0.1 914 | checksum: d4ea81502d3799439bb955a3a5d1d808592cf3133350ed352aeaa499647858b27b1c4013984900238b0873ec8d0d8defce72469fb7a83e61d53f5ad61cb80dc8 915 | languageName: node 916 | linkType: hard 917 | 918 | "retry@npm:^0.12.0": 919 | version: 0.12.0 920 | resolution: "retry@npm:0.12.0" 921 | checksum: 623bd7d2e5119467ba66202d733ec3c2e2e26568074923bc0585b6b99db14f357e79bdedb63cab56cec47491c4a0da7e6021a7465ca6dc4f481d3898fdd3158c 922 | languageName: node 923 | linkType: hard 924 | 925 | "rimraf@npm:^3.0.2": 926 | version: 3.0.2 927 | resolution: "rimraf@npm:3.0.2" 928 | dependencies: 929 | glob: ^7.1.3 930 | bin: 931 | rimraf: bin.js 932 | checksum: 87f4164e396f0171b0a3386cc1877a817f572148ee13a7e113b238e48e8a9f2f31d009a92ec38a591ff1567d9662c6b67fd8818a2dbbaed74bc26a87a2a4a9a0 933 | languageName: node 934 | linkType: hard 935 | 936 | "rollup@npm:^3.9.0": 937 | version: 3.9.0 938 | resolution: "rollup@npm:3.9.0" 939 | dependencies: 940 | fsevents: ~2.3.2 941 | dependenciesMeta: 942 | fsevents: 943 | optional: true 944 | bin: 945 | rollup: dist/bin/rollup 946 | checksum: b0ce4baa8db8ee77ab096a4e066b20fb0719efb9cbd84f230838517d35bf159311487112852cfa687126896b58084c8e6cb9ab222f7559c4b6138ca693d63439 947 | languageName: node 948 | linkType: hard 949 | 950 | "rome@npm:^11.0.0": 951 | version: 11.0.0 952 | resolution: "rome@npm:11.0.0" 953 | dependencies: 954 | "@rometools/cli-darwin-arm64": 11.0.0 955 | "@rometools/cli-darwin-x64": 11.0.0 956 | "@rometools/cli-linux-arm64": 11.0.0 957 | "@rometools/cli-linux-x64": 11.0.0 958 | "@rometools/cli-win32-arm64": 11.0.0 959 | "@rometools/cli-win32-x64": 11.0.0 960 | dependenciesMeta: 961 | "@rometools/cli-darwin-arm64": 962 | optional: true 963 | "@rometools/cli-darwin-x64": 964 | optional: true 965 | "@rometools/cli-linux-arm64": 966 | optional: true 967 | "@rometools/cli-linux-x64": 968 | optional: true 969 | "@rometools/cli-win32-arm64": 970 | optional: true 971 | "@rometools/cli-win32-x64": 972 | optional: true 973 | bin: 974 | rome: bin/rome 975 | checksum: 3c92a47c78a66c62f94b6a3a72ead92a20c23326d2d73785ce88c03897b60b8114c285a636acc24bd11039381ded48f8c58c6cc5c4cc46ce7eed092c90d9a054 976 | languageName: node 977 | linkType: hard 978 | 979 | "safe-buffer@npm:~5.2.0": 980 | version: 5.2.1 981 | resolution: "safe-buffer@npm:5.2.1" 982 | checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 983 | languageName: node 984 | linkType: hard 985 | 986 | "safer-buffer@npm:>= 2.1.2 < 3.0.0": 987 | version: 2.1.2 988 | resolution: "safer-buffer@npm:2.1.2" 989 | checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 990 | languageName: node 991 | linkType: hard 992 | 993 | "semver@npm:^7.3.5": 994 | version: 7.3.8 995 | resolution: "semver@npm:7.3.8" 996 | dependencies: 997 | lru-cache: ^6.0.0 998 | bin: 999 | semver: bin/semver.js 1000 | checksum: ba9c7cbbf2b7884696523450a61fee1a09930d888b7a8d7579025ad93d459b2d1949ee5bbfeb188b2be5f4ac163544c5e98491ad6152df34154feebc2cc337c1 1001 | languageName: node 1002 | linkType: hard 1003 | 1004 | "set-blocking@npm:^2.0.0": 1005 | version: 2.0.0 1006 | resolution: "set-blocking@npm:2.0.0" 1007 | checksum: 6e65a05f7cf7ebdf8b7c75b101e18c0b7e3dff4940d480efed8aad3a36a4005140b660fa1d804cb8bce911cac290441dc728084a30504d3516ac2ff7ad607b02 1008 | languageName: node 1009 | linkType: hard 1010 | 1011 | "shiki@npm:^0.11.1": 1012 | version: 0.11.1 1013 | resolution: "shiki@npm:0.11.1" 1014 | dependencies: 1015 | jsonc-parser: ^3.0.0 1016 | vscode-oniguruma: ^1.6.1 1017 | vscode-textmate: ^6.0.0 1018 | checksum: 2a4ebc3b466816263fc244ae4f67a4ff96aa74d863b9c5e7e4affc50f37fd6d1a781405de0dbf763b777bc33e49a0d441de7ff3fededb8b01e3b8dbb37e2927d 1019 | languageName: node 1020 | linkType: hard 1021 | 1022 | "signal-exit@npm:^3.0.7": 1023 | version: 3.0.7 1024 | resolution: "signal-exit@npm:3.0.7" 1025 | checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 1026 | languageName: node 1027 | linkType: hard 1028 | 1029 | "smart-buffer@npm:^4.2.0": 1030 | version: 4.2.0 1031 | resolution: "smart-buffer@npm:4.2.0" 1032 | checksum: b5167a7142c1da704c0e3af85c402002b597081dd9575031a90b4f229ca5678e9a36e8a374f1814c8156a725d17008ae3bde63b92f9cfd132526379e580bec8b 1033 | languageName: node 1034 | linkType: hard 1035 | 1036 | "socks-proxy-agent@npm:^7.0.0": 1037 | version: 7.0.0 1038 | resolution: "socks-proxy-agent@npm:7.0.0" 1039 | dependencies: 1040 | agent-base: ^6.0.2 1041 | debug: ^4.3.3 1042 | socks: ^2.6.2 1043 | checksum: 720554370154cbc979e2e9ce6a6ec6ced205d02757d8f5d93fe95adae454fc187a5cbfc6b022afab850a5ce9b4c7d73e0f98e381879cf45f66317a4895953846 1044 | languageName: node 1045 | linkType: hard 1046 | 1047 | "socks@npm:^2.6.2": 1048 | version: 2.7.1 1049 | resolution: "socks@npm:2.7.1" 1050 | dependencies: 1051 | ip: ^2.0.0 1052 | smart-buffer: ^4.2.0 1053 | checksum: 259d9e3e8e1c9809a7f5c32238c3d4d2a36b39b83851d0f573bfde5f21c4b1288417ce1af06af1452569cd1eb0841169afd4998f0e04ba04656f6b7f0e46d748 1054 | languageName: node 1055 | linkType: hard 1056 | 1057 | "source-map-support@npm:^0.5.21": 1058 | version: 0.5.21 1059 | resolution: "source-map-support@npm:0.5.21" 1060 | dependencies: 1061 | buffer-from: ^1.0.0 1062 | source-map: ^0.6.0 1063 | checksum: 43e98d700d79af1d36f859bdb7318e601dfc918c7ba2e98456118ebc4c4872b327773e5a1df09b0524e9e5063bb18f0934538eace60cca2710d1fa687645d137 1064 | languageName: node 1065 | linkType: hard 1066 | 1067 | "source-map@npm:^0.6.0": 1068 | version: 0.6.1 1069 | resolution: "source-map@npm:0.6.1" 1070 | checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2 1071 | languageName: node 1072 | linkType: hard 1073 | 1074 | "ssri@npm:^9.0.0": 1075 | version: 9.0.1 1076 | resolution: "ssri@npm:9.0.1" 1077 | dependencies: 1078 | minipass: ^3.1.1 1079 | checksum: fb58f5e46b6923ae67b87ad5ef1c5ab6d427a17db0bead84570c2df3cd50b4ceb880ebdba2d60726588272890bae842a744e1ecce5bd2a2a582fccd5068309eb 1080 | languageName: node 1081 | linkType: hard 1082 | 1083 | "string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.2.3": 1084 | version: 4.2.3 1085 | resolution: "string-width@npm:4.2.3" 1086 | dependencies: 1087 | emoji-regex: ^8.0.0 1088 | is-fullwidth-code-point: ^3.0.0 1089 | strip-ansi: ^6.0.1 1090 | checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb 1091 | languageName: node 1092 | linkType: hard 1093 | 1094 | "string_decoder@npm:^1.1.1": 1095 | version: 1.3.0 1096 | resolution: "string_decoder@npm:1.3.0" 1097 | dependencies: 1098 | safe-buffer: ~5.2.0 1099 | checksum: 8417646695a66e73aefc4420eb3b84cc9ffd89572861fe004e6aeb13c7bc00e2f616247505d2dbbef24247c372f70268f594af7126f43548565c68c117bdeb56 1100 | languageName: node 1101 | linkType: hard 1102 | 1103 | "strip-ansi@npm:^6.0.1": 1104 | version: 6.0.1 1105 | resolution: "strip-ansi@npm:6.0.1" 1106 | dependencies: 1107 | ansi-regex: ^5.0.1 1108 | checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c 1109 | languageName: node 1110 | linkType: hard 1111 | 1112 | "tar@npm:^6.1.11, tar@npm:^6.1.2": 1113 | version: 6.1.13 1114 | resolution: "tar@npm:6.1.13" 1115 | dependencies: 1116 | chownr: ^2.0.0 1117 | fs-minipass: ^2.0.0 1118 | minipass: ^4.0.0 1119 | minizlib: ^2.1.1 1120 | mkdirp: ^1.0.3 1121 | yallist: ^4.0.0 1122 | checksum: 8a278bed123aa9f53549b256a36b719e317c8b96fe86a63406f3c62887f78267cea9b22dc6f7007009738509800d4a4dccc444abd71d762287c90f35b002eb1c 1123 | languageName: node 1124 | linkType: hard 1125 | 1126 | "ts-node@npm:^10.9.1": 1127 | version: 10.9.1 1128 | resolution: "ts-node@npm:10.9.1" 1129 | dependencies: 1130 | "@cspotcode/source-map-support": ^0.8.0 1131 | "@tsconfig/node10": ^1.0.7 1132 | "@tsconfig/node12": ^1.0.7 1133 | "@tsconfig/node14": ^1.0.0 1134 | "@tsconfig/node16": ^1.0.2 1135 | acorn: ^8.4.1 1136 | acorn-walk: ^8.1.1 1137 | arg: ^4.1.0 1138 | create-require: ^1.1.0 1139 | diff: ^4.0.1 1140 | make-error: ^1.1.1 1141 | v8-compile-cache-lib: ^3.0.1 1142 | yn: 3.1.1 1143 | peerDependencies: 1144 | "@swc/core": ">=1.2.50" 1145 | "@swc/wasm": ">=1.2.50" 1146 | "@types/node": "*" 1147 | typescript: ">=2.7" 1148 | peerDependenciesMeta: 1149 | "@swc/core": 1150 | optional: true 1151 | "@swc/wasm": 1152 | optional: true 1153 | bin: 1154 | ts-node: dist/bin.js 1155 | ts-node-cwd: dist/bin-cwd.js 1156 | ts-node-esm: dist/bin-esm.js 1157 | ts-node-script: dist/bin-script.js 1158 | ts-node-transpile-only: dist/bin-transpile.js 1159 | ts-script: dist/bin-script-deprecated.js 1160 | checksum: 090adff1302ab20bd3486e6b4799e90f97726ed39e02b39e566f8ab674fd5bd5f727f43615debbfc580d33c6d9d1c6b1b3ce7d8e3cca3e20530a145ffa232c35 1161 | languageName: node 1162 | linkType: hard 1163 | 1164 | "typedoc@npm:^0.23.23": 1165 | version: 0.23.23 1166 | resolution: "typedoc@npm:0.23.23" 1167 | dependencies: 1168 | lunr: ^2.3.9 1169 | marked: ^4.2.4 1170 | minimatch: ^5.1.1 1171 | shiki: ^0.11.1 1172 | peerDependencies: 1173 | typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x 1174 | bin: 1175 | typedoc: bin/typedoc 1176 | checksum: 2b64f9c9dc1992ec1bbcc688f6cfc8161481872c485ba9226d1797f572469d02f7798ebe96e3626587a6952af685fa1f4aaa0d9a6137fe9fb3d37f677cb41161 1177 | languageName: node 1178 | linkType: hard 1179 | 1180 | "typescript@npm:4.9": 1181 | version: 4.9.4 1182 | resolution: "typescript@npm:4.9.4" 1183 | bin: 1184 | tsc: bin/tsc 1185 | tsserver: bin/tsserver 1186 | checksum: e782fb9e0031cb258a80000f6c13530288c6d63f1177ed43f770533fdc15740d271554cdae86701c1dd2c83b082cea808b07e97fd68b38a172a83dbf9e0d0ef9 1187 | languageName: node 1188 | linkType: hard 1189 | 1190 | "typescript@patch:typescript@4.9#~builtin": 1191 | version: 4.9.4 1192 | resolution: "typescript@patch:typescript@npm%3A4.9.4#~builtin::version=4.9.4&hash=ad5954" 1193 | bin: 1194 | tsc: bin/tsc 1195 | tsserver: bin/tsserver 1196 | checksum: 1caaea6cb7f813e64345190fddc4e6c924d0b698ab81189b503763c4a18f7f5501c69362979d36e19c042d89d936443e768a78b0675690b35eb663d19e0eae71 1197 | languageName: node 1198 | linkType: hard 1199 | 1200 | "unique-filename@npm:^2.0.0": 1201 | version: 2.0.1 1202 | resolution: "unique-filename@npm:2.0.1" 1203 | dependencies: 1204 | unique-slug: ^3.0.0 1205 | checksum: 807acf3381aff319086b64dc7125a9a37c09c44af7620bd4f7f3247fcd5565660ac12d8b80534dcbfd067e6fe88a67e621386dd796a8af828d1337a8420a255f 1206 | languageName: node 1207 | linkType: hard 1208 | 1209 | "unique-slug@npm:^3.0.0": 1210 | version: 3.0.0 1211 | resolution: "unique-slug@npm:3.0.0" 1212 | dependencies: 1213 | imurmurhash: ^0.1.4 1214 | checksum: 49f8d915ba7f0101801b922062ee46b7953256c93ceca74303bd8e6413ae10aa7e8216556b54dc5382895e8221d04f1efaf75f945c2e4a515b4139f77aa6640c 1215 | languageName: node 1216 | linkType: hard 1217 | 1218 | "util-deprecate@npm:^1.0.1": 1219 | version: 1.0.2 1220 | resolution: "util-deprecate@npm:1.0.2" 1221 | checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 1222 | languageName: node 1223 | linkType: hard 1224 | 1225 | "v8-compile-cache-lib@npm:^3.0.1": 1226 | version: 3.0.1 1227 | resolution: "v8-compile-cache-lib@npm:3.0.1" 1228 | checksum: 78089ad549e21bcdbfca10c08850022b22024cdcc2da9b168bcf5a73a6ed7bf01a9cebb9eac28e03cd23a684d81e0502797e88f3ccd27a32aeab1cfc44c39da0 1229 | languageName: node 1230 | linkType: hard 1231 | 1232 | "vscode-oniguruma@npm:^1.6.1": 1233 | version: 1.6.2 1234 | resolution: "vscode-oniguruma@npm:1.6.2" 1235 | checksum: 6b754acdafd5b68242ea5938bb00a32effc16c77f471d4f0f337d879d0e8e592622998e2441f42d9a7ff799c1593f31c11f26ca8d9bf9917e3ca881d3c1f3e19 1236 | languageName: node 1237 | linkType: hard 1238 | 1239 | "vscode-textmate@npm:^6.0.0": 1240 | version: 6.0.0 1241 | resolution: "vscode-textmate@npm:6.0.0" 1242 | checksum: ff6f17a406c2906586afc14ef01cb122e33acd35312e815abb5c924347a777c6783ce3fe7db8b83f1760ebf843c669843b9390f905b69c433b3395af28e4b483 1243 | languageName: node 1244 | linkType: hard 1245 | 1246 | "which@npm:^2.0.2": 1247 | version: 2.0.2 1248 | resolution: "which@npm:2.0.2" 1249 | dependencies: 1250 | isexe: ^2.0.0 1251 | bin: 1252 | node-which: ./bin/node-which 1253 | checksum: 1a5c563d3c1b52d5f893c8b61afe11abc3bab4afac492e8da5bde69d550de701cf9806235f20a47b5c8fa8a1d6a9135841de2596535e998027a54589000e66d1 1254 | languageName: node 1255 | linkType: hard 1256 | 1257 | "wide-align@npm:^1.1.5": 1258 | version: 1.1.5 1259 | resolution: "wide-align@npm:1.1.5" 1260 | dependencies: 1261 | string-width: ^1.0.2 || 2 || 3 || 4 1262 | checksum: d5fc37cd561f9daee3c80e03b92ed3e84d80dde3365a8767263d03dacfc8fa06b065ffe1df00d8c2a09f731482fcacae745abfbb478d4af36d0a891fad4834d3 1263 | languageName: node 1264 | linkType: hard 1265 | 1266 | "wrappy@npm:1": 1267 | version: 1.0.2 1268 | resolution: "wrappy@npm:1.0.2" 1269 | checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 1270 | languageName: node 1271 | linkType: hard 1272 | 1273 | "yallist@npm:^4.0.0": 1274 | version: 4.0.0 1275 | resolution: "yallist@npm:4.0.0" 1276 | checksum: 343617202af32df2a15a3be36a5a8c0c8545208f3d3dfbc6bb7c3e3b7e8c6f8e7485432e4f3b88da3031a6e20afa7c711eded32ddfb122896ac5d914e75848d5 1277 | languageName: node 1278 | linkType: hard 1279 | 1280 | "yn@npm:3.1.1": 1281 | version: 3.1.1 1282 | resolution: "yn@npm:3.1.1" 1283 | checksum: 2c487b0e149e746ef48cda9f8bad10fc83693cd69d7f9dcd8be4214e985de33a29c9e24f3c0d6bcf2288427040a8947406ab27f7af67ee9456e6b84854f02dd6 1284 | languageName: node 1285 | linkType: hard 1286 | --------------------------------------------------------------------------------