@dxos/util 0.5.3-main.d7fe7b5 → 0.5.3-main.eb56347

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../../src/array.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,UAAU,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC;AAE3D,MAAM,MAAM,UAAU,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI;IACjC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,OAAO,EAAE,CAAC,EAAE,CAAC;IACb,OAAO,EAAE,CAAC,EAAE,CAAC;CACd,CAAC;AAEF;;;;;GAKG;AAEH,eAAO,MAAM,IAAI,0GAwBhB,CAAC;AAGF,eAAO,MAAM,YAAY,iEACuC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=array.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array.test.d.ts","sourceRoot":"","sources":["../../../src/array.test.ts"],"names":[],"mappings":""}
@@ -1,3 +1,4 @@
1
+ export * from './array';
1
2
  export * from './assign';
2
3
  export * from './binder';
3
4
  export * from './bitfield';
@@ -28,4 +29,5 @@ export * from './weak';
28
29
  export * from './map-values';
29
30
  export * from './defer';
30
31
  export * from './circular-buffer';
32
+ export * from './join-tables';
31
33
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC;AACtB,cAAc,kBAAkB,CAAC;AACjC,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC;AACtB,cAAc,kBAAkB,CAAC;AACjC,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Joins two untyped tables on the given columns.
3
+ * @param leftColumn The column to join on in the first table.
4
+ * @param rightColumn The column to join on in the second table.
5
+ */
6
+ export declare const joinTables: (leftColumn: string, rightColumn: string, left: Record<string, any>[], right: Record<string, any>[]) => any[];
7
+ //# sourceMappingURL=join-tables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join-tables.d.ts","sourceRoot":"","sources":["../../../src/join-tables.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,eAAO,MAAM,UAAU,eACT,MAAM,eACL,MAAM,QACb,OAAO,MAAM,EAAE,GAAG,CAAC,EAAE,SACpB,OAAO,MAAM,EAAE,GAAG,CAAC,EAAE,UAwB7B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=join-tables.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join-tables.test.d.ts","sourceRoot":"","sources":["../../../src/join-tables.test.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/util",
3
- "version": "0.5.3-main.d7fe7b5",
3
+ "version": "0.5.3-main.eb56347",
4
4
  "description": "Temporary bucket for misc functions, which should graduate into separate packages.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -16,13 +16,13 @@
16
16
  "src"
17
17
  ],
18
18
  "dependencies": {
19
- "@dxos/debug": "0.5.3-main.d7fe7b5",
20
- "@dxos/keys": "0.5.3-main.d7fe7b5",
21
- "@dxos/invariant": "0.5.3-main.d7fe7b5",
22
- "@dxos/node-std": "0.5.3-main.d7fe7b5"
19
+ "@dxos/debug": "0.5.3-main.eb56347",
20
+ "@dxos/node-std": "0.5.3-main.eb56347",
21
+ "@dxos/keys": "0.5.3-main.eb56347",
22
+ "@dxos/invariant": "0.5.3-main.eb56347"
23
23
  },
24
24
  "devDependencies": {
25
- "@dxos/crypto": "0.5.3-main.d7fe7b5"
25
+ "@dxos/crypto": "0.5.3-main.eb56347"
26
26
  },
