baqend
Version:
Baqend JavaScript SDK
183 lines (149 loc) • 6.22 kB
text/typescript
// eslint-disable-next-line max-classes-per-file
import {
Class, Json, JsonMap, JsonArray,
} from '../util';
import { File } from '../binding';
import { GeoPoint } from '../GeoPoint';
import { PersistenceType, Type } from './Type';
import { ManagedState } from '../intersection';
function dateToJson(value: Date | null): string | null {
// remove trailing zeros
return value instanceof Date ? value.toISOString().replace(/\.?0*Z/, 'Z') : null;
}
function jsonToDate(json: Json, currentValue: Date | null): Date | null {
const date = typeof json === 'string' ? new Date(json) : null;
if (currentValue && date) {
// compare normalized date strings instead of plain strings
return currentValue.toISOString() === date.toISOString() ? currentValue : date;
}
return date;
}
export class BasicType<T> extends Type<T> {
public static readonly Boolean = new class BooleanType extends BasicType<Boolean> {
fromJsonValue(state: ManagedState, json: Json, currentValue: Boolean | null): Boolean | null {
return typeof json === 'string' ? json !== 'false' : super.fromJsonValue(state, json, currentValue);
}
}('Boolean', Boolean);
public static readonly Double = new class DoubleType extends BasicType<Number> {
fromJsonValue(state: ManagedState, json: Json, currentValue: Number | null) {
return typeof json === 'string' ? parseFloat(json) : super.fromJsonValue(state, json, currentValue);
}
}('Double', Number);
public static readonly Integer = new class IntegerType extends BasicType<Number> {
fromJsonValue(state: ManagedState, json: Json, currentValue: number | null) {
return typeof json === 'string' ? parseInt(json, 10) : super.fromJsonValue(state, json, currentValue);
}
}('Integer', Number);
public static readonly String = new class StringType extends BasicType<String> {
fromJsonValue(state: ManagedState, json: Json, currentValue: String | null): String | null {
return super.fromJsonValue(state, json, currentValue);
}
}('String', String);
public static readonly DateTime = new class DateTimeType extends BasicType<Date> {
toJsonValue(state: ManagedState, value: Date | null) {
return dateToJson(value);
}
fromJsonValue(state: ManagedState, json: Json, currentValue: Date | null) {
return jsonToDate(json, currentValue);
}
}('DateTime', Date);
public static readonly Date = new class DateType extends BasicType<Date> {
toJsonValue(state: ManagedState, value: Date | null) {
const json = dateToJson(value);
return json ? json.substring(0, json.indexOf('T')) : null;
}
fromJsonValue(state: ManagedState, json: Json, currentValue: Date | null) {
return jsonToDate(json, currentValue);
}
}('Date', Date);
public static readonly Time = new class TimeType extends BasicType<Date> {
toJsonValue(state: ManagedState, value: Date | null) {
const json = dateToJson(value);
return json ? json.substring(json.indexOf('T') + 1) : null;
}
fromJsonValue(state: ManagedState, json: Json, currentValue: Date | null): Date | null {
return typeof json === 'string' ? jsonToDate(`1970-01-01T${json}`, currentValue) : null;
}
}('Time', Date);
public static readonly File = new class FileType extends BasicType<File> {
toJsonValue(state: ManagedState, value: File | null) {
return value instanceof File ? value.id : null;
}
fromJsonValue(state: ManagedState, json: Json, currentValue: File | null): File | null {
if (!json) {
return null;
}
if (currentValue && currentValue.id === json) {
return currentValue;
}
if (state.db) {
return new state.db.File(json as string);
}
return null;
}
}('File', File);
public static readonly GeoPoint = new class GeoPointType extends BasicType<GeoPoint> {
toJsonValue(state: ManagedState, value: GeoPoint | null) {
return value instanceof GeoPoint ? value.toJSON() : null;
}
fromJsonValue(state: ManagedState, json: Json) {
return json ? new GeoPoint(json as { latitude: number, longitude: number }) : null;
}
}('GeoPoint', GeoPoint);
public static readonly JsonArray = new class JsonArrayType extends BasicType<JsonArray> {
toJsonValue(state: ManagedState, value: Array<any> | null) {
return Array.isArray(value) ? value : null;
}
fromJsonValue(state: ManagedState, json: Json) {
return Array.isArray(json) ? json : null;
}
}('JsonArray', Array);
public static readonly JsonObject = new class JsonObjectType extends BasicType<JsonMap> {
fromJsonValue(state: ManagedState, json: Json, currentValue: JsonMap | null): JsonMap | null {
return super.fromJsonValue(state, json, currentValue);
}
toJsonValue(state: ManagedState, value: JsonMap | null): JsonMap | null {
if (value && value.constructor === Object) {
return value;
}
return null;
}
}('JsonObject', Object as any);
/**
* Indicates if this type is not the main type of the constructor
*/
public noResolving: boolean;
/**
* @inheritDoc
*/
get persistenceType() {
return PersistenceType.BASIC;
}
/**
* Creates a new instance of a native db type
* @param ref The db ref of this type
* @param typeConstructor The javascript class of this type
* @param noResolving Indicates if this type is not the main type of the constructor
*/
constructor(ref: string, typeConstructor: Class<T>, noResolving?: boolean) {
const id = ref.indexOf('/db/') === 0 ? ref : `/db/${ref}`;
super(id, typeConstructor);
this.noResolving = !!noResolving;
}
/**
* @inheritDoc
*/
toJsonValue(state: ManagedState, currentValue: T | null): Json {
return currentValue === null || currentValue === undefined ? null : (this.typeConstructor as any)(currentValue);
}
/**
* @inheritDoc
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
fromJsonValue(state: ManagedState, json: Json, currentValue: T | null): T | null {
return json === null || json === undefined ? null : json as any;
}
toString() {
return `BasicType(${this.ref})`;
}
}