Forked from
TransFem.org / Sharkey
4939 commits behind the upstream repository.
-
syuilo authored2cd32b22
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
pizzax.ts 9.22 KiB
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
// PIZZAX --- A lightweight store
import { onUnmounted, Ref, ref, watch } from 'vue';
import { BroadcastChannel } from 'broadcast-channel';
import { $i } from '@/account.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { get, set } from '@/scripts/idb-proxy.js';
import { defaultStore } from '@/store.js';
import { useStream } from '@/stream.js';
import { deepClone } from '@/scripts/clone.js';
type StateDef = Record<string, {
where: 'account' | 'device' | 'deviceAccount';
default: any;
}>;
type State<T extends StateDef> = { [K in keyof T]: T[K]['default']; };
type ReactiveState<T extends StateDef> = { [K in keyof T]: Ref<T[K]['default']>; };
type ArrayElement<A> = A extends readonly (infer T)[] ? T : never;
type PizzaxChannelMessage<T extends StateDef> = {
where: 'device' | 'deviceAccount';
key: keyof T;
value: T[keyof T]['default'];
userId?: string;
};
export class Storage<T extends StateDef> {
public readonly ready: Promise<void>;
public readonly loaded: Promise<void>;
public readonly key: string;
public readonly deviceStateKeyName: `pizzax::${this['key']}`;
public readonly deviceAccountStateKeyName: `pizzax::${this['key']}::${string}` | '';
public readonly registryCacheKeyName: `pizzax::${this['key']}::cache::${string}` | '';
public readonly def: T;
// TODO: これが実装されたらreadonlyにしたい: https://github.com/microsoft/TypeScript/issues/37487
public readonly state: State<T>;
public readonly reactiveState: ReactiveState<T>;
private pizzaxChannel: BroadcastChannel<PizzaxChannelMessage<T>>;
// 簡易的にキューイングして占有ロックとする
private currentIdbJob: Promise<any> = Promise.resolve();
private addIdbSetJob<T>(job: () => Promise<T>) {
const promise = this.currentIdbJob.then(job, err => {
console.error('Pizzax failed to save data to idb!', err);
return job();
});
this.currentIdbJob = promise;
return promise;
}
constructor(key: string, def: T) {
this.key = key;
this.deviceStateKeyName = `pizzax::${key}`;
this.deviceAccountStateKeyName = $i ? `pizzax::${key}::${$i.id}` : '';
this.registryCacheKeyName = $i ? `pizzax::${key}::cache::${$i.id}` : '';
this.def = def;
this.pizzaxChannel = new BroadcastChannel(`pizzax::${key}`);