ggoodman / nostalgie

Nostalgie is an opinionated, full-stack, runtime-agnostic framework for building web apps and web pages using react.
https://nostalgie.dev
MIT License
151 stars 6 forks source link

Base on `vite-plugin-ssr` #13

Open brillout opened 3 years ago

brillout commented 3 years ago

I'm working on

The goal of these do-one-thing-do-it-well libraries is two-fold:

Is collaborating something you'd be interested in?

brillout commented 3 years ago

You'll likely have many open questions about the relationship between Nastoalgie and these libraries, I'm happy to elaborate. (They have many convergences!)

ggoodman commented 3 years ago

Hey @brillout, I've taken a quick spin through wildcard-api and agree that there's some huge overlap and a lot of alignment in philosophy. I definitely think that collaborating would be in everyone's best interest.

Some things that I observed in reviewing wildcard-api:

Something that is not yet evident in Nostalgie's codebase is that I hope to make the browser --> server communication less chatty. Basically, I plan to defer the actual http request and collect batches thereof. These would be POSTed as a batch and results would be streamed back to the client (so that the fastest server function isn't blocked by the slowest). Given the 6 connection limit in browsers and the round-trip overhead, I'm speculating that this will provide a faster experience.

I've been tossing around the idea of starting a Discord server for higher-bandwidth discussions. Would you be interested in that sort of thing? Other ideas?

brillout commented 3 years ago

We seem to agree on a lot!

For TypeScript users, there is quite a bit of boilerplate

There is a new version that I didn't release yet that improves this.

I suspect that there may be opportunities for Nostalgie to consume wildcard-api in such a way that this would be avoidable

Yes, allowing tight integrations is definitely a goal.

I'm generally not a huge fan of this sort of implicit contract where functions are called with a 'special' receiver.

I'm curious; why don't you like it? While secondary, I find aesthetics do play a non-negligable role.

can not be written as arrow functions

The aforementioned unreleased version allows telefunctions (the new version is called Telefunc instead of Wildcard API) to be defined as arrow functions.

I think you have a really nice story for distinguishing network and code errors

It took me a while to get there :).

CloudFlare Workers

So neat what they are doing with Wasm. It's going to take a while but I can't wait for their platform to mature enough to be able to ship full-stack WebAssembly apps to Cloudflare, including a Wasm database client.

Something that is not yet evident in Nostalgie's codebase is that I hope to make the browser --> server communication less chatty

When you think about it, this actually does not really happen with RPC. This is a RESTful problem, not an RPC problem. The thing here is that you define telefunctions to retrieve exactly what the frontend needs. This means you end up with one telefunction per frontend need.

Given our RESTful habits, it takes a bit of time to get accustomted to the RPC-way. But once you get the feel of it, it's super neat.

I've been tossing around the idea of starting a Discord server for higher-bandwidth discussions. Would you be interested in that sort of thing? Other ideas?

Sounds good. I'm flexible; I'm fine with async writing as well as sync chat / video call :-).

Curious to see how this is going to go.

One thing we do disagree on though: I believe react-router to be mostly unnecessary for SSR apps. Classical page-based routes a la Express is fine for like 97% of apps. For apps that want nested routes, the user would opt-in to use React Router. By default I believe React Router shouldn't be included.

Also, we should discuss authentication. From first sight, I really like your auth plans, and I believe you'll appreciate https://github.com/brillout/wildcard-api/issues/59. Your plan and Wildcard Sessions fit well. (Wildcard Sessions is already used in production.)

ggoodman commented 3 years ago

Hi @brillout, I've put together a Contribution Guide whose intent is to help explain the codebase's organization and architecture. Hope you enjoy!

I've taken a look at the wildcard sessions issue and it does look interesting. I have some pretty strong opinions on this subject as an Auth0 employee. I think that many auth solutions do a great job at authentication but then fall short on authorization.

