@dxos/protocols 0.8.4-main.72ec0f3 → 0.8.4-main.7ace549

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.
Files changed (58) hide show
  1. package/dist/src/edge/EdgeFunctionEnv.d.ts +95 -0
  2. package/dist/src/edge/EdgeFunctionEnv.d.ts.map +1 -0
  3. package/dist/src/edge/EdgeFunctionEnv.js +4 -0
  4. package/dist/src/edge/EdgeFunctionEnv.js.map +1 -0
  5. package/dist/src/{edge.d.ts → edge/edge.d.ts} +22 -13
  6. package/dist/src/edge/edge.d.ts.map +1 -0
  7. package/dist/src/{edge.js → edge/edge.js} +4 -4
  8. package/dist/src/edge/edge.js.map +1 -0
  9. package/dist/src/{edge-error.d.ts → edge/errors.d.ts} +5 -6
  10. package/dist/src/edge/errors.d.ts.map +1 -0
  11. package/dist/src/{edge-error.js → edge/errors.js} +13 -14
  12. package/dist/src/edge/errors.js.map +1 -0
  13. package/dist/src/edge/index.d.ts +4 -0
  14. package/dist/src/edge/index.d.ts.map +1 -0
  15. package/dist/src/edge/index.js +7 -0
  16. package/dist/src/edge/index.js.map +1 -0
  17. package/dist/src/errors/base-errors.d.ts +92 -8
  18. package/dist/src/errors/base-errors.d.ts.map +1 -1
  19. package/dist/src/errors/base-errors.js +4 -20
  20. package/dist/src/errors/base-errors.js.map +1 -1
  21. package/dist/src/errors/encoding.d.ts +1 -1
  22. package/dist/src/errors/encoding.d.ts.map +1 -1
  23. package/dist/src/errors/errors.d.ts +662 -41
  24. package/dist/src/errors/errors.d.ts.map +1 -1
  25. package/dist/src/errors/errors.js +29 -83
  26. package/dist/src/errors/errors.js.map +1 -1
  27. package/dist/src/errors/errors.test.js +1 -1
  28. package/dist/src/errors/errors.test.js.map +1 -1
  29. package/dist/src/errors/helpers.d.ts +8 -4
  30. package/dist/src/errors/helpers.d.ts.map +1 -1
  31. package/dist/src/errors/helpers.js +3 -3
  32. package/dist/src/errors/helpers.js.map +1 -1
  33. package/dist/src/feed-replication.d.ts.map +1 -1
  34. package/dist/src/index.d.ts +2 -2
  35. package/dist/src/index.d.ts.map +1 -1
  36. package/dist/src/index.js +3 -2
  37. package/dist/src/index.js.map +1 -1
  38. package/dist/src/messenger.d.ts +16 -0
  39. package/dist/src/messenger.d.ts.map +1 -0
  40. package/dist/src/messenger.js +4 -0
  41. package/dist/src/messenger.js.map +1 -0
  42. package/dist/tsconfig.tsbuildinfo +1 -1
  43. package/package.json +9 -9
  44. package/src/edge/EdgeFunctionEnv.ts +165 -0
  45. package/src/{edge.ts → edge/edge.ts} +30 -19
  46. package/src/{edge-error.ts → edge/errors.ts} +14 -15
  47. package/src/edge/index.ts +7 -0
  48. package/src/errors/base-errors.ts +4 -22
  49. package/src/errors/errors.test.ts +1 -1
  50. package/src/errors/errors.ts +35 -101
  51. package/src/errors/helpers.ts +5 -6
  52. package/src/feed-replication.ts +1 -0
  53. package/src/index.ts +4 -2
  54. package/src/messenger.ts +22 -0
  55. package/dist/src/edge-error.d.ts.map +0 -1
  56. package/dist/src/edge-error.js.map +0 -1
  57. package/dist/src/edge.d.ts.map +0 -1
  58. package/dist/src/edge.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/protocols",
3
- "version": "0.8.4-main.72ec0f3",
3
+ "version": "0.8.4-main.7ace549",
4
4
  "description": "Protobuf definitions for DXOS protocols.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -60,19 +60,19 @@
60
60
  ],
