diff --git a/src/data/cbor.ts b/src/data/cbor.ts index ebf449e..0480088 100644 --- a/src/data/cbor.ts +++ b/src/data/cbor.ts @@ -1,4 +1,4 @@ -import { Tagged, decode, encode } from "../cbor"; +import { type Replacer, Tagged, decode, encode } from "../cbor"; import { cborCustomDateToDate, dateToCborCustomDate, @@ -55,7 +55,10 @@ const TAG_GEOMETRY_MULTILINE = 92; const TAG_GEOMETRY_MULTIPOLYGON = 93; const TAG_GEOMETRY_COLLECTION = 94; -export const replacer = { +export const replacer: { + encode: Replacer; + decode: Replacer; +} = { encode(v: unknown): unknown { if (v instanceof Date) { return new Tagged(TAG_CUSTOM_DATETIME, dateToCborCustomDate(v)); diff --git a/src/data/index.ts b/src/data/index.ts index 19c8689..e3e883c 100644 --- a/src/data/index.ts +++ b/src/data/index.ts @@ -25,4 +25,4 @@ export { GeometryPoint, GeometryPolygon, } from "./types/geometry.ts"; -export { encodeCbor, decodeCbor } from "./cbor.ts"; +export { encodeCbor, decodeCbor, replacer } from "./cbor.ts"; diff --git a/src/surreal.ts b/src/surreal.ts index d27630c..4b10e6f 100644 --- a/src/surreal.ts +++ b/src/surreal.ts @@ -3,8 +3,6 @@ import { Table, type Uuid, RecordId as _RecordId, - decodeCbor, - encodeCbor, } from "./data"; import { type AbstractEngine, @@ -34,7 +32,13 @@ import { convertAuth, } from "./types.ts"; -import { type Fill, partiallyEncodeObject } from "./cbor"; +import { + type Fill, + type Replacer, + decode, + encode, + partiallyEncodeObject, +} from "./cbor"; import { replacer } from "./data/cbor.ts"; import type { RecordIdRange } from "./data/types/range.ts"; import { HttpEngine } from "./engines/http.ts"; @@ -51,6 +55,17 @@ import { type R = Prettify>; type RecordId = _RecordId | StringRecordId; +export type SurrealOptions = { + engines?: Engines; + + replacer?: ReplacerOptions; +}; + +export type ReplacerOptions = { + encode: Replacer; + decode: Replacer; +}; + export class Surreal { public connection: AbstractEngine | undefined; ready?: Promise; @@ -61,12 +76,9 @@ export class Surreal { http: HttpEngine, https: HttpEngine, }; + protected replacer: ReplacerOptions; - constructor({ - engines, - }: { - engines?: Engines; - } = {}) { + constructor({ engines, replacer: customReplacer }: SurrealOptions = {}) { this.emitter = new Emitter(); this.emitter.subscribe(ConnectionStatus.Disconnected, () => this.clean()); this.emitter.subscribe(ConnectionStatus.Error, () => this.close()); @@ -77,6 +89,11 @@ export class Surreal { ...engines, }; } + + this.replacer = customReplacer ?? { + encode: replacer.encode, + decode: replacer.decode, + }; } /** @@ -116,8 +133,8 @@ export class Surreal { // to ensure that everything is using the same instance of classes that these methods depend on. const context = new EngineContext({ emitter: this.emitter, - encodeCbor, - decodeCbor, + encodeCbor: (data) => encode(data, { replacer: this.replacer?.encode }), + decodeCbor: (data) => decode(data, { replacer: this.replacer?.decode }), }); // The promise does not know if `this.connection` is undefined or not, but it does about `connection` diff --git a/src/util/prepared-query.ts b/src/util/prepared-query.ts index 771b91d..3613ea8 100644 --- a/src/util/prepared-query.ts +++ b/src/util/prepared-query.ts @@ -3,6 +3,7 @@ import { type Fill, Gap, type PartiallyEncoded, + type Replacer, Writer, encode, partiallyEncodeObject, @@ -19,13 +20,19 @@ export type ConvertMethod = (result: unknown[]) => T; export class PreparedQuery { private _query: Uint8Array; private _bindings: Record; + private _replacer: Replacer; private length: number; - constructor(query: string, bindings?: Record) { + constructor( + query: string, + bindings?: Record, + { replacer: customReplacer }: { replacer?: Replacer } = {}, + ) { textEncoder ??= new TextEncoder(); this._query = textEncoder.encode(query); + this._replacer = customReplacer ?? replacer.encode; this._bindings = partiallyEncodeObject(bindings ?? {}, { - replacer: replacer.encode, + replacer: this._replacer, }); this.length = Object.keys(this._bindings).length; } @@ -53,7 +60,10 @@ export class PreparedQuery { * @param fills - The gap values to fill */ build(fills?: Fill[]): ArrayBuffer { - return encode([this.query, this.bindings], { fills }); + return encode([this.query, this.bindings], { + fills, + replacer: this._replacer, + }); } /** @@ -92,7 +102,7 @@ export class PreparedQuery { for (const [k, v] of mapped_bindings) { this._bindings[k] = encode(v, { - replacer: replacer.encode, + replacer: this._replacer, partial: true, }); }