@arcjet/astro 1.0.0-beta.9 → 1.1.0-rc

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.js CHANGED
@@ -7,107 +7,112 @@ const validateProxies = z.array(z.string());
7
7
  const validateCharacteristics = z.array(z.string());
8
8
  const validateClientOptions = z
9
9
  .object({
10
- baseUrl: z.string(),
11
- timeout: z.number(),
10
+ baseUrl: z.string().optional(),
11
+ timeout: z.number().optional(),
12
12
  })
13
13
  .strict()
14
14
  .optional();
15
+ // TODO: once `arcjet` core has `exactOptionalProperties` we can use
16
+ // `satisfies z.ZodType<ShieldOptions>` and such here.
15
17
  const validateShieldOptions = z
16
18
  .object({
17
- mode: validateMode,
19
+ mode: validateMode.optional(),
18
20
  })
19
- .strict()
20
- .optional();
21
- const validateBotOptions = z
22
- .union([
21
+ .strict();
22
+ const validateBotOptions = z.union([
23
23
  z
24
24
  .object({
25
- mode: validateMode,
25
+ mode: validateMode.optional(),
26
26
  allow: z.array(z.string()),
27
27
  })
28
28
  .strict(),
29
29
  z
30
30
  .object({
31
- mode: validateMode,
31
+ mode: validateMode.optional(),
32
32
  deny: z.array(z.string()),
33
33
  })
34
34
  .strict(),
35
- ])
36
- .optional();
37
- const validateEmailOptions = z
38
- .union([
35
+ ]);
36
+ const validateEmailOptions = z.union([
39
37
  z
40
38
  .object({
41
- mode: validateMode,
39
+ mode: validateMode.optional(),
42
40
  allow: z.array(z.string()),
43
- requireTopLevelDomain: z.boolean(),
44
- allowDomainLiteral: z.boolean(),
41
+ requireTopLevelDomain: z.boolean().optional(),
42
+ allowDomainLiteral: z.boolean().optional(),
45
43
  })
46
44
  .strict(),
47
45
  z
48
46
  .object({
49
- mode: validateMode,
47
+ mode: validateMode.optional(),
50
48
  deny: z.array(z.string()),
51
- requireTopLevelDomain: z.boolean(),
52
- allowDomainLiteral: z.boolean(),
49
+ requireTopLevelDomain: z.boolean().optional(),
50
+ allowDomainLiteral: z.boolean().optional(),
53
51
  })
54
52
  .strict(),
55
- ])
56
- .optional();
57
- const validateSensitiveInfoOptions = z
58
- .union([
53
+ ]);
54
+ const validateFilterOptions = z.union([
59
55
  z
60
56
  .object({
61
- mode: validateMode,
57
+ mode: validateMode.optional(),
62
58
  allow: z.array(z.string()),
63
- contextWindowSize: z.number(),
64
59
  })
65
60
  .strict(),
66
61
  z
67
62
  .object({
68
- mode: validateMode,
63
+ mode: validateMode.optional(),
69
64
  deny: z.array(z.string()),
70
- contextWindowSize: z.number(),
71
65
  })
72
66
  .strict(),
73
- ])
74
- .optional();
67
+ ]);
68
+ const validateSensitiveInfoOptions = z.union([
69
+ z
70
+ .object({
71
+ mode: validateMode.optional(),
72
+ allow: z.array(z.string()),
73
+ contextWindowSize: z.number().optional(),
74
+ })
75
+ .strict(),
76
+ z
77
+ .object({
78
+ mode: validateMode.optional(),
79
+ deny: z.array(z.string()),
80
+ contextWindowSize: z.number().optional(),
81
+ })
82
+ .strict(),
83
+ ]);
75
84
  const validateFixedWindowOptions = z
76
85
  .object({
77
- mode: validateMode,
78
- characteristics: validateCharacteristics,
86
+ mode: validateMode.optional(),
87
+ characteristics: validateCharacteristics.optional(),
79
88
  window: z.union([z.string(), z.number()]),
80
89
  max: z.number(),
81
90
  })
82
- .strict()
83
- .optional();
91
+ .strict();
84
92
  const validateSlidingWindowOptions = z
85
93
  .object({
86
- mode: validateMode,
87
- characteristics: validateCharacteristics,
94
+ mode: validateMode.optional(),
95
+ characteristics: validateCharacteristics.optional(),
88
96
  interval: z.union([z.string(), z.number()]),
89
97
  max: z.number(),
90
98
  })
