@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
|
@@ -21,11 +21,40 @@ import type { CapabilitySet, LegacyPayloadShape, ProductTier } from './capabilit
|
|
|
21
21
|
* a failed verify must never yield more than a valid one.
|
|
22
22
|
*/
|
|
23
23
|
export type LicenseValidationStatus = 'idle' | 'pending' | 'valid' | 'failed';
|
|
24
|
+
/**
|
|
25
|
+
* WHY a validation failed. Gating features is the same either way — a failed
|
|
26
|
+
* verify never grants more than a valid one — but withholding MARKET DATA is
|
|
27
|
+
* not: blanking a live trading chart because the licence server had a blip
|
|
28
|
+
* would be far worse than briefly showing data to an unlicensed user.
|
|
29
|
+
*
|
|
30
|
+
* 'invalid' — the server answered and rejected the key (bad, revoked,
|
|
31
|
+
* expired). A definitive negative; safe to block data.
|
|
32
|
+
* 'unreachable' — network error, timeout, or a 5xx from the licence server.
|
|
33
|
+
* We do NOT know the licence is bad, so data keeps flowing.
|
|
34
|
+
*/
|
|
35
|
+
export type LicenseFailureKind = 'invalid' | 'unreachable';
|
|
36
|
+
/**
|
|
37
|
+
* What the HOST DEPLOYMENT says about its own licence, via GET /api/license.
|
|
38
|
+
*
|
|
39
|
+
* This is the authoritative answer for a self-hosted Kit: the operator installs
|
|
40
|
+
* a key in Admin Studio, and every chart served by that deployment inherits it.
|
|
41
|
+
* A client-side key is only a hint by comparison — the deployment's own answer
|
|
42
|
+
* is what decides whether it is licensed.
|
|
43
|
+
*
|
|
44
|
+
* 'licensed' — the host returned a licence payload.
|
|
45
|
+
* 'unlicensed' — the host answered and said it has NO licence. Definitive.
|
|
46
|
+
* 'unknown' — not asked yet, no host configured, or the host was
|
|
47
|
+
* unreachable. Never blocks: an embed with no host, or a
|
|
48
|
+
* momentary outage, must not blank a live chart.
|
|
49
|
+
*/
|
|
50
|
+
export type HostLicenseState = 'licensed' | 'unlicensed' | 'unknown';
|
|
24
51
|
export declare class LicenseManager {
|
|
25
52
|
#private;
|
|
26
53
|
private static instance;
|
|
27
54
|
private payload;
|
|
28
55
|
private status;
|
|
56
|
+
private failureKind;
|
|
57
|
+
private hostState;
|
|
29
58
|
private readonly subscribers;
|
|
30
59
|
private constructor();
|
|
31
60
|
/**
|
|
@@ -61,6 +90,31 @@ export declare class LicenseManager {
|
|
|
61
90
|
* "omitted = allowed" defaults.
|
|
62
91
|
*/
|
|
63
92
|
isLockedDown(): boolean;
|
|
93
|
+
/** Why the last validation failed, or null if it did not fail. */
|
|
94
|
+
getFailureKind(): LicenseFailureKind | null;
|
|
95
|
+
/**
|
|
96
|
+
* True when MARKET DATA must be withheld — i.e. the licence server gave a
|
|
97
|
+
* definitive negative.
|
|
98
|
+
*
|
|
99
|
+
* Deliberately narrower than `isLockedDown()`. Hiding a button on an
|
|
100
|
+
* ambiguous failure is cheap; blanking a live trading chart is not. So this
|
|
101
|
+
* stays false while a verify is in flight and false when the server was
|
|
102
|
+
* unreachable — only an outright rejection blocks data.
|
|
103
|
+
*
|
|
104
|
+
* 'idle' is also false: a host that never calls validateLicense (tests, the
|
|
105
|
+
* unmanaged SDK path) keeps working exactly as before.
|
|
106
|
+
*/
|
|
107
|
+
isDataBlocked(): boolean;
|
|
108
|
+
/** What the host deployment reports about its own licence. */
|
|
109
|
+
getHostLicenseState(): HostLicenseState;
|
|
110
|
+
/**
|
|
111
|
+
* Record the host deployment's answer from GET /api/license.
|
|
112
|
+
*
|
|
113
|
+
* Pass 'unlicensed' ONLY when the host answered and said it has no licence.
|
|
114
|
+
* A network failure, missing apiUrl, or non-OK response must pass 'unknown',
|
|
115
|
+
* otherwise an outage would blank every chart the deployment serves.
|
|
116
|
+
*/
|
|
117
|
+
setHostLicenseState(state: HostLicenseState): void;
|
|
64
118
|
/** Return the currently loaded payload, or null if none. */
|
|
65
119
|
getLicense(): LicensePayload | null;
|
|
66
120
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LicenseManager.d.ts","sourceRoot":"","sources":["../../src/licensing/LicenseManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAe,MAAM,gBAAgB,CAAC;AAEhG,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AASzF;;;;;;;;GAQG;AACH;;;;;;;;;;GAUG;AACH,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE9E,qBAAa,cAAc;;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA+B;IAEtD,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;IAE1D,OAAO;IAEP;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAKrC,OAAO,CAAC,MAAM;IAMd,MAAM,CAAC,WAAW,IAAI,cAAc;IAepC;;;;;;OAMG;IACG,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"LicenseManager.d.ts","sourceRoot":"","sources":["../../src/licensing/LicenseManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAe,MAAM,gBAAgB,CAAC;AAEhG,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AASzF;;;;;;;;GAQG;AACH;;;;;;;;;;GAUG;AACH,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE9E;;;;;;;;;;GAUG;AACH,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,aAAa,CAAC;AAE3D;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC;AAErE,qBAAa,cAAc;;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA+B;IAEtD,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;IAE1D,OAAO;IAEP;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAKrC,OAAO,CAAC,MAAM;IAMd,MAAM,CAAC,WAAW,IAAI,cAAc;IAepC;;;;;;OAMG;IACG,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA6E9E,gJAAgJ;IAChJ,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAO9C,wDAAwD;IACxD,mBAAmB,IAAI,uBAAuB;IAI9C;;;;;OAKG;IACH,YAAY,IAAI,OAAO;IAIvB,kEAAkE;IAClE,cAAc,IAAI,kBAAkB,GAAG,IAAI;IAI3C;;;;;;;;;;;OAWG;IACH,aAAa,IAAI,OAAO;IAgBxB,8DAA8D;IAC9D,mBAAmB,IAAI,gBAAgB;IAIvC;;;;;;OAMG;IACH,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAsBlD,4DAA4D;IAC5D,UAAU,IAAI,cAAc,GAAG,IAAI;IAInC;;;;OAIG;IACH,OAAO,IAAI,WAAW;IAItB,uDAAuD;IACvD,WAAW,IAAI,eAAe;IAI9B,yEAAyE;IACzE,UAAU,CAAC,IAAI,EAAE,MAAM,eAAe,GAAG,OAAO;IAIhD;;;;OAIG;IACH,cAAc,IAAI,WAAW;IAI7B;;;OAGG;IACH,eAAe,IAAI,aAAa;IAIhC,4EAA4E;IAC5E,aAAa,CAAC,IAAI,EAAE,MAAM,aAAa,GAAG,OAAO;IAIjD,8FAA8F;IAC9F,KAAK,IAAI,IAAI;CAOd"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataBlocking.test.d.ts","sourceRoot":"","sources":["../../../src/licensing/__tests__/dataBlocking.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChartCanvas.d.ts","sourceRoot":"","sources":["../../../src/react/canvas/ChartCanvas.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"ChartCanvas.d.ts","sourceRoot":"","sources":["../../../src/react/canvas/ChartCanvas.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unlicensed overlay — blocks the chart area when there is no valid licence.
|
|
3
|
+
*
|
|
4
|
+
* Restores the overlay that lived in apps/frontend/src/App.tsx until 6e718ac,
|
|
5
|
+
* moved into the SDK so every embedder gets it rather than only the legacy
|
|
6
|
+
* chart app. Same visual language as the original: blurred scrim, padlock,
|
|
7
|
+
* and a pointer to Admin Studio.
|
|
8
|
+
*
|
|
9
|
+
* ChartCanvas also withholds the datafeed while blocked, so there is no market
|
|
10
|
+
* data behind this — it states the situation rather than merely hiding it.
|
|
11
|
+
*/
|
|
12
|
+
export interface LicenseRequiredOverlayProps {
|
|
13
|
+
/** Reason text from the licence server, when it gave one. */
|
|
14
|
+
reason?: string | undefined;
|
|
15
|
+
/** Optional action, e.g. open the host's licence settings. */
|
|
16
|
+
onOpenLicenseSettings?: (() => void) | undefined;
|
|
17
|
+
}
|
|
18
|
+
export declare function LicenseRequiredOverlay({ reason, onOpenLicenseSettings, }: LicenseRequiredOverlayProps): import("react").JSX.Element;
|
|
19
|
+
export default LicenseRequiredOverlay;
|
|
20
|
+
//# sourceMappingURL=LicenseRequiredOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LicenseRequiredOverlay.d.ts","sourceRoot":"","sources":["../../../src/react/canvas/LicenseRequiredOverlay.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,2BAA2B;IAC1C,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,8DAA8D;IAC9D,qBAAqB,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;CAClD;AAED,wBAAgB,sBAAsB,CAAC,EACrC,MAAM,EACN,qBAAqB,GACtB,EAAE,2BAA2B,+BAwD7B;AAED,eAAe,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the HOST DEPLOYMENT's licence from `GET {apiUrl}/api/license`.
|
|
3
|
+
*
|
|
4
|
+
* For a self-hosted Kit this is the authoritative answer: the operator installs
|
|
5
|
+
* a key in Admin Studio and every chart the deployment serves inherits it. A
|
|
6
|
+
* client-side key is a hint by comparison.
|
|
7
|
+
*
|
|
8
|
+
* Three outcomes, and the distinction matters:
|
|
9
|
+
* payload returned -> 'licensed', and the payload is loaded so capabilities apply
|
|
10
|
+
* {licensePayload:null} -> 'unlicensed'. The host ANSWERED and said it holds no
|
|
11
|
+
* licence, so charts are blocked.
|
|
12
|
+
* anything else -> 'unknown'. No apiUrl, network failure, non-OK response
|
|
13
|
+
* or unparseable body. Never blocks — an outage must not
|
|
14
|
+
* blank every chart the deployment serves.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useHostLicense(apiUrl?: string, getAuthToken?: (() => string | Promise<string>) | undefined): void;
|
|
17
|
+
//# sourceMappingURL=useHostLicense.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useHostLicense.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useHostLicense.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,MAAM,CAAC,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,GAC1D,IAAI,CA2CN"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when market data must be withheld because the licence server gave a
|
|
3
|
+
* definitive negative (explicit rejection or 4xx).
|
|
4
|
+
*
|
|
5
|
+
* Deliberately narrow — see LicenseManager.isDataBlocked(). It stays FALSE
|
|
6
|
+
* while a verify is in flight and false when the server was unreachable, so a
|
|
7
|
+
* licence-server blip never blanks a live trading chart; only an outright
|
|
8
|
+
* rejection does. It is also false for hosts that never validate at all, which
|
|
9
|
+
* keeps the unmanaged SDK path and tests working unchanged.
|
|
10
|
+
*
|
|
11
|
+
* Re-renders whenever licence state changes, so installing a valid key
|
|
12
|
+
* restores the chart without a reload.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useLicenseDataBlocked(): boolean;
|
|
15
|
+
//# sourceMappingURL=useLicenseDataBlocked.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLicenseDataBlocked.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useLicenseDataBlocked.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAc/C"}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -20,6 +20,10 @@
|
|
|
20
20
|
*/
|
|
21
21
|
export { ChartCanvas } from './canvas/ChartCanvas';
|
|
22
22
|
export type { ChartCanvasHandle, ChartCanvasProps } from './canvas/ChartCanvas';
|
|
23
|
+
export { LicenseRequiredOverlay } from './canvas/LicenseRequiredOverlay';
|
|
24
|
+
export type { LicenseRequiredOverlayProps } from './canvas/LicenseRequiredOverlay';
|
|
25
|
+
export { useLicenseDataBlocked } from './hooks/useLicenseDataBlocked';
|
|
26
|
+
export { useHostLicense } from './hooks/useHostLicense';
|
|
23
27
|
export { ChartWorkspace } from './workspace/ChartWorkspace';
|
|
24
28
|
export type { ChartWorkspaceProps, TabItem, TradingSession } from './workspace/ChartWorkspace';
|
|
25
29
|
export { useChartCapabilities } from './hooks/useChartCapabilities';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,YAAY,EAAE,mBAAmB,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG/F,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGpE,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAI9D,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG9E,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC3G,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC9D,YAAY,EACV,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,QAAQ,GACT,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,YAAY,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAGxD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,YAAY,EAAE,mBAAmB,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG/F,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGpE,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAI9D,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG9E,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC3G,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC9D,YAAY,EACV,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,QAAQ,GACT,MAAM,oBAAoB,CAAC"}
|
package/dist/react/index.js
CHANGED
|
@@ -10734,6 +10734,8 @@ var LicenseManager = class _LicenseManager {
|
|
|
10734
10734
|
static instance = null;
|
|
10735
10735
|
payload = null;
|
|
10736
10736
|
status = "idle";
|
|
10737
|
+
failureKind = null;
|
|
10738
|
+
hostState = "unknown";
|
|
10737
10739
|
subscribers = /* @__PURE__ */ new Set();
|
|
10738
10740
|
constructor() {
|
|
10739
10741
|
}
|
|
@@ -10784,6 +10786,7 @@ var LicenseManager = class _LicenseManager {
|
|
|
10784
10786
|
}
|
|
10785
10787
|
this.status = "pending";
|
|
10786
10788
|
this.notify();
|
|
10789
|
+
let failureKind = "unreachable";
|
|
10787
10790
|
let data;
|
|
10788
10791
|
try {
|
|
10789
10792
|
const res = await fetch(verifyUrl, {
|
|
@@ -10792,15 +10795,18 @@ var LicenseManager = class _LicenseManager {
|
|
|
10792
10795
|
body: JSON.stringify({ licenseKey: key.trim().toUpperCase() })
|
|
10793
10796
|
});
|
|
10794
10797
|
if (!res.ok) {
|
|
10798
|
+
failureKind = res.status >= 400 && res.status < 500 ? "invalid" : "unreachable";
|
|
10795
10799
|
throw new Error(`License server error: ${res.status} ${res.statusText}`);
|
|
10796
10800
|
}
|
|
10797
10801
|
data = await res.json();
|
|
10798
10802
|
if (!data.valid) {
|
|
10803
|
+
failureKind = "invalid";
|
|
10799
10804
|
throw new Error(data.reason ?? "License invalid");
|
|
10800
10805
|
}
|
|
10801
10806
|
} catch (err) {
|
|
10802
10807
|
this.payload = null;
|
|
10803
10808
|
this.status = "failed";
|
|
10809
|
+
this.failureKind = failureKind;
|
|
10804
10810
|
this.notify();
|
|
10805
10811
|
throw err;
|
|
10806
10812
|
}
|
|
@@ -10818,6 +10824,7 @@ var LicenseManager = class _LicenseManager {
|
|
|
10818
10824
|
const payload = this.#applyPolicyPipeline(raw);
|
|
10819
10825
|
this.payload = payload;
|
|
10820
10826
|
this.status = "valid";
|
|
10827
|
+
this.failureKind = null;
|
|
10821
10828
|
this.notify();
|
|
10822
10829
|
return payload;
|
|
10823
10830
|
}
|
|
@@ -10825,6 +10832,7 @@ var LicenseManager = class _LicenseManager {
|
|
|
10825
10832
|
loadLicense(payload) {
|
|
10826
10833
|
this.payload = this.#applyPolicyPipeline(payload);
|
|
10827
10834
|
this.status = "valid";
|
|
10835
|
+
this.failureKind = null;
|
|
10828
10836
|
this.notify();
|
|
10829
10837
|
}
|
|
10830
10838
|
/** Where the license is in its validation lifecycle. */
|
|
@@ -10840,6 +10848,43 @@ var LicenseManager = class _LicenseManager {
|
|
|
10840
10848
|
isLockedDown() {
|
|
10841
10849
|
return this.status === "pending" || this.status === "failed";
|
|
10842
10850
|
}
|
|
10851
|
+
/** Why the last validation failed, or null if it did not fail. */
|
|
10852
|
+
getFailureKind() {
|
|
10853
|
+
return this.status === "failed" ? this.failureKind : null;
|
|
10854
|
+
}
|
|
10855
|
+
/**
|
|
10856
|
+
* True when MARKET DATA must be withheld — i.e. the licence server gave a
|
|
10857
|
+
* definitive negative.
|
|
10858
|
+
*
|
|
10859
|
+
* Deliberately narrower than `isLockedDown()`. Hiding a button on an
|
|
10860
|
+
* ambiguous failure is cheap; blanking a live trading chart is not. So this
|
|
10861
|
+
* stays false while a verify is in flight and false when the server was
|
|
10862
|
+
* unreachable — only an outright rejection blocks data.
|
|
10863
|
+
*
|
|
10864
|
+
* 'idle' is also false: a host that never calls validateLicense (tests, the
|
|
10865
|
+
* unmanaged SDK path) keeps working exactly as before.
|
|
10866
|
+
*/
|
|
10867
|
+
isDataBlocked() {
|
|
10868
|
+
if (this.hostState === "unlicensed") return true;
|
|
10869
|
+
if (this.hostState === "licensed") return false;
|
|
10870
|
+
return this.status === "failed" && this.failureKind === "invalid";
|
|
10871
|
+
}
|
|
10872
|
+
/** What the host deployment reports about its own licence. */
|
|
10873
|
+
getHostLicenseState() {
|
|
10874
|
+
return this.hostState;
|
|
10875
|
+
}
|
|
10876
|
+
/**
|
|
10877
|
+
* Record the host deployment's answer from GET /api/license.
|
|
10878
|
+
*
|
|
10879
|
+
* Pass 'unlicensed' ONLY when the host answered and said it has no licence.
|
|
10880
|
+
* A network failure, missing apiUrl, or non-OK response must pass 'unknown',
|
|
10881
|
+
* otherwise an outage would blank every chart the deployment serves.
|
|
10882
|
+
*/
|
|
10883
|
+
setHostLicenseState(state) {
|
|
10884
|
+
if (this.hostState === state) return;
|
|
10885
|
+
this.hostState = state;
|
|
10886
|
+
this.notify();
|
|
10887
|
+
}
|
|
10843
10888
|
/**
|
|
10844
10889
|
* Runs a raw/legacy/partial payload through `migrateLegacyPayload` (fills
|
|
10845
10890
|
* missing productTier/capabilities/schemaVersion, deterministically, with
|
|
@@ -10898,6 +10943,8 @@ var LicenseManager = class _LicenseManager {
|
|
|
10898
10943
|
clear() {
|
|
10899
10944
|
this.payload = null;
|
|
10900
10945
|
this.status = "idle";
|
|
10946
|
+
this.failureKind = null;
|
|
10947
|
+
this.hostState = "unknown";
|
|
10901
10948
|
this.notify();
|
|
10902
10949
|
}
|
|
10903
10950
|
};
|
|
@@ -17835,6 +17882,126 @@ function useChartCapabilities(config) {
|
|
|
17835
17882
|
}, []);
|
|
17836
17883
|
return useMemo(() => applyRuntimeConfig(licCaps, config), [licCaps, config]);
|
|
17837
17884
|
}
|
|
17885
|
+
function useLicenseDataBlocked() {
|
|
17886
|
+
const [blocked, setBlocked] = useState(
|
|
17887
|
+
() => LicenseManager.getInstance().isDataBlocked()
|
|
17888
|
+
);
|
|
17889
|
+
useEffect(() => {
|
|
17890
|
+
const lm = LicenseManager.getInstance();
|
|
17891
|
+
setBlocked(lm.isDataBlocked());
|
|
17892
|
+
return lm.subscribe(() => setBlocked(lm.isDataBlocked()));
|
|
17893
|
+
}, []);
|
|
17894
|
+
return blocked;
|
|
17895
|
+
}
|
|
17896
|
+
function useHostLicense(apiUrl, getAuthToken) {
|
|
17897
|
+
useEffect(() => {
|
|
17898
|
+
if (!apiUrl) return;
|
|
17899
|
+
let cancelled = false;
|
|
17900
|
+
const lm = LicenseManager.getInstance();
|
|
17901
|
+
void (async () => {
|
|
17902
|
+
try {
|
|
17903
|
+
const headers = {};
|
|
17904
|
+
if (getAuthToken) {
|
|
17905
|
+
try {
|
|
17906
|
+
const tok = await getAuthToken();
|
|
17907
|
+
if (tok) headers["Authorization"] = `Bearer ${tok}`;
|
|
17908
|
+
} catch {
|
|
17909
|
+
}
|
|
17910
|
+
}
|
|
17911
|
+
const res = await fetch(`${apiUrl.replace(/\/+$/, "")}/api/license`, { headers });
|
|
17912
|
+
if (cancelled) return;
|
|
17913
|
+
if (!res.ok) {
|
|
17914
|
+
lm.setHostLicenseState("unknown");
|
|
17915
|
+
return;
|
|
17916
|
+
}
|
|
17917
|
+
const data = await res.json();
|
|
17918
|
+
if (cancelled) return;
|
|
17919
|
+
if (data.licensePayload && typeof data.licensePayload === "object") {
|
|
17920
|
+
lm.loadLicense(data.licensePayload);
|
|
17921
|
+
lm.setHostLicenseState("licensed");
|
|
17922
|
+
} else {
|
|
17923
|
+
lm.setHostLicenseState("unlicensed");
|
|
17924
|
+
}
|
|
17925
|
+
} catch {
|
|
17926
|
+
if (!cancelled) lm.setHostLicenseState("unknown");
|
|
17927
|
+
}
|
|
17928
|
+
})();
|
|
17929
|
+
return () => {
|
|
17930
|
+
cancelled = true;
|
|
17931
|
+
};
|
|
17932
|
+
}, [apiUrl, getAuthToken]);
|
|
17933
|
+
}
|
|
17934
|
+
function LicenseRequiredOverlay({
|
|
17935
|
+
reason,
|
|
17936
|
+
onOpenLicenseSettings
|
|
17937
|
+
}) {
|
|
17938
|
+
return /* @__PURE__ */ jsxs(
|
|
17939
|
+
"div",
|
|
17940
|
+
{
|
|
17941
|
+
role: "alert",
|
|
17942
|
+
"data-testid": "fc-license-required",
|
|
17943
|
+
style: {
|
|
17944
|
+
position: "absolute",
|
|
17945
|
+
inset: 0,
|
|
17946
|
+
zIndex: 100,
|
|
17947
|
+
background: "rgba(0,0,0,0.6)",
|
|
17948
|
+
backdropFilter: "blur(4px)",
|
|
17949
|
+
display: "flex",
|
|
17950
|
+
flexDirection: "column",
|
|
17951
|
+
alignItems: "center",
|
|
17952
|
+
justifyContent: "center",
|
|
17953
|
+
gap: 12,
|
|
17954
|
+
// Swallow interaction: no crosshair or drawing on a blocked chart.
|
|
17955
|
+
pointerEvents: "auto"
|
|
17956
|
+
},
|
|
17957
|
+
children: [
|
|
17958
|
+
/* @__PURE__ */ jsxs(
|
|
17959
|
+
"svg",
|
|
17960
|
+
{
|
|
17961
|
+
viewBox: "0 0 24 24",
|
|
17962
|
+
width: "40",
|
|
17963
|
+
height: "40",
|
|
17964
|
+
fill: "none",
|
|
17965
|
+
stroke: "rgba(255,255,255,0.7)",
|
|
17966
|
+
strokeWidth: "1.8",
|
|
17967
|
+
strokeLinecap: "round",
|
|
17968
|
+
strokeLinejoin: "round",
|
|
17969
|
+
"aria-hidden": "true",
|
|
17970
|
+
children: [
|
|
17971
|
+
/* @__PURE__ */ jsx("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2" }),
|
|
17972
|
+
/* @__PURE__ */ jsx("path", { d: "M7 11V7a5 5 0 0110 0v4" })
|
|
17973
|
+
]
|
|
17974
|
+
}
|
|
17975
|
+
),
|
|
17976
|
+
/* @__PURE__ */ jsx("div", { style: { color: "#fff", fontWeight: 700, fontSize: 18, letterSpacing: "0.01em" }, children: "Unlicensed" }),
|
|
17977
|
+
/* @__PURE__ */ jsxs("div", { style: { color: "rgba(255,255,255,0.65)", fontSize: 13, textAlign: "center", maxWidth: 340 }, children: [
|
|
17978
|
+
"Please activate your license in the admin studio.",
|
|
17979
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
17980
|
+
"Market data is unavailable until a valid license is installed."
|
|
17981
|
+
] }),
|
|
17982
|
+
reason && /* @__PURE__ */ jsx("div", { style: { color: "rgba(255,255,255,0.45)", fontSize: 12, fontStyle: "italic" }, children: reason }),
|
|
17983
|
+
onOpenLicenseSettings && /* @__PURE__ */ jsx(
|
|
17984
|
+
"button",
|
|
17985
|
+
{
|
|
17986
|
+
onClick: onOpenLicenseSettings,
|
|
17987
|
+
style: {
|
|
17988
|
+
marginTop: 4,
|
|
17989
|
+
padding: "8px 16px",
|
|
17990
|
+
borderRadius: 8,
|
|
17991
|
+
border: "1px solid rgba(255,255,255,0.25)",
|
|
17992
|
+
background: "rgba(255,255,255,0.12)",
|
|
17993
|
+
color: "#fff",
|
|
17994
|
+
fontSize: 13,
|
|
17995
|
+
fontWeight: 600,
|
|
17996
|
+
cursor: "pointer"
|
|
17997
|
+
},
|
|
17998
|
+
children: "Open license settings"
|
|
17999
|
+
}
|
|
18000
|
+
)
|
|
18001
|
+
]
|
|
18002
|
+
}
|
|
18003
|
+
);
|
|
18004
|
+
}
|
|
17838
18005
|
|
|
17839
18006
|
// src/react/assets/logo_dark.png
|
|
17840
18007
|
var logo_dark_default = "data:image/png;base64,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";
|
|
@@ -22478,6 +22645,8 @@ var ChartCanvas = forwardRef(
|
|
|
22478
22645
|
const [bars, setBars] = useState([]);
|
|
22479
22646
|
const [panes, setPanes] = useState([]);
|
|
22480
22647
|
const capabilities = useChartCapabilities();
|
|
22648
|
+
const dataBlocked = useLicenseDataBlocked();
|
|
22649
|
+
useHostLicense(apiUrl, getAuthToken);
|
|
22481
22650
|
const [indicators, setIndicators] = useState([]);
|
|
22482
22651
|
const [totalHeight, setTotalHeight] = useState(600);
|
|
22483
22652
|
const [activeTool, setActiveTool] = useState(initialActiveTool ?? "cursor");
|
|
@@ -22598,7 +22767,10 @@ var ChartCanvas = forwardRef(
|
|
|
22598
22767
|
symbol,
|
|
22599
22768
|
interval: timeframe,
|
|
22600
22769
|
theme,
|
|
22601
|
-
|
|
22770
|
+
// Withhold the datafeed entirely rather than covering the canvas: an
|
|
22771
|
+
// unlicensed deployment should make no market-data requests at all, and
|
|
22772
|
+
// there must be nothing behind the overlay to reveal.
|
|
22773
|
+
...datafeed !== void 0 && !dataBlocked ? { datafeed } : {},
|
|
22602
22774
|
...renderBackend !== void 0 ? { renderBackend } : {}
|
|
22603
22775
|
});
|
|
22604
22776
|
for (const config of initialIndicators) {
|
|
@@ -22742,7 +22914,7 @@ var ChartCanvas = forwardRef(
|
|
|
22742
22914
|
transformRef.current = null;
|
|
22743
22915
|
delete window.__chart;
|
|
22744
22916
|
};
|
|
22745
|
-
}, []);
|
|
22917
|
+
}, [dataBlocked]);
|
|
22746
22918
|
useEffect(() => {
|
|
22747
22919
|
chartRef.current?.setSymbol(symbol);
|
|
22748
22920
|
}, [symbol]);
|
|
@@ -23603,6 +23775,7 @@ var ChartCanvas = forwardRef(
|
|
|
23603
23775
|
overflow: "hidden"
|
|
23604
23776
|
},
|
|
23605
23777
|
children: [
|
|
23778
|
+
dataBlocked && /* @__PURE__ */ jsx(LicenseRequiredOverlay, {}),
|
|
23606
23779
|
/* @__PURE__ */ jsx(
|
|
23607
23780
|
LeftToolbar,
|
|
23608
23781
|
{
|
|
@@ -33027,6 +33200,6 @@ var CommandDispatcher = class {
|
|
|
33027
33200
|
}
|
|
33028
33201
|
};
|
|
33029
33202
|
|
|
33030
|
-
export { AgentFAB, AgentProvider, AssistantPanel, ChartCanvas, ChartWorkspace, CommandDispatcher, OrderTicket, VoiceInput, createTradingBridgeLogger, useAgent, useChartCapabilities };
|
|
33203
|
+
export { AgentFAB, AgentProvider, AssistantPanel, ChartCanvas, ChartWorkspace, CommandDispatcher, LicenseRequiredOverlay, OrderTicket, VoiceInput, createTradingBridgeLogger, useAgent, useChartCapabilities, useHostLicense, useLicenseDataBlocked };
|
|
33031
33204
|
//# sourceMappingURL=index.js.map
|
|
33032
33205
|
//# sourceMappingURL=index.js.map
|