Commit a4338a93 authored by William Naslund's avatar William Naslund

added lookup decorator without constraint implementation

parent 833239a9
import { DBModel, DBModelConstructor } from "../model";
import { LOOKUP_INFO, TABLE_PARENT_LOOKUPS, TABLE_CHILD_LOOKUPS } from "../internal/meta-keys";
/** Information about a lookup from one model to another */
export interface DBLookupInformation {
name: string;
model: DBModelConstructor<any>;
propertyKey: string | symbol
}
/** Registers a lookup on a model */
export function DBLookup(name: string, model: DBModelConstructor<any>) {
return function(proto: DBModel, propertyKey: string | symbol) {
let parentLookups: DBLookupInformation[] = Reflect.getMetadata(TABLE_PARENT_LOOKUPS, proto.constructor) || [];
let childLookups: DBLookupInformation[] = Reflect.getMetadata(TABLE_CHILD_LOOKUPS, model) || [];
const lookupInfo: DBLookupInformation = {
name: name,
model: model,
propertyKey: propertyKey
};
parentLookups.push(lookupInfo);
childLookups.push(lookupInfo);
Reflect.defineMetadata(TABLE_PARENT_LOOKUPS, parentLookups, proto.constructor);
Reflect.defineMetadata(TABLE_CHILD_LOOKUPS, childLookups, model);
Reflect.defineMetadata(LOOKUP_INFO, lookupInfo, proto.constructor, propertyKey);
};
}
export * from './db-table';
export * from './db-field';
\ No newline at end of file
export * from './db-field';
export * from './db-lookup';
\ No newline at end of file
import { DBModelConstructor } from "../model";
import { DBTableInformation, DBFieldInformation } from "../decorators";
import { DBTableInformation, DBFieldInformation, DBLookupInformation } from "../decorators";
/** Identifier for table information */
export const TABLE_INFO = Symbol();
......@@ -7,9 +7,17 @@ export const TABLE_INFO = Symbol();
/** Identifier for table field lists */
export const TABLE_FIELDS = Symbol();
/** Indentifier for table child lookups */
export const TABLE_CHILD_LOOKUPS = Symbol();
/** Identifier for table parent lookups */
export const TABLE_PARENT_LOOKUPS = Symbol();
/** Identifier for field information */
export const FIELD_INFO = Symbol();
/** Identifier for a foreign key (AKA a lookup) */
export const LOOKUP_INFO = Symbol();
/** Loads the table information for a constructor */
export function getTableInformation(modelType: DBModelConstructor<any>): DBTableInformation {
......@@ -18,7 +26,31 @@ export function getTableInformation(modelType: DBModelConstructor<any>): DBTable
/** Loads the fields for a table */
export function getTableFields(modelType: DBModelConstructor<any>): DBFieldInformation[] {
return Reflect.getMetadata(TABLE_FIELDS, modelType) || [];
const fields: DBFieldInformation[] = Reflect.getMetadata(TABLE_FIELDS, modelType) || [];
const parentLookupList: DBLookupInformation[] = Reflect.getMetadata(TABLE_PARENT_LOOKUPS, modelType) || [];
for(const parentLookup of parentLookupList) {
const parentInfo = getTableInformation(parentLookup.model);
if(parentInfo == null) {
throw new Error(`The lookup "${parentLookup.name}" on ${modelType} looks up to a model that has no registered table information`);
}
if(parentInfo.options == null || parentInfo.options.id == null) {
throw new Error(`The lookup "${parentLookup.name}" on ${modelType} looks up to a model that has id defined`);
}
const parentIdInfo = getFieldInformation(parentLookup.model, parentInfo.options.id);
if(parentIdInfo == null) {
throw new Error(`The lookup "${parentLookup.name}" on ${modelType} looks up to a model with an id "${String(parentInfo.options.id)}" that has no registered field inofrmation`);
}
fields.push({
name: parentLookup.name,
propertyKey: parentLookup.propertyKey,
type: parentIdInfo.type.lookupType ? parentIdInfo.type.lookupType() : parentIdInfo.type
});
}
return fields;
}
/** Loads the information for a field */
......
import { DBType } from "./type";
import { DBInteger } from "./integer";
export class DBIdSequence implements DBType {
......@@ -6,4 +7,8 @@ export class DBIdSequence implements DBType {
return `SERIAL`;
}
lookupType() {
return new DBInteger();
}
}
......@@ -8,6 +8,9 @@ export interface DBType {
/** Serializes a value of this type from the driver */
serialize?(parsed: any): any;
/** Returns the type of fields that lookup to this field, if the lookup type is different than this type */
lookupType?(): DBType;
/** Returns the SQL definition of this type for use in creating & modifying columns */
create(): string;
......
import { DBTable, DBModel, DBField, DBIdSequence, DBVarChar, DBLookup } from "@swirl/db";
import { Account } from "./account";
@DBTable('contact', {
id: 'id'
})
export class Contact extends DBModel {
@DBField('id', new DBIdSequence())
public id: number;
@DBLookup('account_id', Account)
public account: Account;
@DBField('first_name', new DBVarChar(60))
public firstName: string;
@DBField('last_name', new DBVarChar(60))
public lastName: string;
}
import { TEST_ADAPTER } from "./db/adapter";
import { Account } from "./db/account";
import { Database } from "@swirl/db";
import { Contact } from "./db/contact";
describe('migrate()', function() {
let db = new Database(TEST_ADAPTER);
......@@ -11,7 +12,7 @@ describe('migrate()', function() {
});
it('Creates the schema', async () => {
await db.register(Account).migrate();
await db.register(Account).register(Contact).migrate();
});
});
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