@ferscloud/fers-calculation 0.2.39 → 0.2.41

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
@@ -2,25 +2,82 @@
2
2
 
3
3
  High-performance structural engineering FEM solver compiled from Rust to WebAssembly. Runs entirely in the browser — no server round-trip per calculation.
4
4
 
5
+ > This README covers both published packages: **`@ferscloud/fers-calculation`** (Node.js / server-side, `--target nodejs`) and **`@ferscloud/fers-calculation-web`** (browser / bundler, `--target bundler`). The API is identical; only installation and bundler setup differ.
6
+
5
7
  ## Installation
6
8
 
7
9
  ```bash
10
+ # Browser apps (Vite, Next.js, webpack):
11
+ npm install @ferscloud/fers-calculation-web
12
+ # Node.js / server-side:
8
13
  npm install @ferscloud/fers-calculation
9
14
  ```
10
15
 
11
- ## Quick start — free tier (up to 100 members)
16
+ ## Bundler setup (browser build)
17
+
18
+ `@ferscloud/fers-calculation-web` is a WASM ES module that initialises via top-level `await`. Most bundlers need a one-time config:
19
+
20
+ **Vite**
21
+
22
+ ```bash
23
+ npm i -D vite-plugin-wasm vite-plugin-top-level-await
24
+ ```
12
25
 
13
26
  ```ts
14
- import init, { calculate_from_json } from "@ferscloud/fers-calculation";
27
+ // vite.config.ts
28
+ import wasm from "vite-plugin-wasm";
29
+ import topLevelAwait from "vite-plugin-top-level-await";
15
30
 
16
- await init(); // load the WASM module once
31
+ export default { plugins: [wasm(), topLevelAwait()] };
32
+ ```
17
33
 
18
- const result = calculate_from_json(JSON.stringify(myModel));
19
- const data = JSON.parse(result);
34
+ **Next.js / webpack**
35
+
36
+ ```js
37
+ // next.config.js
38
+ module.exports = {
39
+ transpilePackages: ["@ferscloud/fers-calculation-web"],
40
+ webpack(config) {
41
+ config.experiments = { ...config.experiments, asyncWebAssembly: true };
42
+ config.output.environment = { ...config.output.environment, asyncFunction: true };
43
+ return config;
44
+ },
45
+ };
46
+ ```
47
+
48
+ The solver is synchronous and CPU-bound; for large models run it inside a Web Worker so the UI thread stays responsive. The Node.js package (`@ferscloud/fers-calculation`) needs no bundler config.
49
+
50
+ ## Quick start — free tier (up to 100 members)
51
+
52
+ ```ts
53
+ import { calculate_from_json } from "@ferscloud/fers-calculation";
54
+
55
+ // No init() call needed — the nodejs and bundler builds initialise the
56
+ // WASM module automatically on import.
57
+ const res = JSON.parse(calculate_from_json(JSON.stringify(myModel)));
58
+ if (res.ok) {
59
+ const data = res.result; // displacements, member_results, unity_checks, …
60
+ } else {
61
+ console.error(res.error.code, res.error.message);
62
+ }
20
63
  ```
21
64
 
22
65
  No API key required. Works for any model with up to 100 members.
23
66
 
67
+ ## Response shape
68
+
69
+ Every solver call returns a JSON **envelope**, so you `JSON.parse` once and branch on `ok` — you never have to sniff whether the returned string "looks like" an error:
70
+
71
+ ```jsonc
72
+ // success
73
+ { "ok": true, "result": { /* the full result document */ } }
74
+ // failure (invalid model, over the member limit, malformed JSON, …)
75
+ { "ok": false, "error": { "code": "LimitExceeded",
76
+ "message": "Number of members (250) exceeds allowed maximum of 100" } }
77
+ ```
78
+
79
+ `error.code` is one of `InvalidJson`, `LimitExceeded`, `SolveError`, `InternalPanic`, `InternalSerialization`. The return value is **always** valid JSON.
80
+
24
81
  ## Authenticated tier — Pro (up to 10 000 members)
25
82
 
26
83
  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.
@@ -74,17 +131,16 @@ Same pattern works for Express, Deno, Bun, Cloudflare Workers, or any server-sid
74
131
  ### 3. Frontend: call the solver with the token
75
132
 
76
133
  ```ts
77
- import init, { calculate_from_json_with_token } from "@ferscloud/fers-calculation";
78
-
79
- await init();
134
+ import { calculate_from_json_with_token } from "@ferscloud/fers-calculation";
80
135
 
81
136
  const { token } = await fetch("/api/solve-token").then(r => r.json());
82
137
 
83
- const result = calculate_from_json_with_token(JSON.stringify(myModel), token);
84
- const data = JSON.parse(result);
138
+ const res = JSON.parse(calculate_from_json_with_token(JSON.stringify(myModel), token));
139
+ if (!res.ok) throw new Error(`${res.error.code}: ${res.error.message}`);
140
+ const data = res.result;
85
141
  ```
86
142
 
87
- If the token is missing, expired, or invalid, the solver falls back to the free 100-member limit — it never throws.
143
+ If the token is missing, expired, or invalid, the solver falls back to the free 100-member limit — it never throws (a genuine solve failure comes back as `{ ok: false, error }`, not an exception).
88
144
 
