React Native Realm data not persisted - react-native

I am using realm.write however my default.realm file is not being updated. I have also added another object to my schema and I can use this whilst developing my React Native app, but the default.realm file is not updated to include this new object.
I can confirm it is not being saved by opening default.realm in Realm Browser. Also, after turning my mac on this morning (after shutting down last night) and running my React Native app then data was not in my Realm when I tried to access it.
Example code:
#queries.js
import Realm from 'realm'
// Define your models and their properties
class Car {}
Car.schema = {
name: 'Car',
primaryKey: 'id',
properties: {
id: 'int',
make: 'string',
model: {type: 'string', optional: true}
}
}
class Person {}
Person.schema = {
name: 'Person',
properties: {
id: 'int',
name: 'string'
}
}
// Get the default Realm with support for our objects
let realm = new Realm({schema: [Car, Person], schemaVersion: 3});
class Queries {
async syncCars()
{
try {
let responsePromise = await fetch(`http://api.localhost.com:3000/v1/cars?auth_token=xxx`).catch(function(error) {
console.log('There has been a problem with your fetch operation: ' + error.message);
});
let responseJson = await responsePromise.json();
realm.write(() => {
responseJson.forEach((values) => {
realm.create('Car', values, true);
});
});
}
catch(error) {
console.log("error " + error);
}
}
}
export default new Queries
and then in my component code I have:
import Queries from './queries'
await Queries.syncCars();

As Kristian Dupont pointed out in the comments above, I was looking at the wrong file.
Following this answer I used realm.path in the Chrome debugger console and found the correct default.realm in a path that included /Library/Developer/CoreSimulator/Devices/. I'm not sure why OSX finder wasn't able to find this file. I'm unsure why a default.realm file was also created in my React Native directory but I have since deleted this file to avoid confusion and have had no further issues.

Related

Realm JS + React-Native: “no internal field” when creating a new object

I’m using the WildAid O-FISH post to create a similar project using realm JS react-native SDK with flexible sync.
I’m trying to create a Photo object but I get a “no internal field” error.
Here’s my Photo model
export class Photo extends Realm.Object {
_id;
user;
result;
picture;
pictureUrl;
annotation;
userInputs;
createdAt;
projectId;
static schema = {
name: "Photo",
properties: {
_id: "objectId",
user: "string",
result: "Result?",
picture: "data?",
pictureUrl: "string?",
annotation: "string?",
userInputs: "{}?",
createdAt: "date",
projectId: "objectId",
},
primaryKey: "_id",
};
}
export const ResultSchema = {
name: "Result",
embedded: true,
properties: {
traits: "{}?",
errors: "{}?",
score: "{}?",
},
};
And here’s how I’m creating a new photo
// Write transaction omitted
// Read a local image and convert it to base64
const picture = await readFile(path, "base64");
// Convert the base64 image to Buffer
const binaryBuffer = Buffer.from(picture, "base64");
const newPhoto = realm.create("Photo", {
_id: new Realm.BSON.ObjectId(),
user: user.profile.email,
userInputs: section.userInputs,
createdAt: new Date(),
projectId: new Realm.BSON.ObjectId(projectId),
annotation: "someString",
picture: binaryBuffer,
})
I feel like the problem might come from the picture property. I read in the doc that data type maps to ArrayBuffer which is what a Buffer is. Maybe it’s another field causing the problem but I really don’t know which one.
Thanks in advance!

cannot use the find functions using sequelize-typescript

