Skip to content

Commit

Permalink
some 'shortcuts'
Browse files Browse the repository at this point in the history
  • Loading branch information
ettoreleandrotognoli committed Nov 2, 2018
1 parent 30b44a4 commit e0d8f21
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 67 deletions.
36 changes: 33 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,42 @@ export interface Parser<E> {
}

export interface ObjectParserRecipe<E> {
target: Type<E> | FunctionalParser<E> | string;
target: Type<E>;
nestedTargets?: { [fieldName: string]: ParserRecipe<any> | string };
}

export type ParserRecipe<E> = ObjectParserRecipe<E> | Type<E> | FunctionalParser<E>;
export type ParserRecipe<E> = ObjectParserRecipe<E> | FunctionalParser<E>;

export interface RepositoryRecipe {
[name: string]: ParserRecipe<any>;
}
}


/**
* @todo common-lang
*/
export const isAnounymous = (obj: any) => {
return obj.name == "";
}

const reduceToObject = (acc, [k, v]) => Object.assign(acc, { [k as string]: v });

const transformValue = it => ([k, v]) => ([k, it(v)]);

const setAtObject = obj => ([k, v]) => obj[k] = v;

export const Mappers = {
Value: transformValue
}

export const Reducers = {
Object: reduceToObject
}

export const Iter = {
SetAt: setAtObject
}

/**
* ------------
*/
33 changes: 4 additions & 29 deletions src/parser.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,7 @@
import { Type, FunctionalParser, ParserRecipe, ObjectParserRecipe, Parser } from "./";
import { Type, FunctionalParser, ParserRecipe, ObjectParserRecipe, Parser, Reducers } from "./";
import { ParserRepository } from "./repository";
import { noop, getattr } from "@huehuejs/common-lang";

/**
* @todo common-lang
*/
const isAnounymous = (obj: any) => {
return obj.name == "";
}

const reduceToObject = (acc, [k, v]) => Object.assign(acc, { [k as string]: v });

const transformValue = it => ([k, v]) => ([k, it(v)]);

const Mappers = {
Value: transformValue
}

const Reducers = {
Object: reduceToObject
}

/**
* ------------
*/
import { Mappers } from "."

