@fabriktor/client 0.0.14 → 0.0.15

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.
@@ -3,13 +3,14 @@
3
3
  // Licensed under the Apache License, Version 2.0 (the "License"); you may
4
4
  // not use this file except in compliance with the License. You may obtain
5
5
  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ import { errAuthTokenEmpty, errAuthTokenProviderMissing } from "./err.js";
6
7
  export async function requiredToken(getToken) {
7
8
  if (!getToken) {
8
- throw new Error("Authenticated client method requires a token provider.");
9
+ throw errAuthTokenProviderMissing();
9
10
  }
10
11
  const out = await getToken();
11
12
  if (!out) {
12
- throw new Error("Authenticated client method received an empty token.");
13
+ throw errAuthTokenEmpty();
13
14
  }
14
15
  return out;
15
16
  }
@@ -1,13 +1,36 @@
1
1
  import type { HTTPErr, WrenchErr } from "@fabriktor/schema";
2
+ export declare const ClientErrKind: {
3
+ readonly AuthTokenProviderMissing: "auth_token_provider_missing";
4
+ readonly AuthTokenEmpty: "auth_token_empty";
5
+ readonly HTTPError: "http_error";
6
+ readonly HTTPRequestFailed: "http_request_failed";
7
+ readonly HTTPResponseInvalid: "http_response_invalid";
8
+ readonly Unknown: "unknown";
9
+ };
10
+ export type ClientErrKind = (typeof ClientErrKind)[keyof typeof ClientErrKind];
2
11
  export type ClientErrOptions = {
3
- code: number;
12
+ kind: ClientErrKind;
4
13
  msg: string;
14
+ status?: number;
5
15
  app_err?: WrenchErr;
16
+ cause?: unknown;
6
17
  };
7
18
  export declare class ClientErr extends Error {
8
- code: number;
9
- app_err?: WrenchErr;
19
+ readonly kind: ClientErrKind;
20
+ readonly status?: number;
21
+ readonly app_err?: WrenchErr;
22
+ readonly cause?: unknown;
10
23
  constructor(opts: ClientErrOptions);
11
24
  }
12
- export declare function newClientErr(opts: ClientErrOptions): ClientErr;
13
- export declare function newClientErrFromHTTP(err: HTTPErr): ClientErr;
25
+ export declare function errClient(opts: ClientErrOptions): ClientErr;
26
+ export declare function errFromHTTP(err: HTTPErr): ClientErr;
27
+ export declare function errAuthTokenProviderMissing(): ClientErr;
28
+ export declare function errAuthTokenEmpty(): ClientErr;
29
+ export declare function errHTTPRequestFailed(cause: unknown): ClientErr;
30
+ export declare function errHTTPResponseInvalid(cause?: unknown): ClientErr;
31
+ export declare function errUnknown(cause: unknown): ClientErr;
32
+ export declare function isClientErr(err: unknown): err is ClientErr;
33
+ export declare function isHTTPClientErr(err: unknown): err is ClientErr;
34
+ export declare function isUnauthorizedClientErr(err: unknown): boolean;
35
+ export declare function isNotFoundClientErr(err: unknown): boolean;
36
+ export declare function clientErrMessage(err: unknown): string;
@@ -3,23 +3,101 @@
3
3
  // Licensed under the Apache License, Version 2.0 (the "License"); you may
4
4
  // not use this file except in compliance with the License. You may obtain
5
5
  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ const msgUnknownClientErr = "Unknown client error.";
7
+ export const ClientErrKind = {
8
+ AuthTokenProviderMissing: "auth_token_provider_missing",
9
+ AuthTokenEmpty: "auth_token_empty",
10
+ HTTPError: "http_error",
11
+ HTTPRequestFailed: "http_request_failed",
12
+ HTTPResponseInvalid: "http_response_invalid",
13
+ Unknown: "unknown",
14
+ };
6
15
  export class ClientErr extends Error {
7
- code;
16
+ kind;
17
+ status;
8
18
  app_err;
19
+ cause;
9
20
  constructor(opts) {
10
21
  super(opts.msg);
11
22
  this.name = new.target.name;
12
- this.code = opts.code;
23
+ this.kind = opts.kind;
24
+ this.status = opts.status;
13
25
  this.app_err = opts.app_err;
26
+ this.cause = opts.cause;
14
27
  }
15
28
  }
16
- export function newClientErr(opts) {
29
+ export function errClient(opts) {
17
30
  return new ClientErr(opts);
18
31
  }
19
- export function newClientErrFromHTTP(err) {
20
- return newClientErr({
21
- code: err.code,
32
+ export function errFromHTTP(err) {
33
+ return errClient({
34
+ kind: ClientErrKind.HTTPError,
35
+ status: err.code,
22
36
  msg: err.msg,
23
37
  app_err: err.app_err,
24
38
  });
25
39
  }
40
+ export function errAuthTokenProviderMissing() {
41
+ return errClient({
42
+ kind: ClientErrKind.AuthTokenProviderMissing,
43
+ msg: "Authenticated client method requires a token provider.",
44
+ });
45
+ }
46
+ export function errAuthTokenEmpty() {
47
+ return errClient({
48
+ kind: ClientErrKind.AuthTokenEmpty,
49
+ msg: "Authenticated client method received an empty token.",
50
+ });
51
+ }
52
+ export function errHTTPRequestFailed(cause) {
53
+ return errClient({
54
+ kind: ClientErrKind.HTTPRequestFailed,
55
+ msg: "HTTP request failed.",
56
+ cause,
57
+ });
58
+ }
59
+ export function errHTTPResponseInvalid(cause) {
60
+ return errClient({
61
+ kind: ClientErrKind.HTTPResponseInvalid,
62
+ msg: "HTTP response is invalid.",
63
+ cause,
64
+ });
65
+ }
66
+ export function errUnknown(cause) {
67
+ if (isClientErr(cause)) {
68
+ return cause;
69
+ }
70
+ if (cause instanceof Error) {
71
+ return errClient({
72
+ kind: ClientErrKind.Unknown,
73
+ msg: cause.message,
74
+ cause,
75
+ });
76
+ }
77
+ return errClient({
78
+ kind: ClientErrKind.Unknown,
79
+ msg: msgUnknownClientErr,
80
+ cause,
81
+ });
82
+ }
83
+ export function isClientErr(err) {
84
+ return err instanceof ClientErr;
85
+ }
86
+ export function isHTTPClientErr(err) {
87
+ return isClientErr(err) && err.kind === ClientErrKind.HTTPError;
88
+ }
89
+ export function isUnauthorizedClientErr(err) {
90
+ return isClientErr(err) && err.status === 401;
91
+ }
92
+ export function isNotFoundClientErr(err) {
93
+ return isClientErr(err) && err.status === 404;
94
+ }
95
+ export function clientErrMessage(err) {
96
+ if (isClientErr(err)) {
97
+ return err.message;
98
+ }
99
+ if (err instanceof Error) {
100
+ return err.message;
101
+ }
102
+ return msgUnknownClientErr;
103
+ }
@@ -4,7 +4,7 @@
4
4
  // not use this file except in compliance with the License. You may obtain
5
5
  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
6
  import { MimeJSON, } from "@fabriktor/schema";
7
- import { newClientErrFromHTTP } from "./err.js";
7
+ import { errFromHTTP, errHTTPRequestFailed, errHTTPResponseInvalid, } from "./err.js";
8
8
  const headerAuthorization = "authorization";
9
9
  const headerContentType = "content-type";
10
10
  const prefixBearer = "Bearer";
@@ -19,18 +19,29 @@ export class HTTPClient {
19
19
  this.fetcher = opts.fetcher;
20
20
  }
21
21
  async do(opts) {
22
- const res = await this.fetcher.fetch(url(opts.base_url, opts.path), {
23
- method: opts.method,
24
- headers: headers(opts),
25
- body: body(opts.body),
26
- });
22
+ let res;
23
+ try {
24
+ res = await this.fetcher.fetch(url(opts.base_url, opts.path), {
25
+ method: opts.method,
26
+ headers: headers(opts),
27
+ body: body(opts.body),
28
+ });
29
+ }
30
+ catch (err) {
31
+ throw errHTTPRequestFailed(err);
32
+ }
27
33
  if (!res.ok) {
28
34
  return await fail(res);
29
35
  }
30
36
  if (res.body === null) {
31
37
  return undefined;
32
38
  }
33
- return (await res.json());
39
+ try {
40
+ return (await res.json());
41
+ }
42
+ catch (err) {
43
+ throw errHTTPResponseInvalid(err);
44
+ }
34
45
  }
35
46
  }
36
47
  export function newHTTPClient(opts) {
@@ -55,16 +66,25 @@ function body(v) {
55
66
  return v === undefined ? undefined : JSON.stringify(v);
56
67
  }
57
68
  async function fail(res) {
58
- const txt = await res.text();
59
- let out;
69
+ const txt = await text(res);
70
+ throw errFromHTTP(httpErr(res, txt));
71
+ }
72
+ async function text(res) {
73
+ try {
74
+ return await res.text();
75
+ }
76
+ catch (err) {
77
+ throw errHTTPResponseInvalid(err);
78
+ }
79
+ }
80
+ function httpErr(res, txt) {
60
81
  try {
61
- out = JSON.parse(txt);
82
+ return JSON.parse(txt);
62
83
  }
63
84
  catch {
64
- out = {
85
+ return {
65
86
  code: res.status,
66
87
  msg: txt || res.statusText || res.status.toString(),
67
88
  };
68
89
  }
69
- throw newClientErrFromHTTP(out);
70
90
  }
@@ -8,9 +8,6 @@ export type ResolveUsernameOptions = PLUsersResolveUsername;
8
8
  export type ForgotPasswordOptions = PLUsersForgotPassword;
9
9
  export type SendSignInLinkOptions = PLUsersSignInLink;
10
10
  export type MatchOptions = PLUsersContactList;
11
- export type MatchResult = {
12
- users: User[];
13
- };
14
11
  export type SearchOptions = {
15
12
  q: string;
16
13
  limit?: number;
@@ -25,7 +22,7 @@ export interface UsersOperator {
25
22
  forgotPassword(opts: ForgotPasswordOptions): Promise<void>;
26
23
  sendSignInLink(opts: SendSignInLinkOptions): Promise<void>;
27
24
  resolveUsername(opts: ResolveUsernameOptions): Promise<Op<string>>;
28
- match(opts: MatchOptions): Promise<Op<MatchResult>>;
25
+ match(opts: MatchOptions): Promise<Op<User[]>>;
29
26
  search(opts: SearchOptions): Promise<Op<User[]>>;
30
27
  getByUID(opts: GetByUIDOptions): Promise<Op<User>>;
31
28
  }
@@ -45,7 +42,7 @@ export declare class UsersClient implements UsersOperator {
45
42
  forgotPassword(opts: ForgotPasswordOptions): Promise<void>;
46
43
  sendSignInLink(opts: SendSignInLinkOptions): Promise<void>;
47
44
  resolveUsername(opts: ResolveUsernameOptions): Promise<Op<string>>;
48
- match(opts: MatchOptions): Promise<Op<MatchResult>>;
45
+ match(opts: MatchOptions): Promise<Op<User[]>>;
49
46
  search(opts: SearchOptions): Promise<Op<User[]>>;
50
47
  getByUID(opts: GetByUIDOptions): Promise<Op<User>>;
51
48
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fabriktor/client",
3
- "version": "0.0.14",
3
+ "version": "0.0.15",
4
4
  "description": "![Fabriktor Logo](./img/fabriktor-character.gif)",
5
5
  "type": "module",
6
6
  "exports": {