@forgecharts/sdk 1.5.10 → 1.5.12
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/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +176 -3
- package/dist/index.js.map +1 -1
- package/dist/internal.js +176 -3
- package/dist/internal.js.map +1 -1
- package/dist/licensing/LicenseManager.d.ts +54 -0
- package/dist/licensing/LicenseManager.d.ts.map +1 -1
- package/dist/licensing/__tests__/dataBlocking.test.d.ts +2 -0
- package/dist/licensing/__tests__/dataBlocking.test.d.ts.map +1 -0
- package/dist/react/canvas/ChartCanvas.d.ts.map +1 -1
- package/dist/react/canvas/LicenseRequiredOverlay.d.ts +20 -0
- package/dist/react/canvas/LicenseRequiredOverlay.d.ts.map +1 -0
- package/dist/react/hooks/useHostLicense.d.ts +17 -0
- package/dist/react/hooks/useHostLicense.d.ts.map +1 -0
- package/dist/react/hooks/useLicenseDataBlocked.d.ts +15 -0
- package/dist/react/hooks/useLicenseDataBlocked.d.ts.map +1 -0
- package/dist/react/index.d.ts +4 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +176 -3
- package/dist/react/index.js.map +1 -1
- package/dist/react/internal.js +176 -3
- package/dist/react/internal.js.map +1 -1
- package/package.json +1 -1
package/dist/internal.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TextStyle, Application, Container, Graphics, Text, FillGradient } from 'pixi.js';
|
|
2
2
|
import { forwardRef, useRef, useState, useImperativeHandle, useEffect, useCallback, createContext, useMemo, useContext } from 'react';
|
|
3
|
-
import ReactDOM from 'react-dom';
|
|
4
3
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
import ReactDOM from 'react-dom';
|
|
5
5
|
|
|
6
6
|
// src/core/CanvasLayer.ts
|
|
7
7
|
var CanvasLayer = class {
|
|
@@ -10800,6 +10800,8 @@ var LicenseManager = class _LicenseManager {
|
|
|
10800
10800
|
static instance = null;
|
|
10801
10801
|
payload = null;
|
|
10802
10802
|
status = "idle";
|
|
10803
|
+
failureKind = null;
|
|
10804
|
+
hostState = "unknown";
|
|
10803
10805
|
subscribers = /* @__PURE__ */ new Set();
|
|
10804
10806
|
constructor() {
|
|
10805
10807
|
}
|
|
@@ -10850,6 +10852,7 @@ var LicenseManager = class _LicenseManager {
|
|
|
10850
10852
|
}
|
|
10851
10853
|
this.status = "pending";
|
|
10852
10854
|
this.notify();
|
|
10855
|
+
let failureKind = "unreachable";
|
|
10853
10856
|
let data;
|
|
10854
10857
|
try {
|
|
10855
10858
|
const res = await fetch(verifyUrl, {
|
|
@@ -10858,15 +10861,18 @@ var LicenseManager = class _LicenseManager {
|
|
|
10858
10861
|
body: JSON.stringify({ licenseKey: key.trim().toUpperCase() })
|
|
10859
10862
|
});
|
|
10860
10863
|
if (!res.ok) {
|
|
10864
|
+
failureKind = res.status >= 400 && res.status < 500 ? "invalid" : "unreachable";
|
|
10861
10865
|
throw new Error(`License server error: ${res.status} ${res.statusText}`);
|
|
10862
10866
|
}
|
|
10863
10867
|
data = await res.json();
|
|
10864
10868
|
if (!data.valid) {
|
|
10869
|
+
failureKind = "invalid";
|
|
10865
10870
|
throw new Error(data.reason ?? "License invalid");
|
|
10866
10871
|
}
|
|
10867
10872
|
} catch (err) {
|
|
10868
10873
|
this.payload = null;
|
|
10869
10874
|
this.status = "failed";
|
|
10875
|
+
this.failureKind = failureKind;
|
|
10870
10876
|
this.notify();
|
|
10871
10877
|
throw err;
|
|
10872
10878
|
}
|
|
@@ -10884,6 +10890,7 @@ var LicenseManager = class _LicenseManager {
|
|
|
10884
10890
|
const payload = this.#applyPolicyPipeline(raw);
|
|
10885
10891
|
this.payload = payload;
|
|
10886
10892
|
this.status = "valid";
|
|
10893
|
+
this.failureKind = null;
|
|
10887
10894
|
this.notify();
|
|
10888
10895
|
return payload;
|
|
10889
10896
|
}
|
|
@@ -10891,6 +10898,7 @@ var LicenseManager = class _LicenseManager {
|
|
|
10891
10898
|
loadLicense(payload) {
|
|
10892
10899
|
this.payload = this.#applyPolicyPipeline(payload);
|
|
10893
10900
|
this.status = "valid";
|
|
10901
|
+
this.failureKind = null;
|
|
10894
10902
|
this.notify();
|
|
10895
10903
|
}
|
|
10896
10904
|
/** Where the license is in its validation lifecycle. */
|
|
@@ -10906,6 +10914,43 @@ var LicenseManager = class _LicenseManager {
|
|
|
10906
10914
|
isLockedDown() {
|
|
10907
10915
|
return this.status === "pending" || this.status === "failed";
|
|
10908
10916
|
}
|
|
10917
|
+
/** Why the last validation failed, or null if it did not fail. */
|
|
10918
|
+
getFailureKind() {
|
|
10919
|
+
return this.status === "failed" ? this.failureKind : null;
|
|
10920
|
+
}
|
|
10921
|
+
/**
|
|
10922
|
+
* True when MARKET DATA must be withheld — i.e. the licence server gave a
|
|
10923
|
+
* definitive negative.
|
|
10924
|
+
*
|
|
10925
|
+
* Deliberately narrower than `isLockedDown()`. Hiding a button on an
|
|
10926
|
+
* ambiguous failure is cheap; blanking a live trading chart is not. So this
|
|
10927
|
+
* stays false while a verify is in flight and false when the server was
|
|
10928
|
+
* unreachable — only an outright rejection blocks data.
|
|
10929
|
+
*
|
|
10930
|
+
* 'idle' is also false: a host that never calls validateLicense (tests, the
|
|
10931
|
+
* unmanaged SDK path) keeps working exactly as before.
|
|
10932
|
+
*/
|
|
10933
|
+
isDataBlocked() {
|
|
10934
|
+
if (this.hostState === "unlicensed") return true;
|
|
10935
|
+
if (this.hostState === "licensed") return false;
|
|
10936
|
+
return this.status === "failed" && this.failureKind === "invalid";
|
|
10937
|
+
}
|
|
10938
|
+
/** What the host deployment reports about its own licence. */
|
|
10939
|
+
getHostLicenseState() {
|
|
10940
|
+
return this.hostState;
|
|
10941
|
+
}
|
|
10942
|
+
/**
|
|
10943
|
+
* Record the host deployment's answer from GET /api/license.
|
|
10944
|
+
*
|
|
10945
|
+
* Pass 'unlicensed' ONLY when the host answered and said it has no licence.
|
|
10946
|
+
* A network failure, missing apiUrl, or non-OK response must pass 'unknown',
|
|
10947
|
+
* otherwise an outage would blank every chart the deployment serves.
|
|
10948
|
+
*/
|
|
10949
|
+
setHostLicenseState(state) {
|
|
10950
|
+
if (this.hostState === state) return;
|
|
10951
|
+
this.hostState = state;
|
|
10952
|
+
this.notify();
|
|
10953
|
+
}
|
|
10909
10954
|
/**
|
|
10910
10955
|
* Runs a raw/legacy/partial payload through `migrateLegacyPayload` (fills
|
|
10911
10956
|
* missing productTier/capabilities/schemaVersion, deterministically, with
|
|
@@ -10964,6 +11009,8 @@ var LicenseManager = class _LicenseManager {
|
|
|
10964
11009
|
clear() {
|
|
10965
11010
|
this.payload = null;
|
|
10966
11011
|
this.status = "idle";
|
|
11012
|
+
this.failureKind = null;
|
|
11013
|
+
this.hostState = "unknown";
|
|
10967
11014
|
this.notify();
|
|
10968
11015
|
}
|
|
10969
11016
|
};
|
|
@@ -18257,6 +18304,126 @@ function useChartCapabilities(config) {
|
|
|
18257
18304
|
}, []);
|
|
18258
18305
|
return useMemo(() => applyRuntimeConfig(licCaps), [licCaps, config]);
|
|
18259
18306
|
}
|
|
18307
|
+
function useLicenseDataBlocked() {
|
|
18308
|
+
const [blocked, setBlocked] = useState(
|
|
18309
|
+
() => LicenseManager.getInstance().isDataBlocked()
|
|
18310
|
+
);
|
|
18311
|
+
useEffect(() => {
|
|
18312
|
+
const lm = LicenseManager.getInstance();
|
|
18313
|
+
setBlocked(lm.isDataBlocked());
|
|
18314
|
+
return lm.subscribe(() => setBlocked(lm.isDataBlocked()));
|
|
18315
|
+
}, []);
|
|
18316
|
+
return blocked;
|
|
18317
|
+
}
|
|
18318
|
+
function useHostLicense(apiUrl, getAuthToken) {
|
|
18319
|
+
useEffect(() => {
|
|
18320
|
+
if (!apiUrl) return;
|
|
18321
|
+
let cancelled = false;
|
|
18322
|
+
const lm = LicenseManager.getInstance();
|
|
18323
|
+
void (async () => {
|
|
18324
|
+
try {
|
|
18325
|
+
const headers = {};
|
|
18326
|
+
if (getAuthToken) {
|
|
18327
|
+
try {
|
|
18328
|
+
const tok = await getAuthToken();
|
|
18329
|
+
if (tok) headers["Authorization"] = `Bearer ${tok}`;
|
|
18330
|
+
} catch {
|
|
18331
|
+
}
|
|
18332
|
+
}
|
|
18333
|
+
const res = await fetch(`${apiUrl.replace(/\/+$/, "")}/api/license`, { headers });
|
|
18334
|
+
if (cancelled) return;
|
|
18335
|
+
if (!res.ok) {
|
|
18336
|
+
lm.setHostLicenseState("unknown");
|
|
18337
|
+
return;
|
|
18338
|
+
}
|
|
18339
|
+
const data = await res.json();
|
|
18340
|
+
if (cancelled) return;
|
|
18341
|
+
if (data.licensePayload && typeof data.licensePayload === "object") {
|
|
18342
|
+
lm.loadLicense(data.licensePayload);
|
|
18343
|
+
lm.setHostLicenseState("licensed");
|
|
18344
|
+
} else {
|
|
18345
|
+
lm.setHostLicenseState("unlicensed");
|
|
18346
|
+
}
|
|
18347
|
+
} catch {
|
|
18348
|
+
if (!cancelled) lm.setHostLicenseState("unknown");
|
|
18349
|
+
}
|
|
18350
|
+
})();
|
|
18351
|
+
return () => {
|
|
18352
|
+
cancelled = true;
|
|
18353
|
+
};
|
|
18354
|
+
}, [apiUrl, getAuthToken]);
|
|
18355
|
+
}
|
|
18356
|
+
function LicenseRequiredOverlay({
|
|
18357
|
+
reason,
|
|
18358
|
+
onOpenLicenseSettings
|
|
18359
|
+
}) {
|
|
18360
|
+
return /* @__PURE__ */ jsxs(
|
|
18361
|
+
"div",
|
|
18362
|
+
{
|
|
18363
|
+
role: "alert",
|
|
18364
|
+
"data-testid": "fc-license-required",
|
|
18365
|
+
style: {
|
|
18366
|
+
position: "absolute",
|
|
18367
|
+
inset: 0,
|
|
18368
|
+
zIndex: 100,
|
|
18369
|
+
background: "rgba(0,0,0,0.6)",
|
|
18370
|
+
backdropFilter: "blur(4px)",
|
|
18371
|
+
display: "flex",
|
|
18372
|
+
flexDirection: "column",
|
|
18373
|
+
alignItems: "center",
|
|
18374
|
+
justifyContent: "center",
|
|
18375
|
+
gap: 12,
|
|
18376
|
+
// Swallow interaction: no crosshair or drawing on a blocked chart.
|
|
18377
|
+
pointerEvents: "auto"
|
|
18378
|
+
},
|
|
18379
|
+
children: [
|
|
18380
|
+
/* @__PURE__ */ jsxs(
|
|
18381
|
+
"svg",
|
|
18382
|
+
{
|
|
18383
|
+
viewBox: "0 0 24 24",
|
|
18384
|
+
width: "40",
|
|
18385
|
+
height: "40",
|
|
18386
|
+
fill: "none",
|
|
18387
|
+
stroke: "rgba(255,255,255,0.7)",
|
|
18388
|
+
strokeWidth: "1.8",
|
|
18389
|
+
strokeLinecap: "round",
|
|
18390
|
+
strokeLinejoin: "round",
|
|
18391
|
+
"aria-hidden": "true",
|
|
18392
|
+
children: [
|
|
18393
|
+
/* @__PURE__ */ jsx("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2" }),
|
|
18394
|
+
/* @__PURE__ */ jsx("path", { d: "M7 11V7a5 5 0 0110 0v4" })
|
|
18395
|
+
]
|
|
18396
|
+
}
|
|
18397
|
+
),
|
|
18398
|
+
/* @__PURE__ */ jsx("div", { style: { color: "#fff", fontWeight: 700, fontSize: 18, letterSpacing: "0.01em" }, children: "Unlicensed" }),
|
|
18399
|
+
/* @__PURE__ */ jsxs("div", { style: { color: "rgba(255,255,255,0.65)", fontSize: 13, textAlign: "center", maxWidth: 340 }, children: [
|
|
18400
|
+
"Please activate your license in the admin studio.",
|
|
18401
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
18402
|
+
"Market data is unavailable until a valid license is installed."
|
|
18403
|
+
] }),
|
|
18404
|
+
reason && /* @__PURE__ */ jsx("div", { style: { color: "rgba(255,255,255,0.45)", fontSize: 12, fontStyle: "italic" }, children: reason }),
|
|
18405
|
+
onOpenLicenseSettings && /* @__PURE__ */ jsx(
|
|
18406
|
+
"button",
|
|
18407
|
+
{
|
|
18408
|
+
onClick: onOpenLicenseSettings,
|
|
18409
|
+
style: {
|
|
18410
|
+
marginTop: 4,
|
|
18411
|
+
padding: "8px 16px",
|
|
18412
|
+
borderRadius: 8,
|
|
18413
|
+
border: "1px solid rgba(255,255,255,0.25)",
|
|
18414
|
+
background: "rgba(255,255,255,0.12)",
|
|
18415
|
+
color: "#fff",
|
|
18416
|
+
fontSize: 13,
|
|
18417
|
+
fontWeight: 600,
|
|
18418
|
+
cursor: "pointer"
|
|
18419
|
+
},
|
|
18420
|
+
children: "Open license settings"
|
|
18421
|
+
}
|
|
18422
|
+
)
|
|
18423
|
+
]
|
|
18424
|
+
}
|
|
18425
|
+
);
|
|
18426
|
+
}
|
|
18260
18427
|
|
|
18261
18428
|
// src/react/assets/logo_dark.png
|
|
18262
18429
|
var logo_dark_default = "data:image/png;base64,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";
|
|
@@ -22764,6 +22931,8 @@ var ChartCanvas = forwardRef(
|
|
|
22764
22931
|
const [bars, setBars] = useState([]);
|
|
22765
22932
|
const [panes, setPanes] = useState([]);
|
|
22766
22933
|
const capabilities = useChartCapabilities();
|
|
22934
|
+
const dataBlocked = useLicenseDataBlocked();
|
|
22935
|
+
useHostLicense(apiUrl, getAuthToken);
|
|
22767
22936
|
const [indicators, setIndicators] = useState([]);
|
|
22768
22937
|
const [totalHeight, setTotalHeight] = useState(600);
|
|
22769
22938
|
const [activeTool, setActiveTool] = useState(initialActiveTool ?? "cursor");
|
|
@@ -22884,7 +23053,10 @@ var ChartCanvas = forwardRef(
|
|
|
22884
23053
|
symbol,
|
|
22885
23054
|
interval: timeframe,
|
|
22886
23055
|
theme,
|
|
22887
|
-
|
|
23056
|
+
// Withhold the datafeed entirely rather than covering the canvas: an
|
|
23057
|
+
// unlicensed deployment should make no market-data requests at all, and
|
|
23058
|
+
// there must be nothing behind the overlay to reveal.
|
|
23059
|
+
...datafeed !== void 0 && !dataBlocked ? { datafeed } : {},
|
|
22888
23060
|
...renderBackend !== void 0 ? { renderBackend } : {}
|
|
22889
23061
|
});
|
|
22890
23062
|
for (const config of initialIndicators) {
|
|
@@ -23028,7 +23200,7 @@ var ChartCanvas = forwardRef(
|
|
|
23028
23200
|
transformRef.current = null;
|
|
23029
23201
|
delete window.__chart;
|
|
23030
23202
|
};
|
|
23031
|
-
}, []);
|
|
23203
|
+
}, [dataBlocked]);
|
|
23032
23204
|
useEffect(() => {
|
|
23033
23205
|
chartRef.current?.setSymbol(symbol);
|
|
23034
23206
|
}, [symbol]);
|
|
@@ -23889,6 +24061,7 @@ var ChartCanvas = forwardRef(
|
|
|
23889
24061
|
overflow: "hidden"
|
|
23890
24062
|
},
|
|
23891
24063
|
children: [
|
|
24064
|
+
dataBlocked && /* @__PURE__ */ jsx(LicenseRequiredOverlay, {}),
|
|
23892
24065
|
/* @__PURE__ */ jsx(
|
|
23893
24066
|
LeftToolbar,
|
|
23894
24067
|
{
|