@dxos/echo-protocol 0.8.4-main.ae835ea → 0.8.4-main.bc2380dfbc

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 CHANGED
@@ -1,8 +1,105 @@
1
- MIT License
2
- Copyright (c) 2022 DXOS
1
+ # Functional Source License, Version 1.1, ALv2 Future License
3
2
 
4
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
3
+ ## Abbreviation
5
4
 
6
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
5
+ FSL-1.1-Apache-2.0
7
6
 
8
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7
+ ## Notice
8
+
9
+ Copyright 2026 DXOS
10
+
11
+ ## Terms and Conditions
12
+
13
+ ### Licensor ("We")
14
+
15
+ The party offering the Software under these Terms and Conditions.
16
+
17
+ ### The Software
18
+
19
+ The "Software" is each version of the software that we make available under
20
+ these Terms and Conditions, as indicated by our inclusion of these Terms and
21
+ Conditions with the Software.
22
+
23
+ ### License Grant
24
+
25
+ Subject to your compliance with this License Grant and the Patents,
26
+ Redistribution and Trademark clauses below, we hereby grant you the right to
27
+ use, copy, modify, create derivative works, publicly perform, publicly display
28
+ and redistribute the Software for any Permitted Purpose identified below.
29
+
30
+ ### Permitted Purpose
31
+
32
+ A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
33
+ means making the Software available to others in a commercial product or
34
+ service that:
35
+
36
+ 1. substitutes for the Software;
37
+
38
+ 2. substitutes for any other product or service we offer using the Software
39
+ that exists as of the date we make the Software available; or
40
+
41
+ 3. offers the same or substantially similar functionality as the Software.
42
+
43
+ Permitted Purposes specifically include using the Software:
44
+
45
+ 1. for your internal use and access;
46
+
47
+ 2. for non-commercial education;
48
+
49
+ 3. for non-commercial research; and
50
+
51
+ 4. in connection with professional services that you provide to a licensee
52
+ using the Software in accordance with these Terms and Conditions.
53
+
54
+ ### Patents
55
+
56
+ To the extent your use for a Permitted Purpose would necessarily infringe our
57
+ patents, the license grant above includes a license under our patents. If you
58
+ make a claim against any party that the Software infringes or contributes to
59
+ the infringement of any patent, then your patent license to the Software ends
60
+ immediately.
61
+
62
+ ### Redistribution
63
+
64
+ The Terms and Conditions apply to all copies, modifications and derivatives of
65
+ the Software.
66
+
67
+ If you redistribute any copies, modifications or derivatives of the Software,
68
+ you must include a copy of or a link to these Terms and Conditions and not
69
+ remove any copyright notices provided in or with the Software.
70
+
71
+ ### Disclaimer
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
74
+ IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
75
+ PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
76
+
77
+ IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
78
+ SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
79
+ EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
80
+
81
+ ### Trademarks
82
+
83
+ Except for displaying the License Details and identifying us as the origin of
84
+ the Software, you have no right under these Terms and Conditions to use our
85
+ trademarks, trade names, service marks or product names.
86
+
87
+ ## Grant of Future License
88
+
89
+ We hereby irrevocably grant you an additional license to use the Software under
90
+ the Apache License, Version 2.0 that is effective on the second anniversary of
91
+ the date we make the Software available. On or after that date, you may use the
92
+ Software under the Apache License, Version 2.0, in which case the following
93
+ will apply:
94
+
95
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
96
+ this file except in compliance with the License.
97
+
98
+ You may obtain a copy of the License at
99
+
100
+ http://www.apache.org/licenses/LICENSE-2.0
101
+
102
+ Unless required by applicable law or agreed to in writing, software distributed
103
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
104
+ CONDITIONS OF ANY KIND, either express or implied. See the License for the
105
+ specific language governing permissions and limitations under the License.
package/README.md CHANGED
@@ -18,4 +18,4 @@ pnpm i @dxos/echo-protocol
18
18
 