61
61
  "dependencies": {
62
62
  "@bufbuild/protobuf": "2.9.0",
63
- "@dxos/codec-protobuf": "0.8.4-main.72ec0f3",
64
- "@dxos/effect": "0.8.4-main.72ec0f3",
65
- "@dxos/errors": "0.8.4-main.72ec0f3",
66
- "@dxos/invariant": "0.8.4-main.72ec0f3",
67
- "@dxos/keys": "0.8.4-main.72ec0f3",
68
- "@dxos/util": "0.8.4-main.72ec0f3",
69
- "@dxos/timeframe": "0.8.4-main.72ec0f3"
63
+ "@dxos/codec-protobuf": "0.8.4-main.7ace549",
64
+ "@dxos/effect": "0.8.4-main.7ace549",
65
+ "@dxos/errors": "0.8.4-main.7ace549",
66
+ "@dxos/invariant": "0.8.4-main.7ace549",
67
+ "@dxos/keys": "0.8.4-main.7ace549",
68
+ "@dxos/timeframe": "0.8.4-main.7ace549",
69
+ "@dxos/util": "0.8.4-main.7ace549"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@bufbuild/buf": "1.43.0",
73
73
  "@bufbuild/protoc-gen-es": "2.9.0",
74
74
  "effect": "3.18.3",
75
- "@dxos/protobuf-compiler": "0.8.4-main.72ec0f3"
75
+ "@dxos/protobuf-compiler": "0.8.4-main.7ace549"
76
76
  },
77
77
  "peerDependencies": {
78
78
  "effect": "^3.13.3"
@@ -0,0 +1,165 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type SpaceId } from '@dxos/keys';
6
+
7
+ import { type QueryResult, type QueueQuery } from '../queue';
8
+
9
+ /*
10
+
11
+ API for the edge functions service.
12
+ A function module should be a valid cloudflare worker module.
13
+
14
+ # Fetching metadata (done on deploy)
15
+
16
+ GET http://functions.dxos.internal/
17
+ X-DXOS-Function-Route: meta
18
+
19
+ Expected to return `FunctionMetadata` in JSON:
20
+
21
+ {
22
+ key: string;
23
+ name?: string;
24
+ description?: string;
25
+ inputSchema?: JsonSchemaType;
26
+ outputSchema?: JsonSchemaType;
27
+ }
28
+
29
+ # Invoking the function
30
+
31
+ POST http://functions.dxos.internal/
32
+ Content-Type: application/json
33
+ X-Trace-Queue-Dxn: dxn:queue:trace:AAAAAA:BBBBBB
34
+ X-Invocation-Id: XXXXXXX
35
+ X-Edge-Env: production
36
+
37
+ {input_data}
38
+
39
+ Expected to return `EdgeEnvelope` with the output data:
40
+
41
+ {
42
+ success: true,
43
+ data: unknown
44
+ }
45
+
46
+ On Error returns `EdgeEnvelope` with error:
47
+
48
+ {
49
+ success: false,
50
+ message: string
51
+ error: EncodedError
52
+ }
53
+
54
+ */
55
+
56
+ /**
57
+ * Environment available to the function running on Cloudflare.
58
+ */
59
+ export interface Env {
60
+ QUEUE_SERVICE: QueueService;
61
+ DATA_SERVICE: DataService;
62
+ }
63
+
64
+ /**
65
+ * Use to trace the execution across multiple services.
66
+ *
67
+ * NOTE: Currently unused in functions.
68
+ */
69
+ export interface ExecutionContext {}
70
+
71
+ /**
72
+ * Database API for other CF services like functions.
73
+ */
74
+ export interface DataService {
75
+ getSpaceMeta(ctx: ExecutionContext, spaceId: SpaceId): Promise<SpaceMeta | undefined>;
76
+ getDocument(ctx: ExecutionContext, spaceId: SpaceId, documentId: string): Promise<RawDocument | undefined>;
77
+
78
+ query(ctx: ExecutionContext, request: QueryRequest): Promise<QueryResponse>;
79
+ queryDocuments(ctx: ExecutionContext, request: QueryRequest): Promise<QueryDocumentsResponse>;
80
+ queryReferences(ctx: ExecutionContext, request: QueryReferencesRequest): Promise<QueryReferencesResponse>;
81
+
82
+ // TODO(burdon): Update? Return DocumentEntry?
83
+ changeDocument(ctx: ExecutionContext, spaceId: SpaceId, documentId: string, changes: Uint8Array): Promise<void>;
84
+ }
85
+
86
+ export interface QueueService {
87
+ query(ctx: ExecutionContext, queueDXN: string, query: Omit<QueueQuery, 'queueId'>): Promise<QueryResult>;
88
+ append(ctx: ExecutionContext, queueDXN: string, objects: unknown[]): Promise<void>;
89
+ }
90
+
91
+ export type ObjectDocumentJson = {
92
+ type?: string;
93
+ objectId: string;
94
+ documentId: string;
95
+ /** Base64 encoding of a document. */
96
+ document: string;
97
+ };
98
+
99
+ export type SpaceMeta = {
100
+ spaceKey: string;
101
+ rootDocumentId: string;
102
+ };
103
+
104
+ export type QueryRequest = {
105
+ spaceId: string;
106
+ type?: string;
107
+ where?: Record<string, any>;
108
+ objectIds?: string[];
109
+ cursor?: string;
110
+ limit?: number;
111
+ };
112
+
113
+ export type QueryResponse = {
114
+ results: ObjectSnapshot[];
115
+ cursor?: string;
116
+ };
117
+
118
+ /**
119
+ * TODO(yaroslav): make Indexer return EchoObject after create() can properly reconstruct an object
120
+ * from this structure (meta, id and type aren't handled properly)
121
+ */
122
+ export type ObjectSnapshot = {
123
+ type?: string;
124
+ documentId: string;
125
+ objectId: string;
126
+ // TODO(mykola): Use ObjectStructure from @dxos/echo-protocol.
127
+ object: unknown;
128
+ };
129
+
130
+ export type ObjectReference = {
131
+ fromId: string;
132
+ toId: string;
133
+ fieldName: string;
134
+ };
135
+
136
+ export type QueryDocumentsResponse = {
137
+ results: RawObject[];
138
+ cursor?: string;
139
+ };
140
+
141
+ export type RawDocument = {
142
+ documentId: string;
143
+ data: Uint8Array;
144
+ };
145
+
146
+ export type RawObject = {
147
+ type?: string;
148
+ objectId: string;
149
+ document: RawDocument;
150
+ };
151
+
152
+ export type QueryReferencesRequest = {
153
+ spaceId: string;
154
+ objectId: string;
155
+ referenceType: 'from' | 'to';
156
+ };
157
+
158
+ export type QueryReferencesResponse = {
159
+ references: ObjectReference[];
160
+ };
161
+
162
+ export type CreateDocumentResponse = {
163
+ /** Automerge document ID. */
164
+ documentId: string;
165
+ };
@@ -40,8 +40,8 @@ export type EdgeErrorData = { type: string } & Record<string, any>;
40
40
  // TODO(dmaretskyi): Refactor this type to just be { success: false, error: SerializedError }
