@arcjet/bun 1.0.0-alpha.17 → 1.0.0-alpha.19

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 (4) hide show
  1. package/index.d.ts +2 -3
  2. package/index.js +65 -63
  3. package/index.ts +109 -108
  4. package/package.json +13 -13
package/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- /// <reference types="bun-types/bun.d.ts" />
2
- import { ArcjetDecision, ArcjetOptions, Primitive, Product, ExtraProps } from "arcjet";
1
+ import type { ArcjetDecision, ArcjetOptions, Primitive, Product, ExtraProps, CharacteristicProps } from "arcjet";
3
2
  import type { Server } from "bun";
4
3
  export * from "arcjet";
5
4
  type Simplify<T> = {
@@ -56,4 +55,4 @@ export interface ArcjetBun<Props extends PlainObject> {
56
55
  *
57
56
  * @param options - Arcjet configuration options to apply to all requests.
58
57
  */
59
- export default function arcjet<const Rules extends (Primitive | Product)[]>(options: ArcjetOptions<Rules>): ArcjetBun<Simplify<ExtraProps<Rules>>>;
58
+ export default function arcjet<const Rules extends (Primitive | Product)[], const Characteristics extends readonly string[]>(options: ArcjetOptions<Rules, Characteristics>): ArcjetBun<Simplify<ExtraProps<Rules> & CharacteristicProps<Characteristics>>>;
package/index.js CHANGED
@@ -4,7 +4,7 @@ export * from 'arcjet';
4
4
  import findIP from '@arcjet/ip';
5
5
  import ArcjetHeaders from '@arcjet/headers';
6
6
  import { env } from 'bun';
7
- import { logLevel, baseUrl, isProduction, platform, isDevelopment } from '@arcjet/env';
7
+ import { logLevel, baseUrl, isDevelopment, platform } from '@arcjet/env';
8
8
  import { Logger } from '@arcjet/logger';
9
9
  import { createClient } from '@arcjet/protocol/client.js';
10
10
 
@@ -15,14 +15,14 @@ function createRemoteClient(options) {
15
15
  const url = options?.baseUrl ?? baseUrl(env);
16
16
  // The timeout for the Arcjet API in milliseconds. This is set to a low value
17
17
  // in production so calls fail open.
18
- const timeout = options?.timeout ?? (isProduction(env) ? 500 : 1000);
18
+ const timeout = options?.timeout ?? (isDevelopment(env) ? 1000 : 500);
19
19
  // Transport is the HTTP client that the client uses to make requests.
20
20
  const transport = createConnectTransport({
21
21
  baseUrl: url,
22
22
  httpVersion: "1.1",
23
23
  });
24
24
  const sdkStack = "BUN";
25
- const sdkVersion = "1.0.0-alpha.17";
25
+ const sdkVersion = "1.0.0-alpha.19";
26
26
  return createClient({
27
27
  transport,
28
28
  baseUrl: url,
@@ -31,66 +31,6 @@ function createRemoteClient(options) {
31
31
  sdkVersion,
32
32
  });
33
33
  }
34
- // This is provided with an `ipCache` where it attempts to lookup the IP. This
35
- // is primarily a workaround to the API design in Bun that requires access to
36
- // the `Server` to lookup an IP.
37
- function toArcjetRequest(ipCache, request, props) {
38
- const cookies = request.headers.get("cookie") ?? undefined;
39
- // We construct an ArcjetHeaders to normalize over Headers
40
- const headers = new ArcjetHeaders(request.headers);
41
- const url = new URL(request.url);
42
- let ip = findIP({
43
- ip: ipCache.get(request),
44
- }, headers, { platform: platform(env) });
45
- if (ip === "") {
46
- // If the `ip` is empty but we're in development mode, we default the IP
47
- // so the request doesn't fail.
48
- if (isDevelopment(env)) {
49
- // TODO: Log that the fingerprint is being overridden once the adapter
50
- // constructs the logger
51
- ip = "127.0.0.1";
52
- }
53
- }
54
- return {
55
- ...props,
56
- ip,
57
- method: request.method,
58
- protocol: url.protocol,
59
- host: url.host,
60
- path: url.pathname,
61
- headers,
62
- cookies,
63
- query: url.search,
64
- };
65
- }
66
- function withClient(aj) {
67
- // Assuming the `handler()` function was used around Bun's fetch handler
68
- // this WeakMap should be populated with IP addresses inspected via
69
- // `server.requestIP()`
70
- const ipCache = new WeakMap();
71
- return Object.freeze({
72
- withRule(rule) {
73
- const client = aj.withRule(rule);
74
- return withClient(client);
75
- },
76
- async protect(request, ...[props]) {
77
- // TODO(#220): The generic manipulations get really mad here, so we cast
78
- // Further investigation makes it seem like it has something to do with
79
- // the definition of `props` in the signature but it's hard to track down
80
- const req = toArcjetRequest(ipCache, request, props ?? {});
81
- return aj.protect({}, req);
82
- },
83
- handler(fetch) {
84
- return async function (request, server) {
85
- const socketAddress = server.requestIP(request);
86
- if (socketAddress) {
87
- ipCache.set(request, socketAddress.address);
88
- }
89
- return fetch.call(server, request, server);
90
- };
91
- },
92
- });
93
- }
94
34
  /**
95
35
  * Create a new {@link ArcjetBun} client. Always build your initial client
96
36
  * outside of a request handler so it persists across requests. If you need to
@@ -101,11 +41,73 @@ function withClient(aj) {
101
41
  */
102
42
  function arcjet(options) {
103
43
  const client = options.client ?? createRemoteClient();
44
+ // Assuming the `handler()` function was used around Bun's fetch handler this
45
+ // WeakMap should be populated with IP addresses inspected via
46
+ // `server.requestIP()`
47
+ const ipCache = new WeakMap();
104
48
  const log = options.log
105
49
  ? options.log
106
50
  : new Logger({
107
51
  level: logLevel(env),
108
52
  });
53
+ function toArcjetRequest(request, props) {
54
+ const cookies = request.headers.get("cookie") ?? undefined;
55
+ // We construct an ArcjetHeaders to normalize over Headers
56
+ const headers = new ArcjetHeaders(request.headers);
57
+ const url = new URL(request.url);
58
+ let ip = findIP({
59
+ // This attempts to lookup the IP in the `ipCache`. This is primarily a
60
+ // workaround to the API design in Bun that requires access to the
61
+ // `Server` to lookup an IP.
62
+ ip: ipCache.get(request),
63
+ }, headers, { platform: platform(env) });
64
+ if (ip === "") {
65
+ // If the `ip` is empty but we're in development mode, we default the IP
66
+ // so the request doesn't fail.
67
+ if (isDevelopment(env)) {
68
+ log.warn("Using 127.0.0.1 as IP address in development mode");
69
+ ip = "127.0.0.1";
70
+ }
71
+ else {
72
+ log.warn(`Client IP address is missing. If this is a dev environment set the ARCJET_ENV env var to "development"`);
73
+ }
74
+ }
75
+ return {
76
+ ...props,
77
+ ip,
78
+ method: request.method,
79
+ protocol: url.protocol,
80
+ host: url.host,
81
+ path: url.pathname,
82
+ headers,
83
+ cookies,
84
+ query: url.search,
85
+ };
86
+ }
87
+ function withClient(aj) {
88
+ return Object.freeze({
89
+ withRule(rule) {
90
+ const client = aj.withRule(rule);
91
+ return withClient(client);
92
+ },
93
+ async protect(request, ...[props]) {
94
+ // TODO(#220): The generic manipulations get really mad here, so we cast
95
+ // Further investigation makes it seem like it has something to do with
96
+ // the definition of `props` in the signature but it's hard to track down
97
+ const req = toArcjetRequest(request, props ?? {});
98
+ return aj.protect({}, req);
99
+ },
100
+ handler(fetch) {
101
+ return async function (request, server) {
102
+ const socketAddress = server.requestIP(request);
103
+ if (socketAddress) {
104
+ ipCache.set(request, socketAddress.address);
105
+ }
106
+ return fetch.call(server, request, server);
107
+ };
108
+ },
109
+ });
110
+ }
109
111
  const aj = core__default({ ...options, client, log });
110
112
  return withClient(aj);
111
113
  }
package/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /// <reference types="bun-types/bun.d.ts" />
2
2
  import { createConnectTransport } from "@connectrpc/connect-node";
3
- import core, {
3
+ import core from "arcjet";
4
+ import type {
4
5
  ArcjetDecision,
5
6
  ArcjetOptions,
6
7
  Primitive,
@@ -8,18 +9,13 @@ import core, {
8
9
  ArcjetRequest,
9
10
  ExtraProps,
10
11
  Arcjet,
12
+ CharacteristicProps,
11
13
  } from "arcjet";
12
14
  import findIP from "@arcjet/ip";
13
15
  import ArcjetHeaders from "@arcjet/headers";
14
16
  import type { Server } from "bun";
15
17
  import { env } from "bun";
16
- import {
17
- baseUrl,
18
- isDevelopment,
19
- isProduction,
20
- logLevel,
21
- platform,
22
- } from "@arcjet/env";
18
+ import { baseUrl, isDevelopment, logLevel, platform } from "@arcjet/env";
23
19
  import { Logger } from "@arcjet/logger";
24
20
  import { createClient } from "@arcjet/protocol/client.js";
25
21
 
@@ -75,7 +71,7 @@ export function createRemoteClient(options?: RemoteClientOptions) {
75
71
 
76
72
  // The timeout for the Arcjet API in milliseconds. This is set to a low value
77
73
  // in production so calls fail open.
78
- const timeout = options?.timeout ?? (isProduction(env) ? 500 : 1000);
74
+ const timeout = options?.timeout ?? (isDevelopment(env) ? 1000 : 500);
79
75
 
80
76
  // Transport is the HTTP client that the client uses to make requests.
81
77
  const transport = createConnectTransport({
@@ -146,102 +142,6 @@ export interface ArcjetBun<Props extends PlainObject> {
146
142
  ) => Response | Promise<Response>;
147
143
  }
148
144
 
149
- // This is provided with an `ipCache` where it attempts to lookup the IP. This
150
- // is primarily a workaround to the API design in Bun that requires access to
151
- // the `Server` to lookup an IP.
152
- function toArcjetRequest<Props extends PlainObject>(
153
- ipCache: WeakMap<Request, string>,
154
- request: Request,
155
- props: Props,
156
- ): ArcjetRequest<Props> {
157
- const cookies = request.headers.get("cookie") ?? undefined;
158
-
159
- // We construct an ArcjetHeaders to normalize over Headers
160
- const headers = new ArcjetHeaders(request.headers);
161
-
162
- const url = new URL(request.url);
163
- let ip = findIP(
164
- {
165
- ip: ipCache.get(request),
166
- },
167
- headers,
168
- { platform: platform(env) },
169
- );
170
- if (ip === "") {
171
- // If the `ip` is empty but we're in development mode, we default the IP
172
- // so the request doesn't fail.
173
- if (isDevelopment(env)) {
174
- // TODO: Log that the fingerprint is being overridden once the adapter
175
- // constructs the logger
176
- ip = "127.0.0.1";
177
- }
178
- }
179
-
180
- return {
181
- ...props,
182
- ip,
183
- method: request.method,
184
- protocol: url.protocol,
185
- host: url.host,
186
- path: url.pathname,
187
- headers,
188
- cookies,
189
- query: url.search,
190
- };
191
- }
192
-
193
- function withClient<const Rules extends (Primitive | Product)[]>(
194
- aj: Arcjet<ExtraProps<Rules>>,
195
- ): ArcjetBun<ExtraProps<Rules>> {
196
- // Assuming the `handler()` function was used around Bun's fetch handler
197
- // this WeakMap should be populated with IP addresses inspected via
198
- // `server.requestIP()`
199
- const ipCache = new WeakMap<Request, string>();
200
-
201
- return Object.freeze({
202
- withRule(rule: Primitive | Product) {
203
- const client = aj.withRule(rule);
204
- return withClient(client);
205
- },
206
- async protect(
207
- request: Request,
208
- ...[props]: ExtraProps<Rules> extends WithoutCustomProps
209
- ? []
210
- : [ExtraProps<Rules>]
211
- ): Promise<ArcjetDecision> {
212
- // TODO(#220): The generic manipulations get really mad here, so we cast
213
- // Further investigation makes it seem like it has something to do with
214
- // the definition of `props` in the signature but it's hard to track down
215
- const req = toArcjetRequest(
216
- ipCache,
217
- request,
218
- props ?? {},
219
- ) as ArcjetRequest<ExtraProps<Rules>>;
220
-
221
- return aj.protect({}, req);
222
- },
223
- handler(
224
- fetch: (
225
- this: Server,
226
- request: Request,
227
- server: Server,
228
- ) => Response | Promise<Response>,
229
- ) {
230
- return async function (
231
- request: Request,
232
- server: Server,
233
- ): Promise<Response> {
234
- const socketAddress = server.requestIP(request);
235
- if (socketAddress) {
236
- ipCache.set(request, socketAddress.address);
237
- }
238
-
239
- return fetch.call(server, request, server);
240
- };
241
- },
242
- });
243
- }
244
-
245
145
  /**
246
146
  * Create a new {@link ArcjetBun} client. Always build your initial client
247
147
  * outside of a request handler so it persists across requests. If you need to
@@ -250,17 +150,118 @@ function withClient<const Rules extends (Primitive | Product)[]>(
250
150
  *
251
151
  * @param options - Arcjet configuration options to apply to all requests.
252
152
  */
253
- export default function arcjet<const Rules extends (Primitive | Product)[]>(
254
- options: ArcjetOptions<Rules>,
255
- ): ArcjetBun<Simplify<ExtraProps<Rules>>> {
153
+ export default function arcjet<
154
+ const Rules extends (Primitive | Product)[],
155
+ const Characteristics extends readonly string[],
156
+ >(
157
+ options: ArcjetOptions<Rules, Characteristics>,
158
+ ): ArcjetBun<
159
+ Simplify<ExtraProps<Rules> & CharacteristicProps<Characteristics>>
160
+ > {
256
161
  const client = options.client ?? createRemoteClient();
257
162
 
163
+ // Assuming the `handler()` function was used around Bun's fetch handler this
164
+ // WeakMap should be populated with IP addresses inspected via
165
+ // `server.requestIP()`
166
+ const ipCache = new WeakMap<Request, string>();
167
+
258
168
  const log = options.log
259
169
  ? options.log
260
170
  : new Logger({
261
171
  level: logLevel(env),
262
172
  });
263
173
 
174
+ function toArcjetRequest<Props extends PlainObject>(
175
+ request: Request,
176
+ props: Props,
177
+ ): ArcjetRequest<Props> {
178
+ const cookies = request.headers.get("cookie") ?? undefined;
179
+
180
+ // We construct an ArcjetHeaders to normalize over Headers
181
+ const headers = new ArcjetHeaders(request.headers);
182
+
183
+ const url = new URL(request.url);
184
+ let ip = findIP(
185
+ {
186
+ // This attempts to lookup the IP in the `ipCache`. This is primarily a
187
+ // workaround to the API design in Bun that requires access to the
188
+ // `Server` to lookup an IP.
189
+ ip: ipCache.get(request),
190
+ },
191
+ headers,
192
+ { platform: platform(env) },
193
+ );
194
+ if (ip === "") {
195
+ // If the `ip` is empty but we're in development mode, we default the IP
196
+ // so the request doesn't fail.
197
+ if (isDevelopment(env)) {
198
+ log.warn("Using 127.0.0.1 as IP address in development mode");
199
+ ip = "127.0.0.1";
200
+ } else {
201
+ log.warn(
202
+ `Client IP address is missing. If this is a dev environment set the ARCJET_ENV env var to "development"`,
203
+ );
204
+ }
205
+ }
206
+
207
+ return {
208
+ ...props,
209
+ ip,
210
+ method: request.method,
211
+ protocol: url.protocol,
212
+ host: url.host,
213
+ path: url.pathname,
214
+ headers,
215
+ cookies,
216
+ query: url.search,
217
+ };
218
+ }
219
+
220
+ function withClient<const Rules extends (Primitive | Product)[]>(
221
+ aj: Arcjet<ExtraProps<Rules>>,
222
+ ): ArcjetBun<ExtraProps<Rules>> {
223
+ return Object.freeze({
224
+ withRule(rule: Primitive | Product) {
225
+ const client = aj.withRule(rule);
226
+ return withClient(client);
227
+ },
228
+ async protect(
229
+ request: Request,
230
+ ...[props]: ExtraProps<Rules> extends WithoutCustomProps
231
+ ? []
232
+ : [ExtraProps<Rules>]
233
+ ): Promise<ArcjetDecision> {
234
+ // TODO(#220): The generic manipulations get really mad here, so we cast
235
+ // Further investigation makes it seem like it has something to do with
236
+ // the definition of `props` in the signature but it's hard to track down
237
+ const req = toArcjetRequest(request, props ?? {}) as ArcjetRequest<
238
+ ExtraProps<Rules>
239
+ >;
240
+
241
+ return aj.protect({}, req);
242
+ },
243
+ handler(
244
+ fetch: (
245
+ this: Server,
246
+ request: Request,
247
+ server: Server,
248
+ ) => Response | Promise<Response>,
249
+ ) {
250
+ return async function (
251
+ request: Request,
252
+ server: Server,
253
+ ): Promise<Response> {
254
+ const socketAddress = server.requestIP(request);
255
+ if (socketAddress) {
256
+ ipCache.set(request, socketAddress.address);
257
+ }
258
+
259
+ return fetch.call(server, request, server);
260
+ };
261
+ },
262
+ });
263
+ }
264
+
264
265
  const aj = core({ ...options, client, log });
265
266
 
266
267
  return withClient(aj);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcjet/bun",
3
- "version": "1.0.0-alpha.17",
3
+ "version": "1.0.0-alpha.19",
4
4
  "description": "Arcjet SDK for Bun.sh",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://arcjet.com",
@@ -38,24 +38,24 @@
38
38
  "test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests"
39
39
  },
40
40
  "dependencies": {
41
- "@arcjet/env": "1.0.0-alpha.17",
42
- "@arcjet/headers": "1.0.0-alpha.17",
43
- "@arcjet/ip": "1.0.0-alpha.17",
44
- "@arcjet/logger": "1.0.0-alpha.17",
45
- "@arcjet/protocol": "1.0.0-alpha.17",
41
+ "@arcjet/env": "1.0.0-alpha.19",
42
+ "@arcjet/headers": "1.0.0-alpha.19",
43
+ "@arcjet/ip": "1.0.0-alpha.19",
44
+ "@arcjet/logger": "1.0.0-alpha.19",
45
+ "@arcjet/protocol": "1.0.0-alpha.19",
46
46
  "@connectrpc/connect-node": "1.4.0",
47
- "arcjet": "1.0.0-alpha.17"
47
+ "arcjet": "1.0.0-alpha.19"
48
48
  },
49
49
  "devDependencies": {
50
- "@arcjet/eslint-config": "1.0.0-alpha.17",
51
- "@arcjet/rollup-config": "1.0.0-alpha.17",
52
- "@arcjet/tsconfig": "1.0.0-alpha.17",
50
+ "@arcjet/eslint-config": "1.0.0-alpha.19",
51
+ "@arcjet/rollup-config": "1.0.0-alpha.19",
52
+ "@arcjet/tsconfig": "1.0.0-alpha.19",
53
53
  "@jest/globals": "29.7.0",
54
54
  "@types/node": "20.12.12",
55
- "@rollup/wasm-node": "4.18.0",
56
- "bun-types": "1.1.13",
55
+ "@rollup/wasm-node": "4.18.1",
56
+ "bun-types": "1.1.20",
57
57
  "jest": "29.7.0",
58
- "typescript": "5.4.5"
58
+ "typescript": "5.5.3"
59
59
  },
60
60
  "publishConfig": {
61
61
  "access": "public",