Commit 0cb2dd23 authored by nanahira's avatar nanahira

finish backref

parent 08f16b10
...@@ -37,11 +37,10 @@ export function SchemaProperty(options: SchemaOptions = {}): PropertyDecorator { ...@@ -37,11 +37,10 @@ export function SchemaProperty(options: SchemaOptions = {}): PropertyDecorator {
) { ) {
options.array = true; options.array = true;
} }
if ( if (
options.type && options.type &&
typeof options.type !== 'string' && typeof options.type !== 'string' &&
(options.type as Schema<any>)[kSchema] ((options.type as Schema<any>)[kSchema] || options.type[RefSym])
) { ) {
const cl = options.type as ClassType<any>; const cl = options.type as ClassType<any>;
let dec: PropertyDecorator; let dec: PropertyDecorator;
......
import { import {
ClassType, ClassType,
GeneratedSym, GeneratedSym,
IndexSym,
RefSym, RefSym,
SchemaClassOptions, SchemaClassOptions,
SchemaOptions, SchemaOptions,
...@@ -16,10 +15,7 @@ import _ from 'lodash'; ...@@ -16,10 +15,7 @@ import _ from 'lodash';
import { Metadata } from '../metadata/metadata'; import { Metadata } from '../metadata/metadata';
import { kSchema } from '../utility/kschema'; import { kSchema } from '../utility/kschema';
let index = 0; export function resolveSchemaType(schemaType: SchemaType): SchemaOrReference {
const refMap = new Map<number, Schema<any>>();
function resolveSchemaType(schemaType: SchemaType): SchemaOrReference {
if (schemaType && schemaType[RefSym]) { if (schemaType && schemaType[RefSym]) {
return schemaType as SchemaReference; return schemaType as SchemaReference;
} }
...@@ -76,13 +72,12 @@ function getPropertySchemaFromOptions<PT>( ...@@ -76,13 +72,12 @@ function getPropertySchemaFromOptions<PT>(
function resolveSchemaReference<S = any, T = S>(ref: SchemaReference<S, T>) { function resolveSchemaReference<S = any, T = S>(ref: SchemaReference<S, T>) {
const value = ref.factory(); const value = ref.factory();
console.log(value); /*if (value[kSchema]) {
if (value[IndexSym]) { return value;
return refMap.get(value[IndexSym]);
} }
if (typeof value === 'function' && !value[kSchema]) { if (typeof value === 'function' && !value[kSchema]) {
return SchemaClass(value as { new (...args: any[]): any }); return SchemaClass(value as { new (...args: any[]): any });
} }*/
return value; return value;
} }
...@@ -121,24 +116,19 @@ function schemasFromDict<T>(dict: SchemaOptionsDict<T>) { ...@@ -121,24 +116,19 @@ function schemasFromDict<T>(dict: SchemaOptionsDict<T>) {
SchemaOptionsDict<T>[P] SchemaOptionsDict<T>[P]
>; >;
} = _.mapValues(dict, (opt) => getPropertySchemaFromOptions(opt)); } = _.mapValues(dict, (opt) => getPropertySchemaFromOptions(opt));
const schema = Schema.object({});
for (const _key of Object.keys(schemaDict)) { for (const _key of Object.keys(schemaDict)) {
const key = _key as keyof T; const key = _key as keyof T;
if (schemaDict[key][RefSym]) { if (schemaDict[key][RefSym]) {
const schemaOptions = dict[key]; const schemaOptions = dict[key];
/*schemaDict[key] = resolvePropertySchemaFromOptions({ tempDefGet(schema.dict, _key, () =>
...schemaOptions, resolvePropertySchemaFromOptions(schemaOptions),
type: resolveSchemaReference(schemaDict[key] as SchemaReference),
});*/
tempDefGet(schemaDict, key, () =>
resolvePropertySchemaFromOptions({
...schemaOptions,
type: resolveSchemaReference(schemaDict[key] as SchemaReference),
}),
); );
} else {
schema.set(_key, schemaDict[_key]);
} }
} }
return Schema.object(schemaDict); return schema;
} }
function schemaOptionsFromClass<T>(cl: ClassType<T>): SchemaOptionsDict<T> { function schemaOptionsFromClass<T>(cl: ClassType<T>): SchemaOptionsDict<T> {
...@@ -266,11 +256,6 @@ export function SchemaClass<T>(originalClass: ClassType<T>) { ...@@ -266,11 +256,6 @@ export function SchemaClass<T>(originalClass: ClassType<T>) {
export function RegisterSchema(options: SchemaClassOptions = {}) { export function RegisterSchema(options: SchemaClassOptions = {}) {
return function <T>(originalClass: ClassType<T>): any { return function <T>(originalClass: ClassType<T>): any {
Metadata.set('SchemaClassOptions', options)(originalClass); Metadata.set('SchemaClassOptions', options)(originalClass);
const newClass = SchemaClass(originalClass); return SchemaClass(originalClass);
const currentIndex = index++;
refMap.set(currentIndex, newClass);
originalClass[IndexSym] = currentIndex;
newClass[IndexSym] = currentIndex;
return newClass;
}; };
} }
...@@ -47,4 +47,3 @@ export type SchemaOptionsDict<T> = { [P in keyof T]?: SchemaOptions }; ...@@ -47,4 +47,3 @@ export type SchemaOptionsDict<T> = { [P in keyof T]?: SchemaOptions };
export const RefSym = Symbol('SchemasteryGenRef'); export const RefSym = Symbol('SchemasteryGenRef');
export const GeneratedSym = Symbol('GeneratedSym'); export const GeneratedSym = Symbol('GeneratedSym');
export const IndexSym = Symbol('IndexSym');
import { Metadata } from '../metadata/metadata'; import { Metadata } from '../metadata/metadata';
import { ClassType } from '../def'; import { ClassType, RefSym, SchemaOrReference, SchemaReference } from '../def';
import Schema from 'schemastery'; import Schema from 'schemastery';
import _ from 'lodash'; import _ from 'lodash';
import { kSchema } from './kschema'; import { kSchema } from './kschema';
import { resolveSchemaType } from '../decorators';
export function SetTransformer(transformer: (val: any) => any) { export function SetTransformer(transformer: (val: any) => any) {
return Metadata.set('Transformer', transformer); return Metadata.set('Transformer', transformer);
} }
export function transformSingle<T>( export function transformSingle<T>(
cl: ClassType<T> & Partial<Schema>, cl: SchemaOrReference<T> | ClassType<T>,
val: any, val: any,
) { ) {
if (cl[kSchema]) { if (cl[RefSym]) {
return new cl(val); const ref = cl as SchemaReference<T>;
return transformSingle(resolveSchemaType(ref.factory()), val);
} else if (cl[kSchema]) {
const schema = cl as Schema<T>;
return new schema(val);
} else { } else {
return val; return val;
} }
} }
export function transformArray<T>(cl: ClassType<T>, val: any[]) { export function transformArray<T>(
cl: SchemaOrReference<T> | ClassType<T>,
val: any[],
) {
if (!val) { if (!val) {
return; return;
} }
...@@ -27,7 +35,11 @@ export function transformArray<T>(cl: ClassType<T>, val: any[]) { ...@@ -27,7 +35,11 @@ export function transformArray<T>(cl: ClassType<T>, val: any[]) {
return result; return result;
} }
export function transformDict<T>(cl: ClassType<T>, val: any, array: boolean) { export function transformDict<T>(
cl: SchemaOrReference<T> | ClassType<T>,
val: any,
array: boolean,
) {
if (!val) { if (!val) {
return; return;
} }
......
...@@ -34,6 +34,11 @@ class Post { ...@@ -34,6 +34,11 @@ class Post {
type: SchemaRef(() => Author), type: SchemaRef(() => Author),
}) })
author?: Author; author?: Author;
@DefineSchema({
type: SchemaRef(() => Post),
})
childPosts?: Post[];
} }
describe('Recurse schema', () => { describe('Recurse schema', () => {
...@@ -47,7 +52,8 @@ describe('Recurse schema', () => { ...@@ -47,7 +52,8 @@ describe('Recurse schema', () => {
}); });
it('child of child should be Schema', () => { it('child of child should be Schema', () => {
const authorSchema = (Post as Schema<Post>).dict.author.inner.dict.posts; const authorSchema = (Post as Schema<Post>).dict.childPosts.inner.dict
.author;
expect(authorSchema[kSchema]).toBeDefined(); expect(authorSchema[kSchema]).toBeDefined();
}); });
...@@ -64,8 +70,11 @@ describe('Recurse schema', () => { ...@@ -64,8 +70,11 @@ describe('Recurse schema', () => {
author: { author: {
name: 'Shigma', name: 'Shigma',
}, },
childPosts: [{ name: 'child' }],
}); });
expect(post.author.getName()).toBe('Shigma'); expect(post.author.getName()).toBe('Shigma');
expect(post.childPosts[0].getName()).toBe('child');
}); });
it('should recurse twice', () => { it('should recurse twice', () => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment