df-script 1.8.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +153 -203
  2. package/dist/api.d.ts +41 -36
  3. package/dist/columnExpressions/ColumnExpr.d.ts +5 -8
  4. package/dist/columnExpressions/ExprBase.d.ts +7 -0
  5. package/dist/columnExpressions/constants.d.ts +1 -0
  6. package/dist/columnExpressions/functions/all.d.ts +13 -13
  7. package/dist/columnExpressions/functions/coalesce.d.ts +2 -2
  8. package/dist/columnExpressions/functions/duration.d.ts +16 -21
  9. package/dist/columnExpressions/functions/element.d.ts +10 -10
  10. package/dist/columnExpressions/functions/exclude.d.ts +14 -14
  11. package/dist/columnExpressions/functions/implode.d.ts +7 -7
  12. package/dist/columnExpressions/functions/lit.d.ts +9 -9
  13. package/dist/columnExpressions/functions/seqRange.d.ts +69 -0
  14. package/dist/columnExpressions/functions/struct.d.ts +6 -6
  15. package/dist/columnExpressions/functions/when.d.ts +31 -32
  16. package/dist/columnExpressions/index.d.ts +4 -7
  17. package/dist/columnExpressions/mixins/AggregationExpr.d.ts +672 -141
  18. package/dist/columnExpressions/mixins/ArithmeticExpr.d.ts +701 -327
  19. package/dist/columnExpressions/mixins/ArrayExpr.d.ts +543 -231
  20. package/dist/columnExpressions/mixins/ComparisonExpr.d.ts +398 -201
  21. package/dist/columnExpressions/mixins/LogicalExpr.d.ts +59 -29
  22. package/dist/columnExpressions/mixins/ManipulationExpr.d.ts +23 -9
  23. package/dist/columnExpressions/mixins/StandardExpr.d.ts +3234 -0
  24. package/dist/columnExpressions/mixins/StringExpr.d.ts +1299 -396
  25. package/dist/columnExpressions/mixins/StructExpr.d.ts +72 -30
  26. package/dist/columnExpressions/mixins/TemporalExpr.d.ts +518 -212
  27. package/dist/columnExpressions/mixins/WindowExpr.d.ts +270 -102
  28. package/dist/columnExpressions/typeInference.d.ts +13 -0
  29. package/dist/columnExpressions/types.d.ts +6 -1
  30. package/dist/columnExpressions/utils.d.ts +16 -0
  31. package/dist/constants.d.ts +38 -0
  32. package/dist/dataframe/dataframe.d.ts +755 -608
  33. package/dist/dataframe/grouped/grouped.d.ts +24 -6
  34. package/dist/dataframe/grouped.d.ts +70 -0
  35. package/dist/dataframe/index.d.ts +1 -1
  36. package/dist/dataframe/lazy.d.ts +37 -0
  37. package/dist/dataframe/types.d.ts +46 -22
  38. package/dist/dataframe/utils.d.ts +10 -4
  39. package/dist/datatypes/index.d.ts +11 -4
  40. package/dist/expressions.js +1 -0
  41. package/dist/expressions.mjs +1 -0
  42. package/dist/functions/concat.d.ts +68 -16
  43. package/dist/functions/index.d.ts +2 -2
  44. package/dist/functions/readCsv.d.ts +35 -0
  45. package/dist/functions/readJson.d.ts +33 -0
  46. package/dist/index.js +5 -6
  47. package/dist/index.mjs +5 -6
  48. package/dist/types.d.ts +148 -7
  49. package/dist/utils/array.d.ts +54 -18
  50. package/dist/utils/binary.d.ts +6 -2
  51. package/dist/utils/csv.d.ts +4 -1
  52. package/dist/utils/date.d.ts +3 -19
  53. package/dist/utils/duration.d.ts +7 -5
  54. package/dist/utils/json.d.ts +56 -2
  55. package/dist/utils/number.d.ts +5 -2
  56. package/dist/utils/object.d.ts +7 -12
  57. package/dist/utils/string.d.ts +83 -2
  58. package/dist/utils/table.d.ts +76 -0
  59. package/dist/utils.js +4 -0
  60. package/dist/utils.mjs +4 -0
  61. package/package.json +29 -8
  62. package/dist/assets/index-DBhGK6Tp.css +0 -1
  63. package/dist/assets/index-DEJEV_tU.js +0 -195
  64. package/dist/index.html +0 -17
