@dxos/echo-protocol 0.8.4-main.c1de068 → 0.8.4-main.c85a9c8dae

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/package.json CHANGED
@@ -1,19 +1,22 @@
1
1
  {
2
2
  "name": "@dxos/echo-protocol",
3
- "version": "0.8.4-main.c1de068",
3
+ "version": "0.8.4-main.c85a9c8dae",
4
4
  "description": "Core ECHO APIs.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
7
- "repository": "github:dxos/dxos",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/dxos/dxos"
10
+ },
8
11
  "license": "MIT",
9
12
  "author": "DXOS.org",
10
- "sideEffects": true,
13
+ "sideEffects": false,
11
14
  "type": "module",
12
15
  "exports": {
13
16
  ".": {
17
+ "source": "./src/index.ts",
14
18
  "types": "./dist/types/src/index.d.ts",
15
- "browser": "./dist/lib/browser/index.mjs",
16
- "node": "./dist/lib/node-esm/index.mjs"
19
+ "default": "./dist/lib/neutral/index.mjs"
17
20
  }
18
21
  },
19
22
  "types": "dist/types/src/index.d.ts",
@@ -25,12 +28,12 @@
25
28
  "src"
26
29
  ],
27
30
  "dependencies": {
28
- "effect": "3.17.0",
29
- "@dxos/crypto": "0.8.4-main.c1de068",
30
- "@dxos/invariant": "0.8.4-main.c1de068",
31
- "@dxos/keys": "0.8.4-main.c1de068",
32
- "@dxos/util": "0.8.4-main.c1de068",
33
- "@dxos/protocols": "0.8.4-main.c1de068"
31
+ "effect": "3.19.16",
32
+ "@dxos/crypto": "0.8.4-main.c85a9c8dae",
33
+ "@dxos/invariant": "0.8.4-main.c85a9c8dae",
34
+ "@dxos/protocols": "0.8.4-main.c85a9c8dae",
35
+ "@dxos/util": "0.8.4-main.c85a9c8dae",
36
+ "@dxos/keys": "0.8.4-main.c85a9c8dae"
34
37
  },
