@arcjet/analyze 1.0.0-alpha.8 → 1.0.0-beta.1

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 CHANGED
@@ -1,21 +1,23 @@
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-logo-dark-planet-arrival.svg">
4
- <img src="https://arcjet.com/arcjet-logo-light-planet-arrival.svg" alt="Arcjet Logo" height="144" width="auto">
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
 
8
8
  # `@arcjet/analyze`
9
9
 
10
10
  <p>
11
- <picture>
12
- <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/npm/v/%40arcjet%2Fanalyze?style=flat-square&label=%E2%9C%A6Aj&labelColor=000000&color=5C5866">
13
- <img alt="npm badge" src="https://img.shields.io/npm/v/%40arcjet%2Fanalyze?style=flat-square&label=%E2%9C%A6Aj&labelColor=ECE6F0&color=ECE6F0">
14
- </picture>
11
+ <a href="https://www.npmjs.com/package/@arcjet/analyze">
12
+ <picture>
13
+ <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/npm/v/%40arcjet%2Fanalyze?style=flat-square&label=%E2%9C%A6Aj&labelColor=000000&color=5C5866">
14
+ <img alt="npm badge" src="https://img.shields.io/npm/v/%40arcjet%2Fanalyze?style=flat-square&label=%E2%9C%A6Aj&labelColor=ECE6F0&color=ECE6F0">
15
+ </picture>
16
+ </a>
15
17
  </p>
16
18
 
17
19
  [Arcjet][arcjet] helps developers protect their apps in just a few lines of
18
- code. Implement rate limiting, bot protection, email verification & defend
20
+ code. Implement rate limiting, bot protection, email verification, and defense
19
21
  against common attacks.
20
22
 
21
23
  This is the [Arcjet][arcjet] local analysis engine.
@@ -40,37 +42,17 @@ console.log("is email valid?", valid);
40
42
 
41
43
  ## Implementation
42
44
 
43
- This package provides analyze logic implemented as a WebAssembly module which
44
- will run local analysis on request details before calling the Arcjet API.
45
-
46
- The [arcjet.wasm.js](./wasm/arcjet.wasm.js) file contains the binary inlined as
47
- a base64 [Data URL][mdn-data-url] with the `application/wasm` MIME type.
48
-
49
- This was chosen to save on storage space over inlining the file directly as a
50
- Uint8Array, which would take up ~3x the space of the Wasm file. See
51
- [Better Binary Batter: Mixing Base64 and Uint8Array][wasm-base64-blog] for more
52
- details.
53
-
54
- It is then decoded into an ArrayBuffer to be used directly via WebAssembly's
55
- `compile()` function in our entry point file.
56
-
57
- This is all done to avoid trying to read or bundle the Wasm asset in various
58
- ways based on the platform or bundler a user is targeting. One example being
59
- that Next.js requires special `asyncWebAssembly` webpack config to load our
60
- Wasm file if we don't do this.
61
-
62
- In the future, we hope to do away with this workaround when all bundlers
63
- properly support consistent asset bundling techniques.
64
-
65
- ## API
45
+ This package uses the Wasm bindings provided by `@arcjet/analyze-wasm` to
46
+ call various functions that are exported by our wasm bindings.
66
47
 
67
- In progress.
48
+ We chose to put this logic in a separate package because we need to change the
49
+ import structure for each runtime that we support in the wasm bindings. Moving
50
+ this to a separate package allows us not to have to duplicate code while providing
51
+ a combined higher-level api for calling our core functionality in Wasm.
68
52
 
69
53
  ## License
70
54
 
71
55
  Licensed under the [Apache License, Version 2.0][apache-license].
72
56
 
73
57
  [arcjet]: https://arcjet.com
74
- [mdn-data-url]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs
75
- [wasm-base64-blog]: https://blobfolio.com/2019/better-binary-batter-mixing-base64-and-uint8array/
76
58
  [apache-license]: http://www.apache.org/licenses/LICENSE-2.0
