realm
Version:
Realm by MongoDB is an offline-first mobile database: an alternative to SQLite and key-value stores
165 lines • 7.16 kB
JavaScript
;
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2022 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClassMap = void 0;
const PropertyMap_1 = require("./PropertyMap");
const Object_1 = require("./Object");
const assert_1 = require("./assert");
const ClassHelpers_1 = require("./ClassHelpers");
const symbols_1 = require("./symbols");
/** @internal */
class ClassMap {
mapping;
nameByTableKey;
static createNamedConstructor(name) {
const result = function () {
/* no-op */
};
// Need to use `defineProperty` since it isn't writable
Object.defineProperty(result, "name", { value: name });
return result;
}
static createClass(schema, constructor) {
const result = ClassMap.createNamedConstructor(schema.name);
// Make the new constructor extend RealmObject
// TODO: Use the end-users constructor, instead of `RealmObject` if provided
if (constructor) {
Object.setPrototypeOf(result, constructor);
Object.setPrototypeOf(result.prototype, constructor.prototype);
}
else {
Object.setPrototypeOf(result, Object_1.RealmObject);
Object.setPrototypeOf(result.prototype, Object_1.RealmObject.prototype);
}
return result;
}
static defineProperties(constructor, schema, propertyMap, realm) {
// Create bound functions for getting and setting properties
const properties = [...schema.persistedProperties, ...schema.computedProperties];
const propertyNames = properties.map((p) => p.publicName || p.name);
// Set up accessors for the properties declared in the schema
for (const property of properties) {
const propertyName = property.publicName || property.name;
const { get, set } = propertyMap.get(propertyName);
Object.defineProperty(constructor.prototype, propertyName, {
enumerable: true,
get() {
return get(this[symbols_1.OBJECT_INTERNAL]);
},
set(value) {
set(this[symbols_1.OBJECT_INTERNAL], value);
},
});
}
Object.defineProperty(constructor.prototype, symbols_1.OBJECT_REALM, {
enumerable: false,
configurable: false,
writable: false,
value: realm,
});
Object.defineProperty(constructor.prototype, Object_1.KEY_ARRAY, {
enumerable: false,
configurable: false,
writable: false,
value: propertyNames,
});
Object.defineProperty(constructor.prototype, Object_1.KEY_SET, {
enumerable: false,
configurable: false,
writable: false,
value: new Set(propertyNames),
});
}
constructor(realm, realmSchema, canonicalRealmSchema) {
this.mapping = Object.fromEntries(realmSchema.map((objectSchema, index) => {
const canonicalObjectSchema = canonicalRealmSchema[index];
assert_1.assert.object(canonicalObjectSchema);
// Create the wrapping class first
const constructor = ClassMap.createClass(objectSchema, canonicalObjectSchema.ctor);
// Create property getters and setters
const properties = new PropertyMap_1.PropertyMap();
// Setting the helpers on the class
(0, ClassHelpers_1.setClassHelpers)(constructor, {
constructor,
objectSchema,
canonicalObjectSchema,
properties,
wrapObject(obj) {
if (obj.isValid) {
return Object_1.RealmObject.createWrapper(obj, constructor);
}
else {
return null;
}
},
});
return [objectSchema.name, constructor];
}));
this.nameByTableKey = Object.fromEntries(realmSchema.map(({ name, tableKey }) => [tableKey, name]));
for (const [index, objectSchema] of realmSchema.entries()) {
const canonicalObjectSchema = canonicalRealmSchema[index];
const defaults = Object.fromEntries(Object.entries(canonicalObjectSchema.properties).map(([name, property]) => {
return [name, property.default];
}));
const constructor = this.mapping[objectSchema.name];
// Get the uninitialized property map
const { properties } = (0, ClassHelpers_1.getClassHelpers)(constructor);
// Initialize the property map, now that all classes have helpers set
properties.initialize(objectSchema, canonicalObjectSchema, defaults, {
realm,
getClassHelpers: (name) => this.getHelpers(name),
});
// Transfer property getters and setters onto the prototype of the class
ClassMap.defineProperties(constructor, objectSchema, properties, realm);
}
}
get(arg) {
if (typeof arg === "string") {
const constructor = this.mapping[arg];
if (!constructor) {
throw new Error(`Object type '${arg}' not found in schema.`);
}
return constructor;
}
else if (arg instanceof Object_1.RealmObject) {
return this.get(arg.constructor.name);
}
else if (typeof arg === "function") {
assert_1.assert.extends(arg, Object_1.RealmObject);
assert_1.assert.object(arg.schema, "schema static");
assert_1.assert.string(arg.schema.name, "name");
const result = this.get(arg.schema.name);
(0, assert_1.assert)(result === arg || Object.getPrototypeOf(result) === arg, "Constructor was not registered in the schema for this Realm");
return result;
}
else if (arg in this.nameByTableKey) {
const name = this.nameByTableKey[arg];
return this.get(name);
}
else {
throw new Error("Expected an object schema name, object instance or class");
}
}
getHelpers(arg) {
const constructor = this.get(arg);
return (0, ClassHelpers_1.getClassHelpers)(constructor);
}
}
exports.ClassMap = ClassMap;
//# sourceMappingURL=ClassMap.js.map