@enspirit/bmg-js 1.0.1 → 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.
Files changed (302) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +3 -2
  3. package/dist/AsyncRelation/Base.d.ts +47 -0
  4. package/dist/AsyncRelation/index.d.ts +25 -0
  5. package/dist/{src/Relation → Relation}/Memory.d.ts +46 -46
  6. package/dist/Relation/index.d.ts +1 -0
  7. package/dist/async/Relation/Base.d.ts +47 -0
  8. package/dist/async/Relation/index.d.ts +25 -0
  9. package/dist/async/operators/_helpers.d.ts +16 -0
  10. package/dist/async/operators/autowrap.d.ts +7 -0
  11. package/dist/async/operators/constants.d.ts +6 -0
  12. package/dist/async/operators/cross_product.d.ts +9 -0
  13. package/dist/async/operators/extend.d.ts +7 -0
  14. package/dist/async/operators/group.d.ts +7 -0
  15. package/dist/async/operators/image.d.ts +8 -0
  16. package/dist/async/operators/index.d.ts +28 -0
  17. package/dist/async/operators/intersect.d.ts +7 -0
  18. package/dist/async/operators/isEqual.d.ts +7 -0
  19. package/dist/async/operators/join.d.ts +7 -0
  20. package/dist/async/operators/left_join.d.ts +8 -0
  21. package/dist/async/operators/matching.d.ts +7 -0
  22. package/dist/async/operators/minus.d.ts +7 -0
  23. package/dist/async/operators/not_matching.d.ts +7 -0
  24. package/dist/async/operators/one.d.ts +6 -0
  25. package/dist/async/operators/prefix.d.ts +6 -0
  26. package/dist/async/operators/project.d.ts +10 -0
  27. package/dist/async/operators/rename.d.ts +6 -0
  28. package/dist/async/operators/restrict.d.ts +14 -0
  29. package/dist/async/operators/suffix.d.ts +6 -0
  30. package/dist/async/operators/summarize.d.ts +8 -0
  31. package/dist/async/operators/toArray.d.ts +5 -0
  32. package/dist/async/operators/transform.d.ts +9 -0
  33. package/dist/async/operators/ungroup.d.ts +7 -0
  34. package/dist/async/operators/union.d.ts +6 -0
  35. package/dist/async/operators/unwrap.d.ts +6 -0
  36. package/dist/async/operators/wrap.d.ts +6 -0
  37. package/dist/async/operators/yByX.d.ts +7 -0
  38. package/dist/async/types.d.ts +58 -0
  39. package/dist/async-operators/_helpers.d.ts +16 -0
  40. package/dist/async-operators/autowrap.d.ts +7 -0
  41. package/dist/async-operators/constants.d.ts +6 -0
  42. package/dist/async-operators/cross_product.d.ts +9 -0
  43. package/dist/async-operators/extend.d.ts +7 -0
  44. package/dist/async-operators/group.d.ts +7 -0
  45. package/dist/async-operators/image.d.ts +8 -0
  46. package/dist/async-operators/index.d.ts +28 -0
  47. package/dist/async-operators/intersect.d.ts +7 -0
  48. package/dist/async-operators/isEqual.d.ts +7 -0
  49. package/dist/async-operators/join.d.ts +7 -0
  50. package/dist/async-operators/left_join.d.ts +8 -0
  51. package/dist/async-operators/matching.d.ts +7 -0
  52. package/dist/async-operators/minus.d.ts +7 -0
  53. package/dist/async-operators/not_matching.d.ts +7 -0
  54. package/dist/async-operators/one.d.ts +6 -0
  55. package/dist/async-operators/prefix.d.ts +6 -0
  56. package/dist/async-operators/project.d.ts +10 -0
  57. package/dist/async-operators/rename.d.ts +6 -0
  58. package/dist/async-operators/restrict.d.ts +14 -0
  59. package/dist/async-operators/suffix.d.ts +6 -0
  60. package/dist/async-operators/summarize.d.ts +8 -0
  61. package/dist/async-operators/toArray.d.ts +5 -0
  62. package/dist/async-operators/transform.d.ts +9 -0
  63. package/dist/async-operators/ungroup.d.ts +7 -0
  64. package/dist/async-operators/union.d.ts +6 -0
  65. package/dist/async-operators/unwrap.d.ts +6 -0
  66. package/dist/async-operators/wrap.d.ts +6 -0
  67. package/dist/async-operators/yByX.d.ts +7 -0
  68. package/dist/async-types.d.ts +58 -0
  69. package/dist/async.d.ts +4 -0
  70. package/dist/bmg.cjs +1 -1
  71. package/dist/bmg.cjs.map +1 -1
  72. package/dist/bmg.modern.js +1 -1
  73. package/dist/bmg.modern.js.map +1 -1
  74. package/dist/bmg.module.js +1 -1
  75. package/dist/bmg.module.js.map +1 -1
  76. package/dist/bmg.umd.js +1 -1
  77. package/dist/bmg.umd.js.map +1 -1
  78. package/dist/index.d.ts +38 -1
  79. package/dist/lib-definitions.d.ts +1 -0
  80. package/dist/{src/operators → operators}/_helpers.d.ts +142 -142
  81. package/dist/{src/operators → operators}/allbut.d.ts +2 -2
  82. package/dist/{src/operators → operators}/autowrap.d.ts +2 -2
  83. package/dist/{src/operators → operators}/constants.d.ts +2 -2
  84. package/dist/{src/operators → operators}/cross_product.d.ts +3 -3
  85. package/dist/{src/operators → operators}/exclude.d.ts +2 -2
  86. package/dist/{src/operators → operators}/extend.d.ts +2 -2
  87. package/dist/{src/src/operators → operators}/group.d.ts +2 -2
  88. package/dist/{src/operators → operators}/image.d.ts +2 -2
  89. package/dist/operators/index.d.ts +1 -0
  90. package/dist/{src/src/operators → operators}/intersect.d.ts +2 -2
  91. package/dist/operators/isEqual.d.ts +1 -0
  92. package/dist/operators/isRelation.d.ts +2 -0
  93. package/dist/{src/operators → operators}/join.d.ts +2 -2
  94. package/dist/{src/operators → operators}/left_join.d.ts +2 -2
  95. package/dist/{src/src/operators → operators}/matching.d.ts +2 -2
  96. package/dist/{src/src/operators → operators}/minus.d.ts +2 -2
  97. package/dist/{src/src/operators → operators}/not_matching.d.ts +2 -2
  98. package/dist/{src/operators → operators}/one.d.ts +2 -2
  99. package/dist/{src/operators → operators}/prefix.d.ts +2 -2
  100. package/dist/{src/src/operators → operators}/project.d.ts +2 -2
  101. package/dist/{src/operators → operators}/rename.d.ts +2 -2
  102. package/dist/{src/operators → operators}/restrict.d.ts +2 -2
  103. package/dist/{src/operators → operators}/suffix.d.ts +2 -2
  104. package/dist/{src/operators → operators}/summarize.d.ts +2 -2
  105. package/dist/{src/operators → operators}/transform.d.ts +2 -2
  106. package/dist/{src/src/operators → operators}/ungroup.d.ts +2 -2
  107. package/dist/{src/operators → operators}/union.d.ts +2 -2
  108. package/dist/{src/operators → operators}/unwrap.d.ts +2 -2
  109. package/dist/{src/operators → operators}/wrap.d.ts +2 -2
  110. package/dist/{src/operators → operators}/yByX.d.ts +2 -2
  111. package/dist/{src/src/support → support}/toPredicateFunc.d.ts +2 -2
  112. package/dist/{src/src → sync}/Relation/Memory.d.ts +46 -46
  113. package/dist/{src/src → sync}/Relation/index.d.ts +1 -1
  114. package/dist/{src/src → sync}/operators/_helpers.d.ts +142 -142
  115. package/dist/{src/src → sync}/operators/allbut.d.ts +2 -2
  116. package/dist/{src/src → sync}/operators/autowrap.d.ts +2 -2
  117. package/dist/{src/src → sync}/operators/constants.d.ts +2 -2
  118. package/dist/{src/src → sync}/operators/cross_product.d.ts +3 -3
  119. package/dist/{src/src → sync}/operators/exclude.d.ts +2 -2
  120. package/dist/{src/src → sync}/operators/extend.d.ts +2 -2
  121. package/dist/{src → sync}/operators/group.d.ts +2 -2
  122. package/dist/{src/src → sync}/operators/image.d.ts +2 -2
  123. package/dist/{src → sync}/operators/index.d.ts +30 -30
  124. package/dist/{src → sync}/operators/intersect.d.ts +2 -2
  125. package/dist/sync/operators/isEqual.d.ts +1 -0
  126. package/dist/sync/operators/isRelation.d.ts +2 -0
  127. package/dist/{src/src → sync}/operators/join.d.ts +2 -2
  128. package/dist/{src/src → sync}/operators/left_join.d.ts +2 -2
  129. package/dist/{src → sync}/operators/matching.d.ts +2 -2
  130. package/dist/{src → sync}/operators/minus.d.ts +2 -2
  131. package/dist/{src → sync}/operators/not_matching.d.ts +2 -2
  132. package/dist/{src/src → sync}/operators/one.d.ts +2 -2
  133. package/dist/{src/src → sync}/operators/prefix.d.ts +2 -2
  134. package/dist/{src → sync}/operators/project.d.ts +2 -2
  135. package/dist/{src/src → sync}/operators/rename.d.ts +2 -2
  136. package/dist/{src/src → sync}/operators/restrict.d.ts +2 -2
  137. package/dist/{src/src → sync}/operators/suffix.d.ts +2 -2
  138. package/dist/{src/src → sync}/operators/summarize.d.ts +2 -2
  139. package/dist/{src/src → sync}/operators/transform.d.ts +2 -2
  140. package/dist/{src → sync}/operators/ungroup.d.ts +2 -2
  141. package/dist/{src/src → sync}/operators/union.d.ts +2 -2
  142. package/dist/{src/src → sync}/operators/unwrap.d.ts +2 -2
  143. package/dist/{src → sync}/operators/where.d.ts +1 -1
  144. package/dist/{src/src → sync}/operators/wrap.d.ts +2 -2
  145. package/dist/{src/src → sync}/operators/yByX.d.ts +2 -2
  146. package/dist/{src/src/types.d.ts → types.d.ts} +169 -101
  147. package/dist/writer/Text.d.ts +40 -0
  148. package/dist/writer/index.d.ts +1 -0
  149. package/package.json +6 -4
  150. package/src/Relation/index.ts +2 -1
  151. package/src/async/Relation/Base.ts +245 -0
  152. package/src/async/Relation/index.ts +31 -0
  153. package/src/async/operators/_helpers.ts +60 -0
  154. package/src/async/operators/autowrap.ts +31 -0
  155. package/src/async/operators/constants.ts +26 -0
  156. package/src/async/operators/cross_product.ts +39 -0
  157. package/src/async/operators/extend.ts +36 -0
  158. package/src/async/operators/group.ts +61 -0
  159. package/src/async/operators/image.ts +42 -0
  160. package/src/async/operators/index.ts +28 -0
  161. package/src/async/operators/intersect.ts +28 -0
  162. package/src/async/operators/isEqual.ts +39 -0
  163. package/src/async/operators/join.ts +39 -0
  164. package/src/async/operators/left_join.ts +55 -0
  165. package/src/async/operators/matching.ts +39 -0
  166. package/src/async/operators/minus.ts +28 -0
  167. package/src/async/operators/not_matching.ts +39 -0
  168. package/src/async/operators/one.ts +25 -0
  169. package/src/async/operators/prefix.ts +15 -0
  170. package/src/async/operators/project.ts +64 -0
  171. package/src/async/operators/rename.ts +33 -0
  172. package/src/async/operators/restrict.ts +61 -0
  173. package/src/async/operators/suffix.ts +15 -0
  174. package/src/async/operators/summarize.ts +90 -0
  175. package/src/async/operators/toArray.ts +18 -0
  176. package/src/async/operators/transform.ts +43 -0
  177. package/src/async/operators/ungroup.ts +43 -0
  178. package/src/async/operators/union.ts +29 -0
  179. package/src/async/operators/unwrap.ts +31 -0
  180. package/src/async/operators/wrap.ts +32 -0
  181. package/src/async/operators/yByX.ts +19 -0
  182. package/src/async/types.ts +86 -0
  183. package/src/async.ts +4 -0
  184. package/src/index.ts +17 -4
  185. package/src/lib-definitions.ts +292 -0
  186. package/src/operators/index.ts +2 -31
  187. package/src/{Relation → sync/Relation}/Memory.ts +22 -13
  188. package/{dist/src/Relation/index.d.ts → src/sync/Relation/index.ts} +1 -1
  189. package/src/{operators → sync/operators}/_helpers.ts +1 -1
  190. package/src/{operators → sync/operators}/allbut.ts +1 -1
  191. package/src/{operators → sync/operators}/autowrap.ts +1 -1
  192. package/src/{operators → sync/operators}/constants.ts +1 -1
  193. package/src/{operators → sync/operators}/cross_product.ts +1 -1
  194. package/src/{operators → sync/operators}/exclude.ts +2 -2
  195. package/src/{operators → sync/operators}/extend.ts +1 -1
  196. package/src/{operators → sync/operators}/group.ts +2 -2
  197. package/src/{operators → sync/operators}/image.ts +2 -2
  198. package/src/sync/operators/index.ts +31 -0
  199. package/src/{operators → sync/operators}/intersect.ts +1 -1
  200. package/src/{operators → sync/operators}/isEqual.ts +1 -2
  201. package/src/sync/operators/isRelation.ts +6 -0
  202. package/src/{operators → sync/operators}/join.ts +1 -1
  203. package/src/{operators → sync/operators}/left_join.ts +1 -1
  204. package/src/{operators → sync/operators}/matching.ts +1 -1
  205. package/src/{operators → sync/operators}/minus.ts +1 -1
  206. package/src/{operators → sync/operators}/not_matching.ts +1 -1
  207. package/src/{operators → sync/operators}/one.ts +1 -1
  208. package/src/{operators → sync/operators}/prefix.ts +1 -1
  209. package/src/{operators → sync/operators}/project.ts +1 -1
  210. package/src/{operators → sync/operators}/rename.ts +1 -1
  211. package/src/{operators → sync/operators}/restrict.ts +2 -2
  212. package/src/{operators → sync/operators}/suffix.ts +1 -1
  213. package/src/{operators → sync/operators}/summarize.ts +1 -1
  214. package/src/{operators → sync/operators}/transform.ts +1 -1
  215. package/src/{operators → sync/operators}/ungroup.ts +1 -1
  216. package/src/{operators → sync/operators}/union.ts +1 -1
  217. package/src/{operators → sync/operators}/unwrap.ts +1 -1
  218. package/{dist/src/src/operators/where.d.ts → src/sync/operators/where.ts} +1 -1
  219. package/src/{operators → sync/operators}/wrap.ts +1 -1
  220. package/src/{operators → sync/operators}/yByX.ts +1 -1
  221. package/src/types.ts +153 -54
  222. package/src/writer/Text.ts +305 -0
  223. package/src/writer/index.ts +1 -0
  224. package/dist/src/Relation.d.ts +0 -8
  225. package/dist/src/index.d.ts +0 -27
  226. package/dist/src/operators/isEqual.d.ts +0 -2
  227. package/dist/src/operators/isRelation.d.ts +0 -1
  228. package/dist/src/src/index.d.ts +0 -27
  229. package/dist/src/src/operators/index.d.ts +0 -30
  230. package/dist/src/src/operators/isEqual.d.ts +0 -2
  231. package/dist/src/src/operators/isRelation.d.ts +0 -1
  232. package/dist/src/src/utility-types.d.ts +0 -43
  233. package/dist/src/support/toPredicateFunc.d.ts +0 -2
  234. package/dist/src/tests/bmg.test.d.ts +0 -1
  235. package/dist/src/tests/fixtures.d.ts +0 -6
  236. package/dist/src/tests/operators/allbut.test.d.ts +0 -1
  237. package/dist/src/tests/operators/autowrap.test.d.ts +0 -1
  238. package/dist/src/tests/operators/constants.test.d.ts +0 -1
  239. package/dist/src/tests/operators/cross_product.test.d.ts +0 -1
  240. package/dist/src/tests/operators/exclude.test.d.ts +0 -1
  241. package/dist/src/tests/operators/extend.test.d.ts +0 -1
  242. package/dist/src/tests/operators/group.test.d.ts +0 -1
  243. package/dist/src/tests/operators/image.test.d.ts +0 -1
  244. package/dist/src/tests/operators/intersect.test.d.ts +0 -1
  245. package/dist/src/tests/operators/isEqual.test.d.ts +0 -1
  246. package/dist/src/tests/operators/join.test.d.ts +0 -1
  247. package/dist/src/tests/operators/left_join.test.d.ts +0 -1
  248. package/dist/src/tests/operators/matching.test.d.ts +0 -1
  249. package/dist/src/tests/operators/minus.test.d.ts +0 -1
  250. package/dist/src/tests/operators/not_matching.test.d.ts +0 -1
  251. package/dist/src/tests/operators/one.test.d.ts +0 -1
  252. package/dist/src/tests/operators/prefix.test.d.ts +0 -1
  253. package/dist/src/tests/operators/project.test.d.ts +0 -1
  254. package/dist/src/tests/operators/rename.test.d.ts +0 -1
  255. package/dist/src/tests/operators/restrict.test.d.ts +0 -1
  256. package/dist/src/tests/operators/suffix.test.d.ts +0 -1
  257. package/dist/src/tests/operators/summarize.test.d.ts +0 -1
  258. package/dist/src/tests/operators/transform.test.d.ts +0 -1
  259. package/dist/src/tests/operators/ungroup.test.d.ts +0 -1
  260. package/dist/src/tests/operators/union.test.d.ts +0 -1
  261. package/dist/src/tests/operators/unwrap.test.d.ts +0 -1
  262. package/dist/src/tests/operators/where.test.d.ts +0 -1
  263. package/dist/src/tests/operators/wrap.test.d.ts +0 -1
  264. package/dist/src/tests/operators/yByX.test.d.ts +0 -1
  265. package/dist/src/tests/types/relation.test.d.ts +0 -1
  266. package/dist/src/types.d.ts +0 -101
  267. package/dist/src/utility-types.d.ts +0 -43
  268. package/dist/tests/bmg.test.d.ts +0 -1
  269. package/dist/tests/fixtures.d.ts +0 -6
  270. package/dist/tests/operators/allbut.test.d.ts +0 -1
  271. package/dist/tests/operators/autowrap.test.d.ts +0 -1
  272. package/dist/tests/operators/constants.test.d.ts +0 -1
  273. package/dist/tests/operators/cross_product.test.d.ts +0 -1
  274. package/dist/tests/operators/exclude.test.d.ts +0 -1
  275. package/dist/tests/operators/extend.test.d.ts +0 -1
  276. package/dist/tests/operators/group.test.d.ts +0 -1
  277. package/dist/tests/operators/image.test.d.ts +0 -1
  278. package/dist/tests/operators/intersect.test.d.ts +0 -1
  279. package/dist/tests/operators/isEqual.test.d.ts +0 -1
  280. package/dist/tests/operators/join.test.d.ts +0 -1
  281. package/dist/tests/operators/left_join.test.d.ts +0 -1
  282. package/dist/tests/operators/matching.test.d.ts +0 -1
  283. package/dist/tests/operators/minus.test.d.ts +0 -1
  284. package/dist/tests/operators/not_matching.test.d.ts +0 -1
  285. package/dist/tests/operators/one.test.d.ts +0 -1
  286. package/dist/tests/operators/prefix.test.d.ts +0 -1
  287. package/dist/tests/operators/project.test.d.ts +0 -1
  288. package/dist/tests/operators/rename.test.d.ts +0 -1
  289. package/dist/tests/operators/restrict.test.d.ts +0 -1
  290. package/dist/tests/operators/suffix.test.d.ts +0 -1
  291. package/dist/tests/operators/summarize.test.d.ts +0 -1
  292. package/dist/tests/operators/transform.test.d.ts +0 -1
  293. package/dist/tests/operators/ungroup.test.d.ts +0 -1
  294. package/dist/tests/operators/union.test.d.ts +0 -1
  295. package/dist/tests/operators/unwrap.test.d.ts +0 -1
  296. package/dist/tests/operators/where.test.d.ts +0 -1
  297. package/dist/tests/operators/wrap.test.d.ts +0 -1
  298. package/dist/tests/operators/yByX.test.d.ts +0 -1
  299. package/dist/tests/types/relation.test.d.ts +0 -1
  300. package/src/operators/isRelation.ts +0 -5
  301. package/src/utility-types.ts +0 -77
  302. /package/{src/operators/where.ts → dist/operators/where.d.ts} +0 -0
