Skip to content

Commit

Permalink
Merge pull request #51 from powersync-ja/jsdoc-comments
Browse files Browse the repository at this point in the history
JSDoc comments for JS
  • Loading branch information
benitav authored Feb 9, 2024
2 parents a88e797 + b4abac5 commit ac800cc
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 25 deletions.
2 changes: 1 addition & 1 deletion packages/powersync-react/src/hooks/usePowerSyncQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { usePowerSync } from './PowerSyncContext';

/**
* A hook to access a single static query.
* For an updated result, use usePowerSyncWatchedQuery instead
* For an updated result, use {@link usePowerSyncWatchedQuery} instead
*/
export const usePowerSyncQuery = <T = any>(sqlStatement: string, parameters: any[] = []): T[] => {
const powerSync = usePowerSync();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ import { EventIterator } from 'event-iterator';
import { quoteIdentifier } from '../utils/strings';

export interface DisconnectAndClearOptions {
/** When set to false, data in local-only tables is preserved. */
clearLocal?: boolean;
}

export interface PowerSyncDatabaseOptions {
/** Schema used for the local database. */
schema: Schema;
database: DBAdapter;
/**
Expand All @@ -44,6 +46,7 @@ export interface PowerSyncDatabaseOptions {
export interface SQLWatchOptions {
signal?: AbortSignal;
tables?: string[];
/** The minimum interval between queries. */
throttleMs?: number;
/**
* Allows for watching any SQL table
Expand Down Expand Up @@ -114,14 +117,25 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
this._isReadyPromise = this.initialize();
}

/**
* Schema used for the local database.
*/
get schema() {
return this._schema;
}

/**
* The underlying database.
*
* For the most part, behavior is the same whether querying on the underlying database, or on {@link AbstractPowerSyncDatabase}.
*/
protected get database() {
return this.options.database;
}

/**
* Whether a connection to the PowerSync service is currently open.
*/
get connected() {
return this.currentStatus?.connected || false;
}
Expand Down Expand Up @@ -163,6 +177,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
this.iterateListeners((cb) => cb.initialized?.());
}

/**
* Replace the schema with a new version. This is for advanced use cases - typically the schema should just be specified once in the constructor.
*
* Cannot be used while connected - this should only be called before {@link AbstractPowerSyncDatabase.connect}.
*/
async updateSchema(schema: Schema) {
if (this.abortController) {
throw new Error('Cannot update schema while connected');
Expand Down Expand Up @@ -226,6 +245,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
this.watchCrudUploads();
}

/**
* Close the sync connection.
*
* Use {@link connect} to connect again.
*/
async disconnect() {
this.abortController?.abort();
this.syncStatusListenerDisposer?.();
Expand All @@ -237,6 +261,8 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
* Use this when logging out.
* The database can still be queried after this is called, but the tables
* would be empty.
*
* To preserve data in local-only tables, set clearLocal to false.
*/
async disconnectAndClear(options = DEFAULT_DISCONNECT_CLEAR_OPTIONS) {
await this.disconnect();
Expand Down Expand Up @@ -270,7 +296,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
/*
* Close the database, releasing resources.
*
* Also [disconnect]s any active connection.
* Also disconnects any active connection.
*
* Once close is called, this connection cannot be used again - a new one
* must be constructed.
Expand Down Expand Up @@ -307,12 +333,12 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
*
* Returns null if there is no data to upload.
*
* Use this from the [PowerSyncBackendConnector.uploadData]` callback.
* Use this from the {@link PowerSyncBackendConnector.uploadData} callback.
*
* Once the data have been successfully uploaded, call [CrudBatch.complete] before
* Once the data have been successfully uploaded, call {@link CrudBatch.complete} before
* requesting the next batch.
*
* Use [limit] to specify the maximum number of updates to return in a single
* Use {@link limit} to specify the maximum number of updates to return in a single
* batch.
*
* This method does include transaction ids in the result, but does not group
Expand Down Expand Up @@ -358,12 +384,12 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
*
* Returns null if there is no data to upload.
*
* Use this from the [PowerSyncBackendConnector.uploadData]` callback.
* Use this from the {@link PowerSyncBackendConnector.uploadData} callback.
*
* Once the data have been successfully uploaded, call [CrudTransaction.complete] before
* Once the data have been successfully uploaded, call {@link CrudTransaction.complete} before
* requesting the next transaction.
*
* Unlike [getCrudBatch], this only returns data from a single transaction at a time.
* Unlike {@link getCrudBatch}, this only returns data from a single transaction at a time.
* All data for the transaction is loaded into memory.
*/
async getNextCrudTransaction(): Promise<CrudTransaction> {
Expand Down Expand Up @@ -413,15 +439,15 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
}

/**
* Execute a statement and optionally return results
* Execute a statement and optionally return results.
*/
async execute(sql: string, parameters?: any[]) {
await this.waitForReady();
return this.database.execute(sql, parameters);
}

/**
* Execute a read-only query and return results
* Execute a read-only query and return results.
*/
async getAll<T>(sql: string, parameters?: any[]): Promise<T[]> {
await this.waitForReady();
Expand All @@ -446,8 +472,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB

/**
* Takes a read lock, without starting a transaction.
*
* In most cases, [readTransaction] should be used instead.
* In most cases, {@link readTransaction} should be used instead.
*/
async readLock<T>(callback: (db: DBAdapter) => Promise<T>) {
await this.waitForReady();
Expand All @@ -456,7 +481,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB

/**
* Takes a global lock, without starting a transaction.
* In most cases, [writeTransaction] should be used instead.
* In most cases, {@link writeTransaction} should be used instead.
*/
async writeLock<T>(callback: (db: DBAdapter) => Promise<T>) {
await this.waitForReady();
Expand All @@ -466,6 +491,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
});
}

/**
* Open a read-only transaction.
* Read transactions can run concurrently to a write transaction.
* Changes from any write transaction are not visible to read transactions started before it.
*/
async readTransaction<T>(
callback: (tx: Transaction) => Promise<T>,
lockTimeout: number = DEFAULT_LOCK_TIMEOUT_MS
Expand All @@ -481,6 +511,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
);
}

/**
* Open a read-write transaction.
* This takes a global lock - only one write transaction can execute against the database at a time.
* Statements within the transaction must be done on the provided {@link Transaction} interface.
*/
async writeTransaction<T>(
callback: (tx: Transaction) => Promise<T>,
lockTimeout: number = DEFAULT_LOCK_TIMEOUT_MS
Expand All @@ -496,6 +531,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
);
}

/**
* Execute a read query every time the source tables are modified.
* Use {@link SQLWatchOptions.throttleMs} to specify the minimum interval between queries.
* Source tables are automatically detected using `EXPLAIN QUERY PLAN`.
*/
async *watch(sql: string, parameters?: any[], options?: SQLWatchOptions): AsyncIterable<QueryResult> {
//Fetch initial data
yield await this.executeReadOnly(sql, parameters);
Expand Down Expand Up @@ -524,7 +564,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
/**
* Create a Stream of changes to any of the specified tables.
*
* This is preferred over [watch] when multiple queries need to be performed
* This is preferred over {@link watch} when multiple queries need to be performed
* together when data is changed.
*
* Note, do not declare this as `async *onChange` as it will not work in React Native
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Schema } from '../db/schema/Schema';
import { AbstractPowerSyncDatabase, PowerSyncDatabaseOptions } from './AbstractPowerSyncDatabase';

export interface PowerSyncOpenFactoryOptions extends Partial<PowerSyncDatabaseOptions> {
/** Schema used for the local database. */
schema: Schema;
/**
* Filename for the database.
Expand All @@ -20,6 +21,9 @@ export abstract class AbstractPowerSyncDatabaseOpenFactory {
options.logger = options.logger ?? Logger.get(`PowerSync ${this.options.dbFilename}`);
}

/**
* Schema used for the local database.
*/
get schema() {
return this.options.schema;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface PowerSyncBackendConnector {

/** Upload local changes to the app backend.
*
* Use [PowerSyncDatabase.getCrudBatch] to get a batch of changes to upload. See [DevConnector] for an example implementation.
* Use {@link AbstractPowerSyncDatabase.getCrudBatch} to get a batch of changes to upload.
*
* Any thrown errors will result in a retry after the configured wait period (default: 5 seconds).
*/
Expand Down
12 changes: 12 additions & 0 deletions packages/powersync-sdk-common/src/client/sync/bucket/CrudBatch.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import { CrudEntry } from './CrudEntry';

/**
* A batch of client-side changes.
*/
export class CrudBatch {
constructor(
/**
* List of client-side changes.
*/
public crud: CrudEntry[],
/**
* true if there are more changes in the local queue.
*/
public haveMore: boolean,
/**
* Call to remove the changes from the local queue, once successfully uploaded.
*/
public complete: (writeCheckpoint?: string) => Promise<void>
) {}
}
27 changes: 27 additions & 0 deletions packages/powersync-sdk-common/src/client/sync/bucket/CrudEntry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,33 @@ export type CrudEntryOutputJSON = {
data: Record<string, any>;
};

/**
* A single client-side change.
*/
export class CrudEntry {
/**
* Auto-incrementing client-side id.
*/
clientId: number;
/**
* ID of the changed row.
*/
id: string;
/**
* Type of change.
*/
op: UpdateType;
/**
* Data associated with the change.
*/
opData?: Record<string, any>;
/**
* Table that contained the change.
*/
table: string;
/**
* Auto-incrementing transaction id. This is the same for all operations within the same transaction.
*/
transactionId?: number;

static fromRow(dbRow: CrudEntryJSON) {
Expand All @@ -67,6 +88,9 @@ export class CrudEntry {
this.transactionId = transactionId;
}

/**
* Converts the change to JSON format.
*/
toJSON(): CrudEntryOutputJSON {
return {
op_id: this.clientId,
Expand All @@ -78,6 +102,9 @@ export class CrudEntry {
};
}

/**
* The hash code for this object.
*/
hashCode() {
return hash([this.transactionId, this.clientId, this.op, this.table, this.id, this.opData]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,17 @@ import { CrudEntry } from './CrudEntry';

export class CrudTransaction extends CrudBatch {
constructor(
/**
* List of client-side changes.
*/
public crud: CrudEntry[],
/**
* Call to remove the changes from the local queue, once successfully uploaded.
*/
public complete: (checkpoint?: string) => Promise<void>,
/**
* If null, this contains a list of changes recorded without an explicit transaction associated.
*/
public transactionId?: number
) {
super(crud, false, complete);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ export class SqliteBucketStorage implements BucketStorageAdapter {

/**
* Mark a bucket for deletion.
*
* @param bucket
*/
private async deleteBucket(bucket: string) {
// Delete a bucket, but allow it to be re-created.
Expand Down
20 changes: 12 additions & 8 deletions packages/powersync-sdk-common/src/db/DBAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,14 @@ import { BaseListener, BaseObserverInterface } from '../utils/BaseObserver';
*/

/**
* Object returned by SQL Query executions {
* insertId: Represent the auto-generated row id if applicable
* rowsAffected: Number of affected rows if result of a update query
* message: if status === 1, here you will find error description
* rows: if status is undefined or 0 this object will contain the query results
* }
*
* @interface QueryResult
* Object returned by SQL Query executions.
*/
export type QueryResult = {
/** Represents the auto-generated row id if applicable. */
insertId?: number;
/** Number of affected rows if result of a update query. */
rowsAffected: number;
/** if status is undefined or 0 this object will contain the query results */
rows?: {
/** Raw array with all dataset */
_array: any[];
Expand All @@ -37,12 +33,16 @@ export type QueryResult = {
};

export interface DBGetUtils {
/** Execute a read-only query and return results. */
getAll<T>(sql: string, parameters?: any[]): Promise<T[]>;
/** Execute a read-only query and return the first result, or null if the ResultSet is empty. */
getOptional<T>(sql: string, parameters?: any[]): Promise<T | null>;
/** Execute a read-only query and return the first result, error if the ResultSet is empty. */
get<T>(sql: string, parameters?: any[]): Promise<T>;
}

export interface LockContext extends DBGetUtils {
/** Execute a statement and optionally return results. */
execute: (query: string, params?: any[] | undefined) => Promise<QueryResult>;
}

Expand All @@ -63,6 +63,10 @@ export interface TableUpdateOperation {
opType: RowUpdateType;
rowId: number;
}

/**
* Notification of an update to one or more tables, for the purpose of realtime change notifications.
*/
export interface UpdateNotification extends TableUpdateOperation {
table: string;
}
Expand Down
Loading

0 comments on commit ac800cc

Please sign in to comment.