forked from mystiq/hydrogen-web
Merge pull request #474 from vector-im/snowpack-ts-storage-3
Snowpack + Typescript conversion (Part 3)
This commit is contained in:
commit
360b4db17a
15 changed files with 274 additions and 134 deletions
|
@ -22,18 +22,18 @@ import {RoomSummaryStore} from "./stores/RoomSummaryStore";
|
||||||
import {InviteStore} from "./stores/InviteStore";
|
import {InviteStore} from "./stores/InviteStore";
|
||||||
import {TimelineEventStore} from "./stores/TimelineEventStore";
|
import {TimelineEventStore} from "./stores/TimelineEventStore";
|
||||||
import {TimelineRelationStore} from "./stores/TimelineRelationStore";
|
import {TimelineRelationStore} from "./stores/TimelineRelationStore";
|
||||||
import {RoomStateStore} from "./stores/RoomStateStore.js";
|
import {RoomStateStore} from "./stores/RoomStateStore";
|
||||||
import {RoomMemberStore} from "./stores/RoomMemberStore";
|
import {RoomMemberStore} from "./stores/RoomMemberStore";
|
||||||
import {TimelineFragmentStore} from "./stores/TimelineFragmentStore.js";
|
import {TimelineFragmentStore} from "./stores/TimelineFragmentStore";
|
||||||
import {PendingEventStore} from "./stores/PendingEventStore.js";
|
import {PendingEventStore} from "./stores/PendingEventStore";
|
||||||
import {UserIdentityStore} from "./stores/UserIdentityStore.js";
|
import {UserIdentityStore} from "./stores/UserIdentityStore";
|
||||||
import {DeviceIdentityStore} from "./stores/DeviceIdentityStore.js";
|
import {DeviceIdentityStore} from "./stores/DeviceIdentityStore";
|
||||||
import {OlmSessionStore} from "./stores/OlmSessionStore.js";
|
import {OlmSessionStore} from "./stores/OlmSessionStore";
|
||||||
import {InboundGroupSessionStore} from "./stores/InboundGroupSessionStore.js";
|
import {InboundGroupSessionStore} from "./stores/InboundGroupSessionStore";
|
||||||
import {OutboundGroupSessionStore} from "./stores/OutboundGroupSessionStore.js";
|
import {OutboundGroupSessionStore} from "./stores/OutboundGroupSessionStore";
|
||||||
import {GroupSessionDecryptionStore} from "./stores/GroupSessionDecryptionStore.js";
|
import {GroupSessionDecryptionStore} from "./stores/GroupSessionDecryptionStore";
|
||||||
import {OperationStore} from "./stores/OperationStore.js";
|
import {OperationStore} from "./stores/OperationStore";
|
||||||
import {AccountDataStore} from "./stores/AccountDataStore.js";
|
import {AccountDataStore} from "./stores/AccountDataStore";
|
||||||
|
|
||||||
export class Transaction {
|
export class Transaction {
|
||||||
constructor(txn, allowedStoreNames, IDBKeyRange) {
|
constructor(txn, allowedStoreNames, IDBKeyRange) {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {RoomMember, EVENT_TYPE as MEMBER_EVENT_TYPE} from "../../room/members/Ro
|
||||||
import {addRoomToIdentity} from "../../e2ee/DeviceTracker.js";
|
import {addRoomToIdentity} from "../../e2ee/DeviceTracker.js";
|
||||||
import {RoomMemberStore} from "./stores/RoomMemberStore";
|
import {RoomMemberStore} from "./stores/RoomMemberStore";
|
||||||
import {SessionStore} from "./stores/SessionStore";
|
import {SessionStore} from "./stores/SessionStore";
|
||||||
import {encodeScopeTypeKey} from "./stores/OperationStore.js";
|
import {encodeScopeTypeKey} from "./stores/OperationStore";
|
||||||
import {MAX_UNICODE} from "./stores/common";
|
import {MAX_UNICODE} from "./stores/common";
|
||||||
|
|
||||||
// FUNCTIONS SHOULD ONLY BE APPENDED!!
|
// FUNCTIONS SHOULD ONLY BE APPENDED!!
|
||||||
|
|
|
@ -13,17 +13,26 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
import {Store} from "../Store";
|
||||||
|
import {Content} from "../../types";
|
||||||
|
|
||||||
|
interface AccountDataEntry {
|
||||||
|
type: string;
|
||||||
|
content: Content;
|
||||||
|
}
|
||||||
|
|
||||||
export class AccountDataStore {
|
export class AccountDataStore {
|
||||||
constructor(store) {
|
private _store: Store<AccountDataEntry>;
|
||||||
|
|
||||||
|
constructor(store: Store<AccountDataEntry>) {
|
||||||
this._store = store;
|
this._store = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(type) {
|
async get(type: string): Promise<AccountDataEntry | null> {
|
||||||
return await this._store.get(type);
|
return await this._store.get(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
set(event) {
|
set(event: AccountDataEntry): void {
|
||||||
return this._store.put(event);
|
this._store.put(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,33 +15,46 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {MAX_UNICODE, MIN_UNICODE} from "./common";
|
import {MAX_UNICODE, MIN_UNICODE} from "./common";
|
||||||
|
import {Store} from "../Store";
|
||||||
|
|
||||||
function encodeKey(userId, deviceId) {
|
interface DeviceIdentity {
|
||||||
|
userId: string;
|
||||||
|
deviceId: string;
|
||||||
|
ed25519Key: string;
|
||||||
|
curve25519Key: string;
|
||||||
|
algorithms: string[];
|
||||||
|
displayName: string;
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function encodeKey(userId: string, deviceId: string): string {
|
||||||
return `${userId}|${deviceId}`;
|
return `${userId}|${deviceId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeKey(key) {
|
function decodeKey(key: string): { userId: string, deviceId: string } {
|
||||||
const [userId, deviceId] = key.split("|");
|
const [userId, deviceId] = key.split("|");
|
||||||
return {userId, deviceId};
|
return {userId, deviceId};
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DeviceIdentityStore {
|
export class DeviceIdentityStore {
|
||||||
constructor(store) {
|
private _store: Store<DeviceIdentity>;
|
||||||
|
|
||||||
|
constructor(store: Store<DeviceIdentity>) {
|
||||||
this._store = store;
|
this._store = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
getAllForUserId(userId) {
|
getAllForUserId(userId: string): Promise<DeviceIdentity[]> {
|
||||||
const range = this._store.IDBKeyRange.lowerBound(encodeKey(userId, ""));
|
const range = this._store.IDBKeyRange.lowerBound(encodeKey(userId, ""));
|
||||||
return this._store.selectWhile(range, device => {
|
return this._store.selectWhile(range, device => {
|
||||||
return device.userId === userId;
|
return device.userId === userId;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllDeviceIds(userId) {
|
async getAllDeviceIds(userId: string): Promise<string[]> {
|
||||||
const deviceIds = [];
|
const deviceIds: string[] = [];
|
||||||
const range = this._store.IDBKeyRange.lowerBound(encodeKey(userId, ""));
|
const range = this._store.IDBKeyRange.lowerBound(encodeKey(userId, ""));
|
||||||
await this._store.iterateKeys(range, key => {
|
await this._store.iterateKeys(range, key => {
|
||||||
const decodedKey = decodeKey(key);
|
const decodedKey = decodeKey(key as string);
|
||||||
// prevent running into the next room
|
// prevent running into the next room
|
||||||
if (decodedKey.userId === userId) {
|
if (decodedKey.userId === userId) {
|
||||||
deviceIds.push(decodedKey.deviceId);
|
deviceIds.push(decodedKey.deviceId);
|
||||||
|
@ -52,27 +65,27 @@ export class DeviceIdentityStore {
|
||||||
return deviceIds;
|
return deviceIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
get(userId, deviceId) {
|
get(userId: string, deviceId: string): Promise<DeviceIdentity | null> {
|
||||||
return this._store.get(encodeKey(userId, deviceId));
|
return this._store.get(encodeKey(userId, deviceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
set(deviceIdentity) {
|
set(deviceIdentity: DeviceIdentity): void {
|
||||||
deviceIdentity.key = encodeKey(deviceIdentity.userId, deviceIdentity.deviceId);
|
deviceIdentity.key = encodeKey(deviceIdentity.userId, deviceIdentity.deviceId);
|
||||||
this._store.put(deviceIdentity);
|
this._store.put(deviceIdentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
getByCurve25519Key(curve25519Key) {
|
getByCurve25519Key(curve25519Key: string): Promise<DeviceIdentity | null> {
|
||||||
return this._store.index("byCurve25519Key").get(curve25519Key);
|
return this._store.index("byCurve25519Key").get(curve25519Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(userId, deviceId) {
|
remove(userId: string, deviceId: string): Promise<undefined> {
|
||||||
this._store.delete(encodeKey(userId, deviceId));
|
return this._store.delete(encodeKey(userId, deviceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAllForUser(userId) {
|
removeAllForUser(userId: string): Promise<undefined> {
|
||||||
// exclude both keys as they are theoretical min and max,
|
// exclude both keys as they are theoretical min and max,
|
||||||
// but we should't have a match for just the room id, or room id with max
|
// but we should't have a match for just the room id, or room id with max
|
||||||
const range = this._store.IDBKeyRange.bound(encodeKey(userId, MIN_UNICODE), encodeKey(userId, MAX_UNICODE), true, true);
|
const range = this._store.IDBKeyRange.bound(encodeKey(userId, MIN_UNICODE), encodeKey(userId, MAX_UNICODE), true, true);
|
||||||
this._store.delete(range);
|
return this._store.delete(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,30 +15,40 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {MIN_UNICODE, MAX_UNICODE} from "./common";
|
import {MIN_UNICODE, MAX_UNICODE} from "./common";
|
||||||
|
import {Store} from "../Store";
|
||||||
|
|
||||||
function encodeKey(roomId, sessionId, messageIndex) {
|
function encodeKey(roomId: string, sessionId: string, messageIndex: number | string): string {
|
||||||
return `${roomId}|${sessionId}|${messageIndex}`;
|
return `${roomId}|${sessionId}|${messageIndex}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface GroupSessionDecryption {
|
||||||
|
eventId: string;
|
||||||
|
timestamp: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type GroupSessionEntry = GroupSessionDecryption & { key: string }
|
||||||
|
|
||||||
export class GroupSessionDecryptionStore {
|
export class GroupSessionDecryptionStore {
|
||||||
constructor(store) {
|
private _store: Store<GroupSessionEntry>;
|
||||||
|
|
||||||
|
constructor(store: Store<GroupSessionEntry>) {
|
||||||
this._store = store;
|
this._store = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
get(roomId, sessionId, messageIndex) {
|
get(roomId: string, sessionId: string, messageIndex: number): Promise<GroupSessionDecryption | null> {
|
||||||
return this._store.get(encodeKey(roomId, sessionId, messageIndex));
|
return this._store.get(encodeKey(roomId, sessionId, messageIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
set(roomId, sessionId, messageIndex, decryption) {
|
set(roomId: string, sessionId: string, messageIndex: number, decryption: GroupSessionDecryption): void {
|
||||||
decryption.key = encodeKey(roomId, sessionId, messageIndex);
|
(decryption as GroupSessionEntry).key = encodeKey(roomId, sessionId, messageIndex);
|
||||||
this._store.put(decryption);
|
this._store.put(decryption as GroupSessionEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAllForRoom(roomId) {
|
removeAllForRoom(roomId: string): Promise<undefined> {
|
||||||
const range = this._store.IDBKeyRange.bound(
|
const range = this._store.IDBKeyRange.bound(
|
||||||
encodeKey(roomId, MIN_UNICODE, MIN_UNICODE),
|
encodeKey(roomId, MIN_UNICODE, MIN_UNICODE),
|
||||||
encodeKey(roomId, MAX_UNICODE, MAX_UNICODE)
|
encodeKey(roomId, MAX_UNICODE, MAX_UNICODE)
|
||||||
);
|
);
|
||||||
this._store.delete(range);
|
return this._store.delete(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,36 +15,49 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {MIN_UNICODE, MAX_UNICODE} from "./common";
|
import {MIN_UNICODE, MAX_UNICODE} from "./common";
|
||||||
|
import {Store} from "../Store";
|
||||||
|
|
||||||
function encodeKey(roomId, senderKey, sessionId) {
|
interface InboundGroupSession {
|
||||||
|
roomId: string;
|
||||||
|
senderKey: string;
|
||||||
|
sessionId: string;
|
||||||
|
session?: string;
|
||||||
|
claimedKeys?: { [algorithm : string] : string };
|
||||||
|
eventIds?: string[];
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function encodeKey(roomId: string, senderKey: string, sessionId: string): string {
|
||||||
return `${roomId}|${senderKey}|${sessionId}`;
|
return `${roomId}|${senderKey}|${sessionId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InboundGroupSessionStore {
|
export class InboundGroupSessionStore {
|
||||||
constructor(store) {
|
private _store: Store<InboundGroupSession>;
|
||||||
|
|
||||||
|
constructor(store: Store<InboundGroupSession>) {
|
||||||
this._store = store;
|
this._store = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
async has(roomId, senderKey, sessionId) {
|
async has(roomId: string, senderKey: string, sessionId: string): Promise<boolean> {
|
||||||
const key = encodeKey(roomId, senderKey, sessionId);
|
const key = encodeKey(roomId, senderKey, sessionId);
|
||||||
const fetchedKey = await this._store.getKey(key);
|
const fetchedKey = await this._store.getKey(key);
|
||||||
return key === fetchedKey;
|
return key === fetchedKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
get(roomId, senderKey, sessionId) {
|
get(roomId: string, senderKey: string, sessionId: string): Promise<InboundGroupSession | null> {
|
||||||
return this._store.get(encodeKey(roomId, senderKey, sessionId));
|
return this._store.get(encodeKey(roomId, senderKey, sessionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
set(session) {
|
set(session: InboundGroupSession): void {
|
||||||
session.key = encodeKey(session.roomId, session.senderKey, session.sessionId);
|
session.key = encodeKey(session.roomId, session.senderKey, session.sessionId);
|
||||||
this._store.put(session);
|
this._store.put(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAllForRoom(roomId) {
|
removeAllForRoom(roomId: string): Promise<undefined> {
|
||||||
const range = this._store.IDBKeyRange.bound(
|
const range = this._store.IDBKeyRange.bound(
|
||||||
encodeKey(roomId, MIN_UNICODE, MIN_UNICODE),
|
encodeKey(roomId, MIN_UNICODE, MIN_UNICODE),
|
||||||
encodeKey(roomId, MAX_UNICODE, MAX_UNICODE)
|
encodeKey(roomId, MAX_UNICODE, MAX_UNICODE)
|
||||||
);
|
);
|
||||||
this._store.delete(range);
|
return this._store.delete(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,26 +13,38 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
import {Store} from "../Store";
|
||||||
|
|
||||||
function encodeKey(senderKey, sessionId) {
|
function encodeKey(senderKey: string, sessionId: string): string {
|
||||||
return `${senderKey}|${sessionId}`;
|
return `${senderKey}|${sessionId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeKey(key) {
|
function decodeKey(key: string): { senderKey: string, sessionId: string } {
|
||||||
const [senderKey, sessionId] = key.split("|");
|
const [senderKey, sessionId] = key.split("|");
|
||||||
return {senderKey, sessionId};
|
return {senderKey, sessionId};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface OlmSession {
|
||||||
|
session: string;
|
||||||
|
sessionId: string;
|
||||||
|
senderKey: string;
|
||||||
|
lastUsed: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type OlmSessionEntry = OlmSession & { key: string };
|
||||||
|
|
||||||
export class OlmSessionStore {
|
export class OlmSessionStore {
|
||||||
constructor(store) {
|
private _store: Store<OlmSessionEntry>;
|
||||||
|
|
||||||
|
constructor(store: Store<OlmSessionEntry>) {
|
||||||
this._store = store;
|
this._store = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSessionIds(senderKey) {
|
async getSessionIds(senderKey: string): Promise<string[]> {
|
||||||
const sessionIds = [];
|
const sessionIds: string[] = [];
|
||||||
const range = this._store.IDBKeyRange.lowerBound(encodeKey(senderKey, ""));
|
const range = this._store.IDBKeyRange.lowerBound(encodeKey(senderKey, ""));
|
||||||
await this._store.iterateKeys(range, key => {
|
await this._store.iterateKeys(range, key => {
|
||||||
const decodedKey = decodeKey(key);
|
const decodedKey = decodeKey(key as string);
|
||||||
// prevent running into the next room
|
// prevent running into the next room
|
||||||
if (decodedKey.senderKey === senderKey) {
|
if (decodedKey.senderKey === senderKey) {
|
||||||
sessionIds.push(decodedKey.sessionId);
|
sessionIds.push(decodedKey.sessionId);
|
||||||
|
@ -43,23 +55,23 @@ export class OlmSessionStore {
|
||||||
return sessionIds;
|
return sessionIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
getAll(senderKey) {
|
getAll(senderKey: string): Promise<OlmSession[]> {
|
||||||
const range = this._store.IDBKeyRange.lowerBound(encodeKey(senderKey, ""));
|
const range = this._store.IDBKeyRange.lowerBound(encodeKey(senderKey, ""));
|
||||||
return this._store.selectWhile(range, session => {
|
return this._store.selectWhile(range, session => {
|
||||||
return session.senderKey === senderKey;
|
return session.senderKey === senderKey;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get(senderKey, sessionId) {
|
get(senderKey: string, sessionId: string): Promise<OlmSession | null> {
|
||||||
return this._store.get(encodeKey(senderKey, sessionId));
|
return this._store.get(encodeKey(senderKey, sessionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
set(session) {
|
set(session: OlmSession): void {
|
||||||
session.key = encodeKey(session.senderKey, session.sessionId);
|
(session as OlmSessionEntry).key = encodeKey(session.senderKey, session.sessionId);
|
||||||
return this._store.put(session);
|
this._store.put(session as OlmSessionEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(senderKey, sessionId) {
|
remove(senderKey: string, sessionId: string): Promise<undefined> {
|
||||||
return this._store.delete(encodeKey(senderKey, sessionId));
|
return this._store.delete(encodeKey(senderKey, sessionId));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,23 +14,46 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
import {MIN_UNICODE, MAX_UNICODE} from "./common";
|
import {MIN_UNICODE, MAX_UNICODE} from "./common";
|
||||||
|
import {Store} from "../Store";
|
||||||
|
|
||||||
export function encodeScopeTypeKey(scope, type) {
|
export function encodeScopeTypeKey(scope: string, type: string): string {
|
||||||
return `${scope}|${type}`;
|
return `${scope}|${type}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface BaseOperation {
|
||||||
|
id: string;
|
||||||
|
scope: string;
|
||||||
|
userIds: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
type OperationType = { type: "share_room_key"; roomKeyMessage: RoomKeyMessage; }
|
||||||
|
|
||||||
|
type Operation = BaseOperation & OperationType
|
||||||
|
|
||||||
|
type OperationEntry = Operation & { scopeTypeKey: string; }
|
||||||
|
|
||||||
|
interface RoomKeyMessage {
|
||||||
|
room_id: string;
|
||||||
|
session_id: string;
|
||||||
|
session_key: string;
|
||||||
|
algorithm: string;
|
||||||
|
chain_index: number;
|
||||||
|
}
|
||||||
|
|
||||||
export class OperationStore {
|
export class OperationStore {
|
||||||
constructor(store) {
|
private _store: Store<OperationEntry>;
|
||||||
|
|
||||||
|
constructor(store: Store<OperationEntry>) {
|
||||||
this._store = store;
|
this._store = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
getAll() {
|
getAll(): Promise<Operation[]> {
|
||||||
return this._store.selectAll();
|
return this._store.selectAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllByTypeAndScope(type, scope) {
|
async getAllByTypeAndScope(type: string, scope: string): Promise<Operation[]> {
|
||||||
const key = encodeScopeTypeKey(scope, type);
|
const key = encodeScopeTypeKey(scope, type);
|
||||||
const results = [];
|
const results: Operation[] = [];
|
||||||
await this._store.index("byScopeAndType").iterateWhile(key, value => {
|
await this._store.index("byScopeAndType").iterateWhile(key, value => {
|
||||||
if (value.scopeTypeKey !== key) {
|
if (value.scopeTypeKey !== key) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -41,20 +64,20 @@ export class OperationStore {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(operation) {
|
add(operation: Operation): void {
|
||||||
operation.scopeTypeKey = encodeScopeTypeKey(operation.scope, operation.type);
|
(operation as OperationEntry).scopeTypeKey = encodeScopeTypeKey(operation.scope, operation.type);
|
||||||
this._store.add(operation);
|
this._store.add(operation as OperationEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(operation) {
|
update(operation: Operation): void {
|
||||||
this._store.put(operation);
|
this._store.put(operation as OperationEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(id) {
|
remove(id: string): Promise<undefined> {
|
||||||
this._store.delete(id);
|
return this._store.delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeAllForScope(scope) {
|
async removeAllForScope(scope: string): Promise<undefined> {
|
||||||
const range = this._store.IDBKeyRange.bound(
|
const range = this._store.IDBKeyRange.bound(
|
||||||
encodeScopeTypeKey(scope, MIN_UNICODE),
|
encodeScopeTypeKey(scope, MIN_UNICODE),
|
||||||
encodeScopeTypeKey(scope, MAX_UNICODE)
|
encodeScopeTypeKey(scope, MAX_UNICODE)
|
||||||
|
@ -64,5 +87,6 @@ export class OperationStore {
|
||||||
cur.delete();
|
cur.delete();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,21 +13,30 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
import {Store} from "../Store";
|
||||||
|
|
||||||
|
interface OutboundSession {
|
||||||
|
roomId: string;
|
||||||
|
session: string;
|
||||||
|
createdAt: number;
|
||||||
|
}
|
||||||
|
|
||||||
export class OutboundGroupSessionStore {
|
export class OutboundGroupSessionStore {
|
||||||
constructor(store) {
|
private _store: Store<OutboundSession>;
|
||||||
|
|
||||||
|
constructor(store: Store<OutboundSession>) {
|
||||||
this._store = store;
|
this._store = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(roomId) {
|
remove(roomId: string): Promise<undefined> {
|
||||||
this._store.delete(roomId);
|
return this._store.delete(roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
get(roomId) {
|
get(roomId: string): Promise<OutboundSession | null> {
|
||||||
return this._store.get(roomId);
|
return this._store.get(roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
set(session) {
|
set(session: OutboundSession): void {
|
||||||
this._store.put(session);
|
this._store.put(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,23 +16,40 @@ limitations under the License.
|
||||||
|
|
||||||
import { encodeUint32, decodeUint32 } from "../utils";
|
import { encodeUint32, decodeUint32 } from "../utils";
|
||||||
import {KeyLimits} from "../../common";
|
import {KeyLimits} from "../../common";
|
||||||
|
import {Store} from "../Store";
|
||||||
|
import {Content} from "../../types";
|
||||||
|
|
||||||
function encodeKey(roomId, queueIndex) {
|
interface PendingEntry {
|
||||||
|
roomId: string;
|
||||||
|
queueIndex: number;
|
||||||
|
eventType: string;
|
||||||
|
content: Content;
|
||||||
|
relatexTxnId: string | null;
|
||||||
|
relatedEventId: string | null;
|
||||||
|
txnId?: string;
|
||||||
|
needsEncryption: boolean;
|
||||||
|
needsUpload: boolean;
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function encodeKey(roomId: string, queueIndex: number): string {
|
||||||
return `${roomId}|${encodeUint32(queueIndex)}`;
|
return `${roomId}|${encodeUint32(queueIndex)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeKey(key) {
|
function decodeKey(key: string): { roomId: string, queueIndex: number } {
|
||||||
const [roomId, encodedQueueIndex] = key.split("|");
|
const [roomId, encodedQueueIndex] = key.split("|");
|
||||||
const queueIndex = decodeUint32(encodedQueueIndex);
|
const queueIndex = decodeUint32(encodedQueueIndex);
|
||||||
return {roomId, queueIndex};
|
return {roomId, queueIndex};
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PendingEventStore {
|
export class PendingEventStore {
|
||||||
constructor(eventStore) {
|
private _eventStore: Store<PendingEntry>;
|
||||||
|
|
||||||
|
constructor(eventStore: Store<PendingEntry>) {
|
||||||
this._eventStore = eventStore;
|
this._eventStore = eventStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMaxQueueIndex(roomId) {
|
async getMaxQueueIndex(roomId: string): Promise<number | undefined> {
|
||||||
const range = this._eventStore.IDBKeyRange.bound(
|
const range = this._eventStore.IDBKeyRange.bound(
|
||||||
encodeKey(roomId, KeyLimits.minStorageKey),
|
encodeKey(roomId, KeyLimits.minStorageKey),
|
||||||
encodeKey(roomId, KeyLimits.maxStorageKey),
|
encodeKey(roomId, KeyLimits.maxStorageKey),
|
||||||
|
@ -41,38 +58,38 @@ export class PendingEventStore {
|
||||||
);
|
);
|
||||||
const maxKey = await this._eventStore.findMaxKey(range);
|
const maxKey = await this._eventStore.findMaxKey(range);
|
||||||
if (maxKey) {
|
if (maxKey) {
|
||||||
return decodeKey(maxKey).queueIndex;
|
return decodeKey(maxKey as string).queueIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(roomId, queueIndex) {
|
remove(roomId: string, queueIndex: number): Promise<undefined> {
|
||||||
const keyRange = this._eventStore.IDBKeyRange.only(encodeKey(roomId, queueIndex));
|
const keyRange = this._eventStore.IDBKeyRange.only(encodeKey(roomId, queueIndex));
|
||||||
this._eventStore.delete(keyRange);
|
return this._eventStore.delete(keyRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
async exists(roomId, queueIndex) {
|
async exists(roomId: string, queueIndex: number): Promise<boolean> {
|
||||||
const keyRange = this._eventStore.IDBKeyRange.only(encodeKey(roomId, queueIndex));
|
const keyRange = this._eventStore.IDBKeyRange.only(encodeKey(roomId, queueIndex));
|
||||||
const key = await this._eventStore.getKey(keyRange);
|
const key = await this._eventStore.getKey(keyRange);
|
||||||
return !!key;
|
return !!key;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(pendingEvent) {
|
add(pendingEvent: PendingEntry): void {
|
||||||
pendingEvent.key = encodeKey(pendingEvent.roomId, pendingEvent.queueIndex);
|
pendingEvent.key = encodeKey(pendingEvent.roomId, pendingEvent.queueIndex);
|
||||||
this._eventStore.add(pendingEvent);
|
this._eventStore.add(pendingEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(pendingEvent) {
|
update(pendingEvent: PendingEntry): void {
|
||||||
this._eventStore.put(pendingEvent);
|
this._eventStore.put(pendingEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
getAll() {
|
getAll(): Promise<PendingEntry[]> {
|
||||||
return this._eventStore.selectAll();
|
return this._eventStore.selectAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAllForRoom(roomId) {
|
removeAllForRoom(roomId: string): Promise<undefined> {
|
||||||
const minKey = encodeKey(roomId, KeyLimits.minStorageKey);
|
const minKey = encodeKey(roomId, KeyLimits.minStorageKey);
|
||||||
const maxKey = encodeKey(roomId, KeyLimits.maxStorageKey);
|
const maxKey = encodeKey(roomId, KeyLimits.maxStorageKey);
|
||||||
const range = this._eventStore.IDBKeyRange.bound(minKey, maxKey);
|
const range = this._eventStore.IDBKeyRange.bound(minKey, maxKey);
|
||||||
this._eventStore.delete(range);
|
return this._eventStore.delete(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -52,7 +52,7 @@ export class RoomMemberStore {
|
||||||
|
|
||||||
set(member: MemberData): void {
|
set(member: MemberData): void {
|
||||||
// Object.assign would be more typesafe, but small objects
|
// Object.assign would be more typesafe, but small objects
|
||||||
(member as any).key = encodeKey(member.roomId, member.userId);
|
(member as MemberStorageEntry).key = encodeKey(member.roomId, member.userId);
|
||||||
this._roomMembersStore.put(member as MemberStorageEntry);
|
this._roomMembersStore.put(member as MemberStorageEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,31 +16,41 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {MAX_UNICODE} from "./common";
|
import {MAX_UNICODE} from "./common";
|
||||||
|
import {Store} from "../Store";
|
||||||
|
import {StateEvent} from "../../types";
|
||||||
|
|
||||||
function encodeKey(roomId, eventType, stateKey) {
|
function encodeKey(roomId: string, eventType: string, stateKey: string) {
|
||||||
return `${roomId}|${eventType}|${stateKey}`;
|
return `${roomId}|${eventType}|${stateKey}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RoomStateEntry {
|
||||||
|
roomId: string;
|
||||||
|
event: StateEvent;
|
||||||
|
key: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class RoomStateStore {
|
export class RoomStateStore {
|
||||||
constructor(idbStore) {
|
private _roomStateStore: Store<RoomStateEntry>;
|
||||||
|
|
||||||
|
constructor(idbStore: Store<RoomStateEntry>) {
|
||||||
this._roomStateStore = idbStore;
|
this._roomStateStore = idbStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
get(roomId, type, stateKey) {
|
get(roomId: string, type: string, stateKey: string): Promise<RoomStateEntry | null> {
|
||||||
const key = encodeKey(roomId, type, stateKey);
|
const key = encodeKey(roomId, type, stateKey);
|
||||||
return this._roomStateStore.get(key);
|
return this._roomStateStore.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
set(roomId, event) {
|
set(roomId: string, event: StateEvent): void {
|
||||||
const key = encodeKey(roomId, event.type, event.state_key);
|
const key = encodeKey(roomId, event.type, event.state_key);
|
||||||
const entry = {roomId, event, key};
|
const entry = {roomId, event, key};
|
||||||
return this._roomStateStore.put(entry);
|
this._roomStateStore.put(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAllForRoom(roomId) {
|
removeAllForRoom(roomId: string): Promise<undefined> {
|
||||||
// exclude both keys as they are theoretical min and max,
|
// exclude both keys as they are theoretical min and max,
|
||||||
// but we should't have a match for just the room id, or room id with max
|
// but we should't have a match for just the room id, or room id with max
|
||||||
const range = this._roomStateStore.IDBKeyRange.bound(roomId, `${roomId}|${MAX_UNICODE}`, true, true);
|
const range = this._roomStateStore.IDBKeyRange.bound(roomId, `${roomId}|${MAX_UNICODE}`, true, true);
|
||||||
this._roomStateStore.delete(range);
|
return this._roomStateStore.delete(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -27,7 +27,7 @@ interface Annotation {
|
||||||
firstTimestamp: number;
|
firstTimestamp: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface StorageEntry {
|
interface TimelineEventEntry {
|
||||||
roomId: string;
|
roomId: string;
|
||||||
fragmentId: number;
|
fragmentId: number;
|
||||||
eventIndex: number;
|
eventIndex: number;
|
||||||
|
@ -35,10 +35,10 @@ interface StorageEntry {
|
||||||
displayName?: string;
|
displayName?: string;
|
||||||
avatarUrl?: string;
|
avatarUrl?: string;
|
||||||
annotations?: { [key : string]: Annotation };
|
annotations?: { [key : string]: Annotation };
|
||||||
key: string;
|
|
||||||
eventIdKey: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TimelineEventStorageEntry = TimelineEventEntry & { key: string, eventIdKey: string };
|
||||||
|
|
||||||
function encodeKey(roomId: string, fragmentId: number, eventIndex: number): string {
|
function encodeKey(roomId: string, fragmentId: number, eventIndex: number): string {
|
||||||
return `${roomId}|${encodeUint32(fragmentId)}|${encodeUint32(eventIndex)}`;
|
return `${roomId}|${encodeUint32(fragmentId)}|${encodeUint32(eventIndex)}`;
|
||||||
}
|
}
|
||||||
|
@ -126,9 +126,9 @@ class Range {
|
||||||
* @property {?Gap} gap if a gap entry, the gap
|
* @property {?Gap} gap if a gap entry, the gap
|
||||||
*/
|
*/
|
||||||
export class TimelineEventStore {
|
export class TimelineEventStore {
|
||||||
private _timelineStore: Store<StorageEntry>;
|
private _timelineStore: Store<TimelineEventStorageEntry>;
|
||||||
|
|
||||||
constructor(timelineStore: Store<StorageEntry>) {
|
constructor(timelineStore: Store<TimelineEventStorageEntry>) {
|
||||||
this._timelineStore = timelineStore;
|
this._timelineStore = timelineStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ export class TimelineEventStore {
|
||||||
* @param amount
|
* @param amount
|
||||||
* @return a promise resolving to an array with 0 or more entries, in ascending order.
|
* @return a promise resolving to an array with 0 or more entries, in ascending order.
|
||||||
*/
|
*/
|
||||||
async lastEvents(roomId: string, fragmentId: number, amount: number): Promise<StorageEntry[]> {
|
async lastEvents(roomId: string, fragmentId: number, amount: number): Promise<TimelineEventEntry[]> {
|
||||||
const eventKey = EventKey.maxKey;
|
const eventKey = EventKey.maxKey;
|
||||||
eventKey.fragmentId = fragmentId;
|
eventKey.fragmentId = fragmentId;
|
||||||
return this.eventsBefore(roomId, eventKey, amount);
|
return this.eventsBefore(roomId, eventKey, amount);
|
||||||
|
@ -187,7 +187,7 @@ export class TimelineEventStore {
|
||||||
* @param amount
|
* @param amount
|
||||||
* @return a promise resolving to an array with 0 or more entries, in ascending order.
|
* @return a promise resolving to an array with 0 or more entries, in ascending order.
|
||||||
*/
|
*/
|
||||||
async firstEvents(roomId: string, fragmentId: number, amount: number): Promise<StorageEntry[]> {
|
async firstEvents(roomId: string, fragmentId: number, amount: number): Promise<TimelineEventEntry[]> {
|
||||||
const eventKey = EventKey.minKey;
|
const eventKey = EventKey.minKey;
|
||||||
eventKey.fragmentId = fragmentId;
|
eventKey.fragmentId = fragmentId;
|
||||||
return this.eventsAfter(roomId, eventKey, amount);
|
return this.eventsAfter(roomId, eventKey, amount);
|
||||||
|
@ -200,7 +200,7 @@ export class TimelineEventStore {
|
||||||
* @param amount
|
* @param amount
|
||||||
* @return a promise resolving to an array with 0 or more entries, in ascending order.
|
* @return a promise resolving to an array with 0 or more entries, in ascending order.
|
||||||
*/
|
*/
|
||||||
eventsAfter(roomId: string, eventKey: EventKey, amount: number): Promise<StorageEntry[]> {
|
eventsAfter(roomId: string, eventKey: EventKey, amount: number): Promise<TimelineEventEntry[]> {
|
||||||
const idbRange = this.lowerBoundRange(eventKey, true).asIDBKeyRange(roomId);
|
const idbRange = this.lowerBoundRange(eventKey, true).asIDBKeyRange(roomId);
|
||||||
return this._timelineStore.selectLimit(idbRange, amount);
|
return this._timelineStore.selectLimit(idbRange, amount);
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,7 @@ export class TimelineEventStore {
|
||||||
* @param amount
|
* @param amount
|
||||||
* @return a promise resolving to an array with 0 or more entries, in ascending order.
|
* @return a promise resolving to an array with 0 or more entries, in ascending order.
|
||||||
*/
|
*/
|
||||||
async eventsBefore(roomId: string, eventKey: EventKey, amount: number): Promise<StorageEntry[]> {
|
async eventsBefore(roomId: string, eventKey: EventKey, amount: number): Promise<TimelineEventEntry[]> {
|
||||||
const range = this.upperBoundRange(eventKey, true).asIDBKeyRange(roomId);
|
const range = this.upperBoundRange(eventKey, true).asIDBKeyRange(roomId);
|
||||||
const events = await this._timelineStore.selectLimitReverse(range, amount);
|
const events = await this._timelineStore.selectLimitReverse(range, amount);
|
||||||
events.reverse(); // because we fetched them backwards
|
events.reverse(); // because we fetched them backwards
|
||||||
|
@ -265,11 +265,11 @@ export class TimelineEventStore {
|
||||||
* @return nothing. To wait for the operation to finish, await the transaction it's part of.
|
* @return nothing. To wait for the operation to finish, await the transaction it's part of.
|
||||||
* @throws {StorageError} ...
|
* @throws {StorageError} ...
|
||||||
*/
|
*/
|
||||||
insert(entry: StorageEntry): void {
|
insert(entry: TimelineEventEntry): void {
|
||||||
entry.key = encodeKey(entry.roomId, entry.fragmentId, entry.eventIndex);
|
(entry as TimelineEventStorageEntry).key = encodeKey(entry.roomId, entry.fragmentId, entry.eventIndex);
|
||||||
entry.eventIdKey = encodeEventIdKey(entry.roomId, entry.event.event_id);
|
(entry as TimelineEventStorageEntry).eventIdKey = encodeEventIdKey(entry.roomId, entry.event.event_id);
|
||||||
// TODO: map error? or in idb/store?
|
// TODO: map error? or in idb/store?
|
||||||
this._timelineStore.add(entry);
|
this._timelineStore.add(entry as TimelineEventStorageEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Updates the entry into the store with the given [roomId, eventKey] combination.
|
/** Updates the entry into the store with the given [roomId, eventKey] combination.
|
||||||
|
@ -277,15 +277,15 @@ export class TimelineEventStore {
|
||||||
* @param entry the entry to update.
|
* @param entry the entry to update.
|
||||||
* @return nothing. To wait for the operation to finish, await the transaction it's part of.
|
* @return nothing. To wait for the operation to finish, await the transaction it's part of.
|
||||||
*/
|
*/
|
||||||
update(entry: StorageEntry): void {
|
update(entry: TimelineEventEntry): void {
|
||||||
this._timelineStore.put(entry);
|
this._timelineStore.put(entry as TimelineEventStorageEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
get(roomId: string, eventKey: EventKey): Promise<StorageEntry | null> {
|
get(roomId: string, eventKey: EventKey): Promise<TimelineEventEntry | null> {
|
||||||
return this._timelineStore.get(encodeKey(roomId, eventKey.fragmentId, eventKey.eventIndex));
|
return this._timelineStore.get(encodeKey(roomId, eventKey.fragmentId, eventKey.eventIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
getByEventId(roomId: string, eventId: string): Promise<StorageEntry | null> {
|
getByEventId(roomId: string, eventId: string): Promise<TimelineEventEntry | null> {
|
||||||
return this._timelineStore.index("byEventId").get(encodeEventIdKey(roomId, eventId));
|
return this._timelineStore.index("byEventId").get(encodeEventIdKey(roomId, eventId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,17 +17,31 @@ limitations under the License.
|
||||||
import { StorageError } from "../../common";
|
import { StorageError } from "../../common";
|
||||||
import {KeyLimits} from "../../common";
|
import {KeyLimits} from "../../common";
|
||||||
import { encodeUint32 } from "../utils";
|
import { encodeUint32 } from "../utils";
|
||||||
|
import {Store} from "../Store";
|
||||||
|
|
||||||
function encodeKey(roomId, fragmentId) {
|
interface Fragment {
|
||||||
|
roomId: string;
|
||||||
|
id: number;
|
||||||
|
previousId: number | null;
|
||||||
|
nextId: number | null;
|
||||||
|
previousToken: string | null;
|
||||||
|
nextToken: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
type FragmentEntry = Fragment & { key: string }
|
||||||
|
|
||||||
|
function encodeKey(roomId: string, fragmentId: number): string {
|
||||||
return `${roomId}|${encodeUint32(fragmentId)}`;
|
return `${roomId}|${encodeUint32(fragmentId)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TimelineFragmentStore {
|
export class TimelineFragmentStore {
|
||||||
constructor(store) {
|
private _store: Store<FragmentEntry>;
|
||||||
|
|
||||||
|
constructor(store: Store<FragmentEntry>) {
|
||||||
this._store = store;
|
this._store = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
_allRange(roomId) {
|
_allRange(roomId: string): IDBKeyRange {
|
||||||
try {
|
try {
|
||||||
return this._store.IDBKeyRange.bound(
|
return this._store.IDBKeyRange.bound(
|
||||||
encodeKey(roomId, KeyLimits.minStorageKey),
|
encodeKey(roomId, KeyLimits.minStorageKey),
|
||||||
|
@ -38,13 +52,13 @@ export class TimelineFragmentStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
all(roomId) {
|
all(roomId: string): Promise<FragmentEntry[]> {
|
||||||
return this._store.selectAll(this._allRange(roomId));
|
return this._store.selectAll(this._allRange(roomId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the fragment without a nextToken and without nextId,
|
/** Returns the fragment without a nextToken and without nextId,
|
||||||
if any, with the largest id if there are multiple (which should not happen) */
|
if any, with the largest id if there are multiple (which should not happen) */
|
||||||
liveFragment(roomId) {
|
liveFragment(roomId: string): Promise<FragmentEntry | undefined> {
|
||||||
// why do we need this?
|
// why do we need this?
|
||||||
// Ok, take the case where you've got a /context fragment and a /sync fragment
|
// Ok, take the case where you've got a /context fragment and a /sync fragment
|
||||||
// They are not connected. So, upon loading the persister, which one do we take? We can't sort them ...
|
// They are not connected. So, upon loading the persister, which one do we take? We can't sort them ...
|
||||||
|
@ -60,20 +74,20 @@ export class TimelineFragmentStore {
|
||||||
// should generate an id an return it?
|
// should generate an id an return it?
|
||||||
// depends if we want to do anything smart with fragment ids,
|
// depends if we want to do anything smart with fragment ids,
|
||||||
// like give them meaning depending on range. not for now probably ...
|
// like give them meaning depending on range. not for now probably ...
|
||||||
add(fragment) {
|
add(fragment: Fragment): void {
|
||||||
fragment.key = encodeKey(fragment.roomId, fragment.id);
|
(fragment as FragmentEntry).key = encodeKey(fragment.roomId, fragment.id);
|
||||||
this._store.add(fragment);
|
this._store.add(fragment as FragmentEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(fragment) {
|
update(fragment: FragmentEntry): void {
|
||||||
this._store.put(fragment);
|
this._store.put(fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
get(roomId, fragmentId) {
|
get(roomId: string, fragmentId: number): Promise<FragmentEntry | null> {
|
||||||
return this._store.get(encodeKey(roomId, fragmentId));
|
return this._store.get(encodeKey(roomId, fragmentId));
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAllForRoom(roomId) {
|
removeAllForRoom(roomId: string): Promise<undefined> {
|
||||||
this._store.delete(this._allRange(roomId));
|
return this._store.delete(this._allRange(roomId));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,21 +13,30 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
import {Store} from "../Store";
|
||||||
|
|
||||||
|
interface UserIdentity {
|
||||||
|
userId: string;
|
||||||
|
roomIds: string[];
|
||||||
|
deviceTrackingStatus: number;
|
||||||
|
}
|
||||||
|
|
||||||
export class UserIdentityStore {
|
export class UserIdentityStore {
|
||||||
constructor(store) {
|
private _store: Store<UserIdentity>;
|
||||||
|
|
||||||
|
constructor(store: Store<UserIdentity>) {
|
||||||
this._store = store;
|
this._store = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
get(userId) {
|
get(userId: string): Promise<UserIdentity | null> {
|
||||||
return this._store.get(userId);
|
return this._store.get(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
set(userIdentity) {
|
set(userIdentity: UserIdentity): void {
|
||||||
this._store.put(userIdentity);
|
this._store.put(userIdentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(userId) {
|
remove(userId: string): Promise<undefined> {
|
||||||
return this._store.delete(userId);
|
return this._store.delete(userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue