maurei / ngx-api-orm Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
So every once in a while you need many-to-ony
and one-to-many
relationships, in angular you can fix this problem with the following fix: (see forwardRef
):
externaltarget.ts
@Model({dashedSingularName : 'external-target', dashedPluralName: 'external-targets'})
export class ExternalTarget extends Resource {
@Field()
public id: string;
@Field()
public percentage: number;
@Field()
public startDate: Date;
@Field()
public endDate: Date;
@ToOne(forwardRef(() => ExternalTarget))
public employee: ToOneRelation<ExternalTarget, Employee>;
public static async get(): Promise<ExternalTarget[]> {
const params = new HttpParams().set('include', 'employee');
return this.fetch();
}
}
employee.ts
Model()
export class Employee extends Resource {
@Field()
public id: number;
@Field()
public code: string;
@Field()
public firstName: string;
@Field()
public middleName: string;
@Field()
public lastName: string;
@ToMany(ExternalTarget, 'external-targets')
public externalTargets: ToManyRelation<Employee, ExternalTarget>;
public fullName: string;
public static async get(): Promise<Employee[]> {
const params = new HttpParams().set('include', 'external-targets');
return this.fetch({ params: params });
}
onInit() {
this.fullName = this.firstName + ' ' + this.middleName + ' ' + this.lastName;
}
}
Now the circular dependency is ok, however when using json:api spec the attribute employee
on external target is not an attribute but a relationship when you encounter it nested in a response.
In short: when a resource is being nested in a response in jsonapi, dont parse the relationships, they are not needed at that point. only go one level deep.
Given the following model
@Model()
export class B extends Resource {
@Field()
public id: string;
}
@Model()
export class A extends Resource {
@Field()
public id: string;
@ToOne()
public toOneB: ToOneRelation<A,B>;
}
Allow for
a = new A();
await a.toOneB.fetch();
Documentation is out of date, should be updated.
So in a perfect world all models come from the same microservice, this would of course in the real world be a utopia.
In my case, I have a dedicated API Gateway (lets say https://graph.nao.com
) and I have multiple microservices containing my model information. Lets say microservice A and B, which their urls being:
https://graph.nao.com/a/v1/*
https://graph.nao.com/b/v1/*
Now, I have a model on the first microservice, and one on the second. They share authentication, and are related to each other. Is this something we can support by means of:
@Model({namespace: 'a'})
export class ModelOnA extends Resource {
@Field()
public id: number;
@Field()
public name: string;
@ToMany(ModelOnB):
public tasks: ToManyRelation<ModelOnA, ModelOnB>;
}
@Model({namespace: 'b'})
export class ModelOnB extends Resource {
@Field()
public id: number;
@Field()
public name: string;
@ToMany(ModelOnA):
public tasks: ToManyRelation<ModelOnB, ModelOnA>;
}
A few things need to be done here:
A few feature requests
This can all be condensed into using a repository as an intermediary between the model and any application logic. By using predefined Repository<TModel>
we can seperate the model (DBAL) and the Caching functinoality from each other (seperation of concerns).
@Cache({TimeToLive: 500})
class TasksRepository extends Repository<Task> { }
With an implementation in a component being
class class ExampleComponent implements OnInit {
public tasks: Task[];
constructor(private taskRepository: TaskRepository){
this.tasks = this.taskRepository.all();
}
public async getSpecificTaskOnHover(id: number) : Task{
return this.taskRepository.find(t => t.id == id);
}
public async refreshTasksOnClick(){
this.tasks = this.taskRepository.forceRefresh();
}
public async updateSpecifiTaskTitle(id: number, newTitle: string){
let task = this.taskRepository.findById(id); // alternative to find(expression)
task.title = newTitle;
this.taskRepository.update(task);
}
public async forceRefresh(){
this.tasks = this.taskRepository.forceRefresh().all();
/// or: this.tasks = this.taskRepository.all({forceRefresh: true});
}
}
This should make apps more snappy using this package. Maybe related to #13
This usage of the repository pattern would allow for a few things
x
seconds with a full refresh force available per repositoryand a general sense of wellbeing :)
When save
'ing a model, the newly saved model is returned as an array. Current hack is to use the first index of this list to continue,
But this is of course not the greatest way to implement this
title says it all
Usage:
@Model()
class Dummy extends Resource {
@Field({optional: true})
public id: number;
@OptionalField() // is an alias for above
public name: any;
@ToOne({relatedResource: RelatedOne, optional: true)
public relatedInstances: any;
@OptionalToOne(RelatedOne) // is an alias for the version above
public relatedInstance: any;
}
I have the following model:
team.resource.ts
import { ResourceModel, Resource, ResourceField } from "@ngx-api-orm/core";
@ResourceModel()
export class Team extends Resource {
@ResourceField()
public id: number;
@ResourceField()
public name: string;
}
For some reason, when importing this in my subcomponent as such it doesnt work:
import { Component, OnInit } from '@angular/core';
import { Team } from '../resources/team.resource';
@Component({
selector: 'app-teams',
templateUrl: './teams.component.html',
styleUrls: ['./teams.component.css']
})
export class TeamsComponent implements OnInit {
constructor() { }
teams: Array<Team> ;
ngOnInit() {
this.importTeams();
}
async importTeams() {
const teams: Array<Team> = await Team.fetch();
}
}
I have a feeling this has to do with type saftey as it is returning a Promise of type Promise<Resource[]>
.
Given the following model
@Model()
export class B extends Resource {
@Field()
public id: string;
}
@Model()
export class A extends Resource {
@Field()
public id: string;
@ToMany()
public toManyB: ToOneRelation<A,B>;
}
Allow for
a = new A();
await a.toManyB.fetch();
I would love to be able to filter the queries sent to the api. A very basic example would include support for the following: JsonApitDotNetCore. Which would include the following:
?filter[attribute]=eq:value
?filter[attribute]=ne:value
?filter[attribute]=lt:value
?filter[attribute]=gt:value
?filter[attribute]=le:value
?filter[attribute]=ge:value
?filter[attribute]=like:value
?filter[attribute]=in:value
Given the following models
@Model()
export class B extends Resource {
@Field()
public id: string;
}
@Model()
export class A extends Resource {
@Field()
public id: string;
@ToOne()
public toOneB: ToOneRelation<A,B>;
}
Then, given a JSON API response
Allow for
{
"data": [
{
"type": "A",
"id": "1",
"attributes": {},
"relationships": {
"toOneB": {
"data": {
"type": "B",
"id": "100"
}
}
}
}
],
"included": [
{
"type": "B",
"id": "100",
"attributes": {}
}
]
}
will work, but
{
"data": [
{
"type": "A",
"id": "1",
"attributes": {},
"relationships": {
"toOneB": {
"data": {
"type": "B",
"id": "100"
}
}
}
}
]
}
will throw an error (expected key toOneB
). This should not be the case.
const instance = new MyResource({ ... });
the instance is not saved to the internal instance registery for that resource ( the one you access with MyResource.collection()
). Only saved instances, i.e. with an ID, are registered.
instance.save()
will then not detect that instance in the alreadyExsists
checksave
method (which for some reason is wrapped in an array, will figure that out.MyResource
floating around that represent the same data: the unsaved instance which it probably bound to your template, and the saved instance which is not used unless you explicitly do so.A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.