pylon
pylon copied to clipboard
[Feature Request ] - Pylon without web server.
Is your feature request related to a problem? Please describe. Would love access to opportunity to use pylon in a way that still allows me native control of the underlying http server.
const app = new Hono(<opportunity to configure here>)
// <various app logic
Bun.serve({
port: Number(process.env.PORT || 3001),
idleTimeout: 120,
fetch: (request, ctx) => {
// some programmatic logic here.
// opportunity to use pylon here.
return app.fetch(request, ctx);
},
});
This has the following advantages:
- Potential to use pylon in other web frameworks that aren't Hono.
- Potential for people to integrate pylon into brownfield apps more easily.
- Simplifies documentation / maintenance because all documentation relating to the "web server" component can be removed or kept for backwards compatibility in another section; Or 'in parallel compatibility'.
- Potential to configure idleTimeout (https://bun.sh/docs/api/http#idletimeout) which prevents slow loris attack and solve other problems.
- Potential to configure PORT as environment variable including the environment variables name which simplifies the pylon command.
- Potential to use different commands for
devI.E
"dev": "pylon dev -c \"bun run .pylon/index.js\" --client --client-port 3003 --client-path gqty\\index.ts",
// becomes
"dev": "bun run --watch ./src/server.ts"
- Simplifies docker entry point command.
- Potential to use pylon (graphql) in environments outside of http I.E udp, LoRA, etc.
The summary of above is it would provide people to separate "pylon" from the underlying "runtime" and "web framework" allowing more flexibility to developers.
Issues and simplifications
export const graphql = { Query: { hello: () => 'Hello World'}, Mutation: {} }
This syntax would potentially need to expose a type of a function that matches the app.fetch signature from Hono. I see this though as an improvement because it would allow people to create different adapters for different web frameworks. I.E
export const graphql = { Query: { hello: () => 'Hello World'}, Mutation: {} }
export default graphql // existing setup non-breaking change stays the same.
// web server control way being proposed
import { adapter } from "pylon/hono";
export const graphql = adapter({ Query: { hello: () => 'Hello World'}, Mutation: {} });
Which leaves room for express/elysia/node/etc adapters.
Adapters would setup a AsyncLocalStorage context, allowing developers to set getContext and potential to use that (request storage context) for other properties/state I.E tracing etc.
resloves
https://github.com/getcronit/pylon/issues/9 https://github.com/getcronit/pylon/issues/21 (because can leverage existing auth strategy's in underlying web framework)
Hi @ShanonJackson!
Thank you for your interesting request. I need to give this deeper thought to determine how a more "general" approach would be feasible, considering Pylon aims to be a framework that simplifies development rather than a universal library for all frameworks.
Here's what I can say for now:
- Pylon's dev command is designed this way because it relies on a prebuild step for schema and client generation. That's why you need to execute
.pylon/index.js. I'm not sure if it's technically possible to change that at this point. - You already have control over the "server." The proposed
Bun.servecommand works out of the box, so you can configureidleTimeout,PORTas an environment variable, etc.
Could you elaborate on how this would fix issue #9?
for #9
app.post("/2024-10-10/graphql", adapter({
Query: {
resource: () => "hello 2024-10-10"
}
}, {output: "2024-10-10.schema.graphql"});
app.post("/graphql", adapter({
Query: {
resource: () => "hello original"
}
}, {output: "schema.graphql" /* default */});
and via spread to override a specific resource without rewriting the whole graphql constant.
const gql = graphql({Query: {resource: () => "hello non versioned"});
app.post("/2024-10-10/graphql", adapter({...gql, Query: {...gql.Query, resource: "hello 2024-10-10"}})); // with "resource" overridden but everything else same.
app.post("/graphql", adapter(gql));
This way you can create new versions of specific resources and/or entire new graphql schemas using whatever version system you desire. I.E standard api numerical based versioning or by date.
Obivously above syntax requires outputting
Pylon's dev command is designed this way because it relies on a prebuild step for schema and client generation
For this yes, the intention was to decouple this "prebuild step" from the dev command itself and run it as an entirely separate command.
I.E pylon generate --watch dev would be concurrently watch and serve. Not that I'm a fan of saying "here they do x" but in most code gen based tooling they have decoupled watch commands.
You already have control over the "server." The proposed Bun.serve
Can you show me the syntax for this?
Can you show me the syntax for this?
import {app} from '@getcronit/pylon'
export const graphql = {
Query: {
test: () => 'Hello, world!'
}
}
export default app
const server = Bun.serve({
fetch: app.fetch,
port: 4000,
idleTimeout: 120
})
console.log(`Server running at ${server.url}`)
for #9
#9 is not just about configuring date based routes, but rather automatic backwards compatible versioning handled by Pylon. Related to #8.
So for example when you release a API with a a test query and later remove the test query, it will still be available in old version endpoint, but no longer in latest.
This should then be the case with all breaking changes that you introduce in your pylon application.
Hi @ShanonJackson.
I just released a new feature that allows setting up the graphql routes manually.
This is mainly used for dependency mocking during test, but is also the first step to be more framework agnostic.
https://pylon.cronit.io/docs/guides/testing#optional-mocking-dependencies