export { LogLevel, LogSink, TeeLogSink, consoleLogSink } from '@rocicorp/logger'; /** The values that can be represented in JSON */ type JSONValue = | null | string | boolean | number | Array | JSONObject; /** * A JSON object. This is a map from strings to JSON values or `undefined`. We * allow `undefined` values as a convenience... but beware that the `undefined` * values do not round trip to the server. For example: * * ``` * // Time t1 * await tx.set('a', {a: undefined}); * * // time passes, in a new transaction * const v = await tx.get('a'); * console.log(v); // either {a: undefined} or {} * ``` */ type JSONObject = {[key: string]: JSONValue | undefined}; /** Like {@link JSONValue} but deeply readonly */ type ReadonlyJSONValue = | null | string | boolean | number | ReadonlyArray | ReadonlyJSONObject; /** Like {@link JSONObject} but deeply readonly */ type ReadonlyJSONObject = { readonly [key: string]: ReadonlyJSONValue | undefined; }; /** * A cookie is a value that is used to determine the order of snapshots. It * needs to be comparable. This can be a `string`, `number` or if you want to * use a more complex value, you can use an object with an `order` property. The * value `null` is considered to be less than any other cookie and it is used * for the first pull when no cookie has been set. * * The order is the natural order of numbers and strings. If one of the cookies * is an object then the value of the `order` property is treated as the cookie * when doing comparison. * * If one of the cookies is a string and the other is a number, the number is * fist converted to a string (using `toString()`). */ type Cookie = null | string | number | (ReadonlyJSONValue & { readonly order: number | string; }); /** * The ID describing a group of clients. All clients in the same group share a * persistent storage (IDB). */ type ClientGroupID = string; /** * The ID describing a client. */ type ClientID = string; /** * When using indexes the key is a tuple of the secondary key and the primary * key. */ type IndexKey = readonly [secondary: string, primary: string]; /** * In certain scenarios the server can signal that it does not know about the * client. For example, the server might have lost all of its state (this might * happen during the development of the server). */ type ClientStateNotFoundResponse = { error: 'ClientStateNotFound'; }; /** * The server endpoint may respond with a `VersionNotSupported` error if it does * not know how to handle the {@link pullVersion}, {@link pushVersion} or the * {@link schemaVersion}. */ type VersionNotSupportedResponse = { error: 'VersionNotSupported'; versionType?: 'pull' | 'push' | 'schema' | undefined; }; type IterableUnion = AsyncIterable | Iterable; /** * Filters an async iterable. * * This utility function is provided because it is useful when using * {@link makeScanResult}. It can be used to filter out tombstones (delete entries) * for example. */ declare function filterAsyncIterable(iter: IterableUnion, predicate: (v: V) => boolean): AsyncIterable; type HTTPRequestInfo = { httpStatusCode: number; errorMessage: string; }; /** * This type describes the patch field in a {@link PullResponse} and it is used * to describe how to update the Replicache key-value store. */ type PatchOperation = { readonly op: 'put'; readonly key: string; readonly value: ReadonlyJSONValue; } | { readonly op: 'del'; readonly key: string; } | { readonly op: 'clear'; }; /** * The JSON value used as the body when doing a POST to the [pull * endpoint](/reference/server-pull). */ type PullRequest = PullRequestV1 | PullRequestV0; /** * The JSON value used as the body when doing a POST to the [pull * endpoint](/reference/server-pull). This is the legacy version (V0) and it is * still used when recovering mutations from old clients. */ type PullRequestV0 = { pullVersion: 0; schemaVersion: string; profileID: string; cookie: ReadonlyJSONValue; clientID: ClientID; lastMutationID: number; }; /** * The JSON value used as the body when doing a POST to the [pull * endpoint](/reference/server-pull). */ type PullRequestV1 = { pullVersion: 1; schemaVersion: string; profileID: string; cookie: Cookie; clientGroupID: ClientGroupID; }; /** * The shape of a pull response under normal circumstances. */ type PullResponseOKV0 = { cookie?: ReadonlyJSONValue | undefined; lastMutationID: number; patch: PatchOperation[]; }; /** * The shape of a pull response under normal circumstances. */ type PullResponseOKV1 = { cookie: Cookie; lastMutationIDChanges: Record; patch: PatchOperation[]; }; /** * PullResponse defines the shape and type of the response of a pull. This is * the JSON you should return from your pull server endpoint. */ type PullResponseV0 = PullResponseOKV0 | ClientStateNotFoundResponse | VersionNotSupportedResponse; /** * PullResponse defines the shape and type of the response of a pull. This is * the JSON you should return from your pull server endpoint. */ type PullResponseV1 = PullResponseOKV1 | ClientStateNotFoundResponse | VersionNotSupportedResponse; type PullResponse = PullResponseV1 | PullResponseV0; /** * Store defines a transactional key/value store that Replicache stores all data * within. * * For correct operation of Replicache, implementations of this interface must * provide [strict * serializable](https://jepsen.io/consistency/models/strict-serializable) * transactions. * * Informally, read and write transactions must behave like a ReadWrite Lock - * multiple read transactions are allowed in parallel, or one write. * Additionally writes from a transaction must appear all at one, atomically. * * @experimental This interface is experimental and might be removed or changed * in the future without following semver versioning. Please be cautious. */ interface Store { read(): Promise; write(): Promise; close(): Promise; closed: boolean; } /** * This interface is used so that we can release the lock when the transaction * is done. * * @experimental This interface is experimental and might be removed or changed * in the future without following semver versioning. Please be cautious. */ interface Release { release(): void; } /** * @experimental This interface is experimental and might be removed or changed * in the future without following semver versioning. Please be cautious. */ interface Read extends Release { has(key: string): Promise; get(key: string): Promise; closed: boolean; } /** * @experimental This interface is experimental and might be removed or changed * in the future without following semver versioning. Please be cautious. */ interface Write extends Read { put(key: string, value: ReadonlyJSONValue): Promise; del(key: string): Promise; commit(): Promise; } /** * A named in-memory Store implementation. * * Two (or more) named memory stores with the same name will share the same * underlying storage. They will also share the same read/write locks, so that * only one write transaction can be running at the same time. * * @experimental This class is experimental and might be removed or changed * in the future without following semver versioning. Please be cautious. */ declare class MemStore implements Store { #private; constructor(name: string); read(): Promise; write(): Promise; close(): Promise; get closed(): boolean; } /** * Merges an iterable on to another iterable. * * The two iterables need to be ordered and the `compare` function is used to * compare two different elements. * * If two elements are equal (`compare` returns `0`) then the element from the * second iterable is picked. * * This utility function is provided because it is useful when using * {@link makeScanResult}. It can be used to merge an in memory pending async * iterable on to a persistent async iterable for example. */ declare function mergeAsyncIterables(iterableBase: IterableUnion, iterableOverlay: IterableUnion, compare: (a: A, b: B) => number): AsyncIterable; /** * Mutation describes a single mutation done on the client. This is the legacy * version (V0) and it is used when recovering mutations from old clients. */ type MutationV0 = { readonly id: number; readonly name: string; readonly args: ReadonlyJSONValue; readonly timestamp: number; }; /** * Mutation describes a single mutation done on the client. */ type MutationV1 = { readonly id: number; readonly name: string; readonly args: ReadonlyJSONValue; readonly timestamp: number; readonly clientID: ClientID; }; /** * The JSON value used as the body when doing a POST to the [push * endpoint](/reference/server-push). This is the legacy version (V0) and it is * still used when recovering mutations from old clients. */ type PushRequestV0 = { pushVersion: 0; /** * `schemaVersion` can optionally be used to specify to the push endpoint * version information about the mutators the app is using (e.g., format of * mutator args). */ schemaVersion: string; profileID: string; clientID: ClientID; mutations: MutationV0[]; }; /** * The JSON value used as the body when doing a POST to the [push * endpoint](/reference/server-push). */ type PushRequestV1 = { pushVersion: 1; /** * `schemaVersion` can optionally be used to specify to the push endpoint * version information about the mutators the app is using (e.g., format of * mutator args). */ schemaVersion: string; profileID: string; clientGroupID: ClientGroupID; mutations: MutationV1[]; }; type PushRequest = PushRequestV0 | PushRequestV1; /** * The response from a push can contain information about error conditions. */ type PushResponse = ClientStateNotFoundResponse | VersionNotSupportedResponse; /** * Options for {@link ReadTransaction.scan | scan} */ type ScanOptions = ScanIndexOptions | ScanNoIndexOptions; /** * Options for {@link ReadTransaction.scan | scan} when scanning over the entire key * space. */ type ScanNoIndexOptions = { /** Only include keys starting with `prefix`. */ prefix?: string | undefined; /** Only include up to `limit` results. */ limit?: number | undefined; /** When provided the scan starts at this key. */ start?: { key: string; /** Whether the `key` is exclusive or inclusive. */ exclusive?: boolean | undefined; } | undefined; }; /** * Options for {@link ReadTransaction.scan | scan} when scanning over an index. When * scanning over and index you need to provide the `indexName` and the `start` * `key` is now a tuple consisting of secondary and primary key */ type ScanIndexOptions = { /** Only include results starting with the *secondary* keys starting with `prefix`. */ prefix?: string | undefined; /** Only include up to `limit` results. */ limit?: number | undefined; /** Do a {@link ReadTransaction.scan | scan} over a named index. The `indexName` is * the name of an index defined when creating the {@link Replicache} instance using * {@link ReplicacheOptions.indexes}. */ indexName: string; /** When provided the scan starts at this key. */ start?: { key: ScanOptionIndexedStartKey; /** Whether the `key` is exclusive or inclusive. */ exclusive?: boolean | undefined; } | undefined; }; /** * Type narrowing of {@link ScanOptions}. */ declare function isScanIndexOptions(options: ScanOptions): options is ScanIndexOptions; /** * If the options contains an `indexName` then the key type is a tuple of * secondary and primary. */ type KeyTypeForScanOptions = O extends ScanIndexOptions ? IndexKey : string; /** * The key to start scanning at. * * If you are scanning the primary index (i.e., you did not specify * `indexName`), then pass a single string for this field, which is the key in * the primary index to scan at. * * If you are scanning a secondary index (i.e., you specified `indexName`), then * use the tuple form. In that case, `secondary` is the secondary key to start * scanning at, and `primary` (if any) is the primary key to start scanning at. */ type ScanOptionIndexedStartKey = readonly [secondary: string, primary?: string | undefined] | string; type ScanKey = string | IndexKey; interface ScanResult extends AsyncIterable { /** The default AsyncIterable. This is the same as {@link values}. */ [Symbol.asyncIterator](): AsyncIterableIteratorToArray; /** Async iterator over the values of the {@link ReadTransaction.scan | scan} call. */ values(): AsyncIterableIteratorToArray; /** * Async iterator over the keys of the {@link ReadTransaction.scan | scan} * call. If the {@link ReadTransaction.scan | scan} is over an index the key * is a tuple of `[secondaryKey: string, primaryKey]` */ keys(): AsyncIterableIteratorToArray; /** * Async iterator over the entries of the {@link ReadTransaction.scan | scan} * call. An entry is a tuple of key values. If the * {@link ReadTransaction.scan | scan} is over an index the key is a tuple of * `[secondaryKey: string, primaryKey]` */ entries(): AsyncIterableIteratorToArray; /** Returns all the values as an array. Same as `values().toArray()` */ toArray(): Promise; } /** * An interface that adds a {@link toArray} method to `AsyncIterableIterator`. * * Usage: * * ```ts * const keys: string[] = await rep.scan().keys().toArray(); * ``` */ interface AsyncIterableIteratorToArray extends AsyncIterableIterator { toArray(): Promise; } type Entry = readonly [key: string, value: V]; /** * This is called when doing a {@link ReadTransaction.scan | scan} without an * `indexName`. * * @param fromKey The `fromKey` is computed by `scan` and is the key of the * first entry to return in the iterator. It is based on `prefix` and * `start.key` of the {@link ScanNoIndexOptions}. */ type GetScanIterator = (fromKey: string) => IterableUnion>; /** * When using {@link makeScanResult} this is the type used for the function called when doing a {@link ReadTransaction.scan | scan} with an * `indexName`. * * @param indexName The name of the index we are scanning over. * @param fromSecondaryKey The `fromSecondaryKey` is computed by `scan` and is * the secondary key of the first entry to return in the iterator. It is based * on `prefix` and `start.key` of the {@link ScanIndexOptions}. * @param fromPrimaryKey The `fromPrimaryKey` is computed by `scan` and is the * primary key of the first entry to return in the iterator. It is based on * `prefix` and `start.key` of the {@link ScanIndexOptions}. */ type GetIndexScanIterator = (indexName: string, fromSecondaryKey: string, fromPrimaryKey: string | undefined) => IterableUnion; /** * A helper function that makes it easier to implement {@link ReadTransaction.scan} * with a custom backend. * * If you are implementing a custom backend and have an in memory pending async * iterable we provide two helper functions to make it easier to merge these * together. {@link mergeAsyncIterables} and {@link filterAsyncIterable}. * * For example: * * ```ts * const scanResult = makeScanResult( * options, * options.indexName * ? () => { * throw Error('not implemented'); * } * : fromKey => { * const persisted: AsyncIterable> = ...; * const pending: AsyncIterable> = ...; * const iter = await mergeAsyncIterables(persisted, pending); * const filteredIter = await filterAsyncIterable( * iter, * entry => entry[1] !== undefined, * ); * return filteredIter; * }, * ); * ``` */ declare function makeScanResult(options: Options, getScanIterator: Options extends ScanIndexOptions ? GetIndexScanIterator : GetScanIterator): ScanResult, ReadonlyJSONValue>; type TransactionEnvironment = 'client' | 'server'; type TransactionLocation = TransactionEnvironment; type TransactionReason = 'initial' | 'rebase' | 'authoritative'; /** * Basic deep readonly type. It works for {@link JSONValue}. */ type DeepReadonly = T extends null | boolean | string | number | undefined ? T : DeepReadonlyObject; type DeepReadonlyObject = { readonly [K in keyof T]: DeepReadonly; }; /** * ReadTransactions are used with {@link Replicache.query} and * {@link Replicache.subscribe} and allows read operations on the * database. */ interface ReadTransaction$1 { readonly clientID: ClientID; /** @deprecated Use {@link ReadTransaction.location} instead. */ readonly environment: TransactionLocation; readonly location: TransactionLocation; /** * Get a single value from the database. If the `key` is not present this * returns `undefined`. * * Important: The returned JSON is readonly and should not be modified. This * is only enforced statically by TypeScript and there are no runtime checks * for performance reasons. If you mutate the return value you will get * undefined behavior. */ get(key: string): Promise; get(key: string): Promise | undefined>; /** Determines if a single `key` is present in the database. */ has(key: string): Promise; /** Whether the database is empty. */ isEmpty(): Promise; /** * Gets many values from the database. This returns a {@link ScanResult} which * implements `AsyncIterable`. It also has methods to iterate over the * {@link ScanResult.keys | keys} and {@link ScanResult.entries | entries}. * * If `options` has an `indexName`, then this does a scan over an index with * that name. A scan over an index uses a tuple for the key consisting of * `[secondary: string, primary: string]`. * * If the {@link ScanResult} is used after the `ReadTransaction` has been closed * it will throw a {@link TransactionClosedError}. * * Important: The returned JSON is readonly and should not be modified. This * is only enforced statically by TypeScript and there are no runtime checks * for performance reasons. If you mutate the return value you will get * undefined behavior. */ scan(options: ScanIndexOptions): ScanResult; scan(options?: ScanNoIndexOptions): ScanResult; scan(options?: ScanOptions): ScanResult; scan(options: ScanIndexOptions): ScanResult>; scan(options?: ScanNoIndexOptions): ScanResult>; scan(options?: ScanOptions): ScanResult>; } /** * WriteTransactions are used with *mutators* which are registered using * {@link ReplicacheOptions.mutators} and allows read and write operations on the * database. */ interface WriteTransaction$1 extends ReadTransaction$1 { /** * The ID of the mutation that is being applied. */ readonly mutationID: number; /** * The reason for the transaction. This can be `initial`, `rebase` or `authoriative`. */ readonly reason: TransactionReason; /** * Sets a single `value` in the database. The value will be frozen (using * `Object.freeze`) in debug mode. */ set(key: string, value: ReadonlyJSONValue): Promise; /** * @deprecated Use {@link WriteTransaction.set} instead. */ put(key: string, value: ReadonlyJSONValue): Promise; /** * Removes a `key` and its value from the database. Returns `true` if there was a * `key` to remove. */ del(key: string): Promise; } type Poke = { baseCookie: ReadonlyJSONValue; pullResponse: PullResponseV1; }; type MaybePromise = T | Promise; /** * Returns the name of the IDB database that will be used for a particular Replicache instance. * @param name The name of the Replicache instance (i.e., the `name` field of `ReplicacheOptions`). * @param schemaVersion The schema version of the database (i.e., the `schemaVersion` field of `ReplicacheOptions`). * @returns */ declare function makeIDBName(name: string, schemaVersion?: string): string; type MutatorReturn = MaybePromise; /** * Base options for {@link PullOptions} and {@link PushOptions} */ interface RequestOptions { /** * When there are pending pull or push requests this is the _minimum_ amount * of time to wait until we try another pull/push. */ minDelayMs?: number; /** * When there are pending pull or push requests this is the _maximum_ amount * of time to wait until we try another pull/push. */ maxDelayMs?: number; } /** * The reason {@link onUpdateNeeded} was called. */ type UpdateNeededReason = { type: 'NewClientGroup'; } | { type: 'VersionNotSupported'; versionType?: 'push' | 'pull' | 'schema' | undefined; }; /** * `AuthData` must include a `userID` which is unique stable identifier * for the user. * `AuthData` has a size limit of 6 KB. * `AuthData` is passed via {@link WriteTransaction.auth} to mutators * when they are run on the server, which can use it to supplement * mutator args and to authorize the mutation. */ type AuthData = ReadonlyJSONObject & { readonly userID: string; }; /** Environment variables. */ type Env = { readonly [key: string]: string; }; interface ReadTransaction extends ReadTransaction$1 { /** * When a mutator is run on the server, the `AuthData` for the connection * that pushed the mutation (i.e. the `AuthData` returned by the * {@link ReflectServerOptions.authHandler} when it authenticated the * connection). Always undefined on the client. This can be used to implement * fine-grained server-side authorization of mutations. */ readonly auth?: AuthData | undefined; /** * When a mutator is run on the server, `Env` contains environment variables. */ readonly env?: Env | undefined; } interface WriteTransaction extends WriteTransaction$1 { /** * When a mutator is run on the server, the `AuthData` for the connection * that pushed the mutation (i.e. the `AuthData` returned by the * {@link ReflectServerOptions.authHandler} when it authenticated the * connection). Always undefined on the client. This can be used to implement * fine-grained server-side authorization of mutations. */ readonly auth?: AuthData | undefined; /** * When a mutator is run on the server, `Env` contains environment variables. */ readonly env?: Env | undefined; } type MutatorDefs = { [key: string]: (tx: WriteTransaction, args?: any) => MutatorReturn; }; declare const ROOM_ID_REGEX: RegExp; declare function isValidRoomID(roomID: string): boolean; declare function makeInvalidRoomIDMessage(roomID: string): string; declare const version: string; export { AsyncIterableIteratorToArray, AuthData, ClientGroupID, ClientID, ClientStateNotFoundResponse, Cookie, Env, MemStore as ExperimentalMemKVStore, GetIndexScanIterator, GetScanIterator, HTTPRequestInfo, IterableUnion, JSONObject, JSONValue, MaybePromise, MutationV0, MutationV1, MutatorDefs, MutatorReturn, PatchOperation, Poke, PullRequest, PullRequestV0, PullRequestV1, PullResponse, PullResponseOKV0, PullResponseOKV1, PullResponseV0, PullResponseV1, PushRequest, PushRequestV0, PushRequestV1, PushResponse, ROOM_ID_REGEX, ReadTransaction, ReadonlyJSONObject, ReadonlyJSONValue, RequestOptions, TransactionEnvironment, TransactionLocation, TransactionReason, UpdateNeededReason, VersionNotSupportedResponse, WriteTransaction, filterAsyncIterable, isScanIndexOptions, isValidRoomID, makeIDBName, makeInvalidRoomIDMessage, makeScanResult, mergeAsyncIterables, version };