Overview

Id and Column

You can add configuration to @Id() and @Column() decorators as follows.

user.model.ts

import { HttpResource } from '@paddls/ngx-http-repository';
import { Id, Column, DateConverter } from '@paddls/ngx-repository';

@HttpResource({
  path: '/api/users'
})
export class User {

@Id() // define the resource id
public id: number;

@Column() // define a column
public firstName: string;

@Column('lastname')  // define a column with special mapping
public lastName: string;

@Column(() => Address) // define a column with a child model
public address: Address;

@Column({type: () => Job, field: 'job'}) // combine model and special mapping
public myJob: Job;

@Column({field: 'createdAt', customConverter: () => DateConverter}) // use custom converter for special type
public createdAt: Date;

}

            

As shown in the example above, each configuration field is optional : you can define any field you want or not to have any configuration at all.

Field Description Available on @Id()
field Field name in JSON Yes
type Field type after deserialization : only fields with @Id() or @Column() decorator in type will be serialized No
readOnly Boolean to indicate to not send the value in json to the server Yes
writeOnly Boolean to indicate to ignore the field in json Yes
customConverter A converter to make a custom serialization/deserialization No
denormalizeNull Boolean to override global configuration to denormalize the column when is set to null value Yes
denormalizeUndefined Boolean to override global configuration to denormalize the column when is set to undefined value Yes
normalizeNull Boolean to override global configuration to normalize the column when is set to null value Yes
normalizeUndefined Boolean to override global configuration to normalize the column when is set to undefined value Yes

The field and type fields can be defined using a shorthand. For field, just specify a string directly in the context, it will be interpreted as such. Same thing for type : specify directly an anonymous function returning the type in the context (as shown in the example).

Path parameters and PathColumn

You can add parameters on a resource path using : character. You can map those parameters with values using the query system.

@PathColumn() decorator allows you to retrieve the path parameter value of a resource and map it to the decorated field.

book.model.ts
                import { HttpResource } from '@paddls/ngx-http-repository';
import { Id, Column, PathColumn } from '@paddls/ngx-repository';

@HttpResource({
  path: '/libraries/:libraryId/books'
})
export class Book {

  @Id()
  public id: number;

  @Column()
  public title: string;

  @PathColumn()
  public libraryId: string;

  // or

  @PathColumn('libraryId')
  public theLibraryId: string;

}
                
            

JoinColumn

You can fetch associated resources using JoinColumn.

import { HttpResource } from '@paddls/ngx-http-repository';
import { Id, Column, JoinColumn } from '@paddls/ngx-repository';
import { FirestoreRepository } from '@paddls/ngx-firestore-repository';
@HttpResource({
  path: '/libraries/:libraryId/books'
})
export class Book {
  @Id()
  public id: number;
  @Column()
  public title: string;
  @Column()
  public authorId: string;
  // initialize the request to get associated author, using instance attribute 'authorId' with User FirestoreRepository
  @JoinColumn({attribute: 'authorId', resourceType: () => User, repository: () => FirestoreRepository})
  public author$: Observable<Person>; // data will be lazy fetched on subscribe
}

SubCollection

You can fetch associated resources using SubCollection.

import { HttpResource, HttpRepository } from '@paddls/ngx-http-repository';
import { Id, Column, SubCollection } from '@paddls/ngx-repository';
@HttpResource({
  path: '/libraries/:libraryId/books'
})
export class Book {
  @Id()
  public id: number;
  @Column()
  public title: string;
  // you should specify the corresponding resource, how to request resources and the repository to use
  @SubCollection({
    resourceType: () => Comment,
    // params are extra information context request (for example libraryId in path) 
    params: (book: Book, params: any) => new CommentQuery({bookId: book.id, libraryId: params.libraryId}),
    repository: () => HttpRepository
  })
  public comments$: Observable<Comment[]>;
}

Query

With NgxRepository, a Query is an object holding some informations associated with the querying of one or several resources. You can then provide an instance of this Query as a parameter of any method available on HttpRepository or FirestoreRepository.

Here is an example of a query for a @HttpResource() :

import { HttpQueryParam, HttpHeader } from '@paddls/ngx-http-repository';
import { PathParam } from '@paddls/ngx-repository';
export class BookQuery {
  // use http query param
  @HttpQueryParam() // param is forwarded into http query param
  public title: string;
  // or
  @HttpQueryParam('title')
  public theTitle: string;
  // use path param
  @PathParam() // param replace :libraryId into resource path
  public libraryId: string;
  // or
  @PathParam('libraryId')
  public library: string;
  // use http header
  @HttpHeader() // path is forwarded into http header
  public page: number = 1;
  // or
  @HttpHeader('itemPerPage')
  public size: number = 2;
  public constructor(data: Partial<BookQuery> = {}) {
    Object.assign(this, data);
  }
}

And an example of a query for a @FirestoreResource() :

import {
  FirestoreCriteria,
  FirestoreEndAt,
  FirestoreEndBefore,
  FirestoreLimit,
  FirestoreLimitToLast,
  FirestoreOrderBy,
  FirestoreOrderByContext,
  FirestoreStartAfter,
  FirestoreStartAt
} from '@paddls/ngx-firestore-repository';
export class ClientQuery {
  @FirestoreCriteria({field: 'lastName', operator: '=='})
  public lastNameEqual?: string;
  @FirestoreOrderBy()
  public orderBy?: string | FirestoreOrderByContext | (FirestoreOrderByContext | string)[];
  @FirestoreStartAt()
  public startAt?: any;
  @FirestoreStartAfter()
  public startAfter?: any;
  @FirestoreEndAt()
  public endAt?: any;
  @FirestoreEndBefore()
  public endBefore?: any;
  @FirestoreLimit()
  public limit?: number;
  @FirestoreLimitToLast()
  public limitToLast?: number;
  public constructor(data: Partial<ClientQuery> = {}) {
    Object.assign(this, data);
  }
}

The following table lists all the type of fields you can add to a query object and with which repository they are available.

Decorator Description Repository type
@PathParam() Replaces path parameter with field value HttpRepository, FirestoreRepository
@HttpQueryParam() Adds a query param to the HTTP request (eg. /users/?name=Oscar) HttpRepository
@HttpHeader() Adds a HTTP header to the request with field value HttpRepository
@FirestoreCriteria() Adds a Firestore query criteria FirestoreRepository
@FirestoreOrderBy() Adds a .orderBy() clause to Firestore request FirestoreRepository
@FirestoreLimit() Adds a .limit() clause to Firestore request FirestoreRepository
@FirestoreLimitToLast() Adds a .limitToLast() clause to Firestore request FirestoreRepository
@FirestoreStartAt() Adds a .startAt() query cursor to Firestore request FirestoreRepository
@FirestoreStartAfter() Adds a .startAfter() query cursor to Firestore request FirestoreRepository
@FirestoreEndAt() Adds a .endAt() query cursor to Firestore request FirestoreRepository
@FirestoreEndBefore() Adds a .endBefore() query cursor to Firestore request FirestoreRepository

The following example shows a query used in a findAll() operation on a Firestore resource.

@Injectable()
export class ClientService {
  @InjectRepository({resourceType: () => Client, repository: () => FirestoreRepository})
  private repository: FirestoreRepository<Client, string>;
  public searchByLastName(searchedLastName: string): Observable<Page<Client>> {
    return this.repository.findAll(new ClientQuery({
      lastNameEqual: searchedLastName,
      orderBy: ['firstName']
    }));
  }
}