Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/radfish/Application.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Application, IndexedDBMethod, LocalStorageMethod } from './index';

describe ('Application', () => {
describe('Application', () => {
describe('storage', () => {
it('should return the storage method', () => {
// IndexedDB Storage application
Expand Down
6 changes: 6 additions & 0 deletions packages/radfish/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-typescript',
],
};
135 changes: 114 additions & 21 deletions packages/radfish/index.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,121 @@
import { setupWorker } from "msw/browser";
import { Store, Schema, LocalStorageConnector, IndexedDBConnector } from './storage';
import { StorageMethod, IndexedDBMethod, LocalStorageMethod } from "./on-device-storage/storage";

class EventEmitter extends EventTarget {}
const registerServiceWorker = async (url) => {
if ("serviceWorker" in navigator) {
try {
const registration = await navigator.serviceWorker.register(url, {
scope: "/",
});
if (registration.installing) {
console.log("Service worker installing");
} else if (registration.waiting) {
console.log("Service worker installed");
} else if (registration.active) {
console.log("Service worker active");
}
return registration;
} catch (error) {
console.error(`Registration failed with ${error}`);
}
}
};

export class Application {
constructor(options = {}) {
this.emitter = new EventEmitter();
this.emitter = new EventTarget();
this.serviceWorker = null;
this.isOnline = navigator.onLine;
this._options = options;
this._initializationPromise = null;

// Register event listeners
this._registerEventListeners();

// Initialize everything
this._initializationPromise = this._initialize();
}

/**
* Initialize the application stores and collections
* @private
*/
async _initialize() {
// Initialize stores
this.stores = null;
if (this._options.stores && typeof this._options.stores === 'object') {
this.stores = {};

// Initialize each store and its connector
const storeInitPromises = [];

for (let storeKey in this._options.stores) {
const store = this._options.stores[storeKey]
let name = store.name || storeKey;
let connector = store.connector;

if (!connector) {
throw new Error(`Store ${name} is missing a connector`);
}

// Create the store
this.stores[name] = new Store({name, connector});

// Initialize the connector
const initPromise = this.stores[name].connector.initialize()
.then(async () => {
// Add collections if they exist
if (store.collections) {
const collectionPromises = [];

for (let collectionKey in store.collections) {
let collection = store.collections[collectionKey];
let schema = collection.schema;

// Handle schema configuration object
if (typeof schema === 'object' && !(schema instanceof Schema)) {
// If schema doesn't have a name, use the collectionKey as default
if (!schema.name) {
schema = { ...schema, name: collectionKey };
}
schema = new Schema(schema);
}

// Add collection (might be async for IndexedDBConnector)
const addCollectionPromise = Promise.resolve(
this.stores[name].connector.addCollection(schema)
);
collectionPromises.push(addCollectionPromise);
}

// Wait for all collections to be added
return Promise.all(collectionPromises);
}
});

storeInitPromises.push(initPromise);
}

// Wait for all stores to be initialized
await Promise.all(storeInitPromises);
console.log(storeInitPromises[0])
console.log(this.stores.weatherSurvey.connector.collections);
}

// Dispatch the init event
this._dispatch("init");

return true;
}

get storage() {
if (!this._options.storage) {
return null;
}

console.warn('Deprecation: Please update to use Connectors instead of StorageMethod: https://nmfs-radfish.github.io/radfish/design-system/storage');

if (!(this._options.storage instanceof StorageMethod)) {
console.warn('Please update the storage method to be an instance of StorageMethod');

switch (this._options.storage?.type) {
case "indexedDB": {
return new IndexedDBMethod(
Expand Down Expand Up @@ -64,7 +157,11 @@ export class Application {
this._options?.mocks?.handlers,
this._options?.serviceWorker?.url
);
this._dispatch("ready", { worker });

this.serviceWorker = worker;

// Only dispatch ready event if worker is successfully installed or if no service worker was configured
this._dispatch("ready");
});

const handleOnline = (event) => {
Expand All @@ -83,21 +180,17 @@ export class Application {
async _installServiceWorker(handlers, url) {
if (!url) return null;
console.info("Installing service worker");
const worker = setupWorker(...((await handlers)?.default || []));
const onUnhandledRequest = "bypass";

this.serviceWorker = worker;

worker
.start({
onUnhandledRequest,
serviceWorker: {
url: url,
},
})
.then(() => {
console.debug("Service worker installed");
});

try {
const registration = await registerServiceWorker(url);

console.debug("Service worker installed and started successfully");
// return worker;
return registration;
} catch (error) {
console.error("Failed to install service worker:", error);
return null;
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions packages/radfish/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import('jest').Config} */
const config = {
testEnvironment: 'jsdom',
};

module.exports = config;
12 changes: 10 additions & 2 deletions packages/radfish/package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "@nmfs-radfish/radfish",
"version": "1.0.0",
"version": "1.1.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "jest"
},
"keywords": [],
"author": "",
Expand All @@ -13,5 +13,13 @@
"dexie": "4.0.x",
"msw": "^2.3.1",
"react": "^18.3.1"
},
"devDependencies": {
"@babel/core": "^7.26.8",
"@babel/preset-env": "^7.26.8",
"@babel/preset-typescript": "^7.26.0",
"babel-jest": "^29.7.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0"
}
}
Loading