@@ -1,4 +1,4 @@
1
- import { RelationOperand, AttrName, Tuple } from "../types";
1
+ import { RelationOperand, AttrName, Tuple } from "../../types";
2
2
  import { toOperationalOperand } from "./_helpers";
3
3
 
4
4
  export const unwrap = (operand: RelationOperand, attr: AttrName): RelationOperand => {
@@ -1 +1 @@
1
- export { restrict as where } from './restrict';
1
+ export { restrict as where } from './restrict';
@@ -1,4 +1,4 @@
1
- import { RelationOperand, AttrName, Tuple } from "../types";
1
+ import { RelationOperand, AttrName, Tuple } from "../../types";
2
2
  import { toOperationalOperand } from "./_helpers";
3
3
 
4
4
  export const wrap = (operand: RelationOperand, attrs: AttrName[], as: AttrName): RelationOperand => {
@@ -1,4 +1,4 @@
1
- import { AttrName, RelationOperand, Tuple } from "../types";
1
+ import { AttrName, RelationOperand, Tuple } from "../../types";
2
2
  import { toOperationalOperand } from "./_helpers";
3
3
 
4
4
  export const yByX = (operand: RelationOperand, y: AttrName, x: AttrName): Tuple => {
package/src/types.ts CHANGED
@@ -1,36 +1,118 @@
1
- import type {
2
- RenameMap, Renamed,
3
- Prefixed, Suffixed,
4
- Joined, LeftJoined,
5
- Wrapped, Unwrapped,
6
- AggregatorResults
7
- } from './utility-types';
1
+ /**
2
+ * Type definitions for Bmg.js relational algebra library.
3
+ *
4
+ * This file defines all types needed for type-safe relational operations:
5
+ * - Base types (AttrName, Tuple)
6
+ * - Utility types for transformations (Renamed, Prefixed, Joined, etc.)
7
+ * - The Relation interface with all operators
8
+ * - Helper types for predicates, extensions, aggregators, etc.
9
+ */
10
+
11
+ // ============================================================================
12
+ // Base Types
13
+ // ============================================================================
14
+
15
+ /** Attribute name in a tuple */
16
+ export type AttrName = string
17
+
18
+ /** A tuple is a record mapping attribute names to values */
19
+ export type Tuple = Record<AttrName, unknown>
20
+
21
+ // ============================================================================
22
+ // Rename Types
23
+ // ============================================================================
24
+
25
+ /** Map from old attribute names to new attribute names */
26
+ export type RenameMap<T> = { [K in keyof T]?: string };
27
+
28
+ /** Transform tuple type by renaming keys according to RenameMap */
29
+ export type Renamed<T, R extends RenameMap<T>> = {
30
+ [K in keyof T as K extends keyof R ? (R[K] extends string ? R[K] : K) : K]: T[K];
31
+ };
8
32
 
9
33
  // ============================================================================
10
- // Group/Ungroup Types (defined here due to Relation dependency)
34
+ // Prefix/Suffix Types
11
35
  // ============================================================================
12
36
 
37
+ /** Prefix all keys except those in Except */
38
+ export type Prefixed<T, P extends string, Except extends keyof T = never> = {
39
+ [K in keyof T as K extends Except ? K : `${P}${K & string}`]: T[K];
40
+ };
41
+
42
+ /** Suffix all keys except those in Except */
43
+ export type Suffixed<T, S extends string, Except extends keyof T = never> = {
44
+ [K in keyof T as K extends Except ? K : `${K & string}${S}`]: T[K];
45
+ };
46
+
47
+ // ============================================================================
48
+ // Join Types
49
+ // ============================================================================
50
+
51
+ /** Extract common keys between two tuple types */
52
+ export type CommonKeys<L, R> = Extract<keyof L, keyof R>;
53
+
54
+ /** Result of inner join: L & R with R's common keys removed */
55
+ export type Joined<L, R> = L & Omit<R, CommonKeys<L, R>>;
56
+
57
+ /** Result of left join: L & optional R attributes (common keys removed) */
58
+ export type LeftJoined<L, R> = L & Partial<Omit<R, CommonKeys<L, R>>>;
59
+
60
+ /**
61
+ * Typed join keys for array form: keys must exist on BOTH operands.
62
+ * Example: suppliers.join(parts, ['city']) - 'city' must be a key of both.
63
+ */
64
+ export type TypedJoinKeysArray<L, R> = (keyof L & keyof R & string)[];
65
+
66
+ /**
67
+ * Typed join keys for object form: maps left keys to right keys.
68
+ * Example: suppliers.join(parts, { sid: 'supplier_id' })
69
+ * - Left key (sid) must exist on L
70
+ * - Right key (supplier_id) must exist on R
71
+ */
72
+ export type TypedJoinKeysObject<L, R> = { [K in keyof L & string]?: keyof R & string };
73
+
74
+ // ============================================================================
75
+ // Wrap/Unwrap Types
76
+ // ============================================================================
77
+
78
+ /** Result of wrap: remove wrapped attrs, add nested object */
79
+ export type Wrapped<T, K extends keyof T, As extends string> =
80
+ Omit<T, K> & Record<As, Pick<T, K>>;
81
+
82
+ /** Result of unwrap: remove object attr, spread its properties */
83
+ export type Unwrapped<T, K extends keyof T> =
84
+ T[K] extends Record<string, unknown> ? Omit<T, K> & T[K] : Omit<T, K>;
85
+
13
86
  /** Result of ungroup: remove relation attr, flatten its tuple type */
14
87
  export type Ungrouped<T, K extends keyof T> =
15
88
  T[K] extends Relation<infer N> ? Omit<T, K> & N : Omit<T, K>;
16
89
 
17
- export type AttrName = string
18
- export type Tuple = Record<AttrName, unknown>
90
+ // ============================================================================
91
+ // Aggregator Types
92
+ // ============================================================================
19
93
 
20
- export interface PrefixOptions {
21
- except?: AttrName[]
22
- }
94
+ export type AggregatorName = 'count' | 'sum' | 'min' | 'max' | 'avg' | 'collect'
95
+ export type AggregatorSpec = { op: AggregatorName, attr: AttrName }
96
+ export type AggregatorFunc = (tuples: Tuple[]) => unknown
97
+ export type Aggregator = AggregatorName | AggregatorSpec | AggregatorFunc
98
+ export type Aggregators = Record<AttrName, Aggregator>
23
99
 
24
- export interface SuffixOptions {
25
- except?: AttrName[]
26
- }
100
+ /** Infer result type from aggregator specification */
101
+ export type AggregatorResult<A> =
102
+ A extends 'count' ? number :
103
+ A extends { op: 'count' } ? number :
104
+ A extends { op: 'sum' | 'avg' | 'min' | 'max' } ? number | null :
105
+ A extends { op: 'collect' } ? unknown[] :
106
+ A extends (tuples: Tuple[]) => infer R ? R :
107
+ unknown;
27
108
 
28
- export interface AutowrapOptions {
29
- separator?: string
30
- }
109
+ /** Map aggregator definitions to their result types */
110
+ export type AggregatorResults<Aggs extends Record<string, unknown>> = {
111
+ [K in keyof Aggs]: AggregatorResult<Aggs[K]>;
112
+ };
31
113
 
32
114
  // ============================================================================
33
- // Typed Predicates
115
+ // Predicate Types
34
116
  // ============================================================================
35
117
 
36
118
  /** Predicate function that receives a typed tuple */
@@ -39,8 +121,12 @@ export type TypedPredicateFunc<T> = (t: T) => boolean
39
121
  /** Predicate: either a partial tuple for equality matching, or a function */
40
122
  export type TypedPredicate<T> = Partial<T> | TypedPredicateFunc<T>
41
123
 
124
+ // Legacy predicate types (for backwards compatibility with standalone operators)
125
+ export type PredicateFunc = ((t: Tuple) => any)
126
+ export type Predicate = Tuple | PredicateFunc
127
+
42
128
  // ============================================================================
43
- // Typed Extensions
129
+ // Extension Types
44
130
  // ============================================================================
45
131
 
46
132
  /** Extension function that receives a typed tuple */
@@ -51,8 +137,43 @@ export type TypedExtension<T, E extends Record<string, unknown>> = {
51
137
  [K in keyof E]: TypedExtensionFunc<T, E[K]> | keyof T;
52
138
  }
53
139
 
140
+ export type ExtensionFunc = (tuple: Tuple) => unknown
141
+ export type Extension = Record<AttrName, ExtensionFunc | AttrName>
142
+
54
143
  // ============================================================================
55
- // Generic Relation Interface
144
+ // Other Helper Types
145
+ // ============================================================================
146
+
147
+ export interface PrefixOptions {
148
+ except?: AttrName[]
149
+ }
150
+
151
+ export interface TextOptions {
152
+ /** Precision for floating point numbers (default: 3) */
153
+ floatPrecision?: number;
154
+ /** Maximum width to trim output at */
155
+ trimAt?: number;
156
+ }
157
+
158
+ export interface SuffixOptions {
159
+ except?: AttrName[]
160
+ }
161
+
162
+ export interface AutowrapOptions {
163
+ separator?: string
164
+ }
165
+
166
+ export type Renaming = RenamingObj | RenamingFunc
167
+ export type RenamingFunc = (attr: AttrName) => AttrName
168
+ export type RenamingObj = Record<AttrName, AttrName>
169
+
170
+ export type JoinKeys = AttrName[] | Record<AttrName, AttrName>
171
+
172
+ export type TransformFunc = (value: unknown) => unknown
173
+ export type Transformation = TransformFunc | TransformFunc[] | Record<AttrName, TransformFunc | TransformFunc[]>
174
+
175
+ // ============================================================================
176
+ // Relation Interface
56
177
  // ============================================================================
57
178
 
58
179
  /**
@@ -102,19 +223,19 @@ export interface Relation<T = Tuple> {
102
223
 
103
224
  // === Semi-join operators (preserve left type) ===
104
225
 
105
- matching<R>(right: RelationOperand<R>, keys?: JoinKeys): Relation<T>
106
- not_matching<R>(right: RelationOperand<R>, keys?: JoinKeys): Relation<T>
226
+ matching<R>(right: RelationOperand<R>, keys?: TypedJoinKeysArray<T, R> | TypedJoinKeysObject<T, R>): Relation<T>
227
+ not_matching<R>(right: RelationOperand<R>, keys?: TypedJoinKeysArray<T, R> | TypedJoinKeysObject<T, R>): Relation<T>
107
228
 
108
229
  // === Join operators ===
109
230
 
110
- join<R>(right: RelationOperand<R>, keys?: JoinKeys): Relation<Joined<T, R>>
111
- left_join<R>(right: RelationOperand<R>, keys?: JoinKeys): Relation<LeftJoined<T, R>>
231
+ join<R>(right: RelationOperand<R>, keys?: TypedJoinKeysArray<T, R> | TypedJoinKeysObject<T, R>): Relation<Joined<T, R>>
232
+ left_join<R>(right: RelationOperand<R>, keys?: TypedJoinKeysArray<T, R> | TypedJoinKeysObject<T, R>): Relation<LeftJoined<T, R>>
112
233
  cross_product<R>(right: RelationOperand<R>): Relation<T & R>
113
234
  cross_join<R>(right: RelationOperand<R>): Relation<T & R>
114
235
 
115
236
  // === Nesting operators ===
116
237
 
117
- image<R, As extends string>(right: RelationOperand<R>, as: As, keys?: JoinKeys): Relation<T & Record<As, Relation<Omit<R, keyof T & keyof R>>>>
238
+ image<R, As extends string>(right: RelationOperand<R>, as: As, keys?: TypedJoinKeysArray<T, R> | TypedJoinKeysObject<T, R>): Relation<T & Record<As, Relation<Omit<R, keyof T & keyof R>>>>
118
239
  group<K extends keyof T, As extends string>(attrs: K[], as: As): Relation<Omit<T, K> & Record<As, Relation<Pick<T, K>>>>
119
240
  ungroup<K extends keyof T>(attr: K): Relation<Ungrouped<T, K>>
120
241
  wrap<K extends keyof T, As extends string>(attrs: K[], as: As): Relation<Wrapped<T, K, As>>
@@ -138,10 +259,14 @@ export interface Relation<T = Tuple> {
138
259
  yByX<Y extends keyof T, X extends keyof T>(y: Y, x: X): Record<T[X] & PropertyKey, T[Y]>
139
260
  toArray(): T[]
140
261
  isEqual(right: any): boolean
262
+
263
+ // === Display ===
264
+
265
+ toText(options?: TextOptions): string
141
266
  }
142
267
 
143
268
  // ============================================================================
144
- // Operands and Helpers
269
+ // Operands
145
270
  // ============================================================================
146
271
 
147
272
  export type RelationOperand<T = Tuple> = Relation<T> | T[]
@@ -150,29 +275,3 @@ export interface OperationalOperand<T = Tuple> {
150
275
  tuples(): Iterable<T>
151
276
  output(tuples: T[]): RelationOperand<T>
152
277
  }
153
-
154
- // Legacy predicate types (for backwards compatibility with standalone operators)
155
- export type PredicateFunc = ((t: Tuple) => any)
156
- export type Predicate = Tuple | PredicateFunc
157
-
158
- export type Renaming = RenamingObj | RenamingFunc
159
- export type RenamingFunc = (attr: AttrName) => AttrName
160
- export type RenamingObj = Record<AttrName, AttrName>
161
-
162
- export type ExtensionFunc = (tuple: Tuple) => unknown
163
- export type Extension = Record<AttrName, ExtensionFunc | AttrName>
164
-
165
- export type JoinKeys = AttrName[] | Record<AttrName, AttrName>
166
-
167
- export type AggregatorName = 'count' | 'sum' | 'min' | 'max' | 'avg' | 'collect'
168
- export type AggregatorSpec = { op: AggregatorName, attr: AttrName }
169
- export type AggregatorFunc = (tuples: Tuple[]) => unknown
170
- export type Aggregator = AggregatorName | AggregatorSpec | AggregatorFunc
171
- export type Aggregators = Record<AttrName, Aggregator>
172
-
173
- export type TransformFunc = (value: unknown) => unknown
174
- export type Transformation = TransformFunc | TransformFunc[] | Record<AttrName, TransformFunc | TransformFunc[]>
175
-
176
- // Re-export utility types for convenience
177
- export type { RenameMap, Renamed, Prefixed, Suffixed, Joined, LeftJoined, Wrapped, Unwrapped } from './utility-types';
178
- // Ungrouped is defined in this file (not utility-types) due to Relation dependency
@@ -0,0 +1,305 @@
1
+ import { Relation, Tuple } from '../types';
2
+ import { isRelation } from '../sync/operators/isRelation';
3
+
4
+ /**
5
+ * Options for text rendering
6
+ */
7
+ export interface TextOptions {
8
+ /** Format string for floating point numbers (default: '%.3f' style) */
9
+ floatPrecision?: number;
10
+ /** Maximum width to trim output at */
11
+ trimAt?: number;
12
+ }
13
+
14
+ // Type guards
15
+ const isTupleLike = (t: unknown): t is Tuple =>
16
+ t !== null && typeof t === 'object' && !Array.isArray(t);
17
+
18
+ const isRelationLike = (r: unknown): r is Relation | Tuple[] =>
19
+ isRelation(r) || (Array.isArray(r) && r.every(isTupleLike));
20
+
21
+ /**
22
+ * Utility function to get max of two nullable numbers
23
+ */
24
+ const max = (x: number | null, y: number | null): number => {
25
+ if (x === null) return y ?? 0;
26
+ if (y === null) return x;
27
+ return x > y ? x : y;
28
+ };
29
+
30
+ /**
31
+ * Represents a single cell in the table
32
+ */
33
+ class Cell {
34
+ private value: unknown;
35
+ private renderer: TextWriter;
36
+ private _textRendering: string | null = null;
37
+ private _minWidth: number | null = null;
38
+
39
+ constructor(renderer: TextWriter, value: unknown) {
40
+ this.renderer = renderer;
41
+ this.value = value;
42
+ }
43
+
44
+ get minWidth(): number {
45
+ if (this._minWidth === null) {
46
+ this._minWidth = this.renderingLines().reduce(
47
+ (maxLen, line) => max(maxLen, line.length),
48
+ 0
49
+ );
50
+ }
51
+ return this._minWidth;
52
+ }
53
+
54
+ renderingLines(size?: number): string[] {
55
+ if (size === undefined) {
56
+ return this.textRendering.split('\n');
57
+ } else if (typeof this.value === 'number') {
58
+ // Right-align numbers
59
+ return this.renderingLines().map(l => l.padStart(size));
60
+ } else {
61
+ // Left-align other values
62
+ return this.renderingLines().map(l => l.padEnd(size));
63
+ }
64
+ }
65
+
66
+ get textRendering(): string {
67
+ if (this._textRendering === null) {
68
+ this._textRendering = this.computeTextRendering();
69
+ }
70
+ return this._textRendering;
71
+ }
72
+
73
+ private computeTextRendering(): string {
74
+ const value = this.value;
75
+
76
+ if (value === null) {
77
+ return '[null]';
78
+ }
79
+ if (value === undefined) {
80
+ return '[undefined]';
81
+ }
82
+ if (typeof value === 'symbol') {
83
+ return value.toString();
84
+ }
85
+ if (typeof value === 'number') {
86
+ if (Number.isInteger(value)) {
87
+ return String(value);
88
+ }
89
+ const precision = this.renderer.options.floatPrecision ?? 3;
90
+ return value.toFixed(precision);
91
+ }
92
+ if (isRelationLike(value)) {
93
+ return this.renderer.render(value, '');
94
+ }
95
+ if (Array.isArray(value)) {
96
+ return this.arrayRendering(value);
97
+ }
98
+ if (value instanceof Date) {
99
+ return value.toISOString();
100
+ }
101
+ if (typeof value === 'object') {
102
+ return JSON.stringify(value);
103
+ }
104
+ return String(value);
105
+ }
106
+
107
+ private arrayRendering(value: unknown[]): string {
108
+ if (value.length > 0 && isTupleLike(value[0])) {
109
+ return this.renderer.render(value as Tuple[], '');
110
+ }
111
+ if (value.length === 0) {
112
+ return '[]';
113
+ }
114
+ const values = value.map(x => {
115
+ const cell = new Cell(this.renderer, x);
116
+ return cell.textRendering;
117
+ });
118
+ const totalLength = values.reduce((sum, s) => sum + s.length, 0);
119
+ if (totalLength < 20) {
120
+ return '[' + values.join(', ') + ']';
121
+ } else {
122
+ return '[' + values.join(',\n ') + ']';
123
+ }
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Represents a row of cells in the table
129
+ */
130
+ class Row {
131
+ private cells: Cell[];
132
+
133
+ constructor(renderer: TextWriter, values: unknown[]) {
134
+ this.cells = values.map(v => new Cell(renderer, v));
135
+ }
136
+
137
+ minWidths(): number[] {
138
+ return this.cells.map(cell => cell.minWidth);
139
+ }
140
+
141
+ renderingLines(sizes: number[]): string[] {
142
+ let nbLines = 0;
143
+ const byCell = this.cells.map((cell, i) => {
144
+ const lines = cell.renderingLines(sizes[i]);
145
+ nbLines = max(nbLines, lines.length);
146
+ return lines;
147
+ });
148
+
149
+ const grid: string[] = [];
150
+ for (let lineI = 0; lineI < nbLines; lineI++) {
151
+ const lineContent = byCell
152
+ .map((cellLines, i) => cellLines[lineI] ?? ' '.repeat(sizes[i]))
153
+ .join(' | ');
154
+ grid.push('| ' + lineContent + ' |');
155
+ }
156
+
157
+ return grid.length === 0 ? ['| |'] : grid;
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Represents the entire table structure
163
+ */
164
+ class Table {
165
+ private renderer: TextWriter;
166
+ private header: Row;
167
+ private rows: Row[];
168
+ private _sizes: number[] | null = null;
169
+ private _sep: string | null = null;
170
+
171
+ constructor(renderer: TextWriter, records: unknown[][], attributes: string[]) {
172
+ this.renderer = renderer;
173
+ this.header = new Row(renderer, attributes);
174
+ this.rows = records.map(r => new Row(renderer, r));
175
+ }
176
+
177
+ get sizes(): number[] {
178
+ if (this._sizes === null) {
179
+ const headerWidths = this.header.minWidths();
180
+ this._sizes = this.rows.reduce((memo, row) => {
181
+ const rowWidths = row.minWidths();
182
+ return memo.map((w, i) => max(w, rowWidths[i] ?? 0));
183
+ }, headerWidths);
184
+ }
185
+ return this._sizes;
186
+ }
187
+
188
+ get sep(): string {
189
+ if (this._sep === null) {
190
+ this._sep = '+-' + this.sizes.map(s => '-'.repeat(s)).join('-+-') + '-+';
191
+ }
192
+ return this._sep;
193
+ }
194
+
195
+ *eachLine(): Generator<string> {
196
+ const trimAt = this.renderer.options.trimAt;
197
+
198
+ if (trimAt !== undefined) {
199
+ for (const line of this.eachLineRaw()) {
200
+ yield line.substring(0, trimAt);
201
+ }
202
+ } else {
203
+ yield* this.eachLineRaw();
204
+ }
205
+ }
206
+
207
+ private *eachLineRaw(): Generator<string> {
208
+ yield this.sep;
209
+ yield this.header.renderingLines(this.sizes)[0];
210
+ yield this.sep;
211
+ for (const row of this.rows) {
212
+ for (const line of row.renderingLines(this.sizes)) {
213
+ yield line;
214
+ }
215
+ }
216
+ yield this.sep;
217
+ }
218
+
219
+ *[Symbol.iterator](): Generator<string> {
220
+ for (const line of this.eachLine()) {
221
+ yield line.trimEnd() + '\n';
222
+ }
223
+ }
224
+
225
+ toString(): string {
226
+ let result = '';
227
+ for (const line of this) {
228
+ result += line;
229
+ }
230
+ return result;
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Text writer for rendering relations as ASCII tables
236
+ */
237
+ export class TextWriter {
238
+ readonly options: TextOptions;
239
+
240
+ constructor(options: TextOptions = {}) {
241
+ this.options = options;
242
+ }
243
+
244
+ /**
245
+ * Renders a relation or tuple array to an ASCII table string
246
+ */
247
+ render(input: Relation | Tuple[] | Tuple, output: string = ''): string {
248
+ for (const line of this.eachLine(input)) {
249
+ output += line;
250
+ }
251
+ return output;
252
+ }
253
+
254
+ *eachLine(input: Relation | Tuple[] | Tuple): Generator<string> {
255
+ // Handle single tuple
256
+ let tuples: Tuple[];
257
+ if (isTupleLike(input) && !isRelation(input)) {
258
+ tuples = [input];
259
+ } else if (isRelation(input)) {
260
+ tuples = input.toArray();
261
+ } else {
262
+ tuples = input;
263
+ }
264
+
265
+ // Collect all attribute names across all tuples
266
+ const attrs = tuples.reduce((memo: string[], tuple) => {
267
+ for (const key of Object.keys(tuple)) {
268
+ if (!memo.includes(key)) {
269
+ memo.push(key);
270
+ }
271
+ }
272
+ return memo;
273
+ }, []);
274
+
275
+ // Build records array (values in attribute order)
276
+ const records = tuples.map(t => attrs.map(a => t[a]));
277
+
278
+ const table = new Table(this, records, attrs);
279
+ yield* table;
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Renders a relation as an ASCII table string
285
+ *
286
+ * @param operand - The relation or tuple array to render
287
+ * @param options - Text rendering options
288
+ * @returns ASCII table string representation
289
+ *
290
+ * @example
291
+ * const r = Bmg([{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]);
292
+ * console.log(toText(r));
293
+ * // +----+-------+
294
+ * // | id | name |
295
+ * // +----+-------+
296
+ * // | 1 | Alice |
297
+ * // | 2 | Bob |
298
+ * // +----+-------+
299
+ */
300
+ export const toText = (
301
+ operand: Relation | Tuple[] | Tuple,
302
+ options: TextOptions = {}
303
+ ): string => {
304
+ return new TextWriter(options).render(operand);
305
+ };
@@ -0,0 +1 @@
1
+ export * from './Text';
@@ -1,8 +0,0 @@
1
- import { Predicate, Tuple } from "./types";
2
- export declare class Relation {
3
- private tuples;
4
- constructor(tuples: Tuple[]);
5
- restrict(p: Predicate): Relation;
6
- one(): Tuple;
7
- toArray(): Tuple[];
8
- }
@@ -1,27 +0,0 @@
1
- export * from './operators';
2
- export * from './types';
3
- export * from './utility-types';
4
- import { MemoryRelation } from './Relation';
5
- /**
6
- * Creates a new in-memory relation from an array of tuples.
7
- *
8
- * @typeParam T - The tuple type. Inferred from input or explicitly provided.
9
- *
10
- * @example
11
- * // Untyped usage (backwards compatible)
12
- * const r = Bmg([{ id: 1, name: 'Alice' }]);
13
- *
14
- * @example
15
- * // Typed usage with explicit type parameter
16
- * interface Person { id: number; name: string }
17
- * const r = Bmg<Person>([{ id: 1, name: 'Alice' }]);
18
- * r.project(['id']); // Autocomplete suggests 'id' | 'name'
19
- *
20
- * @example
21
- * // Type is inferred from input
22
- * const r = Bmg([{ id: 1, name: 'Alice' }] as const);
23
- */
24
- export declare function Bmg<T>(tuples: T[]): MemoryRelation<T>;
25
- export declare namespace Bmg {
26
- var isRelation: (op: any) => boolean;
27
- }
@@ -1,2 +0,0 @@
1
- import { RelationOperand } from "../types";
2
- export declare const isEqual: (left: RelationOperand, right: RelationOperand) => boolean;
@@ -1 +0,0 @@
1
- export declare const isRelation: (op: any) => boolean;
@@ -1,27 +0,0 @@
1
- export * from './operators';
2
- export * from './types';
3
- export * from './utility-types';
4
- import { MemoryRelation } from './Relation';
5
- /**
6
- * Creates a new in-memory relation from an array of tuples.
7
- *
8
- * @typeParam T - The tuple type. Inferred from input or explicitly provided.
9
- *
10
- * @example
11
- * // Untyped usage (backwards compatible)
12
- * const r = Bmg([{ id: 1, name: 'Alice' }]);
13
- *
14
- * @example
15
- * // Typed usage with explicit type parameter
16
- * interface Person { id: number; name: string }
17
- * const r = Bmg<Person>([{ id: 1, name: 'Alice' }]);
18
- * r.project(['id']); // Autocomplete suggests 'id' | 'name'
19
- *
20
- * @example
21
- * // Type is inferred from input
22
- * const r = Bmg([{ id: 1, name: 'Alice' }] as const);
23
- */
24
- export declare function Bmg<T>(tuples: T[]): MemoryRelation<T>;
25
- export declare namespace Bmg {
26
- var isRelation: (op: any) => boolean;
27
- }