df-script 1.4.0 → 1.6.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 (142) hide show
  1. package/README.md +203 -38
  2. package/dist/api.d.ts +16 -8
  3. package/dist/columnExpressions/ColumnExpr.d.ts +26 -364
  4. package/dist/columnExpressions/ExprBase.d.ts +8 -11
  5. package/dist/columnExpressions/constants.d.ts +2 -0
  6. package/dist/columnExpressions/functions/coalesce.d.ts +2 -2
  7. package/dist/columnExpressions/functions/element.d.ts +5 -0
  8. package/dist/columnExpressions/functions/implode.d.ts +3 -0
  9. package/dist/columnExpressions/functions/lit.d.ts +3 -1
  10. package/dist/columnExpressions/functions/seq_range.d.ts +31 -0
  11. package/dist/columnExpressions/functions/when.d.ts +2 -2
  12. package/dist/columnExpressions/index.d.ts +6 -3
  13. package/dist/columnExpressions/mixins/AggregationExpr.d.ts +25 -50
  14. package/dist/columnExpressions/mixins/ArithmeticExpr.d.ts +43 -67
  15. package/dist/columnExpressions/mixins/ArrayExpr.d.ts +39 -0
  16. package/dist/columnExpressions/mixins/ComparisonExpr.d.ts +31 -60
  17. package/dist/columnExpressions/mixins/ListExpr.d.ts +16 -40
  18. package/dist/columnExpressions/mixins/LogicalExpr.d.ts +7 -33
  19. package/dist/columnExpressions/mixins/ManipulationExpr.d.ts +6 -31
  20. package/dist/columnExpressions/mixins/StringExpr.d.ts +7 -32
  21. package/dist/columnExpressions/mixins/StructExpr.d.ts +16 -0
  22. package/dist/columnExpressions/mixins/TemporalExpr.d.ts +4 -30
  23. package/dist/columnExpressions/mixins/WindowExpr.d.ts +27 -49
  24. package/dist/columnExpressions/types.d.ts +1 -0
  25. package/dist/columnExpressions/utils.d.ts +4 -0
  26. package/dist/constants.d.ts +11 -0
  27. package/dist/dataframe/constants.d.ts +3 -0
  28. package/dist/dataframe/dataframe.d.ts +28 -11
  29. package/dist/dataframe/grouped/grouped.d.ts +2 -3
  30. package/dist/dataframe/types.d.ts +65 -1
  31. package/dist/dataframe/utils.d.ts +11 -3
  32. package/dist/datatypes/DataType.d.ts +2 -1
  33. package/dist/datatypes/index.d.ts +4 -3
  34. package/dist/datatypes/types.d.ts +42 -41
  35. package/dist/exceptions/index.d.ts +2 -0
  36. package/dist/exceptions/utils.d.ts +1 -0
  37. package/dist/functions/concat.d.ts +1 -2
  38. package/dist/functions/index.d.ts +3 -1
  39. package/dist/functions/read_csv.d.ts +8 -0
  40. package/dist/functions/read_json.d.ts +10 -0
  41. package/dist/index.js +6 -1
  42. package/dist/types.d.ts +34 -6
  43. package/dist/utils/array.d.ts +217 -0
  44. package/dist/utils/binary.d.ts +3 -0
  45. package/dist/utils/csv.d.ts +77 -0
  46. package/dist/utils/date.d.ts +21 -35
  47. package/dist/utils/guards.d.ts +11 -12
  48. package/dist/utils/index.d.ts +5 -2
  49. package/dist/utils/json.d.ts +120 -2
  50. package/dist/utils/list.d.ts +196 -2
  51. package/dist/utils/number.d.ts +47 -29
  52. package/dist/utils/object.d.ts +26 -0
  53. package/dist/utils/string.d.ts +7 -4
  54. package/package.json +6 -2
  55. package/dist/api.js +0 -18
  56. package/dist/bundle.min.js +0 -1
  57. package/dist/columnExpressions/ColumnExpr.js +0 -23
  58. package/dist/columnExpressions/ExprBase.js +0 -133
  59. package/dist/columnExpressions/constants.js +0 -5
  60. package/dist/columnExpressions/functions/all.js +0 -11
  61. package/dist/columnExpressions/functions/coalesce.js +0 -40
  62. package/dist/columnExpressions/functions/exclude.js +0 -13
  63. package/dist/columnExpressions/functions/lit.js +0 -22
  64. package/dist/columnExpressions/functions/when.js +0 -81
  65. package/dist/columnExpressions/index.js +0 -81
  66. package/dist/columnExpressions/mixins/AggregationExpr.js +0 -172
  67. package/dist/columnExpressions/mixins/ArithmeticExpr.js +0 -143
  68. package/dist/columnExpressions/mixins/ComparisonExpr.js +0 -389
  69. package/dist/columnExpressions/mixins/ListExpr.js +0 -248
  70. package/dist/columnExpressions/mixins/LogicalExpr.js +0 -54
  71. package/dist/columnExpressions/mixins/ManipulationExpr.js +0 -35
  72. package/dist/columnExpressions/mixins/StringExpr.js +0 -249
  73. package/dist/columnExpressions/mixins/TemporalExpr.js +0 -127
  74. package/dist/columnExpressions/mixins/WindowExpr.js +0 -281
  75. package/dist/columnExpressions/types.js +0 -2
  76. package/dist/dataframe/constants.js +0 -4
  77. package/dist/dataframe/dataframe.js +0 -749
  78. package/dist/dataframe/grouped/grouped.js +0 -113
  79. package/dist/dataframe/index.js +0 -20
  80. package/dist/dataframe/types.js +0 -2
  81. package/dist/dataframe/utils.js +0 -215
  82. package/dist/datatypes/DataType.js +0 -47
  83. package/dist/datatypes/index.js +0 -46
  84. package/dist/datatypes/types/Binary.d.ts +0 -9
  85. package/dist/datatypes/types/Binary.js +0 -18
  86. package/dist/datatypes/types/Boolean.d.ts +0 -9
  87. package/dist/datatypes/types/Boolean.js +0 -19
  88. package/dist/datatypes/types/Date.d.ts +0 -8
  89. package/dist/datatypes/types/Date.js +0 -21
  90. package/dist/datatypes/types/Datetime.d.ts +0 -8
  91. package/dist/datatypes/types/Datetime.js +0 -17
  92. package/dist/datatypes/types/Decimal.d.ts +0 -10
  93. package/dist/datatypes/types/Decimal.js +0 -28
  94. package/dist/datatypes/types/Duration.d.ts +0 -8
  95. package/dist/datatypes/types/Duration.js +0 -17
  96. package/dist/datatypes/types/Float32.d.ts +0 -8
  97. package/dist/datatypes/types/Float32.js +0 -17
  98. package/dist/datatypes/types/Float64.d.ts +0 -8
  99. package/dist/datatypes/types/Float64.js +0 -17
  100. package/dist/datatypes/types/Int16.d.ts +0 -8
  101. package/dist/datatypes/types/Int16.js +0 -17
  102. package/dist/datatypes/types/Int32.d.ts +0 -8
  103. package/dist/datatypes/types/Int32.js +0 -17
  104. package/dist/datatypes/types/Int64.d.ts +0 -8
  105. package/dist/datatypes/types/Int64.js +0 -17
  106. package/dist/datatypes/types/Int8.d.ts +0 -8
  107. package/dist/datatypes/types/Int8.js +0 -17
  108. package/dist/datatypes/types/List.d.ts +0 -10
  109. package/dist/datatypes/types/List.js +0 -31
  110. package/dist/datatypes/types/Null.d.ts +0 -9
  111. package/dist/datatypes/types/Null.js +0 -17
  112. package/dist/datatypes/types/Object.d.ts +0 -9
  113. package/dist/datatypes/types/Object.js +0 -17
  114. package/dist/datatypes/types/Struct.d.ts +0 -14
  115. package/dist/datatypes/types/Struct.js +0 -39
  116. package/dist/datatypes/types/Time.d.ts +0 -8
  117. package/dist/datatypes/types/Time.js +0 -29
  118. package/dist/datatypes/types/UInt16.d.ts +0 -8
  119. package/dist/datatypes/types/UInt16.js +0 -17
  120. package/dist/datatypes/types/UInt32.d.ts +0 -8
  121. package/dist/datatypes/types/UInt32.js +0 -17
  122. package/dist/datatypes/types/UInt64.d.ts +0 -8
  123. package/dist/datatypes/types/UInt64.js +0 -17
  124. package/dist/datatypes/types/UInt8.d.ts +0 -8
  125. package/dist/datatypes/types/UInt8.js +0 -17
  126. package/dist/datatypes/types/Utf8.d.ts +0 -10
  127. package/dist/datatypes/types/Utf8.js +0 -20
  128. package/dist/datatypes/types.js +0 -286
  129. package/dist/exceptions/index.js +0 -43
  130. package/dist/exceptions/utils.js +0 -9
  131. package/dist/functions/concat.js +0 -248
  132. package/dist/functions/index.js +0 -17
  133. package/dist/types.js +0 -2
  134. package/dist/utils/boolean.d.ts +0 -1
  135. package/dist/utils/boolean.js +0 -18
  136. package/dist/utils/date.js +0 -349
  137. package/dist/utils/guards.js +0 -143
  138. package/dist/utils/index.js +0 -21
  139. package/dist/utils/json.js +0 -33
  140. package/dist/utils/list.js +0 -128
  141. package/dist/utils/number.js +0 -223
  142. package/dist/utils/string.js +0 -120
