Skip to content

Commit

Permalink
WIP: Fix decorator
Browse files Browse the repository at this point in the history
  • Loading branch information
Prior99 committed Aug 9, 2018
1 parent c1550d4 commit 05e5df1
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 25 deletions.
13 changes: 11 additions & 2 deletions packages/hyrest-mobx/src/decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
populate,
ValidationOptions,
universal,
getSpecifiedType,
} from "hyrest";
import { ValidationStatus } from "./validation-status";
import { ContextFactory } from "./context-factory";
Expand Down Expand Up @@ -37,8 +38,16 @@ export function hasFields<TContext>(
const instance = new (target as any)(...args);
const { fieldProperties } = getFieldsMeta(target);
fieldProperties.forEach(({ property, modelType }) => {
const propertyMeta = universal.propertiesForClass(modelType).find(meta => meta.property === property);
(instance as any)[property] = fieldFactory(propertyMeta, contextFactory);
const { expectedType } = universal.propertiesForClass(modelType)
.find(meta => meta.property === property);
if (expectedType === Array) {
throw new Error("TODO: Assert that the specified type was set using `@specify`.");
// TODO: Is `instance.prototype` correct?
const arrayType = getSpecifiedType(instance.prototype, property).property();
(instance as any)[property] = fieldFactory(arrayType, contextFactory, false);
} else {
(instance as any)[property] = fieldFactory(modelType, contextFactory, false);
}
});
return instance;
};
Expand Down
2 changes: 1 addition & 1 deletion packages/hyrest-mobx/src/field-array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class FieldArray<TModel, TContext> extends Array<TModel> implements Reado
constructor (
modelType: Constructable<TModel>,
contextFactory: ContextFactory<TContext>,
validation: ValidationOptions<TModel, TContext>,
validation?: ValidationOptions<TModel, TContext>,
) {
super();
this.contextFactory = contextFactory;
Expand Down
26 changes: 21 additions & 5 deletions packages/hyrest-mobx/src/field-simple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
populate,
ValidationOptions,
universal,
getSpecifiedType,
} from "hyrest";
import { observable, computed, action } from "mobx";
import { ValidationStatus } from "./validation-status";
Expand Down Expand Up @@ -82,16 +83,31 @@ export class FieldSimple<TModel, TContext = any> implements BaseField<TModel> {
}, {} as Fields<TModel, TContext>);
// Create the outfacing `nested` property: Create a getter for each property which lazily initializes
// and caches the real value in `_nested`.
this.nested = this.properties.reduce((result, propertyMeta) => {
this.nested = this.properties.reduce((result, { property, expectedType, target }) => {
// Create a getter on the `fields` property which will lazily initialize all `Field`s.
Object.defineProperty(result, propertyMeta.property, {
Object.defineProperty(result, property, {
get: () => {
const key = propertyMeta.property as keyof TModel;
const key = property as keyof TModel;
if (this._nested[key] !== undefined) { return this._nested[key]; }
// The cast to `any` are neccessary as Typescript cannot deal with this
// kind of types. See https://github.com/Microsoft/TypeScript/issues/22628 (for example).
this._nested[key] =
createField<TModel[keyof TModel], TContext>(propertyMeta, this.contextFactory) as any;
if (expectedType === Array) {
const arrayType = getSpecifiedType(target, property);
throw new Error("TODO: Assert that the specified type was set using `@specify`.");
this._nested[key] =
createField(
arrayType.property() as Constructable<TModel[keyof TModel]>,
this.contextFactory,
true,
) as any;
} else {
this._nested[key] =
createField(
expectedType,
this.contextFactory,
false,
) as any;
}
},
enumerable: true,
});
Expand Down
27 changes: 10 additions & 17 deletions packages/hyrest-mobx/src/field.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PropertyMeta, getPropertyValidation, getSpecifiedType } from "hyrest";
import { Constructable, PropertyMeta, getPropertyValidation, getSpecifiedType } from "hyrest";
import { FieldArray } from "./field-array";
import { FieldSimple } from "./field-simple";
import { ContextFactory } from "./context-factory";
Expand All @@ -18,32 +18,25 @@ export type Field<TModel, TContext> =
);

export function createField<TModel extends any[], TContext>(
propertyMeta: PropertyMeta,
modelType: Constructable<TModel[0]>,
contextFactory: ContextFactory<TContext>,
array: true,
): FieldArray<TModel[0], TContext>;
export function createField<TModel, TContext>(
propertyMeta: PropertyMeta,
modelType: Constructable<TModel>,
contextFactory: ContextFactory<TContext>,
array: false,
): FieldSimple<TModel, TContext>;
export function createField<TModel, TContext>(
{ expectedType, target, property }: PropertyMeta,
modelType: Constructable<TModel>,
contextFactory: ContextFactory<TContext>,
array: boolean,
): Field<TModel, TContext> {
// The casts to `any` are neccessary as Typescript cannot deal with this
// kind of types. See https://github.com/Microsoft/TypeScript/issues/22628 (for example).
if (expectedType === Array) {
const modelType = getSpecifiedType(target, property);
type TModelArray = TModel & any[];
return new FieldArray<TModelArray, TContext>(
modelType.property(),
contextFactory,
getPropertyValidation(target, property),
) as any;
if (array) {
return new FieldArray<TModel, TContext>(modelType, contextFactory) as any;
} else {
return new FieldSimple<TModel, TContext>(
expectedType,
contextFactory,
getPropertyValidation(target, property),
) as any;
return new FieldSimple<TModel, TContext>(modelType, contextFactory) as any;
}
}

0 comments on commit 05e5df1

Please sign in to comment.