UNPKG

@dittolive/ditto

Version:

Ditto is a cross-platform SDK that allows apps to sync with and even without internet connectivity.

1,199 lines (1,180 loc) 129 kB
/** @internal */ declare class KeepAlive { /** @internal */ get isActive(): boolean; /** @internal */ constructor(); /** @internal */ retain(id: string): void; /** @internal */ release(id: string): void; /** @internal */ currentIDs(): string[]; /** @internal */ countForID(id: string): number | null; private static finalizationRegistry; private intervalID; private countsByID; } /** @internal */ type ObserverToken = string; /** @internal */ interface ObserverManaging { hasObserver(token: ObserverToken): boolean; removeObserver(token: ObserverToken): void; } /** @internal */ type ObserverOptions = { stopsWhenFinalized?: boolean; }; /** * Generic observer handle returned by various observation APIs. The observation * remains active until the {@link stop | stop()} method is called explicitly or * the observer instance is garbage collected. Therefore, to keep the observation * alive, you have to keep a reference to the corresponding observer. */ declare class Observer { /** @internal */ readonly observerManager: ObserverManaging; /** @internal */ get token(): ObserverToken | undefined; /** @internal */ readonly options?: ObserverOptions; /** @internal */ constructor(observerManager: ObserverManaging, token: any, options?: ObserverOptions); /** * Returns `true` if the observer has been explicitly stopped via the `stop()` * method. Otherwise returns `false`. */ get isStopped(): boolean; /** * Stops the observation. Calling this method multiple times has no effect. */ stop(): void; private static finalizationRegistry; private _token?; private static finalize; } /** * Error codes for FFI result. * * This should include all variants of `FfiError` in `ffi/src/result/error.rs`. * * @internal */ type FFIResultErrorCode = 'ActivationLicenseTokenExpired' | 'ActivationLicenseTokenInvalid' | 'ActivationLicenseUnsupportedFutureVersion' | 'ActivationNotActivated' | 'ActivationUnnecessary' | 'AuthenticationExpirationHandlerMissing' | 'Base64Invalid' | 'CborInvalid' | 'CborUnsupported' | 'Crdt' | 'DifferIdentityKeyPathInvalid' | 'DqlEvaluationError' | 'DqlInvalidQueryArgs' | 'DqlQueryCompilation' | 'DqlUnsupported' | 'IoAlreadyExists' | 'IoNotFound' | 'IoOperationFailed' | 'IoPermissionDenied' | 'JsFloatingStoreOperation' | 'LockedDittoWorkingDirectory' | 'EncryptionExtraneousPassphraseGiven' | 'ParameterQuery' | 'StoreDatabase' | 'StoreDocumentId' | 'StoreDocumentNotFound' | 'StoreTransactionReadOnly' | 'StoreQuery' | 'Transport' | 'Unknown' | 'Unsupported' | 'ValidationDepthLimitExceeded' | 'ValidationInvalidCbor' | 'ValidationInvalidDittoConfig' | 'ValidationInvalidJson' | 'ValidationNotAMap' | 'ValidationInvalidTransportConfig' | 'ValidationSizeLimitExceeded'; /** * Represents an exception that occurred during a call into the Ditto FFI. * * Use the {@link throwOnErrorStatus | throwOnErrorStatus()} helper to * automatically throw this error when an FFI call returns with a non-zero * return value. * * @internal */ declare class DittoFFIError extends Error { /** * The code identifying this error. * * May be a numerical status code returned by an FFI call or an * {@link FFIResultErrorCode} for errors returned on FFI result objects. * * @see {@link throwOnErrorStatus | throwOnErrorStatus()} */ readonly code: number | FFIResultErrorCode; /** * Only call this constructor after having called `FFI.ensureInitialized()` * and `FFI.trace()`. * * @param code numerical status code returned by an FFI call or an * {@link FFIResultErrorCode} for errors returned on FFI result objects * @param messageOverride overrides the thread-local error message set in * Ditto core * @param messageFallback fallback message to use if the thread-local error * message is empty */ constructor(code: number | FFIResultErrorCode, messageOverride?: string, messageFallback?: string); } /** @internal */ type Pointer<Type> = { type: Type; addr: string; }; /** @internal */ declare const DittoCRDTTypeKey = "_ditto_internal_type_jkb12973t4b"; /** @internal */ type FFIQueryResultItem = 'dittoffi_query_result_item_t'; /** @internal */ type FFIQueryResult = 'dittoffi_query_result_t'; /** @internal */ type FFIDiffer = 'dittoffi_differ_t'; /** @internal */ type FFIDitto = 'CDitto_t'; /** @internal */ declare enum DittoCRDTType { counter = 0, register = 1, attachment = 2, rga = 3, rwMap = 4 } /** Various options to pass the web assembly module to Ditto. */ type WebAssemblyModule = RequestInfo | URL | Response | BufferSource | WebAssembly.Module | string | null; interface DittoConfigConnectServer$1 { type: 'server'; url: string; } interface DittoConfigConnectSmallPeersOnly$1 { type: 'small_peers_only'; private_key?: string; } interface DittoConfig$1 { database_id: string; connect: DittoConfigConnectServer$1 | DittoConfigConnectSmallPeersOnly$1; persistence_directory: string | null; experimental: {}; } /** @internal */ type UntypedAttachmentToken = { id: string; len: number | bigint; metadata: AttachmentMetadata; }; /** @internal */ type TypedAttachmentTokenV1 = { [DittoCRDTTypeKey]?: DittoCRDTType.attachment; _id: Uint8Array; _len: number | bigint; _meta: AttachmentMetadata; }; /** * Serves as a token for a specific attachment that you can pass to a call to * {@link Store.fetchAttachment | ditto.store.fetchAttachment()}. * * @internal */ declare class AttachmentToken { /** The attachment's ID. */ readonly id: string; /** The attachment's size given as number of bytes. */ readonly len: number | bigint; /** The attachment's metadata. */ readonly metadata: AttachmentMetadata; /** @internal */ constructor(jsObj: UntypedAttachmentToken | TypedAttachmentTokenV1); /** @internal */ readonly idBytes: Uint8Array; /** * Validate an input value that has a field `[FFI.DittoCRDTTypeKey]` and * return its contents. * * @throws {Error} If the input is invalid. * @returns {object} binary id, len and metadata of the attachment token */ private static validateTypedInput; /** * Validate an untyped input value and return its contents. * * Converts _unpadded_ base64-encoded ID in input to _padded_ base64-encoded * ID before returning it as `Uint8Array`. * * @throws {@link DittoError} `store/attachment-token-invalid` If the input id * is not a valid base64 string. * @returns {object} binary id, len and metadata of the attachment token */ private static validateUntypedInput; } type ErrorCode = keyof typeof ERROR_CODES; /** * Error code and default error message for all Ditto error messages. * * Keys of this object define _error codes_ with each value containing the * accompanying error description that is set as the default error message for * errors instantiated with this code. * * Error codes may start with an error domain and a slash to group categories of * errors together. */ declare const ERROR_CODES: { /** Internal error for unexpected system states */ readonly internal: "An unexpected internal error occurred. Please get in touch with Ditto customer service to report this incident."; /** Internal error with an unknown error cause */ readonly unknown: "An unexpected internal error occurred. Please get in touch with Ditto customer service to report this incident."; /** Error when using a feature not supported by the current environment */ readonly unsupported: "The feature is not supported by the current environment."; /** Error when authentication failed */ readonly 'authentication/failed-to-authenticate': "Ditto failed to authenticate."; /** Error when the required expiration handler is not set before starting sync. */ readonly 'authentication/expiration-handler-missing': "The expiration handler must be set before starting sync."; /** Error when a file or directory already exists */ readonly 'io/already-exists': "A file or directory already exists."; /** Error when a file or directory could not be found */ readonly 'io/not-found': "A file or directory could not be found."; /** Error when permission is denied for a file operation */ readonly 'io/permission-denied': "The operation failed due to insufficient permissions."; /** Error when an IO operation failed for an unspecified reason. See error message for details. */ readonly 'io/operation-failed': "The operation failed."; /** Error for invalid DQL query arguments. */ readonly 'query/arguments-invalid': "The query arguments were invalid."; /** Errors that occur during evaluation of a query */ readonly 'query/evaluation': "The query could not be evaluated."; /** Errors that occur during execution of a query */ readonly 'query/execution': "The query could not be executed."; /** Error for an invalid DQL query. */ readonly 'query/invalid': "The query was invalid."; /** Error for a query that uses DQL features not supported in this version or not supported by the currently used API. */ readonly 'query/unsupported': "The query contains unsupported features."; /** Error for a failed query updating system parameters */ readonly 'query/parameter': "The query to update system parameters failed."; /** Error in the storage backend. */ readonly 'store/backend': "An error occurred with the storage backend."; /** Error for an invalid CRDT. */ readonly 'store/crdt': "An error occurred processing a CRDT."; /** Error for a document not found. */ readonly 'store/document-not-found': "The document with the provided ID could not be found."; /** Error for writing to a read-only transaction. */ readonly 'store/transaction-read-only': "A mutating DQL query was attempted using a read-only transaction."; /** Error for an invalid document ID. */ readonly 'store/document-id': "The document ID is invalid."; /** Error when the chosen persistence directory is already in use by another Ditto instance. */ readonly 'store/persistence-directory-locked': "The chosen persistence directory is already in use by another Ditto instance."; /** Permission has been denied for a file operation when working with attachments. */ readonly 'store/attachment-file-permission-denied': "Permission has been denied for a file operation when working with attachments."; /** The source file for an attachment does not exist. */ readonly 'store/attachment-file-not-found': "The source file for the attachment does not exist."; /** Attachment could not be found. */ readonly 'store/attachment-not-found': "The attachment could not be found."; /** Attachment token is invalid. */ readonly 'store/attachment-token-invalid': "The attachment token is invalid."; /** An unclassified error while creating an attachment. */ readonly 'store/failed-to-create-attachment': "The attachment could not be created."; /** An unclassified error while fetching an attachment. */ readonly 'store/failed-to-fetch-attachment': "The attachment could not be fetched."; /** An error representing an invalid license token. */ readonly 'activation/license-token-verification-failed': "Please provide a valid license token."; /** An error representing an expired license token. */ readonly 'activation/license-token-expired': "The license token expired. Please renew it."; /** An error representing a token is in an unsupported future format. */ readonly 'activation/license-token-unsupported-future-version': "The provided license token is in an unsupported future format."; /** The operation failed because it requires an activated Ditto instance. */ readonly 'activation/not-activated': "The operation failed because the Ditto instance has not yet been activated."; /** Activation is unnecessary for this Ditto instance, because of its identity. */ readonly 'activation/unnecessary': "Activation is unnecessary for this Ditto instance, because of its identity."; /** A validation error where the maximum depth limit was exceeded. */ readonly 'validation/depth-limit-exceeded': "The maximum depth limit has been exceeded."; /** A validation error where the value is not valid CBOR. */ readonly 'validation/invalid-cbor': "The value provided is not valid CBOR."; /** A validation error where the value is not valid JSON. */ readonly 'validation/invalid-json': "The value provided is not valid JSON."; /** A validation error where the TransportConfig is invalid for the active platform. */ readonly 'validation/invalid-transport-config': "The TransportConfig is invalid for the active platform."; /** A validation error where the {@link DittoConfig} is invalid. */ readonly 'validation/invalid-ditto-config': "The DittoConfig provided is invalid."; /** A validation error where a value is required to be a JavaScript object */ readonly 'validation/not-an-object': "The value provided is not of type object."; /** The value provided can not be serialized as JSON. */ readonly 'validation/not-json-compatible': "Value is not serializable as JSON."; /** A validation error where a size limit was exceeded. */ readonly 'validation/size-limit-exceeded': "The size limit has been exceeded."; /** * Error when a passphrase was provided but the store is not encrypted. * * This error is not in use for the JavaScript SDK, which currently does not * support encrypted stores. */ readonly 'encryption/extraneous-passphrase-given': "Unexpected passphrase provided for the currently unencrypted store."; /** */ readonly 'differ/identity-key-path-invalid': "A provided identity key path is invalid."; }; /** * `DittoError` is a subclass of the default Javascript `Error`. You can * identify specific errors programatically using the * {@link DittoError.code | code} property. * * Please reference {@link ERROR_CODES} for a comprehensive list of * possible error codes in this SDK version. * * @example * Handling a specific error code: * ```typescript * import { Attachment, DittoError } from '@dittolive/ditto' * * let attachment: Attachment * try { * attachment = await ditto.store.newAttachment(filePath) * } catch (error) { * if (error instanceof DittoError && error.code === 'store/attachment-file-not-found') { * // Handle a non-existing file * } * throw error // Rethrow any other error * } * ``` */ declare class DittoError extends Error { /** * Use the error code to identify a specific error programatically. * * @see {@link ERROR_CODES} for a comprehensive list of possible * error codes in this SDK version. */ readonly code: ErrorCode; /** Some environments provide a stack trace that is attached to any error. */ readonly stack?: string; /** * @internal * @param code string error code, see {@link ERROR_CODES} * @param message optional error message that replace's the message for the given error code * @throws {@link DittoError} `internal`: when supplied with an invalid error code */ constructor(code: ErrorCode, message?: string | null); /** * Create a {@link DittoError} from a {@link DittoFFIError}. * * The error message will be set to the optional `messageOverride` parameter * if supplied, otherwise it will be taken from the `message` property of the * given {@link DittoFFIError}. * * @internal * @param code string error code from {@link ERROR_CODES} * @param messageOverride optional string that will be used as the error * message even if a thread-local error message has been retrieved from the * FFI * @returns {@link DittoError} */ static fromFFIError(ffiError: DittoFFIError, code: ErrorCode, messageOverride?: string): DittoError; } /** * Wraps the given function to catch any {@link DittoFFIError} and rethrow it as * a {@link DittoError}, mapping status codes of the {@link DittoFFIError} to * error codes of the {@link DittoError} using the given `statusCodeMapping`. * * Use either this function or {@link mapFFIErrorsAsync} to wrap all calls into * the FFI that can fail. * * If the given status code mapping contains error messages, they will replace * any error message that is returned by the FFI. * * @internal * @param closure function that can throw a {@link DittoFFIError} * @param statusCodeMapping optional mapping of status codes of the * {@link DittoFFIError} to error codes of the {@link DittoError} * @throws {@link DittoError} when the wrapped function throws a {@link DittoFFIError} */ declare function mapFFIErrors<T>(closure: () => T, statusCodeMapping?: Partial<FFIErrorMapping>): T; /** * Wraps the given async function to catch any {@link DittoFFIError} and rethrow * it as a {@link DittoError}, mapping status codes of the {@link DittoFFIError} * to error codes of the {@link DittoError} using the given `statusCodeMapping`. * * Use either this function or {@link mapFFIErrors} to wrap any calls into the * FFI that can fail. * * If the given status code mapping contains error messages, they will replace * any error message that is returned by the FFI. * * @internal * @param closure async function that can throw a {@link DittoFFIError} * @param statusCodeMapping optional mapping of status codes of the * {@link DittoFFIError} to error codes of the {@link DittoError}. * @throws {@link DittoError} when the wrapped function throws a {@link DittoFFIError} */ declare function mapFFIErrorsAsync<T>(closure: () => Promise<T>, statusCodeMapping?: Partial<FFIErrorMapping>): Promise<T>; /** * Defines which status code of an FFI response should be mapped to which error * code of a {@link DittoError}. * * The second element of the tuple is an optional string that will be used as * the error message of the {@link DittoError} instead of the FFI error message * if defined. * * If a key `default` is present, it will be used as the error code if no * mapping for a given status code is found. * * @example * ```typescript * const statusCodeMapping: FFIErrorMapping = { * '-1': ['activation/failed', 'It just didn\'t work out'], * 'default': ['sdk/environment-incompatible'] * } * ``` * * @internal */ type FFIErrorMapping = Record<FFIResultErrorCode | number | 'default' | string, [ ErrorCode, string? ]>; /** * Provides info about the authentication status. */ type AuthenticationStatus = { /** * Returns `true` if authenticated, otherwise returns `false`. */ isAuthenticated: boolean; /** * If authenticated, returns the `userID` if one was provided by the * authentication service. Otherwise returns `null`. */ userID: string | null; }; /** * Represents the result of a login attempt. */ type LoginResult = { /** * JSON-formatted client info returned by the authentication webhook, if any. * This field is populated for both successful and failed login attempts and * is only `null` when no client info was provided by the webhook. * * See Ditto's online documentation for more information on how to provide * client info using an authentication webhook. */ clientInfo: string | null; /** * If the login attempt was successful, this property will be `null`. If the * login attempt failed, this property will contain a {@link DittoError} object with * details about the error. */ error: DittoError | null; }; /** * A function type that handles authentication expiration events for Ditto. * * This handler is called when the authentication for a Ditto instance has or is * about to expire, or if authentication has not yet occurred. It provides the * relevant {@link Ditto} instance and the time interval (in seconds) until * expiration. You can use this to login or to perform other necessary actions * before authentication expires. * * **Important:** When using the _server_ connection mode (i.e. * {@link DittoConfigConnectServer}), you **must** set an expiration handler via * {@link Authenticator.setExpirationHandler | ditto.auth.setExpirationHandler() }. * Otherwise, {@link Sync.start | ditto.sync.start()} will throw * {@link DittoError} with code `authentication/expiration-handler-missing`. * * @param ditto The {@link Ditto} instance whose authentication is expiring. * @param timeUntilExpiration The time interval, in seconds, until * authentication expires. */ type AuthenticationExpirationHandler = (ditto: Ditto, timeUntilExpiration: number) => Promise<any> | any; /** * Provides access to authentication information and methods for logging on to * Ditto Cloud. Relevant when using a `server` connection mode. */ declare class Authenticator { /** * Returns `true` if authentication is available and the login methods can be * used, otherwise returns `false`. Currently, authentication is only * available if Ditto was initialized with an "server" connection mode * (i.e. {@link DittoConfigConnectServer}). */ readonly loginSupported: boolean; /** * The built-in development authentication provider to be used together with * development authentication tokens. * * @see {@link Authenticator.login | Authenticator.login()} for more information * about the `provider` parameter. */ static get DEVELOPMENT_PROVIDER(): string; /** * The handler that will be called when authentication for this Ditto instance * is about to expire. * * **Important:** If the Ditto instance is configured with a * {@link DittoConfigConnectServer} this property **must** be set and the * handler **must** properly authenticate when called. * * @see {@link setExpirationHandler} */ get expirationHandler(): AuthenticationExpirationHandler | null; /** * Sets the handler that will be called when authentication for this Ditto * instance is about to expire. * * Assign a handler function to be notified before authentication expires, * allowing you to login or perform other necessary actions. * * @see {@link expirationHandler} */ setExpirationHandler(handler: AuthenticationExpirationHandler | null): Promise<void>; /** Returns the current authentication status. */ get status(): AuthenticationStatus; /** * Log in to Ditto with a third-party token. * * Returns a promise that resolves to a `LoginResult` object. When the login * attempt is successful, the `error` property of the response will be `null`, * otherwise it will contain a {@link DittoError} object with details about * the error. * * If the authentication service provides additional client info, it will be * returned in the `clientInfo` property of the response, whether the login * attempt was successful or not. * * @param token The authentication token required to log in. * @param provider The name of the authentication provider. Use * {@link Authenticator.DEVELOPMENT_PROVIDER} with development tokens. * @throws {@link DittoError} `authentication/failed-to-authenticate` if the * Ditto instance is closed. * @returns A promise that resolves to a `LoginResult` object. */ login(token: string, provider: string): Promise<LoginResult>; /** * Log out of Ditto. * * This will stop sync, shut down all replication sessions, and remove any * cached authentication credentials. Note that this does not remove any data * from the store. If you wish to delete data from the store then use the * optional `cleanupFn` parameter to perform any required cleanup. * * @param cleanupFn An optional function that will be called with the relevant * [Ditto] instance as the sole argument that allows you to perform any * required cleanup of the store as part of the logout process. */ logout(cleanupFn?: (ditto: Ditto) => void): Promise<void>; observeStatus(callback: (authenticationStatus: AuthenticationStatus) => void): Observer; /** @internal */ constructor(keepAlive: KeepAlive, ditto: Ditto); /** @internal */ close(): void; /** @internal */ private readonly ditto; /** @internal */ private keepAlive; /** @internal */ private observerManager; /** @internal */ private _status; /** @internal */ private _expirationHandler; private authenticationStatusUpdated; private updateAndNotify; private makeFFFIAuthenticationExpirationHandler; } /** * Specifies how this instance discovers and connects to peers, including * network settings and authentication options. This is a substructure of * {@link DittoConfig}. */ type DittoConfigConnect = DittoConfigConnectServer | DittoConfigConnectSmallPeersOnly; /** * Connects this Ditto instance to a Big Peer at the specified URL. This is a * substructure of {@link DittoConfig}. * * **Important**: For sync to work with server connections, Ditto requires (a) a * {@link AuthenticationExpirationHandler} to be set via * {@link Authenticator.setExpirationHandler | ditto.auth.setExpirationHandler()}, and * (b) that handler to properly authenticate when requested. * {@link Sync.start | startSync()} will throw if the expiration handler is * not set. */ interface DittoConfigConnectServer { mode: 'server'; url: string; } /** * Restricts connectivity to small peers only, optionally using a shared secret * (in the form of a private key) for authentication. * * If a {@link DittoConfigConnectSmallPeersOnly.privateKey | privateKey} is * provided, it will be used as a shared secret for authenticating peer-to-peer * connections. The default value is `null`, which means no encryption is used * in transit. */ interface DittoConfigConnectSmallPeersOnly { mode: 'smallPeersOnly'; privateKey?: string | null; } /** * A configuration object for initializing a {@link Ditto} instance. * * Encapsulates all the parameters required to configure a Ditto instance, * including identity, connectivity, and persistence. */ declare class DittoConfig { /** * The default database ID, used when no database ID is provided. * * @see {@link DittoConfig.databaseID | database_id} for more information about the * `databaseID` parameter. */ static get DEFAULT_DATABASE_ID(): string; /** * Returns a default {@link DittoConfig} instance with standard settings. * * This is useful as a starting point or for quickly creating a basic * configuration, but for production use you should customize the * configuration as needed. */ static get default(): DittoConfig; /** * The unique identifier for the Ditto instance. * * This must be a valid UUID string. You can find the ID in the Ditto portal, * or provide your own if you only need to sync with a small set of peers. * * Note: "Database ID" was referred to as "App ID" in older versions of the * SDK. * * @see {@link DittoConfig.DEFAULT_DATABASE_ID | DEFAULT_DATABASE_ID} for the * default database ID used when no ID is provided. */ databaseID: string; /** * The connectivity configuration for this Ditto instance. * * Specifies how this instance discovers and connects to peers, including * network settings and authentication options. */ connect: DittoConfigConnect; /** * The persistence directory used by Ditto to persist data. * * This property can have three types of values: * - **Absolute path**: A string with an absolute file path (e.g., * `/Users/joe/some/path/to/my-project.ddb`) * - **Relative path**: A string with a relative file path (e.g., * `some/path/to/my-project.ddb`) * - **undefined**: Uses the default persistence directory * * When a relative path is set, it will be resolved relative to * {@link Ditto.DEFAULT_ROOT_DIRECTORY}. When this is `undefined`, Ditto will * use a default directory name of `ditto-{id}` within * {@link Ditto.DEFAULT_ROOT_DIRECTORY}, where `{id}` is the lowercase version * of the {@link DittoConfig.databaseID | id} set in this `DittoConfig`. * * To access the final resolved absolute path after creating a Ditto instance, * use {@link Ditto.absolutePersistenceDirectory}. This property will always * return the effective absolute file path being used, regardless of whether * you provided an absolute path, relative path, or `undefined`. * * Note: It is not recommended to directly read from or write to this directory, as * its structure and contents are managed by Ditto and may change in future * versions. * * Note: When {@link Logger} is enabled, logs may be written to this directory even * after a Ditto instance has been deallocated. Please refer to the * documentation of {@link Logger} for more information. * * @see {@link Ditto.absolutePersistenceDirectory} */ persistenceDirectory?: string; /** * Initializes a new {@link DittoConfig} instance with the new API. */ constructor(id: string, connect: DittoConfigConnect, persistenceDirectory?: string); /** * Returns true if the receiver has been frozen using * {@link DittoConfig.freeze | freeze()}. */ get isFrozen(): boolean; /** * Deep freezes the receiver such that it can't be modified anymore. * * Use {@link DittoConfig.copy | copy()} to create a copy of the receiver that * is not frozen. * * @see {@link DittoConfig.isFrozen} */ freeze(): Readonly<this>; /** * Returns a deep copy of the receiver. * * The copy is not frozen, so it's properties can be modified. * * Warning: This does not create copies of * {@link AuthenticationExpirationHandler | authentication expiration handlers} * referenced by the config. Changes inside the handlers will be reflected in * the copy. */ copy(): DittoConfig; private _isFrozen; /** @internal */ get requiresOfflineLicenseToken(): boolean; /** * @param legacyPersistenceDirectory - SDKS-3187: optional v4 default path for * migration fallback. Passed by Ditto.open()/openSync() when the user hasn't * set an explicit persistenceDirectory. * @internal */ toCBOR(legacyPersistenceDirectory?: string): Uint8Array; /** * Validates the config structure. * * Only covers type and presence validation as anything beyond that is handled * by core. */ private validate; } /** * Converts a FFI {@link DittoConfig} into a {@link DittoConfig} instance. * * @internal */ declare function fromFFICBORData(data: DittoConfig$1): DittoConfig; /** * The types of attachment fetch events that can be delivered to an attachment * fetcher's `callback`. */ type AttachmentFetchEventType = 'Completed' | 'Progress' | 'Deleted'; /** * An attachment fetch event used when the attachment's download has completed. */ type AttachmentFetchEventCompleted = { type: 'Completed'; attachment: Attachment; }; /** * An attachment fetch event used when the attachment's download progressed but * is not yet complete. */ type AttachmentFetchEventProgress = { type: 'Progress'; totalBytes: number | bigint; downloadedBytes: number | bigint; }; /** * An attachment fetch event used when the attachment is deleted. */ type AttachmentFetchEventDeleted = { type: 'Deleted'; }; /** * A representation of the events that can occur in relation to an attachment * fetch. * * There are three different attachment fetch events: `Completed`, `Progress`, * or `Deleted`. * * There will be at most one `Completed` or `Deleted` event per attachment * fetch. There can be many `Progress` events delivered for each attachment * fetch. * * Updates relating to an attachment fetch are delivered by registering an * {@link AttachmentFetcher} through a call to * {@link Store["fetchAttachment"] | ditto.store.fetchAttachment()}. */ type AttachmentFetchEvent = AttachmentFetchEventCompleted | AttachmentFetchEventProgress | AttachmentFetchEventDeleted; /** * These objects are returned by calls to * {@link Store.fetchAttachment | ditto.store.fetchAttachment()} * and allow you to stop an in-flight attachment fetch. */ declare class AttachmentFetcher implements PromiseLike<Attachment | null> { /** * Returns a promise for the attachment that you can `await`. * * The promise is rejected if an error occurs during the fetch. Note that the * `AttachmentFetcher` itself implements `PromiseLike`, so you can `await` it * directly. */ readonly attachment: Promise<Attachment>; /** * Stops fetching the associated attachment and cleans up any associated * resources. * * Note that you are not required to call `stop()` once your attachment fetch * operation has finished. The method primarily exists to allow you to cancel * an attachment fetch request while it is ongoing if you no longer wish for * the attachment to be made available locally to the device. */ stop(): void; /** @internal */ readonly cancelTokenPromise: Promise<number | bigint | null> | null; /** @internal */ readonly ditto: Ditto; /** @internal */ readonly id: string; /** @internal */ readonly tokenIDBytes: Uint8Array; /** @internal */ readonly token: UntypedAttachmentToken; /** @internal */ then<TResult1 = any, TResult2 = never>(onfulfilled?: ((value: any) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined): PromiseLike<TResult1 | TResult2>; /** @internal */ constructor(ditto: Ditto, token: UntypedAttachmentToken, eventHandler?: (attachmentFetchEvent: AttachmentFetchEvent) => void); /** * `true` if the fetcher has completed or was stopped. * * @internal */ get isStopped(): boolean; /** * This function is defined while a fetch is in progress and is used to reject * the promise `this.attachment` when the fetch is canceled. * * @internal */ private rejectPendingFetch; } declare const CUSTOM_INSPECT_SYMBOL: unique symbol; /** * Represents a single match of a DQL query, similar to a “row” in SQL terms. * It’s a reference type serving as a “cursor”, allowing for efficient access of * the underlying data in various formats. * * The {@link QueryResultItem.value | value } property is lazily materialized * and kept in memory until it goes out of scope. To reduce the memory * footprint, structure your code such that items can be processed as a stream, * i.e. one by one (or in batches) and * {@link QueryResultItem.dematerialize | dematerialize() } them right after * use. * * @template T The type of the item's {@link QueryResultItem.value | value }. */ declare class QueryResultItem<T = any> { /** * Returns the content as a materialized object. * * The item's value is * {@link QueryResultItem.materialize | materialized() } on first access * and subsequently on each access after performing * {@link QueryResultItem.dematerialize | dematerialize() }. Once * materialized, the value is kept in memory until explicitly * {@link QueryResultItem.dematerialize | dematerialize() }-ed or the item * goes out of scope. */ get value(): T; /** * Returns `true` if value is currently held materialized in memory, otherwise * returns `false`. * * See {@link QueryResultItem.materialize | materialize()} and * {@link QueryResultItem.dematerialize | dematerialize()}. */ get isMaterialized(): boolean; /** * Loads the CBOR representation of the item's content, decodes it as an * object so it can be accessed via {@link QueryResultItem.value | value }. * Keeps the object in memory until * {@link QueryResultItem.dematerialize | dematerialize() } is called. No-op * if {@link QueryResultItem.value | value } is already materialized. */ materialize(): void; /** * Releases the materialized value from memory. No-op if item is not * materialized. */ dematerialize(): void; /** * Returns the content of the item as CBOR data. * * Important: The returned CBOR data is not cached, make sure to call this * method once and keep it for as long as needed. */ cborData(): Uint8Array; /** * Returns the content of the item as a JSON string. * * Important: The returned JSON string is not cached, make sure to call this * method once and keep it for as long as needed. */ jsonString(): string; /** * Defines a custom inspect representation for Node.js that will be used when * the object is inspected with console.log() or util.inspect(). * * @internal */ [CUSTOM_INSPECT_SYMBOL](_depth: number, _inspectOptions: any, inspect: any): string; private materializedValue; /** @internal */ constructor(); /** @internal */ static fromJSON(jsonData: string): QueryResultItem<any>; /** @internal */ deref(): Pointer<FFIQueryResultItem>; } /** * Represents results returned when executing a DQL query containing a * {@link QueryResultItem} for each match. * * More info, such as metrics, will be provided in the near future. * * @template T The type of items in the query result. */ declare class QueryResult<T = any> { /** * Individual items matching a DQL query. */ readonly items: QueryResultItem<T>[]; /** * IDs of documents that were mutated _locally_ by a _mutating_ DQL query * passed to {@link Store.execute | `execute()`}. Empty array if no documents * have been mutated. * * **Note: Query results received from a {@link StoreObserver} never contain * mutated document IDs because a store observer is always registered using a * non-mutating `SELECT` query. /** * IDs of documents that were mutated _locally_ by a _mutating_ DQL query * passed to {@link Store.execute | `execute()`}. Empty array if no documents * have been mutated. * * **Note: Query results received from a {@link StoreObserver} never contain * mutated document IDs because a store observer is always registered using a * non-mutating `SELECT` query. * * **Important:** The returned document IDs are not cached, make sure to call * this method once and keep the return value for as long as needed. * * @returns an array of document ID values as JSON-compatible values */ mutatedDocumentIDsV2(): any[]; /** * The commit ID associated with this query result, if any. * * This ID uniquely identifies the commit in which this change was accepted * into the _local_ store. The commit ID is available for all query results * involving insertions, updates, or deletions. This ID can be used to track * whether a local change has been synced to other peers. * * For write transactions, the commit ID is only available after the * transaction has been successfully committed. Queries executed within an * uncommitted transaction will not have a commit ID. */ get commitID(): bigint | null; /** @internal */ constructor(queryResultPointer: Pointer<FFIQueryResult>); } /** * A store observation handler is called whenever an active store observer * receives new results. * * @template T The type of items in the query result. */ type StoreObservationHandler<T = any> = (queryResult: QueryResult<T>) => void; /** * A store observation handler is called whenever an active store observer * receives new results. * * Call `signalNext()` to signal that the handler is ready to receive the next * callback from the store observer. * * @template T The type of items in the query result. */ type StoreObservationHandlerWithSignalNext<T = any> = (queryResult: QueryResult<T>, signalNext: () => any) => void; /** * A store observer invokes a given handler whenever results for its query * change. * * The store observer will remain active until it is {@link cancel | cancelled}, * or the Ditto instance managing the observer has been * {@link Ditto.close | closed}. * * Create a store observer by calling * {@link Store.registerObserver | `ditto.store.registerObserver()`}. * * {@link StoreObserver.queryString | query} nor validated against it. * @template S The type of query arguments. */ declare class StoreObserver { /** * The Ditto instance this store observer is registered with. */ readonly ditto: Ditto; /** * The query string of the store observer (as passed when registering it). */ get queryString(): string; /** * The query arguments of the store observer (as passed when registering it). */ get queryArguments(): Readonly<any> | undefined; /** * The query arguments of the store observer, serialized as CBOR, (as passed * when adding it to the store). * * Note that any {@link Attachment} values passed in as query arguments when * creating this store observer will be represented by a serialized version of * that attachment. */ get queryArgumentsCBORData(): Uint8Array | undefined; /** * The query arguments of the store observer, serialized as JSON, (as passed * when adding it to the store). * * Note that any {@link Attachment} values passed in as query arguments when * creating this store observer will be represented by a serialized version of * that attachment. */ get queryArgumentsJSONString(): string | undefined; /** * Convenience property, returns `true` once the store observer has been * cancelled. */ get isCancelled(): boolean; /** * Cancels the store observer and unregisters it. No-op if the store observer * has already been cancelled. */ cancel(): void; /** @internal */ constructor(ditto: Ditto); private deref; } /** * Defines the interface for executing DQL queries. Implemented by * {@link Store | Store} and {@link Transaction | Transaction}. */ interface QueryExecuting { /** * Executes a DQL query and returns matching items as a query result. * * **Note:** only returns results from the local store without waiting for any * {@link SyncSubscription | sync subscriptions} to have caught up with the * latest changes. Only use this method if your program must proceed with * immediate results. Use a {@link StoreObserver | store observer} to receive * updates to query results as soon as they have been synced to this peer. * * @param query A string containing a valid query expressed in DQL. * @param args An object of values keyed by the placeholder name * without the leading `:`. Example: `{ "name": "John" }` for a query like * `SELECT * FROM people WHERE name = :name`. * @template T The type of items returned by the query. This is a convenience * type that is neither inferred from the `query` parameter nor validated * against it. * @template U The type of the query arguments * @returns A promise for a {@link QueryResult} containing a * {@link QueryResultItem} for each match. * @throws {@link DittoError} `query/invalid`: if `query` argument is not a * string or not valid DQL. * @throws {@link DittoError} `query/arguments-invalid`: if `args` * argument is invalid (e.g. contains unsupported types). * @throws {@link DittoError} `transaction-read-only`: if a mutating DQL query * was attempted using a read-only transaction. (only for * the `transaction.execute()` API). * @throws {@link DittoError} may throw other errors. */ execute<T = any, U extends DQLQueryArguments = DQLQueryArguments>(query: string, args?: U): Promise<QueryResult<T>>; } /** Encapsulates information about a transaction. * * @see {@link Store.transaction | ditto.store.transaction()} */ declare class TransactionInfo { /** A globally unique ID of the transaction. */ id: string; /** * The user hint passed when creating the transaction, useful * for debugging and testing. */ hint?: string | undefined; /** * Indicates whether mutating DQL statements can be executed in the * transaction. Defaults to `false`. */ isReadOnly: boolean; constructor(id: string, isReadOnly: boolean, hint?: string); } /** * Represents an action that completes a transaction, by either committing it or * rolling it back. */ type TransactionCompletionAction = 'commit' | 'rollback'; /** * Represents a transaction in the Ditto store. * * A `Transaction` groups multiple operations into a single atomic unit, * ensuring that all operations within the transaction are either fully applied * or not applied at all, thereby maintaining data integrity. * * For more information on creating and using transactions, refer to the * {@link Store.transaction | ditto.store.transaction()} method. For a comprehensive guide on * transactions, please visit the * [Ditto documentation](https://ditto.com/link/sdk-latest-crud-transactions). */ declare class Transaction implements QueryExecuting { /** The store this transaction belongs to. */ readonly store: Store; constructor(store: Store); /** Provides information about the current transaction. */ get info(): TransactionInfo; execute<T = any, U extends DQLQueryArguments = DQLQueryArguments>(query: string, queryArguments?: U): Promise<QueryResult<T>>; /** @internal */ complete(action: TransactionCompletionAction): Promise<TransactionCompletionAction>; } /** * Interface representing options for a transaction. */ type TransactionOptions = { /** * Indicates whether the transaction is read-only. Defaults to `false`. */ isReadOnly?: boolean; /** * A hint for the transaction, useful for debugging and testing. * Defaults to `null`. */ hint?: string; }; /** * The entrypoint for all actions that relate to data stored by Ditto. Provides * access to collections, a write transaction API, and a query hash API. * * You don't create one directly but can access it from a particular * {@link Ditto} instance via its {@link Ditto.store | store} property. */ declare class Store implements QueryExecuting { /** The {@link Ditto} instance this store belongs to. */ readonly ditto: Ditto; /** * All currently active store observers. * * **Note:** Manage store observers using * {@link registerObserver | registerObserver()} to register a new store * observer and {@link StoreObserver.cancel | StoreObserver.cancel()} to * remove an existing store observer. * * @throws when this Ditto instance has been closed. */ get observers(): Readonly<Array<StoreObserver>>; /** * All currently active attachment fetchers. * * **Note:** Manage attachment fetchers using * {@link fetchAttachment | fetchAttachment()} to start a new attachment fetch * and {@link AttachmentFetcher.stop | AttachmentFetcher.stop()} to cancel * an existing attachment fetch. */ readonly attachmentFetchers: Readonly<Array<AttachmentFetcher>>; /** @internal */ get transactions(): TransactionInfo[]; /** * Register a handler to be called whenever a query's results change in the * local store. * * Convenience method, same as * {@link registerObserverWithSignalNext | registerObserverWithSignalNext()}, * except that here, the next invocation of the observation handler is * triggered automatically instead of having to call the passed in * `signalNext` function. * * @param query A string containing a valid query expressed in DQL. * @param observationHandler A function that is called whenever the query's * results change. The function is passed a {@link QueryResult} containing a * {@link QueryResultItem} for each match. * @param queryArguments An object of values keyed by the placeholder name * without the leading `:`. Example: `{ "name": "Joanna" }` for a query like * `SELECT * FROM people WHERE name = :name`. * @template T The type of items returned by the query. This is a convenience * type that is neither inferred from the `query` parameter nor validated * against it. * @returns A {@link StoreObserver} that can be used to cancel the * observation. * @throws {@link DittoError} `query/invalid`: if `query` argument is not a * string or not valid DQL. * @throws {@link DittoError} `query/arguments-invalid`: if `queryArguments` * argument is invalid (e.g. contains unsupported types). * @throws {@link DittoError} `query/unsupported`: if the query is not a * `SELECT` query. * @throws {@link DittoError} may throw other errors. */ registerObserver<T = any>(query: string, observationHandler: StoreObservationHandler<T>, queryArguments?: DQLQueryArguments): StoreObserver; /** * Registers and returns a store observer for a query, configuring Ditto to * trigger the passe