@tearleads/client-sdk 0.1.113 → 0.1.114
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.
- package/data/persistence/container-contents/containerContentsPersistence.js +3 -8
- package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerHydrationPersistence.js +15 -5
- package/data/persistence/container-contents/containerHydrationPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerMetadataMutationPersistence.js +8 -2
- package/data/persistence/container-contents/containerMetadataMutationPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerMetadataRows.js +34 -2
- package/data/persistence/container-contents/containerMetadataRows.js.map +1 -1
- package/data/persistence/container-contents/containerPersistence.d.ts +231 -0
- package/data/persistence/container-contents/containerPersistence.js +20 -16
- package/data/persistence/container-contents/containerPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerRecoveryPersistence.js +15 -13
- package/data/persistence/container-contents/containerRecoveryPersistence.js.map +1 -1
- package/data/persistence/container-contents/documentContainerProjectionPersistence.js +10 -2
- package/data/persistence/container-contents/documentContainerProjectionPersistence.js.map +1 -1
- package/data/persistence/container-contents/documentMoveIntentPersistence.js +29 -5
- package/data/persistence/container-contents/documentMoveIntentPersistence.js.map +1 -1
- package/data/persistence/container-contents/documentPlacementIntentEnqueue.js +1 -1
- package/data/persistence/container-contents/documentPlacementIntentEnqueue.js.map +1 -1
- package/data/persistence/documents/internal/documentMutationPersistence.js +15 -15
- package/data/persistence/documents/internal/documentMutationPersistence.js.map +1 -1
- package/data/persistence/documents/internal/documentRows.js +26 -10
- package/data/persistence/documents/internal/documentRows.js.map +1 -1
- package/data/persistence/documents/internal/rowQueryPersistence.js +52 -27
- package/data/persistence/documents/internal/rowQueryPersistence.js.map +1 -1
- package/data/persistence/documents/records/documentHistoryPersistence.js +17 -11
- package/data/persistence/documents/records/documentHistoryPersistence.js.map +1 -1
- package/package.json +1 -1
- package/workflows/container-contents/documentQueries/index.js +21 -6
- package/workflows/container-contents/documentQueries/index.js.map +1 -1
- package/workflows/documents/documentMutationCommit.js +11 -12
- package/workflows/documents/documentMutationCommit.js.map +1 -1
- package/workflows/documents/documentMutationPreparation.d.ts +1 -0
- package/workflows/documents/documentMutationPreparation.js +1 -0
- package/workflows/documents/documentMutationPreparation.js.map +1 -1
- package/workflows/documents/documentPersistGuards.js +24 -0
- package/workflows/documents/documentPersistGuards.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documentMutationCommit.js","sourceRoot":"","sources":["documentMutationCommit.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,EACL,6BAA6B,EAC7B,qBAAqB,GACtB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAGL,uBAAuB,GACxB,MAAM,oCAAoC,CAAC;AAO5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EACL,kCAAkC,EAElC,uBAAuB,GACxB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AAUvE,MAAM,qCAAqC,GAAG,CAAC,CAAC;AAoChD,KAAK,UAAU,oCAAoC,CAAC,KAOnD;IACC,MAAM,EAAE,QAAQ,EAAE,mBAAmB,EAAE,GACrC,MAAM,KAAK,CAAC,WAAW,CAAC,mCAAmC,CACzD,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,OAAO,CACd,CAAC;IACJ,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,MAAM,sBAAsB,GAC1B,KAAK,CAAC,sBAAsB;QAC5B,CAAC,kCAAkC,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9D,OAAO;QACL,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,IAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,mBAAmB;QACnB,0BAA0B,EAAE,IAAI;QAChC,MAAM,EAAE,QAAQ;QAChB,GAAG,CAAC,sBAAsB;YACxB,CAAC,CAAC,EAAE,sBAAsB,EAAE,IAAa,EAAE;YAC3C,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED,SAAS,mCAAmC,CAC1C,KAAoC,EACpC,GAAiC,EACjC,YAAuC,EACvC,kBAAkB,GAAG,KAAK;IAE1B,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IACzD,OAAO,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,gCAAgC,CAAC,KAIzC;IACC,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC,KAAK,CAAC,WAAW,IAAI,IAAI,CAAC;IACzC,CAAC;IACD,OAAO,KAAK,CAAC,aAAa,EAAE,WAAW,IAAI,KAAK,CAAC,WAAW,IAAI,IAAI,CAAC;AACvE,CAAC;AAED,SAAS,8BAA8B,CAAC,KAIvC;IAIC,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,kBAAkB,CAAC,EAAE,CAAC;QACnD,OAAO,EAAE,gBAAgB,EAAE,KAAK,CAAC,KAAK,CAAC,gBAAgB,IAAI,IAAI,EAAE,CAAC;IACpE,CAAC;IACD,IAAI,KAAK,CAAC,sBAAsB;QAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC;IACpE,IAAI,KAAK,CAAC,aAAa,EAAE,gCAAgC,EAAE,CAAC;QAC1D,OAAO,EAAE,gCAAgC,EAAE,IAAI,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,EAAE,gBAAgB,EAAE,KAAK,CAAC,aAAa,EAAE,gBAAgB,IAAI,IAAI,EAAE,CAAC;AAC7E,CAAC;AAED,SAAS,yBAAyB,CAAC,KAOlC;IACC,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,kBAAkB,EAAE,OAAO,EAAE,KAAK,EAAE,GACrE,KAAK,CAAC;IACR,MAAM,iBAAiB,GAAG,aAAa,EAAE,UAAU,IAAI,IAAI,CAAC;IAC5D,MAAM,cAAc,GAAG,KAAK,CAAC,UAAU,IAAI,iBAAiB,CAAC;IAC7D,MAAM,iBAAiB,GAAG,cAAc,KAAK,iBAAiB,CAAC;IAC/D,MAAM,kBAAkB,GACtB,aAAa,EAAE,WAAW,IAAI,6BAA6B,CAAC;IAC9D,MAAM,eAAe,GAAG,KAAK,CAAC,WAAW,IAAI,kBAAkB,CAAC;IAChE,MAAM,sBAAsB,GAC1B,iBAAiB,IAAI,eAAe,KAAK,kBAAkB,CAAC;IAC9D,MAAM,aAAa,GAAG,uBAAuB,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IAC9E,MAAM,MAAM,GAAyB;QACnC,EAAE,EAAE,aAAa,EAAE,EAAE,IAAI,OAAO;QAChC,WAAW,EAAE,eAAe;QAC5B,eAAe,EAAE,mCAAmC,CAClD,KAAK,EACL,iBAAiB,EACjB,aAAa,EAAE,eAAe,EAC9B,sBAAsB,CACvB;QACD,WAAW,EAAE,gCAAgC,CAAC;YAC5C,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,aAAa;YACb,KAAK;SACN,CAAC;QACF,gBAAgB,EAAE,mCAAmC,CACnD,KAAK,EACL,kBAAkB,EAClB,aAAa,EAAE,gBAAgB,EAC/B,sBAAsB,CACvB;QACD,UAAU,EAAE,cAAc;QAC1B,oBAAoB,EAClB,KAAK,CAAC,oBAAoB,IAAI,aAAa,EAAE,oBAAoB,IAAI,IAAI;QAC3E,kBAAkB,EAAE,mCAAmC,CACrD,KAAK,EACL,oBAAoB,EACpB,aAAa,EAAE,kBAAkB,EACjC,sBAAsB,CACvB;QACD,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,aAAa,CAAC,YAAY;QAC9D,sBAAsB,EAAE,mCAAmC,CACzD,KAAK,EACL,wBAAwB,EACxB,aAAa,EAAE,sBAAsB,EACrC,sBAAsB,CACvB;QACD,aAAa,EAAE,mCAAmC,CAChD,KAAK,EACL,eAAe,EACf,aAAa,EAAE,aAAa,EAC5B,iBAAiB,CAClB;QACD,kBAAkB,EAChB,KAAK,CAAC,kBAAkB,IAAI,aAAa,EAAE,kBAAkB,IAAI,EAAE;QACrE,kBAAkB,EAChB,KAAK,CAAC,kBAAkB,KAAK,SAAS;YACpC,CAAC,CAAC,KAAK,CAAC,kBAAkB;YAC1B,CAAC,CAAC,CAAC,aAAa,EAAE,kBAAkB,IAAI,IAAI,CAAC;QACjD,kBAAkB,EAChB,KAAK,CAAC,kBAAkB,IAAI,aAAa,EAAE,kBAAkB,IAAI,CAAC;QACpE,GAAG,8BAA8B,CAAC;YAChC,aAAa;YACb,KAAK;YACL,sBAAsB;SACvB,CAAC;QACF,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,YAAY,CAAC,UAAU,CAAC;QAC5C,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,aAAa,CAAC,KAAK;KAC1C,CAAC;IACF,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC;AACnC,CAAC;AAED,KAAK,UAAU,4BAA4B,CAAC,KAQ3C;IACC,MAAM,YAAY,GAChB,KAAK,CAAC,aAAa,EAAE,YAAY,IAAI,qBAAqB,CAAC;IAC7D,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,IAAI,qBAAqB,CAAC;IACpE,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,KAAK,CAAC,kBAAkB,CAAC,oCAAoC,CAAC;YAClE,YAAY,EAAE,YAAY;YAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC;IACL,CAAC;IACD,MAAM,KAAK,CAAC,kBAAkB,CAAC,kCAAkC,CAAC;QAChE,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,WAAW;QACrC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU;QACnC,YAAY,EAAE,QAAQ;QACtB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE;QACxB,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,gBAAgB;QACtD,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI;QACvB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,aAAa,CAAC,KAAK;QACtD,SAAS,EAAE,KAAK,CAAC,SAAS;KAC3B,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,gCAAgC,CAAC,KAK/C;IACC,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;IACzC,IAAI,CAAC,QAAQ,CAAC,qBAAqB;QAAE,OAAO,IAAI,CAAC;IACjD,MAAM,mBAAmB,GAAG,YAAY,CAAC,iBAAiB;QACxD,CAAC,CAAC,MAAM,YAAY,CAAC,WAAW,CAAC,4BAA4B,CACzD,KAAK,CAAC,aAAa,EACnB;YACE,cAAc,EAAE,YAAY,CAAC,iBAAiB,CAAC,MAAM;YACrD,gBAAgB,EAAE,KAAK,CAAC,wBAAwB;SACjD,CACF;QACH,CAAC,CAAC,QAAQ,CAAC,qBAAqB,CAAC;IACnC,IAAI,CAAC,mBAAmB;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,oCAAoC,CAAC;QAC1C,kBAAkB,EAAE,QAAQ,CAAC,kBAAkB;QAC/C,OAAO,EAAE,KAAK,CAAC,aAAa;QAC5B,OAAO,EAAE,YAAY,CAAC,OAAO;QAC7B,WAAW,EAAE,YAAY,CAAC,WAAW;QACrC,MAAM,EAAE,mBAAmB;QAC3B,sBAAsB,EAAE,CAAC,QAAQ,CAAC,sBAAsB;KACzD,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,4BAA4B,CAAC,KAG3C;IACC,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,YAAY,CACrE,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,YAAY,CAAC,OAAO,CAC3B,CAAC;IACF,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,oCAAoC,CAAC;QACxD,kBAAkB,EAAE,IAAI;QACxB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC,OAAO;QACnC,WAAW,EAAE,KAAK,CAAC,YAAY,CAAC,WAAW;QAC3C,MAAM,EAAE,aAAa;QACrB,sBAAsB,EAAE,IAAI;KAC7B,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,8BAA8B,CAAC,KAK7C;IACC,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IAC5D,CAAC;IACD,IACE,KAAK,CAAC,YAAY,CAAC,uBAAuB;QAC1C,CAAC,KAAK,CAAC,YAAY,CAAC,uBAAuB,EAAE,EAC7C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,4BAA4B,CAAC;QAClC,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,YAAY,EAAE,KAAK,CAAC,YAAY;KACjC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,6BAA6B,CAAC,KAO5C;IACC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAClD,IACE,YAAY,CAAC,uBAAuB;QACpC,CAAC,YAAY,CAAC,uBAAuB,EAAE,EACvC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,SAAS,CAAC,SAAS;QAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,CAAC;IAC3E,IAAI,CAAC,SAAS,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,YAAY,CAAC,iBAAiB,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IACjE,OAAO,oCAAoC,CAAC;QAC1C,kBAAkB,EAAE,KAAK;QACzB,OAAO,EAAE,KAAK,CAAC,aAAa;QAC5B,OAAO,EAAE,YAAY,CAAC,OAAO;QAC7B,WAAW,EAAE,YAAY,CAAC,WAAW;QACrC,MAAM,EAAE,SAAS,CAAC,aAAa;QAC/B,sBAAsB,EAAE,CAAC,kCAAkC,CACzD,SAAS,CAAC,aAAa,EACvB,YAAY,CAAC,iBAAiB,CAAC,MAAM,CACtC;KACF,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,iCAAiC,CAAC,KAShD;IACC,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;IACzC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,yBAAyB,CAAC;QAC1D,WAAW,EAAE,YAAY,CAAC,WAAW;QACrC,UAAU,EAAE,YAAY,CAAC,UAAU;QACnC,aAAa,EAAE,QAAQ,CAAC,qBAAqB;QAC7C,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,OAAO,EAAE,YAAY,CAAC,OAAO;QAC7B,KAAK,EAAE,QAAQ,CAAC,aAAa;KAC9B,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,qBAAqB,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,MAAM,yBAAyB,CAAC;YAC9C,UAAU,EAAE,YAAY,CAAC,UAAU;YACnC,OAAO,EAAE,KAAK,CAAC,aAAa;YAC5B,aAAa,EAAE,YAAY,CAAC,aAAa;YACzC,WAAW,EAAE,YAAY,CAAC,WAAW;YACrC,MAAM;YACN,YAAY,EAAE,YAAY,CAAC,uBAAuB;YAClD,oBAAoB,EAAE,CAAC,kBAAkB,EAAE,SAAS,EAAE,EAAE,CACtD,4BAA4B,CAAC;gBAC3B,aAAa,EAAE,IAAI;gBACnB,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;gBAC5C,aAAa;gBACb,OAAO,EAAE,kBAAkB;gBAC3B,OAAO,EAAE,YAAY,CAAC,OAAO;gBAC7B,MAAM;gBACN,SAAS;aACV,CAAC;SACL,CAAC,CAAC;QACH,OAAO,8BAA8B,CAAC;YACpC,OAAO,EAAE,KAAK,CAAC,aAAa;YAC5B,YAAY;YACZ,MAAM;YACN,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,sBAAsB,CACrE,KAAK,CAAC,aAAa,EACnB;QACE,wBAAwB,EAAE,KAAK,CAAC,wBAAwB;QACxD,gBAAgB,EAAE,YAAY,CAAC,gBAAgB;QAC/C,GAAG,CAAC,YAAY,CAAC,iBAAiB;YAChC,CAAC,CAAC,EAAE,iBAAiB,EAAE,YAAY,CAAC,iBAAiB,EAAE;YACvD,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,YAAY,CAAC,iBAAiB;YAChC,CAAC,CAAC,EAAE,iBAAiB,EAAE,YAAY,CAAC,iBAAiB,EAAE;YACvD,CAAC,CAAC,EAAE,CAAC;QACP,QAAQ,EAAE,MAAM;QAChB,cAAc,EAAE,QAAQ,CAAC,qBAAqB;QAC9C,GAAG,CAAC,YAAY,CAAC,iBAAiB;YAChC,CAAC,CAAC,EAAE,iBAAiB,EAAE,YAAY,CAAC,iBAAiB,EAAE;YACvD,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,YAAY,CAAC,mBAAmB;YAClC,CAAC,CAAC,EAAE,mBAAmB,EAAE,YAAY,CAAC,mBAAmB,EAAE;YAC3D,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,YAAY,CAAC,cAAc;YAC7B,CAAC,CAAC,EAAE,cAAc,EAAE,YAAY,CAAC,cAAc,EAAE;YACjD,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,YAAY,CAAC,aAAa;YAC5B,CAAC,CAAC,EAAE,aAAa,EAAE,YAAY,CAAC,aAAa,EAAE;YAC/C,CAAC,CAAC,EAAE,CAAC;QACP,+BAA+B,EAC7B,YAAY,CAAC,iBAAiB,KAAK,SAAS;QAC9C,GAAG,CAAC,YAAY,CAAC,uBAAuB;YACtC,CAAC,CAAC,EAAE,YAAY,EAAE,YAAY,CAAC,uBAAuB,EAAE;YACxD,CAAC,CAAC,EAAE,CAAC;KACR,EACD,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,EAAE;QACtC,MAAM,4BAA4B,CAAC;YACjC,aAAa,EAAE,QAAQ,CAAC,qBAAqB;YAC7C,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;YAC5C,aAAa;YACb,OAAO,EAAE,kBAAkB;YAC3B,OAAO,EAAE,YAAY,CAAC,OAAO;YAC7B,MAAM;YACN,SAAS;SACV,CAAC,CAAC;QACH,MAAM,YAAY,CAAC,gBAAgB,EAAE,CAAC,kBAAkB,CAAC,CAAC;IAC5D,CAAC,CACF,CAAC;IACF,OAAO,6BAA6B,CAAC;QACnC,SAAS;QACT,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,YAAY;QACZ,MAAM;KACP,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,KAKjD;IACC,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;IAC9C,IACE,MAAM,4BAA4B,CAAC;QACjC,aAAa,EAAE,YAAY,CAAC,aAAa;QACzC,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,OAAO,EAAE,aAAa;QACtB,OAAO,EAAE,YAAY,CAAC,OAAO;QAC7B,WAAW,EAAE,YAAY,CAAC,WAAW;KACtC,CAAC,EACF,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,wBAAwB,GAAG,YAAY,CAAC,wBAAwB,IAAI,EAAE,CAAC;IAC7E,KACE,IAAI,OAAO,GAAG,CAAC,EACf,OAAO,GAAG,qCAAqC,EAC/C,OAAO,IAAI,CAAC,EACZ,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAC5C,YAAY,EACZ,aAAa,EACb,KAAK,CAAC,KAAK,CACZ,CAAC;QACF,IAAI,QAAQ,CAAC,0BAA0B,EAAE,CAAC;YACxC,OAAO,gCAAgC,CAAC;gBACtC,wBAAwB;gBACxB,aAAa;gBACb,QAAQ;gBACR,YAAY;aACb,CAAC,CAAC;QACL,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,iCAAiC,CAAC;YACrD,wBAAwB;YACxB,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;YAC5C,aAAa;YACb,QAAQ;YACR,YAAY;SACb,CAAC,CAAC;QACH,IAAI,MAAM,KAAK,OAAO;YAAE,OAAO,MAAM,CAAC;IACxC,CAAC;IACD,MAAM,IAAI,KAAK,CACb,0CAA0C,qCAAqC,uBAAuB,CACvG,CAAC;AACJ,CAAC","sourcesContent":["import { type encodeVersionVector, getTextValue } from \"@tearleads/loro\";\nimport {\n DEFAULT_DOCUMENT_ACCESS_EPOCH,\n DEFAULT_DOCUMENT_KIND,\n} from \"../../data/documents/documentConstants\";\nimport {\n type DocumentProjectorRegistry,\n type DocumentProjectorRegistryInput,\n readStoredDocumentState,\n} from \"../../data/documents/documentKinds\";\nimport type {\n DocumentsPersistence,\n StoredDocumentRecord,\n} from \"../../data/persistence/documents/documentsPersistence\";\nimport type { PendingUpdateFields } from \"../../data/persistence/documents/records\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { createInitialDocumentRows } from \"./create/documentCreationPersistence\";\nimport {\n documentSyncSecurityContextMatches,\n type PrepareDocumentMutationInput,\n prepareDocumentMutation,\n} from \"./documentMutationPreparation\";\nimport { refuseDeletedDocumentPersist } from \"./documentPersistGuards\";\n\ntype DocumentContentState = Parameters<typeof encodeVersionVector>[0];\ntype NullableDocumentRuntimeField =\n | \"accessStateHash\"\n | \"lastCommitLsn\"\n | \"contentKeyBundle\"\n | \"documentKekTargets\"\n | \"documentManifestBundle\";\n\nconst MAX_DOCUMENT_MUTATION_COMMIT_ATTEMPTS = 8;\n\nexport interface PersistedDocumentState {\n creationSuperseded?: true;\n historyRestoreState?:\n | Awaited<ReturnType<DocumentsPersistence[\"loadHistoryRestoreState\"]>>\n | undefined;\n pullContinuationSuperseded?: true;\n record: StoredDocumentRecord;\n syncIdentitySuperseded?: true;\n updatedAt?: string | undefined;\n}\n\nexport interface PersistDocumentStateInput\n extends PrepareDocumentMutationInput {\n acceptedPendingUpdateIds?: readonly string[] | undefined;\n attachmentRemoval?:\n | Parameters<\n DocumentsPersistence[\"commitDocumentMutation\"]\n >[1][\"attachmentRemoval\"]\n | undefined;\n attachmentStaging?:\n | Parameters<\n DocumentsPersistence[\"commitDocumentMutation\"]\n >[1][\"attachmentStaging\"]\n | undefined;\n canStartDurableMutation?: (() => boolean) | undefined;\n clearSyncFailure?: boolean | undefined;\n commitSideEffect?: (transactionExecSql: ExecSql) => Promise<void>;\n containerId?: string | null | undefined;\n documentProjectors: DocumentProjectorRegistryInput;\n execSql: ExecSql;\n patch?: Partial<StoredDocumentRecord> | undefined;\n pendingUpdate?: PendingUpdateFields | undefined;\n}\n\nasync function loadSupersededPersistedDocumentState(input: {\n creationSuperseded: boolean;\n execSql: ExecSql;\n localId: string;\n persistence: DocumentsPersistence;\n record: StoredDocumentRecord;\n syncIdentitySuperseded: boolean;\n}): Promise<PersistedDocumentState | null> {\n const { document, historyRestoreState } =\n await input.persistence.loadDocumentWithHistoryRestoreState(\n input.execSql,\n input.localId,\n );\n if (!document) return null;\n const syncIdentitySuperseded =\n input.syncIdentitySuperseded ||\n !documentSyncSecurityContextMatches(document, input.record);\n return {\n ...(input.creationSuperseded ? { creationSuperseded: true as const } : {}),\n historyRestoreState,\n pullContinuationSuperseded: true,\n record: document,\n ...(syncIdentitySuperseded\n ? { syncIdentitySuperseded: true as const }\n : {}),\n };\n}\n\nfunction resolveNullableDocumentRuntimeField(\n patch: Partial<StoredDocumentRecord>,\n key: NullableDocumentRuntimeField,\n currentValue: string | null | undefined,\n resetWhenUnpatched = false,\n): string | null {\n if (Object.hasOwn(patch, key)) return patch[key] ?? null;\n return resetWhenUnpatched ? null : (currentValue ?? null);\n}\n\nfunction resolveStoredDocumentContainerId(input: {\n containerId?: string | null | undefined;\n currentRecord: StoredDocumentRecord | null;\n patch: Partial<StoredDocumentRecord>;\n}): string | null {\n if (Object.hasOwn(input.patch, \"containerId\")) {\n return input.patch.containerId ?? null;\n }\n return input.currentRecord?.containerId ?? input.containerId ?? null;\n}\n\nfunction resolveStoredDocumentPullState(input: {\n currentRecord: StoredDocumentRecord | null;\n patch: Partial<StoredDocumentRecord>;\n securityContextChanged: boolean;\n}): Pick<\n StoredDocumentRecord,\n \"pullContinuation\" | \"pullContinuationRecoveryRequired\"\n> {\n if (Object.hasOwn(input.patch, \"pullContinuation\")) {\n return { pullContinuation: input.patch.pullContinuation ?? null };\n }\n if (input.securityContextChanged) return { pullContinuation: null };\n if (input.currentRecord?.pullContinuationRecoveryRequired) {\n return { pullContinuationRecoveryRequired: true };\n }\n return { pullContinuation: input.currentRecord?.pullContinuation ?? null };\n}\n\nfunction buildStoredDocumentRecord(input: {\n containerId?: string | null | undefined;\n currentDoc: DocumentContentState;\n currentRecord: StoredDocumentRecord | null;\n documentProjectors: DocumentProjectorRegistry;\n localId: string;\n patch: Partial<StoredDocumentRecord>;\n}) {\n const { currentDoc, currentRecord, documentProjectors, localId, patch } =\n input;\n const currentDocumentId = currentRecord?.documentId ?? null;\n const nextDocumentId = patch.documentId ?? currentDocumentId;\n const documentIdChanged = nextDocumentId !== currentDocumentId;\n const currentAccessEpoch =\n currentRecord?.accessEpoch ?? DEFAULT_DOCUMENT_ACCESS_EPOCH;\n const nextAccessEpoch = patch.accessEpoch ?? currentAccessEpoch;\n const securityContextChanged =\n documentIdChanged || nextAccessEpoch !== currentAccessEpoch;\n const documentState = readStoredDocumentState(currentDoc, documentProjectors);\n const record: StoredDocumentRecord = {\n id: currentRecord?.id ?? localId,\n accessEpoch: nextAccessEpoch,\n accessStateHash: resolveNullableDocumentRuntimeField(\n patch,\n \"accessStateHash\",\n currentRecord?.accessStateHash,\n securityContextChanged,\n ),\n containerId: resolveStoredDocumentContainerId({\n containerId: input.containerId,\n currentRecord,\n patch,\n }),\n contentKeyBundle: resolveNullableDocumentRuntimeField(\n patch,\n \"contentKeyBundle\",\n currentRecord?.contentKeyBundle,\n securityContextChanged,\n ),\n documentId: nextDocumentId,\n effectiveAccessLevel:\n patch.effectiveAccessLevel ?? currentRecord?.effectiveAccessLevel ?? null,\n documentKekTargets: resolveNullableDocumentRuntimeField(\n patch,\n \"documentKekTargets\",\n currentRecord?.documentKekTargets,\n securityContextChanged,\n ),\n documentKind: patch.documentKind ?? documentState.documentKind,\n documentManifestBundle: resolveNullableDocumentRuntimeField(\n patch,\n \"documentManifestBundle\",\n currentRecord?.documentManifestBundle,\n securityContextChanged,\n ),\n lastCommitLsn: resolveNullableDocumentRuntimeField(\n patch,\n \"lastCommitLsn\",\n currentRecord?.lastCommitLsn,\n documentIdChanged,\n ),\n snapshotEndVersion:\n patch.snapshotEndVersion ?? currentRecord?.snapshotEndVersion ?? \"\",\n pendingBaseVersion:\n patch.pendingBaseVersion !== undefined\n ? patch.pendingBaseVersion\n : (currentRecord?.pendingBaseVersion ?? null),\n recoveryGeneration:\n patch.recoveryGeneration ?? currentRecord?.recoveryGeneration ?? 0,\n ...resolveStoredDocumentPullState({\n currentRecord,\n patch,\n securityContextChanged,\n }),\n text: patch.text ?? getTextValue(currentDoc),\n title: patch.title ?? documentState.title,\n };\n return { documentState, record };\n}\n\nasync function saveDocumentClientProjection(input: {\n currentRecord: StoredDocumentRecord | null;\n documentProjectors: DocumentProjectorRegistry;\n documentState: ReturnType<typeof readStoredDocumentState>;\n execSql: ExecSql;\n localId: string;\n record: StoredDocumentRecord;\n updatedAt: string;\n}): Promise<void> {\n const previousKind =\n input.currentRecord?.documentKind ?? DEFAULT_DOCUMENT_KIND;\n const nextKind = input.record.documentKind ?? DEFAULT_DOCUMENT_KIND;\n if (previousKind !== nextKind) {\n await input.documentProjectors.deleteStoredDocumentClientProjection({\n documentKind: previousKind,\n execSql: input.execSql,\n localId: input.localId,\n });\n }\n await input.documentProjectors.saveStoredDocumentClientProjection({\n containerId: input.record.containerId,\n documentId: input.record.documentId,\n documentKind: nextKind,\n execSql: input.execSql,\n localId: input.record.id,\n structuredFields: input.documentState.structuredFields,\n text: input.record.text,\n title: input.record.title ?? input.documentState.title,\n updatedAt: input.updatedAt,\n });\n}\n\nasync function settleSupersededDocumentMutation(input: {\n acceptedPendingUpdateIds: readonly string[];\n lockedExecSql: ExecSql;\n mutation: Awaited<ReturnType<typeof prepareDocumentMutation>>;\n persistInput: PersistDocumentStateInput;\n}): Promise<PersistedDocumentState | null> {\n const { mutation, persistInput } = input;\n if (!mutation.mutationCurrentRecord) return null;\n const authoritativeRecord = persistInput.expectedSyncState\n ? await persistInput.persistence.settleAcceptedPendingUpdates(\n input.lockedExecSql,\n {\n expectedRecord: persistInput.expectedSyncState.record,\n pendingUpdateIds: input.acceptedPendingUpdateIds,\n },\n )\n : mutation.mutationCurrentRecord;\n if (!authoritativeRecord) return null;\n return loadSupersededPersistedDocumentState({\n creationSuperseded: mutation.creationSuperseded,\n execSql: input.lockedExecSql,\n localId: persistInput.localId,\n persistence: persistInput.persistence,\n record: authoritativeRecord,\n syncIdentitySuperseded: !mutation.securityContextMatches,\n });\n}\n\nasync function loadConcurrentCreationWinner(input: {\n execSql: ExecSql;\n persistInput: PersistDocumentStateInput;\n}): Promise<PersistedDocumentState> {\n const winningRecord = await input.persistInput.persistence.loadDocument(\n input.execSql,\n input.persistInput.localId,\n );\n if (!winningRecord) {\n throw new Error(\"Concurrent document creation lost without a winner\");\n }\n const winner = await loadSupersededPersistedDocumentState({\n creationSuperseded: true,\n execSql: input.execSql,\n localId: input.persistInput.localId,\n persistence: input.persistInput.persistence,\n record: winningRecord,\n syncIdentitySuperseded: true,\n });\n if (!winner) {\n throw new Error(\"Concurrent document creation winner disappeared\");\n }\n return winner;\n}\n\nasync function resolveInitialDocumentCreation(input: {\n execSql: ExecSql;\n persistInput: PersistDocumentStateInput;\n record: StoredDocumentRecord;\n savedAt: string | null;\n}): Promise<PersistedDocumentState | null> {\n if (input.savedAt !== null) {\n return { record: input.record, updatedAt: input.savedAt };\n }\n if (\n input.persistInput.canStartDurableMutation &&\n !input.persistInput.canStartDurableMutation()\n ) {\n return null;\n }\n return loadConcurrentCreationWinner({\n execSql: input.execSql,\n persistInput: input.persistInput,\n });\n}\n\nasync function resolveDocumentMutationCommit(input: {\n committed: Awaited<\n ReturnType<DocumentsPersistence[\"commitDocumentMutation\"]>\n >;\n lockedExecSql: ExecSql;\n persistInput: PersistDocumentStateInput;\n record: StoredDocumentRecord;\n}): Promise<PersistedDocumentState | null | \"retry\"> {\n const { committed, persistInput, record } = input;\n if (\n persistInput.canStartDurableMutation &&\n !persistInput.canStartDurableMutation()\n ) {\n return null;\n }\n if (committed.committed) return { record, updatedAt: committed.updatedAt };\n if (!committed.currentRecord) return null;\n if (persistInput.expectedSyncState === undefined) return \"retry\";\n return loadSupersededPersistedDocumentState({\n creationSuperseded: false,\n execSql: input.lockedExecSql,\n localId: persistInput.localId,\n persistence: persistInput.persistence,\n record: committed.currentRecord,\n syncIdentitySuperseded: !documentSyncSecurityContextMatches(\n committed.currentRecord,\n persistInput.expectedSyncState.record,\n ),\n });\n}\n\nasync function commitOnePreparedDocumentMutation(input: {\n acceptedPendingUpdateIds: readonly string[];\n documentProjectors: DocumentProjectorRegistry;\n lockedExecSql: ExecSql;\n mutation: Exclude<\n Awaited<ReturnType<typeof prepareDocumentMutation>>,\n { pullContinuationSuperseded: true }\n >;\n persistInput: PersistDocumentStateInput;\n}): Promise<PersistedDocumentState | null | \"retry\"> {\n const { mutation, persistInput } = input;\n const { documentState, record } = buildStoredDocumentRecord({\n containerId: persistInput.containerId,\n currentDoc: persistInput.currentDoc,\n currentRecord: mutation.mutationCurrentRecord,\n documentProjectors: input.documentProjectors,\n localId: persistInput.localId,\n patch: mutation.resolvedPatch,\n });\n if (!mutation.mutationCurrentRecord) {\n const savedAt = await createInitialDocumentRows({\n currentDoc: persistInput.currentDoc,\n execSql: input.lockedExecSql,\n pendingUpdate: persistInput.pendingUpdate,\n persistence: persistInput.persistence,\n record,\n stillCurrent: persistInput.canStartDurableMutation,\n saveClientProjection: (transactionExecSql, updatedAt) =>\n saveDocumentClientProjection({\n currentRecord: null,\n documentProjectors: input.documentProjectors,\n documentState,\n execSql: transactionExecSql,\n localId: persistInput.localId,\n record,\n updatedAt,\n }),\n });\n return resolveInitialDocumentCreation({\n execSql: input.lockedExecSql,\n persistInput,\n record,\n savedAt,\n });\n }\n\n const committed = await persistInput.persistence.commitDocumentMutation(\n input.lockedExecSql,\n {\n acceptedPendingUpdateIds: input.acceptedPendingUpdateIds,\n clearSyncFailure: persistInput.clearSyncFailure,\n ...(persistInput.attachmentRemoval\n ? { attachmentRemoval: persistInput.attachmentRemoval }\n : {}),\n ...(persistInput.attachmentStaging\n ? { attachmentStaging: persistInput.attachmentStaging }\n : {}),\n document: record,\n expectedRecord: mutation.mutationCurrentRecord,\n ...(persistInput.historyCheckpoint\n ? { historyCheckpoint: persistInput.historyCheckpoint }\n : {}),\n ...(persistInput.historyUpdateOrigin\n ? { historyUpdateOrigin: persistInput.historyUpdateOrigin }\n : {}),\n ...(persistInput.historyUpdates\n ? { historyUpdates: persistInput.historyUpdates }\n : {}),\n ...(persistInput.pendingUpdate\n ? { pendingUpdate: persistInput.pendingUpdate }\n : {}),\n settleAcceptedPendingOnConflict:\n persistInput.expectedSyncState !== undefined,\n ...(persistInput.canStartDurableMutation\n ? { stillCurrent: persistInput.canStartDurableMutation }\n : {}),\n },\n async (transactionExecSql, updatedAt) => {\n await saveDocumentClientProjection({\n currentRecord: mutation.mutationCurrentRecord,\n documentProjectors: input.documentProjectors,\n documentState,\n execSql: transactionExecSql,\n localId: persistInput.localId,\n record,\n updatedAt,\n });\n await persistInput.commitSideEffect?.(transactionExecSql);\n },\n );\n return resolveDocumentMutationCommit({\n committed,\n lockedExecSql: input.lockedExecSql,\n persistInput,\n record,\n });\n}\n\nexport async function commitPreparedDocumentState(input: {\n documentProjectors: DocumentProjectorRegistry;\n lockedExecSql: ExecSql;\n patch: Partial<StoredDocumentRecord>;\n persistInput: PersistDocumentStateInput;\n}): Promise<PersistedDocumentState | null> {\n const { lockedExecSql, persistInput } = input;\n if (\n await refuseDeletedDocumentPersist({\n currentRecord: persistInput.currentRecord,\n documentProjectors: input.documentProjectors,\n execSql: lockedExecSql,\n localId: persistInput.localId,\n persistence: persistInput.persistence,\n })\n ) {\n return null;\n }\n const acceptedPendingUpdateIds = persistInput.acceptedPendingUpdateIds ?? [];\n for (\n let attempt = 0;\n attempt < MAX_DOCUMENT_MUTATION_COMMIT_ATTEMPTS;\n attempt += 1\n ) {\n const mutation = await prepareDocumentMutation(\n persistInput,\n lockedExecSql,\n input.patch,\n );\n if (mutation.pullContinuationSuperseded) {\n return settleSupersededDocumentMutation({\n acceptedPendingUpdateIds,\n lockedExecSql,\n mutation,\n persistInput,\n });\n }\n const result = await commitOnePreparedDocumentMutation({\n acceptedPendingUpdateIds,\n documentProjectors: input.documentProjectors,\n lockedExecSql,\n mutation,\n persistInput,\n });\n if (result !== \"retry\") return result;\n }\n throw new Error(\n `Document mutation commit gave up after ${MAX_DOCUMENT_MUTATION_COMMIT_ATTEMPTS} concurrent conflicts`,\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"documentMutationCommit.js","sourceRoot":"","sources":["documentMutationCommit.ts"],"names":[],"mappings":"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","sourcesContent":["import { type encodeVersionVector, getTextValue } from \"@tearleads/loro\";\nimport {\n DEFAULT_DOCUMENT_ACCESS_EPOCH,\n DEFAULT_DOCUMENT_KIND,\n} from \"../../data/documents/documentConstants\";\nimport {\n type DocumentProjectorRegistry,\n type DocumentProjectorRegistryInput,\n readStoredDocumentState,\n} from \"../../data/documents/documentKinds\";\nimport type {\n DocumentsPersistence,\n StoredDocumentRecord,\n} from \"../../data/persistence/documents/documentsPersistence\";\nimport type { PendingUpdateFields } from \"../../data/persistence/documents/records\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { createInitialDocumentRows } from \"./create/documentCreationPersistence\";\nimport {\n documentSyncSecurityContextMatches,\n type PrepareDocumentMutationInput,\n type prepareDocumentMutation,\n} from \"./documentMutationPreparation\";\nimport { prepareDocumentMutationUnlessDeleted } from \"./documentPersistGuards\";\n\ntype DocumentContentState = Parameters<typeof encodeVersionVector>[0];\ntype NullableDocumentRuntimeField =\n | \"accessStateHash\"\n | \"lastCommitLsn\"\n | \"contentKeyBundle\"\n | \"documentKekTargets\"\n | \"documentManifestBundle\";\n\nconst MAX_DOCUMENT_MUTATION_COMMIT_ATTEMPTS = 8;\n\nexport interface PersistedDocumentState {\n creationSuperseded?: true;\n historyRestoreState?:\n | Awaited<ReturnType<DocumentsPersistence[\"loadHistoryRestoreState\"]>>\n | undefined;\n pullContinuationSuperseded?: true;\n record: StoredDocumentRecord;\n syncIdentitySuperseded?: true;\n updatedAt?: string | undefined;\n}\n\nexport interface PersistDocumentStateInput\n extends PrepareDocumentMutationInput {\n acceptedPendingUpdateIds?: readonly string[] | undefined;\n attachmentRemoval?:\n | Parameters<\n DocumentsPersistence[\"commitDocumentMutation\"]\n >[1][\"attachmentRemoval\"]\n | undefined;\n attachmentStaging?:\n | Parameters<\n DocumentsPersistence[\"commitDocumentMutation\"]\n >[1][\"attachmentStaging\"]\n | undefined;\n canStartDurableMutation?: (() => boolean) | undefined;\n clearSyncFailure?: boolean | undefined;\n commitSideEffect?: (transactionExecSql: ExecSql) => Promise<void>;\n containerId?: string | null | undefined;\n documentProjectors: DocumentProjectorRegistryInput;\n execSql: ExecSql;\n patch?: Partial<StoredDocumentRecord> | undefined;\n pendingUpdate?: PendingUpdateFields | undefined;\n}\n\nasync function loadSupersededPersistedDocumentState(input: {\n creationSuperseded: boolean;\n execSql: ExecSql;\n localId: string;\n persistence: DocumentsPersistence;\n record: StoredDocumentRecord;\n syncIdentitySuperseded: boolean;\n}): Promise<PersistedDocumentState | null> {\n const { document, historyRestoreState } =\n await input.persistence.loadDocumentWithHistoryRestoreState(\n input.execSql,\n input.localId,\n );\n if (!document) return null;\n const syncIdentitySuperseded =\n input.syncIdentitySuperseded ||\n !documentSyncSecurityContextMatches(document, input.record);\n return {\n ...(input.creationSuperseded ? { creationSuperseded: true as const } : {}),\n historyRestoreState,\n pullContinuationSuperseded: true,\n record: document,\n ...(syncIdentitySuperseded\n ? { syncIdentitySuperseded: true as const }\n : {}),\n };\n}\n\nfunction resolveNullableDocumentRuntimeField(\n patch: Partial<StoredDocumentRecord>,\n key: NullableDocumentRuntimeField,\n currentValue: string | null | undefined,\n resetWhenUnpatched = false,\n): string | null {\n if (Object.hasOwn(patch, key)) return patch[key] ?? null;\n return resetWhenUnpatched ? null : (currentValue ?? null);\n}\n\nfunction resolveStoredDocumentContainerId(input: {\n containerId?: string | null | undefined;\n currentRecord: StoredDocumentRecord | null;\n patch: Partial<StoredDocumentRecord>;\n}): string | null {\n if (Object.hasOwn(input.patch, \"containerId\")) {\n return input.patch.containerId ?? null;\n }\n return input.currentRecord?.containerId ?? input.containerId ?? null;\n}\n\nfunction resolveStoredDocumentPullState(input: {\n currentRecord: StoredDocumentRecord | null;\n patch: Partial<StoredDocumentRecord>;\n securityContextChanged: boolean;\n}): Pick<\n StoredDocumentRecord,\n \"pullContinuation\" | \"pullContinuationRecoveryRequired\"\n> {\n if (Object.hasOwn(input.patch, \"pullContinuation\")) {\n return { pullContinuation: input.patch.pullContinuation ?? null };\n }\n if (input.securityContextChanged) return { pullContinuation: null };\n if (input.currentRecord?.pullContinuationRecoveryRequired) {\n return { pullContinuationRecoveryRequired: true };\n }\n return { pullContinuation: input.currentRecord?.pullContinuation ?? null };\n}\n\nfunction buildStoredDocumentRecord(input: {\n containerId?: string | null | undefined;\n currentDoc: DocumentContentState;\n currentRecord: StoredDocumentRecord | null;\n documentProjectors: DocumentProjectorRegistry;\n localId: string;\n patch: Partial<StoredDocumentRecord>;\n}) {\n const { currentDoc, currentRecord, documentProjectors, localId, patch } =\n input;\n const currentDocumentId = currentRecord?.documentId ?? null;\n const nextDocumentId = patch.documentId ?? currentDocumentId;\n const documentIdChanged = nextDocumentId !== currentDocumentId;\n const currentAccessEpoch =\n currentRecord?.accessEpoch ?? DEFAULT_DOCUMENT_ACCESS_EPOCH;\n const nextAccessEpoch = patch.accessEpoch ?? currentAccessEpoch;\n const securityContextChanged =\n documentIdChanged || nextAccessEpoch !== currentAccessEpoch;\n const documentState = readStoredDocumentState(currentDoc, documentProjectors);\n const record: StoredDocumentRecord = {\n id: currentRecord?.id ?? localId,\n accessEpoch: nextAccessEpoch,\n accessStateHash: resolveNullableDocumentRuntimeField(\n patch,\n \"accessStateHash\",\n currentRecord?.accessStateHash,\n securityContextChanged,\n ),\n containerId: resolveStoredDocumentContainerId({\n containerId: input.containerId,\n currentRecord,\n patch,\n }),\n contentKeyBundle: resolveNullableDocumentRuntimeField(\n patch,\n \"contentKeyBundle\",\n currentRecord?.contentKeyBundle,\n securityContextChanged,\n ),\n documentId: nextDocumentId,\n effectiveAccessLevel:\n patch.effectiveAccessLevel ?? currentRecord?.effectiveAccessLevel ?? null,\n documentKekTargets: resolveNullableDocumentRuntimeField(\n patch,\n \"documentKekTargets\",\n currentRecord?.documentKekTargets,\n securityContextChanged,\n ),\n documentKind: patch.documentKind ?? documentState.documentKind,\n documentManifestBundle: resolveNullableDocumentRuntimeField(\n patch,\n \"documentManifestBundle\",\n currentRecord?.documentManifestBundle,\n securityContextChanged,\n ),\n lastCommitLsn: resolveNullableDocumentRuntimeField(\n patch,\n \"lastCommitLsn\",\n currentRecord?.lastCommitLsn,\n documentIdChanged,\n ),\n snapshotEndVersion:\n patch.snapshotEndVersion ?? currentRecord?.snapshotEndVersion ?? \"\",\n pendingBaseVersion:\n patch.pendingBaseVersion !== undefined\n ? patch.pendingBaseVersion\n : (currentRecord?.pendingBaseVersion ?? null),\n recoveryGeneration:\n patch.recoveryGeneration ?? currentRecord?.recoveryGeneration ?? 0,\n ...resolveStoredDocumentPullState({\n currentRecord,\n patch,\n securityContextChanged,\n }),\n text: patch.text ?? getTextValue(currentDoc),\n title: patch.title ?? documentState.title,\n };\n return { documentState, record };\n}\n\nasync function saveDocumentClientProjection(input: {\n currentRecord: StoredDocumentRecord | null;\n documentProjectors: DocumentProjectorRegistry;\n documentState: ReturnType<typeof readStoredDocumentState>;\n execSql: ExecSql;\n localId: string;\n record: StoredDocumentRecord;\n updatedAt: string;\n}): Promise<void> {\n const previousKind =\n input.currentRecord?.documentKind ?? DEFAULT_DOCUMENT_KIND;\n const nextKind = input.record.documentKind ?? DEFAULT_DOCUMENT_KIND;\n if (previousKind !== nextKind) {\n await input.documentProjectors.deleteStoredDocumentClientProjection({\n documentKind: previousKind,\n execSql: input.execSql,\n localId: input.localId,\n });\n }\n await input.documentProjectors.saveStoredDocumentClientProjection({\n containerId: input.record.containerId,\n documentId: input.record.documentId,\n documentKind: nextKind,\n execSql: input.execSql,\n localId: input.record.id,\n structuredFields: input.documentState.structuredFields,\n text: input.record.text,\n title: input.record.title ?? input.documentState.title,\n updatedAt: input.updatedAt,\n });\n}\n\nasync function settleSupersededDocumentMutation(input: {\n acceptedPendingUpdateIds: readonly string[];\n lockedExecSql: ExecSql;\n mutation: Awaited<ReturnType<typeof prepareDocumentMutation>>;\n persistInput: PersistDocumentStateInput;\n}): Promise<PersistedDocumentState | null> {\n const { mutation, persistInput } = input;\n if (!mutation.mutationCurrentRecord) return null;\n const authoritativeRecord = persistInput.expectedSyncState\n ? await persistInput.persistence.settleAcceptedPendingUpdates(\n input.lockedExecSql,\n {\n expectedRecord: persistInput.expectedSyncState.record,\n pendingUpdateIds: input.acceptedPendingUpdateIds,\n },\n )\n : mutation.mutationCurrentRecord;\n if (!authoritativeRecord) return null;\n return loadSupersededPersistedDocumentState({\n creationSuperseded: mutation.creationSuperseded,\n execSql: input.lockedExecSql,\n localId: persistInput.localId,\n persistence: persistInput.persistence,\n record: authoritativeRecord,\n syncIdentitySuperseded: !mutation.securityContextMatches,\n });\n}\n\nasync function loadConcurrentCreationWinner(input: {\n execSql: ExecSql;\n persistInput: PersistDocumentStateInput;\n}): Promise<PersistedDocumentState> {\n const winningRecord = await input.persistInput.persistence.loadDocument(\n input.execSql,\n input.persistInput.localId,\n );\n if (!winningRecord) {\n throw new Error(\"Concurrent document creation lost without a winner\");\n }\n const winner = await loadSupersededPersistedDocumentState({\n creationSuperseded: true,\n execSql: input.execSql,\n localId: input.persistInput.localId,\n persistence: input.persistInput.persistence,\n record: winningRecord,\n syncIdentitySuperseded: true,\n });\n if (!winner) {\n throw new Error(\"Concurrent document creation winner disappeared\");\n }\n return winner;\n}\n\nasync function resolveInitialDocumentCreation(input: {\n execSql: ExecSql;\n persistInput: PersistDocumentStateInput;\n record: StoredDocumentRecord;\n savedAt: string | null;\n}): Promise<PersistedDocumentState | null> {\n if (input.savedAt !== null) {\n return { record: input.record, updatedAt: input.savedAt };\n }\n if (\n input.persistInput.canStartDurableMutation &&\n !input.persistInput.canStartDurableMutation()\n ) {\n return null;\n }\n return loadConcurrentCreationWinner({\n execSql: input.execSql,\n persistInput: input.persistInput,\n });\n}\n\nasync function resolveDocumentMutationCommit(input: {\n committed: Awaited<\n ReturnType<DocumentsPersistence[\"commitDocumentMutation\"]>\n >;\n lockedExecSql: ExecSql;\n persistInput: PersistDocumentStateInput;\n record: StoredDocumentRecord;\n}): Promise<PersistedDocumentState | null | \"retry\"> {\n const { committed, persistInput, record } = input;\n if (\n persistInput.canStartDurableMutation &&\n !persistInput.canStartDurableMutation()\n ) {\n return null;\n }\n if (committed.committed) return { record, updatedAt: committed.updatedAt };\n if (!committed.currentRecord) return null;\n if (persistInput.expectedSyncState === undefined) return \"retry\";\n return loadSupersededPersistedDocumentState({\n creationSuperseded: false,\n execSql: input.lockedExecSql,\n localId: persistInput.localId,\n persistence: persistInput.persistence,\n record: committed.currentRecord,\n syncIdentitySuperseded: !documentSyncSecurityContextMatches(\n committed.currentRecord,\n persistInput.expectedSyncState.record,\n ),\n });\n}\n\nasync function commitOnePreparedDocumentMutation(input: {\n acceptedPendingUpdateIds: readonly string[];\n documentProjectors: DocumentProjectorRegistry;\n lockedExecSql: ExecSql;\n mutation: Exclude<\n Awaited<ReturnType<typeof prepareDocumentMutation>>,\n { pullContinuationSuperseded: true }\n >;\n persistInput: PersistDocumentStateInput;\n}): Promise<PersistedDocumentState | null | \"retry\"> {\n const { mutation, persistInput } = input;\n const { documentState, record } = buildStoredDocumentRecord({\n containerId: persistInput.containerId,\n currentDoc: persistInput.currentDoc,\n currentRecord: mutation.mutationCurrentRecord,\n documentProjectors: input.documentProjectors,\n localId: persistInput.localId,\n patch: mutation.resolvedPatch,\n });\n if (!mutation.mutationCurrentRecord) {\n const savedAt = await createInitialDocumentRows({\n currentDoc: persistInput.currentDoc,\n execSql: input.lockedExecSql,\n pendingUpdate: persistInput.pendingUpdate,\n persistence: persistInput.persistence,\n record,\n stillCurrent: persistInput.canStartDurableMutation,\n saveClientProjection: (transactionExecSql, updatedAt) =>\n saveDocumentClientProjection({\n currentRecord: null,\n documentProjectors: input.documentProjectors,\n documentState,\n execSql: transactionExecSql,\n localId: persistInput.localId,\n record,\n updatedAt,\n }),\n });\n return resolveInitialDocumentCreation({\n execSql: input.lockedExecSql,\n persistInput,\n record,\n savedAt,\n });\n }\n\n const committed = await persistInput.persistence.commitDocumentMutation(\n input.lockedExecSql,\n {\n acceptedPendingUpdateIds: input.acceptedPendingUpdateIds,\n clearSyncFailure: persistInput.clearSyncFailure,\n ...(persistInput.attachmentRemoval\n ? { attachmentRemoval: persistInput.attachmentRemoval }\n : {}),\n ...(persistInput.attachmentStaging\n ? { attachmentStaging: persistInput.attachmentStaging }\n : {}),\n document: record,\n expectedRecord: mutation.mutationCurrentRecord,\n ...(persistInput.historyCheckpoint\n ? { historyCheckpoint: persistInput.historyCheckpoint }\n : {}),\n ...(persistInput.historyUpdateOrigin\n ? { historyUpdateOrigin: persistInput.historyUpdateOrigin }\n : {}),\n ...(persistInput.historyUpdates\n ? { historyUpdates: persistInput.historyUpdates }\n : {}),\n ...(persistInput.pendingUpdate\n ? { pendingUpdate: persistInput.pendingUpdate }\n : {}),\n settleAcceptedPendingOnConflict:\n persistInput.expectedSyncState !== undefined,\n ...(persistInput.canStartDurableMutation\n ? { stillCurrent: persistInput.canStartDurableMutation }\n : {}),\n },\n async (transactionExecSql, updatedAt) => {\n await saveDocumentClientProjection({\n currentRecord: mutation.mutationCurrentRecord,\n documentProjectors: input.documentProjectors,\n documentState,\n execSql: transactionExecSql,\n localId: persistInput.localId,\n record,\n updatedAt,\n });\n await persistInput.commitSideEffect?.(transactionExecSql);\n },\n );\n return resolveDocumentMutationCommit({\n committed,\n lockedExecSql: input.lockedExecSql,\n persistInput,\n record,\n });\n}\n\nexport async function commitPreparedDocumentState(input: {\n documentProjectors: DocumentProjectorRegistry;\n lockedExecSql: ExecSql;\n patch: Partial<StoredDocumentRecord>;\n persistInput: PersistDocumentStateInput;\n}): Promise<PersistedDocumentState | null> {\n const { lockedExecSql, persistInput } = input;\n const acceptedPendingUpdateIds = persistInput.acceptedPendingUpdateIds ?? [];\n for (\n let attempt = 0;\n attempt < MAX_DOCUMENT_MUTATION_COMMIT_ATTEMPTS;\n attempt += 1\n ) {\n const mutation = await prepareDocumentMutationUnlessDeleted({\n documentProjectors: input.documentProjectors,\n guard: attempt === 0,\n lockedExecSql,\n patch: input.patch,\n persistInput,\n });\n if (!mutation) return null;\n if (mutation.pullContinuationSuperseded) {\n return settleSupersededDocumentMutation({\n acceptedPendingUpdateIds,\n lockedExecSql,\n mutation,\n persistInput,\n });\n }\n const result = await commitOnePreparedDocumentMutation({\n acceptedPendingUpdateIds,\n documentProjectors: input.documentProjectors,\n lockedExecSql,\n mutation,\n persistInput,\n });\n if (result !== \"retry\") return result;\n }\n throw new Error(\n `Document mutation commit gave up after ${MAX_DOCUMENT_MUTATION_COMMIT_ATTEMPTS} concurrent conflicts`,\n );\n}\n"]}
|
|
@@ -24,6 +24,7 @@ export interface PrepareDocumentMutationInput {
|
|
|
24
24
|
export declare function documentSyncSecurityContextMatches(current: StoredDocumentRecord | null, expected: StoredDocumentRecord): boolean;
|
|
25
25
|
export declare function prepareDocumentMutation(input: PrepareDocumentMutationInput, execSql: ExecSql, patch: Partial<StoredDocumentRecord>): Promise<{
|
|
26
26
|
creationSuperseded: boolean;
|
|
27
|
+
durableCurrentRecord: StoredDocumentRecord | null;
|
|
27
28
|
mutationCurrentRecord: StoredDocumentRecord | null;
|
|
28
29
|
pullContinuationSuperseded: boolean;
|
|
29
30
|
resolvedPatch: Partial<StoredDocumentRecord>;
|
|
@@ -135,6 +135,7 @@ export async function prepareDocumentMutation(input, execSql, patch) {
|
|
|
135
135
|
: await input.persistence.loadDocumentContainer(execSql, input.localId);
|
|
136
136
|
return {
|
|
137
137
|
creationSuperseded,
|
|
138
|
+
durableCurrentRecord,
|
|
138
139
|
mutationCurrentRecord,
|
|
139
140
|
pullContinuationSuperseded,
|
|
140
141
|
resolvedPatch: authoritativeContainer === undefined
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documentMutationPreparation.js","sourceRoot":"","sources":["documentMutationPreparation.ts"],"names":[],"mappings":"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","sourcesContent":["import { mergeVersionVectors, satisfiesVersionVector } from \"@tearleads/loro\";\nimport {\n type DocumentSyncPullContinuation,\n documentSyncPullContinuationsEqual,\n} from \"../../data/documents/shared/sync/syncPagination\";\nimport { canWriteEffectiveAccessLevel } from \"../../data/keying/accessLevel\";\nimport type {\n DocumentsPersistence,\n StoredDocumentRecord,\n} from \"../../data/persistence/documents/documentsPersistence\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { mergePersistedDocumentHistory } from \"./historyContent\";\n\nexport interface ExpectedDocumentSyncState {\n pullContinuation: DocumentSyncPullContinuation | null;\n record: StoredDocumentRecord;\n}\n\nexport interface PrepareDocumentMutationInput {\n currentDoc: Parameters<typeof mergePersistedDocumentHistory>[0][\"doc\"];\n currentRecord: StoredDocumentRecord | null;\n expectedSyncState?: ExpectedDocumentSyncState | undefined;\n historyCheckpoint?:\n | {\n coveredTailIds: readonly string[];\n endVersionVector: string;\n pruneCoveredLocalState: boolean;\n snapshot: string;\n }\n | undefined;\n historyUpdateOrigin?: \"local\" | \"remote\" | undefined;\n historyUpdates?: readonly string[] | undefined;\n localId: string;\n persistence: DocumentsPersistence;\n}\n\nfunction sameNullableDocumentValue(\n left: string | null | undefined,\n right: string | null | undefined,\n): boolean {\n return (left ?? null) === (right ?? null);\n}\n\nexport function documentSyncSecurityContextMatches(\n current: StoredDocumentRecord | null,\n expected: StoredDocumentRecord,\n): boolean {\n return (\n current !== null &&\n current.id === expected.id &&\n current.documentId === expected.documentId &&\n current.containerId === expected.containerId &&\n current.accessEpoch === expected.accessEpoch &&\n sameNullableDocumentValue(\n current.accessStateHash,\n expected.accessStateHash,\n ) &&\n (current.effectiveAccessLevel ?? null) ===\n (expected.effectiveAccessLevel ?? null) &&\n sameNullableDocumentValue(\n current.contentKeyBundle,\n expected.contentKeyBundle,\n ) &&\n sameNullableDocumentValue(\n current.documentKekTargets,\n expected.documentKekTargets,\n ) &&\n sameNullableDocumentValue(\n current.documentManifestBundle,\n expected.documentManifestBundle,\n )\n );\n}\n\nfunction patchSpecifiesContainer(\n patch: Partial<StoredDocumentRecord>,\n): boolean {\n return Object.hasOwn(patch, \"containerId\");\n}\n\nfunction documentSyncStateDiffers(\n current: StoredDocumentRecord,\n cached: StoredDocumentRecord,\n): boolean {\n return (\n !sameNullableDocumentValue(current.lastCommitLsn, cached.lastCommitLsn) ||\n current.snapshotEndVersion !== cached.snapshotEndVersion ||\n !sameNullableDocumentValue(\n current.pendingBaseVersion,\n cached.pendingBaseVersion,\n ) ||\n !documentSyncPullContinuationsEqual(\n current.pullContinuation,\n cached.pullContinuation,\n ) ||\n Boolean(current.pullContinuationRecoveryRequired) !==\n Boolean(cached.pullContinuationRecoveryRequired)\n );\n}\n\nfunction mergeMutationFrontiers(\n patch: Partial<StoredDocumentRecord>,\n durableRecord: StoredDocumentRecord,\n): Partial<StoredDocumentRecord> {\n const nextPatch = { ...patch };\n if (patch.snapshotEndVersion !== undefined) {\n nextPatch.snapshotEndVersion = mergeVersionVectors([\n durableRecord.snapshotEndVersion,\n patch.snapshotEndVersion,\n ]);\n }\n if (\n patch.pendingBaseVersion !== undefined &&\n patch.pendingBaseVersion !== null &&\n durableRecord.pendingBaseVersion\n ) {\n nextPatch.pendingBaseVersion = mergeVersionVectors([\n durableRecord.pendingBaseVersion,\n patch.pendingBaseVersion,\n ]);\n }\n return nextPatch;\n}\n\nfunction ordinarySaveNeedsHistoryRebase(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n if (\n input.expectedSyncState !== undefined ||\n durableRecord === null ||\n input.currentRecord === null\n ) {\n return false;\n }\n const cachedPendingBase = input.currentRecord.pendingBaseVersion;\n const durableCoversCachedPendingBase =\n !cachedPendingBase ||\n (durableRecord.pendingBaseVersion !== null &&\n durableRecord.pendingBaseVersion !== undefined &&\n satisfiesVersionVector(\n durableRecord.pendingBaseVersion,\n cachedPendingBase,\n ));\n return (\n durableRecord.id === input.currentRecord.id &&\n durableRecord.documentId === input.currentRecord.documentId &&\n satisfiesVersionVector(\n durableRecord.snapshotEndVersion,\n input.currentRecord.snapshotEndVersion,\n ) &&\n durableCoversCachedPendingBase &&\n documentSyncStateDiffers(durableRecord, input.currentRecord)\n );\n}\n\nfunction ordinarySaveIdentityWasReplaced(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n return (\n input.expectedSyncState === undefined &&\n input.currentRecord !== null &&\n durableRecord !== null &&\n (durableRecord.id !== input.currentRecord.id ||\n durableRecord.documentId !== input.currentRecord.documentId)\n );\n}\n\nfunction ordinarySaveWriteAccessWasRevoked(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n return (\n input.expectedSyncState === undefined &&\n input.currentRecord !== null &&\n durableRecord !== null &&\n canWriteEffectiveAccessLevel(input.currentRecord.effectiveAccessLevel) &&\n !canWriteEffectiveAccessLevel(durableRecord.effectiveAccessLevel)\n );\n}\n\nfunction recoveryGenerationWasSuperseded(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n return (\n input.currentRecord !== null &&\n durableRecord !== null &&\n (input.currentRecord.recoveryGeneration ?? 0) !==\n (durableRecord.recoveryGeneration ?? 0)\n );\n}\n\nfunction resolveSyncSettlementState(\n current: StoredDocumentRecord | null,\n expected: ExpectedDocumentSyncState | undefined,\n): { pullContinuationSuperseded: boolean; securityContextMatches: boolean } {\n if (!expected) {\n return { pullContinuationSuperseded: false, securityContextMatches: true };\n }\n const securityContextMatches = documentSyncSecurityContextMatches(\n current,\n expected.record,\n );\n const contentFrontiersMatch =\n sameNullableDocumentValue(\n current?.lastCommitLsn,\n expected.record.lastCommitLsn,\n ) &&\n current?.snapshotEndVersion === expected.record.snapshotEndVersion &&\n sameNullableDocumentValue(\n current?.pendingBaseVersion,\n expected.record.pendingBaseVersion,\n );\n const recoveryStateMatches =\n Boolean(current?.pullContinuationRecoveryRequired) ===\n Boolean(expected.record.pullContinuationRecoveryRequired) &&\n (current?.recoveryGeneration ?? 0) ===\n (expected.record.recoveryGeneration ?? 0);\n return {\n pullContinuationSuperseded:\n !securityContextMatches ||\n !contentFrontiersMatch ||\n !recoveryStateMatches ||\n !documentSyncPullContinuationsEqual(\n current?.pullContinuation,\n expected.pullContinuation,\n ),\n securityContextMatches,\n };\n}\n\nexport async function prepareDocumentMutation(\n input: PrepareDocumentMutationInput,\n execSql: ExecSql,\n patch: Partial<StoredDocumentRecord>,\n) {\n const durableCurrentRecord = await input.persistence.loadDocument(\n execSql,\n input.localId,\n );\n const creationSuperseded =\n input.currentRecord === null && durableCurrentRecord !== null;\n const mutationCurrentRecord = durableCurrentRecord ?? input.currentRecord;\n const identityWasReplaced = ordinarySaveIdentityWasReplaced(\n input,\n durableCurrentRecord,\n );\n const writeAccessWasRevoked = ordinarySaveWriteAccessWasRevoked(\n input,\n durableCurrentRecord,\n );\n const recoveryWasSuperseded = recoveryGenerationWasSuperseded(\n input,\n durableCurrentRecord,\n );\n const { pullContinuationSuperseded, securityContextMatches } =\n creationSuperseded || identityWasReplaced || writeAccessWasRevoked\n ? { pullContinuationSuperseded: true, securityContextMatches: false }\n : recoveryWasSuperseded\n ? { pullContinuationSuperseded: true, securityContextMatches: true }\n : resolveSyncSettlementState(\n mutationCurrentRecord,\n input.expectedSyncState,\n );\n const ordinarySaveNeedsRebase = ordinarySaveNeedsHistoryRebase(\n input,\n durableCurrentRecord,\n );\n\n if (ordinarySaveNeedsRebase && securityContextMatches) {\n await mergePersistedDocumentHistory({\n doc: input.currentDoc,\n execSql,\n localId: input.localId,\n persistence: input.persistence,\n });\n }\n const mutationPatch = pullContinuationSuperseded\n ? {}\n : ordinarySaveNeedsRebase && durableCurrentRecord\n ? mergeMutationFrontiers(patch, durableCurrentRecord)\n : patch;\n const authoritativeContainer = patchSpecifiesContainer(mutationPatch)\n ? undefined\n : await input.persistence.loadDocumentContainer(execSql, input.localId);\n return {\n creationSuperseded,\n mutationCurrentRecord,\n pullContinuationSuperseded,\n resolvedPatch:\n authoritativeContainer === undefined\n ? mutationPatch\n : { ...mutationPatch, containerId: authoritativeContainer.containerId },\n securityContextMatches,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"documentMutationPreparation.js","sourceRoot":"","sources":["documentMutationPreparation.ts"],"names":[],"mappings":"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","sourcesContent":["import { mergeVersionVectors, satisfiesVersionVector } from \"@tearleads/loro\";\nimport {\n type DocumentSyncPullContinuation,\n documentSyncPullContinuationsEqual,\n} from \"../../data/documents/shared/sync/syncPagination\";\nimport { canWriteEffectiveAccessLevel } from \"../../data/keying/accessLevel\";\nimport type {\n DocumentsPersistence,\n StoredDocumentRecord,\n} from \"../../data/persistence/documents/documentsPersistence\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { mergePersistedDocumentHistory } from \"./historyContent\";\n\nexport interface ExpectedDocumentSyncState {\n pullContinuation: DocumentSyncPullContinuation | null;\n record: StoredDocumentRecord;\n}\n\nexport interface PrepareDocumentMutationInput {\n currentDoc: Parameters<typeof mergePersistedDocumentHistory>[0][\"doc\"];\n currentRecord: StoredDocumentRecord | null;\n expectedSyncState?: ExpectedDocumentSyncState | undefined;\n historyCheckpoint?:\n | {\n coveredTailIds: readonly string[];\n endVersionVector: string;\n pruneCoveredLocalState: boolean;\n snapshot: string;\n }\n | undefined;\n historyUpdateOrigin?: \"local\" | \"remote\" | undefined;\n historyUpdates?: readonly string[] | undefined;\n localId: string;\n persistence: DocumentsPersistence;\n}\n\nfunction sameNullableDocumentValue(\n left: string | null | undefined,\n right: string | null | undefined,\n): boolean {\n return (left ?? null) === (right ?? null);\n}\n\nexport function documentSyncSecurityContextMatches(\n current: StoredDocumentRecord | null,\n expected: StoredDocumentRecord,\n): boolean {\n return (\n current !== null &&\n current.id === expected.id &&\n current.documentId === expected.documentId &&\n current.containerId === expected.containerId &&\n current.accessEpoch === expected.accessEpoch &&\n sameNullableDocumentValue(\n current.accessStateHash,\n expected.accessStateHash,\n ) &&\n (current.effectiveAccessLevel ?? null) ===\n (expected.effectiveAccessLevel ?? null) &&\n sameNullableDocumentValue(\n current.contentKeyBundle,\n expected.contentKeyBundle,\n ) &&\n sameNullableDocumentValue(\n current.documentKekTargets,\n expected.documentKekTargets,\n ) &&\n sameNullableDocumentValue(\n current.documentManifestBundle,\n expected.documentManifestBundle,\n )\n );\n}\n\nfunction patchSpecifiesContainer(\n patch: Partial<StoredDocumentRecord>,\n): boolean {\n return Object.hasOwn(patch, \"containerId\");\n}\n\nfunction documentSyncStateDiffers(\n current: StoredDocumentRecord,\n cached: StoredDocumentRecord,\n): boolean {\n return (\n !sameNullableDocumentValue(current.lastCommitLsn, cached.lastCommitLsn) ||\n current.snapshotEndVersion !== cached.snapshotEndVersion ||\n !sameNullableDocumentValue(\n current.pendingBaseVersion,\n cached.pendingBaseVersion,\n ) ||\n !documentSyncPullContinuationsEqual(\n current.pullContinuation,\n cached.pullContinuation,\n ) ||\n Boolean(current.pullContinuationRecoveryRequired) !==\n Boolean(cached.pullContinuationRecoveryRequired)\n );\n}\n\nfunction mergeMutationFrontiers(\n patch: Partial<StoredDocumentRecord>,\n durableRecord: StoredDocumentRecord,\n): Partial<StoredDocumentRecord> {\n const nextPatch = { ...patch };\n if (patch.snapshotEndVersion !== undefined) {\n nextPatch.snapshotEndVersion = mergeVersionVectors([\n durableRecord.snapshotEndVersion,\n patch.snapshotEndVersion,\n ]);\n }\n if (\n patch.pendingBaseVersion !== undefined &&\n patch.pendingBaseVersion !== null &&\n durableRecord.pendingBaseVersion\n ) {\n nextPatch.pendingBaseVersion = mergeVersionVectors([\n durableRecord.pendingBaseVersion,\n patch.pendingBaseVersion,\n ]);\n }\n return nextPatch;\n}\n\nfunction ordinarySaveNeedsHistoryRebase(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n if (\n input.expectedSyncState !== undefined ||\n durableRecord === null ||\n input.currentRecord === null\n ) {\n return false;\n }\n const cachedPendingBase = input.currentRecord.pendingBaseVersion;\n const durableCoversCachedPendingBase =\n !cachedPendingBase ||\n (durableRecord.pendingBaseVersion !== null &&\n durableRecord.pendingBaseVersion !== undefined &&\n satisfiesVersionVector(\n durableRecord.pendingBaseVersion,\n cachedPendingBase,\n ));\n return (\n durableRecord.id === input.currentRecord.id &&\n durableRecord.documentId === input.currentRecord.documentId &&\n satisfiesVersionVector(\n durableRecord.snapshotEndVersion,\n input.currentRecord.snapshotEndVersion,\n ) &&\n durableCoversCachedPendingBase &&\n documentSyncStateDiffers(durableRecord, input.currentRecord)\n );\n}\n\nfunction ordinarySaveIdentityWasReplaced(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n return (\n input.expectedSyncState === undefined &&\n input.currentRecord !== null &&\n durableRecord !== null &&\n (durableRecord.id !== input.currentRecord.id ||\n durableRecord.documentId !== input.currentRecord.documentId)\n );\n}\n\nfunction ordinarySaveWriteAccessWasRevoked(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n return (\n input.expectedSyncState === undefined &&\n input.currentRecord !== null &&\n durableRecord !== null &&\n canWriteEffectiveAccessLevel(input.currentRecord.effectiveAccessLevel) &&\n !canWriteEffectiveAccessLevel(durableRecord.effectiveAccessLevel)\n );\n}\n\nfunction recoveryGenerationWasSuperseded(\n input: PrepareDocumentMutationInput,\n durableRecord: StoredDocumentRecord | null,\n): boolean {\n return (\n input.currentRecord !== null &&\n durableRecord !== null &&\n (input.currentRecord.recoveryGeneration ?? 0) !==\n (durableRecord.recoveryGeneration ?? 0)\n );\n}\n\nfunction resolveSyncSettlementState(\n current: StoredDocumentRecord | null,\n expected: ExpectedDocumentSyncState | undefined,\n): { pullContinuationSuperseded: boolean; securityContextMatches: boolean } {\n if (!expected) {\n return { pullContinuationSuperseded: false, securityContextMatches: true };\n }\n const securityContextMatches = documentSyncSecurityContextMatches(\n current,\n expected.record,\n );\n const contentFrontiersMatch =\n sameNullableDocumentValue(\n current?.lastCommitLsn,\n expected.record.lastCommitLsn,\n ) &&\n current?.snapshotEndVersion === expected.record.snapshotEndVersion &&\n sameNullableDocumentValue(\n current?.pendingBaseVersion,\n expected.record.pendingBaseVersion,\n );\n const recoveryStateMatches =\n Boolean(current?.pullContinuationRecoveryRequired) ===\n Boolean(expected.record.pullContinuationRecoveryRequired) &&\n (current?.recoveryGeneration ?? 0) ===\n (expected.record.recoveryGeneration ?? 0);\n return {\n pullContinuationSuperseded:\n !securityContextMatches ||\n !contentFrontiersMatch ||\n !recoveryStateMatches ||\n !documentSyncPullContinuationsEqual(\n current?.pullContinuation,\n expected.pullContinuation,\n ),\n securityContextMatches,\n };\n}\n\nexport async function prepareDocumentMutation(\n input: PrepareDocumentMutationInput,\n execSql: ExecSql,\n patch: Partial<StoredDocumentRecord>,\n) {\n const durableCurrentRecord = await input.persistence.loadDocument(\n execSql,\n input.localId,\n );\n const creationSuperseded =\n input.currentRecord === null && durableCurrentRecord !== null;\n const mutationCurrentRecord = durableCurrentRecord ?? input.currentRecord;\n const identityWasReplaced = ordinarySaveIdentityWasReplaced(\n input,\n durableCurrentRecord,\n );\n const writeAccessWasRevoked = ordinarySaveWriteAccessWasRevoked(\n input,\n durableCurrentRecord,\n );\n const recoveryWasSuperseded = recoveryGenerationWasSuperseded(\n input,\n durableCurrentRecord,\n );\n const { pullContinuationSuperseded, securityContextMatches } =\n creationSuperseded || identityWasReplaced || writeAccessWasRevoked\n ? { pullContinuationSuperseded: true, securityContextMatches: false }\n : recoveryWasSuperseded\n ? { pullContinuationSuperseded: true, securityContextMatches: true }\n : resolveSyncSettlementState(\n mutationCurrentRecord,\n input.expectedSyncState,\n );\n const ordinarySaveNeedsRebase = ordinarySaveNeedsHistoryRebase(\n input,\n durableCurrentRecord,\n );\n\n if (ordinarySaveNeedsRebase && securityContextMatches) {\n await mergePersistedDocumentHistory({\n doc: input.currentDoc,\n execSql,\n localId: input.localId,\n persistence: input.persistence,\n });\n }\n const mutationPatch = pullContinuationSuperseded\n ? {}\n : ordinarySaveNeedsRebase && durableCurrentRecord\n ? mergeMutationFrontiers(patch, durableCurrentRecord)\n : patch;\n const authoritativeContainer = patchSpecifiesContainer(mutationPatch)\n ? undefined\n : await input.persistence.loadDocumentContainer(execSql, input.localId);\n return {\n creationSuperseded,\n durableCurrentRecord,\n mutationCurrentRecord,\n pullContinuationSuperseded,\n resolvedPatch:\n authoritativeContainer === undefined\n ? mutationPatch\n : { ...mutationPatch, containerId: authoritativeContainer.containerId },\n securityContextMatches,\n };\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_DOCUMENT_KIND } from "../../data/documents/documentConstants.js";
|
|
2
|
+
import { prepareDocumentMutation, } from "./documentMutationPreparation.js";
|
|
2
3
|
/** Refuse a queued update after another subsystem deleted its canonical row. */
|
|
3
4
|
export async function refuseDeletedDocumentPersist(input) {
|
|
4
5
|
const { currentRecord } = input;
|
|
@@ -12,4 +13,27 @@ export async function refuseDeletedDocumentPersist(input) {
|
|
|
12
13
|
});
|
|
13
14
|
});
|
|
14
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* The preparation read doubles as the first look for a deleted row: only when
|
|
18
|
+
* it finds none does the guard open its own transaction, which reads again
|
|
19
|
+
* under the write lock before it refuses. A row it then finds (or an alias it
|
|
20
|
+
* must keep) is prepared afresh, as before the guard moved.
|
|
21
|
+
*/
|
|
22
|
+
export async function prepareDocumentMutationUnlessDeleted(input) {
|
|
23
|
+
const { lockedExecSql, persistInput } = input;
|
|
24
|
+
const prepare = () => prepareDocumentMutation(persistInput, lockedExecSql, input.patch);
|
|
25
|
+
const mutation = await prepare();
|
|
26
|
+
if (!input.guard ||
|
|
27
|
+
persistInput.currentRecord === null ||
|
|
28
|
+
mutation.durableCurrentRecord !== null)
|
|
29
|
+
return mutation;
|
|
30
|
+
const refused = await refuseDeletedDocumentPersist({
|
|
31
|
+
currentRecord: persistInput.currentRecord,
|
|
32
|
+
documentProjectors: input.documentProjectors,
|
|
33
|
+
execSql: lockedExecSql,
|
|
34
|
+
localId: persistInput.localId,
|
|
35
|
+
persistence: persistInput.persistence,
|
|
36
|
+
});
|
|
37
|
+
return refused ? null : prepare();
|
|
38
|
+
}
|
|
15
39
|
//# sourceMappingURL=documentPersistGuards.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documentPersistGuards.js","sourceRoot":"","sources":["documentPersistGuards.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;
|
|
1
|
+
{"version":3,"file":"documentPersistGuards.js","sourceRoot":"","sources":["documentPersistGuards.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAO/E,OAAO,EAEL,uBAAuB,GACxB,MAAM,+BAA+B,CAAC;AAEvC,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,KAMlD;IACC,MAAM,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC;IAChC,IAAI,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IACjC,OAAO,KAAK,CAAC,WAAW,CAAC,8BAA8B,CACrD,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,OAAO,EACb,aAAa,CAAC,UAAU,EACxB,KAAK,EAAE,kBAAkB,EAAE,EAAE;QAC3B,MAAM,KAAK,CAAC,kBAAkB,CAAC,oCAAoC,CAAC;YAClE,YAAY,EAAE,aAAa,CAAC,YAAY,IAAI,qBAAqB;YACjE,OAAO,EAAE,kBAAkB;YAC3B,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oCAAoC,CAAC,KAM1D;IACC,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;IAC9C,MAAM,OAAO,GAAG,GAAG,EAAE,CACnB,uBAAuB,CAAC,YAAY,EAAE,aAAa,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,MAAM,OAAO,EAAE,CAAC;IACjC,IACE,CAAC,KAAK,CAAC,KAAK;QACZ,YAAY,CAAC,aAAa,KAAK,IAAI;QACnC,QAAQ,CAAC,oBAAoB,KAAK,IAAI;QAEtC,OAAO,QAAQ,CAAC;IAClB,MAAM,OAAO,GAAG,MAAM,4BAA4B,CAAC;QACjD,aAAa,EAAE,YAAY,CAAC,aAAa;QACzC,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,OAAO,EAAE,aAAa;QACtB,OAAO,EAAE,YAAY,CAAC,OAAO;QAC7B,WAAW,EAAE,YAAY,CAAC,WAAW;KACtC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;AACpC,CAAC","sourcesContent":["import { DEFAULT_DOCUMENT_KIND } from \"../../data/documents/documentConstants\";\nimport type { DocumentProjectorRegistry } from \"../../data/documents/documentKinds\";\nimport type {\n DocumentsPersistence,\n StoredDocumentRecord,\n} from \"../../data/persistence/documents/documentsPersistence\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport {\n type PrepareDocumentMutationInput,\n prepareDocumentMutation,\n} from \"./documentMutationPreparation\";\n\n/** Refuse a queued update after another subsystem deleted its canonical row. */\nexport async function refuseDeletedDocumentPersist(input: {\n currentRecord: StoredDocumentRecord | null;\n documentProjectors: DocumentProjectorRegistry;\n execSql: ExecSql;\n localId: string;\n persistence: DocumentsPersistence;\n}): Promise<boolean> {\n const { currentRecord } = input;\n if (!currentRecord) return false;\n return input.persistence.deleteDocumentSideRowsIfAbsent(\n input.execSql,\n input.localId,\n currentRecord.documentId,\n async (transactionExecSql) => {\n await input.documentProjectors.deleteStoredDocumentClientProjection({\n documentKind: currentRecord.documentKind ?? DEFAULT_DOCUMENT_KIND,\n execSql: transactionExecSql,\n localId: input.localId,\n });\n },\n );\n}\n\n/**\n * The preparation read doubles as the first look for a deleted row: only when\n * it finds none does the guard open its own transaction, which reads again\n * under the write lock before it refuses. A row it then finds (or an alias it\n * must keep) is prepared afresh, as before the guard moved.\n */\nexport async function prepareDocumentMutationUnlessDeleted(input: {\n documentProjectors: DocumentProjectorRegistry;\n guard: boolean;\n lockedExecSql: ExecSql;\n patch: Partial<StoredDocumentRecord>;\n persistInput: PrepareDocumentMutationInput & { localId: string };\n}) {\n const { lockedExecSql, persistInput } = input;\n const prepare = () =>\n prepareDocumentMutation(persistInput, lockedExecSql, input.patch);\n const mutation = await prepare();\n if (\n !input.guard ||\n persistInput.currentRecord === null ||\n mutation.durableCurrentRecord !== null\n )\n return mutation;\n const refused = await refuseDeletedDocumentPersist({\n currentRecord: persistInput.currentRecord,\n documentProjectors: input.documentProjectors,\n execSql: lockedExecSql,\n localId: persistInput.localId,\n persistence: persistInput.persistence,\n });\n return refused ? null : prepare();\n}\n"]}
|