Skip to content

Commit

Permalink
TS - add contains, csv, csvparse, date, digest & entries
Browse files Browse the repository at this point in the history
  • Loading branch information
elisherer committed Aug 4, 2024
1 parent c5e375c commit 0a939ef
Show file tree
Hide file tree
Showing 51 changed files with 1,969 additions and 928 deletions.
12 changes: 8 additions & 4 deletions javascript/json-transform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@
# Usage

```typescript
const transformer = new JsonTransformer("$$lower:$.x")
expect(
transformer.transform({ x: "HELLO" })
).toEqual("hello");
(async() => { // in an async context

const transformer = new JsonTransformer("$$lower:$.x")
expect(
await transformer.transform({x: "HELLO"})
).toEqual("hello");

})();
```

# License
Expand Down
56 changes: 44 additions & 12 deletions javascript/json-transform/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions javascript/json-transform/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,28 @@
"homepage": "https://github.com/nlighten-oss/json-transform#readme",
"peerDependencies": {
"@nlighten/json-schema-utils": "^1.0.2",
"@wortise/sequency": "^0.20.0",
"bignumber.js": "^9.1.2",
"date-fns": "^3.6.0",
"date-fns-tz": "^3.1.3",
"fast-json-stable-stringify": "^2.1.0",
"jsonpath": "^1.1.1",
"uuid": "^10.0.0"
},
"devDependencies": {
"@nlighten/json-schema-utils": "^1.0.2",
"@types/jsonpath": "^0.2.4",
"@types/uuid": "^10.0.0",
"@wortise/sequency": "^0.20.0",
"bignumber.js": "^9.1.2",
"date-fns": "^3.6.0",
"date-fns-tz": "^3.1.3",
"fast-json-stable-stringify": "^2.1.0",
"jsonpath": "^1.1.1",
"microbundle": "^0.15.1",
"prettier": "3.1.1",
"typescript": "^5.3.3",
"uuid": "^10.0.0",
"vitest": "1.2.2"
},
"dependencies": {
"bignumber.js": "^9.1.2",
"sequency": "^0.20.0"
}
}
21 changes: 10 additions & 11 deletions javascript/json-transform/src/JsonElementStreamer.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import FunctionContext from "./functions/common/FunctionContext";
import Sequence, { asSequence, emptySequence } from "sequency";
import { asAsyncSequence, AsyncSequence, emptyAsyncSequence } from "@wortise/sequency";

