@prisma-next/sql-orm-lane 0.3.0-pr.95.1 → 0.3.0-pr.98.1

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.
@@ -4,22 +4,21 @@ import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
4
4
  import type {
5
5
  BinaryExpr,
6
6
  ExistsExpr,
7
- Expression,
8
7
  LoweredStatement,
8
+ OperationExpr,
9
9
  SelectAst,
10
10
  TableRef,
11
11
  } from '@prisma-next/sql-relational-core/ast';
12
12
  import { compact } from '@prisma-next/sql-relational-core/ast';
13
13
  import type {
14
- AnyExpressionSource,
14
+ AnyColumnBuilder,
15
15
  AnyOrderBuilder,
16
16
  BinaryBuilder,
17
17
  } from '@prisma-next/sql-relational-core/types';
18
18
  import {
19
19
  collectColumnRefs,
20
+ getColumnInfo,
20
21
  getColumnMeta,
21
- isColumnBuilder,
22
- isExpressionBuilder,
23
22
  isOperationExpr,
24
23
  } from '@prisma-next/sql-relational-core/utils/guards';
25
24
  import type { IncludeState } from '../relations/include-plan';
@@ -36,66 +35,29 @@ export interface MetaBuildArgs {
36
35
  readonly paramCodecs?: Record<string, string>;
37
36
  }
38
37
 
39
- /**
40
- * Extracts column references from an ExpressionSource (ColumnBuilder or ExpressionBuilder).
41
- * Skips entries with empty table or column names (e.g., placeholder columns for includes).
42
- */
43
- function collectRefsFromExpressionSource(
44
- source: AnyExpressionSource,
45
- refsColumns: Map<string, { table: string; column: string }>,
46
- ): void {
47
- if (isExpressionBuilder(source)) {
48
- const allRefs = collectColumnRefs(source.expr);
49
- for (const ref of allRefs) {
50
- // Skip empty table/column (placeholders for includes)
51
- if (ref.table && ref.column) {
38
+ export function buildMeta(args: MetaBuildArgs): PlanMeta {
39
+ const refsColumns = new Map<string, { table: string; column: string }>();
40
+ const refsTables = new Set<string>([args.table.name]);
41
+
42
+ for (const column of args.projection.columns) {
43
+ const operationExpr = (column as { _operationExpr?: OperationExpr })._operationExpr;
44
+ if (operationExpr) {
45
+ const allRefs = collectColumnRefs(operationExpr);
46
+ for (const ref of allRefs) {
52
47
  refsColumns.set(`${ref.table}.${ref.column}`, {
53
48
  table: ref.table,
54
49
  column: ref.column,
55
50
  });
56
51
  }
52
+ } else {
53
+ const col = column as unknown as { table?: string; column?: string };
54
+ if (col.table && col.column) {
55
+ refsColumns.set(`${col.table}.${col.column}`, {
56
+ table: col.table,
57
+ column: col.column,
58
+ });
59
+ }
57
60
  }
58
- } else if (isColumnBuilder(source)) {
59
- const col = source as unknown as { table: string; column: string };
60
- // Skip empty table/column (placeholders for includes)
61
- if (col.table && col.column) {
62
- refsColumns.set(`${col.table}.${col.column}`, {
63
- table: col.table,
64
- column: col.column,
65
- });
66
- }
67
- }
68
- }
69
-
70
- /**
71
- * Extracts column references from an Expression (AST node).
72
- */
73
- function collectRefsFromExpression(
74
- expr: Expression,
75
- refsColumns: Map<string, { table: string; column: string }>,
76
- ): void {
77
- if (isOperationExpr(expr)) {
78
- const allRefs = collectColumnRefs(expr);
79
- for (const ref of allRefs) {
80
- refsColumns.set(`${ref.table}.${ref.column}`, {
81
- table: ref.table,
82
- column: ref.column,
83
- });
84
- }
85
- } else if (expr.kind === 'col') {
86
- refsColumns.set(`${expr.table}.${expr.column}`, {
87
- table: expr.table,
88
- column: expr.column,
89
- });
90
- }
91
- }
92
-
93
- export function buildMeta(args: MetaBuildArgs): PlanMeta {
94
- const refsColumns = new Map<string, { table: string; column: string }>();
95
- const refsTables = new Set<string>([args.table.name]);
96
-
97
- for (const column of args.projection.columns) {
98
- collectRefsFromExpressionSource(column, refsColumns);
99
61
  }
100
62
 
101
63
  if (args.includes) {
@@ -123,21 +85,32 @@ export function buildMeta(args: MetaBuildArgs): PlanMeta {
123
85
  }
124
86
  }
125
87
  if (include.childWhere) {
126
- // childWhere.left is Expression (already converted at builder creation time)
127
- collectRefsFromExpression(include.childWhere.left, refsColumns);
88
+ const colInfo = getColumnInfo(include.childWhere.left);
89
+ refsColumns.set(`${colInfo.table}.${colInfo.column}`, {
90
+ table: colInfo.table,
91
+ column: colInfo.column,
92
+ });
128
93
  }
129
94
  if (include.childOrderBy) {
130
- // childOrderBy.expr is Expression (already converted at builder creation time)
131
- collectRefsFromExpression(include.childOrderBy.expr, refsColumns);
95
+ const orderBy = include.childOrderBy as unknown as {
96
+ expr?: AnyColumnBuilder | OperationExpr;
97
+ };
98
+ if (orderBy.expr) {
99
+ const colInfo = getColumnInfo(orderBy.expr);
100
+ refsColumns.set(`${colInfo.table}.${colInfo.column}`, {
101
+ table: colInfo.table,
102
+ column: colInfo.column,
103
+ });
104
+ }
132
105
  }
133
106
  }
134
107
  }
135
108
 
136
109
  if (args.where) {
137
- // args.where.left is Expression (already converted at builder creation time)
138
- const leftExpr: Expression = args.where.left;
139
- if (isOperationExpr(leftExpr)) {
140
- const allRefs = collectColumnRefs(leftExpr);
110
+ const whereLeft = args.where.left;
111
+ const operationExpr = (whereLeft as { _operationExpr?: OperationExpr })._operationExpr;
112
+ if (operationExpr) {
113
+ const allRefs = collectColumnRefs(operationExpr);
141
114
  for (const ref of allRefs) {
142
115
  refsColumns.set(`${ref.table}.${ref.column}`, {
143
116
  table: ref.table,
@@ -145,31 +118,39 @@ export function buildMeta(args: MetaBuildArgs): PlanMeta {
145
118
  });
146
119
  }
147
120
  } else {
148
- // leftExpr is ColumnRef
149
- refsColumns.set(`${leftExpr.table}.${leftExpr.column}`, {
150
- table: leftExpr.table,
151
- column: leftExpr.column,
152
- });
121
+ const colBuilder = whereLeft as unknown as { table?: string; column?: string };
122
+ if (colBuilder.table && colBuilder.column) {
123
+ refsColumns.set(`${colBuilder.table}.${colBuilder.column}`, {
124
+ table: colBuilder.table,
125
+ column: colBuilder.column,
126
+ });
127
+ }
153
128
  }
154
129
  }
155
130
 
156
131
  if (args.orderBy) {
157
- // args.orderBy.expr is Expression (already converted at builder creation time)
158
- const orderByExpr: Expression = args.orderBy.expr;
159
- if (isOperationExpr(orderByExpr)) {
160
- const allRefs = collectColumnRefs(orderByExpr);
161
- for (const ref of allRefs) {
162
- refsColumns.set(`${ref.table}.${ref.column}`, {
163
- table: ref.table,
164
- column: ref.column,
165
- });
132
+ const orderBy = args.orderBy as unknown as {
133
+ expr?: AnyColumnBuilder | OperationExpr;
134
+ };
135
+ const orderByExpr = orderBy.expr;
136
+ if (orderByExpr) {
137
+ if (isOperationExpr(orderByExpr)) {
138
+ const allRefs = collectColumnRefs(orderByExpr);
139
+ for (const ref of allRefs) {
140
+ refsColumns.set(`${ref.table}.${ref.column}`, {
141
+ table: ref.table,
142
+ column: ref.column,
143
+ });
144
+ }
145
+ } else {
146
+ const colBuilder = orderByExpr as unknown as { table?: string; column?: string };
147
+ if (colBuilder.table && colBuilder.column) {
148
+ refsColumns.set(`${colBuilder.table}.${colBuilder.column}`, {
149
+ table: colBuilder.table,
150
+ column: colBuilder.column,
151
+ });
152
+ }
166
153
  }
167
- } else {
168
- // orderByExpr is ColumnRef
169
- refsColumns.set(`${orderByExpr.table}.${orderByExpr.column}`, {
170
- table: orderByExpr.table,
171
- column: orderByExpr.column,
172
- });
173
154
  }
174
155
  }
175
156
 
@@ -183,14 +164,18 @@ export function buildMeta(args: MetaBuildArgs): PlanMeta {
183
164
  if (!column) {
184
165
  throw planInvalid(`Missing column for alias ${alias} at index ${index}`);
185
166
  }
186
- if (isExpressionBuilder(column)) {
187
- return [alias, `operation:${column.expr.method}`];
188
- }
189
- // column is ColumnBuilder
190
- const col = column as unknown as { table?: string; column?: string };
167
+ const col = column as unknown as {
168
+ table?: string;
169
+ column?: string;
170
+ _operationExpr?: OperationExpr;
171
+ };
191
172
  if (!col.table || !col.column) {
192
173
  return [alias, `include:${alias}`];
193
174
  }
175
+ const operationExpr = col._operationExpr;
176
+ if (operationExpr) {
177
+ return [alias, `operation:${operationExpr.method}`];
178
+ }
194
179
  return [alias, `${col.table}.${col.column}`];
195
180
  }),
196
181
  );
@@ -205,8 +190,8 @@ export function buildMeta(args: MetaBuildArgs): PlanMeta {
205
190
  if (!col) {
206
191
  continue;
207
192
  }
208
- if (isExpressionBuilder(col)) {
209
- const operationExpr = col.expr;
193
+ const operationExpr = (col as { _operationExpr?: OperationExpr })._operationExpr;
194
+ if (operationExpr) {
210
195
  if (operationExpr.returns.kind === 'typeId') {
211
196
  projectionTypes[alias] = operationExpr.returns.type;
212
197
  } else if (operationExpr.returns.kind === 'builtin') {
@@ -231,8 +216,8 @@ export function buildMeta(args: MetaBuildArgs): PlanMeta {
231
216
  if (!column) {
232
217
  continue;
233
218
  }
234
- if (isExpressionBuilder(column)) {
235
- const operationExpr = column.expr;
219
+ const operationExpr = (column as { _operationExpr?: OperationExpr })._operationExpr;
220
+ if (operationExpr) {
236
221
  if (operationExpr.returns.kind === 'typeId') {
237
222
  projectionCodecs[alias] = operationExpr.returns.type;
238
223
  }
@@ -19,7 +19,6 @@ import type {
19
19
  BuildOptions,
20
20
  NestedProjection,
21
21
  } from '@prisma-next/sql-relational-core/types';
22
- import { isExpressionBuilder } from '@prisma-next/sql-relational-core/utils/guards';
23
22
  import { checkIncludeCapabilities } from '../orm/capabilities';
24
23
  import type { OrmIncludeState, RelationFilter } from '../orm/state';
25
24
  import { buildJoinOnExpr } from '../selection/join';
@@ -176,11 +175,12 @@ export function buildIncludeAsts(input: BuildIncludeAstsInput): {
176
175
  if (!column) {
177
176
  errorMissingColumn(alias, i);
178
177
  }
179
- if (isExpressionBuilder(column)) {
180
- childProjectionItems.push({ alias, expr: column.expr });
178
+ const operationExpr = (column as { _operationExpr?: OperationExpr })._operationExpr;
179
+ if (operationExpr) {
180
+ childProjectionItems.push({ alias, expr: operationExpr });
181
181
  } else {
182
- // ColumnBuilder - use toExpr() to get ColumnRef
183
- childProjectionItems.push({ alias, expr: column.toExpr() });
182
+ const col = column as { table: string; column: string };
183
+ childProjectionItems.push({ alias, expr: createColumnRef(col.table, col.column) });
184
184
  }
185
185
  }
186
186
 
@@ -1,14 +1,21 @@
1
1
  import type { ParamDescriptor } from '@prisma-next/contract/types';
2
2
  import type { SqlContract, SqlStorage, StorageColumn } from '@prisma-next/sql-contract/types';
3
- import type { BinaryExpr, Expression, ParamRef } from '@prisma-next/sql-relational-core/ast';
3
+ import type {
4
+ BinaryExpr,
5
+ ColumnRef,
6
+ OperationExpr,
7
+ ParamRef,
8
+ } from '@prisma-next/sql-relational-core/ast';
4
9
  import { augmentDescriptorWithColumnMeta } from '@prisma-next/sql-relational-core/plan';
5
10
  import type { BinaryBuilder, ParamPlaceholder } from '@prisma-next/sql-relational-core/types';
6
11
  import {
12
+ getColumnInfo,
13
+ getColumnMeta,
14
+ getOperationExpr,
7
15
  isColumnBuilder,
8
- isExpressionBuilder,
9
16
  isParamPlaceholder,
10
17
  } from '@prisma-next/sql-relational-core/utils/guards';
11
- import { createBinaryExpr, createParamRef } from '../utils/ast';
18
+ import { createBinaryExpr, createColumnRef, createParamRef } from '../utils/ast';
12
19
  import {
13
20
  errorFailedToBuildWhereClause,
14
21
  errorMissingParameter,
@@ -26,17 +33,16 @@ export function buildWhereExpr(
26
33
  codecId?: string;
27
34
  paramName: string;
28
35
  } {
29
- let leftExpr: Expression;
36
+ let leftExpr: ColumnRef | OperationExpr;
30
37
  let codecId: string | undefined;
31
- let rightExpr: Expression | ParamRef;
38
+ let rightExpr: ColumnRef | ParamRef;
32
39
  let paramName: string;
33
40
 
34
- // where.left is now an Expression (ColumnRef or OperationExpr)
35
- leftExpr = where.left;
36
-
37
- // If leftExpr is a ColumnRef, extract codecId from contract
38
- if (leftExpr.kind === 'col') {
39
- const { table, column } = leftExpr;
41
+ const operationExpr = getOperationExpr(where.left);
42
+ if (operationExpr) {
43
+ leftExpr = operationExpr;
44
+ } else if (isColumnBuilder(where.left)) {
45
+ const { table, column } = getColumnInfo(where.left);
40
46
 
41
47
  const contractTable = contract.storage.tables[table];
42
48
  if (!contractTable) {
@@ -49,9 +55,12 @@ export function buildWhereExpr(
49
55
  if (columnMeta) {
50
56
  codecId = columnMeta.codecId;
51
57
  }
58
+ leftExpr = createColumnRef(table, column);
59
+ } else {
60
+ errorFailedToBuildWhereClause();
52
61
  }
53
62
 
54
- // Handle where.right - can be ParamPlaceholder or AnyExpressionSource
63
+ // Handle where.right - can be ParamPlaceholder or AnyColumnBuilder
55
64
  if (isParamPlaceholder(where.right)) {
56
65
  // Handle param placeholder (existing logic)
57
66
  const placeholder: ParamPlaceholder = where.right;
@@ -64,35 +73,42 @@ export function buildWhereExpr(
64
73
  const value = paramsMap[paramName];
65
74
  const index = values.push(value);
66
75
 
67
- // Construct descriptor from where.left Expression
68
- // For ColumnRef, we can extract table/column directly
69
- // For OperationExpr, we extract the base column reference
70
- if (leftExpr.kind === 'col') {
71
- const { table, column } = leftExpr;
76
+ // Construct descriptor if where.left is a ColumnBuilder
77
+ if (isColumnBuilder(where.left)) {
78
+ const { table, column } = getColumnInfo(where.left);
72
79
  const contractTable = contract.storage.tables[table];
73
80
  const columnMeta = contractTable?.columns[column];
81
+ const builderColumnMeta = getColumnMeta(where.left);
74
82
 
75
83
  descriptors.push({
76
84
  name: paramName,
77
85
  source: 'dsl',
78
86
  refs: { table, column },
79
- ...(columnMeta && typeof columnMeta.nullable === 'boolean'
80
- ? { nullable: columnMeta.nullable }
87
+ ...(typeof builderColumnMeta?.nullable === 'boolean'
88
+ ? { nullable: builderColumnMeta.nullable }
81
89
  : {}),
82
90
  });
83
91
 
84
92
  augmentDescriptorWithColumnMeta(descriptors, columnMeta);
85
93
  }
86
- // For OperationExpr, we don't create descriptors since we can't reliably extract column info
87
94
 
88
95
  rightExpr = createParamRef(index, paramName);
89
- } else if (isColumnBuilder(where.right) || isExpressionBuilder(where.right)) {
90
- // Handle ExpressionSource on the right - use toExpr() to get the Expression
91
- rightExpr = where.right.toExpr();
92
- // Use a placeholder paramName for expression references (not used for params)
96
+ } else if (isColumnBuilder(where.right)) {
97
+ // Handle column builder on the right
98
+ const { table, column } = getColumnInfo(where.right);
99
+
100
+ const contractTable = contract.storage.tables[table];
101
+ if (!contractTable) {
102
+ errorUnknownTable(table);
103
+ }
104
+
105
+ // If column not found in contract, still build expression
106
+ // This allows flexibility when columnMeta is available on the column builder
107
+ rightExpr = createColumnRef(table, column);
108
+ // Use a placeholder paramName for column references (not used for params)
93
109
  paramName = '';
94
110
  } else {
95
- // where.right is neither ParamPlaceholder nor ExpressionSource - invalid state
111
+ // where.right is neither ParamPlaceholder nor ColumnBuilder - invalid state
96
112
  errorFailedToBuildWhereClause();
97
113
  }
98
114
 
@@ -1,15 +1,12 @@
1
1
  import type { TableRef } from '@prisma-next/sql-relational-core/ast';
2
2
  import type {
3
3
  AnyBinaryBuilder,
4
- AnyExpressionSource,
4
+ AnyColumnBuilder,
5
5
  AnyOrderBuilder,
6
6
  JoinOnPredicate,
7
7
  NestedProjection,
8
8
  } from '@prisma-next/sql-relational-core/types';
9
- import {
10
- isColumnBuilder,
11
- isExpressionBuilder,
12
- } from '@prisma-next/sql-relational-core/utils/guards';
9
+ import { isColumnBuilder } from '@prisma-next/sql-relational-core/utils/guards';
13
10
  import {
14
11
  errorAliasCollision,
15
12
  errorAliasPathEmpty,
@@ -21,10 +18,10 @@ import {
21
18
 
22
19
  export interface ProjectionState {
23
20
  readonly aliases: string[];
24
- readonly columns: AnyExpressionSource[];
21
+ readonly columns: AnyColumnBuilder[];
25
22
  }
26
23
 
27
- export type ProjectionInput = Record<string, AnyExpressionSource | boolean | NestedProjection>;
24
+ export type ProjectionInput = Record<string, AnyColumnBuilder | boolean | NestedProjection>;
28
25
 
29
26
  function generateAlias(path: string[]): string {
30
27
  if (path.length === 0) {
@@ -61,14 +58,14 @@ export function flattenProjection(
61
58
  projection: NestedProjection,
62
59
  tracker: AliasTracker,
63
60
  currentPath: string[] = [],
64
- ): { aliases: string[]; columns: AnyExpressionSource[] } {
61
+ ): { aliases: string[]; columns: AnyColumnBuilder[] } {
65
62
  const aliases: string[] = [];
66
- const columns: AnyExpressionSource[] = [];
63
+ const columns: AnyColumnBuilder[] = [];
67
64
 
68
65
  for (const [key, value] of Object.entries(projection)) {
69
66
  const path = [...currentPath, key];
70
67
 
71
- if (isColumnBuilder(value) || isExpressionBuilder(value)) {
68
+ if (isColumnBuilder(value)) {
72
69
  const alias = tracker.register(path);
73
70
  aliases.push(alias);
74
71
  columns.push(value);
@@ -99,7 +96,7 @@ export function buildProjectionState(
99
96
  ): ProjectionState {
100
97
  const tracker = new AliasTracker();
101
98
  const aliases: string[] = [];
102
- const columns: AnyExpressionSource[] = [];
99
+ const columns: AnyColumnBuilder[] = [];
103
100
 
104
101
  for (const [key, value] of Object.entries(projection)) {
105
102
  if (value === true) {
@@ -117,11 +114,8 @@ export function buildProjectionState(
117
114
  codecId: 'core/json@1',
118
115
  nullable: true,
119
116
  },
120
- toExpr() {
121
- return { kind: 'col', table: matchingInclude.table.name, column: '' };
122
- },
123
- } as AnyExpressionSource);
124
- } else if (isColumnBuilder(value) || isExpressionBuilder(value)) {
117
+ } as AnyColumnBuilder);
118
+ } else if (isColumnBuilder(value)) {
125
119
  const alias = tracker.register([key]);
126
120
  aliases.push(alias);
127
121
  columns.push(value);
@@ -1,24 +1,24 @@
1
1
  import type {
2
2
  BinaryExpr,
3
+ ColumnRef,
3
4
  Direction,
4
5
  ExistsExpr,
5
- Expression,
6
6
  IncludeAst,
7
7
  IncludeRef,
8
+ OperationExpr,
8
9
  SelectAst,
9
10
  TableRef,
10
11
  } from '@prisma-next/sql-relational-core/ast';
11
- import { isExpressionBuilder } from '@prisma-next/sql-relational-core/utils/guards';
12
12
  import type { IncludeState } from '../relations/include-plan';
13
- import { createSelectAst, createTableRef } from '../utils/ast';
13
+ import { createColumnRef, createSelectAst, createTableRef } from '../utils/ast';
14
14
  import { errorInvalidColumn, errorMissingAlias, errorMissingColumn } from '../utils/errors';
15
15
  import type { ProjectionState } from './projection';
16
16
 
17
17
  export function buildProjectionItems(
18
18
  projectionState: ProjectionState,
19
19
  includesForMeta: ReadonlyArray<IncludeState>,
20
- ): Array<{ alias: string; expr: Expression | IncludeRef }> {
21
- const projectEntries: Array<{ alias: string; expr: Expression | IncludeRef }> = [];
20
+ ): Array<{ alias: string; expr: ColumnRef | IncludeRef | OperationExpr }> {
21
+ const projectEntries: Array<{ alias: string; expr: ColumnRef | IncludeRef | OperationExpr }> = [];
22
22
  for (let i = 0; i < projectionState.aliases.length; i++) {
23
23
  const alias = projectionState.aliases[i];
24
24
  if (!alias) {
@@ -35,23 +35,25 @@ export function buildProjectionItems(
35
35
  alias,
36
36
  expr: { kind: 'includeRef', alias },
37
37
  });
38
- } else if (isExpressionBuilder(column)) {
39
- // ExpressionBuilder (operation result) - use its expr
40
- projectEntries.push({
41
- alias,
42
- expr: column.expr,
43
- });
44
38
  } else {
45
- // ColumnBuilder - use toExpr() to get ColumnRef
46
- const expr = column.toExpr();
47
- // Validate the expression has valid table and column values
48
- if (expr.kind === 'col' && (!expr.table || !expr.column)) {
49
- errorInvalidColumn(alias, i);
39
+ const operationExpr = (column as { _operationExpr?: OperationExpr })._operationExpr;
40
+ if (operationExpr) {
41
+ projectEntries.push({
42
+ alias,
43
+ expr: operationExpr,
44
+ });
45
+ } else {
46
+ const col = column as { table: string; column: string };
47
+ const tableName = col.table;
48
+ const columnName = col.column;
49
+ if (!tableName || !columnName) {
50
+ errorInvalidColumn(alias, i);
51
+ }
52
+ projectEntries.push({
53
+ alias,
54
+ expr: createColumnRef(tableName, columnName),
55
+ });
50
56
  }
51
- projectEntries.push({
52
- alias,
53
- expr,
54
- });
55
57
  }
56
58
  }
57
59
  return projectEntries;
@@ -59,11 +61,11 @@ export function buildProjectionItems(
59
61
 
60
62
  export function buildSelectAst(params: {
61
63
  table: TableRef;
62
- projectEntries: Array<{ alias: string; expr: Expression | IncludeRef }>;
64
+ projectEntries: Array<{ alias: string; expr: ColumnRef | IncludeRef | OperationExpr }>;
63
65
  includesAst?: ReadonlyArray<IncludeAst>;
64
66
  whereExpr?: BinaryExpr | ExistsExpr;
65
67
  orderByClause?: ReadonlyArray<{
66
- expr: Expression;
68
+ expr: ColumnRef | OperationExpr;
67
69
  dir: Direction;
68
70
  }>;
69
71
  limit?: number;