import {assertArray, assertNumber, assertObject, assertString} from './asserts';import {httpRequest} from './http-request';import {assertJSONValue, JSONValue, ReadonlyJSONValue} from './json';import type {HTTPRequestInfo} from './http-request-info';
export type PullerResult = { response?: PullResponse; httpRequestInfo: HTTPRequestInfo;};
export type Puller = (request: Request) => Promise<PullerResult>;
export type PullResponseOK = { cookie?: ReadonlyJSONValue; lastMutationID: number; patch: PatchOperation[];};
export type ClientStateNotFoundResponse = { error: 'ClientStateNotFound';};
export type PullResponse = PullResponseOK | ClientStateNotFoundResponse;
export function isClientStateNotFoundResponse( result: unknown,): result is ClientStateNotFoundResponse { return ( typeof result === 'object' && result !== null && (result as Partial<ClientStateNotFoundResponse>).error === 'ClientStateNotFound' );}
export function assertPullResponse(v: unknown): asserts v is PullResponse { if (typeof v !== 'object' || v === null) { throw new Error('PullResponse must be an object'); } if (isClientStateNotFoundResponse(v)) { return; } const v2 = v as Partial<PullResponseOK>; if (v2.cookie !== undefined) { assertJSONValue(v2.cookie); } assertNumber(v2.lastMutationID); assertPatchOperations(v2.patch);}
export type PatchOperation = | { op: 'put'; key: string; value: JSONValue; } | {op: 'del'; key: string} | {op: 'clear'};
export const defaultPuller: Puller = async request => { const {httpRequestInfo, response} = await httpRequest(request); if (httpRequestInfo.httpStatusCode !== 200) { return { httpRequestInfo, }; } return { response: await response.json(), httpRequestInfo, };};
export function assertPatchOperations( p: unknown,): asserts p is PatchOperation[] { assertArray(p); for (const item of p) { assertPatchOperation(item); }}
function assertPatchOperation(p: unknown): asserts p is PatchOperation { assertObject(p); switch (p.op) { case 'put': assertString(p.key); assertJSONValue(p.value); break; case 'del': assertString(p.key); break; case 'clear': break; default: throw new Error( `unknown patch op \`${p.op}\`, expected one of \`put\`, \`del\`, \`clear\``, ); }}
export class PullError extends Error { name = 'PullError'; causedBy?: Error; constructor(causedBy?: Error) { super('Failed to pull'); this.causedBy = causedBy; }}