@synnaxlabs/freighter 0.23.0 → 0.25.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/dist/http.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { UnaryClient } from './unary';
2
- import { MiddlewareCollector } from './middleware';
3
- import { z } from 'zod';
4
1
  import { binary, URL } from '@synnaxlabs/x';
2
+ import { z } from 'zod';
3
+ import { MiddlewareCollector } from './middleware';
4
+ import { UnaryClient } from './unary';
5
5
 
6
6
  export declare const CONTENT_TYPE_HEADER_KEY = "Content-Type";
7
7
  /**
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export type { ErrorPayload, TypedError } from './errors';
2
- export { BaseTypedError, decodeError, encodeError, EOF, errorZ, registerError, StreamClosed, Unreachable, } from './errors';
1
+ export type { ErrorPayload, MatchableErrorType, TypedError } from './errors';
2
+ export { BaseTypedError, decodeError, encodeError, EOF, errorMatcher, errorZ, registerError, StreamClosed, Unreachable, } from './errors';
3
3
  export { HTTPClient } from './http';
4
4
  export type { Context, Middleware, Next } from './middleware';
5
5
  export type { Stream, StreamClient } from './stream';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,EACL,cAAc,EACd,WAAW,EACX,WAAW,EACX,GAAG,EACH,MAAM,EACN,aAAa,EACb,YAAY,EACZ,WAAW,GACZ,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAC9D,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC7E,OAAO,EACL,cAAc,EACd,WAAW,EACX,WAAW,EACX,GAAG,EACH,YAAY,EACZ,MAAM,EACN,aAAa,EACb,YAAY,EACZ,WAAW,GACZ,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAC9D,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
package/dist/stream.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Transport } from './transport';
2
1
  import { z } from 'zod';
2
+ import { Transport } from './transport';
3
3
 
4
4
  /**
5
5
  * Interface for an entity that receives a stream of responses.
package/dist/unary.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Transport } from './transport';
2
1
  import { z } from 'zod';
2
+ import { Transport } from './transport';
3
3
 
4
4
  /**
5
5
  * An interface for an entity that implements a simple request-response
@@ -1 +1 @@
1
- {"version":3,"file":"unary.d.ts","sourceRoot":"","sources":["../src/unary.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C;;;;;OAKG;IACH,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,UAAU,EAAE,EAAE,SAAS,CAAC,CAAC,UAAU,GAAG,EAAE,EAC1D,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAC/B,SAAS,EAAE,EAAE,EACb,SAAS,EAAE,EAAE,KACV,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;CACpD;AAED,eAAO,MAAM,YAAY,kEAIf,WAAW,UACX,MAAM,OACT,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,aACpB,EAAE,aACF,EAAE,KACZ,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAItB,CAAC"}
1
+ {"version":3,"file":"unary.d.ts","sourceRoot":"","sources":["../src/unary.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C;;;;;OAKG;IACH,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,UAAU,EAAE,EAAE,SAAS,CAAC,CAAC,UAAU,GAAG,EAAE,EAC1D,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAC/B,SAAS,EAAE,EAAE,EACb,SAAS,EAAE,EAAE,KACV,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;CACpD;AAED,eAAO,MAAM,YAAY,GACvB,EAAE,SAAS,CAAC,CAAC,UAAU,EACvB,EAAE,SAAS,CAAC,CAAC,UAAU,eAEf,WAAW,UACX,MAAM,OACT,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,aACpB,EAAE,aACF,EAAE,KACZ,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAItB,CAAC"}
@@ -1,7 +1,7 @@
1
- import { Stream, StreamClient } from './stream';
2
- import { MiddlewareCollector } from './middleware';
3
- import { z } from 'zod';
4
1
  import { binary, URL } from '@synnaxlabs/x';
2
+ import { z } from 'zod';
3
+ import { MiddlewareCollector } from './middleware';
4
+ import { Stream, StreamClient } from './stream';
5
5
 
6
6
  export declare const FREIGHTER_METADATA_PREFIX = "freighterctx";
7
7
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synnaxlabs/freighter",
3
- "version": "0.23.0",
3
+ "version": "0.25.0",
4
4
  "type": "module",
5
5
  "description": "a modular transport abstraction",
6
6
  "repository": "https://github.com/synnaxlabs/synnax/tree/main/freighter/ts",
@@ -17,8 +17,8 @@
17
17
  "node-fetch": "2.6.11",
18
18
  "ws": "^8.17.0",
19
19
  "zod": "3.23.8",
20
- "@synnaxlabs/alamos": "0.23.0",
21
- "@synnaxlabs/x": "0.23.0"
20
+ "@synnaxlabs/alamos": "0.25.0",
21
+ "@synnaxlabs/x": "0.25.0"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/node": "^20.12.7",
@@ -26,8 +26,8 @@
26
26
  "typescript": "^5.4.5",
27
27
  "vite": "5.2.11",
28
28
  "vitest": "^1.5.0",
29
- "@synnaxlabs/tsconfig": "0.0.2",
30
29
  "@synnaxlabs/vite-plugin": "0.0.1",
30
+ "@synnaxlabs/tsconfig": "0.0.2",
31
31
  "eslint-config-synnaxlabs": "0.0.1"
32
32
  },
33
33
  "peerDependencies": {
@@ -28,12 +28,14 @@ import {
28
28
  } from "@/errors";
29
29
 
30
30
  class MyCustomError extends BaseTypedError {
31
+ type = "MyCustomError";
31
32
  constructor(message: string) {
32
- super(message, "MyCustomError");
33
+ super(message);
33
34
  }
34
35
  }
35
36
 
36
- const myCustomErrorEncoder = (error: MyCustomError): ErrorPayload => {
37
+ const myCustomErrorEncoder = (error: MyCustomError): ErrorPayload | null => {
38
+ if (error.type !== "MyCustomError") return null;
37
39
  return { type: "MyCustomError", data: error.message };
38
40
  };
39
41
 
package/src/errors.ts CHANGED
@@ -10,6 +10,15 @@
10
10
  import { URL } from "@synnaxlabs/x";
11
11
  import { z } from "zod";
12
12
 
13
+ /** Basic interface for an error or error type that can be matched against a candidate error */
14
+ export interface MatchableErrorType {
15
+ /**
16
+ * @returns a function that matches errors of the given type. Returns true if
17
+ * the provided instance of Error or a string message contains the provided error type.
18
+ */
19
+ matches: (e: string | Error | unknown) => boolean;
20
+ }
21
+
13
22
  export interface TypedError extends Error {
14
23
  discriminator: "FreighterError";
15
24
  /**
@@ -19,13 +28,27 @@ export interface TypedError extends Error {
19
28
  type: string;
20
29
  }
21
30
 
31
+ /**
32
+ * @param type - the error type to match
33
+ * @returns a function that matches errors of the given type. Returns true if
34
+ * the provided instance of Error or a string message contains the provided error type.
35
+ */
36
+ export const errorMatcher =
37
+ (type: string) =>
38
+ (e: string | Error | unknown): boolean => {
39
+ if (e != null && typeof e === "object" && "type" in e && typeof e.type === "string")
40
+ return e.type.includes(type);
41
+ if (e instanceof Error) return e.message.includes(type);
42
+ if (typeof e !== "string") return false;
43
+ return e.includes(type);
44
+ };
45
+
22
46
  export class BaseTypedError extends Error implements TypedError {
23
47
  readonly discriminator = "FreighterError";
24
- type: string;
48
+ type: string = "";
25
49
 
26
- constructor(message: string, type: string) {
50
+ constructor(message?: string) {
27
51
  super(message);
28
- this.type = type;
29
52
  }
30
53
  }
31
54
 
@@ -138,8 +161,9 @@ export const decodeError = (payload: ErrorPayload): Error | null => {
138
161
  };
139
162
 
140
163
  export class UnknownError extends BaseTypedError implements TypedError {
164
+ type = "unknown";
141
165
  constructor(message: string) {
142
- super(message, UNKNOWN);
166
+ super(message);
143
167
  }
144
168
  }
145
169
 
@@ -148,18 +172,22 @@ const FREIGHTER_ERROR_TYPE = "freighter.";
148
172
  /** Thrown/returned when a stream closed normally. */
149
173
  export class EOF extends BaseTypedError implements TypedError {
150
174
  static readonly TYPE = FREIGHTER_ERROR_TYPE + "eof";
175
+ type = EOF.TYPE;
176
+ static readonly matches = errorMatcher(EOF.TYPE);
151
177
 
152
178
  constructor() {
153
- super("EOF", FREIGHTER);
179
+ super("EOF");
154
180
  }
155
181
  }
156
182
 
157
183
  /** Thrown/returned when a stream is closed abnormally. */
158
184
  export class StreamClosed extends BaseTypedError implements TypedError {
159
185
  static readonly TYPE = FREIGHTER_ERROR_TYPE + "stream_closed";
186
+ static readonly matches = errorMatcher(StreamClosed.TYPE);
187
+ type = StreamClosed.TYPE;
160
188
 
161
189
  constructor() {
162
- super("StreamClosed", FREIGHTER);
190
+ super("StreamClosed");
163
191
  }
164
192
  }
165
193
 
@@ -171,21 +199,23 @@ export interface UnreachableArgs {
171
199
  /** Thrown when a target is unreachable. */
172
200
  export class Unreachable extends BaseTypedError implements TypedError {
173
201
  static readonly TYPE = FREIGHTER_ERROR_TYPE + "unreachable";
202
+ type = Unreachable.TYPE;
203
+ static readonly matches = errorMatcher(Unreachable.TYPE);
174
204
  url: URL;
175
205
 
176
206
  constructor(args: UnreachableArgs = {}) {
177
207
  const { message = "Unreachable", url = URL.UNKNOWN } = args;
178
- super(message, FREIGHTER);
208
+ super(message);
179
209
  this.url = url;
180
210
  }
181
211
  }
182
212
 
183
213
  const freighterErrorEncoder: ErrorEncoder = (error: TypedError) => {
184
- if (error.type !== FREIGHTER) return null;
185
- if (error instanceof EOF) return { type: EOF.TYPE, data: "EOF" };
186
- if (error instanceof StreamClosed)
214
+ if (!error.type.startsWith(FREIGHTER)) return null;
215
+ if (EOF.matches(error)) return { type: EOF.TYPE, data: "EOF" };
216
+ if (StreamClosed.matches(error))
187
217
  return { type: StreamClosed.TYPE, data: "StreamClosed" };
188
- if (error instanceof Unreachable)
218
+ if (Unreachable.matches(error))
189
219
  return { type: Unreachable.TYPE, data: "Unreachable" };
190
220
  throw new Error(`Unknown error type: ${error.type}: ${error.message}`);
191
221
  };
package/src/index.ts CHANGED
@@ -7,12 +7,13 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
- export type { ErrorPayload, TypedError } from "@/errors";
10
+ export type { ErrorPayload, MatchableErrorType, TypedError } from "@/errors";
11
11
  export {
12
12
  BaseTypedError,
13
13
  decodeError,
14
14
  encodeError,
15
15
  EOF,
16
+ errorMatcher,
16
17
  errorZ,
17
18
  registerError,
18
19
  StreamClosed,
@@ -35,9 +35,10 @@ const client = new WebSocketClient(url, new binary.JSONEncoderDecoder());
35
35
 
36
36
  class MyCustomError extends BaseTypedError {
37
37
  code: number;
38
+ type = "integration.error";
38
39
 
39
40
  constructor(message: string, code: number) {
40
- super(message, "integration.error");
41
+ super(message);
41
42
  this.code = code;
42
43
  }
43
44
  }