@rocicorp/zero 1.10.0-canary.20 → 1.10.0-canary.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,19 @@ import type { ClientID } from '../sync/ids.ts';
8
8
  import type { MutatorDefs } from '../types.ts';
9
9
  import { type Commit, type LocalMeta, type Meta } from './commit.ts';
10
10
  type FormatVersion = Enum<typeof FormatVersion>;
11
- export declare function rebaseMutationAndPutCommit(mutation: Commit<LocalMeta>, dagWrite: DagWrite, basis: Hash, mutators: MutatorDefs, lc: LogContext, mutationClientID: ClientID, formatVersion: FormatVersion, zeroData: ZeroTxData | undefined): Promise<Commit<Meta>>;
12
- export declare function rebaseMutationAndCommit(mutation: Commit<LocalMeta>, dagWrite: DagWrite, basis: Hash, headName: string, mutators: MutatorDefs, lc: LogContext, mutationClientID: ClientID, formatVersion: FormatVersion, zeroData: ZeroTxData | undefined): Promise<Hash>;
11
+ /**
12
+ * The result of replaying one mutation.
13
+ *
14
+ * `zeroData` is the Zero transaction data to use for the next mutation in the
15
+ * same replay. Each mutation runs against its own fork. On success that fork is
16
+ * returned, and if the mutator throws the caller gets back the one it passed
17
+ * in, without the failed mutation's IVM writes. See `rebaseMutation`.
18
+ */
19
+ export type RebaseResult<T> = {
20
+ result: T;
21
+ zeroData: ZeroTxData | undefined;
22
+ };
23
+ export declare function rebaseMutationAndPutCommit(mutation: Commit<LocalMeta>, dagWrite: DagWrite, basis: Hash, mutators: MutatorDefs, lc: LogContext, mutationClientID: ClientID, formatVersion: FormatVersion, zeroData: ZeroTxData | undefined): Promise<RebaseResult<Commit<Meta>>>;
24
+ export declare function rebaseMutationAndCommit(mutation: Commit<LocalMeta>, dagWrite: DagWrite, basis: Hash, headName: string, mutators: MutatorDefs, lc: LogContext, mutationClientID: ClientID, formatVersion: FormatVersion, zeroData: ZeroTxData | undefined): Promise<RebaseResult<Hash>>;
13
25
  export {};
14
26
  //# sourceMappingURL=rebase.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rebase.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/db/rebase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,EAAC,KAAK,IAAI,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,YAAY,CAAC;AACrC,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAE7C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,aAAa,CAAC;AAC7C,OAAO,EACL,KAAK,MAAM,EACX,KAAK,SAAS,EAEd,KAAK,IAAI,EAIV,MAAM,aAAa,CAAC;AAIrB,KAAK,aAAa,GAAG,IAAI,CAAC,OAAO,aAAa,CAAC,CAAC;AA8EhD,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,EAC3B,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,WAAW,EACrB,EAAE,EAAE,UAAU,EAGd,gBAAgB,EAAE,QAAQ,EAC1B,aAAa,EAAE,aAAa,EAC5B,QAAQ,EAAE,UAAU,GAAG,SAAS,GAC/B,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAYvB;AAED,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,EAC3B,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,WAAW,EACrB,EAAE,EAAE,UAAU,EAGd,gBAAgB,EAAE,QAAQ,EAC1B,aAAa,EAAE,aAAa,EAC5B,QAAQ,EAAE,UAAU,GAAG,SAAS,GAC/B,OAAO,CAAC,IAAI,CAAC,CAYf"}
1
+ {"version":3,"file":"rebase.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/db/rebase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,EAAC,KAAK,IAAI,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,YAAY,CAAC;AACrC,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAE7C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,aAAa,CAAC;AAC7C,OAAO,EACL,KAAK,MAAM,EACX,KAAK,SAAS,EAEd,KAAK,IAAI,EAIV,MAAM,aAAa,CAAC;AAIrB,KAAK,aAAa,GAAG,IAAI,CAAC,OAAO,aAAa,CAAC,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAC5B,MAAM,EAAE,CAAC,CAAC;IACV,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAC;CAClC,CAAC;AA8GF,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,EAC3B,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,WAAW,EACrB,EAAE,EAAE,UAAU,EAGd,gBAAgB,EAAE,QAAQ,EAC1B,aAAa,EAAE,aAAa,EAC5B,QAAQ,EAAE,UAAU,GAAG,SAAS,GAC/B,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAYrC;AAED,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,EAC3B,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,WAAW,EACrB,EAAE,EAAE,UAAU,EAGd,gBAAgB,EAAE,QAAQ,EAC1B,aAAa,EAAE,aAAa,EAC5B,QAAQ,EAAE,UAAU,GAAG,SAAS,GAC/B,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAY7B"}
@@ -14,15 +14,37 @@ async function rebaseMutation(mutation, dagWrite, basisHash, mutators, lc, mutat
14
14
  const nextMutationID = await (await commitFromHash(basisHash, dagWrite)).getNextMutationID(mutationClientID, dagWrite);
15
15
  if (nextMutationID !== localMeta.mutationID) throw new Error(`Inconsistent mutation ID: original: ${localMeta.mutationID}, next: ${nextMutationID} - mutationClientID: ${mutationClientID} mutatorName: ${name}`);
16
16
  if (formatVersion >= 5) assertLocalMetaDD31(localMeta);
17
- const dbWrite = await newWriteLocal(basisHash, name, args, mutation.chunk.hash, dagWrite, localMeta.timestamp, mutationClientID, formatVersion);
18
- await mutatorImpl(new WriteTransactionImpl(mutationClientID, await dbWrite.getMutationID(), "rebase", zeroData, dbWrite, lc), args);
19
- return dbWrite;
17
+ const newWrite = () => newWriteLocal(basisHash, name, args, mutation.chunk.hash, dagWrite, localMeta.timestamp, mutationClientID, formatVersion);
18
+ const dbWrite = await newWrite();
19
+ const txData = zeroData?.fork();
20
+ const tx = new WriteTransactionImpl(mutationClientID, await dbWrite.getMutationID(), "rebase", txData, dbWrite, lc);
21
+ try {
22
+ await mutatorImpl(tx, args);
23
+ } catch (e) {
24
+ lc.info?.(`Rebase of mutator ${name} threw, abandoning its prediction`, e);
25
+ return {
26
+ result: await newWrite(),
27
+ zeroData
28
+ };
29
+ }
30
+ return {
31
+ result: dbWrite,
32
+ zeroData: txData
33
+ };
20
34
  }
21
35
  async function rebaseMutationAndPutCommit(mutation, dagWrite, basis, mutators, lc, mutationClientID, formatVersion, zeroData) {
22
- return (await rebaseMutation(mutation, dagWrite, basis, mutators, lc, mutationClientID, formatVersion, zeroData)).putCommit();
36
+ const { result: tx, zeroData: next } = await rebaseMutation(mutation, dagWrite, basis, mutators, lc, mutationClientID, formatVersion, zeroData);
37
+ return {
38
+ result: await tx.putCommit(),
39
+ zeroData: next
40
+ };
23
41
  }
24
42
  async function rebaseMutationAndCommit(mutation, dagWrite, basis, headName, mutators, lc, mutationClientID, formatVersion, zeroData) {
25
- return (await rebaseMutation(mutation, dagWrite, basis, mutators, lc, mutationClientID, formatVersion, zeroData)).commit(headName);
43
+ const { result: dbWrite, zeroData: next } = await rebaseMutation(mutation, dagWrite, basis, mutators, lc, mutationClientID, formatVersion, zeroData);
44
+ return {
45
+ result: await dbWrite.commit(headName),
46
+ zeroData: next
47
+ };
26
48
  }
27
49
  //#endregion
28
50
  export { rebaseMutationAndCommit, rebaseMutationAndPutCommit };
@@ -1 +1 @@
1
- {"version":3,"file":"rebase.js","names":[],"sources":["../../../../../replicache/src/db/rebase.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport type {Write as DagWrite} from '../dag/store.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\nimport type {ZeroTxData} from '../replicache-options.ts';\nimport type {ClientID} from '../sync/ids.ts';\nimport {WriteTransactionImpl} from '../transactions.ts';\nimport type {MutatorDefs} from '../types.ts';\nimport {\n type Commit,\n type LocalMeta,\n type LocalMetaDD31,\n type Meta,\n assertLocalMetaDD31,\n commitFromHash,\n isLocalMetaDD31,\n} from './commit.ts';\nimport type {Write} from './write.ts';\nimport {newWriteLocal} from './write.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\nasync function rebaseMutation(\n mutation: Commit<LocalMetaDD31>,\n dagWrite: DagWrite,\n basisHash: Hash,\n mutators: MutatorDefs,\n lc: LogContext,\n mutationClientID: ClientID,\n formatVersion: FormatVersion,\n zeroData: ZeroTxData | undefined,\n): Promise<Write> {\n const localMeta = mutation.meta;\n const name = localMeta.mutatorName;\n if (isLocalMetaDD31(localMeta)) {\n assert(\n localMeta.clientID === mutationClientID,\n 'mutationClientID must match clientID of LocalMeta',\n );\n }\n const maybeMutatorImpl = mutators[name];\n if (!maybeMutatorImpl) {\n // Developers must not remove mutator names from code deployed with the\n // same schemaVersion because Replicache needs to be able to replay\n // mutations during pull.\n //\n // If we detect that this has happened, stub in a no-op mutator so that at\n // least sync can move forward. Note that the server-side mutation will\n // still get sent. This doesn't remove the queued local mutation, it just\n // removes its visible effects.\n lc.error?.(`Cannot rebase unknown mutator ${name}`);\n }\n const mutatorImpl =\n maybeMutatorImpl ||\n (async () => {\n // no op\n });\n\n const args = localMeta.mutatorArgsJSON;\n\n const basisCommit = await commitFromHash(basisHash, dagWrite);\n const nextMutationID = await basisCommit.getNextMutationID(\n mutationClientID,\n dagWrite,\n );\n if (nextMutationID !== localMeta.mutationID) {\n throw new Error(\n `Inconsistent mutation ID: original: ${localMeta.mutationID}, next: ${nextMutationID} - mutationClientID: ${mutationClientID} mutatorName: ${name}`,\n );\n }\n\n if (formatVersion >= FormatVersion.DD31) {\n assertLocalMetaDD31(localMeta);\n }\n\n const dbWrite = await newWriteLocal(\n basisHash,\n name,\n args,\n mutation.chunk.hash,\n dagWrite,\n localMeta.timestamp,\n mutationClientID,\n formatVersion,\n );\n\n const tx = new WriteTransactionImpl(\n mutationClientID,\n await dbWrite.getMutationID(),\n 'rebase',\n zeroData,\n dbWrite,\n lc,\n );\n await mutatorImpl(tx, args);\n return dbWrite;\n}\n\nexport async function rebaseMutationAndPutCommit(\n mutation: Commit<LocalMeta>,\n dagWrite: DagWrite,\n basis: Hash,\n mutators: MutatorDefs,\n lc: LogContext,\n // TODO(greg): mutationClientID can be retrieved from mutation if LocalMeta\n // is a LocalMetaDD31. As part of DD31 cleanup we can remove this arg.\n mutationClientID: ClientID,\n formatVersion: FormatVersion,\n zeroData: ZeroTxData | undefined,\n): Promise<Commit<Meta>> {\n const tx = await rebaseMutation(\n mutation,\n dagWrite,\n basis,\n mutators,\n lc,\n mutationClientID,\n formatVersion,\n zeroData,\n );\n return tx.putCommit();\n}\n\nexport async function rebaseMutationAndCommit(\n mutation: Commit<LocalMeta>,\n dagWrite: DagWrite,\n basis: Hash,\n headName: string,\n mutators: MutatorDefs,\n lc: LogContext,\n // TODO(greg): mutationClientID can be retrieved from mutation if LocalMeta\n // is a LocalMetaDD31. As part of DD31 cleanup we can remove this arg.\n mutationClientID: ClientID,\n formatVersion: FormatVersion,\n zeroData: ZeroTxData | undefined,\n): Promise<Hash> {\n const dbWrite = await rebaseMutation(\n mutation,\n dagWrite,\n basis,\n mutators,\n lc,\n mutationClientID,\n formatVersion,\n zeroData,\n );\n return dbWrite.commit(headName);\n}\n"],"mappings":";;;;;AAwBA,eAAe,eACb,UACA,UACA,WACA,UACA,IACA,kBACA,eACA,UACgB;CAChB,MAAM,YAAY,SAAS;CAC3B,MAAM,OAAO,UAAU;CACvB,IAAI,gBAAgB,SAAS,GAC3B,OACE,UAAU,aAAa,kBACvB,mDACF;CAEF,MAAM,mBAAmB,SAAS;CAClC,IAAI,CAAC,kBASH,GAAG,QAAQ,iCAAiC,MAAM;CAEpD,MAAM,cACJ,qBACC,YAAY,CAEb;CAEF,MAAM,OAAO,UAAU;CAGvB,MAAM,iBAAiB,OAAM,MADH,eAAe,WAAW,QAAQ,GACnB,kBACvC,kBACA,QACF;CACA,IAAI,mBAAmB,UAAU,YAC/B,MAAM,IAAI,MACR,uCAAuC,UAAU,WAAW,UAAU,eAAe,uBAAuB,iBAAiB,gBAAgB,MAC/I;CAGF,IAAI,iBAAiB,GACnB,oBAAoB,SAAS;CAG/B,MAAM,UAAU,MAAM,cACpB,WACA,MACA,MACA,SAAS,MAAM,MACf,UACA,UAAU,WACV,kBACA,aACF;CAUA,MAAM,YAAY,IARH,qBACb,kBACA,MAAM,QAAQ,cAAc,GAC5B,UACA,UACA,SACA,EAEgB,GAAI,IAAI;CAC1B,OAAO;AACT;AAEA,eAAsB,2BACpB,UACA,UACA,OACA,UACA,IAGA,kBACA,eACA,UACuB;CAWvB,QAAO,MAVU,eACf,UACA,UACA,OACA,UACA,IACA,kBACA,eACA,QACF,GACU,UAAU;AACtB;AAEA,eAAsB,wBACpB,UACA,UACA,OACA,UACA,UACA,IAGA,kBACA,eACA,UACe;CAWf,QAAO,MAVe,eACpB,UACA,UACA,OACA,UACA,IACA,kBACA,eACA,QACF,GACe,OAAO,QAAQ;AAChC"}
1
+ {"version":3,"file":"rebase.js","names":[],"sources":["../../../../../replicache/src/db/rebase.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport type {Write as DagWrite} from '../dag/store.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\nimport type {ZeroTxData} from '../replicache-options.ts';\nimport type {ClientID} from '../sync/ids.ts';\nimport {WriteTransactionImpl} from '../transactions.ts';\nimport type {MutatorDefs} from '../types.ts';\nimport {\n type Commit,\n type LocalMeta,\n type LocalMetaDD31,\n type Meta,\n assertLocalMetaDD31,\n commitFromHash,\n isLocalMetaDD31,\n} from './commit.ts';\nimport type {Write} from './write.ts';\nimport {newWriteLocal} from './write.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\n/**\n * The result of replaying one mutation.\n *\n * `zeroData` is the Zero transaction data to use for the next mutation in the\n * same replay. Each mutation runs against its own fork. On success that fork is\n * returned, and if the mutator throws the caller gets back the one it passed\n * in, without the failed mutation's IVM writes. See `rebaseMutation`.\n */\nexport type RebaseResult<T> = {\n result: T;\n zeroData: ZeroTxData | undefined;\n};\n\nasync function rebaseMutation(\n mutation: Commit<LocalMetaDD31>,\n dagWrite: DagWrite,\n basisHash: Hash,\n mutators: MutatorDefs,\n lc: LogContext,\n mutationClientID: ClientID,\n formatVersion: FormatVersion,\n zeroData: ZeroTxData | undefined,\n): Promise<RebaseResult<Write>> {\n const localMeta = mutation.meta;\n const name = localMeta.mutatorName;\n if (isLocalMetaDD31(localMeta)) {\n assert(\n localMeta.clientID === mutationClientID,\n 'mutationClientID must match clientID of LocalMeta',\n );\n }\n const maybeMutatorImpl = mutators[name];\n if (!maybeMutatorImpl) {\n // Developers must not remove mutator names from code deployed with the\n // same schemaVersion because Replicache needs to be able to replay\n // mutations during pull.\n //\n // If we detect that this has happened, stub in a no-op mutator so that at\n // least sync can move forward. Note that the server-side mutation will\n // still get sent. This doesn't remove the queued local mutation, it just\n // removes its visible effects.\n lc.error?.(`Cannot rebase unknown mutator ${name}`);\n }\n const mutatorImpl =\n maybeMutatorImpl ||\n (async () => {\n // no op\n });\n\n const args = localMeta.mutatorArgsJSON;\n\n const basisCommit = await commitFromHash(basisHash, dagWrite);\n const nextMutationID = await basisCommit.getNextMutationID(\n mutationClientID,\n dagWrite,\n );\n if (nextMutationID !== localMeta.mutationID) {\n throw new Error(\n `Inconsistent mutation ID: original: ${localMeta.mutationID}, next: ${nextMutationID} - mutationClientID: ${mutationClientID} mutatorName: ${name}`,\n );\n }\n\n if (formatVersion >= FormatVersion.DD31) {\n assertLocalMetaDD31(localMeta);\n }\n\n const newWrite = () =>\n newWriteLocal(\n basisHash,\n name,\n args,\n mutation.chunk.hash,\n dagWrite,\n localMeta.timestamp,\n mutationClientID,\n formatVersion,\n );\n\n const dbWrite = await newWrite();\n\n // Run the mutator against a fork so that if it throws, its IVM writes are\n // discarded along with its `Write`.\n const txData = zeroData?.fork();\n\n const tx = new WriteTransactionImpl(\n mutationClientID,\n await dbWrite.getMutationID(),\n 'rebase',\n txData,\n dbWrite,\n lc,\n );\n\n try {\n await mutatorImpl(tx, args);\n } catch (e) {\n // A mutator can throw here without anything being wrong: it is being run\n // again against a newer server snapshot, so a check that passed when the\n // user first ran it can fail now. Rethrowing fails the whole rebase, which\n // in Zero fails the poke and disconnects the client. The mutation stays\n // pending, so the next poke fails the same way.\n //\n // Only the local prediction is dropped. The mutation is still pending and\n // is still sent to the server, which decides whether it applied.\n //\n // `dbWrite` is dropped rather than closed: it shares `dagWrite` with the\n // caller. Dropping it is enough because a `Write` does not modify anything\n // outside itself and only writes chunks when it is committed.\n //\n // Engine errors raised inside the mutator are retired the same way, rather\n // than being sorted out here. A client whose state was garbage collected\n // throws ChunkNotFoundError from its reads, and that is detected on its\n // next mutation, where replicache-impl converts it to a\n // ClientStateNotFoundError and calls onClientStateNotFound.\n lc.info?.(`Rebase of mutator ${name} threw, abandoning its prediction`, e);\n return {result: await newWrite(), zeroData};\n }\n\n return {result: dbWrite, zeroData: txData};\n}\n\nexport async function rebaseMutationAndPutCommit(\n mutation: Commit<LocalMeta>,\n dagWrite: DagWrite,\n basis: Hash,\n mutators: MutatorDefs,\n lc: LogContext,\n // TODO(greg): mutationClientID can be retrieved from mutation if LocalMeta\n // is a LocalMetaDD31. As part of DD31 cleanup we can remove this arg.\n mutationClientID: ClientID,\n formatVersion: FormatVersion,\n zeroData: ZeroTxData | undefined,\n): Promise<RebaseResult<Commit<Meta>>> {\n const {result: tx, zeroData: next} = await rebaseMutation(\n mutation,\n dagWrite,\n basis,\n mutators,\n lc,\n mutationClientID,\n formatVersion,\n zeroData,\n );\n return {result: await tx.putCommit(), zeroData: next};\n}\n\nexport async function rebaseMutationAndCommit(\n mutation: Commit<LocalMeta>,\n dagWrite: DagWrite,\n basis: Hash,\n headName: string,\n mutators: MutatorDefs,\n lc: LogContext,\n // TODO(greg): mutationClientID can be retrieved from mutation if LocalMeta\n // is a LocalMetaDD31. As part of DD31 cleanup we can remove this arg.\n mutationClientID: ClientID,\n formatVersion: FormatVersion,\n zeroData: ZeroTxData | undefined,\n): Promise<RebaseResult<Hash>> {\n const {result: dbWrite, zeroData: next} = await rebaseMutation(\n mutation,\n dagWrite,\n basis,\n mutators,\n lc,\n mutationClientID,\n formatVersion,\n zeroData,\n );\n return {result: await dbWrite.commit(headName), zeroData: next};\n}\n"],"mappings":";;;;;AAqCA,eAAe,eACb,UACA,UACA,WACA,UACA,IACA,kBACA,eACA,UAC8B;CAC9B,MAAM,YAAY,SAAS;CAC3B,MAAM,OAAO,UAAU;CACvB,IAAI,gBAAgB,SAAS,GAC3B,OACE,UAAU,aAAa,kBACvB,mDACF;CAEF,MAAM,mBAAmB,SAAS;CAClC,IAAI,CAAC,kBASH,GAAG,QAAQ,iCAAiC,MAAM;CAEpD,MAAM,cACJ,qBACC,YAAY,CAEb;CAEF,MAAM,OAAO,UAAU;CAGvB,MAAM,iBAAiB,OAAM,MADH,eAAe,WAAW,QAAQ,GACnB,kBACvC,kBACA,QACF;CACA,IAAI,mBAAmB,UAAU,YAC/B,MAAM,IAAI,MACR,uCAAuC,UAAU,WAAW,UAAU,eAAe,uBAAuB,iBAAiB,gBAAgB,MAC/I;CAGF,IAAI,iBAAiB,GACnB,oBAAoB,SAAS;CAG/B,MAAM,iBACJ,cACE,WACA,MACA,MACA,SAAS,MAAM,MACf,UACA,UAAU,WACV,kBACA,aACF;CAEF,MAAM,UAAU,MAAM,SAAS;CAI/B,MAAM,SAAS,UAAU,KAAK;CAE9B,MAAM,KAAK,IAAI,qBACb,kBACA,MAAM,QAAQ,cAAc,GAC5B,UACA,QACA,SACA,EACF;CAEA,IAAI;EACF,MAAM,YAAY,IAAI,IAAI;CAC5B,SAAS,GAAG;EAmBV,GAAG,OAAO,qBAAqB,KAAK,oCAAoC,CAAC;EACzE,OAAO;GAAC,QAAQ,MAAM,SAAS;GAAG;EAAQ;CAC5C;CAEA,OAAO;EAAC,QAAQ;EAAS,UAAU;CAAM;AAC3C;AAEA,eAAsB,2BACpB,UACA,UACA,OACA,UACA,IAGA,kBACA,eACA,UACqC;CACrC,MAAM,EAAC,QAAQ,IAAI,UAAU,SAAQ,MAAM,eACzC,UACA,UACA,OACA,UACA,IACA,kBACA,eACA,QACF;CACA,OAAO;EAAC,QAAQ,MAAM,GAAG,UAAU;EAAG,UAAU;CAAI;AACtD;AAEA,eAAsB,wBACpB,UACA,UACA,OACA,UACA,UACA,IAGA,kBACA,eACA,UAC6B;CAC7B,MAAM,EAAC,QAAQ,SAAS,UAAU,SAAQ,MAAM,eAC9C,UACA,UACA,OACA,UACA,IACA,kBACA,eACA,QACF;CACA,OAAO;EAAC,QAAQ,MAAM,QAAQ,OAAO,QAAQ;EAAG,UAAU;CAAI;AAChE"}
@@ -1 +1 @@
1
- {"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/persist/persist.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AAGtD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAO,KAAK,EAAQ,MAAM,iBAAiB,CAAC;AAexD,OAAO,KAAK,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAEhE,OAAO,KAAK,EAAC,UAAU,EAAa,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,EAAgB,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAC5D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,aAAa,CAAC;AAgB7C,KAAK,aAAa,GAAG,IAAI,CAAC,OAAO,aAAa,CAAC,CAAC;AAEhD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,KAAK,EACb,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,MAAM,OAAO,EACrB,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,SAAS,EAChD,4BAA4B,sBAA0B,GACrD,OAAO,CAAC,IAAI,CAAC,CA2Lf"}
1
+ {"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/persist/persist.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AAGtD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAO,KAAK,EAAQ,MAAM,iBAAiB,CAAC;AAexD,OAAO,KAAK,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAEhE,OAAO,KAAK,EAAC,UAAU,EAAa,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,EAAgB,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAC5D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,aAAa,CAAC;AAgB7C,KAAK,aAAa,GAAG,IAAI,CAAC,OAAO,aAAa,CAAC,CAAC;AAEhD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,KAAK,EACb,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,MAAM,OAAO,EACrB,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,SAAS,EAChD,4BAA4B,sBAA0B,GACrD,OAAO,CAAC,IAAI,CAAC,CAmMf"}
@@ -63,7 +63,7 @@ async function persistDD31(lc, clientID, memdag, perdag, mutators, closed, forma
63
63
  });
64
64
  if (closed()) return;
65
65
  let memdagBaseSnapshotPersisted = false;
