Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

sqlite-replication

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sqlite-replication - npm Package Compare versions

Comparing version 0.0.22-b to 0.0.23-b

dist/SQLHelpers.d.ts

1

dist/index.d.ts
export * from './replicationHelpers';
export * from './replicationService';
export * from './SQLHelpers';
export * from './replicationSQLiteStorage';
export * from './replicationHelpers';
export * from './replicationService';
export * from './SQLHelpers';
export * from './replicationSQLiteStorage';

4

dist/replicationHelpers.d.ts

@@ -8,6 +8,2 @@ import { SQLiteDBConnection } from '@capacitor-community/sqlite';

}): ReplicationCollectionOptions;
static getUpsertStatement(collectionName: string, document: any, option?: {
ignoreUndefinedProperties: boolean;
}): string | Promise<void>;
static safeValue(value: any): any;
static ensureRequiredColumns(db: ReplicationStorage, collections: ReplicationCollectionOptions[]): Promise<void>;

@@ -14,0 +10,0 @@ static ensureFetchPull(config: ReplicationOptions): void;

@@ -0,1 +1,2 @@

import { SQLHelpers } from './SQLHelpers';
const EXPECTED_COLUMNS = ['id', '_forkParent', 'updatedAt', 'deletedAt'];

@@ -30,3 +31,3 @@ export class ReplicationHelpers {

const keys = Object.keys(documents[0]);
const values = documents.map((document) => `(${keys.map((key) => ReplicationHelpers.safeValue(document[key])).join()})`);
const values = documents.map((document) => `(${keys.map((key) => SQLHelpers.safeValue(document[key])).join()})`);
const conflictUpdate = keys.map((key) => `"${key}"=excluded."${key}"`).join();

@@ -40,3 +41,3 @@ return db.execute(`INSERT INTO "${collectionName}" (${keys.map((key) => `"${key}"`).join()}) values ${values.join()}

return db.execute(`UPDATE "${collectionName}" SET "deletedAt"=unixepoch(), "updatedAt"=unixepoch() WHERE id IN (${documents
.map((document) => ReplicationHelpers.safeValue(document.id))
.map((document) => SQLHelpers.safeValue(document.id))
.join()});`, false);

@@ -46,31 +47,2 @@ },

}
static getUpsertStatement(collectionName, document, option = { ignoreUndefinedProperties: true }) {
if (!document)
return Promise.resolve();
const keys = Object.keys(document).filter((key) => typeof document[key] !== 'undefined' || !option.ignoreUndefinedProperties);
const values = keys.map((key) => ReplicationHelpers.safeValue(document[key])).join();
const conflictUpdate = keys.map((key) => `"${key}"=excluded."${key}"`).join();
return `INSERT INTO "${collectionName}" (${keys.map((key) => `"${key}"`).join()}) values (${values})
ON CONFLICT DO UPDATE SET ${conflictUpdate}`;
}
static safeValue(value) {
if (value === null || typeof value === 'undefined') {
return 'NULL';
}
else if (value.toISOString) {
return value.getTime();
}
else if (Array.isArray(value) || typeof value === 'object') {
return `'${JSON.stringify(value).replaceAll("'", "''")}'`;
}
else if (typeof value === 'string') {
return `'${value.replaceAll("'", "''")}'`;
}
else if (typeof value === 'boolean') {
return value ? '1' : '0';
}
else {
return value.toString();
}
}
static async ensureRequiredColumns(db, collections) {

@@ -77,0 +49,0 @@ for (const collection of collections) {

{
"name": "sqlite-replication",
"version": "0.0.22b",
"version": "0.0.23b",
"description": "A Typescript module to replicate SQLite DB with server.",

@@ -5,0 +5,0 @@ "scripts": {

export * from './replicationHelpers';
export * from './replicationService';
export * from './SQLHelpers';
export * from './replicationSQLiteStorage';

@@ -73,84 +73,2 @@ import { ReplicationHelpers } from './replicationHelpers';

});
describe('upsert', () => {
it('should generate SQL from random object', async () => {
const resultingSQL = await ReplicationHelpers.getUpsertStatement('users', { id: 123, firstName: 'Andrew' });
expect(resultingSQL).toEqual(
`INSERT INTO "users" ("id","firstName") values (123,'Andrew')
ON CONFLICT DO UPDATE SET "id"=excluded."id","firstName"=excluded."firstName"`,
);
});
it('should generate SQL from random object changing undefined to null', async () => {
const resultingSQL = await ReplicationHelpers.getUpsertStatement(
'users',
{
id: 123,
firstName: 'Andrew',
lastName: undefined,
},
{ ignoreUndefinedProperties: false },
);
expect(resultingSQL).toEqual(
`INSERT INTO "users" ("id","firstName","lastName") values (123,'Andrew',NULL)
ON CONFLICT DO UPDATE SET "id"=excluded."id","firstName"=excluded."firstName","lastName"=excluded."lastName"`,
);
});
it('should generate SQL from random object ignored undefined properties', async () => {
const resultingSQL = await ReplicationHelpers.getUpsertStatement(
'users',
{
id: 123,
firstName: 'Andrew',
lastName: undefined,
},
{ ignoreUndefinedProperties: true },
);
expect(resultingSQL).toEqual(
`INSERT INTO "users" ("id","firstName") values (123,'Andrew')
ON CONFLICT DO UPDATE SET "id"=excluded."id","firstName"=excluded."firstName"`,
);
});
});
describe('safeValue', () => {
it('should wrap strings with single quotes', async () => {
expect(ReplicationHelpers.safeValue('value')).toEqual(`'value'`);
});
it('should escape single quote, replaced by two single quotes', async () => {
expect(ReplicationHelpers.safeValue("value with single quote in : 'here' ")).toEqual(
"'value with single quote in : ''here'' '",
);
});
it('should not wrap numbers', async () => {
expect(ReplicationHelpers.safeValue(5.2)).toEqual('5.2');
});
it('should convert dates to timestamp', async () => {
expect(ReplicationHelpers.safeValue(new Date('2023-01-01'))).toEqual(1672531200000);
});
it('should keep null', async () => {
expect(ReplicationHelpers.safeValue(null)).toEqual('NULL');
});
it('should map undefined to null', async () => {
let val;
expect(ReplicationHelpers.safeValue(val)).toEqual('NULL');
});
it('should convert boolean to 0/1', async () => {
expect(ReplicationHelpers.safeValue(true)).toEqual('1');
});
it('should convert boolean to 0/1', async () => {
expect(ReplicationHelpers.safeValue(false)).toEqual('0');
});
it('should stringify object', async () => {
expect(ReplicationHelpers.safeValue({ id: 1, toto: 2 })).toEqual(`'{"id":1,"toto":2}'`);
});
it("should stringify object with '", async () => {
expect(ReplicationHelpers.safeValue({ id: 1, toto: "coucou o'bryan" })).toEqual(
`'{"id":1,"toto":"coucou o''bryan"}'`,
);
});
it('should stringify array', async () => {
expect(ReplicationHelpers.safeValue([1, 2, 3])).toEqual(`'[1,2,3]'`);
});
it("should stringify array with '", async () => {
expect(ReplicationHelpers.safeValue(["o'connor", { id: 5 }, 3])).toEqual(`'["o''connor",{"id":5},3]'`);
});
});
});
import { SQLiteDBConnection } from '@capacitor-community/sqlite';
import { ReplicationCollectionOptions, ReplicationConfig, ReplicationOptions, ReplicationStorage } from './replication';
import { SQLHelpers } from './SQLHelpers';
const EXPECTED_COLUMNS = ['id', '_forkParent', 'updatedAt', 'deletedAt'];