I have setup passport and sequelize-typescript for my project. In the passport setup, I use a strategy for example google like this:
passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_AUTH_CLIENT_ID,
clientSecret: process.env.GOOGLE_AUTH_CLIENT_SECRET,
callbackURL: process.env.GOOGLE_AUTH_CALLBACK_URL,
profileFields: ['id', 'displayName', 'photos', 'email'],
enableProof: true
},
function(accessToken, refreshToken, profile, done) {
console.log(profile)
const { name, email, picture } = profile._json;
User.findOne({where: {id: profile.id}})
.then(user => {
console.log(user)
if(user === null) {
const { name, email, picture } = profile._json;
// new User({
// id: profile.id,
// name: name,
// email: email,
// pictureUrl: picture,
// })
}
})
done(null, profile)
}
)
)
When I try to use functions such as findOrCreate() or findOne(), I receive a typescript error that says:
[ERROR] 23:29:01 ⨯ Unable to compile TypeScript:
src/passport_strategies.ts:45:18 - error TS2339: Property 'findOne' does not exist on type 'typeof User'.
45 User.findOne({where: {id: profile.id}})
I also get the same error for the part commented out in the first code snippet. The model user I have created is declared like this:
export class User extends Model<User> {} (It has the columns set in the file) Model being imported from sequelize-typescript
Here is where sequelize is created:
export const sequelize = new Sequelize({
"username": c.username,
"password": c.password,
"database": c.database,
"host": c.host,
dialect: 'postgres',
storage: ':memory:',
models: [__dirname + '/models']
});
I tried checking other examples that are on the internet but they all have the same setup and I couldn't figure out why I'm getting this error. Not sure if this helps at all but I'm using postgres dialect.
I suspect that it is a version mismatch.
sequelize-typescript#2 is for sequelize#6.2>= and sequelize-typescript#1 is for sequelize#5>=.
I also suggest for educational purposes to implement typescript with sequelize without the use of the sequelize-typescript package just for understanding the need of the package itself. https://sequelize.org/master/manual/typescript.html
Also just in case with all the respect, i point that #Table is needed if you are using the latest version.

Preload / Pre-populate PouchDB in React Native Application

Is it possible to preload / pre-populate a database in my React Native application and then the first time it is run, simply do a sync? I already have most, if not all of the database information before the app is distributed, it would be awesome if it just had to do a quick sync when the app is run. Any ideas how I would go about doing that?
I found this - https://pouchdb.com/2016/04/28/prebuilt-databases-with-pouchdb.html but it doesn't mention React Native
Using:
pouchdb-find: ^7.0.0
pouchdb-react-native: ^6.4.1
react: 16.3.1
react-moment: ^0.7.9
react-native: ~0.55.2
Thanks for any pointers.
Update Here is the code I'm using to try the loading of a dump file. This code exists in /screens/Home.js
The dump file is located in /client/dbfile/database.txt
var db = new PouchDB("cs1");
db.get("_local/initial_load_complete")
.catch(function(err) {
console.log("loading dumpfile");
if (err.status !== 404) {
// 404 means not found
throw err;
}
db.load("/client/dbfile/database.txt").then(function() {
return db.put({ _id: "_local/initial_load_complete" });
});
})
.then(function() {
// at this point, we are sure that
// initial replication is complete
console.log("loading is complete!");
return db.allDocs({ include_docs: true });
})
.then(
function(res) {
// display all docs for debugging purposes (empty)
console.log(res);
});
this.localDB = db;
When this runs my console displays this - showing there have been 0 rows added.
Object {
"offset": 0,
"rows": Array [],
"total_rows": 0,
}
Possible Unhandled Promise Rejection (id: 0):
Object {
"message": undefined,
"name": "unknown",
"status": 0,
}
In my project I have couple of db docs I distribute with app (translations JSON is the one good example).
So at app init I just try to read translations doc from db, if there is none - I import content from js module and store in db.
Then translations changes just being replicated from server to local db.
//transmob.js
const transMobFile = {
//content goes here
);
module.exports = transMobFile
//dbInit.js
import transMobFile from 'data/transMob';
..
PDB.getDoc('TransMob')
.then((doc)=> {
if (!doc) {
global.locales = transMobFile.localesMob; // locales
global.translations = transMobFile.langMob; // translations
return PDB.saveDoc('TransMob', transMobFile)
}
})
You can use react-native-fs to load a file from /android/app/src/main/assets. Just put the file into the assets folder and read it with RNFS.readFileAssets.
import PouchDB from 'pouchdb-core';
PouchDB
.plugin(require('pouchdb-find'))
.plugin(require('pouchdb-load'));
import RNFS from 'react-native-fs';
const localDB = new PouchDB("cs1", {adapter: 'asyncstorage'});
localDB.get("_local/initial_load_complete")
.catch(function(err) {
console.log("loading dumpfile");
if (err.status !== 404) {
// 404 means not found
throw err;
}
RNFS.readFileAssets('yourdb.txt', 'utf8')
.then((contents) => {
localDB.load(contents).then(function() {
return localDB.put({ _id: "_local/initial_load_complete" });
}).then(function() {
// at this point, we are sure that
// initial replication is complete
console.log("loading is complete!");
return localDB.allDocs({ include_docs: true }).then(
function(res) {
// display all docs for debugging purposes (empty)
console.log(res);
});
}, function(err) {
console.log(err);
});
})
})
You'll need to rebuild your project, reloading is not sufficient.
My project crashes when I attempt to load a 30MB file, so I probably will split it into a few smaller files. Check out https://github.com/pouchdb-community/pouchdb-load to see how this works if needed.
I found that the db.load() function from the pouchdb-load module requires a URL. I was pointing it to a file path on the device's filesystem. I placed my database.txt file on my server, changed it to use the url and it worked.
In my mind this isn't ideal because if they install the app and have slow wireless, it still has to pull the file from the server. It is still much faster than performing a full-on replicate when the app opens for the first time however.