66
- const zeroDataForMemdagBaseSnapshot = getZeroData && await getZeroData(memdagBaseSnapshot.chunk.hash);
66
+ let zeroDataForRebase = getZeroData && await getZeroData(memdagBaseSnapshot.chunk.hash);
67
67
  await withWrite(perdag, async (perdagWrite) => {
68
68
  const [mainClientGroup, latestPerdagMainClientGroupHeadCommit] = await getClientGroupInfo(perdagWrite, mainClientGroupID);
69
69
  let newMainClientGroupHeadHash = latestPerdagMainClientGroupHeadCommit.chunk.hash;
@@ -85,12 +85,14 @@ async function persistDD31(lc, clientID, memdag, perdag, mutators, closed, forma
85
85
  const mainClientGroupLocalMutations = await localMutationsDD31(mainClientGroup.headHash, perdagWrite);
86
86
  lastServerAckdMutationIDs = memdagBaseSnapshot.meta.lastMutationIDs;
87
87
  mutationIDs = { ...lastServerAckdMutationIDs };
88
- newMainClientGroupHeadHash = await rebase(mainClientGroupLocalMutations, newMainClientGroupHeadHash, perdagWrite, mutators, mutationIDs, lc, formatVersion, zeroDataForMemdagBaseSnapshot);
88
+ const rebased = await rebase(mainClientGroupLocalMutations, newMainClientGroupHeadHash, perdagWrite, mutators, mutationIDs, lc, formatVersion, zeroDataForRebase);
89
+ newMainClientGroupHeadHash = rebased.hash;
90
+ zeroDataForRebase = rebased.zeroData;
89
91
  }
90
92
  }
91
93
  let zeroDataForPerdagHeadCommit;
92
94
  if (!memdagBaseSnapshotPersisted) zeroDataForPerdagHeadCommit = getZeroData && await getZeroData(newMainClientGroupHeadHash, { openLazySourceRead: perdagWrite });
93
- newMainClientGroupHeadHash = await rebase(newMemdagMutations, newMainClientGroupHeadHash, perdagWrite, mutators, mutationIDs, lc, formatVersion, zeroDataForPerdagHeadCommit ?? zeroDataForMemdagBaseSnapshot);
95
+ newMainClientGroupHeadHash = (await rebase(newMemdagMutations, newMainClientGroupHeadHash, perdagWrite, mutators, mutationIDs, lc, formatVersion, zeroDataForPerdagHeadCommit ?? zeroDataForRebase)).hash;
94
96
  await setClientGroup(mainClientGroupID, {
95
97
  ...mainClientGroup,
96
98
  headHash: newMainClientGroupHeadHash,
@@ -113,10 +115,15 @@ async function rebase(mutations, basis, write, mutators, mutationIDs, lc, format
113
115
  const { meta } = mutationCommit;
114
116
  if (meta.mutationID > await getBasisMutationID(basis, meta.clientID)) {
115
117
  mutationIDs[meta.clientID] = meta.mutationID;
116
- basis = (await rebaseMutationAndPutCommit(mutationCommit, write, basis, mutators, lc, meta.clientID, formatVersion, zeroData)).chunk.hash;
118
+ const { result, zeroData: next } = await rebaseMutationAndPutCommit(mutationCommit, write, basis, mutators, lc, meta.clientID, formatVersion, zeroData);
119
+ basis = result.chunk.hash;
120
+ zeroData = next;
117
121
  }
118
122
  }
119
- return basis;
123
+ return {
124
+ hash: basis,
125
+ zeroData
126
+ };
120
127
  }
121
128
  //#endregion
122
129
  export { persistDD31 };
@@ -1 +1 @@
1
- {"version":3,"file":"persist.js","names":[],"sources":["../../../../../replicache/src/persist/persist.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport {getOrInsert, getOrInsertComputed} from '../../../shared/src/map.ts';\nimport type {Chunk} from '../dag/chunk.ts';\nimport type {LazyStore} from '../dag/lazy-store.ts';\nimport type {Read, Store, Write} from '../dag/store.ts';\nimport type {Commit} from '../db/commit.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type LocalMetaDD31,\n type Meta,\n assertSnapshotCommitDD31,\n baseSnapshotFromCommit,\n commitFromHash,\n commitFromHead,\n compareCookiesForSnapshots,\n localMutationsDD31,\n localMutationsGreaterThan,\n} from '../db/commit.ts';\nimport {rebaseMutationAndPutCommit} from '../db/rebase.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\nimport type {ZeroOption, ZeroTxData} from '../replicache-options.ts';\nimport type {ClientGroupID, ClientID} from '../sync/ids.ts';\nimport type {MutatorDefs} from '../types.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n type ClientGroup,\n getClientGroup,\n setClientGroup,\n} from './client-groups.ts';\nimport {\n assertClientV6,\n assertHasClientState,\n getClientGroupIDForClient,\n mustGetClient,\n setClient,\n} from './clients.ts';\nimport {GatherMemoryOnlyVisitor} from './gather-mem-only-visitor.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\n/**\n * Persists the client's memdag state to the client's perdag client group.\n *\n * Persists the base snapshot from memdag to the client's perdag client group,\n * but only if it’s newer than the client's perdag client group’s base snapshot.\n * The base snapshot is persisted by gathering all memory-only chunks in the dag\n * subgraph rooted at the base snapshot's commit and writing them to the perdag.\n * Once the base snapshot is persisted, rebases onto this new base snapshot all\n * local commits from the client's perdag client group that are not already\n * reflected in the base snapshot.\n *\n * Whether or not the base snapshot is persisted, rebases onto the client's\n * perdag client group all memdag local commits not already in the client's\n * perdag client group's history.\n *\n * Also updates the `lastMutationIDs` and `lastServerAckdMutationIDs` properties\n * of the client's client group's entry in the `ClientGroupMap`.\n */\nexport async function persistDD31(\n lc: LogContext,\n clientID: ClientID,\n memdag: LazyStore,\n perdag: Store,\n mutators: MutatorDefs,\n closed: () => boolean,\n formatVersion: FormatVersion,\n getZeroData: ZeroOption['getTxData'] | undefined,\n onGatherMemOnlyChunksForTest = () => Promise.resolve(),\n): Promise<void> {\n if (closed()) {\n return;\n }\n\n const [perdagLMID, perdagBaseSnapshot, mainClientGroupID] = await withRead(\n perdag,\n async perdagRead => {\n await assertHasClientState(clientID, perdagRead);\n const mainClientGroupID = await getClientGroupIDForClient(\n clientID,\n perdagRead,\n );\n assert(\n mainClientGroupID,\n `No main client group for clientID: ${clientID}`,\n );\n const [, perdagMainClientGroupHeadCommit] = await getClientGroupInfo(\n perdagRead,\n mainClientGroupID,\n );\n const perdagLMID = await perdagMainClientGroupHeadCommit.getMutationID(\n clientID,\n perdagRead,\n );\n const perdagBaseSnapshot = await baseSnapshotFromCommit(\n perdagMainClientGroupHeadCommit,\n perdagRead,\n );\n assertSnapshotCommitDD31(perdagBaseSnapshot);\n return [perdagLMID, perdagBaseSnapshot, mainClientGroupID];\n },\n );\n\n if (closed()) {\n return;\n }\n const [newMemdagMutations, memdagBaseSnapshot, gatheredChunks] =\n await withRead(memdag, async memdagRead => {\n const memdagHeadCommit = await commitFromHead(\n DEFAULT_HEAD_NAME,\n memdagRead,\n );\n const newMutations = await localMutationsGreaterThan(\n memdagHeadCommit,\n {[clientID]: perdagLMID || 0},\n memdagRead,\n );\n const memdagBaseSnapshot = await baseSnapshotFromCommit(\n memdagHeadCommit,\n memdagRead,\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n\n let gatheredChunks: ReadonlyMap<Hash, Chunk> | undefined;\n if (\n compareCookiesForSnapshots(memdagBaseSnapshot, perdagBaseSnapshot) > 0\n ) {\n await onGatherMemOnlyChunksForTest();\n // Might need to persist snapshot, we will have to double check\n // after gathering the snapshot chunks from memdag\n const memdagBaseSnapshotHash = memdagBaseSnapshot.chunk.hash;\n // Gather all memory only chunks from base snapshot on the memdag.\n const visitor = new GatherMemoryOnlyVisitor(memdagRead);\n await visitor.visit(memdagBaseSnapshotHash);\n gatheredChunks = visitor.gatheredChunks;\n }\n\n return [newMutations, memdagBaseSnapshot, gatheredChunks];\n });\n\n if (closed()) {\n return;\n }\n\n let memdagBaseSnapshotPersisted = false;\n const zeroDataForMemdagBaseSnapshot =\n getZeroData && (await getZeroData(memdagBaseSnapshot.chunk.hash));\n\n await withWrite(perdag, async perdagWrite => {\n const [mainClientGroup, latestPerdagMainClientGroupHeadCommit] =\n await getClientGroupInfo(perdagWrite, mainClientGroupID);\n\n // These initial values for newMainClientGroupHeadHash, mutationIDs,\n // lastServerAckdMutationIDs are correct for the case where the memdag\n // snapshot is *not* persisted. If the memdag snapshot is persisted\n // these values are overwritten appropriately.\n let newMainClientGroupHeadHash: Hash =\n latestPerdagMainClientGroupHeadCommit.chunk.hash;\n let mutationIDs: Record<ClientID, number> = {\n ...mainClientGroup.mutationIDs,\n };\n let {lastServerAckdMutationIDs} = mainClientGroup;\n\n if (gatheredChunks) {\n // check if memdag snapshot still newer than perdag snapshot\n\n const client = await mustGetClient(clientID, perdagWrite);\n assertClientV6(client);\n\n const latestPerdagBaseSnapshot = await baseSnapshotFromCommit(\n latestPerdagMainClientGroupHeadCommit,\n perdagWrite,\n );\n assertSnapshotCommitDD31(latestPerdagBaseSnapshot);\n\n // check if memdag snapshot still newer than perdag snapshot\n if (\n compareCookiesForSnapshots(\n memdagBaseSnapshot,\n latestPerdagBaseSnapshot,\n ) > 0\n ) {\n // still newer, persist memdag snapshot by writing chunks\n memdagBaseSnapshotPersisted = true;\n await Promise.all(\n Array.from(gatheredChunks.values(), c => perdagWrite.putChunk(c)),\n );\n\n await setClient(\n clientID,\n {\n ...client,\n persistHash: memdagBaseSnapshot.chunk.hash,\n },\n perdagWrite,\n );\n // Rebase local mutations from perdag main client group onto new\n // snapshot\n newMainClientGroupHeadHash = memdagBaseSnapshot.chunk.hash;\n const mainClientGroupLocalMutations = await localMutationsDD31(\n mainClientGroup.headHash,\n perdagWrite,\n );\n\n lastServerAckdMutationIDs = memdagBaseSnapshot.meta.lastMutationIDs;\n mutationIDs = {...lastServerAckdMutationIDs};\n\n newMainClientGroupHeadHash = await rebase(\n mainClientGroupLocalMutations,\n newMainClientGroupHeadHash,\n perdagWrite,\n mutators,\n mutationIDs,\n lc,\n formatVersion,\n zeroDataForMemdagBaseSnapshot,\n );\n }\n }\n\n let zeroDataForPerdagHeadCommit: ZeroTxData | undefined;\n if (!memdagBaseSnapshotPersisted) {\n zeroDataForPerdagHeadCommit =\n getZeroData &&\n (await getZeroData(newMainClientGroupHeadHash, {\n openLazySourceRead: perdagWrite,\n }));\n }\n\n // rebase new memdag mutations onto perdag\n newMainClientGroupHeadHash = await rebase(\n newMemdagMutations,\n newMainClientGroupHeadHash,\n perdagWrite,\n mutators,\n mutationIDs,\n lc,\n formatVersion,\n zeroDataForPerdagHeadCommit ?? zeroDataForMemdagBaseSnapshot,\n );\n\n const newMainClientGroup = {\n ...mainClientGroup,\n headHash: newMainClientGroupHeadHash,\n mutationIDs,\n lastServerAckdMutationIDs,\n };\n\n await setClientGroup(mainClientGroupID, newMainClientGroup, perdagWrite);\n });\n\n if (gatheredChunks && memdagBaseSnapshotPersisted) {\n await withWrite(memdag, memdagWrite =>\n memdagWrite.chunksPersisted([...gatheredChunks.keys()]),\n );\n }\n}\n\nasync function getClientGroupInfo(\n perdagRead: Read,\n clientGroupID: ClientGroupID,\n): Promise<[ClientGroup, Commit<Meta>]> {\n const clientGroup = await getClientGroup(clientGroupID, perdagRead);\n assert(clientGroup, `No client group for clientGroupID: ${clientGroupID}`);\n return [clientGroup, await commitFromHash(clientGroup.headHash, perdagRead)];\n}\n\nasync function rebase(\n mutations: Commit<LocalMetaDD31>[],\n basis: Hash,\n write: Write,\n mutators: MutatorDefs,\n mutationIDs: Record<ClientID, number>,\n lc: LogContext,\n formatVersion: FormatVersion,\n zeroData: ZeroTxData | undefined,\n): Promise<Hash> {\n const basisMutationIDs = new Map<Hash, Map<ClientID, Promise<number>>>();\n const getBasisMutationID = (\n basisHash: Hash,\n clientID: ClientID,\n ): Promise<number> =>\n getOrInsertComputed(\n getOrInsert(basisMutationIDs, basisHash, new Map()),\n clientID,\n () =>\n commitFromHash(basisHash, write).then(commit =>\n commit.getMutationID(clientID, write),\n ),\n );\n for (let i = mutations.length - 1; i >= 0; i--) {\n const mutationCommit = mutations[i];\n const {meta} = mutationCommit;\n if (meta.mutationID > (await getBasisMutationID(basis, meta.clientID))) {\n mutationIDs[meta.clientID] = meta.mutationID;\n basis = (\n await rebaseMutationAndPutCommit(\n mutationCommit,\n write,\n basis,\n mutators,\n lc,\n meta.clientID,\n formatVersion,\n zeroData,\n )\n ).chunk.hash;\n }\n }\n return basis;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"persist.js","names":[],"sources":["../../../../../replicache/src/persist/persist.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport {getOrInsert, getOrInsertComputed} from '../../../shared/src/map.ts';\nimport type {Chunk} from '../dag/chunk.ts';\nimport type {LazyStore} from '../dag/lazy-store.ts';\nimport type {Read, Store, Write} from '../dag/store.ts';\nimport type {Commit} from '../db/commit.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type LocalMetaDD31,\n type Meta,\n assertSnapshotCommitDD31,\n baseSnapshotFromCommit,\n commitFromHash,\n commitFromHead,\n compareCookiesForSnapshots,\n localMutationsDD31,\n localMutationsGreaterThan,\n} from '../db/commit.ts';\nimport {rebaseMutationAndPutCommit} from '../db/rebase.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\nimport type {ZeroOption, ZeroTxData} from '../replicache-options.ts';\nimport type {ClientGroupID, ClientID} from '../sync/ids.ts';\nimport type {MutatorDefs} from '../types.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n type ClientGroup,\n getClientGroup,\n setClientGroup,\n} from './client-groups.ts';\nimport {\n assertClientV6,\n assertHasClientState,\n getClientGroupIDForClient,\n mustGetClient,\n setClient,\n} from './clients.ts';\nimport {GatherMemoryOnlyVisitor} from './gather-mem-only-visitor.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\n/**\n * Persists the client's memdag state to the client's perdag client group.\n *\n * Persists the base snapshot from memdag to the client's perdag client group,\n * but only if it’s newer than the client's perdag client group’s base snapshot.\n * The base snapshot is persisted by gathering all memory-only chunks in the dag\n * subgraph rooted at the base snapshot's commit and writing them to the perdag.\n * Once the base snapshot is persisted, rebases onto this new base snapshot all\n * local commits from the client's perdag client group that are not already\n * reflected in the base snapshot.\n *\n * Whether or not the base snapshot is persisted, rebases onto the client's\n * perdag client group all memdag local commits not already in the client's\n * perdag client group's history.\n *\n * Also updates the `lastMutationIDs` and `lastServerAckdMutationIDs` properties\n * of the client's client group's entry in the `ClientGroupMap`.\n */\nexport async function persistDD31(\n lc: LogContext,\n clientID: ClientID,\n memdag: LazyStore,\n perdag: Store,\n mutators: MutatorDefs,\n closed: () => boolean,\n formatVersion: FormatVersion,\n getZeroData: ZeroOption['getTxData'] | undefined,\n onGatherMemOnlyChunksForTest = () => Promise.resolve(),\n): Promise<void> {\n if (closed()) {\n return;\n }\n\n const [perdagLMID, perdagBaseSnapshot, mainClientGroupID] = await withRead(\n perdag,\n async perdagRead => {\n await assertHasClientState(clientID, perdagRead);\n const mainClientGroupID = await getClientGroupIDForClient(\n clientID,\n perdagRead,\n );\n assert(\n mainClientGroupID,\n `No main client group for clientID: ${clientID}`,\n );\n const [, perdagMainClientGroupHeadCommit] = await getClientGroupInfo(\n perdagRead,\n mainClientGroupID,\n );\n const perdagLMID = await perdagMainClientGroupHeadCommit.getMutationID(\n clientID,\n perdagRead,\n );\n const perdagBaseSnapshot = await baseSnapshotFromCommit(\n perdagMainClientGroupHeadCommit,\n perdagRead,\n );\n assertSnapshotCommitDD31(perdagBaseSnapshot);\n return [perdagLMID, perdagBaseSnapshot, mainClientGroupID];\n },\n );\n\n if (closed()) {\n return;\n }\n const [newMemdagMutations, memdagBaseSnapshot, gatheredChunks] =\n await withRead(memdag, async memdagRead => {\n const memdagHeadCommit = await commitFromHead(\n DEFAULT_HEAD_NAME,\n memdagRead,\n );\n const newMutations = await localMutationsGreaterThan(\n memdagHeadCommit,\n {[clientID]: perdagLMID || 0},\n memdagRead,\n );\n const memdagBaseSnapshot = await baseSnapshotFromCommit(\n memdagHeadCommit,\n memdagRead,\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n\n let gatheredChunks: ReadonlyMap<Hash, Chunk> | undefined;\n if (\n compareCookiesForSnapshots(memdagBaseSnapshot, perdagBaseSnapshot) > 0\n ) {\n await onGatherMemOnlyChunksForTest();\n // Might need to persist snapshot, we will have to double check\n // after gathering the snapshot chunks from memdag\n const memdagBaseSnapshotHash = memdagBaseSnapshot.chunk.hash;\n // Gather all memory only chunks from base snapshot on the memdag.\n const visitor = new GatherMemoryOnlyVisitor(memdagRead);\n await visitor.visit(memdagBaseSnapshotHash);\n gatheredChunks = visitor.gatheredChunks;\n }\n\n return [newMutations, memdagBaseSnapshot, gatheredChunks];\n });\n\n if (closed()) {\n return;\n }\n\n let memdagBaseSnapshotPersisted = false;\n // Carried across both rebase batches below: each batch continues from the\n // branch the previous one ended on.\n let zeroDataForRebase =\n getZeroData && (await getZeroData(memdagBaseSnapshot.chunk.hash));\n\n await withWrite(perdag, async perdagWrite => {\n const [mainClientGroup, latestPerdagMainClientGroupHeadCommit] =\n await getClientGroupInfo(perdagWrite, mainClientGroupID);\n\n // These initial values for newMainClientGroupHeadHash, mutationIDs,\n // lastServerAckdMutationIDs are correct for the case where the memdag\n // snapshot is *not* persisted. If the memdag snapshot is persisted\n // these values are overwritten appropriately.\n let newMainClientGroupHeadHash: Hash =\n latestPerdagMainClientGroupHeadCommit.chunk.hash;\n let mutationIDs: Record<ClientID, number> = {\n ...mainClientGroup.mutationIDs,\n };\n let {lastServerAckdMutationIDs} = mainClientGroup;\n\n if (gatheredChunks) {\n // check if memdag snapshot still newer than perdag snapshot\n\n const client = await mustGetClient(clientID, perdagWrite);\n assertClientV6(client);\n\n const latestPerdagBaseSnapshot = await baseSnapshotFromCommit(\n latestPerdagMainClientGroupHeadCommit,\n perdagWrite,\n );\n assertSnapshotCommitDD31(latestPerdagBaseSnapshot);\n\n // check if memdag snapshot still newer than perdag snapshot\n if (\n compareCookiesForSnapshots(\n memdagBaseSnapshot,\n latestPerdagBaseSnapshot,\n ) > 0\n ) {\n // still newer, persist memdag snapshot by writing chunks\n memdagBaseSnapshotPersisted = true;\n await Promise.all(\n Array.from(gatheredChunks.values(), c => perdagWrite.putChunk(c)),\n );\n\n await setClient(\n clientID,\n {\n ...client,\n persistHash: memdagBaseSnapshot.chunk.hash,\n },\n perdagWrite,\n );\n // Rebase local mutations from perdag main client group onto new\n // snapshot\n newMainClientGroupHeadHash = memdagBaseSnapshot.chunk.hash;\n const mainClientGroupLocalMutations = await localMutationsDD31(\n mainClientGroup.headHash,\n perdagWrite,\n );\n\n lastServerAckdMutationIDs = memdagBaseSnapshot.meta.lastMutationIDs;\n mutationIDs = {...lastServerAckdMutationIDs};\n\n const rebased = await rebase(\n mainClientGroupLocalMutations,\n newMainClientGroupHeadHash,\n perdagWrite,\n mutators,\n mutationIDs,\n lc,\n formatVersion,\n zeroDataForRebase,\n );\n newMainClientGroupHeadHash = rebased.hash;\n // The mutations rebased below run after these, so they have to see\n // what these wrote.\n zeroDataForRebase = rebased.zeroData;\n }\n }\n\n let zeroDataForPerdagHeadCommit: ZeroTxData | undefined;\n if (!memdagBaseSnapshotPersisted) {\n zeroDataForPerdagHeadCommit =\n getZeroData &&\n (await getZeroData(newMainClientGroupHeadHash, {\n openLazySourceRead: perdagWrite,\n }));\n }\n\n // rebase new memdag mutations onto perdag\n newMainClientGroupHeadHash = (\n await rebase(\n newMemdagMutations,\n newMainClientGroupHeadHash,\n perdagWrite,\n mutators,\n mutationIDs,\n lc,\n formatVersion,\n zeroDataForPerdagHeadCommit ?? zeroDataForRebase,\n )\n ).hash;\n\n const newMainClientGroup = {\n ...mainClientGroup,\n headHash: newMainClientGroupHeadHash,\n mutationIDs,\n lastServerAckdMutationIDs,\n };\n\n await setClientGroup(mainClientGroupID, newMainClientGroup, perdagWrite);\n });\n\n if (gatheredChunks && memdagBaseSnapshotPersisted) {\n await withWrite(memdag, memdagWrite =>\n memdagWrite.chunksPersisted([...gatheredChunks.keys()]),\n );\n }\n}\n\nasync function getClientGroupInfo(\n perdagRead: Read,\n clientGroupID: ClientGroupID,\n): Promise<[ClientGroup, Commit<Meta>]> {\n const clientGroup = await getClientGroup(clientGroupID, perdagRead);\n assert(clientGroup, `No client group for clientGroupID: ${clientGroupID}`);\n return [clientGroup, await commitFromHash(clientGroup.headHash, perdagRead)];\n}\n\ntype RebasedBatch = {\n hash: Hash;\n zeroData: ZeroTxData | undefined;\n};\n\nasync function rebase(\n mutations: Commit<LocalMetaDD31>[],\n basis: Hash,\n write: Write,\n mutators: MutatorDefs,\n mutationIDs: Record<ClientID, number>,\n lc: LogContext,\n formatVersion: FormatVersion,\n zeroData: ZeroTxData | undefined,\n): Promise<RebasedBatch> {\n const basisMutationIDs = new Map<Hash, Map<ClientID, Promise<number>>>();\n const getBasisMutationID = (\n basisHash: Hash,\n clientID: ClientID,\n ): Promise<number> =>\n getOrInsertComputed(\n getOrInsert(basisMutationIDs, basisHash, new Map()),\n clientID,\n () =>\n commitFromHash(basisHash, write).then(commit =>\n commit.getMutationID(clientID, write),\n ),\n );\n for (let i = mutations.length - 1; i >= 0; i--) {\n const mutationCommit = mutations[i];\n const {meta} = mutationCommit;\n if (meta.mutationID > (await getBasisMutationID(basis, meta.clientID))) {\n mutationIDs[meta.clientID] = meta.mutationID;\n const {result, zeroData: next} = await rebaseMutationAndPutCommit(\n mutationCommit,\n write,\n basis,\n mutators,\n lc,\n meta.clientID,\n formatVersion,\n zeroData,\n );\n basis = result.chunk.hash;\n zeroData = next;\n }\n }\n return {hash: basis, zeroData};\n}\n"],"mappings":"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"}
@@ -58,8 +58,12 @@ async function refresh(lc, memdag, perdag, clientID, mutators, diffConfig, close
58
58
  await Promise.all(ps);
59
59
  let newMemdagHeadHash = perdagClientGroupHeadHash;
60
60
  if (newMemdagMutations.length > 0) {
61
- const zeroData = await zero?.getTxData?.(newMemdagHeadHash, { openLazyRead: memdagWrite });
62
- for (let i = newMemdagMutations.length - 1; i >= 0; i--) newMemdagHeadHash = (await rebaseMutationAndPutCommit(newMemdagMutations[i], memdagWrite, newMemdagHeadHash, mutators, lc, newMemdagMutations[i].meta.clientID, formatVersion, zeroData)).chunk.hash;
61
+ let zeroData = await zero?.getTxData?.(newMemdagHeadHash, { openLazyRead: memdagWrite });
62
+ for (let i = newMemdagMutations.length - 1; i >= 0; i--) {
63
+ const { result, zeroData: next } = await rebaseMutationAndPutCommit(newMemdagMutations[i], memdagWrite, newMemdagHeadHash, mutators, lc, newMemdagMutations[i].meta.clientID, formatVersion, zeroData);
64
+ newMemdagHeadHash = result.chunk.hash;
65
+ zeroData = next;
66
+ }
63
67
  }
64
68
  const diffs = await diffCommits(memdagHeadCommit, await commitFromHash(newMemdagHeadHash, memdagWrite), memdagWrite, diffConfig, formatVersion);
65
69
  await memdagWrite.setHead(DEFAULT_HEAD_NAME, newMemdagHeadHash);
@@ -1 +1 @@
1
- {"version":3,"file":"refresh.js","names":[],"sources":["../../../../../replicache/src/persist/refresh.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport type {LazyStore} from '../dag/lazy-store.ts';\nimport type {Store} from '../dag/store.ts';\nimport type {Commit} from '../db/commit.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type SnapshotMetaDD31,\n assertSnapshotCommitDD31,\n baseSnapshotFromCommit,\n baseSnapshotFromHash,\n baseSnapshotFromHead,\n commitFromHash,\n commitFromHead,\n compareCookiesForSnapshots,\n localMutationsGreaterThan,\n} from '../db/commit.ts';\nimport {rebaseMutationAndPutCommit} from '../db/rebase.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\nimport type {ZeroOption} from '../replicache-options.ts';\nimport type {DiffsMap} from '../sync/diff.ts';\nimport {type DiffComputationConfig, diffCommits} from '../sync/diff.ts';\nimport type {ClientID} from '../sync/ids.ts';\nimport type {MutatorDefs} from '../types.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n ClientStateNotFoundError,\n type ClientV6,\n assertClientV6,\n getClientGroupForClient,\n mustGetClient,\n setClient,\n} from './clients.ts';\nimport {\n type ChunkWithSize,\n GatherNotCachedVisitor,\n} from './gather-not-cached-visitor.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\nconst GATHER_SIZE_LIMIT = 5 * 2 ** 20; // 5 MB\n\ntype RefreshResult =\n | {\n type: 'aborted';\n refreshHashesForRevert?: readonly Hash[] | undefined;\n }\n | {\n type: 'complete';\n diffs: DiffsMap;\n newPerdagClientHeadHash: Hash;\n oldHead: Hash;\n newHead: Hash;\n };\n\n/**\n * This returns the diff between the state of the btree before and after\n * refresh. It returns `undefined` if the refresh was aborted.\n */\nexport async function refresh(\n lc: LogContext,\n memdag: LazyStore,\n perdag: Store,\n clientID: ClientID,\n mutators: MutatorDefs,\n diffConfig: DiffComputationConfig,\n closed: () => boolean,\n formatVersion: FormatVersion,\n zero: ZeroOption | undefined,\n): Promise<{oldHead: Hash; newHead: Hash; diffs: DiffsMap} | undefined> {\n if (closed()) {\n return;\n }\n const memdagBaseSnapshot = await withRead(memdag, memdagRead =>\n baseSnapshotFromHead(DEFAULT_HEAD_NAME, memdagRead),\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n\n type PerdagWriteResult = [\n perdagClientGroupHeadHash: Hash,\n perdagClientGroupBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagLmid: number,\n gatheredChunks: ReadonlyMap<Hash, ChunkWithSize>,\n refreshHashesForRevert: readonly Hash[],\n ];\n\n // Suspend eviction and deletion of chunks cached by the lazy store\n // to prevent cache misses. If eviction and deletion are not suspended\n // some chunks that are not gathered due to already being cached, may be\n // evicted or deleted by the time the write lock is acquired on the memdag,\n // which can lead to cache misses when performing the rebase and diff.\n // It is important to avoid these cache misses because they often create jank\n // because they block local mutations, pulls and queries on reading from idb.\n // Cache misses can still happen during the rebase and diff, but only\n // if the gather step hits its size limit.\n const result: RefreshResult =\n await memdag.withSuspendedSourceCacheEvictsAndDeletes(async () => {\n const perdagWriteResult: PerdagWriteResult | undefined = await withWrite(\n perdag,\n async perdagWrite => {\n const clientGroup = await getClientGroupForClient(\n clientID,\n perdagWrite,\n );\n if (!clientGroup) {\n throw new ClientStateNotFoundError(clientID);\n }\n\n const perdagClientGroupHeadHash = clientGroup.headHash;\n const perdagClientGroupHeadCommit = await commitFromHash(\n perdagClientGroupHeadHash,\n perdagWrite,\n );\n const perdagLmid = await perdagClientGroupHeadCommit.getMutationID(\n clientID,\n perdagWrite,\n );\n\n // Need to pull this head into memdag, but can't have it disappear if\n // perdag moves forward while we're rebasing in memdag. Can't change\n // client headHash until our rebase in memdag is complete, because if\n // rebase fails, then nothing is keeping client's chunks alive in\n // perdag.\n const client = await mustGetClient(clientID, perdagWrite);\n assertClientV6(client);\n const perdagClientGroupBaseSnapshot = await baseSnapshotFromHash(\n perdagClientGroupHeadHash,\n perdagWrite,\n );\n assertSnapshotCommitDD31(perdagClientGroupBaseSnapshot);\n if (\n shouldAbortRefresh(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n perdagClientGroupHeadHash,\n )\n ) {\n return undefined;\n }\n\n // To avoid pulling the entire perdag graph into the memdag\n // the amount of chunk data gathered is limited by size.\n const visitor = new GatherNotCachedVisitor(\n perdagWrite,\n memdag,\n GATHER_SIZE_LIMIT,\n );\n await visitor.visit(perdagClientGroupHeadHash);\n const {gatheredChunks} = visitor;\n\n const refreshHashesSet = new Set(client.refreshHashes);\n refreshHashesSet.add(perdagClientGroupHeadHash);\n\n const newClient: ClientV6 = {\n ...client,\n refreshHashes: [...refreshHashesSet],\n };\n\n await setClient(clientID, newClient, perdagWrite);\n return [\n perdagClientGroupHeadHash,\n perdagClientGroupBaseSnapshot,\n perdagLmid,\n gatheredChunks,\n client.refreshHashes,\n ];\n },\n );\n\n if (closed() || !perdagWriteResult) {\n return {\n type: 'aborted',\n } as const;\n }\n\n const [\n perdagClientGroupHeadHash,\n perdagClientGroupBaseSnapshot,\n perdagLmid,\n gatheredChunks,\n refreshHashesForRevert,\n ] = perdagWriteResult;\n return withWrite(memdag, async memdagWrite => {\n const memdagHeadCommit = await commitFromHead(\n DEFAULT_HEAD_NAME,\n memdagWrite,\n );\n const memdagBaseSnapshot = await baseSnapshotFromCommit(\n memdagHeadCommit,\n memdagWrite,\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n if (\n shouldAbortRefresh(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n perdagClientGroupHeadHash,\n )\n ) {\n return {\n type: 'aborted',\n refreshHashesForRevert,\n };\n }\n\n const newMemdagMutations = await localMutationsGreaterThan(\n memdagHeadCommit,\n {[clientID]: perdagLmid},\n memdagWrite,\n );\n const ps = [];\n for (const {chunk, size} of gatheredChunks.values()) {\n ps.push(memdagWrite.putChunk(chunk, size));\n }\n await Promise.all(ps);\n\n let newMemdagHeadHash = perdagClientGroupHeadHash;\n if (newMemdagMutations.length > 0) {\n const zeroData = await zero?.getTxData?.(newMemdagHeadHash, {\n openLazyRead: memdagWrite,\n });\n for (let i = newMemdagMutations.length - 1; i >= 0; i--) {\n newMemdagHeadHash = (\n await rebaseMutationAndPutCommit(\n newMemdagMutations[i],\n memdagWrite,\n newMemdagHeadHash,\n mutators,\n lc,\n newMemdagMutations[i].meta.clientID,\n formatVersion,\n zeroData,\n )\n ).chunk.hash;\n }\n }\n\n const newMemdagHeadCommit = await commitFromHash(\n newMemdagHeadHash,\n memdagWrite,\n );\n const diffs = await diffCommits(\n memdagHeadCommit,\n newMemdagHeadCommit,\n memdagWrite,\n diffConfig,\n formatVersion,\n );\n\n await memdagWrite.setHead(DEFAULT_HEAD_NAME, newMemdagHeadHash);\n return {\n type: 'complete',\n diffs,\n oldHead: memdagHeadCommit.chunk.hash,\n newHead: newMemdagHeadHash,\n newPerdagClientHeadHash: perdagClientGroupHeadHash,\n } as const;\n });\n });\n\n if (closed()) {\n return;\n }\n\n const setRefreshHashes = (refreshHashes: readonly Hash[]) =>\n withWrite(perdag, async perdagWrite => {\n const client = await mustGetClient(clientID, perdagWrite);\n const newClient = {\n ...client,\n refreshHashes,\n };\n\n // If this cleanup never happens, it's no big deal, some data will stay\n // alive longer but next refresh will fix it.\n await setClient(clientID, newClient, perdagWrite);\n });\n\n if (result.type === 'aborted') {\n if (result.refreshHashesForRevert) {\n await setRefreshHashes(result.refreshHashesForRevert);\n }\n return undefined;\n }\n\n // Advance zero here before setting refresh hashes\n // since we must advance before delegating control of the microtask\n // loop.\n zero?.advance(result.oldHead, result.newHead, result.diffs.get('') ?? []);\n await setRefreshHashes([result.newPerdagClientHeadHash]);\n return {\n oldHead: result.oldHead,\n newHead: result.newHead,\n diffs: result.diffs,\n };\n}\n\nfunction shouldAbortRefresh(\n memdagBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagClientGroupBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagClientGroupHeadHash: Hash,\n): boolean {\n const baseSnapshotCookieCompareResult = compareCookiesForSnapshots(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n );\n return (\n baseSnapshotCookieCompareResult > 0 ||\n (baseSnapshotCookieCompareResult === 0 &&\n perdagClientGroupHeadHash === perdagClientGroupBaseSnapshot.chunk.hash)\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"refresh.js","names":[],"sources":["../../../../../replicache/src/persist/refresh.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport type {LazyStore} from '../dag/lazy-store.ts';\nimport type {Store} from '../dag/store.ts';\nimport type {Commit} from '../db/commit.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type SnapshotMetaDD31,\n assertSnapshotCommitDD31,\n baseSnapshotFromCommit,\n baseSnapshotFromHash,\n baseSnapshotFromHead,\n commitFromHash,\n commitFromHead,\n compareCookiesForSnapshots,\n localMutationsGreaterThan,\n} from '../db/commit.ts';\nimport {rebaseMutationAndPutCommit} from '../db/rebase.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\nimport type {ZeroOption} from '../replicache-options.ts';\nimport type {DiffsMap} from '../sync/diff.ts';\nimport {type DiffComputationConfig, diffCommits} from '../sync/diff.ts';\nimport type {ClientID} from '../sync/ids.ts';\nimport type {MutatorDefs} from '../types.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n ClientStateNotFoundError,\n type ClientV6,\n assertClientV6,\n getClientGroupForClient,\n mustGetClient,\n setClient,\n} from './clients.ts';\nimport {\n type ChunkWithSize,\n GatherNotCachedVisitor,\n} from './gather-not-cached-visitor.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\nconst GATHER_SIZE_LIMIT = 5 * 2 ** 20; // 5 MB\n\ntype RefreshResult =\n | {\n type: 'aborted';\n refreshHashesForRevert?: readonly Hash[] | undefined;\n }\n | {\n type: 'complete';\n diffs: DiffsMap;\n newPerdagClientHeadHash: Hash;\n oldHead: Hash;\n newHead: Hash;\n };\n\n/**\n * This returns the diff between the state of the btree before and after\n * refresh. It returns `undefined` if the refresh was aborted.\n */\nexport async function refresh(\n lc: LogContext,\n memdag: LazyStore,\n perdag: Store,\n clientID: ClientID,\n mutators: MutatorDefs,\n diffConfig: DiffComputationConfig,\n closed: () => boolean,\n formatVersion: FormatVersion,\n zero: ZeroOption | undefined,\n): Promise<{oldHead: Hash; newHead: Hash; diffs: DiffsMap} | undefined> {\n if (closed()) {\n return;\n }\n const memdagBaseSnapshot = await withRead(memdag, memdagRead =>\n baseSnapshotFromHead(DEFAULT_HEAD_NAME, memdagRead),\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n\n type PerdagWriteResult = [\n perdagClientGroupHeadHash: Hash,\n perdagClientGroupBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagLmid: number,\n gatheredChunks: ReadonlyMap<Hash, ChunkWithSize>,\n refreshHashesForRevert: readonly Hash[],\n ];\n\n // Suspend eviction and deletion of chunks cached by the lazy store\n // to prevent cache misses. If eviction and deletion are not suspended\n // some chunks that are not gathered due to already being cached, may be\n // evicted or deleted by the time the write lock is acquired on the memdag,\n // which can lead to cache misses when performing the rebase and diff.\n // It is important to avoid these cache misses because they often create jank\n // because they block local mutations, pulls and queries on reading from idb.\n // Cache misses can still happen during the rebase and diff, but only\n // if the gather step hits its size limit.\n const result: RefreshResult =\n await memdag.withSuspendedSourceCacheEvictsAndDeletes(async () => {\n const perdagWriteResult: PerdagWriteResult | undefined = await withWrite(\n perdag,\n async perdagWrite => {\n const clientGroup = await getClientGroupForClient(\n clientID,\n perdagWrite,\n );\n if (!clientGroup) {\n throw new ClientStateNotFoundError(clientID);\n }\n\n const perdagClientGroupHeadHash = clientGroup.headHash;\n const perdagClientGroupHeadCommit = await commitFromHash(\n perdagClientGroupHeadHash,\n perdagWrite,\n );\n const perdagLmid = await perdagClientGroupHeadCommit.getMutationID(\n clientID,\n perdagWrite,\n );\n\n // Need to pull this head into memdag, but can't have it disappear if\n // perdag moves forward while we're rebasing in memdag. Can't change\n // client headHash until our rebase in memdag is complete, because if\n // rebase fails, then nothing is keeping client's chunks alive in\n // perdag.\n const client = await mustGetClient(clientID, perdagWrite);\n assertClientV6(client);\n const perdagClientGroupBaseSnapshot = await baseSnapshotFromHash(\n perdagClientGroupHeadHash,\n perdagWrite,\n );\n assertSnapshotCommitDD31(perdagClientGroupBaseSnapshot);\n if (\n shouldAbortRefresh(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n perdagClientGroupHeadHash,\n )\n ) {\n return undefined;\n }\n\n // To avoid pulling the entire perdag graph into the memdag\n // the amount of chunk data gathered is limited by size.\n const visitor = new GatherNotCachedVisitor(\n perdagWrite,\n memdag,\n GATHER_SIZE_LIMIT,\n );\n await visitor.visit(perdagClientGroupHeadHash);\n const {gatheredChunks} = visitor;\n\n const refreshHashesSet = new Set(client.refreshHashes);\n refreshHashesSet.add(perdagClientGroupHeadHash);\n\n const newClient: ClientV6 = {\n ...client,\n refreshHashes: [...refreshHashesSet],\n };\n\n await setClient(clientID, newClient, perdagWrite);\n return [\n perdagClientGroupHeadHash,\n perdagClientGroupBaseSnapshot,\n perdagLmid,\n gatheredChunks,\n client.refreshHashes,\n ];\n },\n );\n\n if (closed() || !perdagWriteResult) {\n return {\n type: 'aborted',\n } as const;\n }\n\n const [\n perdagClientGroupHeadHash,\n perdagClientGroupBaseSnapshot,\n perdagLmid,\n gatheredChunks,\n refreshHashesForRevert,\n ] = perdagWriteResult;\n return withWrite(memdag, async memdagWrite => {\n const memdagHeadCommit = await commitFromHead(\n DEFAULT_HEAD_NAME,\n memdagWrite,\n );\n const memdagBaseSnapshot = await baseSnapshotFromCommit(\n memdagHeadCommit,\n memdagWrite,\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n if (\n shouldAbortRefresh(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n perdagClientGroupHeadHash,\n )\n ) {\n return {\n type: 'aborted',\n refreshHashesForRevert,\n };\n }\n\n const newMemdagMutations = await localMutationsGreaterThan(\n memdagHeadCommit,\n {[clientID]: perdagLmid},\n memdagWrite,\n );\n const ps = [];\n for (const {chunk, size} of gatheredChunks.values()) {\n ps.push(memdagWrite.putChunk(chunk, size));\n }\n await Promise.all(ps);\n\n let newMemdagHeadHash = perdagClientGroupHeadHash;\n if (newMemdagMutations.length > 0) {\n let zeroData = await zero?.getTxData?.(newMemdagHeadHash, {\n openLazyRead: memdagWrite,\n });\n for (let i = newMemdagMutations.length - 1; i >= 0; i--) {\n const {result, zeroData: next} = await rebaseMutationAndPutCommit(\n newMemdagMutations[i],\n memdagWrite,\n newMemdagHeadHash,\n mutators,\n lc,\n newMemdagMutations[i].meta.clientID,\n formatVersion,\n zeroData,\n );\n newMemdagHeadHash = result.chunk.hash;\n zeroData = next;\n }\n }\n\n const newMemdagHeadCommit = await commitFromHash(\n newMemdagHeadHash,\n memdagWrite,\n );\n const diffs = await diffCommits(\n memdagHeadCommit,\n newMemdagHeadCommit,\n memdagWrite,\n diffConfig,\n formatVersion,\n );\n\n await memdagWrite.setHead(DEFAULT_HEAD_NAME, newMemdagHeadHash);\n return {\n type: 'complete',\n diffs,\n oldHead: memdagHeadCommit.chunk.hash,\n newHead: newMemdagHeadHash,\n newPerdagClientHeadHash: perdagClientGroupHeadHash,\n } as const;\n });\n });\n\n if (closed()) {\n return;\n }\n\n const setRefreshHashes = (refreshHashes: readonly Hash[]) =>\n withWrite(perdag, async perdagWrite => {\n const client = await mustGetClient(clientID, perdagWrite);\n const newClient = {\n ...client,\n refreshHashes,\n };\n\n // If this cleanup never happens, it's no big deal, some data will stay\n // alive longer but next refresh will fix it.\n await setClient(clientID, newClient, perdagWrite);\n });\n\n if (result.type === 'aborted') {\n if (result.refreshHashesForRevert) {\n await setRefreshHashes(result.refreshHashesForRevert);\n }\n return undefined;\n }\n\n // Advance zero here before setting refresh hashes\n // since we must advance before delegating control of the microtask\n // loop.\n zero?.advance(result.oldHead, result.newHead, result.diffs.get('') ?? []);\n await setRefreshHashes([result.newPerdagClientHeadHash]);\n return {\n oldHead: result.oldHead,\n newHead: result.newHead,\n diffs: result.diffs,\n };\n}\n\nfunction shouldAbortRefresh(\n memdagBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagClientGroupBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagClientGroupHeadHash: Hash,\n): boolean {\n const baseSnapshotCookieCompareResult = compareCookiesForSnapshots(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n );\n return (\n baseSnapshotCookieCompareResult > 0 ||\n (baseSnapshotCookieCompareResult === 0 &&\n perdagClientGroupHeadHash === perdagClientGroupBaseSnapshot.chunk.hash)\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"replicache-impl.d.ts","sourceRoot":"","sources":["../../../../replicache/src/replicache-impl.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"replicache-impl.d.ts","sourceRoot":"","sources":["../../../../replicache/src/replicache-impl.ts"],"names":[],"mappings":"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"}
@@ -401,11 +401,13 @@ var ReplicacheImpl = class {
401
401
  this.#schedulePersist();
402
402
  return;
403
403
  }
404
- const zeroData = await this.#zero?.getTxData?.(syncHead);
404
+ let zeroData = await this.#zero?.getTxData?.(syncHead);
405
405
  for (const mutation of replayMutations) {
406
406
  if (this.#subscriptions.hasPendingSubscriptionRuns) await Promise.resolve();
407
407
  const { meta } = mutation;
408
- syncHead = await withWriteNoImplicitCommit(this.memdag, (dagWrite) => rebaseMutationAndCommit(mutation, dagWrite, syncHead, SYNC_HEAD_NAME, this.#mutatorRegistry, lc, isLocalMetaDD31(meta) ? meta.clientID : clientID, 7, zeroData));
408
+ const { result, zeroData: next } = await withWriteNoImplicitCommit(this.memdag, (dagWrite) => rebaseMutationAndCommit(mutation, dagWrite, syncHead, SYNC_HEAD_NAME, this.#mutatorRegistry, lc, isLocalMetaDD31(meta) ? meta.clientID : clientID, 7, zeroData));
409
+ syncHead = result;
410
+ zeroData = next;
409
411
  }
410
412
  }
411
413
  }
@@ -1 +1 @@
1
- {"version":3,"file":"replicache-impl.js","names":["#subscriptions","#mutationRecovery","#kvStoreProvider","#zero","#auth","#idbDatabase","#clientID","#ready","#profileIDPromise","#clientGroupIDPromise","#mutatorRegistry","#requestOptions","#idbDatabases","#lc","#closeAbortController","#persistLock","#enableScheduledPersist","#enableScheduledRefresh","#enableRefresh","#enablePullAndPushInOpen","#onPersist","#queryInternal","#pullConnectionLoop","#invokePull","#pushConnectionLoop","#invokePush","#registerMutators","#wrapInOnlineCheck","#wrapInReauthRetries","#isPullDisabled","#isPushDisabled","#handlePersist","#open","#clientStateNotFoundOnClient","#fireOnUpdateNeeded","#onVisibilityChange","#closed","#checkForClientStateNotFoundAndCallHandler","#online","#schedulePersist","#changeSyncCounters","#convertToClientStateNotFoundError","#handleVersionNotSupportedResponse","#clientStateNotFoundOnServer","#fireOnClientStateNotFound","#schedule","#persistScheduler","#scheduleRefresh","#refreshScheduler","#pushCounter","#pullCounter","#mutate","#register"],"sources":["../../../../replicache/src/replicache-impl.ts"],"sourcesContent":["import {Lock} from '@rocicorp/lock';\nimport type {LogContext} from '@rocicorp/logger';\nimport {consoleLogSink} from '@rocicorp/logger';\nimport {resolver} from '@rocicorp/resolver';\nimport {AbortError} from '../../shared/src/abort-error.ts';\nimport {assert} from '../../shared/src/asserts.ts';\nimport {getBrowserGlobal} from '../../shared/src/browser-env.ts';\nimport {getDocumentVisibilityWatcher} from '../../shared/src/document-visible.ts';\nimport type {JSONValue, ReadonlyJSONValue} from '../../shared/src/json.ts';\nimport {promiseVoid} from '../../shared/src/resolved-promises.ts';\nimport {TESTING} from '../../shared/src/testing.ts';\nimport type {MaybePromise} from '../../shared/src/types.ts';\nimport {PullDelegate, PushDelegate} from './connection-loop-delegates.ts';\nimport {ConnectionLoop, MAX_DELAY_MS, MIN_DELAY_MS} from './connection-loop.ts';\nimport {assertCookie, type Cookie} from './cookies.ts';\nimport {LazyStore} from './dag/lazy-store.ts';\nimport {StoreImpl} from './dag/store-impl.ts';\nimport {ChunkNotFoundError, mustGetHeadHash, type Store} from './dag/store.ts';\nimport {\n baseSnapshotFromHash,\n DEFAULT_HEAD_NAME,\n isLocalMetaDD31,\n type LocalMeta,\n} from './db/commit.ts';\nimport {readFromDefaultHead} from './db/read.ts';\nimport {rebaseMutationAndCommit} from './db/rebase.ts';\nimport {newWriteLocal} from './db/write.ts';\nimport {\n isClientStateNotFoundResponse,\n isVersionNotSupportedResponse,\n type VersionNotSupportedResponse,\n} from './error-responses.ts';\nimport * as FormatVersion from './format-version-enum.ts';\nimport {deepFreeze} from './frozen-json.ts';\nimport {getDefaultPuller, isDefaultPuller} from './get-default-puller.ts';\nimport {getDefaultPusher, isDefaultPusher} from './get-default-pusher.ts';\nimport {getKVStoreProvider} from './get-kv-store-provider.ts';\nimport {assertHash, emptyHash, type Hash, newRandomHash} from './hash.ts';\nimport type {HTTPRequestInfo} from './http-request-info.ts';\nimport {httpStatusUnauthorized} from './http-status-unauthorized.ts';\nimport type {IndexDefinitions} from './index-defs.ts';\nimport type {StoreProvider} from './kv/store.ts';\nimport {createLogContext} from './log-options.ts';\nimport {makeIDBName} from './make-idb-name.ts';\nimport {MutationRecovery} from './mutation-recovery.ts';\nimport {initNewClientChannel} from './new-client-channel.ts';\nimport {\n initOnPersistChannel,\n type OnPersist,\n type PersistInfo,\n} from './on-persist-channel.ts';\nimport {\n type PendingMutation,\n pendingMutationsForAPI,\n} from './pending-mutations.ts';\nimport {\n CLIENT_MAX_INACTIVE_TIME,\n GC_INTERVAL,\n initClientGC,\n} from './persist/client-gc.ts';\nimport {initClientGroupGC} from './persist/client-group-gc.ts';\nimport {disableClientGroup} from './persist/client-groups.ts';\nimport {\n ClientStateNotFoundError,\n initClientV6,\n type OnClientsDeleted,\n hasClientState as persistHasClientState,\n} from './persist/clients.ts';\nimport {\n COLLECT_IDB_INTERVAL,\n initCollectIDBDatabases,\n INITIAL_COLLECT_IDB_DELAY,\n} from './persist/collect-idb-databases.ts';\nimport {HEARTBEAT_INTERVAL, startHeartbeats} from './persist/heartbeat.ts';\nimport {\n IDBDatabasesStore,\n type IndexedDBDatabase,\n} from './persist/idb-databases-store.ts';\nimport {makeClientID} from './persist/make-client-id.ts';\nimport {persistDD31} from './persist/persist.ts';\nimport {refresh} from './persist/refresh.ts';\nimport {ProcessScheduler} from './process-scheduler.ts';\nimport type {Puller} from './puller.ts';\nimport {type Pusher, PushError} from './pusher.ts';\nimport type {\n MutationTrackingData,\n ReplicacheOptions,\n ZeroOption,\n} from './replicache-options.ts';\nimport {ReportError} from './report-error.ts';\nimport {setIntervalWithSignal} from './set-interval-with-signal.ts';\nimport {\n type SubscribeOptions,\n SubscriptionImpl,\n type SubscriptionsManager,\n SubscriptionsManagerImpl,\n type WatchCallback,\n type WatchCallbackForOptions,\n type WatchNoIndexCallback,\n type WatchOptions,\n WatchSubscription,\n} from './subscriptions.ts';\nimport type {DiffsMap} from './sync/diff.ts';\nimport * as HandlePullResponseResultEnum from './sync/handle-pull-response-result-type-enum.ts';\nimport type {ClientGroupID, ClientID} from './sync/ids.ts';\nimport {PullError} from './sync/pull-error.ts';\nimport {beginPullV1, handlePullResponseV1, maybeEndPull} from './sync/pull.ts';\nimport {push, PUSH_VERSION_DD31} from './sync/push.ts';\nimport {newRequestID} from './sync/request-id.ts';\nimport {SYNC_HEAD_NAME} from './sync/sync-head-name.ts';\nimport {throwIfClosed} from './transaction-closed-error.ts';\nimport type {ReadTransaction, WriteTransaction} from './transactions.ts';\nimport {ReadTransactionImpl, WriteTransactionImpl} from './transactions.ts';\nimport type {\n BeginPullResult,\n MakeMutator,\n MakeMutators,\n MutatorDefs,\n MutatorReturn,\n PokeInternal,\n QueryInternal,\n RequestOptions,\n UpdateNeededReason,\n} from './types.ts';\nimport {version} from './version.ts';\nimport {\n withRead,\n withWrite,\n withWriteNoImplicitCommit,\n} from './with-transactions.ts';\n\n/**\n * The maximum number of time to call out to getAuth before giving up\n * and throwing an error.\n */\nconst MAX_REAUTH_TRIES = 8;\n\nconst PERSIST_IDLE_TIMEOUT_MS = 1000;\nconst REFRESH_IDLE_TIMEOUT_MS = 1000;\n\nconst PERSIST_THROTTLE_MS = 500;\nconst REFRESH_THROTTLE_MS = 500;\n\n/**\n * Opening the database blocks everything Replicache does, including Zero's\n * first connect attempt, so a slow open is worth a warning rather than a\n * debug line.\n */\nconst SLOW_DB_OPEN_THRESHOLD_MS = 50;\n\nconst LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT = 100 * 2 ** 20; // 100 MB\n\nconst RECOVER_MUTATIONS_INTERVAL_MS = 5 * 60 * 1000; // 5 mins\n\nconst noop = () => {\n // noop\n};\n\nconst updateNeededReasonNewClientGroup: UpdateNeededReason = {\n type: 'NewClientGroup',\n} as const;\n\n/** @deprecated Not used any more */\nexport interface MakeSubscriptionsManager {\n (queryInternal: QueryInternal, lc: LogContext): SubscriptionsManager;\n}\n\nexport interface ReplicacheImplOptions {\n /**\n * Defaults to true.\n */\n enableMutationRecovery?: boolean | undefined;\n\n /**\n * Defaults to true.\n */\n enableScheduledPersist?: boolean | undefined;\n\n /**\n * Defaults to true.\n */\n enableScheduledRefresh?: boolean | undefined;\n\n /**\n * Defaults to `() => true`.\n */\n enableRefresh?: (() => boolean) | undefined;\n\n /**\n * Defaults to true.\n */\n enablePullAndPushInOpen?: boolean | undefined;\n\n /**\n * @deprecated Not used anymore.\n */\n makeSubscriptionsManager?: unknown;\n\n /**\n * Default is `true`. If `false` if an exact match client group\n * is not found, a new client group is always made instead of forking\n * from an existing client group.\n */\n enableClientGroupForking?: boolean | undefined;\n\n /**\n * Callback for when Replicache has deleted clients.\n */\n onClientsDeleted?: OnClientsDeleted | undefined;\n\n /**\n * Internal option used by Zero.\n * Replicache will call this to and, if zero is enabled, will\n * invoke various hooks to allow Zero the keep IVM in sync with Replicache's b-trees.\n */\n zero?: ZeroOption | undefined;\n}\n\nexport class ReplicacheImpl<MD extends MutatorDefs = {}> {\n /** The URL to use when doing a pull request. */\n pullURL: string;\n\n /** The URL to use when doing a push request. */\n pushURL: string;\n\n /** The authorization token used when doing a push request. */\n #auth: string;\n\n /** The name of the Replicache database. Populated by {@link ReplicacheOptions#name}. */\n readonly name: string;\n\n readonly #subscriptions: SubscriptionsManager;\n readonly #mutationRecovery: MutationRecovery | undefined;\n\n /**\n * Client groups gets disabled when the server does not know about it.\n * A disabled client group prevents the client from pushing and pulling.\n */\n isClientGroupDisabled = false;\n\n readonly #kvStoreProvider: StoreProvider;\n\n lastMutationID: number = 0;\n\n /**\n * This is the name Replicache uses for the IndexedDB database where data is\n * stored.\n */\n get idbName(): string {\n return makeIDBName(this.name, this.schemaVersion);\n }\n\n set auth(auth: string) {\n if (this.#zero) {\n this.#zero.auth = auth;\n }\n\n this.#auth = auth;\n }\n\n get auth() {\n return this.#auth;\n }\n\n /** The schema version of the data understood by this application. */\n readonly schemaVersion: string;\n\n get #idbDatabase(): IndexedDBDatabase {\n return {\n name: this.idbName,\n replicacheName: this.name,\n replicacheFormatVersion: FormatVersion.Latest,\n schemaVersion: this.schemaVersion,\n };\n }\n #closed = false;\n #online = true;\n readonly #clientID = makeClientID();\n readonly #ready: Promise<void>;\n readonly #profileIDPromise: Promise<string>;\n readonly #clientGroupIDPromise: Promise<string>;\n readonly #mutatorRegistry: MutatorDefs = {};\n\n /**\n * The mutators that was registered in the constructor.\n */\n readonly mutate: MakeMutators<MD>;\n\n // Number of pushes/pulls at the moment.\n #pushCounter = 0;\n #pullCounter = 0;\n\n #pullConnectionLoop: ConnectionLoop;\n #pushConnectionLoop: ConnectionLoop;\n\n /**\n * The duration between each periodic {@link pull}. Setting this to `null`\n * disables periodic pull completely. Pull will still happen if you call\n * {@link pull} manually.\n */\n pullInterval: number | null;\n\n /**\n * The delay between when a change is made to Replicache and when Replicache\n * attempts to push that change.\n */\n pushDelay: number;\n\n readonly #requestOptions: Required<RequestOptions>;\n\n /**\n * The function to use to pull data from the server.\n */\n puller: Puller;\n\n /**\n * The function to use to push data to the server.\n */\n pusher: Pusher;\n\n readonly memdag: LazyStore;\n readonly perdag: Store;\n readonly #idbDatabases: IDBDatabasesStore;\n readonly #lc: LogContext;\n readonly #zero: ZeroOption | undefined;\n\n readonly #closeAbortController = new AbortController();\n\n readonly #persistLock = new Lock();\n readonly #enableScheduledPersist: boolean;\n readonly #enableScheduledRefresh: boolean;\n readonly #enableRefresh: () => boolean;\n readonly #enablePullAndPushInOpen: boolean;\n #persistScheduler = new ProcessScheduler(\n () => this.persist(),\n PERSIST_IDLE_TIMEOUT_MS,\n PERSIST_THROTTLE_MS,\n this.#closeAbortController.signal,\n );\n readonly #onPersist: OnPersist;\n #refreshScheduler = new ProcessScheduler(\n () => this.refresh(),\n REFRESH_IDLE_TIMEOUT_MS,\n REFRESH_THROTTLE_MS,\n this.#closeAbortController.signal,\n );\n\n /**\n * The options used to control the {@link pull} and push request behavior. This\n * object is live so changes to it will affect the next pull or push call.\n */\n get requestOptions(): Required<RequestOptions> {\n return this.#requestOptions;\n }\n\n /**\n * `onSync(true)` is called when Replicache transitions from no push or pull\n * happening to at least one happening. `onSync(false)` is called in the\n * opposite case: when Replicache transitions from at least one push or pull\n * happening to none happening.\n *\n * This can be used in a React like app by doing something like the following:\n *\n * ```js\n * const [syncing, setSyncing] = useState(false);\n * useEffect(() => {\n * rep.onSync = setSyncing;\n * }, [rep]);\n * ```\n */\n onSync: ((syncing: boolean) => void) | null = null;\n\n /**\n * `onClientStateNotFound` is called when the persistent client has been\n * garbage collected. This can happen if the client has no pending mutations\n * and has not been used for a while.\n *\n * The default behavior is to reload the page (using `location.reload()`). Set\n * this to `null` or provide your own function to prevent the page from\n * reloading automatically.\n */\n onClientStateNotFound: (() => void) | null = reload;\n\n /**\n * `onUpdateNeeded` is called when a code update is needed.\n *\n * A code update can be needed because:\n * - the server no longer supports the {@link pushVersion},\n * {@link pullVersion} or {@link schemaVersion} of the current code.\n * - a new Replicache client has created a new client group, because its code\n * has different mutators, indexes, schema version and/or format version\n * from this Replicache client. This is likely due to the new client having\n * newer code. A code update is needed to be able to locally sync with this\n * new Replicache client (i.e. to sync while offline, the clients can still\n * sync with each other via the server).\n *\n * The default behavior is to reload the page (using `location.reload()`). Set\n * this to `null` or provide your own function to prevent the page from\n * reloading automatically. You may want to provide your own function to\n * display a toast to inform the end user there is a new version of your app\n * available and prompting them to refresh.\n */\n onUpdateNeeded: ((reason: UpdateNeededReason) => void) | null = reload;\n\n /**\n * This gets called when we get an HTTP unauthorized (401) response from the\n * push or pull endpoint. Set this to a function that will ask your user to\n * reauthenticate.\n */\n getAuth: (() => MaybePromise<string | null | undefined>) | null | undefined =\n null;\n\n // These three are used for testing\n onPushInvoked = () => undefined;\n onBeginPull = () => undefined;\n onRecoverMutations = (r: Promise<boolean>) => r;\n\n constructor(\n options: ReplicacheOptions<MD>,\n implOptions: ReplicacheImplOptions = {},\n ) {\n validateOptions(options);\n const {\n name,\n logLevel = 'info',\n logSinks = [consoleLogSink],\n pullURL = '',\n auth,\n pushDelay = 10,\n pushURL = '',\n schemaVersion = '',\n pullInterval = 60000,\n mutators = {} as MD,\n requestOptions = {},\n puller,\n pusher,\n indexes = {},\n clientMaxAgeMs = CLIENT_MAX_INACTIVE_TIME,\n } = options;\n const {\n enableMutationRecovery = true,\n enableScheduledPersist = true,\n enableScheduledRefresh = true,\n enableRefresh = () => true,\n enablePullAndPushInOpen = true,\n enableClientGroupForking = true,\n onClientsDeleted = () => promiseVoid,\n } = implOptions;\n this.#zero = implOptions.zero;\n this.#auth = auth ?? '';\n this.pullURL = pullURL;\n this.pushURL = pushURL;\n this.name = name;\n this.schemaVersion = schemaVersion;\n this.pullInterval = pullInterval;\n this.pushDelay = pushDelay;\n this.puller = puller ?? getDefaultPuller(this);\n this.pusher = pusher ?? getDefaultPusher(this);\n\n this.#enableScheduledPersist = enableScheduledPersist;\n this.#enableScheduledRefresh = enableScheduledRefresh;\n this.#enableRefresh = enableRefresh;\n this.#enablePullAndPushInOpen = enablePullAndPushInOpen;\n\n this.#lc = createLogContext(logLevel, logSinks, {name});\n this.#lc.debug?.('Constructing Replicache', {\n name,\n 'replicache version': version,\n });\n\n this.#subscriptions = new SubscriptionsManagerImpl(\n this.#queryInternal,\n this.#lc,\n this.#closeAbortController.signal,\n );\n\n const kvStoreProvider = getKVStoreProvider(this.#lc, options.kvStore);\n this.#kvStoreProvider = kvStoreProvider;\n\n const perKVStore = kvStoreProvider.create(this.idbName);\n\n this.#idbDatabases = new IDBDatabasesStore(kvStoreProvider.create);\n this.perdag = new StoreImpl(perKVStore, newRandomHash, assertHash);\n this.memdag = new LazyStore(\n this.perdag,\n LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT,\n newRandomHash,\n assertHash,\n );\n\n // Use a promise-resolve pair so that we have a promise to use even before\n // we call the Open RPC.\n const readyResolver = resolver<void>();\n this.#ready = readyResolver.promise;\n\n const {minDelayMs = MIN_DELAY_MS, maxDelayMs = MAX_DELAY_MS} =\n requestOptions;\n this.#requestOptions = {maxDelayMs, minDelayMs};\n\n const visibilityWatcher = getDocumentVisibilityWatcher(\n getBrowserGlobal('document'),\n 0,\n this.#closeAbortController.signal,\n );\n\n this.#pullConnectionLoop = new ConnectionLoop(\n this.#lc.withContext('PULL'),\n new PullDelegate(this, () => this.#invokePull()),\n visibilityWatcher,\n );\n\n this.#pushConnectionLoop = new ConnectionLoop(\n this.#lc.withContext('PUSH'),\n new PushDelegate(this, () => this.#invokePush()),\n );\n\n this.mutate = this.#registerMutators(mutators);\n\n const profileIDResolver = resolver<string>();\n this.#profileIDPromise = profileIDResolver.promise;\n const clientGroupIDResolver = resolver<string>();\n this.#clientGroupIDPromise = clientGroupIDResolver.promise;\n\n if (!process.env.DISABLE_MUTATION_RECOVERY) {\n this.#mutationRecovery = new MutationRecovery({\n delegate: this,\n lc: this.#lc,\n enableMutationRecovery,\n wrapInOnlineCheck: this.#wrapInOnlineCheck.bind(this),\n wrapInReauthRetries: this.#wrapInReauthRetries.bind(this),\n isPullDisabled: this.#isPullDisabled.bind(this),\n isPushDisabled: this.#isPushDisabled.bind(this),\n clientGroupIDPromise: this.#clientGroupIDPromise,\n });\n }\n\n this.#onPersist = initOnPersistChannel(\n this.name,\n this.#closeAbortController.signal,\n persistInfo => {\n void this.#handlePersist(persistInfo);\n },\n );\n\n void this.#open(\n indexes,\n enableClientGroupForking,\n enableMutationRecovery,\n clientMaxAgeMs,\n profileIDResolver.resolve,\n clientGroupIDResolver.resolve,\n readyResolver.resolve,\n onClientsDeleted,\n );\n }\n\n async #open(\n indexes: IndexDefinitions,\n enableClientGroupForking: boolean,\n enableMutationRecovery: boolean,\n clientMaxAgeMs: number,\n profileIDResolver: (profileID: string) => void,\n resolveClientGroupID: (clientGroupID: ClientGroupID) => void,\n resolveReady: () => void,\n onClientsDeleted: OnClientsDeleted,\n ): Promise<void> {\n const {clientID} = this;\n // Everything up to the head write is what it takes to have a usable\n // database, including waiting out a previous instance of the same name.\n // The timer stops before the replica is loaded into Zero's IVM sources,\n // which is separate work and usually the larger of the two: a number that\n // spanned both would report a slow hydration as a slow disk.\n const openStart = performance.now();\n // If we are currently closing a Replicache instance with the same name,\n // wait for it to finish closing.\n await closingInstances.get(this.name);\n await this.#idbDatabases.getProfileID().then(profileIDResolver);\n await this.#idbDatabases.putDatabase(this.#idbDatabase);\n const [client, headHash, , isNewClientGroup] = await initClientV6(\n clientID,\n this.#lc,\n this.perdag,\n Object.keys(this.#mutatorRegistry),\n indexes,\n FormatVersion.Latest,\n enableClientGroupForking,\n );\n\n resolveClientGroupID(client.clientGroupID);\n await withWrite(this.memdag, write =>\n write.setHead(DEFAULT_HEAD_NAME, headHash),\n );\n\n // Now we have a profileID, a clientID, a clientGroupID and DB!\n const dbOpenMs = performance.now() - openStart;\n if (dbOpenMs > SLOW_DB_OPEN_THRESHOLD_MS) {\n this.#lc.warn?.(`Opening the database took ${Math.round(dbOpenMs)}ms`, {\n name: this.idbName,\n });\n } else {\n this.#lc.debug?.('Opened the database in', Math.round(dbOpenMs), 'ms');\n }\n\n await this.#zero?.init(headHash, this.memdag);\n resolveReady();\n\n if (this.#enablePullAndPushInOpen) {\n this.pull().catch(noop);\n this.push().catch(noop);\n }\n\n const {signal} = this.#closeAbortController;\n\n startHeartbeats(\n clientID,\n this.perdag,\n () => {\n this.#clientStateNotFoundOnClient(clientID);\n },\n HEARTBEAT_INTERVAL,\n this.#lc,\n signal,\n );\n initClientGC(\n clientID,\n this.perdag,\n clientMaxAgeMs,\n GC_INTERVAL,\n onClientsDeleted,\n this.#lc,\n signal,\n );\n initCollectIDBDatabases(\n this.#idbDatabases,\n this.#kvStoreProvider,\n COLLECT_IDB_INTERVAL,\n INITIAL_COLLECT_IDB_DELAY,\n 2 * clientMaxAgeMs,\n enableMutationRecovery,\n onClientsDeleted,\n this.#lc,\n signal,\n );\n initClientGroupGC(this.perdag, enableMutationRecovery, this.#lc, signal);\n initNewClientChannel(\n this.name,\n this.idbName,\n signal,\n client.clientGroupID,\n isNewClientGroup,\n () => {\n this.#fireOnUpdateNeeded(updateNeededReasonNewClientGroup);\n },\n this.perdag,\n );\n\n setIntervalWithSignal(\n () => this.recoverMutations(),\n RECOVER_MUTATIONS_INTERVAL_MS,\n signal,\n );\n void this.recoverMutations();\n\n getBrowserGlobal('document')?.addEventListener(\n 'visibilitychange',\n this.#onVisibilityChange,\n );\n }\n\n #onVisibilityChange = async () => {\n if (this.#closed) {\n return;\n }\n\n // In case of running in a worker, we don't have a document.\n if (getBrowserGlobal('document')?.visibilityState !== 'visible') {\n return;\n }\n\n await this.#checkForClientStateNotFoundAndCallHandler();\n };\n\n async #checkForClientStateNotFoundAndCallHandler(): Promise<boolean> {\n const {clientID} = this;\n const hasClientState = await withRead(this.perdag, read =>\n persistHasClientState(clientID, read),\n );\n if (!hasClientState) {\n this.#clientStateNotFoundOnClient(clientID);\n }\n return !hasClientState;\n }\n\n /**\n * The browser profile ID for this browser profile. Every instance of Replicache\n * browser-profile-wide shares the same profile ID.\n */\n get profileID(): Promise<string> {\n return this.#profileIDPromise;\n }\n\n /**\n * The client ID for this instance of Replicache. Each instance of Replicache\n * gets a unique client ID.\n */\n get clientID(): string {\n return this.#clientID;\n }\n\n /**\n * The client group ID for this instance of Replicache. Instances of\n * Replicache will have the same client group ID if and only if they have\n * the same name, mutators, indexes, schema version, format version, and\n * browser profile.\n */\n get clientGroupID(): Promise<string> {\n return this.#clientGroupIDPromise;\n }\n\n /**\n * `onOnlineChange` is called when the {@link online} property changes. See\n * {@link online} for more details.\n */\n onOnlineChange: ((online: boolean) => void) | null = null;\n\n /**\n * A rough heuristic for whether the client is currently online. Note that\n * there is no way to know for certain whether a client is online - the next\n * request can always fail. This property returns true if the last sync attempt succeeded,\n * and false otherwise.\n */\n get online(): boolean {\n return this.#online;\n }\n\n /**\n * Whether the Replicache database has been closed. Once Replicache has been\n * closed it no longer syncs and you can no longer read or write data out of\n * it. After it has been closed it is pretty much useless and should not be\n * used any more.\n */\n get closed(): boolean {\n return this.#closed;\n }\n\n /**\n * Closes this Replicache instance.\n *\n * When closed all subscriptions end and no more read or writes are allowed.\n */\n async close(): Promise<void> {\n this.#closed = true;\n const {promise, resolve} = resolver();\n closingInstances.set(this.name, promise);\n\n this.#closeAbortController.abort();\n\n getBrowserGlobal('document')?.removeEventListener(\n 'visibilitychange',\n this.#onVisibilityChange,\n );\n\n await this.#ready;\n const closingPromises = [\n this.memdag.close(),\n this.perdag.close(),\n this.#idbDatabases.close(),\n ];\n\n this.#pullConnectionLoop.close();\n this.#pushConnectionLoop.close();\n\n this.#subscriptions.clear();\n\n await Promise.all(closingPromises);\n closingInstances.delete(this.name);\n resolve();\n }\n\n async maybeEndPull(syncHead: Hash, requestID: string): Promise<void> {\n for (;;) {\n if (this.#closed) {\n return;\n }\n\n await this.#ready;\n const {clientID} = this;\n const lc = this.#lc\n .withContext('maybeEndPull')\n .withContext('requestID', requestID);\n const {replayMutations, diffs, oldMainHead, mainHead} =\n await maybeEndPull<LocalMeta>(\n this.memdag,\n lc,\n syncHead,\n clientID,\n this.#subscriptions,\n FormatVersion.Latest,\n );\n\n if (!replayMutations || replayMutations.length === 0) {\n // All done.\n this.#zero?.advance(oldMainHead, mainHead, diffs.get('') ?? []);\n await this.#subscriptions.fire(diffs);\n void this.#schedulePersist();\n return;\n }\n\n // Replay.\n const zeroData = await this.#zero?.getTxData?.(syncHead);\n for (const mutation of replayMutations) {\n // TODO(greg): I'm not sure why this was in Replicache#_mutate...\n // Ensure that we run initial pending subscribe functions before starting a\n // write transaction.\n if (this.#subscriptions.hasPendingSubscriptionRuns) {\n await Promise.resolve();\n }\n const {meta} = mutation;\n syncHead = await withWriteNoImplicitCommit(this.memdag, dagWrite =>\n rebaseMutationAndCommit(\n mutation,\n dagWrite,\n syncHead,\n SYNC_HEAD_NAME,\n this.#mutatorRegistry,\n lc,\n isLocalMetaDD31(meta) ? meta.clientID : clientID,\n FormatVersion.Latest,\n zeroData,\n ),\n );\n }\n }\n }\n\n #invokePull(): Promise<boolean> {\n if (this.#isPullDisabled()) {\n return Promise.resolve(true);\n }\n\n return this.#wrapInOnlineCheck(async () => {\n try {\n this.#changeSyncCounters(0, 1);\n const {syncHead, requestID, ok} = await this.beginPull();\n if (!ok) {\n return false;\n }\n if (syncHead !== emptyHash) {\n await this.maybeEndPull(syncHead, requestID);\n }\n } catch (e) {\n throw await this.#convertToClientStateNotFoundError(e);\n } finally {\n this.#changeSyncCounters(0, -1);\n }\n return true;\n }, 'Pull');\n }\n\n #isPullDisabled() {\n return (\n this.isClientGroupDisabled ||\n (this.pullURL === '' && isDefaultPuller(this.puller))\n );\n }\n\n async #wrapInOnlineCheck(\n f: () => Promise<boolean>,\n name: string,\n ): Promise<boolean> {\n let online = true;\n\n try {\n return await f();\n } catch (e) {\n // The error paths of beginPull and maybeEndPull need to be reworked.\n //\n // We want to distinguish between:\n // a) network requests failed -- we're offline basically\n // b) sync was aborted because one's already in progress\n // c) oh noes - something unexpected happened\n //\n // Right now, all of these come out as errors. We distinguish (b) with a\n // hacky string search. (a) and (c) are not distinguishable currently\n // because repc doesn't provide sufficient information, so we treat all\n // errors that aren't (b) as (a).\n if (e instanceof PushError || e instanceof PullError) {\n online = false;\n this.#lc.debug?.(`${name} threw:\\n`, e, '\\nwith cause:\\n', e.causedBy);\n } else if (e instanceof ReportError) {\n this.#lc.error?.(e);\n } else {\n this.#lc.info?.(`${name} threw:\\n`, e);\n }\n return false;\n } finally {\n if (this.#online !== online) {\n this.#online = online;\n this.onOnlineChange?.(online);\n if (online) {\n void this.recoverMutations();\n }\n }\n }\n }\n\n async #wrapInReauthRetries<R>(\n f: (\n requestID: string,\n requestLc: LogContext,\n ) => Promise<{\n httpRequestInfo: HTTPRequestInfo | undefined;\n result: R;\n }>,\n verb: string,\n lc: LogContext,\n preAuth: () => MaybePromise<void> = noop,\n postAuth: () => MaybePromise<void> = noop,\n ): Promise<{\n result: R;\n authFailure: boolean;\n }> {\n const {clientID} = this;\n let reauthAttempts = 0;\n let lastResult;\n lc = lc.withContext(verb);\n do {\n const requestID = newRequestID(clientID);\n const requestLc = lc.withContext('requestID', requestID);\n const {httpRequestInfo, result} = await f(requestID, requestLc);\n lastResult = result;\n if (!httpRequestInfo) {\n return {\n result,\n authFailure: false,\n };\n }\n const {errorMessage, httpStatusCode} = httpRequestInfo;\n\n if (errorMessage || httpStatusCode !== 200) {\n // TODO(arv): Maybe we should not log the server URL when the error comes\n // from a Pusher/Puller?\n requestLc.error?.(\n `Got a non 200 response doing ${verb}: ${httpStatusCode}` +\n (errorMessage ? `: ${errorMessage}` : ''),\n );\n }\n if (httpStatusCode !== httpStatusUnauthorized) {\n return {\n result,\n authFailure: false,\n };\n }\n if (!this.getAuth) {\n return {\n result,\n authFailure: true,\n };\n }\n let auth;\n try {\n await preAuth();\n auth = await this.getAuth();\n } finally {\n await postAuth();\n }\n if (auth === null || auth === undefined) {\n return {\n result,\n authFailure: true,\n };\n }\n this.auth = auth;\n reauthAttempts++;\n } while (reauthAttempts < MAX_REAUTH_TRIES);\n lc.info?.('Tried to reauthenticate too many times');\n return {\n result: lastResult,\n authFailure: true,\n };\n }\n\n #isPushDisabled() {\n return (\n this.isClientGroupDisabled ||\n (this.pushURL === '' && isDefaultPusher(this.pusher))\n );\n }\n\n async #invokePush(): Promise<boolean> {\n if (TESTING) {\n this.onPushInvoked();\n }\n if (this.#isPushDisabled()) {\n return true;\n }\n\n await this.#ready;\n const profileID = await this.#profileIDPromise;\n const {clientID} = this;\n const clientGroupID = await this.#clientGroupIDPromise;\n return this.#wrapInOnlineCheck(async () => {\n const {result: pusherResult} = await this.#wrapInReauthRetries(\n async (requestID: string, requestLc: LogContext) => {\n try {\n this.#changeSyncCounters(1, 0);\n const pusherResult = await push(\n requestID,\n this.memdag,\n requestLc,\n profileID,\n clientGroupID,\n clientID,\n this.pusher,\n this.schemaVersion,\n PUSH_VERSION_DD31,\n );\n return {\n result: pusherResult,\n httpRequestInfo: pusherResult?.httpRequestInfo,\n };\n } finally {\n this.#changeSyncCounters(-1, 0);\n }\n },\n 'push',\n this.#lc,\n );\n\n if (pusherResult === undefined) {\n // No pending mutations.\n return true;\n }\n\n const {response, httpRequestInfo} = pusherResult;\n\n if (isVersionNotSupportedResponse(response)) {\n this.#handleVersionNotSupportedResponse(response);\n } else if (isClientStateNotFoundResponse(response)) {\n await this.#clientStateNotFoundOnServer();\n }\n\n // No pushResponse means we didn't do a push because there were no\n // pending mutations.\n return httpRequestInfo.httpStatusCode === 200;\n }, 'Push');\n }\n\n #handleVersionNotSupportedResponse(response: VersionNotSupportedResponse) {\n const reason: UpdateNeededReason = {\n type: response.error,\n };\n if (response.versionType) {\n reason.versionType = response.versionType;\n }\n this.#fireOnUpdateNeeded(reason);\n }\n\n /**\n * Push pushes pending changes to the {@link pushURL}.\n *\n * You do not usually need to manually call push. If {@link pushDelay} is\n * non-zero (which it is by default) pushes happen automatically shortly after\n * mutations.\n *\n * If the server endpoint fails push will be continuously retried with an\n * exponential backoff.\n *\n * @param [now=false] If true, push will happen immediately and ignore\n * {@link pushDelay}, {@link RequestOptions.minDelayMs} as well as the\n * exponential backoff in case of errors.\n * @returns A promise that resolves when the next push completes. In case of\n * errors the first error will reject the returned promise. Subsequent errors\n * will not be reflected in the promise.\n */\n push({now = false} = {}): Promise<void> {\n return throwIfError(this.#pushConnectionLoop.send(now));\n }\n\n /**\n * Pull pulls changes from the {@link pullURL}. If there are any changes local\n * changes will get replayed on top of the new server state.\n *\n * If the server endpoint fails pull will be continuously retried with an\n * exponential backoff.\n *\n * @param [now=false] If true, pull will happen immediately and ignore\n * {@link RequestOptions.minDelayMs} as well as the exponential backoff in\n * case of errors.\n * @returns A promise that resolves when the next pull completes. In case of\n * errors the first error will reject the returned promise. Subsequent errors\n * will not be reflected in the promise.\n */\n pull({now = false} = {}): Promise<void> {\n return throwIfError(this.#pullConnectionLoop.send(now));\n }\n\n /**\n * Applies an update from the server to Replicache.\n * Throws an error if cookie does not match. In that case the server thinks\n * this client has a different cookie than it does; the caller should disconnect\n * from the server and re-register, which transmits the cookie the client actually\n * has.\n *\n * @experimental This method is under development and its semantics will change.\n */\n async poke(poke: PokeInternal): Promise<void> {\n await this.#ready;\n // TODO(MP) Previously we created a request ID here and included it with the\n // PullRequest to the server so we could tie events across client and server\n // together. Since the direction is now reversed, creating and adding a request ID\n // here is kind of silly. We should consider creating the request ID\n // on the *server* and passing it down in the poke for inclusion here in the log\n // context\n const {clientID} = this;\n const requestID = newRequestID(clientID);\n const lc = this.#lc\n .withContext('handlePullResponse')\n .withContext('requestID', requestID);\n\n const {pullResponse} = poke;\n\n if (isVersionNotSupportedResponse(pullResponse)) {\n this.#handleVersionNotSupportedResponse(pullResponse);\n return;\n }\n\n if (isClientStateNotFoundResponse(pullResponse)) {\n await this.#clientStateNotFoundOnServer();\n return;\n }\n\n const result = await handlePullResponseV1(\n lc,\n this.memdag,\n deepFreeze(poke.baseCookie),\n pullResponse,\n clientID,\n FormatVersion.Latest,\n );\n\n switch (result.type) {\n case HandlePullResponseResultEnum.Applied:\n await this.maybeEndPull(result.syncHead, requestID);\n break;\n case HandlePullResponseResultEnum.CookieMismatch:\n throw new Error(\n 'unexpected base cookie for poke: ' + JSON.stringify(poke),\n );\n case HandlePullResponseResultEnum.NoOp:\n break;\n }\n }\n\n async beginPull(): Promise<BeginPullResult> {\n if (TESTING) {\n this.onBeginPull();\n }\n await this.#ready;\n const profileID = await this.profileID;\n const {clientID} = this;\n const clientGroupID = await this.#clientGroupIDPromise;\n const {\n result: {beginPullResponse, requestID},\n } = await this.#wrapInReauthRetries(\n async (requestID: string, requestLc: LogContext) => {\n const beginPullResponse = await beginPullV1(\n profileID,\n clientID,\n clientGroupID,\n this.schemaVersion,\n this.puller,\n requestID,\n this.memdag,\n FormatVersion.Latest,\n requestLc,\n );\n return {\n result: {beginPullResponse, requestID},\n httpRequestInfo: beginPullResponse.httpRequestInfo,\n };\n },\n 'pull',\n this.#lc,\n () => this.#changeSyncCounters(0, -1),\n () => this.#changeSyncCounters(0, 1),\n );\n\n const {pullResponse} = beginPullResponse;\n if (isVersionNotSupportedResponse(pullResponse)) {\n this.#handleVersionNotSupportedResponse(pullResponse);\n } else if (isClientStateNotFoundResponse(beginPullResponse.pullResponse)) {\n await this.#clientStateNotFoundOnServer();\n }\n\n const {syncHead, httpRequestInfo} = beginPullResponse;\n return {requestID, syncHead, ok: httpRequestInfo.httpStatusCode === 200};\n }\n\n persist(): Promise<void> {\n // Prevent multiple persist calls from running at the same time.\n return this.#persistLock.withLock(async () => {\n const {clientID} = this;\n await this.#ready;\n if (this.#closed) {\n return;\n }\n try {\n await persistDD31(\n this.#lc,\n clientID,\n this.memdag,\n this.perdag,\n this.#mutatorRegistry,\n () => this.#closed,\n FormatVersion.Latest,\n this.#zero?.getTxData,\n );\n } catch (e) {\n if (e instanceof ClientStateNotFoundError) {\n this.#clientStateNotFoundOnClient(clientID);\n } else if (this.#closed) {\n this.#lc.debug?.('Exception persisting during close', e);\n } else {\n throw e;\n }\n }\n\n const clientGroupID = await this.#clientGroupIDPromise;\n assert(clientGroupID, 'Expected clientGroupID to be defined');\n this.#onPersist({clientID, clientGroupID});\n });\n }\n\n async refresh(): Promise<void> {\n await this.#ready;\n const {clientID} = this;\n if (this.#closed || !this.#enableRefresh()) {\n return;\n }\n let refreshResult: Awaited<ReturnType<typeof refresh>>;\n try {\n refreshResult = await refresh(\n this.#lc,\n this.memdag,\n this.perdag,\n clientID,\n this.#mutatorRegistry,\n this.#subscriptions,\n () => this.closed,\n FormatVersion.Latest,\n this.#zero,\n );\n } catch (e) {\n if (e instanceof ClientStateNotFoundError) {\n this.#clientStateNotFoundOnClient(clientID);\n } else if (this.#closed) {\n this.#lc.debug?.('Exception refreshing during close', e);\n } else {\n throw e;\n }\n }\n if (refreshResult !== undefined) {\n await this.#subscriptions.fire(refreshResult.diffs);\n }\n }\n\n #fireOnClientStateNotFound() {\n this.onClientStateNotFound?.();\n }\n\n #clientStateNotFoundOnClient(clientID: ClientID) {\n this.#lc.error?.(`Client state not found on client, clientID: ${clientID}`);\n this.#fireOnClientStateNotFound();\n }\n\n async #clientStateNotFoundOnServer() {\n const clientGroupID = await this.#clientGroupIDPromise;\n this.#lc.error?.(\n `Client state not found on server, clientGroupID: ${clientGroupID}`,\n );\n await this.disableClientGroup();\n this.#fireOnClientStateNotFound();\n }\n\n async disableClientGroup(): Promise<void> {\n const clientGroupID = await this.#clientGroupIDPromise;\n assert(clientGroupID, 'Expected clientGroupID to be defined');\n this.isClientGroupDisabled = true;\n await withWrite(this.perdag, dagWrite =>\n disableClientGroup(clientGroupID, dagWrite),\n );\n }\n\n #fireOnUpdateNeeded(reason: UpdateNeededReason) {\n this.#lc.debug?.(`Update needed, reason: ${reason}`);\n this.onUpdateNeeded?.(reason);\n }\n\n async #schedulePersist(): Promise<void> {\n if (!this.#enableScheduledPersist) {\n return;\n }\n await this.#schedule('persist', this.#persistScheduler);\n }\n\n async #handlePersist(persistInfo: PersistInfo): Promise<void> {\n this.#lc.debug?.('Handling persist', persistInfo);\n const clientGroupID = await this.#clientGroupIDPromise;\n if (persistInfo.clientGroupID === clientGroupID) {\n void this.#scheduleRefresh();\n }\n }\n\n async #scheduleRefresh(): Promise<void> {\n if (!this.#enableScheduledRefresh) {\n return;\n }\n await this.#schedule('refresh from storage', this.#refreshScheduler);\n }\n\n async #schedule(name: string, scheduler: ProcessScheduler): Promise<void> {\n try {\n await scheduler.schedule();\n } catch (e) {\n if (e instanceof AbortError) {\n this.#lc.debug?.(`Scheduled ${name} did not complete before close.`);\n } else {\n this.#lc.error?.(`Error during ${name}`, e);\n }\n }\n }\n\n /**\n * Runs a refresh as soon as possible through the refresh scheduler.\n */\n runRefresh(): Promise<void> {\n return this.#refreshScheduler.run();\n }\n\n #changeSyncCounters(pushDelta: 0, pullDelta: 1 | -1): void;\n #changeSyncCounters(pushDelta: 1 | -1, pullDelta: 0): void;\n #changeSyncCounters(pushDelta: number, pullDelta: number): void {\n this.#pushCounter += pushDelta;\n this.#pullCounter += pullDelta;\n const delta = pushDelta + pullDelta;\n const counter = this.#pushCounter + this.#pullCounter;\n if ((delta === 1 && counter === 1) || counter === 0) {\n const syncing = counter > 0;\n // Run in a new microtask.\n void Promise.resolve().then(() => this.onSync?.(syncing));\n }\n }\n\n /**\n * Subscribe to the result of a {@link query}. The `body` function is\n * evaluated once and its results are returned via `onData`.\n *\n * Thereafter, each time the the result of `body` changes, `onData` is fired\n * again with the new result.\n *\n * `subscribe()` goes to significant effort to avoid extraneous work\n * re-evaluating subscriptions:\n *\n * 1. subscribe tracks the keys that `body` accesses each time it runs. `body`\n * is only re-evaluated when those keys change.\n * 2. subscribe only re-fires `onData` in the case that a result changes by\n * way of the `isEqual` option which defaults to doing a deep JSON value\n * equality check.\n *\n * Because of (1), `body` must be a pure function of the data in Replicache.\n * `body` must not access anything other than the `tx` parameter passed to it.\n *\n * Although subscribe is as efficient as it can be, it is somewhat constrained\n * by the goal of returning an arbitrary computation of the cache. For even\n * better performance (but worse dx), see {@link experimentalWatch}.\n *\n * If an error occurs in the `body` the `onError` function is called if\n * present. Otherwise, the error is logged at log level 'error'.\n *\n * To cancel the subscription, call the returned function.\n *\n * @param body The function to evaluate to get the value to pass into\n * `onData`.\n * @param options Options is either a function or an object. If it is a\n * function it is equivalent to passing it as the `onData` property of an\n * object.\n */\n subscribe<R>(\n body: (tx: ReadTransaction) => Promise<R>,\n options: SubscribeOptions<R> | ((result: R) => void),\n ): () => void {\n if (typeof options === 'function') {\n options = {onData: options};\n }\n\n const {onData, onError, onDone, isEqual} = options;\n return this.#subscriptions.add(\n new SubscriptionImpl(body, onData, onError, onDone, isEqual),\n );\n }\n\n /**\n * Watches Replicache for changes.\n *\n * The `callback` gets called whenever the underlying data changes and the\n * `key` changes matches the `prefix` of {@link ExperimentalWatchIndexOptions} or\n * {@link ExperimentalWatchNoIndexOptions} if present. If a change\n * occurs to the data but the change does not impact the key space the\n * callback is not called. In other words, the callback is never called with\n * an empty diff.\n *\n * This gets called after commit (a mutation or a rebase).\n *\n * @experimental This method is under development and its semantics will\n * change.\n */\n experimentalWatch(callback: WatchNoIndexCallback): () => void;\n experimentalWatch<Options extends WatchOptions>(\n callback: WatchCallbackForOptions<Options>,\n options?: Options,\n ): () => void;\n experimentalWatch<Options extends WatchOptions>(\n callback: WatchCallbackForOptions<Options>,\n options?: Options,\n ): () => void {\n return this.#subscriptions.add(\n new WatchSubscription(callback as WatchCallback, options),\n );\n }\n\n /**\n * Query is used for read transactions. It is recommended to use transactions\n * to ensure you get a consistent view across multiple calls to `get`, `has`\n * and `scan`.\n */\n query<R>(body: (tx: ReadTransaction) => Promise<R> | R): Promise<R> {\n return this.#queryInternal(body);\n }\n\n get cookie(): Promise<Cookie> {\n return this.#ready.then(() =>\n withRead(this.memdag, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head found');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n const cookie = baseSnapshotMeta.cookieJSON;\n assertCookie(cookie);\n return cookie;\n }),\n );\n }\n\n #queryInternal: QueryInternal = async body => {\n await this.#ready;\n const {clientID} = this;\n return withRead(this.memdag, async dagRead => {\n try {\n const dbRead = await readFromDefaultHead(dagRead, FormatVersion.Latest);\n const tx = new ReadTransactionImpl(clientID, dbRead, this.#lc);\n return await body(tx);\n } catch (ex) {\n throw await this.#convertToClientStateNotFoundError(ex);\n }\n });\n };\n\n #register<Return extends ReadonlyJSONValue | void, Args extends JSONValue>(\n name: string,\n mutatorImpl: (tx: WriteTransaction, args?: Args) => MaybePromise<Return>,\n ): (\n args?: Args,\n ) => Promise<Return> | {client: Promise<Return>; server: Promise<unknown>} {\n this.#mutatorRegistry[name] = mutatorImpl as (\n tx: WriteTransaction,\n args: JSONValue | undefined,\n ) => Promise<void | JSONValue>;\n\n return (\n args?: Args,\n ):\n | Promise<Return>\n | {client: Promise<Return>; server: Promise<unknown>} => {\n // DO NOT track CRUD mutations as they do not receive responses from\n // the server.\n const trackingData =\n name === '_zero_crud' ? undefined : this.#zero?.trackMutation();\n\n const result = this.#mutate(\n trackingData,\n name,\n mutatorImpl,\n args,\n performance.now(),\n );\n\n if (trackingData) {\n return {\n client: result,\n server: trackingData.serverPromise,\n };\n }\n\n return result;\n };\n }\n\n #registerMutators<\n M extends {\n [key: string]: (\n tx: WriteTransaction,\n args?: ReadonlyJSONValue,\n ) => MutatorReturn;\n },\n >(regs: M): MakeMutators<M> {\n type Mut = MakeMutators<M>;\n const rv: Partial<Mut> = Object.create(null);\n for (const k in regs) {\n rv[k] = this.#register(k, regs[k]) as MakeMutator<M[typeof k]>;\n }\n return rv as Mut;\n }\n\n async #mutate<\n R extends ReadonlyJSONValue | void,\n A extends ReadonlyJSONValue,\n >(\n trackingData: MutationTrackingData | undefined,\n name: string,\n mutatorImpl: (tx: WriteTransaction, args?: A) => MaybePromise<R>,\n args: A | undefined,\n timestamp: number,\n ): Promise<R> {\n const frozenArgs = deepFreeze(args ?? null);\n\n // Ensure that we run initial pending subscribe functions before starting a\n // write transaction.\n if (this.#subscriptions.hasPendingSubscriptionRuns) {\n await Promise.resolve();\n }\n\n await this.#ready;\n const {clientID} = this;\n return withWriteNoImplicitCommit(this.memdag, async dagWrite => {\n try {\n let result: R;\n let newHead: Hash;\n let diffs: DiffsMap;\n let headHash: Hash;\n try {\n headHash = await mustGetHeadHash(DEFAULT_HEAD_NAME, dagWrite);\n const originalHash = null;\n\n const dbWrite = await newWriteLocal(\n headHash,\n name,\n frozenArgs,\n originalHash,\n dagWrite,\n timestamp,\n clientID,\n FormatVersion.Latest,\n );\n\n const mutationID = await dbWrite.getMutationID();\n const tx = new WriteTransactionImpl(\n clientID,\n mutationID,\n 'initial',\n await this.#zero?.getTxData(headHash, {\n openLazyRead: dagWrite,\n }),\n dbWrite,\n this.#lc,\n );\n\n if (trackingData) {\n this.#zero?.mutationIDAssigned(\n trackingData.ephemeralID,\n mutationID,\n );\n }\n\n result = await mutatorImpl(tx, args);\n\n throwIfClosed(dbWrite);\n const lastMutationID = await dbWrite.getMutationID();\n [newHead, diffs] = await dbWrite.commitWithDiffs(\n DEFAULT_HEAD_NAME,\n this.#subscriptions,\n );\n\n // Update this after the commit in case the commit fails.\n this.lastMutationID = lastMutationID;\n } catch (e) {\n // If we threw before we could persist the mutation\n // then we need to reject the mutation.\n if (trackingData) {\n this.#zero?.rejectMutation(trackingData.ephemeralID, e);\n }\n throw e;\n }\n\n this.#zero?.advance(headHash, newHead, diffs.get('') ?? []);\n\n // Send is not supposed to reject\n this.#pushConnectionLoop.send(false).catch(() => void 0);\n await this.#subscriptions.fire(diffs);\n void this.#schedulePersist();\n return result;\n } catch (ex) {\n throw await this.#convertToClientStateNotFoundError(ex);\n }\n });\n }\n\n /**\n * In the case we get a ChunkNotFoundError we check if the client got garbage\n * collected and if so change the error to a ClientStateNotFoundError instead\n */\n async #convertToClientStateNotFoundError(ex: unknown): Promise<unknown> {\n if (\n ex instanceof ChunkNotFoundError &&\n (await this.#checkForClientStateNotFoundAndCallHandler())\n ) {\n return new ClientStateNotFoundError(this.clientID);\n }\n\n return ex;\n }\n\n recoverMutations(): Promise<boolean> | void {\n if (!process.env.DISABLE_MUTATION_RECOVERY) {\n // oxlint-disable-next-line no-non-null-assertion\n const result = this.#mutationRecovery!.recoverMutations(\n this.#ready,\n this.perdag,\n this.#idbDatabase,\n this.#idbDatabases,\n this.#kvStoreProvider.create,\n );\n if (TESTING) {\n void this.onRecoverMutations(result);\n }\n return result;\n }\n }\n\n /**\n * List of pending mutations. The order of this is from oldest to newest.\n *\n * Gives a list of local mutations that have `mutationID` >\n * `syncHead.mutationID` that exists on the main client group.\n *\n * @experimental This method is experimental and may change in the future.\n */\n experimentalPendingMutations(): Promise<readonly PendingMutation[]> {\n return withRead(this.memdag, pendingMutationsForAPI);\n }\n}\n\n// This map is used to keep track of closing instances of Replicache. When an\n// instance is opening we wait for any currently closing instances.\nconst closingInstances: Map<string, Promise<unknown>> = new Map();\n\nasync function throwIfError(p: Promise<undefined | {error: unknown}>) {\n const res = await p;\n if (res) {\n throw res.error;\n }\n}\n\nfunction reload(): void {\n if (typeof location !== 'undefined') {\n location.reload();\n }\n}\n\nfunction validateOptions<MD extends MutatorDefs>(\n options: ReplicacheOptions<MD>,\n): void {\n const {name, clientMaxAgeMs} = options;\n if (typeof name !== 'string' || !name) {\n throw new TypeError('name is required and must be non-empty');\n }\n\n if (clientMaxAgeMs !== undefined) {\n const min = Math.max(GC_INTERVAL, HEARTBEAT_INTERVAL);\n if (typeof clientMaxAgeMs !== 'number' || clientMaxAgeMs <= min) {\n throw new TypeError(\n `clientAgeMaxMs must be a number larger than ${min}ms`,\n );\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"replicache-impl.js","names":["#subscriptions","#mutationRecovery","#kvStoreProvider","#zero","#auth","#idbDatabase","#clientID","#ready","#profileIDPromise","#clientGroupIDPromise","#mutatorRegistry","#requestOptions","#idbDatabases","#lc","#closeAbortController","#persistLock","#enableScheduledPersist","#enableScheduledRefresh","#enableRefresh","#enablePullAndPushInOpen","#onPersist","#queryInternal","#pullConnectionLoop","#invokePull","#pushConnectionLoop","#invokePush","#registerMutators","#wrapInOnlineCheck","#wrapInReauthRetries","#isPullDisabled","#isPushDisabled","#handlePersist","#open","#clientStateNotFoundOnClient","#fireOnUpdateNeeded","#onVisibilityChange","#closed","#checkForClientStateNotFoundAndCallHandler","#online","#schedulePersist","#changeSyncCounters","#convertToClientStateNotFoundError","#handleVersionNotSupportedResponse","#clientStateNotFoundOnServer","#fireOnClientStateNotFound","#schedule","#persistScheduler","#scheduleRefresh","#refreshScheduler","#pushCounter","#pullCounter","#mutate","#register"],"sources":["../../../../replicache/src/replicache-impl.ts"],"sourcesContent":["import {Lock} from '@rocicorp/lock';\nimport type {LogContext} from '@rocicorp/logger';\nimport {consoleLogSink} from '@rocicorp/logger';\nimport {resolver} from '@rocicorp/resolver';\nimport {AbortError} from '../../shared/src/abort-error.ts';\nimport {assert} from '../../shared/src/asserts.ts';\nimport {getBrowserGlobal} from '../../shared/src/browser-env.ts';\nimport {getDocumentVisibilityWatcher} from '../../shared/src/document-visible.ts';\nimport type {JSONValue, ReadonlyJSONValue} from '../../shared/src/json.ts';\nimport {promiseVoid} from '../../shared/src/resolved-promises.ts';\nimport {TESTING} from '../../shared/src/testing.ts';\nimport type {MaybePromise} from '../../shared/src/types.ts';\nimport {PullDelegate, PushDelegate} from './connection-loop-delegates.ts';\nimport {ConnectionLoop, MAX_DELAY_MS, MIN_DELAY_MS} from './connection-loop.ts';\nimport {assertCookie, type Cookie} from './cookies.ts';\nimport {LazyStore} from './dag/lazy-store.ts';\nimport {StoreImpl} from './dag/store-impl.ts';\nimport {ChunkNotFoundError, mustGetHeadHash, type Store} from './dag/store.ts';\nimport {\n baseSnapshotFromHash,\n DEFAULT_HEAD_NAME,\n isLocalMetaDD31,\n type LocalMeta,\n} from './db/commit.ts';\nimport {readFromDefaultHead} from './db/read.ts';\nimport {rebaseMutationAndCommit} from './db/rebase.ts';\nimport {newWriteLocal} from './db/write.ts';\nimport {\n isClientStateNotFoundResponse,\n isVersionNotSupportedResponse,\n type VersionNotSupportedResponse,\n} from './error-responses.ts';\nimport * as FormatVersion from './format-version-enum.ts';\nimport {deepFreeze} from './frozen-json.ts';\nimport {getDefaultPuller, isDefaultPuller} from './get-default-puller.ts';\nimport {getDefaultPusher, isDefaultPusher} from './get-default-pusher.ts';\nimport {getKVStoreProvider} from './get-kv-store-provider.ts';\nimport {assertHash, emptyHash, type Hash, newRandomHash} from './hash.ts';\nimport type {HTTPRequestInfo} from './http-request-info.ts';\nimport {httpStatusUnauthorized} from './http-status-unauthorized.ts';\nimport type {IndexDefinitions} from './index-defs.ts';\nimport type {StoreProvider} from './kv/store.ts';\nimport {createLogContext} from './log-options.ts';\nimport {makeIDBName} from './make-idb-name.ts';\nimport {MutationRecovery} from './mutation-recovery.ts';\nimport {initNewClientChannel} from './new-client-channel.ts';\nimport {\n initOnPersistChannel,\n type OnPersist,\n type PersistInfo,\n} from './on-persist-channel.ts';\nimport {\n type PendingMutation,\n pendingMutationsForAPI,\n} from './pending-mutations.ts';\nimport {\n CLIENT_MAX_INACTIVE_TIME,\n GC_INTERVAL,\n initClientGC,\n} from './persist/client-gc.ts';\nimport {initClientGroupGC} from './persist/client-group-gc.ts';\nimport {disableClientGroup} from './persist/client-groups.ts';\nimport {\n ClientStateNotFoundError,\n initClientV6,\n type OnClientsDeleted,\n hasClientState as persistHasClientState,\n} from './persist/clients.ts';\nimport {\n COLLECT_IDB_INTERVAL,\n initCollectIDBDatabases,\n INITIAL_COLLECT_IDB_DELAY,\n} from './persist/collect-idb-databases.ts';\nimport {HEARTBEAT_INTERVAL, startHeartbeats} from './persist/heartbeat.ts';\nimport {\n IDBDatabasesStore,\n type IndexedDBDatabase,\n} from './persist/idb-databases-store.ts';\nimport {makeClientID} from './persist/make-client-id.ts';\nimport {persistDD31} from './persist/persist.ts';\nimport {refresh} from './persist/refresh.ts';\nimport {ProcessScheduler} from './process-scheduler.ts';\nimport type {Puller} from './puller.ts';\nimport {type Pusher, PushError} from './pusher.ts';\nimport type {\n MutationTrackingData,\n ReplicacheOptions,\n ZeroOption,\n} from './replicache-options.ts';\nimport {ReportError} from './report-error.ts';\nimport {setIntervalWithSignal} from './set-interval-with-signal.ts';\nimport {\n type SubscribeOptions,\n SubscriptionImpl,\n type SubscriptionsManager,\n SubscriptionsManagerImpl,\n type WatchCallback,\n type WatchCallbackForOptions,\n type WatchNoIndexCallback,\n type WatchOptions,\n WatchSubscription,\n} from './subscriptions.ts';\nimport type {DiffsMap} from './sync/diff.ts';\nimport * as HandlePullResponseResultEnum from './sync/handle-pull-response-result-type-enum.ts';\nimport type {ClientGroupID, ClientID} from './sync/ids.ts';\nimport {PullError} from './sync/pull-error.ts';\nimport {beginPullV1, handlePullResponseV1, maybeEndPull} from './sync/pull.ts';\nimport {push, PUSH_VERSION_DD31} from './sync/push.ts';\nimport {newRequestID} from './sync/request-id.ts';\nimport {SYNC_HEAD_NAME} from './sync/sync-head-name.ts';\nimport {throwIfClosed} from './transaction-closed-error.ts';\nimport type {ReadTransaction, WriteTransaction} from './transactions.ts';\nimport {ReadTransactionImpl, WriteTransactionImpl} from './transactions.ts';\nimport type {\n BeginPullResult,\n MakeMutator,\n MakeMutators,\n MutatorDefs,\n MutatorReturn,\n PokeInternal,\n QueryInternal,\n RequestOptions,\n UpdateNeededReason,\n} from './types.ts';\nimport {version} from './version.ts';\nimport {\n withRead,\n withWrite,\n withWriteNoImplicitCommit,\n} from './with-transactions.ts';\n\n/**\n * The maximum number of time to call out to getAuth before giving up\n * and throwing an error.\n */\nconst MAX_REAUTH_TRIES = 8;\n\nconst PERSIST_IDLE_TIMEOUT_MS = 1000;\nconst REFRESH_IDLE_TIMEOUT_MS = 1000;\n\nconst PERSIST_THROTTLE_MS = 500;\nconst REFRESH_THROTTLE_MS = 500;\n\n/**\n * Opening the database blocks everything Replicache does, including Zero's\n * first connect attempt, so a slow open is worth a warning rather than a\n * debug line.\n */\nconst SLOW_DB_OPEN_THRESHOLD_MS = 50;\n\nconst LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT = 100 * 2 ** 20; // 100 MB\n\nconst RECOVER_MUTATIONS_INTERVAL_MS = 5 * 60 * 1000; // 5 mins\n\nconst noop = () => {\n // noop\n};\n\nconst updateNeededReasonNewClientGroup: UpdateNeededReason = {\n type: 'NewClientGroup',\n} as const;\n\n/** @deprecated Not used any more */\nexport interface MakeSubscriptionsManager {\n (queryInternal: QueryInternal, lc: LogContext): SubscriptionsManager;\n}\n\nexport interface ReplicacheImplOptions {\n /**\n * Defaults to true.\n */\n enableMutationRecovery?: boolean | undefined;\n\n /**\n * Defaults to true.\n */\n enableScheduledPersist?: boolean | undefined;\n\n /**\n * Defaults to true.\n */\n enableScheduledRefresh?: boolean | undefined;\n\n /**\n * Defaults to `() => true`.\n */\n enableRefresh?: (() => boolean) | undefined;\n\n /**\n * Defaults to true.\n */\n enablePullAndPushInOpen?: boolean | undefined;\n\n /**\n * @deprecated Not used anymore.\n */\n makeSubscriptionsManager?: unknown;\n\n /**\n * Default is `true`. If `false` if an exact match client group\n * is not found, a new client group is always made instead of forking\n * from an existing client group.\n */\n enableClientGroupForking?: boolean | undefined;\n\n /**\n * Callback for when Replicache has deleted clients.\n */\n onClientsDeleted?: OnClientsDeleted | undefined;\n\n /**\n * Internal option used by Zero.\n * Replicache will call this to and, if zero is enabled, will\n * invoke various hooks to allow Zero the keep IVM in sync with Replicache's b-trees.\n */\n zero?: ZeroOption | undefined;\n}\n\nexport class ReplicacheImpl<MD extends MutatorDefs = {}> {\n /** The URL to use when doing a pull request. */\n pullURL: string;\n\n /** The URL to use when doing a push request. */\n pushURL: string;\n\n /** The authorization token used when doing a push request. */\n #auth: string;\n\n /** The name of the Replicache database. Populated by {@link ReplicacheOptions#name}. */\n readonly name: string;\n\n readonly #subscriptions: SubscriptionsManager;\n readonly #mutationRecovery: MutationRecovery | undefined;\n\n /**\n * Client groups gets disabled when the server does not know about it.\n * A disabled client group prevents the client from pushing and pulling.\n */\n isClientGroupDisabled = false;\n\n readonly #kvStoreProvider: StoreProvider;\n\n lastMutationID: number = 0;\n\n /**\n * This is the name Replicache uses for the IndexedDB database where data is\n * stored.\n */\n get idbName(): string {\n return makeIDBName(this.name, this.schemaVersion);\n }\n\n set auth(auth: string) {\n if (this.#zero) {\n this.#zero.auth = auth;\n }\n\n this.#auth = auth;\n }\n\n get auth() {\n return this.#auth;\n }\n\n /** The schema version of the data understood by this application. */\n readonly schemaVersion: string;\n\n get #idbDatabase(): IndexedDBDatabase {\n return {\n name: this.idbName,\n replicacheName: this.name,\n replicacheFormatVersion: FormatVersion.Latest,\n schemaVersion: this.schemaVersion,\n };\n }\n #closed = false;\n #online = true;\n readonly #clientID = makeClientID();\n readonly #ready: Promise<void>;\n readonly #profileIDPromise: Promise<string>;\n readonly #clientGroupIDPromise: Promise<string>;\n readonly #mutatorRegistry: MutatorDefs = {};\n\n /**\n * The mutators that was registered in the constructor.\n */\n readonly mutate: MakeMutators<MD>;\n\n // Number of pushes/pulls at the moment.\n #pushCounter = 0;\n #pullCounter = 0;\n\n #pullConnectionLoop: ConnectionLoop;\n #pushConnectionLoop: ConnectionLoop;\n\n /**\n * The duration between each periodic {@link pull}. Setting this to `null`\n * disables periodic pull completely. Pull will still happen if you call\n * {@link pull} manually.\n */\n pullInterval: number | null;\n\n /**\n * The delay between when a change is made to Replicache and when Replicache\n * attempts to push that change.\n */\n pushDelay: number;\n\n readonly #requestOptions: Required<RequestOptions>;\n\n /**\n * The function to use to pull data from the server.\n */\n puller: Puller;\n\n /**\n * The function to use to push data to the server.\n */\n pusher: Pusher;\n\n readonly memdag: LazyStore;\n readonly perdag: Store;\n readonly #idbDatabases: IDBDatabasesStore;\n readonly #lc: LogContext;\n readonly #zero: ZeroOption | undefined;\n\n readonly #closeAbortController = new AbortController();\n\n readonly #persistLock = new Lock();\n readonly #enableScheduledPersist: boolean;\n readonly #enableScheduledRefresh: boolean;\n readonly #enableRefresh: () => boolean;\n readonly #enablePullAndPushInOpen: boolean;\n #persistScheduler = new ProcessScheduler(\n () => this.persist(),\n PERSIST_IDLE_TIMEOUT_MS,\n PERSIST_THROTTLE_MS,\n this.#closeAbortController.signal,\n );\n readonly #onPersist: OnPersist;\n #refreshScheduler = new ProcessScheduler(\n () => this.refresh(),\n REFRESH_IDLE_TIMEOUT_MS,\n REFRESH_THROTTLE_MS,\n this.#closeAbortController.signal,\n );\n\n /**\n * The options used to control the {@link pull} and push request behavior. This\n * object is live so changes to it will affect the next pull or push call.\n */\n get requestOptions(): Required<RequestOptions> {\n return this.#requestOptions;\n }\n\n /**\n * `onSync(true)` is called when Replicache transitions from no push or pull\n * happening to at least one happening. `onSync(false)` is called in the\n * opposite case: when Replicache transitions from at least one push or pull\n * happening to none happening.\n *\n * This can be used in a React like app by doing something like the following:\n *\n * ```js\n * const [syncing, setSyncing] = useState(false);\n * useEffect(() => {\n * rep.onSync = setSyncing;\n * }, [rep]);\n * ```\n */\n onSync: ((syncing: boolean) => void) | null = null;\n\n /**\n * `onClientStateNotFound` is called when the persistent client has been\n * garbage collected. This can happen if the client has no pending mutations\n * and has not been used for a while.\n *\n * The default behavior is to reload the page (using `location.reload()`). Set\n * this to `null` or provide your own function to prevent the page from\n * reloading automatically.\n */\n onClientStateNotFound: (() => void) | null = reload;\n\n /**\n * `onUpdateNeeded` is called when a code update is needed.\n *\n * A code update can be needed because:\n * - the server no longer supports the {@link pushVersion},\n * {@link pullVersion} or {@link schemaVersion} of the current code.\n * - a new Replicache client has created a new client group, because its code\n * has different mutators, indexes, schema version and/or format version\n * from this Replicache client. This is likely due to the new client having\n * newer code. A code update is needed to be able to locally sync with this\n * new Replicache client (i.e. to sync while offline, the clients can still\n * sync with each other via the server).\n *\n * The default behavior is to reload the page (using `location.reload()`). Set\n * this to `null` or provide your own function to prevent the page from\n * reloading automatically. You may want to provide your own function to\n * display a toast to inform the end user there is a new version of your app\n * available and prompting them to refresh.\n */\n onUpdateNeeded: ((reason: UpdateNeededReason) => void) | null = reload;\n\n /**\n * This gets called when we get an HTTP unauthorized (401) response from the\n * push or pull endpoint. Set this to a function that will ask your user to\n * reauthenticate.\n */\n getAuth: (() => MaybePromise<string | null | undefined>) | null | undefined =\n null;\n\n // These three are used for testing\n onPushInvoked = () => undefined;\n onBeginPull = () => undefined;\n onRecoverMutations = (r: Promise<boolean>) => r;\n\n constructor(\n options: ReplicacheOptions<MD>,\n implOptions: ReplicacheImplOptions = {},\n ) {\n validateOptions(options);\n const {\n name,\n logLevel = 'info',\n logSinks = [consoleLogSink],\n pullURL = '',\n auth,\n pushDelay = 10,\n pushURL = '',\n schemaVersion = '',\n pullInterval = 60000,\n mutators = {} as MD,\n requestOptions = {},\n puller,\n pusher,\n indexes = {},\n clientMaxAgeMs = CLIENT_MAX_INACTIVE_TIME,\n } = options;\n const {\n enableMutationRecovery = true,\n enableScheduledPersist = true,\n enableScheduledRefresh = true,\n enableRefresh = () => true,\n enablePullAndPushInOpen = true,\n enableClientGroupForking = true,\n onClientsDeleted = () => promiseVoid,\n } = implOptions;\n this.#zero = implOptions.zero;\n this.#auth = auth ?? '';\n this.pullURL = pullURL;\n this.pushURL = pushURL;\n this.name = name;\n this.schemaVersion = schemaVersion;\n this.pullInterval = pullInterval;\n this.pushDelay = pushDelay;\n this.puller = puller ?? getDefaultPuller(this);\n this.pusher = pusher ?? getDefaultPusher(this);\n\n this.#enableScheduledPersist = enableScheduledPersist;\n this.#enableScheduledRefresh = enableScheduledRefresh;\n this.#enableRefresh = enableRefresh;\n this.#enablePullAndPushInOpen = enablePullAndPushInOpen;\n\n this.#lc = createLogContext(logLevel, logSinks, {name});\n this.#lc.debug?.('Constructing Replicache', {\n name,\n 'replicache version': version,\n });\n\n this.#subscriptions = new SubscriptionsManagerImpl(\n this.#queryInternal,\n this.#lc,\n this.#closeAbortController.signal,\n );\n\n const kvStoreProvider = getKVStoreProvider(this.#lc, options.kvStore);\n this.#kvStoreProvider = kvStoreProvider;\n\n const perKVStore = kvStoreProvider.create(this.idbName);\n\n this.#idbDatabases = new IDBDatabasesStore(kvStoreProvider.create);\n this.perdag = new StoreImpl(perKVStore, newRandomHash, assertHash);\n this.memdag = new LazyStore(\n this.perdag,\n LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT,\n newRandomHash,\n assertHash,\n );\n\n // Use a promise-resolve pair so that we have a promise to use even before\n // we call the Open RPC.\n const readyResolver = resolver<void>();\n this.#ready = readyResolver.promise;\n\n const {minDelayMs = MIN_DELAY_MS, maxDelayMs = MAX_DELAY_MS} =\n requestOptions;\n this.#requestOptions = {maxDelayMs, minDelayMs};\n\n const visibilityWatcher = getDocumentVisibilityWatcher(\n getBrowserGlobal('document'),\n 0,\n this.#closeAbortController.signal,\n );\n\n this.#pullConnectionLoop = new ConnectionLoop(\n this.#lc.withContext('PULL'),\n new PullDelegate(this, () => this.#invokePull()),\n visibilityWatcher,\n );\n\n this.#pushConnectionLoop = new ConnectionLoop(\n this.#lc.withContext('PUSH'),\n new PushDelegate(this, () => this.#invokePush()),\n );\n\n this.mutate = this.#registerMutators(mutators);\n\n const profileIDResolver = resolver<string>();\n this.#profileIDPromise = profileIDResolver.promise;\n const clientGroupIDResolver = resolver<string>();\n this.#clientGroupIDPromise = clientGroupIDResolver.promise;\n\n if (!process.env.DISABLE_MUTATION_RECOVERY) {\n this.#mutationRecovery = new MutationRecovery({\n delegate: this,\n lc: this.#lc,\n enableMutationRecovery,\n wrapInOnlineCheck: this.#wrapInOnlineCheck.bind(this),\n wrapInReauthRetries: this.#wrapInReauthRetries.bind(this),\n isPullDisabled: this.#isPullDisabled.bind(this),\n isPushDisabled: this.#isPushDisabled.bind(this),\n clientGroupIDPromise: this.#clientGroupIDPromise,\n });\n }\n\n this.#onPersist = initOnPersistChannel(\n this.name,\n this.#closeAbortController.signal,\n persistInfo => {\n void this.#handlePersist(persistInfo);\n },\n );\n\n void this.#open(\n indexes,\n enableClientGroupForking,\n enableMutationRecovery,\n clientMaxAgeMs,\n profileIDResolver.resolve,\n clientGroupIDResolver.resolve,\n readyResolver.resolve,\n onClientsDeleted,\n );\n }\n\n async #open(\n indexes: IndexDefinitions,\n enableClientGroupForking: boolean,\n enableMutationRecovery: boolean,\n clientMaxAgeMs: number,\n profileIDResolver: (profileID: string) => void,\n resolveClientGroupID: (clientGroupID: ClientGroupID) => void,\n resolveReady: () => void,\n onClientsDeleted: OnClientsDeleted,\n ): Promise<void> {\n const {clientID} = this;\n // Everything up to the head write is what it takes to have a usable\n // database, including waiting out a previous instance of the same name.\n // The timer stops before the replica is loaded into Zero's IVM sources,\n // which is separate work and usually the larger of the two: a number that\n // spanned both would report a slow hydration as a slow disk.\n const openStart = performance.now();\n // If we are currently closing a Replicache instance with the same name,\n // wait for it to finish closing.\n await closingInstances.get(this.name);\n await this.#idbDatabases.getProfileID().then(profileIDResolver);\n await this.#idbDatabases.putDatabase(this.#idbDatabase);\n const [client, headHash, , isNewClientGroup] = await initClientV6(\n clientID,\n this.#lc,\n this.perdag,\n Object.keys(this.#mutatorRegistry),\n indexes,\n FormatVersion.Latest,\n enableClientGroupForking,\n );\n\n resolveClientGroupID(client.clientGroupID);\n await withWrite(this.memdag, write =>\n write.setHead(DEFAULT_HEAD_NAME, headHash),\n );\n\n // Now we have a profileID, a clientID, a clientGroupID and DB!\n const dbOpenMs = performance.now() - openStart;\n if (dbOpenMs > SLOW_DB_OPEN_THRESHOLD_MS) {\n this.#lc.warn?.(`Opening the database took ${Math.round(dbOpenMs)}ms`, {\n name: this.idbName,\n });\n } else {\n this.#lc.debug?.('Opened the database in', Math.round(dbOpenMs), 'ms');\n }\n\n await this.#zero?.init(headHash, this.memdag);\n resolveReady();\n\n if (this.#enablePullAndPushInOpen) {\n this.pull().catch(noop);\n this.push().catch(noop);\n }\n\n const {signal} = this.#closeAbortController;\n\n startHeartbeats(\n clientID,\n this.perdag,\n () => {\n this.#clientStateNotFoundOnClient(clientID);\n },\n HEARTBEAT_INTERVAL,\n this.#lc,\n signal,\n );\n initClientGC(\n clientID,\n this.perdag,\n clientMaxAgeMs,\n GC_INTERVAL,\n onClientsDeleted,\n this.#lc,\n signal,\n );\n initCollectIDBDatabases(\n this.#idbDatabases,\n this.#kvStoreProvider,\n COLLECT_IDB_INTERVAL,\n INITIAL_COLLECT_IDB_DELAY,\n 2 * clientMaxAgeMs,\n enableMutationRecovery,\n onClientsDeleted,\n this.#lc,\n signal,\n );\n initClientGroupGC(this.perdag, enableMutationRecovery, this.#lc, signal);\n initNewClientChannel(\n this.name,\n this.idbName,\n signal,\n client.clientGroupID,\n isNewClientGroup,\n () => {\n this.#fireOnUpdateNeeded(updateNeededReasonNewClientGroup);\n },\n this.perdag,\n );\n\n setIntervalWithSignal(\n () => this.recoverMutations(),\n RECOVER_MUTATIONS_INTERVAL_MS,\n signal,\n );\n void this.recoverMutations();\n\n getBrowserGlobal('document')?.addEventListener(\n 'visibilitychange',\n this.#onVisibilityChange,\n );\n }\n\n #onVisibilityChange = async () => {\n if (this.#closed) {\n return;\n }\n\n // In case of running in a worker, we don't have a document.\n if (getBrowserGlobal('document')?.visibilityState !== 'visible') {\n return;\n }\n\n await this.#checkForClientStateNotFoundAndCallHandler();\n };\n\n async #checkForClientStateNotFoundAndCallHandler(): Promise<boolean> {\n const {clientID} = this;\n const hasClientState = await withRead(this.perdag, read =>\n persistHasClientState(clientID, read),\n );\n if (!hasClientState) {\n this.#clientStateNotFoundOnClient(clientID);\n }\n return !hasClientState;\n }\n\n /**\n * The browser profile ID for this browser profile. Every instance of Replicache\n * browser-profile-wide shares the same profile ID.\n */\n get profileID(): Promise<string> {\n return this.#profileIDPromise;\n }\n\n /**\n * The client ID for this instance of Replicache. Each instance of Replicache\n * gets a unique client ID.\n */\n get clientID(): string {\n return this.#clientID;\n }\n\n /**\n * The client group ID for this instance of Replicache. Instances of\n * Replicache will have the same client group ID if and only if they have\n * the same name, mutators, indexes, schema version, format version, and\n * browser profile.\n */\n get clientGroupID(): Promise<string> {\n return this.#clientGroupIDPromise;\n }\n\n /**\n * `onOnlineChange` is called when the {@link online} property changes. See\n * {@link online} for more details.\n */\n onOnlineChange: ((online: boolean) => void) | null = null;\n\n /**\n * A rough heuristic for whether the client is currently online. Note that\n * there is no way to know for certain whether a client is online - the next\n * request can always fail. This property returns true if the last sync attempt succeeded,\n * and false otherwise.\n */\n get online(): boolean {\n return this.#online;\n }\n\n /**\n * Whether the Replicache database has been closed. Once Replicache has been\n * closed it no longer syncs and you can no longer read or write data out of\n * it. After it has been closed it is pretty much useless and should not be\n * used any more.\n */\n get closed(): boolean {\n return this.#closed;\n }\n\n /**\n * Closes this Replicache instance.\n *\n * When closed all subscriptions end and no more read or writes are allowed.\n */\n async close(): Promise<void> {\n this.#closed = true;\n const {promise, resolve} = resolver();\n closingInstances.set(this.name, promise);\n\n this.#closeAbortController.abort();\n\n getBrowserGlobal('document')?.removeEventListener(\n 'visibilitychange',\n this.#onVisibilityChange,\n );\n\n await this.#ready;\n const closingPromises = [\n this.memdag.close(),\n this.perdag.close(),\n this.#idbDatabases.close(),\n ];\n\n this.#pullConnectionLoop.close();\n this.#pushConnectionLoop.close();\n\n this.#subscriptions.clear();\n\n await Promise.all(closingPromises);\n closingInstances.delete(this.name);\n resolve();\n }\n\n async maybeEndPull(syncHead: Hash, requestID: string): Promise<void> {\n for (;;) {\n if (this.#closed) {\n return;\n }\n\n await this.#ready;\n const {clientID} = this;\n const lc = this.#lc\n .withContext('maybeEndPull')\n .withContext('requestID', requestID);\n const {replayMutations, diffs, oldMainHead, mainHead} =\n await maybeEndPull<LocalMeta>(\n this.memdag,\n lc,\n syncHead,\n clientID,\n this.#subscriptions,\n FormatVersion.Latest,\n );\n\n if (!replayMutations || replayMutations.length === 0) {\n // All done.\n this.#zero?.advance(oldMainHead, mainHead, diffs.get('') ?? []);\n await this.#subscriptions.fire(diffs);\n void this.#schedulePersist();\n return;\n }\n\n // Replay.\n let zeroData = await this.#zero?.getTxData?.(syncHead);\n for (const mutation of replayMutations) {\n // TODO(greg): I'm not sure why this was in Replicache#_mutate...\n // Ensure that we run initial pending subscribe functions before starting a\n // write transaction.\n if (this.#subscriptions.hasPendingSubscriptionRuns) {\n await Promise.resolve();\n }\n const {meta} = mutation;\n const {result, zeroData: next} = await withWriteNoImplicitCommit(\n this.memdag,\n dagWrite =>\n rebaseMutationAndCommit(\n mutation,\n dagWrite,\n syncHead,\n SYNC_HEAD_NAME,\n this.#mutatorRegistry,\n lc,\n isLocalMetaDD31(meta) ? meta.clientID : clientID,\n FormatVersion.Latest,\n zeroData,\n ),\n );\n syncHead = result;\n // The fork the mutation ran against when it succeeded, or the branch we\n // came in with when it threw.\n zeroData = next;\n }\n }\n }\n\n #invokePull(): Promise<boolean> {\n if (this.#isPullDisabled()) {\n return Promise.resolve(true);\n }\n\n return this.#wrapInOnlineCheck(async () => {\n try {\n this.#changeSyncCounters(0, 1);\n const {syncHead, requestID, ok} = await this.beginPull();\n if (!ok) {\n return false;\n }\n if (syncHead !== emptyHash) {\n await this.maybeEndPull(syncHead, requestID);\n }\n } catch (e) {\n throw await this.#convertToClientStateNotFoundError(e);\n } finally {\n this.#changeSyncCounters(0, -1);\n }\n return true;\n }, 'Pull');\n }\n\n #isPullDisabled() {\n return (\n this.isClientGroupDisabled ||\n (this.pullURL === '' && isDefaultPuller(this.puller))\n );\n }\n\n async #wrapInOnlineCheck(\n f: () => Promise<boolean>,\n name: string,\n ): Promise<boolean> {\n let online = true;\n\n try {\n return await f();\n } catch (e) {\n // The error paths of beginPull and maybeEndPull need to be reworked.\n //\n // We want to distinguish between:\n // a) network requests failed -- we're offline basically\n // b) sync was aborted because one's already in progress\n // c) oh noes - something unexpected happened\n //\n // Right now, all of these come out as errors. We distinguish (b) with a\n // hacky string search. (a) and (c) are not distinguishable currently\n // because repc doesn't provide sufficient information, so we treat all\n // errors that aren't (b) as (a).\n if (e instanceof PushError || e instanceof PullError) {\n online = false;\n this.#lc.debug?.(`${name} threw:\\n`, e, '\\nwith cause:\\n', e.causedBy);\n } else if (e instanceof ReportError) {\n this.#lc.error?.(e);\n } else {\n this.#lc.info?.(`${name} threw:\\n`, e);\n }\n return false;\n } finally {\n if (this.#online !== online) {\n this.#online = online;\n this.onOnlineChange?.(online);\n if (online) {\n void this.recoverMutations();\n }\n }\n }\n }\n\n async #wrapInReauthRetries<R>(\n f: (\n requestID: string,\n requestLc: LogContext,\n ) => Promise<{\n httpRequestInfo: HTTPRequestInfo | undefined;\n result: R;\n }>,\n verb: string,\n lc: LogContext,\n preAuth: () => MaybePromise<void> = noop,\n postAuth: () => MaybePromise<void> = noop,\n ): Promise<{\n result: R;\n authFailure: boolean;\n }> {\n const {clientID} = this;\n let reauthAttempts = 0;\n let lastResult;\n lc = lc.withContext(verb);\n do {\n const requestID = newRequestID(clientID);\n const requestLc = lc.withContext('requestID', requestID);\n const {httpRequestInfo, result} = await f(requestID, requestLc);\n lastResult = result;\n if (!httpRequestInfo) {\n return {\n result,\n authFailure: false,\n };\n }\n const {errorMessage, httpStatusCode} = httpRequestInfo;\n\n if (errorMessage || httpStatusCode !== 200) {\n // TODO(arv): Maybe we should not log the server URL when the error comes\n // from a Pusher/Puller?\n requestLc.error?.(\n `Got a non 200 response doing ${verb}: ${httpStatusCode}` +\n (errorMessage ? `: ${errorMessage}` : ''),\n );\n }\n if (httpStatusCode !== httpStatusUnauthorized) {\n return {\n result,\n authFailure: false,\n };\n }\n if (!this.getAuth) {\n return {\n result,\n authFailure: true,\n };\n }\n let auth;\n try {\n await preAuth();\n auth = await this.getAuth();\n } finally {\n await postAuth();\n }\n if (auth === null || auth === undefined) {\n return {\n result,\n authFailure: true,\n };\n }\n this.auth = auth;\n reauthAttempts++;\n } while (reauthAttempts < MAX_REAUTH_TRIES);\n lc.info?.('Tried to reauthenticate too many times');\n return {\n result: lastResult,\n authFailure: true,\n };\n }\n\n #isPushDisabled() {\n return (\n this.isClientGroupDisabled ||\n (this.pushURL === '' && isDefaultPusher(this.pusher))\n );\n }\n\n async #invokePush(): Promise<boolean> {\n if (TESTING) {\n this.onPushInvoked();\n }\n if (this.#isPushDisabled()) {\n return true;\n }\n\n await this.#ready;\n const profileID = await this.#profileIDPromise;\n const {clientID} = this;\n const clientGroupID = await this.#clientGroupIDPromise;\n return this.#wrapInOnlineCheck(async () => {\n const {result: pusherResult} = await this.#wrapInReauthRetries(\n async (requestID: string, requestLc: LogContext) => {\n try {\n this.#changeSyncCounters(1, 0);\n const pusherResult = await push(\n requestID,\n this.memdag,\n requestLc,\n profileID,\n clientGroupID,\n clientID,\n this.pusher,\n this.schemaVersion,\n PUSH_VERSION_DD31,\n );\n return {\n result: pusherResult,\n httpRequestInfo: pusherResult?.httpRequestInfo,\n };\n } finally {\n this.#changeSyncCounters(-1, 0);\n }\n },\n 'push',\n this.#lc,\n );\n\n if (pusherResult === undefined) {\n // No pending mutations.\n return true;\n }\n\n const {response, httpRequestInfo} = pusherResult;\n\n if (isVersionNotSupportedResponse(response)) {\n this.#handleVersionNotSupportedResponse(response);\n } else if (isClientStateNotFoundResponse(response)) {\n await this.#clientStateNotFoundOnServer();\n }\n\n // No pushResponse means we didn't do a push because there were no\n // pending mutations.\n return httpRequestInfo.httpStatusCode === 200;\n }, 'Push');\n }\n\n #handleVersionNotSupportedResponse(response: VersionNotSupportedResponse) {\n const reason: UpdateNeededReason = {\n type: response.error,\n };\n if (response.versionType) {\n reason.versionType = response.versionType;\n }\n this.#fireOnUpdateNeeded(reason);\n }\n\n /**\n * Push pushes pending changes to the {@link pushURL}.\n *\n * You do not usually need to manually call push. If {@link pushDelay} is\n * non-zero (which it is by default) pushes happen automatically shortly after\n * mutations.\n *\n * If the server endpoint fails push will be continuously retried with an\n * exponential backoff.\n *\n * @param [now=false] If true, push will happen immediately and ignore\n * {@link pushDelay}, {@link RequestOptions.minDelayMs} as well as the\n * exponential backoff in case of errors.\n * @returns A promise that resolves when the next push completes. In case of\n * errors the first error will reject the returned promise. Subsequent errors\n * will not be reflected in the promise.\n */\n push({now = false} = {}): Promise<void> {\n return throwIfError(this.#pushConnectionLoop.send(now));\n }\n\n /**\n * Pull pulls changes from the {@link pullURL}. If there are any changes local\n * changes will get replayed on top of the new server state.\n *\n * If the server endpoint fails pull will be continuously retried with an\n * exponential backoff.\n *\n * @param [now=false] If true, pull will happen immediately and ignore\n * {@link RequestOptions.minDelayMs} as well as the exponential backoff in\n * case of errors.\n * @returns A promise that resolves when the next pull completes. In case of\n * errors the first error will reject the returned promise. Subsequent errors\n * will not be reflected in the promise.\n */\n pull({now = false} = {}): Promise<void> {\n return throwIfError(this.#pullConnectionLoop.send(now));\n }\n\n /**\n * Applies an update from the server to Replicache.\n * Throws an error if cookie does not match. In that case the server thinks\n * this client has a different cookie than it does; the caller should disconnect\n * from the server and re-register, which transmits the cookie the client actually\n * has.\n *\n * @experimental This method is under development and its semantics will change.\n */\n async poke(poke: PokeInternal): Promise<void> {\n await this.#ready;\n // TODO(MP) Previously we created a request ID here and included it with the\n // PullRequest to the server so we could tie events across client and server\n // together. Since the direction is now reversed, creating and adding a request ID\n // here is kind of silly. We should consider creating the request ID\n // on the *server* and passing it down in the poke for inclusion here in the log\n // context\n const {clientID} = this;\n const requestID = newRequestID(clientID);\n const lc = this.#lc\n .withContext('handlePullResponse')\n .withContext('requestID', requestID);\n\n const {pullResponse} = poke;\n\n if (isVersionNotSupportedResponse(pullResponse)) {\n this.#handleVersionNotSupportedResponse(pullResponse);\n return;\n }\n\n if (isClientStateNotFoundResponse(pullResponse)) {\n await this.#clientStateNotFoundOnServer();\n return;\n }\n\n const result = await handlePullResponseV1(\n lc,\n this.memdag,\n deepFreeze(poke.baseCookie),\n pullResponse,\n clientID,\n FormatVersion.Latest,\n );\n\n switch (result.type) {\n case HandlePullResponseResultEnum.Applied:\n await this.maybeEndPull(result.syncHead, requestID);\n break;\n case HandlePullResponseResultEnum.CookieMismatch:\n throw new Error(\n 'unexpected base cookie for poke: ' + JSON.stringify(poke),\n );\n case HandlePullResponseResultEnum.NoOp:\n break;\n }\n }\n\n async beginPull(): Promise<BeginPullResult> {\n if (TESTING) {\n this.onBeginPull();\n }\n await this.#ready;\n const profileID = await this.profileID;\n const {clientID} = this;\n const clientGroupID = await this.#clientGroupIDPromise;\n const {\n result: {beginPullResponse, requestID},\n } = await this.#wrapInReauthRetries(\n async (requestID: string, requestLc: LogContext) => {\n const beginPullResponse = await beginPullV1(\n profileID,\n clientID,\n clientGroupID,\n this.schemaVersion,\n this.puller,\n requestID,\n this.memdag,\n FormatVersion.Latest,\n requestLc,\n );\n return {\n result: {beginPullResponse, requestID},\n httpRequestInfo: beginPullResponse.httpRequestInfo,\n };\n },\n 'pull',\n this.#lc,\n () => this.#changeSyncCounters(0, -1),\n () => this.#changeSyncCounters(0, 1),\n );\n\n const {pullResponse} = beginPullResponse;\n if (isVersionNotSupportedResponse(pullResponse)) {\n this.#handleVersionNotSupportedResponse(pullResponse);\n } else if (isClientStateNotFoundResponse(beginPullResponse.pullResponse)) {\n await this.#clientStateNotFoundOnServer();\n }\n\n const {syncHead, httpRequestInfo} = beginPullResponse;\n return {requestID, syncHead, ok: httpRequestInfo.httpStatusCode === 200};\n }\n\n persist(): Promise<void> {\n // Prevent multiple persist calls from running at the same time.\n return this.#persistLock.withLock(async () => {\n const {clientID} = this;\n await this.#ready;\n if (this.#closed) {\n return;\n }\n try {\n await persistDD31(\n this.#lc,\n clientID,\n this.memdag,\n this.perdag,\n this.#mutatorRegistry,\n () => this.#closed,\n FormatVersion.Latest,\n this.#zero?.getTxData,\n );\n } catch (e) {\n if (e instanceof ClientStateNotFoundError) {\n this.#clientStateNotFoundOnClient(clientID);\n } else if (this.#closed) {\n this.#lc.debug?.('Exception persisting during close', e);\n } else {\n throw e;\n }\n }\n\n const clientGroupID = await this.#clientGroupIDPromise;\n assert(clientGroupID, 'Expected clientGroupID to be defined');\n this.#onPersist({clientID, clientGroupID});\n });\n }\n\n async refresh(): Promise<void> {\n await this.#ready;\n const {clientID} = this;\n if (this.#closed || !this.#enableRefresh()) {\n return;\n }\n let refreshResult: Awaited<ReturnType<typeof refresh>>;\n try {\n refreshResult = await refresh(\n this.#lc,\n this.memdag,\n this.perdag,\n clientID,\n this.#mutatorRegistry,\n this.#subscriptions,\n () => this.closed,\n FormatVersion.Latest,\n this.#zero,\n );\n } catch (e) {\n if (e instanceof ClientStateNotFoundError) {\n this.#clientStateNotFoundOnClient(clientID);\n } else if (this.#closed) {\n this.#lc.debug?.('Exception refreshing during close', e);\n } else {\n throw e;\n }\n }\n if (refreshResult !== undefined) {\n await this.#subscriptions.fire(refreshResult.diffs);\n }\n }\n\n #fireOnClientStateNotFound() {\n this.onClientStateNotFound?.();\n }\n\n #clientStateNotFoundOnClient(clientID: ClientID) {\n this.#lc.error?.(`Client state not found on client, clientID: ${clientID}`);\n this.#fireOnClientStateNotFound();\n }\n\n async #clientStateNotFoundOnServer() {\n const clientGroupID = await this.#clientGroupIDPromise;\n this.#lc.error?.(\n `Client state not found on server, clientGroupID: ${clientGroupID}`,\n );\n await this.disableClientGroup();\n this.#fireOnClientStateNotFound();\n }\n\n async disableClientGroup(): Promise<void> {\n const clientGroupID = await this.#clientGroupIDPromise;\n assert(clientGroupID, 'Expected clientGroupID to be defined');\n this.isClientGroupDisabled = true;\n await withWrite(this.perdag, dagWrite =>\n disableClientGroup(clientGroupID, dagWrite),\n );\n }\n\n #fireOnUpdateNeeded(reason: UpdateNeededReason) {\n this.#lc.debug?.(`Update needed, reason: ${reason}`);\n this.onUpdateNeeded?.(reason);\n }\n\n async #schedulePersist(): Promise<void> {\n if (!this.#enableScheduledPersist) {\n return;\n }\n await this.#schedule('persist', this.#persistScheduler);\n }\n\n async #handlePersist(persistInfo: PersistInfo): Promise<void> {\n this.#lc.debug?.('Handling persist', persistInfo);\n const clientGroupID = await this.#clientGroupIDPromise;\n if (persistInfo.clientGroupID === clientGroupID) {\n void this.#scheduleRefresh();\n }\n }\n\n async #scheduleRefresh(): Promise<void> {\n if (!this.#enableScheduledRefresh) {\n return;\n }\n await this.#schedule('refresh from storage', this.#refreshScheduler);\n }\n\n async #schedule(name: string, scheduler: ProcessScheduler): Promise<void> {\n try {\n await scheduler.schedule();\n } catch (e) {\n if (e instanceof AbortError) {\n this.#lc.debug?.(`Scheduled ${name} did not complete before close.`);\n } else {\n this.#lc.error?.(`Error during ${name}`, e);\n }\n }\n }\n\n /**\n * Runs a refresh as soon as possible through the refresh scheduler.\n */\n runRefresh(): Promise<void> {\n return this.#refreshScheduler.run();\n }\n\n #changeSyncCounters(pushDelta: 0, pullDelta: 1 | -1): void;\n #changeSyncCounters(pushDelta: 1 | -1, pullDelta: 0): void;\n #changeSyncCounters(pushDelta: number, pullDelta: number): void {\n this.#pushCounter += pushDelta;\n this.#pullCounter += pullDelta;\n const delta = pushDelta + pullDelta;\n const counter = this.#pushCounter + this.#pullCounter;\n if ((delta === 1 && counter === 1) || counter === 0) {\n const syncing = counter > 0;\n // Run in a new microtask.\n void Promise.resolve().then(() => this.onSync?.(syncing));\n }\n }\n\n /**\n * Subscribe to the result of a {@link query}. The `body` function is\n * evaluated once and its results are returned via `onData`.\n *\n * Thereafter, each time the the result of `body` changes, `onData` is fired\n * again with the new result.\n *\n * `subscribe()` goes to significant effort to avoid extraneous work\n * re-evaluating subscriptions:\n *\n * 1. subscribe tracks the keys that `body` accesses each time it runs. `body`\n * is only re-evaluated when those keys change.\n * 2. subscribe only re-fires `onData` in the case that a result changes by\n * way of the `isEqual` option which defaults to doing a deep JSON value\n * equality check.\n *\n * Because of (1), `body` must be a pure function of the data in Replicache.\n * `body` must not access anything other than the `tx` parameter passed to it.\n *\n * Although subscribe is as efficient as it can be, it is somewhat constrained\n * by the goal of returning an arbitrary computation of the cache. For even\n * better performance (but worse dx), see {@link experimentalWatch}.\n *\n * If an error occurs in the `body` the `onError` function is called if\n * present. Otherwise, the error is logged at log level 'error'.\n *\n * To cancel the subscription, call the returned function.\n *\n * @param body The function to evaluate to get the value to pass into\n * `onData`.\n * @param options Options is either a function or an object. If it is a\n * function it is equivalent to passing it as the `onData` property of an\n * object.\n */\n subscribe<R>(\n body: (tx: ReadTransaction) => Promise<R>,\n options: SubscribeOptions<R> | ((result: R) => void),\n ): () => void {\n if (typeof options === 'function') {\n options = {onData: options};\n }\n\n const {onData, onError, onDone, isEqual} = options;\n return this.#subscriptions.add(\n new SubscriptionImpl(body, onData, onError, onDone, isEqual),\n );\n }\n\n /**\n * Watches Replicache for changes.\n *\n * The `callback` gets called whenever the underlying data changes and the\n * `key` changes matches the `prefix` of {@link ExperimentalWatchIndexOptions} or\n * {@link ExperimentalWatchNoIndexOptions} if present. If a change\n * occurs to the data but the change does not impact the key space the\n * callback is not called. In other words, the callback is never called with\n * an empty diff.\n *\n * This gets called after commit (a mutation or a rebase).\n *\n * @experimental This method is under development and its semantics will\n * change.\n */\n experimentalWatch(callback: WatchNoIndexCallback): () => void;\n experimentalWatch<Options extends WatchOptions>(\n callback: WatchCallbackForOptions<Options>,\n options?: Options,\n ): () => void;\n experimentalWatch<Options extends WatchOptions>(\n callback: WatchCallbackForOptions<Options>,\n options?: Options,\n ): () => void {\n return this.#subscriptions.add(\n new WatchSubscription(callback as WatchCallback, options),\n );\n }\n\n /**\n * Query is used for read transactions. It is recommended to use transactions\n * to ensure you get a consistent view across multiple calls to `get`, `has`\n * and `scan`.\n */\n query<R>(body: (tx: ReadTransaction) => Promise<R> | R): Promise<R> {\n return this.#queryInternal(body);\n }\n\n get cookie(): Promise<Cookie> {\n return this.#ready.then(() =>\n withRead(this.memdag, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head found');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n const cookie = baseSnapshotMeta.cookieJSON;\n assertCookie(cookie);\n return cookie;\n }),\n );\n }\n\n #queryInternal: QueryInternal = async body => {\n await this.#ready;\n const {clientID} = this;\n return withRead(this.memdag, async dagRead => {\n try {\n const dbRead = await readFromDefaultHead(dagRead, FormatVersion.Latest);\n const tx = new ReadTransactionImpl(clientID, dbRead, this.#lc);\n return await body(tx);\n } catch (ex) {\n throw await this.#convertToClientStateNotFoundError(ex);\n }\n });\n };\n\n #register<Return extends ReadonlyJSONValue | void, Args extends JSONValue>(\n name: string,\n mutatorImpl: (tx: WriteTransaction, args?: Args) => MaybePromise<Return>,\n ): (\n args?: Args,\n ) => Promise<Return> | {client: Promise<Return>; server: Promise<unknown>} {\n this.#mutatorRegistry[name] = mutatorImpl as (\n tx: WriteTransaction,\n args: JSONValue | undefined,\n ) => Promise<void | JSONValue>;\n\n return (\n args?: Args,\n ):\n | Promise<Return>\n | {client: Promise<Return>; server: Promise<unknown>} => {\n // DO NOT track CRUD mutations as they do not receive responses from\n // the server.\n const trackingData =\n name === '_zero_crud' ? undefined : this.#zero?.trackMutation();\n\n const result = this.#mutate(\n trackingData,\n name,\n mutatorImpl,\n args,\n performance.now(),\n );\n\n if (trackingData) {\n return {\n client: result,\n server: trackingData.serverPromise,\n };\n }\n\n return result;\n };\n }\n\n #registerMutators<\n M extends {\n [key: string]: (\n tx: WriteTransaction,\n args?: ReadonlyJSONValue,\n ) => MutatorReturn;\n },\n >(regs: M): MakeMutators<M> {\n type Mut = MakeMutators<M>;\n const rv: Partial<Mut> = Object.create(null);\n for (const k in regs) {\n rv[k] = this.#register(k, regs[k]) as MakeMutator<M[typeof k]>;\n }\n return rv as Mut;\n }\n\n async #mutate<\n R extends ReadonlyJSONValue | void,\n A extends ReadonlyJSONValue,\n >(\n trackingData: MutationTrackingData | undefined,\n name: string,\n mutatorImpl: (tx: WriteTransaction, args?: A) => MaybePromise<R>,\n args: A | undefined,\n timestamp: number,\n ): Promise<R> {\n const frozenArgs = deepFreeze(args ?? null);\n\n // Ensure that we run initial pending subscribe functions before starting a\n // write transaction.\n if (this.#subscriptions.hasPendingSubscriptionRuns) {\n await Promise.resolve();\n }\n\n await this.#ready;\n const {clientID} = this;\n return withWriteNoImplicitCommit(this.memdag, async dagWrite => {\n try {\n let result: R;\n let newHead: Hash;\n let diffs: DiffsMap;\n let headHash: Hash;\n try {\n headHash = await mustGetHeadHash(DEFAULT_HEAD_NAME, dagWrite);\n const originalHash = null;\n\n const dbWrite = await newWriteLocal(\n headHash,\n name,\n frozenArgs,\n originalHash,\n dagWrite,\n timestamp,\n clientID,\n FormatVersion.Latest,\n );\n\n const mutationID = await dbWrite.getMutationID();\n const tx = new WriteTransactionImpl(\n clientID,\n mutationID,\n 'initial',\n await this.#zero?.getTxData(headHash, {\n openLazyRead: dagWrite,\n }),\n dbWrite,\n this.#lc,\n );\n\n if (trackingData) {\n this.#zero?.mutationIDAssigned(\n trackingData.ephemeralID,\n mutationID,\n );\n }\n\n result = await mutatorImpl(tx, args);\n\n throwIfClosed(dbWrite);\n const lastMutationID = await dbWrite.getMutationID();\n [newHead, diffs] = await dbWrite.commitWithDiffs(\n DEFAULT_HEAD_NAME,\n this.#subscriptions,\n );\n\n // Update this after the commit in case the commit fails.\n this.lastMutationID = lastMutationID;\n } catch (e) {\n // If we threw before we could persist the mutation\n // then we need to reject the mutation.\n if (trackingData) {\n this.#zero?.rejectMutation(trackingData.ephemeralID, e);\n }\n throw e;\n }\n\n this.#zero?.advance(headHash, newHead, diffs.get('') ?? []);\n\n // Send is not supposed to reject\n this.#pushConnectionLoop.send(false).catch(() => void 0);\n await this.#subscriptions.fire(diffs);\n void this.#schedulePersist();\n return result;\n } catch (ex) {\n throw await this.#convertToClientStateNotFoundError(ex);\n }\n });\n }\n\n /**\n * In the case we get a ChunkNotFoundError we check if the client got garbage\n * collected and if so change the error to a ClientStateNotFoundError instead\n */\n async #convertToClientStateNotFoundError(ex: unknown): Promise<unknown> {\n if (\n ex instanceof ChunkNotFoundError &&\n (await this.#checkForClientStateNotFoundAndCallHandler())\n ) {\n return new ClientStateNotFoundError(this.clientID);\n }\n\n return ex;\n }\n\n recoverMutations(): Promise<boolean> | void {\n if (!process.env.DISABLE_MUTATION_RECOVERY) {\n // oxlint-disable-next-line no-non-null-assertion\n const result = this.#mutationRecovery!.recoverMutations(\n this.#ready,\n this.perdag,\n this.#idbDatabase,\n this.#idbDatabases,\n this.#kvStoreProvider.create,\n );\n if (TESTING) {\n void this.onRecoverMutations(result);\n }\n return result;\n }\n }\n\n /**\n * List of pending mutations. The order of this is from oldest to newest.\n *\n * Gives a list of local mutations that have `mutationID` >\n * `syncHead.mutationID` that exists on the main client group.\n *\n * @experimental This method is experimental and may change in the future.\n */\n experimentalPendingMutations(): Promise<readonly PendingMutation[]> {\n return withRead(this.memdag, pendingMutationsForAPI);\n }\n}\n\n// This map is used to keep track of closing instances of Replicache. When an\n// instance is opening we wait for any currently closing instances.\nconst closingInstances: Map<string, Promise<unknown>> = new Map();\n\nasync function throwIfError(p: Promise<undefined | {error: unknown}>) {\n const res = await p;\n if (res) {\n throw res.error;\n }\n}\n\nfunction reload(): void {\n if (typeof location !== 'undefined') {\n location.reload();\n }\n}\n\nfunction validateOptions<MD extends MutatorDefs>(\n options: ReplicacheOptions<MD>,\n): void {\n const {name, clientMaxAgeMs} = options;\n if (typeof name !== 'string' || !name) {\n throw new TypeError('name is required and must be non-empty');\n }\n\n if (clientMaxAgeMs !== undefined) {\n const min = Math.max(GC_INTERVAL, HEARTBEAT_INTERVAL);\n if (typeof clientMaxAgeMs !== 'number' || clientMaxAgeMs <= min) {\n throw new TypeError(\n `clientAgeMaxMs must be a number larger than ${min}ms`,\n );\n }\n }\n}\n"],"mappings":"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"}
@@ -236,6 +236,15 @@ export interface ZeroTxData {
236
236
  ivmSources: unknown;
237
237
  token: string | undefined;
238
238
  context: unknown;
239
+ /**
240
+ * A cheap copy, used for one mutation's speculative writes.
241
+ *
242
+ * Replaying a mutation writes to two places: Replicache's `Write` and the
243
+ * IVM sources held here. If the mutator throws, the `Write` is discarded,
244
+ * and the fork lets the IVM writes be discarded with it. The caller adopts
245
+ * the fork when the mutator succeeds and drops it when it throws.
246
+ */
247
+ fork(): ZeroTxData;
239
248
  }
240
249
  export type ZeroReadOptions = {
241
250
  openLazyRead?: Read | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"replicache-options.d.ts","sourceRoot":"","sources":["../../../../replicache/src/replicache-options.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"replicache-options.d.ts","sourceRoot":"","sources":["../../../../replicache/src/replicache-options.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  var package_default = {
2
2
  name: "@rocicorp/zero",
3
- version: "1.10.0-canary.20",
3
+ version: "1.10.0-canary.21",
4
4
  description: "Zero is a web framework for serverless web development.",
5
5
  homepage: "https://zero.rocicorp.dev",
6
6
  bugs: { "url": "https://bugs.rocicorp.dev" },
@@ -1 +1 @@
1
- {"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":["{\n \"name\": \"@rocicorp/zero\",\n \"version\": \"1.10.0-canary.20\",\n \"description\": \"Zero is a web framework for serverless web development.\",\n \"homepage\": \"https://zero.rocicorp.dev\",\n \"bugs\": {\n \"url\": \"https://bugs.rocicorp.dev\"\n },\n \"license\": \"Apache-2.0\",\n \"author\": \"Rocicorp, Inc.\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/rocicorp/mono.git\",\n \"directory\": \"packages/zero\"\n },\n \"bin\": {\n \"analyze-query\": \"./out/zero/src/analyze-query.js\",\n \"ast-to-zql\": \"./out/zero/src/ast-to-zql.js\",\n \"transform-query\": \"./out/zero/src/transform-query.js\",\n \"zero-build-schema\": \"./out/zero/src/build-schema.js\",\n \"zero-cache\": \"./out/zero/src/cli.js\",\n \"zero-cache-dev\": \"./out/zero/src/zero-cache-dev.js\",\n \"zero-deploy-permissions\": \"./out/zero/src/deploy-permissions.js\",\n \"zero-out\": \"./out/zero/src/zero-out.js\"\n },\n \"files\": [\n \"out\",\n \"!*.tsbuildinfo\"\n ],\n \"type\": \"module\",\n \"main\": \"out/zero/src/zero.js\",\n \"module\": \"out/zero/src/zero.js\",\n \"types\": \"out/zero/src/zero.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./out/zero/src/zero.d.ts\",\n \"default\": \"./out/zero/src/zero.js\"\n },\n \"./analyze\": {\n \"types\": \"./out/zero/src/analyze.d.ts\",\n \"default\": \"./out/zero/src/analyze.js\"\n },\n \"./bindings\": {\n \"types\": \"./out/zero/src/bindings.d.ts\",\n \"default\": \"./out/zero/src/bindings.js\"\n },\n \"./change-protocol/v0\": {\n \"types\": \"./out/zero/src/change-protocol/v0.d.ts\",\n \"default\": \"./out/zero/src/change-protocol/v0.js\"\n },\n \"./expo-sqlite\": {\n \"types\": \"./out/zero/src/expo-sqlite.d.ts\",\n \"default\": \"./out/zero/src/expo-sqlite.js\"\n },\n \"./op-sqlite\": {\n \"types\": \"./out/zero/src/op-sqlite.d.ts\",\n \"default\": \"./out/zero/src/op-sqlite.js\"\n },\n \"./pg\": {\n \"types\": \"./out/zero/src/pg.d.ts\",\n \"default\": \"./out/zero/src/pg.js\"\n },\n \"./react\": {\n \"types\": \"./out/zero/src/react.d.ts\",\n \"default\": \"./out/zero/src/react.js\"\n },\n \"./react-native\": {\n \"types\": \"./out/zero/src/react-native.d.ts\",\n \"default\": \"./out/zero/src/react-native.js\"\n },\n \"./server\": {\n \"types\": \"./out/zero/src/server.d.ts\",\n \"default\": \"./out/zero/src/server.js\"\n },\n \"./server/adapters/drizzle\": {\n \"types\": \"./out/zero/src/adapters/drizzle.d.ts\",\n \"default\": \"./out/zero/src/adapters/drizzle.js\"\n },\n \"./server/adapters/kysely\": {\n \"types\": \"./out/zero/src/adapters/kysely.d.ts\",\n \"default\": \"./out/zero/src/adapters/kysely.js\"\n },\n \"./server/adapters/prisma\": {\n \"types\": \"./out/zero/src/adapters/prisma.d.ts\",\n \"default\": \"./out/zero/src/adapters/prisma.js\"\n },\n \"./server/adapters/pg\": {\n \"types\": \"./out/zero/src/adapters/pg.d.ts\",\n \"default\": \"./out/zero/src/adapters/pg.js\"\n },\n \"./server/adapters/postgresjs\": {\n \"types\": \"./out/zero/src/adapters/postgresjs.d.ts\",\n \"default\": \"./out/zero/src/adapters/postgresjs.js\"\n },\n \"./solid\": {\n \"types\": \"./out/zero/src/solid.d.ts\",\n \"default\": \"./out/zero/src/solid.js\"\n },\n \"./sqlite\": {\n \"types\": \"./out/zero/src/sqlite.d.ts\",\n \"default\": \"./out/zero/src/sqlite.js\"\n },\n \"./zqlite\": {\n \"types\": \"./out/zero/src/zqlite.d.ts\",\n \"default\": \"./out/zero/src/zqlite.js\"\n }\n },\n \"scripts\": {\n \"build\": \"node --experimental-strip-types --no-warnings tool/build.ts\",\n \"build:watch\": \"node --experimental-strip-types --no-warnings tool/build.ts --watch\",\n \"check-types\": \"tsc -p tsconfig.client.json && tsc -p tsconfig.server.json\",\n \"check-types:client:watch\": \"tsc -p tsconfig.client.json --watch\",\n \"check-types:server:watch\": \"tsc -p tsconfig.server.json --watch\",\n \"format\": \"oxfmt .\",\n \"check-format\": \"oxfmt --check .\",\n \"lint\": \"oxlint --quiet --config ../../oxlint.config.ts src/\",\n \"docs\": \"node --experimental-strip-types --no-warnings tool/generate-docs.ts\",\n \"docs:server\": \"node --watch --experimental-strip-types --no-warnings tool/generate-docs.ts --server\",\n \"fmt\": \"oxfmt .\",\n \"check-fmt\": \"oxfmt --check .\"\n },\n \"dependencies\": {\n \"@badrap/valita\": \"0.3.11\",\n \"@databases/escape-identifier\": \"^1.0.3\",\n \"@databases/sql\": \"^3.3.0\",\n \"@dotenvx/dotenvx\": \"^1.39.0\",\n \"@drdgvhbh/postgres-error-codes\": \"^0.0.6\",\n \"@fastify/cors\": \"^10.0.0\",\n \"@fastify/websocket\": \"^11.0.0\",\n \"@google-cloud/precise-date\": \"^4.0.0\",\n \"@opentelemetry/api\": \"^1.9.0\",\n \"@opentelemetry/api-logs\": \"^0.218.0\",\n \"@opentelemetry/auto-instrumentations-node\": \"^0.76.0\",\n \"@opentelemetry/exporter-metrics-otlp-http\": \"^0.218.0\",\n \"@opentelemetry/resources\": \"^2.7.1\",\n \"@opentelemetry/sdk-metrics\": \"^2.7.1\",\n \"@opentelemetry/sdk-node\": \"^0.218.0\",\n \"@opentelemetry/sdk-trace-node\": \"^2.7.1\",\n \"@opentelemetry/semantic-conventions\": \"^1.41.1\",\n \"@postgresql-typed/oids\": \"^0.2.0\",\n \"@rocicorp/lock\": \"^1.0.4\",\n \"@rocicorp/logger\": \"^6.1.0\",\n \"@rocicorp/resolver\": \"^1.0.2\",\n \"@rocicorp/zero-sqlite3\": \"^1.1.4\",\n \"@standard-schema/spec\": \"^1.0.0\",\n \"@types/basic-auth\": \"^1.1.8\",\n \"@types/ws\": \"^8.5.12\",\n \"basic-auth\": \"^2.0.1\",\n \"chalk-template\": \"^1.1.0\",\n \"chokidar\": \"^4.0.1\",\n \"cloudevents\": \"^10.0.0\",\n \"command-line-args\": \"^6.0.1\",\n \"command-line-usage\": \"^7.0.3\",\n \"compare-utf8\": \"^0.2.3\",\n \"defu\": \"^6.1.4\",\n \"eventemitter3\": \"^5.0.1\",\n \"fastify\": \"^5.0.0\",\n \"is-in-subnet\": \"^4.0.1\",\n \"jose\": \"^5.9.3\",\n \"json-custom-numbers\": \"^3.1.1\",\n \"kasi\": \"^1.1.0\",\n \"nanoid\": \"^5.1.2\",\n \"oxfmt\": \"^0.45.0\",\n \"parse-prometheus-text-format\": \"^1.1.1\",\n \"pg-format\": \"npm:pg-format-fix@^1.0.5\",\n \"postgres\": \"3.4.7\",\n \"semver\": \"^7.5.4\",\n \"url-pattern\": \"^1.0.3\",\n \"urlpattern-polyfill\": \"^10.1.0\",\n \"ws\": \"^8.18.1\"\n },\n \"devDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"@vitest/runner\": \"^4.1.6\",\n \"analyze-query\": \"workspace:*\",\n \"ast-to-zql\": \"workspace:*\",\n \"expo-sqlite\": \">=15\",\n \"oxc-parser\": \"^0.129.0\",\n \"replicache\": \"workspace:*\",\n \"shared\": \"workspace:*\",\n \"syncpack\": \"^14.3.0\",\n \"typedoc\": \"^0.28.17\",\n \"typedoc-plugin-markdown\": \"^4.10.0\",\n \"typescript\": \"~6.0.2\",\n \"vite\": \"^8.0.13\",\n \"vitest\": \"^4.1.6\",\n \"zero-cache\": \"workspace:*\",\n \"zero-client\": \"workspace:*\",\n \"zero-pg\": \"workspace:*\",\n \"zero-react\": \"workspace:*\",\n \"zero-server\": \"workspace:*\",\n \"zero-solid\": \"workspace:*\",\n \"zqlite\": \"workspace:*\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"packageManager\": \"pnpm@11.11.0\"\n}\n"],"mappings":""}
1
+ {"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":["{\n \"name\": \"@rocicorp/zero\",\n \"version\": \"1.10.0-canary.21\",\n \"description\": \"Zero is a web framework for serverless web development.\",\n \"homepage\": \"https://zero.rocicorp.dev\",\n \"bugs\": {\n \"url\": \"https://bugs.rocicorp.dev\"\n },\n \"license\": \"Apache-2.0\",\n \"author\": \"Rocicorp, Inc.\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/rocicorp/mono.git\",\n \"directory\": \"packages/zero\"\n },\n \"bin\": {\n \"analyze-query\": \"./out/zero/src/analyze-query.js\",\n \"ast-to-zql\": \"./out/zero/src/ast-to-zql.js\",\n \"transform-query\": \"./out/zero/src/transform-query.js\",\n \"zero-build-schema\": \"./out/zero/src/build-schema.js\",\n \"zero-cache\": \"./out/zero/src/cli.js\",\n \"zero-cache-dev\": \"./out/zero/src/zero-cache-dev.js\",\n \"zero-deploy-permissions\": \"./out/zero/src/deploy-permissions.js\",\n \"zero-out\": \"./out/zero/src/zero-out.js\"\n },\n \"files\": [\n \"out\",\n \"!*.tsbuildinfo\"\n ],\n \"type\": \"module\",\n \"main\": \"out/zero/src/zero.js\",\n \"module\": \"out/zero/src/zero.js\",\n \"types\": \"out/zero/src/zero.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./out/zero/src/zero.d.ts\",\n \"default\": \"./out/zero/src/zero.js\"\n },\n \"./analyze\": {\n \"types\": \"./out/zero/src/analyze.d.ts\",\n \"default\": \"./out/zero/src/analyze.js\"\n },\n \"./bindings\": {\n \"types\": \"./out/zero/src/bindings.d.ts\",\n \"default\": \"./out/zero/src/bindings.js\"\n },\n \"./change-protocol/v0\": {\n \"types\": \"./out/zero/src/change-protocol/v0.d.ts\",\n \"default\": \"./out/zero/src/change-protocol/v0.js\"\n },\n \"./expo-sqlite\": {\n \"types\": \"./out/zero/src/expo-sqlite.d.ts\",\n \"default\": \"./out/zero/src/expo-sqlite.js\"\n },\n \"./op-sqlite\": {\n \"types\": \"./out/zero/src/op-sqlite.d.ts\",\n \"default\": \"./out/zero/src/op-sqlite.js\"\n },\n \"./pg\": {\n \"types\": \"./out/zero/src/pg.d.ts\",\n \"default\": \"./out/zero/src/pg.js\"\n },\n \"./react\": {\n \"types\": \"./out/zero/src/react.d.ts\",\n \"default\": \"./out/zero/src/react.js\"\n },\n \"./react-native\": {\n \"types\": \"./out/zero/src/react-native.d.ts\",\n \"default\": \"./out/zero/src/react-native.js\"\n },\n \"./server\": {\n \"types\": \"./out/zero/src/server.d.ts\",\n \"default\": \"./out/zero/src/server.js\"\n },\n \"./server/adapters/drizzle\": {\n \"types\": \"./out/zero/src/adapters/drizzle.d.ts\",\n \"default\": \"./out/zero/src/adapters/drizzle.js\"\n },\n \"./server/adapters/kysely\": {\n \"types\": \"./out/zero/src/adapters/kysely.d.ts\",\n \"default\": \"./out/zero/src/adapters/kysely.js\"\n },\n \"./server/adapters/prisma\": {\n \"types\": \"./out/zero/src/adapters/prisma.d.ts\",\n \"default\": \"./out/zero/src/adapters/prisma.js\"\n },\n \"./server/adapters/pg\": {\n \"types\": \"./out/zero/src/adapters/pg.d.ts\",\n \"default\": \"./out/zero/src/adapters/pg.js\"\n },\n \"./server/adapters/postgresjs\": {\n \"types\": \"./out/zero/src/adapters/postgresjs.d.ts\",\n \"default\": \"./out/zero/src/adapters/postgresjs.js\"\n },\n \"./solid\": {\n \"types\": \"./out/zero/src/solid.d.ts\",\n \"default\": \"./out/zero/src/solid.js\"\n },\n \"./sqlite\": {\n \"types\": \"./out/zero/src/sqlite.d.ts\",\n \"default\": \"./out/zero/src/sqlite.js\"\n },\n \"./zqlite\": {\n \"types\": \"./out/zero/src/zqlite.d.ts\",\n \"default\": \"./out/zero/src/zqlite.js\"\n }\n },\n \"scripts\": {\n \"build\": \"node --experimental-strip-types --no-warnings tool/build.ts\",\n \"build:watch\": \"node --experimental-strip-types --no-warnings tool/build.ts --watch\",\n \"check-types\": \"tsc -p tsconfig.client.json && tsc -p tsconfig.server.json\",\n \"check-types:client:watch\": \"tsc -p tsconfig.client.json --watch\",\n \"check-types:server:watch\": \"tsc -p tsconfig.server.json --watch\",\n \"format\": \"oxfmt .\",\n \"check-format\": \"oxfmt --check .\",\n \"lint\": \"oxlint --quiet --config ../../oxlint.config.ts src/\",\n \"docs\": \"node --experimental-strip-types --no-warnings tool/generate-docs.ts\",\n \"docs:server\": \"node --watch --experimental-strip-types --no-warnings tool/generate-docs.ts --server\",\n \"fmt\": \"oxfmt .\",\n \"check-fmt\": \"oxfmt --check .\"\n },\n \"dependencies\": {\n \"@badrap/valita\": \"0.3.11\",\n \"@databases/escape-identifier\": \"^1.0.3\",\n \"@databases/sql\": \"^3.3.0\",\n \"@dotenvx/dotenvx\": \"^1.39.0\",\n \"@drdgvhbh/postgres-error-codes\": \"^0.0.6\",\n \"@fastify/cors\": \"^10.0.0\",\n \"@fastify/websocket\": \"^11.0.0\",\n \"@google-cloud/precise-date\": \"^4.0.0\",\n \"@opentelemetry/api\": \"^1.9.0\",\n \"@opentelemetry/api-logs\": \"^0.218.0\",\n \"@opentelemetry/auto-instrumentations-node\": \"^0.76.0\",\n \"@opentelemetry/exporter-metrics-otlp-http\": \"^0.218.0\",\n \"@opentelemetry/resources\": \"^2.7.1\",\n \"@opentelemetry/sdk-metrics\": \"^2.7.1\",\n \"@opentelemetry/sdk-node\": \"^0.218.0\",\n \"@opentelemetry/sdk-trace-node\": \"^2.7.1\",\n \"@opentelemetry/semantic-conventions\": \"^1.41.1\",\n \"@postgresql-typed/oids\": \"^0.2.0\",\n \"@rocicorp/lock\": \"^1.0.4\",\n \"@rocicorp/logger\": \"^6.1.0\",\n \"@rocicorp/resolver\": \"^1.0.2\",\n \"@rocicorp/zero-sqlite3\": \"^1.1.4\",\n \"@standard-schema/spec\": \"^1.0.0\",\n \"@types/basic-auth\": \"^1.1.8\",\n \"@types/ws\": \"^8.5.12\",\n \"basic-auth\": \"^2.0.1\",\n \"chalk-template\": \"^1.1.0\",\n \"chokidar\": \"^4.0.1\",\n \"cloudevents\": \"^10.0.0\",\n \"command-line-args\": \"^6.0.1\",\n \"command-line-usage\": \"^7.0.3\",\n \"compare-utf8\": \"^0.2.3\",\n \"defu\": \"^6.1.4\",\n \"eventemitter3\": \"^5.0.1\",\n \"fastify\": \"^5.0.0\",\n \"is-in-subnet\": \"^4.0.1\",\n \"jose\": \"^5.9.3\",\n \"json-custom-numbers\": \"^3.1.1\",\n \"kasi\": \"^1.1.0\",\n \"nanoid\": \"^5.1.2\",\n \"oxfmt\": \"^0.45.0\",\n \"parse-prometheus-text-format\": \"^1.1.1\",\n \"pg-format\": \"npm:pg-format-fix@^1.0.5\",\n \"postgres\": \"3.4.7\",\n \"semver\": \"^7.5.4\",\n \"url-pattern\": \"^1.0.3\",\n \"urlpattern-polyfill\": \"^10.1.0\",\n \"ws\": \"^8.18.1\"\n },\n \"devDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"@vitest/runner\": \"^4.1.6\",\n \"analyze-query\": \"workspace:*\",\n \"ast-to-zql\": \"workspace:*\",\n \"expo-sqlite\": \">=15\",\n \"oxc-parser\": \"^0.129.0\",\n \"replicache\": \"workspace:*\",\n \"shared\": \"workspace:*\",\n \"syncpack\": \"^14.3.0\",\n \"typedoc\": \"^0.28.17\",\n \"typedoc-plugin-markdown\": \"^4.10.0\",\n \"typescript\": \"~6.0.2\",\n \"vite\": \"^8.0.13\",\n \"vitest\": \"^4.1.6\",\n \"zero-cache\": \"workspace:*\",\n \"zero-client\": \"workspace:*\",\n \"zero-pg\": \"workspace:*\",\n \"zero-react\": \"workspace:*\",\n \"zero-server\": \"workspace:*\",\n \"zero-solid\": \"workspace:*\",\n \"zqlite\": \"workspace:*\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"packageManager\": \"pnpm@11.11.0\"\n}\n"],"mappings":""}
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * The current version of Zero.
4
4
  */
5
- var version = "1.10.0-canary.20";
5
+ var version = "1.10.0-canary.21";
6
6
  //#endregion
7
7
  export { version };
8
8
 
@@ -11,6 +11,7 @@ type TxData = {
11
11
  ivmSources: IVMSourceBranch;
12
12
  token: string | undefined;
13
13
  context: unknown;
14
+ fork: () => TxData;
14
15
  };
15
16
  export declare class ZeroRep implements ZeroOption {
16
17
  #private;
@@ -1 +1 @@
1
- {"version":3,"file":"zero-rep.d.ts","sourceRoot":"","sources":["../../../../../zero-client/src/client/zero-rep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,2CAA2C,CAAC;AAGzE,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,iCAAiC,CAAC;AAC1D,OAAO,KAAK,EACV,WAAW,EACX,oBAAoB,EACpB,UAAU,EACV,eAAe,EAChB,MAAM,+CAA+C,CAAC;AAGvD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,iBAAiB,CAAC;AAErD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAK3D,eAAO,MAAM,qBAAqB,GAChC,MAAM,MAAM,GAAG,SAAS,GAAG,IAAI,KAC9B,MAA0C,CAAC;AAE9C,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,KAAG,MAAM,GAAG,SACtC,CAAC;AAE3B,KAAK,MAAM,GAAG;IACZ,UAAU,EAAE,eAAe,CAAC;IAC5B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,qBAAa,OAAQ,YAAW,UAAU;;gBAUtC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,eAAe,EACxB,qBAAqB,EAAE,OAAO,EAC9B,eAAe,EAAE,eAAe;IAQlC,IAAI,IAAI,CAAC,IAAI,EAAE,MAAM,EAEpB;IAEK,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS;IAwBvC,SAAS,GACP,aAAa,IAAI,EACjB,cAAc,eAAe,KAC5B,OAAO,CAAC,MAAM,CAAC,GAAG,SAAS,CAe5B;IAEF,OAAO,GAAI,cAAc,IAAI,EAAE,SAAS,IAAI,EAAE,OAAO,YAAY,KAAG,IAAI,CAEtE;IAEF,aAAa,IAAI,oBAAoB;IAGrC,kBAAkB,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAGtE,cAAc,CAAC,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,GAAG,IAAI;CAG5D"}
1
+ {"version":3,"file":"zero-rep.d.ts","sourceRoot":"","sources":["../../../../../zero-client/src/client/zero-rep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,2CAA2C,CAAC;AAGzE,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,iCAAiC,CAAC;AAC1D,OAAO,KAAK,EACV,WAAW,EACX,oBAAoB,EACpB,UAAU,EACV,eAAe,EAChB,MAAM,+CAA+C,CAAC;AAGvD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,iBAAiB,CAAC;AAErD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAK3D,eAAO,MAAM,qBAAqB,GAChC,MAAM,MAAM,GAAG,SAAS,GAAG,IAAI,KAC9B,MAA0C,CAAC;AAE9C,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,KAAG,MAAM,GAAG,SACtC,CAAC;AAE3B,KAAK,MAAM,GAAG;IACZ,UAAU,EAAE,eAAe,CAAC;IAC5B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,MAAM,CAAC;CACpB,CAAC;AAEF,qBAAa,OAAQ,YAAW,UAAU;;gBAUtC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,eAAe,EACxB,qBAAqB,EAAE,OAAO,EAC9B,eAAe,EAAE,eAAe;IAQlC,IAAI,IAAI,CAAC,IAAI,EAAE,MAAM,EAEpB;IAEK,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS;IAwBvC,SAAS,GACP,aAAa,IAAI,EACjB,cAAc,eAAe,KAC5B,OAAO,CAAC,MAAM,CAAC,GAAG,SAAS,CAW5B;IASF,OAAO,GAAI,cAAc,IAAI,EAAE,SAAS,IAAI,EAAE,OAAO,YAAY,KAAG,IAAI,CAEtE;IAEF,aAAa,IAAI,oBAAoB;IAGrC,kBAAkB,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAGtE,cAAc,CAAC,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,GAAG,IAAI;CAG5D"}
@@ -41,12 +41,14 @@ var ZeroRep = class {
41
41
  }
42
42
  getTxData = (desiredHead, readOptions) => {
43
43
  if (!this.#customMutatorsEnabled) return;
44
- return this.#ivmMain.forkToHead(must(this.#store), desiredHead, readOptions).then((branch) => ({
45
- ivmSources: branch,
46
- token: fromReplicacheAuthToken(this.#auth),
47
- context: this.#context
48
- }));
44
+ return this.#ivmMain.forkToHead(must(this.#store), desiredHead, readOptions).then((branch) => this.#makeTxData(branch));
49
45
  };
46
+ #makeTxData = (branch) => ({
47
+ ivmSources: branch,
48
+ token: fromReplicacheAuthToken(this.#auth),
49
+ context: this.#context,
50
+ fork: () => this.#makeTxData(branch.fork())
51
+ });
50
52
  advance = (expectedHash, newHash, diffs) => {
51
53
  this.#context.processChanges(expectedHash, newHash, diffs);
52
54
  };
@@ -1 +1 @@
1
- {"version":3,"file":"zero-rep.js","names":["#context","#ivmMain","#customMutatorsEnabled","#mutationTracker","#auth","#store"],"sources":["../../../../../zero-client/src/client/zero-rep.ts"],"sourcesContent":["import type {\n InternalDiff,\n InternalDiffOperation,\n} from '../../../replicache/src/btree/node.ts';\nimport type {LazyStore} from '../../../replicache/src/dag/lazy-store.ts';\nimport {readFromHash} from '../../../replicache/src/db/read.ts';\nimport * as FormatVersion from '../../../replicache/src/format-version-enum.ts';\nimport type {Hash} from '../../../replicache/src/hash.ts';\nimport type {\n EphemeralID,\n MutationTrackingData,\n ZeroOption,\n ZeroReadOptions,\n} from '../../../replicache/src/replicache-options.ts';\nimport {withRead} from '../../../replicache/src/with-transactions.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {ZeroContext} from './context.ts';\nimport type {IVMSourceBranch} from './ivm-branch.ts';\nimport {ENTITIES_KEY_PREFIX} from './keys.ts';\nimport type {MutationTracker} from './mutation-tracker.ts';\n\n// Replicache doesn't support undefined auth tokens\nconst REPLICACHE_NO_AUTH_TOKEN = '';\n\nexport const toReplicacheAuthToken = (\n auth: string | undefined | null,\n): string => auth ?? REPLICACHE_NO_AUTH_TOKEN;\n\nexport const fromReplicacheAuthToken = (auth: string): string | undefined =>\n !auth ? undefined : auth;\n\ntype TxData = {\n ivmSources: IVMSourceBranch;\n token: string | undefined;\n context: unknown;\n};\n\nexport class ZeroRep implements ZeroOption {\n readonly #context: ZeroContext;\n readonly #ivmMain: IVMSourceBranch;\n readonly #customMutatorsEnabled: boolean;\n readonly #mutationTracker: MutationTracker;\n #store: LazyStore | undefined;\n // matches replicache's auth token type\n #auth: string = REPLICACHE_NO_AUTH_TOKEN;\n\n constructor(\n context: ZeroContext,\n ivmMain: IVMSourceBranch,\n customMutatorsEnabled: boolean,\n mutationTracker: MutationTracker,\n ) {\n this.#context = context;\n this.#ivmMain = ivmMain;\n this.#customMutatorsEnabled = customMutatorsEnabled;\n this.#mutationTracker = mutationTracker;\n }\n\n set auth(auth: string) {\n this.#auth = auth;\n }\n\n async init(hash: Hash, store: LazyStore) {\n const diffs: InternalDiffOperation[] = [];\n await withRead(store, async dagRead => {\n const read = await readFromHash(hash, dagRead, FormatVersion.Latest);\n for await (const entry of read.map.scan(ENTITIES_KEY_PREFIX, true)) {\n if (!entry[0].startsWith(ENTITIES_KEY_PREFIX)) {\n break;\n }\n diffs.push({\n op: 'add',\n key: entry[0],\n newValue: entry[1],\n });\n }\n });\n this.#store = store;\n\n this.#context.processChanges(undefined, hash, diffs);\n // Pipelines for queries materialized before this point were deferred so\n // the replica above was loaded into the sources without fanning out to\n // them. Build and hydrate them now that the sources are populated.\n this.#context.markPipelinesReady();\n }\n\n getTxData = (\n desiredHead: Hash,\n readOptions?: ZeroReadOptions,\n ): Promise<TxData> | undefined => {\n // getTxData requires some extensive testing for complete confidence\n // that it will not break. Do not enable `getTxData` unless the user\n // has opted into custom mutators.\n if (!this.#customMutatorsEnabled) {\n return;\n }\n\n return this.#ivmMain\n .forkToHead(must(this.#store), desiredHead, readOptions)\n .then(branch => ({\n ivmSources: branch,\n token: fromReplicacheAuthToken(this.#auth),\n context: this.#context,\n }));\n };\n\n advance = (expectedHash: Hash, newHash: Hash, diffs: InternalDiff): void => {\n this.#context.processChanges(expectedHash, newHash, diffs);\n };\n\n trackMutation(): MutationTrackingData {\n return this.#mutationTracker.trackMutation();\n }\n mutationIDAssigned(ephemeralID: EphemeralID, mutationID: number): void {\n this.#mutationTracker.mutationIDAssigned(ephemeralID, mutationID);\n }\n rejectMutation(ephemeralID: EphemeralID, ex: unknown): void {\n this.#mutationTracker.rejectMutation(ephemeralID, ex);\n }\n}\n"],"mappings":";;;;;AAsBA,IAAM,2BAA2B;AAEjC,IAAa,yBACX,SACW,QAAQ;AAErB,IAAa,2BAA2B,SACtC,CAAC,OAAO,KAAA,IAAY;AAQtB,IAAa,UAAb,MAA2C;CACzC;CACA;CACA;CACA;CACA;CAEA,QAAgB;CAEhB,YACE,SACA,SACA,uBACA,iBACA;EACA,KAAKA,WAAW;EAChB,KAAKC,WAAW;EAChB,KAAKC,yBAAyB;EAC9B,KAAKC,mBAAmB;CAC1B;CAEA,IAAI,KAAK,MAAc;EACrB,KAAKC,QAAQ;CACf;CAEA,MAAM,KAAK,MAAY,OAAkB;EACvC,MAAM,QAAiC,CAAC;EACxC,MAAM,SAAS,OAAO,OAAM,YAAW;GACrC,MAAM,OAAO,MAAM,aAAa,MAAM,SAAS,CAAoB;GACnE,WAAW,MAAM,SAAS,KAAK,IAAI,KAAA,MAA0B,IAAI,GAAG;IAClE,IAAI,CAAC,MAAM,GAAG,WAAA,IAA8B,GAC1C;IAEF,MAAM,KAAK;KACT,IAAI;KACJ,KAAK,MAAM;KACX,UAAU,MAAM;IAClB,CAAC;GACH;EACF,CAAC;EACD,KAAKC,SAAS;EAEd,KAAKL,SAAS,eAAe,KAAA,GAAW,MAAM,KAAK;EAInD,KAAKA,SAAS,mBAAmB;CACnC;CAEA,aACE,aACA,gBACgC;EAIhC,IAAI,CAAC,KAAKE,wBACR;EAGF,OAAO,KAAKD,SACT,WAAW,KAAK,KAAKI,MAAM,GAAG,aAAa,WAAW,EACtD,MAAK,YAAW;GACf,YAAY;GACZ,OAAO,wBAAwB,KAAKD,KAAK;GACzC,SAAS,KAAKJ;EAChB,EAAE;CACN;CAEA,WAAW,cAAoB,SAAe,UAA8B;EAC1E,KAAKA,SAAS,eAAe,cAAc,SAAS,KAAK;CAC3D;CAEA,gBAAsC;EACpC,OAAO,KAAKG,iBAAiB,cAAc;CAC7C;CACA,mBAAmB,aAA0B,YAA0B;EACrE,KAAKA,iBAAiB,mBAAmB,aAAa,UAAU;CAClE;CACA,eAAe,aAA0B,IAAmB;EAC1D,KAAKA,iBAAiB,eAAe,aAAa,EAAE;CACtD;AACF"}
1
+ {"version":3,"file":"zero-rep.js","names":["#context","#ivmMain","#customMutatorsEnabled","#mutationTracker","#auth","#store","#makeTxData"],"sources":["../../../../../zero-client/src/client/zero-rep.ts"],"sourcesContent":["import type {\n InternalDiff,\n InternalDiffOperation,\n} from '../../../replicache/src/btree/node.ts';\nimport type {LazyStore} from '../../../replicache/src/dag/lazy-store.ts';\nimport {readFromHash} from '../../../replicache/src/db/read.ts';\nimport * as FormatVersion from '../../../replicache/src/format-version-enum.ts';\nimport type {Hash} from '../../../replicache/src/hash.ts';\nimport type {\n EphemeralID,\n MutationTrackingData,\n ZeroOption,\n ZeroReadOptions,\n} from '../../../replicache/src/replicache-options.ts';\nimport {withRead} from '../../../replicache/src/with-transactions.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {ZeroContext} from './context.ts';\nimport type {IVMSourceBranch} from './ivm-branch.ts';\nimport {ENTITIES_KEY_PREFIX} from './keys.ts';\nimport type {MutationTracker} from './mutation-tracker.ts';\n\n// Replicache doesn't support undefined auth tokens\nconst REPLICACHE_NO_AUTH_TOKEN = '';\n\nexport const toReplicacheAuthToken = (\n auth: string | undefined | null,\n): string => auth ?? REPLICACHE_NO_AUTH_TOKEN;\n\nexport const fromReplicacheAuthToken = (auth: string): string | undefined =>\n !auth ? undefined : auth;\n\ntype TxData = {\n ivmSources: IVMSourceBranch;\n token: string | undefined;\n context: unknown;\n fork: () => TxData;\n};\n\nexport class ZeroRep implements ZeroOption {\n readonly #context: ZeroContext;\n readonly #ivmMain: IVMSourceBranch;\n readonly #customMutatorsEnabled: boolean;\n readonly #mutationTracker: MutationTracker;\n #store: LazyStore | undefined;\n // matches replicache's auth token type\n #auth: string = REPLICACHE_NO_AUTH_TOKEN;\n\n constructor(\n context: ZeroContext,\n ivmMain: IVMSourceBranch,\n customMutatorsEnabled: boolean,\n mutationTracker: MutationTracker,\n ) {\n this.#context = context;\n this.#ivmMain = ivmMain;\n this.#customMutatorsEnabled = customMutatorsEnabled;\n this.#mutationTracker = mutationTracker;\n }\n\n set auth(auth: string) {\n this.#auth = auth;\n }\n\n async init(hash: Hash, store: LazyStore) {\n const diffs: InternalDiffOperation[] = [];\n await withRead(store, async dagRead => {\n const read = await readFromHash(hash, dagRead, FormatVersion.Latest);\n for await (const entry of read.map.scan(ENTITIES_KEY_PREFIX, true)) {\n if (!entry[0].startsWith(ENTITIES_KEY_PREFIX)) {\n break;\n }\n diffs.push({\n op: 'add',\n key: entry[0],\n newValue: entry[1],\n });\n }\n });\n this.#store = store;\n\n this.#context.processChanges(undefined, hash, diffs);\n // Pipelines for queries materialized before this point were deferred so\n // the replica above was loaded into the sources without fanning out to\n // them. Build and hydrate them now that the sources are populated.\n this.#context.markPipelinesReady();\n }\n\n getTxData = (\n desiredHead: Hash,\n readOptions?: ZeroReadOptions,\n ): Promise<TxData> | undefined => {\n // getTxData requires some extensive testing for complete confidence\n // that it will not break. Do not enable `getTxData` unless the user\n // has opted into custom mutators.\n if (!this.#customMutatorsEnabled) {\n return;\n }\n\n return this.#ivmMain\n .forkToHead(must(this.#store), desiredHead, readOptions)\n .then(branch => this.#makeTxData(branch));\n };\n\n #makeTxData = (branch: IVMSourceBranch): TxData => ({\n ivmSources: branch,\n token: fromReplicacheAuthToken(this.#auth),\n context: this.#context,\n fork: () => this.#makeTxData(branch.fork()),\n });\n\n advance = (expectedHash: Hash, newHash: Hash, diffs: InternalDiff): void => {\n this.#context.processChanges(expectedHash, newHash, diffs);\n };\n\n trackMutation(): MutationTrackingData {\n return this.#mutationTracker.trackMutation();\n }\n mutationIDAssigned(ephemeralID: EphemeralID, mutationID: number): void {\n this.#mutationTracker.mutationIDAssigned(ephemeralID, mutationID);\n }\n rejectMutation(ephemeralID: EphemeralID, ex: unknown): void {\n this.#mutationTracker.rejectMutation(ephemeralID, ex);\n }\n}\n"],"mappings":";;;;;AAsBA,IAAM,2BAA2B;AAEjC,IAAa,yBACX,SACW,QAAQ;AAErB,IAAa,2BAA2B,SACtC,CAAC,OAAO,KAAA,IAAY;AAStB,IAAa,UAAb,MAA2C;CACzC;CACA;CACA;CACA;CACA;CAEA,QAAgB;CAEhB,YACE,SACA,SACA,uBACA,iBACA;EACA,KAAKA,WAAW;EAChB,KAAKC,WAAW;EAChB,KAAKC,yBAAyB;EAC9B,KAAKC,mBAAmB;CAC1B;CAEA,IAAI,KAAK,MAAc;EACrB,KAAKC,QAAQ;CACf;CAEA,MAAM,KAAK,MAAY,OAAkB;EACvC,MAAM,QAAiC,CAAC;EACxC,MAAM,SAAS,OAAO,OAAM,YAAW;GACrC,MAAM,OAAO,MAAM,aAAa,MAAM,SAAS,CAAoB;GACnE,WAAW,MAAM,SAAS,KAAK,IAAI,KAAA,MAA0B,IAAI,GAAG;IAClE,IAAI,CAAC,MAAM,GAAG,WAAA,IAA8B,GAC1C;IAEF,MAAM,KAAK;KACT,IAAI;KACJ,KAAK,MAAM;KACX,UAAU,MAAM;IAClB,CAAC;GACH;EACF,CAAC;EACD,KAAKC,SAAS;EAEd,KAAKL,SAAS,eAAe,KAAA,GAAW,MAAM,KAAK;EAInD,KAAKA,SAAS,mBAAmB;CACnC;CAEA,aACE,aACA,gBACgC;EAIhC,IAAI,CAAC,KAAKE,wBACR;EAGF,OAAO,KAAKD,SACT,WAAW,KAAK,KAAKI,MAAM,GAAG,aAAa,WAAW,EACtD,MAAK,WAAU,KAAKC,YAAY,MAAM,CAAC;CAC5C;CAEA,eAAe,YAAqC;EAClD,YAAY;EACZ,OAAO,wBAAwB,KAAKF,KAAK;EACzC,SAAS,KAAKJ;EACd,YAAY,KAAKM,YAAY,OAAO,KAAK,CAAC;CAC5C;CAEA,WAAW,cAAoB,SAAe,UAA8B;EAC1E,KAAKN,SAAS,eAAe,cAAc,SAAS,KAAK;CAC3D;CAEA,gBAAsC;EACpC,OAAO,KAAKG,iBAAiB,cAAc;CAC7C;CACA,mBAAmB,aAA0B,YAA0B;EACrE,KAAKA,iBAAiB,mBAAmB,aAAa,UAAU;CAClE;CACA,eAAe,aAA0B,IAAmB;EAC1D,KAAKA,iBAAiB,eAAe,aAAa,EAAE;CACtD;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rocicorp/zero",
3
- "version": "1.10.0-canary.20",
3
+ "version": "1.10.0-canary.21",
4
4
  "description": "Zero is a web framework for serverless web development.",
5
5
  "homepage": "https://zero.rocicorp.dev",
6
6
  "bugs": {