Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement decode method #3

Merged
merged 4 commits into from
Dec 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# TypeScript Codable

> A Typescript implementation of [Swift Codable](https://developer.apple.com/documentation/swift/codable)
another strict json parser inspired by [Swift Codable](https://developer.apple.com/documentation/swift/codable) ❤️

![Alt text](docs/cover.png 'Title')

Expand All @@ -15,7 +15,7 @@ Works almost same as [Swift Codable](https://developer.apple.com/documentation/s

## Supported Types

Types design was inspired by [mobx-state-tree](https://github.com/mobxjs/mobx-state-tree#types-overview)
Types design was inspired by [MobX State Tree](https://github.com/mobxjs/mobx-state-tree#types-overview) ❤️

- Primitives
- String
Expand All @@ -38,7 +38,7 @@ npm install ts-codable
## Usage

```ts
class Post extends Codable {
class Post extends BaseCodable {
title!: string;
isActive?: boolean;
}
Expand All @@ -51,7 +51,7 @@ Post.CodingProperties = {
},
};

class User extends Codable {
class User extends BaseCodable {
id!: number;
username!: string;
posts!: Post[];
Expand All @@ -63,7 +63,7 @@ User.CodingProperties = {
posts: types.array(Post),
};

const user: User = new User({
const user: User = decode(User, {
id: 123,
username: 'Gorhom',
posts: [
Expand Down
Binary file modified docs/cover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"decodable",
"encoding"
],
"author": "Gorhom",
"author": "Mo Gorhom",
"license": "MIT",
"bugs": {
"url": "https://github.com/Gorhom/ts-codable/issues"
Expand All @@ -48,14 +48,14 @@
"trailingComma": "es5"
},
"devDependencies": {
"@types/jest": "^24.0.17",
"@types/lodash": "^4.14.136",
"husky": "^3.0.2",
"prettier": "^1.18.2",
"pretty-quick": "^1.11.1",
"tsdx": "^0.7.2",
"@types/jest": "^24.0.24",
"@types/lodash": "^4.14.149",
"husky": "^3.1.0",
"prettier": "^1.19.1",
"pretty-quick": "^2.0.1",
"tsdx": "^0.12.0",
"tslib": "^1.10.0",
"typescript": "^3.5.3"
"typescript": "^3.7.4"
},
"dependencies": {
"lodash": "^4.17.15",
Expand Down
18 changes: 5 additions & 13 deletions src/codable.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import get from 'lodash/get';
import { ICodingPropertyType, IDictionary, decodePayload } from './internal';
import { ICodingPropertyType, IDictionary, IBaseCodable } from './internal';

export class Codable {
static CodingProperties: IDictionary<ICodingPropertyType>;
[key: string]: any;

constructor(payload: object) {
Object.assign(this, decodePayload(payload, this.getCodingProperties()));
}

private getCodingProperties = (): IDictionary<ICodingPropertyType> => {
return get(this, '__proto__.constructor.CodingProperties', {});
};
export abstract class BaseCodable implements IBaseCodable {
public static CodingProperties: IDictionary<ICodingPropertyType>;
constructor(payload: object) {}
public toJSON = () => '';
}
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { types, Codable } from './internal';
export { types, BaseCodable, decode } from './internal';
2 changes: 1 addition & 1 deletion src/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ export { optional as optionalModel } from './models/optional';
export * from './models';

export * from './utils/types';
export * from './utils/index';
export * from './utils/typecheck';
export * from './utils/decoder';
4 changes: 1 addition & 3 deletions src/models/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ export const array = (subType?: ISubType): IModel => {
const decode = (value: any[]) => {
if (validate(value)) {
if (isCodable(subType!)) {
return value.map(item =>
decodePayload(item, subType!.CodingProperties)
);
return value.map(item => decodePayload(item, subType.CodingProperties));
}
return value;
} else {
Expand Down
34 changes: 30 additions & 4 deletions src/utils/decoder.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,39 @@
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import {
models,
IType,
ICodingPropertyType,
IDictionary,
ICodable,
isCodable,
BaseCodable,
} from '../internal';
import { IModel } from './types';
import { IModel, INewable, IBaseCodable, ICodable } from './types';

export const decode = <T extends BaseCodable>(
type: INewable<T>,
json: any
): T & IBaseCodable => decodeCodable(type, json, true);

const decodeCodable = <T extends BaseCodable>(
type: INewable<T>,
json: any,
isRoot: boolean
): T & IBaseCodable => {
if (isRoot === false && isEmpty(json) === true) {
throw `Missing value for a non optional property`;
}

let result = new type(json);

// @ts-ignore
if (json !== undefined && type.CodingProperties !== undefined) {
// @ts-ignore
Object.assign(result, decodePayload(json, type.CodingProperties));
}

return result;
};

export const decodePayload = (
payload: object,
Expand All @@ -34,9 +60,9 @@ export const decodeProperty = (

export const decodeValue = (type: IType | ICodable, value?: object) => {
if (isCodable(type)) {
const object = Object.create(type.prototype);
return object.constructor.call(object, value);
return decodeCodable(type, value, false);
}

const model: IModel = models[type.name](type.subtype);
return model.validate(value) ? model.decode(value) : undefined;
};
5 changes: 0 additions & 5 deletions src/utils/index.ts

This file was deleted.

5 changes: 5 additions & 0 deletions src/utils/typecheck.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import get from 'lodash/get';
import { ISubType, BaseCodable, ICodable } from '../internal';

export const isCodable = (type: ISubType): type is ICodable =>
get(type, 'prototype', null) instanceof BaseCodable;
12 changes: 9 additions & 3 deletions src/utils/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import has from 'lodash/has';
import get from 'lodash/get';
import { Codable, types } from '../internal';
import { types, BaseCodable } from '../internal';

export interface ICodingProperty {
type: IType | ICodable;
Expand Down Expand Up @@ -31,6 +31,12 @@ export interface IDictionary<T> {
[index: string]: T;
}

export type ICodable = INewable<Codable> & {
export interface IBaseCodable {
toJSON: () => string;
}

interface IBaseCodableStatic {
CodingProperties: IDictionary<ICodingPropertyType>;
};
}

export type ICodable = INewable<BaseCodable> & IBaseCodableStatic;
Loading