41
41
  // reason -> error.message
42
42
  // cause -> error.cause
43
- // errorData.type -> error.code
44
- // ...errorData -> error.context
43
+ // data.type -> error.code
44
+ // ...data -> error.context
45
45
  export type EdgeFailure = {
46
46
  /**
47
47
  * Branded Type.
@@ -50,11 +50,11 @@ export type EdgeFailure = {
50
50
  /**
51
51
  * An explanation of why the call failed. Used mostly for logging and monitoring.
52
52
  */
53
- reason: string;
53
+ message: string;
54
54
  /**
55
55
  * Cause Error captured on the EDGE service to aid debugging on the client.
56
56
  */
57
- cause?: SerializedError;
57
+ error?: SerializedError;
58
58
  /**
59
59
  * Information that can be used to retry the request such that it will succeed, for example:
60
60
  * 1. { type: 'auth_required', challenge: string }
@@ -62,16 +62,16 @@ export type EdgeFailure = {
62
62
  * 2. { type: 'user_confirmation_required', dialog: { title: string, message: string, confirmation_payload: string } }
63
63
  * Requires showing a confirmation dialog to a user and retrying the request with confirmation_payload included
64
64
  * if the user confirms.
65
- * When errorData is returned simply retrying the request won't have any effect.
66
- * EdgeHttpClient should parse well-known errorData into Error types and throw.
65
+ * When data is returned simply retrying the request won't have any effect.
66
+ * EdgeHttpClient should parse well-known data into Error types and throw.
67
67
  */
68
- errorData?: EdgeErrorData;
68
+ data?: EdgeErrorData;
69
69
  };
70
70
 
71
71
  /**
72
72
  * Represents a body response from the Edge service.
73
73
  */
