@arcjet/bun 1.0.0-alpha.13 → 1.0.0-alpha.14
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/README.md +17 -5
- package/index.d.ts +2 -3
- package/index.js +37 -13
- package/index.ts +44 -15
- package/package.json +11 -8
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<a href="https://arcjet.com" target="_arcjet-home">
|
|
2
2
|
<picture>
|
|
3
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://arcjet.com/arcjet-
|
|
4
|
-
<img src="https://arcjet.com/arcjet-
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://arcjet.com/logo/arcjet-dark-lockup-voyage-horizontal.svg">
|
|
4
|
+
<img src="https://arcjet.com/logo/arcjet-light-lockup-voyage-horizontal.svg" alt="Arcjet Logo" height="128" width="auto">
|
|
5
5
|
</picture>
|
|
6
6
|
</a>
|
|
7
7
|
|
|
@@ -17,11 +17,20 @@
|
|
|
17
17
|
</p>
|
|
18
18
|
|
|
19
19
|
[Arcjet][arcjet] helps developers protect their apps in just a few lines of
|
|
20
|
-
code. Implement rate limiting, bot protection, email verification
|
|
20
|
+
code. Implement rate limiting, bot protection, email verification, and defense
|
|
21
21
|
against common attacks.
|
|
22
22
|
|
|
23
23
|
This is the [Arcjet][arcjet] SDK for [Bun.sh][bun-sh].
|
|
24
24
|
|
|
25
|
+
## Getting started
|
|
26
|
+
|
|
27
|
+
Visit the [quick start guide][quick-start] to get started.
|
|
28
|
+
|
|
29
|
+
## Example app
|
|
30
|
+
|
|
31
|
+
Try an Arcjet protected app live at [https://example.arcjet.com][example-url]
|
|
32
|
+
([source code][example-source]).
|
|
33
|
+
|
|
25
34
|
## Installation
|
|
26
35
|
|
|
27
36
|
```shell
|
|
@@ -75,8 +84,8 @@ export default {
|
|
|
75
84
|
## Shield example
|
|
76
85
|
|
|
77
86
|
[Arcjet Shield][shield-concepts-docs] protects your application against common
|
|
78
|
-
attacks, including the OWASP Top 10.
|
|
79
|
-
|
|
87
|
+
attacks, including the OWASP Top 10. You can run Shield on every request with
|
|
88
|
+
negligible performance impact.
|
|
80
89
|
|
|
81
90
|
```ts
|
|
82
91
|
import arcjet, { shield } from "@arcjet/bun";
|
|
@@ -110,6 +119,9 @@ Licensed under the [Apache License, Version 2.0][apache-license].
|
|
|
110
119
|
|
|
111
120
|
[arcjet]: https://arcjet.com
|
|
112
121
|
[bun-sh]: https://bun.sh/
|
|
122
|
+
[example-url]: https://example.arcjet.com
|
|
123
|
+
[quick-start]: https://docs.arcjet.com/get-started/bun
|
|
124
|
+
[example-source]: https://github.com/arcjet/arcjet-js-example
|
|
113
125
|
[rate-limit-concepts-docs]: https://docs.arcjet.com/rate-limiting/concepts
|
|
114
126
|
[shield-concepts-docs]: https://docs.arcjet.com/shield/concepts
|
|
115
127
|
[apache-license]: http://www.apache.org/licenses/LICENSE-2.0
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="bun-types/bun.d.ts" />
|
|
2
|
-
import { ArcjetDecision, ArcjetOptions, Primitive, Product,
|
|
2
|
+
import { ArcjetDecision, ArcjetOptions, Primitive, Product, ExtraProps, RemoteClient, RemoteClientOptions } from "arcjet";
|
|
3
3
|
import type { Server } from "bun";
|
|
4
4
|
export * from "arcjet";
|
|
5
5
|
type Simplify<T> = {
|
|
@@ -12,13 +12,12 @@ type WithoutCustomProps = {
|
|
|
12
12
|
type PlainObject = {
|
|
13
13
|
[key: string]: unknown;
|
|
14
14
|
};
|
|
15
|
-
export declare function createBunRemoteClient(options?: RemoteClientOptions): RemoteClient;
|
|
15
|
+
export declare function createBunRemoteClient(options?: Partial<RemoteClientOptions>): RemoteClient;
|
|
16
16
|
/**
|
|
17
17
|
* The ArcjetBun client provides a public `protect()` method to
|
|
18
18
|
* make a decision about how a Bun.sh request should be handled.
|
|
19
19
|
*/
|
|
20
20
|
export interface ArcjetBun<Props extends PlainObject> {
|
|
21
|
-
get runtime(): Runtime;
|
|
22
21
|
/**
|
|
23
22
|
* Runs a request through the configured protections. The request is
|
|
24
23
|
* analyzed and then a decision made on whether to allow, deny, or challenge
|
package/index.js
CHANGED
|
@@ -1,23 +1,36 @@
|
|
|
1
1
|
import { createConnectTransport } from '@connectrpc/connect-node';
|
|
2
|
-
import core__default, {
|
|
2
|
+
import core__default, { createRemoteClient } from 'arcjet';
|
|
3
3
|
export * from 'arcjet';
|
|
4
4
|
import findIP from '@arcjet/ip';
|
|
5
|
+
import ArcjetHeaders from '@arcjet/headers';
|
|
6
|
+
import { env } from 'bun';
|
|
7
|
+
import { logLevel, baseUrl, isProduction, platform, isDevelopment } from '@arcjet/env';
|
|
8
|
+
import { Logger } from '@arcjet/logger';
|
|
5
9
|
|
|
6
10
|
/// <reference types="bun-types/bun.d.ts" />
|
|
7
11
|
function createBunRemoteClient(options) {
|
|
8
12
|
// The base URL for the Arcjet API. Will default to the standard production
|
|
9
13
|
// API unless environment variable `ARCJET_BASE_URL` is set.
|
|
10
|
-
const
|
|
14
|
+
const url = options?.baseUrl ?? baseUrl(env);
|
|
15
|
+
// The timeout for the Arcjet API in milliseconds. This is set to a low value
|
|
16
|
+
// in production so calls fail open.
|
|
17
|
+
const timeout = options?.timeout ?? (isProduction(env) ? 500 : 1000);
|
|
11
18
|
// Transport is the HTTP client that the client uses to make requests.
|
|
12
19
|
const transport = options?.transport ??
|
|
13
20
|
createConnectTransport({
|
|
14
|
-
baseUrl,
|
|
21
|
+
baseUrl: url,
|
|
15
22
|
httpVersion: "1.1",
|
|
16
23
|
});
|
|
17
|
-
// TODO(#223):
|
|
24
|
+
// TODO(#223): Create separate options type to exclude these
|
|
18
25
|
const sdkStack = "BUN";
|
|
19
|
-
const sdkVersion = "1.0.0-alpha.
|
|
20
|
-
return createRemoteClient({
|
|
26
|
+
const sdkVersion = "1.0.0-alpha.14";
|
|
27
|
+
return createRemoteClient({
|
|
28
|
+
transport,
|
|
29
|
+
baseUrl: url,
|
|
30
|
+
timeout,
|
|
31
|
+
sdkStack,
|
|
32
|
+
sdkVersion,
|
|
33
|
+
});
|
|
21
34
|
}
|
|
22
35
|
// This is provided with an `ipCache` where it attempts to lookup the IP. This
|
|
23
36
|
// is primarily a workaround to the API design in Bun that requires access to
|
|
@@ -27,9 +40,18 @@ function toArcjetRequest(ipCache, request, props) {
|
|
|
27
40
|
// We construct an ArcjetHeaders to normalize over Headers
|
|
28
41
|
const headers = new ArcjetHeaders(request.headers);
|
|
29
42
|
const url = new URL(request.url);
|
|
30
|
-
|
|
43
|
+
let ip = findIP({
|
|
31
44
|
ip: ipCache.get(request),
|
|
32
|
-
}, headers);
|
|
45
|
+
}, headers, { platform: platform(env) });
|
|
46
|
+
if (ip === "") {
|
|
47
|
+
// If the `ip` is empty but we're in development mode, we default the IP
|
|
48
|
+
// so the request doesn't fail.
|
|
49
|
+
if (isDevelopment(env)) {
|
|
50
|
+
// TODO: Log that the fingerprint is being overridden once the adapter
|
|
51
|
+
// constructs the logger
|
|
52
|
+
ip = "127.0.0.1";
|
|
53
|
+
}
|
|
54
|
+
}
|
|
33
55
|
return {
|
|
34
56
|
...props,
|
|
35
57
|
ip,
|
|
@@ -48,9 +70,6 @@ function withClient(aj) {
|
|
|
48
70
|
// `server.requestIP()`
|
|
49
71
|
const ipCache = new WeakMap();
|
|
50
72
|
return Object.freeze({
|
|
51
|
-
get runtime() {
|
|
52
|
-
return aj.runtime;
|
|
53
|
-
},
|
|
54
73
|
withRule(rule) {
|
|
55
74
|
const client = aj.withRule(rule);
|
|
56
75
|
return withClient(client);
|
|
@@ -60,7 +79,7 @@ function withClient(aj) {
|
|
|
60
79
|
// Further investigation makes it seem like it has something to do with
|
|
61
80
|
// the definition of `props` in the signature but it's hard to track down
|
|
62
81
|
const req = toArcjetRequest(ipCache, request, props ?? {});
|
|
63
|
-
return aj.protect(req);
|
|
82
|
+
return aj.protect({}, req);
|
|
64
83
|
},
|
|
65
84
|
handler(fetch) {
|
|
66
85
|
return async function (request, server) {
|
|
@@ -83,7 +102,12 @@ function withClient(aj) {
|
|
|
83
102
|
*/
|
|
84
103
|
function arcjet(options) {
|
|
85
104
|
const client = options.client ?? createBunRemoteClient();
|
|
86
|
-
const
|
|
105
|
+
const log = options.log
|
|
106
|
+
? options.log
|
|
107
|
+
: new Logger({
|
|
108
|
+
level: logLevel(env),
|
|
109
|
+
});
|
|
110
|
+
const aj = core__default({ ...options, client, log });
|
|
87
111
|
return withClient(aj);
|
|
88
112
|
}
|
|
89
113
|
|
package/index.ts
CHANGED
|
@@ -5,18 +5,25 @@ import core, {
|
|
|
5
5
|
ArcjetOptions,
|
|
6
6
|
Primitive,
|
|
7
7
|
Product,
|
|
8
|
-
ArcjetHeaders,
|
|
9
|
-
Runtime,
|
|
10
8
|
ArcjetRequest,
|
|
11
9
|
ExtraProps,
|
|
12
10
|
RemoteClient,
|
|
13
11
|
RemoteClientOptions,
|
|
14
|
-
defaultBaseUrl,
|
|
15
12
|
createRemoteClient,
|
|
16
13
|
Arcjet,
|
|
17
14
|
} from "arcjet";
|
|
18
15
|
import findIP from "@arcjet/ip";
|
|
16
|
+
import ArcjetHeaders from "@arcjet/headers";
|
|
19
17
|
import type { Server } from "bun";
|
|
18
|
+
import { env } from "bun";
|
|
19
|
+
import {
|
|
20
|
+
baseUrl,
|
|
21
|
+
isDevelopment,
|
|
22
|
+
isProduction,
|
|
23
|
+
logLevel,
|
|
24
|
+
platform,
|
|
25
|
+
} from "@arcjet/env";
|
|
26
|
+
import { Logger } from "@arcjet/logger";
|
|
20
27
|
|
|
21
28
|
// Re-export all named exports from the generic SDK
|
|
22
29
|
export * from "arcjet";
|
|
@@ -59,25 +66,35 @@ type PlainObject = {
|
|
|
59
66
|
};
|
|
60
67
|
|
|
61
68
|
export function createBunRemoteClient(
|
|
62
|
-
options?: RemoteClientOptions
|
|
69
|
+
options?: Partial<RemoteClientOptions>,
|
|
63
70
|
): RemoteClient {
|
|
64
71
|
// The base URL for the Arcjet API. Will default to the standard production
|
|
65
72
|
// API unless environment variable `ARCJET_BASE_URL` is set.
|
|
66
|
-
const
|
|
73
|
+
const url = options?.baseUrl ?? baseUrl(env);
|
|
74
|
+
|
|
75
|
+
// The timeout for the Arcjet API in milliseconds. This is set to a low value
|
|
76
|
+
// in production so calls fail open.
|
|
77
|
+
const timeout = options?.timeout ?? (isProduction(env) ? 500 : 1000);
|
|
67
78
|
|
|
68
79
|
// Transport is the HTTP client that the client uses to make requests.
|
|
69
80
|
const transport =
|
|
70
81
|
options?.transport ??
|
|
71
82
|
createConnectTransport({
|
|
72
|
-
baseUrl,
|
|
83
|
+
baseUrl: url,
|
|
73
84
|
httpVersion: "1.1",
|
|
74
85
|
});
|
|
75
86
|
|
|
76
|
-
// TODO(#223):
|
|
87
|
+
// TODO(#223): Create separate options type to exclude these
|
|
77
88
|
const sdkStack = "BUN";
|
|
78
89
|
const sdkVersion = "__ARCJET_SDK_VERSION__";
|
|
79
90
|
|
|
80
|
-
return createRemoteClient({
|
|
91
|
+
return createRemoteClient({
|
|
92
|
+
transport,
|
|
93
|
+
baseUrl: url,
|
|
94
|
+
timeout,
|
|
95
|
+
sdkStack,
|
|
96
|
+
sdkVersion,
|
|
97
|
+
});
|
|
81
98
|
}
|
|
82
99
|
|
|
83
100
|
/**
|
|
@@ -85,7 +102,6 @@ export function createBunRemoteClient(
|
|
|
85
102
|
* make a decision about how a Bun.sh request should be handled.
|
|
86
103
|
*/
|
|
87
104
|
export interface ArcjetBun<Props extends PlainObject> {
|
|
88
|
-
get runtime(): Runtime;
|
|
89
105
|
/**
|
|
90
106
|
* Runs a request through the configured protections. The request is
|
|
91
107
|
* analyzed and then a decision made on whether to allow, deny, or challenge
|
|
@@ -146,12 +162,22 @@ function toArcjetRequest<Props extends PlainObject>(
|
|
|
146
162
|
const headers = new ArcjetHeaders(request.headers);
|
|
147
163
|
|
|
148
164
|
const url = new URL(request.url);
|
|
149
|
-
|
|
165
|
+
let ip = findIP(
|
|
150
166
|
{
|
|
151
167
|
ip: ipCache.get(request),
|
|
152
168
|
},
|
|
153
169
|
headers,
|
|
170
|
+
{ platform: platform(env) },
|
|
154
171
|
);
|
|
172
|
+
if (ip === "") {
|
|
173
|
+
// If the `ip` is empty but we're in development mode, we default the IP
|
|
174
|
+
// so the request doesn't fail.
|
|
175
|
+
if (isDevelopment(env)) {
|
|
176
|
+
// TODO: Log that the fingerprint is being overridden once the adapter
|
|
177
|
+
// constructs the logger
|
|
178
|
+
ip = "127.0.0.1";
|
|
179
|
+
}
|
|
180
|
+
}
|
|
155
181
|
|
|
156
182
|
return {
|
|
157
183
|
...props,
|
|
@@ -175,9 +201,6 @@ function withClient<const Rules extends (Primitive | Product)[]>(
|
|
|
175
201
|
const ipCache = new WeakMap<Request, string>();
|
|
176
202
|
|
|
177
203
|
return Object.freeze({
|
|
178
|
-
get runtime() {
|
|
179
|
-
return aj.runtime;
|
|
180
|
-
},
|
|
181
204
|
withRule(rule: Primitive | Product) {
|
|
182
205
|
const client = aj.withRule(rule);
|
|
183
206
|
return withClient(client);
|
|
@@ -197,7 +220,7 @@ function withClient<const Rules extends (Primitive | Product)[]>(
|
|
|
197
220
|
props ?? {},
|
|
198
221
|
) as ArcjetRequest<ExtraProps<Rules>>;
|
|
199
222
|
|
|
200
|
-
return aj.protect(req);
|
|
223
|
+
return aj.protect({}, req);
|
|
201
224
|
},
|
|
202
225
|
handler(
|
|
203
226
|
fetch: (
|
|
@@ -234,7 +257,13 @@ export default function arcjet<const Rules extends (Primitive | Product)[]>(
|
|
|
234
257
|
): ArcjetBun<Simplify<ExtraProps<Rules>>> {
|
|
235
258
|
const client = options.client ?? createBunRemoteClient();
|
|
236
259
|
|
|
237
|
-
const
|
|
260
|
+
const log = options.log
|
|
261
|
+
? options.log
|
|
262
|
+
: new Logger({
|
|
263
|
+
level: logLevel(env),
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
const aj = core({ ...options, client, log });
|
|
238
267
|
|
|
239
268
|
return withClient(aj);
|
|
240
269
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcjet/bun",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.14",
|
|
4
4
|
"description": "Arcjet SDK for Bun.sh",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://arcjet.com",
|
|
@@ -38,18 +38,21 @@
|
|
|
38
38
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@arcjet/
|
|
41
|
+
"@arcjet/env": "1.0.0-alpha.14",
|
|
42
|
+
"@arcjet/headers": "1.0.0-alpha.14",
|
|
43
|
+
"@arcjet/ip": "1.0.0-alpha.14",
|
|
44
|
+
"@arcjet/logger": "1.0.0-alpha.14",
|
|
42
45
|
"@connectrpc/connect-node": "1.4.0",
|
|
43
|
-
"arcjet": "1.0.0-alpha.
|
|
46
|
+
"arcjet": "1.0.0-alpha.14"
|
|
44
47
|
},
|
|
45
48
|
"devDependencies": {
|
|
46
|
-
"@arcjet/eslint-config": "1.0.0-alpha.
|
|
47
|
-
"@arcjet/rollup-config": "1.0.0-alpha.
|
|
48
|
-
"@arcjet/tsconfig": "1.0.0-alpha.
|
|
49
|
+
"@arcjet/eslint-config": "1.0.0-alpha.14",
|
|
50
|
+
"@arcjet/rollup-config": "1.0.0-alpha.14",
|
|
51
|
+
"@arcjet/tsconfig": "1.0.0-alpha.14",
|
|
49
52
|
"@jest/globals": "29.7.0",
|
|
50
53
|
"@types/node": "20.12.12",
|
|
51
|
-
"@rollup/wasm-node": "4.
|
|
52
|
-
"bun-types": "1.1.
|
|
54
|
+
"@rollup/wasm-node": "4.18.0",
|
|
55
|
+
"bun-types": "1.1.12",
|
|
53
56
|
"jest": "29.7.0",
|
|
54
57
|
"typescript": "5.4.5"
|
|
55
58
|
},
|