data-finder-ts 0.1.0 → 0.1.4
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.
- package/README.md +17 -55
- package/dist/chunk-4JVW4TAB.js +180 -0
- package/dist/chunk-4JVW4TAB.js.map +1 -0
- package/dist/chunk-4LNZV6EN.js +500 -0
- package/dist/chunk-4LNZV6EN.js.map +1 -0
- package/dist/chunk-FJYA2ASS.js +136 -0
- package/dist/chunk-FJYA2ASS.js.map +1 -0
- package/dist/chunk-FLEIUDZZ.js +14 -0
- package/dist/chunk-FLEIUDZZ.js.map +1 -0
- package/dist/chunk-MH4XMYVB.js +696 -0
- package/dist/chunk-MH4XMYVB.js.map +1 -0
- package/dist/chunk-PMPLCEWQ.js +90 -0
- package/dist/chunk-PMPLCEWQ.js.map +1 -0
- package/dist/chunk-UYMOE6YU.js +509 -0
- package/dist/chunk-UYMOE6YU.js.map +1 -0
- package/dist/datafinder/attribute.cjs +320 -0
- package/dist/datafinder/attribute.cjs.map +1 -0
- package/dist/datafinder/attribute.d.cts +86 -0
- package/dist/datafinder/attribute.d.ts +86 -0
- package/dist/datafinder/attribute.js +8 -0
- package/dist/datafinder/attribute.js.map +1 -0
- package/dist/datafinder/finder-registry.cjs +39 -0
- package/dist/datafinder/finder-registry.cjs.map +1 -0
- package/dist/datafinder/finder-registry.d.cts +4 -0
- package/dist/datafinder/finder-registry.d.ts +4 -0
- package/dist/datafinder/finder-registry.js +9 -0
- package/dist/datafinder/finder-registry.js.map +1 -0
- package/dist/datafinder/runner.cjs +1595 -0
- package/dist/datafinder/runner.cjs.map +1 -0
- package/dist/datafinder/runner.d.cts +44 -0
- package/dist/datafinder/runner.d.ts +44 -0
- package/dist/datafinder/runner.js +26 -0
- package/dist/datafinder/runner.js.map +1 -0
- package/dist/datafinder/sql-generator.cjs +1467 -0
- package/dist/datafinder/sql-generator.cjs.map +1 -0
- package/dist/datafinder/sql-generator.d.cts +8 -0
- package/dist/datafinder/sql-generator.d.ts +8 -0
- package/dist/datafinder/sql-generator.js +15 -0
- package/dist/datafinder/sql-generator.js.map +1 -0
- package/dist/datafinder/typed-attributes.cjs +909 -0
- package/dist/datafinder/typed-attributes.cjs.map +1 -0
- package/dist/datafinder/typed-attributes.d.cts +242 -0
- package/dist/datafinder/typed-attributes.d.ts +242 -0
- package/dist/datafinder/typed-attributes.js +25 -0
- package/dist/datafinder/typed-attributes.js.map +1 -0
- package/dist/index.cjs +2153 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +28 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +199 -0
- package/dist/index.js.map +1 -0
- package/dist/model/milestoning.cjs +145 -0
- package/dist/model/milestoning.cjs.map +1 -0
- package/dist/model/milestoning.d.cts +40 -0
- package/dist/model/milestoning.d.ts +40 -0
- package/dist/model/milestoning.js +18 -0
- package/dist/model/milestoning.js.map +1 -0
- package/dist/model/relational.cjs +579 -0
- package/dist/model/relational.cjs.map +1 -0
- package/dist/model/relational.d.cts +291 -0
- package/dist/model/relational.d.ts +291 -0
- package/dist/model/relational.js +99 -0
- package/dist/model/relational.js.map +1 -0
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -1,69 +1,42 @@
|
|
|
1
1
|
# data-finder-ts
|
|
2
2
|
|
|
3
|
-
TypeScript port of [data-finder](https://github.com/jackie-h/data-finder), a model-driven SQL query builder with temporal (milestoned) data support. A Python generator reads
|
|
3
|
+
TypeScript port of [data-finder](https://github.com/jackie-h/data-finder), a model-driven SQL query builder with temporal (milestoned) data support. A Python generator reads mapping definitions and emits strongly-typed TypeScript finder classes.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
For runtime usage and query API see **[FINDERS.md](FINDERS.md)**.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Requirements
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
- Node ≥ 24
|
|
10
|
+
- [uv](https://docs.astral.sh/uv/) (Python package manager)
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
const rows = await tf.findAll(
|
|
14
|
-
null, // business date (null = not applicable)
|
|
15
|
-
new Date(), // processing valid-at (temporal snapshot)
|
|
16
|
-
[tf.symbol(), tf.price(), tf.account().name()],
|
|
17
|
-
tf.symbol().eq('AAPL'),
|
|
18
|
-
).toRows();
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Temporal filtering (`in_z <= ? AND out_z > ?`) is injected automatically based on the milestoning type declared in the mapping.
|
|
22
|
-
|
|
23
|
-
## Setup
|
|
12
|
+
## Install
|
|
24
13
|
|
|
25
14
|
```bash
|
|
26
15
|
npm install
|
|
27
|
-
|
|
28
|
-
# Install Python generator dependencies (system-wide, no virtualenv)
|
|
29
|
-
pip3 install jinja2 markdown-it-py
|
|
16
|
+
uv sync # install Python generator dependencies
|
|
30
17
|
```
|
|
31
18
|
|
|
32
|
-
Node ≥ 20 required.
|
|
33
|
-
|
|
34
19
|
## Generating finders
|
|
35
20
|
|
|
36
|
-
Generated files are gitignored — regenerate
|
|
21
|
+
Generated files are gitignored — regenerate before running tests on a fresh clone.
|
|
37
22
|
|
|
38
23
|
```bash
|
|
39
|
-
#
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
# From a markdown mapping file (finance_mapping.md in sibling data-finder repo)
|
|
43
|
-
python3 example/generate_from_markdown.py # → tests/generated_markdown/
|
|
24
|
+
npm run generate # from programmatic mappings (example/mappings.py) → example/generated/
|
|
25
|
+
npm run generate:examples # from all datafinder_examples mappings → tests/generated_examples/
|
|
44
26
|
```
|
|
45
27
|
|
|
46
|
-
The
|
|
28
|
+
The generator uses the [`data-finder`](https://pypi.org/project/data-finder/) PyPI package (installed via `uv sync`).
|
|
47
29
|
|
|
48
30
|
## Running tests
|
|
49
31
|
|
|
50
32
|
```bash
|
|
51
|
-
npm test
|
|
52
|
-
npx vitest run tests/duckdb.test.ts
|
|
53
|
-
npm run build
|
|
33
|
+
npm test # all tests
|
|
34
|
+
npx vitest run tests/duckdb.test.ts # single file
|
|
35
|
+
npm run build # type-check only
|
|
36
|
+
npm run build:lib # build distributable (tsup)
|
|
54
37
|
```
|
|
55
38
|
|
|
56
|
-
Tests use an in-memory DuckDB instance via `@duckdb/node-api`.
|
|
57
|
-
|
|
58
|
-
## Milestoning types
|
|
59
|
-
|
|
60
|
-
| Type | Mapping class | `findAll` args used |
|
|
61
|
-
|---|---|---|
|
|
62
|
-
| None | — | neither |
|
|
63
|
-
| Processing temporal | `ProcessingDateMilestonesPropertyMapping` | `processingValidAt` |
|
|
64
|
-
| Single business date | `SingleBusinessDateMilestonePropertyMapping` | `businessDate` |
|
|
65
|
-
| Business date + processing | `BusinessDateAndProcessingMilestonePropertyMapping` | both |
|
|
66
|
-
| Bi-temporal | `BiTemporalMilestonePropertyMapping` | both |
|
|
39
|
+
Tests use an in-memory DuckDB instance via `@duckdb/node-api`.
|
|
67
40
|
|
|
68
41
|
## Defining a mapping (Markdown)
|
|
69
42
|
|
|
@@ -98,20 +71,9 @@ Tests use an in-memory DuckDB instance via `@duckdb/node-api`. `tests/duckdb.tes
|
|
|
98
71
|
Load and generate:
|
|
99
72
|
|
|
100
73
|
```python
|
|
101
|
-
from
|
|
74
|
+
from datafinder_examples.finance_mapping import load
|
|
102
75
|
from ts_generator.generator import generate
|
|
103
76
|
|
|
104
77
|
mapping = load('my_mapping.md')
|
|
105
78
|
generate(mapping, 'output/')
|
|
106
79
|
```
|
|
107
|
-
|
|
108
|
-
## Reverse associations
|
|
109
|
-
|
|
110
|
-
When a model association is declared (e.g. `Trade → Account`), the generator adds a `trades()` method on `AccountFinder` pointing back to `TradeRelatedFinder`. Because ESM circular imports can't be resolved with static `import`, finders self-register at module load via `registerRelatedFinderClass`. When using a reverse association in tests, import the source finder's module first:
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
await import('./generated/TradeFinder'); // ensures TradeRelatedFinder is registered
|
|
114
|
-
const { AccountFinder } = await import('./generated/AccountFinder');
|
|
115
|
-
const af = new AccountFinder();
|
|
116
|
-
const rows = await af.findAll(null, null, [af.name(), af.trades().symbol()]).toRows();
|
|
117
|
-
```
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AggregateOperation,
|
|
3
|
+
Column,
|
|
4
|
+
ColumnWithJoin,
|
|
5
|
+
IsNotNullOperation,
|
|
6
|
+
IsNullOperation,
|
|
7
|
+
SortOperation,
|
|
8
|
+
WindowFunctionOperation,
|
|
9
|
+
WindowSpecification
|
|
10
|
+
} from "./chunk-UYMOE6YU.js";
|
|
11
|
+
|
|
12
|
+
// src/datafinder/attribute.ts
|
|
13
|
+
var Attribute = class _Attribute {
|
|
14
|
+
_displayName;
|
|
15
|
+
_column;
|
|
16
|
+
_owner;
|
|
17
|
+
_parent;
|
|
18
|
+
_embedded;
|
|
19
|
+
constructor(displayName, columnName, columnDbType, owner, parent, embedded) {
|
|
20
|
+
this._displayName = displayName;
|
|
21
|
+
this._column = new Column(columnName, columnDbType, owner);
|
|
22
|
+
this._owner = owner;
|
|
23
|
+
this._parent = parent;
|
|
24
|
+
this._embedded = embedded;
|
|
25
|
+
}
|
|
26
|
+
column() {
|
|
27
|
+
return this._column;
|
|
28
|
+
}
|
|
29
|
+
owner() {
|
|
30
|
+
return this._owner;
|
|
31
|
+
}
|
|
32
|
+
parent() {
|
|
33
|
+
return this._parent;
|
|
34
|
+
}
|
|
35
|
+
displayName() {
|
|
36
|
+
return this._displayName;
|
|
37
|
+
}
|
|
38
|
+
/** Alternate attribute on a flat column of the owning table, used in place of this one when its join is elided. */
|
|
39
|
+
embedded() {
|
|
40
|
+
return this._embedded;
|
|
41
|
+
}
|
|
42
|
+
cwj() {
|
|
43
|
+
return new ColumnWithJoin(this._column, this._parent, this._embedded?.cwj());
|
|
44
|
+
}
|
|
45
|
+
/** Count the number of non-null values. Use in a projection with `groupByOp` to aggregate per group. */
|
|
46
|
+
count() {
|
|
47
|
+
return new AggregateOperation(
|
|
48
|
+
this.cwj(),
|
|
49
|
+
"COUNT" /* COUNT */,
|
|
50
|
+
this._displayName + " Count"
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
/** Sort this attribute in ascending order. Pass to `orderByOp` or a window function's `orderBy`. */
|
|
54
|
+
ascending() {
|
|
55
|
+
return new SortOperation(this.cwj(), "ASC" /* ASC */);
|
|
56
|
+
}
|
|
57
|
+
/** Sort this attribute in descending order. Pass to `orderByOp` or a window function's `orderBy`. */
|
|
58
|
+
descending() {
|
|
59
|
+
return new SortOperation(this.cwj(), "DESC" /* DESC */);
|
|
60
|
+
}
|
|
61
|
+
/** Filter to rows where this attribute has no value. */
|
|
62
|
+
isNull() {
|
|
63
|
+
return new IsNullOperation(this.cwj());
|
|
64
|
+
}
|
|
65
|
+
/** Filter to rows where this attribute has a value. */
|
|
66
|
+
isNotNull() {
|
|
67
|
+
return new IsNotNullOperation(this.cwj());
|
|
68
|
+
}
|
|
69
|
+
_windowSpec(partitionBy, orderBy) {
|
|
70
|
+
const pbArr = partitionBy === void 0 ? [] : Array.isArray(partitionBy) ? partitionBy : [partitionBy];
|
|
71
|
+
const pb = pbArr.map((x) => x instanceof _Attribute ? x.cwj() : x);
|
|
72
|
+
const ob = orderBy === void 0 ? [] : Array.isArray(orderBy) ? orderBy : [orderBy];
|
|
73
|
+
return new WindowSpecification(pb, ob);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Assign a rank to each row within the ordered window, following pandas `Series.rank` conventions.
|
|
77
|
+
*
|
|
78
|
+
* `method` controls tie-breaking (default `'min'`):
|
|
79
|
+
* - `'min'` — tied rows share the lowest rank; the next rank skips.
|
|
80
|
+
* - `'dense'` — like `'min'` but ranks are contiguous (no gaps).
|
|
81
|
+
* - `'first'` — each row gets a unique sequential integer (no ties).
|
|
82
|
+
* - `'max'` — only meaningful with `pct: true` (see below).
|
|
83
|
+
*
|
|
84
|
+
* When `pct: true` the result is a relative rank between 0 and 1:
|
|
85
|
+
* - `method: 'min'` (default) → fraction of values strictly below this row (PERCENT_RANK).
|
|
86
|
+
* - `method: 'max'` → fraction of values at or below this row (cumulative distribution).
|
|
87
|
+
*
|
|
88
|
+
* `partitionBy` restarts the ranking within each group of distinct values.
|
|
89
|
+
*/
|
|
90
|
+
rank(opts = {}) {
|
|
91
|
+
const { method = "min", pct = false, partitionBy, orderBy } = opts;
|
|
92
|
+
let func;
|
|
93
|
+
let name;
|
|
94
|
+
if (pct) {
|
|
95
|
+
if (method === "max") {
|
|
96
|
+
func = "CUME_DIST" /* CUME_DIST */;
|
|
97
|
+
name = "Cume Dist";
|
|
98
|
+
} else {
|
|
99
|
+
func = "PERCENT_RANK" /* PERCENT_RANK */;
|
|
100
|
+
name = "Percent Rank";
|
|
101
|
+
}
|
|
102
|
+
} else if (method === "first") {
|
|
103
|
+
func = "ROW_NUMBER" /* ROW_NUMBER */;
|
|
104
|
+
name = "Row Number";
|
|
105
|
+
} else if (method === "dense") {
|
|
106
|
+
func = "DENSE_RANK" /* DENSE_RANK */;
|
|
107
|
+
name = "Dense Rank";
|
|
108
|
+
} else {
|
|
109
|
+
func = "RANK" /* RANK */;
|
|
110
|
+
name = "Rank";
|
|
111
|
+
}
|
|
112
|
+
return new WindowFunctionOperation(null, func, name, void 0, [], this._windowSpec(partitionBy, orderBy));
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Split rows into `buckets` equal-sized quantile bins ordered by `orderBy`.
|
|
116
|
+
* Each row receives a bucket number from 1 (lowest) to `buckets` (highest).
|
|
117
|
+
* Named after `pandas.qcut`.
|
|
118
|
+
*/
|
|
119
|
+
qcut(buckets, opts = {}) {
|
|
120
|
+
return new WindowFunctionOperation(
|
|
121
|
+
null,
|
|
122
|
+
"NTILE" /* NTILE */,
|
|
123
|
+
"Quantile",
|
|
124
|
+
buckets,
|
|
125
|
+
[],
|
|
126
|
+
this._windowSpec(opts.partitionBy, opts.orderBy)
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Return the value of this attribute from `periods` rows earlier (positive) or later (negative)
|
|
131
|
+
* within the ordered window, following `pandas.Series.shift`.
|
|
132
|
+
* Rows with no neighbour at the given offset return `null` (or `fillValue` if provided).
|
|
133
|
+
*/
|
|
134
|
+
shift(periods = 1, opts = {}) {
|
|
135
|
+
const extraArgs = opts.fillValue !== void 0 ? [opts.fillValue] : [];
|
|
136
|
+
const func = periods >= 0 ? "LAG" /* LAG */ : "LEAD" /* LEAD */;
|
|
137
|
+
const label = periods >= 0 ? "Lag" : "Lead";
|
|
138
|
+
return new WindowFunctionOperation(
|
|
139
|
+
this.cwj(),
|
|
140
|
+
func,
|
|
141
|
+
label + " " + this._displayName,
|
|
142
|
+
Math.abs(periods),
|
|
143
|
+
extraArgs,
|
|
144
|
+
this._windowSpec(opts.partitionBy, opts.orderBy)
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Return the first value of this attribute in the window frame.
|
|
149
|
+
* Use `partitionBy` to restart the frame for each group.
|
|
150
|
+
*/
|
|
151
|
+
first(opts = {}) {
|
|
152
|
+
return new WindowFunctionOperation(
|
|
153
|
+
this.cwj(),
|
|
154
|
+
"FIRST_VALUE" /* FIRST_VALUE */,
|
|
155
|
+
"First " + this._displayName,
|
|
156
|
+
void 0,
|
|
157
|
+
[],
|
|
158
|
+
this._windowSpec(opts.partitionBy, opts.orderBy)
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Return the last value of this attribute in the window frame.
|
|
163
|
+
* Use `partitionBy` to restart the frame for each group.
|
|
164
|
+
*/
|
|
165
|
+
last(opts = {}) {
|
|
166
|
+
return new WindowFunctionOperation(
|
|
167
|
+
this.cwj(),
|
|
168
|
+
"LAST_VALUE" /* LAST_VALUE */,
|
|
169
|
+
"Last " + this._displayName,
|
|
170
|
+
void 0,
|
|
171
|
+
[],
|
|
172
|
+
this._windowSpec(opts.partitionBy, opts.orderBy)
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
export {
|
|
178
|
+
Attribute
|
|
179
|
+
};
|
|
180
|
+
//# sourceMappingURL=chunk-4JVW4TAB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/datafinder/attribute.ts"],"sourcesContent":["import {\n Column,\n AggregateOperation,\n AggregateOperator,\n ColumnWithJoin,\n SortOperation,\n SortDirection,\n IsNullOperation,\n IsNotNullOperation,\n JoinTreeNodeOperation,\n WindowFunction,\n WindowFunctionOperation,\n WindowSpecification,\n} from '../model/relational';\n\nexport abstract class Attribute {\n private readonly _displayName: string;\n private readonly _column: Column;\n private readonly _owner: string;\n private readonly _parent?: JoinTreeNodeOperation;\n private readonly _embedded?: Attribute;\n\n constructor(\n displayName: string,\n columnName: string,\n columnDbType: string,\n owner: string,\n parent?: JoinTreeNodeOperation,\n embedded?: Attribute,\n ) {\n this._displayName = displayName;\n this._column = new Column(columnName, columnDbType, owner);\n this._owner = owner;\n this._parent = parent;\n this._embedded = embedded;\n }\n\n column(): Column { return this._column; }\n owner(): string { return this._owner; }\n parent(): JoinTreeNodeOperation | undefined { return this._parent; }\n displayName(): string { return this._displayName; }\n\n /** Alternate attribute on a flat column of the owning table, used in place of this one when its join is elided. */\n embedded(): Attribute | undefined { return this._embedded; }\n\n cwj(): ColumnWithJoin {\n return new ColumnWithJoin(this._column, this._parent, this._embedded?.cwj());\n }\n\n /** Count the number of non-null values. Use in a projection with `groupByOp` to aggregate per group. */\n count(): AggregateOperation {\n return new AggregateOperation(\n this.cwj(),\n AggregateOperator.COUNT,\n this._displayName + ' Count',\n );\n }\n\n /** Sort this attribute in ascending order. Pass to `orderByOp` or a window function's `orderBy`. */\n ascending(): SortOperation {\n return new SortOperation(this.cwj(), SortDirection.ASC);\n }\n\n /** Sort this attribute in descending order. Pass to `orderByOp` or a window function's `orderBy`. */\n descending(): SortOperation {\n return new SortOperation(this.cwj(), SortDirection.DESC);\n }\n\n /** Filter to rows where this attribute has no value. */\n isNull(): IsNullOperation {\n return new IsNullOperation(this.cwj());\n }\n\n /** Filter to rows where this attribute has a value. */\n isNotNull(): IsNotNullOperation {\n return new IsNotNullOperation(this.cwj());\n }\n\n private _windowSpec(\n partitionBy?: Attribute | ColumnWithJoin | (Attribute | ColumnWithJoin)[],\n orderBy?: SortOperation | SortOperation[],\n ): WindowSpecification {\n const pbArr = partitionBy === undefined ? [] : Array.isArray(partitionBy) ? partitionBy : [partitionBy];\n const pb = pbArr.map(x => x instanceof Attribute ? x.cwj() : x);\n const ob = orderBy === undefined ? [] : Array.isArray(orderBy) ? orderBy : [orderBy];\n return new WindowSpecification(pb, ob);\n }\n\n /**\n * Assign a rank to each row within the ordered window, following pandas `Series.rank` conventions.\n *\n * `method` controls tie-breaking (default `'min'`):\n * - `'min'` — tied rows share the lowest rank; the next rank skips.\n * - `'dense'` — like `'min'` but ranks are contiguous (no gaps).\n * - `'first'` — each row gets a unique sequential integer (no ties).\n * - `'max'` — only meaningful with `pct: true` (see below).\n *\n * When `pct: true` the result is a relative rank between 0 and 1:\n * - `method: 'min'` (default) → fraction of values strictly below this row (PERCENT_RANK).\n * - `method: 'max'` → fraction of values at or below this row (cumulative distribution).\n *\n * `partitionBy` restarts the ranking within each group of distinct values.\n */\n rank(opts: {\n method?: 'min' | 'dense' | 'first' | 'max';\n pct?: boolean;\n partitionBy?: Attribute | ColumnWithJoin | (Attribute | ColumnWithJoin)[];\n orderBy?: SortOperation | SortOperation[];\n } = {}): WindowFunctionOperation {\n const { method = 'min', pct = false, partitionBy, orderBy } = opts;\n let func: WindowFunction;\n let name: string;\n if (pct) {\n if (method === 'max') { func = WindowFunction.CUME_DIST; name = 'Cume Dist'; }\n else { func = WindowFunction.PERCENT_RANK; name = 'Percent Rank'; }\n } else if (method === 'first') { func = WindowFunction.ROW_NUMBER; name = 'Row Number'; }\n else if (method === 'dense') { func = WindowFunction.DENSE_RANK; name = 'Dense Rank'; }\n else { func = WindowFunction.RANK; name = 'Rank'; }\n return new WindowFunctionOperation(null, func, name, undefined, [], this._windowSpec(partitionBy, orderBy));\n }\n\n /**\n * Split rows into `buckets` equal-sized quantile bins ordered by `orderBy`.\n * Each row receives a bucket number from 1 (lowest) to `buckets` (highest).\n * Named after `pandas.qcut`.\n */\n qcut(buckets: number, opts: {\n partitionBy?: Attribute | ColumnWithJoin | (Attribute | ColumnWithJoin)[];\n orderBy?: SortOperation | SortOperation[];\n } = {}): WindowFunctionOperation {\n return new WindowFunctionOperation(null, WindowFunction.NTILE, 'Quantile', buckets, [],\n this._windowSpec(opts.partitionBy, opts.orderBy));\n }\n\n /**\n * Return the value of this attribute from `periods` rows earlier (positive) or later (negative)\n * within the ordered window, following `pandas.Series.shift`.\n * Rows with no neighbour at the given offset return `null` (or `fillValue` if provided).\n */\n shift(periods = 1, opts: {\n fillValue?: string | number;\n partitionBy?: Attribute | ColumnWithJoin | (Attribute | ColumnWithJoin)[];\n orderBy?: SortOperation | SortOperation[];\n } = {}): WindowFunctionOperation {\n const extraArgs: (string | number)[] = opts.fillValue !== undefined ? [opts.fillValue] : [];\n const func = periods >= 0 ? WindowFunction.LAG : WindowFunction.LEAD;\n const label = periods >= 0 ? 'Lag' : 'Lead';\n return new WindowFunctionOperation(\n this.cwj(),\n func,\n label + ' ' + this._displayName,\n Math.abs(periods),\n extraArgs,\n this._windowSpec(opts.partitionBy, opts.orderBy),\n );\n }\n\n /**\n * Return the first value of this attribute in the window frame.\n * Use `partitionBy` to restart the frame for each group.\n */\n first(opts: {\n partitionBy?: Attribute | ColumnWithJoin | (Attribute | ColumnWithJoin)[];\n orderBy?: SortOperation | SortOperation[];\n } = {}): WindowFunctionOperation {\n return new WindowFunctionOperation(\n this.cwj(),\n WindowFunction.FIRST_VALUE,\n 'First ' + this._displayName,\n undefined, [],\n this._windowSpec(opts.partitionBy, opts.orderBy),\n );\n }\n\n /**\n * Return the last value of this attribute in the window frame.\n * Use `partitionBy` to restart the frame for each group.\n */\n last(opts: {\n partitionBy?: Attribute | ColumnWithJoin | (Attribute | ColumnWithJoin)[];\n orderBy?: SortOperation | SortOperation[];\n } = {}): WindowFunctionOperation {\n return new WindowFunctionOperation(\n this.cwj(),\n WindowFunction.LAST_VALUE,\n 'Last ' + this._displayName,\n undefined, [],\n this._windowSpec(opts.partitionBy, opts.orderBy),\n );\n }\n}\n"],"mappings":"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","names":[]}
|