35
38
  "publishConfig": {
36
39
  "access": "public"
@@ -8,7 +8,7 @@ import { visitValues } from '@dxos/util';
8
8
 
9
9
  import { type RawString } from './automerge';
10
10
  import type { ForeignKey } from './foreign-key';
11
- import { isEncodedReference, type EncodedReference } from './reference';
11
+ import { type EncodedReference, isEncodedReference } from './reference';
12
12
  import { type SpaceDocVersion } from './space-doc-version';
13
13
 
14
14
  export type SpaceState = {
@@ -137,6 +137,10 @@ export const ObjectStructure = Object.freeze({
137
137
  return object.system?.target;
138
138
  },
139
139
 
140
+ getParent: (object: ObjectStructure): EncodedReference | undefined => {
141
+ return object.system?.parent;
142
+ },
143
+
140
144
  /**
141
145
  * @returns All references in the data section of the object.
142
146
  */
@@ -153,6 +157,10 @@ export const ObjectStructure = Object.freeze({
153
157
  return references;
154
158
  },
155
159
 
160
+ getTags: (object: ObjectStructure): string[] => {
161
+ return object.meta.tags ?? [];
162
+ },
163
+
156
164
  makeObject: ({
157
165
  type,
158
166
  data,
@@ -214,6 +222,14 @@ export type ObjectMeta = {
214
222
  * Foreign keys.
215
223
  */
216
224
  keys: ForeignKey[];
225
+
226
+ /**
227
+ * Tags.
228
+ * An array of DXNs of Tag objects within the space.
229
+ *
230
+ * NOTE: Optional for backwards compatibilty.
231
+ */
232
+ tags?: string[];
217
233
  };
218
234
 
219
235
  /**
@@ -236,13 +252,19 @@ export type ObjectSystem = {
236
252
  */
237
253
  deleted?: boolean;
238
254
 
255
+ /**
256
+ * Object parent.
257
+ * Objects with no parent are at the top level of the object hierarchy in the space.
258
+ */
259
+ parent?: EncodedReference;
260
+
239
261
  /**
240
262
  * Only for relations.
241
263
  */
242
264
  source?: EncodedReference;
243
265
 
244
266
  /**
245
- * Only for relations.w
267
+ * Only for relations.
246
268
  */
247
269
  target?: EncodedReference;
248
270
  };
@@ -0,0 +1,67 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { FeedProtocol } from '@dxos/protocols';
6
+
7
+ import type { ForeignKey } from './foreign-key';
8
+
9
+ /** Property name for meta when object is serialized to JSON. Matches @dxos/echo/internal ATTR_META. */
10
+ const ATTR_META = '@meta';
11
+
12
+ /**
13
+ * Codec for ECHO objects in feed block payload: JSON object ↔ UTF-8 bytes.
14
+ * Encodes with queue position stripped; decodes with optional position injection.
15
+ */
16
+ export class EchoFeedCodec {
17
+ static readonly #encoder = new TextEncoder();
18
+ static readonly #decoder = new TextDecoder();
19
+
20
+ /**
21
+ * Prepares a value for feed storage (strips queue position from metadata) and encodes to bytes.
22
+ */
23
+ static encode(value: Record<string, unknown>): Uint8Array {
24
+ const prepared = EchoFeedCodec.#stripQueuePosition(value);
25
+ return EchoFeedCodec.#encoder.encode(JSON.stringify(prepared));
26
+ }
27
+
28
+ /**
29
+ * Decodes feed block bytes to a JSON value.
30
+ * If position is provided, injects queue position into the decoded object's metadata.
31
+ */
32
+ static decode(data: Uint8Array, position?: number): Record<string, unknown> {
33
+ const decoded = JSON.parse(EchoFeedCodec.#decoder.decode(data));
34
+ if (position !== undefined && typeof decoded === 'object' && decoded !== null) {
35
+ EchoFeedCodec.#setQueuePosition(decoded, position);
36
+ }
37
+ return decoded;
38
+ }
39
+
40
+ static #stripQueuePosition(value: Record<string, unknown>): Record<string, unknown> {
41
+ if (typeof value !== 'object' || value === null) {
42
+ return value;
43
+ }
44
+ const obj = structuredClone(value);
45
+ const meta = obj[ATTR_META] as { keys?: ForeignKey[] } | undefined;
46
+ if (meta?.keys?.some((key: ForeignKey) => key.source === FeedProtocol.KEY_QUEUE_POSITION)) {
47
+ meta.keys = meta.keys.filter((key: ForeignKey) => key.source !== FeedProtocol.KEY_QUEUE_POSITION);
48
+ }
49
+ return obj;
50
+ }
51
+
52
+ static #setQueuePosition(obj: Record<string, any>, position: number): void {
53
+ obj[ATTR_META] ??= { keys: [] };
54
+ obj[ATTR_META]!.keys ??= [];
55
+ const keys = obj[ATTR_META]!.keys!;
56
+ for (let i = 0; i < keys.length; i++) {
57
+ if (keys[i].source === FeedProtocol.KEY_QUEUE_POSITION) {
58
+ keys.splice(i, 1);
59
+ i--;
60
+ }
61
+ }
62
+ keys.push({
63
+ source: FeedProtocol.KEY_QUEUE_POSITION,
64
+ id: position.toString(),
65
+ });
66
+ }
67
+ }
@@ -2,7 +2,8 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Schema, SchemaAST } from 'effect';
5
+ import * as Schema from 'effect/Schema';
6
+ import * as SchemaAST from 'effect/SchemaAST';
6
7
 
7
8
  const ForeignKey_ = Schema.Struct({
8
9
  /**
@@ -15,8 +16,8 @@ const ForeignKey_ = Schema.Struct({
15
16
  * Id within the foreign database.
16
17
  */
17
18
  // TODO(wittjosiah): This annotation is currently used to ensure id field shows up in forms.
18
- // TODO(dmaretskyi): `false` is not a valid value for the annotation.
19
- id: Schema.String.annotations({ [SchemaAST.IdentifierAnnotationId]: false }),
19
+ // TODO(dmaretskyi): `false` is not a valid value for the annotation. Use a different annotation.
20
+ id: Schema.String.annotations({ [SchemaAST.IdentifierAnnotationId]: 'false' }),
20
21
  });
21
22
 
22
23
  export type ForeignKey = Schema.Schema.Type<typeof ForeignKey_>;
package/src/index.ts CHANGED
@@ -2,10 +2,11 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ export type * from './collection-sync';
5
6
  export * from './document-structure';
7
+ export * from './echo-feed-codec';
8
+ export * from './foreign-key';
9
+ export * from './query';
6
10
  export * from './reference';
7
11
  export * from './space-doc-version';
8
- export type * from './collection-sync';
9
12
  export * from './space-id';
10
- export * from './foreign-key';
11
- export * from './query';