package/README.md CHANGED
@@ -1,9 +1,39 @@
1
1
  # 🚀 DFScript
2
2
 
3
+ [![GitHub Repository](https://img.shields.io/badge/GitHub-Repository-blue?style=for-the-badge&logo=github)](https://github.com/trentamorris/df-script)
4
+ [![Donate](https://img.shields.io/badge/Donate-Support-green?style=for-the-badge)](DONATIONS.md)
5
+
3
6
  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.
4
7
 
5
8
  With optimized columnar storage under the hood, DFScript enables you to build clean, maintainable, and type-safe data pipelines using a declarative expression API.
6
9
 
10
+ ## 💡 Why DFScript?
11
+
12
+ 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.
13
+
14
+ 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?
15
+
16
+ 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.
17
+
18
+ ---
19
+
20
+ ## 🗺️ Table of Contents
21
+
22
+ - [✨ Key Features](#-key-features)
23
+ - [⚙️ Compatibility & Design Principles](#-compatibility--design-principles)
24
+ - [🤝 Contributing & Collective Wisdom](#-contributing--collective-wisdom)
25
+ - [📦 Installation](#-installation)
26
+ - [🚀 Quick Start](#-quick-start)
27
+ - [📖 Core Concepts](#-core-concepts)
28
+ - [🛠️ DataFrame API Reference](#-dataframe-api-reference)
29
+ - [📂 File / Data I/O](#-file--data-io)
30
+ - [🧮 Expressions API Reference](#-expressions-api-reference)
31
+ - [📂 Namespaces](#-namespaces)
32
+ - [🪟 Window & Rolling Expressions](#-window--rolling-expressions)
33
+ - [🛡️ Typing and Schema Registry](#-typing-and-schema-registry)
34
+ - [🧑‍💻 Contributing & Development](#-contributing--development)
35
+ - [📄 License](#-license)
36
+
7
37
  ---
8
38
 
9
39
  ## ✨ Key Features
@@ -14,13 +44,34 @@ With optimized columnar storage under the hood, DFScript enables you to build cl
14
44
  - 📂 **Strict Namespaces** — Clear API organization for specific domains:
15
45
  - `.str` for advanced string manipulations.
16
46
  - `.dt` for microsecond-precision datetimes, timezones, and duration calculations.
17
- - `.list` for robust array/list column operations.
47
+ - `.arr` for robust array/list column operations.
48
+ - `.struct` for nested object and struct manipulation.
18
49
  - 🪟 **Analytical Window Functions** — Windowing (`over()`), cumulative aggregations (`cum_sum()`, `cum_max()`), and rolling metrics (`rolling_mean()`, `rolling_std()`).
19
50
  - 🛠️ **Relational Operations** — Rich, high-speed joins, pivots, unpivots, vertical/horizontal concatenations, and group-by aggregations.
20
51
  - 🛡️ **Defensive & Type-Safe** — Native type-coercion, robust null-safety, and strict schema validation.
21
52
 
22
53
  ---
23
54
 
55
+ ## ⚙️ Compatibility & Design Principles
56
+
57
+ DFScript is designed with a **low-abstraction, zero-dependency** philosophy to guarantee maximum compatibility, predictability, and runtime performance:
58
+
59
+ - 📦 **Zero External Dependencies** — Lightweight footprint with zero runtime overhead or supply chain vulnerabilities.
60
+ - 🌐 **Universal Compatibility** — Works out-of-the-box in any JavaScript/TypeScript environment, including Node.js, Deno, Bun, web browsers, and cloud/edge workers.
61
+ - 🧱 **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.
62
+ - ⚡ **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.
63
+ - 🔄 **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.
64
+
65
+ ---
66
+
67
+ ## 🤝 Contributing & Collective Wisdom
68
+
69
+ 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.
70
+
71
+ 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.
72
+
73
+ ---
74
+
24
75
  ## 📦 Installation
25
76
 
26
77
  Install DFScript using your favorite package manager:
@@ -43,10 +94,10 @@ pnpm add df-script
43
94
  Here is a quick example showing how to load data, run expressions, perform aggregations, and compute rolling statistics.
44
95
 
45
96
  ```typescript
46
- import { $tbl } from "df-script";
97
+ import { $df } from "df-script";
47
98
 
48
99
  // 1. Create a DataFrame with structured data and automatic schema inference
49
- const df = $tbl.data([
100
+ const df = $df.data([
50
101
  { id: 1, name: "Alice", join_date: "2026-01-15", sales: 1200.50, tags: ["sales", "east"] },
51
102
  { id: 2, name: "Bob", join_date: "2026-02-20", sales: 850.00, tags: ["support", "west"] },
52
103
  { id: 3, name: "Charlie", join_date: "2026-03-05", sales: 2300.00, tags: ["sales", "north"] },
@@ -55,11 +106,11 @@ const df = $tbl.data([
55
106
 
56
107
  // 2. Select columns, transform strings, format dates, and fill missing values
57
108
  const processedDf = df.select(
58
- $tbl.col("id"),
59
- $tbl.col("name").str.upper().alias("NAME_UPPER"),
60
- $tbl.col("join_date").str.to_datetime().dt.year().alias("join_year"),
61
- $tbl.col("sales").add(500).alias("sales_adjusted"),
62
- $tbl.col("tags").list.lengths().alias("tag_count")
109
+ $df.col("id"),
110
+ $df.col("name").str.upper().alias("NAME_UPPER"),
111
+ $df.col("join_date").str.to_datetime().dt.year().alias("join_year"),
112
+ $df.col("sales").add(500).alias("sales_adjusted"),
113
+ $df.col("tags").arr.lengths().alias("tag_count")
63
114
  );
64
115
 
65
116
  console.log(processedDf.to_dicts());
@@ -77,14 +128,23 @@ console.log(processedDf.to_dicts());
77
128
 
78
129
  ## 📖 Core Concepts
79
130
 
80
- ### The `$tbl` Entry Point
131
+ ### The `$df` Entry Point
81
132
 
82
- DFScript uses the `$tbl` namespace to bootstrap DataFrames, refer to columns, and access general types.
133
+ DFScript uses the `$df` namespace to bootstrap DataFrames, refer to columns, build expressions, and access data types.
83
134
 
84
- - `$tbl.data(dataRowsOrCols, schema?)`: Instantiates a new `DataFrame`.
85
- - `$tbl.col(name)`: Creates a column reference expression.
86
- - `$tbl.all()`: Selects all columns in the DataFrame.
87
- - `$tbl.DataType`: Direct access to the `DataTypeRegistry` for schema specification.
135
+ - `$df.data(dataRowsOrCols, schema?)`: Instantiates a new `DataFrame`.
136
+ - `$df.read_json(content, options?)`: Reads JSON/NDJSON content into a new `DataFrame`.
137
+ - `$df.read_csv(content, options?)`: Reads CSV content into a new `DataFrame`.
138
+ - `$df.col(name)`: Creates a column reference expression.
139
+ - `$df.all()`: Selects all columns in the DataFrame.
140
+ - `$df.exclude(columns)`: Creates an expression matching all columns except the specified ones.
141
+ - `$df.coalesce(...exprs)`: Returns the first non-null value among columns or literal expressions.
142
+ - `$df.lit(val)`: Explicitly wraps a raw value into a literal expression.
143
+ - `$df.when(predicate).then(value)...otherwise(value)`: Constructs a conditional expression (when-then-otherwise chain).
144
+ - `$df.implode(column)`: Aggregates a column's rows (or grouped values) into a list.
145
+ - `$df.seq_range(value, options?)`: Generates a sequence range of values.
146
+ - `$df.element()`: References the current array element within an `.arr.eval(...)` expression.
147
+ - `$df.DataType`: Direct access to the `DataTypeRegistry` for schema specification.
88
148
 
89
149
  ### DataFrames vs. Columns
90
150
 
@@ -96,7 +156,7 @@ DFScript uses the `$tbl` namespace to bootstrap DataFrames, refer to columns, an
96
156
  ## 🛠️ DataFrame API Reference
97
157
 
98
158
  ### 1. Transformations & Projection
99
- - **`select(...exprs)`**: Projects columns. Supports strings, raw column names, `$tbl.col(...)` expressions, and `$tbl.all()`.
159
+ - **`select(...exprs)`**: Projects columns. Supports strings, raw column names, `$df.col(...)` expressions, and `$df.all()`.
100
160
  - **`with_columns(...exprs)`**: Adds or overrides columns. Accepts expressions, strings, or options objects mapping keys to values/expressions.
101
161
  - **`drop(...names)`**: Drops one or more columns from the DataFrame.
102
162
  - **`rename(mapping)`**: Renames columns using a `{ oldName: newName }` object.
@@ -107,13 +167,14 @@ DFScript uses the `$tbl` namespace to bootstrap DataFrames, refer to columns, an
107
167
  - **`limit(n, options?)`**: Returns the first `n` rows. Options include `offset` and direction `from: "start" | "end"`.
108
168
  - **`head(n)`** / **`tail(n)`**: Shortcuts for `limit` from the start or end of the DataFrame.
109
169
  - **`slice(start, end?)`**: Extract a subset of rows using standard index slicing.
170
+ - **`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).
110
171
 
111
172
  ### 3. Sorting
112
173
  - **`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.
113
174
 
114
175
  ### 4. Grouping & Aggregations
115
176
  - **`groupby(keys)`**: Groups the data by one or more columns, returning a `GroupedData` object.
116
- - **`GroupedData.agg(...exprs)`**: Run aggregations on grouped data (e.g. `$tbl.col("sales").sum()`).
177
+ - **`GroupedData.agg(...exprs)`**: Run aggregations on grouped data (e.g. `$df.col("sales").sum()`).
117
178
 
118
179
  ### 5. Reshaping & Joining
119
180
  - **`join(other, on, how, suffixes?)`**: Merges two DataFrames on join keys. Supported join types: `"inner" | "left" | "right" | "outer"`.
@@ -123,6 +184,50 @@ DFScript uses the `$tbl` namespace to bootstrap DataFrames, refer to columns, an
123
184
 
124
185
  ---
125
186
 
187
+ ## 📂 File / Data I/O
188
+
189
+ DFScript provides helpers to serialize and parse data formats like JSON and CSV.
190
+
191
+ ### Reading Data
192
+ - **`$df.read_json(content, options?)`**: Reads a JSON array or Newline Delimited JSON (NDJSON) string and loads it into a new DataFrame.
193
+ ```typescript
194
+ import { $df } from "df-script";
195
+
196
+ // Read standard JSON array
197
+ const df = $df.read_json('[{"id": 1, "name": "Alice"}]');
198
+
199
+ // Read Newline Delimited JSON (NDJSON)
200
+ const dfNdjson = $df.read_json('{"id": 1}\n{"id": 2}', { format: "ndjson" });
201
+ ```
202
+ - **`$df.read_csv(content, options?)`**: Reads a CSV string and loads it into a new DataFrame, with automatic data type inference.
203
+ ```typescript
204
+ import { $df } from "df-script";
205
+
206
+ const csvContent = "id,name,active\n1,Alice,true\n2,Bob,false";
207
+ const df = $df.read_csv(csvContent, {
208
+ separator: ",",
209
+ hasHeader: true,
210
+ inferSchema: true
211
+ });
212
+ ```
213
+
214
+ ### Writing Data
215
+ - **`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.
216
+ ```typescript
217
+ // Write to a file and get the string
218
+ const jsonStr = df.write_json("output.json");
219
+ ```
220
+ - **`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.
221
+ ```typescript
222
+ // Serialize to a CSV string
223
+ const csvStr = df.write_csv();
224
+
225
+ // Write to a file with custom separator
226
+ df.write_csv("output.csv", { separator: ";" });
227
+ ```
228
+
229
+ ---
230
+
126
231
  ## 🧮 Expressions API Reference
127
232
 
128
233
  All column expressions inherit from `ExprBase` and support standard operators.
@@ -148,6 +253,23 @@ Chained mathematical functions execute cleanly with built-in null-safety (Kleene
148
253
  - `.first()`, `.last()`
149
254
  - `.any()`, `.all()`, `.any_null()`, `.all_null()`, `.n_unique()`
150
255
 
256
+ ### 🔀 Control Flow & Conditionals
257
+ Construct dynamic `CASE WHEN` branches using the `$df.when` API:
258
+ ```typescript
259
+ import { $df } from "df-script";
260
+
261
+ df.select(
262
+ $df.col("sales"),
263
+ $df.when($df.col("sales").gt(2000)).then("High Performance")
264
+ .when($df.col("sales").gt(1000)).then("Standard Performance")
265
+ .otherwise("Low Performance")
266
+ .alias("sales_category")
267
+ );
268
+ ```
269
+ - `$df.when(predicate).then(value)`: Starts a conditional evaluation.
270
+ - `.when(predicate).then(value)`: Chains additional conditions.
271
+ - `.otherwise(value)`: Specifies the fallback value when no conditions match (returns a complete `ColumnExpr`).
272
+
151
273
  ---
152
274
 
153
275
  ## 📂 Namespaces
@@ -157,29 +279,52 @@ To maintain a clean and uncluttered API namespace, specific data transforms are
157
279
  ### 🔤 String Operations (`.str`)
158
280
  Available on any expression via `.str`:
159
281
  ```typescript
160
- $tbl.col("name").str.lower()
161
- $tbl.col("code").str.starts_with("A")
162
- $tbl.col("description").str.replace(/foo/i, "bar")
282
+ $df.col("name").str.lower()
283
+ $df.col("code").str.starts_with("A")
284
+ $df.col("description").str.replace(/foo/i, "bar")
163
285
  ```
164
286
  - **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()`.
165
287
 
166
288
  ### 📅 Temporal Operations (`.dt`)
167
289
  Available on datetime or duration values via `.dt`:
168
290
  ```typescript
169
- $tbl.col("timestamp").dt.year()
170
- $tbl.col("timestamp").dt.strftime("%Y-%m-%d %H:%M:%S")
171
- $tbl.col("duration").dt.total_seconds()
291
+ $df.col("timestamp").dt.year()
292
+ $df.col("timestamp").dt.strftime("%Y-%m-%d %H:%M:%S")
293
+ $df.col("duration").dt.total_seconds()
172
294
  ```
173
295
  - **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()`, `datetime()`, `epoch(unit)`, `timestamp(unit)`, `strftime(format, locale?)`.
174
296
  - **Duration Methods**: `total_days()`, `total_hours()`, `total_minutes()`, `total_seconds()`, `total_milliseconds()`, `total_microseconds()`, `total_nanoseconds()`.
175
297
 
176
- ### 📊 List Operations (`.list`)
177
- Available on arrays or lists via `.list`:
298
+ ### 📊 Array/List Operations (`.arr`)
299
+ Available on any array or list column expression via `.arr`:
178
300
  ```typescript
179
- $tbl.col("tags").list.contains("vip")
180
- $tbl.col("matrix").list.get(2)
301
+ $df.col("tags").arr.contains("vip")
302
+ $df.col("matrix").arr.get(2)
303
+
304
+ // Element-wise manipulation inside arrays:
305
+ $df.col("numbers").arr.eval(element().mul(2)).alias("numbers_doubled")
306
+ $df.col("tags").arr.eval(element().str.to_uppercase()).alias("upper_tags")
307
+ ```
308
+ - **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)`.
309
+
310
+ ### 🗃️ Struct/Object Operations (`.struct`)
311
+ Available on any struct or nested object column expression via `.struct`. You can access fields dynamically via properties or explicit methods:
312
+ ```typescript
313
+ // Sibling fields access via Proxy
314
+ $df.col("address").struct.city.alias("city")
315
+
316
+ // Or using the explicit field method
317
+ $df.col("address").struct.field("city")
181
318
  ```
182
- - **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()`.
319
+ - **Methods**:
320
+ - `field(name)`: Accesses a field within the struct.
321
+ - `rename_fields(mapping)`: Renames fields in the struct based on a `{ oldKey: newKey }` mapping.
322
+ - `with_fields(fields)`: Adds or overrides fields in the struct. Accepts an array of aliased expressions or an object.
323
+ - `unnest()`: Expands the fields of the struct into individual top-level columns in a select projection.
324
+ ```typescript
325
+ // Flattens the address struct into "city", "state", etc. at the top-level
326
+ df.select($df.col("address").struct.unnest())
327
+ ```
183
328
 
184
329
  ---
185
330
 
@@ -190,11 +335,11 @@ DFScript provides full support for analytic partition window operations using `.
190
335
  ```typescript
191
336
  // Calculate partition cumulative sums and row numbers
192
337
  df.select(
193
- $tbl.col("department"),
194
- $tbl.col("sales"),
195
- $tbl.col("sales").sum().over("department").alias("dept_total_sales"),
196
- $tbl.col("sales").cum_sum().over("department").alias("dept_running_sales"),
197
- $tbl.all().row_number().over("department").alias("dept_rank")
338
+ $df.col("department"),
339
+ $df.col("sales"),
340
+ $df.col("sales").sum().over("department").alias("dept_total_sales"),
341
+ $df.col("sales").cum_sum().over("department").alias("dept_running_sales"),
342
+ $df.all().row_number().over("department").alias("dept_rank")
198
343
  );
199
344
  ```
200
345
 
@@ -230,16 +375,36 @@ Apply moving calculations over a fixed window size:
230
375
  You can optionally declare schemas to enforce precise data types and automatic type coercion during construction.
231
376
 
232
377
  ```typescript
233
- import { $tbl } from "df-script";
378
+ import { $df } from "df-script";
234
379
 
235
380
  const schema = {
236
- id: $tbl.DataType.Int32,
237
- price: $tbl.DataType.Decimal(10, 2),
238
- active: $tbl.DataType.Boolean,
239
- created_at: $tbl.DataType.Datetime
381
+ id: $df.DataType.Int32,
382
+ price: $df.DataType.Decimal(10, 2),
383
+ active: $df.DataType.Boolean,
384
+ created_at: $df.DataType.Datetime
240
385
  };
241
386
 
242
- const df = $tbl.data(rawData, schema);
387
+ const df = $df.data(rawData, schema);
388
+ ```
389
+
390
+ ### 🧠 TypeScript Type Inference & IDE Safety
391
+
392
+ 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.
393
+
394
+ ```typescript
395
+ import { $df } from "df-script";
396
+
397
+ const schema = {
398
+ name: $df.DataType.Utf8,
399
+ age: $df.DataType.Int32,
400
+ is_active: $df.DataType.Boolean
401
+ };
402
+
403
+ // Inferred DataFrame type is DataFrame<{ name: string; age: number; is_active: boolean }>
404
+ const df = $df.data(rawData, schema);
405
+
406
+ // Full IDE autocomplete, type validation, and compiler safety!
407
+ const activeUsers = df.filter($df.col("is_active").eq(true));
243
408
  ```
244
409
 
245
410
  ### Supported Data Types
package/dist/api.d.ts CHANGED
@@ -1,17 +1,24 @@
1
1
  import { DataFrame } from "./dataframe";
2
- import { ColumnExpr, lit, all, exclude, coalesce, when } from "./columnExpressions";
2
+ import { ColumnExpr, lit, all, exclude, coalesce, when, implode, seq_range, element } from "./columnExpressions";
3
3
  import { DataType } from "./datatypes";
4
- import { concat } from "./functions";
5
- import type { RowRecord } from "./types";
6
- export declare const $tbl: {
7
- data: <T extends RowRecord>(data: T[], schema?: Record<string, DataType>) => DataFrame<T>;
8
- col: <T = any>(name: keyof T | string) => ColumnExpr<T>;
4
+ import { concat, read_json, read_csv } from "./functions";
5
+ import type { RowRecord, DataFrameSchema, ColumnDict, InferSchema } from "./types";
6
+ declare function data<S extends DataFrameSchema>(data: any[] | ColumnDict, schema: S): DataFrame<InferSchema<S>>;
7
+ declare function data<T extends RowRecord = any>(data: T[] | ColumnDict, schema?: DataFrameSchema): DataFrame<T>;
8
+ export declare const $df: {
9
+ data: typeof data;
10
+ col: <T = any>(name: keyof T | string | (keyof T | string)[] | DataType | Function | (DataType | Function)[]) => ColumnExpr<T>;
9
11
  all: typeof all;
10
12
  exclude: typeof exclude;
11
13
  coalesce: typeof coalesce;
12
14
  concat: typeof concat;
15
+ read_json: typeof read_json;
16
+ read_csv: typeof read_csv;
13
17
  lit: typeof lit;
14
18
  when: typeof when;
19
+ implode: typeof implode;
20
+ seq_range: typeof seq_range;
21
+ element: typeof element;
15
22
  DataType: {
16
23
  Int8: import("./datatypes").Int8Type;
17
24
  Int16: import("./datatypes").Int16Type;
@@ -33,7 +40,8 @@ export declare const $tbl: {
33
40
  Duration: import("./datatypes").DurationType;
34
41
  Object: import("./datatypes").ObjectType;
35
42
  Null: import("./datatypes").NullType;
36
- List: <TInner>(inner: DataType<TInner>) => import("./datatypes").ListType<TInner>;
37
- Struct: <TFields extends RowRecord>(fields: { [K in keyof TFields]: DataType<TFields[K]>; }) => import("./datatypes").StructType<TFields>;
43
+ Array: <TInner>(inner: import("./datatypes").RegisteredDataType & DataType<TInner>) => import("./datatypes").ArrayType<TInner>;
44
+ Struct: <TFields extends RowRecord>(fields: { [K in keyof TFields]: import("./datatypes").RegisteredDataType & DataType<TFields[K]>; }) => import("./datatypes").StructType<TFields>;
38
45
  };
39
46
  };
47
+ export {};