package/index.d.ts CHANGED
@@ -1,27 +1,29 @@
1
- import { type EmailValidationConfig } from "./wasm/arcjet_analyze_js_req.js";
2
- export { type EmailValidationConfig };
1
+ import type { BotConfig, BotResult, DetectedSensitiveInfoEntity, DetectSensitiveInfoFunction, EmailValidationConfig, EmailValidationResult, SensitiveInfoEntities, SensitiveInfoEntity, SensitiveInfoResult } from "@arcjet/analyze-wasm";
2
+ import type { ArcjetLogger } from "@arcjet/protocol";
3
+ interface AnalyzeContext {
4
+ log: ArcjetLogger;
5
+ characteristics: string[];
6
+ }
7
+ type AnalyzeRequest = {
8
+ ip?: string;
9
+ method?: string;
10
+ protocol?: string;
11
+ host?: string;
12
+ path?: string;
13
+ headers?: Record<string, string>;
14
+ cookies?: string;
15
+ query?: string;
16
+ extra?: Record<string, string>;
17
+ };
18
+ export { type EmailValidationConfig, type BotConfig, type SensitiveInfoEntity, type DetectedSensitiveInfoEntity, };
3
19
  /**
4
20
  * Generate a fingerprint for the client. This is used to identify the client
5
21
  * across multiple requests.
6
- * @param ip - The IP address of the client.
22
+ * @param context - The Arcjet Analyze context.
23
+ * @param request - The request to fingerprint.
7
24
  * @returns A SHA-256 string fingerprint.
8
25
  */
9
- export declare function generateFingerprint(ip: string): Promise<string>;
10
- export declare function isValidEmail(candidate: string, options?: EmailValidationConfig): Promise<boolean>;
11
- /**
12
- * Represents the result of the bot detection.
13
- *
14
- * @property `bot_type` - What type of bot this is. This will be one of `BotType`.
15
- * @property `bot_score` - A score ranging from 0 to 99 representing the degree of
16
- * certainty. The higher the number within the type category, the greater the
17
- * degree of certainty. E.g. `BotType.Automated` with a score of 1 means we are
18
- * sure the request was made by an automated bot. `BotType.LikelyNotABot` with a
19
- * score of 30 means we don't think this request was a bot, but it's lowest
20
- * confidence level. `BotType.LikelyNotABot` with a score of 99 means we are
21
- * almost certain this request was not a bot.
22
- */
23
- export interface BotResult {
24
- bot_type: number;
25
- bot_score: number;
26
- }
27
- export declare function detectBot(headers: string, patterns_add: string, patterns_remove: string): Promise<BotResult>;
26
+ export declare function generateFingerprint(context: AnalyzeContext, request: AnalyzeRequest): Promise<string>;
27
+ export declare function isValidEmail(context: AnalyzeContext, candidate: string, options: EmailValidationConfig): Promise<EmailValidationResult>;
28
+ export declare function detectBot(context: AnalyzeContext, request: AnalyzeRequest, options: BotConfig): Promise<BotResult>;
29
+ export declare function detectSensitiveInfo(context: AnalyzeContext, candidate: string, entities: SensitiveInfoEntities, contextWindowSize: number, detect?: DetectSensitiveInfoFunction): Promise<SensitiveInfoResult>;
package/index.js CHANGED
@@ -1,109 +1,116 @@
1
- import initWasm, { detect_bot, generate_fingerprint, is_valid_email } from './wasm/arcjet_analyze_js_req.js';
1
+ import { initializeWasm } from '@arcjet/analyze-wasm';
2
2
 
