Giter VIP home page Giter VIP logo

ngx-crud's People

Contributors

henryruhs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ngx-crud's Issues

Decorators for release 16 are broken

Not sure what is causing this, but I have trouble using @ApiUrl() and @ApiRoute() within a project. I assume this is a configuration issue as the decorators work for the testing.

Alternative we can use the old fashion approach:

@Injectable(
{
	providedIn: 'root'
})
export class XXXService extends CrudService<unknown, unknown>
{
	protected override apiUrl : string = environment.apiUrl;
	protected override apiRoute : string = environment.apiRoutes.xxx;
}

CRUD Decorators

Instead of having a fixed CrudService there would be the possibility to use a decorators for each HTTP operation.

export function Read<ReadResponseBody>() : Function
{
	return function(service : typeof CommonService) : typeof CommonService
	{
		return class extends service
		{
			protected readService : ReadService<ReadResponseBody> = this.injector.get(ReadService);

			read<ResponseBody = ReadResponseBody>(id : Id, options ?: Options) : Observable<ResponseBody>
			{
				return this.readService.bind(this).read(id, options);
			}
		};
	};
}

Then this could be used over extend from CrudService:

@Injectable()
@Read()
export class ExampleService {}

While this is technical working using exampleService.read('1) will throw an error as TypeScript does not support Class Decoration Mutation. Using (exampleService as any).read('1)on the other hand proves the point that the class is technical extended. Another issue is passing of typings what is not doable as of writting this in 2022.

This is just for the records to my future self or others who like to suggest that feature.

Improve documentation

Developer feedback:

  • improve readme with simple example
  • remove example for "Searchable Collection"

Introduce getter and setter to handle single values

Needed helpers:

  • getParam
  • setParam
  • getHeader
  • setHeader

Example for setting a single parameter;

public setParam(name: string, value: string): this
{
    return this.setParams(
        this.getParams().set(name, value)
    );
   return this;
}

Proposal renaming OptionInterface

Hi,

I like to avoid technical expressions when it comes to write abstractions.
That's why I thought it would be cleaner to read if Interface-Suffix is removed from OptionInterface.

You could either go with Option or CrudOption.

You can close this issue after reading this, since it is just my opinion and the change has no technical impact on the library itself.

Allow <T> for Request Service

Request Service should be extended to <T> return type. So <T> and <T[]> are allowed to support content types such as text/plan too.

Restore endpoint and options after call

Since the very beginning of this library, there is an flaw of service wide properties like endpoint, params, headers and other options. Once set for a specific method, it manipulates other (parallel and afterwards) requests.

1. Approach

Using finalize() inside a pipe() comes handy but does not solve falsy request being called parallel:

@Injectable()
export class JokeService extends CrudService<JokeInterface>
{
	protected apiUrl : string = environment.apiUrl;
	protected apiRoute : string = environment.apiRoutes.joke;

	public search(query : string) : Observable<Joke[]>
	{
		return this
			.setParam('query', query)
			.request<Joke[]>('GET')
			.pipe(
				finalize(() => this.clearParam('query'))
			);
	}
}

2. Approach

Implement a custom clone() method to create another instance of your service that does not touch sibling requests:

@Injectable()
export class JokeService extends CrudService<Joke>
{
	protected apiUrl : string = environment.apiUrl;
	protected apiRoute : string = environment.apiRoutes.joke;

	public search(query : string) : Observable<Joke[]>
	{
		return this
			.clone()
			.setParam('query', query)
			.request<Joke[]>('GET');
	}

	protected clone() : JokeService
	{
		return new JokeService(this.injector);
	}
}

Introduce forRoot(options) pattern

It would be nice to configure enableAbort, enableCache and enableObserve defaults via forRoot(). I have to rethink about the defaults, properly 10000ms for aborting and caching and observing.

