@arcjet/node 1.0.0-alpha.21 → 1.0.0-alpha.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +5 -0
- package/index.js +60 -2
- package/index.ts +78 -1
- package/package.json +13 -12
package/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export type RemoteClientOptions = {
|
|
|
15
15
|
timeout?: number;
|
|
16
16
|
};
|
|
17
17
|
export declare function createRemoteClient(options?: RemoteClientOptions): import("@arcjet/protocol/client.js").Client;
|
|
18
|
+
type EventHandlerLike = (event: string, listener: (...args: any[]) => void) => void;
|
|
18
19
|
export interface ArcjetNodeRequest {
|
|
19
20
|
headers?: Record<string, string | string[] | undefined>;
|
|
20
21
|
socket?: Partial<{
|
|
@@ -24,6 +25,10 @@ export interface ArcjetNodeRequest {
|
|
|
24
25
|
method?: string;
|
|
25
26
|
httpVersion?: string;
|
|
26
27
|
url?: string;
|
|
28
|
+
body?: unknown;
|
|
29
|
+
on?: EventHandlerLike;
|
|
30
|
+
removeListener?: EventHandlerLike;
|
|
31
|
+
readable?: boolean;
|
|
27
32
|
}
|
|
28
33
|
/**
|
|
29
34
|
* The ArcjetNode client provides a public `protect()` method to
|
package/index.js
CHANGED
|
@@ -6,7 +6,22 @@ import { logLevel, baseUrl, isDevelopment, platform } from '@arcjet/env';
|
|
|
6
6
|
import { Logger } from '@arcjet/logger';
|
|
7
7
|
import { createClient } from '@arcjet/protocol/client.js';
|
|
8
8
|
import { createTransport } from '@arcjet/transport';
|
|
9
|
+
import { readBody } from '@arcjet/body';
|
|
9
10
|
|
|
11
|
+
// TODO: Deduplicate with other packages
|
|
12
|
+
function errorMessage(err) {
|
|
13
|
+
if (err) {
|
|
14
|
+
if (typeof err === "string") {
|
|
15
|
+
return err;
|
|
16
|
+
}
|
|
17
|
+
if (typeof err === "object" &&
|
|
18
|
+
"message" in err &&
|
|
19
|
+
typeof err.message === "string") {
|
|
20
|
+
return err.message;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return "Unknown problem";
|
|
24
|
+
}
|
|
10
25
|
function createRemoteClient(options) {
|
|
11
26
|
// The base URL for the Arcjet API. Will default to the standard production
|
|
12
27
|
// API unless environment variable `ARCJET_BASE_URL` is set.
|
|
@@ -17,7 +32,7 @@ function createRemoteClient(options) {
|
|
|
17
32
|
// Transport is the HTTP client that the client uses to make requests.
|
|
18
33
|
const transport = createTransport(url);
|
|
19
34
|
const sdkStack = "NODEJS";
|
|
20
|
-
const sdkVersion = "1.0.0-alpha.
|
|
35
|
+
const sdkVersion = "1.0.0-alpha.22";
|
|
21
36
|
return createClient({
|
|
22
37
|
transport,
|
|
23
38
|
baseUrl: url,
|
|
@@ -122,7 +137,50 @@ function arcjet(options) {
|
|
|
122
137
|
// Further investigation makes it seem like it has something to do with
|
|
123
138
|
// the definition of `props` in the signature but it's hard to track down
|
|
124
139
|
const req = toArcjetRequest(request, props ?? {});
|
|
125
|
-
|
|
140
|
+
const getBody = async () => {
|
|
141
|
+
try {
|
|
142
|
+
// If request.body is present then the body was likely read by a package like express' `body-parser`.
|
|
143
|
+
// If it's not present then we attempt to read the bytes from the IncomingMessage ourselves.
|
|
144
|
+
if (typeof request.body === "string") {
|
|
145
|
+
return request.body;
|
|
146
|
+
}
|
|
147
|
+
else if (typeof request.body !== "undefined" &&
|
|
148
|
+
// BigInt cannot be serialized with JSON.stringify
|
|
149
|
+
typeof request.body !== "bigint") {
|
|
150
|
+
return JSON.stringify(request.body);
|
|
151
|
+
}
|
|
152
|
+
if (typeof request.on === "function" &&
|
|
153
|
+
typeof request.removeListener === "function") {
|
|
154
|
+
let expectedLength;
|
|
155
|
+
// TODO: This shouldn't need to build headers again but the type
|
|
156
|
+
// for `req` above is overly relaxed
|
|
157
|
+
const headers = new ArcjetHeaders(request.headers);
|
|
158
|
+
const expectedLengthStr = headers.get("content-length");
|
|
159
|
+
if (typeof expectedLengthStr === "string") {
|
|
160
|
+
try {
|
|
161
|
+
expectedLength = parseInt(expectedLengthStr, 10);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// If the expected length couldn't be parsed we'll just not set one.
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Awaited to throw if it rejects and we'll just return undefined
|
|
168
|
+
const body = await readBody(request, {
|
|
169
|
+
// We will process 1mb bodies
|
|
170
|
+
limit: 1048576,
|
|
171
|
+
expectedLength,
|
|
172
|
+
});
|
|
173
|
+
return body;
|
|
174
|
+
}
|
|
175
|
+
log.warn("no body available");
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
catch (e) {
|
|
179
|
+
log.error("failed to get request body: %s", errorMessage(e));
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
return aj.protect({ getBody }, req);
|
|
126
184
|
},
|
|
127
185
|
});
|
|
128
186
|
}
|
package/index.ts
CHANGED
|
@@ -15,10 +15,30 @@ import { baseUrl, isDevelopment, logLevel, platform } from "@arcjet/env";
|
|
|
15
15
|
import { Logger } from "@arcjet/logger";
|
|
16
16
|
import { createClient } from "@arcjet/protocol/client.js";
|
|
17
17
|
import { createTransport } from "@arcjet/transport";
|
|
18
|
+
import { readBody } from "@arcjet/body";
|
|
18
19
|
|
|
19
20
|
// Re-export all named exports from the generic SDK
|
|
20
21
|
export * from "arcjet";
|
|
21
22
|
|
|
23
|
+
// TODO: Deduplicate with other packages
|
|
24
|
+
function errorMessage(err: unknown): string {
|
|
25
|
+
if (err) {
|
|
26
|
+
if (typeof err === "string") {
|
|
27
|
+
return err;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (
|
|
31
|
+
typeof err === "object" &&
|
|
32
|
+
"message" in err &&
|
|
33
|
+
typeof err.message === "string"
|
|
34
|
+
) {
|
|
35
|
+
return err.message;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return "Unknown problem";
|
|
40
|
+
}
|
|
41
|
+
|
|
22
42
|
// Type helpers from https://github.com/sindresorhus/type-fest but adjusted for
|
|
23
43
|
// our use.
|
|
24
44
|
//
|
|
@@ -85,6 +105,11 @@ export function createRemoteClient(options?: RemoteClientOptions) {
|
|
|
85
105
|
});
|
|
86
106
|
}
|
|
87
107
|
|
|
108
|
+
type EventHandlerLike = (
|
|
109
|
+
event: string,
|
|
110
|
+
listener: (...args: any[]) => void,
|
|
111
|
+
) => void;
|
|
112
|
+
|
|
88
113
|
// Interface of fields that the Arcjet Node.js SDK expects on `IncomingMessage`
|
|
89
114
|
// objects.
|
|
90
115
|
export interface ArcjetNodeRequest {
|
|
@@ -93,6 +118,11 @@ export interface ArcjetNodeRequest {
|
|
|
93
118
|
method?: string;
|
|
94
119
|
httpVersion?: string;
|
|
95
120
|
url?: string;
|
|
121
|
+
// Things needed for getting a body
|
|
122
|
+
body?: unknown;
|
|
123
|
+
on?: EventHandlerLike;
|
|
124
|
+
removeListener?: EventHandlerLike;
|
|
125
|
+
readable?: boolean;
|
|
96
126
|
}
|
|
97
127
|
|
|
98
128
|
function cookiesToString(cookies: string | string[] | undefined): string {
|
|
@@ -255,7 +285,54 @@ export default function arcjet<
|
|
|
255
285
|
ExtraProps<Rules>
|
|
256
286
|
>;
|
|
257
287
|
|
|
258
|
-
|
|
288
|
+
const getBody = async () => {
|
|
289
|
+
try {
|
|
290
|
+
// If request.body is present then the body was likely read by a package like express' `body-parser`.
|
|
291
|
+
// If it's not present then we attempt to read the bytes from the IncomingMessage ourselves.
|
|
292
|
+
if (typeof request.body === "string") {
|
|
293
|
+
return request.body;
|
|
294
|
+
} else if (
|
|
295
|
+
typeof request.body !== "undefined" &&
|
|
296
|
+
// BigInt cannot be serialized with JSON.stringify
|
|
297
|
+
typeof request.body !== "bigint"
|
|
298
|
+
) {
|
|
299
|
+
return JSON.stringify(request.body);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (
|
|
303
|
+
typeof request.on === "function" &&
|
|
304
|
+
typeof request.removeListener === "function"
|
|
305
|
+
) {
|
|
306
|
+
let expectedLength: number | undefined;
|
|
307
|
+
// TODO: This shouldn't need to build headers again but the type
|
|
308
|
+
// for `req` above is overly relaxed
|
|
309
|
+
const headers = new ArcjetHeaders(request.headers);
|
|
310
|
+
const expectedLengthStr = headers.get("content-length");
|
|
311
|
+
if (typeof expectedLengthStr === "string") {
|
|
312
|
+
try {
|
|
313
|
+
expectedLength = parseInt(expectedLengthStr, 10);
|
|
314
|
+
} catch {
|
|
315
|
+
// If the expected length couldn't be parsed we'll just not set one.
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// Awaited to throw if it rejects and we'll just return undefined
|
|
319
|
+
const body = await readBody(request, {
|
|
320
|
+
// We will process 1mb bodies
|
|
321
|
+
limit: 1048576,
|
|
322
|
+
expectedLength,
|
|
323
|
+
});
|
|
324
|
+
return body;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
log.warn("no body available");
|
|
328
|
+
return;
|
|
329
|
+
} catch (e) {
|
|
330
|
+
log.error("failed to get request body: %s", errorMessage(e));
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
return aj.protect({ getBody }, req);
|
|
259
336
|
},
|
|
260
337
|
});
|
|
261
338
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcjet/node",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.22",
|
|
4
4
|
"description": "Arcjet SDK for Node.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://arcjet.com",
|
|
@@ -40,21 +40,22 @@
|
|
|
40
40
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@arcjet/env": "1.0.0-alpha.
|
|
44
|
-
"@arcjet/headers": "1.0.0-alpha.
|
|
45
|
-
"@arcjet/ip": "1.0.0-alpha.
|
|
46
|
-
"@arcjet/logger": "1.0.0-alpha.
|
|
47
|
-
"@arcjet/protocol": "1.0.0-alpha.
|
|
48
|
-
"@arcjet/transport": "1.0.0-alpha.
|
|
49
|
-
"arcjet": "1.0.0-alpha.
|
|
43
|
+
"@arcjet/env": "1.0.0-alpha.22",
|
|
44
|
+
"@arcjet/headers": "1.0.0-alpha.22",
|
|
45
|
+
"@arcjet/ip": "1.0.0-alpha.22",
|
|
46
|
+
"@arcjet/logger": "1.0.0-alpha.22",
|
|
47
|
+
"@arcjet/protocol": "1.0.0-alpha.22",
|
|
48
|
+
"@arcjet/transport": "1.0.0-alpha.22",
|
|
49
|
+
"@arcjet/body": "1.0.0-alpha.22",
|
|
50
|
+
"arcjet": "1.0.0-alpha.22"
|
|
50
51
|
},
|
|
51
52
|
"devDependencies": {
|
|
52
|
-
"@arcjet/eslint-config": "1.0.0-alpha.
|
|
53
|
-
"@arcjet/rollup-config": "1.0.0-alpha.
|
|
54
|
-
"@arcjet/tsconfig": "1.0.0-alpha.
|
|
53
|
+
"@arcjet/eslint-config": "1.0.0-alpha.22",
|
|
54
|
+
"@arcjet/rollup-config": "1.0.0-alpha.22",
|
|
55
|
+
"@arcjet/tsconfig": "1.0.0-alpha.22",
|
|
55
56
|
"@jest/globals": "29.7.0",
|
|
56
57
|
"@types/node": "18.18.0",
|
|
57
|
-
"@rollup/wasm-node": "4.
|
|
58
|
+
"@rollup/wasm-node": "4.21.0",
|
|
58
59
|
"jest": "29.7.0",
|
|
59
60
|
"typescript": "5.5.4"
|
|
60
61
|
},
|