Skip to content

Commit f836ea2

Browse files
docs: add JSDocs to exposed API in 10 utilities (#4741)
This commit adds JSDoc documentation to everything exposed from 10 of the about 30 packages. There’s a lot we are exposing that we don’t need to expose, but also things that are in parameters/return values/elsewhere which we should probably expose, which I noted inline. As for `@arcjet/inspect`, that’s something that was already documented, but also (more up to date) on the website. I kept some small useful things in the code and the readme here, but mostly deferred with links to the website. Related-to: GH-3327.
1 parent 4fdf71f commit f836ea2

File tree

10 files changed

+660
-257
lines changed

10 files changed

+660
-257
lines changed

analyze/index.ts

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,23 @@ function createCoreImports(detect?: DetectSensitiveInfoFunction): ImportObject {
9292
};
9393
}
9494

95-
// TODO(@wooorm-arcjet): document what is used to fingerprint.
9695
/**
97-
* Generate a fingerprint for the client. This is used to identify the client
98-
* across multiple requests.
99-
* @param context - The Arcjet Analyze context.
100-
* @param request - The request to fingerprint.
101-
* @returns A SHA-256 string fingerprint.
96+
* Generate a fingerprint.
97+
*
98+
* Fingerprints can be used to identify the client across multiple requests.
99+
*
100+
* This considers different things on the `request` based on the passed
101+
* `context.characteristics`.
102+
*
103+
* See [*Fingerprints* on
104+
* `docs.arcjet.com`](https://docs.arcjet.com/fingerprints/) for more info.
105+
*
106+
* @param context
107+
* Context.
108+
* @param request
109+
* Request.
110+
* @returns
111+
* Promise for a SHA-256 fingerprint.
102112
*/
103113
export async function generateFingerprint(
104114
context: AnalyzeContext,
@@ -121,18 +131,29 @@ export async function generateFingerprint(
121131
return "";
122132
}
123133

124-
// TODO(@wooorm-arcjet): docs.
134+
/**
135+
* Check whether an email is valid.
136+
*
137+
* @param context
138+
* Context.
139+
* @param value
140+
* Value.
141+
* @param options
142+
* Configuration.
143+
* @returns
144+
* Promise for a result.
145+
*/
125146
export async function isValidEmail(
126147
context: AnalyzeContext,
127-
candidate: string,
148+
value: string,
128149
options: EmailValidationConfig,
129150
): Promise<EmailValidationResult> {
130151
const { log } = context;
131152
const coreImports = createCoreImports();
132153
const analyze = await initializeWasm(coreImports);
133154

134155
if (typeof analyze !== "undefined") {
135-
return analyze.isValidEmail(candidate, options);
156+
return analyze.isValidEmail(value, options);
136157
// Ignore the `else` branch as we test in places that have WebAssembly.
137158
/* node:coverage ignore next 4 */
138159
}
@@ -141,7 +162,18 @@ export async function isValidEmail(
141162
return { blocked: [], validity: "valid" };
142163
}
143164

144-
// TODO(@wooorm-arcjet): docs.
165+
/**
166+
* Detect whether a request is by a bot.
167+
*
168+
* @param context
169+
* Context.
170+
* @param request
171+
* Request.
172+
* @param options
173+
* Configuration.
174+
* @returns
175+
* Promise for a result.
176+
*/
145177
export async function detectBot(
146178
context: AnalyzeContext,
147179
request: AnalyzeRequest,
@@ -161,10 +193,27 @@ export async function detectBot(
161193
return { allowed: [], denied: [], spoofed: false, verified: false };
162194
}
163195

164-
// TODO(@wooorm-arcjet): docs.
196+
/**
197+
* Detect sensitive info in a value.
198+
*
199+
* @param context
200+
* Context.
201+
* @param value
202+
* Value.
203+
* @param entities
204+
* Strategy to use for detecting sensitive info;
205+
* either by denying everything and allowing certain tags or by allowing
206+
* everything and denying certain tags.
207+
* @param contextWindowSize
208+
* Number of tokens to pass to `detect`.
209+
* @param detect
210+
* Function to detect sensitive info (optional).
211+
* @returns
212+
* Promise for a result.
213+
*/
165214
export async function detectSensitiveInfo(
166215
context: AnalyzeContext,
167-
candidate: string,
216+
value: string,
168217
entities: SensitiveInfoEntities,
169218
contextWindowSize: number,
170219
detect?: DetectSensitiveInfoFunction,
@@ -175,7 +224,7 @@ export async function detectSensitiveInfo(
175224

176225
if (typeof analyze !== "undefined") {
177226
const skipCustomDetect = typeof detect !== "function";
178-
return analyze.detectSensitiveInfo(candidate, {
227+
return analyze.detectSensitiveInfo(value, {
179228
entities,
180229
contextWindowSize,
181230
skipCustomDetect,

body/index.ts

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,33 @@
1+
/**
2+
* Configuration.
3+
*/
14
export type ReadBodyOpts = {
2-
limit: number;
5+
/**
6+
* Length of the stream in bytes (optional);
7+
* an error is returned if the contents of the stream do not add up to this length;
8+
* useful when the exact size is known.
9+
*/
310
expectedLength?: number | null | undefined;
11+
/**
12+
* Limit of the body in bytes (required);
13+
* an error is returned if the body ends up being larger than this limit;
14+
* used to prevent reading too much data from malicious clients.
15+
*/
16+
limit: number;
417
};
518

619
type EventHandlerLike = (
720
event: string,
821
listener: (...args: any[]) => void,
922
) => void;
1023

11-
// The fields from stream.Readable that we use
24+
/**
25+
* Stream.
26+
*/
1227
export interface ReadableStreamLike {
1328
on?: EventHandlerLike | null | undefined;
14-
removeListener?: EventHandlerLike | null | undefined;
1529
readable?: boolean | null | undefined;
30+
removeListener?: EventHandlerLike | null | undefined;
1631
}
1732

1833
// This `readBody` function is a derivitive of the `getRawBody` function in the `raw-body`
@@ -46,19 +61,30 @@ export interface ReadableStreamLike {
4661
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
4762
// SOFTWARE.
4863

64+
/**
65+
* Read the body of a stream.
66+
*
67+
* @param stream
68+
* Stream.
69+
* @param options
70+
* Configuration (required).
71+
* @returns
72+
* Promise to a concatenated body.
73+
*/
4974
export async function readBody(
5075
stream: ReadableStreamLike,
51-
opts: ReadBodyOpts,
76+
// TODO(@wooorm-arcjet): make optional.
77+
options: ReadBodyOpts,
5278
): Promise<string> {
5379
const decoder = new TextDecoder("utf-8");
5480
let buffer = "";
5581
let complete = false;
5682
let received = 0;
57-
const limit = opts.limit;
83+
const limit = options.limit;
5884
if (typeof limit !== "number") {
5985
return Promise.reject(new Error("must set a limit"));
6086
}
61-
const length = opts.expectedLength || null;
87+
const length = options.expectedLength || null;
6288

6389
if (typeof stream.readable !== "undefined" && !stream.readable) {
6490
return Promise.reject(new Error("stream is not readable"));

cache/index.ts

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,33 @@
1+
/**
2+
* Interface for a cache.
3+
*/
14
export interface Cache<T = unknown> {
25
/**
3-
* Attempts to retrieve a value from the cache. If a value exists, it will be
4-
* returned with the remaining time-to-live (in seconds).
6+
* Retrieve a value from the cache;
7+
* it will be returned with the remaining time-to-live (in seconds) if it exists.
58
*
6-
* @param namespace A isolated segement of the cache where keys are tracked.
7-
* @param key The identifier used to retrieve the value.
8-
* @returns A promise for a 2-element tuple containing the value and TTL in
9-
* seconds. If no value is retrieved, the value will be `undefined` and the
10-
* TTL will be `0`.
9+
* @param namespace
10+
* Isolated segment of the cache where keys are tracked.
11+
* @param key
12+
* Key.
13+
* @returns
14+
* Promise for a tuple with the value and TTL in seconds;
15+
* value will be `undefined` and TTL will be `0` if not found.
1116
*/
1217
get(namespace: string, key: string): Promise<[T | undefined, number]>;
1318
/**
14-
* If the cache implementation supports storing values, `set` makes a best
15-
* attempt at storing the value provided until the time-to-live specified.
19+
* Store a value in the cache.
1620
*
17-
* @param namespace A isolated segement of the cache where keys are tracked.
18-
* @param key The identifier used to store the value.
19-
* @param value The value to be stored under the key.
20-
* @param ttl The amount of seconds the value stays valid in the cache.
21+
* @param namespace
22+
* Isolated segment of the cache where keys are tracked.
23+
* @param key
24+
* Key.
25+
* @param value
26+
* Value.
27+
* @param ttl
28+
* Number of seconds the entry stays valid.
29+
* @returns
30+
* Nothing.
2131
*/
2232
set(namespace: string, key: string, value: T, ttl: number): void;
2333
}
@@ -58,9 +68,18 @@ class Bucket<T> {
5868
}
5969
}
6070

71+
/**
72+
* In-memory cache.
73+
*/
6174
export class MemoryCache<T> implements Cache<T> {
75+
/**
76+
* Data.
77+
*/
6278
namespaces: Map<string, Bucket<T>>;
6379

80+
/**
81+
* Create a new in-memory cache.
82+
*/
6483
constructor() {
6584
this.namespaces = new Map();
6685
}

decorate/index.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import {
88

99
// If these are defined, we can expect to be working with `Headers` directly.
1010
interface HeaderLike {
11-
has(name: string): boolean;
1211
get(name: string): string | null;
12+
has(name: string): boolean;
1313
set(name: string, value: string): void;
1414
}
1515

@@ -22,12 +22,12 @@ interface ResponseLike {
2222
// Otherwise, we'll be working with an `http.OutgoingMessage` and we'll need
2323
// to use these values.
2424
interface OutgoingMessageLike {
25+
getHeader: (name: string) => string[] | number | string | undefined;
2526
headersSent: boolean;
2627
hasHeader: (name: string) => boolean;
27-
getHeader: (name: string) => number | string | string[] | undefined;
2828
setHeader: (
2929
name: string,
30-
value: number | string | ReadonlyArray<string>,
30+
value: ReadonlyArray<string> | number | string,
3131
) => unknown;
3232
}
3333

@@ -154,14 +154,19 @@ function nearestLimit(
154154
}
155155

156156
/**
157-
* Decorates an object with `RateLimit` and `RateLimit-Policy` headers based
158-
* on an {@link ArcjetDecision} and conforming to the [Rate Limit fields for
157+
* Decorate something based on an Arcjet decision with rate limit headers.
158+
*
159+
* Sets `RateLimit-Policy` and `RateLimit` and conform to the
160+
* [Rate Limit fields for
159161
* HTTP](https://ietf-wg-httpapi.github.io/ratelimit-headers/draft-ietf-httpapi-ratelimit-headers.html)
160162
* draft specification.
161163
*
162-
* @param value The object to decorate—must be similar to {@link Headers}, {@link Response} or
163-
* {@link OutgoingMessage}.
164-
* @param decision The {@link ArcjetDecision} that was made by calling `protect()` on the SDK.
164+
* @param value
165+
* Decorable value.
166+
* @param decision
167+
* Decision from `protect()`.
168+
* @returns
169+
* Nothing.
165170
*/
166171
export function setRateLimitHeaders(
167172
value: ArcjetCanDecorate,

0 commit comments

Comments
 (0)