@clickup/rest-client 2.10.294 → 2.11.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 (120) hide show
  1. package/.eslintrc.base.js +12 -2
  2. package/.eslintrc.js +4 -4
  3. package/.github/workflows/ci.yml +26 -0
  4. package/.github/workflows/semgrep.yml +36 -0
  5. package/.prettierrc +8 -0
  6. package/.vscode/extensions.json +8 -0
  7. package/.vscode/tasks.json +20 -0
  8. package/README.md +2 -0
  9. package/dist/.eslintcache +1 -1
  10. package/dist/RestClient.js +2 -2
  11. package/dist/RestClient.js.map +1 -1
  12. package/dist/RestOptions.d.ts +3 -0
  13. package/dist/RestOptions.d.ts.map +1 -1
  14. package/dist/RestOptions.js +1 -0
  15. package/dist/RestOptions.js.map +1 -1
  16. package/dist/RestRequest.d.ts.map +1 -1
  17. package/dist/RestRequest.js +1 -0
  18. package/dist/RestRequest.js.map +1 -1
  19. package/dist/errors/RestRateLimitError.d.ts.map +1 -1
  20. package/dist/errors/RestRateLimitError.js.map +1 -1
  21. package/dist/errors/RestRetriableError.d.ts.map +1 -1
  22. package/dist/errors/RestRetriableError.js.map +1 -1
  23. package/dist/errors/RestTokenInvalidError.d.ts.map +1 -1
  24. package/dist/errors/RestTokenInvalidError.js.map +1 -1
  25. package/dist/index.d.ts +2 -5
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +1 -5
  28. package/dist/index.js.map +1 -1
  29. package/dist/internal/RestFetchReader.d.ts +4 -2
  30. package/dist/internal/RestFetchReader.d.ts.map +1 -1
  31. package/dist/internal/RestFetchReader.js +4 -4
  32. package/dist/internal/RestFetchReader.js.map +1 -1
  33. package/dist/internal/ellipsis.d.ts +6 -0
  34. package/dist/internal/ellipsis.d.ts.map +1 -0
  35. package/dist/internal/ellipsis.js +17 -0
  36. package/dist/internal/ellipsis.js.map +1 -0
  37. package/dist/internal/inferResBodyEncoding.js.map +1 -1
  38. package/dist/internal/inspectPossibleJSON.js +5 -8
  39. package/dist/internal/inspectPossibleJSON.js.map +1 -1
  40. package/dist/internal/throwIfErrorResponse.js +1 -1
  41. package/dist/internal/throwIfErrorResponse.js.map +1 -1
  42. package/dist/middlewares/paceRequests.d.ts +21 -2
  43. package/dist/middlewares/paceRequests.d.ts.map +1 -1
  44. package/dist/middlewares/paceRequests.js +3 -2
  45. package/dist/middlewares/paceRequests.js.map +1 -1
  46. package/docs/README.md +2 -0
  47. package/docs/classes/RestClient.md +32 -28
  48. package/docs/classes/RestContentSizeOverLimitError.md +5 -1
  49. package/docs/classes/RestError.md +5 -1
  50. package/docs/classes/RestRateLimitError.md +6 -2
  51. package/docs/classes/RestRequest.md +22 -18
  52. package/docs/classes/RestResponse.md +7 -3
  53. package/docs/classes/RestResponseError.md +5 -1
  54. package/docs/classes/RestRetriableError.md +6 -2
  55. package/docs/classes/RestStream.md +12 -8
  56. package/docs/classes/RestTimeoutError.md +5 -1
  57. package/docs/classes/RestTokenInvalidError.md +6 -2
  58. package/docs/interfaces/Middleware.md +4 -4
  59. package/docs/interfaces/Pacer.md +7 -12
  60. package/docs/interfaces/PacerOutcome.md +25 -0
  61. package/docs/interfaces/RestLogEvent.md +1 -1
  62. package/docs/interfaces/RestOptions.md +42 -30
  63. package/docs/interfaces/TokenGetter.md +3 -3
  64. package/docs/modules.md +8 -11
  65. package/internal/clean.sh +4 -0
  66. package/internal/deploy.sh +7 -0
  67. package/internal/docs.sh +6 -0
  68. package/internal/lint.sh +4 -0
  69. package/jest.config.base.js +13 -0
  70. package/jest.config.js +1 -10
  71. package/package.json +10 -6
  72. package/src/RestClient.ts +21 -21
  73. package/src/RestOptions.ts +6 -3
  74. package/src/RestRequest.ts +12 -11
  75. package/src/RestResponse.ts +1 -1
  76. package/src/RestStream.ts +1 -1
  77. package/src/__tests__/RestClient.test.ts +53 -0
  78. package/src/__tests__/RestFetchReader.test.ts +150 -0
  79. package/src/__tests__/RestRequest.test.ts +262 -0
  80. package/src/__tests__/RestStream.test.ts +63 -0
  81. package/src/__tests__/helpers.ts +173 -0
  82. package/src/errors/RestRateLimitError.ts +5 -1
  83. package/src/errors/RestResponseError.ts +3 -3
  84. package/src/errors/RestRetriableError.ts +5 -1
  85. package/src/errors/RestTokenInvalidError.ts +4 -1
  86. package/src/helpers/depaginate.ts +3 -3
  87. package/src/index.ts +2 -7
  88. package/src/internal/RestFetchReader.ts +6 -3
  89. package/src/internal/RestRangeUploader.ts +2 -2
  90. package/src/internal/calcRetryDelay.ts +2 -2
  91. package/src/internal/ellipsis.ts +16 -0
  92. package/src/internal/inferResBodyEncoding.ts +13 -13
  93. package/src/internal/inspectPossibleJSON.ts +6 -10
  94. package/src/internal/substituteParams.ts +1 -1
  95. package/src/internal/throwIfErrorResponse.ts +8 -8
  96. package/src/middlewares/paceRequests.ts +28 -3
  97. package/tsconfig.base.json +31 -0
  98. package/tsconfig.json +1 -32
  99. package/typedoc.config.js +20 -0
  100. package/dist/pacers/Pacer.d.ts +0 -21
  101. package/dist/pacers/Pacer.d.ts.map +0 -1
  102. package/dist/pacers/Pacer.js +0 -3
  103. package/dist/pacers/Pacer.js.map +0 -1
  104. package/dist/pacers/PacerComposite.d.ts +0 -14
  105. package/dist/pacers/PacerComposite.d.ts.map +0 -1
  106. package/dist/pacers/PacerComposite.js +0 -32
  107. package/dist/pacers/PacerComposite.js.map +0 -1
  108. package/dist/pacers/PacerQPS.d.ts +0 -53
  109. package/dist/pacers/PacerQPS.d.ts.map +0 -1
  110. package/dist/pacers/PacerQPS.js +0 -105
  111. package/dist/pacers/PacerQPS.js.map +0 -1
  112. package/docs/classes/PacerComposite.md +0 -62
  113. package/docs/classes/PacerQPS.md +0 -75
  114. package/docs/interfaces/PacerDelay.md +0 -25
  115. package/docs/interfaces/PacerQPSBackend.md +0 -44
  116. package/docs/interfaces/PacerQPSOptions.md +0 -40
  117. package/src/pacers/Pacer.ts +0 -22
  118. package/src/pacers/PacerComposite.ts +0 -29
  119. package/src/pacers/PacerQPS.ts +0 -147
  120. package/typedoc.json +0 -22
@@ -8,8 +8,8 @@
8
8
  */
9
9
  export default async function* depaginate<TItem, TCursor = string>(
10
10
  readFunc: (
11
- cursor: TCursor | undefined
12
- ) => Promise<readonly [TItem[], TCursor | null | undefined]>
11
+ cursor: TCursor | undefined,
12
+ ) => Promise<readonly [TItem[], TCursor | null | undefined]>,
13
13
  ): AsyncGenerator<TItem, void, undefined> {
14
14
  let prevCursor: TCursor | null | undefined = undefined;
15
15
  let cursor: TCursor | null | undefined = undefined;
@@ -28,7 +28,7 @@ export default async function* depaginate<TItem, TCursor = string>(
28
28
  JSON.stringify(prevCursor) +
29
29
  ", cursor=" +
30
30
  JSON.stringify(cursor) +
31
- " (they must differ)"
31
+ " (they must differ)",
32
32
  );
33
33
  }
34
34
 
package/src/index.ts CHANGED
@@ -7,10 +7,7 @@ import RestRetriableError from "./errors/RestRetriableError";
7
7
  import RestTimeoutError from "./errors/RestTimeoutError";
8
8
  import RestTokenInvalidError from "./errors/RestTokenInvalidError";
9
9
  import depaginate from "./helpers/depaginate";
10
- import paceRequests from "./middlewares/paceRequests";
11
- import Pacer from "./pacers/Pacer";
12
- import PacerComposite from "./pacers/PacerComposite";
13
- import PacerQPS, { PacerQPSBackend } from "./pacers/PacerQPS";
10
+ import paceRequests, { Pacer, PacerOutcome } from "./middlewares/paceRequests";
14
11
  import RestClient, { TokenGetter } from "./RestClient";
15
12
  import RestOptions, {
16
13
  RestLogEvent,
@@ -29,10 +26,8 @@ export {
29
26
  Headers,
30
27
  Middleware,
31
28
  Pacer,
32
- PacerComposite,
33
29
  paceRequests,
34
- PacerQPS,
35
- PacerQPSBackend,
30
+ PacerOutcome,
36
31
  RestClient,
37
32
  RestContentSizeOverLimitError,
38
33
  RestError,
@@ -10,6 +10,7 @@ export interface RestFetchReaderOptions {
10
10
  heartbeat?: () => Promise<void>;
11
11
  onTimeout?: (reader: RestFetchReader, e: any) => void;
12
12
  onAfterRead?: (reader: RestFetchReader) => void;
13
+ responseEncoding?: NodeJS.BufferEncoding;
13
14
  }
14
15
 
15
16
  /**
@@ -34,7 +35,7 @@ export default class RestFetchReader {
34
35
  constructor(
35
36
  private _url: string,
36
37
  private _reqInit: RequestInit,
37
- private _options: RestFetchReaderOptions
38
+ private _options: RestFetchReaderOptions,
38
39
  ) {}
39
40
 
40
41
  /**
@@ -151,7 +152,7 @@ export default class RestFetchReader {
151
152
  new Request(this._url, {
152
153
  ...this._reqInit,
153
154
  signal: controller.signal as any,
154
- })
155
+ }),
155
156
  );
156
157
  this._status = res.status;
157
158
  this._headers = res.headers;
@@ -160,7 +161,9 @@ export default class RestFetchReader {
160
161
  // how Node streams and setEncoding() handle decoding when the returned
161
162
  // chunks cross the boundaries of multi-byte characters (TL;DR: it works
162
163
  // fine, that's why we work with string and not Buffer here).
163
- res.body.setEncoding(inferResBodyEncoding(res));
164
+ res.body.setEncoding(
165
+ this._options.responseEncoding ?? inferResBodyEncoding(res),
166
+ );
164
167
 
165
168
  await this._options.heartbeat?.();
166
169
  for await (const chunk of res.body) {
@@ -18,7 +18,7 @@ export default class RestRangeUploader {
18
18
  private _chunkSize: number,
19
19
  private _method: "POST" | "PUT",
20
20
  private _path: string,
21
- private _mimeType: string
21
+ private _mimeType: string,
22
22
  ) {}
23
23
 
24
24
  async upload(stream: AsyncIterable<Buffer>) {
@@ -52,7 +52,7 @@ export default class RestRangeUploader {
52
52
  .writeRaw(this._path, buf, this._mimeType, this._method, "*/*")
53
53
  .setHeader(
54
54
  "Content-Range",
55
- `bytes ${this._pos}-${this._pos + buf.length - 1}/${totalSize}`
55
+ `bytes ${this._pos}-${this._pos + buf.length - 1}/${totalSize}`,
56
56
  )
57
57
  .text();
58
58
  this._pos += buf.length;
@@ -13,7 +13,7 @@ export default function calcRetryDelay(
13
13
  error: any,
14
14
  options: RestOptions,
15
15
  res: RestResponse,
16
- retryDelayMs: number
16
+ retryDelayMs: number,
17
17
  ): number | "no_retry" {
18
18
  if (
19
19
  error instanceof RestRateLimitError ||
@@ -22,7 +22,7 @@ export default function calcRetryDelay(
22
22
  // We've already made a decision to retry this error.
23
23
  return Math.min(
24
24
  options.retryDelayMaxMs,
25
- Math.max(retryDelayMs, error.delayMs)
25
+ Math.max(retryDelayMs, error.delayMs),
26
26
  );
27
27
  }
28
28
 
@@ -0,0 +1,16 @@
1
+ const ELLIPSIS = "…";
2
+
3
+ /**
4
+ * The fastest possible version of truncation. Lodash'es truncate() messes up
5
+ * with unicode a lot, so for e.g. logging purposes, it's super-slow.
6
+ */
7
+ export default function ellipsis(string: any, length: number) {
8
+ string = ("" + string).trimEnd();
9
+ length = Math.max(length, ELLIPSIS.length);
10
+
11
+ if (string.length <= length) {
12
+ return string;
13
+ }
14
+
15
+ return string.substring(0, length - ELLIPSIS.length) + ELLIPSIS;
16
+ }
@@ -17,17 +17,17 @@ export default function inferResBodyEncoding(res: Response): BufferEncoding {
17
17
  ? // It's a binary Content-Type.
18
18
  "binary"
19
19
  : charset && !BUFFER_ENCODINGS.includes(charset)
20
- ? // The charset is provided in Content-Type, but unknown by Buffer.
21
- "binary"
22
- : charset && BUFFER_ENCODINGS.includes(charset)
23
- ? // Charset is provided in Content-Type header, and Buffer knows
24
- // how to decode it.
25
- (charset as BufferEncoding)
26
- : // An opinionated choice is made here to always default-decode the
27
- // response stream as UTF-8. This is because JSON is by definition a UTF-8
28
- // stream, and people often time respond with JSONs forgetting to provide
29
- // "; charset=utf-8" part of the Content-Type header (or they forget
30
- // Content-Type header at all, or put some wrong value as "text/plain"
31
- // there; there is an endless list of mistake variations here).
32
- "utf-8";
20
+ ? // The charset is provided in Content-Type, but unknown by Buffer.
21
+ "binary"
22
+ : charset && BUFFER_ENCODINGS.includes(charset)
23
+ ? // Charset is provided in Content-Type header, and Buffer knows
24
+ // how to decode it.
25
+ (charset as BufferEncoding)
26
+ : // An opinionated choice is made here to always default-decode the
27
+ // response stream as UTF-8. This is because JSON is by definition a UTF-8
28
+ // stream, and people often time respond with JSONs forgetting to provide
29
+ // "; charset=utf-8" part of the Content-Type header (or they forget
30
+ // Content-Type header at all, or put some wrong value as "text/plain"
31
+ // there; there is an endless list of mistake variations here).
32
+ "utf-8";
33
33
  }
@@ -1,11 +1,11 @@
1
1
  import { inspect } from "util";
2
2
  import sortBy from "lodash/sortBy";
3
- import truncate from "lodash/truncate";
3
+ import ellipsis from "./ellipsis";
4
4
 
5
5
  export default function inspectPossibleJSON(
6
6
  headers: { get(name: string): string | null },
7
7
  text: string | Buffer | NodeJS.ReadableStream,
8
- maxOutputLen: number
8
+ maxOutputLen: number,
9
9
  ): string {
10
10
  const MAX_LEN_TO_TRY_PARSE = 1024 * 1024;
11
11
 
@@ -31,13 +31,13 @@ export default function inspectPossibleJSON(
31
31
  // man's approach: of course not all APIs return error/errors fields at
32
32
  // all, but it's hard to reorder at any other layer of abstraction.
33
33
  reorderObjectProps(json, (k) =>
34
- k === "error" || k === "errors" ? "" : k
34
+ k === "error" || k === "errors" ? "" : k,
35
35
  );
36
36
  }
37
37
 
38
38
  return ellipsis(
39
39
  inspect(json, { depth: 20, compact: true }),
40
- maxOutputLen
40
+ maxOutputLen,
41
41
  );
42
42
  } catch (e: any) {
43
43
  return ellipsis(text, maxOutputLen);
@@ -53,7 +53,7 @@ export default function inspectPossibleJSON(
53
53
  */
54
54
  function reorderObjectProps(
55
55
  obj: Record<string, any>,
56
- ranker: (k: string, v: any) => string | number
56
+ ranker: (k: string, v: any) => string | number,
57
57
  ) {
58
58
  const entries = Object.entries(obj);
59
59
  for (const k in obj) {
@@ -62,10 +62,6 @@ function reorderObjectProps(
62
62
 
63
63
  Object.assign(
64
64
  obj,
65
- Object.fromEntries(sortBy(entries, ([k, v]) => ranker(k, v)))
65
+ Object.fromEntries(sortBy(entries, ([k, v]) => ranker(k, v))),
66
66
  );
67
67
  }
68
-
69
- function ellipsis(text: any, length: number) {
70
- return truncate("" + text, { length }).trimEnd();
71
- }
@@ -5,7 +5,7 @@
5
5
  */
6
6
  export default function substituteParams<TBody>(
7
7
  url: string,
8
- body: TBody
8
+ body: TBody,
9
9
  ): [string, TBody] {
10
10
  if (!body || typeof body !== "object") {
11
11
  return [url, body];
@@ -16,7 +16,7 @@ const STATUS_TOO_MANY_REQUESTS = 429;
16
16
  */
17
17
  export default function throwIfErrorResponse(
18
18
  options: RestOptions,
19
- res: RestResponse
19
+ res: RestResponse,
20
20
  ) {
21
21
  const isSuccessResponse = options.isSuccessResponse(res);
22
22
  if (isSuccessResponse === "SUCCESS") {
@@ -29,15 +29,15 @@ export default function throwIfErrorResponse(
29
29
  throw new RestRateLimitError(
30
30
  `isRateLimitError() returned ${rateLimitDelayMs}`,
31
31
  0,
32
- res
32
+ res,
33
33
  );
34
34
  case "BEST_EFFORT":
35
35
  if (res.status === STATUS_TOO_MANY_REQUESTS) {
36
36
  const retryAfterHeader = res.headers.get("Retry-After") || "0";
37
37
  throw new RestRateLimitError(
38
38
  `Rate limited by HTTP status ${STATUS_TOO_MANY_REQUESTS}`,
39
- parseInt(retryAfterHeader) || 0,
40
- res
39
+ 1000 * parseInt(retryAfterHeader) || 0,
40
+ res,
41
41
  );
42
42
  }
43
43
 
@@ -48,7 +48,7 @@ export default function throwIfErrorResponse(
48
48
  throw new RestRateLimitError(
49
49
  `isRateLimitError() returned retry delay ${rateLimitDelayMs} ms`,
50
50
  rateLimitDelayMs,
51
- res
51
+ res,
52
52
  );
53
53
  }
54
54
 
@@ -63,7 +63,7 @@ export default function throwIfErrorResponse(
63
63
  throw new RestRetriableError(
64
64
  `isRetriableError() returned ${retryDelayMs}`,
65
65
  0,
66
- res
66
+ res,
67
67
  );
68
68
  case "BEST_EFFORT":
69
69
  case "NEVER_RETRY":
@@ -72,14 +72,14 @@ export default function throwIfErrorResponse(
72
72
  throw new RestRetriableError(
73
73
  `"isRetriableError() returned retry delay ${retryDelayMs} ms`,
74
74
  retryDelayMs,
75
- res
75
+ res,
76
76
  );
77
77
  }
78
78
 
79
79
  if (isSuccessResponse === "THROW") {
80
80
  throw new RestResponseError(
81
81
  `isSuccessResponse() returned ${isSuccessResponse}`,
82
- res
82
+ res,
83
83
  );
84
84
  }
85
85
 
@@ -1,15 +1,38 @@
1
- import type Pacer from "../pacers/Pacer";
2
1
  import type { Middleware } from "../RestOptions";
3
2
  import type RestRequest from "../RestRequest";
4
3
 
5
4
  const MIN_LOG_DELAY_MS = 10;
6
5
 
6
+ /**
7
+ * Pacer is a class which allows to pace requests on some resource identified by
8
+ * the instance of this class.
9
+ */
10
+ export interface Pacer {
11
+ /** Human readable name of the pacer, used when composing multiple pacers. */
12
+ readonly key: string;
13
+
14
+ /**
15
+ * Signals that we're about to send a request. Returns the delay we need to
16
+ * wait for before actually sending.
17
+ */
18
+ pace(): Promise<PacerOutcome>;
19
+ }
20
+
21
+ /**
22
+ * A result of some Pacer work.
23
+ */
24
+ export interface PacerOutcome {
25
+ delayMs: number;
26
+ reason: string;
27
+ }
28
+
7
29
  /**
8
30
  * Rest Client middleware that adds some delay between requests using one of
9
31
  * Pacer implementations.
10
32
  */
11
33
  export default function paceRequests(
12
- pacer: Pacer | ((req: RestRequest) => Promise<Pacer | null>) | null
34
+ pacer: Pacer | ((req: RestRequest) => Promise<Pacer | null>) | null,
35
+ delayMetric?: (delay: number, reason: string) => void,
13
36
  ): Middleware {
14
37
  return async (req, next) => {
15
38
  if (typeof pacer === "function") {
@@ -17,8 +40,10 @@ export default function paceRequests(
17
40
  }
18
41
 
19
42
  if (pacer) {
20
- const { delayMs, reason } = await pacer.touch();
43
+ const { delayMs, reason } = await pacer.pace();
44
+
21
45
  if (delayMs > 0) {
46
+ delayMetric?.(delayMs, reason);
22
47
  await req.options.heartbeater.delay(delayMs);
23
48
  }
24
49
 
@@ -0,0 +1,31 @@
1
+ {
2
+ "include": ["src/**/*"],
3
+ "compilerOptions": {
4
+ "allowJs": true,
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "disableReferencedProjectLoad": true,
8
+ "disableSourceOfProjectReferenceRedirect": true,
9
+ "esModuleInterop": true,
10
+ "experimentalDecorators": true,
11
+ "incremental": true,
12
+ "lib": ["ES2019"],
13
+ "module": "Node16",
14
+ "noEmitOnError": true,
15
+ "noErrorTruncation": true,
16
+ "noImplicitOverride": true,
17
+ "noImplicitReturns": true,
18
+ "noPropertyAccessFromIndexSignature": true,
19
+ "outDir": "dist",
20
+ "pretty": true,
21
+ "removeComments": false,
22
+ "resolveJsonModule": true,
23
+ "rootDir": "src",
24
+ "skipLibCheck": true,
25
+ "sourceMap": true,
26
+ "strict": true,
27
+ "target": "ES2019",
28
+ "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo",
29
+ "types": ["node", "jest"]
30
+ }
31
+ }
package/tsconfig.json CHANGED
@@ -1,32 +1 @@
1
- {
2
- "include": ["src/**/*"],
3
- "compilerOptions": {
4
- "allowJs": true,
5
- "declaration": true,
6
- "declarationMap": true,
7
- "disableReferencedProjectLoad": true,
8
- "disableSourceOfProjectReferenceRedirect": true,
9
- "esModuleInterop": true,
10
- "experimentalDecorators": true,
11
- "incremental": true,
12
- "lib": ["es2019"],
13
- "module": "commonjs",
14
- "moduleResolution": "node",
15
- "noEmitOnError": true,
16
- "noErrorTruncation": true,
17
- "noImplicitOverride": true,
18
- "noImplicitReturns": true,
19
- "noPropertyAccessFromIndexSignature": true,
20
- "outDir": "dist",
21
- "pretty": true,
22
- "removeComments": false,
23
- "resolveJsonModule": true,
24
- "rootDir": "src",
25
- "skipLibCheck": true,
26
- "sourceMap": true,
27
- "strict": true,
28
- "target": "es2019",
29
- "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo",
30
- "types": ["node", "jest"]
31
- }
32
- }
1
+ { "extends": "./tsconfig.base.json" }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ const { basename } = require("path");
3
+
4
+ module.exports = {
5
+ entryPoints: ["src"],
6
+ exclude: ["**/internal/**", "**/__tests__/**", "**/node_modules/**"],
7
+ entryPointStrategy: "expand",
8
+ mergeModulesMergeMode: "project",
9
+ sort: ["source-order"],
10
+ out: "docs",
11
+ logLevel: "Warn",
12
+ hideGenerator: true,
13
+ excludeInternal: true,
14
+ excludePrivate: true,
15
+ categorizeByGroup: true,
16
+ hideInPageTOC: true,
17
+ gitRevision: "master",
18
+ sourceLinkTemplate: `https://github.com/clickup/${basename(__dirname)}/blob/master/{path}#L{line}`,
19
+ basePath: ".",
20
+ };
@@ -1,21 +0,0 @@
1
- /**
2
- * A result of some Pacer work.
3
- */
4
- export interface PacerDelay {
5
- delayMs: number;
6
- reason: string;
7
- }
8
- /**
9
- * Pacer is a class which allows to pace requests on some resource identified by
10
- * the instance of this class.
11
- */
12
- export default interface Pacer {
13
- /** Human readable name of the pacer, used when composing multiple pacers. */
14
- readonly name: string;
15
- /**
16
- * Signals that we're about to send a request. Returns the delay we need to
17
- * wait for before actually sending.
18
- */
19
- touch(): Promise<PacerDelay>;
20
- }
21
- //# sourceMappingURL=Pacer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Pacer.d.ts","sourceRoot":"","sources":["../../src/pacers/Pacer.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,CAAC,OAAO,WAAW,KAAK;IAC5B,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;CAC9B"}
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=Pacer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Pacer.js","sourceRoot":"","sources":["../../src/pacers/Pacer.ts"],"names":[],"mappings":""}
@@ -1,14 +0,0 @@
1
- import type Pacer from "./Pacer";
2
- /**
3
- * A Pacer which runs all sub-pacers and chooses the largest delay.
4
- */
5
- export default class PacerComposite implements Pacer {
6
- private _pacers;
7
- readonly name = "";
8
- constructor(_pacers: Pacer[]);
9
- touch(): Promise<{
10
- reason: string;
11
- delayMs: number;
12
- }>;
13
- }
14
- //# sourceMappingURL=PacerComposite.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PacerComposite.d.ts","sourceRoot":"","sources":["../../src/pacers/PacerComposite.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,SAAS,CAAC;AAEjC;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,cAAe,YAAW,KAAK;IAGtC,OAAO,CAAC,OAAO;IAF3B,QAAQ,CAAC,IAAI,MAAM;gBAEC,OAAO,EAAE,KAAK,EAAE;IAE9B,KAAK;;;;CAiBZ"}
@@ -1,32 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const maxBy_1 = __importDefault(require("lodash/maxBy"));
7
- /**
8
- * A Pacer which runs all sub-pacers and chooses the largest delay.
9
- */
10
- class PacerComposite {
11
- constructor(_pacers) {
12
- this._pacers = _pacers;
13
- this.name = "";
14
- }
15
- async touch() {
16
- const delays = await Promise["all"](this._pacers.map(async (pacer) => ({
17
- pacer,
18
- delay: await pacer.touch(),
19
- })));
20
- const pair = (0, maxBy_1.default)(delays, ({ delay }) => delay.delayMs);
21
- return pair
22
- ? {
23
- ...pair.delay,
24
- reason: pair.pacer.name
25
- ? `${pair.pacer.constructor.name} ${pair.pacer.name}\n${pair.delay.reason}`
26
- : pair.delay.reason,
27
- }
28
- : { delayMs: 0, reason: "no pacers" };
29
- }
30
- }
31
- exports.default = PacerComposite;
32
- //# sourceMappingURL=PacerComposite.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PacerComposite.js","sourceRoot":"","sources":["../../src/pacers/PacerComposite.ts"],"names":[],"mappings":";;;;;AAAA,yDAAiC;AAGjC;;GAEG;AACH,MAAqB,cAAc;IAGjC,YAAoB,OAAgB;QAAhB,YAAO,GAAP,OAAO,CAAS;QAF3B,SAAI,GAAG,EAAE,CAAC;IAEoB,CAAC;IAExC,KAAK,CAAC,KAAK;QACT,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,CACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YACjC,KAAK;YACL,KAAK,EAAE,MAAM,KAAK,CAAC,KAAK,EAAE;SAC3B,CAAC,CAAC,CACJ,CAAC;QACF,MAAM,IAAI,GAAG,IAAA,eAAK,EAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACzD,OAAO,IAAI;YACT,CAAC,CAAC;gBACE,GAAG,IAAI,CAAC,KAAK;gBACb,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;oBACrB,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;oBAC3E,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM;aACtB;YACH,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAC1C,CAAC;CACF;AAtBD,iCAsBC"}
@@ -1,53 +0,0 @@
1
- import type { PacerDelay } from "./Pacer";
2
- import type Pacer from "./Pacer";
3
- export interface PacerQPSBackend {
4
- /** Resource key which this backend is operating on. */
5
- readonly key: string;
6
- /**
7
- * Maintains the array of numbers somewhere in memory (time-value pairs),
8
- * inserts a new time-value pair to the end of this list, and removes all the
9
- * entries which are earlier than `minTime`. Returns the size of the resulting
10
- * array and some central tendency statistics about its values.
11
- */
12
- push(props: {
13
- time: number;
14
- minTime: number;
15
- value: number;
16
- minCountForCentralTendency: number;
17
- }): Promise<{
18
- count: number;
19
- sum: number;
20
- avg: number;
21
- median: number;
22
- }>;
23
- }
24
- export interface PacerQPSOptions {
25
- /** The maximum QPS allowed within the rolling window. */
26
- qps: number;
27
- /** The length of the rolling windows in milliseconds. */
28
- windowSec?: number;
29
- /** Decrease the delay if the number of requests in the window has dropped
30
- * below `decreaseThreshold` portion of the limit. */
31
- decreaseThreshold?: number;
32
- }
33
- /**
34
- * Implements a very simple heuristic:
35
- * - increase the delay if we're above the QPS within the rolling window;
36
- * - decrease the delay if we're below the desired QPS.
37
- *
38
- * Each worker keeps (and grows/shrinks) its delay individually; this way, we
39
- * don't need to elect, who's the "source of truth" for the delay.
40
- *
41
- * Backend is a concrete (and minimal) implementation of the storage logic for
42
- * the pacing algorithm.
43
- */
44
- export default class PacerQPS implements Pacer {
45
- private _options;
46
- private _backend;
47
- private _isFirstTouch;
48
- private _delay;
49
- constructor(_options: PacerQPSOptions, _backend: PacerQPSBackend);
50
- get name(): string;
51
- touch(): Promise<PacerDelay>;
52
- }
53
- //# sourceMappingURL=PacerQPS.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PacerQPS.d.ts","sourceRoot":"","sources":["../../src/pacers/PacerQPS.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,KAAK,KAAK,MAAM,SAAS,CAAC;AA4BjC,MAAM,WAAW,eAAe;IAC9B,uDAAuD;IACvD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB;;;;;OAKG;IACH,IAAI,CAAC,KAAK,EAAE;QACV,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,0BAA0B,EAAE,MAAM,CAAC;KACpC,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1E;AAED,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,GAAG,EAAE,MAAM,CAAC;IACZ,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;yDACqD;IACrD,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,OAAO,OAAO,QAAS,YAAW,KAAK;IAK1C,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,QAAQ;IALlB,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,MAAM,CAAK;gBAGT,QAAQ,EAAE,eAAe,EACzB,QAAQ,EAAE,eAAe;IAGnC,IAAI,IAAI,WAEP;IAEK,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC;CAgEnC"}