🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Sign inDemoInstall
Socket

expo-sqlite

Package Overview
Dependencies
Maintainers
27
Versions
155
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

expo-sqlite - npm Package Compare versions

Comparing version

to
15.2.10

8

build/Storage.d.ts
/**
* @hidden
*/
export declare function checkValidInput(...input: unknown[]): void;
/**
* Update function for the [`setItemAsync()`](#setitemasynckey-value) or [`setItemSync()`](#setitemsynckey-value) method. It computes the new value based on the previous value. The function returns the new value to set for the key.

@@ -17,2 +13,3 @@ * @param prevValue The previous value associated with the key, or `null` if the key was not set.

private db;
private readonly awaitLock;
constructor(databaseName: string);

@@ -115,3 +112,5 @@ /**

close(): Promise<void>;
private getDbAsync;
private getDbSync;
private maybeMigrateDbAsync;
private maybeMigrateDbSync;

@@ -122,2 +121,3 @@ /**

private static mergeDeep;
private checkValidInput;
}

@@ -124,0 +124,0 @@ /**

@@ -1,14 +0,3 @@

import { openDatabaseSync } from './index';
/**
* @hidden
*/
export function checkValidInput(...input) {
const [key, value] = input;
if (typeof key !== 'string') {
throw new Error(`[SQLiteStorage] Using ${typeof key} type for key is not supported. Use string instead. Key passed: ${key}`);
}
if (input.length > 1 && typeof value !== 'string' && typeof value !== 'function') {
throw new Error(`[SQLiteStorage] Using ${typeof value} type for value is not supported. Use string instead. Key passed: ${key}. Value passed : ${value}`);
}
}
import AwaitLock from 'await-lock';
import { openDatabaseAsync, openDatabaseSync } from './index';
const DATABASE_VERSION = 1;

@@ -27,2 +16,3 @@ const STATEMENT_GET = 'SELECT value FROM storage WHERE key = ?;';

