-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lazy app initialization code #758
Comments
Another use-case came up recently: graphql-nexus/nexus#523 (comment) The reason we can consider it a use-case is that we can tap into the lifecycle to solve it, for example: on.before.start((data) => {
server.express.get('*', () => {
// ...
})
}) |
New idea for an API. Also, we now have better definition of the runtime hooks.
// style 1
on(async ({ before, after }) => {
let data
data = await before.assembly
data = await before.assembly.loadPlugins
data = await before.assembly.makeSchema
data = await before.assembly.makeServer
data = await before.assembly.checks
data = await before.start
data = await before.start.serverListening
data = await after.assembly
data = await after.assembly.loadPlugins // [1] reflect on used plugins short circuit here
data = await after.assembly.makeSchema // [2] reflect on schema short circuit here
data = await after.assembly.makeServer
data = await after.assembly.checks
data = await after.start
data = await after.start.serverListening
}) // style 2
on.before.start((data) => {})
... // Example style 1 v 2
on(async ({ before }) => {
const data = await before.start
server.express.get('*', () => {
// ...
})
})
on.before.start((data) => {
server.express.get('*', () => {
// ...
})
}) Style 1 may pose too challenging to implement but I'm interested in trying. It will require some trickery but so far doesn't look impossible. Also, quite interesting to think about DX of top-level await that we could explore in the future: let data
data = await on.before.assembly
data = await on.before.assembly.loadPlugins
data = await on.before.assembly.makeSchema
data = await on.before.assembly.makeServer
data = await on.before.assembly.checks
data = await on.before.start
data = await on.before.start.serverListening
data = await on.after.assembly
data = await on.after.assembly.loadPlugins // [1] reflect on used plugins short circuit here
data = await on.after.assembly.makeSchema // [2] reflect on schema short circuit here
data = await on.after.assembly.makeServer
data = await on.after.assembly.checks
data = await on.after.start
data = await on.after.start.serverListening |
We could also entertain worktime hooks, but probably in a new issue, and later. on.worktime.build(async ({ before, after }) => {
// e.g.
await before.reflection
await after.typescript.checker.pass
await before.typescript.emit
}) |
Discussion with @Weakky the other day.
|
Another instance graphql-nexus/nexus#983 |
Wow! Listening on events in booting process is grat feature. What to you think about global event emitter with events:
Accessible in:
Node js Api: |
I think that API is more than we need and would degrade the simplicity of the Nexus API. Open to hearing specific pros about it though. |
Another instance #1201 |
Users should probably be able to tap into reflection as well. Doing so will require removing the code at build time, so that bundling doesn't drag in work time dependencies. This would make it easy for users to, for example, generate a genql client. While in that case Nexus might integrate it (genql) the point is any tool. Some of the events we have:
|
Another idea. Path and module name convention. I’m not convinced we should do this. But I want to document it.
Examples:
What’s nice about this is:
What’s not good about this:
|
I would like to unify a few things: runtime events, worktime events, stage "events" (?). Stage is about what "environment" the app is running in: dev, preview, prod, etc. Example, rewriting use-case of https://github.com/graphql-nexus/nexus/issues/1201:import { on, schema, settings } from 'nexus'
import Redis from 'redis';
on.run.before(() => {
schema.addToContext({
redis: Redis.createClient(settings.current.redis)
})
}) Note, this requires allowing objects to be passed to Example, generate genql:import { generate } from 'genql-cli'
import { on } from 'nexus'
on.reflect.after(async (project) => { // <-- this codeblock stripped at build time <3
await generate({
schema: project.data.schema,
output: project.path('client'),
scalarTypes: {
MongoID: 'string',
},
})
}) Access to booleans:if (on.stage.now === 'production') {
}
if (on.reflect.now) {
}
if (on.run.now) {
} |
Addressing another use-case https://prisma.slack.com/archives/CM2LEN7JL/p1594329877332200 Example, access built graphql schema import { createServer } from 'http';
import { SubscriptionServer } from 'subscriptions-transport-ws';
import { execute, subscribe } from 'graphql';
import { schema } from './my-schema';
on.run.graphql.after(({ schema }) => {
const websocketServer = createServer((request, response) => {
response.writeHead(404)
response.end()
})
const subscriptionServer = SubscriptionServer.create(
{
schema,
execute,
subscribe,
},
{
server: websocketServer,
path: '/graphql',
},
)
return new Promise(res => { websocketServer.listen(5000, res) }).then(() => {
console.log(
`Websocket Server is now running on http://localhost:${WS_PORT}`
)
})
}) |
Current Workaround
Please see this graphql-nexus/nexus#732 (comment)
Perceived Problem
Ideas / Proposed Solution(s)
Raw sketches (with @Weakky)
We identified that the execution phase is not the same thing as the deployment stage (Deployment stage conditional code #535)
The deployment stage is a union of e.g.
dev|prod|qa|test
The execution phase is a union of
run|reflect
We think most use-cases will be for
not:
For one thing reflection isn't meant to be user-facing concept, but an internal engine one that just impacts the user with constraints.
For another, we just don't see use-cases for it right now.
We think this code would be far from ideal:
We think an event concept would be easiest to understand
Lifecycle wise we need an event that is:
We think that event can be called
boot
.References
Instances
The text was updated successfully, but these errors were encountered: