@earendil-works/chord 0.87.0 → 0.99.0
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/README.md +80 -27
- package/dist/api.d.ts +6 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +8 -3
- package/dist/api.js.map +1 -1
- package/dist/bundler.d.ts.map +1 -1
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js.map +1 -1
- 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/{state → delta}/diff.d.ts +1 -1
- 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 +11 -21
- package/dist/delta/index.d.ts.map +1 -1
- package/dist/delta/index.js +43 -1341
- package/dist/delta/index.js.map +1 -1
- 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.map +1 -1
- package/dist/facets/host.js.map +1 -1
- package/dist/facets/loader.d.ts.map +1 -1
- package/dist/facets/loader.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/json.d.ts +6 -0
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +73 -6
- package/dist/json.js.map +1 -1
- package/dist/node/bundle-loader.d.ts.map +1 -1
- package/dist/node/bundle-loader.js.map +1 -1
- package/dist/node/bundle.d.ts.map +1 -1
- package/dist/node/bundle.js.map +1 -1
- package/dist/node/manifest.d.ts.map +1 -1
- package/dist/node/package.d.ts.map +1 -1
- package/dist/node/package.js.map +1 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/services/consumer.d.ts.map +1 -1
- package/dist/services/consumer.js +49 -1
- package/dist/services/consumer.js.map +1 -1
- package/dist/services/errors.d.ts.map +1 -1
- package/dist/services/errors.js.map +1 -1
- package/dist/services/handle.d.ts.map +1 -1
- package/dist/services/handle.js +3 -1
- package/dist/services/handle.js.map +1 -1
- package/dist/services/instances.d.ts +1 -0
- package/dist/services/instances.d.ts.map +1 -1
- package/dist/services/instances.js +3 -0
- package/dist/services/instances.js.map +1 -1
- package/dist/services/loopback.d.ts.map +1 -1
- package/dist/services/loopback.js.map +1 -1
- package/dist/services/provider.d.ts.map +1 -1
- package/dist/services/provider.js +48 -29
- package/dist/services/provider.js.map +1 -1
- package/dist/services/state-codec.d.ts.map +1 -1
- package/dist/services/state-codec.js +18 -0
- package/dist/services/state-codec.js.map +1 -1
- package/dist/services/state-internals.d.ts +5 -2
- package/dist/services/state-internals.d.ts.map +1 -1
- package/dist/services/state-internals.js.map +1 -1
- package/dist/services/state.d.ts +8 -3
- package/dist/services/state.d.ts.map +1 -1
- package/dist/services/state.js +288 -88
- package/dist/services/state.js.map +1 -1
- package/dist/services/wire.d.ts +3 -0
- package/dist/services/wire.d.ts.map +1 -1
- package/dist/services/wire.js +13 -0
- package/dist/services/wire.js.map +1 -1
- package/dist/types.d.ts +74 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
- package/src/delta/README.md +143 -360
- package/dist/state/diff.d.ts.map +0 -1
- package/dist/state/diff.js +0 -259
- package/dist/state/diff.js.map +0 -1
- package/dist/state/draft.d.ts +0 -13
- package/dist/state/draft.d.ts.map +0 -1
- package/dist/state/draft.js +0 -540
- package/dist/state/draft.js.map +0 -1
- package/dist/state/value.d.ts +0 -9
- package/dist/state/value.d.ts.map +0 -1
- package/dist/state/value.js +0 -175
- package/dist/state/value.js.map +0 -1
package/README.md
CHANGED
|
@@ -32,12 +32,12 @@ The design has a few connected pieces:
|
|
|
32
32
|
stable facade while a provider disconnects or is replaced.
|
|
33
33
|
|
|
34
34
|
- **Replicated state** exposes authoritative state to local and remote
|
|
35
|
-
connected consumers. Producers publish atomic
|
|
35
|
+
connected consumers. Producers publish atomic overlay transactions with
|
|
36
36
|
`change(context, callback)`; consumers receive complete immutable values. Draft
|
|
37
|
-
proxies exist only during the callback and
|
|
38
|
-
|
|
39
|
-
while each remote client/state stream owns independent path-codec
|
|
40
|
-
become unready on disconnect or replacement until
|
|
37
|
+
proxies exist only during the callback and become unusable afterward. Preparation
|
|
38
|
+
materializes a structurally shared immutable candidate and one exact decoded
|
|
39
|
+
operation batch, while each remote client/state stream owns independent path-codec
|
|
40
|
+
state. Replicas become unready on disconnect or replacement until rehydrated.
|
|
41
41
|
|
|
42
42
|
- **Delta tracking** records and coalesces operations over tracked plain JSON.
|
|
43
43
|
It preserves common string and array operations, supports durable base
|
|
@@ -87,28 +87,60 @@ close, or fresh hydration. Applications may place these values inside any
|
|
|
87
87
|
routing, request, response, or event envelope; Chord does not prescribe that
|
|
88
88
|
outer protocol.
|
|
89
89
|
|
|
90
|
+
Provider subscriptions atomically capture a snapshot and buffer subsequent
|
|
91
|
+
updates until activation. Activation and reentrant publication use the same FIFO.
|
|
92
|
+
The provider retains at most 100 pending updates per subscription, excluding the
|
|
93
|
+
running delivery. Adding update 101 replaces the entire pending queue with
|
|
94
|
+
`{ type: "reset", snapshot }`: a current full subscription snapshot whose state
|
|
95
|
+
members contain `[["r", value]]` and their new sequence baselines. It also captures
|
|
96
|
+
current instance membership, so discarded spawn/close/replacement events cannot
|
|
97
|
+
leave stale instances behind. Live keyed generations retain their existing handles.
|
|
98
|
+
The reset carries the context of the publication that triggered overflow.
|
|
99
|
+
|
|
100
|
+
Consumers and codecs must handle this explicit reset before accepting subsequent
|
|
101
|
+
ordinary deltas. A root operation in an ordinary `state` update does **not** permit
|
|
102
|
+
a sequence gap. Resets restart the subscription's path dictionaries, and later
|
|
103
|
+
deltas must be contiguous from each reset baseline. Transport adapters must
|
|
104
|
+
preserve snapshot/reset/update order; they must not drop encoded delta batches or
|
|
105
|
+
assume their own asynchronous queues are bounded by the provider's queue.
|
|
106
|
+
|
|
90
107
|
## Tracking JSON deltas
|
|
91
108
|
|
|
92
|
-
Import the standalone
|
|
109
|
+
Import the standalone transactional tracker from `@earendil-works/chord/delta`:
|
|
93
110
|
|
|
94
111
|
```ts
|
|
95
|
-
import {
|
|
112
|
+
import { applyImmutable, track } from "@earendil-works/chord/delta";
|
|
96
113
|
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
114
|
+
const tracker = track({ output: "", count: 0 });
|
|
115
|
+
const change = tracker.beginChange();
|
|
116
|
+
change.state.output += "done\n";
|
|
117
|
+
change.state.count += 1;
|
|
118
|
+
const prepared = change.prepare();
|
|
101
119
|
|
|
102
|
-
|
|
103
|
-
const replica =
|
|
120
|
+
tracker.adopt(prepared);
|
|
121
|
+
const replica = applyImmutable(prepared.base, prepared.ops);
|
|
104
122
|
```
|
|
105
123
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
124
|
+
`tracker.value` is always the latest adopted immutable revision. Preparation does
|
|
125
|
+
not change authority; adoption validates the preparation and swaps the root pointer.
|
|
126
|
+
Assigned containers are copied by value and unchanged subtrees may be shared between
|
|
127
|
+
revisions.
|
|
128
|
+
|
|
129
|
+
The tracker uses trusted immutable ownership rather than defensive copying or
|
|
130
|
+
freezing. `track(initial)`, `prepareReplace(value)`, `replicatedState(initial)`, and
|
|
131
|
+
`replace(context, value)` take ownership of alias-free strict-JSON roots without
|
|
132
|
+
walking them. Callers must not mutate transferred or published data. Values placed
|
|
133
|
+
through drafts are already copied, so that walk also rejects non-strict JSON before
|
|
134
|
+
the draft changes. Published values are not frozen. In-process loopback consumers
|
|
135
|
+
may share their containers with the provider; mutating a consumed value violates
|
|
136
|
+
the contract and can corrupt authority. Clone or serialize at any mutable trust
|
|
137
|
+
boundary.
|
|
138
|
+
|
|
139
|
+
Replicated state provides the same model through a callback:
|
|
109
140
|
|
|
110
141
|
```ts
|
|
111
|
-
const
|
|
142
|
+
const initial = { output: "", count: 0 };
|
|
143
|
+
const status = env.replicatedState(initial); // transfers ownership of initial
|
|
112
144
|
status.change(context, (draft) => {
|
|
113
145
|
draft.output += "done\n";
|
|
114
146
|
draft.count += 1;
|
|
@@ -116,16 +148,37 @@ status.change(context, (draft) => {
|
|
|
116
148
|
```
|
|
117
149
|
|
|
118
150
|
A successful `change()` publishes exactly one atomic revision. If its callback
|
|
119
|
-
throws, the original value and sequence remain unchanged. Draft handles
|
|
120
|
-
when the callback returns
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
151
|
+
throws, the original value and sequence remain unchanged. Draft handles become
|
|
152
|
+
unusable when the callback returns. Chord emits string append and front-truncate
|
|
153
|
+
operations, array splices and permutations, sets, and deletes; large edit sets may
|
|
154
|
+
fold into a complete replacement. Remote connection plumbing encodes each batch
|
|
155
|
+
independently for every client/state pairing.
|
|
156
|
+
|
|
157
|
+
### Public state subscriptions
|
|
158
|
+
|
|
159
|
+
`state.subscribe(async (value, context, delivery) => { ... })` serializes callbacks
|
|
160
|
+
independently for each subscription. Hydration starts immediately when a value is
|
|
161
|
+
available, and its returned promise must settle before updates start. Synchronous
|
|
162
|
+
callbacks still run synchronously. Read the captured `value` inside an asynchronous
|
|
163
|
+
callback: `state.value` may already refer to a later revision.
|
|
164
|
+
|
|
165
|
+
Each subscription retains at most 100 pending complete-value deliveries, excluding
|
|
166
|
+
the running callback. On overflow, only the newest pending value, context, and
|
|
167
|
+
delivery metadata are retained; a not-yet-started initial hydration is preserved.
|
|
168
|
+
Thus public delivery sequences may skip. This is a frame-count policy, not a byte
|
|
169
|
+
limit. Internal exact-operation subscriptions remain synchronous and receive every
|
|
170
|
+
revision, independently of slow public callbacks.
|
|
171
|
+
|
|
172
|
+
The returned unsubscribe function immediately discards pending work and prevents
|
|
173
|
+
new callbacks. It neither aborts nor waits for the running callback. Synchronous
|
|
174
|
+
throws and promise rejections are observed, reported, and do not stop other
|
|
175
|
+
subscriptions or subsequent callbacks. Attached sources and remote bindings use
|
|
176
|
+
their `onError` handler; local mutable states (and attached sources without a
|
|
177
|
+
handler) report failures by throwing in a microtask. Unsubscribing does not hide a
|
|
178
|
+
later rejection from the running callback.
|
|
179
|
+
|
|
180
|
+
The standalone [Delta guide](src/delta/README.md) defines the complete ownership,
|
|
181
|
+
lifecycle, operation, and replica contracts.
|
|
129
182
|
|
|
130
183
|
## Bundling and loading facets
|
|
131
184
|
|
package/dist/api.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Facet, FacetHost, FacetLoader, FacetOptions, MutableReplicatedState, RemoteServiceBinding, RemoteServiceBindingOptions, RemoteServiceContract, Service } from "./types.ts";
|
|
1
|
+
import type { AttachedReplicatedState, Facet, FacetHost, FacetLoader, FacetOptions, MutableReplicatedState, RemoteServiceBinding, RemoteServiceBindingOptions, RemoteServiceContract, ReplicatedStateSource, ReplicatedStateSourceOptions, Service } from "./types.ts";
|
|
2
2
|
/** Create an active host for one complete set of facets. */
|
|
3
3
|
export declare function createFacetHost(options: FacetOptions): Promise<FacetHost>;
|
|
4
4
|
export declare function createStaticFacetLoader(facets: readonly Facet[]): FacetLoader;
|
|
@@ -11,5 +11,10 @@ export declare function defineService<T>(id: string, ...options: [RemoteServiceC
|
|
|
11
11
|
readonly local?: false;
|
|
12
12
|
}]): Service<T>;
|
|
13
13
|
export declare function createRemoteServiceBinding(options: RemoteServiceBindingOptions): RemoteServiceBinding;
|
|
14
|
+
export declare function replicatedState<T>(source: ReplicatedStateSource<T>, options?: ReplicatedStateSourceOptions): AttachedReplicatedState<T>;
|
|
15
|
+
/**
|
|
16
|
+
* Create authoritative state by taking immutable ownership of an alias-free strict-JSON root.
|
|
17
|
+
* The caller must not mutate `initial` after this call.
|
|
18
|
+
*/
|
|
14
19
|
export declare function replicatedState<T extends object>(initial: T): MutableReplicatedState<T>;
|
|
15
20
|
//# sourceMappingURL=api.d.ts.map
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACX,KAAK,EACL,SAAS,EACT,WAAW,EACX,YAAY,EAEZ,sBAAsB,EACtB,oBAAoB,EACpB,2BAA2B,EAC3B,qBAAqB,EACrB,OAAO,EACP,MAAM,YAAY,CAAC;AAEpB,4DAA4D;AAC5D,wBAAsB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAQ/E;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,WAAW,CAO7E;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,CA0BhF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAE/C;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAC5F,wBAAgB,aAAa,CAAC,CAAC,EAC9B,EAAE,EAAE,MAAM,EACV,GAAG,OAAO,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GACnD,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,GACzB,SAAS,CAAC,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,GAChD,OAAO,CAAC,CAAC,CAAC,CAAC;AAQd,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,2BAA2B,GAAG,oBAAoB,CAErG;AAED,wBAAgB,eAAe,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACX,uBAAuB,EACvB,KAAK,EACL,SAAS,EACT,WAAW,EACX,YAAY,EAEZ,sBAAsB,EACtB,oBAAoB,EACpB,2BAA2B,EAC3B,qBAAqB,EACrB,qBAAqB,EACrB,4BAA4B,EAC5B,OAAO,EACP,MAAM,YAAY,CAAC;AAEpB,4DAA4D;AAC5D,wBAAsB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAQ/E;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,WAAW,CAO7E;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,CA0BhF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAE/C;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAC5F,wBAAgB,aAAa,CAAC,CAAC,EAC9B,EAAE,EAAE,MAAM,EACV,GAAG,OAAO,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GACnD,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,GACzB,SAAS,CAAC,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,GAChD,OAAO,CAAC,CAAC,CAAC,CAAC;AAQd,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,2BAA2B,GAAG,oBAAoB,CAErG;AAED,wBAAgB,eAAe,CAAC,CAAC,EAChC,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC,EAChC,OAAO,CAAC,EAAE,4BAA4B,GACpC,uBAAuB,CAAC,CAAC,CAAC,CAAC;AAC9B;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/api.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FacetKernel } from "./facets/host.js";
|
|
2
2
|
import { disposeLoadedFacets } from "./facets/loader.js";
|
|
3
3
|
import { RemoteServiceBindingImpl } from "./services/consumer.js";
|
|
4
|
-
import { MutableReplicatedStateImpl } from "./services/state.js";
|
|
4
|
+
import { attachReplicatedStateSource, MutableReplicatedStateImpl } from "./services/state.js";
|
|
5
5
|
/** Create an active host for one complete set of facets. */
|
|
6
6
|
export async function createFacetHost(options) {
|
|
7
7
|
const kernel = new FacetKernel(options);
|
|
@@ -66,7 +66,12 @@ export function defineService(id, options) {
|
|
|
66
66
|
export function createRemoteServiceBinding(options) {
|
|
67
67
|
return new RemoteServiceBindingImpl(options);
|
|
68
68
|
}
|
|
69
|
-
export function replicatedState(
|
|
70
|
-
|
|
69
|
+
export function replicatedState(initialOrSource, options) {
|
|
70
|
+
if (isReplicatedStateSource(initialOrSource))
|
|
71
|
+
return attachReplicatedStateSource(initialOrSource, options);
|
|
72
|
+
return new MutableReplicatedStateImpl(initialOrSource);
|
|
73
|
+
}
|
|
74
|
+
function isReplicatedStateSource(value) {
|
|
75
|
+
return typeof value.attach === "function";
|
|
71
76
|
}
|
|
72
77
|
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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","sourcesContent":["import { FacetKernel } from \"./facets/host.ts\";\nimport { disposeLoadedFacets } from \"./facets/loader.ts\";\nimport { RemoteServiceBindingImpl } from \"./services/consumer.ts\";\nimport { attachReplicatedStateSource, MutableReplicatedStateImpl } from \"./services/state.ts\";\nimport type {\n\tAttachedReplicatedState,\n\tFacet,\n\tFacetHost,\n\tFacetLoader,\n\tFacetOptions,\n\tLoadedFacets,\n\tMutableReplicatedState,\n\tRemoteServiceBinding,\n\tRemoteServiceBindingOptions,\n\tRemoteServiceContract,\n\tReplicatedStateSource,\n\tReplicatedStateSourceOptions,\n\tService,\n} from \"./types.ts\";\n\n/** Create an active host for one complete set of facets. */\nexport async function createFacetHost(options: FacetOptions): Promise<FacetHost> {\n\tconst kernel = new FacetKernel(options);\n\tawait kernel.activate();\n\treturn Object.freeze({\n\t\tservices: kernel.provider,\n\t\treload: (facets: readonly Facet[]) => kernel.reload(facets),\n\t\tdispose: () => kernel.dispose(),\n\t});\n}\n\nexport function createStaticFacetLoader(facets: readonly Facet[]): FacetLoader {\n\tconst loadedFacets = Object.freeze([...facets]);\n\treturn {\n\t\tasync load() {\n\t\t\treturn { facets: loadedFacets, async dispose() {} };\n\t\t},\n\t};\n}\n\nexport function combineFacetLoaders(loaders: readonly FacetLoader[]): FacetLoader {\n\treturn {\n\t\tasync load() {\n\t\t\tconst loaded: LoadedFacets[] = [];\n\t\t\ttry {\n\t\t\t\tfor (const loader of loaders) loaded.push(await loader.load());\n\t\t\t} catch (error) {\n\t\t\t\tconst cleanupErrors = await disposeLoadedFacets(loaded.reverse());\n\t\t\t\tif (cleanupErrors.length > 0) {\n\t\t\t\t\tthrow new AggregateError([error, ...cleanupErrors], \"Facet loading and cleanup failed\");\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tlet disposed = false;\n\t\t\treturn {\n\t\t\t\tfacets: Object.freeze(loaded.flatMap(({ facets }) => facets)),\n\t\t\t\tasync dispose() {\n\t\t\t\t\tif (disposed) return;\n\t\t\t\t\tdisposed = true;\n\t\t\t\t\tconst errors = await disposeLoadedFacets([...loaded].reverse());\n\t\t\t\t\tif (errors.length === 1) throw errors[0];\n\t\t\t\t\tif (errors.length > 1) throw new AggregateError(errors, \"Failed to dispose loaded facets\");\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n\nexport function defineFacet(facet: Facet): Facet {\n\treturn facet;\n}\n\nexport function defineService<T>(id: string, options: { readonly local: true }): Service<T>;\nexport function defineService<T>(\n\tid: string,\n\t...options: [RemoteServiceContract<T>] extends [never]\n\t\t? readonly [options: never]\n\t\t: readonly [options?: { readonly local?: false }]\n): Service<T>;\nexport function defineService(id: string, options?: { readonly local?: boolean }): Service<unknown> {\n\tif (id.length === 0) throw new TypeError(\"Service ID must not be empty\");\n\t// TODO: check if the reserved namespace should be part of Chord.\n\tif (id.startsWith(\"$chord.\")) throw new TypeError(\"Service IDs beginning with $chord. are reserved\");\n\treturn Object.freeze({ id, local: options?.local ?? false });\n}\n\nexport function createRemoteServiceBinding(options: RemoteServiceBindingOptions): RemoteServiceBinding {\n\treturn new RemoteServiceBindingImpl(options);\n}\n\nexport function replicatedState<T>(\n\tsource: ReplicatedStateSource<T>,\n\toptions?: ReplicatedStateSourceOptions,\n): AttachedReplicatedState<T>;\n/**\n * Create authoritative state by taking immutable ownership of an alias-free strict-JSON root.\n * The caller must not mutate `initial` after this call.\n */\nexport function replicatedState<T extends object>(initial: T): MutableReplicatedState<T>;\nexport function replicatedState(\n\tinitialOrSource: object | ReplicatedStateSource<unknown>,\n\toptions?: ReplicatedStateSourceOptions,\n): MutableReplicatedState<object> | AttachedReplicatedState<unknown> {\n\tif (isReplicatedStateSource(initialOrSource)) return attachReplicatedStateSource(initialOrSource, options);\n\treturn new MutableReplicatedStateImpl(initialOrSource);\n}\n\nfunction isReplicatedStateSource(value: object): value is ReplicatedStateSource<unknown> {\n\treturn typeof (value as { readonly attach?: unknown }).attach === \"function\";\n}\n"]}
|
package/dist/bundler.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundler.d.ts","sourceRoot":"","sources":["../src/bundler.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAChF,YAAY,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7F,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC"
|
|
1
|
+
{"version":3,"file":"bundler.d.ts","sourceRoot":"","sources":["../src/bundler.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAChF,YAAY,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7F,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAsDvD,eAAO,MAAM,kBAAkB,EAAE,OAA0D,CAAC;AAC5F,eAAO,MAAM,YAAY,EAAE,OAAoD,CAAC;AAEhF,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAEtE;AAED,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAE1F;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAI9E;AAED,6GAA6G;AAC7G,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAE5D;AAED,yDAAyD;AACzD,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG;IAC7C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C,CAMA;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAkBrF"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAsDvD,eAAO,MAAM,kBAAkB,EAAE,OAA0D,CAAC;AAC5F,eAAO,MAAM,YAAY,EAAE,OAAoD,CAAC;AAEhF,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAEtE;AAED,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAE1F;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAI9E;AAED,6GAA6G;AAC7G,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAE5D;AAED,yDAAyD;AACzD,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG;IAC7C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C,CAMA;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAkBrF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAEA,MAAM,wBAAwB,GAAwC,MAAM,CAAC,MAAM,CAAC;IACnF,KAAK,EAAE,MAAM,CAAC,mBAAmB,CAAC;CAClC,CAAC,CAAC;AAEH,MAAe,WAAW;IAIzB,IAAI,WAAW
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Context, ContextKey } from \"../types.ts\";\n\nconst ABORT_SIGNAL_CONTEXT_KEY: ContextKey<AbortSignal | undefined> = Object.freeze({\n\ttoken: Symbol(\"chord.abortSignal\"),\n});\n\nabstract class BaseContext implements Context {\n\tabstract value<T>(key: ContextKey<T>): T | undefined;\n\tabstract toString(): string;\n\n\tget abortSignal(): AbortSignal | undefined {\n\t\treturn this.value(ABORT_SIGNAL_CONTEXT_KEY);\n\t}\n}\n\nclass EmptyContext extends BaseContext {\n\treadonly #name: string;\n\n\tconstructor(name: string) {\n\t\tsuper();\n\t\tthis.#name = name;\n\t}\n\n\tvalue<T>(_key: ContextKey<T>): T | undefined {\n\t\treturn undefined;\n\t}\n\n\ttoString(): string {\n\t\treturn this.#name;\n\t}\n}\n\nclass ContextValue<T> extends BaseContext {\n\treadonly #parent: Context;\n\treadonly #key: ContextKey<T>;\n\treadonly #value: T;\n\n\tconstructor(parent: Context, key: ContextKey<T>, value: T) {\n\t\tsuper();\n\t\tthis.#parent = parent;\n\t\tthis.#key = key;\n\t\tthis.#value = value;\n\t}\n\n\tvalue<Value>(key: ContextKey<Value>): Value | undefined {\n\t\tif (key.token === this.#key.token) return this.#value as unknown as Value;\n\t\treturn this.#parent.value(key);\n\t}\n\n\ttoString(): string {\n\t\treturn `${this.#parent}.WithValue(${this.#key.token.description ?? \"anonymous\"})`;\n\t}\n}\n\nexport const BACKGROUND_CONTEXT: Context = new EmptyContext(\"[Context BACKGROUND_CONTEXT]\");\nexport const TODO_CONTEXT: Context = new EmptyContext(\"[Context TODO_CONTEXT]\");\n\nexport function createContextKey<T>(description: string): ContextKey<T> {\n\treturn Object.freeze({ token: Symbol(description) });\n}\n\n/** Derive a context containing one additional or replaced value. */\nexport function withContextValue<T>(key: ContextKey<T>, value: T, parent: Context): Context {\n\treturn new ContextValue(parent, key, value);\n}\n\n/**\n * Derive a context cancelled by either the parent signal or the supplied signal.\n * The parent context remains unchanged.\n */\nexport function withAbortSignal(signal: AbortSignal, context: Context): Context {\n\tconst parentSignal = context.abortSignal;\n\tconst combined = parentSignal === undefined ? signal : AbortSignal.any([parentSignal, signal]);\n\treturn withContextValue(ABORT_SIGNAL_CONTEXT_KEY, combined, context);\n}\n\n/** Derive a context retaining all values except caller cancellation. Intended for mandatory cleanup only. */\nexport function withoutAbortSignal(context: Context): Context {\n\treturn withContextValue(ABORT_SIGNAL_CONTEXT_KEY, undefined, context);\n}\n\n/** Derive an independently cancellable child context. */\nexport function withCancel(context: Context): {\n\treadonly context: Context;\n\treadonly cancel: (reason?: unknown) => void;\n} {\n\tconst controller = new AbortController();\n\treturn {\n\t\tcontext: withAbortSignal(controller.signal, context),\n\t\tcancel: (reason?: unknown) => controller.abort(reason),\n\t};\n}\n\n/**\n * Observe a promise until it settles or the invocation is cancelled.\n * Cancellation rejects only this waiter; it does not cancel the underlying promise.\n */\nexport function awaitWithContext<T>(promise: Promise<T>, context: Context): Promise<T> {\n\tconst signal = context.abortSignal;\n\tif (signal === undefined) return promise;\n\tif (signal.aborted) return Promise.reject(abortError(signal));\n\treturn new Promise<T>((resolve, reject) => {\n\t\tconst onAbort = (): void => reject(abortError(signal));\n\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\tvoid promise.then(\n\t\t\t(value) => {\n\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\tresolve(value);\n\t\t\t},\n\t\t\t(error: unknown) => {\n\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\treject(error);\n\t\t\t},\n\t\t);\n\t});\n}\n\nfunction abortError(signal: AbortSignal): Error {\n\tconst reason: unknown = signal.reason;\n\treturn reason instanceof Error ? reason : new DOMException(\"The operation was aborted\", \"AbortError\");\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Op } from "./index.ts";
|
|
2
|
+
/** Apply self-produced trusted operations while copying each touched container once. */
|
|
3
|
+
export declare function applyImmutableTrusted<T>(target: T, operations: readonly Op[]): T;
|
|
4
|
+
//# sourceMappingURL=apply-immutable-trusted.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-immutable-trusted.d.ts","sourceRoot":"","sources":["../../src/delta/apply-immutable-trusted.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAa,MAAM,YAAY,CAAC;AAYhD,wFAAwF;AACxF,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,GAAG,CAAC,CA8ChF"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
const DATA_DESCRIPTOR = {
|
|
2
|
+
value: undefined,
|
|
3
|
+
writable: true,
|
|
4
|
+
enumerable: true,
|
|
5
|
+
configurable: true,
|
|
6
|
+
};
|
|
7
|
+
/** Apply self-produced trusted operations while copying each touched container once. */
|
|
8
|
+
export function applyImmutableTrusted(target, operations) {
|
|
9
|
+
let root = target;
|
|
10
|
+
const owned = new WeakSet();
|
|
11
|
+
for (const operation of operations) {
|
|
12
|
+
if (operation[0] === "r") {
|
|
13
|
+
root = operation[1];
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (operation[0] === "p" || operation[0] === "m") {
|
|
17
|
+
const copied = copyPath(root, operation[1], operation[1].length, owned);
|
|
18
|
+
root = copied.root;
|
|
19
|
+
if (!Array.isArray(copied.target))
|
|
20
|
+
throw new TypeError("Trusted array operation target is not an array");
|
|
21
|
+
if (operation[0] === "p")
|
|
22
|
+
spliceTrusted(copied.target, operation[2], operation[3], operation[4]);
|
|
23
|
+
else
|
|
24
|
+
permuteTrusted(copied.target, operation[2]);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const path = operation[1];
|
|
28
|
+
const copied = copyPath(root, path, path.length - 1, owned);
|
|
29
|
+
root = copied.root;
|
|
30
|
+
const key = path[path.length - 1];
|
|
31
|
+
switch (operation[0]) {
|
|
32
|
+
case "s":
|
|
33
|
+
defineData(copied.target, key, operation[2]);
|
|
34
|
+
break;
|
|
35
|
+
case "d":
|
|
36
|
+
if (Array.isArray(copied.target)) {
|
|
37
|
+
if (typeof key !== "number")
|
|
38
|
+
throw new TypeError("Trusted array deletion key is not numeric");
|
|
39
|
+
spliceTrusted(copied.target, key, 1, []);
|
|
40
|
+
}
|
|
41
|
+
else
|
|
42
|
+
Reflect.deleteProperty(copied.target, key);
|
|
43
|
+
break;
|
|
44
|
+
case "a": {
|
|
45
|
+
const current = read(copied.target, key);
|
|
46
|
+
if (typeof current !== "string")
|
|
47
|
+
throw new TypeError("Trusted append target is not a string");
|
|
48
|
+
defineData(copied.target, key, `${current}${operation[2]}`);
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
case "t": {
|
|
52
|
+
const current = read(copied.target, key);
|
|
53
|
+
if (typeof current !== "string")
|
|
54
|
+
throw new TypeError("Trusted truncate target is not a string");
|
|
55
|
+
defineData(copied.target, key, current.slice(operation[2]));
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return root;
|
|
61
|
+
}
|
|
62
|
+
function copyPath(root, path, length, owned) {
|
|
63
|
+
if (!isContainer(root))
|
|
64
|
+
throw new TypeError("Trusted operation root is not a container");
|
|
65
|
+
let copiedRoot = root;
|
|
66
|
+
if (!owned.has(root)) {
|
|
67
|
+
copiedRoot = shallowCopy(root);
|
|
68
|
+
owned.add(copiedRoot);
|
|
69
|
+
}
|
|
70
|
+
let destination = copiedRoot;
|
|
71
|
+
for (let index = 0; index < length; index++) {
|
|
72
|
+
const segment = path[index];
|
|
73
|
+
const child = read(destination, segment);
|
|
74
|
+
if (!isContainer(child))
|
|
75
|
+
throw new TypeError("Trusted operation path is not a container");
|
|
76
|
+
if (owned.has(child)) {
|
|
77
|
+
destination = child;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const copy = shallowCopy(child);
|
|
81
|
+
defineData(destination, segment, copy);
|
|
82
|
+
owned.add(copy);
|
|
83
|
+
destination = copy;
|
|
84
|
+
}
|
|
85
|
+
return { root: copiedRoot, target: destination };
|
|
86
|
+
}
|
|
87
|
+
function shallowCopy(value) {
|
|
88
|
+
if (Array.isArray(value))
|
|
89
|
+
return Array.from(value);
|
|
90
|
+
const result = Object.create(Object.getPrototypeOf(value) === null ? null : Object.prototype);
|
|
91
|
+
for (const key of Object.keys(value))
|
|
92
|
+
defineData(result, key, value[key]);
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
function read(target, key) {
|
|
96
|
+
return target[key];
|
|
97
|
+
}
|
|
98
|
+
function defineData(target, key, value) {
|
|
99
|
+
DATA_DESCRIPTOR.value = value;
|
|
100
|
+
Object.defineProperty(target, key, DATA_DESCRIPTOR);
|
|
101
|
+
DATA_DESCRIPTOR.value = undefined;
|
|
102
|
+
}
|
|
103
|
+
function spliceTrusted(target, start, remove, items) {
|
|
104
|
+
const oldLength = target.length;
|
|
105
|
+
const delta = items.length - remove;
|
|
106
|
+
if (delta > 0) {
|
|
107
|
+
target.length = oldLength + delta;
|
|
108
|
+
target.copyWithin(start + items.length, start + remove, oldLength);
|
|
109
|
+
}
|
|
110
|
+
else if (delta < 0) {
|
|
111
|
+
target.copyWithin(start + items.length, start + remove, oldLength);
|
|
112
|
+
target.length = oldLength + delta;
|
|
113
|
+
}
|
|
114
|
+
for (let index = 0; index < items.length; index++)
|
|
115
|
+
defineData(target, start + index, items[index]);
|
|
116
|
+
}
|
|
117
|
+
function permuteTrusted(target, permutation) {
|
|
118
|
+
if (target.length !== permutation.length)
|
|
119
|
+
throw new TypeError("Trusted permutation length mismatch");
|
|
120
|
+
const previous = target.slice();
|
|
121
|
+
for (let index = 0; index < permutation.length; index++)
|
|
122
|
+
target[index] = previous[permutation[index]];
|
|
123
|
+
}
|
|
124
|
+
function isContainer(value) {
|
|
125
|
+
return value !== null && typeof value === "object";
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=apply-immutable-trusted.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-immutable-trusted.js","sourceRoot":"","sources":["../../src/delta/apply-immutable-trusted.ts"],"names":[],"mappings":"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","sourcesContent":["import type { JsonValue } from \"../types.ts\";\nimport type { Op, Path, Seg } from \"./index.ts\";\n\ntype JsonContainer = JsonValue[] | Record<string, JsonValue>;\ntype CopiedPath = { root: JsonValue; target: JsonContainer };\n\nconst DATA_DESCRIPTOR: PropertyDescriptor = {\n\tvalue: undefined,\n\twritable: true,\n\tenumerable: true,\n\tconfigurable: true,\n};\n\n/** Apply self-produced trusted operations while copying each touched container once. */\nexport function applyImmutableTrusted<T>(target: T, operations: readonly Op[]): T {\n\tlet root = target as unknown as JsonValue;\n\tconst owned = new WeakSet<object>();\n\tfor (const operation of operations) {\n\t\tif (operation[0] === \"r\") {\n\t\t\troot = operation[1];\n\t\t\tcontinue;\n\t\t}\n\t\tif (operation[0] === \"p\" || operation[0] === \"m\") {\n\t\t\tconst copied = copyPath(root, operation[1], operation[1].length, owned);\n\t\t\troot = copied.root;\n\t\t\tif (!Array.isArray(copied.target)) throw new TypeError(\"Trusted array operation target is not an array\");\n\t\t\tif (operation[0] === \"p\") spliceTrusted(copied.target, operation[2], operation[3], operation[4]);\n\t\t\telse permuteTrusted(copied.target, operation[2]);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst path = operation[1];\n\t\tconst copied = copyPath(root, path, path.length - 1, owned);\n\t\troot = copied.root;\n\t\tconst key = path[path.length - 1]!;\n\t\tswitch (operation[0]) {\n\t\t\tcase \"s\":\n\t\t\t\tdefineData(copied.target, key, operation[2]);\n\t\t\t\tbreak;\n\t\t\tcase \"d\":\n\t\t\t\tif (Array.isArray(copied.target)) {\n\t\t\t\t\tif (typeof key !== \"number\") throw new TypeError(\"Trusted array deletion key is not numeric\");\n\t\t\t\t\tspliceTrusted(copied.target, key, 1, []);\n\t\t\t\t} else Reflect.deleteProperty(copied.target, key);\n\t\t\t\tbreak;\n\t\t\tcase \"a\": {\n\t\t\t\tconst current = read(copied.target, key);\n\t\t\t\tif (typeof current !== \"string\") throw new TypeError(\"Trusted append target is not a string\");\n\t\t\t\tdefineData(copied.target, key, `${current}${operation[2]}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"t\": {\n\t\t\t\tconst current = read(copied.target, key);\n\t\t\t\tif (typeof current !== \"string\") throw new TypeError(\"Trusted truncate target is not a string\");\n\t\t\t\tdefineData(copied.target, key, current.slice(operation[2]));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn root as unknown as T;\n}\n\nfunction copyPath(root: JsonValue, path: Path, length: number, owned: WeakSet<object>): CopiedPath {\n\tif (!isContainer(root)) throw new TypeError(\"Trusted operation root is not a container\");\n\tlet copiedRoot = root;\n\tif (!owned.has(root)) {\n\t\tcopiedRoot = shallowCopy(root);\n\t\towned.add(copiedRoot);\n\t}\n\tlet destination = copiedRoot as JsonContainer;\n\tfor (let index = 0; index < length; index++) {\n\t\tconst segment = path[index]!;\n\t\tconst child = read(destination, segment);\n\t\tif (!isContainer(child)) throw new TypeError(\"Trusted operation path is not a container\");\n\t\tif (owned.has(child)) {\n\t\t\tdestination = child;\n\t\t\tcontinue;\n\t\t}\n\t\tconst copy = shallowCopy(child);\n\t\tdefineData(destination, segment, copy);\n\t\towned.add(copy);\n\t\tdestination = copy;\n\t}\n\treturn { root: copiedRoot, target: destination };\n}\n\nfunction shallowCopy(value: JsonContainer): JsonContainer {\n\tif (Array.isArray(value)) return Array.from(value);\n\tconst result = Object.create(Object.getPrototypeOf(value) === null ? null : Object.prototype) as Record<\n\t\tstring,\n\t\tJsonValue\n\t>;\n\tfor (const key of Object.keys(value)) defineData(result, key, value[key]!);\n\treturn result;\n}\n\nfunction read(target: JsonContainer, key: Seg): JsonValue {\n\treturn (target as Record<Seg, JsonValue>)[key]!;\n}\n\nfunction defineData(target: JsonContainer, key: Seg, value: JsonValue): void {\n\tDATA_DESCRIPTOR.value = value;\n\tObject.defineProperty(target, key, DATA_DESCRIPTOR);\n\tDATA_DESCRIPTOR.value = undefined;\n}\n\nfunction spliceTrusted(target: JsonValue[], start: number, remove: number, items: readonly JsonValue[]): void {\n\tconst oldLength = target.length;\n\tconst delta = items.length - remove;\n\tif (delta > 0) {\n\t\ttarget.length = oldLength + delta;\n\t\ttarget.copyWithin(start + items.length, start + remove, oldLength);\n\t} else if (delta < 0) {\n\t\ttarget.copyWithin(start + items.length, start + remove, oldLength);\n\t\ttarget.length = oldLength + delta;\n\t}\n\tfor (let index = 0; index < items.length; index++) defineData(target, start + index, items[index]!);\n}\n\nfunction permuteTrusted(target: JsonValue[], permutation: readonly number[]): void {\n\tif (target.length !== permutation.length) throw new TypeError(\"Trusted permutation length mismatch\");\n\tconst previous = target.slice();\n\tfor (let index = 0; index < permutation.length; index++) target[index] = previous[permutation[index]!]!;\n}\n\nfunction isContainer(value: unknown): value is JsonContainer {\n\treturn value !== null && typeof value === \"object\";\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type Op } from "../delta/index.ts";
|
|
2
1
|
import type { JsonValue } from "../types.ts";
|
|
2
|
+
import { type Op } from "./index.ts";
|
|
3
3
|
/** Compute a compact operation batch from two immutable JSON revisions. */
|
|
4
4
|
export declare function diffRevisions(before: JsonValue, after: JsonValue): Op[];
|
|
5
5
|
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/delta/diff.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAqB,KAAK,EAAE,EAAmD,MAAM,YAAY,CAAC;AA8fzG,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,EAAE,EAAE,CAUvE"}
|