db = null;
awaitLock = new AwaitLock();
constructor(databaseName) {

@@ -36,4 +26,4 @@ this.databaseName = databaseName;

async getItemAsync(key) {
checkValidInput(key);
const db = this.getDbSync();
this.checkValidInput(key);
const db = await this.getDbAsync();
const result = await db.getFirstAsync(STATEMENT_GET, key);

@@ -47,4 +37,4 @@ return result?.value ?? null;

async setItemAsync(key, value) {
checkValidInput(key, value);
const db = this.getDbSync();
this.checkValidInput(key, value);
const db = await this.getDbAsync();
if (typeof value === 'function') {

@@ -55,3 +45,3 @@ await db.withExclusiveTransactionAsync(async (tx) => {

const nextValue = value(prevValue);
checkValidInput(key, nextValue);
this.checkValidInput(key, nextValue);
await tx.runAsync(STATEMENT_SET, key, nextValue);

@@ -67,4 +57,4 @@ });

async removeItemAsync(key) {
checkValidInput(key);
const db = this.getDbSync();
this.checkValidInput(key);
const db = await this.getDbAsync();
const result = await db.runAsync(STATEMENT_REMOVE, key);

@@ -77,3 +67,3 @@ return result.changes > 0;

async getAllKeysAsync() {
const db = this.getDbSync();
const db = await this.getDbAsync();
const result = await db.getAllAsync(STATEMENT_GET_ALL_KEYS);

@@ -86,3 +76,3 @@ return result.map(({ key }) => key);

async clearAsync() {
const db = this.getDbSync();
const db = await this.getDbAsync();
const result = await db.runAsync(STATEMENT_CLEAR);

@@ -95,6 +85,12 @@ return result.changes > 0;

async closeAsync() {
if (this.db) {
await this.db.closeAsync();
this.db = null;
await this.awaitLock.acquireAsync();
try {
if (this.db) {
await this.db.closeAsync();
this.db = null;
}
}
finally {
this.awaitLock.release();
}
}

@@ -107,3 +103,3 @@ //#endregion

getItemSync(key) {
checkValidInput(key);
this.checkValidInput(key);
const db = this.getDbSync();

@@ -118,3 +114,3 @@ const result = db.getFirstSync(STATEMENT_GET, key);

setItemSync(key, value) {
checkValidInput(key, value);
this.checkValidInput(key, value);
const db = this.getDbSync();

@@ -126,3 +122,3 @@ if (typeof value === 'function') {

const nextValue = value(prevValue);
checkValidInput(key, nextValue);
this.checkValidInput(key, nextValue);
db.runSync(STATEMENT_SET, key, nextValue);

@@ -138,3 +134,3 @@ });

removeItemSync(key) {
checkValidInput(key);
this.checkValidInput(key);
const db = this.getDbSync();

@@ -206,3 +202,3 @@ const result = db.runSync(STATEMENT_REMOVE, key);

async mergeItem(key, value) {
checkValidInput(key, value);
this.checkValidInput(key, value);
await this.setItemAsync(key, (prevValue) => {

@@ -223,3 +219,3 @@ if (prevValue == null) {

return Promise.all(keys.map(async (key) => {
checkValidInput(key);
this.checkValidInput(key);
return [key, await this.getItemAsync(key)];

@@ -232,6 +228,6 @@ }));

async multiSet(keyValuePairs) {
const db = this.getDbSync();
const db = await this.getDbAsync();
await db.withExclusiveTransactionAsync(async (tx) => {
for (const [key, value] of keyValuePairs) {
checkValidInput(key, value);
this.checkValidInput(key, value);
await tx.runAsync(STATEMENT_SET, key, value);

@@ -245,6 +241,6 @@ }

async multiRemove(keys) {
const db = this.getDbSync();
const db = await this.getDbAsync();
await db.withExclusiveTransactionAsync(async (tx) => {
for (const key of keys) {
checkValidInput(key);
this.checkValidInput(key);
await tx.runAsync(STATEMENT_REMOVE, key);

@@ -259,6 +255,6 @@ }

async multiMerge(keyValuePairs) {
const db = this.getDbSync();
const db = await this.getDbAsync();
await db.withExclusiveTransactionAsync(async (tx) => {
for (const [key, value] of keyValuePairs) {
checkValidInput(key, value);
this.checkValidInput(key, value);
const prevValue = await tx.getFirstAsync(STATEMENT_GET, key);

@@ -284,2 +280,16 @@ if (prevValue == null) {

//#region Internals
async getDbAsync() {
await this.awaitLock.acquireAsync();
try {
if (!this.db) {
const db = await openDatabaseAsync(this.databaseName);
await this.maybeMigrateDbAsync(db);
this.db = db;
}
}
finally {
this.awaitLock.release();
}
return this.db;
}
getDbSync() {

@@ -293,2 +303,16 @@ if (!this.db) {

}
maybeMigrateDbAsync(db) {
return db.withTransactionAsync(async () => {
const result = await db.getFirstAsync('PRAGMA user_version');
let currentDbVersion = result?.user_version ?? 0;
if (currentDbVersion >= DATABASE_VERSION) {
return;
}
if (currentDbVersion === 0) {
await db.execAsync(MIGRATION_STATEMENT_0);
currentDbVersion = 1;
}
await db.execAsync(`PRAGMA user_version = ${DATABASE_VERSION}`);
});
}
maybeMigrateDbSync(db) {

@@ -335,2 +359,11 @@ db.withTransactionSync(() => {

}
checkValidInput(...input) {
const [key, value] = input;
if (typeof key !== 'string') {
throw new Error(`[SQLiteStorage] Using ${typeof key} type for key is not supported. Use string instead. Key passed: ${key}`);
}
if (input.length > 1 && typeof value !== 'string' && typeof value !== 'function') {
throw new Error(`[SQLiteStorage] Using ${typeof value} type for value is not supported. Use string instead. Key passed: ${key}. Value passed : ${value}`);
}
}
}

@@ -337,0 +370,0 @@ /**

@@ -13,2 +13,13 @@ # Changelog

## 15.2.10 — 2025-05-08
### 🐛 Bug fixes
- Fixed parallel issue for `Statement.executeAsync`. ([#36674](https://github.com/expo/expo/pull/36674) by [@kudo](https://github.com/kudo))
### 💡 Others
- Avoided synchronous API calls for `kv-store`. ([#36669](https://github.com/expo/expo/pull/36669) by [@kudo](https://github.com/kudo))
- Improved synchronous APIs on web. ([#36670](https://github.com/expo/expo/pull/36670) by [@kudo](https://github.com/kudo))
## 15.2.9 — 2025-04-30

@@ -15,0 +26,0 @@

@@ -8,10 +8,4 @@ {

"modules": ["expo.modules.sqlite.SQLiteModule"],
"shouldUsePublicationScriptPath": "android/shouldUsePublication.groovy",
"publication": {
"groupId": "host.exp.exponent",
"artifactId": "expo.modules.sqlite",
"version": "15.2.9",
"repository": "local-maven-repo"
}
"shouldUsePublicationScriptPath": "android/shouldUsePublication.groovy"
}
}
{
"name": "expo-sqlite",
"version": "15.2.9",
"version": "15.2.10",
"description": "Provides access to a database using SQLite (https://www.sqlite.org/). The database is persisted across restarts of your app.",

@@ -51,3 +51,5 @@ "main": "build/index.js",

},
"dependencies": {},
"dependencies": {
"await-lock": "^2.2.2"
},
"devDependencies": {

@@ -57,3 +59,3 @@ "@testing-library/react-native": "^13.1.0",

"better-sqlite3": "^11.6.0",
"expo-module-scripts": "^4.1.6",
"expo-module-scripts": "^4.1.7",
"react-error-boundary": "^4.0.11"

@@ -66,3 +68,3 @@ },

},
"gitHead": "84355076bc31a356aa3d23257f387f221885f53d"
"gitHead": "49c9d53cf0a9fc8179d1c8f5268beadd141f70ca"
}

@@ -1,22 +0,5 @@

import { openDatabaseSync, type SQLiteDatabase } from './index';
import AwaitLock from 'await-lock';
/**
* @hidden
*/
export function checkValidInput(...input: unknown[]) {
const [key, value] = input;
import { openDatabaseAsync, openDatabaseSync, type SQLiteDatabase } from './index';
if (typeof key !== 'string') {
throw new Error(
`[SQLiteStorage] Using ${typeof key} type for key is not supported. Use string instead. Key passed: ${key}`
);
}
if (input.length > 1 && typeof value !== 'string' && typeof value !== 'function') {
throw new Error(
`[SQLiteStorage] Using ${typeof value} type for value is not supported. Use string instead. Key passed: ${key}. Value passed : ${value}`
);
}
}
/**

@@ -45,2 +28,3 @@ * Update function for the [`setItemAsync()`](#setitemasynckey-value) or [`setItemSync()`](#setitemsynckey-value) method. It computes the new value based on the previous value. The function returns the new value to set for the key.

private db: SQLiteDatabase | null = null;
private readonly awaitLock = new AwaitLock();

@@ -55,4 +39,4 @@ constructor(private readonly databaseName: string) {}

async getItemAsync(key: string): Promise<string | null> {
checkValidInput(key);
const db = this.getDbSync();
this.checkValidInput(key);
const db = await this.getDbAsync();
const result = await db.getFirstAsync<{ value: string }>(STATEMENT_GET, key);

@@ -70,4 +54,4 @@ return result?.value ?? null;

): Promise<void> {
checkValidInput(key, value);
const db = this.getDbSync();
this.checkValidInput(key, value);
const db = await this.getDbAsync();

@@ -79,3 +63,3 @@ if (typeof value === 'function') {

const nextValue = value(prevValue);
checkValidInput(key, nextValue);
this.checkValidInput(key, nextValue);
await tx.runAsync(STATEMENT_SET, key, nextValue);

@@ -93,4 +77,4 @@ });

async removeItemAsync(key: string): Promise<boolean> {
checkValidInput(key);
const db = this.getDbSync();
this.checkValidInput(key);
const db = await this.getDbAsync();
const result = await db.runAsync(STATEMENT_REMOVE, key);

@@ -104,3 +88,3 @@ return result.changes > 0;

async getAllKeysAsync(): Promise<string[]> {
const db = this.getDbSync();
const db = await this.getDbAsync();
const result = await db.getAllAsync<{ key: string }>(STATEMENT_GET_ALL_KEYS);

@@ -114,3 +98,3 @@ return result.map(({ key }) => key);

async clearAsync(): Promise<boolean> {
const db = this.getDbSync();
const db = await this.getDbAsync();
const result = await db.runAsync(STATEMENT_CLEAR);

@@ -124,5 +108,10 @@ return result.changes > 0;

async closeAsync(): Promise<void> {
if (this.db) {
await this.db.closeAsync();
this.db = null;
await this.awaitLock.acquireAsync();
try {
if (this.db) {
await this.db.closeAsync();
this.db = null;
}
} finally {
this.awaitLock.release();
}

@@ -139,3 +128,3 @@ }

getItemSync(key: string): string | null {
checkValidInput(key);
this.checkValidInput(key);
const db = this.getDbSync();

@@ -151,3 +140,3 @@ const result = db.getFirstSync<{ value: string }>(STATEMENT_GET, key);

setItemSync(key: string, value: string | SQLiteStorageSetItemUpdateFunction): void {
checkValidInput(key, value);
this.checkValidInput(key, value);
const db = this.getDbSync();

@@ -160,3 +149,3 @@

const nextValue = value(prevValue);
checkValidInput(key, nextValue);
this.checkValidInput(key, nextValue);
db.runSync(STATEMENT_SET, key, nextValue);

@@ -174,3 +163,3 @@ });

removeItemSync(key: string): boolean {
checkValidInput(key);
this.checkValidInput(key);
const db = this.getDbSync();

@@ -253,3 +242,3 @@ const result = db.runSync(STATEMENT_REMOVE, key);

async mergeItem(key: string, value: string): Promise<void> {
checkValidInput(key, value);
this.checkValidInput(key, value);
await this.setItemAsync(key, (prevValue) => {

@@ -272,3 +261,3 @@ if (prevValue == null) {

keys.map(async (key): Promise<[string, string | null]> => {
checkValidInput(key);
this.checkValidInput(key);
return [key, await this.getItemAsync(key)];

@@ -283,6 +272,6 @@ })

async multiSet(keyValuePairs: [string, string][]): Promise<void> {
const db = this.getDbSync();
const db = await this.getDbAsync();
await db.withExclusiveTransactionAsync(async (tx) => {
for (const [key, value] of keyValuePairs) {
checkValidInput(key, value);
this.checkValidInput(key, value);
await tx.runAsync(STATEMENT_SET, key, value);

@@ -297,6 +286,6 @@ }

async multiRemove(keys: string[]): Promise<void> {
const db = this.getDbSync();
const db = await this.getDbAsync();
await db.withExclusiveTransactionAsync(async (tx) => {
for (const key of keys) {
checkValidInput(key);
this.checkValidInput(key);
await tx.runAsync(STATEMENT_REMOVE, key);

@@ -312,6 +301,6 @@ }

async multiMerge(keyValuePairs: [string, string][]): Promise<void> {
const db = this.getDbSync();
const db = await this.getDbAsync();
await db.withExclusiveTransactionAsync(async (tx) => {
for (const [key, value] of keyValuePairs) {
checkValidInput(key, value);
this.checkValidInput(key, value);
const prevValue = await tx.getFirstAsync<{ value: string }>(STATEMENT_GET, key);

@@ -341,2 +330,16 @@ if (prevValue == null) {

private async getDbAsync(): Promise<SQLiteDatabase> {
await this.awaitLock.acquireAsync();
try {
if (!this.db) {
const db = await openDatabaseAsync(this.databaseName);
await this.maybeMigrateDbAsync(db);
this.db = db;
}
} finally {
this.awaitLock.release();
}
return this.db;
}
private getDbSync(): SQLiteDatabase {

@@ -351,2 +354,17 @@ if (!this.db) {

private maybeMigrateDbAsync(db: SQLiteDatabase) {
return db.withTransactionAsync(async () => {
const result = await db.getFirstAsync<{ user_version: number }>('PRAGMA user_version');
let currentDbVersion = result?.user_version ?? 0;
if (currentDbVersion >= DATABASE_VERSION) {
return;
}
if (currentDbVersion === 0) {
await db.execAsync(MIGRATION_STATEMENT_0);
currentDbVersion = 1;
}
await db.execAsync(`PRAGMA user_version = ${DATABASE_VERSION}`);
});
}
private maybeMigrateDbSync(db: SQLiteDatabase) {

@@ -397,2 +415,18 @@ db.withTransactionSync(() => {

private checkValidInput(...input: unknown[]) {
const [key, value] = input;
if (typeof key !== 'string') {
throw new Error(
`[SQLiteStorage] Using ${typeof key} type for key is not supported. Use string instead. Key passed: ${key}`
);
}
if (input.length > 1 && typeof value !== 'string' && typeof value !== 'function') {
throw new Error(
`[SQLiteStorage] Using ${typeof value} type for value is not supported. Use string instead. Key passed: ${key}. Value passed : ${value}`
);
}
}
//#endregion

@@ -399,0 +433,0 @@ }

@@ -40,3 +40,3 @@ // Copyright 2015-present 650 Industries. All rights reserved.

const resultArray = new Uint8Array(resultBuffer);
const resultJson = result ? serialize({ result }) : serialize({ error });
const resultJson = error != null ? serialize({ error }) : serialize({ result });
const resultBytes = new TextEncoder().encode(resultJson);

@@ -121,9 +121,19 @@ const length = resultBytes.length;

let i = 0;
// @ts-expect-error: Remove this when TypeScript supports Atomics.pause
const useAtomicsPause = typeof Atomics.pause === 'function';
while (Atomics.load(lock, 0) === PENDING) {
// NOTE(kudo): Unfortunate busy loop,
// because we don't have a way for main thread to yield its execution to other callbacks.
// Maybe we can wait for [`Atomics.pause`](https://github.com/tc39/proposal-atomics-microwait) to be implemented.
++i;
if (i > 1000000000) {
throw new Error('Sync operation timeout');
if (useAtomicsPause) {
if (i > 1_000_000) {
throw new Error('Sync operation timeout');
}
// @ts-expect-error: Remove this when TypeScript supports Atomics.pause
Atomics.pause();
} else {
// NOTE(kudo): Unfortunate for the busy loop,
// because we don't have a way for main thread to yield its execution to other callbacks.
if (i > 1000_000_000) {
throw new Error('Sync operation timeout');
}
}

@@ -130,0 +140,0 @@ }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet