@atproto/xrpc-server 0.10.20 → 0.11.0-next.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.
Files changed (83) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/auth.js +25 -65
  3. package/dist/auth.js.map +1 -1
  4. package/dist/errors.d.ts.map +1 -1
  5. package/dist/errors.js +59 -85
  6. package/dist/errors.js.map +1 -1
  7. package/dist/index.d.ts +8 -8
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +7 -28
  10. package/dist/index.js.map +1 -1
  11. package/dist/logger.js +4 -7
  12. package/dist/logger.js.map +1 -1
  13. package/dist/rate-limiter.d.ts +1 -1
  14. package/dist/rate-limiter.d.ts.map +1 -1
  15. package/dist/rate-limiter.js +27 -91
  16. package/dist/rate-limiter.js.map +1 -1
  17. package/dist/server.d.ts +4 -4
  18. package/dist/server.d.ts.map +1 -1
  19. package/dist/server.js +94 -178
  20. package/dist/server.js.map +1 -1
  21. package/dist/stream/frames.d.ts +1 -1
  22. package/dist/stream/frames.d.ts.map +1 -1
  23. package/dist/stream/frames.js +20 -50
  24. package/dist/stream/frames.js.map +1 -1
  25. package/dist/stream/index.d.ts +5 -5
  26. package/dist/stream/index.d.ts.map +1 -1
  27. package/dist/stream/index.js +5 -21
  28. package/dist/stream/index.js.map +1 -1
  29. package/dist/stream/logger.js +3 -6
  30. package/dist/stream/logger.js.map +1 -1
  31. package/dist/stream/server.d.ts +3 -2
  32. package/dist/stream/server.d.ts.map +1 -1
  33. package/dist/stream/server.js +12 -22
  34. package/dist/stream/server.js.map +1 -1
  35. package/dist/stream/stream.d.ts +2 -2
  36. package/dist/stream/stream.d.ts.map +1 -1
  37. package/dist/stream/stream.js +12 -18
  38. package/dist/stream/stream.js.map +1 -1
  39. package/dist/stream/subscription.d.ts +1 -1
  40. package/dist/stream/subscription.d.ts.map +1 -1
  41. package/dist/stream/subscription.js +9 -18
  42. package/dist/stream/subscription.js.map +1 -1
  43. package/dist/stream/types.js +12 -15
  44. package/dist/stream/types.js.map +1 -1
  45. package/dist/types.d.ts +2 -2
  46. package/dist/types.d.ts.map +1 -1
  47. package/dist/types.js +22 -29
  48. package/dist/types.js.map +1 -1
  49. package/dist/util.d.ts +2 -2
  50. package/dist/util.d.ts.map +1 -1
  51. package/dist/util.js +75 -116
  52. package/dist/util.js.map +1 -1
  53. package/{jest.config.js → jest.config.cjs} +8 -2
  54. package/package.json +28 -22
  55. package/src/auth.ts +1 -1
  56. package/src/errors.ts +4 -1
  57. package/src/index.ts +8 -8
  58. package/src/rate-limiter.ts +2 -2
  59. package/src/server.ts +11 -6
  60. package/src/stream/frames.ts +2 -2
  61. package/src/stream/index.ts +5 -5
  62. package/src/stream/server.ts +4 -3
  63. package/src/stream/stream.ts +1 -1
  64. package/src/stream/subscription.ts +2 -2
  65. package/src/types.ts +2 -2
  66. package/src/util.ts +6 -3
  67. package/tests/_util.ts +1 -1
  68. package/tests/auth.test.ts +6 -3
  69. package/tests/bodies.test.ts +4 -3
  70. package/tests/errors.test.ts +2 -2
  71. package/tests/frames.test.ts +1 -1
  72. package/tests/ipld.test.ts +2 -2
  73. package/tests/parameters.test.ts +2 -2
  74. package/tests/parsing.test.ts +1 -1
  75. package/tests/procedures.test.ts +2 -2
  76. package/tests/queries.test.ts +2 -2
  77. package/tests/rate-limiter.test.ts +3 -3
  78. package/tests/responses.test.ts +2 -2
  79. package/tests/stream.test.ts +1 -1
  80. package/tests/subscriptions.test.ts +11 -5
  81. package/tsconfig.build.json +1 -1
  82. package/tsconfig.build.tsbuildinfo +1 -1
  83. package/tsconfig.tests.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
1
  # @atproto/xrpc-server
2
2
 
3
+ ## 0.11.0-next.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#4929](https://github.com/bluesky-social/atproto/pull/4929) [`bb7491c`](https://github.com/bluesky-social/atproto/commit/bb7491c29e06181e1d2f8cf6eb454f9bb8ab961b) Thanks [@devinivy](https://github.com/devinivy)! - **BREAKING:** Drop support for Node.js 18 and 20. Node.js 22 is now the minimum supported version. Docker images now use Node.js 24.
8
+
9
+ - [#4943](https://github.com/bluesky-social/atproto/pull/4943) [`07ae5d4`](https://github.com/bluesky-social/atproto/commit/07ae5d4452df51e045e0239da7a04cf0bc154028) Thanks [@devinivy](https://github.com/devinivy)! - **BREAKING:** Convert to pure ESM. All packages now ship `"type": "module"` with ES module output and Node16 module resolution.
10
+
11
+ Node.js 22's `require()` compatibility layer can still load these packages in CommonJS code.
12
+
13
+ - [#4930](https://github.com/bluesky-social/atproto/pull/4930) [`042df15`](https://github.com/bluesky-social/atproto/commit/042df15087c0e62cd1e715fcbf58852fab875af9) Thanks [@devinivy](https://github.com/devinivy)! - Build with TypeScript 6.0. Emitted `.d.ts` files now use TypeScript 6's stricter `Uint8Array<ArrayBuffer>` typing in places where Web/Node APIs require buffer-backed (not shared-memory) byte arrays. Consumers compiling against these types on older TypeScript should see no runtime impact, but may need to widen or cast in spots that previously relied on `Uint8Array` defaulting to `<ArrayBufferLike>`.
14
+
15
+ Internal: tsconfig `moduleResolution: "node"` is silenced via `ignoreDeprecations: "6.0"` for now; the proper migration to `node16`/`bundler` resolution is deferred.
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies [[`bb7491c`](https://github.com/bluesky-social/atproto/commit/bb7491c29e06181e1d2f8cf6eb454f9bb8ab961b), [`07ae5d4`](https://github.com/bluesky-social/atproto/commit/07ae5d4452df51e045e0239da7a04cf0bc154028), [`042df15`](https://github.com/bluesky-social/atproto/commit/042df15087c0e62cd1e715fcbf58852fab875af9)]:
20
+ - @atproto/common@0.6.0-next.0
21
+ - @atproto/crypto@0.5.0-next.0
22
+ - @atproto/lex-cbor@0.1.0-next.0
23
+ - @atproto/lex-client@0.1.0-next.0
24
+ - @atproto/lex-data@0.1.0-next.0
25
+ - @atproto/lex-json@0.1.0-next.0
26
+ - @atproto/lex-schema@0.1.0-next.0
27
+ - @atproto/lexicon@0.7.0-next.0
28
+ - @atproto/ws-client@0.1.0-next.0
29
+ - @atproto/xrpc@0.8.0-next.0
30
+
31
+ ## 0.10.21
32
+
33
+ ### Patch Changes
34
+
35
+ - Updated dependencies [[`2fd8d62`](https://github.com/bluesky-social/atproto/commit/2fd8d62708dc23de6ed21cbcccfebab68b19f588), [`907edfa`](https://github.com/bluesky-social/atproto/commit/907edfa1d16b1074bab4dc617d0bd1a810f3da02)]:
36
+ - @atproto/lex-schema@0.0.20
37
+ - @atproto/lex-client@0.0.21
38
+
3
39
  ## 0.10.20
4
40
 
5
41
  ### Patch Changes
package/dist/auth.js CHANGED
@@ -1,48 +1,12 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.cryptoVerifySignatureWithKey = exports.verifyJwt = exports.createServiceAuthHeaders = exports.createServiceJwt = void 0;
37
- const common = __importStar(require("@atproto/common"));
38
- const common_1 = require("@atproto/common");
39
- const crypto = __importStar(require("@atproto/crypto"));
40
- const lex_schema_1 = require("@atproto/lex-schema");
41
- const errors_1 = require("./errors");
42
- const createServiceJwt = async (params) => {
1
+ import * as common from '@atproto/common';
2
+ import { MINUTE } from '@atproto/common';
3
+ import * as crypto from '@atproto/crypto';
4
+ import { isDidString } from '@atproto/lex-schema';
5
+ import { AuthRequiredError } from './errors.js';
6
+ export const createServiceJwt = async (params) => {
43
7
  const { iss, aud, keypair } = params;
44
8
  const iat = params.iat ?? Math.floor(Date.now() / 1e3);
45
- const exp = params.exp ?? iat + common_1.MINUTE / 1e3;
9
+ const exp = params.exp ?? iat + MINUTE / 1e3;
46
10
  const lxm = params.lxm ?? undefined;
47
11
  const jti = await crypto.randomStr(16, 'hex');
48
12
  const header = {
@@ -62,23 +26,21 @@ const createServiceJwt = async (params) => {
62
26
  const sig = Buffer.from(await keypair.sign(toSign));
63
27
  return `${toSignStr}.${sig.toString('base64url')}`;
64
28
  };
65
- exports.createServiceJwt = createServiceJwt;
66
- const createServiceAuthHeaders = async (params) => {
67
- const jwt = await (0, exports.createServiceJwt)(params);
29
+ export const createServiceAuthHeaders = async (params) => {
30
+ const jwt = await createServiceJwt(params);
68
31
  return {
69
32
  headers: { authorization: `Bearer ${jwt}` },
70
33
  };
71
34
  };
72
- exports.createServiceAuthHeaders = createServiceAuthHeaders;
73
35
  const jsonToB64Url = (json) => {
74
36
  return Buffer.from(JSON.stringify(json)).toString('base64url');
75
37
  };
76
- const verifyJwt = async (jwtStr, ownDid, // null indicates to skip the audience check
38
+ export const verifyJwt = async (jwtStr, ownDid, // null indicates to skip the audience check
77
39
  lxm, // null indicates to skip the lxm check
78
- getSigningKey, verifySignatureWithKey = exports.cryptoVerifySignatureWithKey) => {
40
+ getSigningKey, verifySignatureWithKey = cryptoVerifySignatureWithKey) => {
79
41
  const parts = jwtStr.split('.');
80
42
  if (parts.length !== 3) {
81
- throw new errors_1.AuthRequiredError('poorly formatted jwt', 'BadJwt');
43
+ throw new AuthRequiredError('poorly formatted jwt', 'BadJwt');
82
44
  }
83
45
  const header = parseHeader(parts[0]);
84
46
  // The spec does not describe what to do with the "typ" claim. We can,
@@ -92,23 +54,23 @@ getSigningKey, verifySignatureWithKey = exports.cryptoVerifySignatureWithKey) =>
92
54
  // "DPoP" proofs are not meant to be used as service tokens
93
55
  // https://datatracker.ietf.org/doc/html/rfc9449
94
56
  header['typ'] === 'dpop+jwt') {
95
- throw new errors_1.AuthRequiredError(`Invalid jwt type "${header['typ']}"`, 'BadJwtType');
57
+ throw new AuthRequiredError(`Invalid jwt type "${header['typ']}"`, 'BadJwtType');
96
58
  }
97
59
  const payload = parsePayload(parts[1]);
98
60
  const sig = parts[2];
99
61
  if (Date.now() / 1000 > payload.exp) {
100
- throw new errors_1.AuthRequiredError('jwt expired', 'JwtExpired');
62
+ throw new AuthRequiredError('jwt expired', 'JwtExpired');
101
63
  }
102
64
  if (ownDid !== null && payload.aud !== ownDid) {
103
- throw new errors_1.AuthRequiredError('jwt audience does not match service did', 'BadJwtAudience');
65
+ throw new AuthRequiredError('jwt audience does not match service did', 'BadJwtAudience');
104
66
  }
105
67
  if (lxm !== null && payload.lxm !== lxm) {
106
- throw new errors_1.AuthRequiredError(payload.lxm !== undefined
68
+ throw new AuthRequiredError(payload.lxm !== undefined
107
69
  ? `bad jwt lexicon method ("lxm"). must match: ${lxm}`
108
70
  : `missing jwt lexicon method ("lxm"). must match: ${lxm}`, 'BadJwtLexiconMethod');
109
71
  }
110
72
  if (!payload.iss || !isDidStringOrService(payload.iss)) {
111
- throw new errors_1.AuthRequiredError('jwt iss is not a valid did', 'BadJwtIss');
73
+ throw new AuthRequiredError('jwt iss is not a valid did', 'BadJwtIss');
112
74
  }
113
75
  const msgBytes = Buffer.from(parts.slice(0, 2).join('.'), 'utf8');
114
76
  const sigBytes = Buffer.from(sig, 'base64url');
@@ -119,7 +81,7 @@ getSigningKey, verifySignatureWithKey = exports.cryptoVerifySignatureWithKey) =>
119
81
  validSig = await verifySignatureWithKey(signingKey, msgBytes, sigBytes, alg);
120
82
  }
121
83
  catch (err) {
122
- throw new errors_1.AuthRequiredError('could not verify jwt signature', 'BadJwtSignature');
84
+ throw new AuthRequiredError('could not verify jwt signature', 'BadJwtSignature');
123
85
  }
124
86
  if (!validSig) {
125
87
  // get fresh signing key in case it failed due to a recent rotation
@@ -131,29 +93,27 @@ getSigningKey, verifySignatureWithKey = exports.cryptoVerifySignatureWithKey) =>
131
93
  : false;
132
94
  }
133
95
  catch (err) {
134
- throw new errors_1.AuthRequiredError('could not verify jwt signature', 'BadJwtSignature');
96
+ throw new AuthRequiredError('could not verify jwt signature', 'BadJwtSignature');
135
97
  }
136
98
  }
137
99
  if (!validSig) {
138
- throw new errors_1.AuthRequiredError('jwt signature does not match jwt issuer', 'BadJwtSignature');
100
+ throw new AuthRequiredError('jwt signature does not match jwt issuer', 'BadJwtSignature');
139
101
  }
140
102
  return payload;
141
103
  };
142
- exports.verifyJwt = verifyJwt;
143
- const cryptoVerifySignatureWithKey = async (key, msgBytes, sigBytes, alg) => {
104
+ export const cryptoVerifySignatureWithKey = async (key, msgBytes, sigBytes, alg) => {
144
105
  return crypto.verifySignature(key, msgBytes, sigBytes, {
145
106
  jwtAlg: alg,
146
107
  allowMalleableSig: true,
147
108
  });
148
109
  };
149
- exports.cryptoVerifySignatureWithKey = cryptoVerifySignatureWithKey;
150
110
  const parseB64UrlToJson = (b64) => {
151
111
  return JSON.parse(Buffer.from(b64, 'base64url').toString('utf8'));
152
112
  };
153
113
  const parseHeader = (b64) => {
154
114
  const header = parseB64UrlToJson(b64);
155
115
  if (!header || typeof header !== 'object' || typeof header.alg !== 'string') {
156
- throw new errors_1.AuthRequiredError('poorly formatted jwt', 'BadJwt');
116
+ throw new AuthRequiredError('poorly formatted jwt', 'BadJwt');
157
117
  }
158
118
  return header;
159
119
  };
@@ -166,14 +126,14 @@ const parsePayload = (b64) => {
166
126
  typeof payload.exp !== 'number' ||
167
127
  (payload.lxm && typeof payload.lxm !== 'string') ||
168
128
  (payload.nonce && typeof payload.nonce !== 'string')) {
169
- throw new errors_1.AuthRequiredError('poorly formatted jwt', 'BadJwt');
129
+ throw new AuthRequiredError('poorly formatted jwt', 'BadJwt');
170
130
  }
171
131
  return payload;
172
132
  };
173
133
  function isDidStringOrService(value) {
174
134
  const hashIdx = value.indexOf('#');
175
135
  if (hashIdx === -1) {
176
- return (0, lex_schema_1.isDidString)(value);
136
+ return isDidString(value);
177
137
  }
178
138
  // basic validation of the fragment part
179
139
  const fragmentLen = value.length - hashIdx - 1;
@@ -182,6 +142,6 @@ function isDidStringOrService(value) {
182
142
  }
183
143
  // Validate the did part
184
144
  const didPart = value.slice(0, hashIdx);
185
- return (0, lex_schema_1.isDidString)(didPart);
145
+ return isDidString(didPart);
186
146
  }
187
147
  //# sourceMappingURL=auth.js.map
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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","sourcesContent":["import * as common from '@atproto/common'\nimport { MINUTE } from '@atproto/common'\nimport * as crypto from '@atproto/crypto'\nimport { DidString, isDidString } from '@atproto/lex-schema'\nimport { AuthRequiredError } from './errors'\n\ntype ServiceJwtParams = {\n iss: string\n aud: string\n iat?: number\n exp?: number\n lxm: string | null\n keypair: crypto.Keypair\n}\n\ntype ServiceJwtHeaders = {\n alg: string\n} & Record<string, unknown>\n\ntype ServiceJwtPayload = {\n iss: DidString | `${DidString}#${string}`\n aud: string\n exp: number\n lxm?: string\n jti?: string\n}\n\nexport const createServiceJwt = async (\n params: ServiceJwtParams,\n): Promise<string> => {\n const { iss, aud, keypair } = params\n const iat = params.iat ?? Math.floor(Date.now() / 1e3)\n const exp = params.exp ?? iat + MINUTE / 1e3\n const lxm = params.lxm ?? undefined\n const jti = await crypto.randomStr(16, 'hex')\n const header = {\n typ: 'JWT',\n alg: keypair.jwtAlg,\n }\n const payload = common.noUndefinedVals({\n iat,\n iss,\n aud,\n exp,\n lxm,\n jti,\n })\n const toSignStr = `${jsonToB64Url(header)}.${jsonToB64Url(payload)}`\n const toSign = Buffer.from(toSignStr, 'utf8')\n const sig = Buffer.from(await keypair.sign(toSign))\n return `${toSignStr}.${sig.toString('base64url')}`\n}\n\nexport const createServiceAuthHeaders = async (params: ServiceJwtParams) => {\n const jwt = await createServiceJwt(params)\n return {\n headers: { authorization: `Bearer ${jwt}` },\n }\n}\n\nconst jsonToB64Url = (json: Record<string, unknown>): string => {\n return Buffer.from(JSON.stringify(json)).toString('base64url')\n}\n\nexport type VerifySignatureWithKeyFn = (\n key: string,\n msgBytes: Uint8Array,\n sigBytes: Uint8Array,\n alg: string,\n) => Promise<boolean>\n\nexport const verifyJwt = async (\n jwtStr: string,\n ownDid: string | null, // null indicates to skip the audience check\n lxm: string | null, // null indicates to skip the lxm check\n getSigningKey: (\n iss: DidString | `${DidString}#${string}`,\n forceRefresh: boolean,\n ) => Promise<string>,\n verifySignatureWithKey: VerifySignatureWithKeyFn = cryptoVerifySignatureWithKey,\n): Promise<ServiceJwtPayload> => {\n const parts = jwtStr.split('.')\n if (parts.length !== 3) {\n throw new AuthRequiredError('poorly formatted jwt', 'BadJwt')\n }\n\n const header = parseHeader(parts[0])\n\n // The spec does not describe what to do with the \"typ\" claim. We can,\n // however, forbid some values that are not compatible with our use case.\n if (\n // service tokens are not OAuth 2.0 access tokens\n // https://datatracker.ietf.org/doc/html/rfc9068\n header['typ'] === 'at+jwt' ||\n // \"refresh+jwt\" is a non-standard type used by the @atproto packages\n header['typ'] === 'refresh+jwt' ||\n // \"DPoP\" proofs are not meant to be used as service tokens\n // https://datatracker.ietf.org/doc/html/rfc9449\n header['typ'] === 'dpop+jwt'\n ) {\n throw new AuthRequiredError(\n `Invalid jwt type \"${header['typ']}\"`,\n 'BadJwtType',\n )\n }\n\n const payload = parsePayload(parts[1])\n const sig = parts[2]\n\n if (Date.now() / 1000 > payload.exp) {\n throw new AuthRequiredError('jwt expired', 'JwtExpired')\n }\n if (ownDid !== null && payload.aud !== ownDid) {\n throw new AuthRequiredError(\n 'jwt audience does not match service did',\n 'BadJwtAudience',\n )\n }\n if (lxm !== null && payload.lxm !== lxm) {\n throw new AuthRequiredError(\n payload.lxm !== undefined\n ? `bad jwt lexicon method (\"lxm\"). must match: ${lxm}`\n : `missing jwt lexicon method (\"lxm\"). must match: ${lxm}`,\n 'BadJwtLexiconMethod',\n )\n }\n if (!payload.iss || !isDidStringOrService(payload.iss)) {\n throw new AuthRequiredError('jwt iss is not a valid did', 'BadJwtIss')\n }\n\n const msgBytes = Buffer.from(parts.slice(0, 2).join('.'), 'utf8')\n const sigBytes = Buffer.from(sig, 'base64url')\n\n const signingKey = await getSigningKey(payload.iss, false)\n const { alg } = header\n\n let validSig: boolean\n try {\n validSig = await verifySignatureWithKey(signingKey, msgBytes, sigBytes, alg)\n } catch (err) {\n throw new AuthRequiredError(\n 'could not verify jwt signature',\n 'BadJwtSignature',\n )\n }\n\n if (!validSig) {\n // get fresh signing key in case it failed due to a recent rotation\n const freshSigningKey = await getSigningKey(payload.iss, true)\n try {\n validSig =\n freshSigningKey !== signingKey\n ? await verifySignatureWithKey(\n freshSigningKey,\n msgBytes,\n sigBytes,\n alg,\n )\n : false\n } catch (err) {\n throw new AuthRequiredError(\n 'could not verify jwt signature',\n 'BadJwtSignature',\n )\n }\n }\n\n if (!validSig) {\n throw new AuthRequiredError(\n 'jwt signature does not match jwt issuer',\n 'BadJwtSignature',\n )\n }\n\n return payload\n}\n\nexport const cryptoVerifySignatureWithKey: VerifySignatureWithKeyFn = async (\n key: string,\n msgBytes: Uint8Array,\n sigBytes: Uint8Array,\n alg: string,\n) => {\n return crypto.verifySignature(key, msgBytes, sigBytes, {\n jwtAlg: alg,\n allowMalleableSig: true,\n })\n}\n\nconst parseB64UrlToJson = (b64: string) => {\n return JSON.parse(Buffer.from(b64, 'base64url').toString('utf8'))\n}\n\nconst parseHeader = (b64: string): ServiceJwtHeaders => {\n const header = parseB64UrlToJson(b64)\n if (!header || typeof header !== 'object' || typeof header.alg !== 'string') {\n throw new AuthRequiredError('poorly formatted jwt', 'BadJwt')\n }\n return header\n}\n\nconst parsePayload = (b64: string): ServiceJwtPayload => {\n const payload = parseB64UrlToJson(b64)\n if (\n !payload ||\n typeof payload !== 'object' ||\n typeof payload.iss !== 'string' ||\n typeof payload.aud !== 'string' ||\n typeof payload.exp !== 'number' ||\n (payload.lxm && typeof payload.lxm !== 'string') ||\n (payload.nonce && typeof payload.nonce !== 'string')\n ) {\n throw new AuthRequiredError('poorly formatted jwt', 'BadJwt')\n }\n return payload\n}\n\nfunction isDidStringOrService(\n value: string,\n): value is DidString | `${DidString}#${string}` {\n const hashIdx = value.indexOf('#')\n if (hashIdx === -1) {\n return isDidString(value)\n }\n\n // basic validation of the fragment part\n const fragmentLen = value.length - hashIdx - 1\n if (fragmentLen < 1 || value.includes('#', hashIdx + 1)) {\n return false\n }\n\n // Validate the did part\n const didPart = value.slice(0, hashIdx)\n return isDidString(didPart)\n}\n"]}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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","sourcesContent":["import * as common from '@atproto/common'\nimport { MINUTE } from '@atproto/common'\nimport * as crypto from '@atproto/crypto'\nimport { DidString, isDidString } from '@atproto/lex-schema'\nimport { AuthRequiredError } from './errors.js'\n\ntype ServiceJwtParams = {\n iss: string\n aud: string\n iat?: number\n exp?: number\n lxm: string | null\n keypair: crypto.Keypair\n}\n\ntype ServiceJwtHeaders = {\n alg: string\n} & Record<string, unknown>\n\ntype ServiceJwtPayload = {\n iss: DidString | `${DidString}#${string}`\n aud: string\n exp: number\n lxm?: string\n jti?: string\n}\n\nexport const createServiceJwt = async (\n params: ServiceJwtParams,\n): Promise<string> => {\n const { iss, aud, keypair } = params\n const iat = params.iat ?? Math.floor(Date.now() / 1e3)\n const exp = params.exp ?? iat + MINUTE / 1e3\n const lxm = params.lxm ?? undefined\n const jti = await crypto.randomStr(16, 'hex')\n const header = {\n typ: 'JWT',\n alg: keypair.jwtAlg,\n }\n const payload = common.noUndefinedVals({\n iat,\n iss,\n aud,\n exp,\n lxm,\n jti,\n })\n const toSignStr = `${jsonToB64Url(header)}.${jsonToB64Url(payload)}`\n const toSign = Buffer.from(toSignStr, 'utf8')\n const sig = Buffer.from(await keypair.sign(toSign))\n return `${toSignStr}.${sig.toString('base64url')}`\n}\n\nexport const createServiceAuthHeaders = async (params: ServiceJwtParams) => {\n const jwt = await createServiceJwt(params)\n return {\n headers: { authorization: `Bearer ${jwt}` },\n }\n}\n\nconst jsonToB64Url = (json: Record<string, unknown>): string => {\n return Buffer.from(JSON.stringify(json)).toString('base64url')\n}\n\nexport type VerifySignatureWithKeyFn = (\n key: string,\n msgBytes: Uint8Array,\n sigBytes: Uint8Array,\n alg: string,\n) => Promise<boolean>\n\nexport const verifyJwt = async (\n jwtStr: string,\n ownDid: string | null, // null indicates to skip the audience check\n lxm: string | null, // null indicates to skip the lxm check\n getSigningKey: (\n iss: DidString | `${DidString}#${string}`,\n forceRefresh: boolean,\n ) => Promise<string>,\n verifySignatureWithKey: VerifySignatureWithKeyFn = cryptoVerifySignatureWithKey,\n): Promise<ServiceJwtPayload> => {\n const parts = jwtStr.split('.')\n if (parts.length !== 3) {\n throw new AuthRequiredError('poorly formatted jwt', 'BadJwt')\n }\n\n const header = parseHeader(parts[0])\n\n // The spec does not describe what to do with the \"typ\" claim. We can,\n // however, forbid some values that are not compatible with our use case.\n if (\n // service tokens are not OAuth 2.0 access tokens\n // https://datatracker.ietf.org/doc/html/rfc9068\n header['typ'] === 'at+jwt' ||\n // \"refresh+jwt\" is a non-standard type used by the @atproto packages\n header['typ'] === 'refresh+jwt' ||\n // \"DPoP\" proofs are not meant to be used as service tokens\n // https://datatracker.ietf.org/doc/html/rfc9449\n header['typ'] === 'dpop+jwt'\n ) {\n throw new AuthRequiredError(\n `Invalid jwt type \"${header['typ']}\"`,\n 'BadJwtType',\n )\n }\n\n const payload = parsePayload(parts[1])\n const sig = parts[2]\n\n if (Date.now() / 1000 > payload.exp) {\n throw new AuthRequiredError('jwt expired', 'JwtExpired')\n }\n if (ownDid !== null && payload.aud !== ownDid) {\n throw new AuthRequiredError(\n 'jwt audience does not match service did',\n 'BadJwtAudience',\n )\n }\n if (lxm !== null && payload.lxm !== lxm) {\n throw new AuthRequiredError(\n payload.lxm !== undefined\n ? `bad jwt lexicon method (\"lxm\"). must match: ${lxm}`\n : `missing jwt lexicon method (\"lxm\"). must match: ${lxm}`,\n 'BadJwtLexiconMethod',\n )\n }\n if (!payload.iss || !isDidStringOrService(payload.iss)) {\n throw new AuthRequiredError('jwt iss is not a valid did', 'BadJwtIss')\n }\n\n const msgBytes = Buffer.from(parts.slice(0, 2).join('.'), 'utf8')\n const sigBytes = Buffer.from(sig, 'base64url')\n\n const signingKey = await getSigningKey(payload.iss, false)\n const { alg } = header\n\n let validSig: boolean\n try {\n validSig = await verifySignatureWithKey(signingKey, msgBytes, sigBytes, alg)\n } catch (err) {\n throw new AuthRequiredError(\n 'could not verify jwt signature',\n 'BadJwtSignature',\n )\n }\n\n if (!validSig) {\n // get fresh signing key in case it failed due to a recent rotation\n const freshSigningKey = await getSigningKey(payload.iss, true)\n try {\n validSig =\n freshSigningKey !== signingKey\n ? await verifySignatureWithKey(\n freshSigningKey,\n msgBytes,\n sigBytes,\n alg,\n )\n : false\n } catch (err) {\n throw new AuthRequiredError(\n 'could not verify jwt signature',\n 'BadJwtSignature',\n )\n }\n }\n\n if (!validSig) {\n throw new AuthRequiredError(\n 'jwt signature does not match jwt issuer',\n 'BadJwtSignature',\n )\n }\n\n return payload\n}\n\nexport const cryptoVerifySignatureWithKey: VerifySignatureWithKeyFn = async (\n key: string,\n msgBytes: Uint8Array,\n sigBytes: Uint8Array,\n alg: string,\n) => {\n return crypto.verifySignature(key, msgBytes, sigBytes, {\n jwtAlg: alg,\n allowMalleableSig: true,\n })\n}\n\nconst parseB64UrlToJson = (b64: string) => {\n return JSON.parse(Buffer.from(b64, 'base64url').toString('utf8'))\n}\n\nconst parseHeader = (b64: string): ServiceJwtHeaders => {\n const header = parseB64UrlToJson(b64)\n if (!header || typeof header !== 'object' || typeof header.alg !== 'string') {\n throw new AuthRequiredError('poorly formatted jwt', 'BadJwt')\n }\n return header\n}\n\nconst parsePayload = (b64: string): ServiceJwtPayload => {\n const payload = parseB64UrlToJson(b64)\n if (\n !payload ||\n typeof payload !== 'object' ||\n typeof payload.iss !== 'string' ||\n typeof payload.aud !== 'string' ||\n typeof payload.exp !== 'number' ||\n (payload.lxm && typeof payload.lxm !== 'string') ||\n (payload.nonce && typeof payload.nonce !== 'string')\n ) {\n throw new AuthRequiredError('poorly formatted jwt', 'BadJwt')\n }\n return payload\n}\n\nfunction isDidStringOrService(\n value: string,\n): value is DidString | `${DidString}#${string}` {\n const hashIdx = value.indexOf('#')\n if (hashIdx === -1) {\n return isDidString(value)\n }\n\n // basic validation of the fragment part\n const fragmentLen = value.length - hashIdx - 1\n if (fragmentLen < 1 || value.includes('#', hashIdx + 1)) {\n return false\n }\n\n // Validate the did part\n const didPart = value.slice(0, hashIdx)\n return isDidString(didPart)\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,qBAAqB,CAAA;AACvC,OAAO,EACL,YAAY,EAKb,MAAM,eAAe,CAAA;AAKtB,eAAO,MAAM,WAAW;;;;EAItB,CAAA;AACF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AAErD,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,WAAW,CAE1D;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAE5B,OAAO,CAAC,CAAC,EAAE,WAAW,CAAC,CACpC;AAED,OAAO,EAAE,YAAY,EAAE,CAAA;AAEvB,qBAAa,SAAU,SAAQ,KAAK;IAEzB,IAAI,EAAE,YAAY;IAClB,YAAY,CAAC,EAAE,MAAM;IACrB,eAAe,CAAC,EAAE,MAAM;gBAFxB,IAAI,EAAE,YAAY,EAClB,YAAY,CAAC,EAAE,MAAM,YAAA,EACrB,eAAe,CAAC,EAAE,MAAM,YAAA,EAC/B,OAAO,CAAC,EAAE,YAAY;IAKxB,IAAI,UAAU,IAAI,MAAM,CAWvB;IAED,IAAI,KAAK,IAAI,MAAM,GAAG,SAAS,CAE9B;IAED,IAAI,OAAO;;;MAQV;IAED,IAAI,QAAQ,IAAI,MAAM,GAAG,SAAS,CAEjC;IAED,IAAI,OAAO,IAAI,MAAM,GAAG,SAAS,CAEhC;IAED,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS;IAwC3C,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,WAAW,GAAG,SAAS;CAGpD;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBAE9C,YAAY,CAAC,EAAE,MAAM,EACrB,eAAe,CAAC,EAAE,MAAM,EACxB,OAAO,CAAC,EAAE,YAAY;IAKxB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO;CAMjD;AAED,qBAAa,iBAAkB,SAAQ,SAAS;gBAE5C,YAAY,CAAC,EAAE,MAAM,EACrB,eAAe,CAAC,EAAE,MAAM,EACxB,OAAO,CAAC,EAAE,YAAY;IAUxB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO;CAMjD;AAED,qBAAa,cAAe,SAAQ,SAAS;gBAEzC,YAAY,CAAC,EAAE,MAAM,EACrB,eAAe,CAAC,EAAE,MAAM,EACxB,OAAO,CAAC,EAAE,YAAY;IAKxB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO;CAKjD;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBAE9C,YAAY,CAAC,EAAE,MAAM,EACrB,eAAe,CAAC,EAAE,MAAM,EACxB,OAAO,CAAC,EAAE,YAAY;IAUxB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO;CAMjD;AAED,qBAAa,oBAAqB,SAAQ,SAAS;gBAE/C,YAAY,CAAC,EAAE,MAAM,EACrB,eAAe,CAAC,EAAE,MAAM,EACxB,OAAO,CAAC,EAAE,YAAY;IAKxB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO;CAMjD;AAED,qBAAa,uBAAwB,SAAQ,SAAS;gBAElD,YAAY,CAAC,EAAE,MAAM,EACrB,eAAe,CAAC,EAAE,MAAM,EACxB,OAAO,CAAC,EAAE,YAAY;IAUxB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO;CAMjD;AAED,qBAAa,oBAAqB,SAAQ,SAAS;gBAE/C,YAAY,CAAC,EAAE,MAAM,EACrB,eAAe,CAAC,EAAE,MAAM,EACxB,OAAO,CAAC,EAAE,YAAY;IAKxB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO;CAMjD;AAED,qBAAa,yBAA0B,SAAQ,SAAS;gBAEpD,YAAY,CAAC,EAAE,MAAM,EACrB,eAAe,CAAC,EAAE,MAAM,EACxB,OAAO,CAAC,EAAE,YAAY;IAUxB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO;CAMjD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
package/dist/errors.js CHANGED
@@ -1,49 +1,32 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MethodNotImplementedError = exports.UpstreamTimeoutError = exports.NotEnoughResourcesError = exports.UpstreamFailureError = exports.InternalServerError = exports.ForbiddenError = exports.AuthRequiredError = exports.InvalidRequestError = exports.XRPCError = exports.ResponseType = exports.errorResult = void 0;
4
- exports.isErrorResult = isErrorResult;
5
- exports.excludeErrorResult = excludeErrorResult;
6
- const http_errors_1 = require("http-errors");
7
- const lex_client_1 = require("@atproto/lex-client");
8
- const lex_schema_1 = require("@atproto/lex-schema");
9
- const xrpc_1 = require("@atproto/xrpc");
10
- Object.defineProperty(exports, "ResponseType", { enumerable: true, get: function () { return xrpc_1.ResponseType; } });
1
+ // eslint-disable-next-line import/default, import/no-named-as-default-member
2
+ import httpErrors from 'http-errors';
3
+ // eslint-disable-next-line import/no-named-as-default-member
4
+ const { isHttpError } = httpErrors;
5
+ import { LexError, XrpcError } from '@atproto/lex-client';
6
+ import { l } from '@atproto/lex-schema';
7
+ import { ResponseType, ResponseTypeStrings, XRPCError as XRPCClientError, httpResponseCodeToName, httpResponseCodeToString, } from '@atproto/xrpc';
11
8
  // @NOTE Do not depend (directly or indirectly) on "./types" here, as it would
12
9
  // create a circular dependency.
13
- exports.errorResult = lex_schema_1.l.object({
14
- status: lex_schema_1.l.integer({ minimum: 400 }),
15
- error: lex_schema_1.l.optional(lex_schema_1.l.string()),
16
- message: lex_schema_1.l.optional(lex_schema_1.l.string()),
10
+ export const errorResult = l.object({
11
+ status: l.integer({ minimum: 400 }),
12
+ error: l.optional(l.string()),
13
+ message: l.optional(l.string()),
17
14
  });
18
- function isErrorResult(v) {
19
- return exports.errorResult.safeParse(v).success;
15
+ export function isErrorResult(v) {
16
+ return errorResult.safeParse(v).success;
20
17
  }
21
- function excludeErrorResult(v) {
18
+ export function excludeErrorResult(v) {
22
19
  if (isErrorResult(v))
23
20
  throw XRPCError.fromErrorResult(v);
24
21
  return v;
25
22
  }
26
- class XRPCError extends Error {
23
+ export { ResponseType };
24
+ export class XRPCError extends Error {
27
25
  constructor(type, errorMessage, customErrorName, options) {
28
26
  super(errorMessage, options);
29
- Object.defineProperty(this, "type", {
30
- enumerable: true,
31
- configurable: true,
32
- writable: true,
33
- value: type
34
- });
35
- Object.defineProperty(this, "errorMessage", {
36
- enumerable: true,
37
- configurable: true,
38
- writable: true,
39
- value: errorMessage
40
- });
41
- Object.defineProperty(this, "customErrorName", {
42
- enumerable: true,
43
- configurable: true,
44
- writable: true,
45
- value: customErrorName
46
- });
27
+ this.type = type;
28
+ this.errorMessage = errorMessage;
29
+ this.customErrorName = customErrorName;
47
30
  }
48
31
  get statusCode() {
49
32
  const { type } = this;
@@ -61,35 +44,35 @@ class XRPCError extends Error {
61
44
  get payload() {
62
45
  return {
63
46
  error: this.error,
64
- message: this.type === xrpc_1.ResponseType.InternalServerError
47
+ message: this.type === ResponseType.InternalServerError
65
48
  ? this.typeStr // Do not respond with error details for 500s
66
49
  : this.errorMessage || this.typeStr,
67
50
  };
68
51
  }
69
52
  get typeName() {
70
- return xrpc_1.ResponseType[this.type];
53
+ return ResponseType[this.type];
71
54
  }
72
55
  get typeStr() {
73
- return xrpc_1.ResponseTypeStrings[this.type];
56
+ return ResponseTypeStrings[this.type];
74
57
  }
75
58
  static fromError(cause) {
76
59
  if (cause instanceof XRPCError) {
77
60
  return cause;
78
61
  }
79
- if (cause instanceof xrpc_1.XRPCError) {
62
+ if (cause instanceof XRPCClientError) {
80
63
  const { error, message, type } = mapFromClientError(cause);
81
64
  return new XRPCError(type, message, error, { cause });
82
65
  }
83
- if (cause instanceof lex_client_1.XrpcError) {
66
+ if (cause instanceof XrpcError) {
84
67
  const { status, body } = cause.toDownstreamError();
85
68
  return new XRPCError(status, body.message, body.error, { cause });
86
69
  }
87
- if (cause instanceof lex_client_1.LexError) {
70
+ if (cause instanceof LexError) {
88
71
  const data = cause.toJSON();
89
- const type = xrpc_1.ResponseType.InternalServerError;
72
+ const type = ResponseType.InternalServerError;
90
73
  return new XRPCError(type, data.message, data.error, { cause });
91
74
  }
92
- if ((0, http_errors_1.isHttpError)(cause)) {
75
+ if (isHttpError(cause)) {
93
76
  return new XRPCError(cause.status, cause.message, cause.name, { cause });
94
77
  }
95
78
  if (isErrorResult(cause)) {
@@ -104,105 +87,96 @@ class XRPCError extends Error {
104
87
  return new XRPCError(err.status, err.message, err.error, { cause: err });
105
88
  }
106
89
  }
107
- exports.XRPCError = XRPCError;
108
- class InvalidRequestError extends XRPCError {
90
+ export class InvalidRequestError extends XRPCError {
109
91
  constructor(errorMessage, customErrorName, options) {
110
- super(xrpc_1.ResponseType.InvalidRequest, errorMessage, customErrorName, options);
92
+ super(ResponseType.InvalidRequest, errorMessage, customErrorName, options);
111
93
  }
112
94
  [Symbol.hasInstance](instance) {
113
95
  return (instance instanceof XRPCError &&
114
- instance.type === xrpc_1.ResponseType.InvalidRequest);
96
+ instance.type === ResponseType.InvalidRequest);
115
97
  }
116
98
  }
117
- exports.InvalidRequestError = InvalidRequestError;
118
- class AuthRequiredError extends XRPCError {
99
+ export class AuthRequiredError extends XRPCError {
119
100
  constructor(errorMessage, customErrorName, options) {
120
- super(xrpc_1.ResponseType.AuthenticationRequired, errorMessage, customErrorName, options);
101
+ super(ResponseType.AuthenticationRequired, errorMessage, customErrorName, options);
121
102
  }
122
103
  [Symbol.hasInstance](instance) {
123
104
  return (instance instanceof XRPCError &&
124
- instance.type === xrpc_1.ResponseType.AuthenticationRequired);
105
+ instance.type === ResponseType.AuthenticationRequired);
125
106
  }
126
107
  }
127
- exports.AuthRequiredError = AuthRequiredError;
128
- class ForbiddenError extends XRPCError {
108
+ export class ForbiddenError extends XRPCError {
129
109
  constructor(errorMessage, customErrorName, options) {
130
- super(xrpc_1.ResponseType.Forbidden, errorMessage, customErrorName, options);
110
+ super(ResponseType.Forbidden, errorMessage, customErrorName, options);
131
111
  }
132
112
  [Symbol.hasInstance](instance) {
133
- return (instance instanceof XRPCError && instance.type === xrpc_1.ResponseType.Forbidden);
113
+ return (instance instanceof XRPCError && instance.type === ResponseType.Forbidden);
134
114
  }
135
115
  }
136
- exports.ForbiddenError = ForbiddenError;
137
- class InternalServerError extends XRPCError {
116
+ export class InternalServerError extends XRPCError {
138
117
  constructor(errorMessage, customErrorName, options) {
139
- super(xrpc_1.ResponseType.InternalServerError, errorMessage, customErrorName, options);
118
+ super(ResponseType.InternalServerError, errorMessage, customErrorName, options);
140
119
  }
141
120
  [Symbol.hasInstance](instance) {
142
121
  return (instance instanceof XRPCError &&
143
- instance.type === xrpc_1.ResponseType.InternalServerError);
122
+ instance.type === ResponseType.InternalServerError);
144
123
  }
145
124
  }
146
- exports.InternalServerError = InternalServerError;
147
- class UpstreamFailureError extends XRPCError {
125
+ export class UpstreamFailureError extends XRPCError {
148
126
  constructor(errorMessage, customErrorName, options) {
149
- super(xrpc_1.ResponseType.UpstreamFailure, errorMessage, customErrorName, options);
127
+ super(ResponseType.UpstreamFailure, errorMessage, customErrorName, options);
150
128
  }
151
129
  [Symbol.hasInstance](instance) {
152
130
  return (instance instanceof XRPCError &&
153
- instance.type === xrpc_1.ResponseType.UpstreamFailure);
131
+ instance.type === ResponseType.UpstreamFailure);
154
132
  }
155
133
  }
156
- exports.UpstreamFailureError = UpstreamFailureError;
157
- class NotEnoughResourcesError extends XRPCError {
134
+ export class NotEnoughResourcesError extends XRPCError {
158
135
  constructor(errorMessage, customErrorName, options) {
159
- super(xrpc_1.ResponseType.NotEnoughResources, errorMessage, customErrorName, options);
136
+ super(ResponseType.NotEnoughResources, errorMessage, customErrorName, options);
160
137
  }
161
138
  [Symbol.hasInstance](instance) {
162
139
  return (instance instanceof XRPCError &&
163
- instance.type === xrpc_1.ResponseType.NotEnoughResources);
140
+ instance.type === ResponseType.NotEnoughResources);
164
141
  }
165
142
  }
166
- exports.NotEnoughResourcesError = NotEnoughResourcesError;
167
- class UpstreamTimeoutError extends XRPCError {
143
+ export class UpstreamTimeoutError extends XRPCError {
168
144
  constructor(errorMessage, customErrorName, options) {
169
- super(xrpc_1.ResponseType.UpstreamTimeout, errorMessage, customErrorName, options);
145
+ super(ResponseType.UpstreamTimeout, errorMessage, customErrorName, options);
170
146
  }
171
147
  [Symbol.hasInstance](instance) {
172
148
  return (instance instanceof XRPCError &&
173
- instance.type === xrpc_1.ResponseType.UpstreamTimeout);
149
+ instance.type === ResponseType.UpstreamTimeout);
174
150
  }
175
151
  }
176
- exports.UpstreamTimeoutError = UpstreamTimeoutError;
177
- class MethodNotImplementedError extends XRPCError {
152
+ export class MethodNotImplementedError extends XRPCError {
178
153
  constructor(errorMessage, customErrorName, options) {
179
- super(xrpc_1.ResponseType.MethodNotImplemented, errorMessage, customErrorName, options);
154
+ super(ResponseType.MethodNotImplemented, errorMessage, customErrorName, options);
180
155
  }
181
156
  [Symbol.hasInstance](instance) {
182
157
  return (instance instanceof XRPCError &&
183
- instance.type === xrpc_1.ResponseType.MethodNotImplemented);
158
+ instance.type === ResponseType.MethodNotImplemented);
184
159
  }
185
160
  }
186
- exports.MethodNotImplementedError = MethodNotImplementedError;
187
161
  /**
188
162
  * Converts an upstream XRPC {@link ResponseType} into a downstream {@link ResponseType}.
189
163
  */
190
164
  function mapFromClientError(error) {
191
165
  switch (error.status) {
192
- case xrpc_1.ResponseType.InvalidResponse:
166
+ case ResponseType.InvalidResponse:
193
167
  // Upstream server returned an XRPC response that is not compatible with our internal lexicon definitions for that XRPC method.
194
168
  // @NOTE This could be reflected as both a 500 ("we" are at fault) and 502 ("they" are at fault). Let's be gents about it.
195
169
  return {
196
- error: (0, xrpc_1.httpResponseCodeToName)(xrpc_1.ResponseType.InternalServerError),
197
- message: (0, xrpc_1.httpResponseCodeToString)(xrpc_1.ResponseType.InternalServerError),
198
- type: xrpc_1.ResponseType.InternalServerError,
170
+ error: httpResponseCodeToName(ResponseType.InternalServerError),
171
+ message: httpResponseCodeToString(ResponseType.InternalServerError),
172
+ type: ResponseType.InternalServerError,
199
173
  };
200
- case xrpc_1.ResponseType.Unknown:
174
+ case ResponseType.Unknown:
201
175
  // Typically a network error / unknown host
202
176
  return {
203
- error: (0, xrpc_1.httpResponseCodeToName)(xrpc_1.ResponseType.InternalServerError),
204
- message: (0, xrpc_1.httpResponseCodeToString)(xrpc_1.ResponseType.InternalServerError),
205
- type: xrpc_1.ResponseType.InternalServerError,
177
+ error: httpResponseCodeToName(ResponseType.InternalServerError),
178
+ message: httpResponseCodeToString(ResponseType.InternalServerError),
179
+ type: ResponseType.InternalServerError,
206
180
  };
207
181
  default:
208
182
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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","sourcesContent":["import { isHttpError } from 'http-errors'\nimport { LexError, XrpcError } from '@atproto/lex-client'\nimport { l } from '@atproto/lex-schema'\nimport {\n ResponseType,\n ResponseTypeStrings,\n XRPCError as XRPCClientError,\n httpResponseCodeToName,\n httpResponseCodeToString,\n} from '@atproto/xrpc'\n\n// @NOTE Do not depend (directly or indirectly) on \"./types\" here, as it would\n// create a circular dependency.\n\nexport const errorResult = l.object({\n status: l.integer({ minimum: 400 }),\n error: l.optional(l.string()),\n message: l.optional(l.string()),\n})\nexport type ErrorResult = l.Infer<typeof errorResult>\n\nexport function isErrorResult(v: unknown): v is ErrorResult {\n return errorResult.safeParse(v).success\n}\n\nexport function excludeErrorResult<V>(v: V) {\n if (isErrorResult(v)) throw XRPCError.fromErrorResult(v)\n return v as Exclude<V, ErrorResult>\n}\n\nexport { ResponseType }\n\nexport class XRPCError extends Error {\n constructor(\n public type: ResponseType,\n public errorMessage?: string,\n public customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(errorMessage, options)\n }\n\n get statusCode(): number {\n const { type } = this\n\n // Fool-proofing. `new XRPCError(123.5 as number, '')` does not generate a TypeScript error.\n // Because of this, we can end-up with any numeric value instead of an actual `ResponseType`.\n // For legacy reasons, the `type` argument is not checked in the constructor, so we check it here.\n if (type < 400 || type >= 600 || !Number.isFinite(type)) {\n return 500\n }\n\n return type\n }\n\n get error(): string | undefined {\n return this.customErrorName ?? this.typeName\n }\n\n get payload() {\n return {\n error: this.error,\n message:\n this.type === ResponseType.InternalServerError\n ? this.typeStr // Do not respond with error details for 500s\n : this.errorMessage || this.typeStr,\n }\n }\n\n get typeName(): string | undefined {\n return ResponseType[this.type]\n }\n\n get typeStr(): string | undefined {\n return ResponseTypeStrings[this.type]\n }\n\n static fromError(cause: unknown): XRPCError {\n if (cause instanceof XRPCError) {\n return cause\n }\n\n if (cause instanceof XRPCClientError) {\n const { error, message, type } = mapFromClientError(cause)\n return new XRPCError(type, message, error, { cause })\n }\n\n if (cause instanceof XrpcError) {\n const { status, body } = cause.toDownstreamError()\n return new XRPCError(status, body.message, body.error, { cause })\n }\n\n if (cause instanceof LexError) {\n const data = cause.toJSON()\n const type = ResponseType.InternalServerError\n return new XRPCError(type, data.message, data.error, { cause })\n }\n\n if (isHttpError(cause)) {\n return new XRPCError(cause.status, cause.message, cause.name, { cause })\n }\n\n if (isErrorResult(cause)) {\n return this.fromErrorResult(cause)\n }\n\n if (cause instanceof Error) {\n return new InternalServerError(cause.message, undefined, { cause })\n }\n\n return new InternalServerError(\n 'Unexpected internal server error',\n undefined,\n { cause },\n )\n }\n\n static fromErrorResult(err: ErrorResult): XRPCError {\n return new XRPCError(err.status, err.message, err.error, { cause: err })\n }\n}\n\nexport class InvalidRequestError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.InvalidRequest, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.InvalidRequest\n )\n }\n}\n\nexport class AuthRequiredError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.AuthenticationRequired,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.AuthenticationRequired\n )\n }\n}\n\nexport class ForbiddenError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.Forbidden, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError && instance.type === ResponseType.Forbidden\n )\n }\n}\n\nexport class InternalServerError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.InternalServerError,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.InternalServerError\n )\n }\n}\n\nexport class UpstreamFailureError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.UpstreamFailure, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.UpstreamFailure\n )\n }\n}\n\nexport class NotEnoughResourcesError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.NotEnoughResources,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.NotEnoughResources\n )\n }\n}\n\nexport class UpstreamTimeoutError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.UpstreamTimeout, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.UpstreamTimeout\n )\n }\n}\n\nexport class MethodNotImplementedError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.MethodNotImplemented,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.MethodNotImplemented\n )\n }\n}\n\n/**\n * Converts an upstream XRPC {@link ResponseType} into a downstream {@link ResponseType}.\n */\nfunction mapFromClientError(error: XRPCClientError): {\n error: string\n message: string\n type: ResponseType\n} {\n switch (error.status) {\n case ResponseType.InvalidResponse:\n // Upstream server returned an XRPC response that is not compatible with our internal lexicon definitions for that XRPC method.\n // @NOTE This could be reflected as both a 500 (\"we\" are at fault) and 502 (\"they\" are at fault). Let's be gents about it.\n return {\n error: httpResponseCodeToName(ResponseType.InternalServerError),\n message: httpResponseCodeToString(ResponseType.InternalServerError),\n type: ResponseType.InternalServerError,\n }\n case ResponseType.Unknown:\n // Typically a network error / unknown host\n return {\n error: httpResponseCodeToName(ResponseType.InternalServerError),\n message: httpResponseCodeToString(ResponseType.InternalServerError),\n type: ResponseType.InternalServerError,\n }\n default:\n return {\n error: error.error,\n message: error.message,\n type: error.status,\n }\n }\n}\n"]}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,OAAO,UAAU,MAAM,aAAa,CAAA;AACpC,6DAA6D;AAC7D,MAAM,EAAE,WAAW,EAAE,GAAG,UAAU,CAAA;AAClC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,EAAE,CAAC,EAAE,MAAM,qBAAqB,CAAA;AACvC,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,SAAS,IAAI,eAAe,EAC5B,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,eAAe,CAAA;AAEtB,8EAA8E;AAC9E,gCAAgC;AAEhC,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IACnC,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC7B,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;CAChC,CAAC,CAAA;AAGF,MAAM,UAAU,aAAa,CAAC,CAAU;IACtC,OAAO,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;AACzC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAI,CAAI;IACxC,IAAI,aAAa,CAAC,CAAC,CAAC;QAAE,MAAM,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;IACxD,OAAO,CAA4B,CAAA;AACrC,CAAC;AAED,OAAO,EAAE,YAAY,EAAE,CAAA;AAEvB,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,YACS,IAAkB,EAClB,YAAqB,EACrB,eAAwB,EAC/B,OAAsB;QAEtB,KAAK,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;QALrB,SAAI,GAAJ,IAAI,CAAc;QAClB,iBAAY,GAAZ,YAAY,CAAS;QACrB,oBAAe,GAAf,eAAe,CAAS;IAIjC,CAAC;IAED,IAAI,UAAU;QACZ,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAA;QAErB,4FAA4F;QAC5F,6FAA6F;QAC7F,kGAAkG;QAClG,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACxD,OAAO,GAAG,CAAA;QACZ,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,QAAQ,CAAA;IAC9C,CAAC;IAED,IAAI,OAAO;QACT,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EACL,IAAI,CAAC,IAAI,KAAK,YAAY,CAAC,mBAAmB;gBAC5C,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,6CAA6C;gBAC5D,CAAC,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO;SACxC,CAAA;IACH,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChC,CAAC;IAED,IAAI,OAAO;QACT,OAAO,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACvC,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,KAAc;QAC7B,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;YAC/B,OAAO,KAAK,CAAA;QACd,CAAC;QAED,IAAI,KAAK,YAAY,eAAe,EAAE,CAAC;YACrC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAA;YAC1D,OAAO,IAAI,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QACvD,CAAC;QAED,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;YAC/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,iBAAiB,EAAE,CAAA;YAClD,OAAO,IAAI,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QACnE,CAAC;QAED,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAA;YAC3B,MAAM,IAAI,GAAG,YAAY,CAAC,mBAAmB,CAAA;YAC7C,OAAO,IAAI,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QACjE,CAAC;QAED,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QAC1E,CAAC;QAED,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAA;QACpC,CAAC;QAED,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,IAAI,mBAAmB,CAAC,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QACrE,CAAC;QAED,OAAO,IAAI,mBAAmB,CAC5B,kCAAkC,EAClC,SAAS,EACT,EAAE,KAAK,EAAE,CACV,CAAA;IACH,CAAC;IAED,MAAM,CAAC,eAAe,CAAC,GAAgB;QACrC,OAAO,IAAI,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;IAC1E,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IAChD,YACE,YAAqB,EACrB,eAAwB,EACxB,OAAsB;QAEtB,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,OAAO,CAAC,CAAA;IAC5E,CAAC;IAED,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAiB;QACpC,OAAO,CACL,QAAQ,YAAY,SAAS;YAC7B,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,cAAc,CAC9C,CAAA;IACH,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,SAAS;IAC9C,YACE,YAAqB,EACrB,eAAwB,EACxB,OAAsB;QAEtB,KAAK,CACH,YAAY,CAAC,sBAAsB,EACnC,YAAY,EACZ,eAAe,EACf,OAAO,CACR,CAAA;IACH,CAAC;IAED,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAiB;QACpC,OAAO,CACL,QAAQ,YAAY,SAAS;YAC7B,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,sBAAsB,CACtD,CAAA;IACH,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,SAAS;IAC3C,YACE,YAAqB,EACrB,eAAwB,EACxB,OAAsB;QAEtB,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,YAAY,EAAE,eAAe,EAAE,OAAO,CAAC,CAAA;IACvE,CAAC;IAED,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAiB;QACpC,OAAO,CACL,QAAQ,YAAY,SAAS,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,SAAS,CAC1E,CAAA;IACH,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IAChD,YACE,YAAqB,EACrB,eAAwB,EACxB,OAAsB;QAEtB,KAAK,CACH,YAAY,CAAC,mBAAmB,EAChC,YAAY,EACZ,eAAe,EACf,OAAO,CACR,CAAA;IACH,CAAC;IAED,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAiB;QACpC,OAAO,CACL,QAAQ,YAAY,SAAS;YAC7B,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,mBAAmB,CACnD,CAAA;IACH,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,SAAS;IACjD,YACE,YAAqB,EACrB,eAAwB,EACxB,OAAsB;QAEtB,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,OAAO,CAAC,CAAA;IAC7E,CAAC;IAED,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAiB;QACpC,OAAO,CACL,QAAQ,YAAY,SAAS;YAC7B,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,eAAe,CAC/C,CAAA;IACH,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,SAAS;IACpD,YACE,YAAqB,EACrB,eAAwB,EACxB,OAAsB;QAEtB,KAAK,CACH,YAAY,CAAC,kBAAkB,EAC/B,YAAY,EACZ,eAAe,EACf,OAAO,CACR,CAAA;IACH,CAAC;IAED,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAiB;QACpC,OAAO,CACL,QAAQ,YAAY,SAAS;YAC7B,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,kBAAkB,CAClD,CAAA;IACH,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,SAAS;IACjD,YACE,YAAqB,EACrB,eAAwB,EACxB,OAAsB;QAEtB,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,OAAO,CAAC,CAAA;IAC7E,CAAC;IAED,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAiB;QACpC,OAAO,CACL,QAAQ,YAAY,SAAS;YAC7B,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,eAAe,CAC/C,CAAA;IACH,CAAC;CACF;AAED,MAAM,OAAO,yBAA0B,SAAQ,SAAS;IACtD,YACE,YAAqB,EACrB,eAAwB,EACxB,OAAsB;QAEtB,KAAK,CACH,YAAY,CAAC,oBAAoB,EACjC,YAAY,EACZ,eAAe,EACf,OAAO,CACR,CAAA;IACH,CAAC;IAED,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAiB;QACpC,OAAO,CACL,QAAQ,YAAY,SAAS;YAC7B,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,oBAAoB,CACpD,CAAA;IACH,CAAC;CACF;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,KAAsB;IAKhD,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;QACrB,KAAK,YAAY,CAAC,eAAe;YAC/B,+HAA+H;YAC/H,0HAA0H;YAC1H,OAAO;gBACL,KAAK,EAAE,sBAAsB,CAAC,YAAY,CAAC,mBAAmB,CAAC;gBAC/D,OAAO,EAAE,wBAAwB,CAAC,YAAY,CAAC,mBAAmB,CAAC;gBACnE,IAAI,EAAE,YAAY,CAAC,mBAAmB;aACvC,CAAA;QACH,KAAK,YAAY,CAAC,OAAO;YACvB,2CAA2C;YAC3C,OAAO;gBACL,KAAK,EAAE,sBAAsB,CAAC,YAAY,CAAC,mBAAmB,CAAC;gBAC/D,OAAO,EAAE,wBAAwB,CAAC,YAAY,CAAC,mBAAmB,CAAC;gBACnE,IAAI,EAAE,YAAY,CAAC,mBAAmB;aACvC,CAAA;QACH;YACE,OAAO;gBACL,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,IAAI,EAAE,KAAK,CAAC,MAAM;aACnB,CAAA;IACL,CAAC;AACH,CAAC","sourcesContent":["// eslint-disable-next-line import/default, import/no-named-as-default-member\nimport httpErrors from 'http-errors'\n// eslint-disable-next-line import/no-named-as-default-member\nconst { isHttpError } = httpErrors\nimport { LexError, XrpcError } from '@atproto/lex-client'\nimport { l } from '@atproto/lex-schema'\nimport {\n ResponseType,\n ResponseTypeStrings,\n XRPCError as XRPCClientError,\n httpResponseCodeToName,\n httpResponseCodeToString,\n} from '@atproto/xrpc'\n\n// @NOTE Do not depend (directly or indirectly) on \"./types\" here, as it would\n// create a circular dependency.\n\nexport const errorResult = l.object({\n status: l.integer({ minimum: 400 }),\n error: l.optional(l.string()),\n message: l.optional(l.string()),\n})\nexport type ErrorResult = l.Infer<typeof errorResult>\n\nexport function isErrorResult(v: unknown): v is ErrorResult {\n return errorResult.safeParse(v).success\n}\n\nexport function excludeErrorResult<V>(v: V) {\n if (isErrorResult(v)) throw XRPCError.fromErrorResult(v)\n return v as Exclude<V, ErrorResult>\n}\n\nexport { ResponseType }\n\nexport class XRPCError extends Error {\n constructor(\n public type: ResponseType,\n public errorMessage?: string,\n public customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(errorMessage, options)\n }\n\n get statusCode(): number {\n const { type } = this\n\n // Fool-proofing. `new XRPCError(123.5 as number, '')` does not generate a TypeScript error.\n // Because of this, we can end-up with any numeric value instead of an actual `ResponseType`.\n // For legacy reasons, the `type` argument is not checked in the constructor, so we check it here.\n if (type < 400 || type >= 600 || !Number.isFinite(type)) {\n return 500\n }\n\n return type\n }\n\n get error(): string | undefined {\n return this.customErrorName ?? this.typeName\n }\n\n get payload() {\n return {\n error: this.error,\n message:\n this.type === ResponseType.InternalServerError\n ? this.typeStr // Do not respond with error details for 500s\n : this.errorMessage || this.typeStr,\n }\n }\n\n get typeName(): string | undefined {\n return ResponseType[this.type]\n }\n\n get typeStr(): string | undefined {\n return ResponseTypeStrings[this.type]\n }\n\n static fromError(cause: unknown): XRPCError {\n if (cause instanceof XRPCError) {\n return cause\n }\n\n if (cause instanceof XRPCClientError) {\n const { error, message, type } = mapFromClientError(cause)\n return new XRPCError(type, message, error, { cause })\n }\n\n if (cause instanceof XrpcError) {\n const { status, body } = cause.toDownstreamError()\n return new XRPCError(status, body.message, body.error, { cause })\n }\n\n if (cause instanceof LexError) {\n const data = cause.toJSON()\n const type = ResponseType.InternalServerError\n return new XRPCError(type, data.message, data.error, { cause })\n }\n\n if (isHttpError(cause)) {\n return new XRPCError(cause.status, cause.message, cause.name, { cause })\n }\n\n if (isErrorResult(cause)) {\n return this.fromErrorResult(cause)\n }\n\n if (cause instanceof Error) {\n return new InternalServerError(cause.message, undefined, { cause })\n }\n\n return new InternalServerError(\n 'Unexpected internal server error',\n undefined,\n { cause },\n )\n }\n\n static fromErrorResult(err: ErrorResult): XRPCError {\n return new XRPCError(err.status, err.message, err.error, { cause: err })\n }\n}\n\nexport class InvalidRequestError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.InvalidRequest, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.InvalidRequest\n )\n }\n}\n\nexport class AuthRequiredError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.AuthenticationRequired,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.AuthenticationRequired\n )\n }\n}\n\nexport class ForbiddenError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.Forbidden, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError && instance.type === ResponseType.Forbidden\n )\n }\n}\n\nexport class InternalServerError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.InternalServerError,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.InternalServerError\n )\n }\n}\n\nexport class UpstreamFailureError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.UpstreamFailure, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.UpstreamFailure\n )\n }\n}\n\nexport class NotEnoughResourcesError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.NotEnoughResources,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.NotEnoughResources\n )\n }\n}\n\nexport class UpstreamTimeoutError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(ResponseType.UpstreamTimeout, errorMessage, customErrorName, options)\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.UpstreamTimeout\n )\n }\n}\n\nexport class MethodNotImplementedError extends XRPCError {\n constructor(\n errorMessage?: string,\n customErrorName?: string,\n options?: ErrorOptions,\n ) {\n super(\n ResponseType.MethodNotImplemented,\n errorMessage,\n customErrorName,\n options,\n )\n }\n\n [Symbol.hasInstance](instance: unknown): boolean {\n return (\n instance instanceof XRPCError &&\n instance.type === ResponseType.MethodNotImplemented\n )\n }\n}\n\n/**\n * Converts an upstream XRPC {@link ResponseType} into a downstream {@link ResponseType}.\n */\nfunction mapFromClientError(error: XRPCClientError): {\n error: string\n message: string\n type: ResponseType\n} {\n switch (error.status) {\n case ResponseType.InvalidResponse:\n // Upstream server returned an XRPC response that is not compatible with our internal lexicon definitions for that XRPC method.\n // @NOTE This could be reflected as both a 500 (\"we\" are at fault) and 502 (\"they\" are at fault). Let's be gents about it.\n return {\n error: httpResponseCodeToName(ResponseType.InternalServerError),\n message: httpResponseCodeToString(ResponseType.InternalServerError),\n type: ResponseType.InternalServerError,\n }\n case ResponseType.Unknown:\n // Typically a network error / unknown host\n return {\n error: httpResponseCodeToName(ResponseType.InternalServerError),\n message: httpResponseCodeToString(ResponseType.InternalServerError),\n type: ResponseType.InternalServerError,\n }\n default:\n return {\n error: error.error,\n message: error.message,\n type: error.status,\n }\n }\n}\n"]}