@@ -37,3 +38,3 @@

const values = documents.map(
(document) => `(${keys.map((key) => ReplicationHelpers.safeValue(document[key])).join()})`,
(document) => `(${keys.map((key) => SQLHelpers.safeValue(document[key])).join()})`,
);

@@ -51,3 +52,3 @@ const conflictUpdate = keys.map((key) => `"${key}"=excluded."${key}"`).join();

`UPDATE "${collectionName}" SET "deletedAt"=unixepoch(), "updatedAt"=unixepoch() WHERE id IN (${documents
.map((document) => ReplicationHelpers.safeValue(document.id))
.map((document) => SQLHelpers.safeValue(document.id))
.join()});`,

@@ -60,33 +61,2 @@ false,

static getUpsertStatement(
collectionName: string,
document: any,
option: { ignoreUndefinedProperties: boolean } = { ignoreUndefinedProperties: true },
) {
if (!document) return Promise.resolve();
const keys = Object.keys(document).filter(
(key) => typeof document[key] !== 'undefined' || !option.ignoreUndefinedProperties,
);
const values = keys.map((key) => ReplicationHelpers.safeValue(document[key])).join();
const conflictUpdate = keys.map((key) => `"${key}"=excluded."${key}"`).join();
return `INSERT INTO "${collectionName}" (${keys.map((key) => `"${key}"`).join()}) values (${values})
ON CONFLICT DO UPDATE SET ${conflictUpdate}`;
}
static safeValue(value: any) {
if (value === null || typeof value === 'undefined') {
return 'NULL';
} else if (value.toISOString) {
return value.getTime();
} else if (Array.isArray(value) || typeof value === 'object') {
return `'${JSON.stringify(value).replaceAll("'", "''")}'`;
} else if (typeof value === 'string') {
return `'${(value as string).replaceAll("'", "''")}'`;
} else if (typeof value === 'boolean') {
return value ? '1' : '0';
} else {
return value.toString();
}
}
static async ensureRequiredColumns(db: ReplicationStorage, collections: ReplicationCollectionOptions[]) {

@@ -93,0 +63,0 @@ for (const collection of collections) {

@@ -9,7 +9,7 @@ import { ReplicationService } from './replicationService';

async function testReplicationPush(
documents,
documents: any[],
replicationPushState = { users: { offset: 0, cursor: 0 } },
batchSize = 10,
) {
const stateUpdates = [];
const stateUpdates: any[] = [];
const storage = new ReplicationTestStorage(null, replicationPushState, (collectionName, offset, cursor) => {

@@ -26,3 +26,3 @@ stateUpdates.push({ collectionName, offset, cursor });

batchSize,
getDocumentOffset: (cursor, id) =>
getDocumentOffset: (cursor: number, id: string) =>
Promise.resolve(

@@ -29,0 +29,0 @@ documents.filter((document) => document.updatedAt === cursor && document.id <= id)

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc