UNPKG

@react-native-ohos/realm

Version:

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

245 lines 11 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.List = void 0; const assert_1 = require("./assert"); const binding_1 = require("./binding"); const indirect_1 = require("./indirect"); const Collection_1 = require("./Collection"); const errors_1 = require("./errors"); const OrderedCollection_1 = require("./OrderedCollection"); const TypeHelpers_1 = require("./TypeHelpers"); /** * Instances of this class will be returned when accessing object properties whose type is `"list"`. * * Lists mostly behave like normal Javascript Arrays, except for that they can * only store values of a single type (indicated by the `type` and `optional` * properties of the List), and can only be modified inside a {@link Realm.write | write} transaction. */ class List extends OrderedCollection_1.OrderedCollection { /** @internal */ constructor(realm, internal, accessor, typeHelpers) { if (arguments.length === 0 || !(internal instanceof binding_1.binding.List)) { throw new errors_1.IllegalConstructorError("List"); } const results = internal.asResults(); super(realm, results, accessor, typeHelpers); // Getting the `objectSchema` off the internal will throw if base type isn't object const isEmbedded = (0, TypeHelpers_1.toItemType)(results.type) === 7 /* binding.PropertyType.Object */ && internal.objectSchema.tableType === 1 /* binding.TableType.Embedded */; Object.defineProperty(this, "internal", { enumerable: false, configurable: false, writable: false, value: internal, }); Object.defineProperty(this, "isEmbedded", { enumerable: false, configurable: false, writable: false, value: isEmbedded, }); } /** @internal */ get(index) { return this[Collection_1.COLLECTION_ACCESSOR].get(this.internal, index); } /** @internal */ set(index, value) { this[Collection_1.COLLECTION_ACCESSOR].set(this.internal, index, value); } /** * Checks if this collection has not been deleted and is part of a valid Realm. * @returns `true` if the collection can be safely accessed. */ isValid() { return this.internal.isValid; } /** * @returns The number of values in the list. */ get length() { return this.internal.size; } /** * @throws An {@link Error} as the length property cannot be assigned. */ set length(value) { throw new Error("Cannot assign to read only property 'length'"); } /** * Remove the **last** value from the list and return it. * @throws an {@link AssertionError} If not inside a write transaction. * @returns The last value or undefined if the list is empty. */ pop() { assert_1.assert.inTransaction(this.realm); const { internal } = this; const lastIndex = internal.size - 1; if (lastIndex >= 0) { const result = this.get(lastIndex); internal.remove(lastIndex); return result; } } /** * Add one or more values to the _end_ of the list. * @param items - Values to add to the list. * @throws A {TypeError} if a value is not of a type which can be stored in * the list, or if an object being added to the list does not match the {@link ObjectSchema} for the list. * @throws An {@link AssertionError} if not inside a write transaction. * @returns The new length of the list after adding the values. */ push(...items) { assert_1.assert.inTransaction(this.realm); const { internal } = this; const start = internal.size; for (const [offset, item] of items.entries()) { const index = start + offset; this[Collection_1.COLLECTION_ACCESSOR].insert(internal, index, item); } return internal.size; } /** * Remove the **first** value from the list and return it. * @throws An {@link AssertionError} if not inside a write transaction. * @returns The first value or `undefined` if the list is empty. */ shift() { assert_1.assert.inTransaction(this.realm); const { internal } = this; if (internal.size > 0) { const result = this.get(0); internal.remove(0); return result; } } /** * Add one or more values to the _beginning_ of the list. * @param items - Values to add to the list. * @throws A {TypeError} if a value is not of a type which can be stored in * the list, or if an object being added to the list does not match the {@link ObjectSchema} for the list. * @throws An {@link AssertionError} if not inside a write transaction. * @returns The new length of the list after adding the values. */ unshift(...items) { assert_1.assert.inTransaction(this.realm); const { internal } = this; const { insert } = this[Collection_1.COLLECTION_ACCESSOR]; for (const [index, item] of items.entries()) { insert(internal, index, item); } return internal.size; } /** * Changes the contents of the list by removing value and/or inserting new value. * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice Array.prototype.splice} * @param start - The start index. If greater than the length of the list, * the start index will be set to the length instead. If negative, then the start index * will be counted from the end of the list (e.g. `list.length - index`). * @param deleteCount - The number of values to remove from the list. * If not provided, then all values from the start index through the end of * the list will be removed. * @param items - Values to insert into the list starting at `index`. * @returns An array containing the value that were removed from the list. The * array is empty if no value were removed. */ splice(start, deleteCount, ...items) { // Comments in the code below is copied from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice assert_1.assert.inTransaction(this.realm); assert_1.assert.number(start, "start"); const { internal } = this; // If negative, it will begin that many elements from the end of the array. if (start < 0) { start = internal.size + start; } // If greater than the length of the array, start will be set to the length of the array. if (start > internal.size) { start = internal.size; } // If deleteCount is omitted, or if its value is equal to or larger than array.length - start // (that is, if it is equal to or greater than the number of elements left in the array, starting at start), // then all the elements from start to the end of the array will be deleted. const end = typeof deleteCount === "number" ? Math.min(start + deleteCount, internal.size) : internal.size; // Get the elements that are about to be deleted const result = []; for (let i = start; i < end; i++) { result.push(this.get(i)); } // Remove the elements from the list (backwards to avoid skipping elements as they're being deleted) for (let i = end - 1; i >= start; i--) { internal.remove(i); } // Insert any new elements const { insert } = this[Collection_1.COLLECTION_ACCESSOR]; for (const [offset, item] of items.entries()) { const index = start + offset; insert(internal, index, item); } return result; } /** * Removes the element of the list at the specified index. * @param index - The index of the element to remove. * @throws An {@link AssertionError} if not inside a write transaction or the input index is less than 0 * or greater than or equal to the size of the list. */ remove(index) { assert_1.assert.inTransaction(this.realm); assert_1.assert.number(index, "index"); (0, assert_1.assert)(index >= 0, "Index cannot be smaller than 0"); (0, assert_1.assert)(index < this.internal.size, "Index cannot be greater than the size of the list"); this.internal.remove(index); } /** * Moves one element of the list from one index to another. * @param from - The index of the element to move. * @param to - The destination index of the element. * @throws An {@link AssertionError} if not inside a write transaction or if any of the input indexes * is less than 0 or greater than or equal to the size of the list. */ move(from, to) { assert_1.assert.inTransaction(this.realm); assert_1.assert.number(from, "from"); assert_1.assert.number(to, "to"); const size = this.internal.size; (0, assert_1.assert)(from >= 0 && to >= 0, "Indexes cannot be smaller than 0"); (0, assert_1.assert)(from < size && to < size, "Indexes cannot be greater than the size of the list"); this.internal.move(from, to); } /** * Swaps the positions of the elements of the list at two indexes. * @param index1 - The index of the first element. * @param index2 - The index of the second element. * @throws An {@link AssertionError} if not inside a write transaction or if any of the input indexes * is less than 0 or greater than or equal to the size of the list. */ swap(index1, index2) { assert_1.assert.inTransaction(this.realm); assert_1.assert.number(index1, "index1"); assert_1.assert.number(index2, "index2"); const size = this.internal.size; (0, assert_1.assert)(index1 >= 0 && index2 >= 0, "Indexes cannot be smaller than 0"); (0, assert_1.assert)(index1 < size && index2 < size, "Indexes cannot be greater than the size of the list"); this.internal.swap(index1, index2); } } exports.List = List; (0, indirect_1.injectIndirect)("List", List); //# sourceMappingURL=List.js.map