@leuduan/block 3.0.0 → 3.1.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.
package/README.md CHANGED
@@ -12,7 +12,10 @@ renderer (`l`, 120 columns by default) and the builders on top of it: `p` (pipes
12
12
  helpers), `q` (queries), `t` (table expressions) and the `sql` tag, with `from` exported at the root. Every function
13
13
  has one name and one home; the namespaces export factories, not the concrete classes behind them. A pipe is applied
14
14
  one way: `pipe(query, p.where(...), ...)`. Pipe syntax is GoogleSQL's, so the result is a `GoogleSqlQuery`; applying
15
- pipes to one extends its own pipe list instead of nesting (reusable steps are a `Pipe[]` to spread into the call).
15
+ pipes to one extends its own pipe list instead of nesting. A step can also be a function from the query built so far
16
+ to the next query, for what `|>` cannot express (the input on the right of a join, inside a subquery, or rewritten);
17
+ later steps apply to what it returns. Reusable steps are a `Pipe[]` to spread into the call, or such a function, with
18
+ any inputs taken as arguments of the function that makes them.
16
19
  Deliberate nesting is `q.googleQuery({ queryExpression, pipes })`. Pipes that take a list take an array. String
17
20
  literals (`e.literalString`, the typed date and time literals) and quoted identifiers (`e.ident`, `t.path(id, true)`)
18
21
  are escaped with GoogleSQL's backslash escapes.
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ export * as q from './query.js';
6
6
  export * as t from './t.js';
7
7
  export type { Line, LineOrStr, Options } from './line.js';
8
8
  export { DEFAULT_OPTIONS } from './line.js';
9
- export type { SqlSegment, Pipe, TableExpression, GoogleSqlQuery } from './sql.js';
9
+ export type { SqlSegment, Pipe, PipeStep, TableExpression, GoogleSqlQuery } from './sql.js';
10
10
  export { QueryExpression, from, pipe, sql } from './sql.js';
11
11
  export { define } from './define.js';
12
12
  export { Dataset, PARAM_TYPES } from './descriptor.js';
package/dist/sql.d.ts CHANGED
@@ -53,12 +53,15 @@ export declare class GoogleSqlQuery extends QueryExpression {
53
53
  constructor({ ctes, queryExpression, orderByLine, limitOffset, pipes }: GoogleSqlQueryProps);
54
54
  toLine(): Line;
55
55
  }
56
+ /** A step of `pipe`: a `|>` operator, or a function from the query built so far to the next query. */
57
+ export type PipeStep = Pipe | ((query: QueryExpression) => QueryExpression);
56
58
  /**
57
- * Apply `|>` steps to a query. Pipe syntax is GoogleSQL's, so the result is a GoogleSqlQuery. A GoogleSqlQuery takes
58
- * the steps on its own pipe list (only its outer wrapper is flattened); anything else is wrapped. The input is not
59
- * changed.
59
+ * Apply steps to a query, left to right. `|>` operators are GoogleSQL's pipe syntax, so a call of only those returns a
60
+ * GoogleSqlQuery; a function step gets the query built so far and its result is what later steps apply to. The input
61
+ * is not changed.
60
62
  */
61
63
  export declare function pipe(query: QueryExpression, ...steps: Pipe[]): GoogleSqlQuery;
64
+ export declare function pipe(query: QueryExpression, ...steps: PipeStep[]): QueryExpression;
62
65
  type SqlInterp = string | number | Line | SqlSegment;
63
66
  /**
64
67
  * Tagged template for raw SQL fragments.
package/dist/sql.js CHANGED
@@ -119,22 +119,32 @@ export class GoogleSqlQuery extends QueryExpression {
119
119
  ]);
120
120
  }
121
121
  }
122
- /**
123
- * Apply `|>` steps to a query. Pipe syntax is GoogleSQL's, so the result is a GoogleSqlQuery. A GoogleSqlQuery takes
124
- * the steps on its own pipe list (only its outer wrapper is flattened); anything else is wrapped. The input is not
125
- * changed.
126
- */
127
- export function pipe(query, ...steps) {
122
+ /** A GoogleSqlQuery takes the pipes on its own pipe list (only its outer wrapper is flattened); anything else is wrapped. */
123
+ function appendPipes(query, pipes) {
128
124
  if (query instanceof GoogleSqlQuery) {
129
125
  return new GoogleSqlQuery({
130
126
  ctes: query.ctes,
131
127
  queryExpression: query.queryExpression,
132
128
  orderByLine: query.orderByLine,
133
129
  limitOffset: query.limitOffset,
134
- pipes: [...query.pipes, ...steps],
130
+ pipes: [...query.pipes, ...pipes],
135
131
  });
136
132
  }
137
- return new GoogleSqlQuery({ queryExpression: query, pipes: steps });
133
+ return new GoogleSqlQuery({ queryExpression: query, pipes });
134
+ }
135
+ export function pipe(query, ...steps) {
136
+ let result = query;
137
+ let pending = [];
138
+ for (const step of steps) {
139
+ if (step instanceof Pipe) {
140
+ pending.push(step);
141
+ continue;
142
+ }
143
+ result = step(pending.length > 0 ? appendPipes(result, pending) : result);
144
+ pending = [];
145
+ }
146
+ const endsWithFunction = steps.length > 0 && !(steps[steps.length - 1] instanceof Pipe);
147
+ return endsWithFunction ? result : appendPipes(result, pending);
138
148
  }
139
149
  /**
140
150
  * Tagged template for raw SQL fragments.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leuduan/block",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "SQL builder and renderer for GoogleSQL",
5
5
  "license": "ISC",
6
6
  "author": "Duan Leu",