class RefParser implements Parser<any>{

Expand Down Expand Up @@ -88,17 +66,14 @@ export function makeFromString(name: string): FunctionalParser<any> {

export function makeFromObjectRecipe<E>(parserRecipe: ObjectParserRecipe<E>): FunctionalParser<E> {
return new ObjectParser(
makeFromRecipe(parserRecipe.target),
Object.entries(parserRecipe.nestedTargets)
makeFromType(parserRecipe.target),
Object.entries(parserRecipe.nestedTargets || {})
.map(Mappers.Value(makeFromRecipe))
.reduce(Reducers.Object, {})
).asFunctionalParser()
}

export function makeFromRecipe<E>(parserRecipe: ParserRecipe<E> | string): FunctionalParser<E> {
if (!isAnounymous(parserRecipe) && typeof parserRecipe == "function") {
return makeFromType(parserRecipe as Type<E>);
}
if (typeof parserRecipe == "function") {
return parserRecipe as FunctionalParser<E>;
}
Expand Down
22 changes: 20 additions & 2 deletions src/repository.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FunctionalParser, Type } from "."
import { FunctionalParser, ParserRecipe, RepositoryRecipe, Mappers, Iter, Type } from "."
import { noop, getattr } from "@huehuejs/common-lang";
import { makeFromRecipe, makeFromType } from "./parser";


export interface ParserRepository {
Expand Down Expand Up @@ -40,11 +41,28 @@ export class ParserRepositoryBuilder {

}

add(name: string, parser: FunctionalParser<any>): ParserRepositoryBuilder {
addParser(name: string, parser: FunctionalParser<any>): ParserRepositoryBuilder {
this.repository[name] = parser;
return this;
}

addType(type: Type<any>) {
this.repository[type.name] = makeFromType(type);
return this;
}

addRecipe(repositoryRecipe: RepositoryRecipe): ParserRepositoryBuilder {
Object.entries(repositoryRecipe)
.map(Mappers.Value(makeFromRecipe))
.forEach(Iter.SetAt(this.repository));
return this;
}

addParserRecipe(name: string, recipe: ParserRecipe<any>): ParserRepositoryBuilder {
const parser = makeFromRecipe(recipe);
return this.addParser(name, parser);
}

build(): ParserRepository {
return asSelfFeederRepostiory(this.repository);
}
Expand Down
76 changes: 46 additions & 30 deletions test/swapi.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
import { makeFromRecipe, makeFromFunction } from "../src/parser";
import { expect } from "chai";
import { ParserRepositoryBuilder } from "../src/repository";
import { RepositoryRecipe, Parser, FunctionalParser } from "../src";



export class Planet {
name: string//"Tatooine"
rotationPeriod: number//"23"
orbitalPeriod: number//"304"
diameter: number//"10465"
climate: string//"arid"
gravity: string//"1 standard"
terrain: string//"desert"
surfaceWater: number//"1"
population: number//"200000"
residents: Array<string>
films: Array<string>
created: Date//"2014-12-09T13:50:49.641000Z"
edited: Date//"2014-12-21T20:48:04.175778Z"
url: string//"https://swapi.co/api/planets/1/"
}

const recipe: RepositoryRecipe = {
stringToNumber: makeFromFunction((it: string) => parseInt(it)),
stringToDate: makeFromFunction((it: string) => new Date(it)),
Planet: {
target: Planet,
nestedTargets: {
rotationPeriod: 'stringToNumber',
orbitalPeriod: 'stringToNumber',
diameter: 'stringToNumber',
surfaceWater: 'stringToNumber',
population: 'stringToNumber',
created: 'stringToDate',
edited: 'stringToDate',
}
}
}

const repositoryBuilder = new ParserRepositoryBuilder();
const repository = repositoryBuilder
.addRecipe(recipe)
.build();


const rawPlanet = {
name: 'Tatooine',
Expand Down Expand Up @@ -36,38 +80,10 @@ const rawPlanet = {
};


export class Planet {
name: string//"Tatooine"
rotationPeriod: number//"23"
orbitalPeriod: number//"304"
diameter: number//"10465"
climate: string//"arid"
gravity: string//"1 standard"
terrain: string//"desert"
surfaceWater: number//"1"
population: number//"200000"
residents: Array<string>
films: Array<string>
created: Date//"2014-12-09T13:50:49.641000Z"
edited: Date//"2014-12-21T20:48:04.175778Z"
url: string//"https://swapi.co/api/planets/1/"
}

const planetParser = makeFromRecipe({
target: Planet,
nestedTargets: {
rotationPeriod: makeFromFunction((it: string) => parseInt(it)),
orbitalPeriod: makeFromFunction((it: string) => parseInt(it)),
diameter: makeFromFunction((it: string) => parseInt(it)),
surfaceWater: makeFromFunction((it: string) => parseInt(it)),
population: makeFromFunction((it: string) => parseInt(it)),
created: makeFromFunction((it: string) => new Date(it)),
edited: makeFromFunction((it: string) => new Date(it)),
}
})

describe("Swapi", () => {
it("Get Planet", () => {
const planetParser = repository[Planet.name] as FunctionalParser<Planet>;
console.log(planetParser);
const planet = planetParser(rawPlanet)
expect(planet).to.instanceof(Planet)
expect(typeof planet.name).to.equals("string")
Expand Down
6 changes: 3 additions & 3 deletions test/xparser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ describe('XParser', () => {

describe("#makeFromRecipe", () => {
it('should work with only a type', () => {
const justAType: ParserRecipe<Math> = Math;
const justAType: ParserRecipe<Math> = { target: Math };
const rawData = rawMathData();
const parser = makeFromRecipe(justAType);
const mathData = parser(rawData);
Expand All @@ -126,8 +126,8 @@ describe('XParser', () => {
const rationalParser = makeFromRecipe(rationalParserRecipe);
const repositoryBuilder = new ParserRepositoryBuilder();
const repository = repositoryBuilder
.add("Rational", rationalParser)
.add("number|Rational", numberOrRationalParser)
.addParser("Rational", rationalParser)
.addParser("number|Rational", numberOrRationalParser)
.build();
it('should work with a complex type', () => {
const rawData = {
Expand Down

0 comments on commit e0d8f21

Please sign in to comment.