class JsonElementStreamer {
private readonly context: FunctionContext;
private readonly transformed: boolean;
private readonly value?: any[];
private readonly _stream?: Sequence<any>;
private readonly _stream?: AsyncSequence<any>;

private constructor(context: FunctionContext, value: any[] | Sequence<any>, transformed: boolean) {
private constructor(context: FunctionContext, value: any[] | AsyncSequence<any>, transformed: boolean) {
this.context = context;
this.transformed = transformed;
if (Array.isArray(value)) {
Expand All @@ -29,9 +29,9 @@ class JsonElementStreamer {
return limit > -1 ? skipped.take(limit) : skipped;
}
if (this.value == null) {
return emptySequence();
return emptyAsyncSequence();
}
let valueStream = asSequence(this.value);
let valueStream = asAsyncSequence(this.value);
if (skip > 0) {
valueStream = valueStream.drop(skip);
}
Expand All @@ -48,20 +48,19 @@ class JsonElementStreamer {
return new JsonElementStreamer(context, value, transformed);
}

public static fromTransformedStream(context: FunctionContext, stream: Sequence<any>) {
public static fromTransformedStream(context: FunctionContext, stream: AsyncSequence<any>) {
return new JsonElementStreamer(context, stream, true);
}

public toJsonArray() {
public async toJsonArray() {
if (this.value) {
return this.value;
}
const ja: any[] = [];
if (this._stream) {
this._stream.forEach(item => ja.push(item));
return this._stream.toArray();
}
return ja;
return [];
}
}

export default JsonElementStreamer;
export default JsonElementStreamer;
51 changes: 26 additions & 25 deletions javascript/json-transform/src/JsonTransformer.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import {Transformer} from "./Transformer";
import {JsonTransformerFunction} from "./JsonTransformerFunction";
import {ParameterResolver} from "./ParameterResolver";
import {createPayloadResolver, isNullOrUndefined} from "./JsonHelpers";
import { Transformer } from "./Transformer";
import { JsonTransformerFunction } from "./JsonTransformerFunction";
import { ParameterResolver } from "./ParameterResolver";
import { createPayloadResolver, isNullOrUndefined } from "./JsonHelpers";
import transformerFunctions, { TransformerFunctions } from "./transformerFunctions";
import JsonElementStreamer from "./JsonElementStreamer";

class JsonTransformer implements Transformer {

static readonly OBJ_DESTRUCT_KEY = "*";
static readonly FUNCTION_PREFIX = "$$";

Expand All @@ -18,30 +17,29 @@ class JsonTransformer implements Transformer {
this.transformerFunctions = transformerFunctions;
this.definition = definition;
this.JSON_TRANSFORMER = {
transform: this.fromJsonElement.bind(this)
transform: this.fromJsonElement.bind(this),
};
}


transform(payload: any = null, additionalContext: Record<string, any> = {}) {
async transform(payload: any = null, additionalContext: Record<string, any> = {}) {
if (isNullOrUndefined(this.definition)) {
return null;
}
const resolver : ParameterResolver = createPayloadResolver(payload, additionalContext)
const resolver: ParameterResolver = createPayloadResolver(payload, additionalContext);
return this.fromJsonElement(this.definition, resolver, false);
}

fromJsonPrimitive(definition: any, resolver: ParameterResolver, allowReturningStreams: boolean) : any {
if (typeof definition !== 'string') {
async fromJsonPrimitive(definition: any, resolver: ParameterResolver, allowReturningStreams: boolean): Promise<any> {
if (typeof definition !== "string") {
return definition ?? null;
}
try {
// test for inline function (e.g. $$function:...)
const match = this.transformerFunctions.matchInline(definition, resolver, this.JSON_TRANSFORMER);
const match = await this.transformerFunctions.matchInline(definition, resolver, this.JSON_TRANSFORMER);
if (match != null) {
const matchResult = match.getResult();
if (matchResult instanceof JsonElementStreamer) {
return allowReturningStreams ? matchResult : matchResult.toJsonArray();
return allowReturningStreams ? matchResult : await matchResult.toJsonArray();
}
return match.getResult();
}
Expand All @@ -53,29 +51,29 @@ class JsonTransformer implements Transformer {
}
}

fromJsonObject(definition: any, resolver: ParameterResolver, allowReturningStreams: boolean) : any {
const match = this.transformerFunctions.matchObject(definition, resolver, this.JSON_TRANSFORMER);
async fromJsonObject(definition: any, resolver: ParameterResolver, allowReturningStreams: boolean): Promise<any> {
const match = await this.transformerFunctions.matchObject(definition, resolver, this.JSON_TRANSFORMER);
if (match != null) {
const res = match.getResult();
if (res instanceof JsonElementStreamer) {
return allowReturningStreams ? res : res.toJsonArray();
return allowReturningStreams ? res : await res.toJsonArray();
}
return match.getResult();
}

let result: Record<string, any> = {};
if (Object.prototype.hasOwnProperty.call(definition, JsonTransformer.OBJ_DESTRUCT_KEY)) {
const val = definition[JsonTransformer.OBJ_DESTRUCT_KEY];
const res = this.fromJsonElement(val, resolver, false);
const res = await this.fromJsonElement(val, resolver, false);
if (res != null) {
const isArray = Array.isArray(val);
if (isArray && Array.isArray(res)) {
for (let i = 0; i < res.length; i++) {
if (typeof res[i] === 'object') {
if (typeof res[i] === "object") {
Object.assign(result, res[i]);
}
}
} else if (typeof res === 'object') {
} else if (typeof res === "object") {
result = res;
} else {
result[JsonTransformer.OBJ_DESTRUCT_KEY] = res;
Expand All @@ -85,23 +83,26 @@ class JsonTransformer implements Transformer {

for (const key in definition) {
if (key === JsonTransformer.OBJ_DESTRUCT_KEY) continue;
const value = this.fromJsonElement(definition[key], resolver, false);
if (!isNullOrUndefined(value) || Object.prototype.hasOwnProperty.call(result, key) /* we allow overriding with null*/) {
const value = await this.fromJsonElement(definition[key], resolver, false);
if (
!isNullOrUndefined(value) ||
Object.prototype.hasOwnProperty.call(result, key) /* we allow overriding with null*/
) {
result[key] = value;
}
}

return result;
}

fromJsonElement(definition: any, resolver: ParameterResolver, allowReturningStreams: boolean) : any {
async fromJsonElement(definition: any, resolver: ParameterResolver, allowReturningStreams: boolean): Promise<any> {
if (isNullOrUndefined(definition)) {
return null;
}
if (Array.isArray(definition)) {
return definition.map((d: any) => this.fromJsonElement(d, resolver, false));
return Promise.all(definition.map((d: any) => this.fromJsonElement(d, resolver, false)));
}
if (typeof definition === 'object') {
if (typeof definition === "object") {
return this.fromJsonObject(definition, resolver, allowReturningStreams);
}
return this.fromJsonPrimitive(definition, resolver, allowReturningStreams);
Expand All @@ -112,4 +113,4 @@ class JsonTransformer implements Transformer {
}
}

export default JsonTransformer;
export default JsonTransformer;
2 changes: 1 addition & 1 deletion javascript/json-transform/src/JsonTransformerFunction.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {ParameterResolver} from "./ParameterResolver";

export interface JsonTransformerFunction {
transform(definition: any, resolver: ParameterResolver, allowReturningStreams?: boolean): any;
transform(definition: any, resolver: ParameterResolver, allowReturningStreams?: boolean): Promise<any>;
}
23 changes: 14 additions & 9 deletions javascript/json-transform/src/__tests__/BaseTransformationTest.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import JsonTransformer from "../JsonTransformer";
import {expect} from "vitest";
import { expect } from "vitest";

export const assertTransformation = (payload: any, definition: any, output: any, additionalContext: any = {}) => {
const x = new JsonTransformer(definition)
expect(x.transform(payload, additionalContext)).toEqual(output);
}
export const assertTransformation = async (payload: any, definition: any, output: any, additionalContext: any = {}) => {
const x = new JsonTransformer(definition);
expect(await x.transform(payload, additionalContext)).toEqual(output);
};

export const assertFailTransformation = (payload: any, definition: any, output: any, additionalContext: any = {}) => {
const x = new JsonTransformer(definition)
expect(x.transform(payload, additionalContext)).not.toEqual(output);
}
export const assertFailTransformation = async (
payload: any,
definition: any,
output: any,
additionalContext: any = {},
) => {
const x = new JsonTransformer(definition);
expect(await x.transform(payload, additionalContext)).not.toEqual(output);
};
Loading

0 comments on commit 0a939ef

Please sign in to comment.