@enspirit/bmg-js 1.0.2 → 1.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 +3 -2
- package/dist/AsyncRelation/Base.d.ts +47 -0
- package/dist/AsyncRelation/index.d.ts +25 -0
- package/dist/Relation/Memory.d.ts +2 -1
- package/dist/Relation/index.d.ts +1 -1
- package/dist/async/Relation/Base.d.ts +47 -0
- package/dist/async/Relation/index.d.ts +25 -0
- package/dist/async/operators/_helpers.d.ts +16 -0
- package/dist/async/operators/autowrap.d.ts +7 -0
- package/dist/async/operators/constants.d.ts +6 -0
- package/dist/async/operators/cross_product.d.ts +9 -0
- package/dist/async/operators/extend.d.ts +7 -0
- package/dist/async/operators/group.d.ts +7 -0
- package/dist/async/operators/image.d.ts +8 -0
- package/dist/async/operators/index.d.ts +28 -0
- package/dist/async/operators/intersect.d.ts +7 -0
- package/dist/async/operators/isEqual.d.ts +7 -0
- package/dist/async/operators/join.d.ts +7 -0
- package/dist/async/operators/left_join.d.ts +8 -0
- package/dist/async/operators/matching.d.ts +7 -0
- package/dist/async/operators/minus.d.ts +7 -0
- package/dist/async/operators/not_matching.d.ts +7 -0
- package/dist/async/operators/one.d.ts +6 -0
- package/dist/async/operators/prefix.d.ts +6 -0
- package/dist/async/operators/project.d.ts +10 -0
- package/dist/async/operators/rename.d.ts +6 -0
- package/dist/async/operators/restrict.d.ts +14 -0
- package/dist/async/operators/suffix.d.ts +6 -0
- package/dist/async/operators/summarize.d.ts +8 -0
- package/dist/async/operators/toArray.d.ts +5 -0
- package/dist/async/operators/transform.d.ts +9 -0
- package/dist/async/operators/ungroup.d.ts +7 -0
- package/dist/async/operators/union.d.ts +6 -0
- package/dist/async/operators/unwrap.d.ts +6 -0
- package/dist/async/operators/wrap.d.ts +6 -0
- package/dist/async/operators/yByX.d.ts +7 -0
- package/dist/async/types.d.ts +58 -0
- package/dist/async-operators/_helpers.d.ts +16 -0
- package/dist/async-operators/autowrap.d.ts +7 -0
- package/dist/async-operators/constants.d.ts +6 -0
- package/dist/async-operators/cross_product.d.ts +9 -0
- package/dist/async-operators/extend.d.ts +7 -0
- package/dist/async-operators/group.d.ts +7 -0
- package/dist/async-operators/image.d.ts +8 -0
- package/dist/async-operators/index.d.ts +28 -0
- package/dist/async-operators/intersect.d.ts +7 -0
- package/dist/async-operators/isEqual.d.ts +7 -0
- package/dist/async-operators/join.d.ts +7 -0
- package/dist/async-operators/left_join.d.ts +8 -0
- package/dist/async-operators/matching.d.ts +7 -0
- package/dist/async-operators/minus.d.ts +7 -0
- package/dist/async-operators/not_matching.d.ts +7 -0
- package/dist/async-operators/one.d.ts +6 -0
- package/dist/async-operators/prefix.d.ts +6 -0
- package/dist/async-operators/project.d.ts +10 -0
- package/dist/async-operators/rename.d.ts +6 -0
- package/dist/async-operators/restrict.d.ts +14 -0
- package/dist/async-operators/suffix.d.ts +6 -0
- package/dist/async-operators/summarize.d.ts +8 -0
- package/dist/async-operators/toArray.d.ts +5 -0
- package/dist/async-operators/transform.d.ts +9 -0
- package/dist/async-operators/ungroup.d.ts +7 -0
- package/dist/async-operators/union.d.ts +6 -0
- package/dist/async-operators/unwrap.d.ts +6 -0
- package/dist/async-operators/wrap.d.ts +6 -0
- package/dist/async-operators/yByX.d.ts +7 -0
- package/dist/async-types.d.ts +58 -0
- package/dist/async.d.ts +4 -0
- package/dist/bmg.cjs +1 -1
- package/dist/bmg.cjs.map +1 -1
- package/dist/bmg.modern.js +1 -1
- package/dist/bmg.modern.js.map +1 -1
- package/dist/bmg.module.js +1 -1
- package/dist/bmg.module.js.map +1 -1
- package/dist/bmg.umd.js +1 -1
- package/dist/bmg.umd.js.map +1 -1
- package/dist/index.d.ts +14 -3
- package/dist/lib-definitions.d.ts +1 -1
- package/dist/operators/index.d.ts +1 -30
- package/dist/operators/isEqual.d.ts +1 -2
- package/dist/operators/isRelation.d.ts +2 -1
- package/dist/sync/Relation/Memory.d.ts +46 -0
- package/dist/sync/Relation/index.d.ts +1 -0
- package/dist/sync/operators/_helpers.d.ts +142 -0
- package/dist/sync/operators/allbut.d.ts +2 -0
- package/dist/sync/operators/autowrap.d.ts +2 -0
- package/dist/sync/operators/constants.d.ts +2 -0
- package/dist/sync/operators/cross_product.d.ts +3 -0
- package/dist/sync/operators/exclude.d.ts +2 -0
- package/dist/sync/operators/extend.d.ts +2 -0
- package/dist/sync/operators/group.d.ts +2 -0
- package/dist/sync/operators/image.d.ts +2 -0
- package/dist/sync/operators/index.d.ts +30 -0
- package/dist/sync/operators/intersect.d.ts +2 -0
- package/dist/sync/operators/isEqual.d.ts +1 -0
- package/dist/sync/operators/isRelation.d.ts +2 -0
- package/dist/sync/operators/join.d.ts +2 -0
- package/dist/sync/operators/left_join.d.ts +2 -0
- package/dist/sync/operators/matching.d.ts +2 -0
- package/dist/sync/operators/minus.d.ts +2 -0
- package/dist/sync/operators/not_matching.d.ts +2 -0
- package/dist/sync/operators/one.d.ts +2 -0
- package/dist/sync/operators/prefix.d.ts +2 -0
- package/dist/sync/operators/project.d.ts +2 -0
- package/dist/sync/operators/rename.d.ts +2 -0
- package/dist/sync/operators/restrict.d.ts +2 -0
- package/dist/sync/operators/suffix.d.ts +2 -0
- package/dist/sync/operators/summarize.d.ts +2 -0
- package/dist/sync/operators/transform.d.ts +2 -0
- package/dist/sync/operators/ungroup.d.ts +2 -0
- package/dist/sync/operators/union.d.ts +2 -0
- package/dist/sync/operators/unwrap.d.ts +2 -0
- package/dist/sync/operators/wrap.d.ts +2 -0
- package/dist/sync/operators/yByX.d.ts +2 -0
- package/dist/types.d.ts +7 -0
- package/dist/writer/Text.d.ts +40 -0
- package/dist/writer/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/Relation/index.ts +2 -1
- package/src/async/Relation/Base.ts +245 -0
- package/src/async/Relation/index.ts +31 -0
- package/src/async/operators/_helpers.ts +60 -0
- package/src/async/operators/autowrap.ts +31 -0
- package/src/async/operators/constants.ts +26 -0
- package/src/async/operators/cross_product.ts +39 -0
- package/src/async/operators/extend.ts +36 -0
- package/src/async/operators/group.ts +61 -0
- package/src/async/operators/image.ts +42 -0
- package/src/async/operators/index.ts +28 -0
- package/src/async/operators/intersect.ts +28 -0
- package/src/async/operators/isEqual.ts +39 -0
- package/src/async/operators/join.ts +39 -0
- package/src/async/operators/left_join.ts +55 -0
- package/src/async/operators/matching.ts +39 -0
- package/src/async/operators/minus.ts +28 -0
- package/src/async/operators/not_matching.ts +39 -0
- package/src/async/operators/one.ts +25 -0
- package/src/async/operators/prefix.ts +15 -0
- package/src/async/operators/project.ts +64 -0
- package/src/async/operators/rename.ts +33 -0
- package/src/async/operators/restrict.ts +61 -0
- package/src/async/operators/suffix.ts +15 -0
- package/src/async/operators/summarize.ts +90 -0
- package/src/async/operators/toArray.ts +18 -0
- package/src/async/operators/transform.ts +43 -0
- package/src/async/operators/ungroup.ts +43 -0
- package/src/async/operators/union.ts +29 -0
- package/src/async/operators/unwrap.ts +31 -0
- package/src/async/operators/wrap.ts +32 -0
- package/src/async/operators/yByX.ts +19 -0
- package/src/async/types.ts +86 -0
- package/src/async.ts +4 -0
- package/src/index.ts +16 -3
- package/src/lib-definitions.ts +11 -0
- package/src/operators/index.ts +2 -31
- package/src/{Relation → sync/Relation}/Memory.ts +9 -1
- package/src/sync/Relation/index.ts +1 -0
- package/src/{operators → sync/operators}/_helpers.ts +1 -1
- package/src/{operators → sync/operators}/allbut.ts +1 -1
- package/src/{operators → sync/operators}/autowrap.ts +1 -1
- package/src/{operators → sync/operators}/constants.ts +1 -1
- package/src/{operators → sync/operators}/cross_product.ts +1 -1
- package/src/{operators → sync/operators}/exclude.ts +2 -2
- package/src/{operators → sync/operators}/extend.ts +1 -1
- package/src/{operators → sync/operators}/group.ts +2 -2
- package/src/{operators → sync/operators}/image.ts +2 -2
- package/src/sync/operators/index.ts +31 -0
- package/src/{operators → sync/operators}/intersect.ts +1 -1
- package/src/{operators → sync/operators}/isEqual.ts +1 -2
- package/src/sync/operators/isRelation.ts +6 -0
- package/src/{operators → sync/operators}/join.ts +1 -1
- package/src/{operators → sync/operators}/left_join.ts +1 -1
- package/src/{operators → sync/operators}/matching.ts +1 -1
- package/src/{operators → sync/operators}/minus.ts +1 -1
- package/src/{operators → sync/operators}/not_matching.ts +1 -1
- package/src/{operators → sync/operators}/one.ts +1 -1
- package/src/{operators → sync/operators}/prefix.ts +1 -1
- package/src/{operators → sync/operators}/project.ts +1 -1
- package/src/{operators → sync/operators}/rename.ts +1 -1
- package/src/{operators → sync/operators}/restrict.ts +2 -2
- package/src/{operators → sync/operators}/suffix.ts +1 -1
- package/src/{operators → sync/operators}/summarize.ts +1 -1
- package/src/{operators → sync/operators}/transform.ts +1 -1
- package/src/{operators → sync/operators}/ungroup.ts +1 -1
- package/src/{operators → sync/operators}/union.ts +1 -1
- package/src/{operators → sync/operators}/unwrap.ts +1 -1
- package/src/sync/operators/where.ts +1 -0
- package/src/{operators → sync/operators}/wrap.ts +1 -1
- package/src/{operators → sync/operators}/yByX.ts +1 -1
- package/src/types.ts +11 -0
- package/src/writer/Text.ts +305 -0
- package/src/writer/index.ts +1 -0
- package/src/operators/isRelation.ts +0 -5
- /package/{src/operators/where.ts → dist/sync/operators/where.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Memory';
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { OperationalOperand, RelationOperand, Renaming, RenamingFunc, Tuple, JoinKeys, AttrName } from "@/types";
|
|
2
|
+
/**
|
|
3
|
+
* Generates a unique string key for a tuple, used for equality comparison and deduplication.
|
|
4
|
+
* Handles nested relations by converting them to sorted tuple keys.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* tupleKey({ name: 'Alice', age: 30 })
|
|
8
|
+
* // => '[["age",30],["name","Alice"]]'
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* tupleKey({ id: 1, items: Bmg([{ x: 1 }, { x: 2 }]) })
|
|
12
|
+
* // => '[["id",1],["items",[...]]]' (nested relation converted to sorted keys)
|
|
13
|
+
*/
|
|
14
|
+
export declare const tupleKey: (tuple: Tuple) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Removes duplicate tuples from an array, preserving order of first occurrence.
|
|
17
|
+
* Uses tupleKey() for equality comparison.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* deduplicate([
|
|
21
|
+
* { id: 1, name: 'Alice' },
|
|
22
|
+
* { id: 2, name: 'Bob' },
|
|
23
|
+
* { id: 1, name: 'Alice' }, // duplicate
|
|
24
|
+
* ])
|
|
25
|
+
* // => [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
|
|
26
|
+
*/
|
|
27
|
+
export declare const deduplicate: (tuples: Tuple[]) => Tuple[];
|
|
28
|
+
/**
|
|
29
|
+
* Converts a RelationOperand (Relation or Tuple[]) to an OperationalOperand
|
|
30
|
+
* that provides a uniform interface for iteration and output.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // With array input, output remains array
|
|
34
|
+
* const op = toOperationalOperand([{ id: 1 }]);
|
|
35
|
+
* [...op.tuples()]; // => [{ id: 1 }]
|
|
36
|
+
* op.output([{ id: 2 }]); // => [{ id: 2 }]
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* // With Relation input, output is a new Relation
|
|
40
|
+
* const op = toOperationalOperand(Bmg([{ id: 1 }]));
|
|
41
|
+
* [...op.tuples()]; // => [{ id: 1 }]
|
|
42
|
+
* op.output([{ id: 2 }]); // => Bmg([{ id: 2 }])
|
|
43
|
+
*/
|
|
44
|
+
export declare const toOperationalOperand: (operand: RelationOperand) => OperationalOperand;
|
|
45
|
+
/**
|
|
46
|
+
* Converts a Renaming (object or function) to a RenamingFunc.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* // Object renaming
|
|
50
|
+
* const fn = toRenamingFunc({ name: 'fullName', age: 'years' });
|
|
51
|
+
* fn('name'); // => 'fullName'
|
|
52
|
+
* fn('age'); // => 'years'
|
|
53
|
+
* fn('other'); // => 'other' (unchanged)
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* // Function renaming (passed through)
|
|
57
|
+
* const fn = toRenamingFunc(attr => attr.toUpperCase());
|
|
58
|
+
* fn('name'); // => 'NAME'
|
|
59
|
+
*/
|
|
60
|
+
export declare const toRenamingFunc: (renaming: Renaming) => RenamingFunc;
|
|
61
|
+
export declare const error: (msg: string) => never;
|
|
62
|
+
/**
|
|
63
|
+
* Finds attribute names that exist in both left and right tuple arrays.
|
|
64
|
+
* Used for natural joins when no explicit keys are provided.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* const left = [{ id: 1, name: 'Alice', city: 'NYC' }];
|
|
68
|
+
* const right = [{ city: 'NYC', country: 'USA' }];
|
|
69
|
+
* getCommonAttrs(left, right);
|
|
70
|
+
* // => ['city']
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* const left = [{ a: 1, b: 2 }];
|
|
74
|
+
* const right = [{ b: 2, c: 3 }];
|
|
75
|
+
* getCommonAttrs(left, right);
|
|
76
|
+
* // => ['b']
|
|
77
|
+
*/
|
|
78
|
+
export declare const getCommonAttrs: (left: Tuple[], right: Tuple[]) => AttrName[];
|
|
79
|
+
/**
|
|
80
|
+
* Normalizes JoinKeys to a Record<AttrName, AttrName> mapping left attrs to right attrs.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* // undefined => use common attributes
|
|
84
|
+
* normalizeKeys(undefined, [{ id: 1, city: 'NYC' }], [{ city: 'NYC' }]);
|
|
85
|
+
* // => { city: 'city' }
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* // Array of common attribute names
|
|
89
|
+
* normalizeKeys(['city', 'country'], leftTuples, rightTuples);
|
|
90
|
+
* // => { city: 'city', country: 'country' }
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* // Object mapping left attr to right attr
|
|
94
|
+
* normalizeKeys({ city: 'location' }, leftTuples, rightTuples);
|
|
95
|
+
* // => { city: 'location' }
|
|
96
|
+
*/
|
|
97
|
+
export declare const normalizeKeys: (keys: JoinKeys | undefined, leftTuples: Tuple[], rightTuples: Tuple[]) => Record<AttrName, AttrName>;
|
|
98
|
+
/**
|
|
99
|
+
* Checks if two tuples match on the specified key mapping.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* const keyMap = { city: 'location' };
|
|
103
|
+
* tuplesMatch({ id: 1, city: 'NYC' }, { location: 'NYC', pop: 8 }, keyMap);
|
|
104
|
+
* // => true (left.city === right.location)
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* const keyMap = { city: 'city' };
|
|
108
|
+
* tuplesMatch({ city: 'NYC' }, { city: 'LA' }, keyMap);
|
|
109
|
+
* // => false
|
|
110
|
+
*/
|
|
111
|
+
export declare const tuplesMatch: (left: Tuple, right: Tuple, keyMap: Record<AttrName, AttrName>) => boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Creates a string key from a tuple's join attributes for fast Set-based lookups.
|
|
114
|
+
* Used by matching/not_matching for efficient semi-join operations.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* const keyMap = { first: 'fname', last: 'lname' };
|
|
118
|
+
*
|
|
119
|
+
* // Left side uses left attr names (keys of keyMap)
|
|
120
|
+
* matchKey({ id: 1, first: 'John', last: 'Doe' }, keyMap, 'left');
|
|
121
|
+
* // => '"John"|"Doe"'
|
|
122
|
+
*
|
|
123
|
+
* // Right side uses right attr names (values of keyMap)
|
|
124
|
+
* matchKey({ fname: 'John', lname: 'Doe', age: 30 }, keyMap, 'right');
|
|
125
|
+
* // => '"John"|"Doe"'
|
|
126
|
+
*/
|
|
127
|
+
export declare const matchKey: (tuple: Tuple, keyMap: Record<AttrName, AttrName>, side: 'left' | 'right') => string;
|
|
128
|
+
/**
|
|
129
|
+
* Removes join key attributes from a right tuple when merging.
|
|
130
|
+
* Used to avoid duplicate columns in join results.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* const keyMap = { city: 'location' };
|
|
134
|
+
* projectOutKeys({ location: 'NYC', country: 'USA', pop: 8 }, keyMap);
|
|
135
|
+
* // => { country: 'USA', pop: 8 } (location removed)
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* const keyMap = { a: 'a', b: 'b' };
|
|
139
|
+
* projectOutKeys({ a: 1, b: 2, c: 3 }, keyMap);
|
|
140
|
+
* // => { c: 3 } (a and b removed)
|
|
141
|
+
*/
|
|
142
|
+
export declare const projectOutKeys: (tuple: Tuple, keyMap: Record<AttrName, AttrName>) => Tuple;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export * from './restrict';
|
|
2
|
+
export * from './where';
|
|
3
|
+
export * from './exclude';
|
|
4
|
+
export * from './constants';
|
|
5
|
+
export * from './rename';
|
|
6
|
+
export * from './prefix';
|
|
7
|
+
export * from './suffix';
|
|
8
|
+
export * from './project';
|
|
9
|
+
export * from './allbut';
|
|
10
|
+
export * from './extend';
|
|
11
|
+
export * from './union';
|
|
12
|
+
export * from './minus';
|
|
13
|
+
export * from './intersect';
|
|
14
|
+
export * from './matching';
|
|
15
|
+
export * from './not_matching';
|
|
16
|
+
export * from './join';
|
|
17
|
+
export * from './left_join';
|
|
18
|
+
export * from './cross_product';
|
|
19
|
+
export * from './image';
|
|
20
|
+
export * from './summarize';
|
|
21
|
+
export * from './group';
|
|
22
|
+
export * from './ungroup';
|
|
23
|
+
export * from './wrap';
|
|
24
|
+
export * from './unwrap';
|
|
25
|
+
export * from './autowrap';
|
|
26
|
+
export * from './transform';
|
|
27
|
+
export * from './isRelation';
|
|
28
|
+
export * from './isEqual';
|
|
29
|
+
export * from './one';
|
|
30
|
+
export * from './yByX';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isEqual: (left: any, right: any) => boolean;
|
package/dist/types.d.ts
CHANGED
|
@@ -90,6 +90,12 @@ export type Extension = Record<AttrName, ExtensionFunc | AttrName>;
|
|
|
90
90
|
export interface PrefixOptions {
|
|
91
91
|
except?: AttrName[];
|
|
92
92
|
}
|
|
93
|
+
export interface TextOptions {
|
|
94
|
+
/** Precision for floating point numbers (default: 3) */
|
|
95
|
+
floatPrecision?: number;
|
|
96
|
+
/** Maximum width to trim output at */
|
|
97
|
+
trimAt?: number;
|
|
98
|
+
}
|
|
93
99
|
export interface SuffixOptions {
|
|
94
100
|
except?: AttrName[];
|
|
95
101
|
}
|
|
@@ -154,6 +160,7 @@ export interface Relation<T = Tuple> {
|
|
|
154
160
|
yByX<Y extends keyof T, X extends keyof T>(y: Y, x: X): Record<T[X] & PropertyKey, T[Y]>;
|
|
155
161
|
toArray(): T[];
|
|
156
162
|
isEqual(right: any): boolean;
|
|
163
|
+
toText(options?: TextOptions): string;
|
|
157
164
|
}
|
|
158
165
|
export type RelationOperand<T = Tuple> = Relation<T> | T[];
|
|
159
166
|
export interface OperationalOperand<T = Tuple> {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Relation, Tuple } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Options for text rendering
|
|
4
|
+
*/
|
|
5
|
+
export interface TextOptions {
|
|
6
|
+
/** Format string for floating point numbers (default: '%.3f' style) */
|
|
7
|
+
floatPrecision?: number;
|
|
8
|
+
/** Maximum width to trim output at */
|
|
9
|
+
trimAt?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Text writer for rendering relations as ASCII tables
|
|
13
|
+
*/
|
|
14
|
+
export declare class TextWriter {
|
|
15
|
+
readonly options: TextOptions;
|
|
16
|
+
constructor(options?: TextOptions);
|
|
17
|
+
/**
|
|
18
|
+
* Renders a relation or tuple array to an ASCII table string
|
|
19
|
+
*/
|
|
20
|
+
render(input: Relation | Tuple[] | Tuple, output?: string): string;
|
|
21
|
+
eachLine(input: Relation | Tuple[] | Tuple): Generator<string>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Renders a relation as an ASCII table string
|
|
25
|
+
*
|
|
26
|
+
* @param operand - The relation or tuple array to render
|
|
27
|
+
* @param options - Text rendering options
|
|
28
|
+
* @returns ASCII table string representation
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const r = Bmg([{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]);
|
|
32
|
+
* console.log(toText(r));
|
|
33
|
+
* // +----+-------+
|
|
34
|
+
* // | id | name |
|
|
35
|
+
* // +----+-------+
|
|
36
|
+
* // | 1 | Alice |
|
|
37
|
+
* // | 2 | Bob |
|
|
38
|
+
* // +----+-------+
|
|
39
|
+
*/
|
|
40
|
+
export declare const toText: (operand: Relation | Tuple[] | Tuple, options?: TextOptions) => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Text';
|
package/package.json
CHANGED
package/src/Relation/index.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
// Re-export sync Relation for backward compatibility
|
|
2
|
+
export * from '../sync/Relation';
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import type { AsyncRelation, AsyncRelationOperand } from '../types';
|
|
2
|
+
import type { Tuple, TypedPredicate, TypedExtension, AttrName, Relation, RenameMap, Renamed, Prefixed, Suffixed, Transformation, JoinKeys, Aggregators, AutowrapOptions, TextOptions } from '../../types';
|
|
3
|
+
import { MemoryRelation } from '../../sync/Relation';
|
|
4
|
+
import {
|
|
5
|
+
restrict as restrictOp,
|
|
6
|
+
where as whereOp,
|
|
7
|
+
exclude as excludeOp,
|
|
8
|
+
} from '../operators/restrict';
|
|
9
|
+
import {
|
|
10
|
+
project as projectOp,
|
|
11
|
+
allbut as allbutOp,
|
|
12
|
+
} from '../operators/project';
|
|
13
|
+
import { extend as extendOp } from '../operators/extend';
|
|
14
|
+
import { constants as constantsOp } from '../operators/constants';
|
|
15
|
+
import { rename as renameOp } from '../operators/rename';
|
|
16
|
+
import { prefix as prefixOp } from '../operators/prefix';
|
|
17
|
+
import { suffix as suffixOp } from '../operators/suffix';
|
|
18
|
+
import { transform as transformOp } from '../operators/transform';
|
|
19
|
+
import { union as unionOp } from '../operators/union';
|
|
20
|
+
import { minus as minusOp } from '../operators/minus';
|
|
21
|
+
import { intersect as intersectOp } from '../operators/intersect';
|
|
22
|
+
import { matching as matchingOp } from '../operators/matching';
|
|
23
|
+
import { not_matching as notMatchingOp } from '../operators/not_matching';
|
|
24
|
+
import { join as joinOp } from '../operators/join';
|
|
25
|
+
import { left_join as leftJoinOp } from '../operators/left_join';
|
|
26
|
+
import { cross_product as crossProductOp } from '../operators/cross_product';
|
|
27
|
+
import { group as groupOp } from '../operators/group';
|
|
28
|
+
import { ungroup as ungroupOp } from '../operators/ungroup';
|
|
29
|
+
import { wrap as wrapOp } from '../operators/wrap';
|
|
30
|
+
import { unwrap as unwrapOp } from '../operators/unwrap';
|
|
31
|
+
import { image as imageOp } from '../operators/image';
|
|
32
|
+
import { summarize as summarizeOp } from '../operators/summarize';
|
|
33
|
+
import { autowrap as autowrapOp } from '../operators/autowrap';
|
|
34
|
+
import { yByX as yByXOp } from '../operators/yByX';
|
|
35
|
+
import { one as oneOp } from '../operators/one';
|
|
36
|
+
import { toArray as toArrayOp } from '../operators/toArray';
|
|
37
|
+
import { toText as toTextSync } from '../../writer';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Base implementation of AsyncRelation using lazy evaluation.
|
|
41
|
+
* Each operator returns a new BaseAsyncRelation wrapping the transformed iterable.
|
|
42
|
+
*/
|
|
43
|
+
export class BaseAsyncRelation<T = Tuple> implements AsyncRelation<T> {
|
|
44
|
+
constructor(private source: AsyncIterable<T>) {}
|
|
45
|
+
|
|
46
|
+
// === Type-preserving operators ===
|
|
47
|
+
|
|
48
|
+
restrict(p: TypedPredicate<T>): AsyncRelation<T> {
|
|
49
|
+
return new BaseAsyncRelation(restrictOp(this.source, p as any));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
where(p: TypedPredicate<T>): AsyncRelation<T> {
|
|
53
|
+
return new BaseAsyncRelation(whereOp(this.source, p as any));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
exclude(p: TypedPredicate<T>): AsyncRelation<T> {
|
|
57
|
+
return new BaseAsyncRelation(excludeOp(this.source, p as any));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// === Projection operators ===
|
|
61
|
+
|
|
62
|
+
project<K extends keyof T>(attrs: K[]): AsyncRelation<Pick<T, K>> {
|
|
63
|
+
return new BaseAsyncRelation(
|
|
64
|
+
projectOp(this.source, attrs as AttrName[])
|
|
65
|
+
) as unknown as AsyncRelation<Pick<T, K>>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
allbut<K extends keyof T>(attrs: K[]): AsyncRelation<Omit<T, K>> {
|
|
69
|
+
return new BaseAsyncRelation(
|
|
70
|
+
allbutOp(this.source, attrs as AttrName[])
|
|
71
|
+
) as unknown as AsyncRelation<Omit<T, K>>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// === Extension operators ===
|
|
75
|
+
|
|
76
|
+
extend<E extends Record<string, unknown>>(e: TypedExtension<T, E>): AsyncRelation<T & E> {
|
|
77
|
+
return new BaseAsyncRelation(
|
|
78
|
+
extendOp(this.source, e as any)
|
|
79
|
+
) as unknown as AsyncRelation<T & E>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
constants<C extends Tuple>(consts: C): AsyncRelation<T & C> {
|
|
83
|
+
return new BaseAsyncRelation(
|
|
84
|
+
constantsOp(this.source, consts)
|
|
85
|
+
) as unknown as AsyncRelation<T & C>;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// === Rename operators ===
|
|
89
|
+
|
|
90
|
+
rename<R extends RenameMap<T>>(r: R): AsyncRelation<Renamed<T, R>> {
|
|
91
|
+
return new BaseAsyncRelation(
|
|
92
|
+
renameOp(this.source, r as any)
|
|
93
|
+
) as unknown as AsyncRelation<Renamed<T, R>>;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
prefix<P extends string, Ex extends keyof T = never>(pfx: P, options?: { except?: Ex[] }): AsyncRelation<Prefixed<T, P, Ex>> {
|
|
97
|
+
return new BaseAsyncRelation(
|
|
98
|
+
prefixOp(this.source, pfx, options as any)
|
|
99
|
+
) as unknown as AsyncRelation<Prefixed<T, P, Ex>>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
suffix<S extends string, Ex extends keyof T = never>(sfx: S, options?: { except?: Ex[] }): AsyncRelation<Suffixed<T, S, Ex>> {
|
|
103
|
+
return new BaseAsyncRelation(
|
|
104
|
+
suffixOp(this.source, sfx, options as any)
|
|
105
|
+
) as unknown as AsyncRelation<Suffixed<T, S, Ex>>;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
transform(t: Transformation): AsyncRelation<T> {
|
|
109
|
+
return new BaseAsyncRelation(
|
|
110
|
+
transformOp(this.source, t)
|
|
111
|
+
) as unknown as AsyncRelation<T>;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// === Set operations ===
|
|
115
|
+
|
|
116
|
+
union(other: AsyncRelationOperand<T>): AsyncRelation<T> {
|
|
117
|
+
return new BaseAsyncRelation(
|
|
118
|
+
unionOp(this.source, other)
|
|
119
|
+
) as unknown as AsyncRelation<T>;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
minus(other: AsyncRelationOperand<T>): AsyncRelation<T> {
|
|
123
|
+
return new BaseAsyncRelation(
|
|
124
|
+
minusOp(this.source, other)
|
|
125
|
+
) as unknown as AsyncRelation<T>;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
intersect(other: AsyncRelationOperand<T>): AsyncRelation<T> {
|
|
129
|
+
return new BaseAsyncRelation(
|
|
130
|
+
intersectOp(this.source, other)
|
|
131
|
+
) as unknown as AsyncRelation<T>;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// === Semi-joins ===
|
|
135
|
+
|
|
136
|
+
matching<U>(other: AsyncRelationOperand<U>, keys?: JoinKeys): AsyncRelation<T> {
|
|
137
|
+
return new BaseAsyncRelation(
|
|
138
|
+
matchingOp(this.source, other, keys)
|
|
139
|
+
) as unknown as AsyncRelation<T>;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
not_matching<U>(other: AsyncRelationOperand<U>, keys?: JoinKeys): AsyncRelation<T> {
|
|
143
|
+
return new BaseAsyncRelation(
|
|
144
|
+
notMatchingOp(this.source, other, keys)
|
|
145
|
+
) as unknown as AsyncRelation<T>;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// === Joins ===
|
|
149
|
+
|
|
150
|
+
join<U>(other: AsyncRelationOperand<U>, keys?: JoinKeys): AsyncRelation<T & U> {
|
|
151
|
+
return new BaseAsyncRelation(
|
|
152
|
+
joinOp(this.source, other, keys)
|
|
153
|
+
) as unknown as AsyncRelation<T & U>;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
left_join<U>(other: AsyncRelationOperand<U>, keys?: JoinKeys): AsyncRelation<T & Partial<U>> {
|
|
157
|
+
return new BaseAsyncRelation(
|
|
158
|
+
leftJoinOp(this.source, other, keys)
|
|
159
|
+
) as unknown as AsyncRelation<T & Partial<U>>;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
cross_product<U>(other: AsyncRelationOperand<U>): AsyncRelation<T & U> {
|
|
163
|
+
return new BaseAsyncRelation(
|
|
164
|
+
crossProductOp(this.source, other)
|
|
165
|
+
) as unknown as AsyncRelation<T & U>;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
cross_join<U>(other: AsyncRelationOperand<U>): AsyncRelation<T & U> {
|
|
169
|
+
return this.cross_product(other);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// === Nesting/Grouping ===
|
|
173
|
+
|
|
174
|
+
group<K extends keyof T>(attrs: K[], as: string): AsyncRelation<Omit<T, K> & Record<string, Relation<Pick<T, K>>>> {
|
|
175
|
+
return new BaseAsyncRelation(
|
|
176
|
+
groupOp(this.source, attrs as string[], as)
|
|
177
|
+
) as unknown as AsyncRelation<Omit<T, K> & Record<string, Relation<Pick<T, K>>>>;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
ungroup(attr: string): AsyncRelation<Tuple> {
|
|
181
|
+
return new BaseAsyncRelation(
|
|
182
|
+
ungroupOp(this.source, attr)
|
|
183
|
+
) as unknown as AsyncRelation<Tuple>;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
wrap<K extends keyof T>(attrs: K[], as: string): AsyncRelation<Omit<T, K> & Record<string, Pick<T, K>>> {
|
|
187
|
+
return new BaseAsyncRelation(
|
|
188
|
+
wrapOp(this.source, attrs as string[], as)
|
|
189
|
+
) as unknown as AsyncRelation<Omit<T, K> & Record<string, Pick<T, K>>>;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
unwrap(attr: string): AsyncRelation<Tuple> {
|
|
193
|
+
return new BaseAsyncRelation(
|
|
194
|
+
unwrapOp(this.source, attr)
|
|
195
|
+
) as unknown as AsyncRelation<Tuple>;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
image<U>(other: AsyncRelationOperand<U>, as: string, keys?: JoinKeys): AsyncRelation<T & Record<string, Relation<U>>> {
|
|
199
|
+
return new BaseAsyncRelation(
|
|
200
|
+
imageOp(this.source, other, as, keys)
|
|
201
|
+
) as unknown as AsyncRelation<T & Record<string, Relation<U>>>;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
summarize<K extends keyof T>(by: K[], aggs: Aggregators): AsyncRelation<Pick<T, K> & Tuple> {
|
|
205
|
+
return new BaseAsyncRelation(
|
|
206
|
+
summarizeOp(this.source, by as string[], aggs)
|
|
207
|
+
) as unknown as AsyncRelation<Pick<T, K> & Tuple>;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
autowrap(options?: AutowrapOptions): AsyncRelation<Tuple> {
|
|
211
|
+
return new BaseAsyncRelation(
|
|
212
|
+
autowrapOp(this.source, options)
|
|
213
|
+
) as unknown as AsyncRelation<Tuple>;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// === Terminal operations ===
|
|
217
|
+
|
|
218
|
+
one(): Promise<T> {
|
|
219
|
+
return oneOp(this.source);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
toArray(): Promise<T[]> {
|
|
223
|
+
return toArrayOp(this.source);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async toRelation(): Promise<Relation<T>> {
|
|
227
|
+
const tuples = await toArrayOp(this.source);
|
|
228
|
+
return new MemoryRelation<T>(tuples);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
yByX(y: string, x: string): Promise<Tuple> {
|
|
232
|
+
return yByXOp(this.source, y, x);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async toText(options?: TextOptions): Promise<string> {
|
|
236
|
+
const tuples = await toArrayOp(this.source);
|
|
237
|
+
return toTextSync(tuples as Tuple[], options);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// === Async iteration ===
|
|
241
|
+
|
|
242
|
+
[Symbol.asyncIterator](): AsyncIterator<T> {
|
|
243
|
+
return this.source[Symbol.asyncIterator]();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { BaseAsyncRelation } from './Base';
|
|
2
|
+
import type { AsyncRelation, AsyncRelationOperand } from '../types';
|
|
3
|
+
import { isEqual as isEqualOp } from '../operators/isEqual';
|
|
4
|
+
|
|
5
|
+
export { BaseAsyncRelation };
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Creates a new async relation from an AsyncIterable source.
|
|
9
|
+
*
|
|
10
|
+
* @typeParam T - The tuple type. Inferred from input or explicitly provided.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* // From an async iterable
|
|
14
|
+
* const suppliers = AsyncBmg(fetchSuppliersFromDB());
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Chained operations (lazy - no execution yet)
|
|
18
|
+
* const query = AsyncBmg(source)
|
|
19
|
+
* .restrict({ city: 'London' })
|
|
20
|
+
* .project(['sid', 'name']);
|
|
21
|
+
*
|
|
22
|
+
* // Terminal operation triggers execution
|
|
23
|
+
* const results = await query.toArray();
|
|
24
|
+
*/
|
|
25
|
+
export function AsyncBmg<T>(source: AsyncIterable<T>): AsyncRelation<T> {
|
|
26
|
+
return new BaseAsyncRelation<T>(source);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
AsyncBmg.isEqual = <T, U>(left: AsyncRelationOperand<T>, right: AsyncRelationOperand<U>): Promise<boolean> => {
|
|
30
|
+
return isEqualOp(left, right);
|
|
31
|
+
};
|