19
19
  Your ideas, issues, and code are most welcome. Please take a look at our [community code of conduct](https://github.com/dxos/dxos/blob/main/CODE_OF_CONDUCT.md), the [issue guide](https://github.com/dxos/dxos/blob/main/CONTRIBUTING.md#submitting-issues), and the [PR contribution guide](https://github.com/dxos/dxos/blob/main/CONTRIBUTING.md#submitting-prs).
20
20
 
21
- License: [MIT](./LICENSE) Copyright 2022 © DXOS
21
+ License: [FSL-1.1-Apache-2.0](./LICENSE) Copyright 2022 © DXOS
@@ -145,7 +145,14 @@ var EncodedReference = Object.freeze({
145
145
  return DXN.parse(EncodedReference.getReferenceString(value2));
146
146
  },
147
147
  fromDXN: (dxn) => {
148
- return encodeReference(Reference.fromDXN(dxn));
148
+ return {
149
+ "/": dxn.toString()
150
+ };
151
+ },
152
+ fromLegacyTypename: (typename) => {
153
+ return {
154
+ "/": DXN.fromTypename(typename).toString()
155
+ };
149
156
  }
150
157
  });
151
158
 
@@ -161,15 +168,7 @@ var DatabaseDirectory = Object.freeze({
161
168
  return null;
162
169
  }
163
170
  const rawKey = String(rawSpaceKey);
164
- invariant(!rawKey.startsWith("0x"), "Space key must not start with 0x", {
165
- F: __dxlog_file,
166
- L: 66,
167
- S: void 0,
168
- A: [
169
- "!rawKey.startsWith('0x')",
170
- "'Space key must not start with 0x'"
171
- ]
172
- });
171
+ invariant(!rawKey.startsWith("0x"), "Space key must not start with 0x", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 17, S: void 0, A: ["!rawKey.startsWith('0x')", "'Space key must not start with 0x'"] });
173
172
  return rawKey;
174
173
  },
