@ny4n/chord 0.0.0-stage → 1.0.1
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/LICENSE +21 -0
- package/README.md +261 -2
- package/dist/api.d.ts +20 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +77 -0
- package/dist/api.js.map +1 -0
- package/dist/bundler.d.ts +6 -0
- package/dist/bundler.d.ts.map +1 -0
- package/dist/bundler.js +3 -0
- package/dist/bundler.js.map +1 -0
- package/dist/context/index.d.ts +24 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +97 -0
- package/dist/context/index.js.map +1 -0
- package/dist/delta/apply-immutable-trusted.d.ts +4 -0
- package/dist/delta/apply-immutable-trusted.d.ts.map +1 -0
- package/dist/delta/apply-immutable-trusted.js +127 -0
- package/dist/delta/apply-immutable-trusted.js.map +1 -0
- package/dist/delta/core.d.ts +108 -0
- package/dist/delta/core.d.ts.map +1 -0
- package/dist/delta/core.js +645 -0
- package/dist/delta/core.js.map +1 -0
- package/dist/delta/diff.d.ts +5 -0
- package/dist/delta/diff.d.ts.map +1 -0
- package/dist/delta/diff.js +433 -0
- package/dist/delta/diff.js.map +1 -0
- package/dist/delta/draft.d.ts +5 -0
- package/dist/delta/draft.d.ts.map +1 -0
- package/dist/delta/draft.js +2 -0
- package/dist/delta/draft.js.map +1 -0
- package/dist/delta/index.d.ts +5 -0
- package/dist/delta/index.d.ts.map +1 -0
- package/dist/delta/index.js +6 -0
- package/dist/delta/index.js.map +1 -0
- package/dist/delta/revision-validator.d.ts +7 -0
- package/dist/delta/revision-validator.d.ts.map +1 -0
- package/dist/delta/revision-validator.js +71 -0
- package/dist/delta/revision-validator.js.map +1 -0
- package/dist/delta/tracker.d.ts +26 -0
- package/dist/delta/tracker.d.ts.map +1 -0
- package/dist/delta/tracker.js +2069 -0
- package/dist/delta/tracker.js.map +1 -0
- package/dist/facets/host.d.ts +12 -0
- package/dist/facets/host.d.ts.map +1 -0
- package/dist/facets/host.js +763 -0
- package/dist/facets/host.js.map +1 -0
- package/dist/facets/loader.d.ts +3 -0
- package/dist/facets/loader.d.ts.map +1 -0
- package/dist/facets/loader.js +5 -0
- package/dist/facets/loader.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +10 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +124 -0
- package/dist/json.js.map +1 -0
- package/dist/node/bundle-loader.d.ts +30 -0
- package/dist/node/bundle-loader.d.ts.map +1 -0
- package/dist/node/bundle-loader.js +377 -0
- package/dist/node/bundle-loader.js.map +1 -0
- package/dist/node/bundle.d.ts +26 -0
- package/dist/node/bundle.d.ts.map +1 -0
- package/dist/node/bundle.js +183 -0
- package/dist/node/bundle.js.map +1 -0
- package/dist/node/manifest.d.ts +36 -0
- package/dist/node/manifest.d.ts.map +1 -0
- package/dist/node/manifest.js +6 -0
- package/dist/node/manifest.js.map +1 -0
- package/dist/node/package.d.ts +15 -0
- package/dist/node/package.d.ts.map +1 -0
- package/dist/node/package.js +199 -0
- package/dist/node/package.js.map +1 -0
- package/dist/node.d.ts +5 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +3 -0
- package/dist/node.js.map +1 -0
- package/dist/services/consumer.d.ts +11 -0
- package/dist/services/consumer.d.ts.map +1 -0
- package/dist/services/consumer.js +585 -0
- package/dist/services/consumer.js.map +1 -0
- package/dist/services/errors.d.ts +8 -0
- package/dist/services/errors.d.ts.map +1 -0
- package/dist/services/errors.js +22 -0
- package/dist/services/errors.js.map +1 -0
- package/dist/services/handle.d.ts +15 -0
- package/dist/services/handle.d.ts.map +1 -0
- package/dist/services/handle.js +101 -0
- package/dist/services/handle.js.map +1 -0
- package/dist/services/instances.d.ts +26 -0
- package/dist/services/instances.d.ts.map +1 -0
- package/dist/services/instances.js +140 -0
- package/dist/services/instances.js.map +1 -0
- package/dist/services/loopback.d.ts +5 -0
- package/dist/services/loopback.d.ts.map +1 -0
- package/dist/services/loopback.js +15 -0
- package/dist/services/loopback.js.map +1 -0
- package/dist/services/provider.d.ts +37 -0
- package/dist/services/provider.d.ts.map +1 -0
- package/dist/services/provider.js +521 -0
- package/dist/services/provider.js.map +1 -0
- package/dist/services/state-codec.d.ts +15 -0
- package/dist/services/state-codec.d.ts.map +1 -0
- package/dist/services/state-codec.js +133 -0
- package/dist/services/state-codec.js.map +1 -0
- package/dist/services/state-internals.d.ts +13 -0
- package/dist/services/state-internals.d.ts.map +1 -0
- package/dist/services/state-internals.js +10 -0
- package/dist/services/state-internals.js.map +1 -0
- package/dist/services/state.d.ts +28 -0
- package/dist/services/state.d.ts.map +1 -0
- package/dist/services/state.js +397 -0
- package/dist/services/state.js.map +1 -0
- package/dist/services/wire.d.ts +63 -0
- package/dist/services/wire.d.ts.map +1 -0
- package/dist/services/wire.js +186 -0
- package/dist/services/wire.js.map +1 -0
- package/dist/types.d.ts +277 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +71 -5
- package/src/delta/README.md +191 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAEpE,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,YAAY,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAEpE,iEAAiE;AACjE,MAAM,WAAW,UAAU,CAAC,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,iGAAiG;IACjG,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;CACrC;AAED,+EAA+E;AAC/E,MAAM,WAAW,OAAO;IACvB,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,SAAS,CAAC;IAC9C,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;IAC5C,QAAQ,IAAI,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEtG,KAAK,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;AAE/C,iGAAiG;AACjG,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,SAAS,IAAI,GACtD,SAAS,GACT,OAAO,SAAS,CAAC,GAChB,SAAS,GACT,CAAC,SAAS,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GACzC,CAAC,GACD,CAAC,SAAS,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,GACjC,kBAAkB,CAAC,KAAK,CAAC,EAAE,GAC3B,CAAC,SAAS,MAAM,GACf;KAAG,IAAI,IAAI,MAAM,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;CAAE,GAClD,KAAK,CAAC;AAEb,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe,CAAC,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC;IAC9B;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC;IAClH,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,uBAAuB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACzG;AAED,MAAM,WAAW,sBAAsB,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,eAAe,CAAC,CAAC,CAAC;IACnF,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IAClE;;;OAGG;IACH,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;CAC1C;AAED,mFAAmF;AACnF,MAAM,WAAW,0BAA0B,CAAC,CAAC;IAC5C,+FAA+F;IAC/F,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,oGAAoG;IACpG,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,+BAA+B,CAAC,CAAC;IACjD,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,0BAA0B,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IACzE,+EAA+E;IAC/E,OAAO,IAAI,IAAI,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACvC,MAAM,IAAI,+BAA+B,CAAC,CAAC,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,4BAA4B;IAC5C,wGAAwG;IACxG,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC1C;AAED,uFAAuF;AACvF,MAAM,WAAW,uBAAuB,CAAC,CAAC,CAAE,SAAQ,eAAe,CAAC,CAAC,CAAC;IACrE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,6FAA6F;IAC7F,OAAO,IAAI,IAAI,CAAC;CAChB;AAED,OAAO,CAAC,MAAM,YAAY,EAAE,OAAO,MAAM,CAAC;AAE1C,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,OAAO,CAAC;AAEhD,kEAAkE;AAClE,MAAM,WAAW,OAAO,CAAC,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,oGAAoG;IACpG,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;CAC1C;AAED,mFAAmF;AACnF,KAAK,iBAAiB,GACnB,IAAI,GACJ,OAAO,GACP,MAAM,GACN,MAAM,GACN,SAAS,iBAAiB,EAAE,GAC5B;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAA;CAAE,CAAC;AAIjD,KAAK,eAAe,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,SAAS,IAAI,GAC5C,CAAC,GACD,OAAO,SAAS,CAAC,GAChB,KAAK,GACL,CAAC,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,GAC9B,KAAK,GACL,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAE7B,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;AAEnH,KAAK,oBAAoB,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GACtE,KAAK,GACL,CAAC,SAAS,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,GACjC,eAAe,CAAC,KAAK,CAAC,GACtB,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,GACtC,CAAC,GACD,CAAC,SAAS,MAAM,GACf;KAAG,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;CAAE,CAAC,MAAM,CAAC,CAAC,GAC9D,CAAC,CAAC;AAER,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,SAAS,eAAe,CAAC,MAAM,MAAM,CAAC,GAClE,eAAe,CAAC,MAAM,CAAC,SAAS,KAAK,GACpC,KAAK,GACL,yBAAyB,GAC1B,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,MAAM,KAAK,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,OAAO,CAAC,GACvE,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,SAAS,KAAK,GAC3C,OAAO,SAAS,IAAI,GACnB,KAAK,GACL,eAAe,CAAC,OAAO,CAAC,SAAS,KAAK,GACrC,KAAK,GACL,mCAAmC,GACrC,6BAA6B,GAC9B,kDAAkD,CAAC;AAEvD,KAAK,wBAAwB,CAAC,CAAC,IAAI;KACjC,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK,GAAG,IAAI;CAC9E,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX,MAAM,MAAM,qBAAqB,CAAC,CAAC,IAAI,wBAAwB,CAAC,CAAC,CAAC,SAAS,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC;AAE7F,MAAM,WAAW,cAAc,CAAC,CAAC;IAChC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,GAAG,MAAM,IAAI,CAAC;CAClD;AAED,MAAM,WAAW,cAAc;IAC9B,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC;IAC7G,sFAAsF;IACtF,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzC;AAED,MAAM,MAAM,qBAAqB,GAAG;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,CAAA;CAAE,CAAC;AAE7G,MAAM,MAAM,uBAAuB,GAAG;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,SAAS,qBAAqB,EAAE,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACzC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,uBAAuB,EAAE,CAAC;CACvD,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAC9B;IACA,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC;CAC3B;AACH,0GAA0G;GACxG;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,2BAA2B,CAAA;CAAE,GAC1E;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;CAAE,GAChC;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAA;CAAE,GACzE;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAA;CAAE,GACxE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAA;CAAE,CAAC;AAE1E,MAAM,MAAM,WAAW,GAAG;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,CAAC;CACpC,CAAC;AAEF,MAAM,WAAW,mBAAmB;IACnC,yGAAyG;IACzG,QAAQ,CAAC,QAAQ,EAAE,2BAA2B,CAAC;IAC/C,QAAQ,IAAI,IAAI,CAAC;IACjB,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAsB;IACtC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAC5E,SAAS,CACR,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,WAAW,EACjB,QAAQ,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,EACnE,OAAO,EAAE,OAAO,GACd,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,CAAC,QAAQ,EAAE,SAAS;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACtD,QAAQ,CAAC,SAAS,EAAE,sBAAsB,CAAC;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IAC3D,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,gBAAgB;IAChC,uFAAuF;IACvF,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC/B,mFAAmF;IACnF,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACvG,8EAA8E;IAC9E,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAClE,iGAAiG;IACjG,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IACvD;;;OAGG;IACH,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACzE,+DAA+D;IAC/D,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAChD,mFAAmF;IACnF,UAAU,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACvD,qCAAqC;IACrC,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACzD;AAED,MAAM,WAAW,KAAK;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,mBAAmB;IACnC,2FAA2F;IAC3F,QAAQ,CAAC,0BAA0B,EAAE,OAAO,CAAC;IAC7C,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,qBAAqB,EAAE,CAAC,CAAC;IACvE,IAAI,CAAC,OAAO,EAAE;QACb,QAAQ,CAAC,QAAQ,EAAE,SAAS;YAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QACtD,YAAY,IAAI,IAAI,CAAC;QACrB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;KAC5B,GAAG,cAAc,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAClC,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC1C;AAED,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;IACzC,oGAAoG;IACpG,MAAM,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAClC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;CAC9B"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Draft, Op } from \"./delta/index.ts\";\nimport type { RemoteServiceProvider } from \"./services/provider.ts\";\n\nexport type { RemoteServiceError } from \"./services/errors.ts\";\nexport type { RemoteServiceProvider } from \"./services/provider.ts\";\n\n/** Typed identity for one value carried by a {@link Context}. */\nexport interface ContextKey<T> {\n\treadonly token: symbol;\n\t/** Type-only marker that prevents keys with different value types from being interchangeable. */\n\treadonly valueType?: (value: T) => T;\n}\n\n/** Immutable invocation-scoped values passed explicitly through operations. */\nexport interface Context {\n\treadonly abortSignal: AbortSignal | undefined;\n\tvalue<T>(key: ContextKey<T>): T | undefined;\n\ttoString(): string;\n}\n\nexport type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue };\n\ntype IsAny<T> = 0 extends 1 & T ? true : false;\n\n/** Strict-JSON representation of an application data type. Unknown payloads become JsonValue. */\nexport type JsonRepresentation<T> = IsAny<T> extends true\n\t? JsonValue\n\t: unknown extends T\n\t\t? JsonValue\n\t\t: T extends null | boolean | number | string\n\t\t\t? T\n\t\t\t: T extends readonly (infer TItem)[]\n\t\t\t\t? JsonRepresentation<TItem>[]\n\t\t\t\t: T extends object\n\t\t\t\t\t? { [TKey in keyof T]: JsonRepresentation<T[TKey]> }\n\t\t\t\t\t: never;\n\nexport interface ReplicatedStateDelivery {\n\treadonly kind: \"hydrate\" | \"update\";\n\treadonly sequence: number;\n}\n\nexport interface ReplicatedState<T> {\n\t/**\n\t * Contract-immutable value, or undefined until hydration. It is not frozen and may share containers with an\n\t * in-process provider; consumers must not mutate it. Later updates do not mutate previously returned values.\n\t */\n\treadonly value: T | undefined;\n\t/**\n\t * Each subscription serializes callbacks, awaiting hydration before updates. Values are immutable and may\n\t * share unchanged revision data. At most 100 deliveries wait behind the running callback; overflow keeps\n\t * only the newest pending value/context/delivery, so update sequences may skip. Failures are reported in\n\t * isolation and delivery continues. Unsubscribe discards pending work without aborting or joining a callback.\n\t */\n\tsubscribe(listener: (value: T, context: Context, delivery: ReplicatedStateDelivery) => Promise<void>): () => void;\n\tsubscribe(listener: (value: T, context: Context, delivery: ReplicatedStateDelivery) => void): () => void;\n}\n\nexport interface MutableReplicatedState<T extends object> extends ReplicatedState<T> {\n\treadonly value: T;\n\t/**\n\t * Atomically publish one synchronous overlay mutation. Draft handles are unusable after the callback returns.\n\t * Values placed through the draft are cloned by value; assigning `undefined` to an object property deletes it.\n\t */\n\tchange(context: Context, mutate: (draft: Draft<T>) => void): void;\n\t/**\n\t * Atomically take immutable ownership of an alias-free strict-JSON replacement.\n\t * The caller must not mutate the transferred root after this call.\n\t */\n\treplace(context: Context, value: T): void;\n}\n\n/** One immutable authoritative revision committed after an attachment snapshot. */\nexport interface ReplicatedStateSourceFrame<T> {\n\t/** Monotonic source cursor. The first frame after a snapshot must be `snapshot.cursor + 1`. */\n\treadonly cursor: number;\n\t/** The exact immutable value produced by this commit. */\n\treadonly value: T;\n\t/** The exact immutable operation batch that produced `value` from the preceding source revision. */\n\treadonly ops: readonly Op[];\n\treadonly context: Context;\n}\n\nexport interface ReplicatedStateSourceAttachment<T> {\n\t/** Fixed immutable snapshot captured at the atomic attachment boundary. */\n\treadonly snapshot: { readonly value: T; readonly cursor: number };\n\t/**\n\t * Install the sole listener and synchronously drain every buffered frame in source commit order.\n\t * This method is single-use. After it begins, every new committed frame must also be delivered in order\n\t * until disposal, including commits made reentrantly while a prior frame is being delivered.\n\t */\n\tactivate(listener: (frame: ReplicatedStateSourceFrame<T>) => void): void;\n\t/** Stop delivery and release source resources. Disposal must be idempotent. */\n\tdispose(): void;\n}\n\n/**\n * An authoritative immutable revision source.\n *\n * `attach()` must synchronously and atomically capture one snapshot and register the returned attachment to buffer\n * every later committed frame. The snapshot must include every commit before that boundary; buffered frames must\n * include every commit after it, with no overlap or gap. Snapshot values, frame values, and operation batches are\n * immutable and remain valid after delivery. Chord only publishes these references; it never applies or re-diffs them.\n */\nexport interface ReplicatedStateSource<T> {\n\tattach(): ReplicatedStateSourceAttachment<T>;\n}\n\nexport interface ReplicatedStateSourceOptions {\n\t/** Receives source-contract and publication-listener failures without throwing them into the source. */\n\treadonly onError?: (error: Error) => void;\n}\n\n/** A synchronously hydrated publication-only state backed by one source attachment. */\nexport interface AttachedReplicatedState<T> extends ReplicatedState<T> {\n\treadonly value: T;\n\t/** Idempotently release the source attachment. The last published value remains readable. */\n\tdispose(): void;\n}\n\ndeclare const SERVICE_TYPE: unique symbol;\n\nexport type ServiceMode = \"singleton\" | \"keyed\";\n\n/** Stable identity for one shared TypeScript service contract. */\nexport interface Service<T> {\n\treadonly id: string;\n\t/** Process-local services accept unrestricted object contracts and are never published remotely. */\n\treadonly local: boolean;\n\treadonly [SERVICE_TYPE]?: (value: T) => T;\n}\n\n/** JSON with readonly containers, such as other packages' recursive JSON types. */\ntype ReadonlyJsonValue =\n\t| null\n\t| boolean\n\t| number\n\t| string\n\t| readonly ReadonlyJsonValue[]\n\t| { readonly [key: string]: ReadonlyJsonValue };\n\n// A type assignable to readonly JSON is valid as is. Walking a recursive JSON type instead, for example one with\n// readonly arrays, would never terminate.\ntype InvalidJsonPart<T> = IsAny<T> extends true\n\t? T\n\t: unknown extends T\n\t\t? never\n\t\t: [T] extends [ReadonlyJsonValue]\n\t\t\t? never\n\t\t\t: InvalidJsonStructure<T>;\n\ntype InvalidJsonProperty<T> = [Exclude<T, undefined>] extends [never] ? T : InvalidJsonPart<Exclude<T, undefined>>;\n\ntype InvalidJsonStructure<T> = T extends null | boolean | number | string\n\t? never\n\t: T extends readonly (infer TItem)[]\n\t\t? InvalidJsonPart<TItem>\n\t\t: T extends (...args: never[]) => unknown\n\t\t\t? T\n\t\t\t: T extends object\n\t\t\t\t? { [TKey in keyof T]-?: InvalidJsonProperty<T[TKey]> }[keyof T]\n\t\t\t\t: T;\n\ntype InvalidRemoteMember<T> = T extends ReplicatedState<infer TValue>\n\t? InvalidJsonPart<TValue> extends never\n\t\t? never\n\t\t: \"state value is not JSON\"\n\t: T extends (...args: [...infer TArgs, Context]) => Promise<infer TResult>\n\t\t? InvalidJsonPart<TArgs[number]> extends never\n\t\t\t? TResult extends void\n\t\t\t\t? never\n\t\t\t\t: InvalidJsonPart<TResult> extends never\n\t\t\t\t\t? never\n\t\t\t\t\t: \"method result is not JSON or void\"\n\t\t\t: \"method argument is not JSON\"\n\t\t: \"member is not a remote method or ReplicatedState\";\n\ntype InvalidRemoteMemberNames<T> = {\n\t[TKey in keyof T]-?: InvalidRemoteMember<T[TKey]> extends never ? never : TKey;\n}[keyof T];\n\nexport type RemoteServiceContract<T> = InvalidRemoteMemberNames<T> extends never ? T : never;\n\nexport interface ServiceSpawner<T> {\n\tspawn(key: string, implementation: T): () => void;\n}\n\nexport interface RemoteServices {\n\tuse<T>(service: Service<T>): T;\n\tobserve<T>(service: Service<T>, handler: (service: T, context: Context) => void | Promise<void>): () => void;\n\t/** Wait until every currently acquired service has installed its initial snapshot. */\n\tready(context: Context): Promise<void>;\n\tdispose(context: Context): Promise<void>;\n}\n\nexport type ServiceCatalogueEntry = {\n\treadonly serviceId: string;\n\treadonly mode: ServiceMode;\n};\n\nexport type ServiceInstanceAddress = {\n\treadonly key: string;\n\treadonly generation: number;\n};\n\nexport type ServiceMemberSnapshot =\n\t| { readonly name: string; readonly kind: \"method\" }\n\t| { readonly name: string; readonly kind: \"state\"; readonly sequence: number; readonly ops: readonly Op[] };\n\nexport type ServiceInstanceSnapshot = {\n\treadonly instance?: ServiceInstanceAddress;\n\treadonly members: readonly ServiceMemberSnapshot[];\n};\n\nexport type ServiceSubscriptionSnapshot = {\n\treadonly serviceId: string;\n\treadonly mode: ServiceMode;\n\treadonly instances: readonly ServiceInstanceSnapshot[];\n};\n\nexport type ServiceProviderUpdate =\n\t| {\n\t\t\treadonly type: \"state\";\n\t\t\treadonly instance?: ServiceInstanceAddress;\n\t\t\treadonly member: string;\n\t\t\treadonly sequence: number;\n\t\t\treadonly ops: readonly Op[];\n\t }\n\t/** Full subscription rebaseline after overflow; every state is a root replacement at its new sequence. */\n\t| { readonly type: \"reset\"; readonly snapshot: ServiceSubscriptionSnapshot }\n\t| { readonly type: \"unavailable\" }\n\t| { readonly type: \"replaced\"; readonly snapshot: ServiceInstanceSnapshot }\n\t| { readonly type: \"spawned\"; readonly instance: ServiceInstanceSnapshot }\n\t| { readonly type: \"closed\"; readonly instance: ServiceInstanceAddress };\n\nexport type ServiceCall = {\n\treadonly serviceId: string;\n\treadonly instance?: ServiceInstanceAddress;\n\treadonly member: string;\n\t/** Borrowed immutable values. Chord validates but does not clone them. */\n\treadonly args: readonly JsonValue[];\n};\n\nexport interface ServiceSubscription {\n\t/** Atomic baseline. Later updates buffer until activation, with a full reset on pending delivery 101. */\n\treadonly snapshot: ServiceSubscriptionSnapshot;\n\tactivate(): void;\n\tclose(context?: Context): void | Promise<void>;\n}\n\n/**\n * Pluggable wire boundary consumed by a remote service binding.\n *\n * Implementations choose transport, framing, routing, and envelope encoding. Values crossing this\n * boundary must remain strict JSON. Chord does not clone values or require a particular application wire protocol;\n * adapters own serialization and any isolation copies they require.\n *\n */\nexport interface RemoteServiceTransport {\n\tinvoke(call: ServiceCall, context: Context): Promise<JsonValue | undefined>;\n\tsubscribe(\n\t\tserviceId: string,\n\t\tmode: ServiceMode,\n\t\tlistener: (update: ServiceProviderUpdate, context: Context) => void,\n\t\tcontext: Context,\n\t): Promise<ServiceSubscription>;\n}\n\nexport interface RemoteServiceBindingOptions {\n\treadonly services: readonly { readonly id: string }[];\n\treadonly transport: RemoteServiceTransport;\n\treadonly bound?: boolean;\n\treadonly onError?: (error: Error) => void;\n\treadonly assertAccess?: () => void;\n}\n\nexport interface RemoteServiceBinding extends RemoteServices {\n\trebind(bound: boolean, context: Context): Promise<void>;\n}\n\nexport interface FacetEnvironment {\n\t/** Declare a hard dependency on one singleton service and return its stable handle. */\n\tuse<T>(service: Service<T>): T;\n\t/** Declare a hard dependency on a keyed service and observe each live instance. */\n\tobserve<T>(service: Service<T>, handler: (service: T, context: Context) => void | Promise<void>): void;\n\t/** Declare and install this facet's singleton implementation of a service. */\n\tprovide<T>(service: Service<T>, implementation: NoInfer<T>): void;\n\t/** Declare ownership of a multi-instance service and return its deferred spawning capability. */\n\tprovideMany<T>(service: Service<T>): ServiceSpawner<T>;\n\t/**\n\t * Create initialized mutable state by taking immutable ownership of an alias-free strict-JSON root.\n\t * The caller must not mutate `initial` after this call.\n\t */\n\treplicatedState<T extends object>(initial: T): MutableReplicatedState<T>;\n\t/** Give the facet ownership of a resource cleanup function. */\n\town(disposal: () => void | Promise<void>): void;\n\t/** Register asynchronous initialization after dependencies are bound and ready. */\n\tonActivate(callback: () => void | Promise<void>): void;\n\t/** Register final facet teardown. */\n\tonDeactivate(callback: () => void | Promise<void>): void;\n}\n\nexport interface Facet {\n\treadonly id: string;\n\tsetup(env: FacetEnvironment): void;\n}\n\nexport interface RemoteServiceSource {\n\t/** Whether this currently unavailable source may provisionally own absent requirements. */\n\treadonly acceptsUnavailableServices: boolean;\n\tcatalogue(context: Context): Promise<readonly ServiceCatalogueEntry[]>;\n\topen(options: {\n\t\treadonly services: readonly { readonly id: string }[];\n\t\tassertAccess(): void;\n\t\tonError(error: Error): void;\n\t}): RemoteServices;\n}\n\nexport interface FacetOptions {\n\treadonly facets: readonly Facet[];\n\treadonly serviceSources?: readonly RemoteServiceSource[];\n\treadonly onError?: (error: Error) => void;\n}\n\nexport interface FacetHost {\n\treadonly services: RemoteServiceProvider;\n\t/** Activate and replace facets with matching IDs without disconnecting consumer service handles. */\n\treload(facets: readonly Facet[]): Promise<void>;\n\tdispose(): Promise<void>;\n}\n\nexport interface LoadedFacets {\n\treadonly facets: readonly Facet[];\n\tdispose(): Promise<void>;\n}\n\nexport interface FacetLoader {\n\tload(): Promise<LoadedFacets>;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,72 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"name": "@ny4n/chord",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Application composition runtime for services, replicated state, RPC, and plugins",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"source": "./src/index.ts",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./context": {
|
|
15
|
+
"source": "./src/context/index.ts",
|
|
16
|
+
"types": "./dist/context/index.d.ts",
|
|
17
|
+
"import": "./dist/context/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./delta": {
|
|
20
|
+
"source": "./src/delta/index.ts",
|
|
21
|
+
"types": "./dist/delta/index.d.ts",
|
|
22
|
+
"import": "./dist/delta/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./bundler": {
|
|
25
|
+
"source": "./src/bundler.ts",
|
|
26
|
+
"types": "./dist/bundler.d.ts",
|
|
27
|
+
"import": "./dist/bundler.js"
|
|
28
|
+
},
|
|
29
|
+
"./node": {
|
|
30
|
+
"source": "./src/node.ts",
|
|
31
|
+
"types": "./dist/node.d.ts",
|
|
32
|
+
"import": "./dist/node.js"
|
|
33
|
+
},
|
|
34
|
+
"./package.json": "./package.json"
|
|
35
|
+
},
|
|
36
|
+
"sideEffects": false,
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"README.md",
|
|
40
|
+
"src/delta/README.md"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"clean": "shx rm -rf dist",
|
|
44
|
+
"build": "tsc -p tsconfig.build.json",
|
|
45
|
+
"test": "vitest --run",
|
|
46
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
47
|
+
},
|
|
48
|
+
"keywords": [
|
|
49
|
+
"application",
|
|
50
|
+
"plugins",
|
|
51
|
+
"rpc",
|
|
52
|
+
"services",
|
|
53
|
+
"state"
|
|
54
|
+
],
|
|
55
|
+
"author": "Nyan",
|
|
56
|
+
"license": "MIT",
|
|
57
|
+
"repository": {
|
|
58
|
+
"type": "git",
|
|
59
|
+
"url": "git+https://github.com/blxzer77/nyan.git",
|
|
60
|
+
"directory": "packages/chord"
|
|
61
|
+
},
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=22.19.0"
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"esbuild": "0.28.2"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"shx": "0.3.4",
|
|
70
|
+
"vitest": "4.1.11"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Chord Delta
|
|
2
|
+
|
|
3
|
+
Chord Delta produces immutable JSON revisions and exact operation batches for
|
|
4
|
+
ordered replicas. Import it from `@ny4n/chord/delta`.
|
|
5
|
+
|
|
6
|
+
Immutability is an ownership contract. Nothing is frozen or defensively copied,
|
|
7
|
+
so an illegal mutation is not detected. It silently corrupts state.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { applyImmutable, applyImmutableBatches, track } from "@ny4n/chord/delta";
|
|
11
|
+
|
|
12
|
+
const initial = { output: "", entries: [] as { id: number }[] };
|
|
13
|
+
const tracker = track(initial); // `initial` is transferred: never mutate it again
|
|
14
|
+
|
|
15
|
+
const change = tracker.beginChange();
|
|
16
|
+
change.state.output += "done\n"; // the draft is mutable only while the change is open
|
|
17
|
+
change.state.entries.push({ id: 1 }); // placed values are cloned; the caller keeps its object
|
|
18
|
+
const prepared = change.prepare(); // draft handles are unusable from here on
|
|
19
|
+
|
|
20
|
+
// tracker.value, prepared.base, prepared.value, and prepared.ops (including paths
|
|
21
|
+
// and payloads) are immutable by contract.
|
|
22
|
+
tracker.adopt(prepared); // tracker.value === prepared.value
|
|
23
|
+
|
|
24
|
+
// Shares containers with prepared.base and the op payloads: never mutate it either.
|
|
25
|
+
const replica = applyImmutable(prepared.base, prepared.ops);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Mutation rights
|
|
29
|
+
|
|
30
|
+
| Value | May it be mutated? |
|
|
31
|
+
| --- | --- |
|
|
32
|
+
| Root passed to `track()`, `prepareReplace()`, `replicatedState()`, or `replace()` | No. Ownership moved to the tracker. |
|
|
33
|
+
| `change.state` and handles read from it | Yes, only while that change is open. After `prepare()`, `abort()`, or another adoption, every use throws. Writes through a handle whose element was removed from the draft are ignored. |
|
|
34
|
+
| External value after assigning or inserting it into a draft | Yes. The draft stored a validated clone. |
|
|
35
|
+
| `tracker.value`, `prepared.base`, retained older revisions | No. |
|
|
36
|
+
| `prepared.value`, `prepared.ops`, op tuples, paths, permutations, payloads | No. Payloads may be the same objects as parts of `prepared.value`. |
|
|
37
|
+
| `applyImmutable()` / `applyImmutableBatches()` inputs and result | No. The result shares containers with both inputs. |
|
|
38
|
+
| Values from replicated state (`value`, listener values, loopback consumers) | No. In-process consumers may share the provider's containers. |
|
|
39
|
+
| Mutable replica passed to `apply()` | Only through `apply()`, with batches it owns exclusively. Code that edits it between batches breaks convergence. |
|
|
40
|
+
| Batch passed to `apply()` | Consumed. `apply()` adopts payload containers into the replica. Use a detached copy for exactly one replica and never touch it again. |
|
|
41
|
+
|
|
42
|
+
## Replaying batches
|
|
43
|
+
|
|
44
|
+
Immutable replay is the preferred in-process path. One batch can fan out to any
|
|
45
|
+
number of immutable replicas:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
let replica = tracker.value; // shared with authority; never mutated
|
|
49
|
+
// For each adopted batch, in order:
|
|
50
|
+
replica = applyImmutable(replica, prepared.ops); // replica must equal prepared.base
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
When only the final result of an ordered backlog is needed, replay its batches
|
|
54
|
+
without concatenating their operations. One copy-on-write scope is shared across
|
|
55
|
+
the complete call, so no intermediate revision is exposed or safe to retain:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
replica = applyImmutableBatches(
|
|
59
|
+
replica,
|
|
60
|
+
queuedFrames.map((frame) => frame.ops),
|
|
61
|
+
);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Use separate `applyImmutable()` calls when every intermediate revision is
|
|
65
|
+
published or retained.
|
|
66
|
+
|
|
67
|
+
Mutable replay needs a detached starting root and a detached copy of every batch
|
|
68
|
+
for every replica. Never apply one in-memory batch to two mutable replicas:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { apply } from "@ny4n/chord/delta";
|
|
72
|
+
|
|
73
|
+
const detach = <T>(value: T): T => JSON.parse(JSON.stringify(value)) as T;
|
|
74
|
+
|
|
75
|
+
let replica = detach(tracker.value); // exclusively owned starting root
|
|
76
|
+
// For each adopted batch, in order:
|
|
77
|
+
replica = apply(replica, detach(prepared.ops)); // fresh copy for this replica only
|
|
78
|
+
// Only apply() may change `replica`; do not edit it in application code.
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Parsing a separately serialized message per replica is also a valid detachment.
|
|
82
|
+
`decode()` does not copy payloads, so decoding one in-memory `WireOp[]` for two
|
|
83
|
+
mutable replicas makes them alias each other.
|
|
84
|
+
|
|
85
|
+
## Do and don't
|
|
86
|
+
|
|
87
|
+
- Do build a fresh root and then transfer it; validate untrusted roots at your ingestion boundary.
|
|
88
|
+
- Do keep structural sharing between revisions, for example `replace(ctx, { ...state.value, changed })`.
|
|
89
|
+
- Do clone or serialize before handing any published value to code that may mutate it.
|
|
90
|
+
- Do settle every change with `prepare()` or `abort()`.
|
|
91
|
+
- Don't reuse one container at two places in a transferred root.
|
|
92
|
+
- Don't mutate anything the tracker owns, published, or received from a batch.
|
|
93
|
+
- Don't keep draft handles past their change or place a settled handle.
|
|
94
|
+
- Don't infer meaning from op shape. Only the resulting value is contractual.
|
|
95
|
+
|
|
96
|
+
## Roots and placements
|
|
97
|
+
|
|
98
|
+
Full roots are trusted. `track()` and `prepareReplace()` take ownership in O(1)
|
|
99
|
+
and never walk the tree. Roots must be alias-free, acyclic strict JSON: dense
|
|
100
|
+
plain arrays, plain or null-prototype objects with enumerable own data
|
|
101
|
+
properties, strings, booleans, finite numbers, and `null`. Violations have
|
|
102
|
+
unspecified behavior. For example, a container shared by two keys can make
|
|
103
|
+
`prepared.value` diverge from what replicas compute from `prepared.ops`.
|
|
104
|
+
|
|
105
|
+
Draft placements are copied, and that copy walk also validates. Placements come
|
|
106
|
+
from property writes, index writes, `push`, `unshift`, `splice`, `fill`, and
|
|
107
|
+
`copyWithin`. A non-strict value throws `TypeError` before the draft changes;
|
|
108
|
+
for example, `push(valid, invalid)` inserts nothing. Rejected values include:
|
|
109
|
+
cycles, accessors (never invoked), symbol keys, class instances, sparse or
|
|
110
|
+
non-plain arrays, functions, bigint, `NaN`, infinities, and `undefined`.
|
|
111
|
+
Null-prototype objects are accepted and preserved. Placing a draft handle clones
|
|
112
|
+
its current content. Placing one value at several paths yields independent
|
|
113
|
+
containers.
|
|
114
|
+
|
|
115
|
+
`undefined` rules:
|
|
116
|
+
|
|
117
|
+
- `draft.obj.key = undefined` deletes `key`.
|
|
118
|
+
- `arr[i] = undefined`, `push(undefined)`, `unshift`, `splice`, and `fill` with `undefined` throw.
|
|
119
|
+
- `undefined` nested anywhere inside a placed object or array throws. It is not dropped like `JSON.stringify` does.
|
|
120
|
+
|
|
121
|
+
Arrays stay dense. Writing past the next index and deleting an element throw.
|
|
122
|
+
Growing `length` inserts `null`; shrinking it removes elements.
|
|
123
|
+
|
|
124
|
+
## Lifecycle
|
|
125
|
+
|
|
126
|
+
`tracker.value` is the latest adopted revision. `beginChange()` opens an overlay
|
|
127
|
+
draft over it and never modifies it. A draft may stay open across `await`.
|
|
128
|
+
`prepare()` materializes the candidate and ops and does not change authority.
|
|
129
|
+
`adopt()` checks the preparation and swaps the root pointer.
|
|
130
|
+
|
|
131
|
+
Several changes may be open or prepared from one revision. Adopting one makes all
|
|
132
|
+
others stale: open drafts become unusable and their `prepare()` throws, and
|
|
133
|
+
prepared competitors are rejected by `adopt()`. `adopt()` also rejects foreign,
|
|
134
|
+
aborted, and already consumed preparations. `Change.abort()` or
|
|
135
|
+
`Prepared.abort()` after `prepare()` prevents adoption. The candidate stays
|
|
136
|
+
readable.
|
|
137
|
+
|
|
138
|
+
No-op batches:
|
|
139
|
+
|
|
140
|
+
- Empty `ops` means `prepared.value === prepared.base`. Writes restored to their original value and deeply equal container assignments usually normalize to empty.
|
|
141
|
+
- Equality ignores key order and prototype. A deeply equal assignment keeps the previous revision's order and prototype, even if the draft showed the new ones.
|
|
142
|
+
- Structural array edits may emit a nonempty exact batch even when the result is deeply equal.
|
|
143
|
+
- Adopting a no-op still advances `tracker.revision` and stales competitors. Replicated state does not publish no-ops.
|
|
144
|
+
|
|
145
|
+
`prepareReplace(value)` is a whole-root operation, not a diff. If `value` is
|
|
146
|
+
deeply equal to the current root, `ops` is empty and the current root is kept
|
|
147
|
+
(the comparison may traverse both trees). Otherwise `ops` is `[["r", value]]`
|
|
148
|
+
and `prepared.value === value`, so replicas receive the complete root.
|
|
149
|
+
|
|
150
|
+
Array mutators: `push`, `pop`, `shift`, `unshift`, `splice`, `reverse`, `sort`,
|
|
151
|
+
`fill`, and `copyWithin`. Held handles follow elements through reindexing.
|
|
152
|
+
|
|
153
|
+
## Operations
|
|
154
|
+
|
|
155
|
+
Paths contain object keys and non-negative integer array indices.
|
|
156
|
+
|
|
157
|
+
| Tuple | Meaning |
|
|
158
|
+
| --- | --- |
|
|
159
|
+
| `["r", value]` | Replace the complete value. |
|
|
160
|
+
| `["s", path, value]` | Set an object property or array element. |
|
|
161
|
+
| `["d", path]` | Delete an object property or remove an array element. |
|
|
162
|
+
| `["a", path, text]` | Append to a string. |
|
|
163
|
+
| `["t", path, count]` | Remove `count` UTF-16 code units from a string's front. |
|
|
164
|
+
| `["p", path, index, remove, items]` | Splice an array. |
|
|
165
|
+
| `["m", path, permutation]` | Reorder an array: `new[i] = old[permutation[i]]`. |
|
|
166
|
+
|
|
167
|
+
Batches are exact but not canonical. The same change may use different tuples,
|
|
168
|
+
and large edit sets may fold into a region splice, an ancestor `s`, or `r`.
|
|
169
|
+
|
|
170
|
+
Reserved keys: the tracker never emits `__proto__`, `constructor`, or
|
|
171
|
+
`prototype` as a path segment. A mutation at or below such a key is folded into a
|
|
172
|
+
set of the nearest safe ancestor, or `r` at the root. `apply()`, `applyImmutable()`, `applyImmutableBatches()`, and `decoder()` reject
|
|
173
|
+
those segments with `UnsafePathError`.
|
|
174
|
+
The appliers write values as own data properties, never through a prototype setter.
|
|
175
|
+
Appliers check op shape and path safety but not payload strictness. Chord's
|
|
176
|
+
replicated-state replicas validate each resulting revision.
|
|
177
|
+
|
|
178
|
+
`encoder()` interns repeated paths into `WireOp` tuples; `decoder()` validates
|
|
179
|
+
and restores `Op` tuples. Use one encoder/decoder pair per ordered state stream.
|
|
180
|
+
Path IDs span batches and an `r` resets both dictionaries. After a decode or
|
|
181
|
+
apply error, discard the decoder and replica and recover from a later `r`.
|
|
182
|
+
|
|
183
|
+
## Limits and footguns
|
|
184
|
+
|
|
185
|
+
- No freezing. Mutating any immutable value corrupts state silently.
|
|
186
|
+
- Loopback sharing: in-process service consumers may receive the provider's containers. A consumer mutation corrupts authority and makes remote replicas diverge.
|
|
187
|
+
- A change inside a large flat array copies that array's pointer storage for the new revision.
|
|
188
|
+
- Placement validation costs time and memory on bulk inserts. In a benchmark unshifting 100k three-field objects, it added about 19 ms and 20 MiB of transient heap.
|
|
189
|
+
- External proxies as placements, argument coercion callbacks that mutate the draft, non-primitive array indices, and non-numeric comparator results are out of contract. So are sort comparators that mutate, prepare, abort, or adopt. Behavior is unspecified.
|
|
190
|
+
- Object identity is not replicated. Each path is an independent value placement.
|
|
191
|
+
- One tracker is one revision sequence. Delivery order and persistence belong to the surrounding protocol.
|