-
Notifications
You must be signed in to change notification settings - Fork 5
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
ServiceSchema
implementation
#76
Conversation
ServiceSchema
implementationServiceSchema
implementation
/** | ||
* Serializes this schema's procedures into a plain object that is JSON compatible. | ||
*/ | ||
serialize(): object { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe for another PR but i'd like to have a helper type that reconstructs ServiceSchemaMap
from a bunch of serialized services
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would the state be serialized? Do we even care about state ever being serialized?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think ok for state to not be serialized, i meant for the client type (the result of Server<typeof serviceDefs>>
normally
mostly to help us ensure we have a way to go from JSON schema generated by a non-TS implementation of river (e.g. Python or Protobufs ala AI chat) to something we can consume in TS
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahh okay I get it, if you have a literal serialized state (in types) it lets you convert to (approximately) the service schema map that was serialized, albeit without state info
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good! can we bump to 0.16.0 before merging?
@@ -251,18 +298,30 @@ export class ServiceSchema< | |||
>; | |||
// actual implementation | |||
static define( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i wonder if, instead of overloading, we should just have define
and defineWithConfig
and have define
just call defineWithConfig
with the default config { initializeState: () => ({}) }
TypeScript has nearly taken my soul.
This PR replaces our current way of creating services. You now create them like this:
or like this, if you have no state:
Either way, you're given back a
ServiceSchema
, which you can basically treat like a class for your service. Services also no longer have names, instead you provide a dictionary to the server where the keys are the names, and the values are the service schemas:This way of constructing services gets us 90% out of recursive TypeScript hell, and is also intended to make writing services easier, primarily through better legibility.
Some other changes:
never
, procedures can now always emitRiverUncaughtSchema
errors and it is now allowed to omit theerrors
property when creating procedures. If you don't provide the prop, it just defaults toType.Never()
.Procedure
object, e.g.Procedure.rpc(...)
. This prevents footguns that can happen by manually providing procedures to services (TS gets confused and doesn't type check your procedure!), and also lets us enable ergonomics (like omitting theerrors
prop). The way the footgun is forcibly avoided is purely through the type system - procedures created by these constructors are "branded" with an inaccessible unique symbol (which is not actually there), andServiceSchema.define
accepts only branded procedures.