74
- export type EdgeBody<T> = EdgeSuccess<T> | EdgeFailure;
74
+ export type EdgeEnvelope<T> = EdgeSuccess<T> | EdgeFailure;
75
75
 
76
76
  /**
77
77
  * Use this to create a response from the Edge service.
@@ -92,21 +92,32 @@ export const EdgeResponse = Object.freeze({
92
92
  );
93
93
  },
94
94
  failure: ({
95
- reason,
96
- cause,
97
- errorData,
95
+ message,
96
+ error,
97
+ errorEncoded,
98
+ data,
98
99
  shouldRetryAfter,
99
100
  status = 500,
100
101
  }: {
101
102
  /**
102
103
  * An explanation of why the call failed. Used mostly for logging and monitoring.
103
104
  */
104
- reason: string;
105
+ message: string;
105
106
  /**
106
107
  * Error that caused the failure.
107
108
  * Useful for debugging.
109
+ *
110
+ * Use only one of the fields `error` or `errorEncoded`.s
111
+ */
112
+ error?: Error;
113
+ /**
114
+ * Encoded Error that caused the failure.
115
+ * Useful for debugging.
116
+ *
117
+ * Use only one of the fields `error` or `errorEncoded`.
108
118
  */
109
- cause?: Error;
119
+ errorEncoded?: SerializedError;
120
+
110
121
  /**
111
122
  * Information that can be used to retry the request such that it will succeed, for example:
112
123
  * 1. { type: 'auth_required', challenge: string }
@@ -114,10 +125,10 @@ export const EdgeResponse = Object.freeze({
114
125
  * 2. { type: 'user_confirmation_required', dialog: { title: string, message: string, confirmation_payload: string } }
115
126
  * Requires showing a confirmation dialog to a user and retrying the request with confirmation_payload included
116
127
  * if the user confirms.
117
- * When errorData is returned simply retrying the request won't have any effect.
118
- * EdgeHttpClient should parse well-known errorData into Error types and throw.
128
+ * When data is returned simply retrying the request won't have any effect.
129
+ * EdgeHttpClient should parse well-known data into Error types and throw.
119
130
  */
