Skip to content

Instantly share code, notes, and snippets.

@sidferreira
Last active June 14, 2023 14:50
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save sidferreira/2b6b640e25544d601f311e35e430bce0 to your computer and use it in GitHub Desktop.
Save sidferreira/2b6b640e25544d601f311e35e430bce0 to your computer and use it in GitHub Desktop.
WatermelonDB preloaded db

This is the basic structure I'm using in an app.

getDatabasePath will handle any detail on unzip, copy, etc,

index will do all the usual dirty work, including withDatabase that won't explode if the database is missing

WatermelonProvider to cover original one til the DB is ready

import RNFS from "react-native-fs";
// Currently android will add `.db` to file name...
async function getDatabasePath(dbName) {
let dbPath = `${RNFS.DocumentDirectoryPath}/${dbName}`;
const exists = await RNFS.exists(dbPath.concat(".db"));
if (!exists) {
try {
await RNFS.copyFileAssets(dbName.concat(".db"), dbPath.concat(".db"));
} catch (e) {
console.log(">>> getDatabasePath error", e);
}
}
return dbPath;
}
export default getDatabasePath;
import RNFS from 'react-native-fs';
import * as RNZIP from 'react-native-zip-archive
async function getDatabasePath(dbName) {
let sanitizedDbName = dbName;
if (!sanitizedDbName.endsWith(".db")) {
sanitizedDbName = sanitizedDbName.concat(".db");
}
let dbPath = `${RNFS.DocumentDirectoryPath}/${sanitizedDbName}`;
const exists = await RNFS.exists(dbPath);
if (!exists) {
const assetPath = `${RNFS.MainBundlePath}/${sanitizedDbName.replace(
".db",
".zip"
)}`;
const existsZip = await RNFS.exists(assetPath);
if (existsZip) {
const tmpPath = `${RNFS.DocumentDirectoryPath}/tmp`;
await RNZIP.unzip(assetPath, tmpPath);
await RNFS.moveFile(`${tmpPath}/${sanitizedDbName}`, dbPath);
await RNFS.unlink(tmpPath);
}
}
return dbPath;
}
export default getDatabasePath;
async function getDatabasePath(dbName) {
let fullDbName = dbName;
if (!fullDbName.endsWith('.db') && !fullDbName.includes('?')) {
fullDbName = fullDbName.concat('.db');
}
let dbPath = dbName.includes(process.cwd())
? fullDbName
: `${process.cwd()}/${fullDbName}`;
return dbPath;
}
export default getDatabasePath;
import getDatabasePath from './getDatabasePath';
const DEFAULT_DATABASE_NAME = 'watermelon';
const promises: { [key: string]: Promise<Database> } = {};
const instances: { [key: string]: Database } = {};
async function init(dbName: string = DEFAULT_DATABASE_NAME) {
const dbPath = await getDatabasePath(dbName);
const adapter = new SQLiteAdapter({
schema,
migrations,
dbName: dbPath,
});
const instance = new Database({
adapter,
modelClasses,
actionsEnabled: true,
});
instances[dbName] = instance;
// sync();
return db;
}
export const getDatabase = async (
dbName: string = DEFAULT_DATABASE_NAME,
) => {
if (!promises[dbName]) {
promises[dbName] = init(dbName);
}
const instance = await promises[dbName];
return instance;
};
// For _very_ specific uses
export const getDatabaseSync = (altDbName: string = DEFAULT_DATABASE_NAME) => {
return instances[altDbName];
};
// custom withDatabase to handle the possibility of not having the database just yet...
export type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
export const withDatabase = <T extends DatabaseProp>(
Wrapped: React.ComponentType<T>,
) => {
const WrappedComponent: React.ComponentType<Omit<T, DatabaseProp>> = (
props,
) => {
const database = useDatabase();
if (!database) {
return <View />;
}
return <Wrapped {...(props as T)} database={database} />;
};
return WrappedComponent;
};
import React, { ReactChild } from 'react';
import { Database } from '@nozbe/watermelondb';
import { getWatermelon } from 'app/utils/DBWatermelonOld/DBWatermelonOld';
import DatabaseProvider from '@nozbe/watermelondb/DatabaseProvider';
const WatermelonProvider = (props) => {
const watermelonRef = React.useRef();
const [database, setDatabase] = React.useState();
if (!watermelonRef.current) {
const promise = getWatermelon();
if (promise) {
watermelonRef.current = promise;
watermelonRef.current.then(setDatabase);
}
}
return database ? <DatabaseProvider database={database} {...props} /> : null;
};
export default WatermelonProvider;
@gabriel-almeida250
Copy link

Ok, @KosolapovR. I haven't had time to implement the solution yet, I had to prioritize other activities, but thanks for the feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment