Giter Club home page Giter Club logo

pomona's Introduction

Pōmōna

Pomona

Pomona is a framework built for exposing a domain model in a RESTful and hypermedia-driven manner. It embraces the concept of convention over configuration, and provides opiniated defaults on how domain model objects is exposed as HTTP resources.

Pomona was born out of frustrations with the difficulties of exposing a complex business domain model as a RESTful web service.

master develop future
GitHub GitHub release - -
NuGet NuGet NuGet -
Travis Master Develop Future
AppVeyor Master Develop Future
Codefactor Codefactor Codefactor Codefactor

Table of Contents

  1. Overview
  2. Documentation
  3. Contributing
  4. Get in touch
  5. License
  6. Acknowledgements

Overview

To illustrate what Pomona does, here's a diagram:

Pomona - Overview

  1. Starting on the top left, in the client:
    1. A Linq statement is written inside a client application against a statically typed and auto-generated client library.
    2. The query is run through a Linq Provider and translated to an HTTP query string.
  2. Inside the server:
    1. The HTTP query string is received by the Pomona Server and parsed back into a Linq Expression Tree.
    2. The Linq Expression is fed through a (custom) Linq Provider that can execute it against any back-end datastore supporting Linq as a query method.
    3. The Data is mapped from Data Transfer Objects, to database objects, back into DTOs and fed through a JSON serializer.
  3. Back inside the client:
    1. The JSON is deserialized to statically typed DTOs.
    2. The DTOs are made available to the client with just the data requested with the initial .Select() statement.

This is in many ways similar to what Falcor does, only in a statically typed way tailored for .NET instead of a Promise-based approach for JavaScript.

Documentation

To get started with Pomona please read the documentation.

Contributing

Do you want to contribute to Pomona? Lovely! Contributions of any kind are highly appreciated! Just make sure you've read and agreed to the contribution guidelines before submitting a pull request.

Get in touch

License

Copyright Karsten N. Strand, Asbjørn Ulsberg, PayEx and contributors. Pomona is provided as-is under the MIT License.

Acknowledgements

Thanks to:

pomona's People

Contributors

asbjornu avatar beewarloc avatar bitdeli-chef avatar dependabot[bot] avatar ehvattum avatar gitter-badger avatar jarlrasm avatar jonanders avatar timorzadir avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar

pomona's Issues

Improve profiling

It would be nice if Pomona (perhaps through a separate Pomona.Profiling package) made it easier to profile the queries it sends, so lazy loading in loops and such was easier to detect and remedy.

I'm thinking that when a flag (perhaps HttpContext.IsDebuggingEnabled) is set, the Pomona Client will gather information about all requests being made and when the context (i.e. incoming URI) is the same for a bunch of requests being made within a very short timeframe, a warning should be sent somewhere.

This "somewhere" should probably be pluggable, with plugs like logging an error to log4net or sending an error event to Sentry.

Pomona needs to support literal booleans

Pomona needs to support this:

{
    "isSantaReal" : true
}

In addition to this (which is currently supported):

{
    "isSantaReal" : {
        "_type" : "Boolean",
        "value" : "True",
    }
}

Constructor parameter and property type mismatch

When a constructor's parameter type doesn't match the type of its target property, a non-wrapped exception like the following is thrown:

System.ArgumentException: Got an unexpected exception: Expression of type 'PropertyType' cannot be used for constructor parameter of type 'ParameterType'.

It would be nice if this exception was wrapped in an exception with more context and information so it would be easier to debug and fix.

return of custom client types on post

It vould be nice if this vould work:

when:

interface ICustomType : IBaseClass

then:

ICustomType result = client.BaseClasses.Post<ICustomType>(BaseClassForm);

and:

ICustomType result = client.Post<ICustomType>(BaseClassForm);

Since query is already supporting this:

client.BaseClasses.Query<ICustomType> ();

is already doing the wanted mapping, if ICustomType inherits IBaseClass

Fix interface IPomonaQuery

Right now IPomonaQuery is a useless empty interface, so it is cast to PomonaQuery in a lot of places right now.

This should be cleaned up.

Add support for HTCPCP

Pomona should support the Hyper Text Coffee Pot Control Protocol (RFC 2324) so people can use Pomona in a way everyone expects a RESTful API to work by being able to brew a fresh cup of coffee.

Implement Delta type to for patching

Right now an object is patched directly in deserializer.
This makes it impossible to add validation rules for patching, or custom patching behaviour, before applying it.