89
145
  ## Tier comparison
90
146
 
@@ -99,6 +155,16 @@ If the token is missing, expired, or invalid, the solver falls back to the free
99
155
 
100
156
  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
157
 
158
+ ## TypeScript types
159
+
160
+ The browser package ships generated model types alongside the function signatures:
161
+
162
+ ```ts
163
+ import type { FERS, ResultsBundle } from "@ferscloud/fers-calculation-web/fers-models";
164
+ ```
165
+
166
+ `FERS` is the input model; `ResultsBundle` is the `result` payload of a successful envelope. Both are generated from the engine's OpenAPI schema, so they track the published version.
167
+
102
168
  ## Links
103
169
 
104
170
  - [Full documentation & getting started](https://ferscloud.com/getting-started)
@@ -3,6 +3,7 @@
3
3
 
4
4
  /**
5
5
  * Free-tier solver (100-member limit). Used when no valid solve token is present.
6
+ * Returns the JSON envelope described above.
6
7
  */
7
8
  export function calculate_from_json(json_data: string): string;
8
9
 
@@ -10,15 +11,19 @@ export function calculate_from_json(json_data: string): string;
10
11
  * Tier-aware solver. Verifies the Ed25519-signed solve token issued by the
11
12
  * FERS Cloud server; grants Premium limits (10 000 members) when the token
12
13
  * is valid and contains `"tier":"premium"`. Falls back to Free on any
13
- * failure — expired, malformed, or wrong signature.
14
+ * failure — expired, malformed, or wrong signature. Returns the JSON envelope.
14
15
  */
15
16
  export function calculate_from_json_with_token(json_data: string, solve_token: string): string;
16
17
 
18
+ /**
19
+ * Parse (without solving) a model from a file path and return it as the JSON
20
+ * envelope: `{"ok":true,"result": <FERS JSON> }` or an error envelope.
21
+ */
17
22
  export function load_fers_from_file(path: string): string;
18
23
 
19
24
  /**
20
25
  * Re-render unity-check reports from already-solved results (no re-solve). Fills
21
26
  * each `rendered_report` from its check's `report_template` and rebuilds
22
- * `report_html`. Returns the error string on failure.
27
+ * `report_html`. Returns the JSON envelope.
23
28
  */
24
29
  export function render_reports_from_json(json_data: string): string;
@@ -2,6 +2,7 @@
2
2
 
3
3
  /**
4
4
  * Free-tier solver (100-member limit). Used when no valid solve token is present.
5
+ * Returns the JSON envelope described above.
5
6
  * @param {string} json_data
6
7
  * @returns {string}
7
8
  */
@@ -25,7 +26,7 @@ exports.calculate_from_json = calculate_from_json;
25
26
  * Tier-aware solver. Verifies the Ed25519-signed solve token issued by the
26
27
  * FERS Cloud server; grants Premium limits (10 000 members) when the token
27
28
  * is valid and contains `"tier":"premium"`. Falls back to Free on any
28
- * failure — expired, malformed, or wrong signature.
29
+ * failure — expired, malformed, or wrong signature. Returns the JSON envelope.
29
30
  * @param {string} json_data
30
31
  * @param {string} solve_token
31
32
  * @returns {string}
@@ -49,6 +50,8 @@ function calculate_from_json_with_token(json_data, solve_token) {
49
50
  exports.calculate_from_json_with_token = calculate_from_json_with_token;
50
51
 
51
52
  /**
53
+ * Parse (without solving) a model from a file path and return it as the JSON
54
+ * envelope: `{"ok":true,"result": <FERS JSON> }` or an error envelope.
52
55
  * @param {string} path
53
56
  * @returns {string}
54
57
  */
@@ -71,7 +74,7 @@ exports.load_fers_from_file = load_fers_from_file;
71
74
  /**
72
75
  * Re-render unity-check reports from already-solved results (no re-solve). Fills
73
76
  * each `rendered_report` from its check's `report_template` and rebuilds
74
- * `report_html`. Returns the error string on failure.
77
+ * `report_html`. Returns the JSON envelope.
75
78
  * @param {string} json_data
76
79
  * @returns {string}
77
80
  */
@@ -93,10 +96,10 @@ exports.render_reports_from_json = render_reports_from_json;
93
96
  function __wbg_get_imports() {
94
97
  const import0 = {
95
98
  __proto__: null,
96
- __wbg___wbindgen_throw_ea4887a5f8f9a9db: function(arg0, arg1) {
99
+ __wbg___wbindgen_throw_344f42d3211c4765: function(arg0, arg1) {
97
100
  throw new Error(getStringFromWasm0(arg0, arg1));
98
101
  },
99
- __wbg_now_d2e0afbad4edbe82: function() {
102
+ __wbg_now_86c0d4ba3fa605b8: function() {
100
103
  const ret = Date.now();
101
104
  return ret;
102
105
  },
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ferscloud/fers-calculation",
3
- "version": "0.2.39",
3
+ "version": "0.2.41",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/Jeroen124/FERS_calculations.git"