Skip to content

Commit

Permalink
Simplify state and storage
Browse files Browse the repository at this point in the history
  • Loading branch information
redmundas committed Apr 19, 2024
1 parent 7a9ee6d commit 4b9a4bd
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 191 deletions.
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@
"yargs": "^17.7.2"
},
"dependencies": {
"dexie": "^4.0.4",
"emittery": "^1.0.3",
"loglevel": "^1.9.1",
"uuid": "^9.0.1",
"webextension-polyfill": "^0.11.0",
"xstate": "^5.10.0"
"webextension-polyfill": "^0.11.0"
}
}
16 changes: 0 additions & 16 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 4 additions & 6 deletions src/popup/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { getContext as getCtx } from 'svelte';
import { type Readable, readable } from 'svelte/store';

import Connection from '../comms/child';
import type { UrlData } from '../state';
import StateDatabase from '../store';
import type { UrlData, Store } from '../store';

/**
* context object for svelte app
Expand All @@ -14,11 +13,10 @@ export type Context = {
urls: Readable<UrlData[]>;
};

export function makeContext(name: string) {
const db = new StateDatabase();
export function makeContext(name: string, store: Store) {
const port = new Connection(name);
const urls = readable<UrlData[]>([], (set) => {
db.subscribe('urls', (data) => {
const urls = readable<UrlData[]>(store.urls, (set) => {
store.subscribe<UrlData[]>('urls', (data) => {
set(data);
});
});
Expand Down
7 changes: 5 additions & 2 deletions src/popup/main.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import '../css/reset.css';

import { Store } from '../store';
import App from './App.svelte';
import { makeContext } from './context';

start();

function start() {
const context = makeContext('popup');
async function start() {
const store = new Store();
await store.init();
const context = makeContext('popup', store);

new App({
context,
Expand Down
119 changes: 0 additions & 119 deletions src/state.ts

This file was deleted.

56 changes: 33 additions & 23 deletions src/store.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,43 @@
import Dexie, { liveQuery, type PromiseExtended, type Subscription, type Table } from 'dexie';
import { v4 as uuid } from 'uuid';
import browser from 'webextension-polyfill';

import type { UrlData } from './state';
export type UrlData = {
id: string;
url: string;
};

//
// Declare Database
//
export default class StateDatabase extends Dexie {
public urls!: Table<UrlData, string>;
export class Store {
private _urls: { id: string; url: string }[] = [];

public constructor() {
super('StateDatabase');
this.version(2).stores({
urls: 'id,url',
});
constructor(private engine = browser.storage.local) {}

get urls() {
return this._urls;
}

public subscribe<T = UrlData>(tableName: 'urls', callback: (values: T[]) => void): Subscription;
public subscribe<T = UrlData>(tableName: 'urls', callback: (values: T) => void, id: string): Subscription;
public subscribe<T = UrlData>(tableName: 'urls', callback: (values: T | T[]) => void, id?: string) {
const table = this[tableName];
public async init() {
this._urls = await this.getItem<{ id: string; url: string }[]>('urls', this._urls);
}

if (id) {
return liveQuery(() => table.get({ [table.schema.primKey.name]: id }) as PromiseExtended<T>).subscribe({
next: callback,
});
}
public async addUrl(url: string) {
this._urls.push({ id: uuid(), url });
await this.persistUrls();
}

return liveQuery(() => table.toArray() as PromiseExtended<T[]>).subscribe({
next: callback,
public subscribe<T = undefined>(key: 'urls', callback: (value: T) => void) {
this.engine.onChanged.addListener((changes) => {
if (key in changes) {
callback(changes[key].newValue);
}
});
}

private async persistUrls() {
await this.engine.set({ urls: this._urls });
}

private async getItem<T = unknown>(key: string, value: T) {
const store = await this.engine.get({ [key]: value });
return store[key] as T;
}
}
27 changes: 5 additions & 22 deletions src/worker.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
import { v4 as uuid } from 'uuid';
import browser from 'webextension-polyfill';

import Connection from './comms/main';
import { addEventListener, type DomContentLoadedData } from './events';
import { injectScript } from './libs/utils';
import logger from './logger';
import createStateMachine from './state';
import StateDatabase from './store';
import { Store } from './store';

start();

async function start() {
const db = new StateDatabase();
const state = createStateMachine();
await restoreState(db, state);

// persist state changes
state.subscribe(async ({ context }) => {
const { urls } = context;
await db.urls.clear();
await db.urls.bulkPut(urls);
});
const store = new Store();
await store.init();

// listen for messages from popup
const popup = new Connection('popup');
Expand All @@ -37,8 +27,8 @@ async function start() {
});

// listen for store_url messages
widget.addListener(({ data }) => {
state.send({ type: 'INSERT_URL', id: uuid(), url: data });
widget.addListener(async ({ data }) => {
await store.addUrl(data);
}, 'store_url');

// inject content script into third party pages
Expand All @@ -55,11 +45,4 @@ async function start() {
await injectScript(tabId, 'content/main.js');
logger.debug('CONTENT_SCRIPT_INJECTED', tabId, url);
});

state.send({ type: 'START' });
}

async function restoreState(db: StateDatabase, state: ReturnType<typeof createStateMachine>) {
const urls = await db.urls.toArray();
state.send({ type: 'RESTORE_STATE', urls });
}

0 comments on commit 4b9a4bd

Please sign in to comment.