package/README.md CHANGED
@@ -1,38 +1,57 @@
1
- # 🚀 DFScript
2
-
3
- [![GitHub Repository](https://img.shields.io/badge/GitHub-Repository-blue?style=for-the-badge&logo=github)](https://github.com/trentamorris/df-script)
1
+ # 🚀 df-script: High-Performance TypeScript DataFrame Library
2
+
3
+ [![GitHub Repository](https://img.shields.io/badge/GitHub-Repository-181717?style=for-the-badge&logo=github)](https://github.com/trentamorris/df-script)
4
+ [![npm version](https://img.shields.io/npm/v/df-script?style=for-the-badge&logo=npm&color=CB3837)](https://www.npmjs.com/package/df-script)
5
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/df-script?style=for-the-badge&color=blue)](https://bundlephobia.com/package/df-script)
6
+ [![Zero Dependencies](https://img.shields.io/badge/Dependencies-0-success?style=for-the-badge)](#)
7
+ [![TypeScript & JavaScript](https://img.shields.io/badge/Supports-TS%20%7C%20TSX%20%7C%20JS%20%7C%20JSX-blue?style=for-the-badge&logo=typescript)](https://www.typescriptlang.org/)
8
+ [![Universal Runtimes](https://img.shields.io/badge/Runtimes-Node%20%7C%20Bun%20%7C%20Deno%20%7C%20Browser-brightgreen?style=for-the-badge)](#)
9
+ [![License](https://img.shields.io/npm/l/df-script?style=for-the-badge&color=informational)](LICENSE)
4
10
  [![Donate](https://img.shields.io/badge/Donate-Support-green?style=for-the-badge)](DONATIONS.md)
5
- [![Environment](https://img.shields.io/badge/Environment-Node.js%20%7C%20Browser%20%7C%20Bun%20%7C%20Deno%20%7C%20Workers-brightgreen?style=for-the-badge)](#)
6
- [![Zero Dependencies](https://img.shields.io/badge/Dependencies-Zero-success?style=for-the-badge)](#)
11
+ **df-script** is a blazing-fast, **zero-dependency**, expression-based DataFrame and data manipulation library for **TypeScript** and **JavaScript**. Heavily inspired by modern columnar engines like **Polars** and **Pandas**, `df-script` brings declarative, high-performance columnar analytical queries and ETL workflows directly to JavaScript environments (Node.js, Browser, Bun, Deno, and Edge Workers).
12
+
13
+ With cache-optimized columnar storage and flat memory layout under the hood, `df-script` eliminates garbage collection thrashing caused by intermediate array allocations in chained `.map()`, `.filter()`, and `.reduce()` calls.
14
+
15
+ ---
16
+
17
+ ## 🌐 Universal Language & Environment Support
7
18
 
8
- DFScript is a lightweight, high-performance, and **zero-dependency** data analysis library for TypeScript and JavaScript. Heavily inspired by modern dataframe libraries like **Polars** and **Pandas**, DFScript brings a robust, expression-based columnar data processing engine directly to the JavaScript ecosystem.
19
+ `df-script` is built with **zero native dependencies** and ships with dual **ESM** (`dist/index.mjs`) and **CommonJS** (`dist/index.js`) modules alongside comprehensive `.d.ts` type declarations. It runs natively everywhere JavaScript or TypeScript runs:
9
20
 
10
- With optimized columnar storage under the hood, DFScript enables you to build clean, maintainable, and type-safe data pipelines using a declarative expression API.
21
+ - 📄 **Languages & File Formats**: Full first-class support in **TypeScript (`.ts`, `.tsx`)**, **JavaScript (`.js`, `.jsx`)**, and module formats (`.mjs`, `.cjs`).
22
+ - ⚛️ **UI Frameworks & Bundlers**: React (JSX/TSX), Next.js, Vue, Nuxt, Svelte, SolidJS, Astro, Vite, Webpack, and esbuild.
23
+ - ⚙️ **Runtimes & Target Standard**: Standard **ES2020+** compatible. Fully tested on **Node.js** (14+), **Bun**, **Deno**, modern **Web Browsers** (Chrome 80+, Safari 13.1+, Firefox 74+, Edge 80+), Cloudflare Workers, Fastly Compute, and AWS Lambda.
24
+ - 🌐 **Browser / Client-Side Compatibility**: 100% in-memory analytical transformations, joins, grouping, and expressions run natively in all browser runtimes. File writing methods (`df.writeCsv()`, `df.writeJson()`) automatically fallback to returning strings or writing to custom stream objects when running in browser environments.
25
+ - 📦 **Package Managers**: Works seamlessly with `npm`, `pnpm`, `bun`, and `yarn`.
11
26
 
12
- ## 💡 Why DFScript?
27
+ ---
13
28
 
14
- Like many developers, I spent years working on frontend codebases filled with deeply nested, unoptimized data processing loops. We've all seen them: chained `.map()`, `.filter()`, `.sort()`, and `.forEach()` loops processing arrays of objects. Each step in the chain allocates new intermediate arrays, triggers garbage collection thrashing, and operates on row-based layouts that slow down browser main threads.
29
+ ## 💡 Why df-script? (Polars & Pandas for TypeScript)
15
30
 
16
- When you need to perform complex analytical transformations on the client-side—handling missing values, formatting timezone-aware datetimes, parsing decimals, or computing rolling averages—relying on standard JavaScript array methods quickly becomes a performance and maintenance nightmare. There had to be a better, cleaner, and faster way to express these pipelines. I realized that if nobody else had built a lightweight, zero-dependency columnar expression engine for the JavaScript ecosystem yet, why not roll up my sleeves and build it myself?
31
+ In modern web apps and Node.js backend services, data transformation code often degrades into nested chains of `.map()`, `.filter()`, and `.sort()` on arrays of objects. Each step in the chain allocates new intermediate arrays, slows down garbage collection, and creates maintenance overhead.
17
32
 
18
- DFScript was born from that frustration. It brings Polars-like columnar execution, strict domain namespaces (`.str`, `.dt`, `.arr`, `.struct`), and lazy/declarative expression compilation to JavaScript. Under the hood, it avoids intermediate array allocations and uses highly optimized loops with cached lengths, so your frontend code stays clean, type-safe, and incredibly fast.
33
+ `df-script` provides:
34
+ - ⚡ **Columnar Execution**: Column-oriented arrays with cached loop lengths for fast computation and minimal memory allocation.
35
+ - 🔗 **Fluent Expressions**: Declarative, composable queries using `$df.col(...)` expressions with automatic post-operation schema deduction.
36
+ - 📂 **Strict Domain Namespaces**: Clean, dedicated namespaces (`.str`, `.dt`, `.arr`, `.struct`) to prevent method clutter and ensure discoverable APIs.
37
+ - 🛡️ **Zero External Dependencies**: Lightweight runtime footprint with zero supply-chain risk.
38
+ - 🧠 **TypeScript First**: Full IDE autocomplete and compile-time type safety for column selections and schemas.
19
39
 
20
40
  ---
21
41
 
22
42
  ## 🗺️ Table of Contents
23
43
 
24
44
  - [✨ Key Features](#-key-features)
25
- - [⚙️ Compatibility & Design Principles](#-compatibility--design-principles)
26
- - [🤝 Contributing & Collective Wisdom](#-contributing--collective-wisdom)
45
+ - [🌐 Universal Language & Environment Support](#-universal-language--environment-support)
27
46
  - [📦 Installation](#-installation)
28
47
  - [🚀 Quick Start](#-quick-start)
29
48
  - [📖 Core Concepts](#-core-concepts)
30
- - [🛠️ DataFrame API Reference](#-dataframe-api-reference)
49
+ - [🛠️ DataFrame API Reference](#️-dataframe-api-reference)
31
50
  - [📂 File / Data I/O](#-file--data-io)
32
51
  - [🧮 Expressions API Reference](#-expressions-api-reference)
33
52
  - [📂 Namespaces](#-namespaces)
34
53
  - [🪟 Window & Rolling Expressions](#-window--rolling-expressions)
35
- - [🛡️ Typing and Schema Registry](#-typing-and-schema-registry)
54
+ - [🛡️ Typing and Schema Registry](#️-typing-and-schema-registry)
36
55
  - [🧑‍💻 Contributing & Development](#-contributing--development)
37
56
  - [📄 License](#-license)
38
57
 
@@ -40,88 +59,67 @@ DFScript was born from that frustration. It brings Polars-like columnar executio
40
59
 
41
60
  ## ✨ Key Features
42
61
 
43
- - 📦 **Zero Dependencies** — Extremely lightweight with zero runtime overhead.
44
- - ⚡ **Columnar Execution** — Operates on efficient columnar arrays, minimizing allocations and speed bottlenecks.
45
- - 🔗 **Expression-Based API** — Compose complex calculations, mappings, and filters using fluent, Polars-like expressions.
46
- - 📂 **Strict Namespaces** — Clear API organization for specific domains:
47
- - `.str` for advanced string manipulations.
48
- - `.dt` for microsecond-precision datetimes, timezones, and duration calculations.
49
- - `.arr` for robust array/list column operations.
50
- - `.struct` for nested object and struct manipulation.
51
- - 🪟 **Analytical Window Functions** — Windowing (`over()`), cumulative aggregations (`cum_sum()`, `cum_max()`), and rolling metrics (`rolling_mean()`, `rolling_std()`).
52
- - 🛠️ **Relational Operations** — Rich, high-speed joins, pivots, unpivots, vertical/horizontal concatenations, and group-by aggregations.
53
- - 🛡️ **Defensive & Type-Safe** — Native type-coercion, robust null-safety, and strict schema validation.
54
-
55
- ---
56
-
57
- ## ⚙️ Compatibility & Design Principles
58
-
59
- DFScript is designed with a **low-abstraction, zero-dependency** philosophy to guarantee maximum compatibility, predictability, and runtime performance:
60
-
61
- - 📦 **Zero External Dependencies** — Lightweight footprint with zero runtime overhead or supply chain vulnerabilities.
62
- - 🌐 **Universal Compatibility** — Works out-of-the-box in any JavaScript/TypeScript environment, including Node.js, Deno, Bun, web browsers, and cloud/edge workers.
63
- - 🧱 **Built-in Standards** — Prioritizes native, built-in APIs (like standard `Date`, `Intl` formatting, and `TextEncoder`) and standard arrays rather than custom wrappers or heavy runtime abstractions.
64
- - ⚡ **Optimized Execution Paths** — Under the hood, performance-critical code avoids higher-level array iterators and short-lived intermediate allocations in favor of simple, fast `for` and `while` loops with cached lengths, keeping garbage collection overhead to an absolute minimum.
65
- - 🔄 **Easy Transpilation** — Relies strictly on low-level native operations, making it fully compatible with older environments (like ES6 or even ES5) without requiring complex polyfills or modern engine-specific features.
66
-
67
- ---
68
-
69
- ## 🤝 Contributing & Collective Wisdom
70
-
71
- We don’t pretend to have encountered every localized date format, database quirk, or environment-specific edge case. DFScript is built on the belief that software correctness is a collective endeavor.
72
-
73
- If you run into an unsupported edge case or unexpected behavior in any of our functions, we want to hear about it. Help us harden this engine by opening a GitHub Issue or submitting a PR—every report makes the library more robust for everyone.
62
+ - 📦 **Zero Dependencies** — 0 external runtime dependencies; completely standalone.
63
+ - ⚡ **Columnar Execution** — Fast columnar processing that eliminates intermediate array allocations.
64
+ - 🔗 **Expression-Based API** — Compose complex transformations, aggregations, and conditions using fluent `$df` expressions.
65
+ - 📂 **Strict Namespaces**:
66
+ - `.str` Unicode string manipulations, regex extractions, and JSON path lookups.
67
+ - `.dt` Timezone conversions, business days, microsecond-precision datetimes, and durations.
68
+ - `.arr` Array/list column operations and element-wise `.arr.eval()` mapping.
69
+ - `.struct` Nested object handling and `.struct.unnest()` column flattening.
70
+ - 🪟 **Analytical Window Functions** — Partitioned windowing (`.over()`), cumulative aggregations (`cumSum()`, `cumMax()`), and rolling moving statistics (`rollingMean()`, `rollingStd()`).
71
+ - 🛠️ **Relational Operations** — Inner/left/right/outer/cross joins, `joinAsof` time-series matching, pivots, unpivots, and multi-axis concatenations.
72
+ - 🛡️ **Defensive & Type-Safe** — Automatic type coercion, Kleene three-valued logic for null safety, and strict schema validation.
74
73
 
75
74
  ---
76
75
 
77
76
  ## 📦 Installation
78
77
 
79
- Install DFScript using your favorite package manager:
78
+ Install `df-script` using your package manager:
80
79
 
81
80
  ```bash
82
81
  npm install df-script
83
82
  ```
84
83
 
85
- Or with Yarn/PNPM:
84
+ Or with Yarn, PNPM, or Bun:
86
85
 
87
86
  ```bash
88
87
  yarn add df-script
89
88
  pnpm add df-script
89
+ bun add df-script
90
90
  ```
91
91
 
92
92
  ---
93
93
 
94
94
  ## 🚀 Quick Start
95
95
 
96
- Here is a quick example showing how to load data, run expressions, perform aggregations, and compute rolling statistics.
97
-
98
96
  ```typescript
99
97
  import { $df } from "df-script";
100
98
 
101
99
  // 1. Create a DataFrame with structured data and automatic schema inference
102
100
  const df = $df.data([
103
- { id: 1, name: "Alice", join_date: "2026-01-15", sales: 1200.50, tags: ["sales", "east"] },
104
- { id: 2, name: "Bob", join_date: "2026-02-20", sales: 850.00, tags: ["support", "west"] },
105
- { id: 3, name: "Charlie", join_date: "2026-03-05", sales: 2300.00, tags: ["sales", "north"] },
106
- { id: 4, name: "David", join_date: "2026-03-12", sales: null, tags: ["marketing"] },
101
+ { id: 1, name: "Alice", joinDate: "2026-01-15", sales: 1200.50, tags: ["sales", "east"] },
102
+ { id: 2, name: "Bob", joinDate: "2026-02-20", sales: 850.00, tags: ["support", "west"] },
103
+ { id: 3, name: "Charlie", joinDate: "2026-03-05", sales: 2300.00, tags: ["sales", "north"] },
104
+ { id: 4, name: "David", joinDate: "2026-03-12", sales: null, tags: ["marketing"] },
107
105
  ]);
108
106
 
109
- // 2. Select columns, transform strings, format dates, and fill missing values
107
+ // 2. Select columns, transform strings, format dates, and compute expressions
110
108
  const processedDf = df.select(
111
109
  $df.col("id"),
112
110
  $df.col("name").str.upper().alias("NAME_UPPER"),
113
- $df.col("join_date").str.to_datetime().dt.year().alias("join_year"),
114
- $df.col("sales").add(500).alias("sales_adjusted"),
115
- $df.col("tags").arr.lengths().alias("tag_count")
111
+ $df.col("joinDate").str.toDatetime().dt.year().alias("joinYear"),
112
+ $df.col("sales").add(500).alias("salesAdjusted"),
113
+ $df.col("tags").arr.lengths().alias("tagCount")
116
114
  );
117
115
 
118
- console.log(processedDf.to_dicts());
116
+ console.log(processedDf.toDicts());
119
117
  /* Output:
120
118
  [
121
- { id: 1, NAME_UPPER: 'ALICE', join_year: 2026, sales_adjusted: 1700.5, tag_count: 2 },
122
- { id: 2, NAME_UPPER: 'BOB', join_year: 2026, sales_adjusted: 1350, tag_count: 2 },
123
- { id: 3, NAME_UPPER: 'CHARLIE', join_year: 2026, sales_adjusted: 2800, tag_count: 2 },
124
- { id: 4, NAME_UPPER: 'DAVID', join_year: 2026, sales_adjusted: null, tag_count: 1 }
119
+ { id: 1, NAME_UPPER: 'ALICE', joinYear: 2026, salesAdjusted: 1700.5, tagCount: 2 },
120
+ { id: 2, NAME_UPPER: 'BOB', joinYear: 2026, salesAdjusted: 1350, tagCount: 2 },
121
+ { id: 3, NAME_UPPER: 'CHARLIE', joinYear: 2026, salesAdjusted: 2800, tagCount: 2 },
122
+ { id: 4, NAME_UPPER: 'DAVID', joinYear: 2026, salesAdjusted: null, tagCount: 1 }
125
123
  ]
126
124
  */
127
125
  ```
@@ -132,81 +130,88 @@ console.log(processedDf.to_dicts());
132
130
 
133
131
  ### The `$df` Entry Point
134
132
 
135
- DFScript uses the `$df` namespace to bootstrap DataFrames, refer to columns, build expressions, and access data types.
133
+ `df-script` uses the `$df` namespace to instantiate DataFrames, reference columns, construct expressions, and specify data types.
136
134
 
137
135
  - `$df.data(dataRowsOrCols, schema?)`: Instantiates a new `DataFrame`.
138
- - `$df.read_json(content, options?)`: Reads JSON/NDJSON content into a new `DataFrame`.
139
- - `$df.read_csv(content, options?)`: Reads CSV content into a new `DataFrame`.
140
- - `$df.col(name)`: Creates a column reference expression.
136
+ - `$df.readJson(content, options?)`: Reads JSON/NDJSON content into a new `DataFrame`.
137
+ - `$df.readCsv(content, options?)`: Reads CSV content into a new `DataFrame` with automatic schema inference.
138
+ - `$df.col(selector)`: Creates a column reference expression by column name (`"a"`), multiple names (`["a", "b"]`), RegExp pattern (`/^user_/`), or DataType selector (`$df.Float64`, `$df.Numeric`).
141
139
  - `$df.all()`: Selects all columns in the DataFrame.
142
- - `$df.exclude(columns)`: Creates an expression matching all columns except the specified ones.
143
- - `$df.coalesce(...exprs)`: Returns the first non-null value among columns or literal expressions.
140
+ - `$df.exclude(columns)`: Matches all columns except the specified ones.
141
+ - `$df.coalesce(...exprs)`: Returns the first non-null value among columns or expressions.
144
142
  - `$df.lit(val)`: Explicitly wraps a raw value into a literal expression.
145
- - `$df.when(predicate).then(value)...otherwise(value)`: Constructs a conditional expression (when-then-otherwise chain).
146
- - `$df.implode(column)`: Aggregates a column's rows (or grouped values) into a list.
147
- - `$df.seq_range(value, options?)`: Generates a sequence range of values.
143
+ - `$df.duration(optionsOrString)`: Constructs a `Duration` expression from component options (`{ days: 1, hours: 12 }`) or compound duration strings (`"1d 12h 30m"`).
144
+ - `$df.struct(fields)`: Constructs a nested struct object expression from named expressions or sibling columns.
145
+ - `$df.when(predicate).then(value)...otherwise(value)`: Constructs a conditional `CASE WHEN` expression chain.
146
+ - `$df.implode(column)`: Aggregates a column's rows or grouped values into a list.
147
+ - `$df.seqRange(value, options?)`: Generates a sequence range of values.
148
148
  - `$df.element()`: References the current array element within an `.arr.eval(...)` expression.
149
- - `$df.DataType`: Direct access to the `DataTypeRegistry` for schema specification.
150
-
151
- ### DataFrames vs. Columns
152
-
153
- - **`DataFrame`** holds data in a columnar-oriented object: `columns: Record<string, any[]>`.
154
- - **`ColumnExpr`** represents an evaluation sequence over rows. Operations (arithmetic, strings, lists, date-time, comparisons) are chained to build a tree of computations evaluated lazily.
149
+ - `$df.Float64`, `$df.Int32`, `$df.Utf8`, etc.: Direct access to data types and constructors for schema definitions and type-based column selection.
155
150
 
156
151
  ---
157
152
 
158
153
  ## 🛠️ DataFrame API Reference
159
154
 
160
155
  ### 1. Transformations & Projection
161
- - **`select(...exprs)`**: Projects columns. Supports strings, raw column names, `$df.col(...)` expressions, and `$df.all()`.
162
- - **`with_columns(...exprs)`**: Adds or overrides columns. Accepts expressions, strings, or options objects mapping keys to values/expressions.
156
+ - **`select(...exprs)`**: Projects columns. Supports strings, `$df.col(...)` expressions, `$df.all()`, RegExp patterns (`/^prefix_/`), DataType selectors (`$df.Numeric`), and `$df.col("struct").struct.unnest()`.
157
+ - **`withColumns(...exprs)`**: Adds or overrides columns. Accepts expressions, options mapping keys, RegExp patterns, or DataType selectors.
163
158
  - **`drop(...names)`**: Drops one or more columns from the DataFrame.
164
159
  - **`rename(mapping)`**: Renames columns using a `{ oldName: newName }` object.
160
+ - **`explode(columns)`**: Unnests list-like columns into multiple rows, replicating other columns per list element.
161
+ - **`implode(columns)`**: Groups values in specified columns back into a list element per column.
165
162
 
166
163
  ### 2. Filtering & Row Selection
167
- - **`filter(...predicates)`**: Filters rows where all predicate expressions evaluate to `true` (or non-null truthy values).
168
- - **`unique(columns?)`**: Returns unique rows. If a subset of columns is provided, deduplicates based on those columns.
164
+ - **`filter(...predicates)`**: Filters rows where all predicate expressions evaluate to `true`.
165
+ - **`find(predicate)`**: Returns the first matching row record object (or `undefined`).
166
+ - **`unique(columns?)`**: Returns unique rows, optionally deduplicating based on a subset of columns.
169
167
  - **`limit(n, options?)`**: Returns the first `n` rows. Options include `offset` and direction `from: "start" | "end"`.
170
168
  - **`head(n)`** / **`tail(n)`**: Shortcuts for `limit` from the start or end of the DataFrame.
171
- - **`slice(start, end?)`**: Extract a subset of rows using standard index slicing.
172
- - **`gather(indices, options?)`**: Gathers rows at specified indices. Supports single index, arrays of indices, and negative indexing. Options include `{ null_on_oob?: boolean }` (default: `false` which throws an error on out-of-bounds indices; if `true`, out-of-bounds indices result in `null` values).
169
+ - **`slice(start, end?)`**: Extracts a subset of rows using standard index slicing.
170
+ - **`gather(indices, options?)`**: Gathers rows at specified indices (supports negative indexing and `{ nullOnOob?: boolean }`).
173
171
 
174
- ### 3. Sorting
175
- - **`sort({ by, descending?, nullsLast?, custom? })`**: Sorts rows. Supports single or multiple columns/expressions, custom descending configurations per column, custom null sorting rules, and custom comparator functions.
172
+ ### 3. Sorting & Structural Operations
173
+ - **`sort({ by, descending?, nullsLast?, custom? })`**: Sorts rows by single/multiple columns, custom null ordering, or comparator functions.
174
+ - **`clone()`**: Performs a deep copy of the `DataFrame`, replicating all underlying column arrays and schema metadata.
175
+ - **`transpose(options?)`**: Transposes the DataFrame (swapping rows and columns).
176
176
 
177
177
  ### 4. Grouping & Aggregations
178
- - **`groupby(keys)`**: Groups the data by one or more columns, returning a `GroupedData` object.
179
- - **`GroupedData.agg(...exprs)`**: Run aggregations on grouped data (e.g. `$df.col("sales").sum()`).
178
+ - **`groupBy(keys)`**: Groups data by one or more columns, returning a `GroupedData` object.
179
+ - **`groupByDynamic(indexColumn, options)`**: Dynamic time-series / numeric window grouping over tumbling, sliding, or rolling temporal aggregation intervals (`every`, `period`, `offset`, `closed`, `label`, `startBy`, `includeBoundaries`, `by`).
180
+ - **`GroupedData.agg(...exprs)`**: Computes aggregations on grouped data (e.g. `$df.col("sales").sum()`).
180
181
 
181
182
  ### 5. Reshaping & Joining
182
- - **`join(other, on, how, suffixes?)`**: Merges two DataFrames on join keys. Supported join types: `"inner" | "left" | "right" | "outer"`.
183
+ - **`join(other, onOrOptions, how?, suffixes?)`**: Merges two DataFrames. Supports:
184
+ - Join modes (`how`): `"inner" | "left" | "right" | "outer" | "semi" | "anti" | "cross"`.
185
+ - Keys: `leftOn`, `rightOn`, `coalesce`, and order preservation options.
186
+ - **`joinAsof(other, options)`**: Inexact time-series / nearest-neighbor joins on sorted key columns.
187
+ - Parameters: `on`, `leftOn`, `rightOn`, `by`, `strategy` (`"backward" | "forward" | "nearest"`), and `tolerance`.
183
188
  - **`pivot(index, columns, values)`**: Pivots the table, converting unique values in `columns` into column headers.
184
- - **`unpivot(idVars, valueVars, varName?, valueName?)`**: Melts/unpivots the table, converting wide columns into long format name-value pairs.
185
- - **`concat(items, options?)`**: Concatenates multiple DataFrames. Supported concat strategies: `"vertical" | "horizontal" | "diagonal"`.
189
+ - **`unpivot(idVars, valueVars, varName?, valueName?)`**: Melts/unpivots wide columns into long format name-value pairs.
190
+ - **`concat(items, options?)`**: Concatenates multiple DataFrames (`"vertical" | "horizontal" | "diagonal"`).
186
191
 
187
192
  ---
188
193
 
189
194
  ## 📂 File / Data I/O
190
195
 
191
- DFScript provides helpers to serialize and parse data formats like JSON and CSV.
196
+ `df-script` provides built-in parsers and serializers for JSON and CSV formats.
192
197
 
193
198
  ### Reading Data
194
- - **`$df.read_json(content, options?)`**: Reads a JSON array or Newline Delimited JSON (NDJSON) string and loads it into a new DataFrame.
199
+ - **`$df.readJson(content, options?)`**: Reads standard JSON or Newline Delimited JSON (NDJSON) string.
195
200
  ```typescript
196
201
  import { $df } from "df-script";
197
202
 
198
- // Read standard JSON array
199
- const df = $df.read_json('[{"id": 1, "name": "Alice"}]');
203
+ // Read standard JSON
204
+ const df = $df.readJson('[{"id": 1, "name": "Alice"}]');
200
205
 
201
- // Read Newline Delimited JSON (NDJSON)
202
- const dfNdjson = $df.read_json('{"id": 1}\n{"id": 2}', { format: "ndjson" });
206
+ // Read NDJSON
207
+ const dfNdjson = $df.readJson('{"id": 1}\n{"id": 2}', { format: "ndjson" });
203
208
  ```
204
- - **`$df.read_csv(content, options?)`**: Reads a CSV string and loads it into a new DataFrame, with automatic data type inference.
209
+ - **`$df.readCsv(content, options?)`**: Reads a CSV string with automatic type inference.
205
210
  ```typescript
206
211
  import { $df } from "df-script";
207
212
 
208
213
  const csvContent = "id,name,active\n1,Alice,true\n2,Bob,false";
209
- const df = $df.read_csv(csvContent, {
214
+ const df = $df.readCsv(csvContent, {
210
215
  separator: ",",
211
216
  hasHeader: true,
212
217
  inferSchema: true
@@ -214,46 +219,45 @@ DFScript provides helpers to serialize and parse data formats like JSON and CSV.
214
219
  ```
215
220
 
216
221
  ### Writing Data
217
- - **`df.write_json(file?, options?)`**: Serializes a DataFrame into a JSON or NDJSON string. If a file path or writable stream/object (with a `.write` method) is provided, writes/streams the content as a side-effect. Always returns the serialized string.
222
+ - **`df.writeJson(file?, options?)`**: Serializes a DataFrame into a JSON or NDJSON string.
218
223
  ```typescript
219
- // Write to a file and get the string
220
- const jsonStr = df.write_json("output.json");
224
+ const jsonStr = df.writeJson();
225
+ df.writeJson("output.json");
221
226
  ```
222
- - **`df.write_csv(file?, options?)`**: Serializes a DataFrame into a CSV string. Supports options for headers, custom separators, quote styles, float precision, and BOM. If a file path or writable stream/object (with a `.write` method) is provided, writes/streams the content as a side-effect. Always returns the serialized string.
227
+ - **`df.writeCsv(file?, options?)`**: Serializes a DataFrame into a CSV string.
223
228
  ```typescript
224
- // Serialize to a CSV string
225
- const csvStr = df.write_csv();
226
-
227
- // Write to a file with custom separator
228
- df.write_csv("output.csv", { separator: ";" });
229
+ const csvStr = df.writeCsv();
230
+ df.writeCsv("output.csv", { separator: ";" });
229
231
  ```
230
232
 
231
233
  ---
232
234
 
233
235
  ## 🧮 Expressions API Reference
234
236
 
235
- All column expressions inherit from `ExprBase` and support standard operators.
237
+ All column expressions inherit from `ExprBase` and support chaining.
236
238
 
237
239
  ### ➕ Arithmetic Expressions
238
- Chained mathematical functions execute cleanly with built-in null-safety (Kleene logic).
239
240
  - `.add(val)`, `.sub(val)`, `.mul(val)`, `.div(val)`, `.floordiv(val)`, `.mod(val)`, `.pow(val)`
240
241
  - `.abs()`, `.sqrt()`, `.cbrt()`, `.exp()`, `.expm1()`, `.log(base?)`, `.log1p()`
241
242
  - `.ceil()`, `.floor()`, `.trunc()`, `.round(decimals)`, `.clip(lower, upper)`, `.sign()`, `.negate()`
242
- - `.sin()`, `.cos()`, `.tan()`, `.sinh()`, `.cosh()`, `.tanh()`, `.asin()`, `.acos()`, `.atan()`, `.asinh()`, `.acosh()`, `.atanh()`, `.degrees()`, `.radians()`, `.hypot(val)`
243
+ - `.sin()`, `.cos()`, `.tan()`, `.cot()`, `.sinh()`, `.cosh()`, `.tanh()`, `.arcsin()`, `.arccos()`, `.arctan()`, `.arctan2(val)`, `.arcsinh()`, `.arccosh()`, `.arctanh()`, `.degrees()`, `.radians()`, `.hypot(val)`
243
244
 
244
245
  ### 🔍 Comparison Expressions
245
- - `.eq(val)`, `.ne(val)` — Strict value equivalence (null values return null).
246
- - `.eq_missing(val)`, `.ne_missing(val)` — Equality checking that treats null/undefined values as equal.
246
+ - `.eq(val)`, `.ne(val)` — Strict value equivalence (Kleene null-propagation).
247
+ - `.eqMissing(val)`, `.neMissing(val)` — Null-safe equality treating null/undefined as equal.
247
248
  - `.gt(val)`, `.ge(val)`, `.lt(val)`, `.le(val)`
248
- - `.is_null()`, `.is_not_null()`
249
- - `.is_finite()`, `.is_infinite()`, `.is_nan()`, `.is_not_nan()`
250
- - `.is_in(arrayOrExpr)`, `.not_in(arrayOrExpr)`
249
+ - `.isNull()`, `.isNotNull()`
250
+ - `.isFinite()`, `.isInfinite()`, `.isNan()`, `.isNotNan()`
251
+ - `.isNDistinct(index, nullOnOob?)` — Matches the N-th distinct value by positive/negative index position.
252
+ - `.isIn(arrayOrExpr)`, `.notIn(arrayOrExpr)`
251
253
 
252
254
  ### ⚡ Aggregations
253
- - `.sum()`, `.avg()` / `.mean()`, `.median()`, `.mode()`, `.std()`, `.min()`, `.max()`
254
- - `.count(options?)` Option `{ includeNulls: boolean }`.
255
+ - `.sum()`, `.product()`, `.avg()` / `.mean()`, `.median()`, `.mode()`, `.variance()`, `.std()`, `.skew()`, `.kurtosis()`, `.entropy(base?, normalize?)`
256
+ - `.min()`, `.max()`, `.nanMin()`, `.nanMax()`, `.minBy(by)`, `.maxBy(by)`, `.argMin()`, `.argMax()`
257
+ - `.count(options?)` — Options: `{ includeNulls: boolean }`.
255
258
  - `.first()`, `.last()`
256
- - `.any()`, `.all()`, `.any_null()`, `.all_null()`, `.n_unique()`
259
+ - `.any()`, `.all()`, `.anyNull()`, `.allNull()`, `.nUnique()`, `.nullCount()`
260
+ - `.bitwiseAnd()`, `.bitwiseOr()`, `.bitwiseXor()`
257
261
 
258
262
  ### 🔀 Control Flow & Conditionals
259
263
  Construct dynamic `CASE WHEN` branches using the `$df.when` API:
@@ -265,117 +269,84 @@ df.select(
265
269
  $df.when($df.col("sales").gt(2000)).then("High Performance")
266
270
  .when($df.col("sales").gt(1000)).then("Standard Performance")
267
271
  .otherwise("Low Performance")
268
- .alias("sales_category")
272
+ .alias("salesCategory")
269
273
  );
270
274
  ```
271
- - `$df.when(predicate).then(value)`: Starts a conditional evaluation.
272
- - `.when(predicate).then(value)`: Chains additional conditions.
273
- - `.otherwise(value)`: Specifies the fallback value when no conditions match (returns a complete `ColumnExpr`).
274
275
 
275
276
  ---
276
277
 
277
278
  ## 📂 Namespaces
278
279
 
279
- To maintain a clean and uncluttered API namespace, specific data transforms are grouped under dedicated accessors.
280
+ Specific domain transforms are grouped under dedicated namespaces:
280
281
 
281
282
  ### 🔤 String Operations (`.str`)
282
283
  Available on any expression via `.str`:
283
284
  ```typescript
284
285
  $df.col("name").str.lower()
285
- $df.col("code").str.starts_with("A")
286
+ $df.col("code").str.startsWith("A")
286
287
  $df.col("description").str.replace(/foo/i, "bar")
287
288
  ```
288
- - **Methods**: `lower()`, `upper()`, `len()`, `len_bytes()`, `len_chars()`, `trim()`, `trim_start()`, `trim_end()`, `starts_with(prefix)`, `ends_with(suffix)`, `contains(pattern)`, `replace(pattern, repl)`, `replace_all(pattern, repl)`, `slice(offset, length?)`, `split(delimiter)`, `explode()`, `reverse()`, `lpad(w, f)`, `rpad(w, f)`, `zfill(w)`, `strip_chars(chars?)`, `strip_chars_start(chars?)`, `strip_chars_end(chars?)`, `strip_prefix(pfx)`, `strip_suffix(sfx)`, `to_titlecase()`, `strptime(format, strict?)`, `to_integer()`, `to_decimal(p, s)`, `to_date()`, `to_datetime()`, `to_time()`.
289
+ - **Methods**: `lower()`, `upper()`, `toTitlecase()`, `len()`, `lenBytes()`, `lenChars()`, `trim()`, `trimStart()`, `trimEnd()`, `startsWith(pfx)`, `endsWith(sfx)`, `contains(pat)`, `containsAny(pats)`, `countMatches(pat)`, `find(pat)`, `findMany(pats)`, `replace(pat, repl)`, `replaceAll(pat, repl)`, `replaceMany(pats, repls)`, `slice(offset, len?)`, `split(delim, options?)`, `explode()`, `reverse()`, `lpad(w, f)`, `rpad(w, f)`, `zfill(w)`, `stripChars(chars?)`, `stripCharsStart(chars?)`, `stripCharsEnd(chars?)`, `stripPrefix(pfx)`, `stripSuffix(sfx)`, `escapeRegex()`, `extract(pat, group?)`, `extractAll(pat)`, `extractGroups(pat)`, `extractMany(pats)`, `encode(enc)`, `decode(enc, strict?)`, `jsonDecode(options?)`, `jsonPathMatch(path)`, `normalize(form?)`, `join(sep)`, `strptime(fmt, strict?)`, `toInteger()`, `toDecimal(p, s)`, `toDate()`, `toDatetime()`, `toTime()`.
289
290
 
290
291
  ### 📅 Temporal Operations (`.dt`)
291
292
  Available on datetime or duration values via `.dt`:
292
293
  ```typescript
293
294
  $df.col("timestamp").dt.year()
294
- $df.col("timestamp").dt.strftime("%Y-%m-%d %H:%M:%S")
295
- $df.col("duration").dt.total_seconds()
295
+ $df.col("timestamp").dt.convertTimeZone("America/New_York")
296
+ $df.col("duration").dt.totalSeconds()
296
297
  ```
297
- - **Datetime Methods**: `year()`, `month()`, `day()`, `hour()`, `minute()`, `second()`, `millisecond()`, `microsecond()`, `nanosecond()`, `weekday()`, `week()`, `quarter()`, `century()`, `millennium()`, `ordinal_day()`, `is_leap_year()`, `month_start()`, `month_end()`, `date()`, `time()`, `offset_day(n, options?)`, `offset_business_day(n, options?)`, `utc_offset(timeZone?, options?)`, `epoch(unit)`, `timestamp(unit)`, `strftime(format, locale?)`.
298
- - **Duration Methods**: `total_days()`, `total_hours()`, `total_minutes()`, `total_seconds()`, `total_milliseconds()`, `total_microseconds()`, `total_nanoseconds()`.
298
+ - **Datetime Methods**: `year()`, `month()`, `day()`, `hour()`, `minute()`, `second()`, `millisecond()`, `microsecond()`, `nanosecond()`, `weekday()`, `week()`, `quarter()`, `century()`, `millennium()`, `ordinalDay()`, `isLeapYear()`, `monthStart()`, `monthEnd()`, `date()`, `time()`, `offsetDay(n, options?)`, `offsetBusinessDay(n, options?)`, `convertTimeZone(tz)`, `castTimeUnit(unit)`, `withTimeUnit(unit)`, `replace(options)`, `truncate(every)`, `utcOffset(tz?, options?)`, `epoch(unit)`, `timestamp(unit)`, `strftime(fmt, locale?)`.
299
+ - **Duration Methods**: `totalDays()`, `totalHours()`, `totalMinutes()`, `totalSeconds()`, `totalMilliseconds()`, `totalMicroseconds()`, `totalNanoseconds()`.
299
300
 
300
301
  ### 📊 Array/List Operations (`.arr`)
301
- Available on any array or list column expression via `.arr`:
302
+ Available on array/list column expressions via `.arr`:
302
303
  ```typescript
303
304
  $df.col("tags").arr.contains("vip")
304
- $df.col("matrix").arr.get(2)
305
-
306
- // Element-wise manipulation inside arrays:
307
- $df.col("numbers").arr.eval(element().mul(2)).alias("numbers_doubled")
308
- $df.col("tags").arr.eval(element().str.to_uppercase()).alias("upper_tags")
305
+ $df.col("numbers").arr.eval($df.element().mul(2)).alias("numbersDoubled")
309
306
  ```
310
- - **Methods**: `lengths()`, `len()`, `get(idx, null_on_oob?)`, `first(null_on_oob?)`, `last(null_on_oob?)`, `gather(indices, null_on_oob?)`, `gather_every(n, offset?)`, `slice(offset, length?)`, `contains(item)`, `count_matches(item)`, `join(separator)`, `sort(descending?)`, `reverse()`, `unique()`, `sum()`, `mean()`, `median()`, `mode()`, `min()`, `max()`, `eval(expr)`.
307
+ - **Methods**: `lengths()`, `len()`, `get(idx, nullOnOob?)`, `first(nullOnOob?)`, `last(nullOnOob?)`, `gather(indices, nullOnOob?)`, `gatherEvery(n, offset?)`, `slice(offset, len?)`, `contains(item)`, `countMatches(item)`, `join(sep)`, `sort(descending?)`, `reverse()`, `unique()`, `sum()`, `mean()`, `median()`, `mode()`, `min()`, `max()`, `argMin()`, `argMax()`, `agg(expr)`, `eval(expr)`.
311
308
 
312
309
  ### 🗃️ Struct/Object Operations (`.struct`)
313
- Available on any struct or nested object column expression via `.struct`. You can access fields dynamically via properties or explicit methods:
310
+ Available on nested struct/object column expressions via `.struct`:
314
311
  ```typescript
315
312
  // Sibling fields access via Proxy
316
313
  $df.col("address").struct.city.alias("city")
317
314
 
318
- // Or using the explicit field method
319
- $df.col("address").struct.field("city")
315
+ // Struct unnesting (flattens fields to top-level columns in select)
316
+ df.select($df.col("address").struct.unnest())
320
317
  ```
321
- - **Methods**:
322
- - `field(name)`: Accesses a field within the struct.
323
- - `rename_fields(mapping)`: Renames fields in the struct based on a `{ oldKey: newKey }` mapping.
324
- - `with_fields(fields)`: Adds or overrides fields in the struct. Accepts an array of aliased expressions or an object.
325
- - `unnest()`: Expands the fields of the struct into individual top-level columns in a select projection.
326
- ```typescript
327
- // Flattens the address struct into "city", "state", etc. at the top-level
328
- df.select($df.col("address").struct.unnest())
329
- ```
318
+ - **Methods**: `field(name)`, `renameFields(mapping)`, `withFields(fields)`, `unnest()`.
330
319
 
331
320
  ---
332
321
 
333
322
  ## 🪟 Window & Rolling Expressions
334
323
 
335
- DFScript provides full support for analytic partition window operations using `.over()` and rolling filters.
324
+ Analytical partition window operations using `.over()` and moving calculations:
336
325
 
337
326
  ```typescript
338
- // Calculate partition cumulative sums and row numbers
339
327
  df.select(
340
328
  $df.col("department"),
341
329
  $df.col("sales"),
342
- $df.col("sales").sum().over("department").alias("dept_total_sales"),
343
- $df.col("sales").cum_sum().over("department").alias("dept_running_sales"),
344
- $df.all().row_number().over("department").alias("dept_rank")
330
+ $df.col("sales").sum().over("department").alias("deptTotalSales"),
331
+ $df.col("sales").cumSum().over("department").alias("deptRunningSales"),
332
+ $df.all().rowNumber().over("department").alias("deptRank")
345
333
  );
346
334
  ```
347
335
 
348
336
  ### 1. Cumulative Windows
349
- - `.cum_sum(reverse?)`
350
- - `.cum_prod(reverse?)`
351
- - `.cum_min(reverse?)`
352
- - `.cum_max(reverse?)`
353
- - `.cum_count(reverse?)`
337
+ - `.cumSum(reverse?)`, `.cumProd(reverse?)`, `.cumMin(reverse?)`, `.cumMax(reverse?)`, `.cumCount(reverse?)`
354
338
 
355
339
  ### 2. Rolling Metrics (Moving Window)
356
- Apply moving calculations over a fixed window size:
357
- - `.rolling_sum(size)`
358
- - `.rolling_mean(size)`
359
- - `.rolling_median(size)`
360
- - `.rolling_min(size)`
361
- - `.rolling_max(size)`
362
- - `.rolling_std(size)`
363
- - `.rolling_rank(size)`
364
- - `.rolling_quantile(quantile, size)`
340
+ - **Generic Rolling Reducer**: `.rolling(sizeOrOptions, exprOrFn)` (evaluates custom functions or `$df` column expressions over each sliding window).
341
+ - **Specialized Rolling Reducers**: `.rollingSum(size)`, `.rollingMean(size)`, `.rollingMedian(size)`, `.rollingMin(size)`, `.rollingMax(size)`, `.rollingStd(size)`, `.rollingRank(size)`, `.rollingQuantile(quantile, size)`
365
342
 
366
343
  ### 3. Positional & Rank Windows
367
- - `.lead(offset, defaultVal?)`
368
- - `.lag(offset, defaultVal?)`
369
- - `.rank()`
370
- - `.dense_rank()`
371
- - `.row_number()`
344
+ - `.lead(offset, defaultVal?)`, `.lag(offset, defaultVal?)`, `.rank()`, `.denseRank()`, `.rowNumber()`
372
345
 
373
346
  ---
374
347
 
375
348
  ## 🛡️ Typing and Schema Registry
376
349
 
377
- You can optionally declare schemas to enforce precise data types and automatic type coercion during construction.
378
-
379
350
  ```typescript
380
351
  import { $df } from "df-script";
381
352
 
@@ -383,30 +354,10 @@ const schema = {
383
354
  id: $df.DataType.Int32,
384
355
  price: $df.DataType.Decimal(10, 2),
385
356
  active: $df.DataType.Boolean,
386
- created_at: $df.DataType.Datetime
387
- };
388
-
389
- const df = $df.data(rawData, schema);
390
- ```
391
-
392
- ### 🧠 TypeScript Type Inference & IDE Safety
393
-
394
- When you pass a schema to `$df.data()`, DFScript's types automatically infer the target types of the fields, turning dynamic dataframes into compile-safe records. Your IDE will auto-complete column names and validate that operations match the underlying types.
395
-
396
- ```typescript
397
- import { $df } from "df-script";
398
-
399
- const schema = {
400
- name: $df.DataType.Utf8,
401
- age: $df.DataType.Int32,
402
- is_active: $df.DataType.Boolean
357
+ createdAt: $df.DataType.Datetime
403
358
  };
404
359
 
405
- // Inferred DataFrame type is DataFrame<{ name: string; age: number; is_active: boolean }>
406
360
  const df = $df.data(rawData, schema);
407
-
408
- // Full IDE autocomplete, type validation, and compiler safety!
409
- const activeUsers = df.filter($df.col("is_active").eq(true));
410
361
  ```
411
362
 
412
363
  ### Supported Data Types
@@ -420,17 +371,16 @@ const activeUsers = df.filter($df.col("is_active").eq(true));
420
371
 
421
372
  ## 🧑‍💻 Contributing & Development
422
373
 
423
- We welcome contributions! Please make sure to review our [Developer Guidelines](DEVELOPER_GUIDELINES.md) when writing code.
424
-
425
- ### Running Project Tests
426
- DFScript has a comprehensive suite of unit tests. Run them using:
427
-
428
374
  ```bash
429
- npx tsx _tests/run_all_project_tests.ts
375
+ # Run test suite
376
+ npm test
377
+
378
+ # Build production bundles
379
+ npm run build
430
380
  ```
431
381
 
432
382
  ---
433
383
 
434
384
  ## 📄 License
435
385
 
436
- DFScript is open-source software licensed under the [MIT License](LICENSE).
386
+ `df-script` is open-source software licensed under the [MIT License](LICENSE).