surrealdb
Version:
The official SurrealDB SDK for JavaScript.
1,742 lines (1,729 loc) • 225 kB
JavaScript
//#region src/internal/normalize-path.ts
function normalizePath(prefix, path) {
return `/${[...prefix.split("/"), ...path.split("/")].filter(Boolean).join("/")}`;
}
//#endregion
//#region src/errors.ts
var SurrealError = class extends Error {};
/**
* Thrown when a call has been terminated because the connection was closed
*/
var CallTerminatedError = class extends SurrealError {
name = "CallTerminatedError";
message = "The call has been terminated because the connection was closed";
};
/**
* Thrown when reconnect attempts have been exhausted
*/
var ReconnectExhaustionError = class extends SurrealError {
name = "ReconnectExhaustionError";
message = "The reconnect attempts have been exhausted";
};
/**
* Thrown when a reconnect iterator fails to iterate
*/
var ReconnectIterationError = class extends SurrealError {
name = "ReconnectIterationError";
message = "The reconnect iterator failed to iterate";
};
/**
* Thrown when an unexpected server response is received
*/
var UnexpectedServerResponseError = class extends SurrealError {
name = "UnexpectedServerResponseError";
response;
constructor(response) {
super(`The server returned an unexpected response: ${JSON.stringify(response)}`);
this.response = response;
}
};
/**
* Thrown when an unexpected connection error occurs
*/
var UnexpectedConnectionError = class extends SurrealError {
name = "UnexpectedConnectionError";
message = "An unexpected connection error occurred";
constructor(cause) {
super();
this.cause = cause;
}
};
/**
* Thrown when an engine is not supported
*/
var UnsupportedEngineError = class extends SurrealError {
name = "UnsupportedEngineError";
engine;
constructor(engine) {
super(`The engine "${engine}" is not supported or configured`);
this.engine = engine;
}
};
/**
* Thrown when there is no connection available
*/
var ConnectionUnavailableError = class extends SurrealError {
name = "ConnectionUnavailableError";
message = "You must be connected to a SurrealDB instance before performing this operation";
};
/**
* Thrown when there is no namespace and/or database selected
*/
var MissingNamespaceDatabaseError = class extends SurrealError {
name = "MissingNamespaceDatabaseError";
message = "There is no namespace and/or database selected";
};
/**
* Thrown when a connection to the server fails
*/
var HttpConnectionError = class extends SurrealError {
name = "HttpConnectionError";
status;
statusText;
buffer;
constructor(message, status, statusText, buffer) {
super(`HTTP connection failed: ${message}`);
this.status = status;
this.statusText = statusText;
this.buffer = buffer;
}
};
/**
* Known error kinds returned by the SurrealDB server.
* Use these constants for matching against `ServerError.kind`.
*/
const ErrorKind = {
Validation: "Validation",
Configuration: "Configuration",
Thrown: "Thrown",
Query: "Query",
Serialization: "Serialization",
NotAllowed: "NotAllowed",
NotFound: "NotFound",
AlreadyExists: "AlreadyExists",
Connection: "Connection",
Internal: "Internal"
};
/**
* Base class for all errors originating from the SurrealDB server.
* Replaces the former `ResponseError` class.
*
* Server errors carry structured information:
* - `kind` — the error category (e.g. `"NotAllowed"`, `"NotFound"`)
* - `code` — legacy JSON-RPC numeric error code (0 when unavailable)
* - `details` — kind-specific structured details from the server (`{ kind, details? }` format)
* - `cause` — optional inner `ServerError` forming a recursive error chain
*
* The `cause` field mirrors Rust's `Option<Box<Error>>` — each error can
* optionally wrap an inner error, creating a stack of structured errors.
* It is set as the native `Error.cause` so that standard JS tooling
* (Node.js, Chrome DevTools, debuggers) displays the full chain
* automatically using the `[cause]:` format.
*
* Use `instanceof` on subclasses (e.g. `NotFoundError`, `NotAllowedError`)
* for type-safe matching, or check the `kind` property directly.
*/
var ServerError = class extends SurrealError {
get name() {
return `ServerError [${this.kind}]`;
}
/** The structured error kind (e.g. "NotAllowed", "NotFound", "Internal") */
kind;
/** Legacy JSON-RPC error code. 0 when not available (e.g. query result errors). */
code;
/**
* Kind-specific structured details using the `{ kind, details? }` wire format.
* `undefined` when not provided by the server. Subclasses narrow this type
* to their specific detail union (e.g. `NotAllowedErrorDetail`).
*/
details;
constructor(options) {
const innerCause = options.cause ?? void 0;
super(options.message, innerCause ? { cause: innerCause } : void 0);
this.kind = options.kind;
this.code = options.code ?? 0;
this.details = options.details ?? void 0;
}
};
/**
* Server error: validation failure (parse error, invalid request/params, bad input).
*/
var ValidationError = class extends ServerError {
kind = "Validation";
get name() {
return "ValidationError";
}
/** True if this is a SurrealQL parse error. */
get isParseError() {
return this.details?.kind === "Parse";
}
/** The name of the invalid parameter, if applicable. */
get parameterName() {
if (this.details?.kind !== "InvalidParameter") return void 0;
return this.details.details?.name;
}
};
/**
* Server error: feature or configuration not supported (live queries, GraphQL).
*/
var ConfigurationError = class extends ServerError {
kind = "Configuration";
get name() {
return "ConfigurationError";
}
/** True if live queries are not supported by the server configuration. */
get isLiveQueryNotSupported() {
return this.details?.kind === "LiveQueryNotSupported";
}
};
/**
* Server error: user-thrown error via THROW in SurrealQL.
*/
var ThrownError = class extends ServerError {
kind = "Thrown";
get name() {
return "ThrownError";
}
};
/**
* Server error: query execution failure (timeout, cancelled, not executed).
*/
var QueryError = class extends ServerError {
kind = "Query";
get name() {
return "QueryError";
}
/** True if the query was not executed (e.g. due to a prior error in the batch). */
get isNotExecuted() {
return this.details?.kind === "NotExecuted";
}
/** True if the query timed out. */
get isTimedOut() {
return this.details?.kind === "TimedOut";
}
/** True if the query was cancelled. */
get isCancelled() {
return this.details?.kind === "Cancelled";
}
/** The timeout duration, if this is a timeout error. Returns `{ secs, nanos }` or undefined. */
get timeout() {
if (this.details?.kind !== "TimedOut") return void 0;
return this.details.details?.duration;
}
};
/**
* Server error: serialization or deserialization failure.
*/
var SerializationError = class extends ServerError {
kind = "Serialization";
get name() {
return "SerializationError";
}
/** True if this is a deserialization error (as opposed to serialization). */
get isDeserialization() {
return this.details?.kind === "Deserialization";
}
};
/**
* Server error: permission denied, method not allowed, function/scripting blocked.
*/
var NotAllowedError = class extends ServerError {
kind = "NotAllowed";
get name() {
return "NotAllowedError";
}
/** True if the auth token has expired. */
get isTokenExpired() {
return this.details?.kind === "Auth" && this.details.details?.kind === "TokenExpired";
}
/** True if authentication credentials are invalid. */
get isInvalidAuth() {
return this.details?.kind === "Auth" && this.details.details?.kind === "InvalidAuth";
}
/** True if scripting is blocked. */
get isScriptingBlocked() {
return this.details?.kind === "Scripting";
}
/** The method name that is not allowed, if applicable. */
get methodName() {
if (this.details?.kind !== "Method") return void 0;
return this.details.details?.name;
}
/** The function name that is not allowed, if applicable. */
get functionName() {
if (this.details?.kind !== "Function") return void 0;
return this.details.details?.name;
}
};
/**
* Server error: resource not found (table, record, namespace, method, etc.).
*/
var NotFoundError = class extends ServerError {
kind = "NotFound";
get name() {
return "NotFoundError";
}
/** The table name that was not found, if applicable. */
get tableName() {
if (this.details?.kind !== "Table") return void 0;
return this.details.details?.name;
}
/** The record ID that was not found, if applicable. */
get recordId() {
if (this.details?.kind !== "Record") return void 0;
return this.details.details?.id;
}
/** The RPC method name that was not found, if applicable. */
get methodName() {
if (this.details?.kind !== "Method") return void 0;
return this.details.details?.name;
}
/** The namespace name that was not found, if applicable. */
get namespaceName() {
if (this.details?.kind !== "Namespace") return void 0;
return this.details.details?.name;
}
/** The database name that was not found, if applicable. */
get databaseName() {
if (this.details?.kind !== "Database") return void 0;
return this.details.details?.name;
}
};
/**
* Server error: duplicate resource (record, table, namespace, etc.).
*/
var AlreadyExistsError = class extends ServerError {
kind = "AlreadyExists";
get name() {
return "AlreadyExistsError";
}
/** The record ID that already exists, if applicable. */
get recordId() {
if (this.details?.kind !== "Record") return void 0;
return this.details.details?.id;
}
/** The table name that already exists, if applicable. */
get tableName() {
if (this.details?.kind !== "Table") return void 0;
return this.details.details?.name;
}
};
/**
* Server error: unexpected or unknown internal error.
* Also used as the fallback for unrecognized `kind` strings from newer servers.
*/
var InternalError = class extends ServerError {
kind = "Internal";
get name() {
return "InternalError";
}
};
/**
* @deprecated Use `ServerError` instead. This alias exists for backward compatibility.
*/
const ResponseError = ServerError;
/**
* Thrown when authentication fails
*/
var AuthenticationError = class extends SurrealError {
name = "AuthenticationError";
message = "Authentication did not succeed";
constructor(cause) {
super();
this.cause = cause;
}
};
/**
* Thrown when a live subscription fails to listen
*/
var LiveSubscriptionError = class extends SurrealError {
name = "LiveSubscriptionError";
constructor(messageOrCause) {
if (typeof messageOrCause === "string") super(messageOrCause);
else {
super("Live subscription failed to listen");
this.cause = messageOrCause;
}
}
};
/**
* Thrown when the version of the remote datastore is not supported
*/
var UnsupportedVersionError = class extends SurrealError {
name = "UnsupportedVersionError";
version;
minimum;
maximum;
constructor(version, minimum, maximum) {
super(`The version "${version}" reported by the engine is not supported by this library, expected a version that satisfies >= ${minimum} < ${maximum}`);
this.version = version;
this.minimum = minimum;
this.maximum = maximum;
}
};
/**
* Thrown when a SurrealQL expression fails to compute
*/
var ExpressionError = class extends SurrealError {
name = "ExpressionError";
constructor(messageOrCause) {
if (typeof messageOrCause === "string") super(messageOrCause);
else {
super("Failed to parse invalid expression");
this.cause = messageOrCause;
}
}
};
/**
* Thrown when one or more subscribers throw an error
*/
var PublishError = class PublishError extends SurrealError {
name = "PublishError";
message = "One or more subscribers threw an error:";
causes;
constructor(causes) {
super();
this.causes = causes;
this.message += PublishError.#appendCauses(causes, "");
}
static #appendCauses(causes, msg) {
let message = msg;
for (const cause of causes) if (cause instanceof PublishError) message = PublishError.#appendCauses(cause.causes, msg);
else message += `\n - ${cause instanceof Error ? cause.message : cause}`;
return message;
}
};
/**
* Thrown when a parsed date or datetime is invalid
*/
var InvalidDateError = class extends SurrealError {
name = "InvalidDateError";
constructor(dateOrMessage) {
if (typeof dateOrMessage === "string") super(dateOrMessage);
else super(`The provided date is invalid: ${dateOrMessage}`);
}
};
/**
* Thrown when a feature is not supported by the current engine
*/
var UnsupportedFeatureError = class extends SurrealError {
name = "UnsupportedFeatureError";
feature;
constructor(feature) {
super(`The configured engine does not support the feature: ${feature.name}`);
this.feature = feature;
}
};
/**
* Thrown when a feature is not available in the used version of SurrealDB
*/
var UnavailableFeatureError = class extends SurrealError {
name = "UnavailableFeatureError";
feature;
version;
constructor(feature, version) {
super(`The version of SurrealDB (${version}) does not support the feature: ${feature.name} (>= ${feature.sinceVersion} < ${feature.untilVersion})`);
this.feature = feature;
this.version = version;
}
};
/**
* Thrown when a session is invalid
*/
var InvalidSessionError = class extends SurrealError {
name = "InvalidSessionError";
message = "The provided session is invalid";
session;
constructor(session) {
super(`Invalid session: ${session}`);
this.session = session;
}
};
/**
* Thrown when an API request was unsuccessful
*/
var UnsuccessfulApiError = class extends SurrealError {
name = "UnsuccessfulApiError";
path;
method;
response;
constructor(path, method, response) {
super(`The ${method.toUpperCase()} ${path} request failed with status ${response.status}`);
this.path = path;
this.method = method;
this.response = response;
}
};
/**
* Thrown when a RecordId or RecordIdRange is constructed with invalid parts
*/
var InvalidRecordIdError = class extends SurrealError {
name = "InvalidRecordIdError";
};
/**
* Thrown when a Duration string cannot be parsed or a duration operation is invalid
*/
var InvalidDurationError = class extends SurrealError {
name = "InvalidDurationError";
};
/**
* Thrown when a Decimal operation fails (division by zero, invalid input, etc.)
*/
var InvalidDecimalError = class extends SurrealError {
name = "InvalidDecimalError";
};
/**
* Thrown when a Table or StringRecordId is constructed with an invalid value
*/
var InvalidTableError = class extends SurrealError {
name = "InvalidTableError";
};
//#endregion
//#region src/internal/dispatched-promise.ts
var DispatchedPromise = class extends Promise {
#resolve;
#reject;
#dispatched = false;
constructor() {
let _resolve;
let _reject;
super((resolve, reject) => {
_resolve = resolve;
_reject = reject;
});
if (!_resolve || !_reject) throw new Error("resolve and reject required");
this.#resolve = _resolve;
this.#reject = _reject;
}
#ensureDispatched() {
if (!this.#dispatched) {
this.#dispatched = true;
this.dispatch().then(this.#resolve, this.#reject);
}
return this;
}
then(onfulfilled, onrejected) {
this.#ensureDispatched();
return super.then(onfulfilled, onrejected);
}
catch(onrejected) {
this.#ensureDispatched();
return super.catch(onrejected);
}
finally(onfinally) {
this.#ensureDispatched();
return super.finally(onfinally);
}
static get [Symbol.species]() {
return Promise;
}
get [Symbol.toStringTag]() {
return "DispatchedPromise";
}
};
//#endregion
//#region src/internal/get-incremental-id.ts
let id = 0;
function getIncrementalID() {
id = (id + 1) % Number.MAX_SAFE_INTEGER;
return id.toString();
}
//#endregion
//#region src/utils/range.ts
/**
* Represents a range bound which includes the value within the range
*/
var BoundIncluded = class {
constructor(value) {
this.value = value;
}
};
/**
* Represents a range bound which excludes the value from the range
*/
var BoundExcluded = class {
constructor(value) {
this.value = value;
}
};
//#endregion
//#region src/internal/escape-regex.ts
function escapeRegex(str) {
return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
}
//#endregion
//#region src/value/value.ts
/**
* A complex SurrealQL value type
*/
var Value = class {};
//#endregion
//#region src/value/duration.ts
const NANOSECOND$1 = 1n;
const MICROSECOND$1 = 1000n * NANOSECOND$1;
const MILLISECOND$1 = 1000n * MICROSECOND$1;
const SECOND$1 = 1000n * MILLISECOND$1;
const MINUTE = 60n * SECOND$1;
const HOUR = 60n * MINUTE;
const DAY = 24n * HOUR;
const WEEK = 7n * DAY;
const YEAR = 365n * DAY;
const UNITS = new Map([
["ns", NANOSECOND$1],
["µs", MICROSECOND$1],
["μs", MICROSECOND$1],
["us", MICROSECOND$1],
["ms", MILLISECOND$1],
["s", SECOND$1],
["m", MINUTE],
["h", HOUR],
["d", DAY],
["w", WEEK],
["y", YEAR]
]);
const UNITS_REVERSED = Array.from(UNITS).reduce((map, [unit, size]) => {
map.set(size, unit);
return map;
}, /* @__PURE__ */ new Map());
const DURATION_PART_REGEX = /* @__PURE__ */ new RegExp(`^(\\d+)\\.?\\d*(${Array.from(UNITS.keys()).map(escapeRegex).join("|")})`);
const FLOAT_DURATION_REGEX = /* @__PURE__ */ new RegExp(`^(\\d+(?:\\.\\d+)?)(${Array.from(UNITS.keys()).map(escapeRegex).join("|")})$`);
/**
* A SurrealQL duration value with support for parsing, formatting, arithmetic, and nanosecond precision.
*/
var Duration = class Duration extends Value {
#seconds;
#nanoseconds;
constructor(input) {
super();
if (input instanceof Duration) {
this.#seconds = input.#seconds;
this.#nanoseconds = input.#nanoseconds;
} else if (typeof input === "string") {
const [s$1, ns] = Duration.parseString(input);
this.#seconds = s$1;
this.#nanoseconds = ns;
} else {
const s$1 = typeof input[0] === "bigint" ? input[0] : BigInt(Math.floor(input[0] ?? 0));
const ns = typeof input[1] === "bigint" ? input[1] : BigInt(Math.floor(input[1] ?? 0));
const total = s$1 * SECOND$1 + ns;
this.#seconds = total / SECOND$1;
this.#nanoseconds = total % SECOND$1;
}
}
equals(other) {
if (!(other instanceof Duration)) return false;
return this.#seconds === other.#seconds && this.#nanoseconds === other.#nanoseconds;
}
toJSON() {
return this.toString();
}
/**
* @returns Human readable duration string
*/
toString() {
let remainingSeconds = this.#seconds;
let result = "";
for (const [size, unit] of Array.from(UNITS_REVERSED).reverse()) if (size >= SECOND$1) {
const amount = remainingSeconds / (size / SECOND$1);
if (amount > 0n) {
remainingSeconds %= size / SECOND$1;
result += `${amount}${unit}`;
}
}
let remainingNanoseconds = remainingSeconds * SECOND$1 + this.#nanoseconds;
for (const [size, unit] of Array.from(UNITS_REVERSED).reverse()) if (size < SECOND$1) {
const amount = remainingNanoseconds / size;
if (amount > 0n) {
remainingNanoseconds %= size;
result += `${amount}${unit}`;
}
}
return result;
}
/**
* Converts the duration to a tuple
*/
toCompact() {
return this.#nanoseconds > 0n ? [this.#seconds, this.#nanoseconds] : this.#seconds > 0n ? [this.#seconds] : [];
}
/**
* Parses a duration string like "1h30m"
*
* @param input Input string
* @returns [seconds, nanoseconds]
*/
static parseString(input) {
let seconds = 0n;
let nanoseconds = 0n;
let left = input;
while (left !== "") {
const match = left.match(DURATION_PART_REGEX);
if (match) {
const amount = BigInt(match[1]);
const unit = match[2];
const factor = UNITS.get(unit);
if (!factor) throw new InvalidDurationError(`Invalid duration unit: ${unit}`);
if (factor >= SECOND$1) seconds += amount * (factor / SECOND$1);
else nanoseconds += amount * factor;
left = left.slice(match[0].length);
} else throw new InvalidDurationError("Could not match a next duration part");
}
seconds += nanoseconds / SECOND$1;
nanoseconds %= SECOND$1;
return [seconds, nanoseconds];
}
/**
* Adds two durations together
*
* @param other The duration to add
* @returns The resulting duration
*/
add(other) {
let sec = this.#seconds + other.#seconds;
let ns = this.#nanoseconds + other.#nanoseconds;
if (ns >= SECOND$1) {
sec += 1n;
ns -= SECOND$1;
}
return new Duration([sec, ns]);
}
/**
* Subtracts another duration from this one
*
* @param other The duration to subtract
* @returns The resulting duration
*/
sub(other) {
let sec = this.#seconds - other.#seconds;
let ns = this.#nanoseconds - other.#nanoseconds;
if (ns < 0n) {
sec -= 1n;
ns += SECOND$1;
}
return new Duration([sec, ns]);
}
/**
* Multiplies the duration by a scalar
*
* @param factor The factor to multiply by
* @returns The resulting duration
*/
mul(factor) {
const factorBig = typeof factor === "bigint" ? factor : BigInt(Math.floor(factor));
const totalNs = this.#seconds * SECOND$1 + this.#nanoseconds;
const resultNs = totalNs * factorBig;
return new Duration([resultNs / SECOND$1, resultNs % SECOND$1]);
}
div(divisor) {
if (typeof divisor === "object" && divisor instanceof Duration) {
const a = this.#seconds * SECOND$1 + this.#nanoseconds;
const b = divisor.#seconds * SECOND$1 + divisor.#nanoseconds;
if (b === 0n) throw new InvalidDurationError("Division by zero duration");
return a / b;
}
const divisorBig = typeof divisor === "bigint" ? divisor : BigInt(Math.floor(divisor));
if (divisorBig === 0n) throw new InvalidDurationError("Division by zero");
const totalNs = this.#seconds * SECOND$1 + this.#nanoseconds;
const resultNs = totalNs / divisorBig;
return new Duration([resultNs / SECOND$1, resultNs % SECOND$1]);
}
/**
* Computes the remainder after division
*
* @param mod The divisor
* @returns The remainder duration
*/
mod(mod) {
const a = this.#seconds * SECOND$1 + this.#nanoseconds;
const b = mod.#seconds * SECOND$1 + mod.#nanoseconds;
if (b === 0n) throw new InvalidDurationError("Modulo by zero duration");
const resultNs = a % b;
return new Duration([resultNs / SECOND$1, resultNs % SECOND$1]);
}
/**
* Total nanoseconds in this duration
*/
get nanoseconds() {
return this.#seconds * SECOND$1 + this.#nanoseconds;
}
/**
* Total microseconds
*/
get microseconds() {
return this.nanoseconds / MICROSECOND$1;
}
/**
* Total milliseconds
*/
get milliseconds() {
return this.nanoseconds / MILLISECOND$1;
}
/**
* Whole seconds in the duration
*/
get seconds() {
return this.#seconds;
}
/**
* Total whole minutes in the duration
*/
get minutes() {
return this.#seconds / (MINUTE / SECOND$1);
}
/**
* Total whole hours in the duration
*/
get hours() {
return this.#seconds / (HOUR / SECOND$1);
}
/**
* Total whole days in the duration
*/
get days() {
return this.#seconds / (DAY / SECOND$1);
}
/**
* Total whole weeks in the duration
*/
get weeks() {
return this.#seconds / (WEEK / SECOND$1);
}
/**
* Total whole years in the duration
*/
get years() {
return this.#seconds / (YEAR / SECOND$1);
}
/**
* Creates a Duration from nanoseconds
*
* @param ns Nanoseconds value
* @returns The resulting duration
*/
static nanoseconds(ns) {
const n = typeof ns === "bigint" ? ns : BigInt(Math.floor(ns));
return new Duration([n / SECOND$1, n % SECOND$1]);
}
/**
* Creates a Duration from microseconds
*
* @param µs Microseconds value
* @returns The resulting duration
*/
static microseconds(µs) {
const n = typeof µs === "bigint" ? µs : BigInt(Math.floor(µs));
return Duration.nanoseconds(n * MICROSECOND$1);
}
/**
* Creates a Duration from milliseconds
*
* @param ms Milliseconds value
* @returns The resulting duration
*/
static milliseconds(ms) {
const n = typeof ms === "bigint" ? ms : BigInt(Math.floor(ms));
return Duration.nanoseconds(n * MILLISECOND$1);
}
/**
* Creates a Duration from seconds
*
* @param s Seconds value
* @returns The resulting duration
*/
static seconds(s$1) {
const n = typeof s$1 === "bigint" ? s$1 : BigInt(Math.floor(s$1));
return new Duration([n, 0n]);
}
/**
* Creates a Duration from minutes
*
* @param m Minutes value
* @returns The resulting duration
*/
static minutes(m) {
const n = typeof m === "bigint" ? m : BigInt(Math.floor(m));
return new Duration([n * (MINUTE / SECOND$1), 0n]);
}
/**
* Creates a Duration from hours
*
* @param h Hours value
* @returns The resulting duration
*/
static hours(h) {
const n = typeof h === "bigint" ? h : BigInt(Math.floor(h));
return new Duration([n * (HOUR / SECOND$1), 0n]);
}
/**
* Creates a Duration from days
*
* @param d Days value
* @returns The resulting duration
*/
static days(d$1) {
const n = typeof d$1 === "bigint" ? d$1 : BigInt(Math.floor(d$1));
return new Duration([n * (DAY / SECOND$1), 0n]);
}
/**
* Creates a Duration from weeks
*
* @param w Weeks value
* @returns The resulting duration
*/
static weeks(w) {
const n = typeof w === "bigint" ? w : BigInt(Math.floor(w));
return new Duration([n * (WEEK / SECOND$1), 0n]);
}
/**
* Creates a Duration from years
*
* @param y Years value
* @returns The resulting duration
*/
static years(y) {
const n = typeof y === "bigint" ? y : BigInt(Math.floor(y));
return new Duration([n * (YEAR / SECOND$1), 0n]);
}
/**
* Parses a duration from a float string with a single time unit, e.g. "1.998487792s", "1.5m", "500.0ms"
*
* @param input Float duration string
* @returns The resulting duration
*/
static parseFloat(input) {
const match = input.match(FLOAT_DURATION_REGEX);
if (!match) throw new InvalidDurationError(`Invalid float duration string: ${input}`);
const numStr = match[1];
const unit = match[2];
const factor = UNITS.get(unit);
if (!factor) throw new InvalidDurationError(`Invalid duration unit: ${unit}`);
const [intPart, fracPart = ""] = numStr.split(".");
const scale = 10n ** BigInt(fracPart.length);
const scaledValue = BigInt(intPart) * scale + BigInt(fracPart || "0");
const totalNs = scaledValue * factor / scale;
return new Duration([totalNs / SECOND$1, totalNs % SECOND$1]);
}
/**
* Measures the elapsed time since the function was called
* If the Performance API is available, it uses it to measure the elapsed time in nanoseconds
*
* @returns A function that returns the elapsed time as a Duration
*/
static measure() {
if (typeof performance !== "undefined" && performance.now) {
const start$1 = performance.now();
return () => {
const end = performance.now();
return Duration.nanoseconds((end - start$1) * 1e6);
};
}
const start = Date.now();
return () => {
const end = Date.now();
return Duration.milliseconds(end - start);
};
}
};
//#endregion
//#region src/value/datetime.ts
const NANOSECOND = 1n;
const MICROSECOND = 1000n * NANOSECOND;
const MILLISECOND = 1000n * MICROSECOND;
const SECOND = 1000n * MILLISECOND;
/**
* A SurrealQL datetime value with support for parsing, formatting, arithmetic, and nanosecond precision.
*/
var DateTime = class DateTime extends Value {
#seconds;
#nanoseconds;
static loadHr = typeof process !== "undefined" && process.hrtime ? {
ns: process.hrtime.bigint(),
ms: BigInt(Date.now())
} : void 0;
constructor(input) {
super();
if (input === void 0) {
const now = DateTime.now();
this.#seconds = now.#seconds;
this.#nanoseconds = now.#nanoseconds;
} else if (input instanceof DateTime) {
this.#seconds = input.#seconds;
this.#nanoseconds = input.#nanoseconds;
} else if (input instanceof Date) {
const time = input.getTime();
if (Number.isNaN(time)) throw new InvalidDateError(input);
const s$1 = BigInt(Math.floor(time / 1e3));
const ns = BigInt(time % 1e3 * 1e6);
this.#seconds = s$1;
this.#nanoseconds = ns;
} else if (typeof input === "string") {
const [s$1, ns] = DateTime.parseString(input);
this.#seconds = s$1;
this.#nanoseconds = ns;
} else if (typeof input === "number") {
this.#seconds = BigInt(Math.floor(input));
this.#nanoseconds = 0n;
} else if (typeof input === "bigint") {
this.#seconds = input;
this.#nanoseconds = 0n;
} else {
const s$1 = typeof input[0] === "bigint" ? input[0] : BigInt(Math.floor(input[0] ?? 0));
const ns = typeof input[1] === "bigint" ? input[1] : BigInt(Math.floor(input[1] ?? 0));
const totalSeconds = s$1 + ns / SECOND;
this.#seconds = totalSeconds;
this.#nanoseconds = ns % SECOND;
}
}
equals(other) {
if (!(other instanceof DateTime)) return false;
return this.#seconds === other.#seconds && this.#nanoseconds === other.#nanoseconds;
}
toJSON() {
return this.toISOString();
}
/**
* @returns The ISO 8601 string representation of the datetime
*/
toString() {
return this.toISOString();
}
/**
* Converts the datetime to a tuple
*/
toCompact() {
return [this.#seconds, this.#nanoseconds];
}
/**
* Formats the datetime as an ISO 8601 string
*/
toISOString() {
const totalMilliseconds = Number(this.#seconds) * 1e3 + Number(this.#nanoseconds) / 1e6;
const date = new Date(totalMilliseconds);
const isoString = date.toISOString();
if (this.#nanoseconds === 0n) return isoString;
const nanoseconds = this.#nanoseconds.toString().padStart(9, "0");
const trimmed = nanoseconds.replace(/0+$/, "");
return isoString.replace(/\.\d{3}Z$/, `.${trimmed}Z`);
}
/**
* Converts to JavaScript Date object
*/
toDate() {
const milliseconds = Number(this.#seconds) * 1e3 + Math.floor(Number(this.#nanoseconds) / 1e6);
return new Date(milliseconds);
}
/**
* Parses a datetime string
*
* @param input Input string (ISO 8601 format)
* @returns [seconds, nanoseconds] tuple
*/
static parseString(input) {
const isoRegex = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,9}))?Z?$/;
const match = input.match(isoRegex);
if (match) {
const [, year, month, day, hour, minute, second, fraction] = match;
const baseIsoString = `${year}-${month}-${day}T${hour}:${minute}:${second}Z`;
const baseDate = new Date(baseIsoString);
const baseTimestamp = baseDate.getTime();
if (Number.isNaN(baseTimestamp)) throw new InvalidDateError(baseDate);
const seconds = BigInt(Math.floor(baseTimestamp / 1e3));
let nanoseconds = 0n;
if (fraction) {
const fractionLength = fraction.length;
if (fractionLength <= 3) nanoseconds = BigInt(fraction.padEnd(3, "0")) * 1000000n;
else if (fractionLength <= 6) nanoseconds = BigInt(fraction.padEnd(6, "0")) * 1000n;
else nanoseconds = BigInt(fraction.padEnd(9, "0"));
}
return [seconds, nanoseconds];
}
const timestamp = Date.parse(input);
if (!Number.isNaN(timestamp)) {
const seconds = BigInt(Math.floor(timestamp / 1e3));
const nanoseconds = BigInt(timestamp % 1e3 * 1e6);
return [seconds, nanoseconds];
}
throw new InvalidDateError(`Invalid datetime format: ${input}`);
}
/**
* Adds a duration to this datetime
*
* @param duration The duration to add
* @returns The new datetime instance
*/
add(duration) {
const [durSeconds, durNanoseconds] = duration.toCompact();
let newSeconds = this.#seconds + (durSeconds || 0n);
let newNanoseconds = this.#nanoseconds + (durNanoseconds || 0n);
if (newNanoseconds >= SECOND) {
newSeconds += 1n;
newNanoseconds -= SECOND;
}
return new DateTime([newSeconds, newNanoseconds]);
}
/**
* Subtracts a duration from this datetime
*
* @param duration The duration to subtract
* @returns The new datetime instance
*/
sub(duration) {
const [durSeconds, durNanoseconds] = duration.toCompact();
let newSeconds = this.#seconds - (durSeconds || 0n);
let newNanoseconds = this.#nanoseconds - (durNanoseconds || 0n);
if (newNanoseconds < 0n) {
newSeconds -= 1n;
newNanoseconds += SECOND;
}
return new DateTime([newSeconds, newNanoseconds]);
}
/**
* Calculates the duration between two datetimes
*
* @param other The other datetime
*/
diff(other) {
const totalThis = this.#seconds * SECOND + this.#nanoseconds;
const totalOther = other.#seconds * SECOND + other.#nanoseconds;
const diff = totalThis > totalOther ? totalThis - totalOther : totalOther - totalThis;
return Duration.nanoseconds(diff);
}
/**
* Compares this DateTime with another
*
* @param other The DateTime to compare with
* @returns -1 if other is before, 0 if equal, 1 if other is after
*/
compare(other) {
const a = this.nanoseconds;
const b = other.nanoseconds;
if (a < b) return -1;
if (a > b) return 1;
return 0;
}
/**
* Total nanoseconds since Unix epoch
*/
get nanoseconds() {
return this.#seconds * SECOND + this.#nanoseconds;
}
/**
* Total microseconds since Unix epoch
*/
get microseconds() {
return this.nanoseconds / MICROSECOND;
}
/**
* Total milliseconds since Unix epoch
*/
get milliseconds() {
return Number(this.nanoseconds / MILLISECOND);
}
/**
* Seconds since Unix epoch
*/
get seconds() {
return Number(this.#seconds);
}
/**
* Creates a DateTime from nanoseconds since Unix epoch
*
* @param ns Nanoseconds value
*/
static fromEpochNanoseconds(ns) {
const n = typeof ns === "bigint" ? ns : BigInt(Math.floor(ns));
return new DateTime([n / SECOND, n % SECOND]);
}
/**
* Creates a DateTime from microseconds since Unix epoch
*
* @param µs Microseconds value
*/
static fromEpochMicroseconds(µs) {
const n = typeof µs === "bigint" ? µs : BigInt(Math.floor(µs));
return DateTime.fromEpochNanoseconds(n * MICROSECOND);
}
/**
* Creates a DateTime from milliseconds since Unix epoch
*
* @param ms Milliseconds value
*/
static fromEpochMilliseconds(ms) {
const n = typeof ms === "bigint" ? ms : BigInt(Math.floor(ms));
return DateTime.fromEpochNanoseconds(n * MILLISECOND);
}
/**
* Creates a DateTime from seconds since Unix epoch
*
* @param s Seconds value
*/
static fromEpochSeconds(s$1) {
const n = typeof s$1 === "bigint" ? s$1 : BigInt(Math.floor(s$1));
return new DateTime([n, 0n]);
}
/**
* Returns a new DateTime representing the current time
*/
static now() {
if (DateTime.loadHr) {
const diffNs = process.hrtime.bigint() - DateTime.loadHr.ns;
const totalNanoseconds = DateTime.loadHr.ms * 1000000n + diffNs;
const seconds$1 = totalNanoseconds / 1000000000n;
const nanoseconds$1 = totalNanoseconds % 1000000000n;
return new DateTime([seconds$1, nanoseconds$1]);
}
if (typeof performance !== "undefined" && performance.now && performance.timeOrigin) {
const totalMilliseconds = performance.timeOrigin + performance.now();
const seconds$1 = BigInt(Math.floor(totalMilliseconds / 1e3));
const nanoseconds$1 = BigInt(Math.floor(totalMilliseconds % 1e3 * 1e6));
return new DateTime([seconds$1, nanoseconds$1]);
}
const now = Date.now();
const seconds = BigInt(Math.floor(now / 1e3));
const nanoseconds = BigInt(now % 1e3 * 1e6);
return new DateTime([seconds, nanoseconds]);
}
/**
* Returns a new DateTime representing the Unix epoch (1970-01-01T00:00:00Z)
*/
static epoch() {
return new DateTime([0n, 0n]);
}
};
//#endregion
//#region src/value/decimal.ts
/**
* A SurrealQL decimal number value with support for parsing, formatting, arithmetic, and high precision.
*/
var Decimal = class Decimal extends Value {
#int;
#frac;
#scale;
constructor(input) {
super();
if (input instanceof Decimal) {
this.#int = input.#int;
this.#frac = input.#frac;
this.#scale = input.#scale;
} else if (typeof input === "bigint") {
this.#int = input;
this.#frac = 0n;
this.#scale = 0;
} else if (Array.isArray(input)) {
let [int, frac, scale] = input;
const maxFrac = 10n ** BigInt(scale);
if (frac >= maxFrac) {
int += frac / maxFrac;
frac %= maxFrac;
}
this.#int = int;
this.#frac = frac;
this.#scale = scale;
} else if (typeof input === "string" && /e/i.test(input)) {
const dec = Decimal.fromScientificNotation(input);
this.#int = dec.#int;
this.#frac = dec.#frac;
this.#scale = dec.#scale;
} else {
const str = input.toString().trim();
const isNegative = str.startsWith("-");
const clean = isNegative ? str.slice(1) : str;
const [intStrRaw, fracStrRaw = ""] = clean.split(".");
const safeInt = /^\d+$/.test(intStrRaw) ? intStrRaw : "0";
const safeFrac = /^\d+$/.test(fracStrRaw) ? fracStrRaw : "0";
const intStr = safeInt || "0";
const fracStr = safeFrac.padEnd(safeFrac.length || 1, "0");
const absInt = BigInt(intStr);
const absFrac = BigInt(fracStr);
this.#int = isNegative ? -absInt : absInt;
this.#frac = isNegative ? -absFrac : absFrac;
this.#scale = safeFrac.length;
}
}
equals(other) {
if (!(other instanceof Decimal)) return false;
const a = this.toBigIntWithScale();
const b = other.toBigIntWithScale();
const scale = Math.max(a.scale, b.scale);
const aVal = a.value * 10n ** BigInt(scale - a.scale);
const bVal = b.value * 10n ** BigInt(scale - b.scale);
return aVal === bVal;
}
toJSON() {
return this.toString();
}
/**
* @returns The canonical string representation of the decimal with
* trailing zeros in fractional part trimmed
*/
toString() {
const sign = this.#int < 0n || this.#frac < 0n ? "-" : "";
const absInt = this.#int < 0n ? -this.#int : this.#int;
const absFrac = this.#frac < 0n ? -this.#frac : this.#frac;
if (this.#scale === 0) return `${sign}${absInt}`;
let fracStr = absFrac.toString().padStart(this.#scale, "0");
let end = fracStr.length;
while (end > 0 && fracStr.charCodeAt(end - 1) === 48) end--;
fracStr = fracStr.slice(0, end);
return fracStr === "" ? `${sign}${absInt}` : `${sign}${absInt}.${fracStr}`;
}
/** Returns the integer part of the number */
get int() {
return this.#int;
}
/** Returns the fractional part of the number */
get frac() {
return this.#frac;
}
/** Returns the scale (number of decimal places) */
get scale() {
return this.#scale;
}
/**
* Adds another Decimal to this one
*
* @param other The Decimal to add
* @returns A new Decimal representing the sum
*/
add(other) {
const a = this.toBigIntWithScale();
const b = other.toBigIntWithScale();
const scale = Math.max(a.scale, b.scale);
const scaleDiffA = BigInt(scale - a.scale);
const scaleDiffB = BigInt(scale - b.scale);
const valA = a.value * 10n ** scaleDiffA;
const valB = b.value * 10n ** scaleDiffB;
const sum = valA + valB;
const intPart = sum / 10n ** BigInt(scale);
const fracPart = sum % 10n ** BigInt(scale);
return new Decimal([
intPart,
fracPart,
scale
]);
}
/**
* Subtracts another Decimal from this one
*
* @param other The Decimal to subtract
* @returns A new Decimal representing the difference
*/
sub(other) {
const a = this.toBigIntWithScale();
const b = other.toBigIntWithScale();
const scale = Math.max(a.scale, b.scale);
const factorA = 10n ** BigInt(scale - a.scale);
const factorB = 10n ** BigInt(scale - b.scale);
const valA = a.value * factorA;
const valB = b.value * factorB;
const result = valA - valB;
const intPart = result / 10n ** BigInt(scale);
const fracPart = result % 10n ** BigInt(scale);
return new Decimal([
intPart,
fracPart,
scale
]);
}
/**
* Multiplies this Decimal by another
*
* @param other The Decimal to multiply by
* @returns A new Decimal representing the product
*/
mul(other) {
const a = this.toBigIntWithScale();
const b = other.toBigIntWithScale();
const result = a.value * b.value;
const scale = a.scale + b.scale;
const intPart = result / 10n ** BigInt(scale);
const fracPart = result % 10n ** BigInt(scale);
return new Decimal([
intPart,
fracPart,
scale
]);
}
/**
* Divides this Decimal by another, with fixed precision
*
* @param other The Decimal to divide by
* @returns A new Decimal representing the quotient
*/
div(other) {
const a = this.toBigIntWithScale();
const b = other.toBigIntWithScale();
if (b.value === 0n) throw new InvalidDecimalError("Division by zero");
const targetScale = 38;
const scaleDiff = BigInt(targetScale + b.scale - a.scale);
const scaledA = a.value * 10n ** scaleDiff;
const result = scaledA / b.value;
const intPart = result / 10n ** BigInt(targetScale);
const fracPart = result % 10n ** BigInt(targetScale);
return new Decimal([
intPart,
fracPart,
targetScale
]);
}
/**
* Computes the remainder of this Decimal divided by another
*
* @param other The divisor Decimal
* @returns A new Decimal representing the remainder
*/
mod(other) {
const a = this.toBigIntWithScale();
const b = other.toBigIntWithScale();
if (b.value === 0n) throw new InvalidDecimalError("Modulo by zero");
const scale = Math.max(a.scale, b.scale);
const scaleDiffA = BigInt(scale - a.scale);
const scaleDiffB = BigInt(scale - b.scale);
const valA = a.value * 10n ** scaleDiffA;
const valB = b.value * 10n ** scaleDiffB;
const result = valA % valB;
const intPart = result / 10n ** BigInt(scale);
const fracPart = result % 10n ** BigInt(scale);
return new Decimal([
intPart,
fracPart,
scale
]);
}
/**
* Returns the absolute value of this Decimal
* @returns A new Decimal with non-negative components
*/
abs() {
return this.#int < 0n || this.#frac < 0n ? new Decimal([
this.#int < 0n ? -this.#int : this.#int,
this.#frac < 0n ? -this.#frac : this.#frac,
this.#scale
]) : this;
}
/**
* Returns the negated value of this Decimal
* @returns A new Decimal with inverted sign
*/
neg() {
return new Decimal([
-this.#int,
-this.#frac,
this.#scale
]);
}
/**
* Checks if the value is exactly zero
* @returns True if both int and frac parts are zero
*/
isZero() {
return this.#int === 0n && this.#frac === 0n;
}
/**
* Checks if the value is negative
* @returns True if negative
*/
isNegative() {
return this.#int < 0n || this.#int === 0n && this.#frac < 0n;
}
/**
* Compares this Decimal with another
*
* @param other The Decimal to compare with
* @returns -1 if less, 0 if equal, 1 if greater
*/
compare(other) {
const a = this.toBigIntWithScale();
const b = other.toBigIntWithScale();
const scale = Math.max(a.scale, b.scale);
const aVal = a.value * 10n ** BigInt(scale - a.scale);
const bVal = b.value * 10n ** BigInt(scale - b.scale);
if (aVal < bVal) return -1;
if (aVal > bVal) return 1;
return 0;
}
/**
* Rounds the Decimal to a fixed number of decimal places
*
* @param precision Number of digits to keep after the decimal point
* @returns The new decimal instance
*/
round(precision) {
if (precision < 0) throw new InvalidDecimalError("Precision must be >= 0");
const full = this.toBigIntWithScale();
if (this.#scale <= precision) {
const factor$1 = 10n ** BigInt(precision - this.#scale);
const newValue = full.value * factor$1;
const intPart$1 = newValue / 10n ** BigInt(precision);
const fracPart$1 = newValue % 10n ** BigInt(precision);
return new Decimal([
intPart$1,
fracPart$1,
precision
]);
}
const factor = 10n ** BigInt(this.#scale - precision);
const half = factor / 2n;
const rounded = full.value >= 0n ? (full.value + half) / factor : (full.value - half) / factor;
const intPart = rounded / 10n ** BigInt(precision);
const fracPart = rounded % 10n ** BigInt(precision);
return new Decimal([
intPart,
fracPart,
precision
]);
}
/**
* Converts the number to fixed-point notation string
*
* @param precision Number of digits after the decimal point
*/
toFixed(precision) {
const rounded = this.round(precision);
const sign = rounded.int < 0n || rounded.frac < 0n ? "-" : "";
const absInt = rounded.int < 0n ? -rounded.int : rounded.int;
if (precision === 0) return `${sign}${absInt}`;
const absFrac = rounded.frac < 0n ? -rounded.frac : rounded.frac;
const fracStr = absFrac.toString().padStart(precision, "0");
return `${sign}${absInt}.${fracStr}`;
}
/**
* Converts the Decimal to a native JavaScript number
* @returns A number approximation (may lose precision)
*/
toFloat() {
return Number(this.toString());
}
/**
* Converts to bigint by truncating the fractional part
* @returns An bigint approximation (may lose precision)
*/
toBigInt() {
if (this.#int >= 0n) return this.#int;
if (this.#frac !== 0n) return this.#int - 1n;
return this.#int;
}
/**
* Returns the raw parts of the Decimal
* @returns An object with int, frac, and scale
*/
toParts() {
return {
int: this.#int,
frac: this.#frac,
scale: this.#scale
};
}
/**
* Converts to scientific notation string (e.g., "1.23e4")
*/
toScientific() {
if (this.isZero()) return "0e0";
const negative = this.isNegative();
const abs = negative ? this.neg() : this;
const str = abs.toString();
const [intPart, fracPart = ""] = str.split(".");
const raw$1 = (intPart + fracPart).replace(/^0+/, "");
const firstSig = raw$1.search(/[1-9]/);
if (firstSig === -1) return "0e0";
let exponent;
if (intPart !== "0") exponent = intPart.length - 1;
else {
let leading = 0;
while (leading < fracPart.length && fracPart.charCodeAt(leading) === 48) leading++;
exponent = -leading - 1;
}
let end = raw$1.length;
while (end > 0 && raw$1.charCodeAt(end - 1) === 48) end--;
const digits = raw$1.slice(0, end);
const mantissa = digits.length > 1 ? `${digits[0]}.${digits.slice(1)}` : digits[0];
return `${negative ? "-" : ""}${mantissa}e${exponent}`;
}
/**
* Parses a number in scientific notation into a Decimal
*
* @param input The scientific notation string
*/
static fromScientificNotation(input) {
const trimmed = input.trim();
if (!/^[+-]?\d+(\.\d+)?[eE][+-]?\d+$/.test(trimmed)) throw new InvalidDecimalError(`Invalid scientific notation: ${input}`);
const [baseStr, expStr] = trimmed.split(/[eE]/);
const exp = Number.parseInt(expStr, 10);
const negative = baseStr.startsWith("-");
const [intPart, fracPart = ""] = baseStr.replace(/^[-+]/, "").split(".");
const raw$1 = intPart + fracPart;
let start = 0;
while (start < raw$1.length && raw$1.charCodeAt(start) === 48) start++;
const digits = raw$1.slice(start) || "0";
const pointIndex = intPart.length;
const newPointIndex = pointIndex + exp;
let result;
if (newPointIndex <= 0) result = `0.${"0".repeat(-newPointIndex)}${digits}`;
else if (newPointIndex >= digits.length) result = digits + "0".repeat(newPointIndex - digits.length);
else result = `${digits.slice(0, newPointIndex)}.${digits.slice(newPointIndex)}`;
return new Decimal(negative ? `-${result}` : result);
}
toBigIntWithScale() {
return {
value: this.#int * 10n ** BigInt(this.#scale) + this.#frac,
scale: this.#scale
};
}
};
//#endregion
//#region src/value/file.ts
/**
* A SurrealQL file reference value.
*/
var FileRef = class FileRef extends Value {
#bucket;
#key;
constructor(bucket, key) {
super();
this.#bucket = bucket;
this.#key = key.startsWith("/") ? key : `/${key}`;
}
get bucket() {
return this.#bucket;
}
get key() {
return this.#key;
}
equals(other) {
if (!(other instanceof FileRef)) return false;
return this.#bucket === other.#bucket && this.#key === other.#key;
}
toJSON() {
return this.toString();
}
toString() {
return `${fmtInner(this.#bucket, true)}:${fmtInner(this.#key, false)}`;
}
};
function fmtInner(str, escapeSlash) {
let result = "";
for (let i = 0; i < str.length; i++) {
const char = str[i];
const code = str.charCodeAt(i);
if (code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || code === 95 || code === 45 || code === 46 || !escapeSlash && code === 47) result += char;
else result += `\\${char}`;
}
return result;
}
//#endregion
//#region src/value/future.ts
/**
* An uncomputed SurrealQL future value.
*
* @deprecated Futures were removed in SurrealDB 3.0
*/
var Future = class Future extends Value {
#body;
constructor(body) {
super();
this.#body = body;
}
equals(other) {
if (!(other instanceof Future)) return false;
return this.#body === other.#body;
}
toJSON() {
return this.toString();
}
/**
* @returns The uncomputed future notation
*/
toString() {
return `<future> ${this.#body}`;
}
/**
* The body of the future
*/
get body() {
return this.#body;
}
};
//#endregion
//#region src/value/geometry.ts
/**
* A SurrealQL geometry value.
*/
var Geometry = class Geometry extends Value {
equals(other) {
if (!(other instanceof Geometry)) return false;
return this.is(other);
}
toString() {
return JSON.stringify(this.toJSON());
}
};
function f(num) {
if (num instanceof Decimal) return num.toFloat();
return num;
}
/**
* A SurrealQL point geometry value.
*/
var GeometryPoint = class GeometryPoint extends Geometry {
point;
constructor(point) {
super();
if (point instanceof GeometryPoint) this.point = point.clone().point;
else this.point = [f(point[0]), f(point[1])];
}
toJSON() {
return {
type: "Point",
coordinates: this.coordinates
};
}
get coordinates() {
return this.point;
}
is(geometry) {
if (!(geometry instanceof GeometryPoint)) return false;
return this.point[0] === geometry.point[0] && this.point[1] === geometry.point[1];
}
clone() {
return new GeometryPoint([...this.point]);
}
};
/**
* A SurrealQL line geometry value.
*/
var GeometryLine = class GeometryLine extends Geometry {
line;
constructor(line) {
super();
this.line = line instanceof GeometryLine ? line.clone().line : line;
}
toJSON() {
return {
type: "LineString",
coordinates: this.coordinates
};
}
get coordinates() {
return this.line.map((g) => g.coordinates);
}
close() {
if (!this.line[0].is(this.line.at(-1))) this.line.push(this.line[0]);
}
is(geometry) {
if (!(geometry instanceof GeometryLine)) return false;
if (this.line.length !== geometry.line.length) return false;
for (let i = 0; i < this.line.length; i++) if (!this.line[i].is(geometry.line[i])) return false;
return true;
}
clone() {
return new GeometryLine(this.line.map((p) => p.clone()));
}
};
/**
* A SurrealQL polygon geometry value.
*/
var GeometryPolygon = class GeometryPolygon extends Geometry {
polygon;
constructor(polygon) {
super();
this.polygon = polygon instanceof GeometryPolygon ? polygon.clone().polygon : pol