npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

expo-sqlite-orm

v2.2.0

Published

Simple orm for expo

Downloads

902

Readme

Expo SQLite ORM

Build Status

It is a simple ORM utility to use with expo sqlite

Warn: it works only on iOS and Android. Web is not supported (SEE)

Install

yarn add expo-sqlite-orm

Basic usage

You need to provide 3 things:

  • databaseName: Name of the database to be created/used by expo SQLite
  • tableName: The name of the table
  • columnMapping: The columns for the model and their types
    • Supported options: type, primary_key, autoincrement, not_null, unique, default
import { Text } from '@components'
import { ColumnMapping, columnTypes, IStatement, Migrations, Repository, sql } from 'expo-sqlite-orm'
import React, { useMemo, useState } from 'react'
import { ScrollView } from 'react-native'

import { RootTabScreenProps } from '../../navigation/types'

/**
 * Expo Sqlite ORM V2 - Usage example
 */

interface Animal {
  id: number
  name: string
  color: string
  age: number
  another_uid?: number
  timestamp?: number
}

const columMapping: ColumnMapping<Animal> = {
  id: { type: columnTypes.INTEGER },
  name: { type: columnTypes.TEXT },
  color: { type: columnTypes.TEXT },
  age: { type: columnTypes.NUMERIC },
  another_uid: { type: columnTypes.INTEGER },
  timestamp: { type: columnTypes.INTEGER, default: () => Date.now() },
}

const statements: IStatement = {
  '1662689376195_create_animals': sql`
        CREATE TABLE animals (
          id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
          name TEXT NOT NULL,
          color TEXT,
          age NUMERIC,
          another_uid TEXT UNIQUE,
          timestamp INTEGER
        );`,
}

const databaseName = 'dbName'

export function MeusServicosScreen({ navigation }: RootTabScreenProps<'MeusServicos'>) {
  const [animals, setAnimals] = useState<Animal[]>([])
  const migrations = useMemo(() => new Migrations(databaseName, statements), [])

  const animalRepository = useMemo(() => {
    return new Repository(databaseName, 'animals', columMapping)
  }, [])

  const onPressRunMigrations = async () => {
    await migrations.migrate()
  }

  const onPressReset = async () => {
    await migrations.reset()
    setAnimals([])
  }

  const onPressInsert = () => {
    animalRepository.insert({ name: 'Bob', color: 'Brown', age: 2 }).then((createdAnimal) => {
      console.log(createdAnimal)
    })
  }

  const onPressQuery = () => {
    animalRepository.query({ where: { age: { gte: 1 } } }).then((foundAnimals) => {
      console.log(foundAnimals)
      setAnimals(foundAnimals)
    })
  }

  return (
    <ScrollView>
      <Text type="text2" onPress={onPressRunMigrations}>
        Migrate
      </Text>
      <Text type="text2" onPress={onPressReset}>
        Reset Database
      </Text>
      <Text type="text2" onPress={onPressInsert}>
        Insert Animal
      </Text>
      <Text type="text2" onPress={onPressQuery}>
        List Animals
      </Text>
      <Text type="text2">{JSON.stringify(animals, null, 1)}</Text>
    </ScrollView>
  )
}

Database operations

Insert a record

const props: Animal = {
  name: 'Bob',
  color: 'Brown',
  age: 2
}

animalRepository.insert(props)

Find a record

const id = 1
animalRepository.find(id)

or

animalRepository.findBy({ age: { equals: 12345 }, color: { contains: '%Brown%' } })

Update a record

const props = {
  id: 1 // required
  age: 3
}

animalRepository.update(props)

Destroy a record

const id = 1
animalRepository.destroy(id)

Destroy all records

animalRepository.destroyAll()

Query

const options = {
  columns: 'id, name',
  where: {
    id: { in: [1, 2, 3, 4] },
    age: { gt: 2, lt: 10 }
  },
  page: 2,
  limit: 30,
  order: { name: 'ASC' }
}

animalRepository.query(options)

The property page is applied only if you pass the limit as well

Where operations

  • equals: =,
  • notEquals: <>,
  • lt: <,
  • lte: <=,
  • gt: >,
  • gte: >=,
  • contains: LIKE
  • in: IN (?)
  • notIn: NOT IN (?)

Data types

  • INTEGER
  • FLOAT
  • TEXT
  • NUMERIC
  • DATE
  • DATETIME
  • BOOLEAN
  • JSON

How to exec a sql manually?

myCustomMethod() {
  const sql = 'SELECT * FROM table_name WHERE status = ?'
  const params = ['active']
  return animalRepository.databaseLayer.executeSql(sql, params).then(({ rows }) => rows)
}

Bulk insert or replace?

const itens = [{id: 1, color: 'green'}, {id: 2, color: 'red'}]
animalRepository.databaseLayer.bulkInsertOrReplace(itens).then(response => {
  console.log(response)
})

Migrations

Execute the migrations

import * as SQLite from 'expo-sqlite/legacy'
import { Migrations, sql } from 'expo-sqlite-orm'

const statements: IStatement = {
  '1662689376195_init': sql`CREATE TABLE animals (id TEXT, name TEXT);`,
  '1662689376196_add_age_column': sql`ALTER TABLE animals ADD age NUMERIC;`,
  '1662689376197_add_color_column': sql`ALTER TABLE animals ADD color TEXT;`
}

const migrations = new Migrations('databaseName', statements)
await migrations.migrate()

Reset the database

const migrations = new Migrations('databaseName', statements)
await migrations.reset()

TODO

  • [x] Add basic typescript support
  • [x] Make it easier to use with react-hooks
  • [x] Complete typescript autocomplete for where queries
  • [x] Add migrations feature
  • [x] Create a singleton to handle the instances easily
  • [x] Allow IN statement
  • [ ] Allow OR statement

Changelog

  • 1.5.0 - Return unlimited rows if page is not specified in the query params
  • 1.6.0 - Make autoincrement property to be optional
  • 2.0.0 - BREAKING CHANGE
    • Add typescript support
    • Remove BaseModel in favor of Repository (Easier to use with react-hooks)
    • Add migrations support

Development

docker-compose run --rm bump         # patch
docker-compose run --rm bump --minor # minor

git push
git push --tags

Test

docker-compose run --rm app install
docker-compose run --rm app test

Working examples

Author

License

This project is licensed under MIT License