UNPKG

realm

Version:

Realm by MongoDB is an offline-first mobile database: an alternative to SQLite and key-value stores

165 lines 7.16 kB
"use strict"; //////////////////////////////////////////////////////////////////////////// // // 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