@ferscloud/fers-calculation-web 0.2.59 → 0.2.61
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 +25 -2
- package/badge.d.ts +33 -0
- package/badge.js +69 -0
- package/fers-models.d.ts +30 -1
- package/fers_calculations_bg.wasm +0 -0
- package/package.json +35 -3
package/README.md
CHANGED
|
@@ -185,8 +185,31 @@ const mr = res.result.results.loadcases["…"].member_results["1"];
|
|
|
185
185
|
|
|
186
186
|
Off by default to keep the payload lean; omitted from `member_results` when not requested.
|
|
187
187
|
|
|
188
|
+
## Attribution
|
|
189
|
+
|
|
190
|
+
Free-tier results carry an `attribution` object minted inside the solver.
|
|
191
|
+
Premium results (solved with a valid solve token) do not, so the same code
|
|
192
|
+
credits FERS on the free tier and white-labels on Pro:
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
import { fersAttributionHtml } from "@ferscloud/fers-calculation-web/badge";
|
|
196
|
+
|
|
197
|
+
// "" when the result came back from a Pro solve.
|
|
198
|
+
const credit = fersAttributionHtml(res);
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
`getFersAttribution`, `fersAttributionText` and `createFersBadge` are also
|
|
202
|
+
exported. All of them accept the envelope, the parsed model or the results
|
|
203
|
+
bundle, and all return nothing for a Pro result or an error envelope.
|
|
204
|
+
|
|
205
|
+
Using the free tier in an application? Please display the credit. It is the
|
|
206
|
+
only thing the free tier asks of you.
|
|
207
|
+
|
|
188
208
|
## Links
|
|
189
209
|
|
|
190
|
-
- [
|
|
210
|
+
- [Structural analysis in JavaScript](https://ferscloud.com/structural-analysis-javascript) — why run the solver client-side
|
|
211
|
+
- [JavaScript documentation](https://ferscloud.com/docs/javascript) — bundler setup, error codes, types, solve tokens
|
|
212
|
+
- [Full documentation](https://ferscloud.com/getting-started) — every route into FERS
|
|
213
|
+
- [llms-full.txt](https://ferscloud.com/llms-full.txt) — the whole documentation in one fetch, for agents
|
|
191
214
|
- [FERS Cloud](https://ferscloud.com)
|
|
192
|
-
- [
|
|
215
|
+
- [FERS Python package](https://pypi.org/project/fers/) — `pip install FERS`
|
package/badge.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Free-tier provenance stamp. Absent from Premium results. */
|
|
2
|
+
export interface FersAttribution {
|
|
3
|
+
/** Always "FERS". */
|
|
4
|
+
generated_by: string;
|
|
5
|
+
/** Canonical product URL. */
|
|
6
|
+
url: string;
|
|
7
|
+
/** Engine version that produced the results. */
|
|
8
|
+
engine_version: string;
|
|
9
|
+
/** Always "free" — Premium results carry no attribution at all. */
|
|
10
|
+
tier: string;
|
|
11
|
+
/** Plain-text credit. */
|
|
12
|
+
text: string;
|
|
13
|
+
/** Ready-to-inject HTML anchor. */
|
|
14
|
+
html: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Find the attribution object in a solver envelope, a parsed model, or a
|
|
19
|
+
* results bundle. Returns null for Premium results and for error envelopes.
|
|
20
|
+
*/
|
|
21
|
+
export function getFersAttribution(input: unknown): FersAttribution | null;
|
|
22
|
+
|
|
23
|
+
/** Ready-to-inject HTML anchor, or "" on Pro. */
|
|
24
|
+
export function fersAttributionHtml(input: unknown): string;
|
|
25
|
+
|
|
26
|
+
/** Plain-text credit, or "" on Pro. */
|
|
27
|
+
export function fersAttributionText(input: unknown): string;
|
|
28
|
+
|
|
29
|
+
/** A detached DOM element carrying the credit, or null on Pro. */
|
|
30
|
+
export function createFersBadge(
|
|
31
|
+
input: unknown,
|
|
32
|
+
doc?: Document,
|
|
33
|
+
): HTMLElement | null;
|
package/badge.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Attribution helpers for @ferscloud/fers-calculation-web.
|
|
2
|
+
//
|
|
3
|
+
// Free-tier results carry an `attribution` object minted inside the solver;
|
|
4
|
+
// Premium results (solved with a valid solve token) do not. Everything here
|
|
5
|
+
// returns nothing when the field is absent, so the same code shows a credit on
|
|
6
|
+
// the free tier and white-labels on Pro with no flag to set and no branch to
|
|
7
|
+
// write.
|
|
8
|
+
//
|
|
9
|
+
// Deliberately framework-free: a solver package should not drag in React. Use
|
|
10
|
+
// `fersAttributionHtml()` with your framework's raw-HTML escape hatch, or
|
|
11
|
+
// `createFersBadge()` if you would rather be handed a DOM node.
|
|
12
|
+
//
|
|
13
|
+
// Shipped only with the browser package. The Node build is server-side, where
|
|
14
|
+
// a badge has nothing to render into — read `attribution.text` directly there.
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Find the attribution object, accepting whichever shape you happen to hold:
|
|
18
|
+
* the solver envelope, the parsed model, or the results bundle itself.
|
|
19
|
+
* @returns {{generated_by: string, url: string, engine_version: string, tier: string, text: string, html: string} | null}
|
|
20
|
+
*/
|
|
21
|
+
export function getFersAttribution(input) {
|
|
22
|
+
if (!input || typeof input !== "object") return null;
|
|
23
|
+
// Envelope: { ok, result } — an error envelope has nothing to credit.
|
|
24
|
+
if ("ok" in input) return input.ok ? getFersAttribution(input.result) : null;
|
|
25
|
+
// Parsed model: { ..., results: ResultsBundle }
|
|
26
|
+
if (input.results) return getFersAttribution(input.results);
|
|
27
|
+
// Results bundle.
|
|
28
|
+
return input.attribution ?? null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Ready-to-inject HTML anchor, or "" on Pro. */
|
|
32
|
+
export function fersAttributionHtml(input) {
|
|
33
|
+
return getFersAttribution(input)?.html ?? "";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Plain-text credit, or "" on Pro. Use for text reports and console output. */
|
|
37
|
+
export function fersAttributionText(input) {
|
|
38
|
+
return getFersAttribution(input)?.text ?? "";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Build a detached DOM element carrying the credit, or null on Pro.
|
|
43
|
+
* @param {object} input solver envelope, model, or results bundle
|
|
44
|
+
* @param {Document} [doc] defaults to the global document
|
|
45
|
+
* @returns {HTMLElement | null}
|
|
46
|
+
*/
|
|
47
|
+
export function createFersBadge(input, doc) {
|
|
48
|
+
const attribution = getFersAttribution(input);
|
|
49
|
+
if (!attribution) return null;
|
|
50
|
+
|
|
51
|
+
const d = doc ?? (typeof document !== "undefined" ? document : null);
|
|
52
|
+
if (!d) return null;
|
|
53
|
+
|
|
54
|
+
const el = d.createElement("span");
|
|
55
|
+
el.className = "fers-attribution";
|
|
56
|
+
el.style.fontSize = "12px";
|
|
57
|
+
el.style.opacity = "0.75";
|
|
58
|
+
|
|
59
|
+
const a = d.createElement("a");
|
|
60
|
+
a.href = attribution.url;
|
|
61
|
+
a.target = "_blank";
|
|
62
|
+
a.rel = "noopener";
|
|
63
|
+
// textContent, not innerHTML: the string comes from the solver, but building
|
|
64
|
+
// the node by hand keeps this helper injection-proof by construction.
|
|
65
|
+
a.textContent = attribution.text;
|
|
66
|
+
|
|
67
|
+
el.appendChild(a);
|
|
68
|
+
return el;
|
|
69
|
+
}
|
package/fers-models.d.ts
CHANGED
|
@@ -56,6 +56,11 @@ export interface components {
|
|
|
56
56
|
AnalysisOptions: {
|
|
57
57
|
/** Format: double */
|
|
58
58
|
axial_slack?: number;
|
|
59
|
+
/**
|
|
60
|
+
* @description Declarative only; the solver always assembles the full 3D formulation.
|
|
61
|
+
* A planar model must restrain its out-of-plane DOFs at every node itself
|
|
62
|
+
* — see [`Dimensionality`].
|
|
63
|
+
*/
|
|
59
64
|
dimensionality: components["schemas"]["Dimensionality"];
|
|
60
65
|
/**
|
|
61
66
|
* @description When true, the engine generates self-weight (dead load) for every member
|
|
@@ -225,6 +230,16 @@ export interface components {
|
|
|
225
230
|
* results are reported in `results.buckling_runs` (with
|
|
226
231
|
* `results.buckling` carrying the first successful run for backward
|
|
227
232
|
* compatibility).
|
|
233
|
+
*
|
|
234
|
+
* **The eigenvalue is mesh-sensitive, unlike the rest of the bundle.**
|
|
235
|
+
* Reactions and the internal forces recovered along a member come out exact on
|
|
236
|
+
* one element for a straight prismatic member; α_cr does not. A buckling
|
|
237
|
+
* half-wave cannot form on a single cubic element — its consistent geometric
|
|
238
|
+
* stiffness gives `12EI/L²` against Euler's `π²EI/L²`, so α_cr comes out about
|
|
239
|
+
* **21 % high, which is unconservative**. Two elements per member are within
|
|
240
|
+
* 0.75 %, four within 0.05 %. Mesh compressed members into at least four
|
|
241
|
+
* elements; the solve stays in the millisecond range. A run left on one element
|
|
242
|
+
* raises `buckling_unrefined_mesh` in [`crate::models::results::modalresult::BucklingResults::warnings`].
|
|
228
243
|
*/
|
|
229
244
|
BucklingAnalysisSettings: {
|
|
230
245
|
/**
|
|
@@ -494,7 +509,21 @@ export interface components {
|
|
|
494
509
|
*/
|
|
495
510
|
DensityUnit: "kg/m3" | "kg/mm3";
|
|
496
511
|
/**
|
|
497
|
-
* @description
|
|
512
|
+
* @description **Declarative only — the solver does not branch on this.** The formulation
|
|
513
|
+
* is always the full 3D beam with 6 structural DOFs (plus warping) per node,
|
|
514
|
+
* whichever value is given.
|
|
515
|
+
*
|
|
516
|
+
* So a planar model is planar only because the caller made it so: it must
|
|
517
|
+
* restrain the out-of-plane DOFs — `Z`, `RX` and `RY` for an XY model — on
|
|
518
|
+
* **every node**, not just at the supports. Leave them free and the
|
|
519
|
+
* out-of-plane subsystem is unrestrained, which is either a singular stiffness
|
|
520
|
+
* matrix or, worse, a solve that succeeds with movement nobody asked for; see
|
|
521
|
+
* the `singular_model` diagnostic.
|
|
522
|
+
*
|
|
523
|
+
* The field is required because the payload has to carry something, and it is
|
|
524
|
+
* kept because dropping it would break every existing caller for no gain.
|
|
525
|
+
*
|
|
526
|
+
* Python:
|
|
498
527
|
* class Dimensionality(Enum):
|
|
499
528
|
* TWO_DIMENSIONAL = "2D"
|
|
500
529
|
* THREE_DIMENSIONAL = "3D"
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ferscloud/fers-calculation-web",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.61",
|
|
5
5
|
"license": "BSD-3-Clause",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -12,15 +12,47 @@
|
|
|
12
12
|
"fers_calculations.js",
|
|
13
13
|
"fers_calculations_bg.js",
|
|
14
14
|
"fers_calculations.d.ts",
|
|
15
|
-
"fers-models.d.ts"
|
|
15
|
+
"fers-models.d.ts",
|
|
16
|
+
"badge.js",
|
|
17
|
+
"badge.d.ts"
|
|
16
18
|
],
|
|
17
19
|
"main": "fers_calculations.js",
|
|
18
|
-
"homepage": "https://ferscloud.com",
|
|
20
|
+
"homepage": "https://ferscloud.com/structural-analysis-javascript",
|
|
19
21
|
"types": "fers_calculations.d.ts",
|
|
20
22
|
"sideEffects": [
|
|
21
23
|
"./fers_calculations.js",
|
|
22
24
|
"./snippets/*"
|
|
23
25
|
],
|
|
26
|
+
"description": "Structural analysis FEM solver for beams, frames and trusses, compiled from Rust to WebAssembly. Runs in the browser or in Node with no server round-trip. Includes Eurocode EN 1993-1-1 steel checks.",
|
|
27
|
+
"keywords": [
|
|
28
|
+
"structural-analysis",
|
|
29
|
+
"structural-engineering",
|
|
30
|
+
"finite-element",
|
|
31
|
+
"finite-element-analysis",
|
|
32
|
+
"fem",
|
|
33
|
+
"fea",
|
|
34
|
+
"solver",
|
|
35
|
+
"beam",
|
|
36
|
+
"frame",
|
|
37
|
+
"truss",
|
|
38
|
+
"stiffness-matrix",
|
|
39
|
+
"bending-moment",
|
|
40
|
+
"shear-force",
|
|
41
|
+
"deflection",
|
|
42
|
+
"buckling",
|
|
43
|
+
"eurocode",
|
|
44
|
+
"en1993",
|
|
45
|
+
"steel-design",
|
|
46
|
+
"wasm",
|
|
47
|
+
"webassembly",
|
|
48
|
+
"rust",
|
|
49
|
+
"engineering",
|
|
50
|
+
"civil-engineering",
|
|
51
|
+
"cad"
|
|
52
|
+
],
|
|
53
|
+
"bugs": {
|
|
54
|
+
"url": "https://github.com/Jeroen124/FERS_calculations/issues"
|
|
55
|
+
},
|
|
24
56
|
"publishConfig": {
|
|
25
57
|
"access": "public"
|
|
26
58
|
}
|