react-native - require() must have a sing string literal argument

I'm writing a sampler app in React-Native using Expo and have run into the follow error:
react-native - require() must have a sing string literal argument
Pre-recorded samples are played called like this:
const SAMPLES = [
{ name: 'air horn', uri: require('../samples/air_horn.mp3') },
{ name: 'rim shot', uri: require('../samples/rimshot.mp3') },
]
playSample = (uri) => {
const { soundObject, status } = Expo.Audio.Sound.create(
uri,
{ shouldPlay: true }
)
}
It's somewhat based off the Expo documentation and works fine. However, I also want the user to record their own samples, which means it's coming from a custom URL:
playCustomSample = () => {
const customSample = this.props.navigation.state.params
? require(this.props.navigation.state.params.custom.toString())
: require('./samples/blank.mp3')
try {
const { soundObject, status } = Expo.Audio.Sound.create(
customSample,
{ shouldPlay: true }
)
} catch(error) {
console.log('ERROR:', error)
}
When I log the custom param I'm being passed by navigation, it's there. So I get that I'm doing it conceptually wrong--that require() requires a string, but I'm not going to know the name/location of the file until it is recorded.
How would I get access to the audio file without knowing the link ahead of time so I can include it?
Also, I don't have access to a Mac so ejecting it from Expo, so using something like react-native-audio or react-native-sound isn't an option.

Worklight 5.0.6 JSONStore with Sync error

I try to init JSONStore Sync with Adapter in Worklight 5.0.6 like below:
var usersSearchFields = {"age":"integer","name.demo":"string"},
usersAdapterOptions = {
name: 'user',
replace: 'updateUser',
remove: 'deleteUser',
add: 'addUser',
load: {
procedure: 'getUsers',
params: [],
key: 'users'
},
accept: function (data) {
return (data.status === 200);
}
};
var collections = {
users : {
searchFields : usersSearchFields,
adapter : usersAdapterOptions
}
};
var options = {
username: 'carlos',
password: '123'
};
var usersCollection=WL.JSONStore.init(collections, options)
.then(function (res) {
logMessage('Collection has been initialized');
})
.fail(function (errobject) {
WL.Logger.debug(errobject.toString());
});
It runs successfully in the first time but after i exit app then return, it gets error:
*"PROVISION_TABLE_SEARCH_FIELDS_MISMATCH"*
Anyone can help me please? Thank you very much.
It looks like the following known issue:
PM85364: JSONSTORE ERROR AFTER FIRST LAUNCH ON ANDROID WITH '.' IN SEARCH FIELDS.. To fix it upgrade to the 5.0.6.1 Fix Pack (Source).
Typically:
-2 PROVISION_TABLE_SEARCH_FIELDS_MISMATCH
You cannot change search fields without calling destroy or removeCollection and init or initCollection with the new search fields. This error can happen if you change the name or type of the search field. For example: {key: 'string'} to {key: 'number'} or {myKey: 'string'} to {theKey: 'string'}.
The documentation is here. I also recommend this StackOverflow answer on JSONStore debugging.
This fixes issues like the one you're facing:
Reset the Simulator or Emulator and/or call WL.JSONStore.destroy().