@ferscloud/fers-calculation 0.2.25 → 0.2.27
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 +100 -4
- package/fers_calculations.js +2 -2
- package/fers_calculations_bg.wasm +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,10 +1,106 @@
|
|
|
1
1
|
# @ferscloud/fers-calculation
|
|
2
2
|
|
|
3
|
-
High-performance structural
|
|
4
|
-
|
|
5
|
-
This package is the WebAssembly build of your Rust solver so it can be used from JavaScript and TypeScript (browser apps with a bundler, and in some Node.js setups). It is designed to take structured input (for example JSON) and return results efficiently.
|
|
3
|
+
High-performance structural engineering FEM solver compiled from Rust to WebAssembly. Runs entirely in the browser — no server round-trip per calculation.
|
|
6
4
|
|
|
7
5
|
## Installation
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
|
-
npm install @ferscloud/fers-calculation
|
|
8
|
+
npm install @ferscloud/fers-calculation
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start — free tier (up to 100 members)
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import init, { calculate_from_json } from "@ferscloud/fers-calculation";
|
|
15
|
+
|
|
16
|
+
await init(); // load the WASM module once
|
|
17
|
+
|
|
18
|
+
const result = calculate_from_json(JSON.stringify(myModel));
|
|
19
|
+
const data = JSON.parse(result);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
No API key required. Works for any model with up to 100 members.
|
|
23
|
+
|
|
24
|
+
## Authenticated tier — Pro (up to 10 000 members)
|
|
25
|
+
|
|
26
|
+
Pro limits are unlocked by passing a short-lived signed token issued by the FERS Cloud server. The token is verified inside the WASM using an Ed25519 public key baked into the binary — it cannot be forged.
|
|
27
|
+
|
|
28
|
+
### How it works
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
Your server → POST https://ferscloud.com/api/solver/token → signed 30-min token
|
|
32
|
+
(X-API-Key: <your-api-key>)
|
|
33
|
+
|
|
34
|
+
Browser → calculate_from_json_with_token(model, token) → Pro limits unlocked
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 1. Get an API key
|
|
38
|
+
|
|
39
|
+
Log in at [ferscloud.com](https://ferscloud.com), go to **Profile → API Keys**, and create a key. Store it as an environment variable on your server — never in browser code.
|
|
40
|
+
|
|
41
|
+
### 2. Backend: fetch a solve token
|
|
42
|
+
|
|
43
|
+
Your server fetches and caches the token. Example for a Next.js API route:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// pages/api/solve-token.ts
|
|
47
|
+
const FERS_API_KEY = process.env.FERS_API_KEY!;
|
|
48
|
+
|
|
49
|
+
let cached: { token: string; expiresAt: number } | null = null;
|
|
50
|
+
|
|
51
|
+
export default async function handler(req, res) {
|
|
52
|
+
const now = Date.now();
|
|
53
|
+
|
|
54
|
+
// Re-use if more than 5 minutes remain
|
|
55
|
+
if (cached && cached.expiresAt - now > 5 * 60 * 1000) {
|
|
56
|
+
return res.json({ token: cached.token });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const resp = await fetch("https://ferscloud.com/api/solver/token", {
|
|
60
|
+
method: "POST",
|
|
61
|
+
headers: { "X-API-Key": FERS_API_KEY },
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (!resp.ok) return res.status(502).json({ error: "Token fetch failed" });
|
|
65
|
+
|
|
66
|
+
const { token, expiresAt } = await resp.json();
|
|
67
|
+
cached = { token, expiresAt: new Date(expiresAt).getTime() };
|
|
68
|
+
return res.json({ token });
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Same pattern works for Express, Deno, Bun, Cloudflare Workers, or any server-side runtime.
|
|
73
|
+
|
|
74
|
+
### 3. Frontend: call the solver with the token
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import init, { calculate_from_json_with_token } from "@ferscloud/fers-calculation";
|
|
78
|
+
|
|
79
|
+
await init();
|
|
80
|
+
|
|
81
|
+
const { token } = await fetch("/api/solve-token").then(r => r.json());
|
|
82
|
+
|
|
83
|
+
const result = calculate_from_json_with_token(JSON.stringify(myModel), token);
|
|
84
|
+
const data = JSON.parse(result);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
If the token is missing, expired, or invalid, the solver falls back to the free 100-member limit — it never throws.
|
|
88
|
+
|
|
89
|
+
## Tier comparison
|
|
90
|
+
|
|
91
|
+
| Feature | Free | Pro |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| Max members | 100 | 10 000 |
|
|
94
|
+
| WASM function | `calculate_from_json` | `calculate_from_json_with_token` |
|
|
95
|
+
| Requires token | No | Yes |
|
|
96
|
+
| Token TTL | — | 30 minutes |
|
|
97
|
+
|
|
98
|
+
## Security note
|
|
99
|
+
|
|
100
|
+
Keep your `FERS_API_KEY` server-side only. The solve token it fetches is safe to pass to the browser — it is short-lived and cryptographically signed. Only FERS Cloud can issue valid tokens; the browser WASM can only verify them.
|
|
101
|
+
|
|
102
|
+
## Links
|
|
103
|
+
|
|
104
|
+
- [Full documentation & getting started](https://ferscloud.com/getting-started)
|
|
105
|
+
- [FERS Cloud](https://ferscloud.com)
|
|
106
|
+
- [FERS_core Python package](https://pypi.org/project/fers-core/)
|
package/fers_calculations.js
CHANGED
|
@@ -70,10 +70,10 @@ exports.load_fers_from_file = load_fers_from_file;
|
|
|
70
70
|
function __wbg_get_imports() {
|
|
71
71
|
const import0 = {
|
|
72
72
|
__proto__: null,
|
|
73
|
-
|
|
73
|
+
__wbg___wbindgen_throw_1506f2235d1bdba0: function(arg0, arg1) {
|
|
74
74
|
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
75
75
|
},
|
|
76
|
-
|
|
76
|
+
__wbg_now_190933fa139cc119: function() {
|
|
77
77
|
const ret = Date.now();
|
|
78
78
|
return ret;
|
|
79
79
|
},
|
|
Binary file
|