Skip to content

Commit d7bd8b3

Browse files
authored
Merge pull request #481 from M4xymm/RDBC-909
RDBC-909 - Returning class instances in client causes issues in Next.js — responses should be plain objects
2 parents ff50e35 + 75425f9 commit d7bd8b3

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

src/Documents/Conventions/DocumentConventions.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,25 @@ export class DocumentConventions {
116116
return this._sharding;
117117
}
118118

119+
private _returnPlainJsObjects: boolean = false;
120+
121+
/**
122+
* Gets whether all values returned from API will be plain objects (not class instances).
123+
* This is useful for environments like Next.js that require serializable results.
124+
*/
125+
public get returnPlainJsObjects(): boolean {
126+
return this._returnPlainJsObjects;
127+
}
128+
129+
/**
130+
* Sets whether all values returned from API will be plain objects (not class instances).
131+
* This is useful for environments like Next.js that require serializable results.
132+
*/
133+
public set returnPlainJsObjects(value: boolean) {
134+
this._assertNotFrozen();
135+
this._returnPlainJsObjects = value;
136+
}
137+
119138
public constructor() {
120139
this._readBalanceBehavior = "None";
121140
this._identityPartsSeparator = "/";

src/Documents/Session/AbstractDocumentQuery.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ import {
9797
} from "./IVectorFieldFactory.js";
9898
import { VectorEmbeddingFieldFactory } from "../Queries/VectorSearch/VectorEmbeddingFieldFactory.js";
9999
import { Field } from "../../Types/index.js";
100+
import { JsonSerializer } from "../../Mapping/Json/Serializer.js";
100101

101102
/**
102103
* A query against a Raven index
@@ -2193,7 +2194,13 @@ export abstract class AbstractDocumentQuery<T extends object, TSelf extends Abst
21932194

21942195
public async all(): Promise<T[]> {
21952196
const results = await this.iterator();
2196-
return [...results];
2197+
const array = [...results];
2198+
2199+
if (this.conventions.returnPlainJsObjects) {
2200+
return array.map(item => JsonSerializer.toPlainObject(item))
2201+
}
2202+
2203+
return array;
21972204
}
21982205

21992206
public async getQueryResult(): Promise<QueryResult> {
@@ -2208,11 +2215,20 @@ export abstract class AbstractDocumentQuery<T extends object, TSelf extends Abst
22082215
throwError("InvalidOperationException", "Expected at least one result.");
22092216
}
22102217

2218+
if (this.conventions.returnPlainJsObjects) {
2219+
return JsonSerializer.toPlainObject(entries[0]);
2220+
}
2221+
22112222
return entries[0];
22122223
}
22132224

22142225
public async firstOrNull(): Promise<T | null> {
22152226
const entries = await this._executeQueryOperation(1);
2227+
2228+
if (this.conventions.returnPlainJsObjects) {
2229+
return JsonSerializer.toPlainObject(entries[0]) || null;
2230+
}
2231+
22162232
return entries[0] || null;
22172233
}
22182234

@@ -2224,6 +2240,10 @@ export abstract class AbstractDocumentQuery<T extends object, TSelf extends Abst
22242240
`Expected single result, but got ${ entries.length ? "more than that" : 0 }.`);
22252241
}
22262242

2243+
if (this.conventions.returnPlainJsObjects) {
2244+
return JsonSerializer.toPlainObject(entries[0]);
2245+
}
2246+
22272247
return entries[0];
22282248
}
22292249

@@ -2233,6 +2253,11 @@ export abstract class AbstractDocumentQuery<T extends object, TSelf extends Abst
22332253
throwError("InvalidOperationException",
22342254
`Expected single result, but got more than that.`);
22352255
}
2256+
2257+
if (this.conventions.returnPlainJsObjects) {
2258+
return entries.length === 1 ? JsonSerializer.toPlainObject(entries[0]) : null;
2259+
}
2260+
22362261
return entries.length === 1 ? entries[0] : null;
22372262
}
22382263

src/Mapping/Json/Serializer.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,12 @@ export class JsonSerializer {
3737
public static getDefaultForCommandPayload(): JsonSerializer {
3838
return new JsonSerializer(camelCaseReviver, pascalCaseReplacer);
3939
}
40+
41+
public static toPlainObject<T>(obj: T): T {
42+
if (obj === undefined) {
43+
return undefined as T;
44+
}
45+
46+
return JSON.parse(JSON.stringify(obj));
47+
}
4048
}

0 commit comments

Comments
 (0)