@forgecharts/sdk 1.5.71 → 1.5.73
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.js +19 -55
- package/dist/index.js.map +1 -1
- package/dist/internal.js +19 -55
- package/dist/internal.js.map +1 -1
- package/dist/pixi/PixiChart.d.ts +8 -1
- package/dist/pixi/PixiChart.d.ts.map +1 -1
- package/dist/pixi/PixiLastPriceRenderer.d.ts.map +1 -1
- package/dist/react/index.js +74 -65
- package/dist/react/index.js.map +1 -1
- package/dist/react/internal.js +75 -66
- package/dist/react/internal.js.map +1 -1
- package/dist/react/shell/ScriptDrawer.d.ts.map +1 -1
- package/dist/react/shell/useWatchlistQuotes.d.ts +12 -0
- package/dist/react/shell/useWatchlistQuotes.d.ts.map +1 -1
- package/dist/react/workspace/ChartWorkspace.d.ts +12 -1
- package/dist/react/workspace/ChartWorkspace.d.ts.map +1 -1
- package/dist/react/workspace/toolbars/TopToolbar.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/react/internal.js
CHANGED
|
@@ -47,8 +47,14 @@ function timeframeToMs(tf) {
|
|
|
47
47
|
const secs = parseTfSeconds(tf);
|
|
48
48
|
return secs !== null ? secs * 1e3 : null;
|
|
49
49
|
}
|
|
50
|
+
function normalizeTimeframe(tf) {
|
|
51
|
+
const m = /^(\d+)([a-zA-Z])$/.exec(tf.trim());
|
|
52
|
+
if (!m) return tf.trim();
|
|
53
|
+
const unit = m[2];
|
|
54
|
+
return m[1] + (unit === "M" ? unit : unit.toLowerCase());
|
|
55
|
+
}
|
|
50
56
|
function parseTfSeconds(tf) {
|
|
51
|
-
const m = /^(\d+)(s|m|h|d|w|M)$/.exec(tf);
|
|
57
|
+
const m = /^(\d+)(s|m|h|d|w|M)$/.exec(normalizeTimeframe(tf));
|
|
52
58
|
if (!m) return null;
|
|
53
59
|
const n = parseInt(m[1], 10);
|
|
54
60
|
const unit = m[2];
|
|
@@ -64,6 +70,7 @@ function parseTfSeconds(tf) {
|
|
|
64
70
|
return unitSec !== void 0 ? n * unitSec : null;
|
|
65
71
|
}
|
|
66
72
|
function getBucketStart(timeMs, timeframe) {
|
|
73
|
+
timeframe = normalizeTimeframe(timeframe);
|
|
67
74
|
if (timeframe === "1w") return getWeekBucketStart(timeMs);
|
|
68
75
|
if (timeframe === "1M") return getMonthBucketStart(timeMs);
|
|
69
76
|
if (timeframe === "3M") return getQuarterBucketStart(timeMs);
|
|
@@ -7670,32 +7677,7 @@ function formatCountdown(secs) {
|
|
|
7670
7677
|
return `${m}:${String(s).padStart(2, "0")}`;
|
|
7671
7678
|
}
|
|
7672
7679
|
function tfToSeconds(tf) {
|
|
7673
|
-
|
|
7674
|
-
"1s": 1,
|
|
7675
|
-
"5s": 5,
|
|
7676
|
-
"10s": 10,
|
|
7677
|
-
"15s": 15,
|
|
7678
|
-
"30s": 30,
|
|
7679
|
-
"1m": 60,
|
|
7680
|
-
"3m": 180,
|
|
7681
|
-
"5m": 300,
|
|
7682
|
-
"15m": 900,
|
|
7683
|
-
"30m": 1800,
|
|
7684
|
-
"1h": 3600,
|
|
7685
|
-
"2h": 7200,
|
|
7686
|
-
"4h": 14400,
|
|
7687
|
-
"6h": 21600,
|
|
7688
|
-
"8h": 28800,
|
|
7689
|
-
"12h": 43200,
|
|
7690
|
-
"1D": 86400,
|
|
7691
|
-
"3D": 259200,
|
|
7692
|
-
"1W": 604800,
|
|
7693
|
-
"1M": 2592e3,
|
|
7694
|
-
"3M": 7776e3,
|
|
7695
|
-
"6M": 15552e3,
|
|
7696
|
-
"12M": 31536e3
|
|
7697
|
-
};
|
|
7698
|
-
return map[tf] ?? 3600;
|
|
7680
|
+
return parseTfSeconds(tf) ?? 3600;
|
|
7699
7681
|
}
|
|
7700
7682
|
var PixiLastPriceRenderer = class {
|
|
7701
7683
|
_lineGfx;
|
|
@@ -9680,34 +9662,16 @@ var PixiChart = class {
|
|
|
9680
9662
|
}
|
|
9681
9663
|
return { time: bestBar.time, price: snappedPrice };
|
|
9682
9664
|
}
|
|
9683
|
-
/**
|
|
9665
|
+
/**
|
|
9666
|
+
* Convert a Timeframe string to seconds (internal helper).
|
|
9667
|
+
*
|
|
9668
|
+
* Delegates to the shared parser — this was one of three private maps, and
|
|
9669
|
+
* the only one still keyed '1D'/'1W' uppercase, so canonical '1d' fell to
|
|
9670
|
+
* the 3600 fallback here while '1D' fell to the 1m fallback everywhere
|
|
9671
|
+
* else. One derivation, one dialect.
|
|
9672
|
+
*/
|
|
9684
9673
|
_tfToSeconds(tf) {
|
|
9685
|
-
|
|
9686
|
-
"1s": 1,
|
|
9687
|
-
"5s": 5,
|
|
9688
|
-
"10s": 10,
|
|
9689
|
-
"15s": 15,
|
|
9690
|
-
"30s": 30,
|
|
9691
|
-
"1m": 60,
|
|
9692
|
-
"3m": 180,
|
|
9693
|
-
"5m": 300,
|
|
9694
|
-
"15m": 900,
|
|
9695
|
-
"30m": 1800,
|
|
9696
|
-
"1h": 3600,
|
|
9697
|
-
"2h": 7200,
|
|
9698
|
-
"4h": 14400,
|
|
9699
|
-
"6h": 21600,
|
|
9700
|
-
"8h": 28800,
|
|
9701
|
-
"12h": 43200,
|
|
9702
|
-
"1D": 86400,
|
|
9703
|
-
"3D": 259200,
|
|
9704
|
-
"1W": 604800,
|
|
9705
|
-
"1M": 2592e3,
|
|
9706
|
-
"3M": 7776e3,
|
|
9707
|
-
"6M": 15552e3,
|
|
9708
|
-
"12M": 31536e3
|
|
9709
|
-
};
|
|
9710
|
-
return map[tf] ?? 3600;
|
|
9674
|
+
return parseTfSeconds(tf) ?? 3600;
|
|
9711
9675
|
}
|
|
9712
9676
|
// ─── Option resolvers ────────────────────────────────────────────────────────
|
|
9713
9677
|
_resolveOptions(opts) {
|
|
@@ -18367,7 +18331,7 @@ var DEMONSTRATION_STROKE = "rgba(255, 200, 50, 0.7)";
|
|
|
18367
18331
|
var DEMONSTRATION_COLOR = "var(--crosshair-overlay, rgba(255,255,255,0.75))";
|
|
18368
18332
|
|
|
18369
18333
|
// src/version.ts
|
|
18370
|
-
var FORGECHARTS_VERSION = "1.5.
|
|
18334
|
+
var FORGECHARTS_VERSION = "1.5.73" ;
|
|
18371
18335
|
function applyRuntimeConfig(caps, config) {
|
|
18372
18336
|
if (!config) return caps;
|
|
18373
18337
|
const orderEntry = config.enableOrderEntry === false ? false : caps.orderEntry;
|
|
@@ -18594,11 +18558,19 @@ var _listeners = /* @__PURE__ */ new Set();
|
|
|
18594
18558
|
var _subscribed = /* @__PURE__ */ new Set();
|
|
18595
18559
|
var _reconnectTimer = null;
|
|
18596
18560
|
var _authToken = null;
|
|
18561
|
+
var _baseUrl = null;
|
|
18597
18562
|
function setWsAuthToken(token) {
|
|
18598
18563
|
_authToken = token;
|
|
18599
18564
|
}
|
|
18565
|
+
function setWsBaseUrl(url) {
|
|
18566
|
+
if (!url) {
|
|
18567
|
+
_baseUrl = null;
|
|
18568
|
+
return;
|
|
18569
|
+
}
|
|
18570
|
+
_baseUrl = url.replace(/\/$/, "").replace(/^http/, "ws");
|
|
18571
|
+
}
|
|
18600
18572
|
function _wsUrl() {
|
|
18601
|
-
const base = typeof window === "undefined" ? "ws://localhost:4001/ws" : `${window.location.protocol === "https:" ? "wss" : "ws"}://${window.location.host}/ws
|
|
18573
|
+
const base = _baseUrl ?? (typeof window === "undefined" ? "ws://localhost:4001/ws" : `${window.location.protocol === "https:" ? "wss" : "ws"}://${window.location.host}/ws`);
|
|
18602
18574
|
return _authToken ? `${base}?token=${encodeURIComponent(_authToken)}` : base;
|
|
18603
18575
|
}
|
|
18604
18576
|
function _send(msg) {
|
|
@@ -26198,6 +26170,7 @@ function IndicatorsDialog({ onAdd, onClose, maxIndicators, getAuthToken }) {
|
|
|
26198
26170
|
] }) });
|
|
26199
26171
|
}
|
|
26200
26172
|
var DEFAULT_FAVORITES = ["1m", "5m", "15m", "30m", "1h", "4h", "1d", "1w"];
|
|
26173
|
+
var chipLabel = (tf) => /^\d+[dw]$/.test(tf) ? tf.toUpperCase() : tf;
|
|
26201
26174
|
var TF_LABELS = {
|
|
26202
26175
|
"1m": "1 minute",
|
|
26203
26176
|
"2m": "2 minutes",
|
|
@@ -26637,7 +26610,7 @@ function TopToolbar({
|
|
|
26637
26610
|
onClick: () => onTimeframeChange(tf),
|
|
26638
26611
|
children: tf
|
|
26639
26612
|
},
|
|
26640
|
-
tf
|
|
26613
|
+
chipLabel(tf)
|
|
26641
26614
|
)),
|
|
26642
26615
|
/* @__PURE__ */ jsx(
|
|
26643
26616
|
"button",
|
|
@@ -30205,6 +30178,7 @@ function ScriptDrawer({ onClose, onAddIndicator, apiUrl, getAuthToken }) {
|
|
|
30205
30178
|
const [savedScripts, setSavedScripts] = useState([]);
|
|
30206
30179
|
const [scriptsMenuOpen, setScriptsMenuOpen] = useState(false);
|
|
30207
30180
|
const [saving, setSaving] = useState(false);
|
|
30181
|
+
const [saveError, setSaveError] = useState(null);
|
|
30208
30182
|
const [activeScriptId, setActiveScriptId] = useState(null);
|
|
30209
30183
|
const [saveNameInput, setSaveNameInput] = useState("");
|
|
30210
30184
|
const [showSaveNamePrompt, setShowSaveNamePrompt] = useState(false);
|
|
@@ -30298,6 +30272,7 @@ function ScriptDrawer({ onClose, onAddIndicator, apiUrl, getAuthToken }) {
|
|
|
30298
30272
|
}, [scriptsMenuOpen]);
|
|
30299
30273
|
const handleSaveScript = useCallback(async (name) => {
|
|
30300
30274
|
setSaving(true);
|
|
30275
|
+
setSaveError(null);
|
|
30301
30276
|
const base = apiUrl ?? "";
|
|
30302
30277
|
const auth = await _authHeaders();
|
|
30303
30278
|
const scriptSource = code;
|
|
@@ -30305,27 +30280,28 @@ function ScriptDrawer({ onClose, onAddIndicator, apiUrl, getAuthToken }) {
|
|
|
30305
30280
|
const scriptName = name ?? extractScriptName(scriptSource);
|
|
30306
30281
|
try {
|
|
30307
30282
|
if (activeScriptId) {
|
|
30308
|
-
await fetch(`${base}/api/scripts/${encodeURIComponent(activeScriptId)}/versions`, {
|
|
30283
|
+
const res = await fetch(`${base}/api/scripts/${encodeURIComponent(activeScriptId)}/versions`, {
|
|
30309
30284
|
method: "POST",
|
|
30310
30285
|
headers: { "Content-Type": "application/json", ...auth },
|
|
30311
30286
|
body: JSON.stringify({ source: scriptSource })
|
|
30312
30287
|
});
|
|
30288
|
+
if (!res.ok) throw new Error(`save failed (${res.status})`);
|
|
30313
30289
|
} else {
|
|
30314
30290
|
const res = await fetch(`${base}/api/scripts`, {
|
|
30315
30291
|
method: "POST",
|
|
30316
30292
|
headers: { "Content-Type": "application/json", ...auth },
|
|
30317
30293
|
body: JSON.stringify({ name: scriptName, language: scriptLang, source: scriptSource })
|
|
30318
30294
|
});
|
|
30319
|
-
if (res.ok) {
|
|
30320
|
-
|
|
30321
|
-
|
|
30322
|
-
}
|
|
30295
|
+
if (!res.ok) throw new Error(`save failed (${res.status})`);
|
|
30296
|
+
const created = await res.json();
|
|
30297
|
+
setActiveScriptId(created.id);
|
|
30323
30298
|
}
|
|
30324
30299
|
await fetchSavedScripts();
|
|
30325
|
-
|
|
30300
|
+
setShowSaveNamePrompt(false);
|
|
30301
|
+
} catch (err) {
|
|
30302
|
+
setSaveError(err instanceof Error ? err.message : "save failed");
|
|
30326
30303
|
}
|
|
30327
30304
|
setSaving(false);
|
|
30328
|
-
setShowSaveNamePrompt(false);
|
|
30329
30305
|
}, [apiUrl, _authHeaders, code, activeScriptId, extractScriptName, fetchSavedScripts]);
|
|
30330
30306
|
const handleSaveClick = useCallback(() => {
|
|
30331
30307
|
if (activeScriptId) {
|
|
@@ -30428,6 +30404,16 @@ function ScriptDrawer({ onClose, onAddIndicator, apiUrl, getAuthToken }) {
|
|
|
30428
30404
|
]
|
|
30429
30405
|
}
|
|
30430
30406
|
),
|
|
30407
|
+
saveError && /* @__PURE__ */ jsx(
|
|
30408
|
+
"span",
|
|
30409
|
+
{
|
|
30410
|
+
className: "script-save-error",
|
|
30411
|
+
role: "alert",
|
|
30412
|
+
title: saveError,
|
|
30413
|
+
style: { color: "var(--fc-danger, #e5484d)", fontSize: 11, marginLeft: 6 },
|
|
30414
|
+
children: saveError
|
|
30415
|
+
}
|
|
30416
|
+
),
|
|
30431
30417
|
/* @__PURE__ */ jsxs("div", { className: "script-my-scripts-wrap", ref: scriptsMenuRef, children: [
|
|
30432
30418
|
/* @__PURE__ */ jsxs(
|
|
30433
30419
|
"button",
|
|
@@ -31518,6 +31504,8 @@ function ChartWorkspace({
|
|
|
31518
31504
|
symbolResolver,
|
|
31519
31505
|
rollRule,
|
|
31520
31506
|
onRollRuleChange,
|
|
31507
|
+
quotesWsUrl,
|
|
31508
|
+
getQuotesAuthToken,
|
|
31521
31509
|
extraTfGroups,
|
|
31522
31510
|
// RightToolbar
|
|
31523
31511
|
watchlistOpen,
|
|
@@ -31574,6 +31562,27 @@ function ChartWorkspace({
|
|
|
31574
31562
|
tradingBridge,
|
|
31575
31563
|
tradingOverlayStore
|
|
31576
31564
|
}) {
|
|
31565
|
+
const [quotesReady, setQuotesReady] = React11.useState(false);
|
|
31566
|
+
React11.useEffect(() => {
|
|
31567
|
+
let cancelled = false;
|
|
31568
|
+
if (!quotesWsUrl || !getQuotesAuthToken) {
|
|
31569
|
+
setQuotesReady(false);
|
|
31570
|
+
return void 0;
|
|
31571
|
+
}
|
|
31572
|
+
void (async () => {
|
|
31573
|
+
try {
|
|
31574
|
+
const token = await getQuotesAuthToken();
|
|
31575
|
+
if (cancelled) return;
|
|
31576
|
+
setWsAuthToken(token || null);
|
|
31577
|
+
setWsBaseUrl(quotesWsUrl);
|
|
31578
|
+
setQuotesReady(true);
|
|
31579
|
+
} catch {
|
|
31580
|
+
}
|
|
31581
|
+
})();
|
|
31582
|
+
return () => {
|
|
31583
|
+
cancelled = true;
|
|
31584
|
+
};
|
|
31585
|
+
}, [quotesWsUrl, getQuotesAuthToken]);
|
|
31577
31586
|
const capabilities = useChartCapabilities();
|
|
31578
31587
|
const dataBlocked = useLicenseDataBlocked();
|
|
31579
31588
|
useHostLicense(hostApiUrl, getAuthToken);
|
|
@@ -31754,7 +31763,7 @@ function ChartWorkspace({
|
|
|
31754
31763
|
onClose: closeWatchlist,
|
|
31755
31764
|
onSelectSymbol: onSymbolChange,
|
|
31756
31765
|
symbolResolver,
|
|
31757
|
-
liveQuotes:
|
|
31766
|
+
liveQuotes: quotesReady,
|
|
31758
31767
|
...hostApiUrl !== void 0 ? { apiUrl: hostApiUrl } : {},
|
|
31759
31768
|
...getAuthToken !== void 0 ? { getAuthToken } : {}
|
|
31760
31769
|
}
|
|
@@ -36606,7 +36615,7 @@ var ManagedAppShell = forwardRef(
|
|
|
36606
36615
|
const res = await fetch(`${base}/api/scripts`, {
|
|
36607
36616
|
method: "POST",
|
|
36608
36617
|
headers: { ...auth, "Content-Type": "application/json" },
|
|
36609
|
-
body: JSON.stringify({ name, source, language: "
|
|
36618
|
+
body: JSON.stringify({ name, source, language: "forgescript" })
|
|
36610
36619
|
});
|
|
36611
36620
|
if (!res.ok) throw new Error(`Failed to create script (${res.status})`);
|
|
36612
36621
|
const data = await res.json();
|