3
- let state = "uninitialized";
4
- /**
5
- * Initialize the WASM module. This can be explicitly called after creating
6
- * the client, but it will be called automatically if it has not been called
7
- * when the first request is made. This uses a factory-style pattern because
8
- * the call must be async and the constructor cannot be async.
9
- */
10
- async function init() {
11
- if (state === "errored" || state === "unsupported")
12
- return;
13
- if (typeof WebAssembly === "undefined") {
14
- state = "unsupported";
15
- return;
16
- }
17
- if (state === "uninitialized") {
18
- try {
19
- let wasmModule;
20
- // We use `NEXT_RUNTIME` env var to DCE the Node/Browser code in the `else` block
21
- // possible values: "edge" | "nodejs" | undefined
22
- if (process.env["NEXT_RUNTIME"] === "edge") {
23
- const mod = await import(
24
- // @ts-expect-error
25
- './wasm/arcjet_analyze_js_req_bg.wasm?module');
26
- wasmModule = mod.default;
27
- }
28
- else {
29
- const { wasm } = await import('./wasm/arcjet.wasm.js');
30
- wasmModule = await WebAssembly.compile(await wasm());
31
- }
32
- await initWasm(wasmModule);
33
- state = "initialized";
34
- }
35
- catch (err) {
36
- state = "errored";
37
- return;
38
- }
3
+ const FREE_EMAIL_PROVIDERS = [
4
+ "gmail.com",
5
+ "yahoo.com",
6
+ "hotmail.com",
7
+ "aol.com",
8
+ "hotmail.co.uk",
9
+ ];
10
+ function noOpDetect() {
11
+ return [];
12
+ }
13
+ function createCoreImports(detect) {
14
+ if (typeof detect !== "function") {
15
+ detect = noOpDetect;
39
16
  }
40
17
  return {
41
- detectBot: detect_bot,
42
- fingerprint: generate_fingerprint,
43
- isValidEmail: is_valid_email,
18
+ "arcjet:js-req/email-validator-overrides": {
19
+ isFreeEmail(domain) {
20
+ if (FREE_EMAIL_PROVIDERS.includes(domain)) {
21
+ return "yes";
22
+ }
23
+ return "unknown";
24
+ },
25
+ isDisposableEmail() {
26
+ return "unknown";
27
+ },
28
+ hasMxRecords() {
29
+ return "unknown";
30
+ },
31
+ hasGravatar() {
32
+ return "unknown";
33
+ },
34
+ },
35
+ "arcjet:js-req/sensitive-information-identifier": {
36
+ detect,
37
+ },
38
+ "arcjet:js-req/verify-bot": {
39
+ verify() {
40
+ return "unverifiable";
41
+ },
42
+ },
44
43
  };
45
44
  }
46
45
  /**
47
46
  * Generate a fingerprint for the client. This is used to identify the client
48
47
  * across multiple requests.
49
- * @param ip - The IP address of the client.
48
+ * @param context - The Arcjet Analyze context.
49
+ * @param request - The request to fingerprint.
50
50
  * @returns A SHA-256 string fingerprint.
51
51
  */
52
- async function generateFingerprint(ip) {
53
- if (ip == "") {
54
- return "";
55
- }
56
- // We use `NEXT_RUNTIME` env var to DCE the JS fallback code in the `else` block
57
- // possible values: "edge" | "nodejs" | undefined
58
- if (process.env["NEXT_RUNTIME"] === "edge") {
59
- const analyze = await init();
60
- // We HAVE to have the WasmAPI in Edge
61
- const fingerprint = analyze.fingerprint(ip);
62
- return fingerprint;
52
+ async function generateFingerprint(context, request) {
53
+ const { log } = context;
54
+ const coreImports = createCoreImports();
55
+ const analyze = await initializeWasm(coreImports);
56
+ if (typeof analyze !== "undefined") {
57
+ return analyze.generateFingerprint(JSON.stringify(request), context.characteristics);
63
58
  }
64
59
  else {
65
- const analyze = await init();
66
- if (typeof analyze !== "undefined") {
67
- const fingerprint = analyze.fingerprint(ip);
68
- return fingerprint;
69
- }
70
- else {
71
- // Conditional import because it's not available in some runtimes, we know
72
- // it is when running on Vercel serverless functions.
73
- // TODO(#180): Avoid nodejs-specific import
74
- const createHash = await import('crypto');
75
- // Fingerprint v1 is just the IP address
76
- const fingerprintRaw = `fp_1_${ip}`;
77
- const fingerprint = createHash
78
- .createHash("sha256")
79
- .update(fingerprintRaw)
80
- .digest("hex");
81
- return fingerprint;
82
- }
60
+ log.debug("WebAssembly is not supported in this runtime");
83
61
  }
62
+ return "";
84
63
  }
85
- async function isValidEmail(candidate, options) {
86
- const analyze = await init();
64
+ async function isValidEmail(context, candidate, options) {
65
+ const { log } = context;
66
+ const coreImports = createCoreImports();
67
+ const analyze = await initializeWasm(coreImports);
87
68
  if (typeof analyze !== "undefined") {
88
69
  return analyze.isValidEmail(candidate, options);
89
70
  }
90
71
  else {
91
- // TODO: Fallback to JS if we don't have WASM?
92
- return true;
72
+ log.debug("WebAssembly is not supported in this runtime");
73
+ // Skip the local evaluation of the rule if WASM is not available
74
+ return {
75
+ validity: "valid",
76
+ blocked: [],
77
+ };
93
78
  }
94
79
  }
95
- async function detectBot(headers, patterns_add, patterns_remove) {
96
- const analyze = await init();
80
+ async function detectBot(context, request, options) {
81
+ const { log } = context;
82
+ const coreImports = createCoreImports();
83
+ const analyze = await initializeWasm(coreImports);
97
84
  if (typeof analyze !== "undefined") {
98
- return analyze.detectBot(headers, patterns_add, patterns_remove);
85
+ return analyze.detectBot(JSON.stringify(request), options);
99
86
  }
100
87
  else {
101
- // TODO: Fallback to JS if we don't have WASM?
88
+ log.debug("WebAssembly is not supported in this runtime");
89
+ // Skip the local evaluation of the rule if Wasm is not available
102
90
  return {
103
- bot_type: 1, // NOT_ANALYZED
104
- bot_score: 0,
91
+ allowed: [],
92
+ denied: [],
93
+ spoofed: false,
94
+ verified: false,
105
95
  };
106
96
  }
107
97
  }
98
+ async function detectSensitiveInfo(context, candidate, entities, contextWindowSize, detect) {
99
+ const { log } = context;
100
+ const coreImports = createCoreImports(detect);
101
+ const analyze = await initializeWasm(coreImports);
102
+ if (typeof analyze !== "undefined") {
103
+ const skipCustomDetect = typeof detect !== "function";
104
+ return analyze.detectSensitiveInfo(candidate, {
105
+ entities,
106
+ contextWindowSize,
107
+ skipCustomDetect,
108
+ });
109
+ }
110
+ else {
111
+ log.debug("WebAssembly is not supported in this runtime");
112
+ throw new Error("SENSITIVE_INFO rule failed to run because Wasm is not supported in this environment.");
113
+ }
114
+ }
108
115
 
109
- export { detectBot, generateFingerprint, isValidEmail };
116
+ export { detectBot, detectSensitiveInfo, generateFingerprint, isValidEmail };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcjet/analyze",
3
- "version": "1.0.0-alpha.8",
3
+ "version": "1.0.0-beta.1",
4
4
  "description": "Arcjet local analysis engine",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://arcjet.com",
@@ -9,6 +9,15 @@
9
9
  "url": "git+https://github.com/arcjet/arcjet-js.git",
10
10
  "directory": "analyze"
11
11
  },
12
+ "bugs": {
13
+ "url": "https://github.com/arcjet/arcjet-js/issues",
14
+ "email": "support@arcjet.com"
15
+ },
16
+ "author": {
17
+ "name": "Arcjet",
18
+ "email": "support@arcjet.com",
19
+ "url": "https://arcjet.com"
20
+ },
12
21
  "engines": {
13
22
  "node": ">=18"
14
23
  },
@@ -18,10 +27,10 @@
18
27
  "files": [
19
28
  "LICENSE",
20
29
  "README.md",
30
+ "_virtual/",
21
31
  "wasm/",
22
32
  "*.js",
23
33
  "*.d.ts",
24
- "*.ts",
25
34
  "!*.config.js"
26
35
  ],
27
36
  "scripts": {
@@ -29,23 +38,21 @@
29
38
  "build": "rollup --config rollup.config.js",
30
39
  "lint": "eslint .",
31
40
  "pretest": "npm run build",
32
- "test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests"
41
+ "test": "node --test --experimental-test-coverage"
33
42
  },
34
- "sideEffects": [
35
- "./wasm/arcjet_analyze_js_req_bg.js"
36
- ],
37
43
  "dependencies": {
38
- "@arcjet/logger": "1.0.0-alpha.8"
44
+ "@arcjet/analyze-wasm": "1.0.0-beta.1",
45
+ "@arcjet/protocol": "1.0.0-beta.1"
39
46
  },
40
47
  "devDependencies": {
41
- "@arcjet/eslint-config": "1.0.0-alpha.8",
42
- "@arcjet/rollup-config": "1.0.0-alpha.8",
43
- "@arcjet/tsconfig": "1.0.0-alpha.8",
44
- "@jest/globals": "29.7.0",
45
- "@rollup/wasm-node": "4.9.6",
48
+ "@arcjet/eslint-config": "1.0.0-beta.1",
49
+ "@arcjet/rollup-config": "1.0.0-beta.1",
50
+ "@arcjet/tsconfig": "1.0.0-beta.1",
51
+ "@bytecodealliance/jco": "1.5.0",
52
+ "@rollup/wasm-node": "4.30.1",
46
53
  "@types/node": "18.18.0",
47
- "jest": "29.7.0",
48
- "typescript": "5.3.3"
54
+ "expect": "29.7.0",
55
+ "typescript": "5.7.3"
49
56
  },
50
57
  "publishConfig": {
51
58
  "access": "public",
package/index.ts DELETED
@@ -1,165 +0,0 @@
1
- import initWasm, {
2
- detect_bot,
3
- generate_fingerprint,
4
- is_valid_email,
5
- type EmailValidationConfig,
6
- } from "./wasm/arcjet_analyze_js_req.js";
7
-
8
- export { type EmailValidationConfig };
9
-
10
- type WasmAPI = {
11
- /**
12
- * The WASM detect_bot function. Initialized by calling `init()`. Defined at a
13
- * class level to avoid having to load the WASM module multiple times.
14
- */
15
- detectBot: typeof detect_bot;
16
- /**
17
- * The WASM fingerprint function. Initialized by calling `init()`. Defined at
18
- * a class level to avoid having to load the WASM module multiple times.
19
- */
20
- fingerprint: typeof generate_fingerprint;
21
- /**
22
- * The WASM email validation function. Initialized by calling `init()`. Defined at
23
- * a class level to avoid having to load the WASM module multiple times.
24
- */
25
- isValidEmail: typeof is_valid_email;
26
- };
27
-
28
- type WasmState = "initialized" | "uninitialized" | "unsupported" | "errored";
29
-
30
- let state: WasmState = "uninitialized";
31
-
32
- /**
33
- * Initialize the WASM module. This can be explicitly called after creating
34
- * the client, but it will be called automatically if it has not been called
35
- * when the first request is made. This uses a factory-style pattern because
36
- * the call must be async and the constructor cannot be async.
37
- */
38
- async function init(): Promise<WasmAPI | undefined> {
39
- if (state === "errored" || state === "unsupported") return;
40
-
41
- if (typeof WebAssembly === "undefined") {
42
- state = "unsupported";
43
- return;
44
- }
45
-
46
- if (state === "uninitialized") {
47
- try {
48
- let wasmModule: WebAssembly.Module;
49
- // We use `NEXT_RUNTIME` env var to DCE the Node/Browser code in the `else` block
50
- // possible values: "edge" | "nodejs" | undefined
51
- if (process.env["NEXT_RUNTIME"] === "edge") {
52
- const mod = await import(
53
- // @ts-expect-error
54
- "./wasm/arcjet_analyze_js_req_bg.wasm?module"
55
- );
56
- wasmModule = mod.default;
57
- } else {
58
- const { wasm } = await import("./wasm/arcjet.wasm.js");
59
- wasmModule = await WebAssembly.compile(await wasm());
60
- }
61
-
62
- await initWasm(wasmModule);
63
- state = "initialized";
64
- } catch (err) {
65
- state = "errored";
66
- return;
67
- }
68
- }
69
-
70
- return {
71
- detectBot: detect_bot,
72
- fingerprint: generate_fingerprint,
73
- isValidEmail: is_valid_email,
74
- };
75
- }
76
-
77
- /**
78
- * Generate a fingerprint for the client. This is used to identify the client
79
- * across multiple requests.
80
- * @param ip - The IP address of the client.
81
- * @returns A SHA-256 string fingerprint.
82
- */
83
- export async function generateFingerprint(ip: string): Promise<string> {
84
- if (ip == "") {
85
- return "";
86
- }
87
-
88
- // We use `NEXT_RUNTIME` env var to DCE the JS fallback code in the `else` block
89
- // possible values: "edge" | "nodejs" | undefined
90
- if (process.env["NEXT_RUNTIME"] === "edge") {
91
- const analyze = await init();
92
- // We HAVE to have the WasmAPI in Edge
93
- const fingerprint = analyze!.fingerprint(ip);
94
- return fingerprint;
95
- } else {
96
- const analyze = await init();
97
- if (typeof analyze !== "undefined") {
98
- const fingerprint = analyze.fingerprint(ip);
99
- return fingerprint;
100
- } else {
101
- // Conditional import because it's not available in some runtimes, we know
102
- // it is when running on Vercel serverless functions.
103
- // TODO(#180): Avoid nodejs-specific import
104
- const createHash = await import("crypto");
105
-
106
- // Fingerprint v1 is just the IP address
107
- const fingerprintRaw = `fp_1_${ip}`;
108
-
109
- const fingerprint = createHash
110
- .createHash("sha256")
111
- .update(fingerprintRaw)
112
- .digest("hex");
113
- return fingerprint;
114
- }
115
- }
116
- }
117
-
118
- export async function isValidEmail(
119
- candidate: string,
120
- options?: EmailValidationConfig,
121
- ) {
122
- const analyze = await init();
123
-
124
- if (typeof analyze !== "undefined") {
125
- return analyze.isValidEmail(candidate, options);
126
- } else {
127
- // TODO: Fallback to JS if we don't have WASM?
128
- return true;
129
- }
130
- }
131
-
132
- /**
133
- * Represents the result of the bot detection.
134
- *
135
- * @property `bot_type` - What type of bot this is. This will be one of `BotType`.
136
- * @property `bot_score` - A score ranging from 0 to 99 representing the degree of
137
- * certainty. The higher the number within the type category, the greater the
138
- * degree of certainty. E.g. `BotType.Automated` with a score of 1 means we are
139
- * sure the request was made by an automated bot. `BotType.LikelyNotABot` with a
140
- * score of 30 means we don't think this request was a bot, but it's lowest
141
- * confidence level. `BotType.LikelyNotABot` with a score of 99 means we are
142
- * almost certain this request was not a bot.
143
- */
144
- export interface BotResult {
145
- bot_type: number;
146
- bot_score: number;
147
- }
148
-
149
- export async function detectBot(
150
- headers: string,
151
- patterns_add: string,
152
- patterns_remove: string,
153
- ): Promise<BotResult> {
154
- const analyze = await init();
155
-
156
- if (typeof analyze !== "undefined") {
157
- return analyze.detectBot(headers, patterns_add, patterns_remove);
158
- } else {
159
- // TODO: Fallback to JS if we don't have WASM?
160
- return {
161
- bot_type: 1, // NOT_ANALYZED
162
- bot_score: 0,
163
- };
164
- }
165
- }
@@ -1,31 +0,0 @@
1
- // @generated by wasm2module - DO NOT EDIT
2
- /* tslint:disable */
3
- /* eslint-disable */
4
-
5
- /**
6
- * This file contains the Arcjet Wasm binary inlined as a base64
7
- * [Data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs)
8
- * with the application/wasm MIME type.
9
- *
10
- * This was chosen to save on storage space over inlining the file directly as
11
- * a Uint8Array, which would take up ~3x the space of the Wasm file. See
12
- * https://blobfolio.com/2019/better-binary-batter-mixing-base64-and-uint8array/
13
- * for more details.
14
- *
15
- * It is then decoded into an ArrayBuffer to be used directly via WebAssembly's
16
- * `compile()` function in our entry point file.
17
- *
18
- * This is all done to avoid trying to read or bundle the Wasm asset in various
19
- * ways based on the platform or bundler a user is targeting. One example being
20
- * that Next.js requires special `asyncWebAssembly` webpack config to load our
21
- * Wasm file if we don't do this.
22
- *
23
- * In the future, we hope to do away with this workaround when all bundlers
24
- * properly support consistent asset bundling techniques.
25
- */
26
-
27
- /**
28
- * Returns an ArrayBuffer for the Arcjet Wasm binary, decoded from a base64 Data
29
- * URL.
30
- */
31
- export function wasm(): Promise<ArrayBuffer>;