Skip to content

Commit

Permalink
TS - add map, match, matchall, math, max, min function
Browse files Browse the repository at this point in the history
  • Loading branch information
elisherer committed Sep 3, 2024
1 parent be1e5df commit 59a0db4
Show file tree
Hide file tree
Showing 17 changed files with 1,068 additions and 20 deletions.
56 changes: 52 additions & 4 deletions javascript/json-transform/src/JsonHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { v4 as uuidv4 } from "uuid";
import DocumentContext from "./DocumentContext";
import { BigDecimal } from "./functions/common/FunctionHelpers";
import { areSimilar } from "@nlighten/json-schema-utils";
import { Comparator, ComparatorFactory } from "@wortise/sequency";
import CompareBy from "./functions/common/CompareBy";

const JSONPATH_ROOT = "$",
JSONPATH_ROOT_ESC = "\\$",
Expand Down Expand Up @@ -34,17 +36,17 @@ const numberCompare = (a: number, b: number) => {
return a < b ? -1 : a === b ? 0 : 1;
};

const numberType = (a: any) => typeof a === "number" || typeof a === "bigint" || a instanceof BigDecimal;
const isNumberType = (a: any) => typeof a === "number" || typeof a === "bigint" || a instanceof BigDecimal;

const compareTo = (a: any, b: any) => {
if (Array.isArray(a) && Array.isArray(b)) {
return numberCompare(a.length, b.length);
} else if (isNumberType(a) && isNumberType(b)) {
return BigDecimal(a).comparedTo(BigDecimal(b));
} else if (a && b && typeof a === "object" && typeof b === "object") {
return numberCompare(Object.keys(a).length, Object.keys(b).length);
} else if (typeof a === "string" && typeof b === "string") {
return a.localeCompare(b);
} else if (numberType(a) && numberType(b)) {
return BigDecimal(a).comparedTo(BigDecimal(b));
} else if (typeof a === "boolean" && typeof b === "boolean") {
return a === b ? 0 : a ? 1 : -1;
} else if (isNullOrUndefined(a) && !isNullOrUndefined(b)) {
Expand Down Expand Up @@ -184,7 +186,7 @@ const isEqual = (value: any, other: any): boolean => {
if (value === other) {
return true;
}
if (numberType(value) && numberType(other)) {
if (isNumberType(value) && isNumberType(other)) {
return BigDecimal(value).eq(BigDecimal(other));
}
return areSimilar(value, other);
Expand Down Expand Up @@ -301,12 +303,58 @@ function mergeInto(rootEl: Record<string, any>, value: any, path: string | null)
return root;
}

const factory = new ComparatorFactory<any>();

function createComparator(type: string | null) {
let comparator: Comparator<any>;
if (isNullOrUndefined(type) || "AUTO" === type.toUpperCase()) {
comparator = factory.compare((a, b) => compareTo(a, b) ?? 0);
} else {
switch (type.toUpperCase()) {
case "NUMBER": {
comparator = factory.compare((a, b) => {
if ((isNumberType(a) || typeof a === "string") && (isNumberType(b) || typeof b === "string")) {
return BigDecimal(a).comparedTo(BigDecimal(b));
} else if (isNullOrUndefined(a) && !isNullOrUndefined(b)) {
return -1;
} else if (!isNullOrUndefined(a) && isNullOrUndefined(b)) {
return 1;
}
return 0;
});
break;
}
case "BOOLEAN": {
comparator = factory.compare((a, b) => {
if (typeof a === "boolean" && typeof b === "boolean") {
return a === b ? 0 : a ? 1 : -1;
} else if (isNullOrUndefined(a) && !isNullOrUndefined(b)) {
return -1;
} else if (!isNullOrUndefined(a) && isNullOrUndefined(b)) {
return 1;
}
return 0;
});
break;
}
//case "STRING"
default: {
comparator = factory.compareBy(getAsString);
break;
}
}
}
return comparator;
}

export {
isNullOrUndefined,
isMap,
getAsString,
createPayloadResolver,
isNumberType,
compareTo,
createComparator,
getDocumentContext,
lenientJsonParse,
isTruthy,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { describe, test } from "vitest";
import { assertTransformation } from "../BaseTransformationTest";

describe("TransformerFunctionMap", () => {
test("testObjectFunctionMap", async () => {
const source = {
value: 5,
item: {
foo: "aaa",
id: "bbb",
},
items: [
{ foo: "bar", id: "aaa" },
{ foo: "bar2", id: "bbb" },
],
};
await assertTransformation(
source,
{
$$map: [
"$.items",
{
id: "##current.id",
map_foo: "##current.foo",
idx: "##index",
value: "$.value",
},
],
},
[
{ id: "aaa", map_foo: "bar", idx: 0, value: 5 },
{ id: "bbb", map_foo: "bar2", idx: 1, value: 5 },
],
);

await assertTransformation(
source,
{
$$map: "$.items",
to: {
id: "##current.id",
map_foo: "##current.foo",
idx: "##index",
value: "$.value",
},
},
[
{ id: "aaa", map_foo: "bar", idx: 0, value: 5 },
{ id: "bbb", map_foo: "bar2", idx: 1, value: 5 },
],
);

var valueLookup = {
$$map: [
"$.item",
{
id: "##current.id",
map_foo: "##current.foo",
idx: "##index",
value: "$.value",
},
],
};
await assertTransformation(source, valueLookup, null);
});

test("objectNonTransformed", async () => {
await assertTransformation(
{
a: [1, 2],
b: [2, 4],
},
{
$$map: [["$.a", "$.b"], "##current[1]"],
},
[2, 4],
);
});

test("inline", async () => {
await assertTransformation([{ a: 10 }, { a: 11 }, { a: 12 }], "$$map(##current.a):$", [10, 11, 12]);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { describe, test } from "vitest";
import { assertTransformation } from "../BaseTransformationTest";

describe("TransformerFunctionMatch", () => {
test("inline", async () => {
const input = "hello";
await assertTransformation(input, "$$match([le]):$", "e");
await assertTransformation(input, "$$match([le]+):$", "ell");
await assertTransformation(input, "$$match(hell):$", "hell");
await assertTransformation(input, "$$match(hello$):$", "hello");
await assertTransformation(input, "$$match(hell$):$", null);
});

test("inlineGroup", async () => {
await assertTransformation("world", "$$match('w(\\\\w+)d',1):$", "orl");
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { describe, test } from "vitest";
import { assertTransformation } from "../BaseTransformationTest";

describe("TransformerFunctionMatchAll", () => {
test("inline", async () => {
const input = "hello my helloKitty";
await assertTransformation(input, "$$matchall([el]):$", ["e", "l", "l", "e", "l", "l"]);
await assertTransformation(input, "$$matchall([le]+):$", ["ell", "ell"]);
await assertTransformation(input, "$$matchall(hell):$", ["hell", "hell"]);
await assertTransformation(input, "$$matchall(^hello):$", ["hello"]);
await assertTransformation(input, "$$matchall(hello$):$", null);
});

test("inlineGroup", async () => {
await assertTransformation("world to waterWorld", "$$matchall('w(\\\\w+)d',1):$", ["orl", "aterWorl"]);
});
});
Loading

0 comments on commit 59a0db4

Please sign in to comment.