To change this the deserializer should rather return a Delta, which can be inspected before apply occurs.

This is how ASP.NET web api works, but only supports changing value properties of the entity, not add stuff to collection etc..

When POSTing an abstract class, Pomona throws a NullReferenceException

When POSTing an abstract class, Pomona throws a NullReferenceException because the type's Constructor is null:

System.NullReferenceException: Object reference not set to an instance of an object.
   at Pomona.Common.TypeSystem.TransformedType.Create[T](IConstructorPropertySource`1 propertySource)
   at Pomona.Common.Serialization.Json.PomonaJsonDeserializer.PropertyValueSource`1.Deserialize()
   at Pomona.Common.Serialization.Json.PomonaJsonDeserializer.DeserializeComplexNode(IDeserializerNode node, Reader reader)
   at Pomona.Common.Serialization.Json.PomonaJsonDeserializer.DeserializeNode(IDeserializerNode node, Reader reader)
   at Pomona.Common.Serialization.Json.PomonaJsonDeserializer.<>c__DisplayClass1.<DeserializeThroughContext>b__0(IDeserializerNode n)
   at Pomona.ServerDeserializationContext.Deserialize(IDeserializerNode node, Action`1 nodeDeserializeAction)
   at Pomona.Common.Serialization.Json.PomonaJsonDeserializer.DeserializeThroughContext(IDeserializerNode node, Reader reader)
   at Pomona.Common.Serialization.Json.PomonaJsonDeserializer.Deserialize(TextReader textReader, TypeSpec expectedBaseType, IDeserializationContext context, Object patchedObject)
   at Pomona.Common.Serialization.Json.PomonaJsonDeserializer.Deserialize(TextReader textReader, DeserializeOptions options)
   at Pomona.PomonaRequest.Deserialize(TransformedType expectedBaseType, Stream body, Object patchedObject)
   at Pomona.PomonaRequest.Bind(TypeSpec type, Object patchedObject)
   at Pomona.RequestProcessing.HandlerRequestProcessor`1.PostToCollection(PomonaRequest request, ResourceCollectionNode collectionNode)
   at Pomona.RequestProcessing.HandlerRequestProcessor`1.ProcessCollectionNode(PomonaRequest request, ResourceCollectionNode collectionNode)
   at Pomona.RequestProcessing.HandlerRequestProcessor`1.Process(PomonaRequest request)
   at Pomona.RequestProcessing.DefaultRequestProcessorPipeline.<>c__DisplayClass3.<Process>b__0(IPomonaRequestProcessor x)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
   at Pomona.RequestProcessing.DefaultRequestProcessorPipeline.Process(PomonaRequest request)
   at Pomona.PomonaModule.ProcessRequest()
   at Pomona.PomonaModule.<RegisterRoutesFor>b__27(Object x)
   at CallSite.Target(Closure , CallSite , Func`2 , Object )
   at Pomona.PomonaModule.<>c__DisplayClass1b.<Register>b__1a(Object x)

It would be nice if the exception thrown informed about the class being abstract instead.

It would be nice to get a warning about too much lazy-loading.

The pomona client should provide a warning if a certain number of lazy resources, that could be fetched with expand, has been requested from a single parent resource.

Something like:
pomonaClient.AddLazyThresholdWarning(numberOfLazyCalls,(x)=>DoSomething(x))

Fix cast operator

Need to find out what syntax we want for type literals:

'Edm.Int32', 'Int32' with or without quotes.

Authentication should be configurable per resource

It should be possible to configure each resource to require or not require authentication as well as what type of authentication it requires. Since authentication is configured for the entire module in Nancy, a possible approach could be to create one NancyModule per resource that has a different authentication requirement than its parent.

Comparison between safeget expression and null doesn't work

The c# expression (x => x.Attributes.SafeGet("blah") as string == null) becomes "attributes.blah eq null". Should be "(attributes.blah as t'String') eq null".

This is caused by an optimization that shouldn't have been applied in this case.

Implement support for having query methods in custom resource handlers

Should recognize the following signatures for root resources:

IQueryable QueryFoo();
IQueryable Query();
IQueryable Query();

Should recognize child resources:

IQueryable Query(Parent parent);
IQueryable QueryChildren(Parent parent);

Bonus:
IQueryable Query(PomonaRequest pomonaRequest);

This requires quite a bit of refactoring in node walking and IQuerableResolver related stuff. Basically I think one PomonaRequest might be needed for every part in path. I hope there is some way around this, but I haven't been able to find any clean ways to do this yet.

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.