Open HamishWHC opened 1 year ago
This came up before in various variations, and we're hesitant to add something like this as it complicates the (de)serialization mechanism quite a bit. Also, what about actions
? And should all get the same treatment, or is this per-load
-function, or per-thing-to-(de)-serialize? It's hard to find a good answer here, which is why we have deferred this to "implement a wrapper yourself" so far. You already did one part of this, you could do the other end through running something like
/// +page.svelte
export let data; // is the jsonified thing
$: user = unjsonify<User>(data);
Good points. As a user I would expect the feature to occur for actions, and perhaps error data as well, although my gut feeling is that case would be extremely niche (and tbh I've never even tested if Date
or BigInt
is serialised in those either). I'm not at all familiar with Kit's internals, but I my guess was that actions and loaders share serialization logic, so that applying this to both would be not much more work (or complexity) than applying it to one. I suppose that's not the case when working with type generation?
+1 on this, would be nice to have some transformation hook where we can add custom logic for transforming variables
eg:
async transform(value: unknown) {
if (value instanceof Foo) { ... }
return value
}
I have some classes being added by SurrealDB for RecordId
s linking user objects, but they're just getting converted to JSON which is annoying as it messes with other query types
It's also stupid because this messes with typing, and svelte thinks that a value is still of a certain type when transformed.
Describe the problem
My problem is that my database client returns data that includes classes, and I can't return this from my
+page.server.ts
file and use it in my+page.{ts,svelte}
. Examples of these classes includePrisma.Decimal
, model instances from Type/MikroORM, objects with extra methods returned by an extended Prisma client (see Prisma docs) or anything else that might be a class inside a deeply nested object.Describe the proposed solution
Having read through #6008 (and the pull request), my understanding is that
devalue
creates JS code that recreates the JS object is it passed, and that getting the generated code to reference constructors for these classes would be difficult (that said, I have an idea for this that I'd like to propose, not certain if it'd work, see below).Instead, what I really am looking for is the ability to hand some arbitrary data to Svelte and have it transform it to data that is compatible with
devalue
. i.e. I register a function (server-side) that identifies my class, then provide a function that takes an instance of this class and returns an object that is already compatible withdevalue
. This could then be incorporated into the type generation system (similar to param matchers) so thatPageLoad
functions have corrected types.I don't think my explanation was very clear, so here's an example:
Idea for deserializing classes
Rich's initial explanation of using devalue in #6008 says the deserialization process is (roughly): ```ts await import(`${url.pathname}/__data.js`); const data = window.__data; delete window.__data; ``` Could devalue be made to set `window.__data` to a function that can be passed functions to deserialize the data? This would avoid the issue of ensuring constructors are available to `devalue`'s generated code. The deserialization functions could also be lazy loaded if needed. This isn't really useful in the above example (a database model likely has server-side only functions attached to it, in which case I only want the POJO), but for custom scalars such as `Prisma.Decimal`, this would be quite helpful.Alternatives considered
My current solution is to write a function that 'jsonifies' my complex objects in a type-safe-ish way (
Range
is fromedgedb
):I can then wrap database queries in this (or add it with
.then(jsonify)
). This doesn't allow for deserializing classes.I've also been looking at potentially using
superjson
, but I lose the ability to modify thePageData
type without touching anything else - I have to modify the types that I am reporting tosuperjson
.Importance
nice to have
Additional Information
No response