@ferscloud/fers-calculation-web 0.2.60 → 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 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
- - [Full documentation & getting started](https://ferscloud.com/getting-started)
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
- - [FERS_core Python package](https://pypi.org/project/fers-core/)
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
+ }
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.60",
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
  }