120
- errorData?: EdgeErrorData;
131
+ data?: EdgeErrorData;
121
132
  /**
122
133
  * If provided, this request will be marked as retryable and the client will wait for the specified number of milliseconds before retrying.
123
134
  * If not provided, the client will not retry the request.
@@ -138,9 +149,9 @@ export const EdgeResponse = Object.freeze({
138
149
  return new Response(
139
150
  JSON.stringify({
140
151
  success: false,
141
- reason,
142
- errorData,
143
- cause: cause ? ErrorCodec.encode(cause) : undefined,
152
+ message,
153
+ data,
154
+ error: error ? ErrorCodec.encode(error) : errorEncoded,
144
155
  } satisfies EdgeFailure),
145
156
  {
146
157
  status,
@@ -16,11 +16,11 @@ import { type EdgeErrorData, type EdgeFailure, EdgeHttpErrorCodec, ErrorCodec }
16
16
  export class EdgeCallFailedError extends Error {
17
17
  public static fromUnsuccessfulResponse(response: Response, body: EdgeFailure): EdgeCallFailedError {
18
18
  const error = new EdgeCallFailedError({
19
- reason: body.reason,
20
- errorData: body.errorData,
21
- isRetryable: body.errorData == null && response.headers.has('Retry-After'),
19
+ message: body.message,
20
+ data: body.data,
21
+ isRetryable: body.data == null && response.headers.has('Retry-After'),
22
22
  retryAfterMs: getRetryAfterMillis(response),
23
- cause: body.cause ? ErrorCodec.decode(body.cause) : undefined,
23
+ cause: body.error ? ErrorCodec.decode(body.error) : undefined,
24
24
  });
25
25
 
26
26
  return error;
@@ -28,7 +28,7 @@ export class EdgeCallFailedError extends Error {
28
28
 
29
29
  public static async fromHttpFailure(response: Response): Promise<EdgeCallFailedError> {
30
30
  return new EdgeCallFailedError({
31
- reason: `HTTP code ${response.status}: ${response.statusText}.`,
31
+ message: `HTTP code ${response.status}: ${response.statusText}.`,
32
32
  isRetryable: isRetryableCode(response.status),
33
33
  retryAfterMs: getRetryAfterMillis(response),
34
34
  cause: await EdgeHttpErrorCodec.decode(response),
@@ -37,27 +37,26 @@ export class EdgeCallFailedError extends Error {
37
37
 
38
38
  public static fromProcessingFailureCause(cause: Error): EdgeCallFailedError {
39
39
  return new EdgeCallFailedError({
40
- reason: 'Error processing request.',
40
+ message: 'Error processing request.',
41
41
  isRetryable: true,
42
42
  cause,
43
43
  });
44
44
  }
45
45
 
46
- readonly reason: string;
47
- readonly errorData?: EdgeErrorData;
46
+ readonly data?: EdgeErrorData;
48
47
  readonly isRetryable?: boolean;
49
48
  readonly retryAfterMs?: number;
50
49
 
51
50
  constructor(args: {
52
- reason: string;
51
+ message: string;
53
52
  isRetryable?: boolean;
54
- errorData?: EdgeErrorData;
53
+ data?: EdgeErrorData;
55
54
  retryAfterMs?: number;
56
55
  cause?: Error;
57
56
  }) {
58
- super(args.reason, { cause: args.cause });
59
- this.reason = args.reason;
60
- this.errorData = args.errorData;
57
+ super(args.message, { cause: args.cause });
58
+ this.message = args.message;
59
+ this.data = args.data;
61
60
  this.retryAfterMs = args.retryAfterMs;
62
61
  this.isRetryable = Boolean(args.isRetryable);
63
62
  }
@@ -66,9 +65,9 @@ export class EdgeCallFailedError extends Error {
66
65
  export class EdgeAuthChallengeError extends EdgeCallFailedError {
67
66
  constructor(
68
67
  public readonly challenge: string,
69
- errorData: EdgeErrorData,
68
+ data: EdgeErrorData,
70
69
  ) {
71
- super({ reason: 'Auth challenge.', errorData, isRetryable: false });
70
+ super({ message: 'Auth challenge.', data, isRetryable: false });
72
71
  }
73
72
  }
74
73
 
@@ -0,0 +1,7 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './edge.js';
6
+ export * as EdgeFunctionEnv from './EdgeFunctionEnv.js';
7
+ export * from './errors.js';
@@ -2,43 +2,25 @@
2
2
  // Copyright 2021 DXOS.org
3
3
  //
4
4
 
5
- // TODO(dmaretskyi): Reconcile with @dxos/errors
6
-
7
5
  /**
8
6
  * NOTE: Messages should be sentences (Start with a capital letter and end with a period).
9
7
  * Errors can optionally include a JSON context object.
10
8
  */
11
- export class BaseError extends Error {
12
- constructor(
13
- readonly code: string,
14
- message?: string,
15
- readonly context?: Record<string, any>,
16
- ) {
17
- // TODO(dmaretskyi): Error.cause.
18
- super(message ?? code);
19
- this.name = code;
20
- // NOTE: Restores prototype chain (https://stackoverflow.com/a/48342359).
21
- Object.setPrototypeOf(this, new.target.prototype);
22
- }
23
- }
24
-
25
- // TODO(dmaretskyi): Consider common error classes with error codes:
26
- // throw new SystemError(ERROR_CODE_OUT_OF_MEMORY, 'Out of memory', { a: 1, b: 2 });
9
+ import { BaseError } from '@dxos/errors';
27
10
 
28
11
  /**
29
12
  * User facing API Errors.
30
13
  * E.g., something was misconfigured.
31
14
  */
32
- export class ApiError extends BaseError {}
15
+ export class ApiError extends BaseError.extend('API') {}
33
16
 
34
17
  /**
35
18
  * Internal system errors.
36
19
  * E.g., unexpected/unrecoverable runtime error.
37
20
  */
38
- export class SystemError extends BaseError {}
21
+ export class SystemError extends BaseError.extend('SYSTEM') {}
39
22
 
40
23
  /**
41
24
  * Database errors.
42
25
  */
43
- // TODO(wittjosiah): Same as ApiError?
44
- export class DatabaseError extends BaseError {}
26
+ export class DatabaseError extends BaseError.extend('DATABASE') {}
@@ -9,7 +9,7 @@ import { ApiError } from './base-errors.js';
9
9
  describe('Errors', () => {
10
10
  test('test', async () => {
11
11
  const runTest = async () => {
12
- throw new ApiError('Test error');
12
+ throw new ApiError({ message: 'Test error' });
13
13
  };
14
14
 
15
15
  await expect(runTest()).rejects.toThrowError('Test error');