Can you run a custom script that affects SQLite storage in react-native - react-native

I am creating an app that will save data on the local phone memory with react-native-sqlite-storage.
I want to make a script that will create a database (if it does not exist), create the necessary tables, and then populate those tables with mock data (basically, a seed script). I plan on adding a script to my package.json to seed this data, something like
{
....
"scripts": {
....
"seed": "ts-node index.ts"
}
}
Where index.ts will contain the necessary seeding script, something like:
// import react-native-sqlite-storage
const seedDatabase = () => {
// Populate the data ...
}
seedDatabase();
But I am uncertain if this would work. Will it work? If not, is there a way to seed data?

You can use this package to create and populate your database https://www.npmjs.com/package/sqlite3
then just run this to copy it to your device
adb push your_db.db /storage/emulated/0/your_db.db
In your react native code just use that file https://github.com/andpor/react-native-sqlite-storage#importing-a-pre-populated-database

Related

expo-sqlite using existing local database

I am using expo and react native to build a truth or dare app. I want to store hundreds of truth or dare questions to feed to the user. I figured SQLite would be most efficient for this (and allow offline usage). I created the db using the DB Browser (SQLite) tool and created a single table named "Prompts" with several rows.
Here's the code I use for opening and performing a transation:
import database from "../assets/db/TruthOrDareDB.db"
const db = SQLite.openDatabase(database);
console.log(db);
db.transaction((tx) => {
console.log("transaction test");
tx.executeSql(
`
SELECT *
FROM Prompts;`,
[],
(_, result) => console.log("executeSql"),
(transaction, error) => console.log(error)
);
});
The openDatabase call returns a webSQLDatabase obj. I recieve the "transaction" log to the console but I do not get the "executeSql" log or an error. I would expect to get at least one, why am I not?
And as far as design do you agree that SQLite is the best for my goal?

How to build individual component chunks with Vite to load with defineAsyncComponent

I'm not sure this is even possible, but it looks like some of the moving parts are there.
GOAL:
Create a library of single file Vue 3 components that will compile into separate chunks using Vite, and be dynamically/async loaded at runtime. The app itself will load, then load up a directory of individually chunk'd elements to put in a toolbox, so afterward each element could be updated, and new ones could be added by putting new chunks in the same path.
So far, I can create the separate chunks within the vite.config as follows:
...
build: {
rollupOptions: {
output: {
...buildChunks()
}
}
}
...
The buildChunks function iterates over SFC files in the ./src/toolbox path and returns an object like...
{
'toolbox/comp1':['./src/toolbox/comp1.vue'],
'toolbox/comp2':['./src/toolbox/comp2.vue'],
'toolbox/comp3':['./src/toolbox/comp3.vue'],
...
}
This all works, but I'm not sure how to make that next leap where the server code dynamically loads all of those generated chunk files without explicitly listing them in code. Also, since the Vite build adds an ID in the file name (e.g. comp.59677d29.js) on each build, referencing the actual file name in the import can't be done explicitly.
So far what I've considered is using defineAsyncComponent(()=>import(url)) to each of the files, but I'd need to generate a list of those files to import...which could be done by building a manifest file at build time, I guess.
Any suggestions? Is there a better approach?

Serverless offline CUSTOM: using external file AND internally added variables?

I am having a weird problem where I need to use Serverless "custom:" variables read both from an external file and internally from the serverless.yml file.
Something like this:
custom: ${file(../config.yml)}
dynamodb:
stages:
-local
..except this doesn't work. (getting bad indendation of a mapping entry error)
I'm not sure if that's possible and how do you do. Please help :)
The reason is dynamodb local serverless plugin won't work if it's config is set in the exteranl file. But we use the external file config in our project and we don't wanna change that.
So I need to have the dynamodb config separate in the serverless.yml file just not sure the proper way to do it.
Please someone help :) Thanks
You will either have to put all your vars in the external file or import each var from the custom file one at the time as {file(../config.yml):foo}
However... you can also use js instead of yml/json and create a serverless.js file instead allowing you to build your file programically if you need more power. I have fairly complex needs for my stuff and have about 10 yml files for all different services. For my offline sls I need to add extra stuff, modify some other so I just read the yaml files using node, parse them into json and build what I need then just export that.
Here's an example of loading multiple configs and exporting a merged one:
import { readFileSync } from 'fs'
import yaml from 'yaml-cfn'
import merge from 'deepmerge'
const { yamlParse } = yaml
const root = './' // wherever the config reside
// List of yml to read
const files = [
'lambdas',
'databases',
'whatever'
]
// A function to load them all
const getConfigs = () =>
files.map((file) =>
yamlParse(readFileSync(resolve(root, `${file}.yml`), 'utf8'))
)
// A function to merge together - you would want to adjust this - this uses deepmerge package which has options
const mergeConfigs = (configs) => merge.all(configs)
// No load and merge into one
const combined = mergeConfigs(getConfigs())
// Do stuff... maybe add some vars just for offline for ex
// Export - sls will pick that up
export default combined

How to run installation script only once in react-native

I have created a react native app.
For this app one simple database installation script should run for only one time.
It should happen when the app is installed.
Is there any better way to add a condition or any function that will run this installation code only once while installation.
Usually, databases have a special feature that called migrations. It`s helpful when you trying migrate your database schemas from one version to another. But also, you can use it like pre-fill script for your database on initial step.
Also, you can have a special script, that can pre-fill your database on initial step. But in this case, you should properly change implementation depend on each new your database scheme.
For achieve 2, you can have some variable in your database (or key-value storage like AsyncStorage) like pre-filled that indicate state of your database. When you start application check if this value is false and start database pre-filling, otherwise just use your already prepared data.
You should use useEffect to execute a piece of your code once.
Import it like this;
import React, { useEffect } from 'react'
Then u can use it to execute once or when a fuction is called;
useEffect(
async () => {
const allItems = await fetchSomeData()
setStatus({ loading: false, dataList: allItems})
},
[
//when leave this array empty this above script will execute once
],
)

Accessing vuex modules data from within a plugin

I am moving some data from the vuex store into its own module. Most of it works great, but I'm running into an issue that I can't seem to fix.
I have a plugin that I add, and that plugin also needs access to the store.
So at the top of that plugin, we import the store:
import store from '../store/store';
great - further down that plugin, I'm accessing the data of the store in a method that I expose on the service:
hasPermission(permission) {
return (store.state.authorization.permissions.indexOf(permission) >= 0);
}
Please note authorization is now a seperate module, and is no longer part of the root state object.
now the funny thing is that the above will return an error telling me indexOf is not a function.
When I add the following, however:
hasPermission(permission) {
console.log('Validating permission ' + permission);
console.log(store.state);
return (store.state.authorization.permissions.indexOf(permission) >= 0);
}
I notice that (1) the output to console is what I expect it to be, and (2), I'm not getting the error, and my menu structure dynamically builds as expected...
so I'm a bit confused to say the least...
authorization.permissions is updated each time a user authenticates, logs out, or chooses another account to work on; in these cases we fetch updated permissions from the server and commit it to the store, so we can build our menu structure based on up-to-date permissions. Works pretty good, but I'm not sure I understand why this fails to be honest.
The plugin is created as follows in the install:
Vue.prototype.$security = new Vue(
...
methods: {
hasPermission: function(permission) {
...
}
}
...
);