91
- .strict()
92
- .optional();
99
+ .strict();
93
100
  const validateTokenBucketOptions = z
94
101
  .object({
95
- mode: validateMode,
96
- characteristics: validateCharacteristics,
102
+ mode: validateMode.optional(),
103
+ characteristics: validateCharacteristics.optional(),
97
104
  refillRate: z.number(),
98
105
  interval: z.union([z.string(), z.number()]),
99
106
  capacity: z.number(),
100
107
  })
101
- .strict()
102
- .optional();
108
+ .strict();
103
109
  const validateProtectSignupOptions = z
104
110
  .object({
105
111
  rateLimit: validateSlidingWindowOptions,
106
112
  bots: validateBotOptions,
107
113
  email: validateEmailOptions,
108
114
  })
109
- .strict()
110
- .optional();
115
+ .strict();
111
116
  function validateAndSerialize(schema, value) {
112
117
  const v = schema.parse(value);
113
118
  return v ? JSON.stringify(v) : "";
@@ -135,6 +140,13 @@ function integrationRuleToClientRule(rule) {
135
140
  code: `validateEmail(${serializedOpts})`,
136
141
  };
137
142
  }
143
+ case "filter": {
144
+ const serializedOpts = validateAndSerialize(validateFilterOptions, rule.options);
145
+ return {
146
+ importName: `filter`,
147
+ code: `filter(${serializedOpts})`,
148
+ };
149
+ }
138
150
  case "sensitiveInfo": {
139
151
  const serializedOpts = validateAndSerialize(validateSensitiveInfoOptions, rule.options);
140
152
  return {
@@ -176,34 +188,270 @@ function integrationRuleToClientRule(rule) {
176
188
  }
177
189
  }
178
190
  // Mirror the rule functions in the SDK but produce serializable rules
191
+ // Note: please keep JSDocs in sync with `arcjet` core.
192
+ /**
193
+ * Arcjet Shield WAF rule.
194
+ *
195
+ * Applying this rule protects your application against common attacks,
196
+ * including the OWASP Top 10.
197
+ *
198
+ * The Arcjet Shield WAF analyzes every request to your application to detect
199
+ * suspicious activity.
200
+ * Once a certain suspicion threshold is reached,
201
+ * subsequent requests from that client are blocked for a period of time.
202
+ *
203
+ * @param options
204
+ * Configuration for the Shield rule.
205
+ * @returns
206
+ * Astro integration Shield rule to provide to the SDK in the `rules` field.
207
+ */
179
208
  function shield(options) {
180
209
  return { type: "shield", options };
181
210
  }
211
+ // Note: please keep JSDocs in sync with `arcjet` core.
212
+ /**
213
+ * Arcjet bot detection rule.
214
+ *
215
+ * Applying this rule allows you to manage traffic by automated clients and
216
+ * bots.
217
+ *
218
+ * Bots can be good (such as search engine crawlers or monitoring agents) or bad
219
+ * (such as scrapers or automated scripts).
220
+ * Arcjet allows you to configure which bots you want to allow or deny by
221
+ * specific bot names such as curl, as well as by category such as search
222
+ * engine bots.
223
+ *
224
+ * Bots are detected based on various signals such as the user agent, IP
225
+ * address, DNS records, and more.
226
+ *
227
+ * @param options
228
+ * Configuration for the bot rule (required).
229
+ * @returns
230
+ * Astro integration Bot rule to provide to the SDK in the `rules` field.
231
+ */
182
232
  function detectBot(options) {
183
233
  return { type: "bot", options };
184
234
  }
235
+ // Note: please keep JSDocs in sync with `arcjet` core.
236
+ /**
237
+ * Arcjet email validation rule.
238
+ *
239
+ * Applying this rule allows you to validate and verify an email address.
240
+ *
241
+ * The first step of the analysis is to validate the email address syntax.
242
+ * This runs locally within the SDK and validates the email address is in the
243
+ * correct format.
244
+ * If the email syntax is valid, the SDK will pass the email address to the
245
+ * Arcjet cloud API to verify the email address.
246
+ * This performs several checks, depending on the rule configuration.
247
+ *
248
+ * @param options
249
+ * Configuration for the email validation rule (required).
250
+ * @returns
251
+ * Astro integration Email rule to provide to the SDK in the `rules` field.
252
+ */
185
253
  function validateEmail(options) {
186
254
  return { type: "email", options };
187
255
  }
256
+ // Note: please keep JSDocs in sync with `arcjet` core.
257
+ /**
258
+ * Arcjet filter rule.
259
+ *
260
+ * Applying this rule lets you block requests using Wireshark-like display
261
+ * filter expressions over HTTP headers, IP addresses, and other request
262
+ * fields.
263
+ * You can quickly enforce rules like allow/deny by country, network, or
264
+ * `user-agent` pattern.
265
+ *
266
+ * See the [reference guide](https://docs.arcjet.com/filters/reference) for
267
+ * more info on the expression language fields, functions, and values.
268
+ *
269
+ * @param options
270
+ * Configuration (required).
271
+ * @returns
272
+ * Astro integration Filter rule to provide to the SDK in the `rules` field.
273
+ *
274
+ * @example
275
+ * In this example, the expression matches non-VPN GET requests from the US.
276
+ * Requests matching the expression are allowed, all others are denied.
277
+ *
278
+ * ```ts
279
+ * filter({
280
+ * allow: [
281
+ * 'http.request.method eq "GET" and ip.src.country eq "US" and not ip.src.vpn',
282
+ * ],
283
+ * mode: "LIVE",
284
+ * })
285
+ * ```
286
+ *
287
+ * @link https://docs.arcjet.com/filters/reference
288
+ */
289
+ function filter(options) {
290
+ return { type: "filter", options };
291
+ }
292
+ // Note: please keep JSDocs in sync with `arcjet` core.
293
+ /**
294
+ * Arcjet sensitive information detection rule.
295
+ *
296
+ * Applying this rule protects against clients sending you sensitive information
297
+ * such as personally identifiable information (PII) that you do not wish to
298
+ * handle.
299
+ * The rule runs entirely locally so no data ever leaves your environment.
300
+ *
301
+ * This rule includes built-in detections for email addresses, credit/debit card
302
+ * numbers, IP addresses, and phone numbers.
303
+ * You can also provide a custom detection function to identify additional
304
+ * sensitive information.
305
+ *
306
+ * @param options
307
+ * Configuration for the sensitive information detection rule (required).
308
+ * @returns
309
+ * Astro integration Sensitive information rule to provide to the SDK in the `rules` field.
310
+ */
188
311
  function sensitiveInfo(options) {
189
312
  return { type: "sensitiveInfo", options };
190
313
  }
314
+ // Note: please keep JSDocs in sync with `arcjet` core.
315
+ /**
316
+ * Arcjet fixed window rate limiting rule.
317
+ *
318
+ * Applying this rule sets a fixed window rate limit which tracks the number of
319
+ * requests made by a client over a fixed time window.
320
+ *
321
+ * This is the simplest algorithm.
322
+ * It tracks the number of requests made by a client over a fixed time window
323
+ * such as 60 seconds.
324
+ * If the client exceeds the limit, they are blocked until the window expires.
325
+ *
326
+ * This algorithm is useful when you want to apply a simple fixed limit in a
327
+ * fixed time window.
328
+ * For example, a simple limit on the total number of requests a client can make.
329
+ * However, it can be susceptible to the stampede problem where a client makes
330
+ * a burst of requests at the start of a window and then is blocked for the rest
331
+ * of the window.
332
+ * The sliding window algorithm can be used to avoid this.
333
+ *
334
+ * @template Characteristics
335
+ * Characteristics to track a user by.
336
+ * @param options
337
+ * Configuration for the fixed window rate limiting rule (required).
338
+ * @returns
339
+ * Astro integration Fixed window rule to provide to the SDK in the `rules` field.
340
+ */
191
341
  function fixedWindow(options) {
192
- return { type: "fixedWindow", options };
342
+ return {
343
+ type: "fixedWindow",
344
+ options,
345
+ };
193
346
  }
347
+ // Note: please keep JSDocs in sync with `arcjet` core.
348
+ /**
349
+ * Arcjet sliding window rate limiting rule.
350
+ *
351
+ * Applying this rule sets a sliding window rate limit which tracks the number
352
+ * of requests made by a client over a sliding window so that the window moves
353
+ * with time.
354
+ *
355
+ * This algorithm is useful to avoid the stampede problem of the fixed window.
356
+ * It provides smoother rate limiting over time and can prevent a client from
357
+ * making a burst of requests at the start of a window and then being blocked
358
+ * for the rest of the window.
359
+ *
360
+ * @template Characteristics
361
+ * Characteristics to track a user by.
362
+ * @param options
363
+ * Configuration for the sliding window rate limiting rule (required).
364
+ * @returns
365
+ * Astro integration Sliding window rule to provide to the SDK in the `rules` field.
366
+ */
194
367
  function slidingWindow(options) {
195
- return { type: "slidingWindow", options };
368
+ return {
369
+ type: "slidingWindow",
370
+ options,
371
+ };
196
372
  }
373
+ // Note: please keep JSDocs in sync with `arcjet` core.
374
+ /**
375
+ * Arcjet token bucket rate limiting rule.
376
+ *
377
+ * Applying this rule sets a token bucket rate limit.
378
+ *
379
+ * This algorithm is based on a bucket filled with a specific number of tokens.
380
+ * Each request withdraws some amount of tokens from the bucket and the bucket
381
+ * is refilled at a fixed rate.
382
+ * Once the bucket is empty, the client is blocked until the bucket refills.
383
+ *
384
+ * This algorithm is useful when you want to allow clients to make a burst of
385
+ * requests and then still be able to make requests at a slower rate.
386
+ *
387
+ * @template Characteristics
388
+ * Characteristics to track a user by.
389
+ * @param options
390
+ * Configuration for the token bucket rate limiting rule (required).
391
+ * @returns
392
+ * Astro integration Token bucket rule to provide to the SDK in the `rules` field.
393
+ */
197
394
  function tokenBucket(options) {
198
- return { type: "tokenBucket", options };
395
+ return {
396
+ type: "tokenBucket",
397
+ options,
398
+ };
199
399
  }
400
+ // Note: please keep JSDocs in sync with `arcjet` core.
401
+ /**
402
+ * Arcjet signup form protection rule.
403
+ *
404
+ * Applying this rule combines rate limiting, bot protection, and email
405
+ * validation to protect your signup forms from abuse.
406
+ * Using this rule will configure the following:
407
+ *
408
+ * - Rate limiting - signup forms are a common target for bots. Arcjet’s rate
409
+ * limiting helps to prevent bots and other automated or malicious clients
410
+ * from submitting your signup form too many times in a short period of time.
411
+ * - Bot protection - signup forms are usually exclusively used by humans, which
412
+ * means that any automated submissions to the form are likely to be
413
+ * fraudulent.
414
+ * - Email validation - email addresses should be validated to ensure the signup
415
+ * is coming from a legitimate user with a real email address that can
416
+ * actually receive messages.
417
+ *
418
+ * @template Characteristics
419
+ * Characteristics to track a user by.
420
+ * @param options
421
+ * Configuration for the signup form protection rule.
422
+ * @returns
423
+ * Astro integration Signup form protection rule to provide to the SDK in the `rules` field.
424
+ */
200
425
  function protectSignup(options) {
201
- return { type: "protectSignup", options };
426
+ return {
427
+ type: "protectSignup",
428
+ options,
429
+ };
202
430
  }
203
- function createRemoteClient({ baseUrl, timeout }) {
204
- return { baseUrl, timeout };
431
+ /**
432
+ * Create a remote client.
433
+ *
434
+ * @param options
435
+ * Configuration (optional).
436
+ * @returns
437
+ * Client.
438
+ */
439
+ function createRemoteClient(options) {
440
+ const settings = options ?? {};
441
+ return { baseUrl: settings.baseUrl, timeout: settings.timeout };
205
442
  }
206
- function arcjet({ rules, characteristics, client, proxies, } = { rules: [] }) {
443
+ /**
444
+ * Create a new Astro integration of Arcjet.
445
+ *
446
+ * @template Characteristics
447
+ * Characteristics to track a user by.
448
+ * @param options
449
+ * Configuration.
450
+ * @returns
451
+ * Astro integration of Arcjet.
452
+ */
453
+ function arcjet(options = { rules: [] }) {
454
+ const { rules, characteristics, client, proxies } = options;
207
455
  const arcjetImports = new Set();
208
456
  const arcjetRules = [];
209
457
  for (const rule of rules) {
@@ -266,6 +514,21 @@ function arcjet({ rules, characteristics, client, proxies, } = { rules: [] }) {
266
514
  access: "public",
267
515
  optional: true,
268
516
  },
517
+ FIREBASE_CONFIG: {
518
+ access: "public",
519
+ context: "server",
520
+ optional: true,
521
+ type: "string",
522
+ },
523
+ // No `MODE`, that is a vite value on `import.meta.env.MODE`,
524
+ // it is inferred in `internal.ts` directly.
525
+ // No `NODE_ENV`.
526
+ RENDER: {
527
+ access: "public",
528
+ context: "server",
529
+ optional: true,
530
+ type: "string",
531
+ },
269
532
  },
270
533
  },
271
534
  vite: {
@@ -331,6 +594,21 @@ function arcjet({ rules, characteristics, client, proxies, } = { rules: [] }) {
331
594
  ${Array.from(arcjetImports).join(",\n")}
332
595
  } from "arcjet"
333
596
 
597
+ /**
598
+ * Instance of the Astro integration of Arcjet.
599
+ *
600
+ * Primarily has a \`protect()\` method to make a decision about how a request
601
+ * should be handled.
602
+ *
603
+ * > 👉 **Note**: this is generated by \`@arcjet/astro\` based on how you configure
604
+ * > Arcjet in your \`astro.config.mjs\` file.
605
+ * > In that configuration file, you can pass the (serializable) options that apply
606
+ * > to all requests.
607
+ * > You can call \`aj.withRule\` *on* this default client to extend its behavior.
608
+ *
609
+ * @template Props
610
+ * Configuration.
611
+ */
334
612
  const client = createArcjetClient({
335
613
  rules: [
336
614
  ${arcjetRules.join(",\n")}
@@ -348,4 +626,4 @@ function arcjet({ rules, characteristics, client, proxies, } = { rules: [] }) {
348
626
  };
349
627
  }
350
628
 
351
- export { createRemoteClient, arcjet as default, detectBot, fixedWindow, protectSignup, sensitiveInfo, shield, slidingWindow, tokenBucket, validateEmail };
629
+ export { createRemoteClient, arcjet as default, detectBot, filter, fixedWindow, protectSignup, sensitiveInfo, shield, slidingWindow, tokenBucket, validateEmail };
package/internal.d.ts CHANGED
@@ -4,57 +4,115 @@ type Simplify<T> = {
4
4
  [KeyType in keyof T]: T[KeyType];
5
5
  } & {};
6
6
  declare const emptyObjectSymbol: unique symbol;
7
- type WithoutCustomProps = {
8
- [emptyObjectSymbol]?: never;
9
- };
10
7
  type PlainObject = {
11
8
  [key: string]: unknown;
12
9
  };
10
+ /**
11
+ * Dynamically generate whether zero or one `properties` object must or can be passed.
12
+ */
13
+ type MaybeProperties<T> = {
14
+ [P in keyof T]?: T[P];
15
+ } extends T ? T extends {
16
+ [emptyObjectSymbol]?: never;
17
+ } ? [
18
+ ] : [
19
+ properties?: T
20
+ ] : [
21
+ properties: T
22
+ ];
23
+ /**
24
+ * Configuration for {@linkcode createRemoteClient}.
25
+ */
13
26
  export type RemoteClientOptions = {
27
+ /**
28
+ * Base URI for HTTP requests to Decide API (optional).
29
+ *
30
+ * Defaults to the environment variable `ARCJET_BASE_URL` (if that value
31
+ * is known and allowed) and the standard production API otherwise.
32
+ */
14
33
  baseUrl?: string;
34
+ /**
35
+ * Timeout in milliseconds for the Decide API (optional).
36
+ *
37
+ * Defaults to `500` in production and `1000` in development.
38
+ */
15
39
  timeout?: number;
16
40
  };
41
+ /**
42
+ * Create a remote client.
43
+ *
44
+ * @param options
45
+ * Configuration (optional).
46
+ * @returns
47
+ * Client.
48
+ */
17
49
  export declare function createRemoteClient(options?: RemoteClientOptions): import("@arcjet/protocol/client.js").Client;
18
50
  /**
19
- * The options used to configure an {@link ArcjetAstro} client.
51
+ * Configuration for the Astro integration of Arcjet.
52
+ *
53
+ * @template Rules
54
+ * List of rules.
55
+ * @template Characteristics
56
+ * Characteristics to track a user by.
20
57
  */
21
58
  export type ArcjetOptions<Rules extends [...Array<Primitive | Product>], Characteristics extends readonly string[]> = Simplify<CoreOptions<Rules, Characteristics> & {
22
59
  /**
23
- * One or more IP Address of trusted proxies in front of the application.
24
- * These addresses will be excluded when Arcjet detects a public IP address.
60
+ * IP addresses and CIDR ranges of trusted load balancers and proxies
61
+ * (optional, example: `["100.100.100.100", "100.100.100.0/24"]`).
25
62
  */
26
63
  proxies?: Array<string>;
27
64
  }>;
28
65
  /**
29
- * The ArcjetAstro client provides a public `protect()` method to
30
- * make a decision about how an Astro request should be handled.
66
+ * Instance of the Astro integration of Arcjet.
67
+ *
68
+ * Primarily has a `protect()` method to make a decision about how a request
69
+ * should be handled.
70
+ *
71
+ * @template Props
72
+ * Configuration.
31
73
  */
32
74
  export interface ArcjetAstro<Props extends PlainObject> {
33
75
  /**
34
- * Runs a request through the configured protections. The request is
35
- * analyzed and then a decision made on whether to allow, deny, or challenge
36
- * the request.
76
+ * Make a decision about how to handle a request.
37
77
  *
38
- * @param request - A `Request` provided to the fetch handler.
39
- * @param props - Additonal properties required for running rules against a request.
40
- * @returns An {@link ArcjetDecision} indicating Arcjet's decision about the request.
78
+ * This will analyze the request locally where possible and otherwise call
79
+ * the Arcjet decision API.
80
+ *
81
+ * @param ctx
82
+ * Additional context for this function call.
83
+ * @param request
84
+ * Details about the {@linkcode ArcjetRequest} that Arcjet needs to make a
85
+ * decision.
86
+ * @returns
87
+ * Promise that resolves to an {@linkcode ArcjetDecision} indicating
88
+ * Arcjet’s decision about the request.
41
89
  */
42
- protect(request: Request, ...props: Props extends WithoutCustomProps ? [] : [Props]): Promise<ArcjetDecision>;
90
+ protect(request: Request, ...props: MaybeProperties<Props>): Promise<ArcjetDecision>;
43
91
  /**
44
- * Augments the client with another rule. Useful for varying rules based on
45
- * criteria in your handler—e.g. different rate limit for logged in users.
92
+ * Augment the client with another rule.
93
+ *
94
+ * Useful for varying rules based on criteria in your handler such as
95
+ * different rate limit for logged in users.
46
96
  *
47
- * @param rule The rule to add to this execution.
48
- * @returns An augmented {@link ArcjetAstro} client.
97
+ * @template Rule
98
+ * Type of rule.
99
+ * @param rule
100
+ * Rule to add to Arcjet.
101
+ * @returns
102
+ * Arcjet instance augmented with the given rule.
49
103
  */
50
- withRule<Rule extends Primitive | Product>(rule: Rule): ArcjetAstro<Simplify<Props & ExtraProps<Rule>>>;
104
+ withRule<ChildProperties extends PlainObject>(rule: Primitive<ChildProperties> | Product<ChildProperties>): ArcjetAstro<Props & ChildProperties>;
51
105
  }
52
106
  /**
53
- * Create a new {@link ArcjetAstro} client. Always build your initial client
54
- * outside of a request handler so it persists across requests. If you need to
55
- * augment a client inside a handler, call the `withRule()` function on the base
56
- * client.
107
+ * Create a new Astro integration of Arcjet.
57
108
  *
58
- * @param options - Arcjet configuration options to apply to all requests.
109
+ * @template Rules
110
+ * List of rules.
111
+ * @template Characteristics
112
+ * Characteristics to track a user by.
113
+ * @param options
114
+ * Configuration.
115
+ * @returns
116
+ * Astro integration of Arcjet.
59
117
  */
60
- export declare function createArcjetClient<const Rules extends (Primitive | Product)[], const Characteristics extends readonly string[]>(options: ArcjetOptions<Rules, Characteristics>): ArcjetAstro<Simplify<ExtraProps<Rules> & CharacteristicProps<Characteristics>>>;
118
+ export declare function createArcjetClient<const Rules extends (Primitive | Product)[], const Characteristics extends readonly string[]>(options: ArcjetOptions<Rules, Characteristics>): ArcjetAstro<ExtraProps<Rules> & CharacteristicProps<Characteristics>>;