CrudModule.forRoot(
{
    abort:
    {
        method: 'GET',
        lifetime: 2000
    },
    cache:
    {
        method: 'GET',
        lifetime: 2000
    },
    observe:
    {
        method: 'GET',
        lifetime: 1000
    }
});
AbortModule.forRoot(
{   
    method: 'GET',
    lifetime: 2000
}

Further reading:

https://angular.io/guide/singleton-services#the-forroot-pattern

Remove interface and type suffixes, Rename Endpoint to ApiRoute

  • Split ObserveEffectInterface to ObserveAfterEffect and ObserverBeforeEffect (8.1.0)
  • Mark the ObserveEffectInterface as deprecated (8.1.0)
  • Remove interface and type suffixes all over the place (8.1.0)
  • Mark *Interface and *Type as deprecated (8.1.0)
  • Rename Endpoint to ApiRoute (8.2.0)
  • Mark Endpoint and related methods as deprecated (8.2.0)

In 9.0.0 all deprecations will be remove!

HTTP Batching support

Support for HTTP batching should be added... there is an thread with ZIP files that include conceptional work: jonsamwell/ngx-http-batcher#2

  • Replace JSONPlaceholder API with local solution to have a proper /$batch endpoint for testing
  • Real batch() that joins different request in a SINGLE request and splits the response after
    • Integrate one of the concepts to work against local api
    • Adjust codebase to ngx-crud approach

Allow generic types for methods

Currently the as T approach is the only way to customize the models / types:

  custom(): Observable<any> {
    return this.request('GET') as Observable<any>;
  }

There should be support to use the approach similar to http client:

  custom(): Observable<any> {
    return this.request<Observable<any>>('GET');
  }

Example for an updated request method:

public request<T>(method : MethodType, options? : OptionWithBodyInterface) : Observable<T | T[]>

Aborting a service can lead to error: TypeError: Cannot read property 'next' of undefined

Build Log:
2019-12-30T09:12:59.5319870Z TypeError: Cannot read property 'next' of undefined
2019-12-30T09:12:59.5321786Z at
2019-12-30T09:12:59.5322079Z at AbortService.push../node_modules/ngx-crud/fesm5/ngx-crud.js.AbortService.abort (http://localhost:9876/_karma_webpack_/node_modules/ngx-crud/fesm5/ngx-crud.js:23:1)

From Debugger:

AbortService.prototype.abort = function (request) {
    this.store.get(request.url).next();
    this.store.get(request.url).complete();
    return this;
};

Support for observe http option

While using request('GET') we need to be able to add observe: 'response' ... therefore we have to extend the body interface.

AbortSignal needs a COMPLETE

The AbortSignal needs to be extended by COMPLETED as the Observable keeps open until timeout kicks in and ABORTED is thrown.

Interceptor therefore needs this:

takeUntil(this.abortService.get(request).pipe(filter(signal => signal === 'ABORTED' || signal === 'COMPLETED')))

Introduce observe(urlWithParams) and observeMany(url)

Just in case we need to observe only specific services:

abortService.observe(urlWithParams : string) : Observable<[string, Store]>
abortService.observeMany(url : string) : Observable<[string, Store]>
cacheService.observe(urlWithParams : string) : Observable<[string, Store]>
cacheService.observeMany(url : string) : Observable<[string, Store]>

Done for Abort and Cache since ngx-crud 11+

Remove JSDocs

As TypeScript is fully transparent when it comes to types, there is no need to stick to the JSDocs anymore.

Support non-standard and nested resources via config

First of all, a service that extends from CrudService without passing a config should behave like before! That being said - we need a default "fully CRUD operation" config.

  1. Take a config like that, operation can be flat or come with custom typing?
{
    root: {
        route: '/orders'
        operation: {
            read: (id: string) => T
            find: () => T[]
        }
    },
    invoice: {
        route: '/orders/{id}/invoices'
        operation: [ 'update' ]
    }
}
  1. Implement a Proxy¹² to work like the magic __call method from PHP to operate like a gate keeper. Is read in the config on that route than call read() or throw Error().

  2. Non rooted API routes work like a fake property in the class.

  3. The following API should be available according to the config:

crudService->read(id: string) : T;
crudService->find() : T[];

// it should be fine to allow "crudService->root" alias too

crudService->invoice->update(1, {}) : T;
  1. Implement a Config() decorator aswell

¹ https://medium.com/@alonronin/magic-methods-in-javascript-meet-proxy-65e6305f4d3e
² https://dev.to/mattzgg_94/typescript-use-mapped-type-to-implement-a-proxy-4im2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.