seanpmaxwell/overnight

Firebase functions implementation

Closed this issue · 8 comments

Hi Sean,

I want to start off by saying again how much I love this project and the simplicity of it, it just makes working on API's so much easier, structured, predictable and consistent.

Now, for multiple reasons, I decided to stop building these live server apps and switched completely to the functions-based approach, more specifically firebase. Now coding these functions, even though it supports typescript out of the box, is a complete pain. There's no decent support for middleware, wrapping functions, it is indeed possible to manually add middleware and use some express features but that isn't a thing for callable functions.

Now I'd like to start working on something similar to overnightjs but for functions, at first, for firebase functions specifically.

The baseline concept is you'd have your controllers + child controllers and your basic decorators are @OnRequest and @OnCall in every class. The basic features to support would be middleware + wrappers for @OnRequest(<NAME>) and just wrappers for @OnCall(<NAME>).

Now because these would be functions operating independently from each other, we'd also want to have some decorator for things to be initialized only for the function, for example, a mongoose db connection, which you wouldn't necessarily want to configure globally for all your stuff, maybe this could be solved with the standard @wrapper?

In index.ts you'd configure your global middleware + global async wrappers for '@oncall and '@OnRequest;

Now for the end result, let's assume we have a controller called 'Reports' which has a child controller called 'Jobs' which has a function called 'daily'; Your end function name would be a camelCase of that tree, such as: reportsJobsDaily;

I was thinking instead of just making my own thing, I'd suggest we build it together as part of the @overnight project?

Let me know what you think, thanks.

Hmm, I don't think I'm really familiar enough with firebase to make a call here. Is it basically a serverless library where you just pass it functions and it handles all the rest for you?

I deleted that comment as I guess there's still a lot of work to be done. I've spent these last couple of days almost exclusively testing things out and getting a better understanding of prototypes and how the reflect-metadata works. Your decorators here have been a great source of inspiration but I have a couple of questions around why/how you're doing certain things:

--- 1 in your middleware decorator:

 let routeProperties = Reflect.getOwnMetadata(propertyKey, target);
        if (!routeProperties) {
            routeProperties = {};
        }
        routeProperties = {
            routeMiddleware: middleware,
            ...routeProperties,
        };
        Reflect.defineMetadata(propertyKey, routeProperties, target);
        // For class methods that are not arrow functions
        if (descriptor) {
            return descriptor;
        }

are you affecting a method's metadata in multiple places? or is there any other reason you need to first retreive it and only after that add the middleware/wrapper functions from the decorator?

--- #2 does the wrapper function always have to return a Promise?

Sorry buddy. I've never used server less before so I don't feel qualified to work on this project. If you want to create a pull request you're welcome to though.

No worries, not looking for someone to code for me for free, was just thinking you might have use for such implementation as well :) I'll make a separate project for now and see what's possible, thanks!

Hey @michaelbats.

Have you managed to get OvernightJS working with Cloud Functions?

I am unsure about how I bind the instance to the functions.https.onRequest, as it expects a request and response object and the server class is build with a listener in mind.
Do you have any solutions? I am also trying to build an API on cloud functions. :)

@Nefiron there's no way to implement overnightjs into something like cloud functions due to their nature, unless you make your whole API 1 cloud function which I have some doubts on how efficient it might be/how it would work.

I have just published minutes ago a super-beta version of the 'mini-framework'/helpers (idk what to call the thing really) I'm working on to write firebase functions in a more structured way. check the folder 'sample-project' -- it should be quite good to get you started but if you have any questions feel free to post them in that repo and I'll do my best to help.

If you want to contribute and grow the thing, let me know and I'll add you to the team, good luck!

Link: https://github.com/decorfn/firebase

Why wouldn't it be efficient, @michaelbats ? Cloud Functions scale your functions out depending on requests. That's the whole idea.

The Firebase team even has a video where they create an Express application and bind it to the functions.https.onRequest.

I was hoping to do the same, but I am running in to some issues.

@Nefiron I know of the thing, of course, and easy scalability is always the strong point of Cloud Functions. But when it comes to actual performance, I haven't actually ran any tests to compare things with a traditional server + express app and how that performance compares as you scale.

Until I do those tests, I'll use common sense and assume that it performs decently once a function is 'woke', but there's got to be some hard data aspect to back these assumptions up.