27
27
  "publishConfig": {
28
28
  "access": "public"
@@ -0,0 +1,42 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { expect } from 'chai';
6
+ import { describe, test } from 'vitest';
7
+
8
+ import { diff, intersection } from './array';
9
+
10
+ describe('diff', () => {
11
+ test('returns the difference between two sets', () => {
12
+ {
13
+ const { added, updated, removed } = diff<number>([], [], (a, b) => a === b);
14
+ expect(added).to.deep.eq([]);
15
+ expect(updated).to.deep.eq([]);
16
+ expect(removed).to.deep.eq([]);
17
+ }
18
+ {
19
+ const previous = [1, 2, 3];
20
+ const next = [2, 3, 4];
21
+ const { added, updated, removed } = diff(previous, next, (a, b) => a === b);
22
+ expect(added).to.deep.eq([4]);
23
+ expect(updated).to.deep.eq([2, 3]);
24
+ expect(removed).to.deep.eq([1]);
25
+ }
26
+ {
27
+ const previous = [{ x: 1 }, { x: 2 }, { x: 3 }];
28
+ const next = [{ x: 2 }, { x: 3 }, { x: 4 }];
29
+ const { added, updated, removed } = diff(previous, next, (a, b) => a.x === b.x);
30
+ expect(added).to.deep.eq([{ x: 4 }]);
31
+ expect(updated).to.deep.eq([{ x: 2 }, { x: 3 }]);
32
+ expect(removed).to.deep.eq([{ x: 1 }]);
33
+ }
34
+ });
35
+
36
+ test('intersection', () => {
37
+ expect(intersection([1, 2, 3], [2, 3, 4], (a, b) => a === b)).to.deep.eq([2, 3]);
38
+ expect(
39
+ intersection([{ x: 1 }, { x: 2 }, { x: 3 }], [{ x: 2 }, { x: 3 }, { x: 4 }], (a, b) => a.x === b.x),
40
+ ).to.deep.eq([{ x: 2 }, { x: 3 }]);
41
+ });
42
+ });
package/src/array.ts ADDED
@@ -0,0 +1,48 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export type Comparator<A, B = A> = (a: A, b: B) => boolean;
6
+
7
+ export type DiffResult<A, B = A> = {
8
+ added: B[];
9
+ updated: B[];
10
+ removed: A[];
11
+ };
12
+
13
+ /**
14
+ * Compute diff between two arrays.
15
+ * @param previous
16
+ * @param next
17
+ * @param comparator
18
+ */
19
+ // TODO(burdon): Factor out.
20
+ export const diff = <A, B = A>(
21
+ previous: readonly A[],
22
+ next: readonly B[],
23
+ comparator: Comparator<A, B>,
24
+ ): DiffResult<A, B> => {
25
+ const remaining = [...previous];
26
+ const result: DiffResult<A, B> = {
27
+ added: [],
28
+ updated: [],
29
+ removed: remaining,
30
+ };
31
+
32
+ // TODO(burdon): Mark and sweep.
33
+ for (const object of next) {
34
+ const index = remaining.findIndex((item) => comparator(item, object));
35
+ if (index === -1) {
36
+ result.added.push(object);
37
+ } else {
38
+ result.updated.push(object);
39
+ remaining.splice(index, 1);
40
+ }
41
+ }
42
+
43
+ return result;
44
+ };
45
+
46
+ // TODO(burdon): Factor out.
47
+ export const intersection = <A, B = A>(a: A[], b: B[], comparator: Comparator<A, B>): A[] =>
48
+ a.filter((a) => b.find((b) => comparator(a, b)) !== undefined);
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
+ export * from './array';
5
6
  export * from './assign';
6
7
  export * from './binder';
7
8
  export * from './bitfield';
@@ -32,3 +33,4 @@ export * from './weak';
32
33
  export * from './map-values';
33
34
  export * from './defer';
34
35
  export * from './circular-buffer';
36
+ export * from './join-tables';
@@ -0,0 +1,30 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { expect } from 'chai';
6
+ import { describe, test } from 'vitest';
7
+
8
+ import { joinTables } from './join-tables';
9
+
10
+ describe('joinTables', () => {
11
+ test('smoke', () => {
12
+ const left = [
13
+ { key: 1, name: 'A' },
14
+ { key: 2, name: 'B' },
15
+ ];
16
+
17
+ const right = [
18
+ { foreignKey: 1, value: 'X' },
19
+ { foreignKey: 3, value: 'Y' },
20
+ ];
21
+
22
+ const result = joinTables('key', 'foreignKey', left, right);
23
+
24
+ expect(result).to.deep.eq([
25
+ { foreignKey: 1, value: 'X', key: 1, name: 'A' },
26
+ { key: 2, name: 'B' },
27
+ { foreignKey: 3, value: 'Y' },
28
+ ]);
29
+ });
30
+ });
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Joins two untyped tables on the given columns.
3
+ * @param leftColumn The column to join on in the first table.
4
+ * @param rightColumn The column to join on in the second table.
5
+ */
6
+ //
7
+ // Copyright 2024 DXOS.org
8
+ //
9
+
10
+ export const joinTables = (
11
+ leftColumn: string,
12
+ rightColumn: string,
13
+ left: Record<string, any>[],
14
+ right: Record<string, any>[],
15
+ ) => {
16
+ const map = new Map();
17
+ const used = new Set();
18
+ for (const row of right) {
19
+ map.set(row[rightColumn], row);
20
+ }
21
+
22
+ const result = [];
23
+ for (const row of left) {
24
+ const right = map.get(row[leftColumn]);
25
+ used.add(right);
26
+
27
+ result.push(Object.assign(right ?? {}, row));
28
+ }
29
+
30
+ // Add unmatched rows from the right table.
31
+ for (const row of right) {
32
+ if (!used.has(row)) {
33
+ result.push(row);
34
+ }
35
+ }
36
+
37
+ return result;
38
+ };