175
174
  getInlineObject: (doc, id) => {
@@ -198,15 +197,7 @@ var ObjectStructure = Object.freeze({
198
197
  */
199
198
  getEntityKind: (object) => {
200
199
  const kind = object.system?.kind ?? "object";
201
- invariant(kind === "object" || kind === "relation", "Invalid kind", {
202
- F: __dxlog_file,
203
- L: 124,
204
- S: void 0,
205
- A: [
206
- "kind === 'object' || kind === 'relation'",
207
- "'Invalid kind'"
208
- ]
209
- });
200
+ invariant(kind === "object" || kind === "relation", "Invalid kind", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 45, S: void 0, A: ["kind === 'object' || kind === 'relation'", "'Invalid kind'"] });
210
201
  return kind;
211
202
  },
212
203
  isDeleted: (object) => {
@@ -218,6 +209,9 @@ var ObjectStructure = Object.freeze({
218
209
  getRelationTarget: (object) => {
219
210
  return object.system?.target;
220
211
  },
212
+ getParent: (object) => {
213
+ return object.system?.parent;
214
+ },
221
215
  /**
222
216
  * @returns All references in the data section of the object.
223
217
  */
@@ -279,33 +273,58 @@ var ObjectStructure = Object.freeze({
279
273
  var PROPERTY_ID = "id";
280
274
  var DATA_NAMESPACE = "data";
281
275
 
282
- // src/space-doc-version.ts
283
- var SpaceDocVersion = Object.freeze({
276
+ // src/echo-feed-codec.ts
277
+ import { FeedProtocol } from "@dxos/protocols";
278
+ var ATTR_META = "@meta";
279
+ var EchoFeedCodec = class _EchoFeedCodec {
280
+ static #encoder = new TextEncoder();
281
+ static #decoder = new TextDecoder();
284
282
  /**
285
- * For the documents created before the versioning was introduced.
283
+ * Prepares a value for feed storage (strips queue position from metadata) and encodes to bytes.
286
284
  */
287
- LEGACY: 0,
285
+ static encode(value2) {
286
+ const prepared = _EchoFeedCodec.#stripQueuePosition(value2);
287
+ return _EchoFeedCodec.#encoder.encode(JSON.stringify(prepared));
288
+ }
288
289
  /**
289
- * Current version.
290
+ * Decodes feed block bytes to a JSON value.
291
+ * If position is provided, injects queue position into the decoded object's metadata.
290
292
  */
291
- CURRENT: 1
292
- });
293
-
294
- // src/space-id.ts
295
- import { subtleCrypto } from "@dxos/crypto";
296
- import { PublicKey, SpaceId } from "@dxos/keys";
297
- import { ComplexMap } from "@dxos/util";
298
- var SPACE_IDS_CACHE = new ComplexMap(PublicKey.hash);
299
- var createIdFromSpaceKey = async (spaceKey) => {
300
- const cachedValue = SPACE_IDS_CACHE.get(spaceKey);
301
- if (cachedValue !== void 0) {
302
- return cachedValue;
293
+ static decode(data, position) {
294
+ const decoded = JSON.parse(_EchoFeedCodec.#decoder.decode(data));
295
+ if (position !== void 0 && typeof decoded === "object" && decoded !== null) {
296
+ _EchoFeedCodec.#setQueuePosition(decoded, position);
297
+ }
298
+ return decoded;
299
+ }
300
+ static #stripQueuePosition(value2) {
301
+ if (typeof value2 !== "object" || value2 === null) {
302
+ return value2;
303
+ }
304
+ const obj = structuredClone(value2);
305
+ const meta = obj[ATTR_META];
306
+ if (meta?.keys?.some((key) => key.source === FeedProtocol.KEY_QUEUE_POSITION)) {
307
+ meta.keys = meta.keys.filter((key) => key.source !== FeedProtocol.KEY_QUEUE_POSITION);
308
+ }
309
+ return obj;
310
+ }
311
+ static #setQueuePosition(obj, position) {
312
+ obj[ATTR_META] ??= {
313
+ keys: []
314
+ };
315
+ obj[ATTR_META].keys ??= [];
316
+ const keys = obj[ATTR_META].keys;
317
+ for (let i = 0; i < keys.length; i++) {
318
+ if (keys[i].source === FeedProtocol.KEY_QUEUE_POSITION) {
319
+ keys.splice(i, 1);
320
+ i--;
321
+ }
322
+ }
323
+ keys.push({
324
+ source: FeedProtocol.KEY_QUEUE_POSITION,
325
+ id: position.toString()
326
+ });
303
327
  }
304
- const digest = await subtleCrypto.digest("SHA-256", spaceKey.asUint8Array());
305
- const bytes = new Uint8Array(digest).slice(0, SpaceId.byteLength);
306
- const spaceId = SpaceId.encode(bytes);
307
- SPACE_IDS_CACHE.set(spaceKey, spaceId);
308
- return spaceId;
309
328
  };
310
329
 
311
330
  // src/foreign-key.ts
@@ -333,6 +352,7 @@ var ast_exports = {};
333
352
  __export(ast_exports, {
334
353
  Filter: () => Filter,
335
354
  FilterAnd: () => FilterAnd,
355
+ FilterChildOf: () => FilterChildOf,
336
356
  FilterCompare: () => FilterCompare,
337
357
  FilterContains: () => FilterContains,
338
358
  FilterIn: () => FilterIn,
@@ -342,11 +362,16 @@ __export(ast_exports, {
342
362
  FilterRange: () => FilterRange,
343
363
  FilterTag: () => FilterTag,
344
364
  FilterTextSearch: () => FilterTextSearch,
365
+ FilterTimestamp: () => FilterTimestamp,
345
366
  Order: () => Order,
346
367
  OrderDirection: () => OrderDirection,
347
368
  Query: () => Query,
348
369
  QueryFilterClause: () => QueryFilterClause,
370
+ QueryFromClause: () => QueryFromClause,
371
+ QueryFromClause_: () => QueryFromClause_,
372
+ QueryHierarchyTraversalClause: () => QueryHierarchyTraversalClause,
349
373
  QueryIncomingReferencesClause: () => QueryIncomingReferencesClause,
374
+ QueryLimitClause: () => QueryLimitClause,
350
375
  QueryOptions: () => QueryOptions,
351
376
  QueryOptionsClause: () => QueryOptionsClause,
352
377
  QueryOrderClause: () => QueryOrderClause,
@@ -356,14 +381,16 @@ __export(ast_exports, {
356
381
  QuerySelectClause: () => QuerySelectClause,
357
382
  QuerySetDifferenceClause: () => QuerySetDifferenceClause,
358
383
  QueryUnionClause: () => QueryUnionClause,
384
+ Scope: () => Scope,
359
385
  fold: () => fold,
386
+ map: () => map,
360
387
  visit: () => visit
361
388
  });
362
389
  import * as Match from "effect/Match";
363
390
  import * as Schema2 from "effect/Schema";
364
391
  import { DXN as DXN2, ObjectId } from "@dxos/keys";
365
392
  var TypenameSpecifier = Schema2.Union(DXN2.Schema, Schema2.Null).annotations({
366
- description: "DXN or null. Null means any type will match"
393
+ description: "DXN or null; null matches any type"
367
394
  });
368
395
  var FilterObject_ = Schema2.Struct({
369
396
  type: Schema2.Literal("object"),
@@ -382,7 +409,16 @@ var FilterObject_ = Schema2.Struct({
382
409
  /**
383
410
  * Objects that have any of the given foreign keys.
384
411
  */
385
- foreignKeys: Schema2.optional(Schema2.Array(ForeignKey))
412
+ foreignKeys: Schema2.optional(Schema2.Array(ForeignKey)),
413
+ /**
414
+ * Match objects whose meta `key` equals this fully-qualified registry key (FQN format).
415
+ */
416
+ metaKey: Schema2.optional(Schema2.String),
417
+ /**
418
+ * Semver range matched against the object's meta `version`.
419
+ * Only consulted when {@link metaKey} is set. Objects with no `version` do not satisfy a version-constrained filter.
420
+ */
421
+ metaVersion: Schema2.optional(Schema2.String)
386
422
  });
387
423
  var FilterObject = FilterObject_;
388
424
  var FilterCompare_ = Schema2.Struct({
@@ -412,6 +448,13 @@ var FilterRange_ = Schema2.Struct({
412
448
  to: Schema2.Any
413
449
  });
414
450
  var FilterRange = FilterRange_;
451
+ var FilterTimestamp_ = Schema2.Struct({
452
+ type: Schema2.Literal("timestamp"),
453
+ field: Schema2.Literal("createdAt", "updatedAt"),
454
+ operator: Schema2.Literal("gt", "gte", "lt", "lte"),
455
+ value: Schema2.Number
456
+ });
457
+ var FilterTimestamp = FilterTimestamp_;
415
458
  var FilterTextSearch_ = Schema2.Struct({
416
459
  type: Schema2.Literal("text-search"),
417
460
  text: Schema2.String,
@@ -433,8 +476,16 @@ var FilterOr_ = Schema2.Struct({
433
476
  filters: Schema2.Array(Schema2.suspend(() => Filter))
434
477
  });
435
478
  var FilterOr = FilterOr_;
436
- var Filter = Schema2.Union(FilterObject, FilterCompare, FilterIn, FilterContains, FilterTag, FilterRange, FilterTextSearch, FilterNot, FilterAnd, FilterOr).annotations({
437
- identifier: "dxos.org/schema/Filter"
479
+ var FilterChildOf_ = Schema2.Struct({
480
+ type: Schema2.Literal("child-of"),
481
+ /** Parent DXNs to match children of. */
482
+ parents: Schema2.Array(DXN2.Schema),
483
+ /** Whether to match transitively (grandchildren, etc.). Defaults to true. */
484
+ transitive: Schema2.Boolean
485
+ });
486
+ var FilterChildOf = FilterChildOf_;
487
+ var Filter = Schema2.Union(FilterObject, FilterCompare, FilterIn, FilterContains, FilterTag, FilterRange, FilterTimestamp, FilterTextSearch, FilterChildOf, FilterNot, FilterAnd, FilterOr).annotations({
488
+ identifier: "org.dxos.schema.filter"
438
489
  });
439
490
  var QuerySelectClause_ = Schema2.Struct({
440
491
  type: Schema2.Literal("select"),
@@ -456,7 +507,11 @@ var QueryReferenceTraversalClause = QueryReferenceTraversalClause_;
456
507
  var QueryIncomingReferencesClause_ = Schema2.Struct({
457
508
  type: Schema2.Literal("incoming-references"),
458
509
  anchor: Schema2.suspend(() => Query),
459
- property: Schema2.String,
510
+ /**
511
+ * Property path where the reference is located.
512
+ * If null, matches references from any property.
513
+ */
514
+ property: Schema2.NullOr(Schema2.String),
460
515
  typename: TypenameSpecifier
461
516
  });
462
517
  var QueryIncomingReferencesClause = QueryIncomingReferencesClause_;
@@ -478,6 +533,16 @@ var QueryRelationTraversalClause_ = Schema2.Struct({
478
533
  direction: Schema2.Literal("source", "target", "both")
479
534
  });
480
535
  var QueryRelationTraversalClause = QueryRelationTraversalClause_;
536
+ var QueryHierarchyTraversalClause_ = Schema2.Struct({
537
+ type: Schema2.Literal("hierarchy-traversal"),
538
+ anchor: Schema2.suspend(() => Query),
539
+ /**
540
+ * to-parent: traverse from child to parent.
541
+ * to-children: traverse from parent to children.
542
+ */
543
+ direction: Schema2.Literal("to-parent", "to-children")
544
+ });
545
+ var QueryHierarchyTraversalClause = QueryHierarchyTraversalClause_;
481
546
  var QueryUnionClause_ = Schema2.Struct({
482
547
  type: Schema2.Literal("union"),
483
548
  queries: Schema2.Array(Schema2.suspend(() => Query))
@@ -497,6 +562,11 @@ var Order_ = Schema2.Union(Schema2.Struct({
497
562
  kind: Schema2.Literal("property"),
498
563
  property: Schema2.String,
499
564
  direction: OrderDirection
565
+ }), Schema2.Struct({
566
+ // Order by relevance rank (for FTS/vector search results).
567
+ // Default direction is 'desc' (higher rank = better match first).
568
+ kind: Schema2.Literal("rank"),
569
+ direction: OrderDirection
500
570
  }));
501
571
  var Order = Order_;
502
572
  var QueryOrderClause_ = Schema2.Struct({
@@ -511,27 +581,53 @@ var QueryOptionsClause_ = Schema2.Struct({
511
581
  options: Schema2.suspend(() => QueryOptions)
512
582
  });
513
583
  var QueryOptionsClause = QueryOptionsClause_;
514
- var Query_ = Schema2.Union(QuerySelectClause, QueryFilterClause, QueryReferenceTraversalClause, QueryIncomingReferencesClause, QueryRelationClause, QueryRelationTraversalClause, QueryUnionClause, QuerySetDifferenceClause, QueryOrderClause, QueryOptionsClause).annotations({
515
- identifier: "dxos.org/schema/Query"
584
+ var QueryLimitClause_ = Schema2.Struct({
585
+ type: Schema2.Literal("limit"),
586
+ query: Schema2.suspend(() => Query),
587
+ limit: Schema2.Number
588
+ });
589
+ var QueryLimitClause = QueryLimitClause_;
590
+ var QueryFromClause_ = Schema2.Struct({
591
+ type: Schema2.Literal("from"),
592
+ query: Schema2.suspend(() => Query),
593
+ from: Schema2.Union(Schema2.TaggedStruct("scope", {
594
+ scope: Schema2.suspend(() => Scope)
595
+ }), Schema2.TaggedStruct("query", {
596
+ query: Schema2.suspend(() => Query)
597
+ }))
598
+ });
599
+ var QueryFromClause = QueryFromClause_;
600
+ var Query_ = Schema2.Union(QuerySelectClause, QueryFilterClause, QueryReferenceTraversalClause, QueryIncomingReferencesClause, QueryRelationClause, QueryRelationTraversalClause, QueryHierarchyTraversalClause, QueryUnionClause, QuerySetDifferenceClause, QueryOrderClause, QueryOptionsClause, QueryLimitClause, QueryFromClause).annotations({
601
+ identifier: "org.dxos.schema.query"
516
602
  });
517
603
  var Query = Query_;
518
604
  var QueryOptions = Schema2.Struct({
605
+ /**
606
+ * Nested select statements will use this option to filter deleted objects.
607
+ */
608
+ deleted: Schema2.optional(Schema2.Literal("include", "exclude", "only")),
609
+ /**
610
+ * Diagnostics-only label for logs / tooling (not used by execution semantics).
611
+ */
612
+ debugLabel: Schema2.optional(Schema2.String)
613
+ });
614
+ var Scope = Schema2.Struct({
519
615
  /**
520
616
  * The nested select statemets will select from the given spaces.
521
617
  *
522
- * NOTE: Spaces and queues are unioned together if both are specified.
618
+ * NOTE: Spaces and feeds are unioned together if both are specified.
523
619
  */
524
620
  spaceIds: Schema2.optional(Schema2.Array(Schema2.String)),
525
621
  /**
526
- * The nested select statemets will select from the given queues.
527
- *
528
- * NOTE: Spaces and queues are unioned together if both are specified.
622
+ * If true, the nested select statements will select from all feeds in the spaces specified by `spaceIds`.
529
623
  */
530
- queues: Schema2.optional(Schema2.Array(DXN2.Schema)),
624
+ allFeedsFromSpaces: Schema2.optional(Schema2.Boolean),
531
625
  /**
532
- * Nested select statements will use this option to filter deleted objects.
626
+ * The nested select statemets will select from the given feeds (by underlying queue DXN).
627
+ *
628
+ * NOTE: Spaces and feeds are unioned together if both are specified.
533
629
  */
534
- deleted: Schema2.optional(Schema2.Literal("include", "exclude", "only"))
630
+ feeds: Schema2.optional(Schema2.Array(DXN2.Schema))
535
631
  });
536
632
  var visit = (query, visitor) => {
537
633
  visitor(query);
@@ -547,6 +643,8 @@ var visit = (query, visitor) => {
547
643
  type: "options"
548
644
  }, ({ query: query2 }) => visit(query2, visitor)), Match.when({
549
645
  type: "relation-traversal"
646
+ }, ({ anchor }) => visit(anchor, visitor)), Match.when({
647
+ type: "hierarchy-traversal"
550
648
  }, ({ anchor }) => visit(anchor, visitor)), Match.when({
551
649
  type: "union"
552
650
  }, ({ queries }) => queries.forEach((q) => visit(q, visitor))), Match.when({
@@ -557,10 +655,92 @@ var visit = (query, visitor) => {
557
655
  }), Match.when({
558
656
  type: "order"
559
657
  }, ({ query: query2 }) => visit(query2, visitor)), Match.when({
658
+ type: "limit"
659
+ }, ({ query: query2 }) => visit(query2, visitor)), Match.when({
660
+ type: "from"
661
+ }, (node) => {
662
+ visit(node.query, visitor);
663
+ if (node.from._tag === "query") {
664
+ visit(node.from.query, visitor);
665
+ }
666
+ }), Match.when({
560
667
  type: "select"
561
668
  }, () => {
562
669
  }), Match.exhaustive);
563
670
  };
671
+ var map = (query, mapper) => {
672
+ const mapped = Match.value(query).pipe(Match.when({
673
+ type: "filter"
674
+ }, (node) => ({
675
+ ...node,
676
+ selection: map(node.selection, mapper)
677
+ })), Match.when({
678
+ type: "reference-traversal"
679
+ }, (node) => ({
680
+ ...node,
681
+ anchor: map(node.anchor, mapper)
682
+ })), Match.when({
683
+ type: "incoming-references"
684
+ }, (node) => ({
685
+ ...node,
686
+ anchor: map(node.anchor, mapper)
687
+ })), Match.when({
688
+ type: "relation"
689
+ }, (node) => ({
690
+ ...node,
691
+ anchor: map(node.anchor, mapper)
692
+ })), Match.when({
693
+ type: "relation-traversal"
694
+ }, (node) => ({
695
+ ...node,
696
+ anchor: map(node.anchor, mapper)
697
+ })), Match.when({
698
+ type: "hierarchy-traversal"
699
+ }, (node) => ({
700
+ ...node,
701
+ anchor: map(node.anchor, mapper)
702
+ })), Match.when({
703
+ type: "options"
704
+ }, (node) => ({
705
+ ...node,
706
+ query: map(node.query, mapper)
707
+ })), Match.when({
708
+ type: "order"
709
+ }, (node) => ({
710
+ ...node,
711
+ query: map(node.query, mapper)
712
+ })), Match.when({
713
+ type: "limit"
714
+ }, (node) => ({
715
+ ...node,
716
+ query: map(node.query, mapper)
717
+ })), Match.when({
718
+ type: "from"
719
+ }, (node) => ({
720
+ ...node,
721
+ query: map(node.query, mapper),
722
+ ...node.from._tag === "query" ? {
723
+ from: {
724
+ _tag: "query",
725
+ query: map(node.from.query, mapper)
726
+ }
727
+ } : {}
728
+ })), Match.when({
729
+ type: "union"
730
+ }, (node) => ({
731
+ ...node,
732
+ queries: node.queries.map((q) => map(q, mapper))
733
+ })), Match.when({
734
+ type: "set-difference"
735
+ }, (node) => ({
736
+ ...node,
737
+ source: map(node.source, mapper),
738
+ exclude: map(node.exclude, mapper)
739
+ })), Match.when({
740
+ type: "select"
741
+ }, (node) => node), Match.exhaustive);
742
+ return mapper(mapped);
743
+ };
564
744
  var fold = (query, reducer) => {
565
745
  return Match.value(query).pipe(Match.withReturnType(), Match.when({
566
746
  type: "filter"
@@ -574,6 +754,8 @@ var fold = (query, reducer) => {
574
754
  type: "options"
575
755
  }, ({ query: query2 }) => fold(query2, reducer)), Match.when({
576
756
  type: "relation-traversal"
757
+ }, ({ anchor }) => fold(anchor, reducer)), Match.when({
758
+ type: "hierarchy-traversal"
577
759
  }, ({ anchor }) => fold(anchor, reducer)), Match.when({
578
760
  type: "union"
579
761
  }, ({ queries }) => queries.flatMap((q) => fold(q, reducer))), Match.when({
@@ -581,12 +763,52 @@ var fold = (query, reducer) => {
581
763
  }, ({ source, exclude }) => fold(source, reducer).concat(fold(exclude, reducer))), Match.when({
582
764
  type: "order"
583
765
  }, ({ query: query2 }) => fold(query2, reducer)), Match.when({
766
+ type: "limit"
767
+ }, ({ query: query2 }) => fold(query2, reducer)), Match.when({
768
+ type: "from"
769
+ }, (node) => {
770
+ const results = fold(node.query, reducer);
771
+ if (node.from._tag === "query") {
772
+ return results.concat(fold(node.from.query, reducer));
773
+ }
774
+ return results;
775
+ }), Match.when({
584
776
  type: "select"
585
777
  }, () => []), Match.exhaustive);
586
778
  };
779
+
780
+ // src/space-doc-version.ts
781
+ var SpaceDocVersion = Object.freeze({
782
+ /**
783
+ * For the documents created before the versioning was introduced.
784
+ */
785
+ LEGACY: 0,
786
+ /**
787
+ * Current version.
788
+ */
789
+ CURRENT: 1
790
+ });
791
+
792
+ // src/space-id.ts
793
+ import { subtleCrypto } from "@dxos/crypto";
794
+ import { PublicKey, SpaceId } from "@dxos/keys";
795
+ import { ComplexMap } from "@dxos/util";
796
+ var SPACE_IDS_CACHE = new ComplexMap(PublicKey.hash);
797
+ var createIdFromSpaceKey = async (spaceKey) => {
798
+ const cachedValue = SPACE_IDS_CACHE.get(spaceKey);
799
+ if (cachedValue !== void 0) {
800
+ return cachedValue;
801
+ }
802
+ const digest = await subtleCrypto.digest("SHA-256", spaceKey.asUint8Array());
803
+ const bytes = new Uint8Array(digest).slice(0, SpaceId.byteLength);
804
+ const spaceId = SpaceId.encode(bytes);
805
+ SPACE_IDS_CACHE.set(spaceKey, spaceId);
806
+ return spaceId;
807
+ };
587
808
  export {
588
809
  DATA_NAMESPACE,
589
810
  DatabaseDirectory,
811
+ EchoFeedCodec,
590
812
  EncodedReference,
591
813
  ForeignKey,
592
814
  ObjectStructure,