One of the interesting ideas in the withAuthenticationRequired HOC is that it can optionally accept a scope and audience. I feel like it is a huge value-added to be able to provide step up auth as an out-of-the-box feature. This is normally something that requires quite a bit of a dance between the client and server when these two parties are not tightly integrated.

ggoodman commented 3 years ago

The realtime / bi-di communication looks really interesting to me!

brillout commented 3 years ago

I've put together a Contribution Guide whose intent is to help explain the codebase's organization and architecture

Neat, I guess I should do the same.

The realtime / bi-di communication looks really interesting to me!

Yea, I can't wait for one of my user to need this, I'll then implement it. My plan is to simply use non-closing HTTP responses, while requiring the user to use HTTP/2 in order to remediate the concurrent number of connections limit problem.

I have some pretty strong opinions on this subject

Love it, me too ;-).

Wouldn't programmaticallly defined permissions be enough?

import { server, context } from "telefunc/server";

server.updateTodoText = async (id, updatedText) => {
  const todo = await Todo.findById(id);

  // Programmaticallly defined permissions
  if (!todo) return;
  if (!(context.user?.id === todo.authorId || context.user?.isAdmin)) return;

  todo.text = updatedText;
  await todo.save();
};

One thing we do disagree on though: I believe react-router to be mostly unnecessary for SSR apps.

Would love to hear your opinion on that. I'm happy to be contradicted.

R :-)

ggoodman commented 3 years ago

Wouldn't programmatically defined permissions be enough?

The vision for Nostalgie is to help build the Frontend and that frontend's backend (backend-for-frontend). These two are developed and deployed as tightly-coupled components. The Frontend talks to its backend's Server Functions. This backend for the frontend is a place to hold credentials and make calls to other APIs in a Service-Oriented Architecture.

To be able to make authenticated requests to these API servers, there are two high-level approaches:

  1. Authenticate using 'service credentials' which means that the ultimate API only knows which other service is making the call but not the user on behalf of whom the call is being made.
  2. Authenticate using some form of delegated authorization (OAuth2 + OpenID). In this scenario, the credentials have a few requirements: a) issued by a trusted issuer (iss claim); b) issued for the correct audience (aud claim); c) associated with the correct user (sub claim); and d) issued with sufficient scope for the given operation.

Nostalgie's authn / authz design aims to facilitate the 2nd scenario, without making the first any harder. This is the sort of 'step-up authentication' I'm talking about. Using it, you can gradually (or just on-demand) increase the authorizations issued to the user's session as the user attempts to perform operations requiring higher / different privileges.

Programmatic authorization is fine in simple cases but usually falls short in larger, SOAs.

ggoodman commented 3 years ago

Would love to hear your opinion on that. I'm happy to be contradicted.

The way I see it is that a forward-thinking SSR framework, like Nostalgie needs a deep integration with 'a router' to be able to fully hydrate arbitrarily complex routing designs. I picked react-router for its maturity and adoption in the community.

A user can easily build an app with Nostalgie that doesn't use any routing and thereby not have their front-end chunks contain any extra routing code. However, Nostalgie wants to provide a deeply-integrated solution and url-based routing is a fundamental primitive of the web so it has made a bet on react-router.

brillout commented 3 years ago

I agree with react-router, I just think it should be opt-in and not the default router. A super simple router like https://github.com/pillarjs/path-to-regexp should be the default. Simply because React Router needs a non-negligable amount of time to be learned and it's frustrating to spend time on it when nested routes are not needed.

As for authn / authz, I'm not sure I'm following; I'm not seeing a concrete situation where something as sophisticated as you decribed is needed.

In the end, the API simply has to know who is doing the request, his permissions, and decide whether to authorize the request. That's it, right?

brillout commented 3 years ago

There is work in progress for a deep integration between vite-plugin-ssr and Vue Router. Something similar could be done for React Router. Maybe we could consider rebasing Nostalgie on https://github.com/brillout/vite-plugin-ssr. Nostalgie would then have a rock-solid SSR foundation.